From 446f66807f078b574cb31d87bebdcff2f55953fa Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 22 Jun 2008 05:42:22 +0000 Subject: Circular references between Zone/Animation and Command are now manually removed, to allow the objects - which are stored into SharedPtr's - to be deallocated. svn-id: r32744 --- engines/parallaction/parallaction.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 25ebe4263d..4f586961a6 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -86,7 +86,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam Parallaction::~Parallaction() { clearSet(_commandOpcodes); clearSet(_instructionOpcodes); - + delete _debugger; delete _globalTable; delete _callableNames; @@ -95,7 +95,7 @@ Parallaction::~Parallaction() { freeCharacter(); destroyInventory(); - + delete _localFlagNames; delete _gfx; delete _soundMan; @@ -193,6 +193,9 @@ AnimationPtr Parallaction::findAnimation(const char *name) { } void Parallaction::freeAnimations() { + for (AnimationList::iterator it = _location._animations.begin(); it != _location._animations.end(); it++) { + (*it)->_commands.clear(); // See comment for freeZones(), about circular references. + } _location._animations.clear(); return; } @@ -479,6 +482,9 @@ void Parallaction::freeZones() { debugC(2, kDebugExec, "freeZones preserving zone '%s'", z->_name); it++; } else { + (*it)->_commands.clear(); // Since commands may reference zones, and both commands and zones are kept stored into + // SharedPtr's, we need to kill commands explicitly to destroy any potential circular + // reference. it = _location._zones.erase(it); } } -- cgit v1.2.3 From 3be9449e6730ec296091e7caaf5dd8f277d95bc9 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 22 Jun 2008 12:31:05 +0000 Subject: this should fix bug #1997149: KYRA2: no text in spellbook svn-id: r32750 --- engines/kyra/gui_hof.cpp | 22 +++++++++++++++++++--- engines/kyra/kyra_hof.cpp | 3 +++ 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 555934cb7f..e94f88a1d2 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -455,13 +455,29 @@ void KyraEngine_HoF::showBookPage() { char filename[16]; sprintf(filename, "PAGE%.01X.", _bookCurPage); - strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); + strcat(filename, _languageExtension[_lang]); uint8 *leftPage = _res->fileData(filename, 0); + if (!leftPage) { + // some floppy version use a TXT extension + sprintf(filename, "PAGE%.01X.", _bookCurPage); + strcat(filename, "TXT"); + leftPage = _res->fileData(filename, 0); + } + int leftPageY = _bookPageYOffset[_bookCurPage]; sprintf(filename, "PAGE%.01X.", _bookCurPage+1); - strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); - uint8 *rightPage = (_bookCurPage != _bookMaxPage) ? _res->fileData(filename, 0) : 0; + strcat(filename, _languageExtension[_lang]); + uint8 *rightPage = 0; + if (_bookCurPage != _bookMaxPage) { + rightPage = _res->fileData(filename, 0); + if (!rightPage) { + sprintf(filename, "PAGE%.01X.", _bookCurPage); + strcat(filename, "TXT"); + rightPage = _res->fileData(filename, 0); + } + } + int rightPageY = _bookPageYOffset[_bookCurPage+1]; _screen->hideMouse(); diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 57f0dcc24a..a8b8c0dced 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -296,6 +296,9 @@ int KyraEngine_HoF::go() { _res->loadFileList("FILEDATA.FDT"); else _res->loadFileList(_ingamePakList, _ingamePakListSize); + + if (_flags.platform == Common::kPlatformPC98) + _res->loadPakFile("AUDIO.PAK"); } _menuDirectlyToLoad = (_menuChoice == 3) ? true : false; -- cgit v1.2.3 From 12d7a5e679683f537d35075a5f67e57817621102 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 22 Jun 2008 12:36:38 +0000 Subject: Cleanup. svn-id: r32751 --- engines/kyra/gui_hof.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index e94f88a1d2..7d56743af5 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -454,26 +454,22 @@ void KyraEngine_HoF::loadBookBkgd() { void KyraEngine_HoF::showBookPage() { char filename[16]; - sprintf(filename, "PAGE%.01X.", _bookCurPage); - strcat(filename, _languageExtension[_lang]); + sprintf(filename, "PAGE%.01X.%s", _bookCurPage, _languageExtension[_lang]); uint8 *leftPage = _res->fileData(filename, 0); if (!leftPage) { // some floppy version use a TXT extension - sprintf(filename, "PAGE%.01X.", _bookCurPage); - strcat(filename, "TXT"); + sprintf(filename, "PAGE%.01X.TXT", _bookCurPage); leftPage = _res->fileData(filename, 0); } int leftPageY = _bookPageYOffset[_bookCurPage]; - sprintf(filename, "PAGE%.01X.", _bookCurPage+1); - strcat(filename, _languageExtension[_lang]); + sprintf(filename, "PAGE%.01X.%s", _bookCurPage+1, _languageExtension[_lang]); uint8 *rightPage = 0; if (_bookCurPage != _bookMaxPage) { rightPage = _res->fileData(filename, 0); if (!rightPage) { - sprintf(filename, "PAGE%.01X.", _bookCurPage); - strcat(filename, "TXT"); + sprintf(filename, "PAGE%.01X.TXT", _bookCurPage); rightPage = _res->fileData(filename, 0); } } -- cgit v1.2.3 From 6360c392f25d880f8905dedaee0f34889817acaf Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 22 Jun 2008 12:41:46 +0000 Subject: missed this in last commit (bug fix for #1997149) svn-id: r32753 --- engines/kyra/script_hof.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index 91fbfb3e49..11b97afbe6 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -800,9 +800,15 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { _screen->fadeToBlack(0x14); sprintf(filename, "LETTER%.1d.", letter); - strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); - + strcat(filename, _languageExtension[_lang]); uint8 *letterBuffer = _res->fileData(filename, 0); + if (!letterBuffer) { + // some floppy versions use a TXT extension + sprintf(filename, "LETTER%.1d.", letter); + strcat(filename, "TXT"); + letterBuffer = _res->fileData(filename, 0); + } + if (letterBuffer) { bookDecodeText(letterBuffer); bookPrintText(2, letterBuffer, 0xC, 0xA, 0x20); -- cgit v1.2.3 From 51000de1626090ac61ace8fa9bbfe233117219cc Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 22 Jun 2008 12:43:32 +0000 Subject: Cleanup. svn-id: r32754 --- engines/kyra/script_hof.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index 11b97afbe6..94f160d11f 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -799,13 +799,11 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { _screen->fadeToBlack(0x14); - sprintf(filename, "LETTER%.1d.", letter); - strcat(filename, _languageExtension[_lang]); + sprintf(filename, "LETTER%.1d.%s", letter, _languageExtension[_lang]); uint8 *letterBuffer = _res->fileData(filename, 0); if (!letterBuffer) { // some floppy versions use a TXT extension - sprintf(filename, "LETTER%.1d.", letter); - strcat(filename, "TXT"); + sprintf(filename, "LETTER%.1d.TXT", letter); letterBuffer = _res->fileData(filename, 0); } -- cgit v1.2.3 From 4e2e46f16cd6480edc3509edfe4b49bde0268756 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 22 Jun 2008 14:31:45 +0000 Subject: Fixed leak when loading sounds for Amiga version of Nippon Safes. svn-id: r32756 --- engines/parallaction/disk_ns.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index cdbe3458a7..8f4f6d8e20 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -1395,9 +1395,7 @@ Common::ReadStream* AmigaDisk_ns::loadSound(const char* name) { char path[PATH_LEN]; sprintf(path, "%s.snd", name); - openArchivedFile(path); - - return new DummyArchiveStream(_resArchive); + return openArchivedFile(path); } } // namespace Parallaction -- cgit v1.2.3 From d2609258ccaf536cc4178d1e9c690ad472ae877c Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 22 Jun 2008 14:46:08 +0000 Subject: Added constructor and destructor to Dialogue, thus fixing a long standing leak. svn-id: r32757 --- engines/parallaction/objects.cpp | 10 ++++++++++ engines/parallaction/objects.h | 3 +++ 2 files changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index cac31911f4..5b5aa85584 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -207,6 +207,16 @@ uint16 Zone::height() const { return _bottom - _top; } +Dialogue::Dialogue() { + memset(_questions, 0, sizeof(_questions)); +} + +Dialogue::~Dialogue() { + for (int i = 0; i < NUM_QUESTIONS; i++) { + delete _questions[i]; + } +} + Answer::Answer() { _text = NULL; _mood = 0; diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index afa6cc5ed5..2bc9df0bbe 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -181,6 +181,9 @@ struct Question { struct Dialogue { Question *_questions[NUM_QUESTIONS]; + + Dialogue(); + ~Dialogue(); }; struct GetData { // size = 24 -- cgit v1.2.3 From 9194f391854466dd5c54341fcc6ba1d5f4ca6eaa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 22 Jun 2008 17:36:14 +0000 Subject: Fixed 2 MSVC warnings (potentially undefined behavior and possibly uninitialized variable used) svn-id: r32758 --- engines/parallaction/dialogue.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index b9dea60dc0..903c71907c 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -268,11 +268,11 @@ int16 DialogueManager::selectAnswer() { } int oldSelection = -1; - int selection; + int selection = 0; uint32 event; Common::Point p; - while (_engineFlags & kEngineQuit == 0) { + while ((_engineFlags & kEngineQuit) == 0) { _vm->_input->readInput(); _vm->_input->getCursorPos(p); -- cgit v1.2.3 From 28e32bb7cb6df6610e137500c0187d4ba36d8bdf Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Tue, 24 Jun 2008 13:21:22 +0000 Subject: Fix for bug #2001193. Character confirmation screen didn't appear and game crashed because too many strings were added to the draw list. svn-id: r32762 --- engines/parallaction/callables_ns.cpp | 5 +++++ engines/parallaction/gui_ns.cpp | 2 ++ engines/parallaction/parallaction.h | 3 +++ engines/parallaction/parallaction_ns.cpp | 8 +++++--- 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index 68e6a70ffb..36f5b00c5b 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -417,6 +417,11 @@ void Parallaction_ns::_c_ridux(void *parm) { } void Parallaction_ns::_c_testResult(void *parm) { + if (_inTestResult) { + return; + } + _inTestResult = true; + _gfx->updateScreen(); _disk->selectArchive("disk1"); diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp index 1d4d44fa46..9c48586dbc 100644 --- a/engines/parallaction/gui_ns.cpp +++ b/engines/parallaction/gui_ns.cpp @@ -166,6 +166,8 @@ void Parallaction_ns::guiStart() { } void Parallaction_ns::selectStartLocation() { + _inTestResult = false; + int character = guiSelectCharacter(); if (character == -1) error("invalid character selected from menu screen"); diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 5ae1386378..f9c2c86a1b 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -548,6 +548,9 @@ private: ZonePtr _moveSarcExaZones[5]; AnimationPtr _rightHandAnim; + bool _inTestResult; + + // common callables void _c_play_boogie(void*); void _c_startIntro(void*); diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index f346a278f7..59b9465d0a 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -147,6 +147,8 @@ int Parallaction_ns::init() { num_foglie = 0; + _inTestResult = false; + _location._animations.push_front(_char._ani); Parallaction::init(); @@ -156,7 +158,7 @@ int Parallaction_ns::init() { Parallaction_ns::~Parallaction_ns() { freeFonts(); - + delete _locationParser; delete _programParser; delete _mouseComposedArrow; @@ -235,10 +237,10 @@ int Parallaction_ns::go() { _globalTable = _disk->loadTable("global"); guiStart(); - + if (_engineFlags & kEngineQuit) return 0; - + changeLocation(_location._name); if (_engineFlags & kEngineQuit) -- cgit v1.2.3 From df1aa7809aad2a6b0404d57aeb9d0c5a423fd91b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 24 Jun 2008 13:59:48 +0000 Subject: Added const to some static data. svn-id: r32763 --- engines/kyra/animator_lok.cpp | 4 ++-- engines/kyra/gui_lok.cpp | 10 +++++----- engines/kyra/gui_lok.h | 2 ++ engines/kyra/items_lok.cpp | 2 +- engines/kyra/scene_hof.cpp | 4 ++-- engines/kyra/scene_lok.cpp | 4 ++-- engines/kyra/script.cpp | 2 +- engines/kyra/script_tim.cpp | 2 +- engines/kyra/seqplayer.cpp | 4 ++-- engines/kyra/sound_towns.cpp | 2 +- 10 files changed, 19 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/kyra/animator_lok.cpp b/engines/kyra/animator_lok.cpp index 1baa78b203..75d5537e4a 100644 --- a/engines/kyra/animator_lok.cpp +++ b/engines/kyra/animator_lok.cpp @@ -665,7 +665,7 @@ void Animator_LoK::animRefreshNPC(int character) { void Animator_LoK::setCharacterDefaultFrame(int character) { debugC(9, kDebugLevelAnimator, "Animator_LoK::setCharacterDefaultFrame()"); - static uint16 initFrameTable[] = { + static const uint16 initFrameTable[] = { 7, 41, 77, 0, 0 }; assert(character < ARRAYSIZE(initFrameTable)); @@ -678,7 +678,7 @@ void Animator_LoK::setCharacterDefaultFrame(int character) { void Animator_LoK::setCharactersHeight() { debugC(9, kDebugLevelAnimator, "Animator_LoK::setCharactersHeight()"); - static int8 initHeightTable[] = { + static const int8 initHeightTable[] = { 48, 40, 48, 47, 56, 44, 42, 47, 38, 35, 40 diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 6fa30c9e9a..35b343fc25 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -188,6 +188,7 @@ int KyraEngine_LoK::buttonAmuletCallback(Button *caller) { #pragma mark - GUI_LoK::GUI_LoK(KyraEngine_LoK *vm, Screen_LoK *screen) : GUI(vm), _vm(vm), _screen(screen) { + _lastScreenUpdate = 0; _menu = 0; initStaticResource(); _scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::scrollUp); @@ -479,7 +480,6 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { void GUI_LoK::getInput() { Common::Event event; - static uint32 lastScreenUpdate = 0; uint32 now = _vm->_system->getMillis(); _mouseWheel = 0; @@ -496,7 +496,7 @@ void GUI_LoK::getInput() { break; case Common::EVENT_MOUSEMOVE: _vm->_system->updateScreen(); - lastScreenUpdate = now; + _lastScreenUpdate = now; break; case Common::EVENT_WHEELUP: _mouseWheel = -1; @@ -512,9 +512,9 @@ void GUI_LoK::getInput() { } } - if (now - lastScreenUpdate > 50) { + if (now - _lastScreenUpdate > 50) { _vm->_system->updateScreen(); - lastScreenUpdate = now; + _lastScreenUpdate = now; } _vm->_system->delayMillis(3); @@ -1056,7 +1056,7 @@ void GUI_LoK::fadePalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return; - static int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1}; + static const int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1}; int index = 0; memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h index 607ef0b605..49081c7ae2 100644 --- a/engines/kyra/gui_lok.h +++ b/engines/kyra/gui_lok.h @@ -157,6 +157,8 @@ private: KyraEngine_LoK *_vm; Screen_LoK *_screen; + uint32 _lastScreenUpdate; + bool _menuRestoreScreen; uint8 _toplevelMenu; int _savegameOffset; diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp index 8eb62c20c2..2c2903d0b3 100644 --- a/engines/kyra/items_lok.cpp +++ b/engines/kyra/items_lok.cpp @@ -39,7 +39,7 @@ namespace Kyra { int KyraEngine_LoK::findDuplicateItemShape(int shape) { - static uint8 dupTable[] = { + static const uint8 dupTable[] = { 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47, 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a, 0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index 1882386b03..62df683ea2 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -723,7 +723,7 @@ void KyraEngine_HoF::fadeScenePal(int srcIndex, int delayTime) { bool KyraEngine_HoF::lineIsPassable(int x, int y) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::lineIsPassable(%d, %d)", x, y); - static int unkTable[] = { 1, 1, 1, 1, 1, 2, 4, 6, 8 }; + static const int widthTable[] = { 1, 1, 1, 1, 1, 2, 4, 6, 8 }; if (_pathfinderFlag & 2) { if (x >= 320) @@ -743,7 +743,7 @@ bool KyraEngine_HoF::lineIsPassable(int x, int y) { if (y > 143) return false; - int unk1 = unkTable[getScale(x, y) >> 5]; + int unk1 = widthTable[getScale(x, y) >> 5]; if (y < 0) y = 0; diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp index e4ae67f751..53c269a926 100644 --- a/engines/kyra/scene_lok.cpp +++ b/engines/kyra/scene_lok.cpp @@ -1144,11 +1144,11 @@ void KyraEngine_LoK::setCharactersInDefaultScene() { } void KyraEngine_LoK::setCharactersPositions(int character) { - static uint16 initXPosTable[] = { + static const uint16 initXPosTable[] = { 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042 }; - static uint8 initYPosTable[] = { + static const uint8 initYPosTable[] = { 0x00, 0xA2, 0x00, 0x42, 0x00, 0x67, 0x67, 0x60, 0x5A, 0x71, 0x76 diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index ef3e259cfa..a29cdc8ca3 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -35,7 +35,7 @@ namespace Kyra { EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm) { #define COMMAND(x) { &EMCInterpreter::x, #x } - static CommandEntry commandProcs[] = { + static const CommandEntry commandProcs[] = { // 0x00 COMMAND(cmd_jmpTo), COMMAND(cmd_setRetValue), diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 4ad6464424..6b82ba06de 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -34,7 +34,7 @@ namespace Kyra { TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _system(system), _currentTim(0) { #define COMMAND(x) { &TIMInterpreter::x, #x } #define COMMAND_UNIMPL() { 0, 0 } - static CommandEntry commandProcs[] = { + static const CommandEntry commandProcs[] = { // 0x00 COMMAND(cmd_initFunc0), COMMAND(cmd_stopCurFunc), diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index 73d69ef10c..dfda5bf859 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -500,7 +500,7 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { debugC(9, kDebugLevelSequence, "SeqPlayer::seq_playSequence(%p, %d)", (const void *)seqData, skipSeq); assert(seqData); - static SeqEntry floppySeqProcs[] = { + static const SeqEntry floppySeqProcs[] = { // 0x00 SEQOP(3, s1_wsaOpen), SEQOP(2, s1_wsaClose), @@ -541,7 +541,7 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { SEQOP(1, s1_endOfScript) }; - static SeqEntry cdromSeqProcs[] = { + static const SeqEntry cdromSeqProcs[] = { // 0x00 SEQOP(3, s1_wsaOpen), SEQOP(2, s1_wsaClose), diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 4265533507..c0e4dd70a9 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -878,7 +878,7 @@ void MidiParser_EuD::parseNextEvent(EventInfo &info) { pos += 6; } } else if (cmd == 0xF2) { - static uint16 tickTable [] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 }; + static const uint16 tickTable[] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 }; _baseTick += tickTable[_nextBaseTickStep >> 4] * ((_nextBaseTickStep & 0x0f) + 1); _nextBaseTickStep = pos[1]; pos += 6; -- cgit v1.2.3 From f1cacafc466ac8689a286d1e712f0ada67e9a994 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Tue, 24 Jun 2008 20:44:37 +0000 Subject: Fixed opcodes: - 0xA0: o2_addGfxElementType20 (Was o2_addGfxElementA0) Implemented opcodes: - 0xA1: o2_removeGfxElementType20 (Was o2_removeGfxElementA0) - 0xA2: o2_addGfxElementType21 (Was o2_opA2) - 0xA3: o2_removeGfxElementType21 (Was o2_opA3) NOTE: Drawing of type 21 overlay elements isn't coded yet. svn-id: r32769 --- engines/cine/object.cpp | 14 ++++++-------- engines/cine/object.h | 4 ++-- engines/cine/script.h | 8 ++++---- engines/cine/script_os.cpp | 38 ++++++++++++++++---------------------- 4 files changed, 28 insertions(+), 36 deletions(-) (limited to 'engines') diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 7666f05352..96048f5214 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -122,24 +122,22 @@ void addOverlay(uint16 objIdx, uint16 param) { * \param objIdx Associate the overlay with this object * \param param source background index */ -void addGfxElementA0(int16 objIdx, int16 param) { +void addGfxElement(int16 objIdx, int16 param, int16 type) { Common::List::iterator it; overlay tmp; for (it = overlayList.begin(); it != overlayList.end(); ++it) { - // wtf?! - if (objectTable[it->objIdx].mask == objectTable[objIdx].mask && - (it->type == 2 || it->type == 3)) { + if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask || it->type == 2 || it->type == 3) { break; } } - if (it != overlayList.end() && it->objIdx == objIdx && it->type == 20 && it->x == param) { + if (it != overlayList.end() && it->objIdx == objIdx && it->type == type && it->x == param) { return; } tmp.objIdx = objIdx; - tmp.type = 20; + tmp.type = type; tmp.x = param; tmp.y = 0; tmp.width = 0; @@ -153,11 +151,11 @@ void addGfxElementA0(int16 objIdx, int16 param) { * \param param Remove overlay using this background * \todo Check that it works */ -void removeGfxElementA0(int16 objIdx, int16 param) { +void removeGfxElement(int16 objIdx, int16 param, int16 type) { Common::List::iterator it; for (it = overlayList.begin(); it != overlayList.end(); ++it) { - if (it->objIdx == objIdx && it->type == 20 && it->x == param) { + if (it->objIdx == objIdx && it->type == type && it->x == param) { overlayList.erase(it); return; } diff --git a/engines/cine/object.h b/engines/cine/object.h index e7de39649d..6252a628cb 100644 --- a/engines/cine/object.h +++ b/engines/cine/object.h @@ -62,8 +62,8 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue); void addOverlay(uint16 objIdx, uint16 param); int removeOverlay(uint16 objIdx, uint16 param); -void addGfxElementA0(int16 objIdx, int16 param); -void removeGfxElementA0(int16 objIdx, int16 param); +void addGfxElement(int16 objIdx, int16 param, int16 type); +void removeGfxElement(int16 objIdx, int16 param, int16 type); int16 getObjectParam(uint16 objIdx, uint16 paramIdx); diff --git a/engines/cine/script.h b/engines/cine/script.h index eeac0e8809..2b6acbba9b 100644 --- a/engines/cine/script.h +++ b/engines/cine/script.h @@ -258,10 +258,10 @@ protected: int o2_useBgScroll(); int o2_setAdditionalBgVScroll(); int o2_op9F(); - int o2_addGfxElementA0(); - int o2_removeGfxElementA0(); - int o2_opA2(); - int o2_opA3(); + int o2_addGfxElementType20(); + int o2_removeGfxElementType20(); + int o2_addGfxElementType21(); + int o2_removeGfxElementType21(); int o2_loadMask22(); int o2_unloadMask22(); diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index 319fca5d3c..ffc0da5790 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -240,10 +240,10 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o2_setAdditionalBgVScroll, "c" }, { &FWScript::o2_op9F, "ww" }, /* TODO: Name this opcode properly. */ /* A0 */ - { &FWScript::o2_addGfxElementA0, "ww" }, /* TODO: Name this opcode properly. */ - { &FWScript::o2_removeGfxElementA0, "ww" }, /* TODO: Name this opcode properly. */ - { &FWScript::o2_opA2, "ww" }, /* TODO: Name this opcode properly. */ - { &FWScript::o2_opA3, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_addGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_removeGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_addGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_removeGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */ /* A4 */ { &FWScript::o2_loadMask22, "b" }, /* TODO: Name this opcode properly. */ { &FWScript::o2_unloadMask22, "b" }, /* TODO: Name this opcode properly. */ @@ -721,42 +721,36 @@ int FWScript::o2_op9F() { return 0; } -int FWScript::o2_addGfxElementA0() { +int FWScript::o2_addGfxElementType20() { uint16 param1 = getNextWord(); uint16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2); - addGfxElementA0(param1, param2); + debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType20(%d,%d)", _line, param1, param2); + addGfxElement(param1, param2, 20); return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o2_removeGfxElementA0() { +int FWScript::o2_removeGfxElementType20() { uint16 idx = getNextWord(); uint16 param = getNextWord(); - warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param); - removeGfxElementA0(idx, param); + debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType20(%d,%d)", _line, idx, param); + removeGfxElement(idx, param, 20); return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o2_opA2() { +int FWScript::o2_addGfxElementType21() { uint16 a = getNextWord(); uint16 b = getNextWord(); - warning("STUB: o2_opA2(%x, %x)", a, b); - // addGfxElementA2(); + debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType21(%d,%d)", _line, a, b); + addGfxElement(a, b, 21); return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o2_opA3() { +int FWScript::o2_removeGfxElementType21() { uint16 a = getNextWord(); uint16 b = getNextWord(); - warning("STUB: o2_opA3(%x, %x)", a, b); - // removeGfxElementA2(); + debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType21(%d,%d)", _line, a, b); + removeGfxElement(a, b, 21); return 0; } -- cgit v1.2.3 From 9654ee4fa3e6ba5fab6fda321542e150a27193b8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jun 2008 08:36:07 +0000 Subject: Possible fix for (for the drascula engine) for bug #2001583 - "WINCE: CRUISE and DRASCULA engines can not be compiled" svn-id: r32777 --- engines/drascula/drascula.h | 2 +- engines/drascula/rooms.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index 567d894b75..8bb73d8dd1 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -328,7 +328,7 @@ public: int curHeight, curWidth, feetHeight; int talkHeight, talkWidth; int floorX1, floorY1, floorX2, floorY2; - int near, far; + int lowerLimit, upperLimit; int trackFinal, walkToObject; int objExit; int timeDiff, startTime; diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index 6fe28bdbdc..37dddf4b7e 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -1672,8 +1672,8 @@ void DrasculaEngine::enterRoom(int roomIndex) { getIntFromLine(buffer, size, &floorY2); if (currentChapter != 2) { - getIntFromLine(buffer, size, &far); - getIntFromLine(buffer, size, &near); + getIntFromLine(buffer, size, &upperLimit); + getIntFromLine(buffer, size, &lowerLimit); } _arj.close(); @@ -1732,27 +1732,27 @@ void DrasculaEngine::enterRoom(int roomIndex) { if (currentChapter != 2) { for (l = 0; l <= floorY1; l++) - factor_red[l] = far; + factor_red[l] = upperLimit; for (l = floorY1; l <= 201; l++) - factor_red[l] = near; + factor_red[l] = lowerLimit; - chiquez = (float)(near - far) / (float)(floorY2 - floorY1); + chiquez = (float)(lowerLimit - upperLimit) / (float)(floorY2 - floorY1); for (l = floorY1; l <= floorY2; l++) { - factor_red[l] = (int)(far + pequegnez); + factor_red[l] = (int)(upperLimit + pequegnez); pequegnez = pequegnez + chiquez; } } if (roomNumber == 24) { for (l = floorY1 - 1; l > 74; l--) { - factor_red[l] = (int)(far - pequegnez); + factor_red[l] = (int)(upperLimit - pequegnez); pequegnez = pequegnez + chiquez; } } if (currentChapter == 5 && roomNumber == 54) { for (l = floorY1 - 1; l > 84; l--) { - factor_red[l] = (int)(far - pequegnez); + factor_red[l] = (int)(upperLimit - pequegnez); pequegnez = pequegnez + chiquez; } } -- cgit v1.2.3 From ef07d7e8a770f9ecd85d0915782775481acfef92 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jun 2008 12:02:34 +0000 Subject: Added patch from bug report #2001189 - "DRASCULA: Wrong intro music in Spanish version" svn-id: r32783 --- engines/drascula/animation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index b0877a2e3e..06868494b5 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -372,7 +372,11 @@ void DrasculaEngine::animation_1_1() { break; clearRoom(); - playMusic(2); + if (_lang == kSpanish) + playMusic(31); + else + playMusic(2); + pause(5); playFLI("intro.bin", 12); term_int = 1; -- cgit v1.2.3 From a2e6f35310b7f4fc4f4a1aa6ca3d5e7ab618b85d Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 25 Jun 2008 15:09:24 +0000 Subject: Implemented opcode: - 0x8D: o2_op8D (Didn't come up with a descriptive name yet) Compares ranges of x, y and mask parameters between two objects. Possibly some kind of an intersection testing function? svn-id: r32785 --- engines/cine/object.cpp | 23 +++++++++++++++++++++++ engines/cine/object.h | 2 ++ engines/cine/script_os.cpp | 21 +++++++++++---------- 3 files changed, 36 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 96048f5214..b00a636ae6 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -219,6 +219,29 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) { } } +/** + * Check if at least one of the range B's endpoints is inside range A, + * not counting the starting and ending points of range A. + * Used at least by Operation Stealth's opcode 0x8D i.e. 141. + */ +bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd) { + return (bStart > aStart && bStart < aEnd) || (bEnd > aStart && bEnd < aEnd); +} + +uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2) { + assert(objIdx1 < NUM_MAX_OBJECT && objIdx2 < NUM_MAX_OBJECT); + const objectStruct &obj1 = objectTable[objIdx1]; + const objectStruct &obj2 = objectTable[objIdx2]; + + if (compareRanges(obj1.x, obj1.x + xAdd1, obj2.x, obj2.x + xAdd2) && + compareRanges(obj1.y, obj1.y + yAdd1, obj2.y, obj2.y + yAdd2) && + compareRanges(obj1.mask, obj1.mask + maskAdd1, obj2.mask, obj2.mask + maskAdd2)) { + return kCmpEQ; + } else { + return 0; + } +} + uint16 compareObjectParam(byte objIdx, byte type, int16 value) { uint16 compareResult = 0; int16 objectParam = getObjectParam(objIdx, type); diff --git a/engines/cine/object.h b/engines/cine/object.h index 6252a628cb..12e72927e1 100644 --- a/engines/cine/object.h +++ b/engines/cine/object.h @@ -69,6 +69,8 @@ int16 getObjectParam(uint16 objIdx, uint16 paramIdx); void addObjectParam(byte objIdx, byte paramIdx, int16 newValue); void subObjectParam(byte objIdx, byte paramIdx, int16 newValue); +bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd); +uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2); uint16 compareObjectParam(byte objIdx, byte param1, int16 param2); } // End of namespace Cine diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index ffc0da5790..09ab5188a0 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -596,16 +596,17 @@ int FWScript::o2_stopObjectScript() { /*! \todo Implement this instruction */ int FWScript::o2_op8D() { - uint16 a = getNextWord(); - uint16 b = getNextWord(); - uint16 c = getNextWord(); - uint16 d = getNextWord(); - uint16 e = getNextWord(); - uint16 f = getNextWord(); - uint16 g = getNextWord(); - uint16 h = getNextWord(); - warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h); - // _currentScriptElement->compareResult = ... + uint16 objIdx1 = getNextWord(); + uint16 xAdd1 = getNextWord(); + uint16 yAdd1 = getNextWord(); + uint16 maskAdd1 = getNextWord(); + uint16 objIdx2 = getNextWord(); + uint16 xAdd2 = getNextWord(); + uint16 yAdd2 = getNextWord(); + uint16 maskAdd2 = getNextWord(); + debugC(5, kCineDebugScript, "Line: %d: o2_op8D(%d, %d, %d, %d, %d, %d, %d, %d)", _line, objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2); + + _compare = compareObjectParamRanges(objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2); return 0; } -- cgit v1.2.3 From d5d09208b4a03eb55697d8831bf87ba8a43385ec Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 25 Jun 2008 17:14:44 +0000 Subject: Implemented opcode: - 0x82: o2_modifySeqListElement (Was o2_op82) Seeks a matching element from the seqList and modifies its values. svn-id: r32786 --- engines/cine/script.h | 2 +- engines/cine/script_os.cpp | 10 +++++----- engines/cine/various.cpp | 13 +++++++++++++ engines/cine/various.h | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/cine/script.h b/engines/cine/script.h index 2b6acbba9b..fcd21990fa 100644 --- a/engines/cine/script.h +++ b/engines/cine/script.h @@ -237,7 +237,7 @@ protected: int o2_playSample(); int o2_playSampleAlt(); int o2_op81(); - int o2_op82(); + int o2_modifySeqListElement(); int o2_isSeqRunning(); int o2_gotoIfSupNearest(); int o2_gotoIfSupEquNearest(); diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index 09ab5188a0..5c6be12ab0 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -202,7 +202,7 @@ const Opcode OSScript::_opcodeTable[] = { /* 80 */ { &FWScript::o2_removeSeq, "bb" }, { &FWScript::o2_op81, "" }, /* TODO: Name this opcode properly. */ - { &FWScript::o2_op82, "bbwwb" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_modifySeqListElement, "bbwwb" }, { &FWScript::o2_isSeqRunning, "bb" }, /* 84 */ { &FWScript::o2_gotoIfSupNearest, "b" }, @@ -449,15 +449,15 @@ int FWScript::o2_op81() { return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o2_op82() { +int FWScript::o2_modifySeqListElement() { byte a = getNextByte(); byte b = getNextByte(); uint16 c = getNextWord(); uint16 d = getNextWord(); byte e = getNextByte(); - warning("STUB: o2_op82(%x, %x, %x, %x, %x)", a, b, c, d, e); + debugC(5, kCineDebugScript, "Line: %d: o2_modifySeqListElement(%d,%d,%d,%d,%d)", _line, a, b, c, d, e); + + modifySeqListElement(a, 0, b, c, d, e); return 0; } diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 9b98ddb253..f39ae4fb35 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1618,6 +1618,19 @@ void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, i seqList.insert(it, tmp); } +void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4) { + // Find a suitable list element and modify it + for (Common::List::iterator it = seqList.begin(); it != seqList.end(); ++it) { + if (it->objIdx == objIdx && it->var4 == var4Test) { + it->varC = param1; + it->var18 = param2; + it->var1A = param3; + it->var10 = it->var12 = param4; + break; + } + } +} + void computeMove1(SeqListElement &element, int16 x, int16 y, int16 param1, int16 param2, int16 x2, int16 y2) { element.var16 = 0; diff --git a/engines/cine/various.h b/engines/cine/various.h index 91662c16ff..17b11bf72a 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -138,6 +138,7 @@ void removeMessages(); void removeSeq(uint16 param1, uint16 param2, uint16 param3); uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8); +void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4); void processSeqList(void); bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y); -- cgit v1.2.3 From dee147eebfce779b834b98b81cdad4e76b3fd984 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 25 Jun 2008 18:51:44 +0000 Subject: Added FIXME about the broken implementation of opcode 0x9A (o2_wasZoneChecked). svn-id: r32789 --- engines/cine/script_os.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index 5c6be12ab0..c79da0e230 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -654,6 +654,7 @@ int FWScript::o2_loadBg() { */ int FWScript::o2_wasZoneChecked() { byte param = getNextByte(); + // FIXME: Using a wrong table here, it's not zoneData we want, but something else (zoneQuery) _compare = (param < 16 && zoneData[param]); debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param); return 0; -- cgit v1.2.3 From 1339a55389efa97e484457a8963b69364a98452d Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 25 Jun 2008 21:57:08 +0000 Subject: Implemented support for zoneQuery (Operation Stealth specific). Fixed opcodes (related to zoneQuery): - 0x08: o1_checkCollision - 0x9A: o2_wasZoneChecked NOTE: Savegame support for the zoneQuery data is broken svn-id: r32790 --- engines/cine/main_loop.cpp | 7 +++++++ engines/cine/script_fw.cpp | 20 +++++++++++++++++--- engines/cine/script_os.cpp | 3 +-- engines/cine/various.cpp | 4 ++++ engines/cine/various.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index 0c5096c0d6..6aa1ec1737 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -235,6 +235,13 @@ void CineEngine::mainLoop(int bootScriptIdx) { do { stopMusicAfterFadeOut(); di = executePlayerInput(); + + // Clear the zoneQuery table (Operation Stealth specific) + if (g_cine->getGameType() == Cine::GType_OS) { + for (uint i = 0; i < NUM_MAX_ZONE; i++) { + zoneQuery[i] = 0; + } + } processSeqList(); executeList1(); diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 845120c99e..b9dcad9877 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1764,18 +1764,32 @@ int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneI int16 lx = objectTable[objIdx].x + x; int16 ly = objectTable[objIdx].y + y; int16 idx; + int16 result = 0; for (int16 i = 0; i < numZones; i++) { idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); - assert(idx >= 0 && idx <= NUM_MAX_ZONE); + assert(idx >= 0 && idx < NUM_MAX_ZONE); + + // The zoneQuery table is updated here only in Operation Stealth + if (g_cine->getGameType() == Cine::GType_OS) { + if (zoneData[idx] >= 0 && zoneData[idx] < NUM_MAX_ZONE) { + zoneQuery[zoneData[idx]]++; + } + } if (zoneData[idx] == zoneIdx) { - return 1; + result = 1; + // Future Wars breaks out early on the first match, but + // Operation Stealth doesn't because it needs to update + // the zoneQuery table for the whole loop's period. + if (g_cine->getGameType() == Cine::GType_FW) { + break; + } } } - return 0; + return result; } uint16 compareVars(int16 a, int16 b) { diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index c79da0e230..f958c66fad 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -654,8 +654,7 @@ int FWScript::o2_loadBg() { */ int FWScript::o2_wasZoneChecked() { byte param = getNextByte(); - // FIXME: Using a wrong table here, it's not zoneData we want, but something else (zoneQuery) - _compare = (param < 16 && zoneData[param]); + _compare = (param < NUM_MAX_ZONE && zoneQuery[param]) ? 1 : 0; debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param); return 0; } diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index f39ae4fb35..640ca8a169 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -112,6 +112,7 @@ int16 objListTab[20]; uint16 exitEngine; uint16 zoneData[NUM_MAX_ZONE]; +uint16 zoneQuery[NUM_MAX_ZONE]; //!< Only exists in Operation Stealth void stopMusicAfterFadeOut(void) { @@ -391,6 +392,7 @@ bool brokenSave(Common::InSaveFile &fHandle) { } /*! \todo Implement Operation Stealth loading, this is obviously Future Wars only + * \todo Add support for loading the zoneQuery table (Operation Stealth specific) */ bool CineEngine::makeLoad(char *saveName) { int16 i; @@ -588,6 +590,8 @@ bool CineEngine::makeLoad(char *saveName) { return true; } +/*! \todo Add support for saving the zoneQuery table (Operation Stealth specific) + */ void makeSave(char *saveFileName) { int16 i; Common::OutSaveFile *fHandle; diff --git a/engines/cine/various.h b/engines/cine/various.h index 17b11bf72a..c17138e487 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -130,6 +130,7 @@ struct SelectedObjStruct { #define NUM_MAX_ZONE 16 extern uint16 zoneData[NUM_MAX_ZONE]; +extern uint16 zoneQuery[NUM_MAX_ZONE]; void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5); -- cgit v1.2.3 From 1d71ab7e1fcf8d1545a9e508c4e21dc10ced2270 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 25 Jun 2008 22:13:18 +0000 Subject: Fix for GCC warning (Warned about testing x >= 0 when x is unsigned and therefore the test is always true). svn-id: r32791 --- engines/cine/script_fw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index b9dcad9877..148e673095 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1773,7 +1773,7 @@ int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneI // The zoneQuery table is updated here only in Operation Stealth if (g_cine->getGameType() == Cine::GType_OS) { - if (zoneData[idx] >= 0 && zoneData[idx] < NUM_MAX_ZONE) { + if (zoneData[idx] < NUM_MAX_ZONE) { zoneQuery[zoneData[idx]]++; } } -- cgit v1.2.3 From b6adcca897963aae66ea68eac043f845500e11b1 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Thu, 26 Jun 2008 10:12:12 +0000 Subject: moved midi driver object creation to MidiPlayer class (to match delete call) svn-id: r32798 --- engines/touche/midi.cpp | 9 ++++++--- engines/touche/midi.h | 2 +- engines/touche/saveload.cpp | 3 --- engines/touche/touche.cpp | 6 +----- 4 files changed, 8 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index ce62849d2f..d77dbf5bfa 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -23,6 +23,7 @@ * */ +#include "common/config-manager.h" #include "common/stream.h" #include "sound/midiparser.h" @@ -31,9 +32,8 @@ namespace Touche { -MidiPlayer::MidiPlayer(MidiDriver *driver, bool nativeMT32) - : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0), _nativeMT32(nativeMT32) { - assert(_driver); +MidiPlayer::MidiPlayer() + : _driver(0), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) { memset(_channelsTable, 0, sizeof(_channelsTable)); memset(_channelsVolume, 0, sizeof(_channelsVolume)); open(); @@ -92,6 +92,9 @@ void MidiPlayer::setVolume(int volume) { } int MidiPlayer::open() { + int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + _driver = MidiDriver::createMidi(midiDriver); int ret = _driver->open(); if (ret == 0) { _parser = MidiParser::createParser_SMF(); diff --git a/engines/touche/midi.h b/engines/touche/midi.h index 3b128593db..a518a4bb29 100644 --- a/engines/touche/midi.h +++ b/engines/touche/midi.h @@ -46,7 +46,7 @@ public: NUM_CHANNELS = 16 }; - MidiPlayer(MidiDriver *driver, bool nativeMT32); + MidiPlayer(); ~MidiPlayer(); void play(Common::ReadStream &stream, int size, bool loop = false); diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp index eb647a1b42..4fcf6e114d 100644 --- a/engines/touche/saveload.cpp +++ b/engines/touche/saveload.cpp @@ -200,9 +200,6 @@ static void saveOrLoad(S &s, ProgramPointData &data) { saveOrLoad(s, data.order); } -template -static void saveOrLoadCommonArray(S &s, A &array); - template static void saveOrLoadCommonArray(Common::WriteStream &stream, A &array) { uint count = array.size(); diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 06ee28dae8..ac8e8a786a 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -91,11 +91,7 @@ int ToucheEngine::init() { setupOpcodes(); - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); - _midiPlayer = new MidiPlayer(driver, native_mt32); - + _midiPlayer = new MidiPlayer; _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); -- cgit v1.2.3 From 358d2ec44ab9a3d98afcf8419b1613c018688d0b Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Thu, 26 Jun 2008 10:12:47 +0000 Subject: fix possible oob access svn-id: r32799 --- engines/queen/resource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp index 5a8db74e3b..b3bd663baf 100644 --- a/engines/queen/resource.cpp +++ b/engines/queen/resource.cpp @@ -106,7 +106,7 @@ ResourceEntry *Resource::resourceEntry(const char *filename) const { re = &_resourceTable[cur]; break; } - } while (cur++ < _resourceEntries); + } while (++cur < _resourceEntries); #endif return re; } -- cgit v1.2.3 From 68c598a3f3ad904dab66a2219d97af9eb5a02ccd Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 26 Jun 2008 15:16:15 +0000 Subject: Comments update. svn-id: r32801 --- engines/cine/script_fw.cpp | 6 ++++++ engines/cine/script_os.cpp | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 148e673095..f84904ccc5 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1760,6 +1760,12 @@ int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { return zoneVar; } +/*! + * \todo Check whether updating the zoneQuery table is appropriate every time + * this function is called because this function is called also from elsewhere + * than simply o1_checkCollision (e.g. from addAni). In Operation Stealth's + * disassembly this probably isn't the case, so there may be weird side-effects. + */ int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) { int16 lx = objectTable[objIdx].x + x; int16 ly = objectTable[objIdx].y + y; diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index f958c66fad..62a5cc6aaa 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -650,8 +650,6 @@ int FWScript::o2_loadBg() { return 0; } -/*! \todo Check the current implementation for correctness - */ int FWScript::o2_wasZoneChecked() { byte param = getNextByte(); _compare = (param < NUM_MAX_ZONE && zoneQuery[param]) ? 1 : 0; -- cgit v1.2.3 From d7051a8ef7e9569bb0d13ef437c6605ce4dbe1cc Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 26 Jun 2008 15:44:26 +0000 Subject: Comments update. svn-id: r32802 --- engines/cine/script_os.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index 62a5cc6aaa..aeb5302c22 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -442,6 +442,7 @@ int FWScript::o2_removeSeq() { } /*! \todo Implement this instruction + * \note According to the scripts' opcode usage comparison this opcode isn't used at all. */ int FWScript::o2_op81() { warning("STUB: o2_op81()"); @@ -593,8 +594,6 @@ int FWScript::o2_stopObjectScript() { return 0; } -/*! \todo Implement this instruction - */ int FWScript::o2_op8D() { uint16 objIdx1 = getNextWord(); uint16 xAdd1 = getNextWord(); @@ -658,6 +657,7 @@ int FWScript::o2_wasZoneChecked() { } /*! \todo Implement this instruction + * \note According to the scripts' opcode usage comparison this opcode isn't used at all. */ int FWScript::o2_op9B() { uint16 a = getNextWord(); @@ -673,6 +673,7 @@ int FWScript::o2_op9B() { } /*! \todo Implement this instruction + * \note According to the scripts' opcode usage comparison this opcode isn't used at all. */ int FWScript::o2_op9C() { uint16 a = getNextWord(); @@ -712,6 +713,7 @@ int FWScript::o2_setAdditionalBgVScroll() { } /*! \todo Implement this instruction + * \note According to the scripts' opcode usage comparison this opcode isn't used at all. */ int FWScript::o2_op9F() { warning("o2_op9F()"); -- cgit v1.2.3 From fafda89d0c53a2ac9b0521c1e4549388f14ccea0 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Thu, 26 Jun 2008 16:51:02 +0000 Subject: Fixed Symbian buildsystem for new defines. Fixed ARM asm syntax for Symbian build. svn-id: r32803 --- engines/scumm/gfxARM.s | 2 +- engines/scumm/smush/codec47ARM.s | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s index cd3e5c7dad..83aaa78927 100644 --- a/engines/scumm/gfxARM.s +++ b/engines/scumm/gfxARM.s @@ -59,7 +59,7 @@ asmDrawStripToScreen: CMP r1,#4 @ If width<4 BLT end @ return - @ Width &= ~4 ? What's that about then? Width &= ~3 I could have + @ Width &= ~4 ? What''s that about then? Width &= ~3 I could have @ understood... BIC r1,r1,#4 diff --git a/engines/scumm/smush/codec47ARM.s b/engines/scumm/smush/codec47ARM.s index 81bfdb2d22..73341c117f 100644 --- a/engines/scumm/smush/codec47ARM.s +++ b/engines/scumm/smush/codec47ARM.s @@ -80,7 +80,7 @@ level1codeFD: LDRB r9,[r8,#384] @ r9 = l = tmp_ptr[384] LDRB r6,[r1],#1 @ r6 = val = *_d_src++ ADD r12,r8,#384 @ r12= &tmp_ptr[384] - @ I don't really believe the next 2 lines are necessary, but... + @ I don''t really believe the next 2 lines are necessary, but... CMP r9,#0 BEQ level1codeFD_over1 level1codeFD_loop1: @@ -94,7 +94,7 @@ level1codeFD_over1: LDRB r9,[r12,#1] @ r9 = l = tmp_ptr[385] LDRB r6,[r1],#1 @ r6 = val = *_d_src++ SUB r12,r12,#256 @ r12= &tmp_ptr[128] (256 = 384-128) - @ I don't really believe the next 2 lines are necessary, but... + @ I don''t really believe the next 2 lines are necessary, but... CMP r9,#0 BEQ level1codeFD_over2 level1codeFD_loop2: @@ -219,7 +219,7 @@ level2codeFD: LDRB r9,[r8,#96] @ r9 = l = tmp_ptr[96] LDRB r6,[r1],#1 @ r6 = val = *_d_src++ ADD r12,r8,#32 @ r12 = tmp_ptr + 32 - @ I don't really believe the next 2 lines are necessary, but... + @ I don''t really believe the next 2 lines are necessary, but... CMP r9,#0 BEQ level2codeFD_over1 level2codeFD_loop1: @@ -232,7 +232,7 @@ level2codeFD_loop1: level2codeFD_over1: LDRB r9,[r12,#65] @ r9 = l = tmp_ptr[97] (65 = 97-32) LDRB r6,[r1],#1 @ r6 = val = *_d_src++ - @ I don't really believe the next 2 lines are necessary, but... + @ I don''t really believe the next 2 lines are necessary, but... CMP r9,#0 MOVEQ PC,R14 level2codeFD_loop2: -- cgit v1.2.3 From 971f27beb27cd853df7f20dbd21dc92e88b3f697 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 26 Jun 2008 17:29:21 +0000 Subject: Fixed opcode: - 0x83: o2_isSeqRunning (Should it be named o2_isSeqNotRunning?) -- Added previously missing test part -- Negated the result (It was backwards before!) svn-id: r32804 --- engines/cine/script_os.cpp | 4 +++- engines/cine/various.cpp | 9 ++++++--- engines/cine/various.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index aeb5302c22..78b6c55564 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -462,11 +462,13 @@ int FWScript::o2_modifySeqListElement() { return 0; } +/*! \todo Check whether this opcode's name is backwards (i.e. should it be o2_isSeqNotRunning?) + */ int FWScript::o2_isSeqRunning() { byte a = getNextByte(); byte b = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b); + debugC(5, kCineDebugScript, "Line: %d: o2_isSeqRunning(%d,%d)", _line, a, b); if (isSeqRunning(a, 0, b)) { _compare = 1; diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 640ca8a169..20d9edc5de 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1586,16 +1586,19 @@ void removeSeq(uint16 param1, uint16 param2, uint16 param3) { } } -uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { +bool isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { Common::List::iterator it; for (it = seqList.begin(); it != seqList.end(); ++it) { if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) { - return 1; + // Just to be on the safe side there's a restriction of the + // addition's result to 16-bit arithmetic here like in the + // original. It's possible that it's not strictly needed. + return ((it->var14 + it->var16) & 0xFFFF) == 0; } } - return 0; + return true; } void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) { diff --git a/engines/cine/various.h b/engines/cine/various.h index c17138e487..d05447fb40 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -137,7 +137,7 @@ void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 par void removeMessages(); void removeSeq(uint16 param1, uint16 param2, uint16 param3); -uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); +bool isSeqRunning(uint16 param1, uint16 param2, uint16 param3); void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8); void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4); void processSeqList(void); -- cgit v1.2.3 From 7b30081be292d793914e44939923a67c2745b914 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 26 Jun 2008 19:42:59 +0000 Subject: - improved hof music support for fm-towns (driver for *.twn tracks) (still needs quite some work) - some PC-98 music support since it uses a very similar driver, but this can't be considered working yet) - Kyra 1 PC-98 music doen't work at all since I haven't figured out yet how to turn track numbers into the corresponding music file names (might require a hard coded track map) svn-id: r32807 --- engines/kyra/detection.cpp | 59 +- engines/kyra/kyra_v1.cpp | 12 +- engines/kyra/screen.cpp | 16 +- engines/kyra/sound.h | 55 +- engines/kyra/sound_lok.cpp | 9 +- engines/kyra/sound_towns.cpp | 1725 +++++++++++++++++++++++++++++++++++++----- engines/kyra/staticres.cpp | 36 +- 7 files changed, 1709 insertions(+), 203 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 344121b503..1e174bdfcf 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -44,6 +44,7 @@ namespace { #define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id } #define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA1) #define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1) #define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, Kyra::GI_KYRA1) #define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, Kyra::GI_KYRA1) @@ -66,6 +67,28 @@ const KYRAGameDescription adGameDescs[] = { { "kyra1", 0, + AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + { + { + "kyra1", + 0, + AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + { + { + "kyra1", + "Extracted", AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), Common::EN_ANY, Common::kPlatformPC, @@ -76,7 +99,7 @@ const KYRAGameDescription adGameDescs[] = { { { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), Common::EN_ANY, Common::kPlatformPC, @@ -87,7 +110,7 @@ const KYRAGameDescription adGameDescs[] = { { { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), Common::FR_FRA, Common::kPlatformPC, @@ -98,7 +121,7 @@ const KYRAGameDescription adGameDescs[] = { { { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), Common::DE_DEU, Common::kPlatformPC, @@ -109,7 +132,7 @@ const KYRAGameDescription adGameDescs[] = { { // from Arne.F { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), Common::DE_DEU, Common::kPlatformPC, @@ -120,7 +143,7 @@ const KYRAGameDescription adGameDescs[] = { { // from VooD { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), Common::ES_ESP, Common::kPlatformPC, @@ -131,7 +154,7 @@ const KYRAGameDescription adGameDescs[] = { { // floppy 1.8 from clemmy { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), Common::ES_ESP, Common::kPlatformPC, @@ -142,7 +165,7 @@ const KYRAGameDescription adGameDescs[] = { { // from gourry { "kyra1", - 0, + "Extracted", AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), Common::IT_ITA, Common::kPlatformPC, @@ -463,6 +486,28 @@ const KYRAGameDescription adGameDescs[] = { }, KYRA2_TOWNS_SJIS_FLAGS }, + { // PC-9821 + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::EN_ANY, + Common::kPlatformPC98, + Common::ADGF_NO_FLAGS + }, + KYRA2_TOWNS_FLAGS + }, + { + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::JA_JPN, + Common::kPlatformPC98, + Common::ADGF_NO_FLAGS + }, + KYRA2_TOWNS_SJIS_FLAGS + }, // Kyra3 diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 1cc1d728bf..980c181c4e 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -107,14 +107,16 @@ int KyraEngine_v1::init() { // "KYRA1: Crash on exceeded polyphony" for more information). int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/); - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { - // TODO: currently we don't support the PC98 sound data, - // but since it has the FM-Towns data files, we just use the - // FM-Towns driver + if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) _sound = new SoundTowns(this, _mixer); else - _sound = new SoundTowns_v2(this, _mixer); + _sound = new SoundTownsPC98_v2(this, _mixer); + } else if (_flags.platform == Common::kPlatformPC98) { + if (_flags.gameID == GI_KYRA1) + _sound = new SoundPC98(this, _mixer); + else + _sound = new SoundTownsPC98_v2(this, _mixer); } else if (midiDriver == MD_ADLIB) { _sound = new SoundAdlibPC(this, _mixer); assert(_sound); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index f00c47ceea..6e7a88b1a3 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -92,9 +92,19 @@ bool Screen::init() { if (_useSJIS) { if (!_sjisFontData) { - _sjisFontData = _vm->resource()->fileData("FMT_FNT.ROM", 0); - if (!_sjisFontData) - error("missing font rom ('FMT_FNT.ROM') required for this version"); + // we use the FM-Towns font rom for PC-98, too, until we feel + // like adding support for the PC-98 font + //if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { + // FM-Towns + _sjisFontData = _vm->resource()->fileData("FMT_FNT.ROM", 0); + if (!_sjisFontData) + error("missing font rom ('FMT_FNT.ROM') required for this version"); + /*} else { + // PC-98 + _sjisFontData = _vm->resource()->fileData("FONT.ROM", 0); + if (!_sjisFontData) + error("missing font rom ('FONT.ROM') required for this version"); + }*/ } if (!_sjisTempPage) { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 1baeb3064a..c08c531ab9 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -73,7 +73,8 @@ public: kAdlib, kMidiMT32, kMidiGM, - kTowns + kTowns, + kPC98 }; virtual kType getMusicType() const = 0; @@ -382,7 +383,9 @@ private: Common::Mutex _mutex; }; -class SoundTowns_EuphonyDriver; +class Towns_EuphonyDriver; +class TownsPC98_OpnDriver; + class SoundTowns : public MidiDriver, public Sound { public: SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer); @@ -417,6 +420,7 @@ public: static float semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey, uint32 sampleRate, uint32 outputRate, int32 pitchWheel); + private: bool loadInstruments(); void playEuphonyTrack(uint32 offset, int loop); @@ -430,7 +434,7 @@ private: uint _sfxFileIndex; uint8 *_sfxFileData; - SoundTowns_EuphonyDriver * _driver; + Towns_EuphonyDriver * _driver; MidiParser * _parser; Common::Mutex _mutex; @@ -439,13 +443,38 @@ private: const uint8 *_sfxWDTable; }; -//class SoundTowns_v2_TwnDriver; -class SoundTowns_v2 : public Sound { +class SoundPC98 : public Sound { public: - SoundTowns_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundTowns_v2(); + SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer); + ~SoundPC98(); - kType getMusicType() const { return kTowns; } + virtual kType getMusicType() const { return kPC98; } + + bool init(); + + void process() {} + void loadSoundFile(uint file) {} + + void playTrack(uint8 track); + void haltTrack(); + void beginFadeOut(); + + int32 voicePlay(const char *file, bool isSfx = false) { return -1; } + void playSoundEffect(uint8); + +protected: + int _lastTrack; + uint8 *_musicTrackData; + uint8 *_sfxTrackData; + TownsPC98_OpnDriver *_driver; +}; + +class SoundTownsPC98_v2 : public Sound { +public: + SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer); + ~SoundTownsPC98_v2(); + + kType getMusicType() const { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; } bool init(); void process(); @@ -459,13 +488,11 @@ public: int32 voicePlay(const char *file, bool isSfx = false); void playSoundEffect(uint8) {} -private: - int _lastTrack; - +protected: Audio::AudioStream *_currentSFX; - - //SoundTowns_v2_TwnDriver *_driver; - uint8 *_twnTrackData; + int _lastTrack; + uint8 *_musicTrackData; + TownsPC98_OpnDriver *_driver; }; class MixedSoundDriver : public Sound { diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index 8a1d16a6b1..d320536507 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -43,7 +43,7 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { if (restart) _lastMusicCommand = -1; - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { + if (_flags.platform == Common::kPlatformFMTowns) { if (command == 1) { _sound->beginFadeOut(); } else if (command >= 35 && command <= 38) { @@ -56,6 +56,13 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { } else { _sound->haltTrack(); } + } else if (_flags.platform == Common::kPlatformPC98) { + + ////////////// + //// TODO //// + ////////////// + _sound->playTrack(command); + } else { KyraEngine_v1::snd_playWanderScoreViaMap(command, restart); } diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index c0e4dd70a9..a6457f509b 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -34,18 +34,21 @@ #include "common/util.h" +#ifdef _MSC_VER +#define _USE_MATH_DEFINES +#endif #include #define EUPHONY_FADEOUT_TICKS 600 namespace Kyra { -enum ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; +enum EnvelopeState { s_ready, s_attacking, s_decaying, s_sustaining, s_releasing }; -class MidiChannel_EuD : public MidiChannel { +class Towns_EuphonyChannel : public MidiChannel { public: - MidiChannel_EuD() {} - ~MidiChannel_EuD() {} + Towns_EuphonyChannel() {} + ~Towns_EuphonyChannel() {} virtual void nextTick(int32 *outbuf, int buflen) = 0; virtual void rate(uint16 r) = 0; @@ -54,10 +57,10 @@ protected: uint16 _rate; }; -class MidiChannel_EuD_FM : public MidiChannel_EuD { +class Towns_EuphonyFmChannel : public Towns_EuphonyChannel { public: - MidiChannel_EuD_FM(); - virtual ~MidiChannel_EuD_FM(); + Towns_EuphonyFmChannel(); + virtual ~Towns_EuphonyFmChannel(); void nextTick(int32 *outbuf, int buflen); void rate(uint16 r); @@ -79,13 +82,13 @@ protected: Voice2612 *_voice; }; -class MidiChannel_EuD_WAVE : public MidiChannel_EuD { +class Towns_EuphonyPcmChannel : public Towns_EuphonyChannel { public: void nextTick(int32 *outbuf, int buflen); void rate(uint16 r); - MidiChannel_EuD_WAVE(); - virtual ~MidiChannel_EuD_WAVE(); + Towns_EuphonyPcmChannel(); + virtual ~Towns_EuphonyPcmChannel(); // MidiChannel interface MidiDriver *device() { return 0; } @@ -126,9 +129,9 @@ protected: int32 keyOffset; int32 keyNote; const int8 *_samples; - } * _snd[8]; + } *_snd[8]; struct Env { - ChannelState state; + EnvelopeState state; int32 currentLevel; int32 rate; int32 tickCount; @@ -141,40 +144,39 @@ protected: int32 releaseRate; int32 rootKeyOffset; int32 size; - } * _env[8]; - } * _voice; + } *_env[8]; + } *_voice; }; -class SoundTowns_EuphonyTrackQueue { +class Towns_EuphonyTrackQueue { public: - SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDriver *driver, SoundTowns_EuphonyTrackQueue *last); - ~SoundTowns_EuphonyTrackQueue() {} + Towns_EuphonyTrackQueue(Towns_EuphonyDriver *driver, Towns_EuphonyTrackQueue *last); + ~Towns_EuphonyTrackQueue() {} - void release(); + Towns_EuphonyTrackQueue *release(); void initDriver(); - void loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop = 0); - void loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop = 0); + void loadDataToCurrentPosition(uint8 *trackdata, uint32 size, bool loop = 0); + void loadDataToEndOfQueue(uint8 *trackdata, uint32 size, bool loop = 0); void setPlayBackStatus(bool playing); - SoundTowns_EuphonyTrackQueue * reset(); bool isPlaying() {return _playing; } - uint8 * trackData() {return _trackData; } + const uint8 * trackData() {return _trackData; } bool _loop; - SoundTowns_EuphonyTrackQueue * _next; + Towns_EuphonyTrackQueue *_next; private: - uint8 * _trackData; - uint8 * _used; - uint8 * _fchan; - uint8 * _wchan; + uint8 *_trackData; + uint8 *_used; + uint8 *_fchan; + uint8 *_wchan; bool _playing; - SoundTowns_EuphonyDriver * _driver; - SoundTowns_EuphonyTrackQueue * _last; + Towns_EuphonyDriver *_driver; + Towns_EuphonyTrackQueue *_last; }; -class MidiParser_EuD : public MidiParser { +class Towns_EuphonyParser : public MidiParser { public: - MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue); + Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue); bool loadMusic (byte *data, uint32 size); int32 calculateTempo(int16 val); @@ -183,11 +185,11 @@ protected: void resetTracking(); void setup(); - byte * _enable; - byte * _mode; - byte * _channel; - byte * _adjVelo; - int8 * _adjNote; + byte *_enable; + byte *_mode; + byte *_channel; + byte *_adjVelo; + int8 *_adjNote; uint8 _firstBaseTickStep; uint8 _nextBaseTickStep; @@ -195,13 +197,13 @@ protected: uint32 _baseTick; byte _tempo[3]; - SoundTowns_EuphonyTrackQueue * _queue; + Towns_EuphonyTrackQueue *_queue; }; -class SoundTowns_EuphonyDriver : public MidiDriver_Emulated { +class Towns_EuphonyDriver : public MidiDriver_Emulated { public: - SoundTowns_EuphonyDriver(Audio::Mixer *mixer); - virtual ~SoundTowns_EuphonyDriver(); + Towns_EuphonyDriver(Audio::Mixer *mixer); + virtual ~Towns_EuphonyDriver(); int open(); void close(); @@ -213,7 +215,7 @@ public: void loadFmInstruments(const byte *instr); void loadWaveInstruments(const byte *instr); - SoundTowns_EuphonyTrackQueue * queue() { return _queue; } + Towns_EuphonyTrackQueue *queue() { return _queue; } MidiChannel *allocateChannel() { return 0; } MidiChannel *getPercussionChannel() { return 0; } @@ -237,10 +239,10 @@ protected: void generateSamples(int16 *buf, int len); - MidiChannel_EuD_FM *_fChannel[6]; - MidiChannel_EuD_WAVE *_wChannel[8]; - MidiChannel_EuD * _channel[16]; - SoundTowns_EuphonyTrackQueue * _queue; + Towns_EuphonyFmChannel *_fChannel[6]; + Towns_EuphonyPcmChannel *_wChannel[8]; + Towns_EuphonyChannel *_channel[16]; + Towns_EuphonyTrackQueue *_queue; int _volume; bool _fading; @@ -251,23 +253,23 @@ protected: int8 * _waveSounds[10]; }; -MidiChannel_EuD_FM::MidiChannel_EuD_FM() { +Towns_EuphonyFmChannel::Towns_EuphonyFmChannel() { _voice = new Voice2612; } -MidiChannel_EuD_FM::~MidiChannel_EuD_FM() { +Towns_EuphonyFmChannel::~Towns_EuphonyFmChannel() { delete _voice; } -void MidiChannel_EuD_FM::noteOn(byte note, byte onVelo) { +void Towns_EuphonyFmChannel::noteOn(byte note, byte onVelo) { _voice->noteOn(note, onVelo); } -void MidiChannel_EuD_FM::noteOff(byte note) { +void Towns_EuphonyFmChannel::noteOff(byte note) { _voice->noteOff(note); } -void MidiChannel_EuD_FM::controlChange(byte control, byte value) { +void Towns_EuphonyFmChannel::controlChange(byte control, byte value) { if (control == 121) { // Reset controller delete _voice; @@ -279,25 +281,25 @@ void MidiChannel_EuD_FM::controlChange(byte control, byte value) { } } -void MidiChannel_EuD_FM::sysEx_customInstrument(uint32, const byte *fmInst) { +void Towns_EuphonyFmChannel::sysEx_customInstrument(uint32, const byte *fmInst) { _voice->_rate = _rate; _voice->setInstrument(fmInst); } -void MidiChannel_EuD_FM::pitchBend(int16 value) { +void Towns_EuphonyFmChannel::pitchBend(int16 value) { _voice->pitchBend(value); } -void MidiChannel_EuD_FM::nextTick(int32 *outbuf, int buflen) { +void Towns_EuphonyFmChannel::nextTick(int32 *outbuf, int buflen) { _voice->nextTick((int*) outbuf, buflen); } -void MidiChannel_EuD_FM::rate(uint16 r) { +void Towns_EuphonyFmChannel::rate(uint16 r) { _rate = r; _voice->_rate = r; } -MidiChannel_EuD_WAVE::MidiChannel_EuD_WAVE() { +Towns_EuphonyPcmChannel::Towns_EuphonyPcmChannel() { _voice = new Voice; for (uint8 i = 0; i < 8; i++) { _voice->_env[i] = new Voice::Env; @@ -310,7 +312,7 @@ MidiChannel_EuD_WAVE::MidiChannel_EuD_WAVE() { _current = -1; } -MidiChannel_EuD_WAVE::~MidiChannel_EuD_WAVE() { +Towns_EuphonyPcmChannel::~Towns_EuphonyPcmChannel() { for (uint8 i = 0; i < 8; i++) { if (_voice->_snd[i]) delete _voice->_snd[i]; @@ -319,7 +321,7 @@ MidiChannel_EuD_WAVE::~MidiChannel_EuD_WAVE() { delete _voice; } -void MidiChannel_EuD_WAVE::noteOn(byte note, byte onVelo) { +void Towns_EuphonyPcmChannel::noteOn(byte note, byte onVelo) { _note = note; velocity(onVelo); _phase = 0; @@ -329,24 +331,24 @@ void MidiChannel_EuD_WAVE::noteOn(byte note, byte onVelo) { break; } - _voice->_env[_current]->state = _s_attacking; + _voice->_env[_current]->state = s_attacking; _voice->_env[_current]->currentLevel = 0; _voice->_env[_current]->rate = _rate; _voice->_env[_current]->tickCount = 0; } -void MidiChannel_EuD_WAVE::noteOff(byte note) { +void Towns_EuphonyPcmChannel::noteOff(byte note) { if (_current == -1) return; - if (_voice->_env[_current]->state == _s_ready) + if (_voice->_env[_current]->state == s_ready) return; - _voice->_env[_current]->state = _s_releasing; + _voice->_env[_current]->state = s_releasing; _voice->_env[_current]->releaseLevel = _voice->_env[_current]->currentLevel; _voice->_env[_current]->tickCount = 0; } -void MidiChannel_EuD_WAVE::controlChange(byte control, byte value) { +void Towns_EuphonyPcmChannel::controlChange(byte control, byte value) { switch (control) { case 0x07: // volume @@ -377,7 +379,7 @@ void MidiChannel_EuD_WAVE::controlChange(byte control, byte value) { } } -void MidiChannel_EuD_WAVE::sysEx_customInstrument(uint32 type, const byte *fmInst) { +void Towns_EuphonyPcmChannel::sysEx_customInstrument(uint32 type, const byte *fmInst) { if (type == 0x80) { for (uint8 i = 0; i < 8; i++) { const byte * const* pos = (const byte * const*) fmInst; @@ -406,7 +408,7 @@ void MidiChannel_EuD_WAVE::sysEx_customInstrument(uint32 type, const byte *fmIns _voice->split[i] = READ_LE_UINT16(fmInst + 16 + 2 * i); _voice->id[i] = READ_LE_UINT32(fmInst + 32 + 4 * i); _voice->_snd[i] = 0; - _voice->_env[i]->state = _s_ready; + _voice->_env[i]->state = s_ready; _voice->_env[i]->currentLevel = 0; _voice->_env[i]->totalLevel = *(fmInst + 64 + 8 * i); _voice->_env[i]->attackRate = *(fmInst + 65 + 8 * i) * 10; @@ -419,11 +421,11 @@ void MidiChannel_EuD_WAVE::sysEx_customInstrument(uint32 type, const byte *fmIns } } -void MidiChannel_EuD_WAVE::pitchBend(int16 value) { +void Towns_EuphonyPcmChannel::pitchBend(int16 value) { _frequencyOffs = value; } -void MidiChannel_EuD_WAVE::nextTick(int32 *outbuf, int buflen) { +void Towns_EuphonyPcmChannel::nextTick(int32 *outbuf, int buflen) { if (_current == -1 || !_voice->_snd[_current] || !_voice->_env[_current]->state || !_velocity) { velocity(0); _current = -1; @@ -475,13 +477,13 @@ void MidiChannel_EuD_WAVE::nextTick(int32 *outbuf, int buflen) { } } -void MidiChannel_EuD_WAVE::evpNextTick() { +void Towns_EuphonyPcmChannel::evpNextTick() { switch (_voice->_env[_current]->state) { - case _s_ready: + case s_ready: _voice->_env[_current]->currentLevel = 0; return; - case _s_attacking: + case s_attacking: if (_voice->_env[_current]->attackRate == 0) _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; else if (_voice->_env[_current]->attackRate >= 1270) @@ -493,12 +495,12 @@ void MidiChannel_EuD_WAVE::evpNextTick() { if (_voice->_env[_current]->currentLevel >= _voice->_env[_current]->totalLevel) { _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; - _voice->_env[_current]->state = _s_decaying; + _voice->_env[_current]->state = s_decaying; _voice->_env[_current]->tickCount = 0; } break; - case _s_decaying: + case s_decaying: if (_voice->_env[_current]->decayRate == 0) _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; else if (_voice->_env[_current]->decayRate >= 1270) @@ -512,12 +514,12 @@ void MidiChannel_EuD_WAVE::evpNextTick() { if (_voice->_env[_current]->currentLevel <= _voice->_env[_current]->sustainLevel) { _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; - _voice->_env[_current]->state = _s_sustaining; + _voice->_env[_current]->state = s_sustaining; _voice->_env[_current]->tickCount = 0; } break; - case _s_sustaining: + case s_sustaining: if (_voice->_env[_current]->sustainRate == 0) _voice->_env[_current]->currentLevel = 0; else if (_voice->_env[_current]->sustainRate >= 2540) @@ -531,12 +533,12 @@ void MidiChannel_EuD_WAVE::evpNextTick() { if (_voice->_env[_current]->currentLevel <= 0) { _voice->_env[_current]->currentLevel = 0; - _voice->_env[_current]->state = _s_ready; + _voice->_env[_current]->state = s_ready; _voice->_env[_current]->tickCount = 0; } break; - case _s_releasing: + case s_releasing: if (_voice->_env[_current]->releaseRate == 0) _voice->_env[_current]->currentLevel = 0; else if (_voice->_env[_current]->releaseRate >= 1270) @@ -550,7 +552,7 @@ void MidiChannel_EuD_WAVE::evpNextTick() { if (_voice->_env[_current]->currentLevel <= 0) { _voice->_env[_current]->currentLevel = 0; - _voice->_env[_current]->state = _s_ready; + _voice->_env[_current]->state = s_ready; } break; @@ -559,15 +561,15 @@ void MidiChannel_EuD_WAVE::evpNextTick() { } } -void MidiChannel_EuD_WAVE::rate(uint16 r) { +void Towns_EuphonyPcmChannel::rate(uint16 r) { _rate = r; } -void MidiChannel_EuD_WAVE::velocity(int velo) { +void Towns_EuphonyPcmChannel::velocity(int velo) { _velocity = velo; } -SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer) +Towns_EuphonyDriver::Towns_EuphonyDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) { _volume = 255; _fadestate = EUPHONY_FADEOUT_TICKS; @@ -576,9 +578,9 @@ SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer) MidiDriver_YM2612::createLookupTables(); for (uint8 i = 0; i < 6; i++) - _channel[i] = _fChannel[i] = new MidiChannel_EuD_FM; + _channel[i] = _fChannel[i] = new Towns_EuphonyFmChannel; for (uint8 i = 0; i < 8; i++) - _channel[i + 6] = _wChannel[i] = new MidiChannel_EuD_WAVE; + _channel[i + 6] = _wChannel[i] = new Towns_EuphonyPcmChannel; _channel[14] = _channel[15] = 0; _fmInstruments = _waveInstruments = 0; @@ -587,10 +589,10 @@ SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer) rate(getRate()); fading(0); - _queue = new SoundTowns_EuphonyTrackQueue(this, 0); + _queue = new Towns_EuphonyTrackQueue(this, 0); } -SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() { +Towns_EuphonyDriver::~Towns_EuphonyDriver() { for (int i = 0; i < 6; i++) delete _fChannel[i]; for (int i = 0; i < 8; i++) @@ -622,7 +624,7 @@ SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() { } } -int SoundTowns_EuphonyDriver::open() { +int Towns_EuphonyDriver::open() { if (_isOpen) return MERR_ALREADY_OPEN; MidiDriver_Emulated::open(); @@ -633,18 +635,18 @@ int SoundTowns_EuphonyDriver::open() { return 0; } -void SoundTowns_EuphonyDriver::close() { +void Towns_EuphonyDriver::close() { if (!_isOpen) return; _isOpen = false; _mixer->stopHandle(_mixerSoundHandle); } -void SoundTowns_EuphonyDriver::send(uint32 b) { +void Towns_EuphonyDriver::send(uint32 b) { send(b & 0xF, b & 0xFFFFFFF0); } -void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) { +void Towns_EuphonyDriver::send(byte chan, uint32 b) { byte param2 = (byte) ((b >> 16) & 0xFF); byte param1 = (byte) ((b >> 8) & 0xFF); byte cmd = (byte) (b & 0xF0); @@ -703,18 +705,18 @@ void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) { _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000); break; default: - warning("SoundTowns_EuphonyDriver: Unknown send() command 0x%02X", cmd); + warning("Towns_EuphonyDriver: Unknown send() command 0x%02X", cmd); } } -void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) { +void Towns_EuphonyDriver::loadFmInstruments(const byte *instr) { if (_fmInstruments) delete[] _fmInstruments; _fmInstruments = new uint8[0x1800]; memcpy(_fmInstruments, instr, 0x1800); } -void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { +void Towns_EuphonyDriver::loadWaveInstruments(const byte *instr) { if (_waveInstruments) delete[] _waveInstruments; _waveInstruments = new uint8[0x1000]; @@ -739,24 +741,24 @@ void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { } -void SoundTowns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) { +void Towns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) { _channel[midiChannelNumber] = _fChannel[fmChannelNumber]; } -void SoundTowns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) { +void Towns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) { _channel[midiChannelNumber] = _wChannel[waveChannelNumber]; } -void SoundTowns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) { +void Towns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) { _channel[midiChannelNumber] = 0; } -void SoundTowns_EuphonyDriver::generateSamples(int16 *data, int len) { +void Towns_EuphonyDriver::generateSamples(int16 *data, int len) { memset(data, 0, 2 * sizeof(int16) * len); nextTick(data, len); } -void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) { +void Towns_EuphonyDriver::nextTick(int16 *buf1, int buflen) { int32 *buf0 = (int32 *)buf1; for (int i = 0; i < ARRAYSIZE(_channel); i++) { @@ -779,33 +781,33 @@ void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) { } } -void SoundTowns_EuphonyDriver::rate(uint16 r) { +void Towns_EuphonyDriver::rate(uint16 r) { for (uint8 i = 0; i < 16; i++) { if (_channel[i]) _channel[i]->rate(r); } } -void SoundTowns_EuphonyDriver::fading(bool status) { +void Towns_EuphonyDriver::fading(bool status) { _fading = status; if (!_fading) _fadestate = EUPHONY_FADEOUT_TICKS; } -MidiParser_EuD::MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue) : MidiParser(), +Towns_EuphonyParser::Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue) : MidiParser(), _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) { _initialTempo = calculateTempo(0x5a); _queue = queue; } -void MidiParser_EuD::parseNextEvent(EventInfo &info) { +void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { byte *pos = _position._play_pos; if (_queue->_next) { if (info.ext.type == 0x2F) { unloadMusic(); memset(&info, 0, sizeof(EventInfo)); - pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806; + pos = _position._play_pos = _tracks[0] = (byte*) _queue->trackData() + 0x806; } else if (_active_track == 255) { _queue = _queue->_next; setup(); @@ -920,15 +922,14 @@ void MidiParser_EuD::parseNextEvent(EventInfo &info) { _position._play_pos = pos; } -bool MidiParser_EuD::loadMusic(byte *data, uint32 size) { +bool Towns_EuphonyParser::loadMusic(byte *data, uint32 size) { bool loop = _autoLoop; if (_queue->isPlaying() && !_queue->_loop) { _queue->loadDataToEndOfQueue(data, size, loop); } else { unloadMusic(); - _queue = _queue->reset(); - _queue->release(); + _queue = _queue->release(); _queue->loadDataToCurrentPosition(data, size, loop); setup(); setTrack(0); @@ -937,7 +938,7 @@ bool MidiParser_EuD::loadMusic(byte *data, uint32 size) { return true; } -int32 MidiParser_EuD::calculateTempo(int16 val) { +int32 Towns_EuphonyParser::calculateTempo(int16 val) { int32 tempo = val; if (tempo < 0) @@ -953,7 +954,7 @@ int32 MidiParser_EuD::calculateTempo(int16 val) { return tempo; } -void MidiParser_EuD::resetTracking() { +void Towns_EuphonyParser::resetTracking() { MidiParser::resetTracking(); _nextBaseTickStep = _firstBaseTickStep; @@ -962,8 +963,8 @@ void MidiParser_EuD::resetTracking() { _queue->setPlayBackStatus(false); } -void MidiParser_EuD::setup() { - uint8 *data = _queue->trackData(); +void Towns_EuphonyParser::setup() { + uint8 *data = (uint8 *) _queue->trackData(); if (!data) return; _queue->initDriver(); @@ -984,7 +985,7 @@ void MidiParser_EuD::setup() { _tracks[0] = data + 0x806; } -SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last) { +Towns_EuphonyTrackQueue::Towns_EuphonyTrackQueue(Towns_EuphonyDriver * driver, Towns_EuphonyTrackQueue * last) { _trackData = 0; _next = 0; _driver = driver; @@ -993,22 +994,15 @@ SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDri _playing = false; } -void SoundTowns_EuphonyTrackQueue::setPlayBackStatus(bool playing) { - SoundTowns_EuphonyTrackQueue * i = this; +void Towns_EuphonyTrackQueue::setPlayBackStatus(bool playing) { + Towns_EuphonyTrackQueue * i = this; do { i->_playing = playing; i = i->_next; } while (i); } -SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() { - SoundTowns_EuphonyTrackQueue * i = this; - while (i->_last) - i = i->_last; - return i; -} - -void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) { +void Towns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) { if (_trackData) delete[] _trackData; _trackData = new uint8[0xC58A]; @@ -1022,17 +1016,17 @@ void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, _playing = false; } -void SoundTowns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) { +void Towns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) { if (!_trackData) { loadDataToCurrentPosition(trackdata, size, loop); return; } - SoundTowns_EuphonyTrackQueue * i = this; + Towns_EuphonyTrackQueue * i = this; while (i->_next) i = i->_next; - i = i->_next = new SoundTowns_EuphonyTrackQueue(_driver, i); + i = i->_next = new Towns_EuphonyTrackQueue(_driver, i); i->_trackData = new uint8[0xC58A]; memset(i->_trackData, 0, 0xC58A); Screen::decodeFrame4(trackdata, i->_trackData, size); @@ -1044,29 +1038,39 @@ void SoundTowns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint3 i->_playing = _playing; } -void SoundTowns_EuphonyTrackQueue::release() { - SoundTowns_EuphonyTrackQueue * i = _next; - _next = 0; - _playing = false; - _used = _fchan = _wchan = 0; +Towns_EuphonyTrackQueue *Towns_EuphonyTrackQueue::release() { + Towns_EuphonyTrackQueue *i = this; + while (i->_next) + i = i->_next; - if (_trackData) { - delete[] _trackData; - _trackData = 0; - } + Towns_EuphonyTrackQueue *res = i; while (i) { + i->_playing = false; + i->_used = i->_fchan = i->_wchan = 0; if (i->_trackData) { delete[] i->_trackData; i->_trackData = 0; } - i = i->_next; - if (i) - delete i->_last; + i = i->_last; + if (i) { + res = i; + if (i->_next) { + delete i->_next; + i->_next = 0; + } + } } + + if (res->_trackData) { + delete[] res->_trackData; + res->_trackData = 0; + } + + return res; } -void SoundTowns_EuphonyTrackQueue::initDriver() { +void Towns_EuphonyTrackQueue::initDriver() { for (uint8 i = 0; i < 6; i++) { if (_used[_fchan[i]]) _driver->assignFmChannel(_fchan[i], i); @@ -1084,11 +1088,1339 @@ void SoundTowns_EuphonyTrackQueue::initDriver() { _driver->send(0x79B0); } +class TownsPC98_OpnOperator { +public: + TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, uint8 id, const uint8 *rateTable, + const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, + const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); + TownsPC98_OpnOperator::~TownsPC98_OpnOperator() {} + + void keyOn(); + void keyOff(); + void frequency(int freq); + void updatePhaseIncrement(); + void recalculateRates(); + void generateOutput(int phasebuf, int *feedbuf, int &out); + + void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; } + void detune(int value) { _detn = (int32*) &_detnTbl[value << 5]; } + void multiple(uint32 value) { _multiple = value ? (value << 1) : 1; } + void attackRate(uint32 value) { _specifiedAttackRate = value; } + bool scaleRate(uint8 value); + void decayRate(uint32 value) { _specifiedDecayRate = value; recalculateRates(); } + void sustainRate(uint32 value) { _specifiedSustainRate = value; recalculateRates(); } + void sustainLevel(uint32 value) { _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5; } + void releaseRate(uint32 value) { _specifiedReleaseRate = value; recalculateRates(); } + void totalLevel(uint32 value) { _totalLevel = value << 3; } + void reset(); + +protected: + EnvelopeState _state; + uint32 _feedbackLevel; + uint32 _multiple; + uint32 _totalLevel; + uint8 _keyScale1; + uint8 _keyScale2; + uint32 _specifiedAttackRate; + uint32 _specifiedDecayRate; + uint32 _specifiedSustainRate; + uint32 _specifiedReleaseRate; + uint32 _tickCount; + uint32 _sustainLevel; + + uint32 _frequency; + uint8 _kcode; + uint32 _phase; + uint32 _phaseIncrement; + int32 *_detn; + + const uint8 *_rateTbl; + const uint8 *_rshiftTbl; + const uint8 *_adTbl; + const uint32 *_fTbl; + const uint32 *_sinTbl; + const int32 *_tLvlTbl; + const int32 *_detnTbl; + + const double _tickLength; + double _tick; + int32 _currentLevel; + + struct EvpState { + uint8 rate; + uint8 shift; + } fs_a, fs_d, fs_s, fs_r; +}; + +TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, uint8 id, + const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, + const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : + _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), + _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(rate * 65536.0), + _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), + _phase(0), _state(s_ready) { + + reset(); +} + +void TownsPC98_OpnOperator::keyOn() { + _state = s_attacking; + _phase = 0; +} + +void TownsPC98_OpnOperator::keyOff() { + if (_state != s_ready) + _state = s_releasing; +} + +void TownsPC98_OpnOperator::frequency(int freq) { + uint8 block = (freq >> 11); + uint16 pos = (freq & 0x7ff); + uint8 c = pos >> 7; + _kcode = (block << 2) | ((c < 7) ? 0 : ((c > 8) ? 3 : c - 6 )); + _frequency = _fTbl[pos << 1] >> (7 - block); +} + +void TownsPC98_OpnOperator::updatePhaseIncrement() { + _phaseIncrement = ((_frequency + _detn[_kcode]) * _multiple) >> 1; + uint8 keyscale = _kcode >> _keyScale1; + if (_keyScale2 != keyscale) { + _keyScale2 = keyscale; + recalculateRates(); + } +} + +void TownsPC98_OpnOperator::recalculateRates() { + int k = _keyScale2; + int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0; + fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136; + fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0; + + r = _specifiedDecayRate ? (_specifiedDecayRate << 1) + 0x20 : 0; + fs_d.rate = _rateTbl[r + k]; + fs_d.shift = _rshiftTbl[r + k]; + + r = _specifiedSustainRate ? (_specifiedSustainRate << 1) + 0x20 : 0; + fs_s.rate = _rateTbl[r + k]; + fs_s.shift = _rshiftTbl[r + k]; + + r = (_specifiedReleaseRate << 2) + 0x22; + fs_r.rate = _rateTbl[r + k]; + fs_r.shift = _rshiftTbl[r + k]; +} + +void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feedbuf, int &out) { + if (_state == s_ready) + return; + + _tick += _tickLength; + while (_tick > 0x30000) { + _tick -= 0x30000; + ++_tickCount; + + int32 levelIncrement = 0; + uint32 targetTime = 0; + int32 targetLevel = 0; + EnvelopeState next_state = s_ready; + + switch (_state) { + case s_ready: + return; + case s_attacking: + next_state = s_decaying; + targetTime = (1 << fs_a.shift) - 1; + targetLevel = 0; + levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4; + break; + case s_decaying: + targetTime = (1 << fs_d.shift) - 1; + next_state = s_sustaining; + targetLevel = _sustainLevel; + levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)]; + break; + case s_sustaining: + targetTime = (1 << fs_s.shift) - 1; + next_state = s_ready; + targetLevel = 1023; + levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)]; + break; + case s_releasing: + targetTime = (1 << fs_r.shift) - 1; + next_state = s_ready; + targetLevel = 1023; + levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)]; + break; + } + + if (!(_tickCount & targetTime)) { + _currentLevel += levelIncrement; + if ((!targetLevel && _currentLevel <= targetLevel) || (targetLevel && _currentLevel >= targetLevel)) { + if (_state != s_decaying) + _currentLevel = targetLevel; + if (_state != s_sustaining) + _state = next_state; + } + } + } + + uint32 lvlout = _totalLevel + (uint32) _currentLevel; + + int outp = 0; + int *i = &outp, *o = &outp; + int phaseShift = 0; + + if (feedbuf) { + o = &feedbuf[0]; + i = &feedbuf[1]; + phaseShift = _feedbackLevel ? ((feedbuf[0] + feedbuf[1]) << _feedbackLevel) : 0; + *o = *i; + } else { + phaseShift = phasebuf << 15; + } + + if (lvlout < 832) { + uint32 index = (lvlout << 3) + _sinTbl[(((int32)((_phase & 0xffff0000) + + phaseShift)) >> 16) & 0x3ff]; + *i = ((index < 6656) ? _tLvlTbl[index] : 0); + } else { + *i = 0; + } + + _phase += _phaseIncrement; + out += *o; + if (out > 32767) + out = 32767; + if (out < -32767) + out = -32767; +} + +void TownsPC98_OpnOperator::reset(){ + keyOff(); + _tick = 0; + _keyScale2 = -1; + _currentLevel = 1023; + + frequency(0); + detune(0); + scaleRate(0); + multiple(0); + updatePhaseIncrement(); + attackRate(0); + decayRate(0); + releaseRate(0); + sustainRate(0); + feedbackLevel(0); + totalLevel(127); +} + +bool TownsPC98_OpnOperator::scaleRate(uint8 value) { + value = 3 - value; + if (_keyScale1 != value) { + _keyScale1 = value; + return true; + } + + int k = _keyScale2; + int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0; + fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136; + fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0; + return false; +} + +class TownsPC98_OpnDriver : public Audio::AudioStream { +public: + enum OpnType { + OD_TOWNS, + OD_TYPE26, + OD_TYPE86 + }; + + TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type); + ~TownsPC98_OpnDriver(); + + bool init(); + void loadData(uint8 *data, bool loadPaused = false); + void reset(); + void fadeOut(); + + void pause() { _playing = false; } + void cont() { _playing = true; } + + void callback(); + void nextTick(int16 *buffer, uint32 bufferSize); + + bool looping() { return _looping == _updateChannelsFlag ? true : false; } + + // AudioStream interface + int inline readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return true; } + bool endOfData() const { return false; } + int getRate() const { return _mixer->getOutputRate(); } + +protected: + void generateTables(); + + typedef enum channelState { + CHS_RECALCFREQ = 0x01, + CHS_KEYOFF = 0x02, + CHS_PITCHWHEELOFF = 0x08, + CHS_ALL_BUT_EOT = 0x0f, + CHS_EOT = 0x80 + } ChannelState; + + struct TwnChannel { + uint8 ticksLeft; + uint8 unk1, unk2, unk3; + uint8 algorithm; + uint8 instrID; + uint8 totalLevel; + uint8 frqBlockMSB; + int8 frqLSB; + uint8 keyOffTime; + bool protect; + uint8 *dataPtr; + uint8 unk15, unk16; + uint8 ptchWhlInitDelayLo; + uint8 ptchWhlInitDelayHi; + int16 ptchWhlModInitVal; + uint8 ptchWhlDuration; + uint8 ptchWhlCurDelay; + int16 ptchWhlModCurVal; + uint8 ptchWhlDurLeft; + uint16 frequency; + uint8 unk28, unk29; + uint8 regOffset; + uint8 flags; + uint8 chanNum; + uint8 keyNum; + uint8 part; + uint8 idFlag; + + TownsPC98_OpnOperator *opr[4]; + uint16 frqTemp; + bool enableLeft; + bool enableRight; + bool updateEnvelopes; + int feedbuf[3]; + } **_channels; + + void processEvents(TwnChannel *chan); + void processFrequency(TwnChannel *chan); + bool processControlEvent(TwnChannel *chan, uint8 cmd); + + void setOutputLevel(TwnChannel *chan); + void setTempo(uint8 tempo); + + void keyOn(TwnChannel *chan); + void keyOff(TwnChannel *chan); + void writeReg(TwnChannel *chan, uint8 regAdress, uint8 value); + + void lock() { _mutex.lock(); } + void unlock() { _mutex.unlock(); } + + bool control_f0_setPatch(TwnChannel *chan, uint8 para); + bool control_f1_presetOutputLevel(TwnChannel *chan, uint8 para); + bool control_f2_setKeyOffTime(TwnChannel *chan, uint8 para); + bool control_f3_setFreqLSB(TwnChannel *chan, uint8 para); + bool control_f4_setOutputLevel(TwnChannel *chan, uint8 para); + bool control_f5_setTempo(TwnChannel *chan, uint8 para); + bool control_f6_repeatSection(TwnChannel *chan, uint8 para); + bool control_f7_setupPitchWheel(TwnChannel *chan, uint8 para); + bool control_f8_togglePitchWheel(TwnChannel *chan, uint8 para); + bool control_f9_unk(TwnChannel *chan, uint8 para); + bool control_fa_writeReg(TwnChannel *chan, uint8 para); + bool control_fb_incOutLevel(TwnChannel *chan, uint8 para); + bool control_fc_decOutLevel(TwnChannel *chan, uint8 para); + bool control_fd_jump(TwnChannel *chan, uint8 para); + bool control_fe_unk(TwnChannel *chan, uint8 para); + bool control_ff_endOfTrack(TwnChannel *chan, uint8 para); + + typedef bool (TownsPC98_OpnDriver::*ControlEventFunc)(TwnChannel * chan, uint8 para); + + Audio::Mixer *_mixer; + TownsPC98_OpnOperator **_operators; + Common::Mutex _mutex; + Audio::SoundHandle _soundHandle; + + const uint8 *_twnCarrier; + const uint8 *_twnFreqTable; + const uint8 *_twnFxCmdLen; + const uint8 *_twnLvlPresets; + + uint8 *_oprRates; + uint8 *_oprRateshift; + uint8 *_oprAttackDecay; + uint32 *_oprFrq; + uint32 *_oprSinTbl; + int32 *_oprLevelOut; + int32 *_oprDetune; + + const uint8 *_trackData; + const uint8 *_patches; + uint8 _cbCounter; + uint8 _updateChannelsFlag; + uint8 _finishedChannelsFlag; + uint16 _tempo; + bool _playing; + bool _fading; + uint8 _looping; + + bool _updateEnvelopes; + + int32 _samplesTillCallback; + int32 _samplesTillCallbackRemainder; + int32 _samplesPerCallback; + int32 _samplesPerCallbackRemainder; + + const int _numChan; + const int _numSSG; + const bool _hasADPCM; + const bool _hasStereo; + + double _baserate; + static const uint8 _drvTables[]; + static const uint32 _adtStat[]; +}; + +TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : + _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), + _operators(0), _looping(0), _twnCarrier(_drvTables + 76), _twnFreqTable(_drvTables + 84), + _twnFxCmdLen(_drvTables + 36), _twnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , + _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), + _oprDetune(0), _cbCounter(4), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), + _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), + _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), + _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { + setTempo(84); + _baserate = (3579545.0 / (double)getRate()) / 144.0; +} + +TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { + _mixer->stopHandle(_soundHandle); + + if (_operators) { + for (int i = 0; i < (_numChan << 2); i++) + delete _operators[i]; + delete [] _operators; + } + + if (_channels) { + for (int i = 0; i < _numChan; i++) + delete _channels[i]; + delete [] _channels; + } + + delete [] _oprRates; + delete [] _oprRateshift; + delete [] _oprFrq; + delete [] _oprAttackDecay; + delete [] _oprSinTbl; + delete [] _oprLevelOut; + delete [] _oprDetune; +} + +bool TownsPC98_OpnDriver::init() { + generateTables(); + + if (_operators) { + for (int i = 0; i < (_numChan << 2); i++) { + if (_operators[i]) { + delete _operators[i]; + } + } + delete [] _operators; + } + + _operators = new TownsPC98_OpnOperator*[(_numChan << 2)]; + for (int i = 0; i < (_numChan << 2); i++) + _operators[i] = new TownsPC98_OpnOperator(_baserate, i & 3, _oprRates, + _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune); + + if (_channels) { + for (int i = 0; i < _numChan; i++) { + if (_channels[i]) + delete _channels[i]; + } + delete [] _channels; + } + _channels = new TwnChannel*[_numChan]; + for (int i = 0; i < _numChan; i++) { + _channels[i] = new TwnChannel; + for (int ii = 0; ii < 4; ii++) { + _channels[i]->opr[ii] = _operators[(i << 2) + ii]; + _channels[i]->updateEnvelopes = false; + } + } + + for (int i = 0; i < _numChan; i++) { + int ix = i * 6; + memset(_channels[i], 0, sizeof(TwnChannel)); + _channels[i]->regOffset = _drvTables[ix]; + _channels[i]->flags = _drvTables[ix + 1]; + _channels[i]->chanNum = _drvTables[ix + 2]; + _channels[i]->keyNum = _drvTables[ix + 3]; + _channels[i]->part = _drvTables[ix + 4]; + _channels[i]->idFlag = _drvTables[ix + 5]; + } + + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + + return true; +} + +int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, sizeof(int16) * numSamples); + int32 samplesLeft = numSamples >> 1; + while (samplesLeft) { + if (!_samplesTillCallback) { + callback(); + _samplesTillCallback = _samplesPerCallback; + _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; + if (_samplesTillCallbackRemainder >= _tempo) { + _samplesTillCallback++; + _samplesTillCallbackRemainder -= _tempo; + } + } + + int32 render = MIN(samplesLeft, _samplesTillCallback); + samplesLeft -= render; + _samplesTillCallback -= render; + + nextTick(buffer, render); + + for (int i = 0; i < render; ++i) { + buffer[i << 1] <<= 2; + buffer[(i << 1) + 1] <<= 2; + } + + buffer += (render << 1); + } + + return numSamples; +} + +void TownsPC98_OpnDriver::loadData(uint8 * data, bool loadPaused) { + + lock(); + _trackData = data; + + reset(); + + for (uint8 i = 0; i < _numChan; i++) { + uint8 tmp1 = _channels[i]->regOffset; + uint8 tmp2 = _channels[i]->flags; + uint8 tmp3 = _channels[i]->chanNum; + uint8 tmp4 = _channels[i]->keyNum; + uint8 tmp5 = _channels[i]->part; + uint8 tmp6 = _channels[i]->idFlag; + memset(_channels[i], 0, sizeof(TwnChannel)); + _channels[i]->regOffset = tmp1; + _channels[i]->flags = tmp2; + _channels[i]->chanNum = tmp3; + _channels[i]->keyNum = tmp4; + _channels[i]->part = tmp5; + _channels[i]->idFlag = tmp6; + _channels[i]->enableLeft = _channels[i]->enableRight = true; + for (int ii = 0; ii < 4; ii++) + _channels[i]->opr[ii] = _operators[(i << 2) + ii]; + } + + const uint8 *src_a = (const uint8*) data; + uint8 bl = 0; + + for (uint8 i = 0; i < _numChan; i++) { + _channels[i]->flags = (_channels[i]->flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + _channels[i]->ticksLeft = 1; + _channels[i]->dataPtr = data + READ_LE_UINT16(src_a); + src_a += 2; + _channels[i]->totalLevel = 0x7F; + if (bl > 2) + bl -= 3; + _channels[i]->regOffset = bl++; + + uint8 * src_b = _channels[i]->dataPtr; + int loop = 1; + uint8 cmd = 0; + while (loop) { + if (loop == 1) { + cmd = *src_b++; + if (cmd < 0xf0) { + src_b++; + loop = 1; + } else { + if (cmd == 0xff) { + loop = *src_b ? 2 : 0; + if (READ_LE_UINT16(src_b)) + _looping |= _channels[i]->idFlag; + } else if (cmd == 0xf6) { + loop = 3; + } else { + loop = 2; + } + } + } else if (loop == 2) { + src_b += _twnFxCmdLen[cmd - 240]; + loop = 1; + } else if (loop == 3) { + src_b[0] = src_b[1]; + src_b += 4; + loop = 1; + } + } + } + + for (int i = 0; i < _numSSG; i++) { + // TODO + //_channels[i]->flags = (_channels[i]->flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + //_channels[i]->ticksLeft = 1; + //_channels[i]->dataPtr = data + READ_LE_UINT16(src_a); + uint8 *tmp = data + READ_LE_UINT16(src_a); + src_a += 2; + } + + if (_hasADPCM) { + // TODO + src_a += 2; + } + + _patches = src_a + 4; + _cbCounter = 4; + _finishedChannelsFlag = 0; + + // AH 0x17 + unlock(); + _playing = (loadPaused ? false : true); +} + +void TownsPC98_OpnDriver::reset() { + for (int i = 0; i < (_numChan << 2); i++) + _operators[i]->reset(); + + _playing = false; + _looping = 0; +} + +void TownsPC98_OpnDriver::fadeOut() { + if (!_playing) + return; + + _fading = true; + + for (int i = 0; i < 20; i++) { + + /// TODO /// + // twnFade(); + //waitTicks(s); + + } + + _fading = false; + + //haltTrack(); +} + +void TownsPC98_OpnDriver::callback() { + if (!_playing || --_cbCounter) + return; + + _cbCounter = 4; + + lock(); + for (int i = 0; i < _numChan; i++) { + if (_updateChannelsFlag & _channels[i]->idFlag) { + processEvents(_channels[i]); + processFrequency(_channels[i]); + } + } + unlock(); + + if (_finishedChannelsFlag == _updateChannelsFlag) + reset(); +} + +void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { + if (!_playing) + return; + + for (int i = 0; i < _numChan ; i++) { + if (_channels[i]->updateEnvelopes) { + _channels[i]->updateEnvelopes = false; + for (int ii = 0; ii < 4 ; ii++) + _channels[i]->opr[ii]->updatePhaseIncrement(); + } + + int phbuf1, phbuf2, output; + int *feed = _channels[i]->feedbuf; + int *del = &feed[2]; + + for (int ii = 0; ii < bufferSize ; ii++) { + phbuf1 = phbuf2 = output = 0; + + switch (_channels[i]->algorithm) { + case 0: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); + *del = 0; + _channels[i]->opr[1]->generateOutput(phbuf1, 0, *del); + _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); + break; + case 1: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); + _channels[i]->opr[1]->generateOutput(0, 0, phbuf1); + _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 2: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf2); + _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); + _channels[i]->opr[1]->generateOutput(0, 0, phbuf1); + _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 3: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf2); + _channels[i]->opr[2]->generateOutput(0, 0, *del); + _channels[i]->opr[1]->generateOutput(phbuf2, 0, phbuf1); + _channels[i]->opr[3]->generateOutput(*del, 0, output); + *del = phbuf1; + break; + case 4: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[2]->generateOutput(0, 0, phbuf2); + _channels[i]->opr[1]->generateOutput(phbuf1, 0, output); + _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); + *del = 0; + break; + case 5: + *del = feed[1]; + _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[2]->generateOutput(*del, 0, output); + _channels[i]->opr[1]->generateOutput(*del, 0, output); + _channels[i]->opr[3]->generateOutput(*del, 0, output); + break; + case 6: + _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[2]->generateOutput(0, 0, output); + _channels[i]->opr[1]->generateOutput(phbuf1, 0, output); + _channels[i]->opr[3]->generateOutput(0, 0, output); + *del = 0; + break; + case 7: + _channels[i]->opr[0]->generateOutput(0, feed, output); + _channels[i]->opr[2]->generateOutput(0, 0, output); + _channels[i]->opr[1]->generateOutput(0, 0, output); + _channels[i]->opr[3]->generateOutput(0, 0, output); + *del = 0; + break; + }; + + if (_channels[i]->enableLeft) { + int l = output + buffer[ii * 2]; + if (l > 32767) + l = 32767; + if (l < -32767) + l = -32767; + buffer[ii * 2] = (int16) l; + } + + if (_channels[i]->enableRight) { + int r = output + buffer[ii * 2 + 1]; + if (r > 32767) + r = 32767; + if (r < -32767) + r = -32767; + buffer[ii * 2 + 1] = (int16) r; + } + } + } +} + +void TownsPC98_OpnDriver::generateTables() { + delete [] _oprRates; + _oprRates = new uint8[128]; + memset(_oprRates, 0x90, 32); + uint8 * dst = (uint8*) _oprRates + 32; + for (int i = 0; i < 48; i += 4) + WRITE_BE_UINT32(dst + i, 0x00081018); + dst += 48; + for (uint8 i = 0; i < 16; i ++) { + uint8 v = (i < 12) ? i : 12; + *dst++ = ((4 + v) << 3); + } + memset(dst, 0x80, 32); + + delete [] _oprRateshift; + _oprRateshift = new uint8[128]; + memset(_oprRateshift, 0, 128); + dst = (uint8*) _oprRateshift + 32; + for (int i = 11; i; i--) { + memset(dst, i, 4); + dst += 4; + } + + delete [] _oprFrq; + _oprFrq = new uint32[0x1000]; + for (uint32 i = 0; i < 0x1000; i++) + _oprFrq[i] = (uint32)(_baserate * (double)(i << 11)); + + delete [] _oprAttackDecay; + _oprAttackDecay = new uint8[152]; + memset(_oprAttackDecay, 0, 152); + for (int i = 0; i < 36; i++) + WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]); + + delete [] _oprSinTbl; + _oprSinTbl = new uint32[1024]; + for (int i = 0; i < 1024; i++) { + double val = sin((double) (((i << 1) + 1) * M_PI / 1024.0)); + double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; + int32 i_dcb = (int32)(2.0 * d_dcb); + i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); + _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1); + } + + delete [] _oprLevelOut; + _oprLevelOut = new int32[0x1a00]; + for (int i = 0; i < 256; i++) { + double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i))); + int32 val_int = ((int32) val) >> 4; + _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2; + _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1]; + for (int ii = 1; ii < 13; ii++) { + _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii; + _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)]; + } + } + + uint8 * dtt = new uint8[128]; + memset(dtt, 0, 36); + memset(dtt + 36, 1, 8); + memcpy(dtt + 44, _drvTables + 144, 84); + + delete [] _oprDetune; + _oprDetune = new int32[256]; + for (int i = 0; i < 128; i++) { + double rate = ((double)dtt[i]) * 1024.0 * _baserate * (1<<16) / ((double)(1<<20)); + _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0); + _oprDetune[i + 128] = -_oprDetune[i]; + } + + delete [] dtt; +} + +void TownsPC98_OpnDriver::processEvents(TwnChannel *chan) { + if (chan->flags & CHS_EOT) + return; + + if (chan->protect == false && chan->ticksLeft == chan->keyOffTime) + keyOff(chan); + + if (--chan->ticksLeft) + return; + + if (chan->protect == false) + keyOff(chan); + + uint8 cmd = 0; + bool loop = true; + + while (loop) { + cmd = *chan->dataPtr++; + if (cmd < 0xf0) + loop = false; + else if (!processControlEvent(chan, cmd)) + return; + } + + uint8 para = *chan->dataPtr++; + + if (cmd == 0x80) { + keyOff(chan); + chan->protect = false; + } else { + keyOn(chan); + + if (chan->protect == false || cmd != chan->frqBlockMSB) + chan->flags |= CHS_RECALCFREQ; + + chan->protect = (para & 0x80) ? true : false; + chan->frqBlockMSB = cmd; + } + + chan->ticksLeft = para & 0x7f; +} + +void TownsPC98_OpnDriver::processFrequency(TwnChannel *chan) { + if (chan->flags & CHS_RECALCFREQ) { + uint8 block = (chan->frqBlockMSB & 0x70) >> 1; + uint16 bfreq = ((uint16*)_twnFreqTable)[chan->frqBlockMSB & 0x0f]; + chan->frequency = (bfreq + chan->frqLSB) | (block << 8); + + writeReg(chan, (chan->regOffset + 0xa4), (chan->frequency >> 8)); + writeReg(chan, (chan->regOffset + 0xa0), (chan->frequency & 0xff)); + + chan->ptchWhlCurDelay = chan->ptchWhlInitDelayHi; + if (chan->flags & CHS_KEYOFF) { + chan->ptchWhlModCurVal = chan->ptchWhlModInitVal; + chan->ptchWhlCurDelay += chan->ptchWhlInitDelayLo; + } + + chan->ptchWhlDurLeft = (chan->ptchWhlDuration >> 1); + chan->flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); + } + + if (!(chan->flags & CHS_PITCHWHEELOFF)) { + if (--chan->ptchWhlCurDelay) + return; + chan->ptchWhlCurDelay = chan->ptchWhlInitDelayHi; + chan->frequency += chan->ptchWhlModCurVal; + + writeReg(chan, (chan->regOffset + 0xa4), (chan->frequency >> 8)); + writeReg(chan, (chan->regOffset + 0xa0), (chan->frequency & 0xff)); + + if(!--chan->ptchWhlDurLeft) { + chan->ptchWhlDurLeft = chan->ptchWhlDuration; + chan->ptchWhlModCurVal = -chan->ptchWhlModCurVal; + } + } +} + +bool TownsPC98_OpnDriver::processControlEvent(TwnChannel *chan, uint8 cmd) { + #define Control(x) &TownsPC98_OpnDriver::control_##x + static const ControlEventFunc twnFxCommands[] = { + Control(f0_setPatch), + Control(f1_presetOutputLevel), + Control(f2_setKeyOffTime), + Control(f3_setFreqLSB), + Control(f4_setOutputLevel), + Control(f5_setTempo), + Control(f6_repeatSection), + Control(f7_setupPitchWheel), + Control(f8_togglePitchWheel), + Control(f9_unk), + Control(fa_writeReg), + Control(fb_incOutLevel), + Control(fc_decOutLevel), + Control(fd_jump), + Control(fe_unk), + Control(ff_endOfTrack) + }; + #undef Control + + uint8 para = *chan->dataPtr++; + return (this->*twnFxCommands[cmd & 0x0f])(chan, para); +} + +void TownsPC98_OpnDriver::setOutputLevel(TwnChannel *chan) { + uint8 outopr = _twnCarrier[chan->algorithm]; + uint8 reg = 0x40 + chan->regOffset; + + for (int i = 0; i < 4; i++) { + if (outopr & 1) + writeReg(chan, reg, chan->totalLevel); + outopr >>= 1; + reg += 4; + } +} + +void TownsPC98_OpnDriver::setTempo(uint8 tempo) { + _tempo = tempo; + _samplesPerCallback = getRate() / _tempo; + _samplesPerCallbackRemainder = getRate() % _tempo; +} + +bool TownsPC98_OpnDriver::control_f0_setPatch(TwnChannel *chan, uint8 para) { + chan->instrID = para; + uint8 reg = chan->regOffset + 0x80; + + for (int i = 0; i < 4; i++) { + // set release rate for each operator + writeReg(chan, reg, 0x0f); + reg += 4; + } + + const uint8 *tptr = (uint8*) _patches + ((uint32)chan->instrID << 5); + reg = chan->regOffset + 0x30; + + // write registers 0x30 to 0x8f + for (int i = 0; i < 6; i++) { + writeReg(chan, reg, tptr[0]); + reg += 4; + writeReg(chan, reg, tptr[2]); + reg += 4; + writeReg(chan, reg, tptr[1]); + reg += 4; + writeReg(chan, reg, tptr[3]); + reg += 4; + tptr += 4; + } + + reg = chan->regOffset + 0xB0; + chan->algorithm = tptr[0] & 7; + // set feedback and algorithm + writeReg(chan, reg, tptr[0]); + + setOutputLevel(chan); + return true; +} + +bool TownsPC98_OpnDriver::control_f1_presetOutputLevel(TwnChannel *chan, uint8 para) { + if (_fading) + return true; + + chan->totalLevel = _twnLvlPresets[para]; + setOutputLevel(chan); + return true; +} + +bool TownsPC98_OpnDriver::control_f2_setKeyOffTime(TwnChannel *chan, uint8 para) { + chan->keyOffTime = para; + return true; +} + +bool TownsPC98_OpnDriver::control_f3_setFreqLSB(TwnChannel *chan, uint8 para) { + chan->frqLSB = (int8) para; + return true; +} + +bool TownsPC98_OpnDriver::control_f4_setOutputLevel(TwnChannel *chan, uint8 para) { + if (_fading) + return true; + + chan->totalLevel = para; + setOutputLevel(chan); + return true; +} + +bool TownsPC98_OpnDriver::control_f5_setTempo(TwnChannel *chan, uint8 para) { + setTempo(para); + return true; +} + +bool TownsPC98_OpnDriver::control_f6_repeatSection(TwnChannel *chan, uint8 para) { + chan->dataPtr--; + chan->dataPtr[0]--; + + if (*chan->dataPtr) { + // repeat section until counter has reached zero + chan->dataPtr = (uint8*) _trackData + READ_LE_UINT16(chan->dataPtr + 2); + } else { + // reset counter, advance to next section + chan->dataPtr[0] = chan->dataPtr[1]; + chan->dataPtr += 4; + } + return true; +} + +bool TownsPC98_OpnDriver::control_f7_setupPitchWheel(TwnChannel *chan, uint8 para) { + chan->ptchWhlInitDelayLo = chan->dataPtr[0]; + chan->ptchWhlInitDelayHi = para; + chan->ptchWhlModInitVal = (int16) READ_LE_UINT16(chan->dataPtr + 1); + chan->ptchWhlDuration = chan->dataPtr[3]; + chan->dataPtr += 4; + chan->flags = (chan->flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF | CHS_RECALCFREQ; + return true; +} + +bool TownsPC98_OpnDriver::control_f8_togglePitchWheel(TwnChannel *chan, uint8 para) { + if (para == 0x10) { + if (*chan->dataPtr++) { + chan->flags = (chan->flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF; + } else { + chan->flags |= CHS_PITCHWHEELOFF; + } + } else { + uint8 skipChannels = para / 36; + uint8 entry = para % 36; + TownsPC98_OpnDriver::TwnChannel *t = &chan[skipChannels]; + ////// NOT IMPLEMENTED + //t->unnamedEntries[entry] = *chan->dataPtr++; + } + return true; +} + +bool TownsPC98_OpnDriver::control_f9_unk(TwnChannel *chan, uint8 para) { + //chan->dataPtr += 5; + return true; +} + +bool TownsPC98_OpnDriver::control_fa_writeReg(TwnChannel *chan, uint8 para) { + writeReg(chan, para, *chan->dataPtr++); + return true; +} + +bool TownsPC98_OpnDriver::control_fb_incOutLevel(TwnChannel *chan, uint8 para) { + chan->dataPtr--; + if (_fading) + return true; + + uint8 val = (chan->totalLevel + 3); + if (val > 0x7f) + val = 0x7f; + + chan->totalLevel = val; + setOutputLevel(chan); + return true; +} + +bool TownsPC98_OpnDriver::control_fc_decOutLevel(TwnChannel *chan, uint8 para) { + chan->dataPtr--; + if (_fading) + return true; + + int8 val = (int8) (chan->totalLevel - 3); + if (val < 0) + val = 0; + + chan->totalLevel = (uint8) val; + setOutputLevel(chan); + return true; +} + +bool TownsPC98_OpnDriver::control_fd_jump(TwnChannel *chan, uint8 para) { + uint8 *tmp = (uint8*) _trackData + READ_LE_UINT16(chan->dataPtr - 1); + chan->dataPtr = (tmp[1] == 1) ? tmp : ++chan->dataPtr; + return true; +} + +bool TownsPC98_OpnDriver::control_fe_unk(TwnChannel *chan, uint8 para) { + chan->dataPtr--; + return true; +} + +bool TownsPC98_OpnDriver::control_ff_endOfTrack(TwnChannel *chan, uint8 para) { + uint16 val = READ_LE_UINT16(--chan->dataPtr); + if (val) { + // loop + chan->dataPtr = (uint8 *) _trackData + val; + return true; + } else { + // quit parsing for active channel + --chan->dataPtr; + chan->flags |= CHS_EOT; + _finishedChannelsFlag |= chan->idFlag; + keyOff(chan); + return false; + } +} + +void TownsPC98_OpnDriver::keyOff(TwnChannel *chan) { + // all operators off + uint8 value = chan->keyNum & 0x0f; + uint8 regAdress = 0x28; + writeReg(chan, regAdress, value); + chan->flags |= CHS_KEYOFF; +} + +void TownsPC98_OpnDriver::keyOn(TwnChannel *chan) { + // all operators on + uint8 value = chan->keyNum | 0xf0; + uint8 regAdress = 0x28; + writeReg(chan, regAdress, value); +} + +void TownsPC98_OpnDriver::writeReg(TwnChannel *chan, uint8 regAdress, uint8 value) { + uint8 h = regAdress & 0xf0; + uint8 l = (regAdress & 0x0f); + static const uint8 opr[] = { 0, 2, 1, 3 }; + uint8 o = opr[(l - chan->regOffset) >> 2]; + + switch (h) { + case 0x00: + // ssg + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + case 0x10: + // adpcm + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + case 0x20: + if (l == 8) { + // Key on/off + for (int i = 0; i < 4; i++) { + if ((value >> (4 + i)) & 1) + chan->opr[i]->keyOn(); + else + chan->opr[i]->keyOff(); + } + } else if (l == 2) { + // LFO + warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)"); + } else if (l == 7) { + // Timers; Ch 3/6 special mode + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE (NOT SUPPORTED)"); + } else if (l == 4 || l == 5) { + // Timer A + warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_A (NOT SUPPORTED)"); + } else if (l == 6) { + // Timer B + warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_B (NOT SUPPORTED)"); + } else if (l == 10 || l == 11) { + // DAC + warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)"); + } + break; + + case 0x30: + // detune, multiple + chan->opr[o]->detune((value >> 4) & 7); + chan->opr[o]->multiple(value & 0x0f); + chan->updateEnvelopes = true; + break; + + case 0x40: + // total level + chan->opr[o]->totalLevel(value & 0x7f); + break; + + case 0x50: + // rate scaling, attack rate + chan->opr[o]->attackRate(value & 0x1f); + if (chan->opr[o]->scaleRate(value >> 6)) + chan->updateEnvelopes = true; + break; + + case 0x60: + // first decay rate, amplitude modulation + chan->opr[o]->decayRate(value & 0x1f); + if (value & 0x80) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); + + break; + + case 0x70: + // secondary decay rate + chan->opr[o]->sustainRate(value & 0x1f); + break; + + case 0x80: + // secondary amplitude, release rate; + chan->opr[o]->sustainLevel(value >> 4); + chan->opr[o]->releaseRate(value & 0x0f); + break; + + case 0x90: + // ssg + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + + case 0xa0: + // frequency + l -= chan->regOffset; + if (l == 0) { + chan->frqTemp = (chan->frqTemp & 0xff00) | value; + chan->updateEnvelopes = true; + for (int i = 0; i < 4; i++) + chan->opr[i]->frequency(chan->frqTemp); + } else if (l == 4) { + chan->frqTemp = (chan->frqTemp & 0xff) | (value << 8); + } else if (l == 8) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } else if (l == 12) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } + break; + + case 0xb0: + l -= chan->regOffset; + if (l == 0) { + // feedback, algorithm + chan->opr[0]->feedbackLevel((value >> 3) & 7); + chan->opr[1]->feedbackLevel(0); + chan->opr[2]->feedbackLevel(0); + chan->opr[3]->feedbackLevel(0); + } else if (l == 4) { + // stereo, LFO sensitivity + chan->enableLeft = value & 0x80 ? true : false; + chan->enableRight = value & 0x40 ? true : false; + uint8 ams = (value & 0x3F) >> 3; + if (ams) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)"); + uint8 fms = value & 3; + if (fms) + warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)"); + } + break; + + default: + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + } +} + +const uint8 TownsPC98_OpnDriver::_drvTables[] = { + // channel presets + 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x80, 0x01, 0x01, 0x00, 0x02, + 0x02, 0x80, 0x02, 0x02, 0x00, 0x04, + 0x00, 0x80, 0x03, 0x04, 0x01, 0x08, + 0x01, 0x80, 0x04, 0x05, 0x01, 0x10, + 0x02, 0x80, 0x05, 0x06, 0x01, 0x20, + + // control event size + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, + 0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, + + // fmt level presets + 0x54, 0x50, 0x4C, 0x48, 0x44, 0x40, 0x3C, 0x38, + 0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18, + 0x14, 0x10, 0x0C, 0x08, 0x04, 0x90, 0x90, 0x90, + + // carriers + 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F, + + // frequencies + 0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02, + 0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03, + 0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04, + 0x00, 0x00, 0x00, 0x00, + + // unused + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + + // detune + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, + 0x08, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x10, 0x10, 0x10, 0x10, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, + 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, + 0x16, 0x16, 0x16, 0x16, + + // pc98 level presets + 0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25, + 0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10, + 0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90 +}; + +const uint32 TownsPC98_OpnDriver::_adtStat[] = { + 0x00010001, 0x00010001, 0x00010001, 0x01010001, + 0x00010101, 0x00010101, 0x00010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010102, 0x01010102, + 0x01020102, 0x01020102, 0x01020202, 0x01020202, + 0x02020202, 0x02020202, 0x02020204, 0x02020204, + 0x02040204, 0x02040204, 0x02040404, 0x02040404, + 0x04040404, 0x04040404, 0x04040408, 0x04040408, + 0x04080408, 0x04080408, 0x04080808, 0x04080808, + 0x08080808, 0x08080808, 0x10101010, 0x10101010 +}; + SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _sfxBTTable(0), _parser(0) { - _driver = new SoundTowns_EuphonyDriver(_mixer); + _driver = new Towns_EuphonyDriver(_mixer); int ret = open(); if (ret != MERR_ALREADY_OPEN && ret != 0) error("couldn't open midi driver"); @@ -1304,7 +2636,7 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { Common::StackLock lock(_mutex); if (!_parser) { - _parser = new MidiParser_EuD(_driver->queue()); + _parser = new Towns_EuphonyParser(_driver->queue()); _parser->setMidiDriver(this); _parser->setTimerRate(getBaseTempo()); } @@ -1356,22 +2688,73 @@ float SoundTowns::semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiTo return (float) sampleRate * 10.0f * rateshift / outputRate; } +SoundPC98::SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer) : + Sound(vm, mixer), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0) { +} + +SoundPC98::~SoundPC98() { + delete[] _musicTrackData; + delete[] _sfxTrackData; + delete _driver; +} + +bool SoundPC98::init() { + _driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26); + _sfxTrackData = _vm->resource()->fileData("se.dat", 0); + if (!_sfxTrackData) + return false; + return _driver->init(); +} + +void SoundPC98::playTrack(uint8 track) { + if (track == _lastTrack && _musicEnabled) + return; + + haltTrack(); + + char musicfile[13]; + sprintf(musicfile, fileListEntry(0), track); + delete[] _musicTrackData; + // This is just for testing purposes atm since we haven't found a way + // to determine the correct file yet + _musicTrackData = _vm->resource()->fileData("kyram40.dat"/*musicfile*/, 0); + if (_musicEnabled) + _driver->loadData(_musicTrackData); + + _lastTrack = track; +} + +void SoundPC98::haltTrack() { + _lastTrack = -1; + AudioCD.stop(); + AudioCD.updateCD(); + _driver->reset(); +} + +void SoundPC98::beginFadeOut() { + _driver->fadeOut(); + haltTrack(); +} + +void SoundPC98::playSoundEffect(uint8) { + /// TODO /// +} + + // KYRA 2 -SoundTowns_v2::SoundTowns_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) - : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), /*_driver(0),*/ - _twnTrackData(0) { +SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) : + Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _lastTrack(-1), _driver(0) { } -SoundTowns_v2::~SoundTowns_v2() { - /*if (_driver) - delete _driver;*/ - if (_twnTrackData) - delete[] _twnTrackData; +SoundTownsPC98_v2::~SoundTownsPC98_v2() { + delete[] _musicTrackData; + delete _driver; } -bool SoundTowns_v2::init() { - //_driver = new SoundTowns_v2_TwnDriver(_mixer); +bool SoundTownsPC98_v2::init() { + _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ? + TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS); _vm->checkCD(); // FIXME: While checking for 'track1.XXX(X)' looks like // a good idea, we should definitely not be doing this @@ -1384,55 +2767,60 @@ bool SoundTowns_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; - return true;//_driver->init(); + return _driver->init(); } -void SoundTowns_v2::process() { +void SoundTownsPC98_v2::process() { AudioCD.updateCD(); } -void SoundTowns_v2::playTrack(uint8 track) { +void SoundTownsPC98_v2::playTrack(uint8 track) { if (track == _lastTrack && _musicEnabled) return; const uint16 * const cdaTracks = (const uint16 * const) cdaData(); int trackNum = -1; - for (int i = 0; i < cdaTrackNum(); i++) { - if (track == (uint8) READ_LE_UINT16(&cdaTracks[i * 2])) { - trackNum = (int) READ_LE_UINT16(&cdaTracks[i * 2 + 1]) - 1; - break; + if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { + for (int i = 0; i < cdaTrackNum(); i++) { + if (track == (uint8) READ_LE_UINT16(&cdaTracks[i * 2])) { + trackNum = (int) READ_LE_UINT16(&cdaTracks[i * 2 + 1]) - 1; + break; + } } } haltTrack(); - // TODO: figure out when to loop and when not for CD Audio - bool loop = false; + char musicfile[13]; + sprintf(musicfile, fileListEntry(0), track); + delete[] _musicTrackData; + _musicTrackData = _vm->resource()->fileData(musicfile, 0); + _driver->loadData(_musicTrackData, true); if (_musicEnabled == 2 && trackNum != -1) { - AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0); + AudioCD.play(trackNum+1, _driver->looping() ? -1 : 1, 0, 0); AudioCD.updateCD(); } else if (_musicEnabled) { - char musicfile[13]; - sprintf(musicfile, fileListEntry(0), track); - if (_twnTrackData) - delete[] _twnTrackData; - _twnTrackData = _vm->resource()->fileData(musicfile, 0); - //_driver->loadData(_twnTrackData); + _driver->cont(); } _lastTrack = track; } -void SoundTowns_v2::haltTrack() { +void SoundTownsPC98_v2::haltTrack() { _lastTrack = -1; AudioCD.stop(); AudioCD.updateCD(); - //_driver->reset(); + _driver->reset(); } -int32 SoundTowns_v2::voicePlay(const char *file, bool) { +void SoundTownsPC98_v2::beginFadeOut() { + _driver->fadeOut(); + haltTrack(); +} + +int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; int h = 0; @@ -1443,7 +2831,7 @@ int32 SoundTowns_v2::voicePlay(const char *file, bool) { return 0; } - char filename [13]; + char filename[13]; sprintf(filename, "%s.PCM", file); uint8 * data = _vm->resource()->fileData(filename, 0); @@ -1500,11 +2888,6 @@ int32 SoundTowns_v2::voicePlay(const char *file, bool) { return 1; } -void SoundTowns_v2::beginFadeOut() { - //_driver->fadeOut(); - haltTrack(); -} - } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index abdf115c1e..5d094fa13f 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1034,6 +1034,9 @@ void KyraEngine_LoK::initStaticResource() { } // audio data tables + static const char *tIntro98[] = { "intro%d.dat" }; + static const char *tIngame98[] = { "kyram%d.dat" }; + static const AudioDataStruct soundData_PC[] = { { _soundFilesIntro, _soundFilesIntroSize, 0, 0 }, { _soundFiles, _soundFilesSize, 0, 0 }, @@ -1045,7 +1048,20 @@ void KyraEngine_LoK::initStaticResource() { { _soundFiles, _soundFilesSize, _cdaTrackTable, _cdaTrackTableSize }, { 0, 0, 0, 0} }; - _soundData = (_flags.platform == Common::kPlatformPC) ? soundData_PC : soundData_TOWNS; + + static const AudioDataStruct soundData_PC98[] = { + { tIntro98, 1, 0, 0 }, + { tIngame98, 1, 0, 0 }, + { 0, 0, 0, 0} + }; + + if (_flags.platform == Common::kPlatformPC) + _soundData = soundData_PC; + else if (_flags.platform == Common::kPlatformFMTowns) + _soundData = soundData_TOWNS; + else if (_flags.platform == Common::kPlatformPC98) + _soundData = soundData_PC98; + } void KyraEngine_LoK::loadMouseShapes() { @@ -1243,6 +1259,10 @@ void KyraEngine_HoF::initStaticResource() { static const char *fmtMusicFileListFinale[] = { "finale%d.twn" }; static const char *fmtMusicFileListIngame[] = { "km%02d.twn" }; + static const char *pc98MusicFileListIntro[] = { "intro%d.86" }; + static const char *pc98MusicFileListFinale[] = { "finale%d.86" }; + static const char *pc98MusicFileListIngame[] = { "km%02d.86" }; + static const AudioDataStruct soundData_PC[] = { { _musicFileListIntro, _musicFileListIntroSize, 0, 0 }, { _musicFileListIngame, _musicFileListIngameSize, 0, 0}, @@ -1254,7 +1274,19 @@ void KyraEngine_HoF::initStaticResource() { { fmtMusicFileListIngame, 1, _cdaTrackTableIngame, _cdaTrackTableIngameSize >> 1 }, { fmtMusicFileListFinale, 1, _cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1 } }; - _soundData = (_flags.platform == Common::kPlatformPC) ? soundData_PC : soundData_TOWNS; + + static const AudioDataStruct soundData_PC98[] = { + { pc98MusicFileListIntro, 1, 0, 0 }, + { pc98MusicFileListIngame, 1, 0, 0 }, + { pc98MusicFileListFinale, 1, 0, 0 } + }; + + if (_flags.platform == Common::kPlatformPC) + _soundData = soundData_PC; + else if (_flags.platform == Common::kPlatformFMTowns) + _soundData = soundData_TOWNS; + else if (_flags.platform == Common::kPlatformPC98) + _soundData = soundData_PC98; // setup sequence data _sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize); -- cgit v1.2.3 From 41dfebc5322a21192b29817662dff290410680b6 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 26 Jun 2008 19:56:18 +0000 Subject: Fixing compilation for me. There are still lots of "cast casts away constness" warnings, though svn-id: r32809 --- engines/kyra/sound_towns.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index a6457f509b..3aeec49fdc 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1090,10 +1090,10 @@ void Towns_EuphonyTrackQueue::initDriver() { class TownsPC98_OpnOperator { public: - TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, uint8 id, const uint8 *rateTable, + TownsPC98_OpnOperator(double rate, uint8 id, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); - TownsPC98_OpnOperator::~TownsPC98_OpnOperator() {} + ~TownsPC98_OpnOperator() {} void keyOn(); void keyOff(); -- cgit v1.2.3 From 6cdb04f9404b57d2ce92a227b18ec4bc32567bce Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 26 Jun 2008 20:13:04 +0000 Subject: cleanup svn-id: r32810 --- engines/kyra/sound_towns.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 3aeec49fdc..0fed93839c 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1455,8 +1455,9 @@ protected: int32 *_oprLevelOut; int32 *_oprDetune; - const uint8 *_trackData; - const uint8 *_patches; + uint8 *_trackData; + uint8 *_patches; + uint8 _cbCounter; uint8 _updateChannelsFlag; uint8 _finishedChannelsFlag; @@ -1626,7 +1627,7 @@ void TownsPC98_OpnDriver::loadData(uint8 * data, bool loadPaused) { _channels[i]->opr[ii] = _operators[(i << 2) + ii]; } - const uint8 *src_a = (const uint8*) data; + uint8 *src_a = data; uint8 bl = 0; for (uint8 i = 0; i < _numChan; i++) { @@ -1955,7 +1956,7 @@ void TownsPC98_OpnDriver::processEvents(TwnChannel *chan) { void TownsPC98_OpnDriver::processFrequency(TwnChannel *chan) { if (chan->flags & CHS_RECALCFREQ) { uint8 block = (chan->frqBlockMSB & 0x70) >> 1; - uint16 bfreq = ((uint16*)_twnFreqTable)[chan->frqBlockMSB & 0x0f]; + uint16 bfreq = ((const uint16*)_twnFreqTable)[chan->frqBlockMSB & 0x0f]; chan->frequency = (bfreq + chan->frqLSB) | (block << 8); writeReg(chan, (chan->regOffset + 0xa4), (chan->frequency >> 8)); @@ -2041,7 +2042,7 @@ bool TownsPC98_OpnDriver::control_f0_setPatch(TwnChannel *chan, uint8 para) { reg += 4; } - const uint8 *tptr = (uint8*) _patches + ((uint32)chan->instrID << 5); + const uint8 *tptr = _patches + ((uint32)chan->instrID << 5); reg = chan->regOffset + 0x30; // write registers 0x30 to 0x8f @@ -2105,7 +2106,7 @@ bool TownsPC98_OpnDriver::control_f6_repeatSection(TwnChannel *chan, uint8 para) if (*chan->dataPtr) { // repeat section until counter has reached zero - chan->dataPtr = (uint8*) _trackData + READ_LE_UINT16(chan->dataPtr + 2); + chan->dataPtr = _trackData + READ_LE_UINT16(chan->dataPtr + 2); } else { // reset counter, advance to next section chan->dataPtr[0] = chan->dataPtr[1]; @@ -2180,7 +2181,7 @@ bool TownsPC98_OpnDriver::control_fc_decOutLevel(TwnChannel *chan, uint8 para) { } bool TownsPC98_OpnDriver::control_fd_jump(TwnChannel *chan, uint8 para) { - uint8 *tmp = (uint8*) _trackData + READ_LE_UINT16(chan->dataPtr - 1); + uint8 *tmp = _trackData + READ_LE_UINT16(chan->dataPtr - 1); chan->dataPtr = (tmp[1] == 1) ? tmp : ++chan->dataPtr; return true; } @@ -2194,7 +2195,7 @@ bool TownsPC98_OpnDriver::control_ff_endOfTrack(TwnChannel *chan, uint8 para) { uint16 val = READ_LE_UINT16(--chan->dataPtr); if (val) { // loop - chan->dataPtr = (uint8 *) _trackData + val; + chan->dataPtr = _trackData + val; return true; } else { // quit parsing for active channel -- cgit v1.2.3 From b695cb74ca3c4e3fe671e670f70d18d503df953c Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 26 Jun 2008 20:30:43 +0000 Subject: more cleanup svn-id: r32811 --- engines/kyra/sound_towns.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 0fed93839c..550908fd0f 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1103,7 +1103,7 @@ public: void generateOutput(int phasebuf, int *feedbuf, int &out); void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; } - void detune(int value) { _detn = (int32*) &_detnTbl[value << 5]; } + void detune(int value) { _detn = &_detnTbl[value << 5]; } void multiple(uint32 value) { _multiple = value ? (value << 1) : 1; } void attackRate(uint32 value) { _specifiedAttackRate = value; } bool scaleRate(uint8 value); @@ -1132,7 +1132,7 @@ protected: uint8 _kcode; uint32 _phase; uint32 _phaseIncrement; - int32 *_detn; + const int32 *_detn; const uint8 *_rateTbl; const uint8 *_rshiftTbl; @@ -1297,7 +1297,7 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feedbuf, int &out) void TownsPC98_OpnOperator::reset(){ keyOff(); _tick = 0; - _keyScale2 = -1; + _keyScale2 = 0; _currentLevel = 1023; frequency(0); @@ -1676,7 +1676,7 @@ void TownsPC98_OpnDriver::loadData(uint8 * data, bool loadPaused) { //_channels[i]->flags = (_channels[i]->flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; //_channels[i]->ticksLeft = 1; //_channels[i]->dataPtr = data + READ_LE_UINT16(src_a); - uint8 *tmp = data + READ_LE_UINT16(src_a); + //uint8 *tmp = data + READ_LE_UINT16(src_a); src_a += 2; } @@ -1755,7 +1755,7 @@ void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { int *feed = _channels[i]->feedbuf; int *del = &feed[2]; - for (int ii = 0; ii < bufferSize ; ii++) { + for (uint32 ii = 0; ii < bufferSize ; ii++) { phbuf1 = phbuf2 = output = 0; switch (_channels[i]->algorithm) { @@ -1903,7 +1903,6 @@ void TownsPC98_OpnDriver::generateTables() { delete [] _oprDetune; _oprDetune = new int32[256]; for (int i = 0; i < 128; i++) { - double rate = ((double)dtt[i]) * 1024.0 * _baserate * (1<<16) / ((double)(1<<20)); _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0); _oprDetune[i + 128] = -_oprDetune[i]; } @@ -2133,9 +2132,9 @@ bool TownsPC98_OpnDriver::control_f8_togglePitchWheel(TwnChannel *chan, uint8 pa chan->flags |= CHS_PITCHWHEELOFF; } } else { - uint8 skipChannels = para / 36; - uint8 entry = para % 36; - TownsPC98_OpnDriver::TwnChannel *t = &chan[skipChannels]; + //uint8 skipChannels = para / 36; + //uint8 entry = para % 36; + //TownsPC98_OpnDriver::TwnChannel *t = &chan[skipChannels]; ////// NOT IMPLEMENTED //t->unnamedEntries[entry] = *chan->dataPtr++; } -- cgit v1.2.3 From 0bea51974e4173cd7432348c334a6bb49f4aca6f Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 26 Jun 2008 20:43:23 +0000 Subject: fix bad const casts svn-id: r32812 --- engines/kyra/sound_towns.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 550908fd0f..40a746f1de 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -159,7 +159,7 @@ public: void loadDataToEndOfQueue(uint8 *trackdata, uint32 size, bool loop = 0); void setPlayBackStatus(bool playing); bool isPlaying() {return _playing; } - const uint8 * trackData() {return _trackData; } + uint8 *trackData() {return _trackData; } bool _loop; Towns_EuphonyTrackQueue *_next; @@ -807,7 +807,7 @@ void Towns_EuphonyParser::parseNextEvent(EventInfo &info) { if (info.ext.type == 0x2F) { unloadMusic(); memset(&info, 0, sizeof(EventInfo)); - pos = _position._play_pos = _tracks[0] = (byte*) _queue->trackData() + 0x806; + pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806; } else if (_active_track == 255) { _queue = _queue->_next; setup(); @@ -964,7 +964,7 @@ void Towns_EuphonyParser::resetTracking() { } void Towns_EuphonyParser::setup() { - uint8 *data = (uint8 *) _queue->trackData(); + uint8 *data = _queue->trackData(); if (!data) return; _queue->initDriver(); -- cgit v1.2.3 From 8cd03780f68a8558fd6b816629b0c2e3c9517a41 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 26 Jun 2008 23:30:45 +0000 Subject: Implemented Operation Stealth's version of addOverlay(objectIndex, overlayType). svn-id: r32816 --- engines/cine/object.cpp | 17 ++++++++++++++--- engines/cine/object.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index b00a636ae6..57a328eef9 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -99,21 +99,32 @@ int removeOverlay(uint16 objIdx, uint16 param) { /*! \brief Add new overlay sprite to the list * \param objIdx Associate the overlay with this object - * \param param Type of new overlay + * \param type Type of new overlay * \todo Why are x, y, width and color left uninitialized? */ -void addOverlay(uint16 objIdx, uint16 param) { +void addOverlay(uint16 objIdx, uint16 type) { Common::List::iterator it; overlay tmp; for (it = overlayList.begin(); it != overlayList.end(); ++it) { + // This is done for both Future Wars and Operation Stealth if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) { break; } + + // There are additional checks in Operation Stealth's implementation + if (g_cine->getGameType() == Cine::GType_OS && (it->type == 2 || it->type == 3)) { + break; + } + } + + // In Operation Stealth's implementation we might bail out early + if (g_cine->getGameType() == Cine::GType_OS && it != overlayList.end() && it->objIdx == objIdx && it->type == type) { + return; } tmp.objIdx = objIdx; - tmp.type = param; + tmp.type = type; overlayList.insert(it, tmp); } diff --git a/engines/cine/object.h b/engines/cine/object.h index 12e72927e1..103b2f50ba 100644 --- a/engines/cine/object.h +++ b/engines/cine/object.h @@ -60,7 +60,7 @@ void loadObject(char *pObjectName); void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4); void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue); -void addOverlay(uint16 objIdx, uint16 param); +void addOverlay(uint16 objIdx, uint16 type); int removeOverlay(uint16 objIdx, uint16 param); void addGfxElement(int16 objIdx, int16 param, int16 type); void removeGfxElement(int16 objIdx, int16 param, int16 type); -- cgit v1.2.3 From b6ad2b00350dffbc4051f3d5eb27b9ce5cb198c4 Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Fri, 27 Jun 2008 09:57:38 +0000 Subject: - Fixed umlauts in printText - Don't exit when a pmv video couldn't be found svn-id: r32817 --- engines/made/pmvplayer.cpp | 5 ++++- engines/made/screen.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 1a8ca9c50a..831f1fab8e 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -40,7 +40,10 @@ void PmvPlayer::play(const char *filename) { _surface = NULL; _fd = new Common::File(); - _fd->open(filename); + if (!_fd->open(filename)) { + delete _fd; + return; + } uint32 chunkType, chunkSize; diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index cecd0c8968..1d81793448 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -688,7 +688,7 @@ void Screen::printText(const char *text) { for (int textPos = 0; textPos < textLen; textPos++) { - uint c = text[textPos]; + uint c = ((byte*)text)[textPos]; int charWidth = _font->getCharWidth(c); if (c == 9) { -- cgit v1.2.3 From e97dff9f33697fac6741a74c02e1034fb126a304 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 28 Jun 2008 13:13:37 +0000 Subject: - HOF: bug fix for music driver - KYRA1 PC98: fix music file selection svn-id: r32819 --- engines/kyra/sound_lok.cpp | 12 ++++++------ engines/kyra/sound_towns.cpp | 12 ++++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index d320536507..7d6e1dd378 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -57,12 +57,12 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { _sound->haltTrack(); } } else if (_flags.platform == Common::kPlatformPC98) { - - ////////////// - //// TODO //// - ////////////// - _sound->playTrack(command); - + if (command == 1) + _sound->beginFadeOut(); + else if (command >= 2) + _sound->playTrack(command); + else + _sound->haltTrack(); } else { KyraEngine_v1::snd_playWanderScoreViaMap(command, restart); } diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 40a746f1de..b487afe8f8 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1273,6 +1273,8 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feedbuf, int &out) o = &feedbuf[0]; i = &feedbuf[1]; phaseShift = _feedbackLevel ? ((feedbuf[0] + feedbuf[1]) << _feedbackLevel) : 0; + if (phasebuf == -1) + *i = 0; *o = *i; } else { phaseShift = phasebuf << 15; @@ -1796,7 +1798,7 @@ void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { break; case 5: *del = feed[1]; - _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); + _channels[i]->opr[0]->generateOutput(-1, feed, phbuf1); _channels[i]->opr[2]->generateOutput(*del, 0, output); _channels[i]->opr[1]->generateOutput(*del, 0, output); _channels[i]->opr[3]->generateOutput(*del, 0, output); @@ -2707,6 +2709,9 @@ bool SoundPC98::init() { } void SoundPC98::playTrack(uint8 track) { + if (--track >= 56) + track -= 55; + if (track == _lastTrack && _musicEnabled) return; @@ -2715,9 +2720,7 @@ void SoundPC98::playTrack(uint8 track) { char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); delete[] _musicTrackData; - // This is just for testing purposes atm since we haven't found a way - // to determine the correct file yet - _musicTrackData = _vm->resource()->fileData("kyram40.dat"/*musicfile*/, 0); + _musicTrackData = _vm->resource()->fileData(musicfile, 0); if (_musicEnabled) _driver->loadData(_musicTrackData); @@ -2767,6 +2770,7 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; + _musicEnabled = 1; return _driver->init(); } -- cgit v1.2.3 From e6e56feb1c61e9d4edb6032e9b759f9875ef00af Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 28 Jun 2008 13:31:58 +0000 Subject: Added comment for fix for bug #2001193. svn-id: r32820 --- engines/parallaction/callables_ns.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index 36f5b00c5b..3ecc7a9534 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -417,7 +417,9 @@ void Parallaction_ns::_c_ridux(void *parm) { } void Parallaction_ns::_c_testResult(void *parm) { - if (_inTestResult) { + if (_inTestResult) { // NOTE: _inTestResult has been added because the scripts call _c_testResult multiple times to cope with + // the multiple buffering that was used in the original engine. _inTestResult now prevents the engine + // from crashing when the scripts are executed. return; } _inTestResult = true; -- cgit v1.2.3 From 09247e7e5a5a78d050b716365a22dc9ccb61b078 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 28 Jun 2008 13:40:03 +0000 Subject: hof: remove debug code svn-id: r32821 --- engines/kyra/sound_towns.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index b487afe8f8..5c9e14e52d 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2770,7 +2770,6 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; - _musicEnabled = 1; return _driver->init(); } -- cgit v1.2.3 From 3f878008dacf420fe48615fd45ae732dc13b1a54 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 28 Jun 2008 15:36:50 +0000 Subject: - implement music fading for Hof FM-Towns svn-id: r32829 --- engines/kyra/sound_towns.cpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 5c9e14e52d..4971d39178 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1090,7 +1090,7 @@ void Towns_EuphonyTrackQueue::initDriver() { class TownsPC98_OpnOperator { public: - TownsPC98_OpnOperator(double rate, uint8 id, const uint8 *rateTable, + TownsPC98_OpnOperator(double rate, const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable); ~TownsPC98_OpnOperator() {} @@ -1152,9 +1152,9 @@ protected: } fs_a, fs_d, fs_s, fs_r; }; -TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, uint8 id, - const uint8 *rateTable, const uint8 *shiftTable, const uint8 *attackDecayTable, - const uint32 *frqTable, const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : +TownsPC98_OpnOperator::TownsPC98_OpnOperator(double rate, const uint8 *rateTable, + const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable, + const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) : _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(rate * 65536.0), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), @@ -1467,6 +1467,7 @@ protected: bool _playing; bool _fading; uint8 _looping; + uint32 _tickCounter; bool _updateEnvelopes; @@ -1490,7 +1491,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _operators(0), _looping(0), _twnCarrier(_drvTables + 76), _twnFreqTable(_drvTables + 84), _twnFxCmdLen(_drvTables + 36), _twnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), - _oprDetune(0), _cbCounter(4), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), + _oprDetune(0), _cbCounter(4), _tickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { @@ -1536,7 +1537,7 @@ bool TownsPC98_OpnDriver::init() { _operators = new TownsPC98_OpnOperator*[(_numChan << 2)]; for (int i = 0; i < (_numChan << 2); i++) - _operators[i] = new TownsPC98_OpnOperator(_baserate, i & 3, _oprRates, + _operators[i] = new TownsPC98_OpnOperator(_baserate, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune); if (_channels) { @@ -1702,6 +1703,7 @@ void TownsPC98_OpnDriver::reset() { _playing = false; _looping = 0; + _tickCounter = 0; } void TownsPC98_OpnDriver::fadeOut() { @@ -1711,16 +1713,29 @@ void TownsPC98_OpnDriver::fadeOut() { _fading = true; for (int i = 0; i < 20; i++) { - - /// TODO /// - // twnFade(); - //waitTicks(s); + lock(); + uint32 dTime = _tickCounter + 2; + for (int i = 0; i < _numChan; i++) { + if (_updateChannelsFlag & _channels[i]->idFlag) { + uint8 tmp = _channels[i]->totalLevel + 3; + if (tmp > 0x7f) + tmp = 0x7f; + _channels[i]->totalLevel = tmp; + setOutputLevel(_channels[i]); + } + } + unlock(); + + while (_playing) { + if (_tickCounter >= dTime) + break; + } } _fading = false; - //haltTrack(); + reset(); } void TownsPC98_OpnDriver::callback() { @@ -1728,6 +1743,7 @@ void TownsPC98_OpnDriver::callback() { return; _cbCounter = 4; + _tickCounter++; lock(); for (int i = 0; i < _numChan; i++) { @@ -2770,6 +2786,7 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; + _musicEnabled = 1; return _driver->init(); } @@ -2793,7 +2810,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { } } - haltTrack(); + beginFadeOut(); char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); -- cgit v1.2.3 From 0184a7b0f9a5bbe4946c2e854f5cbe3c92457474 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 28 Jun 2008 16:00:04 +0000 Subject: Fixed warning. (Hopefully without breaking anything.) svn-id: r32830 --- engines/kyra/sound_towns.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 4971d39178..92e39fc769 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1716,13 +1716,13 @@ void TownsPC98_OpnDriver::fadeOut() { lock(); uint32 dTime = _tickCounter + 2; - for (int i = 0; i < _numChan; i++) { - if (_updateChannelsFlag & _channels[i]->idFlag) { - uint8 tmp = _channels[i]->totalLevel + 3; + for (int j = 0; j < _numChan; j++) { + if (_updateChannelsFlag & _channels[j]->idFlag) { + uint8 tmp = _channels[j]->totalLevel + 3; if (tmp > 0x7f) tmp = 0x7f; - _channels[i]->totalLevel = tmp; - setOutputLevel(_channels[i]); + _channels[j]->totalLevel = tmp; + setOutputLevel(_channels[j]); } } unlock(); -- cgit v1.2.3 From d8645297cd174fbbd7059a317975c45adefaa5e5 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 29 Jun 2008 09:30:32 +0000 Subject: Changed all remaining code to use the GfxObj class to keep frames data. This allows for more uniform processing during rendering, and also fixes the display of dialogue faces for BRA. svn-id: r32833 --- engines/parallaction/dialogue.cpp | 6 ++--- engines/parallaction/disk.h | 46 ++++++++++++++++++------------------- engines/parallaction/disk_br.cpp | 28 +++++++++++----------- engines/parallaction/disk_ns.cpp | 42 ++++++++++++++++----------------- engines/parallaction/gfxbase.cpp | 12 +++++----- engines/parallaction/graphics.cpp | 20 ++++++++++++---- engines/parallaction/graphics.h | 10 ++++---- engines/parallaction/gui_br.cpp | 4 ++-- engines/parallaction/objects.h | 2 +- engines/parallaction/parallaction.h | 6 ++--- 10 files changed, 93 insertions(+), 83 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 903c71907c..3b6c35d3bb 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -51,8 +51,8 @@ class DialogueManager { bool _askPassword; bool isNpc; - Frames *_questioner; - Frames *_answerer; + GfxObj *_questioner; + GfxObj *_answerer; Question *_q; @@ -229,7 +229,7 @@ void DialogueManager::run() { answer = 0; displayQuestion(); - + if (_engineFlags & kEngineQuit) return; diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index b76c66aead..176f10aa10 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -55,13 +55,13 @@ public: virtual Script* loadLocation(const char *name) = 0; virtual Script* loadScript(const char* name) = 0; - virtual Frames* loadTalk(const char *name) = 0; - virtual Frames* loadObjects(const char *name) = 0; + virtual GfxObj* loadTalk(const char *name) = 0; + virtual GfxObj* loadObjects(const char *name) = 0; virtual Frames* loadPointer(const char *name) = 0; - virtual Frames* loadHead(const char* name) = 0; + virtual GfxObj* loadHead(const char* name) = 0; virtual Font* loadFont(const char* name) = 0; - virtual Frames* loadStatic(const char* name) = 0; - virtual Frames* loadFrames(const char* name) = 0; + virtual GfxObj* loadStatic(const char* name) = 0; + virtual GfxObj* loadFrames(const char* name) = 0; virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0; virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0; virtual Table* loadTable(const char* name) = 0; @@ -147,13 +147,13 @@ public: Script* loadLocation(const char *name); Script* loadScript(const char* name); - Frames* loadTalk(const char *name); - Frames* loadObjects(const char *name); + GfxObj* loadTalk(const char *name); + GfxObj* loadObjects(const char *name); Frames* loadPointer(const char *name); - Frames* loadHead(const char* name); + GfxObj* loadHead(const char* name); Font* loadFont(const char* name); - Frames* loadStatic(const char* name); - Frames* loadFrames(const char* name); + GfxObj* loadStatic(const char* name); + GfxObj* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -181,13 +181,13 @@ public: Script* loadLocation(const char *name); Script* loadScript(const char* name); - Frames* loadTalk(const char *name); - Frames* loadObjects(const char *name); + GfxObj* loadTalk(const char *name); + GfxObj* loadObjects(const char *name); Frames* loadPointer(const char *name); - Frames* loadHead(const char* name); + GfxObj* loadHead(const char* name); Font* loadFont(const char* name); - Frames* loadStatic(const char* name); - Frames* loadFrames(const char* name); + GfxObj* loadStatic(const char* name); + GfxObj* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -220,13 +220,13 @@ public: void setLanguage(uint16 language); Script* loadLocation(const char *name); Script* loadScript(const char* name); - Frames* loadTalk(const char *name); - Frames* loadObjects(const char *name); + GfxObj* loadTalk(const char *name); + GfxObj* loadObjects(const char *name); Frames* loadPointer(const char *name); - Frames* loadHead(const char* name); + GfxObj* loadHead(const char* name); Font* loadFont(const char* name); - Frames* loadStatic(const char* name); - Frames* loadFrames(const char* name); + GfxObj* loadStatic(const char* name); + GfxObj* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); Table* loadTable(const char* name); @@ -248,10 +248,10 @@ public: AmigaDisk_br(Parallaction *vm); virtual ~AmigaDisk_br(); - Frames* loadTalk(const char *name); + GfxObj* loadTalk(const char *name); Font* loadFont(const char* name); - Frames* loadStatic(const char* name); - Frames* loadFrames(const char* name); + GfxObj* loadStatic(const char* name); + GfxObj* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); }; diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 5e88327879..0159d9d406 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -138,7 +138,7 @@ DosDisk_br::DosDisk_br(Parallaction* vm) : _vm(vm) { DosDisk_br::~DosDisk_br() { } -Frames* DosDisk_br::loadTalk(const char *name) { +GfxObj* DosDisk_br::loadTalk(const char *name) { debugC(5, kDebugDisk, "DosDisk_br::loadTalk(%s)", name); Common::File stream; @@ -151,7 +151,7 @@ Frames* DosDisk_br::loadTalk(const char *name) { errorFileNotFound(path); } - return createSprites(stream); + return new GfxObj(0, createSprites(stream), name); } Script* DosDisk_br::loadLocation(const char *name) { @@ -184,7 +184,7 @@ Script* DosDisk_br::loadScript(const char* name) { } // there are no Head resources in Big Red Adventure -Frames* DosDisk_br::loadHead(const char* name) { +GfxObj* DosDisk_br::loadHead(const char* name) { debugC(5, kDebugDisk, "DosDisk_br::loadHead"); return 0; } @@ -235,7 +235,7 @@ Font* DosDisk_br::loadFont(const char* name) { } -Frames* DosDisk_br::loadObjects(const char *name) { +GfxObj* DosDisk_br::loadObjects(const char *name) { debugC(5, kDebugDisk, "DosDisk_br::loadObjects"); return 0; } @@ -244,7 +244,7 @@ void genSlidePath(char *path, const char* name) { sprintf(path, "%s.bmp", name); } -Frames* DosDisk_br::loadStatic(const char* name) { +GfxObj* DosDisk_br::loadStatic(const char* name) { debugC(5, kDebugDisk, "DosDisk_br::loadStatic"); char path[PATH_LEN]; @@ -256,7 +256,7 @@ Frames* DosDisk_br::loadStatic(const char* name) { Graphics::Surface *surf = new Graphics::Surface; loadBitmap(stream, *surf, 0); - return new SurfaceToFrames(surf); + return new GfxObj(0, new SurfaceToFrames(surf), name); } Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) { @@ -280,7 +280,7 @@ Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) { return sprites; } -Frames* DosDisk_br::loadFrames(const char* name) { +GfxObj* DosDisk_br::loadFrames(const char* name) { debugC(5, kDebugDisk, "DosDisk_br::loadFrames"); char path[PATH_LEN]; @@ -291,7 +291,7 @@ Frames* DosDisk_br::loadFrames(const char* name) { errorFileNotFound(path); - return createSprites(stream); + return new GfxObj(0, createSprites(stream), name); } // Slides in Nippon Safes are basically screen-sized pictures with valid @@ -552,7 +552,7 @@ void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) { return; } -Frames* AmigaDisk_br::loadStatic(const char* name) { +GfxObj* AmigaDisk_br::loadStatic(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name); char path[PATH_LEN]; @@ -570,7 +570,7 @@ Frames* AmigaDisk_br::loadStatic(const char* name) { free(pal); - return new SurfaceToFrames(surf); + return new GfxObj(0, new SurfaceToFrames(surf)); } Sprites* AmigaDisk_br::createSprites(const char *path) { @@ -600,22 +600,22 @@ Sprites* AmigaDisk_br::createSprites(const char *path) { return sprites; } -Frames* AmigaDisk_br::loadFrames(const char* name) { +GfxObj* AmigaDisk_br::loadFrames(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_br::loadFrames '%s'", name); char path[PATH_LEN]; sprintf(path, "%s/anims/%s", _partPath, name); - return createSprites(path); + return new GfxObj(0, createSprites(path)); } -Frames* AmigaDisk_br::loadTalk(const char *name) { +GfxObj* AmigaDisk_br::loadTalk(const char *name) { debugC(1, kDebugDisk, "AmigaDisk_br::loadTalk '%s'", name); char path[PATH_LEN]; sprintf(path, "%s/talks/%s.tal", _partPath, name); - return createSprites(path); + return new GfxObj(0, createSprites(path)); } Font* AmigaDisk_br::loadFont(const char* name) { diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index 8f4f6d8e20..f45cf83f56 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -385,12 +385,12 @@ Cnv* DosDisk_ns::loadCnv(const char *filename) { return new Cnv(numFrames, width, height, data); } -Frames* DosDisk_ns::loadTalk(const char *name) { +GfxObj* DosDisk_ns::loadTalk(const char *name) { const char *ext = strstr(name, ".talk"); if (ext != NULL) { // npc talk - return loadCnv(name); + return new GfxObj(0, loadCnv(name), name); } @@ -401,7 +401,7 @@ Frames* DosDisk_ns::loadTalk(const char *name) { sprintf(v20, "%stal", name); } - return loadExternalCnv(v20); + return new GfxObj(0, loadExternalCnv(v20), name); } Script* DosDisk_ns::loadLocation(const char *name) { @@ -434,14 +434,14 @@ Script* DosDisk_ns::loadScript(const char* name) { return new Script(new DummyArchiveStream(_resArchive), true); } -Frames* DosDisk_ns::loadHead(const char* name) { +GfxObj* DosDisk_ns::loadHead(const char* name) { char path[PATH_LEN]; sprintf(path, "%shead", name); path[8] = '\0'; - return loadExternalStaticCnv(path); + return new GfxObj(0, loadExternalStaticCnv(path)); } @@ -457,15 +457,15 @@ Font* DosDisk_ns::loadFont(const char* name) { } -Frames* DosDisk_ns::loadObjects(const char *name) { +GfxObj* DosDisk_ns::loadObjects(const char *name) { char path[PATH_LEN]; sprintf(path, "%sobj", name); - return loadExternalCnv(path); + return new GfxObj(0, loadExternalCnv(path), name); } -Frames* DosDisk_ns::loadStatic(const char* name) { +GfxObj* DosDisk_ns::loadStatic(const char* name) { char path[PATH_LEN]; @@ -487,11 +487,11 @@ Frames* DosDisk_ns::loadStatic(const char* name) { Graphics::PackBitsReadStream decoder(_resArchive); decoder.read(cnv->pixels, w*h); - return new SurfaceToFrames(cnv); + return new GfxObj(0, new SurfaceToFrames(cnv), name); } -Frames* DosDisk_ns::loadFrames(const char* name) { - return loadCnv(name); +GfxObj* DosDisk_ns::loadFrames(const char* name) { + return new GfxObj(0, loadCnv(name), name); } // @@ -1025,7 +1025,7 @@ Frames* AmigaDisk_ns::loadPointer(const char* name) { return makeStaticCnv(stream); } -Frames* AmigaDisk_ns::loadStatic(const char* name) { +GfxObj* AmigaDisk_ns::loadStatic(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadStatic '%s'", name); Common::SeekableReadStream *s = openArchivedFile(name, true); @@ -1033,7 +1033,7 @@ Frames* AmigaDisk_ns::loadStatic(const char* name) { delete s; - return cnv; + return new GfxObj(0, cnv, name); } Common::SeekableReadStream *AmigaDisk_ns::openArchivedFile(const char* name, bool errorOnFileNotFound) { @@ -1258,7 +1258,7 @@ void AmigaDisk_ns::loadSlide(BackgroundInfo& info, const char *name) { return; } -Frames* AmigaDisk_ns::loadFrames(const char* name) { +GfxObj* AmigaDisk_ns::loadFrames(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name); Common::SeekableReadStream *s; @@ -1273,10 +1273,10 @@ Frames* AmigaDisk_ns::loadFrames(const char* name) { Cnv *cnv = makeCnv(*s); delete s; - return cnv; + return new GfxObj(0, cnv, name); } -Frames* AmigaDisk_ns::loadHead(const char* name) { +GfxObj* AmigaDisk_ns::loadHead(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadHead '%s'", name); char path[PATH_LEN]; @@ -1287,11 +1287,11 @@ Frames* AmigaDisk_ns::loadHead(const char* name) { delete s; - return cnv; + return new GfxObj(0, cnv, name); } -Frames* AmigaDisk_ns::loadObjects(const char *name) { +GfxObj* AmigaDisk_ns::loadObjects(const char *name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadObjects"); char path[PATH_LEN]; @@ -1305,11 +1305,11 @@ Frames* AmigaDisk_ns::loadObjects(const char *name) { Cnv *cnv = makeCnv(*s); delete s; - return cnv; + return new GfxObj(0, cnv, name); } -Frames* AmigaDisk_ns::loadTalk(const char *name) { +GfxObj* AmigaDisk_ns::loadTalk(const char *name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadTalk '%s'", name); Common::SeekableReadStream *s; @@ -1328,7 +1328,7 @@ Frames* AmigaDisk_ns::loadTalk(const char *name) { Cnv *cnv = makeCnv(*s); delete s; - return cnv; + return new GfxObj(0, cnv, name); } Table* AmigaDisk_ns::loadTable(const char* name) { diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 6599a1f81c..dc28d9d425 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -86,27 +86,27 @@ void GfxObj::clearFlags(uint32 flags) { } GfxObj* Gfx::loadAnim(const char *name) { - Frames *frames = _disk->loadFrames(name); - GfxObj *obj = new GfxObj(kGfxObjTypeAnim, frames, name); + GfxObj *obj = _disk->loadFrames(name); assert(obj); + obj->type = kGfxObjTypeAnim; return obj; } GfxObj* Gfx::loadGet(const char *name) { - Frames *frames = _disk->loadStatic(name); - GfxObj *obj = new GfxObj(kGfxObjTypeGet, frames, name); + GfxObj *obj = _disk->loadStatic(name); assert(obj); + obj->type = kGfxObjTypeGet; return obj; } GfxObj* Gfx::loadDoor(const char *name) { - Frames *frames = _disk->loadFrames(name); - GfxObj *obj = new GfxObj(kGfxObjTypeDoor, frames, name); + GfxObj *obj = _disk->loadFrames(name); assert(obj); + obj->type = kGfxObjTypeDoor; return obj; } diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 58fb02a750..64edd7babe 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -356,7 +356,17 @@ void Gfx::drawItems() { Graphics::Surface *surf = g_system->lockScreen(); for (uint i = 0; i < _numItems; i++) { - blt(_items[i].rect, _items[i].data->getData(_items[i].frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); + GfxObj *obj = _items[i].data; + + Common::Rect rect; + obj->getRect(obj->frame, rect); + rect.translate(obj->x, obj->y); + + if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { + blt(rect, obj->getData(obj->frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); + } else { + unpackBlt(rect, obj->getData(obj->frame), obj->getRawSize(obj->frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); + } } g_system->unlockScreen(); } @@ -949,7 +959,7 @@ Gfx::~Gfx() { -int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) { +int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { int id = _numItems; _items[id].data = frames; @@ -965,9 +975,9 @@ int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) { void Gfx::setItemFrame(uint item, uint16 f) { assert(item < _numItems); - _items[item].frame = f; - _items[item].data->getRect(f, _items[item].rect); - _items[item].rect.moveTo(_items[item].x, _items[item].y); + _items[item].data->frame = f; + _items[item].data->x = _items[item].x; + _items[item].data->y = _items[item].y; } Gfx::Balloon* Gfx::getBalloon(uint id) { diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index f03b8538b8..c4b0c7b321 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -157,11 +157,11 @@ struct SurfaceToMultiFrames : public Frames { r.setHeight(_height); } uint getRawSize(uint16 index) { - assert(index == 0); + assert(index < _num); return getSize(index); } uint getSize(uint16 index) { - assert(index == 0); + assert(index < _num); return _width * _height; } @@ -487,7 +487,7 @@ public: void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height); // other items - int setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor = 0); + int setItem(GfxObj* obj, uint16 x, uint16 y, byte transparentColor = 0); void setItemFrame(uint item, uint16 f); void hideDialogueStuff(); void freeBalloons(); @@ -549,7 +549,7 @@ protected: Graphics::Surface _bitmapMask; int32 getRenderMode(const char *type); -protected: +public: static int16 _dialogueBalloonX[5]; struct Balloon { @@ -567,7 +567,7 @@ protected: uint16 x; uint16 y; uint16 frame; - Frames *data; + GfxObj *data; byte transparentColor; Common::Rect rect; diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index c515299a34..5551108693 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -122,7 +122,7 @@ int Parallaction_br::guiShowMenu() { // TODO: filter menu entries according to progress in game #define NUM_MENULINES 7 - Frames *_lines[NUM_MENULINES]; + GfxObj *_lines[NUM_MENULINES]; const char *menuStrings[NUM_MENULINES] = { "SEE INTRO", @@ -157,7 +157,7 @@ int Parallaction_br::guiShowMenu() { int i; for (i = 0; i < availItems; i++) { - _lines[i] = guiRenderMenuItem(menuStrings[i]); + _lines[i] = new GfxObj(0, guiRenderMenuItem(menuStrings[i]), "MenuItem"); uint id = _gfx->setItem(_lines[i], MENUITEMS_X, MENUITEMS_Y + MENUITEM_HEIGHT * i, 0xFF); _gfx->setItemFrame(id, 0); } diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index 2bc9df0bbe..44ad35e0ab 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -209,7 +209,7 @@ struct SpeakData { // size = 36 } }; struct ExamineData { // size = 28 - Frames *_cnv; + GfxObj *_cnv; uint16 _opBase; // unused uint16 field_12; // unused char* _description; diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index f9c2c86a1b..b1a5995e28 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -202,9 +202,9 @@ struct Character { AnimationPtr _ani; - Frames *_head; - Frames *_talk; - Frames *_objs; + GfxObj *_head; + GfxObj *_talk; + GfxObj *_objs; PathBuilder _builder; WalkNodeList *_walkPath; -- cgit v1.2.3 From 206485ffc676c64134774b9873cd8d333deddfee Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 29 Jun 2008 09:56:44 +0000 Subject: Merged the three render lists (for animations, doors and objects) into a single one. svn-id: r32834 --- engines/parallaction/debug.cpp | 14 +++++------- engines/parallaction/gfxbase.cpp | 47 ++++++++++++++++++++-------------------- engines/parallaction/graphics.h | 12 ++++++++-- 3 files changed, 39 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp index 3c90a76f61..6bd704a2f5 100644 --- a/engines/parallaction/debug.cpp +++ b/engines/parallaction/debug.cpp @@ -191,14 +191,12 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { "| name | x | y | z | f | type | flag |\n" "+--------------------+-----+-----+-----+-----+--------+--------+\n"); - for (uint i = 0; i < 3; i++) { - GfxObjList::iterator b = _vm->_gfx->_gfxobjList[i].begin(); - GfxObjList::iterator e = _vm->_gfx->_gfxobjList[i].end(); - - for ( ; b != e; b++) { - GfxObj *obj = *b; - DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], 6 ); - } + GfxObjList::iterator b = _vm->_gfx->_gfxobjList.begin(); + GfxObjList::iterator e = _vm->_gfx->_gfxobjList.end(); + + for ( ; b != e; b++) { + GfxObj *obj = *b; + DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], 6 ); } DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n"); diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index dc28d9d425..66b1ceecf7 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -89,6 +89,8 @@ GfxObj* Gfx::loadAnim(const char *name) { GfxObj *obj = _disk->loadFrames(name); assert(obj); + // animation Z is not set here, but controlled by game scripts and user interaction. + // it is always >=0 and type = kGfxObjTypeAnim; return obj; } @@ -98,6 +100,7 @@ GfxObj* Gfx::loadGet(const char *name) { GfxObj *obj = _disk->loadStatic(name); assert(obj); + obj->z = kGfxObjGetZ; // this preset Z value ensures that get zones are drawn after doors but before animations obj->type = kGfxObjTypeGet; return obj; } @@ -106,14 +109,13 @@ GfxObj* Gfx::loadDoor(const char *name) { GfxObj *obj = _disk->loadFrames(name); assert(obj); + obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first obj->type = kGfxObjTypeDoor; return obj; } void Gfx::clearGfxObjects() { - _gfxobjList[0].clear(); - _gfxobjList[1].clear(); - _gfxobjList[2].clear(); + _gfxobjList.clear(); } void Gfx::showGfxObj(GfxObj* obj, bool visible) { @@ -123,25 +125,25 @@ void Gfx::showGfxObj(GfxObj* obj, bool visible) { if (visible) { obj->setFlags(kGfxObjVisible); - _gfxobjList[obj->type].push_back(obj); + _gfxobjList.push_back(obj); } else { obj->clearFlags(kGfxObjVisible); - _gfxobjList[obj->type].remove(obj); + _gfxobjList.remove(obj); } } -bool compareAnimationZ(const GfxObj* a1, const GfxObj* a2) { +bool compareZ(const GfxObj* a1, const GfxObj* a2) { return a1->z < a2->z; } void Gfx::sortAnimations() { - GfxObjList::iterator first = _gfxobjList[kGfxObjTypeAnim].begin(); - GfxObjList::iterator last = _gfxobjList[kGfxObjTypeAnim].end(); + GfxObjList::iterator first = _gfxobjList.begin(); + GfxObjList::iterator last = _gfxobjList.end(); - Common::sort(first, last, compareAnimationZ); + Common::sort(first, last, compareZ); } void Gfx::drawGfxObjects(Graphics::Surface &surf) { @@ -154,22 +156,19 @@ void Gfx::drawGfxObjects(Graphics::Surface &surf) { // TODO: Dr.Ki is not visible inside the club - for (uint i = 0; i < 3; i++) { + GfxObjList::iterator b = _gfxobjList.begin(); + GfxObjList::iterator e = _gfxobjList.end(); - GfxObjList::iterator b = _gfxobjList[i].begin(); - GfxObjList::iterator e = _gfxobjList[i].end(); - - for (; b != e; b++) { - GfxObj *obj = *b; - if (obj->isVisible()) { - obj->getRect(obj->frame, rect); - rect.translate(obj->x - _varScrollX, obj->y); - data = obj->getData(obj->frame); - if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { - blt(rect, data, &surf, obj->layer, 0); - } else { - unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, 0); - } + for (; b != e; b++) { + GfxObj *obj = *b; + if (obj->isVisible()) { + obj->getRect(obj->frame, rect); + rect.translate(obj->x - _varScrollX, obj->y); + data = obj->getData(obj->frame); + if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { + blt(rect, data, &surf, obj->layer, 0); + } else { + unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, 0); } } } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index c4b0c7b321..6439941cc5 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -360,6 +360,11 @@ enum { kGfxObjTypeAnim = 2 }; +enum { + kGfxObjDoorZ = -200, + kGfxObjGetZ = -100 +}; + class GfxObj { char *_name; Frames *_frames; @@ -369,7 +374,10 @@ class GfxObj { public: int16 x, y; - uint16 z; + + int32 z; + + uint type; uint frame; uint layer; @@ -461,7 +469,7 @@ public: Disk *_disk; VarMap _vars; - GfxObjList _gfxobjList[3]; + GfxObjList _gfxobjList; GfxObj* loadAnim(const char *name); GfxObj* loadGet(const char *name); GfxObj* loadDoor(const char *name); -- cgit v1.2.3 From b0e22db7a89a27a7f9c09870fded7a64042293c7 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 29 Jun 2008 15:25:45 +0000 Subject: - some more work on the Hof FM-Towns/PC98 music driver - move channels to a separate class svn-id: r32841 --- engines/kyra/detection.cpp | 2 +- engines/kyra/sound.h | 4 +- engines/kyra/sound_towns.cpp | 1951 ++++++++++++++++++++++++------------------ 3 files changed, 1137 insertions(+), 820 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 1e174bdfcf..3fb62b51bd 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -346,7 +346,7 @@ const KYRAGameDescription adGameDescs[] = { KYRA2_FLOPPY_CMP_FLAGS }, - { // // Floppy version extracted + { // Floppy version extracted { "kyra2", "Extracted", diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index c08c531ab9..cebfdf491f 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -486,11 +486,13 @@ public: void beginFadeOut(); int32 voicePlay(const char *file, bool isSfx = false); - void playSoundEffect(uint8) {} + void playSoundEffect(uint8 track); protected: Audio::AudioStream *_currentSFX; int _lastTrack; + bool _useFmSfx; + uint8 *_musicTrackData; TownsPC98_OpnDriver *_driver; }; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 92e39fc769..4a8e8a5b15 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1100,7 +1100,7 @@ public: void frequency(int freq); void updatePhaseIncrement(); void recalculateRates(); - void generateOutput(int phasebuf, int *feedbuf, int &out); + void generateOutput(int phasebuf, int *_feedbuf, int &out); void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; } void detune(int value) { _detn = &_detnTbl[value << 5]; } @@ -1209,7 +1209,7 @@ void TownsPC98_OpnOperator::recalculateRates() { fs_r.shift = _rshiftTbl[r + k]; } -void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feedbuf, int &out) { +void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *_feedbuf, int &out) { if (_state == s_ready) return; @@ -1269,10 +1269,10 @@ void TownsPC98_OpnOperator::generateOutput(int phasebuf, int *feedbuf, int &out) int *i = &outp, *o = &outp; int phaseShift = 0; - if (feedbuf) { - o = &feedbuf[0]; - i = &feedbuf[1]; - phaseShift = _feedbackLevel ? ((feedbuf[0] + feedbuf[1]) << _feedbackLevel) : 0; + if (_feedbuf) { + o = &_feedbuf[0]; + i = &_feedbuf[1]; + phaseShift = _feedbackLevel ? ((_feedbuf[0] + _feedbuf[1]) << _feedbackLevel) : 0; if (phasebuf == -1) *i = 0; *o = *i; @@ -1329,7 +1329,121 @@ bool TownsPC98_OpnOperator::scaleRate(uint8 value) { return false; } +class TownsPC98_OpnDriver; +class TownsPC98_OpnChannel { +public: + TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, + uint8 key, uint8 prt, uint8 id); + ~TownsPC98_OpnChannel(); + virtual void init(); + + typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para); + + typedef enum channelState { + CHS_RECALCFREQ = 0x01, + CHS_KEYOFF = 0x02, + CHS_SSG = 0x04, + CHS_PITCHWHEELOFF = 0x08, + CHS_ALL_BUT_EOT = 0x0f, + CHS_EOT = 0x80 + } ChannelState; + + void loadData(uint8 *data); + virtual void processEvents(); + virtual void processFrequency(); + bool processControlEvent(uint8 cmd); + void writeReg(uint8 regAdress, uint8 value); + + virtual void keyOn(); + virtual void keyOff(); + + void setOutputLevel(); + void fadeStep(); + void reset(); + + void updateEnv(); + void generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed); + + bool _enableLeft; + bool _enableRight; + bool _fading; + bool _updateEnvelopes; + const uint8 _idFlag; + int _feedbuf[3]; + +protected: + bool control_dummy(uint8 para); + bool control_f0_setPatch(uint8 para); + bool control_f1_presetOutputLevel(uint8 para); + bool control_f2_setKeyOffTime(uint8 para); + bool control_f3_setFreqLSB(uint8 para); + bool control_f4_setOutputLevel(uint8 para); + bool control_f5_setTempo(uint8 para); + bool control_f6_repeatSection(uint8 para); + bool control_f7_setupPitchWheel(uint8 para); + bool control_f8_togglePitchWheel(uint8 para); + bool control_fa_writeReg(uint8 para); + bool control_fb_incOutLevel(uint8 para); + bool control_fc_decOutLevel(uint8 para); + bool control_fd_jump(uint8 para); + bool control_ff_endOfTrack(uint8 para); + + bool control_f0_setPatchSSG(uint8 para); + bool control_f1_setTotalLevel(uint8 para); + bool control_f4_setAlgorithm(uint8 para); + bool control_f9_unkSSG(uint8 para); + bool control_fb_incOutLevelSSG(uint8 para); + bool control_fc_decOutLevelSSG(uint8 para); + bool control_ff_endOfTrackSSG(uint8 para); + + uint8 _ticksLeft; + uint8 _algorithm; + uint8 _instrID; + uint8 _totalLevel; + uint8 _frqBlockMSB; + int8 _frqLSB; + uint8 _keyOffTime; + bool _protect; + uint8 *_dataPtr; + uint8 _unk15, _unk16; + uint8 _ptchWhlInitDelayLo; + uint8 _ptchWhlInitDelayHi; + int16 _ptchWhlModInitVal; + uint8 _ptchWhlDuration; + uint8 _ptchWhlCurDelay; + int16 _ptchWhlModCurVal; + uint8 _ptchWhlDurLeft; + uint16 frequency; + uint8 _unk28, _unk29; + uint8 _regOffset; + uint8 _flags; + const uint8 _chanNum; + const uint8 _keyNum; + const uint8 _part; + + TownsPC98_OpnDriver *_drv; + TownsPC98_OpnOperator **_opr; + uint16 _frqTemp; + + const ControlEventFunc *controlEvents; +}; + +class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel { +public: + TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id); + void init(); + + void processEvents(); + void processFrequency(); + + void keyOn(); + void keyOff(); +}; + class TownsPC98_OpnDriver : public Audio::AudioStream { +friend class TownsPC98_OpnChannel; +friend class TownsPC98_OpnChannelSSG; public: enum OpnType { OD_TOWNS, @@ -1362,92 +1476,23 @@ public: protected: void generateTables(); - typedef enum channelState { - CHS_RECALCFREQ = 0x01, - CHS_KEYOFF = 0x02, - CHS_PITCHWHEELOFF = 0x08, - CHS_ALL_BUT_EOT = 0x0f, - CHS_EOT = 0x80 - } ChannelState; + TownsPC98_OpnChannel **_channels; + TownsPC98_OpnChannelSSG **_ssgChannels; + //TownsPC98_OpnChannel *_adpcmChannel; - struct TwnChannel { - uint8 ticksLeft; - uint8 unk1, unk2, unk3; - uint8 algorithm; - uint8 instrID; - uint8 totalLevel; - uint8 frqBlockMSB; - int8 frqLSB; - uint8 keyOffTime; - bool protect; - uint8 *dataPtr; - uint8 unk15, unk16; - uint8 ptchWhlInitDelayLo; - uint8 ptchWhlInitDelayHi; - int16 ptchWhlModInitVal; - uint8 ptchWhlDuration; - uint8 ptchWhlCurDelay; - int16 ptchWhlModCurVal; - uint8 ptchWhlDurLeft; - uint16 frequency; - uint8 unk28, unk29; - uint8 regOffset; - uint8 flags; - uint8 chanNum; - uint8 keyNum; - uint8 part; - uint8 idFlag; - - TownsPC98_OpnOperator *opr[4]; - uint16 frqTemp; - bool enableLeft; - bool enableRight; - bool updateEnvelopes; - int feedbuf[3]; - } **_channels; - - void processEvents(TwnChannel *chan); - void processFrequency(TwnChannel *chan); - bool processControlEvent(TwnChannel *chan, uint8 cmd); - - void setOutputLevel(TwnChannel *chan); void setTempo(uint8 tempo); - void keyOn(TwnChannel *chan); - void keyOff(TwnChannel *chan); - void writeReg(TwnChannel *chan, uint8 regAdress, uint8 value); - void lock() { _mutex.lock(); } void unlock() { _mutex.unlock(); } - bool control_f0_setPatch(TwnChannel *chan, uint8 para); - bool control_f1_presetOutputLevel(TwnChannel *chan, uint8 para); - bool control_f2_setKeyOffTime(TwnChannel *chan, uint8 para); - bool control_f3_setFreqLSB(TwnChannel *chan, uint8 para); - bool control_f4_setOutputLevel(TwnChannel *chan, uint8 para); - bool control_f5_setTempo(TwnChannel *chan, uint8 para); - bool control_f6_repeatSection(TwnChannel *chan, uint8 para); - bool control_f7_setupPitchWheel(TwnChannel *chan, uint8 para); - bool control_f8_togglePitchWheel(TwnChannel *chan, uint8 para); - bool control_f9_unk(TwnChannel *chan, uint8 para); - bool control_fa_writeReg(TwnChannel *chan, uint8 para); - bool control_fb_incOutLevel(TwnChannel *chan, uint8 para); - bool control_fc_decOutLevel(TwnChannel *chan, uint8 para); - bool control_fd_jump(TwnChannel *chan, uint8 para); - bool control_fe_unk(TwnChannel *chan, uint8 para); - bool control_ff_endOfTrack(TwnChannel *chan, uint8 para); - - typedef bool (TownsPC98_OpnDriver::*ControlEventFunc)(TwnChannel * chan, uint8 para); - Audio::Mixer *_mixer; - TownsPC98_OpnOperator **_operators; Common::Mutex _mutex; Audio::SoundHandle _soundHandle; - const uint8 *_twnCarrier; - const uint8 *_twnFreqTable; - const uint8 *_twnFxCmdLen; - const uint8 *_twnLvlPresets; + const uint8 *_opnCarrier; + const uint8 *_opnFreqTable; + const uint8 *_opnFxCmdLen; + const uint8 *_opnLvlPresets; uint8 *_oprRates; uint8 *_oprRateshift; @@ -1465,11 +1510,10 @@ protected: uint8 _finishedChannelsFlag; uint16 _tempo; bool _playing; - bool _fading; uint8 _looping; uint32 _tickCounter; - bool _updateEnvelopes; + bool __updateEnvelopes; int32 _samplesTillCallback; int32 _samplesTillCallbackRemainder; @@ -1484,890 +1528,1148 @@ protected: double _baserate; static const uint8 _drvTables[]; static const uint32 _adtStat[]; + bool _ready; }; -TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : - _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), - _operators(0), _looping(0), _twnCarrier(_drvTables + 76), _twnFreqTable(_drvTables + 84), - _twnFxCmdLen(_drvTables + 36), _twnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , - _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), - _oprDetune(0), _cbCounter(4), _tickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), - _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), - _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), - _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { - setTempo(84); - _baserate = (3579545.0 / (double)getRate()) / 144.0; -} - -TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { - _mixer->stopHandle(_soundHandle); - - if (_operators) { - for (int i = 0; i < (_numChan << 2); i++) - delete _operators[i]; - delete [] _operators; - } - - if (_channels) { - for (int i = 0; i < _numChan; i++) - delete _channels[i]; - delete [] _channels; - } +TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, + uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key), + _part(prt), _idFlag(id) { - delete [] _oprRates; - delete [] _oprRateshift; - delete [] _oprFrq; - delete [] _oprAttackDecay; - delete [] _oprSinTbl; - delete [] _oprLevelOut; - delete [] _oprDetune; + _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _unk15 = _unk16 = 0; + _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = _unk28 = _unk29 = 0; + _frqLSB = 0; + _protect = _updateEnvelopes = _fading = false; + _enableLeft = _enableRight = true; + _dataPtr = 0; + _ptchWhlModInitVal = _ptchWhlModCurVal = 0; + frequency = _frqTemp = 0; + memset(&_feedbuf, 0, sizeof(int) * 3); + _opr = 0; } -bool TownsPC98_OpnDriver::init() { - generateTables(); - - if (_operators) { - for (int i = 0; i < (_numChan << 2); i++) { - if (_operators[i]) { - delete _operators[i]; - } - } - delete [] _operators; +TownsPC98_OpnChannel::~TownsPC98_OpnChannel() { + if (_opr) { + for (int i = 0; i < 4; i++) + delete _opr[i]; + delete [] _opr; } +} - _operators = new TownsPC98_OpnOperator*[(_numChan << 2)]; - for (int i = 0; i < (_numChan << 2); i++) - _operators[i] = new TownsPC98_OpnOperator(_baserate, _oprRates, - _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune); - - if (_channels) { - for (int i = 0; i < _numChan; i++) { - if (_channels[i]) - delete _channels[i]; - } - delete [] _channels; - } - _channels = new TwnChannel*[_numChan]; - for (int i = 0; i < _numChan; i++) { - _channels[i] = new TwnChannel; - for (int ii = 0; ii < 4; ii++) { - _channels[i]->opr[ii] = _operators[(i << 2) + ii]; - _channels[i]->updateEnvelopes = false; - } - } +void TownsPC98_OpnChannel::init() { + + _opr = new TownsPC98_OpnOperator*[4]; + for (int i = 0; i < 4; i++) + _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, + _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune); - for (int i = 0; i < _numChan; i++) { - int ix = i * 6; - memset(_channels[i], 0, sizeof(TwnChannel)); - _channels[i]->regOffset = _drvTables[ix]; - _channels[i]->flags = _drvTables[ix + 1]; - _channels[i]->chanNum = _drvTables[ix + 2]; - _channels[i]->keyNum = _drvTables[ix + 3]; - _channels[i]->part = _drvTables[ix + 4]; - _channels[i]->idFlag = _drvTables[ix + 5]; - } + #define Control(x) &TownsPC98_OpnChannel::control_##x + static const ControlEventFunc ctrlEvents[] = { + Control(f0_setPatch), + Control(f1_presetOutputLevel), + Control(f2_setKeyOffTime), + Control(f3_setFreqLSB), + Control(f4_setOutputLevel), + Control(f5_setTempo), + Control(f6_repeatSection), + Control(f7_setupPitchWheel), + Control(f8_togglePitchWheel), + Control(dummy), + Control(fa_writeReg), + Control(fb_incOutLevel), + Control(fc_decOutLevel), + Control(fd_jump), + Control(dummy), + Control(ff_endOfTrack) + }; + #undef Control - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + controlEvents = ctrlEvents; +} - return true; +void TownsPC98_OpnChannel::keyOff() { + // all operators off + uint8 value = _keyNum & 0x0f; + uint8 regAdress = 0x28; + writeReg(regAdress, value); + _flags |= CHS_KEYOFF; } -int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { - memset(buffer, 0, sizeof(int16) * numSamples); - int32 samplesLeft = numSamples >> 1; - while (samplesLeft) { - if (!_samplesTillCallback) { - callback(); - _samplesTillCallback = _samplesPerCallback; - _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; - if (_samplesTillCallbackRemainder >= _tempo) { - _samplesTillCallback++; - _samplesTillCallbackRemainder -= _tempo; - } - } +void TownsPC98_OpnChannel::keyOn() { + // all operators on + uint8 value = _keyNum | 0xf0; + uint8 regAdress = 0x28; + writeReg(regAdress, value); +} - int32 render = MIN(samplesLeft, _samplesTillCallback); - samplesLeft -= render; - _samplesTillCallback -= render; - nextTick(buffer, render); +void TownsPC98_OpnChannel::loadData(uint8 *data) { + _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; + _ticksLeft = 1; + _dataPtr = data; + _totalLevel = 0x7F; - for (int i = 0; i < render; ++i) { - buffer[i << 1] <<= 2; - buffer[(i << 1) + 1] <<= 2; + uint8 *src_b = _dataPtr; + int loop = 1; + uint8 cmd = 0; + while (loop) { + if (loop == 1) { + cmd = *src_b++; + if (cmd < 0xf0) { + src_b++; + loop = 1; + } else { + if (cmd == 0xff) { + loop = *src_b ? 2 : 0; + if (READ_LE_UINT16(src_b)) + _drv->_looping |= _idFlag; + } else if (cmd == 0xf6) { + loop = 3; + } else { + loop = 2; + } + } + } else if (loop == 2) { + src_b += _drv->_opnFxCmdLen[cmd - 240]; + loop = 1; + } else if (loop == 3) { + src_b[0] = src_b[1]; + src_b += 4; + loop = 1; } - - buffer += (render << 1); } - - return numSamples; } -void TownsPC98_OpnDriver::loadData(uint8 * data, bool loadPaused) { - - lock(); - _trackData = data; - - reset(); +void TownsPC98_OpnChannel::processEvents() { + if (_flags & CHS_EOT) + return; - for (uint8 i = 0; i < _numChan; i++) { - uint8 tmp1 = _channels[i]->regOffset; - uint8 tmp2 = _channels[i]->flags; - uint8 tmp3 = _channels[i]->chanNum; - uint8 tmp4 = _channels[i]->keyNum; - uint8 tmp5 = _channels[i]->part; - uint8 tmp6 = _channels[i]->idFlag; - memset(_channels[i], 0, sizeof(TwnChannel)); - _channels[i]->regOffset = tmp1; - _channels[i]->flags = tmp2; - _channels[i]->chanNum = tmp3; - _channels[i]->keyNum = tmp4; - _channels[i]->part = tmp5; - _channels[i]->idFlag = tmp6; - _channels[i]->enableLeft = _channels[i]->enableRight = true; - for (int ii = 0; ii < 4; ii++) - _channels[i]->opr[ii] = _operators[(i << 2) + ii]; - } + if (_protect == false && _ticksLeft == _keyOffTime) + keyOff(); - uint8 *src_a = data; - uint8 bl = 0; + if (--_ticksLeft) + return; - for (uint8 i = 0; i < _numChan; i++) { - _channels[i]->flags = (_channels[i]->flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; - _channels[i]->ticksLeft = 1; - _channels[i]->dataPtr = data + READ_LE_UINT16(src_a); - src_a += 2; - _channels[i]->totalLevel = 0x7F; - if (bl > 2) - bl -= 3; - _channels[i]->regOffset = bl++; - - uint8 * src_b = _channels[i]->dataPtr; - int loop = 1; - uint8 cmd = 0; - while (loop) { - if (loop == 1) { - cmd = *src_b++; - if (cmd < 0xf0) { - src_b++; - loop = 1; - } else { - if (cmd == 0xff) { - loop = *src_b ? 2 : 0; - if (READ_LE_UINT16(src_b)) - _looping |= _channels[i]->idFlag; - } else if (cmd == 0xf6) { - loop = 3; - } else { - loop = 2; - } - } - } else if (loop == 2) { - src_b += _twnFxCmdLen[cmd - 240]; - loop = 1; - } else if (loop == 3) { - src_b[0] = src_b[1]; - src_b += 4; - loop = 1; - } - } - } + if (_protect == false) + keyOff(); - for (int i = 0; i < _numSSG; i++) { - // TODO - //_channels[i]->flags = (_channels[i]->flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; - //_channels[i]->ticksLeft = 1; - //_channels[i]->dataPtr = data + READ_LE_UINT16(src_a); - //uint8 *tmp = data + READ_LE_UINT16(src_a); - src_a += 2; - } + uint8 cmd = 0; + bool loop = true; - if (_hasADPCM) { - // TODO - src_a += 2; + while (loop) { + cmd = *_dataPtr++; + if (cmd < 0xf0) + loop = false; + else if (!processControlEvent(cmd)) + return; } - _patches = src_a + 4; - _cbCounter = 4; - _finishedChannelsFlag = 0; + uint8 para = *_dataPtr++; - // AH 0x17 - unlock(); - _playing = (loadPaused ? false : true); -} + if (cmd == 0x80) { + keyOff(); + _protect = false; + } else { + keyOn(); -void TownsPC98_OpnDriver::reset() { - for (int i = 0; i < (_numChan << 2); i++) - _operators[i]->reset(); + if (_protect == false || cmd != _frqBlockMSB) + _flags |= CHS_RECALCFREQ; + + _protect = (para & 0x80) ? true : false; + _frqBlockMSB = cmd; + } - _playing = false; - _looping = 0; - _tickCounter = 0; + _ticksLeft = para & 0x7f; } -void TownsPC98_OpnDriver::fadeOut() { - if (!_playing) - return; +void TownsPC98_OpnChannel::processFrequency() { + if (_flags & CHS_RECALCFREQ) { + uint8 block = (_frqBlockMSB & 0x70) >> 1; + uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f]; + frequency = (bfreq + _frqLSB) | (block << 8); - _fading = true; + writeReg(_regOffset + 0xa4, (frequency >> 8)); + writeReg(_regOffset + 0xa0, (frequency & 0xff)); - for (int i = 0; i < 20; i++) { - - lock(); - uint32 dTime = _tickCounter + 2; - for (int j = 0; j < _numChan; j++) { - if (_updateChannelsFlag & _channels[j]->idFlag) { - uint8 tmp = _channels[j]->totalLevel + 3; - if (tmp > 0x7f) - tmp = 0x7f; - _channels[j]->totalLevel = tmp; - setOutputLevel(_channels[j]); - } + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + if (_flags & CHS_KEYOFF) { + _ptchWhlModCurVal = _ptchWhlModInitVal; + _ptchWhlCurDelay += _ptchWhlInitDelayLo; } - unlock(); - while (_playing) { - if (_tickCounter >= dTime) - break; - } + _ptchWhlDurLeft = (_ptchWhlDuration >> 1); + _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); } - _fading = false; + if (!(_flags & CHS_PITCHWHEELOFF)) { + if (--_ptchWhlCurDelay) + return; + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + frequency += _ptchWhlModCurVal; - reset(); + writeReg(_regOffset + 0xa4, (frequency >> 8)); + writeReg(_regOffset + 0xa0, (frequency & 0xff)); + + if(!--_ptchWhlDurLeft) { + _ptchWhlDurLeft = _ptchWhlDuration; + _ptchWhlModCurVal = -_ptchWhlModCurVal; + } + } } -void TownsPC98_OpnDriver::callback() { - if (!_playing || --_cbCounter) - return; +bool TownsPC98_OpnChannel::processControlEvent(uint8 cmd) { + uint8 para = *_dataPtr++; + return (this->*controlEvents[cmd & 0x0f])(para); +} - _cbCounter = 4; - _tickCounter++; +void TownsPC98_OpnChannel::setOutputLevel() { + uint8 outopr = _drv->_opnCarrier[_algorithm]; + uint8 reg = 0x40 + _regOffset; - lock(); - for (int i = 0; i < _numChan; i++) { - if (_updateChannelsFlag & _channels[i]->idFlag) { - processEvents(_channels[i]); - processFrequency(_channels[i]); - } + for (int i = 0; i < 4; i++) { + if (outopr & 1) + writeReg(reg, _totalLevel); + outopr >>= 1; + reg += 4; } - unlock(); +} - if (_finishedChannelsFlag == _updateChannelsFlag) - reset(); +void TownsPC98_OpnChannel::fadeStep() { + _totalLevel += 3; + if (_totalLevel > 0x7f) + _totalLevel = 0x7f; + setOutputLevel(); } -void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { - if (!_playing) - return; +void TownsPC98_OpnChannel::reset() { + for (int i = 0; i < 4; i++) + _opr[i]->reset(); - for (int i = 0; i < _numChan ; i++) { - if (_channels[i]->updateEnvelopes) { - _channels[i]->updateEnvelopes = false; - for (int ii = 0; ii < 4 ; ii++) - _channels[i]->opr[ii]->updatePhaseIncrement(); - } + _fading = _updateEnvelopes = false; + _enableLeft = _enableRight = true; + memset(&_feedbuf, 0, sizeof(int) * 3); +} - int phbuf1, phbuf2, output; - int *feed = _channels[i]->feedbuf; - int *del = &feed[2]; - - for (uint32 ii = 0; ii < bufferSize ; ii++) { - phbuf1 = phbuf2 = output = 0; - - switch (_channels[i]->algorithm) { - case 0: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); - _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); - *del = 0; - _channels[i]->opr[1]->generateOutput(phbuf1, 0, *del); - _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); - break; - case 1: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); - _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); - _channels[i]->opr[1]->generateOutput(0, 0, phbuf1); - _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); - *del = phbuf1; - break; - case 2: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf2); - _channels[i]->opr[2]->generateOutput(*del, 0, phbuf2); - _channels[i]->opr[1]->generateOutput(0, 0, phbuf1); - _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); - *del = phbuf1; - break; - case 3: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf2); - _channels[i]->opr[2]->generateOutput(0, 0, *del); - _channels[i]->opr[1]->generateOutput(phbuf2, 0, phbuf1); - _channels[i]->opr[3]->generateOutput(*del, 0, output); - *del = phbuf1; - break; - case 4: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); - _channels[i]->opr[2]->generateOutput(0, 0, phbuf2); - _channels[i]->opr[1]->generateOutput(phbuf1, 0, output); - _channels[i]->opr[3]->generateOutput(phbuf2, 0, output); - *del = 0; - break; - case 5: - *del = feed[1]; - _channels[i]->opr[0]->generateOutput(-1, feed, phbuf1); - _channels[i]->opr[2]->generateOutput(*del, 0, output); - _channels[i]->opr[1]->generateOutput(*del, 0, output); - _channels[i]->opr[3]->generateOutput(*del, 0, output); - break; - case 6: - _channels[i]->opr[0]->generateOutput(0, feed, phbuf1); - _channels[i]->opr[2]->generateOutput(0, 0, output); - _channels[i]->opr[1]->generateOutput(phbuf1, 0, output); - _channels[i]->opr[3]->generateOutput(0, 0, output); - *del = 0; - break; - case 7: - _channels[i]->opr[0]->generateOutput(0, feed, output); - _channels[i]->opr[2]->generateOutput(0, 0, output); - _channels[i]->opr[1]->generateOutput(0, 0, output); - _channels[i]->opr[3]->generateOutput(0, 0, output); - *del = 0; - break; - }; - - if (_channels[i]->enableLeft) { - int l = output + buffer[ii * 2]; - if (l > 32767) - l = 32767; - if (l < -32767) - l = -32767; - buffer[ii * 2] = (int16) l; - } +void TownsPC98_OpnChannel::updateEnv() { + for (int i = 0; i < 4 ; i++) + _opr[i]->updatePhaseIncrement(); +} - if (_channels[i]->enableRight) { - int r = output + buffer[ii * 2 + 1]; - if (r > 32767) - r = 32767; - if (r < -32767) - r = -32767; - buffer[ii * 2 + 1] = (int16) r; - } - } +void TownsPC98_OpnChannel::generateOutput(int16 &leftSample, int16 &rightSample, int *del, int *feed) { + int phbuf1, phbuf2, output; + phbuf1 = phbuf2 = output = 0; + + switch (_algorithm) { + case 0: + _opr[0]->generateOutput(0, feed, phbuf1); + _opr[2]->generateOutput(*del, 0, phbuf2); + *del = 0; + _opr[1]->generateOutput(phbuf1, 0, *del); + _opr[3]->generateOutput(phbuf2, 0, output); + break; + case 1: + _opr[0]->generateOutput(0, feed, phbuf1); + _opr[2]->generateOutput(*del, 0, phbuf2); + _opr[1]->generateOutput(0, 0, phbuf1); + _opr[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 2: + _opr[0]->generateOutput(0, feed, phbuf2); + _opr[2]->generateOutput(*del, 0, phbuf2); + _opr[1]->generateOutput(0, 0, phbuf1); + _opr[3]->generateOutput(phbuf2, 0, output); + *del = phbuf1; + break; + case 3: + _opr[0]->generateOutput(0, feed, phbuf2); + _opr[2]->generateOutput(0, 0, *del); + _opr[1]->generateOutput(phbuf2, 0, phbuf1); + _opr[3]->generateOutput(*del, 0, output); + *del = phbuf1; + break; + case 4: + _opr[0]->generateOutput(0, feed, phbuf1); + _opr[2]->generateOutput(0, 0, phbuf2); + _opr[1]->generateOutput(phbuf1, 0, output); + _opr[3]->generateOutput(phbuf2, 0, output); + *del = 0; + break; + case 5: + *del = feed[1]; + _opr[0]->generateOutput(-1, feed, phbuf1); + _opr[2]->generateOutput(*del, 0, output); + _opr[1]->generateOutput(*del, 0, output); + _opr[3]->generateOutput(*del, 0, output); + break; + case 6: + _opr[0]->generateOutput(0, feed, phbuf1); + _opr[2]->generateOutput(0, 0, output); + _opr[1]->generateOutput(phbuf1, 0, output); + _opr[3]->generateOutput(0, 0, output); + *del = 0; + break; + case 7: + _opr[0]->generateOutput(0, feed, output); + _opr[2]->generateOutput(0, 0, output); + _opr[1]->generateOutput(0, 0, output); + _opr[3]->generateOutput(0, 0, output); + *del = 0; + break; + }; + + if (_enableLeft) { + int l = output + leftSample; + if (l > 32767) + l = 32767; + if (l < -32767) + l = -32767; + leftSample = (int16) l; } -} -void TownsPC98_OpnDriver::generateTables() { - delete [] _oprRates; - _oprRates = new uint8[128]; - memset(_oprRates, 0x90, 32); - uint8 * dst = (uint8*) _oprRates + 32; - for (int i = 0; i < 48; i += 4) - WRITE_BE_UINT32(dst + i, 0x00081018); - dst += 48; - for (uint8 i = 0; i < 16; i ++) { - uint8 v = (i < 12) ? i : 12; - *dst++ = ((4 + v) << 3); + if (_enableRight) { + int r = output + rightSample; + if (r > 32767) + r = 32767; + if (r < -32767) + r = -32767; + rightSample = (int16) r; } - memset(dst, 0x80, 32); +} - delete [] _oprRateshift; - _oprRateshift = new uint8[128]; - memset(_oprRateshift, 0, 128); - dst = (uint8*) _oprRateshift + 32; - for (int i = 11; i; i--) { - memset(dst, i, 4); - dst += 4; +void TownsPC98_OpnChannel::writeReg(uint8 regAdress, uint8 value) { + uint8 h = regAdress & 0xf0; + uint8 l = (regAdress & 0x0f); + static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; + uint8 o = oprOrdr[(l - _regOffset) >> 2]; + + switch (h) { + case 0x00: + // ssg + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + case 0x10: + // adpcm + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + case 0x20: + if (l == 8) { + // Key on/off + for (int i = 0; i < 4; i++) { + if ((value >> (4 + i)) & 1) + _opr[i]->keyOn(); + else + _opr[i]->keyOff(); + } + } else if (l == 2) { + // LFO + warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)"); + } else if (l == 7) { + // Timers; Ch 3/6 special mode + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE (NOT SUPPORTED)"); + } else if (l == 4 || l == 5) { + // Timer A + warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_A (NOT SUPPORTED)"); + } else if (l == 6) { + // Timer B + warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_B (NOT SUPPORTED)"); + } else if (l == 10 || l == 11) { + // DAC + warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)"); + } + break; + + case 0x30: + // detune, multiple + _opr[o]->detune((value >> 4) & 7); + _opr[o]->multiple(value & 0x0f); + _updateEnvelopes = true; + break; + + case 0x40: + // total level + _opr[o]->totalLevel(value & 0x7f); + break; + + case 0x50: + // rate scaling, attack rate + _opr[o]->attackRate(value & 0x1f); + if (_opr[o]->scaleRate(value >> 6)) + _updateEnvelopes = true; + break; + + case 0x60: + // first decay rate, amplitude modulation + _opr[o]->decayRate(value & 0x1f); + if (value & 0x80) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); + + break; + + case 0x70: + // secondary decay rate + _opr[o]->sustainRate(value & 0x1f); + break; + + case 0x80: + // secondary amplitude, release rate; + _opr[o]->sustainLevel(value >> 4); + _opr[o]->releaseRate(value & 0x0f); + break; + + case 0x90: + // ssg + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; + + case 0xa0: + // frequency + l -= _regOffset; + if (l == 0) { + _frqTemp = (_frqTemp & 0xff00) | value; + _updateEnvelopes = true; + for (int i = 0; i < 4; i++) + _opr[i]->frequency(_frqTemp); + } else if (l == 4) { + _frqTemp = (_frqTemp & 0xff) | (value << 8); + } else if (l == 8) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } else if (l == 12) { + // Ch 3/6 special mode frq + warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); + } + break; + + case 0xb0: + l -= _regOffset; + if (l == 0) { + // feedback, _algorithm + _opr[0]->feedbackLevel((value >> 3) & 7); + _opr[1]->feedbackLevel(0); + _opr[2]->feedbackLevel(0); + _opr[3]->feedbackLevel(0); + } else if (l == 4) { + // stereo, LFO sensitivity + _enableLeft = value & 0x80 ? true : false; + _enableRight = value & 0x40 ? true : false; + uint8 ams = (value & 0x3F) >> 3; + if (ams) + warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)"); + uint8 fms = value & 3; + if (fms) + warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)"); + } + break; + + default: + warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); + break; } +} - delete [] _oprFrq; - _oprFrq = new uint32[0x1000]; - for (uint32 i = 0; i < 0x1000; i++) - _oprFrq[i] = (uint32)(_baserate * (double)(i << 11)); +bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { + _instrID = para; + uint8 reg = _regOffset + 0x80; - delete [] _oprAttackDecay; - _oprAttackDecay = new uint8[152]; - memset(_oprAttackDecay, 0, 152); - for (int i = 0; i < 36; i++) - WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]); + for (int i = 0; i < 4; i++) { + // set release rate for each operator + writeReg(reg, 0x0f); + reg += 4; + } - delete [] _oprSinTbl; - _oprSinTbl = new uint32[1024]; - for (int i = 0; i < 1024; i++) { - double val = sin((double) (((i << 1) + 1) * M_PI / 1024.0)); - double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; - int32 i_dcb = (int32)(2.0 * d_dcb); - i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); - _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1); + const uint8 *tptr = _drv->_patches + ((uint32)_instrID << 5); + reg = _regOffset + 0x30; + + // write registers 0x30 to 0x8f + for (int i = 0; i < 6; i++) { + writeReg(reg, tptr[0]); + reg += 4; + writeReg(reg, tptr[2]); + reg += 4; + writeReg(reg, tptr[1]); + reg += 4; + writeReg(reg, tptr[3]); + reg += 4; + tptr += 4; } - delete [] _oprLevelOut; - _oprLevelOut = new int32[0x1a00]; - for (int i = 0; i < 256; i++) { - double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i))); - int32 val_int = ((int32) val) >> 4; - _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2; - _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1]; - for (int ii = 1; ii < 13; ii++) { - _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii; - _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)]; + reg = _regOffset + 0xB0; + _algorithm = tptr[0] & 7; + // set feedback and algorithm + writeReg(reg, tptr[0]); + + setOutputLevel(); + return true; +} + +bool TownsPC98_OpnChannel::control_f1_presetOutputLevel(uint8 para) { + if (_fading) + return true; + + _totalLevel = _drv->_opnLvlPresets[para]; + setOutputLevel(); + return true; +} + +bool TownsPC98_OpnChannel::control_f2_setKeyOffTime(uint8 para) { + _keyOffTime = para; + return true; +} + +bool TownsPC98_OpnChannel::control_f3_setFreqLSB(uint8 para) { + _frqLSB = (int8) para; + return true; +} + +bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) { + if (_fading) + return true; + + _totalLevel = para; + setOutputLevel(); + return true; +} + +bool TownsPC98_OpnChannel::control_f5_setTempo(uint8 para) { + _drv->setTempo(para); + return true; +} + +bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) { + _dataPtr--; + _dataPtr[0]--; + + if (*_dataPtr) { + // repeat section until counter has reached zero + _dataPtr = _drv->_trackData + READ_LE_UINT16(_dataPtr + 2); + } else { + // reset counter, advance to next section + _dataPtr[0] = _dataPtr[1]; + _dataPtr += 4; + } + return true; +} + +bool TownsPC98_OpnChannel::control_f7_setupPitchWheel(uint8 para) { + _ptchWhlInitDelayLo = _dataPtr[0]; + _ptchWhlInitDelayHi = para; + _ptchWhlModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1); + _ptchWhlDuration = _dataPtr[3]; + _dataPtr += 4; + _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF | CHS_RECALCFREQ; + return true; +} + +bool TownsPC98_OpnChannel::control_f8_togglePitchWheel(uint8 para) { + if (para == 0x10) { + if (*_dataPtr++) { + _flags = (_flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF; + } else { + _flags |= CHS_PITCHWHEELOFF; } + } else { + //uint8 skipChannels = para / 36; + //uint8 entry = para % 36; + //TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels]; + ////// NOT IMPLEMENTED + //t->unnamedEntries[entry] = *_dataPtr++; } + return true; +} - uint8 * dtt = new uint8[128]; - memset(dtt, 0, 36); - memset(dtt + 36, 1, 8); - memcpy(dtt + 44, _drvTables + 144, 84); +bool TownsPC98_OpnChannel::control_fa_writeReg(uint8 para) { + writeReg(para, *_dataPtr++); + return true; +} - delete [] _oprDetune; - _oprDetune = new int32[256]; - for (int i = 0; i < 128; i++) { - _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0); - _oprDetune[i + 128] = -_oprDetune[i]; +bool TownsPC98_OpnChannel::control_fb_incOutLevel(uint8 para) { + _dataPtr--; + if (_fading) + return true; + + uint8 val = (_totalLevel + 3); + if (val > 0x7f) + val = 0x7f; + + _totalLevel = val; + setOutputLevel(); + return true; +} + +bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) { + _dataPtr--; + if (_fading) + return true; + + int8 val = (int8) (_totalLevel - 3); + if (val < 0) + val = 0; + + _totalLevel = (uint8) val; + setOutputLevel(); + return true; +} + +bool TownsPC98_OpnChannel::control_fd_jump(uint8 para) { + uint8 *tmp = _drv->_trackData + READ_LE_UINT16(_dataPtr - 1); + _dataPtr = (tmp[1] == 1) ? tmp : ++_dataPtr; + return true; +} + +bool TownsPC98_OpnChannel::control_dummy(uint8 para) { + _dataPtr--; + return true; +} + +bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) { + uint16 val = READ_LE_UINT16(--_dataPtr); + if (val) { + // loop + _dataPtr = _drv->_trackData + val; + return true; + } else { + // quit parsing for active channel + --_dataPtr; + _flags |= CHS_EOT; + _drv->_finishedChannelsFlag |= _idFlag; + keyOff(); + return false; } +} - delete [] dtt; +bool TownsPC98_OpnChannel::control_f0_setPatchSSG(uint8 para) { + _instrID = para << 4; + para = (para >> 3) & 0x1e; + if (para) + return control_f4_setAlgorithm(para | 0x40); + return true; +} + +bool TownsPC98_OpnChannel::control_f1_setTotalLevel(uint8 para) { + if (!_fading) + _totalLevel = para; + return true; +} + +bool TownsPC98_OpnChannel::control_f4_setAlgorithm(uint8 para) { + _algorithm = para; + return true; +} + +bool TownsPC98_OpnChannel::control_f9_unkSSG(uint8 para) { + _dataPtr += 5; + return true; +} + +bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { + _dataPtr--; + if (_fading) + return true; + + _totalLevel--; + if ((int8)_totalLevel < 0); + _totalLevel = 0; + + return true; +} + +bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) { + _dataPtr--; + if (_fading) + return true; + + if(_totalLevel + 1 < 0x10) + _totalLevel++; + + return true; +} + +bool TownsPC98_OpnChannel::control_ff_endOfTrackSSG(uint8 para) { + uint16 val = READ_LE_UINT16(--_dataPtr); + if (val) { + // loop + _dataPtr = _drv->_trackData + val; + return true; + } else { + // quit parsing for active channel + --_dataPtr; + _flags |= CHS_EOT; + //_finishedChannelsFlag |= _idFlag; + keyOff(); + return false; + } +} + +TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, + uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : + TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id) { +} + +void TownsPC98_OpnChannelSSG::init() { + _algorithm = 0x80; + + _opr = new TownsPC98_OpnOperator*[4]; + for (int i = 0; i < 4; i++) + _opr[i] = new TownsPC98_OpnOperator(_drv->_baserate, _drv->_oprRates, _drv->_oprRateshift, + _drv->_oprAttackDecay, _drv->_oprFrq, _drv->_oprSinTbl, _drv->_oprLevelOut, _drv->_oprDetune); + + #define Control(x) &TownsPC98_OpnChannelSSG::control_##x + static const ControlEventFunc ctrlEventsSSG[] = { + Control(f0_setPatchSSG), + Control(f1_setTotalLevel), + Control(f2_setKeyOffTime), + Control(f3_setFreqLSB), + Control(f4_setOutputLevel), + Control(f5_setTempo), + Control(f6_repeatSection), + Control(f7_setupPitchWheel), + Control(f8_togglePitchWheel), + Control(f9_unkSSG), + Control(fa_writeReg), + Control(fb_incOutLevelSSG), + Control(fc_decOutLevelSSG), + Control(fd_jump), + Control(dummy), + Control(ff_endOfTrackSSG) + }; + #undef Control + + controlEvents = ctrlEventsSSG; } -void TownsPC98_OpnDriver::processEvents(TwnChannel *chan) { - if (chan->flags & CHS_EOT) +void TownsPC98_OpnChannelSSG::processEvents() { + if (_flags & CHS_EOT) return; - if (chan->protect == false && chan->ticksLeft == chan->keyOffTime) - keyOff(chan); + int _ssgUnk = (_flags & CHS_SSG) ? -1 : 0; - if (--chan->ticksLeft) + if (_protect == false && _ticksLeft == _keyOffTime) + keyOff(); + + if (--_ticksLeft) return; - if (chan->protect == false) - keyOff(chan); + if (_protect == false) + keyOff(); uint8 cmd = 0; bool loop = true; while (loop) { - cmd = *chan->dataPtr++; + cmd = *_dataPtr++; if (cmd < 0xf0) loop = false; - else if (!processControlEvent(chan, cmd)) + else if (!processControlEvent(cmd)) return; } - uint8 para = *chan->dataPtr++; + uint8 para = *_dataPtr++; if (cmd == 0x80) { - keyOff(chan); - chan->protect = false; + keyOff(); + _protect = false; } else { - keyOn(chan); + keyOn(); - if (chan->protect == false || cmd != chan->frqBlockMSB) - chan->flags |= CHS_RECALCFREQ; + if (_protect == false || cmd != _frqBlockMSB) + _flags |= CHS_RECALCFREQ; - chan->protect = (para & 0x80) ? true : false; - chan->frqBlockMSB = cmd; + _protect = (para & 0x80) ? true : false; + _frqBlockMSB = cmd; } - chan->ticksLeft = para & 0x7f; + _ticksLeft = para & 0x7f; + + if (!(_flags & CHS_SSG)) { + + } } -void TownsPC98_OpnDriver::processFrequency(TwnChannel *chan) { - if (chan->flags & CHS_RECALCFREQ) { - uint8 block = (chan->frqBlockMSB & 0x70) >> 1; - uint16 bfreq = ((const uint16*)_twnFreqTable)[chan->frqBlockMSB & 0x0f]; - chan->frequency = (bfreq + chan->frqLSB) | (block << 8); +void TownsPC98_OpnChannelSSG::processFrequency() { + if (_flags & CHS_RECALCFREQ) { + uint8 block = (_frqBlockMSB & 0x70) >> 1; + uint16 bfreq = ((const uint16*)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f]; + frequency = (bfreq + _frqLSB) | (block << 8); - writeReg(chan, (chan->regOffset + 0xa4), (chan->frequency >> 8)); - writeReg(chan, (chan->regOffset + 0xa0), (chan->frequency & 0xff)); + writeReg(_regOffset + 0xa4, (frequency >> 8)); + writeReg(_regOffset + 0xa0, (frequency & 0xff)); - chan->ptchWhlCurDelay = chan->ptchWhlInitDelayHi; - if (chan->flags & CHS_KEYOFF) { - chan->ptchWhlModCurVal = chan->ptchWhlModInitVal; - chan->ptchWhlCurDelay += chan->ptchWhlInitDelayLo; + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + if (_flags & CHS_KEYOFF) { + _ptchWhlModCurVal = _ptchWhlModInitVal; + _ptchWhlCurDelay += _ptchWhlInitDelayLo; } - chan->ptchWhlDurLeft = (chan->ptchWhlDuration >> 1); - chan->flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); + _ptchWhlDurLeft = (_ptchWhlDuration >> 1); + _flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ); } - if (!(chan->flags & CHS_PITCHWHEELOFF)) { - if (--chan->ptchWhlCurDelay) + if (!(_flags & CHS_PITCHWHEELOFF)) { + if (--_ptchWhlCurDelay) return; - chan->ptchWhlCurDelay = chan->ptchWhlInitDelayHi; - chan->frequency += chan->ptchWhlModCurVal; + _ptchWhlCurDelay = _ptchWhlInitDelayHi; + frequency += _ptchWhlModCurVal; - writeReg(chan, (chan->regOffset + 0xa4), (chan->frequency >> 8)); - writeReg(chan, (chan->regOffset + 0xa0), (chan->frequency & 0xff)); + writeReg(_regOffset + 0xa4, (frequency >> 8)); + writeReg(_regOffset + 0xa0, (frequency & 0xff)); - if(!--chan->ptchWhlDurLeft) { - chan->ptchWhlDurLeft = chan->ptchWhlDuration; - chan->ptchWhlModCurVal = -chan->ptchWhlModCurVal; + if(!--_ptchWhlDurLeft) { + _ptchWhlDurLeft = _ptchWhlDuration; + _ptchWhlModCurVal = -_ptchWhlModCurVal; } } } -bool TownsPC98_OpnDriver::processControlEvent(TwnChannel *chan, uint8 cmd) { - #define Control(x) &TownsPC98_OpnDriver::control_##x - static const ControlEventFunc twnFxCommands[] = { - Control(f0_setPatch), - Control(f1_presetOutputLevel), - Control(f2_setKeyOffTime), - Control(f3_setFreqLSB), - Control(f4_setOutputLevel), - Control(f5_setTempo), - Control(f6_repeatSection), - Control(f7_setupPitchWheel), - Control(f8_togglePitchWheel), - Control(f9_unk), - Control(fa_writeReg), - Control(fb_incOutLevel), - Control(fc_decOutLevel), - Control(fd_jump), - Control(fe_unk), - Control(ff_endOfTrack) - }; - #undef Control +void TownsPC98_OpnChannelSSG::keyOff() { + // all operators off + uint8 value = _keyNum & 0x0f; + uint8 regAdress = 0x28; + writeReg(regAdress, value); + _flags |= CHS_KEYOFF; +} - uint8 para = *chan->dataPtr++; - return (this->*twnFxCommands[cmd & 0x0f])(chan, para); +void TownsPC98_OpnChannelSSG::keyOn() { + // all operators on + uint8 value = _keyNum | 0xf0; + uint8 regAdress = 0x28; + writeReg(regAdress, value); } -void TownsPC98_OpnDriver::setOutputLevel(TwnChannel *chan) { - uint8 outopr = _twnCarrier[chan->algorithm]; - uint8 reg = 0x40 + chan->regOffset; +TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : + _mixer(mixer), _trackData(0), _playing(false), _channels(0), _ssgChannels(0), + _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), + _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , + _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), + _oprDetune(0), _cbCounter(4), _tickCounter(0), _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), + _finishedChannelsFlag(0), _samplesTillCallback(0), _samplesTillCallbackRemainder(0), _ready(false), + _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), + _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { + setTempo(84); + _baserate = (3579545.0 / (double)getRate()) / 144.0; +} - for (int i = 0; i < 4; i++) { - if (outopr & 1) - writeReg(chan, reg, chan->totalLevel); - outopr >>= 1; - reg += 4; +TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { + _mixer->stopHandle(_soundHandle); + + if (_channels) { + for (int i = 0; i < _numChan; i++) + delete _channels[i]; + delete [] _channels; } -} -void TownsPC98_OpnDriver::setTempo(uint8 tempo) { - _tempo = tempo; - _samplesPerCallback = getRate() / _tempo; - _samplesPerCallbackRemainder = getRate() % _tempo; -} + if (_ssgChannels) { + for (int i = 0; i < _numSSG; i++) + delete _ssgChannels[i]; + delete [] _ssgChannels; + } -bool TownsPC98_OpnDriver::control_f0_setPatch(TwnChannel *chan, uint8 para) { - chan->instrID = para; - uint8 reg = chan->regOffset + 0x80; + delete [] _oprRates; + delete [] _oprRateshift; + delete [] _oprFrq; + delete [] _oprAttackDecay; + delete [] _oprSinTbl; + delete [] _oprLevelOut; + delete [] _oprDetune; +} - for (int i = 0; i < 4; i++) { - // set release rate for each operator - writeReg(chan, reg, 0x0f); - reg += 4; +bool TownsPC98_OpnDriver::init() { + if (_ready) { + reset(); + return true; } - const uint8 *tptr = _patches + ((uint32)chan->instrID << 5); - reg = chan->regOffset + 0x30; + generateTables(); - // write registers 0x30 to 0x8f - for (int i = 0; i < 6; i++) { - writeReg(chan, reg, tptr[0]); - reg += 4; - writeReg(chan, reg, tptr[2]); - reg += 4; - writeReg(chan, reg, tptr[1]); - reg += 4; - writeReg(chan, reg, tptr[3]); - reg += 4; - tptr += 4; + if (_channels) { + for (int i = 0; i < _numChan; i++) { + if (_channels[i]) + delete _channels[i]; + } + delete [] _channels; + } + _channels = new TownsPC98_OpnChannel*[_numChan]; + for (int i = 0; i < _numChan; i++) { + int ii = i * 6; + _channels[i] = new TownsPC98_OpnChannel(this, _drvTables[ii], _drvTables[ii + 1], + _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]); + _channels[i]->init(); } - reg = chan->regOffset + 0xB0; - chan->algorithm = tptr[0] & 7; - // set feedback and algorithm - writeReg(chan, reg, tptr[0]); + if (_ssgChannels) { + for (int i = 0; i < _numSSG; i++) { + if (_ssgChannels[i]) + delete _ssgChannels[i]; + } + delete [] _ssgChannels; + } + if (_numSSG) { + _ssgChannels = new TownsPC98_OpnChannelSSG*[_numSSG]; + for (int i = 0; i < _numSSG; i++) { + int ii = i * 6; + _ssgChannels[i] = new TownsPC98_OpnChannelSSG(this, _drvTables[ii], _drvTables[ii + 1], + _drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]); + _ssgChannels[i]->init(); + } + } - setOutputLevel(chan); + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + + _ready = true; return true; } -bool TownsPC98_OpnDriver::control_f1_presetOutputLevel(TwnChannel *chan, uint8 para) { - if (_fading) - return true; +int inline TownsPC98_OpnDriver::readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, sizeof(int16) * numSamples); + int32 samplesLeft = numSamples >> 1; + while (samplesLeft) { + if (!_samplesTillCallback) { + callback(); + _samplesTillCallback = _samplesPerCallback; + _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; + if (_samplesTillCallbackRemainder >= _tempo) { + _samplesTillCallback++; + _samplesTillCallbackRemainder -= _tempo; + } + } - chan->totalLevel = _twnLvlPresets[para]; - setOutputLevel(chan); - return true; -} + int32 render = MIN(samplesLeft, _samplesTillCallback); + samplesLeft -= render; + _samplesTillCallback -= render; -bool TownsPC98_OpnDriver::control_f2_setKeyOffTime(TwnChannel *chan, uint8 para) { - chan->keyOffTime = para; - return true; + nextTick(buffer, render); + + for (int i = 0; i < render; ++i) { + buffer[i << 1] <<= 2; + buffer[(i << 1) + 1] <<= 2; + } + + buffer += (render << 1); + } + + return numSamples; } -bool TownsPC98_OpnDriver::control_f3_setFreqLSB(TwnChannel *chan, uint8 para) { - chan->frqLSB = (int8) para; - return true; +void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { + if (!_ready) { + warning("TownsPC98_OpnDriver: Driver must be initialized before loading data"); + return; + } + + if (!data) { + warning("TownsPC98_OpnDriver: Invalid music file data"); + return; + } + + lock(); + _trackData = data; + + reset(); + + uint8 *src_a = data; + + for (uint8 i = 0; i < _numChan; i++) { + _channels[i]->loadData(data + READ_LE_UINT16(src_a)); + src_a += 2; + } + + for (int i = 0; i < _numSSG; i++) { + _ssgChannels[i]->loadData(data + READ_LE_UINT16(src_a)); + src_a += 2; + } + + if (_hasADPCM) { + // TODO + src_a += 2; + } + + _patches = src_a + 4; + _cbCounter = 4; + _finishedChannelsFlag = 0; + + // AH 0x17 + unlock(); + _playing = (loadPaused ? false : true); } -bool TownsPC98_OpnDriver::control_f4_setOutputLevel(TwnChannel *chan, uint8 para) { - if (_fading) - return true; +void TownsPC98_OpnDriver::reset() { + for (int i = 0; i < (_numChan); i++) + _channels[i]->reset(); + for (int i = 0; i < (_numSSG); i++) + _ssgChannels[i]->reset(); - chan->totalLevel = para; - setOutputLevel(chan); - return true; + _playing = false; + _looping = 0; + _tickCounter = 0; } -bool TownsPC98_OpnDriver::control_f5_setTempo(TwnChannel *chan, uint8 para) { - setTempo(para); - return true; -} +void TownsPC98_OpnDriver::fadeOut() { + if (!_playing) + return; -bool TownsPC98_OpnDriver::control_f6_repeatSection(TwnChannel *chan, uint8 para) { - chan->dataPtr--; - chan->dataPtr[0]--; + for (int j = 0; j < _numChan; j++) + _channels[j]->_fading = true; + for (int j = 0; j < _numSSG; j++) + _ssgChannels[j]->_fading = true; - if (*chan->dataPtr) { - // repeat section until counter has reached zero - chan->dataPtr = _trackData + READ_LE_UINT16(chan->dataPtr + 2); - } else { - // reset counter, advance to next section - chan->dataPtr[0] = chan->dataPtr[1]; - chan->dataPtr += 4; - } - return true; -} + for (int i = 0; i < 20; i++) { + lock(); + uint32 dTime = _tickCounter + 2; + for (int j = 0; j < _numChan; j++) { + if (_updateChannelsFlag & _channels[j]->_idFlag) + _channels[j]->fadeStep(); + } + for (int j = 0; j < _numSSG; j++) + _ssgChannels[j]->fadeStep(); -bool TownsPC98_OpnDriver::control_f7_setupPitchWheel(TwnChannel *chan, uint8 para) { - chan->ptchWhlInitDelayLo = chan->dataPtr[0]; - chan->ptchWhlInitDelayHi = para; - chan->ptchWhlModInitVal = (int16) READ_LE_UINT16(chan->dataPtr + 1); - chan->ptchWhlDuration = chan->dataPtr[3]; - chan->dataPtr += 4; - chan->flags = (chan->flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF | CHS_RECALCFREQ; - return true; -} + unlock(); -bool TownsPC98_OpnDriver::control_f8_togglePitchWheel(TwnChannel *chan, uint8 para) { - if (para == 0x10) { - if (*chan->dataPtr++) { - chan->flags = (chan->flags & ~CHS_PITCHWHEELOFF) | CHS_KEYOFF; - } else { - chan->flags |= CHS_PITCHWHEELOFF; + while (_playing) { + if (_tickCounter >= dTime) + break; } - } else { - //uint8 skipChannels = para / 36; - //uint8 entry = para % 36; - //TownsPC98_OpnDriver::TwnChannel *t = &chan[skipChannels]; - ////// NOT IMPLEMENTED - //t->unnamedEntries[entry] = *chan->dataPtr++; } - return true; -} -bool TownsPC98_OpnDriver::control_f9_unk(TwnChannel *chan, uint8 para) { - //chan->dataPtr += 5; - return true; -} + for (int j = 0; j < _numChan; j++) + _channels[j]->_fading = false; + for (int j = 0; j < _numSSG; j++) + _ssgChannels[j]->_fading = false; -bool TownsPC98_OpnDriver::control_fa_writeReg(TwnChannel *chan, uint8 para) { - writeReg(chan, para, *chan->dataPtr++); - return true; + reset(); } -bool TownsPC98_OpnDriver::control_fb_incOutLevel(TwnChannel *chan, uint8 para) { - chan->dataPtr--; - if (_fading) - return true; +void TownsPC98_OpnDriver::callback() { + if (!_playing || --_cbCounter) + return; - uint8 val = (chan->totalLevel + 3); - if (val > 0x7f) - val = 0x7f; + _cbCounter = 4; + _tickCounter++; - chan->totalLevel = val; - setOutputLevel(chan); - return true; -} + lock(); -bool TownsPC98_OpnDriver::control_fc_decOutLevel(TwnChannel *chan, uint8 para) { - chan->dataPtr--; - if (_fading) - return true; + for (int i = 0; i < _numChan; i++) { + if (_updateChannelsFlag & _channels[i]->_idFlag) { + _channels[i]->processEvents(); + _channels[i]->processFrequency(); + } + } - int8 val = (int8) (chan->totalLevel - 3); - if (val < 0) - val = 0; + if (_numSSG) { + for (int i = 0; i < _numSSG; i++) { + _ssgChannels[i]->processEvents(); + _ssgChannels[i]->processFrequency(); + } + } - chan->totalLevel = (uint8) val; - setOutputLevel(chan); - return true; -} + unlock(); -bool TownsPC98_OpnDriver::control_fd_jump(TwnChannel *chan, uint8 para) { - uint8 *tmp = _trackData + READ_LE_UINT16(chan->dataPtr - 1); - chan->dataPtr = (tmp[1] == 1) ? tmp : ++chan->dataPtr; - return true; + if (_finishedChannelsFlag == _updateChannelsFlag) + reset(); } -bool TownsPC98_OpnDriver::control_fe_unk(TwnChannel *chan, uint8 para) { - chan->dataPtr--; - return true; -} +void TownsPC98_OpnDriver::nextTick(int16 *buffer, uint32 bufferSize) { + if (!_playing) + return; -bool TownsPC98_OpnDriver::control_ff_endOfTrack(TwnChannel *chan, uint8 para) { - uint16 val = READ_LE_UINT16(--chan->dataPtr); - if (val) { - // loop - chan->dataPtr = _trackData + val; - return true; - } else { - // quit parsing for active channel - --chan->dataPtr; - chan->flags |= CHS_EOT; - _finishedChannelsFlag |= chan->idFlag; - keyOff(chan); - return false; + for (int i = 0; i < _numChan ; i++) { + if (_channels[i]->_updateEnvelopes) { + _channels[i]->_updateEnvelopes = false; + _channels[i]->updateEnv(); + } + + for (uint32 ii = 0; ii < bufferSize ; ii++) + _channels[i]->generateOutput(buffer[ii * 2], + buffer[ii * 2 + 1], &_channels[i]->_feedbuf[2], _channels[i]->_feedbuf); } -} - -void TownsPC98_OpnDriver::keyOff(TwnChannel *chan) { - // all operators off - uint8 value = chan->keyNum & 0x0f; - uint8 regAdress = 0x28; - writeReg(chan, regAdress, value); - chan->flags |= CHS_KEYOFF; -} -void TownsPC98_OpnDriver::keyOn(TwnChannel *chan) { - // all operators on - uint8 value = chan->keyNum | 0xf0; - uint8 regAdress = 0x28; - writeReg(chan, regAdress, value); + for (int i = 0; i < _numSSG ; i++) { + if (_ssgChannels[i]->_updateEnvelopes) { + _ssgChannels[i]->_updateEnvelopes = false; + _ssgChannels[i]->updateEnv(); + } + + for (uint32 ii = 0; ii < bufferSize ; ii++) + _ssgChannels[i]->generateOutput(buffer[ii * 2], + buffer[ii * 2 + 1], &_ssgChannels[i]->_feedbuf[2], _ssgChannels[i]->_feedbuf); + } } -void TownsPC98_OpnDriver::writeReg(TwnChannel *chan, uint8 regAdress, uint8 value) { - uint8 h = regAdress & 0xf0; - uint8 l = (regAdress & 0x0f); - static const uint8 opr[] = { 0, 2, 1, 3 }; - uint8 o = opr[(l - chan->regOffset) >> 2]; - - switch (h) { - case 0x00: - // ssg - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); - break; - case 0x10: - // adpcm - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); - break; - case 0x20: - if (l == 8) { - // Key on/off - for (int i = 0; i < 4; i++) { - if ((value >> (4 + i)) & 1) - chan->opr[i]->keyOn(); - else - chan->opr[i]->keyOff(); - } - } else if (l == 2) { - // LFO - warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)"); - } else if (l == 7) { - // Timers; Ch 3/6 special mode - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE (NOT SUPPORTED)"); - } else if (l == 4 || l == 5) { - // Timer A - warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_A (NOT SUPPORTED)"); - } else if (l == 6) { - // Timer B - warning("TownsPC98_OpnDriver: TRYING TO USE TIMER_B (NOT SUPPORTED)"); - } else if (l == 10 || l == 11) { - // DAC - warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)"); - } - break; - - case 0x30: - // detune, multiple - chan->opr[o]->detune((value >> 4) & 7); - chan->opr[o]->multiple(value & 0x0f); - chan->updateEnvelopes = true; - break; - - case 0x40: - // total level - chan->opr[o]->totalLevel(value & 0x7f); - break; +void TownsPC98_OpnDriver::generateTables() { + delete [] _oprRates; + _oprRates = new uint8[128]; + memset(_oprRates, 0x90, 32); + uint8 *dst = (uint8*) _oprRates + 32; + for (int i = 0; i < 48; i += 4) + WRITE_BE_UINT32(dst + i, 0x00081018); + dst += 48; + for (uint8 i = 0; i < 16; i ++) { + uint8 v = (i < 12) ? i : 12; + *dst++ = ((4 + v) << 3); + } + memset(dst, 0x80, 32); - case 0x50: - // rate scaling, attack rate - chan->opr[o]->attackRate(value & 0x1f); - if (chan->opr[o]->scaleRate(value >> 6)) - chan->updateEnvelopes = true; - break; + delete [] _oprRateshift; + _oprRateshift = new uint8[128]; + memset(_oprRateshift, 0, 128); + dst = (uint8*) _oprRateshift + 32; + for (int i = 11; i; i--) { + memset(dst, i, 4); + dst += 4; + } - case 0x60: - // first decay rate, amplitude modulation - chan->opr[o]->decayRate(value & 0x1f); - if (value & 0x80) - warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)"); + delete [] _oprFrq; + _oprFrq = new uint32[0x1000]; + for (uint32 i = 0; i < 0x1000; i++) + _oprFrq[i] = (uint32)(_baserate * (double)(i << 11)); - break; + delete [] _oprAttackDecay; + _oprAttackDecay = new uint8[152]; + memset(_oprAttackDecay, 0, 152); + for (int i = 0; i < 36; i++) + WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]); - case 0x70: - // secondary decay rate - chan->opr[o]->sustainRate(value & 0x1f); - break; + delete [] _oprSinTbl; + _oprSinTbl = new uint32[1024]; + for (int i = 0; i < 1024; i++) { + double val = sin((double) (((i << 1) + 1) * M_PI / 1024.0)); + double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; + int32 i_dcb = (int32)(2.0 * d_dcb); + i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); + _oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1); + } - case 0x80: - // secondary amplitude, release rate; - chan->opr[o]->sustainLevel(value >> 4); - chan->opr[o]->releaseRate(value & 0x0f); - break; + delete [] _oprLevelOut; + _oprLevelOut = new int32[0x1a00]; + for (int i = 0; i < 256; i++) { + double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i))); + int32 val_int = ((int32) val) >> 4; + _oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2; + _oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1]; + for (int ii = 1; ii < 13; ii++) { + _oprLevelOut[(i << 1) + (ii << 9)] = _oprLevelOut[i << 1] >> ii; + _oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)]; + } + } - case 0x90: - // ssg - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); - break; + uint8 *dtt = new uint8[128]; + memset(dtt, 0, 36); + memset(dtt + 36, 1, 8); + memcpy(dtt + 44, _drvTables + 144, 84); - case 0xa0: - // frequency - l -= chan->regOffset; - if (l == 0) { - chan->frqTemp = (chan->frqTemp & 0xff00) | value; - chan->updateEnvelopes = true; - for (int i = 0; i < 4; i++) - chan->opr[i]->frequency(chan->frqTemp); - } else if (l == 4) { - chan->frqTemp = (chan->frqTemp & 0xff) | (value << 8); - } else if (l == 8) { - // Ch 3/6 special mode frq - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); - } else if (l == 12) { - // Ch 3/6 special mode frq - warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)"); - } - break; + delete [] _oprDetune; + _oprDetune = new int32[256]; + for (int i = 0; i < 128; i++) { + _oprDetune[i] = (int32) ((double)dtt[i] * _baserate * 64.0); + _oprDetune[i + 128] = -_oprDetune[i]; + } - case 0xb0: - l -= chan->regOffset; - if (l == 0) { - // feedback, algorithm - chan->opr[0]->feedbackLevel((value >> 3) & 7); - chan->opr[1]->feedbackLevel(0); - chan->opr[2]->feedbackLevel(0); - chan->opr[3]->feedbackLevel(0); - } else if (l == 4) { - // stereo, LFO sensitivity - chan->enableLeft = value & 0x80 ? true : false; - chan->enableRight = value & 0x40 ? true : false; - uint8 ams = (value & 0x3F) >> 3; - if (ams) - warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)"); - uint8 fms = value & 3; - if (fms) - warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)"); - } - break; + delete [] dtt; +} - default: - warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAdress); - break; - } +void TownsPC98_OpnDriver::setTempo(uint8 tempo) { + _tempo = tempo; + _samplesPerCallback = getRate() / _tempo; + _samplesPerCallbackRemainder = getRate() % _tempo; } const uint8 TownsPC98_OpnDriver::_drvTables[] = { @@ -2474,7 +2776,7 @@ void SoundTowns::playTrack(uint8 track) { return; track -= 2; - const int32 * const tTable = (const int32 * const) cdaData(); + const int32 *const tTable = (const int32 *const) cdaData(); int tTableIndex = 3 * track; int trackNum = (int) READ_LE_UINT32(&tTable[tTableIndex + 2]); @@ -2545,12 +2847,12 @@ void SoundTowns::playSoundEffect(uint8 track) { } } - uint8 * fileBody = _sfxFileData + 0x01b8; + uint8 *fileBody = _sfxFileData + 0x01b8; int32 offset = (int32)READ_LE_UINT32(_sfxFileData + (track - 0x0b) * 4); if (offset == -1) return; - uint32 * sfxHeader = (uint32*)(fileBody + offset); + uint32 *sfxHeader = (uint32*)(fileBody + offset); uint32 sfxHeaderID = READ_LE_UINT32(sfxHeader); uint32 sfxHeaderInBufferSize = READ_LE_UINT32(&sfxHeader[1]); @@ -2570,7 +2872,7 @@ void SoundTowns::playSoundEffect(uint8 track) { } else if (sfxHeaderID == 1) { Screen::decodeFrame4(sfxBody, sfxPlaybackBuffer, playbackBufferSize); } else if (_sfxWDTable) { - uint8 * tgt = sfxPlaybackBuffer; + uint8 *tgt = sfxPlaybackBuffer; uint32 sfx_BtTable_Offset = 0; uint32 sfx_WdTable_Offset = 0; uint32 sfx_WdTable_Number = 5; @@ -2635,7 +2937,7 @@ uint32 SoundTowns::getBaseTempo(void) { } bool SoundTowns::loadInstruments() { - uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); + uint8 *twm = _vm->resource()->fileData("twmusic.pak", 0); if (!twm) return false; _driver->queue()->loadDataToCurrentPosition(twm, 0x8BF0); @@ -2650,7 +2952,7 @@ bool SoundTowns::loadInstruments() { } void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { - uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); + uint8 *twm = _vm->resource()->fileData("twmusic.pak", 0); Common::StackLock lock(_mutex); if (!_parser) { @@ -2665,7 +2967,7 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { delete[] twm; } -void SoundTowns::onTimer(void * data) { +void SoundTowns::onTimer(void *data) { SoundTowns *music = (SoundTowns *)data; Common::StackLock lock(music->_mutex); if (music->_parser) @@ -2763,7 +3065,7 @@ void SoundPC98::playSoundEffect(uint8) { // KYRA 2 SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) : - Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _lastTrack(-1), _driver(0) { + Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) { } SoundTownsPC98_v2::~SoundTownsPC98_v2() { @@ -2774,6 +3076,7 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() { bool SoundTownsPC98_v2::init() { _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ? TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS); + _useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false; _vm->checkCD(); // FIXME: While checking for 'track1.XXX(X)' looks like // a good idea, we should definitely not be doing this @@ -2786,7 +3089,6 @@ bool SoundTownsPC98_v2::init() { (Common::File::exists("track1.mp3") || Common::File::exists("track1.ogg") || Common::File::exists("track1.flac") || Common::File::exists("track1.fla"))) _musicEnabled = 2; - _musicEnabled = 1; return _driver->init(); } @@ -2798,7 +3100,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { if (track == _lastTrack && _musicEnabled) return; - const uint16 * const cdaTracks = (const uint16 * const) cdaData(); + const uint16 *const cdaTracks = (const uint16 *const) cdaData(); int trackNum = -1; if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { @@ -2815,6 +3117,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); delete[] _musicTrackData; + _musicTrackData = _vm->resource()->fileData(musicfile, 0); _driver->loadData(_musicTrackData, true); @@ -2854,8 +3157,8 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { char filename[13]; sprintf(filename, "%s.PCM", file); - uint8 * data = _vm->resource()->fileData(filename, 0); - uint8 * src = data; + uint8 *data = _vm->resource()->fileData(filename, 0); + uint8 *src = data; uint16 sfxRate = rates[READ_LE_UINT16(src)]; src += 2; @@ -2908,6 +3211,18 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, bool) { return 1; } +void SoundTownsPC98_v2::playSoundEffect(uint8 track) { + if (!_useFmSfx) + return; + + uint8 *sd = _vm->resource()->fileData("sound.dat", 0); + + + //TODO + + delete [] sd; +} + } // end of namespace Kyra #undef EUPHONY_FADEOUT_TICKS -- cgit v1.2.3 From f5f97f424569d45987b73414847bda5e009f1f00 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 29 Jun 2008 15:59:35 +0000 Subject: cleanup svn-id: r32842 --- engines/kyra/sound_towns.cpp | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 4a8e8a5b15..f06817a4c1 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1334,7 +1334,7 @@ class TownsPC98_OpnChannel { public: TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id); - ~TownsPC98_OpnChannel(); + virtual ~TownsPC98_OpnChannel(); virtual void init(); typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para); @@ -1366,7 +1366,6 @@ public: bool _enableLeft; bool _enableRight; - bool _fading; bool _updateEnvelopes; const uint8 _idFlag; int _feedbuf[3]; @@ -1432,6 +1431,7 @@ class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel { public: TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id); + ~TownsPC98_OpnChannelSSG() {} void init(); void processEvents(); @@ -1510,6 +1510,7 @@ protected: uint8 _finishedChannelsFlag; uint16 _tempo; bool _playing; + bool _fading; uint8 _looping; uint32 _tickCounter; @@ -1538,7 +1539,7 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _unk15 = _unk16 = 0; _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = _unk28 = _unk29 = 0; _frqLSB = 0; - _protect = _updateEnvelopes = _fading = false; + _protect = _updateEnvelopes = false; _enableLeft = _enableRight = true; _dataPtr = 0; _ptchWhlModInitVal = _ptchWhlModCurVal = 0; @@ -1744,7 +1745,7 @@ void TownsPC98_OpnChannel::reset() { for (int i = 0; i < 4; i++) _opr[i]->reset(); - _fading = _updateEnvelopes = false; + _updateEnvelopes = false; _enableLeft = _enableRight = true; memset(&_feedbuf, 0, sizeof(int) * 3); } @@ -2003,7 +2004,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) { } bool TownsPC98_OpnChannel::control_f1_presetOutputLevel(uint8 para) { - if (_fading) + if (_drv->_fading) return true; _totalLevel = _drv->_opnLvlPresets[para]; @@ -2022,7 +2023,7 @@ bool TownsPC98_OpnChannel::control_f3_setFreqLSB(uint8 para) { } bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) { - if (_fading) + if (_drv->_fading) return true; _totalLevel = para; @@ -2084,7 +2085,7 @@ bool TownsPC98_OpnChannel::control_fa_writeReg(uint8 para) { bool TownsPC98_OpnChannel::control_fb_incOutLevel(uint8 para) { _dataPtr--; - if (_fading) + if (_drv->_fading) return true; uint8 val = (_totalLevel + 3); @@ -2098,7 +2099,7 @@ bool TownsPC98_OpnChannel::control_fb_incOutLevel(uint8 para) { bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) { _dataPtr--; - if (_fading) + if (_drv->_fading) return true; int8 val = (int8) (_totalLevel - 3); @@ -2146,7 +2147,7 @@ bool TownsPC98_OpnChannel::control_f0_setPatchSSG(uint8 para) { } bool TownsPC98_OpnChannel::control_f1_setTotalLevel(uint8 para) { - if (!_fading) + if (!_drv->_fading) _totalLevel = para; return true; } @@ -2163,7 +2164,7 @@ bool TownsPC98_OpnChannel::control_f9_unkSSG(uint8 para) { bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { _dataPtr--; - if (_fading) + if (_drv->_fading) return true; _totalLevel--; @@ -2175,7 +2176,7 @@ bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { bool TownsPC98_OpnChannel::control_fc_decOutLevelSSG(uint8 para) { _dataPtr--; - if (_fading) + if (_drv->_fading) return true; if(_totalLevel + 1 < 0x10) @@ -2241,7 +2242,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (_flags & CHS_EOT) return; - int _ssgUnk = (_flags & CHS_SSG) ? -1 : 0; + //int _ssgUnk = (_flags & CHS_SSG) ? -1 : 0; if (_protect == false && _ticksLeft == _keyOffTime) keyOff(); @@ -2336,7 +2337,7 @@ void TownsPC98_OpnChannelSSG::keyOn() { } TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : - _mixer(mixer), _trackData(0), _playing(false), _channels(0), _ssgChannels(0), + _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), _ssgChannels(0), _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), _opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 220)) , _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), @@ -2498,7 +2499,7 @@ void TownsPC98_OpnDriver::reset() { for (int i = 0; i < (_numSSG); i++) _ssgChannels[i]->reset(); - _playing = false; + _playing = _fading = false; _looping = 0; _tickCounter = 0; } @@ -2507,10 +2508,7 @@ void TownsPC98_OpnDriver::fadeOut() { if (!_playing) return; - for (int j = 0; j < _numChan; j++) - _channels[j]->_fading = true; - for (int j = 0; j < _numSSG; j++) - _ssgChannels[j]->_fading = true; + _fading = true; for (int i = 0; i < 20; i++) { lock(); @@ -2530,10 +2528,7 @@ void TownsPC98_OpnDriver::fadeOut() { } } - for (int j = 0; j < _numChan; j++) - _channels[j]->_fading = false; - for (int j = 0; j < _numSSG; j++) - _ssgChannels[j]->_fading = false; + _fading = false; reset(); } -- cgit v1.2.3 From cbf00ff5654ba1719a35ac139035e55d62b2fea0 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 29 Jun 2008 16:07:29 +0000 Subject: fix warning svn-id: r32843 --- engines/kyra/sound_towns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index f06817a4c1..a4142603e9 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2168,7 +2168,7 @@ bool TownsPC98_OpnChannel::control_fb_incOutLevelSSG(uint8 para) { return true; _totalLevel--; - if ((int8)_totalLevel < 0); + if ((int8)_totalLevel < 0) _totalLevel = 0; return true; -- cgit v1.2.3 From f0df79bb88b61140999afd7af36bf25b34b35e46 Mon Sep 17 00:00:00 2001 From: Kostas Nakos Date: Sun, 29 Jun 2008 16:58:27 +0000 Subject: adding a fixme svn-id: r32844 --- engines/cruise/cruise_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index 60afe5fa4c..c9c27ada49 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -28,7 +28,7 @@ #include #include -#include +#include // FIXME: WINCE: this is not needed/not portable (probably applies to all above includes) #include "common/scummsys.h" -- cgit v1.2.3 From 2779b851ab4328bce306b58e49df515bca58f1ab Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 30 Jun 2008 01:36:50 +0000 Subject: Small cleanup/shuffling of Gfx code. svn-id: r32847 --- engines/parallaction/debug.cpp | 4 +- engines/parallaction/gfxbase.cpp | 220 +++++++++++++++++++++++++++++++++++++- engines/parallaction/graphics.cpp | 208 +---------------------------------- engines/parallaction/graphics.h | 2 - 4 files changed, 219 insertions(+), 215 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp index 6bd704a2f5..f57976594e 100644 --- a/engines/parallaction/debug.cpp +++ b/engines/parallaction/debug.cpp @@ -188,7 +188,7 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { const char *objType[] = { "DOOR", "GET", "ANIM" }; DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n" - "| name | x | y | z | f | type | flag |\n" + "| name | x | y | z | f | type | visi |\n" "+--------------------+-----+-----+-----+-----+--------+--------+\n"); GfxObjList::iterator b = _vm->_gfx->_gfxobjList.begin(); @@ -196,7 +196,7 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { for ( ; b != e; b++) { GfxObj *obj = *b; - DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], 6 ); + DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], obj->isVisible() ); } DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n"); diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 66b1ceecf7..cdf4c9cdf6 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -92,6 +92,7 @@ GfxObj* Gfx::loadAnim(const char *name) { // animation Z is not set here, but controlled by game scripts and user interaction. // it is always >=0 and type = kGfxObjTypeAnim; + _gfxobjList.push_back(obj); return obj; } @@ -102,6 +103,7 @@ GfxObj* Gfx::loadGet(const char *name) { obj->z = kGfxObjGetZ; // this preset Z value ensures that get zones are drawn after doors but before animations obj->type = kGfxObjTypeGet; + _gfxobjList.push_back(obj); return obj; } @@ -111,6 +113,7 @@ GfxObj* Gfx::loadDoor(const char *name) { obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first obj->type = kGfxObjTypeDoor; + _gfxobjList.push_back(obj); return obj; } @@ -119,16 +122,17 @@ void Gfx::clearGfxObjects() { } void Gfx::showGfxObj(GfxObj* obj, bool visible) { - if (!obj || obj->isVisible() == visible) { - return; - } +// if (!obj || obj->isVisible() == visible) { +// return; +// } + + assert(obj); if (visible) { obj->setFlags(kGfxObjVisible); - _gfxobjList.push_back(obj); } else { obj->clearFlags(kGfxObjVisible); - _gfxobjList.remove(obj); +// _gfxobjList.remove(obj); } } @@ -174,4 +178,210 @@ void Gfx::drawGfxObjects(Graphics::Surface &surf) { } } + + +void Gfx::drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color) { + byte *dst = (byte*)surf->getBasePtr(x, y); + font->setColor(color); + font->drawString(dst, surf->w, text); +} + +void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) { + + uint16 lines = 0; + uint16 linewidth = 0; + + uint16 rx = 10; + uint16 ry = 4; + + uint16 blankWidth = font->getStringWidth(" "); + uint16 tokenWidth = 0; + + char token[MAX_TOKEN_LEN]; + + if (wrapwidth == -1) + wrapwidth = _vm->_screenWidth; + + while (strlen(text) > 0) { + + text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true); + + if (!scumm_stricmp(token, "%p")) { + lines++; + rx = 10; + ry = 4 + lines*10; // y + + strcpy(token, "> ......."); + strncpy(token+2, _password, strlen(_password)); + tokenWidth = font->getStringWidth(token); + } else { + tokenWidth = font->getStringWidth(token); + + linewidth += tokenWidth; + + if (linewidth > wrapwidth) { + // wrap line + lines++; + rx = 10; // x + ry = 4 + lines*10; // y + linewidth = tokenWidth; + } + + if (!scumm_stricmp(token, "%s")) { + sprintf(token, "%d", _score); + } + + } + + drawText(font, surf, rx, ry, token, color); + + rx += tokenWidth + blankWidth; + linewidth += blankWidth; + + text = Common::ltrim(text); + } + +} + + +// this is the maximum size of an unpacked frame in BRA +byte _unpackedBitmap[640*401]; + +#if 0 +void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { + + byte *d = _unpackedBitmap; + + while (size > 0) { + + uint8 p = *data++; + size--; + uint8 color = p & 0xF; + uint8 repeat = (p & 0xF0) >> 4; + if (repeat == 0) { + repeat = *data++; + size--; + } + + memset(d, color, repeat); + d += repeat; + } + + blt(r, _unpackedBitmap, surf, z, transparentColor); +} +#endif +void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { + + byte *d = _unpackedBitmap; + uint pixelsLeftInLine = r.width(); + + while (size > 0) { + uint8 p = *data++; + size--; + uint8 color = p & 0xF; + uint8 repeat = (p & 0xF0) >> 4; + if (repeat == 0) { + repeat = *data++; + size--; + } + if (repeat == 0) { + // end of line + repeat = pixelsLeftInLine; + pixelsLeftInLine = r.width(); + } else { + pixelsLeftInLine -= repeat; + } + + memset(d, color, repeat); + d += repeat; + } + + blt(r, _unpackedBitmap, surf, z, transparentColor); +} + + +void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) { + + Common::Point dp; + Common::Rect q(r); + + Common::Rect clipper(surf->w, surf->h); + + q.clip(clipper); + if (!q.isValidRect()) return; + + dp.x = q.left; + dp.y = q.top; + + q.translate(-r.left, -r.top); + + byte *s = data + q.left + q.top * r.width(); + byte *d = (byte*)surf->getBasePtr(dp.x, dp.y); + + uint sPitch = r.width() - q.width(); + uint dPitch = surf->w - q.width(); + + + if (_varRenderMode == 2) { + + for (uint16 i = 0; i < q.height(); i++) { + + for (uint16 j = 0; j < q.width(); j++) { + if (*s != transparentColor) { + if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { + byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); + if (z >= v) *d = 5; + } else { + *d = 5; + } + } + + s++; + d++; + } + + s += sPitch; + d += dPitch; + } + + } else { + if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { + + for (uint16 i = 0; i < q.height(); i++) { + + for (uint16 j = 0; j < q.width(); j++) { + if (*s != transparentColor) { + byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); + if (z >= v) *d = *s; + } + + s++; + d++; + } + + s += sPitch; + d += dPitch; + } + + } else { + + for (uint16 i = q.top; i < q.bottom; i++) { + for (uint16 j = q.left; j < q.right; j++) { + if (*s != transparentColor) + *d = *s; + + s++; + d++; + } + + s += sPitch; + d += dPitch; + } + + } + } + +} + + } // namespace Parallaction diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 64edd7babe..5d8d81253b 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -531,145 +531,6 @@ void Gfx::invertBackground(const Common::Rect& r) { } -// this is the maximum size of an unpacked frame in BRA -byte _unpackedBitmap[640*401]; - -#if 0 -void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - byte *d = _unpackedBitmap; - - while (size > 0) { - - uint8 p = *data++; - size--; - uint8 color = p & 0xF; - uint8 repeat = (p & 0xF0) >> 4; - if (repeat == 0) { - repeat = *data++; - size--; - } - - memset(d, color, repeat); - d += repeat; - } - - blt(r, _unpackedBitmap, surf, z, transparentColor); -} -#endif -void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - byte *d = _unpackedBitmap; - uint pixelsLeftInLine = r.width(); - - while (size > 0) { - uint8 p = *data++; - size--; - uint8 color = p & 0xF; - uint8 repeat = (p & 0xF0) >> 4; - if (repeat == 0) { - repeat = *data++; - size--; - } - if (repeat == 0) { - // end of line - repeat = pixelsLeftInLine; - pixelsLeftInLine = r.width(); - } else { - pixelsLeftInLine -= repeat; - } - - memset(d, color, repeat); - d += repeat; - } - - blt(r, _unpackedBitmap, surf, z, transparentColor); -} - - -void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - Common::Point dp; - Common::Rect q(r); - - Common::Rect clipper(surf->w, surf->h); - - q.clip(clipper); - if (!q.isValidRect()) return; - - dp.x = q.left; - dp.y = q.top; - - q.translate(-r.left, -r.top); - - byte *s = data + q.left + q.top * r.width(); - byte *d = (byte*)surf->getBasePtr(dp.x, dp.y); - - uint sPitch = r.width() - q.width(); - uint dPitch = surf->w - q.width(); - - - if (_varRenderMode == 2) { - - for (uint16 i = 0; i < q.height(); i++) { - - for (uint16 j = 0; j < q.width(); j++) { - if (*s != transparentColor) { - if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { - byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); - if (z >= v) *d = 5; - } else { - *d = 5; - } - } - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } else { - if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { - - for (uint16 i = 0; i < q.height(); i++) { - - for (uint16 j = 0; j < q.width(); j++) { - if (*s != transparentColor) { - byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); - if (z >= v) *d = *s; - } - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } else { - - for (uint16 i = q.top; i < q.bottom; i++) { - for (uint16 j = q.left; j < q.right; j++) { - if (*s != transparentColor) - *d = *s; - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } - } - -} - @@ -963,8 +824,8 @@ int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { int id = _numItems; _items[id].data = frames; - _items[id].x = x; - _items[id].y = y; + _items[id].data->x = x; + _items[id].data->y = y; _items[id].transparentColor = transparentColor; @@ -976,8 +837,6 @@ int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { void Gfx::setItemFrame(uint item, uint16 f) { assert(item < _numItems); _items[item].data->frame = f; - _items[item].data->x = _items[item].x; - _items[item].data->y = _items[item].y; } Gfx::Balloon* Gfx::getBalloon(uint id) { @@ -1112,69 +971,6 @@ void Gfx::hideDialogueStuff() { freeBalloons(); } -void Gfx::drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color) { - byte *dst = (byte*)surf->getBasePtr(x, y); - font->setColor(color); - font->drawString(dst, surf->w, text); -} - -void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) { - - uint16 lines = 0; - uint16 linewidth = 0; - - uint16 rx = 10; - uint16 ry = 4; - - uint16 blankWidth = font->getStringWidth(" "); - uint16 tokenWidth = 0; - - char token[MAX_TOKEN_LEN]; - - if (wrapwidth == -1) - wrapwidth = _vm->_screenWidth; - - while (strlen(text) > 0) { - - text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true); - - if (!scumm_stricmp(token, "%p")) { - lines++; - rx = 10; - ry = 4 + lines*10; // y - - strcpy(token, "> ......."); - strncpy(token+2, _password, strlen(_password)); - tokenWidth = font->getStringWidth(token); - } else { - tokenWidth = font->getStringWidth(token); - - linewidth += tokenWidth; - - if (linewidth > wrapwidth) { - // wrap line - lines++; - rx = 10; // x - ry = 4 + lines*10; // y - linewidth = tokenWidth; - } - - if (!scumm_stricmp(token, "%s")) { - sprintf(token, "%d", _score); - } - - } - - drawText(font, surf, rx, ry, token, color); - - rx += tokenWidth + blankWidth; - linewidth += blankWidth; - - text = Common::ltrim(text); - } - -} - void Gfx::freeBackground() { _backgroundInfo.free(); } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 6439941cc5..17869de432 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -572,8 +572,6 @@ public: uint _numBalloons; struct Item { - uint16 x; - uint16 y; uint16 frame; GfxObj *data; -- cgit v1.2.3 From ecbf8d54ad78dac70f7838e7546196b3bb232c5a Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 30 Jun 2008 03:33:08 +0000 Subject: Implemented resetGfxEntityEntry and made it used where appropriate (The function wasn't very easy to reverse engineer so it may have flaws still, but let's hope it doesn't ;-)). svn-id: r32848 --- engines/cine/object.cpp | 17 +++++-- engines/cine/various.cpp | 118 ++++++++++++++++++----------------------------- engines/cine/various.h | 2 + 3 files changed, 60 insertions(+), 77 deletions(-) (limited to 'engines') diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 57a328eef9..61fecb55f8 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -179,8 +179,12 @@ void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint1 objectTable[objIdx].mask = param3; objectTable[objIdx].frame = param4; - if (removeOverlay(objIdx, 0)) { - addOverlay(objIdx, 0); + if (g_cine->getGameType() == Cine::GType_OS) { + resetGfxEntityEntry(objIdx); + } else { // Future Wars + if (removeOverlay(objIdx, 0)) { + addOverlay(objIdx, 0); + } } } @@ -208,9 +212,12 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) { case 3: objectTable[objIdx].mask = newValue; - // TODO: Check this part against disassembly - if (removeOverlay(objIdx, 0)) { - addOverlay(objIdx, 0); + if (g_cine->getGameType() == Cine::GType_OS) { // Operation Stealth specific + resetGfxEntityEntry(objIdx); + } else { // Future Wars specific + if (removeOverlay(objIdx, 0)) { + addOverlay(objIdx, 0); + } } break; case 4: diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 20d9edc5de..6bbc907eb0 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1682,78 +1682,6 @@ uint16 computeMove2(SeqListElement &element) { return returnVar; } -// sort all the gfx stuff... - -void resetGfxEntityEntry(uint16 objIdx) { -#if 0 - overlayHeadElement* tempHead = &overlayHead; - byte* var_16 = NULL; - uint16 var_10 = 0; - uint16 var_12 = 0; - overlayHeadElement* currentHead = tempHead->next; - byte* var_1A = NULL; - overlayHeadElement* var1E = &overlayHead; - - while (currentHead) { - tempHead2 = currentHead->next; - - if (currentHead->objIdx == objIdx && currentHead->type!=2 && currentHead->type!=3 && currentHead->type!=0x14) { - tempHead->next = tempHead2; - - if (tempHead2) { - tempHead2->previous = currentHead->previous; - } else { - seqVar0 = currentHead->previous; - } - - var_22 = var_16; - - if (!var_22) { - // todo: goto? - } - - var_22->previous = currentHead; - } else { - } - - if (currentHead->type == 0x14) { - } else { - } - - if (currentHead->type == 0x2 || currentHead->type == 0x3) { - si = 10000; - } else { - si = objectTable[currentHead->objIdx]; - } - - if (objectTable[objIdx]>si) { - var1E = currentHead; - } - - tempHead = tempHead->next; - - } - - if (var_1A) { - currentHead = var_16; - var_22 = var_1E->next; - var_1E->next = currentHead; - var_1A->next = var_22; - - if (var_1E != &gfxEntityHead) { - currentHead->previous = var_1E; - } - - if (!var_22) { - seqVar0 = var_1A; - } else { - var_22->previous = var_1A; - } - - } -#endif -} - uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &element, uint16 param3, int16 *param4) { const byte *currentPtr = ptr; const byte *ptrData; @@ -1795,6 +1723,52 @@ uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &ele return 1; } +/*! + * Permutates the overlay list into a different order according to some logic. + * \todo Check this function for correctness (Wasn't very easy to reverse engineer so there may be errors) + */ +void resetGfxEntityEntry(uint16 objIdx) { + Common::List::iterator it, bObjsCutPoint; + Common::List aReverseObjs, bObjs; + bool foundCutPoint = false; + + // Go through the overlay list and partition the whole list into two categories (Type A and type B objects) + for (it = overlayList.begin(); it != overlayList.end(); ++it) { + if (it->objIdx == objIdx && it->type != 2 && it->type != 3) { // Type A object + aReverseObjs.push_front(*it); + } else { // Type B object + bObjs.push_back(*it); + uint16 objectMask; + if (it->type == 2 || it->type == 3) { + objectMask = 10000; + } else { + objectMask = objectTable[it->objIdx].mask; + } + + if (objectTable[objIdx].mask > objectMask) { // Check for B objects' cut point + bObjsCutPoint = bObjs.reverse_begin(); + foundCutPoint = true; + } + } + } + + // Recreate the overlay list in a different order. + overlayList.clear(); + if (foundCutPoint) { + // If a cut point was found the order is: + // B objects before the cut point, the cut point, A objects in reverse order, B objects after cut point. + ++bObjsCutPoint; // Include the cut point in the first list insertion + overlayList.insert(overlayList.end(), bObjs.begin(), bObjsCutPoint); + overlayList.insert(overlayList.end(), aReverseObjs.begin(), aReverseObjs.end()); + overlayList.insert(overlayList.end(), bObjsCutPoint, bObjs.end()); + } else { + // If no cut point was found the order is: + // A objects in reverse order, B objects. + overlayList.insert(overlayList.end(), aReverseObjs.begin(), aReverseObjs.end()); + overlayList.insert(overlayList.end(), bObjs.begin(), bObjs.end()); + } +} + void processSeqListElement(SeqListElement &element) { int16 x = objectTable[element.objIdx].x; int16 y = objectTable[element.objIdx].y; diff --git a/engines/cine/various.h b/engines/cine/various.h index d05447fb40..840f1674a2 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -142,6 +142,8 @@ void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, i void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4); void processSeqList(void); +void resetGfxEntityEntry(uint16 objIdx); + bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y); } // End of namespace Cine -- cgit v1.2.3 From 2ecf8fdbb5a0141ea43a7d2074a2a7356182f12c Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 30 Jun 2008 17:24:23 +0000 Subject: Fixed addAni (A test before using resetGfxEntityEntry was incorrect). Also added comments and checked that most 8-bit values used in this function are used as signed integers. svn-id: r32850 --- engines/cine/various.cpp | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 6bbc907eb0..ea5956be6b 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1682,33 +1682,49 @@ uint16 computeMove2(SeqListElement &element) { return returnVar; } -uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &element, uint16 param3, int16 *param4) { - const byte *currentPtr = ptr; - const byte *ptrData; - const byte *ptr2; +uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptrByte, SeqListElement &element, uint16 param3, int16 *param4) { + const int8 *ptr = (const int8 *)ptrByte; + const int8 *ptrData; + const int8 *ptr2; int16 di; + // In the original an error string is set and 0 is returned if the following doesn't hold assert(ptr); - assert(param4); - - dummyU16 = READ_BE_UINT16((currentPtr + param1 * 2) + 8); + // We probably could just use a local variable here instead of the dummyU16 but + // haven't checked if this has any side-effects so keeping it this way still. + dummyU16 = READ_BE_UINT16(ptr + param1 * 2 + 8); ptrData = ptr + dummyU16; + // In the original an error string is set and 0 is returned if the following doesn't hold assert(*ptrData); di = (objectTable[objIdx].costume + 1) % (*ptrData); - ptr2 = (ptrData + (di * 8)) + 1; - + ++ptrData; // Jump over the just read byte + // Here ptr2 seems to be indexing a table of structs (8 bytes per struct): + // struct { + // int8 x; // 0 (Used with checkCollision) + // int8 y; // 1 (Used with checkCollision) + // int8 numZones; // 2 (Used with checkCollision) + // int8 var3; // 3 (Not used in this function) + // int8 xAdd; // 4 (Used with an object) + // int8 yAdd; // 5 (Used with an object) + // int8 maskAdd; // 6 (Used with an object) + // int8 frameAdd; // 7 (Used with an object) + // }; + ptr2 = ptrData + di * 8; + + // We might probably safely discard the AND by 1 here because + // at least in the original checkCollision returns always 0 or 1. if ((checkCollision(objIdx, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) { return 0; } - objectTable[objIdx].x += (int8)ptr2[4]; - objectTable[objIdx].y += (int8)ptr2[5]; - objectTable[objIdx].mask += (int8)ptr2[6]; + objectTable[objIdx].x += ptr2[4]; + objectTable[objIdx].y += ptr2[5]; + objectTable[objIdx].mask += ptr2[6]; - if (objectTable[objIdx].frame) { + if (ptr2[6]) { resetGfxEntityEntry(objIdx); } @@ -1717,6 +1733,7 @@ uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &ele if (param3 || !element.var14) { objectTable[objIdx].costume = di; } else { + assert(param4); *param4 = di; } -- cgit v1.2.3 From e415a97fe53a3eec537d7d67760af45730ec91fd Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 30 Jun 2008 18:15:34 +0000 Subject: Removed TODO from checkCollision: Updating zoneQuery each time checkCollision is called seems to be fine. svn-id: r32852 --- engines/cine/script_fw.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'engines') diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index f84904ccc5..148e673095 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1760,12 +1760,6 @@ int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { return zoneVar; } -/*! - * \todo Check whether updating the zoneQuery table is appropriate every time - * this function is called because this function is called also from elsewhere - * than simply o1_checkCollision (e.g. from addAni). In Operation Stealth's - * disassembly this probably isn't the case, so there may be weird side-effects. - */ int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) { int16 lx = objectTable[objIdx].x + x; int16 ly = objectTable[objIdx].y + y; -- cgit v1.2.3 From b07ff576233dec6e2138f19a5cf053e2ccf146df Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Mon, 30 Jun 2008 21:55:08 +0000 Subject: - this fixes Hof PC98 music initialization - music sounds exactly like FM-Towns for now svn-id: r32854 --- engines/kyra/kyra_hof.cpp | 2 +- engines/kyra/sound_towns.cpp | 51 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index a8b8c0dced..61a1570893 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -1564,7 +1564,7 @@ void KyraEngine_HoF::snd_playSoundEffect(int track, int volume) { int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); if (vocIndex != -1) _sound->voicePlay(_ingameSoundList[vocIndex], true); - else if (_flags.platform == Common::kPlatformPC) + else if (_flags.platform != Common::kPlatformFMTowns) // TODO ?? Maybe there is a way to let users select whether they want // voc, midi or adl sfx (even though it makes no sense to choose anything but voc). KyraEngine_v1::snd_playSoundEffect(track); diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index a4142603e9..6be2cae7a4 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1348,7 +1348,7 @@ public: CHS_EOT = 0x80 } ChannelState; - void loadData(uint8 *data); + virtual void loadData(uint8 *data); virtual void processEvents(); virtual void processFrequency(); bool processControlEvent(uint8 cmd); @@ -1404,7 +1404,6 @@ protected: uint8 _keyOffTime; bool _protect; uint8 *_dataPtr; - uint8 _unk15, _unk16; uint8 _ptchWhlInitDelayLo; uint8 _ptchWhlInitDelayHi; int16 _ptchWhlModInitVal; @@ -1413,9 +1412,11 @@ protected: int16 _ptchWhlModCurVal; uint8 _ptchWhlDurLeft; uint16 frequency; - uint8 _unk28, _unk29; uint8 _regOffset; uint8 _flags; + uint8 _ssg1; + uint8 _ssg2; + const uint8 _chanNum; const uint8 _keyNum; const uint8 _part; @@ -1439,8 +1440,13 @@ public: void keyOn(); void keyOff(); + void loadData(uint8 *data); + +private: + void opn_SSG_UNK(uint8 a); }; + class TownsPC98_OpnDriver : public Audio::AudioStream { friend class TownsPC98_OpnChannel; friend class TownsPC98_OpnChannelSSG; @@ -1514,7 +1520,8 @@ protected: uint8 _looping; uint32 _tickCounter; - bool __updateEnvelopes; + bool _updateEnvelopes; + int _ssgFlag; int32 _samplesTillCallback; int32 _samplesTillCallbackRemainder; @@ -1536,8 +1543,8 @@ TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 re uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key), _part(prt), _idFlag(id) { - _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _unk15 = _unk16 = 0; - _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = _unk28 = _unk29 = 0; + _ticksLeft = _algorithm = _instrID = _totalLevel = _frqBlockMSB = _keyOffTime = _ssg1 = _ssg2 = 0; + _ptchWhlInitDelayLo = _ptchWhlInitDelayHi = _ptchWhlDuration = _ptchWhlCurDelay = _ptchWhlDurLeft = 0; _frqLSB = 0; _protect = _updateEnvelopes = false; _enableLeft = _enableRight = true; @@ -1602,7 +1609,6 @@ void TownsPC98_OpnChannel::keyOn() { writeReg(regAdress, value); } - void TownsPC98_OpnChannel::loadData(uint8 *data) { _flags = (_flags & ~CHS_EOT) | CHS_ALL_BUT_EOT; _ticksLeft = 1; @@ -2242,7 +2248,7 @@ void TownsPC98_OpnChannelSSG::processEvents() { if (_flags & CHS_EOT) return; - //int _ssgUnk = (_flags & CHS_SSG) ? -1 : 0; + _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0; if (_protect == false && _ticksLeft == _keyOffTime) keyOff(); @@ -2336,6 +2342,22 @@ void TownsPC98_OpnChannelSSG::keyOn() { writeReg(regAdress, value); } +void TownsPC98_OpnChannelSSG::loadData(uint8 *data) { + _drv->_ssgFlag = (_flags & CHS_SSG) ? -1 : 0; + opn_SSG_UNK(0); + TownsPC98_OpnChannel::loadData(data); + _algorithm = 0x80; +} + +void TownsPC98_OpnChannelSSG::opn_SSG_UNK(uint8 a) { + _ssg1 = a; + uint16 h = (_totalLevel + 1) * a; + if ((h >> 8) == _ssg2) + return; + _ssg2 = (h >> 8); + writeReg(8 + _regOffset, _ssg2); +} + TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _mixer(mixer), _trackData(0), _playing(false), _fading(false), _channels(0), _ssgChannels(0), _looping(0), _opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 84), @@ -2469,7 +2491,7 @@ void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { uint8 *src_a = data; - for (uint8 i = 0; i < _numChan; i++) { + for (uint8 i = 0; i < 3; i++) { _channels[i]->loadData(data + READ_LE_UINT16(src_a)); src_a += 2; } @@ -2479,11 +2501,18 @@ void TownsPC98_OpnDriver::loadData(uint8 *data, bool loadPaused) { src_a += 2; } + for (uint8 i = 3; i < _numChan; i++) { + _channels[i]->loadData(data + READ_LE_UINT16(src_a)); + src_a += 2; + } + if (_hasADPCM) { - // TODO + //_adpcmChannel->loadData(data + READ_LE_UINT16(src_a)); src_a += 2; } + _ssgFlag = 0; + _patches = src_a + 4; _cbCounter = 4; _finishedChannelsFlag = 0; @@ -2555,6 +2584,8 @@ void TownsPC98_OpnDriver::callback() { _ssgChannels[i]->processFrequency(); } } + + _ssgFlag = 0; unlock(); -- cgit v1.2.3 From cef7d68fc531dbaac68c2b83a340bfbb3dcf142e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 30 Jun 2008 23:39:56 +0000 Subject: Added support for Spanish fan translation of kyra3 (See fr #1994040 "KYRA3: Add support for Spanish fan translation"). svn-id: r32858 --- engines/kyra/detection.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++- engines/kyra/kyra_hof.cpp | 3 +++ engines/kyra/kyra_mr.cpp | 3 +++ engines/kyra/kyra_v1.cpp | 32 ++--------------------------- engines/kyra/kyra_v1.h | 6 +++++- engines/kyra/kyra_v2.cpp | 32 +++++++++++++++++++++++++++++ engines/kyra/kyra_v2.h | 3 +++ 7 files changed, 98 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 3fb62b51bd..33d0d2c070 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -41,7 +41,8 @@ struct KYRAGameDescription { namespace { -#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id } +#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id } +#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, id } #define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1) #define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA1) @@ -61,6 +62,7 @@ namespace { #define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) #define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, true, Kyra::GI_KYRA3) const KYRAGameDescription adGameDescs[] = { { @@ -605,6 +607,53 @@ const KYRAGameDescription adGameDescs[] = { KYRA3_CD_FLAGS }, + // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::ES_ESP, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) } }; diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 61a1570893..879efab86e 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -2024,6 +2024,9 @@ void KyraEngine_HoF::writeSettings() { break; } + if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG) + _flags.lang = _flags.fanLang; + ConfMan.set("language", Common::getLanguageCode(_flags.lang)); KyraEngine_v1::writeSettings(); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 8a49b8e155..b425c0929f 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -1543,6 +1543,9 @@ void KyraEngine_MR::writeSettings() { break; } + if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG) + _flags.lang = _flags.fanLang; + ConfMan.set("language", Common::getLanguageCode(_flags.lang)); ConfMan.setBool("studio_audience", _configStudio); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 980c181c4e..d2e0f37a60 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -173,36 +173,6 @@ int KyraEngine_v1::init() { _gameToLoad = -1; } - _lang = 0; - Common::Language lang = Common::parseLanguage(ConfMan.get("language")); - - if (_flags.gameID == GI_KYRA2 || _flags.gameID == GI_KYRA3) { - switch (lang) { - case Common::EN_ANY: - case Common::EN_USA: - case Common::EN_GRB: - _lang = 0; - break; - - case Common::FR_FRA: - _lang = 1; - break; - - case Common::DE_DEU: - _lang = 2; - break; - - case Common::JA_JPN: - _lang = 3; - break; - - default: - warning("unsupported language, switching back to English"); - _lang = 0; - break; - } - } - return 0; } @@ -277,6 +247,8 @@ void KyraEngine_v1::delayWithTicks(int ticks) { void KyraEngine_v1::registerDefaultSettings() { if (_flags.gameID != GI_KYRA3) ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)); + if (_flags.fanLang != Common::UNK_LANG) + ConfMan.registerDefault("subtitles", true); } void KyraEngine_v1::readSettings() { diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 4f38ceca98..09efc8cc97 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -44,6 +44,11 @@ namespace Kyra { struct GameFlags { Common::Language lang; + + // language overwrites of fan translations (only needed for multilingual games) + Common::Language fanLang; + Common::Language replacedLang; + Common::Platform platform; bool isDemo : 1; @@ -212,7 +217,6 @@ protected: // detection GameFlags _flags; - int _lang; // opcode virtual void setupOpcodeTable() = 0; diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 12da338843..2e704f2aa2 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -23,6 +23,8 @@ * */ +#include "common/config-manager.h" + #include "kyra/kyra_v2.h" #include "kyra/screen_v2.h" #include "kyra/debugger.h" @@ -70,6 +72,36 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi memset(&_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); _pauseStart = 0; + + _lang = 0; + Common::Language lang = Common::parseLanguage(ConfMan.get("language")); + if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG) + lang = _flags.replacedLang; + + switch (lang) { + case Common::EN_ANY: + case Common::EN_USA: + case Common::EN_GRB: + _lang = 0; + break; + + case Common::FR_FRA: + _lang = 1; + break; + + case Common::DE_DEU: + _lang = 2; + break; + + case Common::JA_JPN: + _lang = 3; + break; + + default: + warning("unsupported language, switching back to English"); + _lang = 0; + break; + } } KyraEngine_v2::~KyraEngine_v2() { diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 24f7aad614..6fdf30fff8 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -94,6 +94,9 @@ protected: virtual void update() = 0; virtual void updateWithText() = 0; + // detection + int _lang; + // MainMenu MainMenu *_menu; -- cgit v1.2.3 From 34a49d4a5acd1e5c71bf3f37b829e37390b3c5e1 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 30 Jun 2008 23:44:33 +0000 Subject: Fix game flags for detection entries of installed kyra3 versions. svn-id: r32859 --- engines/kyra/detection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 33d0d2c070..f55cd1ac5e 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -61,8 +61,8 @@ namespace { #define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_KYRA2) #define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) -#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) -#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, false, Kyra::GI_KYRA3) +#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, false, Kyra::GI_KYRA3) const KYRAGameDescription adGameDescs[] = { { -- cgit v1.2.3 From bd296a45fa2ad9c08b096c50cf53ecbcd94a36a5 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 1 Jul 2008 10:33:25 +0000 Subject: Fixed unitialized variables svn-id: r32865 --- engines/cine/bg_list.cpp | 2 ++ engines/cine/object.cpp | 4 ++++ engines/cine/various.cpp | 1 + engines/drascula/talk.cpp | 2 +- engines/engines.mk | 5 +++++ engines/m4/assets.cpp | 1 + engines/m4/converse.cpp | 2 +- engines/made/screen.cpp | 2 ++ 8 files changed, 17 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp index cf25f1d355..b10211282f 100644 --- a/engines/cine/bg_list.cpp +++ b/engines/cine/bg_list.cpp @@ -63,6 +63,7 @@ void addSpriteFilledToBGList(int16 objIdx) { void createBgIncrustListElement(int16 objIdx, int16 param) { BGIncrust tmp; + tmp.unkPtr = 0; tmp.objIdx = objIdx; tmp.param = param; tmp.x = objectTable[objIdx].x; @@ -90,6 +91,7 @@ void loadBgIncrustFromSave(Common::InSaveFile &fHandle) { fHandle.readUint32BE(); fHandle.readUint32BE(); + tmp.unkPtr = 0; tmp.objIdx = fHandle.readUint16BE(); tmp.param = fHandle.readUint16BE(); tmp.x = fHandle.readUint16BE(); diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 61fecb55f8..c02e01c8ce 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -125,6 +125,10 @@ void addOverlay(uint16 objIdx, uint16 type) { tmp.objIdx = objIdx; tmp.type = type; + tmp.x = 0; + tmp.y = 0; + tmp.width = 0; + tmp.color = 0; overlayList.insert(it, tmp); } diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index ea5956be6b..0439856e5c 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -133,6 +133,7 @@ void runObjectScript(int16 entryIdx) { */ void addPlayerCommandMessage(int16 cmd) { overlay tmp; + memset(&tmp, 0, sizeof(tmp)); tmp.objIdx = cmd; tmp.type = 3; diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 4d3187a0fd..a89c5ff734 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -60,7 +60,7 @@ void DrasculaEngine::talk_igor(int index, int talkerType) { int x_talk1[8] = { 56, 86, 116, 146, 176, 206, 236, 266 }; int x_talk3[4] = { 80, 102, 124, 146 }; int x_talk4[4] = { 119, 158, 197, 236 }; - int face; + int face = 0; int length = strlen(said); color_abc(kColorWhite); diff --git a/engines/engines.mk b/engines/engines.mk index cfb8e69f3e..4dba913173 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -97,6 +97,11 @@ DEFINES += -DENABLE_SWORD2=$(ENABLE_SWORD2) MODULES += engines/sword2 endif +ifdef ENABLE_TINSEL +DEFINES += -DENABLE_TINSEL=$(ENABLE_TINSEL) +MODULES += engines/tinsel +endif + ifdef ENABLE_TOUCHE DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE) MODULES += engines/touche diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 80b21119ff..0488f17d8f 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -201,6 +201,7 @@ void SpriteAsset::loadMadsSpriteAsset(M4Engine *vm, Common::SeekableReadStream* Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); SpriteAssetFrame frame; for (curFrame = 0; curFrame < _frameCount; curFrame++) { + frame.stream = 0; frame.comp = 0; frameOffset = spriteStream->readUint32LE(); _frameOffsets.push_back(frameOffset); diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index a07a175066..a85fdea02f 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -379,7 +379,7 @@ void Converse::loadConversation(const char *convName) { uint32 header = convS->readUint32LE(); uint32 size; uint32 chunk; - uint32 data; + uint32 data = 0; uint32 i; ConvEntry* curEntry = NULL; ConvEntry* replyEntry = NULL; diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index 1d81793448..0c22d40259 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -822,6 +822,8 @@ SpriteListItem Screen::getFromSpriteList(int16 index) { if (((uint) index) > _spriteList.size()) { SpriteListItem emptyItem; emptyItem.index = 0; + emptyItem.xofs = 0; + emptyItem.yofs = 0; return emptyItem; } else { return _spriteList[index - 1]; -- cgit v1.2.3 From 6dc312b9e1ffbfc92452ebdeee8f3f703f07f7fa Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 1 Jul 2008 14:51:44 +0000 Subject: Reverted accidental commit of Tinsel changes in engines.mk svn-id: r32868 --- engines/engines.mk | 5 ----- 1 file changed, 5 deletions(-) (limited to 'engines') diff --git a/engines/engines.mk b/engines/engines.mk index 4dba913173..cfb8e69f3e 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -97,11 +97,6 @@ DEFINES += -DENABLE_SWORD2=$(ENABLE_SWORD2) MODULES += engines/sword2 endif -ifdef ENABLE_TINSEL -DEFINES += -DENABLE_TINSEL=$(ENABLE_TINSEL) -MODULES += engines/tinsel -endif - ifdef ENABLE_TOUCHE DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE) MODULES += engines/touche -- cgit v1.2.3 From 77a60673ef970ec32fc2e4db09aa5ac534481c8d Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Wed, 2 Jul 2008 01:41:08 +0000 Subject: - Changed labels to be GfxObj's, thus removing the Label object altogether. - Changed Item's to be almost GfxObj's, since ownership and destruction of underlying resource is an issue here (got to think some more about it). svn-id: r32873 --- engines/parallaction/exec_br.cpp | 4 +- engines/parallaction/gfxbase.cpp | 38 ++++-- engines/parallaction/graphics.cpp | 199 +++++++++++++++---------------- engines/parallaction/graphics.h | 41 +++---- engines/parallaction/input.h | 2 +- engines/parallaction/objects.cpp | 1 - engines/parallaction/objects.h | 2 +- engines/parallaction/parallaction.cpp | 6 +- engines/parallaction/parallaction_ns.cpp | 4 +- 9 files changed, 146 insertions(+), 151 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index 3b67b4c370..348af2b731 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -100,8 +100,8 @@ void Parallaction_br::setupSubtitles(char *s, char *s2, int y) { } void Parallaction_br::clearSubtitles() { - _gfx->freeLabels(); - _subtitle[0] = _subtitle[1] = -1; + _gfx->hideLabel(_subtitle[0]); + _gfx->hideLabel(_subtitle[1]); } diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index cdf4c9cdf6..383f5d549c 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -92,6 +92,7 @@ GfxObj* Gfx::loadAnim(const char *name) { // animation Z is not set here, but controlled by game scripts and user interaction. // it is always >=0 and type = kGfxObjTypeAnim; + obj->transparentKey = 0; _gfxobjList.push_back(obj); return obj; } @@ -103,6 +104,7 @@ GfxObj* Gfx::loadGet(const char *name) { obj->z = kGfxObjGetZ; // this preset Z value ensures that get zones are drawn after doors but before animations obj->type = kGfxObjTypeGet; + obj->transparentKey = 0; _gfxobjList.push_back(obj); return obj; } @@ -113,6 +115,7 @@ GfxObj* Gfx::loadDoor(const char *name) { obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first obj->type = kGfxObjTypeDoor; + obj->transparentKey = 0; _gfxobjList.push_back(obj); return obj; } @@ -150,11 +153,32 @@ void Gfx::sortAnimations() { Common::sort(first, last, compareZ); } -void Gfx::drawGfxObjects(Graphics::Surface &surf) { + +void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene) { + if (!obj->isVisible()) { + return; + } Common::Rect rect; byte *data; + uint scrollX = (scene) ? -_varScrollX : 0; + + obj->getRect(obj->frame, rect); + rect.translate(obj->x + scrollX, obj->y); + data = obj->getData(obj->frame); + + if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { + blt(rect, data, &surf, obj->layer, obj->transparentKey); + } else { + unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, obj->transparentKey); + } + +} + + +void Gfx::drawGfxObjects(Graphics::Surface &surf) { + sortAnimations(); // TODO: some zones don't appear because of wrong masking (3 or 0?) // TODO: Dr.Ki is not visible inside the club @@ -164,17 +188,7 @@ void Gfx::drawGfxObjects(Graphics::Surface &surf) { GfxObjList::iterator e = _gfxobjList.end(); for (; b != e; b++) { - GfxObj *obj = *b; - if (obj->isVisible()) { - obj->getRect(obj->frame, rect); - rect.translate(obj->x - _varScrollX, obj->y); - data = obj->getData(obj->frame); - if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { - blt(rect, data, &surf, obj->layer, 0); - } else { - unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, 0); - } - } + drawGfxObject(*b, surf, true); } } diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 5d8d81253b..838827b19f 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -356,17 +356,7 @@ void Gfx::drawItems() { Graphics::Surface *surf = g_system->lockScreen(); for (uint i = 0; i < _numItems; i++) { - GfxObj *obj = _items[i].data; - - Common::Rect rect; - obj->getRect(obj->frame, rect); - rect.translate(obj->x, obj->y); - - if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { - blt(rect, obj->getData(obj->frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); - } else { - unpackBlt(rect, obj->getData(obj->frame), obj->getRawSize(obj->frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); - } + drawGfxObject(_items[i].data, *surf, false); } g_system->unlockScreen(); } @@ -540,10 +530,9 @@ void setupLabelSurface(Graphics::Surface &surf, uint w, uint h) { surf.fillRect(Common::Rect(w,h), LABEL_TRANSPARENT_COLOR); } -Label *Gfx::renderFloatingLabel(Font *font, char *text) { +uint Gfx::renderFloatingLabel(Font *font, char *text) { - Label *label = new Label; - Graphics::Surface *cnv = &label->_cnv; + Graphics::Surface *cnv = new Graphics::Surface; uint w, h; @@ -569,14 +558,74 @@ Label *Gfx::renderFloatingLabel(Font *font, char *text) { drawText(font, cnv, 0, 0, text, 0); } - return label; + GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "floatingLabel"); + obj->transparentKey = LABEL_TRANSPARENT_COLOR; + obj->layer = LAYER_FOREGROUND; + + uint id = _labels.size(); + _labels.insert_at(id, obj); + + return id; +} + +void Gfx::showFloatingLabel(uint label) { + assert(label < _labels.size()); + + hideFloatingLabel(); + + _labels[label]->x = -1000; + _labels[label]->y = -1000; + _labels[label]->setFlags(kGfxObjVisible); + + _floatingLabel = label; +} + +void Gfx::hideFloatingLabel() { + if (_floatingLabel != NO_FLOATING_LABEL) { + _labels[_floatingLabel]->clearFlags(kGfxObjVisible); + } + _floatingLabel = NO_FLOATING_LABEL; +} + + +void Gfx::updateFloatingLabel() { + if (_floatingLabel == NO_FLOATING_LABEL) { + return; + } + + int16 _si, _di; + + Common::Point cursor; + _vm->_input->getCursorPos(cursor); + + Common::Rect r; + _labels[_floatingLabel]->getRect(0, r); + + if (_vm->_input->_activeItem._id != 0) { + _si = cursor.x + 16 - r.width()/2; + _di = cursor.y + 34; + } else { + _si = cursor.x + 8 - r.width()/2; + _di = cursor.y + 21; + } + + if (_si < 0) _si = 0; + if (_di > 190) _di = 190; + + if (r.width() + _si > _vm->_screenWidth) + _si = _vm->_screenWidth - r.width(); + + _labels[_floatingLabel]->x = _si; + _labels[_floatingLabel]->y = _di; } + + + uint Gfx::createLabel(Font *font, const char *text, byte color) { - assert(_numLabels < MAX_NUM_LABELS); + assert(_labels.size() < MAX_NUM_LABELS); - Label *label = new Label; - Graphics::Surface *cnv = &label->_cnv; + Graphics::Surface *cnv = new Graphics::Surface; uint w, h; @@ -597,122 +646,64 @@ uint Gfx::createLabel(Font *font, const char *text, byte color) { drawText(font, cnv, 0, 0, text, color); } - uint id = _numLabels; - _labels[id] = label; - _numLabels++; + GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "label"); + obj->transparentKey = LABEL_TRANSPARENT_COLOR; + obj->layer = LAYER_FOREGROUND; + + int id = _labels.size(); + + _labels.insert_at(id, obj); return id; } void Gfx::showLabel(uint id, int16 x, int16 y) { - assert(id < _numLabels); - _labels[id]->_visible = true; + assert(id < _labels.size()); + _labels[id]->setFlags(kGfxObjVisible); + + Common::Rect r; + _labels[id]->getRect(0, r); if (x == CENTER_LABEL_HORIZONTAL) { - x = CLIP((_vm->_screenWidth - _labels[id]->_cnv.w) / 2, 0, _vm->_screenWidth/2); + x = CLIP((_vm->_screenWidth - r.width()) / 2, 0, _vm->_screenWidth/2); } if (y == CENTER_LABEL_VERTICAL) { - y = CLIP((_vm->_screenHeight - _labels[id]->_cnv.h) / 2, 0, _vm->_screenHeight/2); + y = CLIP((_vm->_screenHeight - r.height()) / 2, 0, _vm->_screenHeight/2); } - _labels[id]->_pos.x = x; - _labels[id]->_pos.y = y; + _labels[id]->x = x; + _labels[id]->y = y; } void Gfx::hideLabel(uint id) { - assert(id < _numLabels); - _labels[id]->_visible = false; + assert(id < _labels.size()); + _labels[id]->clearFlags(kGfxObjVisible); } void Gfx::freeLabels() { - for (uint i = 0; i < _numLabels; i++) { + for (uint i = 0; i < _labels.size(); i++) { delete _labels[i]; } - _numLabels = 0; -} - - -void Gfx::setFloatingLabel(Label *label) { - _floatingLabel = label; - - if (_floatingLabel) { - _floatingLabel->resetPosition(); - } -} - -void Gfx::updateFloatingLabel() { - if (!_floatingLabel) { - return; - } - - int16 _si, _di; - - Common::Point cursor; - _vm->_input->getCursorPos(cursor); - - if (_vm->_input->_activeItem._id != 0) { - _si = cursor.x + 16 - _floatingLabel->_cnv.w/2; - _di = cursor.y + 34; - } else { - _si = cursor.x + 8 - _floatingLabel->_cnv.w/2; - _di = cursor.y + 21; - } - - if (_si < 0) _si = 0; - if (_di > 190) _di = 190; - - if (_floatingLabel->_cnv.w + _si > _vm->_screenWidth) - _si = _vm->_screenWidth - _floatingLabel->_cnv.w; - - _floatingLabel->_pos.x = _si; - _floatingLabel->_pos.y = _di; + _labels.clear(); } void Gfx::drawLabels() { - if ((!_floatingLabel) && (_numLabels == 0)) { + if (_labels.size() == 0) { return; } + updateFloatingLabel(); Graphics::Surface* surf = g_system->lockScreen(); - for (uint i = 0; i < _numLabels; i++) { - if (_labels[i]->_visible) { - Common::Rect r(_labels[i]->_cnv.w, _labels[i]->_cnv.h); - r.moveTo(_labels[i]->_pos); - blt(r, (byte*)_labels[i]->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR); - } - } - - if (_floatingLabel) { - Common::Rect r(_floatingLabel->_cnv.w, _floatingLabel->_cnv.h); - r.moveTo(_floatingLabel->_pos); - blt(r, (byte*)_floatingLabel->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR); + for (uint i = 0; i < _labels.size(); i++) { + drawGfxObject(_labels[i], *surf, false); } g_system->unlockScreen(); } -Label::Label() { - resetPosition(); - _visible = false; -} - -Label::~Label() { - free(); -} - -void Label::free() { - _cnv.free(); - resetPosition(); -} - -void Label::resetPosition() { - _pos.x = -1000; - _pos.y = -1000; -} - void Gfx::getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height) { @@ -790,8 +781,7 @@ Gfx::Gfx(Parallaction* vm) : _numBalloons = 0; _numItems = 0; - _numLabels = 0; - _floatingLabel = 0; + _floatingLabel = NO_FLOATING_LABEL; _screenX = 0; _screenY = 0; @@ -826,8 +816,8 @@ int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { _items[id].data = frames; _items[id].data->x = x; _items[id].data->y = y; - - _items[id].transparentColor = transparentColor; + _items[id].data->layer = LAYER_FOREGROUND; + _items[id].data->transparentKey = transparentColor; _numItems++; @@ -837,6 +827,7 @@ int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { void Gfx::setItemFrame(uint item, uint16 f) { assert(item < _numItems); _items[item].data->frame = f; + _items[item].data->setFlags(kGfxObjVisible); } Gfx::Balloon* Gfx::getBalloon(uint id) { diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 17869de432..df4cab4caf 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -326,20 +326,6 @@ public: #define CENTER_LABEL_HORIZONTAL -1 #define CENTER_LABEL_VERTICAL -1 -struct Label { - Graphics::Surface _cnv; - - Common::Point _pos; - bool _visible; - - Label(); - ~Label(); - - void free(); - void resetPosition(); -}; - - #define MAX_BALLOON_WIDTH 130 @@ -357,7 +343,8 @@ enum { kGfxObjTypeDoor = 0, kGfxObjTypeGet = 1, - kGfxObjTypeAnim = 2 + kGfxObjTypeAnim = 2, + kGfxObjTypeLabel = 3 }; enum { @@ -381,6 +368,7 @@ public: uint type; uint frame; uint layer; + uint transparentKey; GfxObj(uint type, Frames *frames, const char *name = NULL); virtual ~GfxObj(); @@ -478,9 +466,12 @@ public: void clearGfxObjects(); void sortAnimations(); + // labels - void setFloatingLabel(Label *label); - Label *renderFloatingLabel(Font *font, char *text); + void showFloatingLabel(uint label); + void hideFloatingLabel(); + + uint renderFloatingLabel(Font *font, char *text); uint createLabel(Font *font, const char *text, byte color); void showLabel(uint id, int16 x, int16 y); void hideLabel(uint id); @@ -572,19 +563,18 @@ public: uint _numBalloons; struct Item { - uint16 frame; GfxObj *data; - - byte transparentColor; - Common::Rect rect; } _items[14]; uint _numItems; - #define MAX_NUM_LABELS 5 - Label* _labels[MAX_NUM_LABELS]; - uint _numLabels; - Label *_floatingLabel; + #define MAX_NUM_LABELS 20 + #define NO_FLOATING_LABEL 1000 + + typedef Common::Array GfxObjArray; + GfxObjArray _labels; + + uint _floatingLabel; void drawInventory(); void updateFloatingLabel(); @@ -601,6 +591,7 @@ public: void drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color); void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth); + void drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene); void blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor); void unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor); }; diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h index 46dbb08c4e..e06fe96705 100644 --- a/engines/parallaction/input.h +++ b/engines/parallaction/input.h @@ -44,7 +44,7 @@ struct InputData { Common::Point _mousePos; int16 _inventoryIndex; ZonePtr _zone; - Label* _label; + uint _label; }; class Input { diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 5b5aa85584..54afabc318 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -182,7 +182,6 @@ Zone::~Zone() { break; } - delete _label; } void Zone::getRect(Common::Rect& r) const { diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index 44ad35e0ab..19835da9d0 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -287,7 +287,7 @@ struct Zone { int16 _bottom; uint32 _type; uint32 _flags; - Label *_label; + uint _label; uint16 field_2C; // unused uint16 field_2E; // unused TypeData u; diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 4f586961a6..5f5cfdb820 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -290,12 +290,12 @@ void Parallaction::processInput(InputData *data) { switch (data->_event) { case kEvEnterZone: debugC(2, kDebugInput, "processInput: kEvEnterZone"); - _gfx->setFloatingLabel(data->_label); + _gfx->showFloatingLabel(data->_label); break; case kEvExitZone: debugC(2, kDebugInput, "processInput: kEvExitZone"); - _gfx->setFloatingLabel(0); + _gfx->hideFloatingLabel(); break; case kEvAction: @@ -308,7 +308,7 @@ void Parallaction::processInput(InputData *data) { case kEvOpenInventory: _input->stopHovering(); - _gfx->setFloatingLabel(0); + _gfx->hideFloatingLabel(); if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) { setArrowCursor(); } diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 59b9465d0a..af848aa6af 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -187,7 +187,7 @@ void Parallaction_ns::setArrowCursor() { debugC(1, kDebugInput, "setting mouse cursor to arrow"); // this stuff is needed to avoid artifacts with labels and selected items when switching cursors - _gfx->setFloatingLabel(0); + _gfx->hideFloatingLabel(); _input->_activeItem._id = 0; _system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0); @@ -298,7 +298,7 @@ void Parallaction_ns::changeLocation(char *location) { _soundMan->playLocationMusic(location); - _gfx->setFloatingLabel(0); + _gfx->hideFloatingLabel(); _gfx->freeLabels(); _input->stopHovering(); -- cgit v1.2.3 From 18559708c620b82f05c490e0ff118a02611730dd Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Wed, 2 Jul 2008 04:31:50 +0000 Subject: Fully implemented processSeqListElement - Added parts that were missing and fixed a couple of errors -- One test was backwards and a global variable was written to when it shouldn't have been Added global variable inputVar0 that's used in processSeqListElement NOTE: inputVar0 isn't updated anywhere yet, so that's a TODO svn-id: r32874 --- engines/cine/various.cpp | 60 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 0439856e5c..4b5d4efe13 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -95,6 +95,9 @@ int16 saveVar2; byte isInPause = 0; +// TODO: Implement inputVar0's changes in the program +// Currently inputVar0 isn't updated anywhere even though it's used at least in processSeqListElement. +uint16 inputVar0 = 0; byte inputVar1 = 0; uint16 inputVar2 = 0, inputVar3 = 0; @@ -1683,8 +1686,7 @@ uint16 computeMove2(SeqListElement &element) { return returnVar; } -uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptrByte, SeqListElement &element, uint16 param3, int16 *param4) { - const int8 *ptr = (const int8 *)ptrByte; +uint16 addAni(uint16 param1, uint16 objIdx, const int8 *ptr, SeqListElement &element, uint16 param3, int16 *param4) { const int8 *ptrData; const int8 *ptr2; int16 di; @@ -1790,7 +1792,7 @@ void resetGfxEntityEntry(uint16 objIdx) { void processSeqListElement(SeqListElement &element) { int16 x = objectTable[element.objIdx].x; int16 y = objectTable[element.objIdx].y; - const byte *ptr1 = animDataTable[element.frame].data(); + const int8 *ptr1 = (const int8 *) animDataTable[element.frame].data(); int16 var_10; int16 var_4; int16 var_2; @@ -1803,22 +1805,44 @@ void processSeqListElement(SeqListElement &element) { element.var12 = 0; if (ptr1) { - uint16 param1 = ptr1[1]; - uint16 param2 = ptr1[2]; + int16 param1 = ptr1[1]; + int16 param2 = ptr1[2]; if (element.varC != 255) { - // FIXME: Why is this here? Fingolfin gets lots of these - // in his copy of Operation Stealth (value 0 or 236) under - // Mac OS X. Maybe it's a endian issue? At least the graphics - // in the copy protection screen are partially messed up. - warning("processSeqListElement: varC = %d", element.varC); - } - - if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) { - computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]); + int16 x2 = element.var18; + int16 y2 = element.var1A; + if (element.varC) { + x2 += objectTable[element.varC].x; + y2 += objectTable[element.varC].y; + } + computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, x2, y2); } else { - element.var16 = 0; - element.var14 = 0; + if (inputVar0 && allowPlayerInput) { + int16 adder = param1 + 1; + if (inputVar0 != 1) { + 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; + } + + if (inputVar1 && allowPlayerInput) { + int16 adder = param2 + 1; + if (inputVar1 != 1) { + adder = -adder; + } + // TODO: Name currently unnamed global variable 252 + globalVars[VAR_MOUSE_Y_POS] = globalVars[252] = ptr1[5] + y + adder; + } + + if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) { + computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]); + } else { + element.var16 = 0; + element.var14 = 0; + } } var_10 = computeMove2(element); @@ -1859,14 +1883,14 @@ void processSeqListElement(SeqListElement &element) { } } - if (element.var16 + element.var14) { + if (element.var16 + element.var14 == 0) { if (element.var1C) { if (element.var1E) { objectTable[element.objIdx].costume = 0; element.var1E = 0; } - addAni(element.var1C + 3, element.objIdx, ptr1, element, 1, (int16 *) & var2); + addAni(element.var1C + 3, element.objIdx, ptr1, element, 1, &var_2); } } -- cgit v1.2.3 From de09845319f43f6bad3582af5d570de43c7f9632 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Thu, 3 Jul 2008 08:44:29 +0000 Subject: Fix for bug #2008054: Parallaction engine doesn't compile under MSVC9 svn-id: r32879 --- engines/parallaction/parser_br.cpp | 2 +- engines/parallaction/parser_ns.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index 51da7eb396..defc917a72 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -390,7 +390,7 @@ DECLARE_LOCATION_PARSER(flags) { if ((_vm->getLocationFlags() & kFlagsVisited) == 0) { // only for 1st visit - _vm->clearLocationFlags(kFlagsAll); + _vm->clearLocationFlags((uint32)kFlagsAll); int _si = 1; do { diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp index c654e3008e..2f4d2df776 100644 --- a/engines/parallaction/parser_ns.cpp +++ b/engines/parallaction/parser_ns.cpp @@ -1059,7 +1059,7 @@ DECLARE_LOCATION_PARSER(flags) { if ((_vm->getLocationFlags() & kFlagsVisited) == 0) { // only for 1st visit - _vm->clearLocationFlags(kFlagsAll); + _vm->clearLocationFlags((uint32)kFlagsAll); int _si = 1; do { -- cgit v1.2.3 From 59e672ef40e4c227c27022ec764f8b811b375220 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Thu, 3 Jul 2008 10:31:25 +0000 Subject: Changed balloons to use GfxObj as well. Next step is to integrate balloons for BRA. svn-id: r32883 --- engines/parallaction/disk.h | 10 ++--- engines/parallaction/disk_br.cpp | 8 ++-- engines/parallaction/disk_ns.cpp | 8 ++-- engines/parallaction/gfxbase.cpp | 12 ++++-- engines/parallaction/graphics.cpp | 85 +++++++++++++++++++++++++-------------- engines/parallaction/graphics.h | 13 +++--- 6 files changed, 82 insertions(+), 54 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index 176f10aa10..694d4efa6d 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -61,7 +61,7 @@ public: virtual GfxObj* loadHead(const char* name) = 0; virtual Font* loadFont(const char* name) = 0; virtual GfxObj* loadStatic(const char* name) = 0; - virtual GfxObj* loadFrames(const char* name) = 0; + virtual Frames* loadFrames(const char* name) = 0; virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0; virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0; virtual Table* loadTable(const char* name) = 0; @@ -153,7 +153,7 @@ public: GfxObj* loadHead(const char* name); Font* loadFont(const char* name); GfxObj* loadStatic(const char* name); - GfxObj* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -187,7 +187,7 @@ public: GfxObj* loadHead(const char* name); Font* loadFont(const char* name); GfxObj* loadStatic(const char* name); - GfxObj* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -226,7 +226,7 @@ public: GfxObj* loadHead(const char* name); Font* loadFont(const char* name); GfxObj* loadStatic(const char* name); - GfxObj* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); Table* loadTable(const char* name); @@ -251,7 +251,7 @@ public: GfxObj* loadTalk(const char *name); Font* loadFont(const char* name); GfxObj* loadStatic(const char* name); - GfxObj* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); }; diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 0159d9d406..543ed14146 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -280,7 +280,7 @@ Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) { return sprites; } -GfxObj* DosDisk_br::loadFrames(const char* name) { +Frames* DosDisk_br::loadFrames(const char* name) { debugC(5, kDebugDisk, "DosDisk_br::loadFrames"); char path[PATH_LEN]; @@ -291,7 +291,7 @@ GfxObj* DosDisk_br::loadFrames(const char* name) { errorFileNotFound(path); - return new GfxObj(0, createSprites(stream), name); + return createSprites(stream); } // Slides in Nippon Safes are basically screen-sized pictures with valid @@ -600,13 +600,13 @@ Sprites* AmigaDisk_br::createSprites(const char *path) { return sprites; } -GfxObj* AmigaDisk_br::loadFrames(const char* name) { +Frames* AmigaDisk_br::loadFrames(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_br::loadFrames '%s'", name); char path[PATH_LEN]; sprintf(path, "%s/anims/%s", _partPath, name); - return new GfxObj(0, createSprites(path)); + return createSprites(path); } GfxObj* AmigaDisk_br::loadTalk(const char *name) { diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index f45cf83f56..55e6fc5e77 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -490,8 +490,8 @@ GfxObj* DosDisk_ns::loadStatic(const char* name) { return new GfxObj(0, new SurfaceToFrames(cnv), name); } -GfxObj* DosDisk_ns::loadFrames(const char* name) { - return new GfxObj(0, loadCnv(name), name); +Frames* DosDisk_ns::loadFrames(const char* name) { + return loadCnv(name); } // @@ -1258,7 +1258,7 @@ void AmigaDisk_ns::loadSlide(BackgroundInfo& info, const char *name) { return; } -GfxObj* AmigaDisk_ns::loadFrames(const char* name) { +Frames* AmigaDisk_ns::loadFrames(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name); Common::SeekableReadStream *s; @@ -1273,7 +1273,7 @@ GfxObj* AmigaDisk_ns::loadFrames(const char* name) { Cnv *cnv = makeCnv(*s); delete s; - return new GfxObj(0, cnv, name); + return cnv; } GfxObj* AmigaDisk_ns::loadHead(const char* name) { diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 383f5d549c..8d7041305d 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -86,12 +86,14 @@ void GfxObj::clearFlags(uint32 flags) { } GfxObj* Gfx::loadAnim(const char *name) { - GfxObj *obj = _disk->loadFrames(name); + Frames* frames = _disk->loadFrames(name); + assert(frames); + + GfxObj *obj = new GfxObj(kGfxObjTypeAnim, frames, name); assert(obj); // animation Z is not set here, but controlled by game scripts and user interaction. // it is always >=0 and type = kGfxObjTypeAnim; obj->transparentKey = 0; _gfxobjList.push_back(obj); return obj; @@ -110,11 +112,13 @@ GfxObj* Gfx::loadGet(const char *name) { } GfxObj* Gfx::loadDoor(const char *name) { - GfxObj *obj = _disk->loadFrames(name); + Frames *frames = _disk->loadFrames(name); + assert(frames); + + GfxObj *obj = new GfxObj(kGfxObjTypeDoor, frames, name); assert(obj); obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first - obj->type = kGfxObjTypeDoor; obj->transparentKey = 0; _gfxobjList.push_back(obj); return obj; diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 838827b19f..24c78d1703 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -362,15 +362,13 @@ void Gfx::drawItems() { } void Gfx::drawBalloons() { - if (_numBalloons == 0) { + if (_balloons.size() == 0) { return; } Graphics::Surface *surf = g_system->lockScreen(); - for (uint i = 0; i < _numBalloons; i++) { - Common::Rect r(_balloons[i].surface.w, _balloons[i].surface.h); - r.moveTo(_balloons[i].x, _balloons[i].y); - blt(r, (byte*)_balloons[i].surface.getBasePtr(0, 0), surf, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); + for (uint i = 0; i < _balloons.size(); i++) { + drawGfxObject(_balloons[i], *surf, false); } g_system->unlockScreen(); } @@ -832,7 +830,7 @@ void Gfx::setItemFrame(uint item, uint16 f) { Gfx::Balloon* Gfx::getBalloon(uint id) { assert(id < _numBalloons); - return &_balloons[id]; + return &_intBalloons[id]; } int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) { @@ -840,18 +838,19 @@ int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) int id = _numBalloons; - Gfx::Balloon *balloon = &_balloons[id]; + Gfx::Balloon *balloon = &_intBalloons[id]; int16 real_h = (winding == -1) ? h : h + 9; - balloon->surface.create(w, real_h, 1); - balloon->surface.fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR); + balloon->surface = new Graphics::Surface; + balloon->surface->create(w, real_h, 1); + balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR); Common::Rect r(w, h); - balloon->surface.fillRect(r, 0); + balloon->surface->fillRect(r, 0); balloon->outerBox = r; r.grow(-borderThickness); - balloon->surface.fillRect(r, 1); + balloon->surface->fillRect(r, 1); balloon->innerBox = r; if (winding != -1) { @@ -860,7 +859,7 @@ int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) winding = (winding == 0 ? 1 : 0); Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT); s.moveTo(r.width()/2 - 5, r.bottom - 1); - blt(s, _resBalloonTail[winding], &balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); + blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); } _numBalloons++; @@ -868,6 +867,20 @@ int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) return id; } +GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) { + + GfxObj *obj = new GfxObj(kGfxObjTypeBalloon, frames, text); + + obj->layer = LAYER_FOREGROUND; + obj->frame = 0; + obj->transparentKey = BALLOON_TRANSPARENT_COLOR; + obj->setFlags(kGfxObjVisible); + + _balloons.push_back(obj); + + return obj; +} + int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) { int16 w, h; @@ -875,12 +888,14 @@ int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte t getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_balloons[id]; + Gfx::Balloon *balloon = &_intBalloons[id]; - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - balloon->x = x; - balloon->y = y; + // TODO: extract some text to make a name for obj + balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = x; + balloon->obj->y = y; return id; } @@ -892,15 +907,17 @@ int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) { getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_balloons[id]; + Gfx::Balloon *balloon = &_intBalloons[id]; - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - balloon->x = _dialogueBalloonX[id]; - balloon->y = 10; + // TODO: extract some text to make a name for obj + balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = _dialogueBalloonX[id]; + balloon->obj->y = 10; if (id > 0) { - balloon->y += _balloons[id - 1].y + _balloons[id - 1].outerBox.height(); + balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].outerBox.height(); } @@ -909,8 +926,8 @@ int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) { void Gfx::setBalloonText(uint id, char *text, byte textColor) { Gfx::Balloon *balloon = getBalloon(id); - balloon->surface.fillRect(balloon->innerBox, 1); - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + balloon->surface->fillRect(balloon->innerBox, 1); + drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); } @@ -921,11 +938,13 @@ int Gfx::setLocationBalloon(char *text, bool endGame) { getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR); - Gfx::Balloon *balloon = &_balloons[id]; - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, 0, MAX_BALLOON_WIDTH); + Gfx::Balloon *balloon = &_intBalloons[id]; + drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH); - balloon->x = 5; - balloon->y = 5; + // TODO: extract some text to make a name for obj + balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = 5; + balloon->obj->y = 5; return id; } @@ -935,10 +954,10 @@ int Gfx::hitTestDialogueBalloon(int x, int y) { Common::Point p; for (uint i = 0; i < _numBalloons; i++) { - p.x = x - _balloons[i].x; - p.y = y - _balloons[i].y; + p.x = x - _intBalloons[i].obj->x; + p.y = y - _intBalloons[i].obj->y; - if (_balloons[i].innerBox.contains(p)) + if (_intBalloons[i].innerBox.contains(p)) return i; } @@ -947,8 +966,12 @@ int Gfx::hitTestDialogueBalloon(int x, int y) { void Gfx::freeBalloons() { + _balloons.clear(); + for (uint i = 0; i < _numBalloons; i++) { - _balloons[i].surface.free(); + delete _intBalloons[i].obj; + _intBalloons[i].obj = 0; + _intBalloons[i].surface = 0; // no need to delete surface, since it is done by obj (GfxObj) } _numBalloons = 0; } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index df4cab4caf..b15da432d9 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -344,7 +344,8 @@ enum { kGfxObjTypeDoor = 0, kGfxObjTypeGet = 1, kGfxObjTypeAnim = 2, - kGfxObjTypeLabel = 3 + kGfxObjTypeLabel = 3, + kGfxObjTypeBalloon = 4 }; enum { @@ -484,6 +485,7 @@ public: void setBalloonText(uint id, char *text, byte textColor); int hitTestDialogueBalloon(int x, int y); void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height); + GfxObj* registerBalloon(Frames *frames, const char *text); // other items int setItem(GfxObj* obj, uint16 x, uint16 y, byte transparentColor = 0); @@ -552,13 +554,11 @@ public: static int16 _dialogueBalloonX[5]; struct Balloon { - uint16 x; - uint16 y; Common::Rect outerBox; Common::Rect innerBox; - uint16 winding; - Graphics::Surface surface; - } _balloons[5]; + Graphics::Surface *surface; + GfxObj *obj; + } _intBalloons[5]; uint _numBalloons; @@ -573,6 +573,7 @@ public: typedef Common::Array GfxObjArray; GfxObjArray _labels; + GfxObjArray _balloons; uint _floatingLabel; -- cgit v1.2.3 From 56c6840ff72ab38a508aa0f46662ef7c636e410f Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 3 Jul 2008 16:25:59 +0000 Subject: Fixing a crash when loading a save made within the cult/bargon building (bug #2005965) svn-id: r32895 --- engines/gob/goblin_v2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index 9144e35070..d763aeb01c 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -88,7 +88,7 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (y + 1) / 2; *obj->pPosX = x * _vm->_map->_tilesWidth; } else { - if (obj->goblinStates[state] != 0) { + if ((obj->goblinStates != 0) && (obj->goblinStates[state] != 0)) { layer = obj->goblinStates[state][0].layer; animation = obj->goblinStates[state][0].animation; objAnim->state = state; -- cgit v1.2.3 From d92085b5071b0bb62642d62857e5853006be3b2c Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 3 Jul 2008 21:09:07 +0000 Subject: minor fix for Towns/PC98 music svn-id: r32899 --- engines/kyra/sequences_lok.cpp | 2 +- engines/kyra/sound_lok.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index b30568c7e2..3a497a258f 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1083,7 +1083,7 @@ void KyraEngine_LoK::seq_playCredits() { _screen->_charWidth = -1; // we only need this for the fm-towns version - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) + if (_flags.platform == Common::kPlatformFMTowns && _configMusic == 1) snd_playWanderScoreViaMap(53, 1); uint8 *buffer = 0; diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index 7d6e1dd378..b43d72ebce 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -49,20 +49,23 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { } else if (command >= 35 && command <= 38) { snd_playSoundEffect(command-20); } else if (command >= 2) { - if (_lastMusicCommand != command) { + if (_lastMusicCommand != command) // the original does -2 here we handle this inside _sound->playTrack() _sound->playTrack(command); - } } else { _sound->haltTrack(); } + _lastMusicCommand = command; } else if (_flags.platform == Common::kPlatformPC98) { - if (command == 1) + if (command == 1) { _sound->beginFadeOut(); - else if (command >= 2) - _sound->playTrack(command); - else + } else if (command >= 2) { + if (_lastMusicCommand != command) + _sound->playTrack(command); + } else { _sound->haltTrack(); + } + _lastMusicCommand = command; } else { KyraEngine_v1::snd_playWanderScoreViaMap(command, restart); } -- cgit v1.2.3 From d387d1af0ec869700da199578f07e5a0c00968f3 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Fri, 4 Jul 2008 00:29:21 +0000 Subject: - Moved dialogue balloon management code from Gfx to its own class - Added a class to draw balloons in BRA (still without text and with wrong placement) svn-id: r32902 --- engines/parallaction/balloons.cpp | 456 +++++++++++++++++++++++++++++++ engines/parallaction/callables_ns.cpp | 2 +- engines/parallaction/dialogue.cpp | 24 +- engines/parallaction/exec_br.cpp | 9 +- engines/parallaction/exec_ns.cpp | 4 +- engines/parallaction/graphics.cpp | 174 +----------- engines/parallaction/graphics.h | 33 +-- engines/parallaction/gui_br.cpp | 2 +- engines/parallaction/input.cpp | 2 +- engines/parallaction/module.mk | 1 + engines/parallaction/parallaction.cpp | 6 +- engines/parallaction/parallaction.h | 9 + engines/parallaction/parallaction_br.cpp | 3 + 13 files changed, 515 insertions(+), 210 deletions(-) create mode 100644 engines/parallaction/balloons.cpp (limited to 'engines') diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp new file mode 100644 index 0000000000..fab92dada9 --- /dev/null +++ b/engines/parallaction/balloons.cpp @@ -0,0 +1,456 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "parallaction/graphics.h" +#include "parallaction/parallaction.h" + +namespace Parallaction { + + +#define BALLOON_TRANSPARENT_COLOR_NS 2 +#define BALLOON_TRANSPARENT_COLOR_BR 0 + +#define BALLOON_TAIL_WIDTH 12 +#define BALLOON_TAIL_HEIGHT 10 + + +byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = { + { + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + }, + { + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02 + } +}; + +class BalloonManager_ns : public BalloonManager { + + static int16 _dialogueBalloonX[5]; + + struct Balloon { + Common::Rect outerBox; + Common::Rect innerBox; + Graphics::Surface *surface; + GfxObj *obj; + } _intBalloons[5]; + + uint _numBalloons; + + void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth); + int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness); + Balloon *getBalloon(uint id); + + Gfx *_gfx; + +public: + BalloonManager_ns(Gfx *gfx); + ~BalloonManager_ns(); + + void freeBalloons(); + int setLocationBalloon(char *text, bool endGame); + int setDialogueBalloon(char *text, uint16 winding, byte textColor); + int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor); + void setBalloonText(uint id, char *text, byte textColor); + int hitTestDialogueBalloon(int x, int y); +}; + +int16 BalloonManager_ns::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 }; + +BalloonManager_ns::BalloonManager_ns(Gfx *gfx) : _numBalloons(0), _gfx(gfx) { + +} + +BalloonManager_ns::~BalloonManager_ns() { + +} + + +BalloonManager_ns::Balloon* BalloonManager_ns::getBalloon(uint id) { + assert(id < _numBalloons); + return &_intBalloons[id]; +} + +int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) { + assert(_numBalloons < 5); + + int id = _numBalloons; + + Balloon *balloon = &_intBalloons[id]; + + int16 real_h = (winding == -1) ? h : h + 9; + balloon->surface = new Graphics::Surface; + balloon->surface->create(w, real_h, 1); + balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR_NS); + + Common::Rect r(w, h); + balloon->surface->fillRect(r, 0); + balloon->outerBox = r; + + r.grow(-borderThickness); + balloon->surface->fillRect(r, 1); + balloon->innerBox = r; + + if (winding != -1) { + // draws tail + // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill. + winding = (winding == 0 ? 1 : 0); + Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT); + s.moveTo(r.width()/2 - 5, r.bottom - 1); + _gfx->blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR_NS); + } + + _numBalloons++; + + return id; +} + + +int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) { + + int16 w, h; + + _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); + + int id = createBalloon(w+5, h, winding, 1); + Balloon *balloon = &_intBalloons[id]; + + _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = x; + balloon->obj->y = y; + balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS; + + return id; +} + +int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textColor) { + + int16 w, h; + + _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); + + int id = createBalloon(w+5, h, winding, 1); + Balloon *balloon = &_intBalloons[id]; + + _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = _dialogueBalloonX[id]; + balloon->obj->y = 10; + balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS; + + if (id > 0) { + balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].outerBox.height(); + } + + + return id; +} + +void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) { + Balloon *balloon = getBalloon(id); + balloon->surface->fillRect(balloon->innerBox, 1); + _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); +} + + +int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) { + + int16 w, h; + + _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); + + int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS); + Balloon *balloon = &_intBalloons[id]; + _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = 5; + balloon->obj->y = 5; + balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS; + + return id; +} + +int BalloonManager_ns::hitTestDialogueBalloon(int x, int y) { + + Common::Point p; + + for (uint i = 0; i < _numBalloons; i++) { + p.x = x - _intBalloons[i].obj->x; + p.y = y - _intBalloons[i].obj->y; + + if (_intBalloons[i].innerBox.contains(p)) + return i; + } + + return -1; +} + +void BalloonManager_ns::freeBalloons() { + _gfx->destroyBalloons(); + + for (uint i = 0; i < _numBalloons; i++) { + _intBalloons[i].obj = 0; + _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons + } + + _numBalloons = 0; +} + + + + + + + + +class BalloonManager_br : public BalloonManager { + + struct Balloon { + Common::Rect box; + Graphics::Surface *surface; + GfxObj *obj; + } _intBalloons[3]; + + uint _numBalloons; + + Frames *_leftBalloon; + Frames *_rightBalloon; + Disk *_disk; + Gfx *_gfx; + + void cacheAnims(); + void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth); + int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness); + Balloon *getBalloon(uint id); + Graphics::Surface *expandBalloon(Frames *data, int frameNum); + + +public: + BalloonManager_br(Disk *disk, Gfx *gfx); + ~BalloonManager_br(); + + void freeBalloons(); + int setLocationBalloon(char *text, bool endGame); + int setDialogueBalloon(char *text, uint16 winding, byte textColor); + int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor); + void setBalloonText(uint id, char *text, byte textColor); + int hitTestDialogueBalloon(int x, int y); +}; + + + +BalloonManager_br::Balloon* BalloonManager_br::getBalloon(uint id) { + assert(id < _numBalloons); + return &_intBalloons[id]; +} + +Graphics::Surface *BalloonManager_br::expandBalloon(Frames *data, int frameNum) { + + Common::Rect rect; + data->getRect(frameNum, rect); + + rect.translate(-rect.left, -rect.top); + + Graphics::Surface *surf = new Graphics::Surface; + surf->create(rect.width(), rect.height(), 1); + + _gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, 0, BALLOON_TRANSPARENT_COLOR_BR); + + return surf; +} + +int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) { + cacheAnims(); + + int id = _numBalloons; + Frames *src = 0; + int srcFrame = 0; + + Balloon *balloon = &_intBalloons[id]; + + if (winding == 0) { + src = _leftBalloon; + srcFrame = 0; + } else + if (winding == 1) { + src = _rightBalloon; + srcFrame = 0; + } + + assert(src); + + balloon->surface = expandBalloon(src, srcFrame); + src->getRect(srcFrame, balloon->box); + +// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = x; + balloon->obj->y = y; + balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR; + + _numBalloons++; + + return id; +} + +int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textColor) { + cacheAnims(); + + int id = _numBalloons; + Frames *src = 0; + int srcFrame = 0; + + Balloon *balloon = &_intBalloons[id]; + + if (winding == 0) { + src = _leftBalloon; + srcFrame = id; + } else + if (winding == 1) { + src = _rightBalloon; + srcFrame = 0; + } + + assert(src); + + balloon->surface = expandBalloon(src, srcFrame); + src->getRect(srcFrame, balloon->box); + +// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = 0; + balloon->obj->y = 10; + balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR; + + if (id > 0) { + balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].box.height(); + } + + _numBalloons++; + + return id; +} + +void BalloonManager_br::setBalloonText(uint id, char *text, byte textColor) { } + +int BalloonManager_br::setLocationBalloon(char *text, bool endGame) { +/* + int16 w, h; + + getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); + + int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR); + Balloon *balloon = &_intBalloons[id]; + drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH); + + // TODO: extract some text to make a name for obj + balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); + balloon->obj->x = 5; + balloon->obj->y = 5; +*/ + return 0; +} + +int BalloonManager_br::hitTestDialogueBalloon(int x, int y) { + + Common::Point p; + + for (uint i = 0; i < _numBalloons; i++) { + p.x = x - _intBalloons[i].obj->x; + p.y = y - _intBalloons[i].obj->y; + + if (_intBalloons[i].box.contains(p)) + return i; + } + + return -1; +} + +void BalloonManager_br::freeBalloons() { + _gfx->destroyBalloons(); + + for (uint i = 0; i < _numBalloons; i++) { + _intBalloons[i].obj = 0; + _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons + } + + _numBalloons = 0; +} + +void BalloonManager_br::cacheAnims() { + if (!_leftBalloon) { + _leftBalloon = _disk->loadFrames("fumetto.ani"); + _rightBalloon = _disk->loadFrames("fumdx.ani"); + } +} + +BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), _leftBalloon(0), _rightBalloon(0) { +} + +BalloonManager_br::~BalloonManager_br() { + delete _leftBalloon; + delete _rightBalloon; +} + +void Parallaction::setupBalloonManager() { + if (_vm->getGameType() == GType_Nippon) { + _balloonMan = new BalloonManager_ns(_vm->_gfx); + } else + if (_vm->getGameType() == GType_BRA) { + _balloonMan = new BalloonManager_br(_vm->_disk, _vm->_gfx); + } else { + error("Unknown game type"); + } +} + +} // namespace Parallaction diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index 3ecc7a9534..7c053715f6 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -341,7 +341,7 @@ void Parallaction_ns::_c_endComment(void *param) { } _input->waitUntilLeftClick(); - _gfx->freeBalloons(); + _balloonMan->freeBalloons(); return; } diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 3b6c35d3bb..1dc4fd5ab3 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -93,7 +93,7 @@ uint16 DialogueManager::askPassword() { uint16 passwordLen = 0; _password[0] = '\0'; - _vm->_gfx->setDialogueBalloon(_q->_answers[0]->_text, 1, 3); + _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3); int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y); _vm->_gfx->setItemFrame(id, 0); @@ -118,7 +118,7 @@ uint16 DialogueManager::askPassword() { } if (changed) { - _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 3); + _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3); _vm->_gfx->updateScreen(); changed = false; } @@ -143,7 +143,7 @@ uint16 DialogueManager::askPassword() { } - _vm->_gfx->hideDialogueStuff(); + _vm->hideDialogueStuff(); return 0; @@ -162,7 +162,7 @@ bool DialogueManager::displayAnswer(uint16 i) { // display suitable answers if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) { - int id = _vm->_gfx->setDialogueBalloon(a->_text, 1, 3); + int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, 3); assert(id >= 0); _visAnswers[id] = i; @@ -190,13 +190,13 @@ void DialogueManager::displayQuestion() { if (!scumm_stricmp(_q->_text, "NULL")) return; - _vm->_gfx->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0); + _vm->_balloonMan->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0); int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y); _vm->_gfx->setItemFrame(id, _q->_mood & 0xF); _vm->_gfx->updateScreen(); _vm->_input->waitUntilLeftClick(); - _vm->_gfx->hideDialogueStuff(); + _vm->hideDialogueStuff(); return; } @@ -261,9 +261,9 @@ int16 DialogueManager::selectAnswer() { _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF); if (numAvailableAnswers == 1) { - _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 0); + _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 0); _vm->_input->waitUntilLeftClick(); - _vm->_gfx->hideDialogueStuff(); + _vm->hideDialogueStuff(); return 0; } @@ -277,15 +277,15 @@ int16 DialogueManager::selectAnswer() { _vm->_input->readInput(); _vm->_input->getCursorPos(p); event = _vm->_input->getLastButtonEvent(); - selection = _vm->_gfx->hitTestDialogueBalloon(p.x, p.y); + selection = _vm->_balloonMan->hitTestDialogueBalloon(p.x, p.y); if (selection != oldSelection) { if (oldSelection != -1) { - _vm->_gfx->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3); + _vm->_balloonMan->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3); } if (selection != -1) { - _vm->_gfx->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0); + _vm->_balloonMan->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0); _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF); } } @@ -300,7 +300,7 @@ int16 DialogueManager::selectAnswer() { oldSelection = selection; } - _vm->_gfx->hideDialogueStuff(); + _vm->hideDialogueStuff(); return _visAnswers[selection]; } diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index 348af2b731..734360167b 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -100,8 +100,13 @@ void Parallaction_br::setupSubtitles(char *s, char *s2, int y) { } void Parallaction_br::clearSubtitles() { - _gfx->hideLabel(_subtitle[0]); - _gfx->hideLabel(_subtitle[1]); + if (_subtitle[0] != -1) { + _gfx->hideLabel(_subtitle[0]); + } + + if (_subtitle[1] != -1) { + _gfx->hideLabel(_subtitle[1]); + } } diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index bd2d54c0a0..abad9f273b 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -469,7 +469,7 @@ void Parallaction::displayComment(ExamineData *data) { } _gfx->setHalfbriteMode(true); - _gfx->setSingleBalloon(data->_description, 0, 90, 0, 0); + _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, 0); Common::Rect r; data->_cnv->getRect(0, r); id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2); @@ -477,7 +477,7 @@ void Parallaction::displayComment(ExamineData *data) { id = _gfx->setItem(_char._head, 100, 152); _gfx->setItemFrame(id, 0); } else { - _gfx->setSingleBalloon(data->_description, 140, 10, 0, 0); + _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, 0); id = _gfx->setItem(_char._talk, 190, 80); _gfx->setItemFrame(id, 0); } diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 24c78d1703..f839f88778 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -64,10 +64,6 @@ int32 Gfx::getVar(const Common::String &name) { #define LABEL_TRANSPARENT_COLOR 0xFF -#define BALLOON_TRANSPARENT_COLOR 2 - - -int16 Gfx::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 }; void halfbritePixel(int x, int y, int color, void *data) { byte *buffer = (byte*)data; @@ -238,37 +234,6 @@ void Palette::rotate(uint first, uint last, bool forward) { } -#define BALLOON_TAIL_WIDTH 12 -#define BALLOON_TAIL_HEIGHT 10 - - -byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = { - { - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - }, - { - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02 - } -}; - void Gfx::setPalette(Palette pal) { byte sysPal[256*4]; @@ -777,7 +742,6 @@ Gfx::Gfx(Parallaction* vm) : setPalette(_palette); - _numBalloons = 0; _numItems = 0; _floatingLabel = NO_FLOATING_LABEL; @@ -828,44 +792,6 @@ void Gfx::setItemFrame(uint item, uint16 f) { _items[item].data->setFlags(kGfxObjVisible); } -Gfx::Balloon* Gfx::getBalloon(uint id) { - assert(id < _numBalloons); - return &_intBalloons[id]; -} - -int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) { - assert(_numBalloons < 5); - - int id = _numBalloons; - - Gfx::Balloon *balloon = &_intBalloons[id]; - - int16 real_h = (winding == -1) ? h : h + 9; - balloon->surface = new Graphics::Surface; - balloon->surface->create(w, real_h, 1); - balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR); - - Common::Rect r(w, h); - balloon->surface->fillRect(r, 0); - balloon->outerBox = r; - - r.grow(-borderThickness); - balloon->surface->fillRect(r, 1); - balloon->innerBox = r; - - if (winding != -1) { - // draws tail - // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill. - winding = (winding == 0 ? 1 : 0); - Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT); - s.moveTo(r.width()/2 - 5, r.bottom - 1); - blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); - } - - _numBalloons++; - - return id; -} GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) { @@ -873,7 +799,6 @@ GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) { obj->layer = LAYER_FOREGROUND; obj->frame = 0; - obj->transparentKey = BALLOON_TRANSPARENT_COLOR; obj->setFlags(kGfxObjVisible); _balloons.push_back(obj); @@ -881,110 +806,17 @@ GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) { return obj; } -int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) { - - int16 w, h; - - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); - - int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_intBalloons[id]; - - drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - - // TODO: extract some text to make a name for obj - balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); - balloon->obj->x = x; - balloon->obj->y = y; - - return id; -} - -int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) { - - int16 w, h; - - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); - - int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_intBalloons[id]; - - drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - - // TODO: extract some text to make a name for obj - balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); - balloon->obj->x = _dialogueBalloonX[id]; - balloon->obj->y = 10; - - if (id > 0) { - balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].outerBox.height(); - } - - - return id; -} - -void Gfx::setBalloonText(uint id, char *text, byte textColor) { - Gfx::Balloon *balloon = getBalloon(id); - balloon->surface->fillRect(balloon->innerBox, 1); - drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); -} - - -int Gfx::setLocationBalloon(char *text, bool endGame) { - - int16 w, h; - - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); - - int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR); - Gfx::Balloon *balloon = &_intBalloons[id]; - drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH); - - // TODO: extract some text to make a name for obj - balloon->obj = registerBalloon(new SurfaceToFrames(balloon->surface), 0); - balloon->obj->x = 5; - balloon->obj->y = 5; - - return id; -} - -int Gfx::hitTestDialogueBalloon(int x, int y) { - - Common::Point p; - - for (uint i = 0; i < _numBalloons; i++) { - p.x = x - _intBalloons[i].obj->x; - p.y = y - _intBalloons[i].obj->y; - - if (_intBalloons[i].innerBox.contains(p)) - return i; +void Gfx::destroyBalloons() { + for (uint i = 0; i < _balloons.size(); i++) { + delete _balloons[i]; } - - return -1; -} - - -void Gfx::freeBalloons() { _balloons.clear(); - - for (uint i = 0; i < _numBalloons; i++) { - delete _intBalloons[i].obj; - _intBalloons[i].obj = 0; - _intBalloons[i].surface = 0; // no need to delete surface, since it is done by obj (GfxObj) - } - _numBalloons = 0; } void Gfx::freeItems() { _numItems = 0; } -void Gfx::hideDialogueStuff() { - freeItems(); - freeBalloons(); -} - void Gfx::freeBackground() { _backgroundInfo.free(); } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index b15da432d9..00718d8c26 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -450,6 +450,20 @@ enum { kBackgroundSlide = 2 }; + +class BalloonManager { +public: + virtual ~BalloonManager() { } + + virtual void freeBalloons() = 0; + virtual int setLocationBalloon(char *text, bool endGame) = 0; + virtual int setDialogueBalloon(char *text, uint16 winding, byte textColor) = 0; + virtual int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) = 0; + virtual void setBalloonText(uint id, char *text, byte textColor) = 0; + virtual int hitTestDialogueBalloon(int x, int y) = 0; +}; + + typedef Common::HashMap VarMap; class Gfx { @@ -479,13 +493,9 @@ public: void freeLabels(); // dialogue balloons - int setLocationBalloon(char *text, bool endGame); - int setDialogueBalloon(char *text, uint16 winding, byte textColor); - int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor); - void setBalloonText(uint id, char *text, byte textColor); - int hitTestDialogueBalloon(int x, int y); void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height); GfxObj* registerBalloon(Frames *frames, const char *text); + void destroyBalloons(); // other items int setItem(GfxObj* obj, uint16 x, uint16 y, byte transparentColor = 0); @@ -551,16 +561,6 @@ protected: int32 getRenderMode(const char *type); public: - static int16 _dialogueBalloonX[5]; - - struct Balloon { - Common::Rect outerBox; - Common::Rect innerBox; - Graphics::Surface *surface; - GfxObj *obj; - } _intBalloons[5]; - - uint _numBalloons; struct Item { GfxObj *data; @@ -585,9 +585,6 @@ public: void copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst); - int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness); - Balloon *getBalloon(uint id); - // low level text and patches void drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color); void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth); diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index 5551108693..0be070e345 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -195,7 +195,7 @@ int Parallaction_br::guiShowMenu() { } _system->showMouse(false); - _gfx->hideDialogueStuff(); + hideDialogueStuff(); for (i = 0; i < availItems; i++) { delete _lines[i]; diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index e758bbd41c..65acbcfe58 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -174,7 +174,7 @@ void Input::updateGameInput() { void Input::updateCommentInput() { waitUntilLeftClick(); - _vm->_gfx->hideDialogueStuff(); + _vm->hideDialogueStuff(); _vm->_gfx->setHalfbriteMode(false); _inputMode = kInputModeGame; diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 2478b4b2e1..92c6ec5227 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -1,6 +1,7 @@ MODULE := engines/parallaction MODULE_OBJS := \ + balloons_o \ callables_br.o \ callables_ns.o \ debug.o \ diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 5f5cfdb820..3a52b28e06 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -134,6 +134,8 @@ int Parallaction::init() { _debugger = new Debugger(this); + setupBalloonManager(); + return 0; } @@ -281,7 +283,7 @@ void Parallaction::setBackground(const char* name, const char* mask, const char* } void Parallaction::showLocationComment(const char *text, bool end) { - _gfx->setLocationBalloon(const_cast(text), end); + _balloonMan->setLocationBalloon(const_cast(text), end); } @@ -422,7 +424,7 @@ void Parallaction::doLocationEnterTransition() { showLocationComment(_location._comment, false); _input->waitUntilLeftClick(); - _gfx->freeBalloons(); + _balloonMan->freeBalloons(); // fades maximum intensity palette towards approximation of main palette for (uint16 _si = 0; _si<6; _si++) { diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index b1a5995e28..c095cab667 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -429,6 +429,15 @@ public: Inventory *_inventory; InventoryRenderer *_inventoryRenderer; + BalloonManager *_balloonMan; + + void setupBalloonManager(); + + void hideDialogueStuff() { + _gfx->freeItems(); + _balloonMan->freeBalloons(); + } + }; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index b22e1b0f2d..e7f08d0339 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -80,6 +80,9 @@ int Parallaction_br::init() { _part = -1; + _subtitle[0] = -1; + _subtitle[1] = -1; + Parallaction::init(); return 0; -- cgit v1.2.3 From 60db8cb8cf9b39b591fd5c9d0c754cbc3577b765 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Fri, 4 Jul 2008 00:35:39 +0000 Subject: Correct typo. svn-id: r32903 --- engines/parallaction/module.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 92c6ec5227..fb867f5285 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -1,7 +1,7 @@ MODULE := engines/parallaction MODULE_OBJS := \ - balloons_o \ + balloons.o \ callables_br.o \ callables_ns.o \ debug.o \ -- cgit v1.2.3 From 357f0c4e3abc23e1a4c711191c1aeca0bfe47000 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 5 Jul 2008 07:47:27 +0000 Subject: Added spanish menu strings for spanish fan translation of Kyrandia 3. svn-id: r32911 --- engines/kyra/kyra_mr.cpp | 5 +++++ engines/kyra/kyra_mr.h | 4 +++- engines/kyra/staticres.cpp | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index b425c0929f..3d1b09561d 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -343,6 +343,11 @@ void KyraEngine_MR::initMainMenu() { 0x80, 0xFF }; + if (_flags.lang == Common::ES_ESP) { + for (int i = 0; i < 4; ++i) + data.strings[i] = _mainMenuSpanishFan[i]; + } + MainMenu::Animation anim; anim.anim = _menuAnim; anim.startFrame = 29; diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 5af138373c..aa103b167b 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -184,9 +184,11 @@ private: private: // main menu - const char *const *_mainMenuStrings; + const char * const *_mainMenuStrings; int _mainMenuStringsSize; + static const char * const _mainMenuSpanishFan[]; + // animator uint8 *_gamePlayBuffer; void restorePage3(); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 5d094fa13f..a25fe4b295 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1980,6 +1980,13 @@ const char *KyraEngine_MR::_languageExtension[] = { "TRS"*/ }; +const char * const KyraEngine_MR::_mainMenuSpanishFan[] = { + "Nouvelle Partie", + "Ver Intro", + "Restaurar", + "Finalizar" +}; + const int KyraEngine_MR::_languageExtensionSize = ARRAYSIZE(KyraEngine_MR::_languageExtension); const KyraEngine_MR::ShapeDesc KyraEngine_MR::_shapeDescs[] = { -- cgit v1.2.3 From 056288f87a2e5ad5251c81901320b2b14ca22443 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 5 Jul 2008 08:20:10 +0000 Subject: Added support for Italian fan translation of Kyrandia 3. (see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3") svn-id: r32912 --- engines/kyra/detection.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ engines/kyra/kyra_mr.cpp | 3 +++ engines/kyra/kyra_mr.h | 1 + engines/kyra/kyra_v1.cpp | 10 ++++++++-- engines/kyra/staticres.cpp | 7 +++++++ 5 files changed, 65 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index f55cd1ac5e..0c8acb59b7 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -654,6 +654,52 @@ const KYRAGameDescription adGameDescs[] = { KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) }, + // Itlian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::IT_ITA, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) } }; diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 3d1b09561d..a4e5b58364 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -346,6 +346,9 @@ void KyraEngine_MR::initMainMenu() { if (_flags.lang == Common::ES_ESP) { for (int i = 0; i < 4; ++i) data.strings[i] = _mainMenuSpanishFan[i]; + } else if (_flags.lang == Common::IT_ITA) { + for (int i = 0; i < 4; ++i) + data.strings[i] = _mainMenuItalianFan[i]; } MainMenu::Animation anim; diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index aa103b167b..5f9f6f91a3 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -188,6 +188,7 @@ private: int _mainMenuStringsSize; static const char * const _mainMenuSpanishFan[]; + static const char * const _mainMenuItalianFan[]; // animator uint8 *_gamePlayBuffer; diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index d2e0f37a60..117194aea2 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -247,8 +247,14 @@ void KyraEngine_v1::delayWithTicks(int ticks) { void KyraEngine_v1::registerDefaultSettings() { if (_flags.gameID != GI_KYRA3) ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)); - if (_flags.fanLang != Common::UNK_LANG) - ConfMan.registerDefault("subtitles", true); + if (_flags.fanLang != Common::UNK_LANG) { + // HACK/WORKAROUND: Since we can't use registerDefault here to overwrite + // the global subtitles settings, we're using this hack to enable subtitles + // for fan translations + const Common::ConfigManager::Domain *cur = ConfMan.getActiveDomain(); + if (!cur || (cur && cur->get("subtitles").empty())) + ConfMan.setBool("subtitles", true); + } } void KyraEngine_v1::readSettings() { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index a25fe4b295..1997039c4a 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1987,6 +1987,13 @@ const char * const KyraEngine_MR::_mainMenuSpanishFan[] = { "Finalizar" }; +const char * const KyraEngine_MR::_mainMenuItalianFan[] = { + "Nuova Partita", + "Introduzione", + "Carica una partita", + "Esci dal gioco" +}; + const int KyraEngine_MR::_languageExtensionSize = ARRAYSIZE(KyraEngine_MR::_languageExtension); const KyraEngine_MR::ShapeDesc KyraEngine_MR::_shapeDescs[] = { -- cgit v1.2.3 From 1cc9af6b1023d438193587171890bf2ca7d5adbf Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 6 Jul 2008 18:37:52 +0000 Subject: Implemented Good Enough(TM) XMIDI looping. This is used by Kyrandia 2 (the loop hack is no longer needed, and has been removed), and will be used by Discworld. svn-id: r32930 --- engines/kyra/sound.cpp | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index f56c43aabd..c768255272 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -249,21 +249,6 @@ void SoundMidiPC::close() { } void SoundMidiPC::send(uint32 b) { - // HACK: For Kyrandia, we make the simplifying assumption that a song - // either loops in its entirety, or not at all. So if we see a FOR_LOOP - // controller event, we turn on looping even if there isn't any - // corresponding NEXT_BREAK event. - // - // This is a gross over-simplification of how XMIDI handles loops. If - // anyone feels like doing a proper implementation, please refer to - // the Exult project, and do it in midiparser_xmidi.cpp - - if ((b & 0xFFF0) == 0x74B0 && _eventFromMusic) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "SoundMidiPC: Looping song"); - _musicParser->property(MidiParser::mpAutoLoop, true); - return; - } - if (_passThrough) { if ((b & 0xFFF0) == 0x007BB0) return; -- cgit v1.2.3 From 0f8f3d51bba952632eb5ee5926cad8814cd19c74 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 7 Jul 2008 14:51:27 +0000 Subject: Fixed regression after label code refactoring. svn-id: r32940 --- engines/parallaction/graphics.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index f839f88778..93ebdd3a65 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -649,6 +649,7 @@ void Gfx::freeLabels() { delete _labels[i]; } _labels.clear(); + _floatingLabel = NO_FLOATING_LABEL; } void Gfx::drawLabels() { -- cgit v1.2.3 From 741214b6568abc10992701cc284569c318181e93 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 7 Jul 2008 19:40:43 +0000 Subject: Some fixes for warnings under GCC 2.95 svn-id: r32948 --- engines/m4/globals.cpp | 10 ++++++---- engines/m4/globals.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 12d9a24d37..58c68979d1 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -75,7 +75,7 @@ bool Kernel::sendTrigger(int32 triggerNum) { bool Kernel::handleTrigger(int32 triggerNum) { - printf("betweenRooms = %d; triggerNum = %08X\n", betweenRooms, triggerNum); + printf("betweenRooms = %d; triggerNum = %08X\n", betweenRooms, (uint)triggerNum); if (betweenRooms) return true; @@ -271,11 +271,13 @@ Globals::Globals(M4Engine *vm): _vm(vm) { } Globals::~Globals() { - for(uint32 i = 0; i < _madsVocab.size(); i++) + uint32 i; + + for(i = 0; i < _madsVocab.size(); i++) free(_madsVocab[i]); _madsVocab.clear(); - for(uint32 i = 0; i < _madsQuotes.size(); i++) + for(i = 0; i < _madsQuotes.size(); i++) free(_madsQuotes[i]); _madsQuotes.clear(); @@ -351,7 +353,7 @@ void Globals::loadMadsMessagesInfo() { _vm->res()->toss("messages.dat"); } -char* Globals::loadMessage(uint32 index) { +char* Globals::loadMessage(uint index) { if (index > _madsMessages.size() - 1) { warning("Invalid message index: %i", index); return NULL; diff --git a/engines/m4/globals.h b/engines/m4/globals.h index a0133db2d6..a80e8bf710 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -177,7 +177,7 @@ public: void loadMadsMessagesInfo(); uint32 getMessagesSize() { return _madsMessages.size(); } - char* loadMessage(uint32 index); + char* loadMessage(uint index); }; #define PLAYER_FIELD_LENGTH 40 -- cgit v1.2.3 From aee23f36a2b0ed26588c40d96ef0eee53c482d75 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 7 Jul 2008 20:40:35 +0000 Subject: Fix for bug #2012293 "KYRA: Bad Spanish String in menu". svn-id: r32949 --- engines/kyra/staticres.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 1997039c4a..4f577c1d1e 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1976,12 +1976,14 @@ const char *KyraEngine_MR::_languageExtension[] = { "TRE", "TRF", "TRG"/*, - "TRI", Italian and Spanish were never included - "TRS"*/ + "TRI", Italian and Spanish were never included, the supported fan translations are using + "TRS" English/French extensions thus overwriting these languages */ }; +const int KyraEngine_MR::_languageExtensionSize = ARRAYSIZE(KyraEngine_MR::_languageExtension); + const char * const KyraEngine_MR::_mainMenuSpanishFan[] = { - "Nouvelle Partie", + "Nueva Partida", "Ver Intro", "Restaurar", "Finalizar" @@ -1994,8 +1996,6 @@ const char * const KyraEngine_MR::_mainMenuItalianFan[] = { "Esci dal gioco" }; -const int KyraEngine_MR::_languageExtensionSize = ARRAYSIZE(KyraEngine_MR::_languageExtension); - const KyraEngine_MR::ShapeDesc KyraEngine_MR::_shapeDescs[] = { { 57, 91, -31, -82 }, { 57, 91, -31, -82 }, -- cgit v1.2.3 From e74d01a59a17894a85723db3b9af4dacac659336 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 7 Jul 2008 22:02:01 +0000 Subject: Fix for bathroom door opening crash in Operation Stealth's start. svn-id: r32951 --- engines/cine/gfx.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 47446f2410..2b7f3b8890 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -969,6 +969,7 @@ void OSRenderer::drawBackground() { /*! \brief Draw one overlay * \param it Overlay info + * \todo Add handling of type 22 overlays */ void OSRenderer::renderOverlay(const Common::List::iterator &it) { int len; @@ -979,6 +980,9 @@ void OSRenderer::renderOverlay(const Common::List::iterator &it) { switch (it->type) { // color sprite case 0: + if (objectTable[it->objIdx].frame < 0) { + break; + } sprite = animDataTable + objectTable[it->objIdx].frame; len = sprite->_realWidth * sprite->_height; mask = new byte[len]; @@ -988,6 +992,13 @@ void OSRenderer::renderOverlay(const Common::List::iterator &it) { delete[] mask; break; + // bitmap + case 4: + if (objectTable[it->objIdx].frame >= 0) { + FWRenderer::renderOverlay(it); + } + break; + // masked background case 20: assert(it->objIdx < NUM_MAX_OBJECT); -- cgit v1.2.3 From dadb771cdcdba41c795053b5115f04109b8fd545 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 8 Jul 2008 10:29:35 +0000 Subject: Remove reference to kPlainSoundType svn-id: r32960 --- engines/scumm/imuse_digi/dimuse_track.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/imuse_digi/dimuse_track.h b/engines/scumm/imuse_digi/dimuse_track.h index 33147128cb..2d4c673cf6 100644 --- a/engines/scumm/imuse_digi/dimuse_track.h +++ b/engines/scumm/imuse_digi/dimuse_track.h @@ -85,13 +85,15 @@ struct Track { int getPan() const { return (pan != 64) ? 2 * pan - 127 : 0; } int getVol() const { return vol / 1000; } Audio::Mixer::SoundType getType() const { - Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType; + Audio::Mixer::SoundType type; if (volGroupId == 1) type = Audio::Mixer::kSpeechSoundType; else if (volGroupId == 2) type = Audio::Mixer::kSFXSoundType; else if (volGroupId == 3) type = Audio::Mixer::kMusicSoundType; + else + error("Track::getType(): invalid sound type"); return type; } }; -- cgit v1.2.3 From 03b36a3a544b7ae36e4528bc63039f7f3de475bb Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 8 Jul 2008 11:18:44 +0000 Subject: Shut couple of MSVC warnings svn-id: r32961 --- engines/m4/converse.cpp | 2 +- engines/m4/resource.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index a85fdea02f..5b8bdab9d6 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -380,7 +380,7 @@ void Converse::loadConversation(const char *convName) { uint32 size; uint32 chunk; uint32 data = 0; - uint32 i; + uint32 i = 0; ConvEntry* curEntry = NULL; ConvEntry* replyEntry = NULL; int32 currentWeightedEntry = -1; diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp index 57816b6600..074cab1095 100644 --- a/engines/m4/resource.cpp +++ b/engines/m4/resource.cpp @@ -310,7 +310,7 @@ const char *MADSResourceManager::getResourceFilename(const char *resourceName) { Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) { Common::File hagFile; - uint32 offset, size; + uint32 offset, size = 0; // If the first character is a '@' then look for an external file -- cgit v1.2.3 From 4a1cc7801661425c0e2eee527e886cd0f6b57263 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Tue, 8 Jul 2008 11:35:09 +0000 Subject: Modified the EGA story image delay to work for the Mac versions as well svn-id: r32962 --- engines/gob/inter.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 9c39653a1d..df9c1353a0 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -212,25 +212,35 @@ void Inter::funcBlock(int16 retFlag) { break; // WORKAROUND: - // The EGA version of gob1 doesn't add a delay after showing + // The EGA and Mac versions of gob1 doesn't add a delay after showing // images between levels. We manually add it here. - if ((_vm->getGameType() == kGameTypeGob1) && _vm->isEGA()) { + if ((_vm->getGameType() == kGameTypeGob1) && + (_vm->isEGA() || (_vm->getPlatform() == Common::kPlatformMacintosh))) { + int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData; - if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie + + if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA + !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || + (startaddr == 0x188D && addr == 0x1A58 && // Zombie, Mac !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || (startaddr == 0x1299 && addr == 0x139A && // Dungeon !strncmp(_vm->_game->_curTotFile, "avt006.tot", 10)) || - (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron + (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron, EGA + !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) || + (startaddr == 0x11C8 && addr == 0x1341 && // Cauldron, Mac !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) || (startaddr == 0x09F2 && addr == 0x0AF3 && // Statue !strncmp(_vm->_game->_curTotFile, "avt016.tot", 10)) || (startaddr == 0x0B92 && addr == 0x0C93 && // Castle !strncmp(_vm->_game->_curTotFile, "avt019.tot", 10)) || - (startaddr == 0x17D9 && addr == 0x18DA && // Finale + (startaddr == 0x17D9 && addr == 0x18DA && // Finale, EGA + !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10)) || + (startaddr == 0x17E9 && addr == 0x19A8 && // Finale, Mac !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10))) { _vm->_util->longDelay(5000); } + } // End of workaround cmd = *_vm->_global->_inter_execPtr; -- cgit v1.2.3 From da0495cd786b7e8a874024a657e062a49a665fba Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Tue, 8 Jul 2008 11:36:52 +0000 Subject: Added a Gob1 version supplied by raina in the forums. It does look like the Mac version with a DOS executable and stripped music to me, so let's hope the Mac level image workaround works there as well. svn-id: r32963 --- engines/gob/detection.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 8351f2ecfb..63a0f8f45b 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -277,6 +277,19 @@ static const GOBGameDescription gameDescriptions[] = { kFeaturesNone, "intro" }, + { // Supplied by raina in the forums + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), + EN_ANY, + kPlatformMacintosh, + Common::ADGF_NO_FLAGS + }, + kGameTypeGob1, + kFeaturesNone, + "intro" + }, { // Supplied by paul66 in bug report #1652352 { "gob1", -- cgit v1.2.3 From 8093dbaf49ae54aac783cdf996911c459aac5468 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 8 Jul 2008 11:48:16 +0000 Subject: One more MSVC warning svn-id: r32964 --- engines/m4/resource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp index 074cab1095..5070a2b79c 100644 --- a/engines/m4/resource.cpp +++ b/engines/m4/resource.cpp @@ -310,7 +310,7 @@ const char *MADSResourceManager::getResourceFilename(const char *resourceName) { Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) { Common::File hagFile; - uint32 offset, size = 0; + uint32 offset = 0, size = 0; // If the first character is a '@' then look for an external file -- cgit v1.2.3 From a294d222136a72534871d2030f828891762146ed Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Wed, 9 Jul 2008 02:49:20 +0000 Subject: Added a couple of NULLity checks. svn-id: r32972 --- engines/parallaction/gfxbase.cpp | 4 +++- engines/parallaction/sound.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 8d7041305d..3e9bd79e5d 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -133,7 +133,9 @@ void Gfx::showGfxObj(GfxObj* obj, bool visible) { // return; // } - assert(obj); + if (!obj) { + return; + } if (visible) { obj->setFlags(kGfxObjVisible); diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp index dd74e8f7aa..d9e78f3a9e 100644 --- a/engines/parallaction/sound.cpp +++ b/engines/parallaction/sound.cpp @@ -249,6 +249,9 @@ void DosSoundMan::stopMusic() { } void DosSoundMan::playCharacterMusic(const char *character) { + if (character == NULL) { + return; + } if (!scumm_stricmp(_vm->_location._name, "night") || !scumm_stricmp(_vm->_location._name, "intsushi")) { -- cgit v1.2.3 From 18b48c74a9de417254badf23744d5c5f73c2966c Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Wed, 9 Jul 2008 10:52:46 +0000 Subject: Fixed regression introduced with GfxObj: the character sprite was sometimes removed from the rendering list. svn-id: r32974 --- engines/parallaction/gfxbase.cpp | 25 ++++++++++++++----------- engines/parallaction/graphics.h | 9 ++++++--- engines/parallaction/parallaction.cpp | 12 +++++++++--- engines/parallaction/parallaction_br.cpp | 2 +- engines/parallaction/parallaction_ns.cpp | 3 +++ 5 files changed, 33 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 3e9bd79e5d..9e7eb12ed8 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -32,7 +32,7 @@ namespace Parallaction { -GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(0), _keep(true) { +GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(kGfxObjNormal), _keep(true) { if (name) { _name = strdup(name); } else { @@ -124,15 +124,22 @@ GfxObj* Gfx::loadDoor(const char *name) { return obj; } -void Gfx::clearGfxObjects() { - _gfxobjList.clear(); +void Gfx::clearGfxObjects(uint filter) { + + GfxObjList::iterator b = _gfxobjList.begin(); + GfxObjList::iterator e = _gfxobjList.end(); + + for ( ; b != e; ) { + if (((*b)->_flags & filter) != 0) { + b = _gfxobjList.erase(b); + } else { + b++; + } + } + } void Gfx::showGfxObj(GfxObj* obj, bool visible) { -// if (!obj || obj->isVisible() == visible) { -// return; -// } - if (!obj) { return; } @@ -141,9 +148,7 @@ void Gfx::showGfxObj(GfxObj* obj, bool visible) { obj->setFlags(kGfxObjVisible); } else { obj->clearFlags(kGfxObjVisible); -// _gfxobjList.remove(obj); } - } @@ -187,8 +192,6 @@ void Gfx::drawGfxObjects(Graphics::Surface &surf) { sortAnimations(); // TODO: some zones don't appear because of wrong masking (3 or 0?) - // TODO: Dr.Ki is not visible inside the club - GfxObjList::iterator b = _gfxobjList.begin(); GfxObjList::iterator e = _gfxobjList.end(); diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 00718d8c26..09f4b2f244 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -340,12 +340,15 @@ class Disk; enum { kGfxObjVisible = 1, + kGfxObjNormal = 2, + kGfxObjCharacter = 4, kGfxObjTypeDoor = 0, kGfxObjTypeGet = 1, kGfxObjTypeAnim = 2, kGfxObjTypeLabel = 3, - kGfxObjTypeBalloon = 4 + kGfxObjTypeBalloon = 4, + kGfxObjTypeCharacter = 8 }; enum { @@ -356,7 +359,6 @@ enum { class GfxObj { char *_name; Frames *_frames; - uint32 _flags; bool _keep; @@ -365,6 +367,7 @@ public: int32 z; + uint32 _flags; uint type; uint frame; @@ -478,7 +481,7 @@ public: GfxObj* loadDoor(const char *name); void drawGfxObjects(Graphics::Surface &surf); void showGfxObj(GfxObj* obj, bool visible); - void clearGfxObjects(); + void clearGfxObjects(uint filter); void sortAnimations(); diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 3a52b28e06..ca99d2a789 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -91,6 +91,8 @@ Parallaction::~Parallaction() { delete _globalTable; delete _callableNames; + _gfx->clearGfxObjects(kGfxObjCharacter | kGfxObjNormal); + hideDialogueStuff(); freeLocation(); freeCharacter(); @@ -166,6 +168,8 @@ void Parallaction::freeCharacter() { delete _objectsNames; _objectsNames = 0; + _gfx->clearGfxObjects(kGfxObjCharacter); + _char.free(); return; @@ -248,7 +252,7 @@ void Parallaction::freeLocation() { _location._walkNodes.clear(); - _gfx->clearGfxObjects(); + _gfx->clearGfxObjects(kGfxObjNormal); freeBackground(); _location._programs.clear(); @@ -569,10 +573,14 @@ void Character::setName(const char *name) { const char *end = begin + strlen(name); _prefix = _empty; + _suffix = _empty; _dummy = IS_DUMMY_CHARACTER(name); if (!_dummy) { + if (!strstr(name, "donna")) { + _engineFlags &= ~kEngineTransformedDonna; + } else if (_engineFlags & kEngineTransformedDonna) { _suffix = _suffixTras; } else { @@ -581,8 +589,6 @@ void Character::setName(const char *name) { _engineFlags |= kEngineTransformedDonna; _suffix = _suffixTras; end = s; - } else { - _suffix = _empty; } } if (IS_MINI_CHARACTER(name)) { diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index e7f08d0339..c382f6a7f6 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -224,7 +224,7 @@ void Parallaction_br::changeLocation(char *location) { // free open location stuff clearSubtitles(); freeBackground(); - _gfx->clearGfxObjects(); + _gfx->clearGfxObjects(kGfxObjNormal | kGfxObjCharacter); _location._programs.clear(); freeZones(); freeAnimations(); diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index af848aa6af..a2217e4a73 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -306,6 +306,7 @@ void Parallaction_ns::changeLocation(char *location) { setArrowCursor(); } + _gfx->showGfxObj(_char._ani->gfxobj, false); _location._animations.remove(_char._ani); freeLocation(); @@ -327,6 +328,7 @@ void Parallaction_ns::changeLocation(char *location) { } _location._animations.push_front(_char._ani); + _gfx->showGfxObj(_char._ani->gfxobj, true); strcpy(_saveData1, locname.location()); parseLocation(_saveData1); @@ -411,6 +413,7 @@ void Parallaction_ns::changeCharacter(const char *name) { Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1"); _char._ani->gfxobj = _gfx->loadAnim(_char.getFullName()); + _char._ani->gfxobj->setFlags(kGfxObjCharacter); if (!_char.dummy()) { if (getPlatform() == Common::kPlatformAmiga) { -- cgit v1.2.3 From 12cefc4132ddb06ce56efd813c88f50d5e8b19ed Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Wed, 9 Jul 2008 13:27:09 +0000 Subject: Fixed leaks in NS and BRA. svn-id: r32976 --- engines/parallaction/graphics.cpp | 1 + engines/parallaction/objects.cpp | 3 +++ engines/parallaction/parallaction.cpp | 1 + 3 files changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 93ebdd3a65..32d0e303eb 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -767,6 +767,7 @@ Gfx::Gfx(Parallaction* vm) : Gfx::~Gfx() { freeBackground(); + freeLabels(); return; } diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 54afabc318..66025cf0f7 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -54,6 +54,7 @@ Animation::Animation() { Animation::~Animation() { free(_scriptName); + gfxobj->release(); } uint16 Animation::width() const { @@ -182,6 +183,8 @@ Zone::~Zone() { break; } + + free(_linkedName); } void Zone::getRect(Common::Rect& r) const { diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index ca99d2a789..b2146bd292 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -93,6 +93,7 @@ Parallaction::~Parallaction() { _gfx->clearGfxObjects(kGfxObjCharacter | kGfxObjNormal); hideDialogueStuff(); + delete _balloonMan; freeLocation(); freeCharacter(); -- cgit v1.2.3 From 03cd937b13d5629f84f52b05c6374e5a3373be15 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Thu, 10 Jul 2008 02:00:54 +0000 Subject: Fixed destruction of sprites in BRA. svn-id: r32983 --- engines/parallaction/disk_br.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 543ed14146..4068cbc202 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -58,7 +58,7 @@ struct Sprites : public Frames { } ~Sprites() { - delete _sprites; + delete[] _sprites; } uint16 getNum() { -- cgit v1.2.3 From 092d9f38c5080da66b4edc2ec52a204448ab9a4f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Jul 2008 11:25:43 +0000 Subject: Workaround for gcc 2.95 compiler bug. svn-id: r32986 --- engines/kyra/script_tim.cpp | 10 ++++++---- engines/kyra/script_tim.h | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 6b82ba06de..8725f6def9 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -34,6 +34,7 @@ namespace Kyra { TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _system(system), _currentTim(0) { #define COMMAND(x) { &TIMInterpreter::x, #x } #define COMMAND_UNIMPL() { 0, 0 } +#define cmd_return(n) cmd_return_##n static const CommandEntry commandProcs[] = { // 0x00 COMMAND(cmd_initFunc0), @@ -66,15 +67,16 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _s COMMAND_UNIMPL(), COMMAND(cmd_resetAllRuntimes), // 0x18 - COMMAND(cmd_return<1>), + COMMAND(cmd_return(1)), COMMAND(cmd_execOpcode), COMMAND(cmd_initFuncNow), COMMAND(cmd_stopFuncNow), // 0x1C - COMMAND(cmd_return<1>), - COMMAND(cmd_return<1>), - COMMAND(cmd_return<-1>) + COMMAND(cmd_return(1)), + COMMAND(cmd_return(1)), + COMMAND(cmd_return(n1)) }; +#undef cmd_return _commands = commandProcs; _commandsSize = ARRAYSIZE(commandProcs); diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index cd715ff4ef..f171823444 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -102,8 +102,12 @@ private: int cmd_execOpcode(const uint16 *param); int cmd_initFuncNow(const uint16 *param); int cmd_stopFuncNow(const uint16 *param); - template - int cmd_return(const uint16 *) { return T; } +#define cmd_return(n, v) \ + int cmd_return_##n(const uint16 *) { return v; } + + cmd_return( 1, 1); + cmd_return(n1, -1); +#undef cmd_return }; } // end of namespace Kyra -- cgit v1.2.3 From 9a34ef702de478611718bc94b4d1bcfc6a922613 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Jul 2008 11:28:51 +0000 Subject: Fixed mem leak in MIDI related code. svn-id: r32987 --- engines/kyra/sound.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index c768255272..5068268d99 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -243,8 +243,10 @@ int SoundMidiPC::open() { } void SoundMidiPC::close() { - if (_driver) + if (_driver) { _driver->close(); + delete _driver; + } _driver = 0; } -- cgit v1.2.3 From e1e95f0c0edf58553af5f31d33f46f5eb864d168 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Jul 2008 12:05:38 +0000 Subject: Added filename to unknown opcode/command warnings of EMC scripts. svn-id: r32988 --- engines/kyra/script.cpp | 6 ++++-- engines/kyra/script.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index a29cdc8ca3..b10a4b32bf 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -132,6 +132,8 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo scriptData->opcodes = opcodes; + strncpy(scriptData->filename, filename, 13); + return true; } @@ -205,7 +207,7 @@ bool EMCInterpreter::run(EMCState *script) { } if (opcode > 18) { - error("Script unknown command: %d", opcode); + error("Script unknown command: %d in file '%s' at offset 0x%.08X", opcode, script->dataPtr->filename, instOffset); } else { debugC(5, kDebugLevelScript, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset, _commands[opcode].desc, _parameter, (uint)_parameter); (this->*(_commands[opcode].proc))(script); @@ -388,7 +390,7 @@ void EMCInterpreter::cmd_execOpcode(EMCState* script) { script->retValue = (*(*script->dataPtr->opcodes)[opcode])(script); } else { script->retValue = 0; - warning("calling unimplemented opcode(0x%.02X/%d)", opcode, opcode); + warning("Calling unimplemented opcode(0x%.02X/%d) from file '%s'", opcode, opcode, script->dataPtr->filename); } } diff --git a/engines/kyra/script.h b/engines/kyra/script.h index de52093f66..2b97a83289 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -36,6 +36,8 @@ struct EMCState; typedef Common::Functor1 Opcode; struct EMCData { + char filename[13]; + byte *text; uint16 *data; uint16 *ordr; -- cgit v1.2.3 From a117024d23c3d43ee0ced9046fdbf8e866ddc135 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Jul 2008 12:12:42 +0000 Subject: Added filename to unkown command/opcode warnings for TIM scripts. svn-id: r32989 --- engines/kyra/script_tim.cpp | 8 +++++--- engines/kyra/script_tim.h | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 8725f6def9..8ea316f159 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -124,6 +124,8 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Arrayfunc[i].avtl = tim->avtl + tim->avtl[i]; + strncpy(tim->filename, filename, 13); + return tim; } @@ -201,12 +203,12 @@ void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) { int TIMInterpreter::execCommand(int cmd, const uint16 *param) { if (cmd < 0 || cmd >= _commandsSize) { - warning("Calling unimplemented TIM command %d", cmd); + warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename); return 0; } if (_commands[cmd].proc == 0) { - warning("Calling unimplemented TIM command %d", cmd); + warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename); return 0; } @@ -261,7 +263,7 @@ int TIMInterpreter::cmd_execOpcode(const uint16 *param) { uint16 opcode = *param++; if (opcode > _currentTim->opcodes->size()) { - warning("Calling unimplemented TIM opcode(0x%.02X/%d)", opcode, opcode); + warning("Calling unimplemented TIM opcode(0x%.02X/%d) form file '%s'", opcode, opcode, _currentTim->filename); return 0; } diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index f171823444..39a1d90a44 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -37,6 +37,8 @@ struct TIM; typedef Common::Functor2 TIMOpcode; struct TIM { + char filename[13]; + int16 procFunc; uint16 procParam; -- cgit v1.2.3 From 985a032871e3296daa2c9cedb4cfabfa9036137d Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Jul 2008 12:14:00 +0000 Subject: Typo. svn-id: r32990 --- engines/kyra/script_tim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 8ea316f159..4b82232049 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -263,7 +263,7 @@ int TIMInterpreter::cmd_execOpcode(const uint16 *param) { uint16 opcode = *param++; if (opcode > _currentTim->opcodes->size()) { - warning("Calling unimplemented TIM opcode(0x%.02X/%d) form file '%s'", opcode, opcode, _currentTim->filename); + warning("Calling unimplemented TIM opcode(0x%.02X/%d) from file '%s'", opcode, opcode, _currentTim->filename); return 0; } -- cgit v1.2.3 From c8488c060cea860d02fdf59221408f7974a80eab Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 10 Jul 2008 16:19:17 +0000 Subject: Fixed Kyra 3 detection regression. svn-id: r32992 --- engines/kyra/detection.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 0c8acb59b7..fce1e93bc2 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -527,7 +527,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_INS_FLAGS + KYRA3_CD_FLAGS }, { { @@ -542,7 +542,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_INS_FLAGS + KYRA3_CD_FLAGS }, { { @@ -557,7 +557,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_INS_FLAGS + KYRA3_CD_FLAGS }, // installed version @@ -574,7 +574,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_FLAGS + KYRA3_CD_INS_FLAGS }, { { @@ -589,7 +589,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_FLAGS + KYRA3_CD_INS_FLAGS }, { { @@ -604,7 +604,7 @@ const KYRAGameDescription adGameDescs[] = { Common::kPlatformPC, Common::ADGF_DROPLANGUAGE }, - KYRA3_CD_FLAGS + KYRA3_CD_INS_FLAGS }, // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" -- cgit v1.2.3 From f41ab55021c98e2ae1aee77fa0c1dd45e0475023 Mon Sep 17 00:00:00 2001 From: Bertrand Augereau Date: Thu, 10 Jul 2008 18:01:54 +0000 Subject: Fixed a few warnings svn-id: r32994 --- engines/scumm/detection.cpp | 2 +- engines/scumm/he/resource_he.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 9359c6610c..753ad45212 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -492,7 +492,7 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com // Note that GF_OLD_BUNDLE is true if and only if GF_OLD256 is false. // Candidates: maniac enhanced, zak enhanced, indy3ega, loom - if (g->version != 2 && g->version != 3 || (g->features & GF_OLD256)) + if ((g->version != 2 && g->version != 3) || (g->features & GF_OLD256)) return false; /* We distinguish the games by the presence/absence of diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 33e6748860..f8fb1efca2 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -522,12 +522,13 @@ int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base, /* get a list of all resources at this level */ wr = list_resources(fi, base, &rescnt); - if (wr == NULL) + if (wr == NULL) { if (size != 0) return size; else return 0; - + } + /* process each resource listed */ for (c = 0 ; c < rescnt ; c++) { /* (over)write the corresponding WinResource holder with the current */ -- cgit v1.2.3 From fe655836575214c33c82120e9dd714b95a96e475 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Fri, 11 Jul 2008 12:55:08 +0000 Subject: Fixed leak in sound code by explicitly deleting the midi driver. svn-id: r33002 --- engines/parallaction/sound.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp index d9e78f3a9e..df6867a90c 100644 --- a/engines/parallaction/sound.cpp +++ b/engines/parallaction/sound.cpp @@ -175,6 +175,7 @@ void MidiPlayer::close() { _mutex.lock(); _driver->setTimerCallback(NULL, NULL); _driver->close(); + delete _driver; _driver = 0; _parser->setMidiDriver(NULL); delete _parser; -- cgit v1.2.3 From 8ed023142a9ce0ee825eb3d6c33759281d68357b Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Fri, 11 Jul 2008 13:06:28 +0000 Subject: Moved program and command execution code out of the engine, into their own brand new classes. svn-id: r33003 --- engines/parallaction/dialogue.cpp | 2 +- engines/parallaction/disk_br.cpp | 9 +- engines/parallaction/exec.h | 237 +++++++++++++++++++++++++++++++ engines/parallaction/exec_br.cpp | 100 +++++++------ engines/parallaction/exec_ns.cpp | 125 +++++++++------- engines/parallaction/input.cpp | 2 +- engines/parallaction/parallaction.cpp | 13 +- engines/parallaction/parallaction.h | 137 ++---------------- engines/parallaction/parallaction_br.cpp | 20 ++- engines/parallaction/parallaction_ns.cpp | 10 +- engines/parallaction/walk.cpp | 6 +- 11 files changed, 419 insertions(+), 242 deletions(-) create mode 100644 engines/parallaction/exec.h (limited to 'engines') diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 1dc4fd5ab3..6e91dd8a88 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -249,7 +249,7 @@ void DialogueManager::run() { } if (cmdlist) - _vm->runCommands(*cmdlist); + _vm->_cmdExec->run(*cmdlist); } diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 4068cbc202..ee1e111139 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -287,9 +287,12 @@ Frames* DosDisk_br::loadFrames(const char* name) { sprintf(path, "%s/ani/%s", _partPath, name); Common::File stream; - if (!stream.open(path)) - errorFileNotFound(path); - + if (!stream.open(path)) { + sprintf(path, "%s/ani/%s.ani", _partPath, name); + if (!stream.open(path)) { + errorFileNotFound(path); + } + } return createSprites(stream); } diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h new file mode 100644 index 0000000000..ca359c2a8e --- /dev/null +++ b/engines/parallaction/exec.h @@ -0,0 +1,237 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + + +#ifndef PARALLACTION_EXEC_H +#define PARALLACTION_EXEC_H + +#include "common/util.h" +#include "parallaction/objects.h" + + +namespace Parallaction { + +typedef Common::Functor0 Opcode; +typedef Common::Array OpcodeSet; + +#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op() +#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op() + +class Parallaction_ns; +class Parallaction_br; + +class CommandExec { +protected: + struct ParallactionStruct1 { + CommandPtr cmd; + ZonePtr z; + } _cmdRunCtxt; + + OpcodeSet _opcodes; + +public: + virtual void init() = 0; + virtual void run(CommandList &list, ZonePtr z = nullZonePtr); + CommandExec() { + } + virtual ~CommandExec() { + for (Common::Array::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i) + delete *i; + _opcodes.clear(); + } +}; + +class CommandExec_ns : public CommandExec { + + Parallaction_ns *_vm; + +protected: + DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(set); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(start); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(get); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(location); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(open); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(close); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(on); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(off); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(call); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(move); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop); + +public: + void init(); + + CommandExec_ns(Parallaction_ns* vm); + ~CommandExec_ns(); +}; + +class CommandExec_br : public CommandExec_ns { + +protected: + Parallaction_br *_vm; + + DECLARE_UNQUALIFIED_COMMAND_OPCODE(location); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(open); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(close); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(on); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(off); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(call); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(move); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(start); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(character); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(add); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(let); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(music); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(give); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(text); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(part); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave); + +public: + void init(); + + CommandExec_br(Parallaction_br* vm); + ~CommandExec_br(); +}; + + + + + +class ProgramExec { +protected: + struct ParallactionStruct2 { + AnimationPtr anim; + ProgramPtr program; + InstructionList::iterator inst; + uint16 modCounter; + bool suspend; + } _instRunCtxt; + + OpcodeSet _opcodes; + +public: + virtual void init() = 0; + virtual void runScripts(ProgramList::iterator first, ProgramList::iterator last); + ProgramExec() { + } + virtual ~ProgramExec() { + for (Common::Array::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i) + delete *i; + _opcodes.clear(); + } +}; + +class ProgramExec_ns : public ProgramExec { + + Parallaction_ns *_vm; + +protected: + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript); + +public: + void init(); + + ProgramExec_ns(Parallaction_ns *vm); + ~ProgramExec_ns(); +}; + +class ProgramExec_br : public ProgramExec_ns { + + Parallaction_br *_vm; + +protected: + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop); + DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript); + +public: + void init(); + ProgramExec_br(Parallaction_br *vm); + ~ProgramExec_br(); +}; + +} // namespace Parallaction + +#endif diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index 734360167b..eca01ea06a 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -23,6 +23,7 @@ * */ +#include "parallaction/exec.h" #include "parallaction/input.h" #include "parallaction/parallaction.h" @@ -64,12 +65,13 @@ namespace Parallaction { #define SetOpcodeTable(x) table = &x; -typedef Common::Functor0Mem OpcodeV2; -#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::cmdOp_##op)) -#define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op() +typedef Common::Functor0Mem OpcodeV1; +#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_br::cmdOp_##op)) +#define DECLARE_COMMAND_OPCODE(op) void CommandExec_br::cmdOp_##op() -#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::instOp_##op)) -#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op() +typedef Common::Functor0Mem OpcodeV2; +#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_br::instOp_##op)) +#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_br::instOp_##op() void Parallaction_br::setupSubtitles(char *s, char *s2, int y) { debugC(5, kDebugExec, "setupSubtitles(%s, %s, %i)", s, s2, y); @@ -114,7 +116,7 @@ DECLARE_COMMAND_OPCODE(location) { warning("Parallaction_br::cmdOp_location command not yet implemented"); // TODO: handle startPos and startPos2 - scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); + _vm->scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); } @@ -137,7 +139,7 @@ DECLARE_COMMAND_OPCODE(on) { z->_flags &= ~kFlagsRemove; if ((z->_type & 0xFFFF) & kZoneGet) { - _gfx->showGfxObj(z->u.get->gfxobj, true); + _vm->_gfx->showGfxObj(z->u.get->gfxobj, true); } } } @@ -151,14 +153,14 @@ DECLARE_COMMAND_OPCODE(off) { z->_flags |= kFlagsRemove; if ((z->_type & 0xFFFF) & kZoneGet) { - _gfx->showGfxObj(z->u.get->gfxobj, false); + _vm->_gfx->showGfxObj(z->u.get->gfxobj, false); } } } DECLARE_COMMAND_OPCODE(call) { - callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); + _vm->callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); } @@ -182,7 +184,7 @@ DECLARE_COMMAND_OPCODE(stop) { DECLARE_COMMAND_OPCODE(character) { debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _cmdRunCtxt.cmd->u._string); - changeCharacter(_cmdRunCtxt.cmd->u._string); + _vm->changeCharacter(_cmdRunCtxt.cmd->u._string); } @@ -192,12 +194,12 @@ DECLARE_COMMAND_OPCODE(followme) { DECLARE_COMMAND_OPCODE(onmouse) { - _input->showCursor(true); + _vm->_input->showCursor(true); } DECLARE_COMMAND_OPCODE(offmouse) { - _input->showCursor(false); + _vm->_input->showCursor(false); } @@ -212,42 +214,42 @@ DECLARE_COMMAND_OPCODE(leave) { DECLARE_COMMAND_OPCODE(inc) { - _counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue; } DECLARE_COMMAND_OPCODE(dec) { - _counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue; } DECLARE_COMMAND_OPCODE(ifeq) { - if (_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) { - setLocationFlags(kFlagsTestTrue); + if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) { + _vm->setLocationFlags(kFlagsTestTrue); } else { - clearLocationFlags(kFlagsTestTrue); + _vm->clearLocationFlags(kFlagsTestTrue); } } DECLARE_COMMAND_OPCODE(iflt) { - if (_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) { - setLocationFlags(kFlagsTestTrue); + if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) { + _vm->setLocationFlags(kFlagsTestTrue); } else { - clearLocationFlags(kFlagsTestTrue); + _vm->clearLocationFlags(kFlagsTestTrue); } } DECLARE_COMMAND_OPCODE(ifgt) { - if (_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) { - setLocationFlags(kFlagsTestTrue); + if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) { + _vm->setLocationFlags(kFlagsTestTrue); } else { - clearLocationFlags(kFlagsTestTrue); + _vm->clearLocationFlags(kFlagsTestTrue); } } DECLARE_COMMAND_OPCODE(let) { - _counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue; } @@ -267,15 +269,15 @@ DECLARE_COMMAND_OPCODE(unfix) { DECLARE_COMMAND_OPCODE(zeta) { - _location._zeta0 = _cmdRunCtxt.cmd->u._zeta0; - _location._zeta1 = _cmdRunCtxt.cmd->u._zeta1; - _location._zeta2 = _cmdRunCtxt.cmd->u._zeta2; + _vm->_location._zeta0 = _cmdRunCtxt.cmd->u._zeta0; + _vm->_location._zeta1 = _cmdRunCtxt.cmd->u._zeta1; + _vm->_location._zeta2 = _cmdRunCtxt.cmd->u._zeta2; } DECLARE_COMMAND_OPCODE(scroll) { warning("Parallaction_br::cmdOp_scroll not yet implemented"); - _gfx->setVar("scroll_x", _cmdRunCtxt.cmd->u._rvalue ); + _vm->_gfx->setVar("scroll_x", _cmdRunCtxt.cmd->u._rvalue ); } @@ -291,7 +293,7 @@ DECLARE_COMMAND_OPCODE(give) { DECLARE_COMMAND_OPCODE(text) { CommandData *data = &_cmdRunCtxt.cmd->u; - setupSubtitles(data->_string, data->_string2, data->_zeta0); + _vm->setupSubtitles(data->_string, data->_string2, data->_zeta0); } @@ -302,7 +304,7 @@ DECLARE_COMMAND_OPCODE(part) { DECLARE_COMMAND_OPCODE(testsfx) { warning("Parallaction_br::cmdOp_testsfx not completely implemented"); - clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled + _vm->clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled } @@ -332,7 +334,7 @@ DECLARE_INSTRUCTION_OPCODE(on) { z->_flags &= ~kFlagsRemove; if ((z->_type & 0xFFFF) & kZoneGet) { - _gfx->showGfxObj(z->u.get->gfxobj, true); + _vm->_gfx->showGfxObj(z->u.get->gfxobj, true); } } } @@ -346,7 +348,7 @@ DECLARE_INSTRUCTION_OPCODE(off) { z->_flags |= kFlagsRemove; if ((z->_type & 0xFFFF) & kZoneGet) { - _gfx->showGfxObj(z->u.get->gfxobj, false); + _vm->_gfx->showGfxObj(z->u.get->gfxobj, false); } } } @@ -430,7 +432,7 @@ DECLARE_INSTRUCTION_OPCODE(start) { DECLARE_INSTRUCTION_OPCODE(process) { - _activeZone2 = (*_instRunCtxt.inst)->_z; + _vm->_activeZone2 = (*_instRunCtxt.inst)->_z; } @@ -444,7 +446,7 @@ DECLARE_INSTRUCTION_OPCODE(color) { int16 entry = inst->_opB.getRValue(); - _gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]); + _vm->_gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]); } @@ -465,7 +467,7 @@ DECLARE_INSTRUCTION_OPCODE(print) { DECLARE_INSTRUCTION_OPCODE(text) { InstructionPtr inst = (*_instRunCtxt.inst); - setupSubtitles(inst->_text, inst->_text2, inst->_y); + _vm->setupSubtitles(inst->_text, inst->_text2, inst->_y); } @@ -496,7 +498,7 @@ DECLARE_INSTRUCTION_OPCODE(stop) { DECLARE_INSTRUCTION_OPCODE(endscript) { if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) { _instRunCtxt.anim->_flags &= ~kFlagsActing; - runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim); + _vm->_cmdExec->run(_instRunCtxt.anim->_commands, _instRunCtxt.anim); _instRunCtxt.program->_status = kProgramDone; } _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin(); @@ -504,11 +506,10 @@ DECLARE_INSTRUCTION_OPCODE(endscript) { _instRunCtxt.suspend = true; } -void Parallaction_br::initOpcodes() { - +void CommandExec_br::init() { Common::Array *table = 0; - SetOpcodeTable(_commandOpcodes); + SetOpcodeTable(_opcodes); COMMAND_OPCODE(invalid); COMMAND_OPCODE(set); COMMAND_OPCODE(clear); @@ -551,8 +552,21 @@ void Parallaction_br::initOpcodes() { COMMAND_OPCODE(ret); COMMAND_OPCODE(onsave); COMMAND_OPCODE(offsave); +} + +CommandExec_br::CommandExec_br(Parallaction_br* vm) : CommandExec_ns(vm), _vm(vm) { + +} + +CommandExec_br::~CommandExec_br() { + +} - SetOpcodeTable(_instructionOpcodes); +void ProgramExec_br::init() { + + Common::Array *table = 0; + + SetOpcodeTable(_opcodes); INSTRUCTION_OPCODE(invalid); INSTRUCTION_OPCODE(on); INSTRUCTION_OPCODE(off); @@ -587,6 +601,12 @@ void Parallaction_br::initOpcodes() { INSTRUCTION_OPCODE(endscript); } +ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : ProgramExec_ns(vm), _vm(vm) { +} + +ProgramExec_br::~ProgramExec_br() { +} + #if 0 void Parallaction_br::jobWaitRemoveLabelJob(void *parm, Job *job) { diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index abad9f273b..1250d276f6 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -23,6 +23,7 @@ * */ +#include "parallaction/exec.h" #include "parallaction/input.h" #include "parallaction/parallaction.h" #include "parallaction/sound.h" @@ -52,12 +53,13 @@ namespace Parallaction { #define SetOpcodeTable(x) table = &x; -typedef Common::Functor0Mem OpcodeV2; -#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::cmdOp_##op)) -#define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op() +typedef Common::Functor0Mem OpcodeV1; +#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_ns::cmdOp_##op)) +#define DECLARE_COMMAND_OPCODE(op) void CommandExec_ns::cmdOp_##op() -#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::instOp_##op)) -#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op() +typedef Common::Functor0Mem OpcodeV2; +#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_ns::instOp_##op)) +#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_ns::instOp_##op() @@ -137,7 +139,7 @@ DECLARE_INSTRUCTION_OPCODE(put) { int16 y = inst->_opB.getRValue(); bool mask = (inst->_flags & kInstMaskedPut) == kInstMaskedPut; - _gfx->patchBackground(v18, x, y, mask); + _vm->_gfx->patchBackground(v18, x, y, mask); } DECLARE_INSTRUCTION_OPCODE(null) { @@ -149,7 +151,7 @@ DECLARE_INSTRUCTION_OPCODE(invalid) { } DECLARE_INSTRUCTION_OPCODE(call) { - callFunction((*_instRunCtxt.inst)->_immediate, 0); + _vm->callFunction((*_instRunCtxt.inst)->_immediate, 0); } @@ -165,7 +167,7 @@ DECLARE_INSTRUCTION_OPCODE(start) { DECLARE_INSTRUCTION_OPCODE(sound) { - _activeZone = (*_instRunCtxt.inst)->_z; + _vm->_activeZone = (*_instRunCtxt.inst)->_z; } @@ -175,13 +177,13 @@ DECLARE_INSTRUCTION_OPCODE(move) { int16 x = inst->_opA.getRValue(); int16 y = inst->_opB.getRValue(); - _char.scheduleWalk(x, y); + _vm->_char.scheduleWalk(x, y); } DECLARE_INSTRUCTION_OPCODE(endscript) { if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) { _instRunCtxt.anim->_flags &= ~kFlagsActing; - runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim); + _vm->_cmdExec->run(_instRunCtxt.anim->_commands, _instRunCtxt.anim); _instRunCtxt.program->_status = kProgramDone; } _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin(); @@ -201,7 +203,7 @@ DECLARE_COMMAND_OPCODE(set) { _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; _commandFlags |= _cmdRunCtxt.cmd->u._flags; } else { - setLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->setLocationFlags(_cmdRunCtxt.cmd->u._flags); } } @@ -211,7 +213,7 @@ DECLARE_COMMAND_OPCODE(clear) { _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; _commandFlags &= ~_cmdRunCtxt.cmd->u._flags; } else { - clearLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->clearLocationFlags(_cmdRunCtxt.cmd->u._flags); } } @@ -222,25 +224,25 @@ DECLARE_COMMAND_OPCODE(start) { DECLARE_COMMAND_OPCODE(speak) { - _activeZone = _cmdRunCtxt.cmd->u._zone; + _vm->_activeZone = _cmdRunCtxt.cmd->u._zone; } DECLARE_COMMAND_OPCODE(get) { _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed; - runZone(_cmdRunCtxt.cmd->u._zone); + _vm->runZone(_cmdRunCtxt.cmd->u._zone); } DECLARE_COMMAND_OPCODE(location) { - scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); + _vm->scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); } DECLARE_COMMAND_OPCODE(open) { _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed; if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) { - updateDoor(_cmdRunCtxt.cmd->u._zone); + _vm->updateDoor(_cmdRunCtxt.cmd->u._zone); } } @@ -248,7 +250,7 @@ DECLARE_COMMAND_OPCODE(open) { DECLARE_COMMAND_OPCODE(close) { _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed; if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) { - updateDoor(_cmdRunCtxt.cmd->u._zone); + _vm->updateDoor(_cmdRunCtxt.cmd->u._zone); } } @@ -265,7 +267,7 @@ DECLARE_COMMAND_OPCODE(on) { z->_flags &= ~kFlagsRemove; z->_flags |= kFlagsActive; if ((z->_type & 0xFFFF) == kZoneGet) { - _gfx->showGfxObj(z->u.get->gfxobj, true); + _vm->_gfx->showGfxObj(z->u.get->gfxobj, true); } } } @@ -277,7 +279,7 @@ DECLARE_COMMAND_OPCODE(off) { DECLARE_COMMAND_OPCODE(call) { - callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); + _vm->callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); } @@ -286,13 +288,13 @@ DECLARE_COMMAND_OPCODE(toggle) { _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; _commandFlags ^= _cmdRunCtxt.cmd->u._flags; } else { - toggleLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->toggleLocationFlags(_cmdRunCtxt.cmd->u._flags); } } DECLARE_COMMAND_OPCODE(drop){ - dropItem( _cmdRunCtxt.cmd->u._object ); + _vm->dropItem( _cmdRunCtxt.cmd->u._object ); } @@ -302,7 +304,7 @@ DECLARE_COMMAND_OPCODE(quit) { DECLARE_COMMAND_OPCODE(move) { - _char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y); + _vm->_char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y); } @@ -356,7 +358,7 @@ void Parallaction_ns::drawAnimations() { } -void Parallaction_ns::runScripts() { +void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator last) { if (_engineFlags & kEnginePauseJobs) { return; } @@ -365,7 +367,7 @@ void Parallaction_ns::runScripts() { static uint16 modCounter = 0; - for (ProgramList::iterator it = _location._programs.begin(); it != _location._programs.end(); it++) { + for (ProgramList::iterator it = first; it != last; it++) { AnimationPtr a = (*it)->_anim; @@ -388,7 +390,7 @@ void Parallaction_ns::runScripts() { _instRunCtxt.modCounter = modCounter; _instRunCtxt.suspend = false; - (*_instructionOpcodes[(*inst)->_index])(); + (*_opcodes[(*inst)->_index])(); inst = _instRunCtxt.inst; // handles endloop correctly @@ -405,17 +407,13 @@ label1: a->_z = a->_top + a->height(); } - _char._ani->_z = _char._ani->height() + _char._ani->_top; - if (_char._ani->gfxobj) { - _char._ani->gfxobj->z = _char._ani->_z; - } modCounter++; return; } -void Parallaction::runCommands(CommandList& list, ZonePtr z) { +void CommandExec::run(CommandList& list, ZonePtr z) { if (list.size() == 0) return; @@ -425,7 +423,7 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) { for ( ; it != list.end(); it++) { CommandPtr cmd = *it; - uint32 v8 = getLocationFlags(); + uint32 v8 = _vm->getLocationFlags(); if (_engineFlags & kEngineQuit) break; @@ -434,15 +432,15 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) { v8 = _commandFlags | kFlagsGlobal; } + debugC(3, kDebugExec, "runCommands[%i] (on: %x, off: %x)", cmd->_id, cmd->_flagsOn, cmd->_flagsOff); + if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue; if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue; -// debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff); - _cmdRunCtxt.z = z; _cmdRunCtxt.cmd = cmd; - (*_commandOpcodes[cmd->_id])(); + (*_opcodes[cmd->_id])(); } debugC(3, kDebugExec, "runCommands completed"); @@ -451,6 +449,13 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) { } +CommandExec_ns::CommandExec_ns(Parallaction_ns* vm) : _vm(vm) { + +} + +CommandExec_ns::~CommandExec_ns() { + +} // // ZONE TYPE: EXAMINE @@ -527,7 +532,7 @@ uint16 Parallaction::runZone(ZonePtr z) { debugC(3, kDebugExec, "runZone completed"); - runCommands(z->_commands, z); + _cmdExec->run(z->_commands, z); return 0; } @@ -654,11 +659,34 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) { } -void Parallaction_ns::initOpcodes() { +void CommandExec_ns::init() { + Common::Array *table = 0; + + SetOpcodeTable(_opcodes); + COMMAND_OPCODE(invalid); + COMMAND_OPCODE(set); + COMMAND_OPCODE(clear); + COMMAND_OPCODE(start); + COMMAND_OPCODE(speak); + COMMAND_OPCODE(get); + COMMAND_OPCODE(location); + COMMAND_OPCODE(open); + COMMAND_OPCODE(close); + COMMAND_OPCODE(on); + COMMAND_OPCODE(off); + COMMAND_OPCODE(call); + COMMAND_OPCODE(toggle); + COMMAND_OPCODE(drop); + COMMAND_OPCODE(quit); + COMMAND_OPCODE(move); + COMMAND_OPCODE(stop); +} + +void ProgramExec_ns::init() { Common::Array *table = 0; - SetOpcodeTable(_instructionOpcodes); + SetOpcodeTable(_opcodes); INSTRUCTION_OPCODE(invalid); INSTRUCTION_OPCODE(on); INSTRUCTION_OPCODE(off); @@ -680,25 +708,12 @@ void Parallaction_ns::initOpcodes() { INSTRUCTION_OPCODE(move); INSTRUCTION_OPCODE(endscript); - SetOpcodeTable(_commandOpcodes); - COMMAND_OPCODE(invalid); - COMMAND_OPCODE(set); - COMMAND_OPCODE(clear); - COMMAND_OPCODE(start); - COMMAND_OPCODE(speak); - COMMAND_OPCODE(get); - COMMAND_OPCODE(location); - COMMAND_OPCODE(open); - COMMAND_OPCODE(close); - COMMAND_OPCODE(on); - COMMAND_OPCODE(off); - COMMAND_OPCODE(call); - COMMAND_OPCODE(toggle); - COMMAND_OPCODE(drop); - COMMAND_OPCODE(quit); - COMMAND_OPCODE(move); - COMMAND_OPCODE(stop); } +ProgramExec_ns::ProgramExec_ns(Parallaction_ns *vm) : _vm(vm) { + } + +ProgramExec_ns::~ProgramExec_ns() { +} } // namespace Parallaction diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index 65acbcfe58..3797158661 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -302,7 +302,7 @@ bool Input::translateInventoryInput() { _vm->dropItem(z->u.merge->_obj1); _vm->dropItem(z->u.merge->_obj2); _vm->addInventoryItem(z->u.merge->_obj3); - _vm->runCommands(z->_commands); + _vm->_cmdExec->run(z->_commands); } return true; diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index b2146bd292..295f10820f 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -84,12 +84,11 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam Parallaction::~Parallaction() { - clearSet(_commandOpcodes); - clearSet(_instructionOpcodes); - delete _debugger; delete _globalTable; delete _callableNames; + delete _cmdExec; + delete _programExec; _gfx->clearGfxObjects(kGfxObjCharacter | kGfxObjNormal); hideDialogueStuff(); @@ -386,7 +385,11 @@ void Parallaction::runGame() { _gfx->beginFrame(); if (_input->_inputMode == Input::kInputModeGame) { - runScripts(); + _programExec->runScripts(_location._programs.begin(), _location._programs.end()); + _char._ani->_z = _char._ani->height() + _char._ani->_top; + if (_char._ani->gfxobj) { + _char._ani->gfxobj->z = _char._ani->_z; + } walk(); drawAnimations(); } @@ -422,7 +425,7 @@ void Parallaction::doLocationEnterTransition() { pal.makeGrayscale(); _gfx->setPalette(pal); - runScripts(); + _programExec->runScripts(_location._programs.begin(), _location._programs.end()); drawAnimations(); _gfx->updateScreen(); diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index c095cab667..13c56cf57b 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -33,6 +33,7 @@ #include "engines/engine.h" +#include "parallaction/exec.h" #include "parallaction/input.h" #include "parallaction/inventory.h" #include "parallaction/parser.h" @@ -238,10 +239,6 @@ public: -#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op() -#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op() - - #define NUM_LOCATIONS 120 class Parallaction : public Engine { @@ -259,23 +256,6 @@ public: Input *_input; - OpcodeSet _commandOpcodes; - - struct ParallactionStruct1 { - CommandPtr cmd; - ZonePtr z; - } _cmdRunCtxt; - - OpcodeSet _instructionOpcodes; - - struct ParallactionStruct2 { - AnimationPtr anim; - ProgramPtr program; - InstructionList::iterator inst; - uint16 modCounter; - bool suspend; - } _instRunCtxt; - void processInput(InputData* data); void pauseJobs(); @@ -292,8 +272,6 @@ public: void runDialogue(SpeakData*); - void runCommands(CommandList& list, ZonePtr z = nullZonePtr); - AnimationPtr findAnimation(const char *name); void freeAnimations(); @@ -327,6 +305,8 @@ public: Gfx* _gfx; Disk* _disk; + CommandExec* _cmdExec; + ProgramExec* _programExec; Character _char; void setLocationFlags(uint32 flags); @@ -367,10 +347,8 @@ protected: // members void runGame(); void updateView(); - void scheduleLocationSwitch(const char *location); void doLocationEnterTransition(); virtual void changeLocation(char *location) = 0; - virtual void changeCharacter(const char *name) = 0; virtual void runPendingZones() = 0; void allocateLocationSlot(const char *name); void finalizeLocationParsing(); @@ -389,6 +367,9 @@ protected: // members public: + void scheduleLocationSwitch(const char *location); + virtual void changeCharacter(const char *name) = 0; + virtual void callFunction(uint index, void* parm) { } virtual void setArrowCursor() = 0; @@ -398,7 +379,6 @@ public: void updateDoor(ZonePtr z); - virtual void runScripts() = 0; virtual void walk() = 0; virtual void drawAnimations() = 0; @@ -533,7 +513,6 @@ private: void initResources(); void initCursors(); - void initParsers(); static byte _resMouseArrow[256]; byte *_mouseArrow; @@ -596,49 +575,12 @@ private: const Callable *_callables; protected: - void runScripts(); void walk(); void drawAnimations(); void parseLocation(const char *filename); void loadProgram(AnimationPtr a, const char *filename); - void initOpcodes(); - - DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(set); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(start); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(get); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(location); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(open); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(close); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(on); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(off); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(call); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(move); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop); - - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript); - void selectStartLocation(); void guiStart(); @@ -671,6 +613,9 @@ public: typedef void (Parallaction_br::*Callable)(void*); virtual void callFunction(uint index, void* parm); void changeCharacter(const char *name); + void setupSubtitles(char *s, char *s2, int y); + void clearSubtitles(); + public: Table *_countersNames; @@ -698,8 +643,6 @@ private: void initResources(); void initFonts(); void freeFonts(); - void initOpcodes(); - void initParsers(); void setArrowCursor(); void setInventoryCursor(int pos); @@ -741,68 +684,6 @@ private: void parseLocation(const char* name); void loadProgram(AnimationPtr a, const char *filename); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(location); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(open); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(close); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(on); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(off); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(call); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(move); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(start); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(character); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(add); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(let); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(music); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(give); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(text); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(part); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave); - DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave); - - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop); - DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript); - - void setupSubtitles(char *s, char *s2, int y); - void clearSubtitles(); #if 0 void jobWaitRemoveLabelJob(void *parm, Job *job); void jobPauseSfx(void *parm, Job *job); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index c382f6a7f6..6606550132 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -72,12 +72,16 @@ int Parallaction_br::init() { initResources(); initFonts(); initCursors(); - initOpcodes(); _locationParser = new LocationParser_br(this); _locationParser->init(); _programParser = new ProgramParser_br(this); _programParser->init(); + _cmdExec = new CommandExec_br(this); + _cmdExec->init(); + _programExec = new ProgramExec_br(this); + _programExec->init(); + _part = -1; _subtitle[0] = -1; @@ -226,8 +230,14 @@ void Parallaction_br::changeLocation(char *location) { freeBackground(); _gfx->clearGfxObjects(kGfxObjNormal | kGfxObjCharacter); _location._programs.clear(); + + _location._animations.remove(_char._ani); + freeZones(); freeAnimations(); + + _location._animations.push_front(_char._ani); + // free(_location._comment); // _location._comment = 0; // _location._commands.clear(); @@ -236,9 +246,9 @@ void Parallaction_br::changeLocation(char *location) { // load new location parseLocation(location); - runCommands(_location._commands); + _cmdExec->run(_location._commands); // doLocationEnterTransition(); - runCommands(_location._aCommands); + _cmdExec->run(_location._aCommands); _engineFlags &= ~kEngineChangeLocation; } @@ -287,12 +297,16 @@ void Parallaction_br::loadProgram(AnimationPtr a, const char *filename) { void Parallaction_br::changeCharacter(const char *name) { + printf("changeCharacter(%s)\n", name); + const char *charName = _char.getName(); if (!scumm_stricmp(charName, name)) { return; } _char.setName(name); + _char._ani->gfxobj = _gfx->loadAnim(name); + _char._ani->gfxobj->setFlags(kGfxObjCharacter); _char._talk = _disk->loadTalk(name); } diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index a2217e4a73..850123de97 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -135,12 +135,16 @@ int Parallaction_ns::init() { initResources(); initFonts(); initCursors(); - initOpcodes(); _locationParser = new LocationParser_ns(this); _locationParser->init(); _programParser = new ProgramParser_ns(this); _programParser->init(); + _cmdExec = new CommandExec_ns(this); + _cmdExec->init(); + _programExec = new ProgramExec_ns(this); + _programExec->init(); + _introSarcData1 = 0; _introSarcData2 = 1; _introSarcData3 = 200; @@ -353,11 +357,11 @@ void Parallaction_ns::changeLocation(char *location) { // and acommands are executed, so that it can be set again if needed. _engineFlags &= ~kEngineChangeLocation; - runCommands(_location._commands); + _cmdExec->run(_location._commands); doLocationEnterTransition(); - runCommands(_location._aCommands); + _cmdExec->run(_location._aCommands); if (_location._hasSound) _soundMan->playSfx(_location._soundFile, 0, true); diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 0a8ded9e29..7d74dd0e0a 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -347,7 +347,7 @@ uint16 Parallaction::checkDoor() { _zoneTrap = nullZonePtr; } else { - runCommands(z->_commands, z); + _cmdExec->run(z->_commands, z); } } @@ -356,13 +356,13 @@ uint16 Parallaction::checkDoor() { if (z) { setLocationFlags(kFlagsEnter); - runCommands(z->_commands, z); + _cmdExec->run(z->_commands, z); clearLocationFlags(kFlagsEnter); _zoneTrap = z; } else if (_zoneTrap) { setLocationFlags(kFlagsExit); - runCommands(_zoneTrap->_commands, _zoneTrap); + _cmdExec->run(_zoneTrap->_commands, _zoneTrap); clearLocationFlags(kFlagsExit); _zoneTrap = nullZonePtr; } -- cgit v1.2.3 From 8ba56e98cf1887600b204f347af4ee183c326cd1 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Fri, 11 Jul 2008 13:36:22 +0000 Subject: Cleanup. svn-id: r33006 --- engines/parallaction/exec.h | 8 ++- engines/parallaction/exec_br.cpp | 80 ++++++++++++------------ engines/parallaction/exec_ns.cpp | 129 +++++++++++++++++++-------------------- 3 files changed, 108 insertions(+), 109 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h index ca359c2a8e..f41ce52302 100644 --- a/engines/parallaction/exec.h +++ b/engines/parallaction/exec.h @@ -47,7 +47,7 @@ protected: struct ParallactionStruct1 { CommandPtr cmd; ZonePtr z; - } _cmdRunCtxt; + } _ctxt; OpcodeSet _opcodes; @@ -153,14 +153,16 @@ protected: InstructionList::iterator inst; uint16 modCounter; bool suspend; - } _instRunCtxt; + } _ctxt; OpcodeSet _opcodes; + uint16 _modCounter; + public: virtual void init() = 0; virtual void runScripts(ProgramList::iterator first, ProgramList::iterator last); - ProgramExec() { + ProgramExec() : _modCounter(0) { } virtual ~ProgramExec() { for (Common::Array::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i) diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index eca01ea06a..edb832cffc 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -116,7 +116,7 @@ DECLARE_COMMAND_OPCODE(location) { warning("Parallaction_br::cmdOp_location command not yet implemented"); // TODO: handle startPos and startPos2 - _vm->scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); + _vm->scheduleLocationSwitch(_ctxt.cmd->u._string); } @@ -131,7 +131,7 @@ DECLARE_COMMAND_OPCODE(close) { DECLARE_COMMAND_OPCODE(on) { - CommandData *data = &_cmdRunCtxt.cmd->u; + CommandData *data = &_ctxt.cmd->u; ZonePtr z = data->_zone; if (z) { @@ -146,7 +146,7 @@ DECLARE_COMMAND_OPCODE(on) { DECLARE_COMMAND_OPCODE(off) { - CommandData *data = &_cmdRunCtxt.cmd->u; + CommandData *data = &_ctxt.cmd->u; ZonePtr z = data->_zone; if (z) { @@ -160,7 +160,7 @@ DECLARE_COMMAND_OPCODE(off) { DECLARE_COMMAND_OPCODE(call) { - _vm->callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); + _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z); } @@ -174,17 +174,17 @@ DECLARE_COMMAND_OPCODE(move) { } DECLARE_COMMAND_OPCODE(start) { - _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing; + _ctxt.cmd->u._zone->_flags |= kFlagsActing; } DECLARE_COMMAND_OPCODE(stop) { - _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing; + _ctxt.cmd->u._zone->_flags &= ~kFlagsActing; } DECLARE_COMMAND_OPCODE(character) { - debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _cmdRunCtxt.cmd->u._string); - _vm->changeCharacter(_cmdRunCtxt.cmd->u._string); + debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _ctxt.cmd->u._string); + _vm->changeCharacter(_ctxt.cmd->u._string); } @@ -214,17 +214,17 @@ DECLARE_COMMAND_OPCODE(leave) { DECLARE_COMMAND_OPCODE(inc) { - _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_ctxt.cmd->u._lvalue] += _ctxt.cmd->u._rvalue; } DECLARE_COMMAND_OPCODE(dec) { - _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_ctxt.cmd->u._lvalue] -= _ctxt.cmd->u._rvalue; } DECLARE_COMMAND_OPCODE(ifeq) { - if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) { + if (_vm->_counters[_ctxt.cmd->u._lvalue] == _ctxt.cmd->u._rvalue) { _vm->setLocationFlags(kFlagsTestTrue); } else { _vm->clearLocationFlags(kFlagsTestTrue); @@ -232,7 +232,7 @@ DECLARE_COMMAND_OPCODE(ifeq) { } DECLARE_COMMAND_OPCODE(iflt) { - if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) { + if (_vm->_counters[_ctxt.cmd->u._lvalue] < _ctxt.cmd->u._rvalue) { _vm->setLocationFlags(kFlagsTestTrue); } else { _vm->clearLocationFlags(kFlagsTestTrue); @@ -240,7 +240,7 @@ DECLARE_COMMAND_OPCODE(iflt) { } DECLARE_COMMAND_OPCODE(ifgt) { - if (_vm->_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) { + if (_vm->_counters[_ctxt.cmd->u._lvalue] > _ctxt.cmd->u._rvalue) { _vm->setLocationFlags(kFlagsTestTrue); } else { _vm->clearLocationFlags(kFlagsTestTrue); @@ -249,7 +249,7 @@ DECLARE_COMMAND_OPCODE(ifgt) { DECLARE_COMMAND_OPCODE(let) { - _vm->_counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue; + _vm->_counters[_ctxt.cmd->u._lvalue] = _ctxt.cmd->u._rvalue; } @@ -259,25 +259,25 @@ DECLARE_COMMAND_OPCODE(music) { DECLARE_COMMAND_OPCODE(fix) { - _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsFixed; + _ctxt.cmd->u._zone->_flags |= kFlagsFixed; } DECLARE_COMMAND_OPCODE(unfix) { - _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed; + _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed; } DECLARE_COMMAND_OPCODE(zeta) { - _vm->_location._zeta0 = _cmdRunCtxt.cmd->u._zeta0; - _vm->_location._zeta1 = _cmdRunCtxt.cmd->u._zeta1; - _vm->_location._zeta2 = _cmdRunCtxt.cmd->u._zeta2; + _vm->_location._zeta0 = _ctxt.cmd->u._zeta0; + _vm->_location._zeta1 = _ctxt.cmd->u._zeta1; + _vm->_location._zeta2 = _ctxt.cmd->u._zeta2; } DECLARE_COMMAND_OPCODE(scroll) { warning("Parallaction_br::cmdOp_scroll not yet implemented"); - _vm->_gfx->setVar("scroll_x", _cmdRunCtxt.cmd->u._rvalue ); + _vm->_gfx->setVar("scroll_x", _ctxt.cmd->u._rvalue ); } @@ -292,7 +292,7 @@ DECLARE_COMMAND_OPCODE(give) { DECLARE_COMMAND_OPCODE(text) { - CommandData *data = &_cmdRunCtxt.cmd->u; + CommandData *data = &_ctxt.cmd->u; _vm->setupSubtitles(data->_string, data->_string2, data->_zeta0); } @@ -326,7 +326,7 @@ DECLARE_COMMAND_OPCODE(offsave) { DECLARE_INSTRUCTION_OPCODE(on) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; ZonePtr z = inst->_z; if (z) { @@ -341,7 +341,7 @@ DECLARE_INSTRUCTION_OPCODE(on) { DECLARE_INSTRUCTION_OPCODE(off) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; ZonePtr z = inst->_z; if (z) { @@ -355,7 +355,7 @@ DECLARE_INSTRUCTION_OPCODE(off) { DECLARE_INSTRUCTION_OPCODE(set) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; int16 rvalue = inst->_opB.getRValue(); int16* lvalue = inst->_opA.getLValue(); @@ -366,21 +366,21 @@ DECLARE_INSTRUCTION_OPCODE(set) { DECLARE_INSTRUCTION_OPCODE(loop) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; - _instRunCtxt.program->_loopCounter = inst->_opB.getRValue(); - _instRunCtxt.program->_loopStart = _instRunCtxt.inst; + _ctxt.program->_loopCounter = inst->_opB.getRValue(); + _ctxt.program->_loopStart = _ctxt.inst; } DECLARE_INSTRUCTION_OPCODE(inc) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; int16 rvalue = inst->_opB.getRValue(); if (inst->_flags & kInstMod) { // mod int16 _bx = (rvalue > 0 ? rvalue : -rvalue); - if (_instRunCtxt.modCounter % _bx != 0) return; + if (_ctxt.modCounter % _bx != 0) return; rvalue = (rvalue > 0 ? 1 : -1); } @@ -427,12 +427,12 @@ DECLARE_INSTRUCTION_OPCODE(wait) { DECLARE_INSTRUCTION_OPCODE(start) { - (*_instRunCtxt.inst)->_z->_flags |= kFlagsActing; + (*_ctxt.inst)->_z->_flags |= kFlagsActing; } DECLARE_INSTRUCTION_OPCODE(process) { - _vm->_activeZone2 = (*_instRunCtxt.inst)->_z; + _vm->_activeZone2 = (*_ctxt.inst)->_z; } @@ -442,7 +442,7 @@ DECLARE_INSTRUCTION_OPCODE(move) { DECLARE_INSTRUCTION_OPCODE(color) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; int16 entry = inst->_opB.getRValue(); @@ -453,7 +453,7 @@ DECLARE_INSTRUCTION_OPCODE(color) { DECLARE_INSTRUCTION_OPCODE(mask) { #if 0 - Instruction *inst = *_instRunCtxt.inst; + Instruction *inst = *_ctxt.inst; _gfx->_bgLayers[0] = inst->_opA.getRValue(); _gfx->_bgLayers[1] = inst->_opB.getRValue(); _gfx->_bgLayers[2] = inst->_opC.getRValue(); @@ -466,7 +466,7 @@ DECLARE_INSTRUCTION_OPCODE(print) { } DECLARE_INSTRUCTION_OPCODE(text) { - InstructionPtr inst = (*_instRunCtxt.inst); + InstructionPtr inst = (*_ctxt.inst); _vm->setupSubtitles(inst->_text, inst->_text2, inst->_y); } @@ -496,14 +496,14 @@ DECLARE_INSTRUCTION_OPCODE(stop) { } DECLARE_INSTRUCTION_OPCODE(endscript) { - if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) { - _instRunCtxt.anim->_flags &= ~kFlagsActing; - _vm->_cmdExec->run(_instRunCtxt.anim->_commands, _instRunCtxt.anim); - _instRunCtxt.program->_status = kProgramDone; + if ((_ctxt.anim->_flags & kFlagsLooping) == 0) { + _ctxt.anim->_flags &= ~kFlagsActing; + _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim); + _ctxt.program->_status = kProgramDone; } - _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin(); + _ctxt.program->_ip = _ctxt.program->_instructions.begin(); - _instRunCtxt.suspend = true; + _ctxt.suspend = true; } void CommandExec_br::init() { diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 1250d276f6..9a93197f04 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -65,7 +65,7 @@ typedef Common::Functor0Mem OpcodeV2; DECLARE_INSTRUCTION_OPCODE(on) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; inst->_a->_flags |= kFlagsActive; inst->_a->_flags &= ~kFlagsRemove; @@ -73,31 +73,31 @@ DECLARE_INSTRUCTION_OPCODE(on) { DECLARE_INSTRUCTION_OPCODE(off) { - (*_instRunCtxt.inst)->_a->_flags |= kFlagsRemove; + (*_ctxt.inst)->_a->_flags |= kFlagsRemove; } DECLARE_INSTRUCTION_OPCODE(loop) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; - _instRunCtxt.program->_loopCounter = inst->_opB.getRValue(); - _instRunCtxt.program->_loopStart = _instRunCtxt.inst; + _ctxt.program->_loopCounter = inst->_opB.getRValue(); + _ctxt.program->_loopStart = _ctxt.inst; } DECLARE_INSTRUCTION_OPCODE(endloop) { - if (--_instRunCtxt.program->_loopCounter > 0) { - _instRunCtxt.inst = _instRunCtxt.program->_loopStart; + if (--_ctxt.program->_loopCounter > 0) { + _ctxt.inst = _ctxt.program->_loopStart; } } DECLARE_INSTRUCTION_OPCODE(inc) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; int16 _si = inst->_opB.getRValue(); if (inst->_flags & kInstMod) { // mod int16 _bx = (_si > 0 ? _si : -_si); - if (_instRunCtxt.modCounter % _bx != 0) return; + if (_modCounter % _bx != 0) return; _si = (_si > 0 ? 1 : -1); } @@ -118,7 +118,7 @@ DECLARE_INSTRUCTION_OPCODE(inc) { DECLARE_INSTRUCTION_OPCODE(set) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; int16 _si = inst->_opB.getRValue(); int16 *lvalue = inst->_opA.getLValue(); @@ -129,7 +129,7 @@ DECLARE_INSTRUCTION_OPCODE(set) { DECLARE_INSTRUCTION_OPCODE(put) { - InstructionPtr inst = *_instRunCtxt.inst; + InstructionPtr inst = *_ctxt.inst; Graphics::Surface v18; v18.w = inst->_a->width(); v18.h = inst->_a->height(); @@ -147,32 +147,32 @@ DECLARE_INSTRUCTION_OPCODE(null) { } DECLARE_INSTRUCTION_OPCODE(invalid) { - error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index); + error("Can't execute invalid opcode %i", (*_ctxt.inst)->_index); } DECLARE_INSTRUCTION_OPCODE(call) { - _vm->callFunction((*_instRunCtxt.inst)->_immediate, 0); + _vm->callFunction((*_ctxt.inst)->_immediate, 0); } DECLARE_INSTRUCTION_OPCODE(wait) { if (_engineFlags & kEngineWalking) - _instRunCtxt.suspend = true; + _ctxt.suspend = true; } DECLARE_INSTRUCTION_OPCODE(start) { - (*_instRunCtxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive); + (*_ctxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive); } DECLARE_INSTRUCTION_OPCODE(sound) { - _vm->_activeZone = (*_instRunCtxt.inst)->_z; + _vm->_activeZone = (*_ctxt.inst)->_z; } DECLARE_INSTRUCTION_OPCODE(move) { - InstructionPtr inst = (*_instRunCtxt.inst); + InstructionPtr inst = (*_ctxt.inst); int16 x = inst->_opA.getRValue(); int16 y = inst->_opB.getRValue(); @@ -181,82 +181,82 @@ DECLARE_INSTRUCTION_OPCODE(move) { } DECLARE_INSTRUCTION_OPCODE(endscript) { - if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) { - _instRunCtxt.anim->_flags &= ~kFlagsActing; - _vm->_cmdExec->run(_instRunCtxt.anim->_commands, _instRunCtxt.anim); - _instRunCtxt.program->_status = kProgramDone; + if ((_ctxt.anim->_flags & kFlagsLooping) == 0) { + _ctxt.anim->_flags &= ~kFlagsActing; + _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim); + _ctxt.program->_status = kProgramDone; } - _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin(); + _ctxt.program->_ip = _ctxt.program->_instructions.begin(); - _instRunCtxt.suspend = true; + _ctxt.suspend = true; } DECLARE_COMMAND_OPCODE(invalid) { - error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id); + error("Can't execute invalid command '%i'", _ctxt.cmd->_id); } DECLARE_COMMAND_OPCODE(set) { - if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) { - _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; - _commandFlags |= _cmdRunCtxt.cmd->u._flags; + if (_ctxt.cmd->u._flags & kFlagsGlobal) { + _ctxt.cmd->u._flags &= ~kFlagsGlobal; + _commandFlags |= _ctxt.cmd->u._flags; } else { - _vm->setLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->setLocationFlags(_ctxt.cmd->u._flags); } } DECLARE_COMMAND_OPCODE(clear) { - if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) { - _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; - _commandFlags &= ~_cmdRunCtxt.cmd->u._flags; + if (_ctxt.cmd->u._flags & kFlagsGlobal) { + _ctxt.cmd->u._flags &= ~kFlagsGlobal; + _commandFlags &= ~_ctxt.cmd->u._flags; } else { - _vm->clearLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->clearLocationFlags(_ctxt.cmd->u._flags); } } DECLARE_COMMAND_OPCODE(start) { - _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing; + _ctxt.cmd->u._zone->_flags |= kFlagsActing; } DECLARE_COMMAND_OPCODE(speak) { - _vm->_activeZone = _cmdRunCtxt.cmd->u._zone; + _vm->_activeZone = _ctxt.cmd->u._zone; } DECLARE_COMMAND_OPCODE(get) { - _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed; - _vm->runZone(_cmdRunCtxt.cmd->u._zone); + _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed; + _vm->runZone(_ctxt.cmd->u._zone); } DECLARE_COMMAND_OPCODE(location) { - _vm->scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string); + _vm->scheduleLocationSwitch(_ctxt.cmd->u._string); } DECLARE_COMMAND_OPCODE(open) { - _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed; - if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) { - _vm->updateDoor(_cmdRunCtxt.cmd->u._zone); + _ctxt.cmd->u._zone->_flags &= ~kFlagsClosed; + if (_ctxt.cmd->u._zone->u.door->gfxobj) { + _vm->updateDoor(_ctxt.cmd->u._zone); } } DECLARE_COMMAND_OPCODE(close) { - _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed; - if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) { - _vm->updateDoor(_cmdRunCtxt.cmd->u._zone); + _ctxt.cmd->u._zone->_flags |= kFlagsClosed; + if (_ctxt.cmd->u._zone->u.door->gfxobj) { + _vm->updateDoor(_ctxt.cmd->u._zone); } } DECLARE_COMMAND_OPCODE(on) { - ZonePtr z = _cmdRunCtxt.cmd->u._zone; + ZonePtr z = _ctxt.cmd->u._zone; // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing // the pointer to get structure members, thus leading to crashes in systems with memory // protection. @@ -274,27 +274,27 @@ DECLARE_COMMAND_OPCODE(on) { DECLARE_COMMAND_OPCODE(off) { - _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove; + _ctxt.cmd->u._zone->_flags |= kFlagsRemove; } DECLARE_COMMAND_OPCODE(call) { - _vm->callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z); + _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z); } DECLARE_COMMAND_OPCODE(toggle) { - if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) { - _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal; - _commandFlags ^= _cmdRunCtxt.cmd->u._flags; + if (_ctxt.cmd->u._flags & kFlagsGlobal) { + _ctxt.cmd->u._flags &= ~kFlagsGlobal; + _commandFlags ^= _ctxt.cmd->u._flags; } else { - _vm->toggleLocationFlags(_cmdRunCtxt.cmd->u._flags); + _vm->toggleLocationFlags(_ctxt.cmd->u._flags); } } DECLARE_COMMAND_OPCODE(drop){ - _vm->dropItem( _cmdRunCtxt.cmd->u._object ); + _vm->dropItem( _ctxt.cmd->u._object ); } @@ -304,12 +304,12 @@ DECLARE_COMMAND_OPCODE(quit) { DECLARE_COMMAND_OPCODE(move) { - _vm->_char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y); + _vm->_char.scheduleWalk(_ctxt.cmd->u._move.x, _ctxt.cmd->u._move.y); } DECLARE_COMMAND_OPCODE(stop) { - _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing; + _ctxt.cmd->u._zone->_flags &= ~kFlagsActing; } @@ -365,8 +365,6 @@ void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator debugC(9, kDebugExec, "runScripts"); - static uint16 modCounter = 0; - for (ProgramList::iterator it = first; it != last; it++) { AnimationPtr a = (*it)->_anim; @@ -384,17 +382,16 @@ void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator debugC(9, kDebugExec, "Animation: %s, instruction: %i", a->_name, (*inst)->_index); //_instructionNamesRes[(*inst)->_index - 1]); - _instRunCtxt.inst = inst; - _instRunCtxt.anim = AnimationPtr(a); - _instRunCtxt.program = *it; - _instRunCtxt.modCounter = modCounter; - _instRunCtxt.suspend = false; + _ctxt.inst = inst; + _ctxt.anim = AnimationPtr(a); + _ctxt.program = *it; + _ctxt.suspend = false; (*_opcodes[(*inst)->_index])(); - inst = _instRunCtxt.inst; // handles endloop correctly + inst = _ctxt.inst; // handles endloop correctly - if (_instRunCtxt.suspend) + if (_ctxt.suspend) goto label1; inst++; @@ -407,7 +404,7 @@ label1: a->_z = a->_top + a->height(); } - modCounter++; + _modCounter++; return; } @@ -437,8 +434,8 @@ void CommandExec::run(CommandList& list, ZonePtr z) { if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue; if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue; - _cmdRunCtxt.z = z; - _cmdRunCtxt.cmd = cmd; + _ctxt.z = z; + _ctxt.cmd = cmd; (*_opcodes[cmd->_id])(); } @@ -711,7 +708,7 @@ void ProgramExec_ns::init() { } ProgramExec_ns::ProgramExec_ns(Parallaction_ns *vm) : _vm(vm) { - } +} ProgramExec_ns::~ProgramExec_ns() { } -- cgit v1.2.3 From 815d75e870bc4d365cfa979f3786840eecece2ec Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 11 Jul 2008 20:28:14 +0000 Subject: Don't use kPlainSoundType if you don't have to svn-id: r33009 --- engines/gob/sound/soundmixer.h | 2 +- engines/igor/igor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h index 5789885a99..3e8e6b5c1b 100644 --- a/engines/gob/sound/soundmixer.h +++ b/engines/gob/sound/soundmixer.h @@ -37,7 +37,7 @@ namespace Gob { class SoundMixer : public Audio::AudioStream { public: - SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType); + SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type); ~SoundMixer(); virtual void play(SoundDesc &sndDesc, int16 repCount, diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp index 018709f34f..4d4fb97762 100644 --- a/engines/igor/igor.cpp +++ b/engines/igor/igor.cpp @@ -404,7 +404,7 @@ void IgorEngine::playSound(int num, int type) { debugC(9, kDebugEngine, "playSound() %d", num); --num; int soundOffset = -1; - Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType; + Audio::Mixer::SoundType soundType; Audio::SoundHandle *soundHandle = 0; if (type == 1) { if (_mixer->isSoundHandleActive(_sfxHandle)) { -- cgit v1.2.3 From 7ddd961bf2ded1d9cad114ea03018d44258e9ca8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 11 Jul 2008 20:28:50 +0000 Subject: cleanup svn-id: r33010 --- engines/scumm/saveload.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 36b82519e9..f9e4eb415c 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -411,15 +411,15 @@ void ScummEngine::listSavegames(bool *marks, int num) { char prefix[256]; char slot[3]; int slotNum; - Common::StringList filenames; + Common::StringList files; makeSavegameName(prefix, 99, false); prefix[strlen(prefix)-2] = '*'; prefix[strlen(prefix)-1] = 0; memset(marks, false, num * sizeof(bool)); //assume no savegames for this title - filenames = _saveFileMan->listSavefiles(prefix); + files = _saveFileMan->listSavefiles(prefix); - for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){ + for (Common::StringList::const_iterator file = files.begin(); file != files.end(); ++file) { //Obtain the last 2 digits of the filename, since they correspond to the save slot slot[0] = file->c_str()[file->size()-2]; slot[1] = file->c_str()[file->size()-1]; -- cgit v1.2.3 From c1ec21d999253d86513ce66876c692be198b91c0 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sat, 12 Jul 2008 15:21:38 +0000 Subject: Changed tricky variable access from pointers to a new class that minds endianess. This should fix a few regressions with BE games on LE systems and vice versa that I introduced when I changed how variables are stored (which was necessary to get Woodruff work on BE systems). svn-id: r33014 --- engines/gob/goblin.cpp | 330 +++++++++++++++++++--------------------------- engines/gob/goblin.h | 103 ++++++++------- engines/gob/inter.h | 2 +- engines/gob/inter_v1.cpp | 173 ++++++++++++------------ engines/gob/inter_v2.cpp | 12 +- engines/gob/mult.cpp | 26 +++- engines/gob/mult.h | 9 +- engines/gob/mult_v1.cpp | 33 +++-- engines/gob/mult_v2.cpp | 26 ++-- engines/gob/sound/sound.h | 2 +- engines/gob/variables.cpp | 58 ++++++++ engines/gob/variables.h | 26 ++++ 12 files changed, 441 insertions(+), 359 deletions(-) (limited to 'engines') diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index e7aed0790e..5add0b9cea 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -78,58 +78,6 @@ Goblin::Goblin(GobEngine *vm) : _vm(vm) { _pressedMapY = 0; _pathExistence = 0; - _some0ValPtr = 0; - - _gobRetVarPtr = 0; - _curGobVarPtr = 0; - _curGobXPosVarPtr = 0; - _curGobYPosVarPtr = 0; - _itemInPocketVarPtr = 0; - - _curGobStateVarPtr = 0; - _curGobFrameVarPtr = 0; - _curGobMultStateVarPtr = 0; - _curGobNextStateVarPtr = 0; - _curGobScrXVarPtr = 0; - _curGobScrYVarPtr = 0; - _curGobLeftVarPtr = 0; - _curGobTopVarPtr = 0; - _curGobRightVarPtr = 0; - _curGobBottomVarPtr = 0; - _curGobDoAnimVarPtr = 0; - _curGobOrderVarPtr = 0; - _curGobNoTickVarPtr = 0; - _curGobTypeVarPtr = 0; - _curGobMaxTickVarPtr = 0; - _curGobTickVarPtr = 0; - _curGobActStartStateVarPtr = 0; - _curGobLookDirVarPtr = 0; - _curGobPickableVarPtr = 0; - _curGobRelaxVarPtr = 0; - _curGobMaxFrameVarPtr = 0; - - _destItemStateVarPtr = 0; - _destItemFrameVarPtr = 0; - _destItemMultStateVarPtr = 0; - _destItemNextStateVarPtr = 0; - _destItemScrXVarPtr = 0; - _destItemScrYVarPtr = 0; - _destItemLeftVarPtr = 0; - _destItemTopVarPtr = 0; - _destItemRightVarPtr = 0; - _destItemBottomVarPtr = 0; - _destItemDoAnimVarPtr = 0; - _destItemOrderVarPtr = 0; - _destItemNoTickVarPtr = 0; - _destItemTypeVarPtr = 0; - _destItemMaxTickVarPtr = 0; - _destItemTickVarPtr = 0; - _destItemActStartStVarPtr = 0; - _destItemLookDirVarPtr = 0; - _destItemPickableVarPtr = 0; - _destItemRelaxVarPtr = 0; - _destItemMaxFrameVarPtr = 0; - _destItemType = 0; _destItemState = 0; for (int i = 0; i < 20; i++) { @@ -690,7 +638,7 @@ void Goblin::switchGoblin(int16 index) { _gobDestY = tmp; _vm->_map->_curGoblinY = tmp; - *_curGobVarPtr = _currentGoblin; + _curGobVarPtr = (uint32) _currentGoblin; _pathExistence = 0; _readyToAct = 0; } @@ -1250,172 +1198,172 @@ void Goblin::loadObjects(const char *source) { void Goblin::saveGobDataToVars(int16 xPos, int16 yPos, int16 someVal) { Gob_Object *obj; - *_some0ValPtr = someVal; - *_curGobXPosVarPtr = xPos; - *_curGobYPosVarPtr = yPos; - *_itemInPocketVarPtr = _itemIndInPocket; + _some0ValPtr = (uint32) someVal; + _curGobXPosVarPtr = (uint32) xPos; + _curGobYPosVarPtr = (uint32) yPos; + _itemInPocketVarPtr = (uint32) _itemIndInPocket; obj = _goblins[_currentGoblin]; - *_curGobStateVarPtr = obj->state; - *_curGobFrameVarPtr = obj->curFrame; - *_curGobMultStateVarPtr = obj->multState; - *_curGobNextStateVarPtr = obj->nextState; - *_curGobScrXVarPtr = obj->xPos; - *_curGobScrYVarPtr = obj->yPos; - *_curGobLeftVarPtr = obj->left; - *_curGobTopVarPtr = obj->top; - *_curGobRightVarPtr = obj->right; - *_curGobBottomVarPtr = obj->bottom; - *_curGobDoAnimVarPtr = obj->doAnim; - *_curGobOrderVarPtr = obj->order; - *_curGobNoTickVarPtr = obj->noTick; - *_curGobTypeVarPtr = obj->type; - *_curGobMaxTickVarPtr = obj->maxTick; - *_curGobTickVarPtr = obj->tick; - *_curGobActStartStateVarPtr = obj->actionStartState; - *_curGobLookDirVarPtr = obj->curLookDir; - *_curGobPickableVarPtr = obj->pickable; - *_curGobRelaxVarPtr = obj->relaxTime; - *_curGobMaxFrameVarPtr = getObjMaxFrame(obj); + _curGobStateVarPtr = (uint32) obj->state; + _curGobFrameVarPtr = (uint32) obj->curFrame; + _curGobMultStateVarPtr = (uint32) obj->multState; + _curGobNextStateVarPtr = (uint32) obj->nextState; + _curGobScrXVarPtr = (uint32) obj->xPos; + _curGobScrYVarPtr = (uint32) obj->yPos; + _curGobLeftVarPtr = (uint32) obj->left; + _curGobTopVarPtr = (uint32) obj->top; + _curGobRightVarPtr = (uint32) obj->right; + _curGobBottomVarPtr = (uint32) obj->bottom; + _curGobDoAnimVarPtr = (uint32) obj->doAnim; + _curGobOrderVarPtr = (uint32) obj->order; + _curGobNoTickVarPtr = (uint32) obj->noTick; + _curGobTypeVarPtr = (uint32) obj->type; + _curGobMaxTickVarPtr = (uint32) obj->maxTick; + _curGobTickVarPtr = (uint32) obj->tick; + _curGobActStartStateVarPtr = (uint32) obj->actionStartState; + _curGobLookDirVarPtr = (uint32) obj->curLookDir; + _curGobPickableVarPtr = (uint32) obj->pickable; + _curGobRelaxVarPtr = (uint32) obj->relaxTime; + _curGobMaxFrameVarPtr = (uint32) getObjMaxFrame(obj); if (_actDestItemDesc == 0) return; obj = _actDestItemDesc; - *_destItemStateVarPtr = obj->state; - *_destItemFrameVarPtr = obj->curFrame; - *_destItemMultStateVarPtr = obj->multState; - *_destItemNextStateVarPtr = obj->nextState; - *_destItemScrXVarPtr = obj->xPos; - *_destItemScrYVarPtr = obj->yPos; - *_destItemLeftVarPtr = obj->left; - *_destItemTopVarPtr = obj->top; - *_destItemRightVarPtr = obj->right; - *_destItemBottomVarPtr = obj->bottom; - *_destItemDoAnimVarPtr = obj->doAnim; - *_destItemOrderVarPtr = obj->order; - *_destItemNoTickVarPtr = obj->noTick; - *_destItemTypeVarPtr = obj->type; - *_destItemMaxTickVarPtr = obj->maxTick; - *_destItemTickVarPtr = obj->tick; - *_destItemActStartStVarPtr = obj->actionStartState; - *_destItemLookDirVarPtr = obj->curLookDir; - *_destItemPickableVarPtr = obj->pickable; - *_destItemRelaxVarPtr = obj->relaxTime; - *_destItemMaxFrameVarPtr = getObjMaxFrame(obj); + _destItemStateVarPtr = (uint32) obj->state; + _destItemFrameVarPtr = (uint32) obj->curFrame; + _destItemMultStateVarPtr = (uint32) obj->multState; + _destItemNextStateVarPtr = (uint32) obj->nextState; + _destItemScrXVarPtr = (uint32) obj->xPos; + _destItemScrYVarPtr = (uint32) obj->yPos; + _destItemLeftVarPtr = (uint32) obj->left; + _destItemTopVarPtr = (uint32) obj->top; + _destItemRightVarPtr = (uint32) obj->right; + _destItemBottomVarPtr = (uint32) obj->bottom; + _destItemDoAnimVarPtr = (uint32) obj->doAnim; + _destItemOrderVarPtr = (uint32) obj->order; + _destItemNoTickVarPtr = (uint32) obj->noTick; + _destItemTypeVarPtr = (uint32) obj->type; + _destItemMaxTickVarPtr = (uint32) obj->maxTick; + _destItemTickVarPtr = (uint32) obj->tick; + _destItemActStartStVarPtr = (uint32) obj->actionStartState; + _destItemLookDirVarPtr = (uint32) obj->curLookDir; + _destItemPickableVarPtr = (uint32) obj->pickable; + _destItemRelaxVarPtr = (uint32) obj->relaxTime; + _destItemMaxFrameVarPtr = (uint32) getObjMaxFrame(obj); _destItemState = obj->state; _destItemType = obj->type; } void Goblin::initVarPointers(void) { - _gobRetVarPtr = (int32 *)VAR_ADDRESS(59); - _curGobStateVarPtr = (int32 *)VAR_ADDRESS(60); - _curGobFrameVarPtr = (int32 *)VAR_ADDRESS(61); - _curGobMultStateVarPtr = (int32 *)VAR_ADDRESS(62); - _curGobNextStateVarPtr = (int32 *)VAR_ADDRESS(63); - _curGobScrXVarPtr = (int32 *)VAR_ADDRESS(64); - _curGobScrYVarPtr = (int32 *)VAR_ADDRESS(65); - _curGobLeftVarPtr = (int32 *)VAR_ADDRESS(66); - _curGobTopVarPtr = (int32 *)VAR_ADDRESS(67); - _curGobRightVarPtr = (int32 *)VAR_ADDRESS(68); - _curGobBottomVarPtr = (int32 *)VAR_ADDRESS(69); - _curGobDoAnimVarPtr = (int32 *)VAR_ADDRESS(70); - _curGobOrderVarPtr = (int32 *)VAR_ADDRESS(71); - _curGobNoTickVarPtr = (int32 *)VAR_ADDRESS(72); - _curGobTypeVarPtr = (int32 *)VAR_ADDRESS(73); - _curGobMaxTickVarPtr = (int32 *)VAR_ADDRESS(74); - _curGobTickVarPtr = (int32 *)VAR_ADDRESS(75); - _curGobActStartStateVarPtr = (int32 *)VAR_ADDRESS(76); - _curGobLookDirVarPtr = (int32 *)VAR_ADDRESS(77); - _curGobPickableVarPtr = (int32 *)VAR_ADDRESS(80); - _curGobRelaxVarPtr = (int32 *)VAR_ADDRESS(81); - _destItemStateVarPtr = (int32 *)VAR_ADDRESS(82); - _destItemFrameVarPtr = (int32 *)VAR_ADDRESS(83); - _destItemMultStateVarPtr = (int32 *)VAR_ADDRESS(84); - _destItemNextStateVarPtr = (int32 *)VAR_ADDRESS(85); - _destItemScrXVarPtr = (int32 *)VAR_ADDRESS(86); - _destItemScrYVarPtr = (int32 *)VAR_ADDRESS(87); - _destItemLeftVarPtr = (int32 *)VAR_ADDRESS(88); - _destItemTopVarPtr = (int32 *)VAR_ADDRESS(89); - _destItemRightVarPtr = (int32 *)VAR_ADDRESS(90); - _destItemBottomVarPtr = (int32 *)VAR_ADDRESS(91); - _destItemDoAnimVarPtr = (int32 *)VAR_ADDRESS(92); - _destItemOrderVarPtr = (int32 *)VAR_ADDRESS(93); - _destItemNoTickVarPtr = (int32 *)VAR_ADDRESS(94); - _destItemTypeVarPtr = (int32 *)VAR_ADDRESS(95); - _destItemMaxTickVarPtr = (int32 *)VAR_ADDRESS(96); - _destItemTickVarPtr = (int32 *)VAR_ADDRESS(97); - _destItemActStartStVarPtr = (int32 *)VAR_ADDRESS(98); - _destItemLookDirVarPtr = (int32 *)VAR_ADDRESS(99); - _destItemPickableVarPtr = (int32 *)VAR_ADDRESS(102); - _destItemRelaxVarPtr = (int32 *)VAR_ADDRESS(103); - _destItemMaxFrameVarPtr = (int32 *)VAR_ADDRESS(105); - _curGobVarPtr = (int32 *)VAR_ADDRESS(106); - _some0ValPtr = (int32 *)VAR_ADDRESS(107); - _curGobXPosVarPtr = (int32 *)VAR_ADDRESS(108); - _curGobYPosVarPtr = (int32 *)VAR_ADDRESS(109); - _curGobMaxFrameVarPtr = (int32 *)VAR_ADDRESS(110); - - _itemInPocketVarPtr = (int32 *)VAR_ADDRESS(114); - - *_itemInPocketVarPtr = -2; + _gobRetVarPtr.set(*_vm->_inter->_variables, 236); + _curGobStateVarPtr.set(*_vm->_inter->_variables, 240); + _curGobFrameVarPtr.set(*_vm->_inter->_variables, 244); + _curGobMultStateVarPtr.set(*_vm->_inter->_variables, 248); + _curGobNextStateVarPtr.set(*_vm->_inter->_variables, 252); + _curGobScrXVarPtr.set(*_vm->_inter->_variables, 256); + _curGobScrYVarPtr.set(*_vm->_inter->_variables, 260); + _curGobLeftVarPtr.set(*_vm->_inter->_variables, 264); + _curGobTopVarPtr.set(*_vm->_inter->_variables, 268); + _curGobRightVarPtr.set(*_vm->_inter->_variables, 272); + _curGobBottomVarPtr.set(*_vm->_inter->_variables, 276); + _curGobDoAnimVarPtr.set(*_vm->_inter->_variables, 280); + _curGobOrderVarPtr.set(*_vm->_inter->_variables, 284); + _curGobNoTickVarPtr.set(*_vm->_inter->_variables, 288); + _curGobTypeVarPtr.set(*_vm->_inter->_variables, 292); + _curGobMaxTickVarPtr.set(*_vm->_inter->_variables, 296); + _curGobTickVarPtr.set(*_vm->_inter->_variables, 300); + _curGobActStartStateVarPtr.set(*_vm->_inter->_variables, 304); + _curGobLookDirVarPtr.set(*_vm->_inter->_variables, 308); + _curGobPickableVarPtr.set(*_vm->_inter->_variables, 320); + _curGobRelaxVarPtr.set(*_vm->_inter->_variables, 324); + _destItemStateVarPtr.set(*_vm->_inter->_variables, 328); + _destItemFrameVarPtr.set(*_vm->_inter->_variables, 332); + _destItemMultStateVarPtr.set(*_vm->_inter->_variables, 336); + _destItemNextStateVarPtr.set(*_vm->_inter->_variables, 340); + _destItemScrXVarPtr.set(*_vm->_inter->_variables, 344); + _destItemScrYVarPtr.set(*_vm->_inter->_variables, 348); + _destItemLeftVarPtr.set(*_vm->_inter->_variables, 352); + _destItemTopVarPtr.set(*_vm->_inter->_variables, 356); + _destItemRightVarPtr.set(*_vm->_inter->_variables, 360); + _destItemBottomVarPtr.set(*_vm->_inter->_variables, 364); + _destItemDoAnimVarPtr.set(*_vm->_inter->_variables, 368); + _destItemOrderVarPtr.set(*_vm->_inter->_variables, 372); + _destItemNoTickVarPtr.set(*_vm->_inter->_variables, 376); + _destItemTypeVarPtr.set(*_vm->_inter->_variables, 380); + _destItemMaxTickVarPtr.set(*_vm->_inter->_variables, 384); + _destItemTickVarPtr.set(*_vm->_inter->_variables, 388); + _destItemActStartStVarPtr.set(*_vm->_inter->_variables, 392); + _destItemLookDirVarPtr.set(*_vm->_inter->_variables, 396); + _destItemPickableVarPtr.set(*_vm->_inter->_variables, 408); + _destItemRelaxVarPtr.set(*_vm->_inter->_variables, 412); + _destItemMaxFrameVarPtr.set(*_vm->_inter->_variables, 420); + _curGobVarPtr.set(*_vm->_inter->_variables, 424); + _some0ValPtr.set(*_vm->_inter->_variables, 428); + _curGobXPosVarPtr.set(*_vm->_inter->_variables, 432); + _curGobYPosVarPtr.set(*_vm->_inter->_variables, 436); + _curGobMaxFrameVarPtr.set(*_vm->_inter->_variables, 440); + + _itemInPocketVarPtr.set(*_vm->_inter->_variables, 456); + + _itemInPocketVarPtr = (uint32) -2; } void Goblin::loadGobDataFromVars(void) { Gob_Object *obj; - _itemIndInPocket = *_itemInPocketVarPtr; + _itemIndInPocket = (int32) _itemInPocketVarPtr; obj = _goblins[_currentGoblin]; - obj->state = *_curGobStateVarPtr; - obj->curFrame = *_curGobFrameVarPtr; - obj->multState = *_curGobMultStateVarPtr; - obj->nextState = *_curGobNextStateVarPtr; - obj->xPos = *_curGobScrXVarPtr; - obj->yPos = *_curGobScrYVarPtr; - obj->left = *_curGobLeftVarPtr; - obj->top = *_curGobTopVarPtr; - obj->right = *_curGobRightVarPtr; - obj->bottom = *_curGobBottomVarPtr; - obj->doAnim = *_curGobDoAnimVarPtr; - obj->order = *_curGobOrderVarPtr; - obj->noTick = *_curGobNoTickVarPtr; - obj->type = *_curGobTypeVarPtr; - obj->maxTick = *_curGobMaxTickVarPtr; - obj->tick = *_curGobTickVarPtr; - obj->actionStartState = *_curGobActStartStateVarPtr; - obj->curLookDir = *_curGobLookDirVarPtr; - obj->pickable = *_curGobPickableVarPtr; - obj->relaxTime = *_curGobRelaxVarPtr; + obj->state = (int32) _curGobStateVarPtr; + obj->curFrame = (int32) _curGobFrameVarPtr; + obj->multState = (int32) _curGobMultStateVarPtr; + obj->nextState = (int32) _curGobNextStateVarPtr; + obj->xPos = (int32) _curGobScrXVarPtr; + obj->yPos = (int32) _curGobScrYVarPtr; + obj->left = (int32) _curGobLeftVarPtr; + obj->top = (int32) _curGobTopVarPtr; + obj->right = (int32) _curGobRightVarPtr; + obj->bottom = (int32) _curGobBottomVarPtr; + obj->doAnim = (int32) _curGobDoAnimVarPtr; + obj->order = (int32) _curGobOrderVarPtr; + obj->noTick = (int32) _curGobNoTickVarPtr; + obj->type = (int32) _curGobTypeVarPtr; + obj->maxTick = (int32) _curGobMaxTickVarPtr; + obj->tick = (int32) _curGobTickVarPtr; + obj->actionStartState = (int32) _curGobActStartStateVarPtr; + obj->curLookDir = (int32) _curGobLookDirVarPtr; + obj->pickable = (int32) _curGobPickableVarPtr; + obj->relaxTime = (int32) _curGobRelaxVarPtr; if (_actDestItemDesc == 0) return; obj = _actDestItemDesc; - obj->state = *_destItemStateVarPtr; - obj->curFrame = *_destItemFrameVarPtr; - obj->multState = *_destItemMultStateVarPtr; - obj->nextState = *_destItemNextStateVarPtr; - obj->xPos = *_destItemScrXVarPtr; - obj->yPos = *_destItemScrYVarPtr; - obj->left = *_destItemLeftVarPtr; - obj->top = *_destItemTopVarPtr; - obj->right = *_destItemRightVarPtr; - obj->bottom = *_destItemBottomVarPtr; - obj->doAnim = *_destItemDoAnimVarPtr; - obj->order = *_destItemOrderVarPtr; - obj->noTick = *_destItemNoTickVarPtr; - obj->type = *_destItemTypeVarPtr; - obj->maxTick = *_destItemMaxTickVarPtr; - obj->tick = *_destItemTickVarPtr; - obj->actionStartState = *_destItemActStartStVarPtr; - obj->curLookDir = *_destItemLookDirVarPtr; - obj->pickable = *_destItemPickableVarPtr; - obj->relaxTime = *_destItemRelaxVarPtr; + obj->state = (int32) _destItemStateVarPtr; + obj->curFrame = (int32) _destItemFrameVarPtr; + obj->multState = (int32) _destItemMultStateVarPtr; + obj->nextState = (int32) _destItemNextStateVarPtr; + obj->xPos = (int32) _destItemScrXVarPtr; + obj->yPos = (int32) _destItemScrYVarPtr; + obj->left = (int32) _destItemLeftVarPtr; + obj->top = (int32) _destItemTopVarPtr; + obj->right = (int32) _destItemRightVarPtr; + obj->bottom = (int32) _destItemBottomVarPtr; + obj->doAnim = (int32) _destItemDoAnimVarPtr; + obj->order = (int32) _destItemOrderVarPtr; + obj->noTick = (int32) _destItemNoTickVarPtr; + obj->type = (int32) _destItemTypeVarPtr; + obj->maxTick = (int32) _destItemMaxTickVarPtr; + obj->tick = (int32) _destItemTickVarPtr; + obj->actionStartState = (int32) _destItemActStartStVarPtr; + obj->curLookDir = (int32) _destItemLookDirVarPtr; + obj->pickable = (int32) _destItemPickableVarPtr; + obj->relaxTime = (int32) _destItemRelaxVarPtr; if (obj->type != _destItemType) obj->toRedraw = 1; diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index 3fd8a9f93b..2100bcbdac 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -28,6 +28,7 @@ #include "gob/util.h" #include "gob/mult.h" +#include "gob/variables.h" #include "gob/sound/sounddesc.h" namespace Gob { @@ -115,57 +116,57 @@ public: char _pathExistence; // Pointers to interpreter variables - int32 *_some0ValPtr; - - int32 *_gobRetVarPtr; - int32 *_curGobVarPtr; - int32 *_curGobXPosVarPtr; - int32 *_curGobYPosVarPtr; - int32 *_itemInPocketVarPtr; - - int32 *_curGobStateVarPtr; - int32 *_curGobFrameVarPtr; - int32 *_curGobMultStateVarPtr; - int32 *_curGobNextStateVarPtr; - int32 *_curGobScrXVarPtr; - int32 *_curGobScrYVarPtr; - int32 *_curGobLeftVarPtr; - int32 *_curGobTopVarPtr; - int32 *_curGobRightVarPtr; - int32 *_curGobBottomVarPtr; - int32 *_curGobDoAnimVarPtr; - int32 *_curGobOrderVarPtr; - int32 *_curGobNoTickVarPtr; - int32 *_curGobTypeVarPtr; - int32 *_curGobMaxTickVarPtr; - int32 *_curGobTickVarPtr; - int32 *_curGobActStartStateVarPtr; - int32 *_curGobLookDirVarPtr; - int32 *_curGobPickableVarPtr; - int32 *_curGobRelaxVarPtr; - int32 *_curGobMaxFrameVarPtr; - - int32 *_destItemStateVarPtr; - int32 *_destItemFrameVarPtr; - int32 *_destItemMultStateVarPtr; - int32 *_destItemNextStateVarPtr; - int32 *_destItemScrXVarPtr; - int32 *_destItemScrYVarPtr; - int32 *_destItemLeftVarPtr; - int32 *_destItemTopVarPtr; - int32 *_destItemRightVarPtr; - int32 *_destItemBottomVarPtr; - int32 *_destItemDoAnimVarPtr; - int32 *_destItemOrderVarPtr; - int32 *_destItemNoTickVarPtr; - int32 *_destItemTypeVarPtr; - int32 *_destItemMaxTickVarPtr; - int32 *_destItemTickVarPtr; - int32 *_destItemActStartStVarPtr; - int32 *_destItemLookDirVarPtr; - int32 *_destItemPickableVarPtr; - int32 *_destItemRelaxVarPtr; - int32 *_destItemMaxFrameVarPtr; + VariableReference _some0ValPtr; + + VariableReference _gobRetVarPtr; + VariableReference _curGobVarPtr; + VariableReference _curGobXPosVarPtr; + VariableReference _curGobYPosVarPtr; + VariableReference _itemInPocketVarPtr; + + VariableReference _curGobStateVarPtr; + VariableReference _curGobFrameVarPtr; + VariableReference _curGobMultStateVarPtr; + VariableReference _curGobNextStateVarPtr; + VariableReference _curGobScrXVarPtr; + VariableReference _curGobScrYVarPtr; + VariableReference _curGobLeftVarPtr; + VariableReference _curGobTopVarPtr; + VariableReference _curGobRightVarPtr; + VariableReference _curGobBottomVarPtr; + VariableReference _curGobDoAnimVarPtr; + VariableReference _curGobOrderVarPtr; + VariableReference _curGobNoTickVarPtr; + VariableReference _curGobTypeVarPtr; + VariableReference _curGobMaxTickVarPtr; + VariableReference _curGobTickVarPtr; + VariableReference _curGobActStartStateVarPtr; + VariableReference _curGobLookDirVarPtr; + VariableReference _curGobPickableVarPtr; + VariableReference _curGobRelaxVarPtr; + VariableReference _curGobMaxFrameVarPtr; + + VariableReference _destItemStateVarPtr; + VariableReference _destItemFrameVarPtr; + VariableReference _destItemMultStateVarPtr; + VariableReference _destItemNextStateVarPtr; + VariableReference _destItemScrXVarPtr; + VariableReference _destItemScrYVarPtr; + VariableReference _destItemLeftVarPtr; + VariableReference _destItemTopVarPtr; + VariableReference _destItemRightVarPtr; + VariableReference _destItemBottomVarPtr; + VariableReference _destItemDoAnimVarPtr; + VariableReference _destItemOrderVarPtr; + VariableReference _destItemNoTickVarPtr; + VariableReference _destItemTypeVarPtr; + VariableReference _destItemMaxTickVarPtr; + VariableReference _destItemTickVarPtr; + VariableReference _destItemActStartStVarPtr; + VariableReference _destItemLookDirVarPtr; + VariableReference _destItemPickableVarPtr; + VariableReference _destItemRelaxVarPtr; + VariableReference _destItemMaxFrameVarPtr; int16 _destItemType; int16 _destItemState; diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 60b3974d6d..b684be6c07 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -79,7 +79,7 @@ protected: }; struct OpGobParams { int16 extraData; - int32 *retVarPtr; + VariableReference retVarPtr; Goblin::Gob_Object *objDesc; }; diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index e2b8d65112..865d188a2e 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -912,12 +912,21 @@ void Inter_v1::o1_initMult() { animDataVar = _vm->_parse->parseVarIndex(); if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) { + warning("Initializing new objects without having " "cleaned up the old ones at first"); + + for (int i = 0; i < _vm->_mult->_objCount; i++) { + delete _vm->_mult->_objects[i].pPosX; + delete _vm->_mult->_objects[i].pPosY; + } + delete[] _vm->_mult->_objects; delete[] _vm->_mult->_renderData; + _vm->_mult->_objects = 0; _vm->_mult->_renderObjs = 0; + } if (_vm->_mult->_objects == 0) { @@ -933,8 +942,8 @@ void Inter_v1::o1_initMult() { uint32 offPosY = i * 4 + (posYVar / 4) * 4; uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; - _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX); - _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY); + _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX); + _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY); _vm->_mult->_objects[i].pAnimData = (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim, @@ -1774,7 +1783,7 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { gobParams.extraData = 0; gobParams.objDesc = 0; - gobParams.retVarPtr = (int32 *) VAR_ADDRESS(59); + gobParams.retVarPtr.set(*_vm->_inter->_variables, 236); cmd = load16(); _vm->_global->_inter_execPtr += 2; @@ -2268,49 +2277,49 @@ bool Inter_v1::o1_manageDataFile(OpFuncParams ¶ms) { void Inter_v1::o1_setState(OpGobParams ¶ms) { params.objDesc->state = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemStateVarPtr = params.extraData; + _vm->_goblin->_destItemStateVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setCurFrame(OpGobParams ¶ms) { params.objDesc->curFrame = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemFrameVarPtr = params.extraData; + _vm->_goblin->_destItemFrameVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setNextState(OpGobParams ¶ms) { params.objDesc->nextState = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemNextStateVarPtr = params.extraData; + _vm->_goblin->_destItemNextStateVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setMultState(OpGobParams ¶ms) { params.objDesc->multState = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemMultStateVarPtr = params.extraData; + _vm->_goblin->_destItemMultStateVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setOrder(OpGobParams ¶ms) { params.objDesc->order = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemOrderVarPtr = params.extraData; + _vm->_goblin->_destItemOrderVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setActionStartState(OpGobParams ¶ms) { params.objDesc->actionStartState = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemActStartStVarPtr = params.extraData; + _vm->_goblin->_destItemActStartStVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setCurLookDir(OpGobParams ¶ms) { params.objDesc->curLookDir = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemLookDirVarPtr = params.extraData; + _vm->_goblin->_destItemLookDirVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setType(OpGobParams ¶ms) { params.objDesc->type = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemTypeVarPtr = params.extraData; + _vm->_goblin->_destItemTypeVarPtr = (uint32) params.extraData; if (params.extraData == 0) params.objDesc->toRedraw = 1; @@ -2319,107 +2328,107 @@ void Inter_v1::o1_setType(OpGobParams ¶ms) { void Inter_v1::o1_setNoTick(OpGobParams ¶ms) { params.objDesc->noTick = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemNoTickVarPtr = params.extraData; + _vm->_goblin->_destItemNoTickVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setPickable(OpGobParams ¶ms) { params.objDesc->pickable = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemPickableVarPtr = params.extraData; + _vm->_goblin->_destItemPickableVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setXPos(OpGobParams ¶ms) { params.objDesc->xPos = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemScrXVarPtr = params.extraData; + _vm->_goblin->_destItemScrXVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setYPos(OpGobParams ¶ms) { params.objDesc->yPos = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemScrYVarPtr = params.extraData; + _vm->_goblin->_destItemScrYVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setDoAnim(OpGobParams ¶ms) { params.objDesc->doAnim = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemDoAnimVarPtr = params.extraData; + _vm->_goblin->_destItemDoAnimVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setRelaxTime(OpGobParams ¶ms) { params.objDesc->relaxTime = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemRelaxVarPtr = params.extraData; + _vm->_goblin->_destItemRelaxVarPtr = (uint32) params.extraData; } void Inter_v1::o1_setMaxTick(OpGobParams ¶ms) { params.objDesc->maxTick = params.extraData; if (params.objDesc == _vm->_goblin->_actDestItemDesc) - *_vm->_goblin->_destItemMaxTickVarPtr = params.extraData; + _vm->_goblin->_destItemMaxTickVarPtr = (uint32) params.extraData; } void Inter_v1::o1_getState(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->state; + params.retVarPtr = (uint32) params.objDesc->state; } void Inter_v1::o1_getCurFrame(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->curFrame; + params.retVarPtr = (uint32) params.objDesc->curFrame; } void Inter_v1::o1_getNextState(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->nextState; + params.retVarPtr = (uint32) params.objDesc->nextState; } void Inter_v1::o1_getMultState(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->multState; + params.retVarPtr = (uint32) params.objDesc->multState; } void Inter_v1::o1_getOrder(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->order; + params.retVarPtr = (uint32) params.objDesc->order; } void Inter_v1::o1_getActionStartState(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->actionStartState; + params.retVarPtr = (uint32) params.objDesc->actionStartState; } void Inter_v1::o1_getCurLookDir(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->curLookDir; + params.retVarPtr = (uint32) params.objDesc->curLookDir; } void Inter_v1::o1_getType(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->type; + params.retVarPtr = (uint32) params.objDesc->type; } void Inter_v1::o1_getNoTick(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->noTick; + params.retVarPtr = (uint32) params.objDesc->noTick; } void Inter_v1::o1_getPickable(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->pickable; + params.retVarPtr = (uint32) params.objDesc->pickable; } void Inter_v1::o1_getObjMaxFrame(OpGobParams ¶ms) { - *params.retVarPtr = _vm->_goblin->getObjMaxFrame(params.objDesc); + params.retVarPtr = (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc); } void Inter_v1::o1_getXPos(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->xPos; + params.retVarPtr = (uint32) params.objDesc->xPos; } void Inter_v1::o1_getYPos(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->yPos; + params.retVarPtr = (uint32) params.objDesc->yPos; } void Inter_v1::o1_getDoAnim(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->doAnim; + params.retVarPtr = (uint32) params.objDesc->doAnim; } void Inter_v1::o1_getRelaxTime(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->relaxTime; + params.retVarPtr = (uint32) params.objDesc->relaxTime; } void Inter_v1::o1_getMaxTick(OpGobParams ¶ms) { - *params.retVarPtr = params.objDesc->maxTick; + params.retVarPtr = (uint32) params.objDesc->maxTick; } void Inter_v1::o1_manipulateMap(OpGobParams ¶ms) { @@ -2435,9 +2444,9 @@ void Inter_v1::o1_getItem(OpGobParams ¶ms) { int16 yPos = load16(); if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) - *params.retVarPtr = (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8; + params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8); else - *params.retVarPtr = _vm->_map->_itemsMap[yPos][xPos]; + params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos]; } void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) { @@ -2460,9 +2469,9 @@ void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) { yPos = VAR(yPos); if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0) - *params.retVarPtr = (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8; + params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8); else - *params.retVarPtr = _vm->_map->_itemsMap[yPos][xPos]; + params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos]; } void Inter_v1::o1_setPassMap(OpGobParams ¶ms) { @@ -2500,11 +2509,11 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { params.objDesc->curFrame = 0; params.objDesc->state = 21; if (_vm->_goblin->_currentGoblin == item) { - *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos; + _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos; - *_vm->_goblin->_curGobFrameVarPtr = 0; - *_vm->_goblin->_curGobStateVarPtr = 18; + _vm->_goblin->_curGobFrameVarPtr = 0; + _vm->_goblin->_curGobStateVarPtr = 18; _vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x; _vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y; } @@ -2512,12 +2521,12 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { void Inter_v1::o1_getGoblinPosXH(OpGobParams ¶ms) { int16 item = load16(); - *params.retVarPtr = _vm->_goblin->_gobPositions[item].x >> 1; + params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1); } void Inter_v1::o1_getGoblinPosYH(OpGobParams ¶ms) { int16 item = load16(); - *params.retVarPtr = _vm->_goblin->_gobPositions[item].y >> 1; + params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1); } void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { @@ -2539,14 +2548,14 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { params.objDesc->xPos = animLayer->posX; params.objDesc->yPos = animLayer->posY; - *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos; - *_vm->_goblin->_curGobFrameVarPtr = 0; - *_vm->_goblin->_curGobStateVarPtr = params.objDesc->state; - *_vm->_goblin->_curGobNextStateVarPtr = params.objDesc->nextState; - *_vm->_goblin->_curGobMultStateVarPtr = params.objDesc->multState; - *_vm->_goblin->_curGobMaxFrameVarPtr = - _vm->_goblin->getObjMaxFrame(params.objDesc); + _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos; + _vm->_goblin->_curGobFrameVarPtr = 0; + _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state; + _vm->_goblin->_curGobNextStateVarPtr = (uint32) params.objDesc->nextState; + _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState; + _vm->_goblin->_curGobMaxFrameVarPtr = + (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc); _vm->_goblin->_noPick = 1; return; } @@ -2573,12 +2582,12 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { _vm->_goblin->_pressedMapY = yPos; _vm->_map->_curGoblinY = yPos; - *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos; - *_vm->_goblin->_curGobFrameVarPtr = 0; - *_vm->_goblin->_curGobStateVarPtr = 21; - *_vm->_goblin->_curGobNextStateVarPtr = 21; - *_vm->_goblin->_curGobMultStateVarPtr = -1; + _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos; + _vm->_goblin->_curGobFrameVarPtr = 0; + _vm->_goblin->_curGobStateVarPtr = 21; + _vm->_goblin->_curGobNextStateVarPtr = 21; + _vm->_goblin->_curGobMultStateVarPtr = (uint32) -1; _vm->_goblin->_noPick = 0; } @@ -2598,11 +2607,11 @@ void Inter_v1::o1_setItemIndInPocket(OpGobParams ¶ms) { } void Inter_v1::o1_getItemIdInPocket(OpGobParams ¶ms) { - *params.retVarPtr = _vm->_goblin->_itemIdInPocket; + params.retVarPtr = (uint32) _vm->_goblin->_itemIdInPocket; } void Inter_v1::o1_getItemIndInPocket(OpGobParams ¶ms) { - *params.retVarPtr = _vm->_goblin->_itemIndInPocket; + params.retVarPtr = (uint32) _vm->_goblin->_itemIndInPocket; } void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { @@ -2632,10 +2641,10 @@ void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { params.objDesc->state = 21; if (_vm->_goblin->_currentGoblin == item) { - *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos; - *_vm->_goblin->_curGobFrameVarPtr = 0; - *_vm->_goblin->_curGobStateVarPtr = 18; + _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos; + _vm->_goblin->_curGobFrameVarPtr = 0; + _vm->_goblin->_curGobStateVarPtr = 18; _vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x; _vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y; @@ -2659,11 +2668,11 @@ void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) { params.objDesc->yPos = animLayer->posY; if (item == _vm->_goblin->_currentGoblin) { - *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos; - *_vm->_goblin->_curGobFrameVarPtr = 0; - *_vm->_goblin->_curGobStateVarPtr = params.objDesc->state; - *_vm->_goblin->_curGobMultStateVarPtr = params.objDesc->multState; + _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos; + _vm->_goblin->_curGobFrameVarPtr = 0; + _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state; + _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState; } } @@ -2686,13 +2695,13 @@ void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) { params.objDesc->toRedraw = 1; params.objDesc->type = 0; if (params.objDesc == _vm->_goblin->_actDestItemDesc) { - *_vm->_goblin->_destItemScrXVarPtr = params.objDesc->xPos; - *_vm->_goblin->_destItemScrYVarPtr = params.objDesc->yPos; + _vm->_goblin->_destItemScrXVarPtr = (uint32) params.objDesc->xPos; + _vm->_goblin->_destItemScrYVarPtr = (uint32) params.objDesc->yPos; - *_vm->_goblin->_destItemStateVarPtr = params.objDesc->state; - *_vm->_goblin->_destItemNextStateVarPtr = -1; - *_vm->_goblin->_destItemMultStateVarPtr = -1; - *_vm->_goblin->_destItemFrameVarPtr = 0; + _vm->_goblin->_destItemStateVarPtr = (uint32) params.objDesc->state; + _vm->_goblin->_destItemNextStateVarPtr = (uint32) -1; + _vm->_goblin->_destItemMultStateVarPtr = (uint32) -1; + _vm->_goblin->_destItemFrameVarPtr = 0; } } @@ -2712,12 +2721,12 @@ void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) { void Inter_v1::o1_getGoblinPosX(OpGobParams ¶ms) { int16 item = load16(); - *params.retVarPtr = _vm->_goblin->_gobPositions[item].x; + params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x; } void Inter_v1::o1_getGoblinPosY(OpGobParams ¶ms) { int16 item = load16(); - *params.retVarPtr = _vm->_goblin->_gobPositions[item].y; + params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y; } void Inter_v1::o1_clearPathExistence(OpGobParams ¶ms) { @@ -2741,9 +2750,9 @@ void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) { params.objDesc = _vm->_goblin->_objects[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, _vm->_goblin->_goblins[item])) - *params.retVarPtr = 1; + params.retVarPtr = 1; else - *params.retVarPtr = 0; + params.retVarPtr = 0; } void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { @@ -2753,9 +2762,9 @@ void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { params.objDesc = _vm->_goblin->_goblins[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, _vm->_goblin->_goblins[item])) - *params.retVarPtr = 1; + params.retVarPtr = 1; else - *params.retVarPtr = 0; + params.retVarPtr = 0; } void Inter_v1::o1_setItemPos(OpGobParams ¶ms) { @@ -2886,7 +2895,7 @@ void Inter_v1::o1_initGoblin(OpGobParams ¶ms) { _vm->_map->_destY = _vm->_goblin->_gobPositions[0].y; _vm->_goblin->_gobDestY = _vm->_goblin->_gobPositions[0].y; - *_vm->_goblin->_curGobVarPtr = 0; + _vm->_goblin->_curGobVarPtr = 0; _vm->_goblin->_pathExistence = 0; _vm->_goblin->_readyToAct = 0; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index d8c33fcce6..2f1d2ec0be 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -880,9 +880,15 @@ void Inter_v2::o2_initMult() { _vm->_mult->clearObjectVideos(); + for (int i = 0; i < _vm->_mult->_objCount; i++) { + delete _vm->_mult->_objects[i].pPosX; + delete _vm->_mult->_objects[i].pPosY; + } + delete[] _vm->_mult->_objects; delete[] _vm->_mult->_renderObjs; delete[] _vm->_mult->_orderArray; + _vm->_mult->_objects = 0; _vm->_mult->_renderObjs = 0; _vm->_mult->_orderArray = 0; @@ -907,8 +913,8 @@ void Inter_v2::o2_initMult() { uint32 offPosY = i * 4 + (posYVar / 4) * 4; uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; - _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX); - _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY); + _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX); + _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY); _vm->_mult->_objects[i].pAnimData = (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim, @@ -1046,7 +1052,7 @@ void Inter_v2::o2_loadMultObject() { } else if ((objAnim.animType != 100) && (objAnim.animType != 101)) { - if ((*(obj.pPosX) == -1234) && (*(obj.pPosY) == -4321)) { + if ((((int32) *(obj.pPosX)) == -1234) && (((int32) *(obj.pPosY)) == -4321)) { if (obj.videoSlot > 0) _vm->_vidPlayer->slotClose(obj.videoSlot - 1); diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 3d6a7942f9..b9373d48b3 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -93,12 +93,18 @@ Mult::Mult(GobEngine *vm) : _vm(vm) { } Mult::~Mult() { + if (_objects) + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + delete[] _objects; delete[] _orderArray; delete[] _renderData; delete[] _renderObjs; - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; delete _multData; } @@ -123,6 +129,12 @@ void Mult::freeAll(void) { void Mult::freeMult() { clearObjectVideos(); + if (_objects) + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + delete[] _objects; delete[] _renderData; delete[] _renderObjs; @@ -203,11 +215,17 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, if (_animDataAllocated) { clearObjectVideos(); + if (_objects) + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + delete[] _objects; delete[] _renderData; delete[] _renderObjs; - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; delete[] _orderArray; diff --git a/engines/gob/mult.h b/engines/gob/mult.h index aaf2e2826c..3bb3af17b3 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -27,6 +27,7 @@ #define GOB_MULT_H #include "gob/video.h" +#include "gob/variables.h" namespace Gob { @@ -77,8 +78,8 @@ public: } PACKED_STRUCT; struct Mult_Object { - int32 *pPosX; - int32 *pPosY; + VariableReference *pPosX; + VariableReference *pPosY; Mult_AnimData *pAnimData; int16 tick; int16 lastLeft; @@ -267,8 +268,8 @@ protected: bool _doPalSubst; - int32 *_animArrayX; - int32 *_animArrayY; + Variables *_animArrayX; + Variables *_animArrayY; Mult_AnimData *_animArrayData; int16 _palKeyIndex; diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index 22683437e7..a369e7d297 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -216,10 +216,16 @@ void Mult_v1::freeMultKeys() { if (_animDataAllocated) { clearObjectVideos(); + if (_objects) + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + delete[] _objects; delete[] _renderData; - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; _objects = 0; @@ -263,6 +269,14 @@ void Mult_v1::playMultInit() { _oldPalette = _vm->_global->_pPaletteDesc->vgaPal; if (!_animSurf) { + if (_objects) + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + + delete[] _objects; + _vm->_util->setFrameRate(_multData->frameRate); _animTop = 0; _animLeft = 0; @@ -270,30 +284,27 @@ void Mult_v1::playMultInit() { _animHeight = 200; _objCount = 4; - delete[] _objects; delete[] _renderData; - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; _objects = new Mult_Object[_objCount]; _renderData = new int16[9 * _objCount]; - _animArrayX = new int32[_objCount]; - _animArrayY = new int32[_objCount]; + _animArrayX = new VariablesLE(_objCount * 4); + _animArrayY = new VariablesLE(_objCount * 4); _animArrayData = new Mult_AnimData[_objCount]; memset(_objects, 0, _objCount * sizeof(Mult_Object)); memset(_renderData, 0, _objCount * 9 * sizeof(int16)); - memset(_animArrayX, 0, _objCount * sizeof(int32)); - memset(_animArrayY, 0, _objCount * sizeof(int32)); memset(_animArrayData, 0, _objCount * sizeof(Mult_AnimData)); for (_counter = 0; _counter < _objCount; _counter++) { Mult_Object &multObj = _objects[_counter]; Mult_AnimData &animData = _animArrayData[_counter]; - multObj.pPosX = (int32 *) &_animArrayX[_counter]; - multObj.pPosY = (int32 *) &_animArrayY[_counter]; + multObj.pPosX = new VariableReference(*_animArrayX, _counter * 4); + multObj.pPosY = new VariableReference(*_animArrayY, _counter * 4); multObj.pAnimData = &animData; animData.isStatic = 1; diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 3a83ac1867..20a81174e5 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -329,8 +329,8 @@ void Mult_v2::freeMultKeys() { if (_animDataAllocated) { freeMult(); - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; _animArrayX = 0; @@ -510,6 +510,13 @@ void Mult_v2::playMultInit() { if (!_animSurf) { int16 width, height; + for (int i = 0; i < _objCount; i++) { + delete _objects[i].pPosX; + delete _objects[i].pPosY; + } + + delete[] _objects; + _vm->_util->setFrameRate(_multData->frameRate); _animTop = 0; _animLeft = 0; @@ -517,33 +524,30 @@ void Mult_v2::playMultInit() { _animHeight = _vm->_video->_surfHeight; _objCount = 4; - delete[] _objects; delete[] _orderArray; delete[] _renderObjs; - delete[] _animArrayX; - delete[] _animArrayY; + delete _animArrayX; + delete _animArrayY; delete[] _animArrayData; _objects = new Mult_Object[_objCount]; _orderArray = new int8[_objCount]; _renderObjs = new Mult_Object*[_objCount]; - _animArrayX = new int32[_objCount]; - _animArrayY = new int32[_objCount]; + _animArrayX = new VariablesLE(_objCount * 4); + _animArrayY = new VariablesLE(_objCount * 4); _animArrayData = new Mult_AnimData[_objCount]; memset(_objects, 0, _objCount * sizeof(Mult_Object)); memset(_orderArray, 0, _objCount * sizeof(int8)); memset(_renderObjs, 0, _objCount * sizeof(Mult_Object *)); - memset(_animArrayX, 0, _objCount * sizeof(int32)); - memset(_animArrayY, 0, _objCount * sizeof(int32)); memset(_animArrayData, 0, _objCount * sizeof(Mult_AnimData)); for (_counter = 0; _counter < _objCount; _counter++) { Mult_Object &multObj = _objects[_counter]; Mult_AnimData &animData = _animArrayData[_counter]; - multObj.pPosX = (int32 *) &_animArrayX[_counter]; - multObj.pPosY = (int32 *) &_animArrayY[_counter]; + multObj.pPosX = new VariableReference(*_animArrayX, _counter * 4); + multObj.pPosY = new VariableReference(*_animArrayY, _counter * 4); multObj.pAnimData = &animData; animData.isStatic = 1; diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h index b59510e4bb..07b5a737db 100644 --- a/engines/gob/sound/sound.h +++ b/engines/gob/sound/sound.h @@ -144,4 +144,4 @@ private: } // End of namespace Gob -#endif // GOB_SOUND_H +#endif // GOB_SOUND_SOUND_H diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp index 0eea2f6547..805aaeb839 100644 --- a/engines/gob/variables.cpp +++ b/engines/gob/variables.cpp @@ -308,4 +308,62 @@ uint32 VariablesBE::read32(const byte *buf) const { return READ_BE_UINT32(buf); } +VariableReference::VariableReference() { + _vars = 0; + _offset = 0; +} + +VariableReference::VariableReference(Variables &vars, uint32 offset, Variables::Type type) { + set(vars, offset, type); +} + +VariableReference::~VariableReference() { +} + +void VariableReference::set(Variables &vars, uint32 offset, Variables::Type type) { + _vars = &vars; + _offset = offset; + _type = type; +} + +VariableReference &VariableReference::operator=(uint32 value) { + if (_vars) { + switch (_type) { + case Variables::kVariableType8: + _vars->writeOff8(_offset, (uint8) value); + break; + case Variables::kVariableType16: + _vars->writeOff16(_offset, (uint16) value); + break; + case Variables::kVariableType32: + _vars->writeOff32(_offset, value); + break; + } + } + return *this; +} + +VariableReference::operator uint32() { + if (_vars) { + switch (_type) { + case Variables::kVariableType8: + return (uint32) _vars->readOff8(_offset); + case Variables::kVariableType16: + return (uint32) _vars->readOff16(_offset); + case Variables::kVariableType32: + return _vars->readOff32(_offset); + } + } + + return 0; +} + +VariableReference &VariableReference::operator+=(uint32 value) { + return (*this = (*this + value)); +} + +VariableReference &VariableReference::operator*=(uint32 value) { + return (*this = (*this * value)); +} + } // End of namespace Gob diff --git a/engines/gob/variables.h b/engines/gob/variables.h index 5989ed38ee..32f160a6bd 100644 --- a/engines/gob/variables.h +++ b/engines/gob/variables.h @@ -30,6 +30,12 @@ namespace Gob { class Variables { public: + enum Type { + kVariableType8, + kVariableType16, + kVariableType32 + }; + Variables(uint32 size); virtual ~Variables(); @@ -142,6 +148,26 @@ protected: uint32 read32(const byte *buf) const; }; +class VariableReference { + public: + VariableReference(); + VariableReference(Variables &vars, uint32 offset, + Variables::Type type = Variables::kVariableType32); + ~VariableReference(); + + void set(Variables &vars, uint32 offset, Variables::Type type = Variables::kVariableType32); + + VariableReference &operator=(uint32 value); + VariableReference &operator+=(uint32 value); + VariableReference &operator*=(uint32 value); + operator uint32(); + + private: + Variables *_vars; + uint32 _offset; + Variables::Type _type; +}; + } // End of namespace Gob #endif // GOB_VARIABLES_H -- cgit v1.2.3 From 5de579930d9ff33c2e7eeb1c267d3ef61227e558 Mon Sep 17 00:00:00 2001 From: Bertrand Augereau Date: Sat, 12 Jul 2008 20:35:44 +0000 Subject: Minor constness fix to help with aliasing svn-id: r33017 --- engines/gob/driver_vga.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp index f68ce47783..2d3a10b570 100644 --- a/engines/gob/driver_vga.cpp +++ b/engines/gob/driver_vga.cpp @@ -112,7 +112,7 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, if ((width < 1) || (height < 1)) return; - byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left; + const byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left; byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x; uint32 size = width * height; -- cgit v1.2.3 From 9c2d96530be10b2f8badb500330f744bd6cdc937 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jul 2008 03:30:14 +0000 Subject: Properly implemented the OFF command. The new rendering order for graphics let this mistake finally surface. svn-id: r33021 --- engines/parallaction/exec.h | 2 ++ engines/parallaction/exec_ns.cpp | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h index f41ce52302..887d6be526 100644 --- a/engines/parallaction/exec.h +++ b/engines/parallaction/exec.h @@ -68,6 +68,8 @@ class CommandExec_ns : public CommandExec { Parallaction_ns *_vm; protected: + void updateGetZone(ZonePtr z, bool visible); + DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid); DECLARE_UNQUALIFIED_COMMAND_OPCODE(set); DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear); diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 9a93197f04..4ee0aca6c1 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -254,27 +254,34 @@ DECLARE_COMMAND_OPCODE(close) { } } +void CommandExec_ns::updateGetZone(ZonePtr z, bool visible) { + if (!z) { + return; + } + + if ((z->_type & 0xFFFF) == kZoneGet) { + _vm->_gfx->showGfxObj(z->u.get->gfxobj, visible); + } +} DECLARE_COMMAND_OPCODE(on) { ZonePtr z = _ctxt.cmd->u._zone; - // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing - // the pointer to get structure members, thus leading to crashes in systems with memory - // protection. - // As a side note, the overwritten address is the 5th entry in the DOS interrupt table - // (print screen handler): this suggests that a system would hang when the print screen - // key is pressed after playing Nippon Safes, provided that this code path is taken. + if (z) { z->_flags &= ~kFlagsRemove; z->_flags |= kFlagsActive; - if ((z->_type & 0xFFFF) == kZoneGet) { - _vm->_gfx->showGfxObj(z->u.get->gfxobj, true); - } + updateGetZone(z, true); } } DECLARE_COMMAND_OPCODE(off) { - _ctxt.cmd->u._zone->_flags |= kFlagsRemove; + ZonePtr z = _ctxt.cmd->u._zone; + + if (z) { + _ctxt.cmd->u._zone->_flags |= kFlagsRemove; + updateGetZone(z, false); + } } -- cgit v1.2.3 From 2a80bd0678c29787dd9959cf66842f2e0483327e Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jul 2008 03:39:42 +0000 Subject: Cleanup and improved debugging output for CommandExec::run() svn-id: r33022 --- engines/parallaction/exec_ns.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 4ee0aca6c1..d1cfb14557 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -418,28 +418,38 @@ label1: void CommandExec::run(CommandList& list, ZonePtr z) { - if (list.size() == 0) + if (list.size() == 0) { + debugC(3, kDebugExec, "runCommands: nothing to do"); return; + } + + debugC(3, kDebugExec, "runCommands starting"); - debugC(3, kDebugExec, "runCommands"); + uint32 useFlags = 0; + bool useLocalFlags; CommandList::iterator it = list.begin(); for ( ; it != list.end(); it++) { - - CommandPtr cmd = *it; - uint32 v8 = _vm->getLocationFlags(); - if (_engineFlags & kEngineQuit) break; + CommandPtr cmd = *it; + if (cmd->_flagsOn & kFlagsGlobal) { - v8 = _commandFlags | kFlagsGlobal; + useFlags = _commandFlags | kFlagsGlobal; + useLocalFlags = false; + } else { + useFlags = _vm->getLocationFlags(); + useLocalFlags = true; } - debugC(3, kDebugExec, "runCommands[%i] (on: %x, off: %x)", cmd->_id, cmd->_flagsOn, cmd->_flagsOff); + bool onMatch = (cmd->_flagsOn & useFlags) == cmd->_flagsOn; + bool offMatch = (cmd->_flagsOff & ~useFlags) == cmd->_flagsOff; + + debugC(3, kDebugExec, "runCommands[%i] (on: %x, off: %x), (%s = %x)", cmd->_id, cmd->_flagsOn, cmd->_flagsOff, + useLocalFlags ? "LOCALFLAGS" : "GLOBALFLAGS", useFlags); - if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue; - if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue; + if (!onMatch || !offMatch) continue; _ctxt.z = z; _ctxt.cmd = cmd; -- cgit v1.2.3 From 059936854c897c8090a776a4af23965e72fa48f9 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jul 2008 06:27:31 +0000 Subject: Cleanup of walk code. svn-id: r33023 --- engines/parallaction/parallaction.cpp | 2 +- engines/parallaction/parallaction.h | 12 ++--- engines/parallaction/walk.cpp | 96 ++++++++++++++++------------------- 3 files changed, 50 insertions(+), 60 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 295f10820f..d03d61fc59 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -390,7 +390,7 @@ void Parallaction::runGame() { if (_char._ani->gfxobj) { _char._ani->gfxobj->z = _char._ani->_z; } - walk(); + walk(_char); drawAnimations(); } diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 13c56cf57b..2d0a201686 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -261,9 +261,9 @@ public: void pauseJobs(); void resumeJobs(); - void finalizeWalk(WalkNodeList *list); - int16 selectWalkFrame(const Common::Point& pos, const WalkNodePtr from); - void clipMove(Common::Point& pos, const WalkNodePtr from); + void finalizeWalk(Character &character); + int16 selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to); + void clipMove(Common::Point& pos, const WalkNodePtr to); ZonePtr findZone(const char *name); ZonePtr hitZone(uint32 type, uint16 x, uint16 y); @@ -357,7 +357,7 @@ protected: // members void displayComment(ExamineData *data); - uint16 checkDoor(); + void checkDoor(Character &character); void freeCharacter(); @@ -379,7 +379,7 @@ public: void updateDoor(ZonePtr z); - virtual void walk() = 0; + virtual void walk(Character &character) = 0; virtual void drawAnimations() = 0; void beep(); @@ -575,7 +575,7 @@ private: const Callable *_callables; protected: - void walk(); + void walk(Character &character); void drawAnimations(); void parseLocation(const char *filename); diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 7d74dd0e0a..7a16960cbf 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -27,9 +27,11 @@ namespace Parallaction { +// should be reset on location switch static uint16 _doorData1 = 1000; static ZonePtr _zoneTrap; +// should be reset on character switch static uint16 walkData1 = 0; static uint16 walkData2 = 0; // next walk frame @@ -259,30 +261,30 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNodePtr Node) { return 1; } -void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr from) { +void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr to) { - if ((pos.x < from->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) { - pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x; + if ((pos.x < to->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) { + pos.x = (pos.x + 2 < to->_x) ? pos.x + 2 : to->_x; } - if ((pos.x > from->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) { - pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x; + if ((pos.x > to->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) { + pos.x = (pos.x - 2 > to->_x) ? pos.x - 2 : to->_x; } - if ((pos.y < from->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) { - pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y; + if ((pos.y < to->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) { + pos.y = (pos.y + 2 <= to->_y) ? pos.y + 2 : to->_y; } - if ((pos.y > from->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) { - pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y; + if ((pos.y > to->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) { + pos.y = (pos.y - 2 >= to->_y) ? pos.y - 2 : to->_y; } return; } -int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr from) { +int16 Parallaction::selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to) { - Common::Point dist(from->_x - pos.x, from->_y - pos.y); + Common::Point dist(to->_x - pos.x, to->_y - pos.y); if (dist.x < 0) dist.x = -dist.x; @@ -293,14 +295,14 @@ int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr // walk frame selection int16 v16; - if (_char._ani->getFrameNum() == 20) { + if (character._ani->getFrameNum() == 20) { if (dist.x > dist.y) { - walkData2 = (from->_x > pos.x) ? 0 : 7; + walkData2 = (to->_x > pos.x) ? 0 : 7; walkData1 %= 12; v16 = walkData1 / 2; } else { - walkData2 = (from->_y > pos.y) ? 14 : 17; + walkData2 = (to->_y > pos.y) ? 14 : 17; walkData1 %= 8; v16 = walkData1 / 4; } @@ -308,11 +310,11 @@ int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr } else { if (dist.x > dist.y) { - walkData2 = (from->_x > pos.x) ? 0 : 9; + walkData2 = (to->_x > pos.x) ? 0 : 9; walkData1 %= 16; v16 = walkData1 / 2; } else { - walkData2 = (from->_y > pos.y) ? 18 : 21; + walkData2 = (to->_y > pos.y) ? 18 : 21; walkData1 %= 8; v16 = walkData1 / 4; } @@ -322,9 +324,7 @@ int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr return v16; } -uint16 Parallaction::checkDoor() { -// printf("checkDoor()..."); - +void Parallaction::checkDoor(Character &character) { if (_currentLocationIndex != _doorData1) { _doorData1 = _currentLocationIndex; _zoneTrap = nullZonePtr; @@ -334,7 +334,7 @@ uint16 Parallaction::checkDoor() { Common::Point foot; - _char.getFoot(foot); + character.getFoot(foot); ZonePtr z = hitZone(kZoneDoor, foot.x, foot.y); if (z) { @@ -351,7 +351,7 @@ uint16 Parallaction::checkDoor() { } } - _char.getFoot(foot); + character.getFoot(foot); z = hitZone(kZoneTrap, foot.x, foot.y); if (z) { @@ -367,61 +367,51 @@ uint16 Parallaction::checkDoor() { _zoneTrap = nullZonePtr; } -// printf("done\n"); - - _char._ani->_frame = walkData2; - return _char._ani->_frame; } -void Parallaction::finalizeWalk(WalkNodeList *list) { - checkDoor(); - delete list; +void Parallaction::finalizeWalk(Character &character) { + checkDoor(character); + delete character._walkPath; + character._walkPath = 0; + + character._ani->_frame = walkData2; } -void Parallaction_ns::walk() { +void Parallaction_ns::walk(Character &character) { if ((_engineFlags & kEngineWalking) == 0) { return; } - WalkNodeList *list = _char._walkPath; + Common::Point curPos; + character.getFoot(curPos); - _char._ani->_oldPos.x = _char._ani->_left; - _char._ani->_oldPos.y = _char._ani->_top; + WalkNodeList::iterator it = character._walkPath->begin(); - Common::Point pos; - _char.getFoot(pos); - - WalkNodeList::iterator it = list->begin(); - - if (it != list->end()) { - if ((*it)->_x == pos.x && (*it)->_y == pos.y) { + if (it != character._walkPath->end()) { + if ((*it)->_x == curPos.x && (*it)->_y == curPos.y) { debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it)->_x, (*it)->_y); - it = list->erase(it); + it = character._walkPath->erase(it); } } - if (it == list->end()) { + if (it == character._walkPath->end()) { debugC(1, kDebugWalk, "walk reached last node"); -// j->_finished = 1; - finalizeWalk(list); + finalizeWalk(character); return; } - _char._walkPath = list; // selectWalkFrame must be performed before position is changed by clipMove - int16 v16 = selectWalkFrame(pos, *it); - clipMove(pos, *it); - - _char.setFoot(pos); + int16 walkFrame = selectWalkFrame(character, curPos, *it); - Common::Point newpos(_char._ani->_left, _char._ani->_top); + Common::Point newPos(curPos); + clipMove(newPos, *it); + character.setFoot(newPos); - if (newpos == _char._ani->_oldPos) { + if (newPos == curPos) { debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle"); -// j->_finished = 1; - finalizeWalk(list); + finalizeWalk(character); } else { - _char._ani->_frame = v16 + walkData2 + 1; + character._ani->_frame = walkFrame + walkData2 + 1; } return; -- cgit v1.2.3 From ba5f14692febafdad9c58be67eb6aa87b9afba2f Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 13 Jul 2008 12:20:24 +0000 Subject: - fix for bug #2016965: KYRA: does not compile in MSVC71 svn-id: r33030 --- engines/kyra/sound_towns.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 6be2cae7a4..e96cef735c 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -34,11 +34,6 @@ #include "common/util.h" -#ifdef _MSC_VER -#define _USE_MATH_DEFINES -#endif -#include - #define EUPHONY_FADEOUT_TICKS 600 namespace Kyra { @@ -2657,7 +2652,7 @@ void TownsPC98_OpnDriver::generateTables() { delete [] _oprSinTbl; _oprSinTbl = new uint32[1024]; for (int i = 0; i < 1024; i++) { - double val = sin((double) (((i << 1) + 1) * M_PI / 1024.0)); + double val = sin((double) (((i << 1) + 1) * PI / 1024.0)); double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0; int32 i_dcb = (int32)(2.0 * d_dcb); i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1); -- cgit v1.2.3 From ef95c6ff70c1b428ab1d086a9b0b551fc82c8451 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jul 2008 13:04:36 +0000 Subject: More refactoring of walk code. svn-id: r33033 --- engines/parallaction/parallaction.cpp | 56 +++++++++++++ engines/parallaction/parallaction.h | 10 ++- engines/parallaction/parallaction_ns.cpp | 2 + engines/parallaction/walk.cpp | 133 ++++++++++--------------------- 4 files changed, 107 insertions(+), 94 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index d03d61fc59..3cde21b49c 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -503,6 +503,34 @@ void Parallaction::freeZones() { } +enum { + WALK_LEFT = 0, + WALK_RIGHT = 1, + WALK_DOWN = 2, + WALK_UP = 3 +}; + +struct WalkFrames { + int16 stillFrame[4]; + int16 firstWalkFrame[4]; + int16 numWalkFrames[4]; + int16 frameRepeat[4]; +}; + +WalkFrames _char20WalkFrames = { + { 0, 7, 14, 17 }, + { 1, 8, 15, 18 }, + { 6, 6, 2, 2 }, + { 2, 2, 4, 4 } +}; + +WalkFrames _char24WalkFrames = { + { 0, 9, 18, 21 }, + { 1, 10, 19, 22 }, + { 8, 8, 2, 2 }, + { 2, 2, 4, 4 } +}; + const char Character::_prefixMini[] = "mini"; const char Character::_suffixTras[] = "tras"; const char Character::_empty[] = "\0"; @@ -513,6 +541,9 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder( _head = NULL; _objs = NULL; + _direction = WALK_DOWN; + _step = 0; + _dummy = false; _ani->_left = 150; @@ -633,4 +664,29 @@ void Parallaction::scheduleLocationSwitch(const char *location) { } + + + +void Character::updateDirection(const Common::Point& pos, const Common::Point& to) { + + Common::Point dist(to.x - pos.x, to.y - pos.y); + WalkFrames *frames = (_ani->getFrameNum() == 20) ? &_char20WalkFrames : &_char24WalkFrames; + + _step++; + + if (dist.x == 0 && dist.y == 0) { + _ani->_frame = frames->stillFrame[_direction]; + return; + } + + if (dist.x < 0) + dist.x = -dist.x; + if (dist.y < 0) + dist.y = -dist.y; + + _direction = (dist.x > dist.y) ? ((to.x > pos.x) ? WALK_LEFT : WALK_RIGHT) : ((to.y > pos.y) ? WALK_DOWN : WALK_UP); + _ani->_frame = frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction]; +} + + } // namespace Parallaction diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 2d0a201686..ef2dad9884 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -229,12 +229,17 @@ protected: static const char _suffixTras[]; static const char _empty[]; + int16 _direction, _step; + public: void setName(const char *name); const char *getName() const; const char *getBaseName() const; const char *getFullName() const; bool dummy() const; + + void updateDirection(const Common::Point& pos, const Common::Point& to); + }; @@ -263,7 +268,7 @@ public: void finalizeWalk(Character &character); int16 selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to); - void clipMove(Common::Point& pos, const WalkNodePtr to); + void clipMove(Common::Point& pos, const Common::Point& to); ZonePtr findZone(const char *name); ZonePtr hitZone(uint32 type, uint16 x, uint16 y); @@ -357,7 +362,7 @@ protected: // members void displayComment(ExamineData *data); - void checkDoor(Character &character); + void checkDoor(const Common::Point &foot); void freeCharacter(); @@ -384,6 +389,7 @@ public: void beep(); + ZonePtr _zoneTrap; public: // const char **_zoneFlagNamesRes; diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 850123de97..d1b25f189a 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -305,6 +305,8 @@ void Parallaction_ns::changeLocation(char *location) { _gfx->hideFloatingLabel(); _gfx->freeLabels(); + _zoneTrap = nullZonePtr; + _input->stopHovering(); if (_engineFlags & kEngineBlockInput) { setArrowCursor(); diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 7a16960cbf..40dfddb903 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -27,14 +27,6 @@ namespace Parallaction { -// should be reset on location switch -static uint16 _doorData1 = 1000; -static ZonePtr _zoneTrap; - -// should be reset on character switch -static uint16 walkData1 = 0; -static uint16 walkData2 = 0; // next walk frame - inline byte PathBuffer::getValue(uint16 x, uint16 y) { byte m = data[(x >> 3) + y * internalWidth]; @@ -261,99 +253,43 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNodePtr Node) { return 1; } -void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr to) { +void Parallaction::clipMove(Common::Point& pos, const Common::Point& to) { - if ((pos.x < to->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) { - pos.x = (pos.x + 2 < to->_x) ? pos.x + 2 : to->_x; + if ((pos.x < to.x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) { + pos.x = (pos.x + 2 < to.x) ? pos.x + 2 : to.x; } - if ((pos.x > to->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) { - pos.x = (pos.x - 2 > to->_x) ? pos.x - 2 : to->_x; + if ((pos.x > to.x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) { + pos.x = (pos.x - 2 > to.x) ? pos.x - 2 : to.x; } - if ((pos.y < to->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) { - pos.y = (pos.y + 2 <= to->_y) ? pos.y + 2 : to->_y; + if ((pos.y < to.y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) { + pos.y = (pos.y + 2 <= to.y) ? pos.y + 2 : to.y; } - if ((pos.y > to->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) { - pos.y = (pos.y - 2 >= to->_y) ? pos.y - 2 : to->_y; + if ((pos.y > to.y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) { + pos.y = (pos.y - 2 >= to.y) ? pos.y - 2 : to.y; } return; } -int16 Parallaction::selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to) { - - Common::Point dist(to->_x - pos.x, to->_y - pos.y); - - if (dist.x < 0) - dist.x = -dist.x; - if (dist.y < 0) - dist.y = -dist.y; - - walkData1++; - - // walk frame selection - int16 v16; - if (character._ani->getFrameNum() == 20) { - - if (dist.x > dist.y) { - walkData2 = (to->_x > pos.x) ? 0 : 7; - walkData1 %= 12; - v16 = walkData1 / 2; - } else { - walkData2 = (to->_y > pos.y) ? 14 : 17; - walkData1 %= 8; - v16 = walkData1 / 4; - } - - } else { - - if (dist.x > dist.y) { - walkData2 = (to->_x > pos.x) ? 0 : 9; - walkData1 %= 16; - v16 = walkData1 / 2; - } else { - walkData2 = (to->_y > pos.y) ? 18 : 21; - walkData1 %= 8; - v16 = walkData1 / 4; - } - - } - - return v16; -} - -void Parallaction::checkDoor(Character &character) { - if (_currentLocationIndex != _doorData1) { - _doorData1 = _currentLocationIndex; - _zoneTrap = nullZonePtr; - } - - _engineFlags &= ~kEngineWalking; - Common::Point foot; +void Parallaction::checkDoor(const Common::Point &foot) { - character.getFoot(foot); ZonePtr z = hitZone(kZoneDoor, foot.x, foot.y); - if (z) { - if ((z->_flags & kFlagsClosed) == 0) { _location._startPosition = z->u.door->_startPos; _location._startFrame = z->u.door->_startFrame; - scheduleLocationSwitch(z->u.door->_location); _zoneTrap = nullZonePtr; - } else { _cmdExec->run(z->_commands, z); } } - character.getFoot(foot); z = hitZone(kZoneTrap, foot.x, foot.y); - if (z) { setLocationFlags(kFlagsEnter); _cmdExec->run(z->_commands, z); @@ -371,11 +307,14 @@ void Parallaction::checkDoor(Character &character) { void Parallaction::finalizeWalk(Character &character) { - checkDoor(character); + _engineFlags &= ~kEngineWalking; + + Common::Point foot; + character.getFoot(foot); + checkDoor(foot); + delete character._walkPath; character._walkPath = 0; - - character._ani->_frame = walkData2; } void Parallaction_ns::walk(Character &character) { @@ -386,35 +325,45 @@ void Parallaction_ns::walk(Character &character) { Common::Point curPos; character.getFoot(curPos); + // update target, if previous was reached WalkNodeList::iterator it = character._walkPath->begin(); - if (it != character._walkPath->end()) { if ((*it)->_x == curPos.x && (*it)->_y == curPos.y) { debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it)->_x, (*it)->_y); it = character._walkPath->erase(it); } } + + // advance character towards the target + Common::Point targetPos; if (it == character._walkPath->end()) { debugC(1, kDebugWalk, "walk reached last node"); finalizeWalk(character); - return; - } - - // selectWalkFrame must be performed before position is changed by clipMove - int16 walkFrame = selectWalkFrame(character, curPos, *it); + targetPos = curPos; + } else { + if (*it) { + // targetPos is saved to help setting character direction + targetPos.x = (*it)->_x; + targetPos.y = (*it)->_y; + } - Common::Point newPos(curPos); - clipMove(newPos, *it); - character.setFoot(newPos); + Common::Point newPos(curPos); + clipMove(newPos, targetPos); + character.setFoot(newPos); - if (newPos == curPos) { - debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle"); - finalizeWalk(character); - } else { - character._ani->_frame = walkFrame + walkData2 + 1; + if (newPos == curPos) { + debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle"); + finalizeWalk(character); + } } - return; + // targetPos is used to select the direction (and the walkFrame) of a character, + // since it doesn't cause the sudden changes in orientation that newPos would. + // Since newPos is 'adjusted' according to walkable areas, an imaginary line drawn + // from curPos to newPos is prone to abrutply change in direction, thus making the + // code select 'too different' frames when walking diagonally against obstacles, + // and yielding an annoying shaking effect in the character. + character.updateDirection(curPos, targetPos); } -- cgit v1.2.3