From 7b2645248c0d645266107bd732256c1c541f7278 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 14 Jul 2008 00:13:31 +0000 Subject: [PATCH 01/48] Made sure characters are not removed from the rendering list during switches. svn-id: r33052 --- engines/parallaction/parallaction_ns.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index d1b25f189a0..cbf9ee985d3 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -420,6 +420,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); + _char._ani->gfxobj->clearFlags(kGfxObjNormal); if (!_char.dummy()) { if (getPlatform() == Common::kPlatformAmiga) { From d0ae6885ac34510cea3363b72f9467dbe62de762 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 14 Jul 2008 00:21:05 +0000 Subject: [PATCH 02/48] Fixed regression in walk code. Now standing frames are correctly selected when the character encounters an unexpected blocking object in his/her path. svn-id: r33053 --- engines/parallaction/walk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 40dfddb9030..a717b615e60 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -354,6 +354,7 @@ void Parallaction_ns::walk(Character &character) { if (newPos == curPos) { debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle"); finalizeWalk(character); + targetPos = newPos; // when walking is interrupted, targetPos must be hacked so that a still frame can be selected } } From 0860df5d0e42fa8f9059b7f3c212bf3487a2f754 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 14 Jul 2008 07:54:18 +0000 Subject: [PATCH 03/48] Fixed code formatting svn-id: r33056 --- backends/midi/quicktime.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backends/midi/quicktime.cpp b/backends/midi/quicktime.cpp index 568adf022b0..a18eadcb301 100644 --- a/backends/midi/quicktime.cpp +++ b/backends/midi/quicktime.cpp @@ -132,8 +132,7 @@ bail: return MERR_DEVICE_NOT_AVAILABLE; } -void MidiDriver_QT::close() -{ +void MidiDriver_QT::close() { MidiDriver_MPU401::close(); dispose(); } @@ -248,8 +247,7 @@ void MidiDriver_QT::setPitchBendRange (byte channel, uint range) { NASetController(qtNoteAllocator, qtNoteChannel[channel], kControllerPitchBend, theBend); } -void MidiDriver_QT::dispose() -{ +void MidiDriver_QT::dispose() { for (int i = 0; i < 16; i++) { if (qtNoteChannel[i] != 0) NADisposeNoteChannel(qtNoteAllocator, qtNoteChannel[i]); From eaeb1587f408e540a1449d4b035e794e65937220 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 14 Jul 2008 10:33:57 +0000 Subject: [PATCH 04/48] Fix for missing data in the savegame format that could result in not being able to talk to Goewin in the apothecary after restoring a savegame svn-id: r33057 --- engines/lure/luredefs.h | 2 +- engines/lure/res_struct.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h index 603102a0991..922e1207d02 100644 --- a/engines/lure/luredefs.h +++ b/engines/lure/luredefs.h @@ -36,7 +36,7 @@ namespace Lure { #define LURE_DAT_MAJOR 1 #define LURE_DAT_MINOR 29 #define LURE_MIN_SAVEGAME_MINOR 25 -#define LURE_SAVEGAME_MINOR 32 +#define LURE_SAVEGAME_MINOR 33 #define LURE_DEBUG 1 diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index de09f982d12..92cea948f98 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -456,6 +456,8 @@ void HotspotData::saveToStream(WriteStream *stream) { stream->writeSint16LE(startY); stream->writeUint16LE(roomNumber); stream->writeByte(layer); + stream->writeUint16LE(walkX); + stream->writeUint16LE(walkY); stream->writeUint16LE(width); stream->writeUint16LE(height); @@ -503,6 +505,10 @@ void HotspotData::loadFromStream(ReadStream *stream) { uint8 saveVersion = LureEngine::getReference().saveVersion(); if (saveVersion >= 29) layer = stream->readByte(); + if (saveVersion >= 33) { + walkX = stream->readUint16LE(); + walkY = stream->readUint16LE(); + } width = stream->readUint16LE(); height = stream->readUint16LE(); From c48f3ca8d8341d642690dbeb0207b77ecd58d291 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 14 Jul 2008 13:35:43 +0000 Subject: [PATCH 05/48] Removed all labels from the rendering list to avoid random crashes after introduction is over. svn-id: r33058 --- engines/parallaction/callables_ns.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index 7c053715f64..ed60a193cee 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -424,6 +424,7 @@ void Parallaction_ns::_c_testResult(void *parm) { } _inTestResult = true; + _gfx->freeLabels(); _gfx->updateScreen(); _disk->selectArchive("disk1"); From c25c406c00175155f635aa1e1d37adb5e37cdb4c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 14 Jul 2008 19:14:26 +0000 Subject: [PATCH 06/48] cleanup (and test for Marwan's branch.... ;) svn-id: r33061 --- engines/scumm/detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 753ad452123..68d3010199c 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -949,7 +949,7 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const { sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; - for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) { + for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { // Obtain the last 2 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 2); From 9c91f091ff7a389da31534bce99908ba4e856163 Mon Sep 17 00:00:00 2001 From: Bertrand Augereau Date: Mon, 14 Jul 2008 20:34:31 +0000 Subject: [PATCH 07/48] Register spilling avoided in AGOS background drawing (and 2x unrolling) svn-id: r33062 --- engines/agos/gfx.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index c014413bdcb..2d7d6641dc6 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -744,10 +744,6 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { } void AGOSEngine::drawBackGroundImage(VC10_state *state) { - const byte *src; - byte *dst; - uint h, i; - state->width = _screenWidth; if (_window3Flag == 1) { state->width = 0; @@ -755,15 +751,19 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) { state->y_skip = 0; } - src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8); - dst = state->surf_addr; + const byte* src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8); + byte* dst = state->surf_addr; state->draw_width *= 2; - h = state->draw_height; + uint h = state->draw_height; + const uint w = state->draw_width; + const byte paletteMod = state->paletteMod; do { - for (i = 0; i != state->draw_width; i++) - dst[i] = src[i] + state->paletteMod; + for (uint i = 0; i != w; i+=2) { + dst[i] = src[i] + paletteMod; + dst[i+1] = src[i+1] + paletteMod; + } dst += state->surf_pitch; src += state->width; } while (--h); From ff5f3730c57a81816e3bc2e3365c4fc30701ca1f Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 14 Jul 2008 21:00:39 +0000 Subject: [PATCH 08/48] Don't draw scumm saveload dialog while reflowing layout, as that would use uninitialized values svn-id: r33063 --- engines/scumm/dialogs.cpp | 33 +++++++++++++++++++++++---------- engines/scumm/dialogs.h | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 6d1cf1bbd89..89532b89615 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -31,6 +31,8 @@ #include "graphics/scaler.h" +#include "valgrind/memcheck.h" + #ifdef __DS__ #include "scummhelp.h" #endif @@ -297,7 +299,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da break; case GUI::kListSelectionChangedCmd: { if (_gfxWidget) { - updateInfos(); + updateInfos(true); } if (_saveMode) { @@ -326,6 +328,10 @@ void SaveLoadChooser::reflowLayout() { _container->resize(thumbX - hPad, thumbY - vPad, kThumbnailWidth + hPad * 2, thumbH + vPad * 2 + kLineHeight * 4); + VALGRIND_CHECK_VALUE_IS_DEFINED(thumbX); + VALGRIND_CHECK_VALUE_IS_DEFINED(thumbY); + VALGRIND_CHECK_VALUE_IS_DEFINED(thumbH); + // Add the thumbnail display _gfxWidget->resize(thumbX, thumbY, kThumbnailWidth, thumbH); @@ -350,7 +356,7 @@ void SaveLoadChooser::reflowLayout() { _fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR"); _fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG"); _fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB"); - updateInfos(); + updateInfos(false); } else { _container->setFlags(GUI::WIDGET_INVISIBLE); _gfxWidget->setFlags(GUI::WIDGET_INVISIBLE); @@ -362,7 +368,7 @@ void SaveLoadChooser::reflowLayout() { Dialog::reflowLayout(); } -void SaveLoadChooser::updateInfos() { +void SaveLoadChooser::updateInfos(bool draw) { int selItem = _list->getSelected(); Graphics::Surface *thumb; thumb = _vm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem); @@ -376,7 +382,8 @@ void SaveLoadChooser::updateInfos() { } delete thumb; - _gfxWidget->draw(); + if (draw) + _gfxWidget->draw(); InfoStuff infos; memset(&infos, 0, sizeof(InfoStuff)); @@ -386,12 +393,14 @@ void SaveLoadChooser::updateInfos() { (infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF, infos.date & 0xFFFF); _date->setLabel(buffer); - _date->draw(); + if (draw) + _date->draw(); snprintf(buffer, 32, "Time: %.2d:%.2d", (infos.time >> 8) & 0xFF, infos.time & 0xFF); _time->setLabel(buffer); - _time->draw(); + if (draw) + _time->draw(); int minutes = infos.playtime / 60; int hours = minutes / 60; @@ -400,19 +409,23 @@ void SaveLoadChooser::updateInfos() { snprintf(buffer, 32, "Playtime: %.2d:%.2d", hours & 0xFF, minutes & 0xFF); _playtime->setLabel(buffer); - _playtime->draw(); + if (draw) + _playtime->draw(); } else { snprintf(buffer, 32, "No date saved"); _date->setLabel(buffer); - _date->draw(); + if (draw) + _date->draw(); snprintf(buffer, 32, "No time saved"); _time->setLabel(buffer); - _time->draw(); + if (draw) + _time->draw(); snprintf(buffer, 32, "No playtime saved"); _playtime->setLabel(buffer); - _playtime->draw(); + if (draw) + _playtime->draw(); } } diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h index 7c99a0ebcce..730952676ce 100644 --- a/engines/scumm/dialogs.h +++ b/engines/scumm/dialogs.h @@ -69,7 +69,7 @@ protected: uint8 _fillR, _fillG, _fillB; - void updateInfos(); + void updateInfos(bool draw); public: SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine); ~SaveLoadChooser(); From ba4ba85124d5cffdd75093abb6759f7588280f06 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 14 Jul 2008 21:04:42 +0000 Subject: [PATCH 09/48] remove accidentally committed debugging code; fix shadowing warning svn-id: r33064 --- engines/scumm/dialogs.cpp | 22 ++++++++-------------- engines/scumm/dialogs.h | 2 +- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 89532b89615..e4e2b2b620b 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -31,8 +31,6 @@ #include "graphics/scaler.h" -#include "valgrind/memcheck.h" - #ifdef __DS__ #include "scummhelp.h" #endif @@ -328,10 +326,6 @@ void SaveLoadChooser::reflowLayout() { _container->resize(thumbX - hPad, thumbY - vPad, kThumbnailWidth + hPad * 2, thumbH + vPad * 2 + kLineHeight * 4); - VALGRIND_CHECK_VALUE_IS_DEFINED(thumbX); - VALGRIND_CHECK_VALUE_IS_DEFINED(thumbY); - VALGRIND_CHECK_VALUE_IS_DEFINED(thumbH); - // Add the thumbnail display _gfxWidget->resize(thumbX, thumbY, kThumbnailWidth, thumbH); @@ -368,7 +362,7 @@ void SaveLoadChooser::reflowLayout() { Dialog::reflowLayout(); } -void SaveLoadChooser::updateInfos(bool draw) { +void SaveLoadChooser::updateInfos(bool redraw) { int selItem = _list->getSelected(); Graphics::Surface *thumb; thumb = _vm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem); @@ -382,7 +376,7 @@ void SaveLoadChooser::updateInfos(bool draw) { } delete thumb; - if (draw) + if (redraw) _gfxWidget->draw(); InfoStuff infos; @@ -393,13 +387,13 @@ void SaveLoadChooser::updateInfos(bool draw) { (infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF, infos.date & 0xFFFF); _date->setLabel(buffer); - if (draw) + if (redraw) _date->draw(); snprintf(buffer, 32, "Time: %.2d:%.2d", (infos.time >> 8) & 0xFF, infos.time & 0xFF); _time->setLabel(buffer); - if (draw) + if (redraw) _time->draw(); int minutes = infos.playtime / 60; @@ -409,22 +403,22 @@ void SaveLoadChooser::updateInfos(bool draw) { snprintf(buffer, 32, "Playtime: %.2d:%.2d", hours & 0xFF, minutes & 0xFF); _playtime->setLabel(buffer); - if (draw) + if (redraw) _playtime->draw(); } else { snprintf(buffer, 32, "No date saved"); _date->setLabel(buffer); - if (draw) + if (redraw) _date->draw(); snprintf(buffer, 32, "No time saved"); _time->setLabel(buffer); - if (draw) + if (redraw) _time->draw(); snprintf(buffer, 32, "No playtime saved"); _playtime->setLabel(buffer); - if (draw) + if (redraw) _playtime->draw(); } } diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h index 730952676ce..0d04d8faeac 100644 --- a/engines/scumm/dialogs.h +++ b/engines/scumm/dialogs.h @@ -69,7 +69,7 @@ protected: uint8 _fillR, _fillG, _fillB; - void updateInfos(bool draw); + void updateInfos(bool redraw); public: SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine); ~SaveLoadChooser(); From 60357650e03c8504b06631bba3ca520285977f15 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 14 Jul 2008 23:10:51 +0000 Subject: [PATCH 10/48] Fix for bug #2016647 (FW: crash with italian amiga version). - Consists of a workaround for a script bug that used local variable 251 when it should've used global variable 251. - Also added a fix for a crash when failing copy protection in Amiga or Atari ST versions of Future Wars. NOTE: That any of the Amiga or Atari ST versions of Future Wars haven't crashed right in the beginning before seems like plain luck because accessing local variable 251 is out of bounds! svn-id: r33068 --- engines/cine/cine.h | 1 + engines/cine/prc.cpp | 9 ++++++--- engines/cine/prc.h | 2 +- engines/cine/script_fw.cpp | 14 ++++++++++++++ engines/cine/various.cpp | 14 ++++++++++++-- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/engines/cine/cine.h b/engines/cine/cine.h index 710840c17e6..7568d8310e1 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -107,6 +107,7 @@ private: extern CineEngine *g_cine; #define BOOT_PRC_NAME "AUTO00.PRC" +#define COPY_PROT_FAIL_PRC_NAME "L201.ANI" enum { VAR_MOUSE_X_MODE = 253, diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp index 402c97b1a64..27b10446201 100644 --- a/engines/cine/prc.cpp +++ b/engines/cine/prc.cpp @@ -40,8 +40,9 @@ ScriptList objectScripts; /*! \todo Is script size of 0 valid? * \todo Fix script dump code + * @return Was the loading successful? */ -void loadPrc(const char *pPrcName) { +bool loadPrc(const char *pPrcName) { byte i; uint16 numScripts; byte *scriptPtr, *dataPtr; @@ -52,9 +53,9 @@ void loadPrc(const char *pPrcName) { scriptTable.clear(); // This is copy protection. Used to hang the machine - if (!scumm_stricmp(pPrcName, "L201.ANI")) { + if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) { exitEngine = 1; - return; + return false; } checkDataDisk(-1); @@ -107,6 +108,8 @@ void loadPrc(const char *pPrcName) { } } #endif + + return true; } } // End of namespace Cine diff --git a/engines/cine/prc.h b/engines/cine/prc.h index f5129d28b1d..05bb2403729 100644 --- a/engines/cine/prc.h +++ b/engines/cine/prc.h @@ -31,7 +31,7 @@ namespace Cine { extern ScriptList globalScripts; extern ScriptList objectScripts; -void loadPrc(const char *pPrcName); +bool loadPrc(const char *pPrcName); } // End of namespace Cine diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 148e6730953..54a49760005 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1019,6 +1019,20 @@ int FWScript::o1_divVar() { } int FWScript::o1_compareVar() { + // WORKAROUND: A workaround for a script bug in script file CODE2.PRC + // in at least some of the Amiga and Atari ST versions of Future Wars. + // Fixes bug #2016647 (FW: crash with italian amiga version). A local + // variable 251 is compared against value 0 although it's quite apparent + // from the context in the script that instead global variable 251 should + // be compared against value 0. So looks like someone made a typo when + // making the scripts. Therefore we change that particular comparison + // from using the local variable 251 to using the global variable 251. + if (g_cine->getGameType() == Cine::GType_FW && scumm_stricmp(currentPrcName, "CODE2.PRC") == 0 && + (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) && + _script.getByte(_pos) == 251 && _script.getByte(_pos + 1) == 0 && _script.getWord(_pos + 2) == 0) { + return o1_compareGlobalVar(); + } + byte varIdx = getNextByte(); byte varType = getNextByte(); diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 4b5d4efe13b..69851aeff2a 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1518,12 +1518,22 @@ void mainLoopSub6(void) { void checkForPendingDataLoad(void) { if (newPrcName[0] != 0) { - loadPrc(newPrcName); + bool loadPrcOk = loadPrc(newPrcName); strcpy(currentPrcName, newPrcName); strcpy(newPrcName, ""); - addScriptToList0(1); + // Check that the loading of the script file was successful before + // trying to add script 1 from it to the global scripts list. This + // fixes a crash when failing copy protection in Amiga or Atari ST + // versions of Future Wars. + if (loadPrcOk) { + addScriptToList0(1); + } else if (scumm_stricmp(currentPrcName, COPY_PROT_FAIL_PRC_NAME)) { + // We only show an error here for other files than the file that + // is loaded if copy protection fails (i.e. L201.ANI). + warning("checkForPendingDataLoad: loadPrc(%s) failed", currentPrcName); + } } if (newRelName[0] != 0) { From 619b45e4d38f8d7a74e77271522361bb7db68567 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jul 2008 10:47:24 +0000 Subject: [PATCH 11/48] config.log and tmp files should be put into the configure (= current) dir, not the source dir svn-id: r33070 --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 0e38034a352..8c3b45a0dc9 100755 --- a/configure +++ b/configure @@ -129,10 +129,10 @@ _srcdir=`dirname $0` if type mktemp > /dev/null 2>&1 ; then TMPO=`mktemp /tmp/scummvm-conf.XXXXXXXXXX` else - TMPO=${_srcdir}/scummvm-conf + TMPO=scummvm-conf fi TMPC=${TMPO}.cpp -TMPLOG=${_srcdir}/config.log +TMPLOG=config.log # For cross compiling _host="" From 551f6d71c3821fac0f9245ed667c8547e05d6778 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Tue, 15 Jul 2008 10:59:58 +0000 Subject: [PATCH 12/48] Made frame unpacking buffer dynamic (this frees some BSS space). svn-id: r33072 --- engines/parallaction/gfxbase.cpp | 3 --- engines/parallaction/graphics.cpp | 10 ++++++++++ engines/parallaction/graphics.h | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 9e7eb12ed81..e8250ac8fd4 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -267,9 +267,6 @@ void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte } -// this is the maximum size of an unpacked frame in BRA -byte _unpackedBitmap[640*401]; - #if 0 void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 32d0e303eb9..9b9ea8605a2 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -33,6 +33,11 @@ namespace Parallaction { +// this is the size of the receiving buffer for unpacked frames, +// since BRA uses some insanely big animations. +#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401 + + void Gfx::registerVar(const Common::String &name, int32 initialValue) { if (_vars.contains(name)) { warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str()); @@ -752,6 +757,9 @@ Gfx::Gfx(Parallaction* vm) : _halfbrite = false; _hbCircleRadius = 0; + _unpackedBitmap = new byte[MAXIMUM_UNPACKED_BITMAP_SIZE]; + assert(_unpackedBitmap); + registerVar("background_mode", 1); _varBackgroundMode = 1; @@ -769,6 +777,8 @@ Gfx::~Gfx() { freeBackground(); freeLabels(); + delete []_unpackedBitmap; + return; } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 09f4b2f2441..a7242ba6f4b 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -547,6 +547,8 @@ public: uint _screenX; // scrolling position uint _screenY; + byte *_unpackedBitmap; + protected: Parallaction* _vm; bool _halfbrite; From 943b4c2036002454b276e0190dfc2c8919fb0cbf Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jul 2008 17:13:06 +0000 Subject: [PATCH 13/48] Implemented audio double buffering (for now OSX only) svn-id: r33075 --- NEWS | 19 ++--- backends/platform/sdl/sdl.cpp | 126 ++++++++++++++++++++++++++++++++-- backends/platform/sdl/sdl.h | 30 +++++++- 3 files changed, 160 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 93ead62d520..2814d47c567 100644 --- a/NEWS +++ b/NEWS @@ -3,20 +3,23 @@ For a more comprehensive changelog for the latest experimental SVN code, see: 0.12.0 (????-??-??) New Games: - - Added support for The Legend of Kyrandia: Book Two: Hand of Fate - - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge - - Added support for Lost in Time - - Added support for The Bizarre Adventures of Woodruff and the Schnibble - - Added support for the PC version of Waxworks + - Added support for The Legend of Kyrandia: Book Two: Hand of Fate. + - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge. + - Added support for Lost in Time. + - Added support for The Bizarre Adventures of Woodruff and the Schnibble. + - Added support for the PC version of Waxworks. - Added support for the Macintosh version of I Have no Mouth, and I - must Scream - - Added support for Drascula: The Vampire Strikes Back + must Scream. + - Added support for Drascula: The Vampire Strikes Back. General: - Added CAMD MIDI driver for AmigaOS4. - Revived the PS2 port (was already in 0.11.1 but was forgotten in the release notes). - - Plugged numerous memory leaks in all engines (part of GSoC'08 task) + - Plugged numerous memory leaks in all engines (part of GSoC'08 task), + - Added audio double buffering to the SDL backend, which fixes the + problems with the MT-32 emulator on Mac OS X (for now only enabled + on Mac OS X). AGOS: - Fixed palette issues in Amiga versions of Simon the Sorcerer 1. diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 290fe63663c..cc5f2478e56 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -191,7 +191,7 @@ OSystem_SDL::OSystem_SDL() OSystem_SDL::~OSystem_SDL() { SDL_RemoveTimer(_timerID); - SDL_CloseAudio(); + closeMixer(); free(_dirtyChecksums); free(_currentPalette); @@ -199,7 +199,6 @@ OSystem_SDL::~OSystem_SDL() { free(_mouseData); delete _savefile; - delete _mixer; delete _timer; } @@ -306,7 +305,7 @@ void OSystem_SDL::quit() { SDL_ShowCursor(SDL_ENABLE); SDL_RemoveTimer(_timerID); - SDL_CloseAudio(); + closeMixer(); free(_dirtyChecksums); free(_currentPalette); @@ -314,7 +313,6 @@ void OSystem_SDL::quit() { free(_mouseData); delete _savefile; - delete _mixer; delete _timer; SDL_Quit(); @@ -389,14 +387,110 @@ void OSystem_SDL::deleteMutex(MutexRef mutex) { #pragma mark --- Audio --- #pragma mark - +#ifdef MIXER_DOUBLE_BUFFERING + +void OSystem_SDL::mixerProducerThread() { + byte nextSoundBuffer; + + SDL_LockMutex(_soundMutex); + while (true) { + // Wait till we are allowed to produce data + SDL_CondWait(_soundCond, _soundMutex); + + if (_soundThreadShouldQuit) + break; + + // Generate samples and put them into the next buffer + nextSoundBuffer = _activeSoundBuf ^ 1; + _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize); + + // Swap buffers + _activeSoundBuf = nextSoundBuffer; + } + SDL_UnlockMutex(_soundMutex); +} + +int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) { + OSystem_SDL *this_ = (OSystem_SDL *)arg; + assert(this_); + this_->mixerProducerThread(); + return 0; +} + + +void OSystem_SDL::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) { + _soundThreadIsRunning = false; + _soundThreadShouldQuit = false; + + // Create mutex and condition variable + _soundMutex = SDL_CreateMutex(); + _soundCond = SDL_CreateCond(); + + // Create two sound buffers + _activeSoundBuf = 0; + _soundBufSize = bufSize; + _soundBuffers[0] = (byte *)calloc(1, bufSize); + _soundBuffers[1] = (byte *)calloc(1, bufSize); + + _soundThreadIsRunning = true; + + // Finally start the thread + _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this); +} + +void OSystem_SDL::deinitThreadedMixer() { + // Kill thread?? _soundThread + + if (_soundThreadIsRunning) { + // Signal the producer thread to end, and wait for it to actually finish. + _soundThreadShouldQuit = true; + SDL_CondBroadcast(_soundCond); + SDL_WaitThread(_soundThread, NULL); + + // Kill the mutex & cond variables. + // Attention: AT this point, the mixer callback must not be running + // anymore, else we will crash! + SDL_DestroyMutex(_soundMutex); + SDL_DestroyCond(_soundCond); + + _soundThreadIsRunning = false; + + free(_soundBuffers[0]); + free(_soundBuffers[1]); + } +} + + +void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) { + OSystem_SDL *this_ = (OSystem_SDL *)arg; + assert(this_); + assert(this_->_mixer); + + assert((int)this_->_soundBufSize == len); + + // Lock mutex, to ensure our data is not overwritten by the producer thread + SDL_LockMutex(this_->_soundMutex); + + // Copy data from the current sound buffer + memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len); + + // Unlock mutex and wake up the produced thread + SDL_UnlockMutex(this_->_soundMutex); + SDL_CondSignal(this_->_soundCond); +} + +#else + void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) { OSystem_SDL *this_ = (OSystem_SDL *)sys; assert(this_); + assert(this_->_mixer); - if (this_->_mixer) - this_->_mixer->mixCallback(samples, len); + this_->_mixer->mixCallback(samples, len); } +#endif + void OSystem_SDL::setupMixer() { SDL_AudioSpec desired; SDL_AudioSpec obtained; @@ -443,10 +537,30 @@ void OSystem_SDL::setupMixer() { // Tell the mixer that we are ready and start the sound processing _mixer->setOutputRate(_samplesPerSec); _mixer->setReady(true); + +#ifdef MIXER_DOUBLE_BUFFERING + initThreadedMixer(_mixer, obtained.samples * 4); +#endif + + // start the sound system SDL_PauseAudio(0); } } +void OSystem_SDL::closeMixer() { + if (_mixer) + _mixer->setReady(false); + delete _mixer; + _mixer = 0; + + SDL_CloseAudio(); + +#ifdef MIXER_DOUBLE_BUFFERING + deinitThreadedMixer(); +#endif + +} + Audio::Mixer *OSystem_SDL::getMixer() { assert(_mixer); return _mixer; diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 8a94a17b009..4ad588f5f55 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -51,6 +51,15 @@ namespace Common { #define USE_OSD 1 #endif +#if defined(MACOSX) +// On Mac OS X, we need to double buffer the audio buffer, else anything +// which produces sampled data with high latency (like the MT-32 emulator) +// will sound terribly. +// This could be enabled for more / most ports in the future, but needs some +// testing. +#define MIXER_DOUBLE_BUFFERING 1 +#endif + enum { GFX_NORMAL = 0, @@ -137,6 +146,8 @@ public: virtual void setupMixer(); static void mixCallback(void *s, byte *samples, int len); + virtual void closeMixer(); + virtual Audio::Mixer *getMixer(); // Poll CD status @@ -369,6 +380,23 @@ protected: */ MutexRef _graphicsMutex; +#ifdef MIXER_DOUBLE_BUFFERING + SDL_mutex *_soundMutex; + SDL_cond *_soundCond; + SDL_Thread *_soundThread; + bool _soundThreadIsRunning; + bool _soundThreadShouldQuit; + + byte _activeSoundBuf; + uint _soundBufSize; + byte *_soundBuffers[2]; + + void mixerProducerThread(); + static int SDLCALL mixerProducerThreadEntry(void *arg); + void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize); + void deinitThreadedMixer(); +#endif + Common::SaveFileManager *_savefile; Audio::MixerImpl *_mixer; @@ -377,7 +405,7 @@ protected: Common::TimerManager *_timer; - +protected: void addDirtyRgnAuto(const byte *buf); void makeChecksums(const byte *buf); From 2bae0df17e2c2a77295b13b107b208e63147638d Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Tue, 15 Jul 2008 20:26:12 +0000 Subject: [PATCH 14/48] fix bug #1995042: stop previous sfx playback when starting a new sfx (matches original dos code). Also removed the "sound skipping" hack in final bam scene. svn-id: r33078 --- engines/queen/graphics.cpp | 11 ++--------- engines/queen/graphics.h | 4 ---- engines/queen/sound.cpp | 13 +++++++------ engines/queen/sound.h | 1 - 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/engines/queen/graphics.cpp b/engines/queen/graphics.cpp index f863f7663cd..6d0a11ccfe5 100644 --- a/engines/queen/graphics.cpp +++ b/engines/queen/graphics.cpp @@ -1175,15 +1175,8 @@ BamScene::BamScene(QueenEngine *vm) } void BamScene::playSfx() { - // Don't try to play all the sounds. This is only necessary for the - // fight bam, in which the number of 'sfx bam frames' is too much - // important / too much closer. The original game does not have - // this problem since its playSfx() function returns immediately - // if a sound is already being played. - if (_lastSoundIndex == 0 || _index - _lastSoundIndex >= SFX_SKIP) { - _vm->sound()->playSfx(_vm->logic()->currentRoomSfx()); - _lastSoundIndex = _index; - } + _vm->sound()->playSfx(_vm->logic()->currentRoomSfx()); + _lastSoundIndex = _index; } void BamScene::prepareAnimation() { diff --git a/engines/queen/graphics.h b/engines/queen/graphics.h index 6f00111635d..7eadf9a1916 100644 --- a/engines/queen/graphics.h +++ b/engines/queen/graphics.h @@ -248,10 +248,6 @@ public: F_REQ_STOP = 2 }; - enum { - SFX_SKIP = 8 - }; - uint16 _flag, _index; private: diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index d70fe7209da..3672eecce88 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -229,11 +229,6 @@ void PCSound::setVolume(int vol) { _music->setVolume(vol); } -void PCSound::waitFinished(bool isSpeech) { - while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle)) - _vm->input()->delay(10); -} - void PCSound::playSound(const char *base, bool isSpeech) { char name[13]; strcpy(name, base); @@ -243,7 +238,13 @@ void PCSound::playSound(const char *base, bool isSpeech) { name[i] = '0'; } strcat(name, ".SB"); - waitFinished(isSpeech); + if (isSpeech) { + while (_mixer->isSoundHandleActive(_speechHandle)) { + _vm->input()->delay(10); + } + } else { + _mixer->stopHandle(_sfxHandle); + } uint32 size; Common::File *f = _vm->resource()->findSound(name, &size); if (f) { diff --git a/engines/queen/sound.h b/engines/queen/sound.h index c2c1481cc63..331034f7465 100644 --- a/engines/queen/sound.h +++ b/engines/queen/sound.h @@ -143,7 +143,6 @@ public: void setVolume(int vol); protected: - void waitFinished(bool isSpeech); void playSound(const char *base, bool isSpeech); virtual void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) = 0; From cdade7eff3e481ef7aca404ca13138cccd920365 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Tue, 15 Jul 2008 20:31:11 +0000 Subject: [PATCH 15/48] fix bug #1876741: changed .SB playback rate to 11840Hz (matches dos game) svn-id: r33079 --- engines/queen/sound.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index 3672eecce88..f4e0116cf1c 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -256,6 +256,8 @@ void PCSound::playSound(const char *base, bool isSpeech) { } void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { + // In order to simplify the code, we don't parse the .sb header but hard-code the + // values. Refer to tracker item #1876741 for details on the format/fields. int headerSize; f->seek(2, SEEK_CUR); uint16 version = f->readUint16LE(); @@ -277,7 +279,7 @@ void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *so if (sound) { f->read(sound, size); byte flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE; - _mixer->playRaw(Audio::Mixer::kSFXSoundType, soundHandle, sound, size, 11025, flags); + _mixer->playRaw(Audio::Mixer::kSFXSoundType, soundHandle, sound, size, 11840, flags); } } From bd17a600dcf86255be4e5d7d359b190e4b1351b1 Mon Sep 17 00:00:00 2001 From: Bertrand Augereau Date: Wed, 16 Jul 2008 09:08:44 +0000 Subject: [PATCH 16/48] Split the drawVertImage function in the agos engine to make it clearer and easier to profile svn-id: r33083 --- engines/agos/agos.h | 2 + engines/agos/gfx.cpp | 121 +++++++++++++++++++++++-------------------- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 74a0b026e99..8ad5487b35a 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -1075,6 +1075,8 @@ protected: virtual void drawImage(VC10_state *state); void drawBackGroundImage(VC10_state *state); void drawVertImage(VC10_state *state); + void drawVertImageCompressed(VC10_state *state); + void drawVertImageUncompressed(VC10_state *state); void setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height); diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 2d7d6641dc6..6e91c5d94c6 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -771,65 +771,76 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) { void AGOSEngine::drawVertImage(VC10_state *state) { if (state->flags & kDFCompressed) { - uint w, h; - byte *src, *dst, *dstPtr; - - state->x_skip *= 4; /* reached */ - - state->dl = state->width; - state->dh = state->height; - - vc10_skip_cols(state); - - dstPtr = state->surf_addr; - if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */ - dstPtr += vcReadVar(252); - } - w = 0; - do { - byte color; - - src = vc10_depackColumn(state); - dst = dstPtr; - - h = 0; - do { - color = (*src / 16); - if ((state->flags & kDFNonTrans) || color != 0) - dst[0] = color | state->palette; - color = (*src & 15); - if ((state->flags & kDFNonTrans) || color != 0) - dst[1] = color | state->palette; - dst += state->surf_pitch; - src++; - } while (++h != state->draw_height); - dstPtr += 2; - } while (++w != state->draw_width); + drawVertImageCompressed(state); } else { - const byte *src; - byte *dst; - uint count; - - src = state->srcPtr + (state->width * state->y_skip) * 8; - dst = state->surf_addr; - state->x_skip *= 4; - - do { - for (count = 0; count != state->draw_width; count++) { - byte color; - color = (src[count + state->x_skip] / 16) + state->paletteMod; - if ((state->flags & kDFNonTrans) || color) - dst[count * 2] = color | state->palette; - color = (src[count + state->x_skip] & 15) + state->paletteMod; - if ((state->flags & kDFNonTrans) || color) - dst[count * 2 + 1] = color | state->palette; - } - dst += state->surf_pitch; - src += state->width * 8; - } while (--state->draw_height); + drawVertImageUncompressed(state); } } +void AGOSEngine::drawVertImageUncompressed(VC10_state *state) { + assert ((state->flags & kDFCompressed) == 0) ; + + const byte *src; + byte *dst; + uint count; + + src = state->srcPtr + (state->width * state->y_skip) * 8; + dst = state->surf_addr; + state->x_skip *= 4; + + do { + for (count = 0; count != state->draw_width; count++) { + byte color; + color = (src[count + state->x_skip] / 16) + state->paletteMod; + if ((state->flags & kDFNonTrans) || color) + dst[count * 2] = color | state->palette; + color = (src[count + state->x_skip] & 15) + state->paletteMod; + if ((state->flags & kDFNonTrans) || color) + dst[count * 2 + 1] = color | state->palette; + } + dst += state->surf_pitch; + src += state->width * 8; + } while (--state->draw_height); +} + +void AGOSEngine::drawVertImageCompressed(VC10_state *state) { + assert (state->flags & kDFCompressed) ; + uint w, h; + byte *src, *dst, *dstPtr; + + state->x_skip *= 4; /* reached */ + + state->dl = state->width; + state->dh = state->height; + + vc10_skip_cols(state); + + dstPtr = state->surf_addr; + if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */ + dstPtr += vcReadVar(252); + } + w = 0; + do { + byte color; + + src = vc10_depackColumn(state); + dst = dstPtr; + + h = 0; + do { + color = (*src / 16); + if ((state->flags & kDFNonTrans) || color != 0) + dst[0] = color | state->palette; + color = (*src & 15); + if ((state->flags & kDFNonTrans) || color != 0) + dst[1] = color | state->palette; + dst += state->surf_pitch; + src++; + } while (++h != state->draw_height); + dstPtr += 2; + } while (++w != state->draw_width); +} + void AGOSEngine::drawImage(VC10_state *state) { const uint16 *vlut = &_videoWindows[_windowNum * 4]; From 17d86414cb5d7c2b4c5159b5b5d1b2330fa8eb83 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Thu, 17 Jul 2008 00:38:11 +0000 Subject: [PATCH 17/48] Fixed regression bug in dialogue, which de-facto allowed user to skip in-game protection. svn-id: r33086 --- engines/parallaction/dialogue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 6e91dd8a882..6d9dfa5e106 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -166,7 +166,7 @@ bool DialogueManager::displayAnswer(uint16 i) { assert(id >= 0); _visAnswers[id] = i; - _askPassword = (strstr(a->_text, "%p") != NULL); + _askPassword = (strstr(a->_text, "%P") != NULL); _numVisAnswers++; return true; From 67bef188d3977478c7d57b4016885c9293642cd2 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 17 Jul 2008 07:13:41 +0000 Subject: [PATCH 18/48] Patch #2019455: Patch for reducing the BSS size of Cine engine. svn-id: r33087 --- engines/cine/cine.h | 1 + engines/cine/gfx.cpp | 4 ++-- engines/cine/texte.cpp | 10 ++++------ engines/cine/texte.h | 5 ++++- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/engines/cine/cine.h b/engines/cine/cine.h index 7568d8310e1..06f2dfd982e 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -94,6 +94,7 @@ public: Common::StringList _volumeResourceFiles; StringPtrHashMap _volumeEntriesMap; + TextHandler _textHandler; private: void initialize(void); diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 2b7f3b8890c..1f868ccb75a 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -337,7 +337,7 @@ int FWRenderer::drawChar(char character, int x, int y) { x += 5; } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) { idx = fontParamTable[(unsigned char)character].characterIdx; - drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y); + drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y); x += width + 1; } @@ -938,7 +938,7 @@ int OSRenderer::drawChar(char character, int x, int y) { x += 5; } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) { idx = fontParamTable[(unsigned char)character].characterIdx; - drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y); + drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y); x += width + 1; } diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp index 9b4b83f4208..e4fd3349263 100644 --- a/engines/cine/texte.cpp +++ b/engines/cine/texte.cpp @@ -31,8 +31,6 @@ namespace Cine { byte *textDataPtr; -byte textTable[256][2][16 * 8]; - const char **failureMessages; const CommandeType *defaultActionCommand; const CommandeType *systemMenu; @@ -77,14 +75,14 @@ void loadTextData(const char *pFileName, byte *pDestinationBuffer) { loadRelatedPalette(pFileName); for (i = 0; i < numCharacters; i++) { - gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 16, 8); - generateMask(textTable[i][0], textTable[i][1], 16 * 8, 0); + gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 16, 8); + generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 16 * 8, 0); tempBuffer += dataSize; } } else { for (i = 0; i < 90; i++) { - gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 8, 8); - generateMask(textTable[i][0], textTable[i][1], 8 * 8, 0); + gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 8, 8); + generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 8 * 8, 0); tempBuffer += 0x40; } } diff --git a/engines/cine/texte.h b/engines/cine/texte.h index ae82832aead..f471c3c49e5 100644 --- a/engines/cine/texte.h +++ b/engines/cine/texte.h @@ -34,7 +34,10 @@ namespace Cine { typedef char CommandeType[20]; extern byte *textDataPtr; -extern byte textTable[256][2][16 * 8]; + +struct TextHandler { + byte textTable[256][2][16 * 8]; +}; extern const char **failureMessages; extern const CommandeType *defaultActionCommand; From 0f74124d789488d42bc62b6a8bcf67d31e0b9bfd Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jul 2008 15:56:24 +0000 Subject: [PATCH 19/48] Committing PS2 changes on behalf of the other Max ;) svn-id: r33089 --- backends/platform/ps2/Makefile.ps2 | 4 +- backends/platform/ps2/fileio.cpp | 71 ++++++++++++++++++++++------- backends/platform/ps2/irxboot.cpp | 2 +- backends/platform/ps2/systemps2.cpp | 19 +++++--- backends/platform/ps2/systemps2.h | 7 +-- 5 files changed, 73 insertions(+), 30 deletions(-) diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2 index 22cd4eaa1b2..9a2c1bad1b2 100644 --- a/backends/platform/ps2/Makefile.ps2 +++ b/backends/platform/ps2/Makefile.ps2 @@ -23,12 +23,12 @@ INCDIR = ../../../ DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_MPEG2 -DUSE_ZLIB -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar # PS2SDK-Ports from ps2dev.org's SVN repository for libmad, zlib and ucl -PS2SDK_PORTS = /home/robby/libStuffNew/ps2sdk-ports +PS2SDK_PORTS = /mnt/winxp/scummvm/ports PS2SDK_PORTS_INCS = /ucl /zlib/include /libmad/ee/include PS2SDK_PORTS_LIBS = /ucl /zlib/lib /libmad/ee/lib # we also need SjPcm, Tremor and libmpeg2 -MORE_LIBS_DIR = /home/robby/libStuff +MORE_LIBS_DIR = /mnt/winxp/scummvm/ports MORE_LIBS_INCS = /SjPcm/ee/src /mpeg2dec/include /tremor MORE_LIBS_LIBS = /SjPcm/ee/lib /mpeg2dec/libmpeg2 /tremor/tremor diff --git a/backends/platform/ps2/fileio.cpp b/backends/platform/ps2/fileio.cpp index bc310a43f45..b7fa8d03f1f 100644 --- a/backends/platform/ps2/fileio.cpp +++ b/backends/platform/ps2/fileio.cpp @@ -340,8 +340,6 @@ FILE *ps2_fopen(const char *fname, const char *mode) { assert(cacheListSema >= 0); } - //printf("ps2_fopen: %s, %s\n", fname, mode); - if (((mode[0] != 'r') && (mode[0] != 'w')) || ((mode[1] != '\0') && (mode[1] != 'b'))) { printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname); return NULL; @@ -363,6 +361,8 @@ FILE *ps2_fopen(const char *fname, const char *mode) { } else { // Regular access to one of the devices + printf("ps2_fopen = %s\n", fname); // romeo : temp + if (!rdOnly) return NULL; // we only provide readaccess for cd,dvd,hdd,usb @@ -378,19 +378,22 @@ FILE *ps2_fopen(const char *fname, const char *mode) { } int64 cacheId = -1; - if (rdOnly && tocManager.haveEntries()) + if (tocManager.haveEntries()) cacheId = tocManager.fileExists(fname); if (cacheId != 0) { Ps2File *file = findInCache(cacheId); - if (file) + if (file) { + printf(" findInCache(%x)\n", cacheId); // romeo : temp return (FILE*)file; + } bool isAudioFile = strstr(fname, ".bun") || strstr(fname, ".BUN") || strstr(fname, ".Bun"); file = new Ps2ReadFile(cacheId, isAudioFile); if (file->open(fname)) { openFileCount++; + printf(" new cacheID = %x\n", cacheId); // romeo : temp return (FILE*)file; } else delete file; @@ -579,7 +582,7 @@ void TocManager::readEntries(const char *root) { } char readPath[256]; sprintf(readPath, "%s/", _root); - printf("readDir: %s\n", readPath); + printf("readDir: %s (root: %s )\n", readPath, root); readDir(readPath, &_rootNode, 0); } @@ -587,28 +590,62 @@ void TocManager::readDir(const char *path, TocNode **node, int level) { if (level <= 2) { // we don't scan deeper than that iox_dirent_t dirent; int fd = fio.dopen(path); - if (fd >= 0) { - while (fio.dread(fd, &dirent) > 0) - if (dirent.name[0] != '.') { // skip '.' and '..' - *node = new TocNode; - (*node)->sub = (*node)->next = NULL; + TocNode *eNode = NULL; // = *node; // entry node + bool first = true; + printf("path=%s - level=%d fd=%d\n", path, level, fd); // romeo : temp + if (fd >= 0) { + while (fio.dread(fd, &dirent) > 0) { + if (dirent.name[0] != '.') { // skip '.' & '..' - romeo : check + // --- do we have them on PS2? + *node = new TocNode; + if (first) { + eNode = *node; + first = false; + } + (*node)->sub = (*node)->next = NULL; (*node)->nameLen = strlen(dirent.name); memcpy((*node)->name, dirent.name, (*node)->nameLen + 1); - if (dirent.stat.mode & FIO_S_IFDIR) { // directory + if (dirent.stat.mode & FIO_S_IFDIR) { (*node)->isDir = true; - char nextPath[256]; - sprintf(nextPath, "%s%s/", path, dirent.name); - readDir(nextPath, &((*node)->sub), level + 1); - } else + printf("dirent.name = %s [DIR]\n", dirent.name); + } + else { (*node)->isDir = false; + printf("dirent.name = %s\n", dirent.name); + } + node = &((*node)->next); } + } + fio.dclose(fd); - } else - printf("Can't open path: %s\n", path); + } + + TocNode *iNode = eNode; + char nextPath[256]; + + while (iNode) { + if (iNode->isDir == true) { + sprintf(nextPath, "%s%s/", path, iNode->name); + readDir(nextPath, &(iNode->sub), level + 1); + } + iNode = iNode->next; + } + } + + /* + ** Wizard of Oz' trick (to get all games running from USB on PS2): + + 1. Make a list of files / dirs in level #0 (dclose before continuing) + + 2. Go through the dirs : dopen / dread them / mark dirs / dclose + + It's a safe recursion, cause it recurses on 'isDir' nodes + after dclosing the higher hierarchy + */ } int64 TocManager::fileExists(const char *name) { diff --git a/backends/platform/ps2/irxboot.cpp b/backends/platform/ps2/irxboot.cpp index 327e5bdc713..65d1e243ebd 100644 --- a/backends/platform/ps2/irxboot.cpp +++ b/backends/platform/ps2/irxboot.cpp @@ -43,7 +43,7 @@ IrxFile irxFiles[] = { { "PADMAN", BIOS, NOTHING, NULL, 0 }, { "LIBSD", BIOS, NOTHING, NULL, 0 }, - { "IOMANX.IRX", SYSTEM | NOT_HOST, NOTHING, NULL, 0 }, // already loaded by ps2link + { "IOMANX.IRX", SYSTEM /*| NOT_HOST*/, NOTHING, NULL, 0 }, // already loaded by ps2link { "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 }, { "CODYVDFS.IRX", SYSTEM, NOTHING, NULL, 0 }, { "SJPCM.IRX", SYSTEM, NOTHING, NULL, 0 }, diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 28ced7b3453..d4dd9aedcf9 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -54,9 +54,11 @@ #include "graphics/surface.h" #include "graphics/font.h" #include "backends/timer/default/default-timer.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h" #include "common/events.h" #include "backends/platform/ps2/ps2debug.h" +#include "backends/fs/ps2/ps2-fs-factory.h" + // asm("mfc0 %0, $9\n" : "=r"(tickStart)); extern void *_gp; @@ -309,7 +311,9 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) { void OSystem_PS2::init(void) { sioprintf("Timer...\n"); _scummTimerManager = new DefaultTimerManager(); - _scummMixer = new Audio::Mixer(); + _scummMixer = new Audio::MixerImpl(this); + _scummMixer->setOutputRate(44100); + _scummMixer->setReady(true); initTimer(); sioprintf("Starting SavefileManager\n"); @@ -410,7 +414,8 @@ void OSystem_PS2::soundThread(void) { // we have to produce more samples, call sound mixer // the scratchpad at 0x70000000 is used as temporary soundbuffer //_scummSoundProc(_scummSoundParam, (uint8*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16)); - Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16)); + // Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16)); + _scummMixer->mixCallback((byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16)); // demux data into 2 buffers, L and R __asm__ ( @@ -534,10 +539,6 @@ Common::TimerManager *OSystem_PS2::getTimerManager() { return _scummTimerManager; } -int OSystem_PS2::getOutputSampleRate(void) const { - return 48000; -} - Audio::Mixer *OSystem_PS2::getMixer() { return _scummMixer; } @@ -546,6 +547,10 @@ Common::SaveFileManager *OSystem_PS2::getSavefileManager(void) { return _saveManager; } +FilesystemFactory *OSystem_PS2::getFilesystemFactory() { + return &Ps2FilesystemFactory::instance(); +} + void OSystem_PS2::setShakePos(int shakeOffset) { _screen->setShakePos(shakeOffset); } diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 9dbe9be5539..08975ab2c85 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -33,6 +33,7 @@ class DefaultTimerManager; class Gs2dScreen; class Ps2Input; class Ps2SaveFileManager; +// class Ps2FilesystemFactory; struct IrxReference; #define MAX_MUTEXES 16 @@ -48,7 +49,7 @@ namespace Common { }; namespace Audio { - class Mixer; + class MixerImpl; }; class OSystem_PS2 : public OSystem { @@ -87,7 +88,6 @@ public: virtual bool pollEvent(Common::Event &event); virtual Audio::Mixer *getMixer(); - virtual int getOutputSampleRate(void) const; virtual bool openCD(int drive); virtual bool pollCD(); @@ -112,6 +112,7 @@ public: virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b); virtual Common::SaveFileManager *getSavefileManager(); + virtual FilesystemFactory *getFilesystemFactory(); virtual void getTimeAndDate(struct tm &t) const; @@ -133,7 +134,7 @@ private: void readRtcTime(void); DefaultTimerManager *_scummTimerManager; - Audio::Mixer *_scummMixer; + Audio::MixerImpl *_scummMixer; bool _mouseVisible; From 702e26965c48e99490c25ca635e41c14ac88add2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Andersson?= Date: Fri, 18 Jul 2008 04:16:00 +0000 Subject: [PATCH 20/48] Don't crash if you try to use music file #2 as music file #1. When the music wasn't found, it would close the file even if something else was already playing from it. (Some music is in both files.) svn-id: r33094 --- engines/sword2/music.cpp | 21 ++++++++++++++------- engines/sword2/sound.h | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp index fd72ba8d529..3b5a09578b0 100644 --- a/engines/sword2/music.cpp +++ b/engines/sword2/music.cpp @@ -52,9 +52,11 @@ namespace Sword2 { static Audio::AudioStream *makeCLUStream(Common::File *fp, int size); static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) { - debug(3, "Playing %s from CD %d", base, cd); + bool alreadyOpen; if (!fh->file.isOpen()) { + alreadyOpen = false; + struct { const char *ext; int mode; @@ -75,16 +77,14 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, char filename[20]; for (int i = 0; i < ARRAYSIZE(file_types); i++) { - Common::File f; - sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext); - if (f.open(filename)) { + if (Common::File::exists(filename)) { soundMode = file_types[i].mode; break; } sprintf(filename, "%s.%s", base, file_types[i].ext); - if (f.open(filename)) { + if (Common::File::exists(filename)) { soundMode = file_types[i].mode; break; } @@ -105,7 +105,8 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, fh->idxTab = NULL; } } - } + } else + alreadyOpen = true; uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3; @@ -134,7 +135,13 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, *numSamples = len; if (!pos || !len) { - fh->file.close(); + // We couldn't find the sound. Possibly as a result of a bad + // installation (e.g. using the music file from CD 2 as the + // first music file). Don't close the file if it was already + // open though, because something is playing from it. + warning("getAudioStream: Could not find %s ID %d! Possibly the wrong file", base, id); + if (!alreadyOpen) + fh->file.close(); return NULL; } diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h index 70bae6f851b..b89ef8f12bc 100644 --- a/engines/sword2/sound.h +++ b/engines/sword2/sound.h @@ -106,7 +106,7 @@ private: void refill(); inline bool eosIntern() const { - return _pos >= _bufferEnd; + return !_file->isOpen() || _pos >= _bufferEnd; } public: From cb366384f7f6a7d45ace3d67f8df529fe8312584 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 18 Jul 2008 09:36:49 +0000 Subject: [PATCH 21/48] In OSystem_SDL::closeMixer moved the call to SDL_CloseAudio to before the deletion of the _mixer variable in to fix an assert that was being generated in OSystem_SDL::mixCallback svn-id: r33095 --- backends/platform/sdl/sdl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index cc5f2478e56..76ac91c282f 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -550,11 +550,12 @@ void OSystem_SDL::setupMixer() { void OSystem_SDL::closeMixer() { if (_mixer) _mixer->setReady(false); - delete _mixer; - _mixer = 0; SDL_CloseAudio(); + delete _mixer; + _mixer = 0; + #ifdef MIXER_DOUBLE_BUFFERING deinitThreadedMixer(); #endif From 8757326b5f2b464ddc6cc2b523f573c31a191ad3 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Fri, 18 Jul 2008 14:01:53 +0000 Subject: [PATCH 22/48] Added savefile position comments to savegame loading routine (Helpful for debugging the formats). svn-id: r33096 --- engines/cine/various.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 69851aeff2a..ab2fa645c79 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -466,17 +466,26 @@ bool CineEngine::makeLoad(char *saveName) { broken = brokenSave(*fHandle); + // At savefile position 0x0000: currentDisk = fHandle->readUint16BE(); + // At 0x0002: fHandle->read(currentPartName, 13); + // At 0x000F: fHandle->read(currentDatName, 13); + // At 0x001C: saveVar2 = fHandle->readSint16BE(); + // At 0x001E: fHandle->read(currentPrcName, 13); + // At 0x002B: fHandle->read(currentRelName, 13); + // At 0x0038: fHandle->read(currentMsgName, 13); + // At 0x0045: fHandle->read(bgName, 13); + // At 0x0052: fHandle->read(currentCtName, 13); checkDataDisk(currentDisk); @@ -501,52 +510,84 @@ bool CineEngine::makeLoad(char *saveName) { loadCtFW(currentCtName); } + // At 0x005F: fHandle->readUint16BE(); + // At 0x0061: fHandle->readUint16BE(); + // At 0x0063: for (i = 0; i < 255; i++) { + // At 0x0063 + i * 32 + 0: objectTable[i].x = fHandle->readSint16BE(); + // At 0x0063 + i * 32 + 2: objectTable[i].y = fHandle->readSint16BE(); + // At 0x0063 + i * 32 + 4: objectTable[i].mask = fHandle->readUint16BE(); + // At 0x0063 + i * 32 + 6: objectTable[i].frame = fHandle->readSint16BE(); + // At 0x0063 + i * 32 + 8: objectTable[i].costume = fHandle->readSint16BE(); + // At 0x0063 + i * 32 + 10: fHandle->read(objectTable[i].name, 20); + // At 0x0063 + i * 32 + 30: objectTable[i].part = fHandle->readUint16BE(); } + // At 0x2043 (i.e. 0x0063 + 255 * 32): renderer->restorePalette(*fHandle); + // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2): globalVars.load(*fHandle, NUM_MAX_VAR - 1); + // At 0x2281 (i.e. 0x2083 + 255 * 2): for (i = 0; i < 16; i++) { + // At 0x2281 + i * 2: zoneData[i] = fHandle->readUint16BE(); } + // At 0x22A1 (i.e. 0x2281 + 16 * 2): for (i = 0; i < 4; i++) { + // At 0x22A1 + i * 2: commandVar3[i] = fHandle->readUint16BE(); } + // At 0x22A9 (i.e. 0x22A1 + 4 * 2): fHandle->read(commandBuffer, 0x50); renderer->setCommand(commandBuffer); + // At 0x22F9 (i.e. 0x22A9 + 0x50): renderer->_cmdY = fHandle->readUint16BE(); + // At 0x22FB: bgVar0 = fHandle->readUint16BE(); + // At 0x22FD: allowPlayerInput = fHandle->readUint16BE(); + // At 0x22FF: playerCommand = fHandle->readSint16BE(); + // At 0x2301: commandVar1 = fHandle->readSint16BE(); + // At 0x2303: isDrawCommandEnabled = fHandle->readUint16BE(); + // At 0x2305: var5 = fHandle->readUint16BE(); + // At 0x2307: var4 = fHandle->readUint16BE(); + // At 0x2309: var3 = fHandle->readUint16BE(); + // At 0x230B: var2 = fHandle->readUint16BE(); + // At 0x230D: commandVar2 = fHandle->readSint16BE(); + // At 0x230F: renderer->_messageBg = fHandle->readUint16BE(); + // At 0x2311: fHandle->readUint16BE(); + // At 0x2313: fHandle->readUint16BE(); + // At 0x2315: loadResourcesFromSave(*fHandle, broken); // TODO: handle screen params (really required ?) From 7b00db03123ae6a4761d0fc42bac0a5be6b4ad28 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Fri, 18 Jul 2008 19:02:40 +0000 Subject: [PATCH 23/48] Symbian soundsmixer update. (Compile fix) svn-id: r33098 --- backends/platform/symbian/src/SymbianOS.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index dfeb24d8259..9e0b8d7c22d 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -33,7 +33,7 @@ #include "gui/Actions.h" #include "gui/Key.h" #include "gui/message.h" - +#include "sound/mixer_intern.h" #include "..\..\sdl\main.cpp" #ifdef SAMPLES_PER_SEC_8000 // the GreanSymbianMMP format cannot handle values for defines :( @@ -246,9 +246,9 @@ void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len) if (!this_->_mixer) return; -#ifdef S60 +#if defined (S60) && !defined(S60V3) // If not stereo then we need to downmix - if (_channels != 2) { + if (this_->_mixer->_channels != 2) { this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2); int16 *bitmixDst = (int16 *)samples; From 0f03a7bcd82ae6e07521cfaf599b41ac6b38f5ef Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Fri, 18 Jul 2008 20:40:48 +0000 Subject: [PATCH 24/48] Introduced cache for filereading to fix slowness in AGOS among others. svn-id: r33099 --- backends/platform/symbian/src/SymbianOS.cpp | 91 +++++++++++++++++++-- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index 9e0b8d7c22d..5544cf08873 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -42,10 +42,22 @@ #define SAMPLES_PER_SEC 16000 #endif +#define KInputBufferLength 128 +// Symbian libc file functionality in order to provide shared file handles +struct TSymbianFileEntry { + RFile iFileHandle; + char iInputBuffer[KInputBufferLength]; + TInt iInputBufferLen; + TInt iInputPos; +}; + +#define FILE void ////////// extern "C" /////////////////////////////////////////////////// namespace Symbian { + + // Show a simple Symbian Info win with Msg & exit void FatalError(const char *msg) { TPtrC8 msgPtr((const TUint8 *)msg); @@ -443,15 +455,9 @@ void OSystem_SDL_Symbian::initZones() { } } -// Symbian libc file functionality in order to provide shared file handles -struct TSymbianFileEntry { - RFile iFileHandle; -}; - -#define FILE void - FILE* symbian_fopen(const char* name, const char* mode) { TSymbianFileEntry* fileEntry = new TSymbianFileEntry; + fileEntry->iInputPos = KErrNotFound; if (fileEntry != NULL) { TInt modeLen = strlen(mode); @@ -509,9 +515,71 @@ void symbian_fclose(FILE* handle) { } size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) { - TPtr8 pointer( (unsigned char*) ptr, size*numItems); + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); + TUint32 totsize = size*numItems; + TPtr8 pointer ( (unsigned char*) ptr, totsize); - ((TSymbianFileEntry*)(handle))->iFileHandle.Read(pointer); + // Nothing cached and we want to load at least KInputBufferLength bytes + if(totsize >= KInputBufferLength) { + TUint32 totLength = 0; + if(entry->iInputPos != KErrNotFound) + { + TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength); + pointer.Append(cacheBuffer); + entry->iInputPos = KErrNotFound; + totLength+=pointer.Length(); + pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength); + } + + entry->iFileHandle.Read(pointer); + totLength+=pointer.Length(); + + pointer.Set((unsigned char*) ptr, totLength, totsize); + + } + else { + // Nothing in buffer + if(entry->iInputPos == KErrNotFound) { + TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength); + entry->iFileHandle.Read(cacheBuffer); + + if(cacheBuffer.Length() >= totsize) { + pointer.Copy(cacheBuffer.Left(totsize)); + entry->iInputPos = totsize; + entry->iInputBufferLen = cacheBuffer.Length(); + } + else { + pointer.Copy(cacheBuffer); + entry->iInputPos = KErrNotFound; + } + + } + else { + TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength, entry->iInputBufferLen); + + if(entry->iInputPos+totsize < entry->iInputBufferLen) { + pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize)); + entry->iInputPos+=totsize; + } + else { + + pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos)); + cacheBuffer.SetLength(0); + entry->iFileHandle.Read(cacheBuffer); + + if(cacheBuffer.Length() >= totsize-pointer.Length()) { + TUint32 restSize = totsize-pointer.Length(); + pointer.Append(cacheBuffer.Left(restSize)); + entry->iInputPos = restSize; + entry->iInputBufferLen = cacheBuffer.Length(); + } + else { + pointer.Append(cacheBuffer); + entry->iInputPos = KErrNotFound; + } + } + } + } return pointer.Length()/size; } @@ -519,6 +587,7 @@ size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { TPtrC8 pointer( (unsigned char*) ptr, size*numItems); + ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound; if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) { return numItems; } @@ -528,6 +597,7 @@ size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handl bool symbian_feof(FILE* handle) { TInt pos = 0; + if (((TSymbianFileEntry*)(handle))->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) { TInt size = 0; @@ -549,6 +619,7 @@ long int symbian_ftell(FILE* handle) { } int symbian_fseek(FILE* handle, long int offset, int whence) { + TSeek seekMode = ESeekStart; TInt pos = offset; @@ -564,6 +635,8 @@ int symbian_fseek(FILE* handle, long int offset, int whence) { break; } + + ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound; return ((TSymbianFileEntry*)(handle))->iFileHandle.Seek(seekMode, pos); } From 4657a52b077740c0c1da6208019ba886d0da2242 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Fri, 18 Jul 2008 22:07:52 +0000 Subject: [PATCH 25/48] Fixed typo in filehandling svn-id: r33104 --- backends/platform/symbian/src/SymbianOS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index 5544cf08873..d362d27d74b 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -555,7 +555,7 @@ size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle } else { - TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength, entry->iInputBufferLen); + TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength); if(entry->iInputPos+totsize < entry->iInputBufferLen) { pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize)); From 6cff2e82399bd9fb7ff87378f84d9f83aedfed5a Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Sat, 19 Jul 2008 07:08:37 +0000 Subject: [PATCH 26/48] eof was not working properly with caching svn-id: r33108 --- backends/platform/symbian/src/SymbianOS.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index d362d27d74b..660b0c69edd 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -597,13 +597,18 @@ size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handl bool symbian_feof(FILE* handle) { TInt pos = 0; + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); - if (((TSymbianFileEntry*)(handle))->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) { + if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) { TInt size = 0; - if (((TSymbianFileEntry*)(handle))->iFileHandle.Size(size) == KErrNone) { - if (pos == size) + if (entry->iFileHandle.Size(size) == KErrNone) { + if(entry->iInputPos == KErrNotFound && pos == size) return true; + + if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen) + return true; + return false; } } From ec02171268db13d069dd312cdd38ab281087366c Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Sat, 19 Jul 2008 07:44:12 +0000 Subject: [PATCH 27/48] Enable support to turn off ALL variations. all variation is most often the one used svn-id: r33109 --- .../symbian/BuildPackageUpload_LocalSettings.pl | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index 1e5e4dc0c84..5d85fc03a29 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -226,28 +226,31 @@ $VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines"; # now one for each ready-for-release engine - + if (0) + { foreach (@WorkingEngines) { $VariationSets{'ALL'}{$_} = "$DefaultFeatures $_"; } # for scumm, we need to add 2 features: - $VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he"; - + #$VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he"; + } + # now one for each not-ready-for-release-or-testing engine - + if (0) + { foreach (@TestingEngines) { $VariationSets{'ALL'}{"test_$_"} = "$DefaultFeatures $_"; } - + } # below here you could specify weird & experimental combinations, non-ready engines # a small version of the saga engine, because it is so big (no tremor,mad,zlib) - $VariationSets{'ALL'}{'saga_mini'} = "saga"; + #$VariationSets{'ALL'}{'saga_mini'} = "saga"; # a smaller version of scumm without support for v7, v8 and HE games - $VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm"; + #$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm"; # maybe you feel lucky and want to test the sword engines? :P #$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2"; From 4ab211f6732afb445e8f0e579b9e07b7fbfaa644 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 19 Jul 2008 21:42:31 +0000 Subject: [PATCH 28/48] Removed -Wundef from the default list of compiler flags, and changed PLUGIN_ENABLED_DYNAMIC to not use 'defined()', thus avoiding compiler problems on e.g. BeOS svn-id: r33114 --- Makefile | 2 +- base/plugins.h | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 506265032a3..2395511ee38 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ CXXFLAGS:= -Wall $(CXXFLAGS) CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder # Enable even more warnings... CXXFLAGS+= -pedantic -Wpointer-arith -Wcast-qual -Wcast-align -CXXFLAGS+= -Wshadow -Wimplicit -Wundef -Wnon-virtual-dtor -Wwrite-strings +CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings # Disable RTTI and exceptions, and enabled checking of pointers returned by "new" CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new diff --git a/base/plugins.h b/base/plugins.h index 9d3ce97c3ba..02116f6433f 100644 --- a/base/plugins.h +++ b/base/plugins.h @@ -81,17 +81,11 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX]; #define STATIC_PLUGIN 1 #define DYNAMIC_PLUGIN 2 -// Note: The spaces around ENABLE_##ID have been added on purpose for -// MSVC. For some reason, MSVC tries to add the parenthesis after -// ENABLE_##ID to the check, thus making it false all the time. -// Please do NOT remove them, otherwise no engine plugins will be -// registered under MSVC - #define PLUGIN_ENABLED_STATIC(ID) \ - (defined( ENABLE_##ID ) && !PLUGIN_ENABLED_DYNAMIC(ID)) + (ENABLE_##ID && !PLUGIN_ENABLED_DYNAMIC(ID)) #define PLUGIN_ENABLED_DYNAMIC(ID) \ - (defined( ENABLE_##ID ) && (ENABLE_##ID == DYNAMIC_PLUGIN) && defined(DYNAMIC_MODULES)) + (ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES) /** * REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare From 282cb3c0df70153c3dcc93ab93b5ce2bb02eb88c Mon Sep 17 00:00:00 2001 From: Max Lingua Date: Sun, 20 Jul 2008 01:30:47 +0000 Subject: [PATCH 29/48] 1. Re-added "rpckbd" as in 0.11.0 2. Committed only its source, you will need to do a make inside its folder before being able to compile our beloved PlayStation2 backend. Enjoy, -max svn-id: r33115 --- backends/platform/ps2/iop/rpckbd/Makefile | 30 + .../platform/ps2/iop/rpckbd/include/ps2kbd.h | 90 + .../platform/ps2/iop/rpckbd/src/imports.lst | 58 + .../platform/ps2/iop/rpckbd/src/irx_imports.h | 35 + backends/platform/ps2/iop/rpckbd/src/ps2kbd.c | 1199 +++++++++++++ .../platform/ps2/iop/rpckbd/src/us_keymap.h | 1579 +++++++++++++++++ 6 files changed, 2991 insertions(+) create mode 100644 backends/platform/ps2/iop/rpckbd/Makefile create mode 100644 backends/platform/ps2/iop/rpckbd/include/ps2kbd.h create mode 100644 backends/platform/ps2/iop/rpckbd/src/imports.lst create mode 100644 backends/platform/ps2/iop/rpckbd/src/irx_imports.h create mode 100644 backends/platform/ps2/iop/rpckbd/src/ps2kbd.c create mode 100644 backends/platform/ps2/iop/rpckbd/src/us_keymap.h diff --git a/backends/platform/ps2/iop/rpckbd/Makefile b/backends/platform/ps2/iop/rpckbd/Makefile new file mode 100644 index 00000000000..b25efa36607 --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/Makefile @@ -0,0 +1,30 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ + + +IOP_OBJS_DIR = obj/ +IOP_BIN_DIR = bin/ +IOP_SRC_DIR = src/ +IOP_INC_DIR = include/ + +IOP_BIN=bin/rpckbd.irx +IOP_OBJS=obj/ps2kbd.o obj/imports.o + +IOP_CFLAGS=-Wall +IOP_INCS += -I$(PS2SDKSRC)/iop/usb/usbd/include + +all: $(IOP_OBJS_DIR) $(IOP_BIN_DIR) $(IOP_BIN) + +clean: + rm -f -r $(IOP_OBJS_DIR) $(IOP_BIN_DIR) + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h new file mode 100644 index 00000000000..f16c7ca12b9 --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h @@ -0,0 +1,90 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# USB Keyboard Driver for PS2 +*/ + +#ifndef __PS2KBD_H__ +#define __PS2KBD_H__ + +#define PS2KBD_RPC_ID 0xb0b0b80 + +#define PS2KBD_LED_NUMLOCK 1 +#define PS2KBD_LED_CAPSLOCK 2 +#define PS2KBD_LED_SCRLOCK 4 +#define PS2KBD_LED_COMPOSE 8 +#define PS2KBD_LED_KANA 16 + +#define PS2KBD_LED_MASK 0x1F; + +#define PS2KBD_ESCAPE_KEY 0x1B + +#define PS2KBD_LEFT_CTRL (1 << 0) +#define PS2KBD_LEFT_SHIFT (1 << 1) +#define PS2KBD_LEFT_ALT (1 << 2) +#define PS2KBD_LEFT_GUI (1 << 3) +#define PS2KBD_RIGHT_CTRL (1 << 4) +#define PS2KBD_RIGHT_SHIFT (1 << 5) +#define PS2KBD_RIGHT_ALT (1 << 6) +#define PS2KBD_RIGHT_GUI (1 << 7) + +#define PS2KBD_CTRL (PS2KBD_LEFT_CTRL | PS2KBD_RIGHT_CTRL) +#define PS2KBD_SHIFT (PS2KBD_LEFT_SHIFT | PS2KBD_RIGHT_SHIFT) +#define PS2KBD_ALT (PS2KBD_LEFT_ALT | PS2KBD_RIGHT_ALT) +#define PS2KBD_GUI (PS2KBD_LEFT_GUI | PS2KBD_RIGHT_GUI) + +#define PS2KBD_RAWKEY_UP 0xF0 +#define PS2KBD_RAWKEY_DOWN 0xF1 + +typedef struct _kbd_rawkey { + u8 state; + u8 key; +} kbd_rawkey __attribute__ ((packed)); + +#define PS2KBD_READMODE_NORMAL 1 +#define PS2KBD_READMODE_RAW 2 + +/* Notes on read mode */ +/* In normal readmode (default) read multiples of 1 character off the keyboard file. These are + processed by the keymaps so that you get back ASCII data */ +/* In raw readmode must read multiples of 2. First byte indicates state (i.e. Up or Down) + Second byte is the USB key code for that key. This table is presented in the USB HID Usage Tables manaual + from usb.org */ + +#define PS2KBD_KEYMAP_SIZE 256 + +typedef struct _kbd_keymap + +{ + u8 keymap[PS2KBD_KEYMAP_SIZE]; + u8 shiftkeymap[PS2KBD_KEYMAP_SIZE]; + u8 keycap[PS2KBD_KEYMAP_SIZE]; +} kbd_keymap; + + +/* IRPC function numbers */ +#define KBD_RPC_SETREADMODE 1 /* Sets up keymapped or raw mode */ +#define KBD_RPC_SETLEDS 2 /* Sets the LED state for ALL keyboards connected */ +#define KBD_RPC_SETREPEATRATE 3 /* Sets the repeat rate of the keyboard */ +#define KBD_RPC_SETKEYMAP 4 /* Sets the keymap for the standard keys, non shifted and shifted */ +#define KBD_RPC_SETCTRLMAP 5 /* Sets the control key mapping */ +#define KBD_RPC_SETALTMAP 6 /* Sets the alt key mapping */ +#define KBD_RPC_SETSPECIALMAP 7 /* Sets the special key mapping */ +#define KBD_RPC_FLUSHBUFFER 9 /* Flush the internal buffer, probably best after a keymap change */ +#define KBD_RPC_RESETKEYMAP 10 /* Reset keymaps to default states */ +#define KBD_RPC_READKEY 11 +#define KBD_RPC_READRAW 12 + +/* Note on keymaps. In normal keymap a 0 would indicate no key */ +/* Key maps are represented by 3 256*8bit tables. First table maps USB key to a char when not shifted */ +/* Second table maps USB key to a char when shifted */ +/* Third table contains boolean values. If 1 then the key is shifted/unshifted in capslock, else capslock is ignored */ + +#endif diff --git a/backends/platform/ps2/iop/rpckbd/src/imports.lst b/backends/platform/ps2/iop/rpckbd/src/imports.lst new file mode 100644 index 00000000000..41e13e6e737 --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/src/imports.lst @@ -0,0 +1,58 @@ + +sysclib_IMPORTS_start +I_memset +I_strcmp +I_memcpy +sysclib_IMPORTS_end + +loadcore_IMPORTS_start +I_FlushDcache +loadcore_IMPORTS_end + +sifcmd_IMPORTS_start +I_sceSifInitRpc +I_sceSifSetRpcQueue +I_sceSifRegisterRpc +I_sceSifRpcLoop +sifcmd_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +thsemap_IMPORTS_start +I_CreateSema +I_SignalSema +I_WaitSema +I_PollSema +I_DeleteSema +thsemap_IMPORTS_end + +thbase_IMPORTS_start +I_StartThread +I_CreateThread +I_USec2SysClock +I_iSetAlarm +I_SetAlarm +I_CancelAlarm +thbase_IMPORTS_end + +thevent_IMPORTS_start +I_WaitEventFlag +I_iSetEventFlag +I_CreateEventFlag +thevent_IMPORTS_end + +sysmem_IMPORTS_start +I_AllocSysMemory +I_FreeSysMemory +sysmem_IMPORTS_end + +usbd_IMPORTS_start +I_UsbGetDeviceStaticDescriptor +I_UsbOpenEndpoint +I_UsbSetDevicePrivateData +I_UsbTransfer +I_UsbRegisterDriver +usbd_IMPORTS_end + diff --git a/backends/platform/ps2/iop/rpckbd/src/irx_imports.h b/backends/platform/ps2/iop/rpckbd/src/irx_imports.h new file mode 100644 index 00000000000..6ecc8e58645 --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/src/irx_imports.h @@ -0,0 +1,35 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright (c) 2003 Marcus R. Brown +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include "irx.h" + +/* Please keep these in alphabetical order! */ +#include "dmacman.h" +#include "intrman.h" +#include "libsd.h" +#include "loadcore.h" +#include "sifcmd.h" +#include "stdio.h" +#include "sysclib.h" +#include "sysmem.h" +#include "thbase.h" +#include "thevent.h" +#include "thmsgbx.h" +#include "thsemap.h" +#include "usbd.h" +#include "vblank.h" + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c new file mode 100644 index 00000000000..f87a47f0cbd --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c @@ -0,0 +1,1199 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2005, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# USB Keyboard Driver for PS2 +*/ + +#include "types.h" +#include "ioman.h" +#include "loadcore.h" +#include "stdio.h" +#include "sifcmd.h" +#include "sifrpc.h" +#include "sysclib.h" +#include "sysmem.h" +#include "usbd.h" +#include "usbd_macro.h" +#include "thbase.h" +#include "thevent.h" +#include "thsemap.h" + +#include "ps2kbd.h" +#include "us_keymap.h" + +#define PS2KBD_VERSION 0x100 + +#define USB_SUBCLASS_BOOT 1 +#define USB_HIDPROTO_KEYBOARD 1 + +#define PS2KBD_MAXDEV 2 +#define PS2KBD_MAXKEYS 6 + +#define PS2KBD_DEFLINELEN 4096 +#define PS2KBD_DEFREPEATRATE 100 +/* Default repeat rate in milliseconds */ +#define PS2KBD_REPEATWAIT 1000 +/* Number of milliseconds to wait before starting key repeat */ +#define USB_KEYB_NUMLOCK 0x53 +#define USB_KEYB_CAPSLOCK 0x39 +#define USB_KEYB_SCRLOCK 0x47 + +#define USB_KEYB_NUMPAD_START 0x54 +#define USB_KEYB_NUMPAD_END 0x63 + +#define SEMA_ZERO -419 +#define SEMA_DELETED -425 + +int ps2kbd_init(); +void ps2kbd_config_set(int resultCode, int bytes, void *arg); +void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg); +void ps2kbd_data_recv(int resultCode, int bytes, void *arg); +int ps2kbd_probe(int devId); +int ps2kbd_connect(int devId); +int ps2kbd_disconnect(int devId); +void usb_getstring(int endp, int index, char *desc); + +typedef struct _kbd_data_recv + +{ + u8 mod_keys; + u8 reserved; + u8 keycodes[PS2KBD_MAXKEYS]; +} kbd_data_recv; + +typedef struct _keyb_dev + +{ + int configEndp; + int dataEndp; + int packetSize; + int devId; + int interfaceNo; /* Holds the interface number selected on this device */ + char repeatkeys[2]; + u32 eventmask; + u8 ledStatus; /* Maintains state on the led status */ + kbd_data_recv oldData; + kbd_data_recv data; /* Holds the data for the transfers */ +} kbd_dev; + +/* Global Variables */ + +int kbd_readmode; +u32 kbd_repeatrate; +kbd_dev *devices[PS2KBD_MAXDEV]; /* Holds a list of current devices */ +int dev_count; +UsbDriver kbd_driver = { NULL, NULL, "PS2Kbd", ps2kbd_probe, ps2kbd_connect, ps2kbd_disconnect }; +u8 *lineBuffer; +u32 lineStartP, lineEndP; +int lineSema; +int bufferSema; +u32 lineSize; +u8 keymap[PS2KBD_KEYMAP_SIZE]; /* Normal key map */ +u8 shiftkeymap[PS2KBD_KEYMAP_SIZE]; /* Shifted key map */ +u8 keycap[PS2KBD_KEYMAP_SIZE]; /* Does this key get shifted by capslock ? */ +u8 special_keys[PS2KBD_KEYMAP_SIZE]; +u8 control_map[PS2KBD_KEYMAP_SIZE]; +u8 alt_map[PS2KBD_KEYMAP_SIZE]; +//static struct fileio_driver kbd_fdriver; +iop_device_t kbd_filedrv; +u8 keyModValue[8] = { 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7 }; +int repeat_tid; +int eventid; /* Id of the repeat event */ + +int _start () +{ + FlushDcache(); + + ps2kbd_init(); + + printf("PS2KBD - USB Keyboard Library\n"); + + return 0; + +} + +int ps2kbd_probe(int devId) + +{ + UsbDeviceDescriptor *dev; + UsbConfigDescriptor *conf; + UsbInterfaceDescriptor *intf; + UsbEndpointDescriptor *endp; + //UsbStringDescriptor *str; + + if(dev_count >= PS2KBD_MAXDEV) + { + printf("ERROR: Maximum keyboard devices reached\n"); + return 0; + } + + //printf("PS2Kbd_probe devId %d\n", devId); + + dev = UsbGetDeviceStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */ + if(!dev) + { + printf("ERROR: Couldn't get device descriptor\n"); + return 0; + } + + //printf("Device class %d, Size %d, Man %d, Product %d Cpnfigurations %d\n", dev->bDeviceClass, dev->bMaxPacketSize0, dev->iManufacturer, dev->iProduct, dev->bNumConfigurations); + /* Check that the device class is specified in the interfaces and it has at least one configuration */ + if((dev->bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->bNumConfigurations < 1)) + { + //printf("This is not the droid you're looking for\n"); + return 0; + } + + conf = UsbGetDeviceStaticDescriptor(devId, dev, USB_DT_CONFIG); + if(!conf) + { + printf("ERROR: Couldn't get configuration descriptor\n"); + return 0; + } + //printf("Config Length %d Total %d Interfaces %d\n", conf->bLength, conf->wTotalLength, conf->bNumInterfaces); + + if((conf->bNumInterfaces < 1) || (conf->wTotalLength < (sizeof(UsbConfigDescriptor) + sizeof(UsbInterfaceDescriptor)))) + { + printf("ERROR: No interfaces available\n"); + return 0; + } + + intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */ +/* printf("Interface Length %d Endpoints %d Class %d Sub %d Proto %d\n", intf->bLength, */ +/* intf->bNumEndpoints, intf->bInterfaceClass, intf->bInterfaceSubClass, */ +/* intf->bInterfaceProtocol); */ + + if((intf->bInterfaceClass != USB_CLASS_HID) || (intf->bInterfaceSubClass != USB_SUBCLASS_BOOT) || + (intf->bInterfaceProtocol != USB_HIDPROTO_KEYBOARD) || (intf->bNumEndpoints < 1)) + + { + //printf("We came, we saw, we told it to fuck off\n"); + return 0; + } + + endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength); + endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */ + + //printf("Endpoint 1 Addr %d, Attr %d, MaxPacket %d\n", endp->bEndpointAddress, endp->bmAttributes, endp->wMaxPacketSizeLB); + + if(((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) || + ((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)) + { + printf("ERROR: Endpoint not interrupt type and/or an input\n"); + return 0; + } + + printf("PS2KBD: Found a keyboard device\n"); + + return 1; +} + +int ps2kbd_connect(int devId) + +{ + /* Assume we can only get here if we have already checked the device is kosher */ + + UsbDeviceDescriptor *dev; + UsbConfigDescriptor *conf; + UsbInterfaceDescriptor *intf; + UsbEndpointDescriptor *endp; + kbd_dev *currDev; + int devLoop; + + //printf("PS2Kbd_connect devId %d\n", devId); + + dev = UsbGetDeviceStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */ + if(!dev) + { + printf("ERROR: Couldn't get device descriptor\n"); + return 1; + } + + conf = UsbGetDeviceStaticDescriptor(devId, dev, USB_DT_CONFIG); + if(!conf) + { + printf("ERROR: Couldn't get configuration descriptor\n"); + return 1; + } + + intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */ + endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength); + endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */ + + for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++) + { + if(devices[devLoop] == NULL) + { + break; + } + } + + if(devLoop == PS2KBD_MAXDEV) + { + /* How the f*** did we end up here ??? */ + printf("ERROR: Device Weirdness!!\n"); + return 1; + } + + currDev = (kbd_dev *) AllocSysMemory(0, sizeof(kbd_dev), NULL); + if(!currDev) + { + printf("ERROR: Couldn't allocate a device point for the kbd\n"); + return 1; + } + + devices[devLoop] = currDev; + memset(currDev, 0, sizeof(kbd_dev)); + currDev->configEndp = UsbOpenEndpoint(devId, NULL); + currDev->dataEndp = UsbOpenEndpoint(devId, endp); + currDev->packetSize = endp->wMaxPacketSizeLB | ((int) endp->wMaxPacketSizeHB << 8); + currDev->eventmask = (1 << devLoop); + if(currDev->packetSize > sizeof(kbd_data_recv)) + { + currDev->packetSize = sizeof(kbd_data_recv); + } + + if(dev->iManufacturer != 0) + { + usb_getstring(currDev->configEndp, dev->iManufacturer, "Keyboard Manufacturer"); + } + + if(dev->iProduct != 0) + { + usb_getstring(currDev->configEndp, dev->iProduct, "Keyboard Product"); + } + + currDev->devId = devId; + currDev->interfaceNo = intf->bInterfaceNumber; + currDev->ledStatus = 0; + + UsbSetDevicePrivateData(devId, currDev); /* Set the index for the device data */ + + //printf("Configuration value %d\n", conf->bConfigurationValue); + UsbSetDeviceConfiguration(currDev->configEndp, conf->bConfigurationValue, ps2kbd_config_set, currDev); + + dev_count++; /* Increment device count */ + printf("PS2KBD: Connected device\n"); + + return 0; +} + +int ps2kbd_disconnect(int devId) + +{ + int devLoop; + printf("PS2Kbd_disconnect devId %d\n", devId); + + for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++) + { + if((devices[devLoop]) && (devices[devLoop]->devId == devId)) + { + dev_count--; + FreeSysMemory(devices[devLoop]); + devices[devLoop] = NULL; + printf("PS2KBD: Disconnected device\n"); + break; + } + } + + return 0; +} + +typedef struct _string_descriptor + +{ + u8 buf[200]; + char *desc; +} string_descriptor; + +void ps2kbd_getstring_set(int resultCode, int bytes, void *arg) + +{ + UsbStringDescriptor *str = (UsbStringDescriptor *) arg; + string_descriptor *strBuf = (string_descriptor *) arg; + char string[50]; + int strLoop; + +/* printf("=========getstring=========\n"); */ + +/* printf("PS2KEYBOARD: GET_DESCRIPTOR res %d, bytes %d, arg %p\n", resultCode, bytes, arg); */ + + if(resultCode == USB_RC_OK) + { + memset(string, 0, 50); + for(strLoop = 0; strLoop < ((bytes - 2) / 2); strLoop++) + { + string[strLoop] = str->wData[strLoop] & 0xFF; + } + printf("%s: %s\n", strBuf->desc, string); + } + + FreeSysMemory(arg); +} + +void usb_getstring(int endp, int index, char *desc) + +{ + u8 *data; + string_descriptor *str; + int ret; + + data = (u8 *) AllocSysMemory(0, sizeof(string_descriptor), NULL); + str = (string_descriptor *) data; + + if(data != NULL) + { + str->desc = desc; + ret = UsbControlTransfer(endp, 0x80, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | index, + 0, sizeof(string_descriptor) - 4, data, ps2kbd_getstring_set, data); + if(ret != USB_RC_OK) + { + printf("PS2KBD: Error sending string descriptor request\n"); + FreeSysMemory(data); + } + } +} + +void ps2kbd_config_set(int resultCode, int bytes, void *arg) + /* Called when we have finished choosing our configuration */ + +{ + kbd_dev *dev; + + if(resultCode != USB_RC_OK) + { + printf("PS2KEYBOARD: Configuration set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg); + return; + } + + //printf("PS2KEYBOARD: Configuration set res %d, bytes %d, arg %p\n", resultCode, bytes, arg); + /* Do a interrupt data transfer */ + + dev = (kbd_dev *) arg; + if(dev != NULL) + { + int ret; + + ret = UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_IDLE, 0, dev->interfaceNo, 0, NULL, ps2kbd_idlemode_set, arg); + } +} + +void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg) + +{ + kbd_dev *dev; + + + + if(resultCode != USB_RC_OK) + { + printf("PS2KBD: Idlemode set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg); + return; + } + + dev = (kbd_dev *) arg; + if(dev != NULL) + { + int ret; + + ret = UsbInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg); + } +} + +void ps2kbd_led_set(int resultCode, int bytes, void *arg) + +{ + //printf("LED Set\n"); +} + +void ps2kbd_build_uniquekeys(u8 *res, const u8 *new, const u8 *old) + + /* Builds a list of unique keys */ + +{ + int loopNew, loopOld; + int loopRes = 0; + int foundKey; + + for(loopNew = 0; loopNew < PS2KBD_MAXKEYS; loopNew++) + { + if(new[loopNew] != 0) + { + foundKey = 0; + for(loopOld = 0; loopOld < PS2KBD_MAXKEYS; loopOld++) + { + if(new[loopNew] == old[loopOld]) + { + foundKey = 1; + break; + } + } + if(!foundKey) + { + res[loopRes++] = new[loopNew]; + } + } + } +} + +u32 ps2kbd_repeathandler(void *arg) + +{ + kbd_dev *dev = arg; + iop_sys_clock_t t; + //printf("Repeat handler\n"); + + iSetEventFlag(eventid, dev->eventmask); + + USec2SysClock(kbd_repeatrate * 1000, &t); + iSetAlarm(&t, ps2kbd_repeathandler, arg); + + return t.hi; +} + +void ps2kbd_getkeys(u8 keyMods, u8 ledStatus, const u8 *keys, kbd_dev *dev) + +{ + int loopKey; + int tempPos = 0; + int byteCount = 0; + u8 currChars[2]; + + if(lineStartP < lineEndP) + { + tempPos = lineStartP + lineSize; + } + else + { + tempPos = lineStartP; + } + + for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) + { + u8 currKey = keys[loopKey]; + + currChars[0] = 0; + currChars[1] = 0; + + if(lineEndP == (tempPos - 1)) + { + break; + } + + if(currKey) /* If this is a valid key */ + { + if((currKey >= USB_KEYB_NUMPAD_START) && (currKey <= USB_KEYB_NUMPAD_END)) + /* Handle numpad specially */ + { + if(ledStatus & PS2KBD_LED_NUMLOCK) + { + if(keymap[currKey]) + { + currChars[0] = keymap[currKey]; + } + } + else + { + if(special_keys[currKey]) + { + currChars[0] = PS2KBD_ESCAPE_KEY; + currChars[1] = special_keys[currKey]; + } + else if(keymap[currKey] != '5') /* Make sure this isnt a 5 key :) */ + { + currChars[0] = keymap[currKey]; + } + } + } + else if(special_keys[currKey]) /* This is a special key */ + { + currChars[0] = PS2KBD_ESCAPE_KEY; + currChars[1] = special_keys[currKey]; + } + else if(keyMods & PS2KBD_CTRL) /* CTRL */ + { + if(control_map[currKey]) + { + currChars[0] = control_map[currKey]; + } + } + else if(keyMods & PS2KBD_ALT) /* ALT */ + { + if(alt_map[currKey]) + { + currChars[0] = alt_map[currKey]; + } + } + else if(keyMods & PS2KBD_SHIFT) /* SHIFT */ + { + if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey])) + { + currChars[0] = keymap[currKey]; + } + else + { + currChars[0] = shiftkeymap[currKey]; + } + } + else /* Normal key */ + { + if(keymap[keys[loopKey]]) + { + if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey])) + { + currChars[0] = shiftkeymap[currKey]; + } + else + { + currChars[0] = keymap[currKey]; + } + } + } + } + + if((currChars[0] == PS2KBD_ESCAPE_KEY) && (currChars[1] != 0)) + { + if(lineEndP != (tempPos - 2)) + { + lineBuffer[lineEndP++] = currChars[0]; + lineEndP %= lineSize; + lineBuffer[lineEndP++] = currChars[1]; + lineEndP %= lineSize; + byteCount += 2; + } + dev->repeatkeys[0] = currChars[0]; + dev->repeatkeys[1] = currChars[1]; + } + else if(currChars[0] != 0) + { + lineBuffer[lineEndP++] = currChars[0]; + lineEndP %= lineSize; + byteCount++; + dev->repeatkeys[0] = currChars[0]; + dev->repeatkeys[1] = 0; + } + } + + if(byteCount > 0) + { + iop_sys_clock_t t; + /* Set alarm to do repeat rate */ + //printf("repeatkeys %d %d\n", kbd_repeatkeys[0], kbd_repeatkeys[1]); + USec2SysClock(PS2KBD_REPEATWAIT * 1000, &t); + SetAlarm(&t, ps2kbd_repeathandler, dev); + } + + for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema to indicate data */ + { + SignalSema(bufferSema); + } + +/* lineBuffer[PS2KBD_DEFLINELEN - 1] = 0; */ +/* printf(lineBuffer); */ + //printf("lineStart %d, lineEnd %d\n", lineStartP, lineEndP); +} + + +void ps2kbd_getkeys_raw(u8 newKeyMods, u8 oldKeyMods, u8 *new, const u8 *old) + +{ + int loopKey; + u8 currKey; + u8 keyMods = newKeyMods ^ oldKeyMods; + u8 keyModsMap = newKeyMods & keyMods; + int tempPos = 0; + int byteCount = 0; + + if(lineStartP < lineEndP) + { + tempPos = lineStartP + lineSize; + } + else + { + tempPos = lineStartP; + } + + for(loopKey = 0; loopKey < 8; loopKey++) + { + int currMod = (1 << loopKey); + if(keyMods & currMod) + { + if(lineEndP == (tempPos - 2)) + { + return; + } + + currKey = keyModValue[loopKey]; + + if(keyModsMap & currMod) /* If key pressed */ + { + lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN; + //printf("Key down\n"); + } + else + { + lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP; + //printf("Key up\n"); + } + + lineEndP %= lineSize; + lineBuffer[lineEndP++] = currKey; + lineEndP %= lineSize; + byteCount += 2; + //printf("Key %d\n", currKey); + } + } + + for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) + { + if(lineEndP == (tempPos - 2)) + { + return; + } + + if(new[loopKey] != 0) + { + lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN; + lineEndP %= lineSize; + lineBuffer[lineEndP++] = new[loopKey]; + lineEndP %= lineSize; + byteCount += 2; + //printf("Key down\nKey %d\n", new[loopKey]); + } + + } + + for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) + { + if(lineEndP == (tempPos - 2)) + { + return; + } + + if(old[loopKey] != 0) + { + lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP; + lineEndP %= lineSize; + lineBuffer[lineEndP++] = old[loopKey]; + lineEndP %= lineSize; + byteCount += 2; + //printf("Key up\nKey %d\n", old[loopKey]); + } + + } + + for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema for the number of bytes read */ + { + SignalSema(bufferSema); + } +} + +void ps2kbd_data_recv(int resultCode, int bytes, void *arg) + +{ + kbd_dev *dev; + int ret; + int phantom; + int loop; + + if(resultCode != USB_RC_OK) + { + printf("PS2KEYBOARD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg); + return; + } + + //printf("PS2KBD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg); + + dev = (kbd_dev *) arg; + if(dev == NULL) + { + printf("PS2KBD: dev == NULL\n"); + return; + } + +/* printf("PS2KBD Modifiers %02X, Keys ", dev->data.mod_keys); */ +/* for(loop = 0; loop < PS2KBD_MAXKEYS; loop++) */ +/* { */ +/* printf("%02X ", dev->data.keycodes[loop]); */ +/* } */ +/* printf("\n"); */ + + CancelAlarm(ps2kbd_repeathandler, dev); /* Make sure repeat alarm is cancelled */ + + /* Check for phantom states */ + phantom = 1; + for(loop = 0; loop < PS2KBD_MAXKEYS; loop++) + { + if(dev->data.keycodes[loop] != 1) + { + phantom = 0; + break; + } + } + + if(!phantom) /* If not in a phantom state */ + { + u8 uniqueKeys[PS2KBD_MAXKEYS]; + u8 missingKeys[PS2KBD_MAXKEYS]; + int loopKey; + + memset(uniqueKeys, 0, PS2KBD_MAXKEYS); + memset(missingKeys, 0, PS2KBD_MAXKEYS); + ps2kbd_build_uniquekeys(uniqueKeys, dev->data.keycodes, dev->oldData.keycodes); + ps2kbd_build_uniquekeys(missingKeys, dev->oldData.keycodes, dev->data.keycodes); + /* Build new and missing key lists */ + +/* printf("Unique keys : "); */ +/* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */ +/* { */ +/* printf("%02X ", uniqueKeys[loopKey]); */ +/* } */ +/* printf("\n"); */ + +/* printf("Missing keys : "); */ +/* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */ +/* { */ +/* printf("%02X ", missingKeys[loopKey]); */ +/* } */ +/* printf("\n"); */ + + if(kbd_readmode == PS2KBD_READMODE_NORMAL) + { + u8 ledStatus; + + ledStatus = dev->ledStatus; + //printf("ledStatus %02X\n", ledStatus); + + for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) /* Process key codes */ + { + switch(uniqueKeys[loopKey]) + { + case USB_KEYB_NUMLOCK : + ledStatus ^= PS2KBD_LED_NUMLOCK; + uniqueKeys[loopKey] = 0; + break; + case USB_KEYB_CAPSLOCK : + ledStatus ^= PS2KBD_LED_CAPSLOCK; + uniqueKeys[loopKey] = 0; + break; + case USB_KEYB_SCRLOCK : + ledStatus ^= PS2KBD_LED_SCRLOCK; + uniqueKeys[loopKey] = 0; + break; + } + } + + if(ledStatus != dev->ledStatus) + { + dev->ledStatus = ledStatus & PS2KBD_LED_MASK; + //printf("LEDS %02X\n", dev->ledStatus); + /* Call Set LEDS */ + UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200, + dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, arg); + } + + WaitSema(lineSema); /* Make sure no other thread is going to manipulate the buffer */ + ps2kbd_getkeys(dev->data.mod_keys, dev->ledStatus, uniqueKeys, dev); /* read in remaining keys */ + SignalSema(lineSema); + } + else /* RAW Mode */ + { + WaitSema(lineSema); + ps2kbd_getkeys_raw(dev->data.mod_keys, dev->oldData.mod_keys, uniqueKeys, missingKeys); + SignalSema(lineSema); + } + + memcpy(&dev->oldData, &dev->data, sizeof(kbd_data_recv)); + } + + ret = UsbInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg); +} + +void flushbuffer() + +{ + iop_sema_t s; + + lineStartP = 0; + lineEndP = 0; + memset(lineBuffer, 0, lineSize); + + DeleteSema(bufferSema); + s.initial = 0; + s.max = lineSize; + s.option = 0; + s.attr = 0; + bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */ + + if(bufferSema <= 0) + { + printf("Error creating buffer sema\n"); + } +} + +void ps2kbd_rpc_setreadmode(u32 readmode) + +{ + int devLoop; + + if(readmode == kbd_readmode) return; + + if((readmode == PS2KBD_READMODE_NORMAL) || (readmode == PS2KBD_READMODE_RAW)) + { + /* Reset line buffer */ + //printf("ioctl_setreadmode %d\n", readmode); + for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++) + { + CancelAlarm(ps2kbd_repeathandler, devices[devLoop]); + } + + WaitSema(lineSema); + kbd_readmode = readmode; + flushbuffer(); + SignalSema(lineSema); + } +} + +void ps2kbd_rpc_setkeymap(kbd_keymap *keymaps) + +{ + //printf("ioctl_setkeymap %p\n", keymaps); + WaitSema(lineSema); /* Lock the input so you dont end up with weird results */ + memcpy(keymap, keymaps->keymap, PS2KBD_KEYMAP_SIZE); + memcpy(shiftkeymap, keymaps->shiftkeymap, PS2KBD_KEYMAP_SIZE); + memcpy(keycap, keymaps->keycap, PS2KBD_KEYMAP_SIZE); + SignalSema(lineSema); +} + +void ps2kbd_rpc_setctrlmap(u8 *ctrlmap) + +{ + //printf("ioctl_setctrlmap %p\n", ctrlmap); + WaitSema(lineSema); + memcpy(control_map, ctrlmap, PS2KBD_KEYMAP_SIZE); + SignalSema(lineSema); +} + +void ps2kbd_rpc_setaltmap(u8 *altmap) + +{ + //printf("ioctl_setaltmap %p\n", altmap); + WaitSema(lineSema); + memcpy(alt_map, altmap, PS2KBD_KEYMAP_SIZE); + SignalSema(lineSema); +} + +void ps2kbd_rpc_setspecialmap(u8 *special) + +{ + //printf("ioctl_setspecialmap %p\n", special); + WaitSema(lineSema); + memcpy(special_keys, special, PS2KBD_KEYMAP_SIZE); + SignalSema(lineSema); +} + +void ps2kbd_rpc_resetkeymap() + /* Reset keymap to default US variety */ + +{ + //printf("ioctl_resetkeymap()\n"); + WaitSema(lineSema); + memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE); + memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE); + memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE); + memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE); + memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE); + memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE); + SignalSema(lineSema); +} + +void ps2kbd_rpc_flushbuffer() + /* Flush the internal buffer */ + +{ + //printf("ioctl_flushbuffer()\n"); + WaitSema(lineSema); + flushbuffer(); + SignalSema(lineSema); +} + +void ps2kbd_rpc_setleds(u8 ledStatus) + +{ + int devLoop; + kbd_dev *dev; + + //printf("ioctl_setleds %d\n", ledStatus); + ledStatus &= PS2KBD_LED_MASK; + for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++) + { + dev = devices[devLoop]; + if(dev) + { + if(ledStatus != dev->ledStatus) + { + dev->ledStatus = ledStatus & PS2KBD_LED_MASK; + UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200, + dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, dev); + } + } + } +} + +void ps2kbd_rpc_setrepeatrate(u32 rate) +{ + kbd_repeatrate = rate; +} + +int kbd_read(void *buf, int size) +{ + int count = 0; + char *data = (char *) buf; + + if(kbd_readmode == PS2KBD_READMODE_RAW) + size &= ~1; /* Ensure size of a multiple of 2 */ + + if (PollSema(bufferSema) >= 0) { + SignalSema(bufferSema); + if (WaitSema(lineSema) >= 0) { + while((count < size) && (lineStartP != lineEndP)) { + data[count] = lineBuffer[lineStartP++]; + lineStartP %= lineSize; + count++; + PollSema(bufferSema); /* Take off one count from the sema */ + } + SignalSema(lineSema); + } + } + return count; +} + +void repeat_thread(void *arg) + +{ + u32 eventmask; + int devLoop; + + for(;;) + { + WaitEventFlag(eventid, 0xFFFFFFFF, 0x01 | 0x10, &eventmask); + //printf("Recieved event %08X\n", eventmask); + for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++) + { + if((eventmask & (1 << devLoop)) && (devices[devLoop])) + { + int tempPos = 0; + + WaitSema(lineSema); + if(lineStartP < lineEndP) + { + tempPos = lineStartP + lineSize; + } + else + { + tempPos = lineStartP; + } + + if((devices[devLoop]->repeatkeys[0]) && (devices[devLoop]->repeatkeys[1])) + { + if(lineEndP != (tempPos - 2)) + { + lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0]; + lineEndP %= lineSize; + lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[1]; + lineEndP %= lineSize; + SignalSema(bufferSema); + SignalSema(bufferSema); + } + } + else if(devices[devLoop]->repeatkeys[0]) + { + if(lineEndP != (tempPos - 1)) + { + lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0]; + lineEndP %= lineSize; + SignalSema(bufferSema); + } + } + + SignalSema(lineSema); + } + } + } +} + +int init_repeatthread() + /* Creates a thread to handle key repeats */ +{ + iop_thread_t param; + iop_event_t event; + + event.attr = 0; + event.option = 0; + event.bits = 0; + eventid = CreateEventFlag(&event); + + param.attr = TH_C; + param.thread = repeat_thread; + param.priority = 40; + param.stacksize = 0x800; + param.option = 0; + + repeat_tid = CreateThread(¶m); + if (repeat_tid > 0) { + StartThread(repeat_tid, 0); + return 0; + } + else + { + return 1; + } +} + +static unsigned long retKey; + +void *ps2kbd_rpc_server(int fno, void *data, int size) { + retKey = 0; + switch (fno) { + case KBD_RPC_SETREADMODE: + ps2kbd_rpc_setreadmode(*(u32 *)data); + break; + case KBD_RPC_SETKEYMAP: + ps2kbd_rpc_setkeymap((kbd_keymap *) data); + break; + case KBD_RPC_SETALTMAP: + ps2kbd_rpc_setaltmap((u8 *) data); + break; + case KBD_RPC_SETCTRLMAP: + ps2kbd_rpc_setctrlmap((u8 *) data); + break; + case KBD_RPC_SETSPECIALMAP: + ps2kbd_rpc_setspecialmap((u8 *) data); + break; + case KBD_RPC_FLUSHBUFFER: + ps2kbd_rpc_flushbuffer(); + break; + case KBD_RPC_SETLEDS: + ps2kbd_rpc_setleds(*(u8*) data); + break; + case KBD_RPC_RESETKEYMAP: + ps2kbd_rpc_resetkeymap(); + break; + case KBD_RPC_SETREPEATRATE: + ps2kbd_rpc_setrepeatrate(*(u32 *) data); + break; + case KBD_RPC_READRAW: + kbd_read(&retKey, 2); + return &retKey; + case KBD_RPC_READKEY: + kbd_read(&retKey, 1); + return &retKey; + default: + printf("Ps2Kbd: Unknown RPC command %d\n", fno); + break; + } + return NULL; +} + +struct t_SifRpcDataQueue qd; +struct t_SifRpcServerData sd0; +void *rpcRcvBuf; + +void ps2kbd_start_rpc(unsigned long tid) { + rpcRcvBuf = AllocSysMemory(0, 3 * PS2KBD_KEYMAP_SIZE, NULL); + printf("Ps2Kbd: starting RPC server\n"); + SifInitRpc(0); + + SifSetRpcQueue(&qd, tid); + SifRegisterRpc(&sd0, PS2KBD_RPC_ID, ps2kbd_rpc_server, rpcRcvBuf, 0, 0, &qd); + SifRpcLoop(&qd); +} + +int ps2kbd_init_rpc(void) { + struct _iop_thread param; + int th; + + param.attr = 0x02000000; + param.thread = (void*)ps2kbd_start_rpc; + param.priority = 40; + param.stacksize = 0x800; + param.option = 0; + + th = CreateThread(¶m); + + if (th > 0) { + StartThread(th, (void *)th); + return 0; + } else + return -1; +} + +int ps2kbd_init() { + int ret; + iop_sema_t s; + + s.initial = 1; + s.max = 1; + s.option = 0; + s.attr = 0; + lineSema = CreateSema(&s); + if(lineSema <= 0) + { + printf("Error creating sema\n"); + return 1; + } + + s.initial = 0; + s.max = PS2KBD_DEFLINELEN; + s.option = 0; + s.attr = 0; + bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */ + if(bufferSema <= 0) + { + printf("Error creating buffer sema\n"); + return 1; + } + + lineBuffer = (u8 *) AllocSysMemory(0, PS2KBD_DEFLINELEN, NULL); + if(lineBuffer == NULL) + { + printf("Error allocating line buffer\n"); + return 1; + } + lineStartP = 0; + lineEndP = 0; + lineSize = PS2KBD_DEFLINELEN; + memset(lineBuffer, 0, PS2KBD_DEFLINELEN); + + memset(devices, 0, sizeof(kbd_dev *) * PS2KBD_MAXDEV); + dev_count = 0; + kbd_readmode = PS2KBD_READMODE_NORMAL; + kbd_repeatrate = PS2KBD_DEFREPEATRATE; + memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE); + memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE); + memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE); + memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE); + memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE); + memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE); + + ps2kbd_init_rpc(); + init_repeatthread(); + + ret = UsbRegisterDriver(&kbd_driver); + if(ret != USB_RC_OK) + { + printf("Error registering USB devices\n"); + return 1; + } + + printf("UsbRegisterDriver %d\n", ret); + + return 0; +} diff --git a/backends/platform/ps2/iop/rpckbd/src/us_keymap.h b/backends/platform/ps2/iop/rpckbd/src/us_keymap.h new file mode 100644 index 00000000000..57f0686cd3e --- /dev/null +++ b/backends/platform/ps2/iop/rpckbd/src/us_keymap.h @@ -0,0 +1,1579 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# $Id$ +# USB Keyboard Driver for PS2 +*/ + +#ifndef __US_KEYMAP_H__ +#define __US_KEYMAP_H__ + +/* Default US keymap */ + +u8 us_keymap[PS2KBD_KEYMAP_SIZE] = + { + 0, + 0, + 0, + 0, + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + 10, /* line feed */ + 0, /* Esc */ + 0x7,/* BS */ + 0x9, /* TAB */ + 0x20, + '-', + '=', + '[', + ']', + '\\', + '#', + ';', + '\'', + '`', + ',', + '.', + '/', + 0, /* CL */ + 0, // F1 + 0, // F2 + 0, // F3 + 0, // F4 + 0, // F5 + 0, // F6 + 0, // F7 + 0, // F8 + 0, // F9 + 0, // F10 + 0, // F11 + 0, // F12 + 0, // PrintScr + 0, // Scroll Lock + 0, // Pause + 0, // Insert + 0, // Home + 0, // Pg Up + 0, // Delete + 0, // End + 0, // Pg Down + 0, // Right + 0, // Left + 0, // Down + 0, // Up + 0, // Numlock + '/', // Keypad + '*', + '-', + '+', + 10, + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '.', + '\\', + 0, + 0, + '=', + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + +u8 us_shiftkeymap[PS2KBD_KEYMAP_SIZE] = + { + 0, + 0, + 0, + 0, + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + '!', + '@', + '#', + '$', + '%', + '^', + '&', + '*', + '(', + ')', + 10, /* line feed */ + 0, /* Esc */ + 0x7,/* BS */ + 0x9, /* TAB */ + 0x20, + '_', + '+', + '{', + '}', + '|', + '~', + ':', + '"', + '~', + '<', + '>', + '?', + 0, /* CL */ + 0, // F1 + 0, // F2 + 0, // F3 + 0, // F4 + 0, // F5 + 0, // F6 + 0, // F7 + 0, // F8 + 0, // F9 + 0, // F10 + 0, // F11 + 0, // F12 + 0, // PrintScr + 0, // Scroll Lock + 0, // Pause + 0, // Insert + 0, // Home + 0, // Pg Up + 0, // Delete + 0, // End + 0, // Pg Down + 0, // Right + 0, // Left + 0, // Down + 0, // Up + 0, // Numlock + '/', // Keypad + '*', + '-', + '+', + 10, + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '.', + '\\', + 0, + 0, + '=', + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + +u8 us_keycap[PS2KBD_KEYMAP_SIZE] = + { + 0, + 0, + 0, + 0, + 1, //a + 1, //b + 1, //c + 1, //d + 1, //e + 1, //f + 1,//g + 1,//h + 1,//i + 1,//j + 1,//k + 1,//l + 1,//m + 1,//n + 1,//o + 1,//p + 1,//q + 1,//r + 1,//s + 1,//t + 1,//u + 1,//v + 1,//w + 1,//x + 1,//y + 1,//z + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* line feed */ + 0, /* Esc */ + 0,/* BS */ + 0, /* TAB */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* CL */ + 0, // F1 + 0, // F2 + 0, // F3 + 0, // F4 + 0, // F5 + 0, // F6 + 0, // F7 + 0, // F8 + 0, // F9 + 0, // F10 + 0, // F11 + 0, // F12 + 0, // PrintScr + 0, // Scroll Lock + 0, // Pause + 0, // Insert + 0, // Home + 0, // Pg Up + 0, // Delete + 0, // End + 0, // Pg Down + 0, // Right + 0, // Left + 0, // Down + 0, // Up + 0, // Numlock + 0, // Keypad + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + +u8 us_special_keys[PS2KBD_KEYMAP_SIZE] = { + + 0, + 0, + 0, + 0, + 0, //a + 0, //b + 0, //c + 0, //d + 0, //e + 0, //f + 0,//g + 0,//h + 0,//i + 0,//j + 0,//k + 0,//l + 0,//m + 0,//n + 0,//o + 0,//p + 0,//q + 0,//r + 0,//s + 0,//t + 0,//u + 0,//v + 0,//w + 0,//x + 0,//y + 0,//z + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* line feed */ + 0x1B, /* Esc */ + 0,/* BS */ + 0, /* TAB */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* CL */ + 1, // F1 + 2, // F2 + 3, // F3 + 4, // F4 + 5, // F5 + 6, // F6 + 7, // F7 + 8, // F8 + 9, // F9 + 10, // F10 + 11, // F11 + 12, // F12 + 32, // PrintScr + 33, // Scroll Lock + 34, // Pause + 35, // Insert + 36, // Home + 37, // Pg Up + 38, // Delete + 39, // End + 40, // Pg Down + 41, // Right + 42, // Left + 43, // Down + 44, // Up + 0, // Numlock + 0, // Keypad / + 0, // Keypad * + 0, // Keypad - + 0, // Keypad + + 0, // Keypad Enter + 39, // Keypad 1/End + 43, // Keypad 2/Down + 40, // Keypad 3/PageDn + 42, // Keypad 4/Left + 0, // Keypad 5 + 41, // Keypad 6/Right + 36, // Keypad 7/Home + 44, // Keypad 8/Up + 37, // Keypad 9/PageUp + 35, // Keypad 0/Insert + 38, // Keypad ./Delete + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + +u8 us_control_map[PS2KBD_KEYMAP_SIZE] = { + + 0, + 0, + 0, + 0, + 1, //a + 2, //b + 3, //c + 4, //d + 5, //e + 6, //f + 7,//g + 8,//h + 9,//i + 10,//j + 11,//k + 12,//l + 13,//m + 14,//n + 15,//o + 16,//p + 17,//q + 18,//r + 19,//s + 20,//t + 21,//u + 22,//v + 23,//w + 24,//x + 25,//y + 26,//z + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* line feed */ + 0, /* Esc */ + 0,/* BS */ + 0, /* TAB */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* CL */ + 0, // F1 + 0, // F2 + 0, // F3 + 0, // F4 + 0, // F5 + 0, // F6 + 0, // F7 + 0, // F8 + 0, // F9 + 0, // F10 + 0, // F11 + 0, // F12 + 0, // PrintScr + 0, // Scroll Lock + 0, // Pause + 0, // Insert + 0, // Home + 0, // Pg Up + 0, // Delete + 0, // End + 0, // Pg Down + 0, // Right + 0, // Left + 0, // Down + 0, // Up + 0, // Numlock + 0, // Keypad + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +u8 us_alt_map[PS2KBD_KEYMAP_SIZE] = { + + 0, + 0, + 0, + 0, + 128, //a + 129, //b + 130, //c + 131, //d + 132, //e + 133, //f + 134,//g + 135,//h + 136,//i + 137,//j + 138,//k + 139,//l + 140,//m + 141,//n + 142,//o + 143,//p + 144,//q + 145,//r + 146,//s + 147,//t + 148,//u + 149,//v + 150,//w + 151,//x + 152,//y + 154,//z + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, /* line feed */ + 0, /* Esc */ + 0,/* BS */ + 0, /* TAB */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* CL */ + 0, // F1 + 0, // F2 + 0, // F3 + 0, // F4 + 0, // F5 + 0, // F6 + 0, // F7 + 0, // F8 + 0, // F9 + 0, // F10 + 0, // F11 + 0, // F12 + 0, // PrintScr + 0, // Scroll Lock + 0, // Pause + 0, // Insert + 0, // Home + 0, // Pg Up + 0, // Delete + 0, // End + 0, // Pg Down + 0, // Right + 0, // Left + 0, // Down + 0, // Up + 0, // Numlock + 0, // Keypad + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + +#endif From 8c807529a7561bbff96b4a7dfecd06102e2a5f43 Mon Sep 17 00:00:00 2001 From: Max Lingua Date: Sun, 20 Jul 2008 01:44:40 +0000 Subject: [PATCH 30/48] Added "DEPDIR := .deps" in Makefile.ps2 Thanks Max [the other one] for pointing it out! svn-id: r33117 --- backends/platform/ps2/Makefile.ps2 | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2 index 9a2c1bad1b2..204f4f7a165 100644 --- a/backends/platform/ps2/Makefile.ps2 +++ b/backends/platform/ps2/Makefile.ps2 @@ -19,6 +19,7 @@ RM = rm -f srcdir = ../../.. VPATH = $(srcdir) INCDIR = ../../../ +DEPDIR = .deps DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_MPEG2 -DUSE_ZLIB -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar From 8b5e175af45fc0ff3f5cccc29dc4c522516ab2b6 Mon Sep 17 00:00:00 2001 From: Kostas Nakos Date: Sun, 20 Jul 2008 11:15:29 +0000 Subject: [PATCH 31/48] workaround for bogus findfirstfile. kyra now starts up correctly svn-id: r33120 --- backends/platform/wince/missing/missing.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index 86d93dcb887..8574e93f928 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -74,6 +74,7 @@ int stat(const char *fname, struct stat *ss) MultiByteToWideChar(CP_ACP, 0, fname, -1, fnameUnc, MAX_PATH); handle = FindFirstFile(fnameUnc, &wfd); + FindClose(handle); if (handle == INVALID_HANDLE_VALUE) return -1; else @@ -83,8 +84,6 @@ int stat(const char *fname, struct stat *ss) ss->st_size = wfd.nFileSizeLow; if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ss->st_mode |= S_IFDIR; - - FindClose(handle); } return 0; } @@ -158,14 +157,22 @@ int _access(const char *path, int mode) { WIN32_FIND_DATA ffd; HANDLE h=FindFirstFile(fname, &ffd); + FindClose(h); if (h == INVALID_HANDLE_VALUE) return -1; //Can't find file - FindClose(h); - if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { + // WORKAROUND: WinCE (or the emulator) sometimes returns bogus direcotry + // hits for files that don't exist. Checking for the same fname twice + // seems to weed out those false positives. + HANDLE h=FindFirstFile(fname, &ffd); + FindClose(h); + if (h == INVALID_HANDLE_VALUE) + return -1; //Can't find file + return 0; //Always return success if target is directory and exists - + } switch (mode) { case 00: //Check existence return 0; From a49a3c6aaa31e3a59c0fa2fec87f82764e6c2bc2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:27:12 +0000 Subject: [PATCH 32/48] cleanup svn-id: r33135 --- engines/scumm/imuse_digi/dimuse_sndmgr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp index 1511b9aefcf..b18b0ba70fc 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -102,10 +102,10 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 version = file->readUint32BE(); if (version != 3) { if (version == 2) { - warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2."); - warning("Suggested to recompress with latest tool from daily builds."); + warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2"); + warning("Suggested to recompress with latest tool from daily builds"); } else - error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d.", version); + error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d", version); } sound->bits = file->readUint32BE(); sound->freq = file->readUint32BE(); From 22ab05aa8a8260f6b0863d951025f9c233fd777d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:28:06 +0000 Subject: [PATCH 33/48] Fixed nasty bug in findPlainGameDescriptor -- contrary to is documentation, it would not return 0 upon failure to find a match, but rather a (0,0) record. svn-id: r33136 --- base/game.cpp | 4 ++-- base/game.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/game.cpp b/base/game.cpp index 96285436726..e65c891dc7b 100644 --- a/base/game.cpp +++ b/base/game.cpp @@ -32,10 +32,10 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla const PlainGameDescriptor *g = list; while (g->gameid) { if (0 == scumm_stricmp(gameid, g->gameid)) - break; + return g; g++; } - return g; + return 0; } void GameDescriptor::updateDesc(const char *extra) { diff --git a/base/game.h b/base/game.h index 18d79673888..b068c300ce1 100644 --- a/base/game.h +++ b/base/game.h @@ -48,7 +48,7 @@ struct PlainGameDescriptor { /** * Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor * matching the given gameid. If not match is found return 0. - * The end of the list marked by a PlainGameDescriptor with gameid equal to 0. + * The end of the list must marked by a PlainGameDescriptor with gameid equal to 0. */ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list); From c625a6a647ec176f9b411872a871ea6488e95643 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:42:56 +0000 Subject: [PATCH 34/48] Fixed potential issue in Common::String when asserting a substring of a string X back to X (memcpy -> memmove); also added some other sanity checks, and merged some duplicate code into a new method String::initWithCStr svn-id: r33137 --- common/str.cpp | 56 ++++++++++++++++++++++++++++++----------------- common/str.h | 19 ++++++++++++++-- test/common/str.h | 53 +++++++++++++++++++++----------------------- 3 files changed, 78 insertions(+), 50 deletions(-) diff --git a/common/str.cpp b/common/str.cpp index ad48ef6087e..a2e6e0c66d2 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -43,32 +43,43 @@ static int computeCapacity(int len) { return ((len + 32 - 1) & ~0x1F) - 1; } -String::String(const char *str, uint32 len) -: _len(0), _str(_storage) { +String::String(const char *str) : _len(0), _str(_storage) { + if (str == 0) { + _storage[0] = 0; + _len = 0; + } else + initWithCStr(str, strlen(str)); +} + +String::String(const char *str, uint32 len) : _len(0), _str(_storage) { + initWithCStr(str, len); +} + +String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) { + assert(endP >= beginP); + initWithCStr(beginP, endP - beginP); +} + +void String::initWithCStr(const char *str, uint32 len) { + assert(str); // Init _storage member explicitly (ie. without calling its constructor) // for GCC 2.95.x compatibility (see also tracker item #1602879). _storage[0] = 0; - if (str && *str) { - const uint32 tmp = strlen(str); - assert(len <= tmp); - if (len <= 0) - len = tmp; - _len = len; + _len = len; - if (len >= _builtinCapacity) { - // Not enough internal storage, so allocate more - _extern._capacity = computeCapacity(len); - _extern._refCount = 0; - _str = (char *)malloc(_extern._capacity+1); - assert(_str != 0); - } - - // Copy the string into the storage area - memcpy(_str, str, len); - _str[len] = 0; + if (len >= _builtinCapacity) { + // Not enough internal storage, so allocate more + _extern._capacity = computeCapacity(len); + _extern._refCount = 0; + _str = (char *)malloc(_extern._capacity+1); + assert(_str != 0); } + + // Copy the string into the storage area + memmove(_str, str, len); + _str[len] = 0; } String::String(const String &str) @@ -91,6 +102,8 @@ String::String(char c) _storage[0] = c; _storage[1] = 0; + // TODO/FIXME: There is no reason for the following check -- we *do* + // allow strings to contain 0 bytes! _len = (c == 0) ? 0 : 1; } @@ -130,11 +143,14 @@ String& String::operator =(const char *str) { uint32 len = strlen(str); ensureCapacity(len, false); _len = len; - memcpy(_str, str, len + 1); + memmove(_str, str, len + 1); return *this; } String &String::operator =(const String &str) { + if (&str == this) + return *this; + if (str.isStorageIntern()) { decRefCount(_extern._refCount); _len = str._len; diff --git a/common/str.h b/common/str.h index a92ec34fff9..ae9cb992b6e 100644 --- a/common/str.h +++ b/common/str.h @@ -96,10 +96,24 @@ public: static const char *emptyString; #endif + /** Construct a new empty string. */ String() : _len(0), _str(_storage) { _storage[0] = 0; } - String(const char *str, uint32 len = 0); + + /** Construct a new string from the given NULL-terminated C string. */ + String(const char *str); + + /** Construct a new string containing exactly len characters read from address str. */ + String(const char *str, uint32 len); + + /** Construct a new string containing the characters between beginP (including) and endP (excluding). */ + String(const char *beginP, const char *endP); + + /** Construct a copy of the given string. */ String(const String &str); + + /** Construct a string consisting of the given character. */ String(char c); + ~String(); String &operator =(const char *str); @@ -162,7 +176,7 @@ public: void toLowercase(); void toUppercase(); - + uint hash() const; public: @@ -189,6 +203,7 @@ protected: void ensureCapacity(uint32 new_len, bool keep_old); void incRefCount() const; void decRefCount(int *oldRefCount); + void initWithCStr(const char *str, uint32 len); }; // Append two strings to form a new (temp) string diff --git a/test/common/str.h b/test/common/str.h index dcba554b5a5..76574ea70f2 100644 --- a/test/common/str.h +++ b/test/common/str.h @@ -5,16 +5,25 @@ class StringTestSuite : public CxxTest::TestSuite { public: - void test_empty_clear( void ) - { + void test_constructors(void) { + Common::String str("test-string"); + TS_ASSERT( str == "test-string" ); + str = Common::String(str.c_str()+5, 3); + TS_ASSERT( str == "str" ); + str = "test-string"; + TS_ASSERT( str == "test-string" ); + str = Common::String(str.c_str()+5, str.c_str()+8); + TS_ASSERT( str == "str" ); + } + + void test_empty_clear(void) { Common::String str("test"); TS_ASSERT( !str.empty() ); str.clear(); TS_ASSERT( str.empty() ); } - void test_lastChar( void ) - { + void test_lastChar(void) { Common::String str; TS_ASSERT_EQUALS( str.lastChar(), '\0' ); str = "test"; @@ -23,8 +32,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( str2.lastChar(), 'r' ); } - void test_concat1( void ) - { + void test_concat1(void) { Common::String str("foo"); Common::String str2("bar"); str += str2; @@ -32,22 +40,19 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( str2, "bar" ); } - void test_concat2( void ) - { + void test_concat2(void) { Common::String str("foo"); str += "bar"; TS_ASSERT_EQUALS( str, "foobar" ); } - void test_concat3( void ) - { + void test_concat3(void) { Common::String str("foo"); str += 'X'; TS_ASSERT_EQUALS( str, "fooX" ); } - void test_refCount( void ) - { + void test_refCount(void) { Common::String foo1("foo"); Common::String foo2("foo"); Common::String foo3(foo2); @@ -57,8 +62,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( foo3, "foo""X" ); } - void test_refCount2( void ) - { + void test_refCount2(void) { Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd"); Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd"); Common::String foo3(foo2); @@ -68,8 +72,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""X" ); } - void test_refCount3( void ) - { + void test_refCount3(void) { Common::String foo1("0123456789abcdefghijk"); Common::String foo2("0123456789abcdefghijk"); Common::String foo3(foo2); @@ -79,8 +82,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( foo3, "0123456789abcdefghijk""0123456789abcdefghijk" ); } - void test_refCount4( void ) - { + void test_refCount4(void) { Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd"); Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd"); Common::String foo3(foo2); @@ -90,8 +92,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd" ); } - void test_hasPrefix( void ) - { + void test_hasPrefix(void) { Common::String str("this/is/a/test, haha"); TS_ASSERT_EQUALS( str.hasPrefix(""), true ); TS_ASSERT_EQUALS( str.hasPrefix("this"), true ); @@ -99,8 +100,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( str.hasPrefix("foo"), false ); } - void test_hasSuffix( void ) - { + void test_hasSuffix(void) { Common::String str("this/is/a/test, haha"); TS_ASSERT_EQUALS( str.hasSuffix(""), true ); TS_ASSERT_EQUALS( str.hasSuffix("haha"), true ); @@ -108,8 +108,7 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( str.hasSuffix("hahah"), false ); } - void test_contains( void ) - { + void test_contains(void) { Common::String str("this/is/a/test, haha"); TS_ASSERT_EQUALS( str.contains(""), true ); TS_ASSERT_EQUALS( str.contains("haha"), true ); @@ -117,15 +116,13 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS( str.contains("test"), true ); } - void test_toLowercase( void ) - { + void test_toLowercase(void) { Common::String str("Test it, NOW! 42"); str.toLowercase(); TS_ASSERT_EQUALS( str, "test it, now! 42" ); } - void test_toUppercase( void ) - { + void test_toUppercase(void) { Common::String str("Test it, NOW! 42"); str.toUppercase(); TS_ASSERT_EQUALS( str, "TEST IT, NOW! 42" ); From 113352bbded6c067bdd05db5c90786f3486e76a3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:47:34 +0000 Subject: [PATCH 35/48] Two new TODO/FIXME comments for class File svn-id: r33138 --- common/file.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/file.cpp b/common/file.cpp index 386777e2c5c..a1ea1aff772 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -452,10 +452,12 @@ bool File::isOpen() const { } bool File::ioFailed() const { + // TODO/FIXME: Just use ferror() here? return _ioFailed != 0; } void File::clearIOFailed() { + // TODO/FIXME: Just use clearerr() here? _ioFailed = false; } From f7ec115f0863f6b5ad93a8ff71cb4adb47b963fa Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:47:52 +0000 Subject: [PATCH 36/48] New SeekableReadStream::readLine_NEW() method, closely modelled after fgets, w/o the line length limitations of the old eekableReadStream::readLine() (which it will replace, after the feature freeze has been lifted) svn-id: r33139 --- common/stream.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++ common/stream.h | 27 +++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/common/stream.cpp b/common/stream.cpp index ab9804d7b65..3933a267243 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -148,6 +148,61 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) { return buf; } +char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { + assert(buf != 0 && bufSize > 1); + char *p = buf; + size_t len = 0; + char c; + + // If end-of-file occurs before any characters are read, return NULL + // and the buffer contents remain unchanged. + if (eos() || ioFailed()) { + return 0; + } + + // Loop as long as the stream has not ended, there is still free + // space in the buffer, and the line has not ended + while (!eos() && len + 1 < bufSize && c != LF) { + c = readByte(); + + // If end-of-file occurs before any characters are read, return + // NULL and the buffer contents remain unchanged. If an error + /// occurs, return NULL and the buffer contents are indeterminate. + if (ioFailed() || (len == 0 && eos())) + return 0; + + // Check for CR or CR/LF + // * DOS and Windows use CRLF line breaks + // * Unix and OS X use LF line breaks + // * Macintosh before OS X used CR line breaks + if (c == CR) { + // Look at the next char -- is it LF? If not, seek back + c = readByte(); + if (c != LF && !eos()) + seek(-1, SEEK_CUR); + // Treat CR & CR/LF as plain LF + c = LF; + } + + *p++ = c; + len++; + } + + // FIXME: + // This should fix a bug while using readLine with Common::File + // it seems that it sets the eos flag after an invalid read + // and at the same time the ioFailed flag + // the config file parser fails out of that reason for the new themes + if (eos()) { + clearIOFailed(); + } + + // We always terminate the buffer if no error occured + *p = 0; + return buf; +} + + uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) { dataSize = MIN(dataSize, _end - _pos); diff --git a/common/stream.h b/common/stream.h index 313a695e826..4cf5fae114e 100644 --- a/common/stream.h +++ b/common/stream.h @@ -304,13 +304,40 @@ public: * Read one line of text from a CR or CR/LF terminated plain text file. * This method is a rough analog of the (f)gets function. * + * @bug A main difference (and flaw) in this function is that there is no + * way to detect that a line exceeeds the length of the buffer. + * Code which needs this should use the new readLine_NEW() method instead. + * * @param buf the buffer to store into * @param bufSize the size of the buffer * @return a pointer to the read string, or NULL if an error occurred + * * @note The line terminator (CR or CR/LF) is stripped and not inserted * into the buffer. */ virtual char *readLine(char *buf, size_t bufSize); + + /** + * Reads at most one less than the number of characters specified + * by bufSize from the and stores them in the string buf. Reading + * stops when the end of a line is reached (CR, CR/LF or LF), at + * end-of-file or error. The newline, if any, is retained (CR and + * CR/LF are translated to LF = 0xA = '\n'). If any characters are + * read and there is no error, a `\0' character is appended to end + * the string. + * + * Upon successful completion, return a pointer to the string. If + * end-of-file occurs before any characters are read, returns NULL + * and the buffer contents remain unchanged. If an error occurs, + * returns NULL and the buffer contents are indeterminate. + * This method does not distinguish between end-of-file and error; + * callers muse use ioFailed() or eos() to determine which occurred. + * + * @param buf the buffer to store into + * @param bufSize the size of the buffer + * @return a pointer to the read string, or NULL if an error occurred + */ + virtual char *readLine_NEW(char *s, size_t bufSize); }; /** From ec1212eadfa30c4a2b40374b732205ac5b739547 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 20 Jul 2008 16:52:25 +0000 Subject: [PATCH 37/48] Fix for bug #1971499: ALL: config manager crashes when reading too long lines svn-id: r33140 --- common/config-manager.cpp | 66 ++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/common/config-manager.cpp b/common/config-manager.cpp index 5afbbad4aee..59855cf6c98 100644 --- a/common/config-manager.cpp +++ b/common/config-manager.cpp @@ -176,7 +176,6 @@ void ConfigManager::loadFile(const String &filename) { if (!cfg_file.open(filename)) { printf("Creating configuration file: %s\n", filename.c_str()); } else { - char buf[MAXLINELEN]; String domain; String comment; int lineno = 0; @@ -184,20 +183,28 @@ void ConfigManager::loadFile(const String &filename) { // TODO: Detect if a domain occurs multiple times (or likewise, if // a key occurs multiple times inside one domain). - while (!cfg_file.eof()) { + while (!cfg_file.eof() && !cfg_file.ioFailed()) { lineno++; - if (!cfg_file.readLine(buf, MAXLINELEN)) - break; - if (buf[0] == '#') { + // Read a line + String line; + while (line.lastChar() != '\n') { + char buf[MAXLINELEN]; + if (!cfg_file.readLine_NEW(buf, MAXLINELEN)) + break; + line += buf; + } + + if (line.size() == 0) { + // Do nothing + } else if (line[0] == '#') { // Accumulate comments here. Once we encounter either the start // of a new domain, or a key-value-pair, we associate the value // of the 'comment' variable with that entity. - comment += buf; - comment += '\n'; - } else if (buf[0] == '[') { + comment += line; + } else if (line[0] == '[') { // It's a new domain which begins here. - char *p = buf + 1; + const char *p = line.c_str() + 1; // Get the domain name, and check whether it's valid (that // is, verify that it only consists of alphanumerics, // dashes and underscores). @@ -209,8 +216,8 @@ void ConfigManager::loadFile(const String &filename) { error("Config file buggy: missing ] in line %d", lineno); break; case ']': - *p = 0; - domain = buf + 1; + domain = String(line.c_str() + 1, p - (line.c_str() + 1)); + //domain = String(line.c_str() + 1, p); // TODO: Pending Common::String changes break; default: error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno); @@ -226,10 +233,14 @@ void ConfigManager::loadFile(const String &filename) { _domainSaveOrder.push_back(domain); } else { - // Skip leading & trailing whitespaces - char *t = rtrim(ltrim(buf)); + // This line should be a line with a 'key=value' pair, or an empty one. + + // Skip leading whitespaces + const char *t = line.c_str(); + while (isspace(*t)) + t++; - // Skip empty lines + // Skip empty lines / lines with only whitespace if (*t == 0) continue; @@ -238,13 +249,30 @@ void ConfigManager::loadFile(const String &filename) { error("Config file buggy: Key/value pair found outside a domain in line %d", lineno); } - // Split string at '=' into 'key' and 'value'. - char *p = strchr(t, '='); + // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. + const char *p = strchr(t, '='); if (!p) error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); - *p = 0; - String key = rtrim(t); - String value = ltrim(p + 1); + + // Trim spaces before the '=' to obtain the key + const char *p2 = p; + while (p2 > t && isspace(*(p2-1))) + p2--; + String key(t, p2 - t); + + // Skip spaces after the '=' + t = p + 1; + while (isspace(*t)) + t++; + + // Trim trailing spaces + p2 = t + strlen(t); + while (p2 > t && isspace(*(p2-1))) + p2--; + + String value(t, p2 - t); + + // Finally, store the key/value pair in the active domain set(key, value, domain); // Store comment From 90781369cbc2a87917f9a0318121cccffc3a40cd Mon Sep 17 00:00:00 2001 From: Kostas Nakos Date: Sun, 20 Jul 2008 16:55:51 +0000 Subject: [PATCH 38/48] modified patch #1882942 - optimize and kill code for really old platforms svn-id: r33141 --- backends/platform/wince/missing/missing.cpp | 383 ++------------------ 1 file changed, 27 insertions(+), 356 deletions(-) diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index 8574e93f928..228df032879 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -40,11 +40,21 @@ char *strdup(const char *strSource); void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { - size_t i; + // Perform binary search + size_t lo = 0; + size_t hi = nmemb; + while (lo < hi) { + size_t mid = (lo + hi) / 2; + const void *p = ((const char *)base) + mid * size; + int tmp = (*compar)(key, p); + if (tmp < 0) + hi = mid; + else if (tmp > 0) + lo = mid + 1; + else + return (void *)p; + } - for (i=0; i= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9')); -} - -char *_strdup(const char *strSource) -#else char *strdup(const char *strSource) -#endif { char* buffer; - buffer = (char*)malloc(strlen(strSource)+1); + size_z len = strlen(strSource)+1; + buffer = (char*)malloc(len); if (buffer) - strcpy(buffer, strSource); + memcpy(buffer, strSource, len); return buffer; } -/* Very limited implementation of sys/time.h */ -void usleep(long usec) -{ - long msec = usec/1000; - if (msec <= 0) - Sleep(0); - else - Sleep(msec); -} - -/* This may provide for better sync mechanism */ -unsigned int clock() -{ - return GetTickCount(); -} - -/* And why do people use this? */ -#if _WIN32_WCE >= 300 -void abort() -{ - exit(1); -} -#endif - -/* -IMHO, no project should use this one, it is not portable at all. This implementation -at least allows some projects to work. -*/ -char* getenv(char* name) -{ - static char buffer[MAX_PATH+1]; - if (strcmp(name, "HOME") == 0 || strcmp(name, "HOMEDIR") == 0) - { - getcwd(buffer, MAX_PATH); - return buffer; - } - else - return ""; -} - -#if _WIN32_WCE < 300 || defined(_TEST_HPC_STDIO) - -void *calloc(size_t n, size_t s) { - void *result = malloc(n * s); - if (result) - memset(result, 0, n * s); - - return result; -} - -char *strpbrk(const char *s, const char *accept) { - int i; - - if (!s || !accept) - return NULL; - - for (i=0; i='0' && c <= '9'); -} - -int isprint(int c) { - return (c >= ' ' && c <= '~'); -} - -int isspace(int c) { - return (c == ' '); -} - -#endif - -#ifndef WIN32_PLATFORM_HPCPRO - - -int printf(const char *format, ...) { - // useless anyway :) - return 0; -} - -FILE *fopen(const char *path, const char *mode) { - TCHAR tempo[MAX_PATH]; - HANDLE result; - bool writeAccess = (mode[0] == 'W' || mode[0] == 'w'); - - MultiByteToWideChar(CP_ACP, 0, path, strlen(path) + 1, tempo, sizeof(tempo)); - - result = CreateFile(tempo, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL); - if (result == INVALID_HANDLE_VALUE) - return NULL; - else - return (FILE*)result; -} - -FILE * _wfopen(const TCHAR *path, const TCHAR *mode) { - HANDLE result; - bool writeAccess = (mode[0] == 'W' || mode[0] == 'w'); - result = CreateFile(path, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL); - if (result == INVALID_HANDLE_VALUE) - return NULL; - else - return (FILE*)result; -} - -FILE *_wfreopen(const TCHAR *path, const TCHAR *mode, FILE *stream) { - fclose(stream); - stream = _wfopen(path, mode); - return stream; -} - -int fclose(FILE *stream) { - CloseHandle((HANDLE)stream); - return 1; -} - -int fseek(FILE *stream, long offset, int whence) { - SetFilePointer((HANDLE)stream, offset, NULL, (whence == SEEK_CUR ? FILE_CURRENT : whence == SEEK_END ? FILE_END : FILE_BEGIN)); - return 0; -} - -long ftell(FILE *stream) { - return (SetFilePointer((HANDLE)stream, 0, NULL, FILE_CURRENT)); -} - -size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { - DWORD sizeWritten; - - WriteFile((HANDLE)stream, ptr, size * nmemb, &sizeWritten, NULL); - - if (size != 0) - return sizeWritten / size; - else - return 0; -} - -size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { - DWORD sizeRead; - - ReadFile((HANDLE)stream, ptr, size * nmemb, &sizeRead, NULL); - - if (size != 0) - return sizeRead / size; - else - return 0; -} - -int fgetc(FILE *stream) { - unsigned char c; - if (fread(&c, 1, 1, stream) != 1) - return -1; - else - return c; -} - -char *fgets(char *s, int size, FILE *stream) { - int i = 0; - char tempo[1]; - - memset(s, 0, size); - while (fread(tempo, 1, 1, stream)) { - //if (tempo[0] == '\r') - // break; - if (tempo[0] == '\r') - continue; - s[i++] = tempo[0]; - if (tempo[0] == '\n') - break; - if (i == size) - break; - } - if (!i) - return NULL; - else - return s; -} - -int feof(FILE *stream) { - DWORD fileSize; - DWORD filePos; - fileSize = GetFileSize((HANDLE)stream, NULL); - filePos = SetFilePointer((HANDLE)stream, 0, 0, FILE_CURRENT); - return (filePos == 0xFFFFFFFF || filePos > (fileSize - 1)); -} - -int ferror(FILE *stream) { - return 0; // FIXME ! -} - -int fprintf(FILE *stream, const char *format, ...) { - char buf[1024]; - va_list va; - - va_start(va, format); - vsnprintf(buf, 1024, format, va); - va_end(va); - - if (buf[strlen(buf) - 1] == '\n') { - int i = strlen(buf) - 1; - buf[i] = '\r'; - buf[i + 1] = '\n'; - buf[i + 2] = 0; - } - - return fwrite(buf, 1, strlen(buf), stream); -} - -FILE* _getstdfilex(int) { - return NULL; -} - -void clearerr(FILE *stream) { -} - -int fflush(FILE *stream) { - return 0; -} - -#endif - -int stricmp( const char *string1, const char *string2 ) { - char src[4096]; - char dest[4096]; - int i; - - for (i=0; i= 'A' && string1[i] <= 'Z') - src[i] = string1[i] + 32; - else - src[i] = string1[i]; - src[i] = 0; - - for (i=0; i= 'A' && string2[i] <= 'Z') - dest[i] = string2[i] + 32; - else - dest[i] = string2[i]; - dest[i] = 0; - - return strcmp(src, dest); -} - -char *strrchr(const char *s, int c) { - int i; - - for (i = strlen(s) - 1; i > 0; i--) - if (s[i] == c) - return (char*)(s + i); - - return NULL; -} - -long int strtol(const char *nptr, char **endptr, int base) { - // not correct but that's all we are using - - long int result; - sscanf(nptr, "%ld", &result); - return result; -} - - -#endif - - // gcc build only functions follow #else // defined(__GNUC__) #ifndef __MINGW32CE__ -int islower(int c) -{ +int islower(int c) { return (c>='a' && c<='z'); } -int isspace(int c) -{ +int isspace(int c) { return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v'); } -int isalpha(int c) -{ - return (islower(c) || (c>='A' && c<='Z')); +int isalpha(int c) { + return ((c>='a' && c<='z') || (c>='A' && c<='Z')); } -int isalnum(int c) -{ - return (isalpha(c) || (c>='0' && c<='9')); +int isalnum(int c) { + return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9')); } -int isprint(int c) -{ - static char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~"; - int i = 0, flag = 0; - while ((punct[i] != 0) && (flag = (punct[i] != c))) - i++; - return (isalnum(c) || flag); -} - -extern "C" int atexit(void (*function)(void)) -{ - return 0; +int isprint(int c) { + //static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~"; + //return (isalnum(c) || strchr(punct, c)); + return (32 <= c && c <= 126); // based on BSD manpage } #endif From 0d08240e45e3389d98aa86771e5b7cdc30b22ea7 Mon Sep 17 00:00:00 2001 From: Kostas Nakos Date: Sun, 20 Jul 2008 17:04:27 +0000 Subject: [PATCH 39/48] a little more cleanup svn-id: r33142 --- backends/platform/wince/missing/missing.cpp | 112 +++++++++----------- 1 file changed, 51 insertions(+), 61 deletions(-) diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index 228df032879..c760b1f7df3 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -1,8 +1,34 @@ -/* MISSING.C - Implementation for standard and semi-standard C library calls missing in WinCE - environment. - by Vasyl Tsvirkunov -*/ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* Original code: + * Implementation for standard and semi-standard C library calls missing in WinCE + * environment. + * by Vasyl Tsvirkunov + */ + #include #include @@ -17,19 +43,8 @@ #include "time.h" #include "dirent.h" -/* forward declaration */ - -#if _WIN32_WCE < 300 - -#define _STDAFX_H -#include "portdefs.h" - -#else - char *strdup(const char *strSource); -#endif - #ifdef __GNUC__ #define EXT_C extern "C" #else @@ -60,9 +75,7 @@ void *bsearch(const void *key, const void *base, size_t nmemb, static WIN32_FIND_DATA wfd; -/* Very limited implementation of stat. Used by UI.C, MEMORY-P.C (latter is not critical) */ -int stat(const char *fname, struct stat *ss) -{ +int stat(const char *fname, struct stat *ss) { TCHAR fnameUnc[MAX_PATH+1]; HANDLE handle; int len; @@ -73,8 +86,7 @@ int stat(const char *fname, struct stat *ss) /* Special case (dummy on WinCE) */ len = strlen(fname); if (len >= 2 && fname[len-1] == '.' && fname[len-2] == '.' && - (len == 2 || fname[len-3] == '\\')) - { + (len == 2 || fname[len-3] == '\\')) { /* That's everything implemented so far */ memset(ss, 0, sizeof(struct stat)); ss->st_size = 1024; @@ -99,13 +111,11 @@ int stat(const char *fname, struct stat *ss) } char cwd[MAX_PATH+1] = ""; -EXT_C char *getcwd(char *buffer, int maxlen) -{ +EXT_C char *getcwd(char *buffer, int maxlen) { TCHAR fileUnc[MAX_PATH+1]; char* plast; - if (cwd[0] == 0) - { + if (cwd[0] == 0) { GetModuleFileName(NULL, fileUnc, MAX_PATH); WideCharToMultiByte(CP_ACP, 0, fileUnc, -1, cwd, MAX_PATH, NULL, NULL); plast = strrchr(cwd, '\\'); @@ -123,8 +133,7 @@ EXT_C char *getcwd(char *buffer, int maxlen) #ifdef __GNUC__ #undef GetCurrentDirectory #endif -EXT_C void GetCurrentDirectory(int len, char *buf) -{ +EXT_C void GetCurrentDirectory(int len, char *buf) { getcwd(buf,len); }; @@ -134,26 +143,22 @@ fully qualified paths refer to root folder rather than current folder (concept not implemented in CE). */ #undef fopen -EXT_C FILE *wce_fopen(const char* fname, const char* fmode) -{ +EXT_C FILE *wce_fopen(const char* fname, const char* fmode) { char fullname[MAX_PATH+1]; if (!fname || fname[0] == '\0') return NULL; - if (fname[0] != '\\' && fname[0] != '/') - { + if (fname[0] != '\\' && fname[0] != '/') { getcwd(fullname, MAX_PATH); strncat(fullname, "\\", MAX_PATH-strlen(fullname)-1); strncat(fullname, fname, MAX_PATH-strlen(fullname)-strlen(fname)); return fopen(fullname, fmode); - } - else + } else return fopen(fname, fmode); } /* Remove file by name */ -int remove(const char* path) -{ +int remove(const char* path) { TCHAR pathUnc[MAX_PATH+1]; MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); return !DeleteFile(pathUnc); @@ -200,8 +205,7 @@ int _access(const char *path, int mode) { #ifndef __GNUC__ /* Limited dirent implementation. Used by UI.C and DEVICES.C */ -DIR* opendir(const char* fname) -{ +DIR* opendir(const char* fname) { DIR* pdir; char fnameMask[MAX_PATH+1]; TCHAR fnameUnc[MAX_PATH+1]; @@ -226,13 +230,10 @@ DIR* opendir(const char* fname) strcpy(pdir->dd_name, fname); /* it has exactly enough space for fname and nul char */ MultiByteToWideChar(CP_ACP, 0, fnameMask, -1, fnameUnc, MAX_PATH); - if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) - { + if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) { free(pdir); return NULL; - } - else - { + } else { WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL); pdir->dd_dir.d_name = strdup(nameFound); @@ -241,34 +242,25 @@ DIR* opendir(const char* fname) return pdir; } -struct dirent* readdir(DIR* dir) -{ +struct dirent* readdir(DIR* dir) { char nameFound[MAX_PATH+1]; static struct dirent dummy; - if (dir->dd_stat == 0) - { + if (dir->dd_stat == 0) { dummy.d_name = "."; dummy.d_namlen = 1; dir->dd_stat ++; return &dummy; - } - else if (dir->dd_stat == 1) - { + } else if (dir->dd_stat == 1) { dummy.d_name = ".."; dummy.d_namlen = 2; dir->dd_stat ++; return &dummy; - } - else if (dir->dd_stat == 2) - { + } else if (dir->dd_stat == 2) { dir->dd_stat++; return &dir->dd_dir; - } - else - { - if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) - { + } else { + if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) { dir->dd_stat = -1; return NULL; } @@ -310,10 +302,8 @@ void mkdir(char* dirname, int mode) if (*path == '/') *path = '\\'; /* Run through the string and attempt creating all subdirs on the path */ - for (ptr = path+1; *ptr; ptr ++) - { - if (*ptr == '\\' || *ptr == '/') - { + for (ptr = path+1; *ptr; ptr ++) { + if (*ptr == '\\' || *ptr == '/') { *ptr = 0; MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); CreateDirectory(pathUnc, 0); From e54ac15109b41e0f2d1c4dd1e65bc8fe88025ef9 Mon Sep 17 00:00:00 2001 From: Marcus Comstedt Date: Sun, 20 Jul 2008 17:56:43 +0000 Subject: [PATCH 40/48] Solaris tr does not like character classes in some locales. Use "C" locale. svn-id: r33143 --- backends/platform/dc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/platform/dc/Makefile b/backends/platform/dc/Makefile index 56848504e11..db5861903bf 100644 --- a/backends/platform/dc/Makefile +++ b/backends/platform/dc/Makefile @@ -75,7 +75,7 @@ SCUMMVM.BIN : scummvm.bin plugin_dist : for p in plugins/*.plg; do \ - sh-elf-strip -g -o "`basename \"$$p\" | tr '[:lower:]' '[:upper:]'`" "$$p"; \ + sh-elf-strip -g -o "`basename \"$$p\" | LC_CTYPE=C tr '[:lower:]' '[:upper:]'`" "$$p"; \ done dist : SCUMMVM.BIN plugins plugin_dist From 2354ea80c6ec0da27594fab91b8dc0e1439cff56 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 20 Jul 2008 18:00:00 +0000 Subject: [PATCH 41/48] KYRA: disable incomplete PC-98 audio support for 0.12.0 release (use towns audio instead) svn-id: r33145 --- engines/kyra/kyra_v1.cpp | 2 +- engines/kyra/sound_towns.cpp | 6 +++--- engines/kyra/staticres.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 117194aea2d..85c03dc1bbd 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -114,7 +114,7 @@ int KyraEngine_v1::init() { _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformPC98) { if (_flags.gameID == GI_KYRA1) - _sound = new SoundPC98(this, _mixer); + _sound = new SoundTowns/*SoundPC98*/(this, _mixer); else _sound = new SoundTownsPC98_v2(this, _mixer); } else if (midiDriver == MD_ADLIB) { diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index e96cef735c2..0f2b916c9d4 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2363,7 +2363,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : _numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false), _numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) { setTempo(84); - _baserate = (3579545.0 / (double)getRate()) / 144.0; + _baserate = (double)getRate() / 10368.0; } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { @@ -3095,8 +3095,8 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() { } bool SoundTownsPC98_v2::init() { - _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ? - TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS); + _driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ? + TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS); _useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false; _vm->checkCD(); // FIXME: While checking for 'track1.XXX(X)' looks like diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 4f577c1d1e9..03b832bf79d 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1060,7 +1060,7 @@ void KyraEngine_LoK::initStaticResource() { else if (_flags.platform == Common::kPlatformFMTowns) _soundData = soundData_TOWNS; else if (_flags.platform == Common::kPlatformPC98) - _soundData = soundData_PC98; + _soundData = soundData_TOWNS/*soundData_PC98*/; } @@ -1286,7 +1286,7 @@ void KyraEngine_HoF::initStaticResource() { else if (_flags.platform == Common::kPlatformFMTowns) _soundData = soundData_TOWNS; else if (_flags.platform == Common::kPlatformPC98) - _soundData = soundData_PC98; + _soundData = soundData_TOWNS/*soundData_PC98*/; // setup sequence data _sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize); From 0b8602f9950dcc6e6f11b719786244094564bb8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Andersson?= Date: Sun, 20 Jul 2008 19:25:16 +0000 Subject: [PATCH 42/48] Commented out some more PC-98 audio stuff, to avoid warnings. svn-id: r33146 --- engines/kyra/staticres.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 03b832bf79d..c05795dacde 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1034,8 +1034,10 @@ void KyraEngine_LoK::initStaticResource() { } // audio data tables +#if 0 static const char *tIntro98[] = { "intro%d.dat" }; static const char *tIngame98[] = { "kyram%d.dat" }; +#endif static const AudioDataStruct soundData_PC[] = { { _soundFilesIntro, _soundFilesIntroSize, 0, 0 }, @@ -1049,11 +1051,13 @@ void KyraEngine_LoK::initStaticResource() { { 0, 0, 0, 0} }; +#if 0 static const AudioDataStruct soundData_PC98[] = { { tIntro98, 1, 0, 0 }, { tIngame98, 1, 0, 0 }, { 0, 0, 0, 0} }; +#endif if (_flags.platform == Common::kPlatformPC) _soundData = soundData_PC; @@ -1259,9 +1263,11 @@ void KyraEngine_HoF::initStaticResource() { static const char *fmtMusicFileListFinale[] = { "finale%d.twn" }; static const char *fmtMusicFileListIngame[] = { "km%02d.twn" }; +#if 0 static const char *pc98MusicFileListIntro[] = { "intro%d.86" }; static const char *pc98MusicFileListFinale[] = { "finale%d.86" }; static const char *pc98MusicFileListIngame[] = { "km%02d.86" }; +#endif static const AudioDataStruct soundData_PC[] = { { _musicFileListIntro, _musicFileListIntroSize, 0, 0 }, @@ -1275,11 +1281,13 @@ void KyraEngine_HoF::initStaticResource() { { fmtMusicFileListFinale, 1, _cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1 } }; +#if 0 static const AudioDataStruct soundData_PC98[] = { { pc98MusicFileListIntro, 1, 0, 0 }, { pc98MusicFileListIngame, 1, 0, 0 }, { pc98MusicFileListFinale, 1, 0, 0 } }; +#endif if (_flags.platform == Common::kPlatformPC) _soundData = soundData_PC; From f82cf58780dde55ad1367a0011ffc7eeed7991c8 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 21 Jul 2008 05:09:29 +0000 Subject: [PATCH 43/48] This is 0.13.0svn now svn-id: r33160 --- base/internal_version.h | 2 +- dists/redhat/scummvm.spec | 2 +- dists/scummvm.rc | 8 ++++---- dists/slackware/scummvm.SlackBuild | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/base/internal_version.h b/base/internal_version.h index 069c20b4c91..c867532dd9a 100644 --- a/base/internal_version.h +++ b/base/internal_version.h @@ -1 +1 @@ -#define SCUMMVM_VERSION "0.12.0svn" +#define SCUMMVM_VERSION "0.13.0svn" diff --git a/dists/redhat/scummvm.spec b/dists/redhat/scummvm.spec index efde789ce3d..1d3b2bce643 100644 --- a/dists/redhat/scummvm.spec +++ b/dists/redhat/scummvm.spec @@ -7,7 +7,7 @@ # Prologue information #------------------------------------------------------------------------------ Name : scummvm -Version : 0.12.0svn +Version : 0.13.0svn Release : 1 Summary : Graphic adventure game interpreter Group : Interpreters diff --git a/dists/scummvm.rc b/dists/scummvm.rc index 73763a1216a..0fb2b870712 100644 --- a/dists/scummvm.rc +++ b/dists/scummvm.rc @@ -7,8 +7,8 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,12,0,0 - PRODUCTVERSION 0,12,0,0 + FILEVERSION 0,13,0,0 + PRODUCTVERSION 0,13,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -25,13 +25,13 @@ BEGIN BEGIN VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0" VALUE "FileDescription", "http://www.scummvm.org/\0" - VALUE "FileVersion", "0.12.0svn\0" + VALUE "FileVersion", "0.13.0svn\0" VALUE "InternalName", "scummvm\0" VALUE "LegalCopyright", "Copyright © 2001-2007 The ScummVM Team\0" VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0" VALUE "OriginalFilename", "scummvm.exe\0" VALUE "ProductName", "ScummVM\0" - VALUE "ProductVersion", "0.12.0svn\0" + VALUE "ProductVersion", "0.13.0svn\0" END END BLOCK "VarFileInfo" diff --git a/dists/slackware/scummvm.SlackBuild b/dists/slackware/scummvm.SlackBuild index 415ee4c8671..6ed0ed6e57c 100755 --- a/dists/slackware/scummvm.SlackBuild +++ b/dists/slackware/scummvm.SlackBuild @@ -8,7 +8,7 @@ if [ "$TMP" = "" ]; then fi PKG=$TMP/package-scummvm -VERSION=0.12.0svn +VERSION=0.13.0svn ARCH=i486 BUILD=1 From 361bed0a9535104611d3e0e88d5b3e1ad788639d Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 21 Jul 2008 06:08:30 +0000 Subject: [PATCH 44/48] Massive refactoring of dialogue code, which is now implemented as a finite state machine. Related code in other files has been updated has well. svn-id: r33162 --- engines/parallaction/dialogue.cpp | 412 ++++++++++++++--------- engines/parallaction/exec_ns.cpp | 17 +- engines/parallaction/input.cpp | 11 + engines/parallaction/input.h | 5 +- engines/parallaction/parallaction.cpp | 45 ++- engines/parallaction/parallaction.h | 12 +- engines/parallaction/parallaction_br.cpp | 12 +- 7 files changed, 319 insertions(+), 195 deletions(-) diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 6d9dfa5e106..290f8cfd4f7 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -42,13 +42,23 @@ namespace Parallaction { #define ANSWER_CHARACTER_X 10 #define ANSWER_CHARACTER_Y 80 + class DialogueManager { + enum { + RUN_QUESTION, + RUN_ANSWER, + NEXT_QUESTION, + NEXT_ANSWER, + DIALOGUE_OVER + } _state; + Parallaction *_vm; - SpeakData *_data; Dialogue *_dialogue; bool _askPassword; + int _passwordLen; + bool _passwordChanged; bool isNpc; GfxObj *_questioner; @@ -59,97 +69,69 @@ class DialogueManager { uint16 _visAnswers[5]; int _numVisAnswers; + int _answerId; + + int _selection, _oldSelection; + + uint32 _mouseButtons; + Common::Point _mousePos; + bool _isKeyDown; + uint16 _downKey; + + public: - DialogueManager(Parallaction *vm, SpeakData *data) : _vm(vm), _data(data) { - _dialogue = _data->_dialogue; - isNpc = scumm_stricmp(_data->_name, "yourself") && _data->_name[0] != '\0'; - _questioner = isNpc ? _vm->_disk->loadTalk(_data->_name) : _vm->_char._talk; - _answerer = _vm->_char._talk; - } + DialogueManager(Parallaction *vm, ZonePtr z); + ~DialogueManager(); - ~DialogueManager() { - if (isNpc) { - delete _questioner; - } + bool isOver() { + return _state == DIALOGUE_OVER; } - void run(); + ZonePtr _z; + CommandList *_cmdList; + protected: - void displayQuestion(); + bool displayQuestion(); bool displayAnswers(); bool displayAnswer(uint16 i); - uint16 getAnswer(); - int16 selectAnswer(); - uint16 askPassword(); + int16 selectAnswer1(); + int16 selectAnswerN(); + int16 askPassword(); int16 getHoverAnswer(int16 x, int16 y); + void runQuestion(); + void runAnswer(); + void nextQuestion(); + void nextAnswer(); + + bool checkPassword(); + void resetPassword(); + void accumPassword(uint16 ascii); }; -uint16 DialogueManager::askPassword() { - debugC(3, kDebugExec, "checkDialoguePassword()"); +DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) { + _dialogue = _z->u.speak->_dialogue; + isNpc = scumm_stricmp(_z->u.speak->_name, "yourself") && _z->u.speak->_name[0] != '\0'; + _questioner = isNpc ? _vm->_disk->loadTalk(_z->u.speak->_name) : _vm->_char._talk; + _answerer = _vm->_char._talk; - uint16 passwordLen = 0; - _password[0] = '\0'; + _askPassword = false; + _q = _dialogue->_questions[0]; - _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); - - Common::Event e; - bool changed = true; // force first refresh - - while (true) { - e.kbd.ascii = 0; - - if (g_system->getEventManager()->pollEvent(e)) { - if (e.type == Common::EVENT_QUIT) { - _engineFlags |= kEngineQuit; - break; - } - - if ((e.type == Common::EVENT_KEYDOWN) && isdigit(e.kbd.ascii)) { - _password[passwordLen] = e.kbd.ascii; - passwordLen++; - _password[passwordLen] = '\0'; - changed = true; - } - } - - if (changed) { - _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3); - _vm->_gfx->updateScreen(); - changed = false; - } - - if ((passwordLen == MAX_PASSWORD_LENGTH) || (e.kbd.ascii == Common::KEYCODE_RETURN)) { - - if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) || - (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) || - (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))) { - - break; - - } else { - passwordLen = 0; - _password[0] = '\0'; - changed = true; - } - - } - - g_system->delayMillis(20); - - } - - _vm->hideDialogueStuff(); - - return 0; + _cmdList = 0; + _answerId = 0; + _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER; } - +DialogueManager::~DialogueManager() { + if (isNpc) { + delete _questioner; + } + _z = nullZonePtr; +} bool DialogueManager::displayAnswer(uint16 i) { @@ -183,134 +165,242 @@ bool DialogueManager::displayAnswers() { displayAnswer(i); } + if (_askPassword) { + resetPassword(); +// _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3); + int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y); + _vm->_gfx->setItemFrame(id, 0); + } else + if (_numVisAnswers == 1) { + int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y); + _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF); + _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0); + } else + if (_numVisAnswers > 1) { + int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y); + _vm->_gfx->setItemFrame(id, _q->_answers[_visAnswers[0]]->_mood & 0xF); + _oldSelection = -1; + _selection = 0; + } + return _numVisAnswers > 0; } -void DialogueManager::displayQuestion() { - - if (!scumm_stricmp(_q->_text, "NULL")) return; +bool DialogueManager::displayQuestion() { + if (!scumm_stricmp(_q->_text, "NULL")) return false; _vm->_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->hideDialogueStuff(); - - return; + return true; } -uint16 DialogueManager::getAnswer() { - uint16 answer = 0; +bool DialogueManager::checkPassword() { + return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) || + (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) || + (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))); +} - if (_askPassword == false) { - answer = selectAnswer(); - } else { - answer = askPassword(); +void DialogueManager::resetPassword() { + _passwordLen = 0; + _password[0] = '\0'; + _passwordChanged = true; +} + +void DialogueManager::accumPassword(uint16 ascii) { + if (!isdigit(ascii)) { + return; } - debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer); - - return answer; + _password[_passwordLen] = ascii; + _passwordLen++; + _password[_passwordLen] = '\0'; + _passwordChanged = true; } -void DialogueManager::run() { +int16 DialogueManager::askPassword() { - _askPassword = false; - CommandList *cmdlist = NULL; + if (_isKeyDown) { + accumPassword(_downKey); + } - _q = _dialogue->_questions[0]; - int16 answer; + if (_passwordChanged) { + _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3); + _passwordChanged = false; + } - while (_q) { - - answer = 0; - - displayQuestion(); - - if (_engineFlags & kEngineQuit) - return; - - if (_q->_answers[0] == NULL) break; - - if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) { - if (!displayAnswers()) break; - answer = getAnswer(); - - if (_engineFlags & kEngineQuit) - return; - - cmdlist = &_q->_answers[answer]->_commands; + if ((_passwordLen == MAX_PASSWORD_LENGTH) || ((_isKeyDown) && (_downKey == Common::KEYCODE_RETURN))) { + if (checkPassword()) { + return 0; + } else { + resetPassword(); } - - _q = _q->_answers[answer]->_following._question; } - if (cmdlist) - _vm->_cmdExec->run(*cmdlist); - + return -1; } -int16 DialogueManager::selectAnswer() { +int16 DialogueManager::selectAnswer1() { - int16 numAvailableAnswers = _numVisAnswers; - - int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y); - _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF); - - if (numAvailableAnswers == 1) { - _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 0); - _vm->_input->waitUntilLeftClick(); - _vm->hideDialogueStuff(); + if (_mouseButtons == kMouseLeftUp) { return 0; } - int oldSelection = -1; - int selection = 0; + return -1; +} - uint32 event; - Common::Point p; - while ((_engineFlags & kEngineQuit) == 0) { +int16 DialogueManager::selectAnswerN() { - _vm->_input->readInput(); - _vm->_input->getCursorPos(p); - event = _vm->_input->getLastButtonEvent(); - selection = _vm->_balloonMan->hitTestDialogueBalloon(p.x, p.y); + _selection = _vm->_balloonMan->hitTestDialogueBalloon(_mousePos.x, _mousePos.y); - if (selection != oldSelection) { - if (oldSelection != -1) { - _vm->_balloonMan->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3); - } - - if (selection != -1) { - _vm->_balloonMan->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0); - _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF); - } + if (_selection != _oldSelection) { + if (_oldSelection != -1) { + _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3); } - if ((selection != -1) && (event == kMouseLeftUp)) { - break; + if (_selection != -1) { + _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0); + _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF); } - - _vm->_gfx->updateScreen(); - g_system->delayMillis(20); - - oldSelection = selection; } - _vm->hideDialogueStuff(); + _oldSelection = _selection; + + if ((_mouseButtons == kMouseLeftUp) && (_selection != -1)) { + return _visAnswers[_selection]; + } + + return -1; +} + +void DialogueManager::runQuestion() { + debugC(9, kDebugDialogue, "runQuestion\n"); + + if (_mouseButtons == kMouseLeftUp) { + _vm->hideDialogueStuff(); + _state = NEXT_ANSWER; + } - return _visAnswers[selection]; } -void Parallaction::runDialogue(SpeakData *data) { - debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name); +void DialogueManager::nextAnswer() { + debugC(9, kDebugDialogue, "nextAnswer\n"); - DialogueManager man(this, data); - man.run(); + if (_q->_answers[0] == NULL) { + _state = DIALOGUE_OVER; + return; + } + + if (!scumm_stricmp(_q->_answers[0]->_text, "NULL")) { + _answerId = 0; + _state = NEXT_QUESTION; + return; + } + + _state = displayAnswers() ? RUN_ANSWER : DIALOGUE_OVER; +} + +void DialogueManager::runAnswer() { + debugC(9, kDebugDialogue, "runAnswer\n"); + + if (_askPassword) { + _answerId = askPassword(); + } else + if (_numVisAnswers == 1) { + _answerId = selectAnswer1(); + } else { + _answerId = selectAnswerN(); + } + + if (_answerId != -1) { + _cmdList = &_q->_answers[_answerId]->_commands; + _vm->hideDialogueStuff(); + _state = NEXT_QUESTION; + } +} + +void DialogueManager::nextQuestion() { + debugC(9, kDebugDialogue, "nextQuestion\n"); + + _q = _q->_answers[_answerId]->_following._question; + if (_q == 0) { + _state = DIALOGUE_OVER; + } else { + _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER; + } +} + + +void DialogueManager::run() { + + // cache event data + _mouseButtons = _vm->_input->getLastButtonEvent(); + _vm->_input->getCursorPos(_mousePos); + _isKeyDown = _vm->_input->getLastKeyDown(_downKey); + + switch (_state) { + case RUN_QUESTION: + runQuestion(); + break; + + case NEXT_ANSWER: + nextAnswer(); + break; + + case NEXT_QUESTION: + nextQuestion(); + break; + + case RUN_ANSWER: + runAnswer(); + break; + + case DIALOGUE_OVER: + if (_cmdList) { + _vm->_cmdExec->run(*_cmdList); + } + break; + + default: + error("unknown state in DialogueManager"); + + } + +} + +void Parallaction::enterDialogueMode(ZonePtr z) { + debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name); + _dialogueMan = new DialogueManager(this, z); + _input->_inputMode = Input::kInputModeDialogue; +} + +void Parallaction::exitDialogueMode() { + debugC(1, kDebugDialogue, "Parallaction::exitDialogueMode()"); + _input->_inputMode = Input::kInputModeGame; + + // The current instance of _dialogueMan must be destroyed before the zone commands + // are executed, because they may create another instance of _dialogueMan that + // overwrite the current one. This would cause headaches (and it did, actually). + ZonePtr z = _dialogueMan->_z; + delete _dialogueMan; + _dialogueMan = 0; + + _cmdExec->run(z->_commands, z); +} + +void Parallaction::runDialogueFrame() { + if (_input->_inputMode != Input::kInputModeDialogue) { + return; + } + + _dialogueMan->run(); + + if (_dialogueMan->isOver()) { + exitDialogueMode(); + } return; } diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index d1cfb145575..9cde27a853d 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -224,7 +224,11 @@ DECLARE_COMMAND_OPCODE(start) { DECLARE_COMMAND_OPCODE(speak) { - _vm->_activeZone = _ctxt.cmd->u._zone; + if ((_ctxt.cmd->u._zone->_type & 0xFFFF) == kZoneSpeak) { + _vm->enterDialogueMode(_ctxt.cmd->u._zone); + } else { + _vm->_activeZone = _ctxt.cmd->u._zone; + } } @@ -321,6 +325,7 @@ DECLARE_COMMAND_OPCODE(stop) { void Parallaction_ns::drawAnimations() { + debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n"); uint16 layer = 0; @@ -361,6 +366,8 @@ void Parallaction_ns::drawAnimations() { } } + debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n"); + return; } @@ -416,7 +423,6 @@ label1: return; } - void CommandExec::run(CommandList& list, ZonePtr z) { if (list.size() == 0) { debugC(3, kDebugExec, "runCommands: nothing to do"); @@ -537,11 +543,8 @@ uint16 Parallaction::runZone(ZonePtr z) { break; case kZoneSpeak: - runDialogue(z->u.speak); - if (_engineFlags & kEngineQuit) - return 0; - break; - + enterDialogueMode(z); + return 0; } debugC(3, kDebugExec, "runZone completed"); diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index 37971586618..4d0b7085c26 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -42,12 +42,14 @@ uint16 Input::readInput() { uint16 KeyDown = 0; _mouseButtons = kMouseNone; + _lastKeyDownAscii = -1; Common::EventManager *eventMan = _vm->_system->getEventManager(); while (eventMan->pollEvent(e)) { switch (e.type) { case Common::EVENT_KEYDOWN: + _lastKeyDownAscii = e.kbd.ascii; if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd') _vm->_debugger->attach(); if (_vm->getFeatures() & GF_DEMO) break; @@ -97,6 +99,11 @@ uint16 Input::readInput() { } +bool Input::getLastKeyDown(uint16 &ascii) { + ascii = _lastKeyDownAscii; + return (_lastKeyDownAscii != -1); +} + // FIXME: see comment for readInput() void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) { @@ -192,6 +199,10 @@ InputData* Input::updateInput() { case kInputModeGame: updateGameInput(); break; + + case kInputModeDialogue: + readInput(); + break; } return &_inputData; diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h index e06fe967051..acc9898e90f 100644 --- a/engines/parallaction/input.h +++ b/engines/parallaction/input.h @@ -66,6 +66,7 @@ class Input { Common::Point _mousePos; uint16 _mouseButtons; + int32 _lastKeyDownAscii; bool _mouseHidden; ZonePtr _hoverZone; @@ -73,7 +74,8 @@ class Input { public: enum { kInputModeGame = 0, - kInputModeComment = 1 + kInputModeComment = 1, + kInputModeDialogue = 2 }; @@ -102,6 +104,7 @@ public: void waitUntilLeftClick(); void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1); uint32 getLastButtonEvent() { return _mouseButtons; } + bool getLastKeyDown(uint16 &ascii); void stopHovering() { _hoverZone = nullZonePtr; diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 3cde21b49c3..bd5ff744738 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -161,6 +161,11 @@ void Parallaction::updateView() { } +void Parallaction::hideDialogueStuff() { + _gfx->freeItems(); + _balloonMan->freeBalloons(); +} + void Parallaction::freeCharacter() { debugC(1, kDebugExec, "freeCharacter()"); @@ -363,25 +368,29 @@ void Parallaction::processInput(InputData *data) { void Parallaction::runGame() { InputData *data = _input->updateInput(); - if (data->_event != kEvNone) { - processInput(data); + if (_engineFlags & kEngineQuit) + return; + + if (_input->_inputMode == Input::kInputModeDialogue) { + runDialogueFrame(); + } else { + if (data->_event != kEvNone) { + processInput(data); + } + + if (_engineFlags & kEngineQuit) + return; + + runPendingZones(); + + if (_engineFlags & kEngineQuit) + return; + + if (_engineFlags & kEngineChangeLocation) { + changeLocation(_location._name); + } } - if (_engineFlags & kEngineQuit) - return; - - runPendingZones(); - - if (_engineFlags & kEngineQuit) - return; - - if (_engineFlags & kEngineChangeLocation) { - changeLocation(_location._name); - } - - if (_engineFlags & kEngineQuit) - return; - _gfx->beginFrame(); if (_input->_inputMode == Input::kInputModeGame) { @@ -396,7 +405,6 @@ void Parallaction::runGame() { // change this to endFrame? updateView(); - } @@ -659,6 +667,7 @@ void Parallaction::beep() { } void Parallaction::scheduleLocationSwitch(const char *location) { + debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location); strcpy(_location._name, location); _engineFlags |= kEngineChangeLocation; } diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index ef2dad9884c..409f2746832 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -165,6 +165,7 @@ class Debugger; class Gfx; class SoundMan; class Input; +class DialogueManager; struct Location { @@ -275,8 +276,6 @@ public: uint16 runZone(ZonePtr z); void freeZones(); - void runDialogue(SpeakData*); - AnimationPtr findAnimation(const char *name); void freeAnimations(); @@ -419,10 +418,11 @@ public: void setupBalloonManager(); - void hideDialogueStuff() { - _gfx->freeItems(); - _balloonMan->freeBalloons(); - } + void hideDialogueStuff(); + DialogueManager *_dialogueMan; + void enterDialogueMode(ZonePtr z); + void exitDialogueMode(); + void runDialogueFrame(); }; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 6606550132f..9e2a0f10f15 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -212,13 +212,21 @@ void Parallaction_br::runPendingZones() { if (_activeZone) { z = _activeZone; // speak Zone or sound _activeZone = nullZonePtr; - runZone(z); // FIXME: BRA doesn't handle sound yet + if ((z->_type & 0xFFFF) == kZoneSpeak) { + enterDialogueMode(z); + } else { + runZone(z); // FIXME: BRA doesn't handle sound yet + } } if (_activeZone2) { z = _activeZone2; // speak Zone or sound _activeZone2 = nullZonePtr; - runZone(z); + if ((z->_type & 0xFFFF) == kZoneSpeak) { + enterDialogueMode(z); + } else { + runZone(z); // FIXME: BRA doesn't handle sound yet + } } } From 5a71d764e7278fd4c9d83ba80e500e05b9b18fc7 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Mon, 21 Jul 2008 09:25:40 +0000 Subject: [PATCH 45/48] Some refactoring for tracking of floating labels. svn-id: r33165 --- engines/parallaction/input.cpp | 44 +++++++++++++++--------- engines/parallaction/input.h | 6 ++-- engines/parallaction/parallaction.cpp | 11 ------ engines/parallaction/parallaction.h | 2 -- engines/parallaction/parallaction_ns.cpp | 5 ++- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index 4d0b7085c26..9601ae3b36a 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -208,6 +208,29 @@ InputData* Input::updateInput() { return &_inputData; } +void Input::trackMouse(ZonePtr z) { + if ((z != _hoverZone) && (_hoverZone)) { + stopHovering(); + return; + } + + if (!z) { + return; + } + + if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) { + _hoverZone = z; + _vm->_gfx->showFloatingLabel(_hoverZone->_label); + return; + } +} + +void Input::stopHovering() { + _hoverZone = nullZonePtr; + _vm->_gfx->hideFloatingLabel(); +} + + bool Input::translateGameInput() { if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) { @@ -242,23 +265,10 @@ bool Input::translateGameInput() { return true; } - if ((z != _hoverZone) && (_hoverZone)) { - _hoverZone = nullZonePtr; - _inputData._event = kEvExitZone; - return true; - } - - if (!z) { - _inputData._event = kEvNone; - return true; - } - - if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) { - _hoverZone = z; - _inputData._event = kEvEnterZone; - _inputData._label = z->_label; - return true; - } + trackMouse(z); + if (!z) { + return true; + } if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) { diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h index acc9898e90f..f260352dba0 100644 --- a/engines/parallaction/input.h +++ b/engines/parallaction/input.h @@ -101,15 +101,13 @@ public: uint16 readInput(); InputData* updateInput(); + void trackMouse(ZonePtr z); void waitUntilLeftClick(); void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1); uint32 getLastButtonEvent() { return _mouseButtons; } bool getLastKeyDown(uint16 &ascii); - void stopHovering() { - _hoverZone = nullZonePtr; - } - + void stopHovering(); }; } // namespace Parallaction diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index bd5ff744738..cd852f7c84d 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -299,16 +299,6 @@ void Parallaction::showLocationComment(const char *text, bool end) { void Parallaction::processInput(InputData *data) { switch (data->_event) { - case kEvEnterZone: - debugC(2, kDebugInput, "processInput: kEvEnterZone"); - _gfx->showFloatingLabel(data->_label); - break; - - case kEvExitZone: - debugC(2, kDebugInput, "processInput: kEvExitZone"); - _gfx->hideFloatingLabel(); - break; - case kEvAction: debugC(2, kDebugInput, "processInput: kEvAction"); _input->stopHovering(); @@ -319,7 +309,6 @@ void Parallaction::processInput(InputData *data) { case kEvOpenInventory: _input->stopHovering(); - _gfx->hideFloatingLabel(); if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) { setArrowCursor(); } diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 409f2746832..c45d32b013c 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -114,8 +114,6 @@ enum EngineFlags { enum { kEvNone = 0, - kEvEnterZone = 1, - kEvExitZone = 2, kEvAction = 3, kEvOpenInventory = 4, kEvCloseInventory = 5, diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index cbf9ee985d3..9e925d1e1dc 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -191,7 +191,7 @@ void Parallaction_ns::setArrowCursor() { debugC(1, kDebugInput, "setting mouse cursor to arrow"); // this stuff is needed to avoid artifacts with labels and selected items when switching cursors - _gfx->hideFloatingLabel(); + _input->stopHovering(); _input->_activeItem._id = 0; _system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0); @@ -302,12 +302,11 @@ void Parallaction_ns::changeLocation(char *location) { _soundMan->playLocationMusic(location); - _gfx->hideFloatingLabel(); + _input->stopHovering(); _gfx->freeLabels(); _zoneTrap = nullZonePtr; - _input->stopHovering(); if (_engineFlags & kEngineBlockInput) { setArrowCursor(); } From ecd44b8f90ec3f1e749f3b8787f6348e95030b0b Mon Sep 17 00:00:00 2001 From: Bertrand Augereau Date: Mon, 21 Jul 2008 10:13:44 +0000 Subject: [PATCH 46/48] Avoid branching in the inner loop of AGOS drawVertImageCompressed svn-id: r33167 --- engines/agos/gfx.cpp | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 6e91c5d94c6..867a4119628 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -8,7 +8,7 @@ * 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. - +d * 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 @@ -806,7 +806,6 @@ void AGOSEngine::drawVertImageUncompressed(VC10_state *state) { void AGOSEngine::drawVertImageCompressed(VC10_state *state) { assert (state->flags & kDFCompressed) ; uint w, h; - byte *src, *dst, *dstPtr; state->x_skip *= 4; /* reached */ @@ -815,7 +814,7 @@ void AGOSEngine::drawVertImageCompressed(VC10_state *state) { vc10_skip_cols(state); - dstPtr = state->surf_addr; + byte *dstPtr = state->surf_addr; if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */ dstPtr += vcReadVar(252); } @@ -823,20 +822,34 @@ void AGOSEngine::drawVertImageCompressed(VC10_state *state) { do { byte color; - src = vc10_depackColumn(state); - dst = dstPtr; + const byte *src = vc10_depackColumn(state); + byte *dst = dstPtr; h = 0; - do { - color = (*src / 16); - if ((state->flags & kDFNonTrans) || color != 0) + if (state->flags & kDFNonTrans) { + do { + byte colors = *src; + color = (colors / 16); dst[0] = color | state->palette; - color = (*src & 15); - if ((state->flags & kDFNonTrans) || color != 0) + color = (colors & 15); dst[1] = color | state->palette; - dst += state->surf_pitch; - src++; - } while (++h != state->draw_height); + dst += state->surf_pitch; + src++; + } while (++h != state->draw_height); + } + else { + do { + byte colors = *src; + color = (colors / 16); + if (color != 0) + dst[0] = color | state->palette; + color = (colors & 15); + if (color != 0) + dst[1] = color | state->palette; + dst += state->surf_pitch; + src++; + } while (++h != state->draw_height); + } dstPtr += 2; } while (++w != state->draw_width); } From e1c71dab99c9bf60ee1cc26da09ebd797a693a3a Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Mon, 21 Jul 2008 10:32:20 +0000 Subject: [PATCH 47/48] Spacing. svn-id: r33168 --- engines/agos/gfx.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 867a4119628..9a3962ea21f 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -8,7 +8,7 @@ * 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. -d + * 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 @@ -836,8 +836,7 @@ void AGOSEngine::drawVertImageCompressed(VC10_state *state) { dst += state->surf_pitch; src++; } while (++h != state->draw_height); - } - else { + } else { do { byte colors = *src; color = (colors / 16); From e09eb75ef77d6e76b763b3a47540a530013a887f Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 21 Jul 2008 11:33:30 +0000 Subject: [PATCH 48/48] Silence a warning which complains about using an uninitialized variable. svn-id: r33169 --- common/stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/stream.cpp b/common/stream.cpp index 3933a267243..61166fd4511 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -152,7 +152,7 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { assert(buf != 0 && bufSize > 1); char *p = buf; size_t len = 0; - char c; + char c = 0; // If end-of-file occurs before any characters are read, return NULL // and the buffer contents remain unchanged.