diff options
173 files changed, 5376 insertions, 1419 deletions
diff --git a/Makefile.common b/Makefile.common index 4071d97150..993b833f4e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -62,6 +62,7 @@ endif ifneq ($(findstring $(MAKEFLAGS),s),s) ifneq ($(VERBOSE_BUILD),1) ifneq ($(VERBOSE_BUILD),yes) +QUIET_CC = @echo ' ' C ' ' $@; QUIET_CXX = @echo ' ' C++ ' ' $@; QUIET_AS = @echo ' ' AS ' ' $@; QUIET_NASM = @echo ' ' NASM ' ' $@; @@ -95,6 +96,9 @@ ifdef CXX_UPDATE_DEP_FLAG # Build rule for C++ files. Makes use of CXX_UPDATE_DEP_FLAG for advanced # dependency tracking. +%.o: %.c + $(QUIET)$(MKDIR) $(*D)/$(DEPDIR) + $(QUIET_CC)$(CC) $(CXX_UPDATE_DEP_FLAG) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $*.o %.o: %.cpp $(QUIET)$(MKDIR) $(*D)/$(DEPDIR) $(QUIET_CXX)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 0620d07a29..16cf5640eb 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -333,7 +333,7 @@ void MixerImpl::stopHandle(SoundHandle handle) { } void MixerImpl::muteSoundType(SoundType type, bool mute) { - assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings)); + assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings)); _soundTypeSettings[type].mute = mute; for (int i = 0; i != NUM_CHANNELS; ++i) { @@ -343,7 +343,7 @@ void MixerImpl::muteSoundType(SoundType type, bool mute) { } bool MixerImpl::isSoundTypeMuted(SoundType type) const { - assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings)); + assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings)); return _soundTypeSettings[type].mute; } @@ -468,7 +468,7 @@ bool MixerImpl::hasActiveChannelOfType(SoundType type) { } void MixerImpl::setVolumeForSoundType(SoundType type, int volume) { - assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings)); + assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings)); // Check range if (volume > kMaxMixerVolume) @@ -489,7 +489,7 @@ void MixerImpl::setVolumeForSoundType(SoundType type, int volume) { } int MixerImpl::getVolumeForSoundType(SoundType type) const { - assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings)); + assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings)); return _soundTypeSettings[type].volume; } diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp index 7cbd205ecb..9b6e1270f1 100644 --- a/backends/fs/ps2/ps2-fs.cpp +++ b/backends/fs/ps2/ps2-fs.cpp @@ -22,9 +22,9 @@ #if defined(__PLAYSTATION2__) -// Disable symbol overrides so that we can use system headers. -#define FORBIDDEN_SYMBOL_ALLOW_ALL - +// Disable symbol overrides so that we can use "FILE" +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE +#define FORBIDDEN_SYMBOL_EXCEPTION_printf #include "backends/fs/ps2/ps2-fs.h" @@ -58,13 +58,13 @@ const char *_lastPathComponent(const Common::String &str) { cur++; - // printf("lastPathComponent path=%s token=%s\n", start, cur); + // dbg_printf("lastPathComponent path=%s token=%s\n", start, cur); return cur; } Ps2FilesystemNode::Ps2FilesystemNode() { - printf("NEW FSNODE()\n"); + dbg_printf("NEW FSNODE()\n"); _isHere = true; _isDirectory = true; @@ -75,7 +75,7 @@ Ps2FilesystemNode::Ps2FilesystemNode() { } Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) { - printf("NEW FSNODE(%s)\n", path.c_str()); + dbg_printf("NEW FSNODE(%s)\n", path.c_str()); _path = path; @@ -107,7 +107,7 @@ Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) { } Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path, bool verify) { - printf("NEW FSNODE(%s, %d)\n", path.c_str(), verify); + dbg_printf("NEW FSNODE(%s, %d)\n", path.c_str(), verify); _path = path; @@ -164,24 +164,24 @@ void Ps2FilesystemNode::doverify(void) { _verified = true; - printf(" verify: %s -> ", _path.c_str()); + dbg_printf(" verify: %s -> ", _path.c_str()); #if 0 if (_path.empty()) { - printf("PlayStation 2 Root !\n"); + dbg_printf("PlayStation 2 Root !\n"); _verified = true; return; } if (_path.lastChar() == ':') { - printf("Dev: %s\n", _path.c_str()); + dbg_printf("Dev: %s\n", _path.c_str()); _verified = true; return; } #endif if (_path[3] != ':' && _path[4] != ':') { - printf("relative path !\n"); + dbg_printf("relative path !\n"); _isHere = false; _isDirectory = false; return; @@ -204,7 +204,7 @@ void Ps2FilesystemNode::doverify(void) { fileXioWaitAsync(FXIO_WAIT, &fd); if (!fd) { - printf(" yes [stat]\n"); + dbg_printf(" yes [stat]\n"); return true; } break; @@ -218,11 +218,11 @@ void Ps2FilesystemNode::doverify(void) { #if 1 fd = fio.open(_path.c_str(), O_RDONLY); - printf("_path = %s -- fio.open -> %d\n", _path.c_str(), fd); + dbg_printf("_path = %s -- fio.open -> %d\n", _path.c_str(), fd); if (fd >=0) { fio.close(fd); - printf(" yes [open]\n"); + dbg_printf(" yes [open]\n"); _isHere = true; if (medium==MC_DEV && _path.lastChar()=='/') _isDirectory = true; @@ -234,7 +234,7 @@ void Ps2FilesystemNode::doverify(void) { fd = fio.dopen(_path.c_str()); if (fd >=0) { fio.dclose(fd); - printf(" yes [dopen]\n"); + dbg_printf(" yes [dopen]\n"); _isHere = true; _isDirectory = true; return; @@ -267,13 +267,13 @@ void Ps2FilesystemNode::doverify(void) { _isHere = false; _isDirectory = false; - printf(" no\n"); + dbg_printf(" no\n"); return; } AbstractFSNode *Ps2FilesystemNode::getChild(const Common::String &n) const { - printf("getChild : %s\n", n.c_str()); + dbg_printf("getChild : %s\n", n.c_str()); if (!_isDirectory) return NULL; @@ -328,13 +328,14 @@ AbstractFSNode *Ps2FilesystemNode::getChild(const Common::String &n) const { bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const { //TODO: honor the hidden flag - // printf("getChildren\n"); + // dbg_printf("getChildren\n"); if (!_isDirectory) return false; if (_isRoot) { - list.push_back(new Ps2FilesystemNode("cdfs:")); + if (g_systemPs2->cdPresent()) + list.push_back(new Ps2FilesystemNode("cdfs:")); if (g_systemPs2->hddPresent()) list.push_back(new Ps2FilesystemNode("pfs0:")); @@ -342,7 +343,7 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi if (g_systemPs2->usbMassPresent()) list.push_back(new Ps2FilesystemNode("mass:")); - if (g_systemPs2->getBootDevice()==HOST_DEV || g_systemPs2->netPresent()) + if (g_systemPs2->netPresent()) list.push_back(new Ps2FilesystemNode("host:")); if (g_systemPs2->mcPresent()) @@ -357,7 +358,7 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi else fd = fio.dopen(_path.c_str()); - // printf("dopen = %d\n", fd); + // dbg_printf("dopen = %d\n", fd); if (fd >= 0) { iox_dirent_t dirent; @@ -399,7 +400,7 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi } AbstractFSNode *Ps2FilesystemNode::getParent() const { - // printf("Ps2FilesystemNode::getParent : path = %s\n", _path.c_str()); + // dbg_printf("Ps2FilesystemNode::getParent : path = %s\n", _path.c_str()); if (_isRoot) return new Ps2FilesystemNode(this); // FIXME : 0 ??? @@ -411,7 +412,7 @@ AbstractFSNode *Ps2FilesystemNode::getParent() const { const char *end = _lastPathComponent(_path); Common::String str(start, end - start); - // printf(" parent = %s\n", str.c_str()); + // dbg_printf(" parent = %s\n", str.c_str()); return new Ps2FilesystemNode(str, true); } diff --git a/backends/fs/ps2/ps2-fs.h b/backends/fs/ps2/ps2-fs.h index 4c1a9bba96..63b866ba5b 100644 --- a/backends/fs/ps2/ps2-fs.h +++ b/backends/fs/ps2/ps2-fs.h @@ -70,12 +70,12 @@ public: virtual Common::String getPath() const { return _path; } virtual bool exists() const { - // printf("%s : is %d\n", _path.c_str(), _isHere); + // dbg_printf("%s : is %d\n", _path.c_str(), _isHere); return _isHere; } virtual bool isDirectory() const { - // printf("%s : dir %d\n", _path.c_str(), _isDirectory); + // dbg_printf("%s : dir %d\n", _path.c_str(), _isDirectory); return _isDirectory; } diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index 92293493f0..b71a98338b 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -759,8 +759,8 @@ void OSystem_Android::setMouseCursor(const void *buf, uint w, uint h, uint16 *d = (uint16 *)tmp; for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w) for (uint16 x = 0; x < w; ++x, d++) - if (*s++ != (keycolor & 0xffff)) - *d |= 1; + if (*s++ == (keycolor & 0xffff)) + *d = 0; _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch); diff --git a/backends/platform/ps2/DmaPipe.cpp b/backends/platform/ps2/DmaPipe.cpp index e0a7d97807..a4bcf6299e 100644 --- a/backends/platform/ps2/DmaPipe.cpp +++ b/backends/platform/ps2/DmaPipe.cpp @@ -50,7 +50,7 @@ DmaPipe::DmaPipe(uint32 size) { size &= ~0x1F; _buf = (uint64 *)memalign(64, size); _curPipe = 0; - _pipes[0] = new SinglePipe(_buf, size >> 4); + _pipes[0] = new SinglePipe(_buf, size >> 4); _pipes[1] = new SinglePipe(_buf + (size >> 4), size >> 4); // reset DMAC Channel 2 @@ -80,7 +80,7 @@ void DmaPipe::uploadTex(uint32 dest, uint16 bufWidth, uint16 destOfsX, uint16 de *(_pipes[_curPipe]->_chainHead) |= (1 << 28); _pipes[_curPipe]->setGifLoopTag(4); _pipes[_curPipe]->setReg(GPR_BITBLTBUF, GS_SET_DEST_BLTBUF((dest/256) & 0x3fff, (bufWidth/64) & 0x3f, pixelFmt & 0x3f)); - _pipes[_curPipe]->setReg( GPR_TRXPOS, GS_SET_DEST_TRXPOS(destOfsX, destOfsY)); + _pipes[_curPipe]->setReg( GPR_TRXPOS, GS_SET_DEST_TRXPOS(destOfsX, destOfsY)); _pipes[_curPipe]->setReg( GPR_TRXREG, GS_SET_TRXREG(width, height)); _pipes[_curPipe]->setReg( GPR_TRXDIR, 0); @@ -194,7 +194,7 @@ void DmaPipe::setConfig(uint8 prModeCont, uint8 dither, uint8 colClamp) { // set some defaults // alpha blending formula: (A-B) * C + D - // set: A = dest pixel, b = 0, C = source alpha, D = source pixel, fix = don't care + // set: A = dest pixel, b = 0, C = source alpha, D = source pixel, fix = don't care _pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0)); _pipes[_curPipe]->setReg( GPR_PRIM, 0); @@ -279,7 +279,7 @@ void SinglePipe::appendChain(uint64 dmaTag) { void SinglePipe::setReg(uint64 reg, uint64 value) { *_bufPos++ = value; *_bufPos++ = reg; - (*_chainSize)++; + (*_chainSize)++; } void SinglePipe::setListReg(uint64 value1, uint64 value2) { diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp index 7eeedc1944..a4ec23329a 100644 --- a/backends/platform/ps2/Gs2dScreen.cpp +++ b/backends/platform/ps2/Gs2dScreen.cpp @@ -32,6 +32,7 @@ #include "DmaPipe.h" #include "GsDefs.h" #include "graphics/surface.h" +#include "graphics/colormasks.h" #include "backends/platform/ps2/ps2debug.h" extern void *_gp; @@ -43,12 +44,49 @@ enum Buffers { PRINTF }; +/* + Supported modes: + + Mode #1 = SDTV progressive (NTSC: 224p / PAL: 256p) + Mode #2 = SDTV interlaced (NTSC: 448i / PAL: 512i) <- default + Mode #3 = EDTV progressive (NTSC: 480p / PAL: 576p) + Mode #4 = HDTV progressive (720p) + Mode #5 = HDTV interlaced (1080i) + Mode #6 = VESA (640x480@60) + Mode #7 = VESA (800x600@60) + Mode #8 = VESA (1024x768@60) +*/ + +static ps2_mode_t ps2_mode[] = { + + // -> w, h, interlaced, pitch, mode, vck, magh, magv, dx, dy + + /* #1 : SDTV - progressive */ + { 640, 224, 0, 640, 0x02, 2560, 4, 0, 160 /*158*/, 25 /*22*/ }, /* NTSC */ + { 640, 256, 0, 640, 0x03, 2560, 4, 0, 170 /*163*/, 35 /*36*/ }, /* PAL */ + + /* #2 : SDTV - interlaced */ + { 640, 448, 1, 640, 0x02, 2560, 4, 0, 156 /*158*/, 50 /*45*/ }, /* NTSC */ + { 640, 512, 1, 640, 0x03, 2560, 4, 0, 170 /*163*/, 70 /*72*/ }, /* PAL */ + + /* #3 : EDTV */ + { 720, 480, 0, 768, 0x50, 1440, 2, 0, 58, 35 }, /* NTSC */ + /* { 720, 576, 0, 768, 0x53, 1440, 2, 0, 62, 45 }, */ /* PAL : full */ + /* { 656, 576, 0, 704, 0x53, 1312, 2, 0, 62, 45 }, */ /* PAL : redux @ (0,0) */ + { 656, 576, 0, 704, 0x53, 1312, 2, 0, 78 /*314*/, 45 }, /* PAL : redux @ center'd */ + + /* #4/#5 : HDTV */ + { 1280, 720, 0, 1280, 0x52, 1280, 1, 0, 76 /*302*/, 24 }, + { 1920, 1080, 1, 1920, 0x51, 1920, 1, 0, 60 /*236*/ /*238*/, 40 }, + + /* #6/#7/#8 : VESA 4:3 @ 60Hz */ + { 640, 480, 0, 640, 0x1A, 1280, 2, 0, 70 /*276*/, 34 }, + { 800, 600, 0, 832, 0x2B, 1600, 2, 0, 105 /*420*/, 26 }, + { 1024, 768, 0, 1024, 0x3B, 2048, 2, 0, 144 /*580*/, 34 } +}; + #define ANIM_STACK_SIZE (1024 * 32) -#define DEFAULT_PAL_X 175 -#define DEFAULT_PAL_Y 72 // 60 -#define DEFAULT_NTSC_X 165 -#define DEFAULT_NTSC_Y 45 #define ORG_X 256 #define ORG_Y 256 #define ORIGIN_X (ORG_X << 4) @@ -77,7 +115,7 @@ void runAnimThread(Gs2dScreen *param); int vblankStartHandler(int cause) { // start of VBlank period - if (g_VblankCmd) { // is there a new image waiting? + if (g_VblankCmd) { // is there a new image waiting? GS_DISPFB1 = g_VblankCmd; // show it. g_VblankCmd = 0; iSignalSema(g_VblankSema); @@ -87,8 +125,8 @@ int vblankStartHandler(int cause) { int dmacHandler(int channel) { if (g_DmacCmd && (channel == 2)) { // GS DMA transfer finished, - g_VblankCmd = g_DmacCmd; // we want to show the image - g_DmacCmd = 0; // when the next vblank occurs + g_VblankCmd = g_DmacCmd; // we want to show the image + g_DmacCmd = 0; // when the next vblank occurs iSignalSema(g_DmacSema); } return 0; @@ -102,7 +140,8 @@ int vblankEndHandler(int cause) { void createAnimThread(Gs2dScreen *screen); -Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { +Gs2dScreen::Gs2dScreen(uint16 width, uint16 height) { + _systemQuit = false; ee_sema_t newSema; newSema.init_count = 1; @@ -125,12 +164,15 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { EnableIntc(INT_VBLANK_END); EnableDmac(2); + _tvMode = 0; // force detection + _gfxMode = 0; + _width = width; _height = height; _pitch = (width + 127) & ~127; _screenBuf = (uint8 *)memalign(64, _width * _height); - _overlayBuf = (uint16 *)memalign(64, _width * _height * 2); + _overlayBuf = (uint16 *)memalign(64, _pitch * _height * 2); _clut = (uint32 *)memalign(64, 256 * 4); memset(_screenBuf, 0, _width * _height); @@ -138,32 +180,102 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _clut[1] = GS_RGBA(0xC0, 0xC0, 0xC0, 0); clearOverlay(); - if (mode == TV_DONT_CARE) { -#if 1 char romver[8]; + uint16 biosver; int fd = fioOpen("rom0:ROMVER", O_RDONLY); fioRead(fd, &romver, 8); fioClose(fd); + biosver=atoi(romver); + printf("ROMVER = %s\n", romver); + printf("ver = %d\n", atoi(romver)); + + if (!_tvMode) { // determine TV standard first + if (ConfMan.hasKey("tv_mode", "PlayStation2")) { + const char *tvname = ConfMan.get("tv_mode", "PlayStation2").c_str(); + + if (strcmp("ntsc", tvname) == 0) { + _tvMode = 2; + } + else if (strcmp("pal", tvname) == 0) { + _tvMode = 1; + } + else + _tvMode = 0; + } + + if (!_tvMode) { + if (romver[4] == 'E') + _tvMode = TV_PAL; + else + _tvMode = TV_NTSC; + + printf("Auto-detect TV mode: PSX:%c PS2:%c\n", *(char *)(0x1FC7FF52), romver[4]); + } + } + + uint8 mode; + if (!_gfxMode) { // determine GFX mode next + if (ConfMan.hasKey("gfx_mode", "PlayStation2")) { + _gfxMode = ConfMan.getInt("gfx_mode", "PlayStation2"); + // TODO: free more video mem to support these modes + if (_gfxMode == 4 || _gfxMode == 5) { + printf("Not enough video mem: using EDTV (3)\n"); + _gfxMode = 3; + } + else + if (_gfxMode == 7 || _gfxMode == 8) { + printf("Not enough video mem: using VGA (6)\n"); + _gfxMode = 6; + } - if (romver[4] == 'E') - _tvMode = TV_PAL; - else - _tvMode = TV_NTSC; -#else - if (PAL_NTSC_FLAG == 'E') - _tvMode = TV_PAL; + if (_gfxMode < 1 || _gfxMode > 8) _gfxMode = 2; + else + if (_gfxMode == 4 || _gfxMode == 5) _tvMode = TV_HDTV; + else + if (_gfxMode > 5) _tvMode = TV_VESA; + } else - _tvMode = TV_NTSC; -#endif - } else - _tvMode = mode; + _gfxMode = 2; + } + + // Remap Mode Index + mode = _gfxMode; + if (_tvMode == TV_NTSC) { + mode = (mode * 2) - 1; + } + else if (_tvMode == TV_PAL) { + mode = (mode * 2); + } + else if (_tvMode == TV_HDTV) { + mode += 3; + } + else /* VESA */ { + _tvMode = TV_VESA; + mode += 3; + } + mode--; + + switch (_tvMode) { + case TV_NTSC: + printf("Setting up TV mode: NTSC\n"); + break; + case TV_PAL: + printf("Setting up TV mode: PAL\n"); + break; + case TV_HDTV: + printf("Setting up TV mode: HDTV\n"); + break; + case TV_VESA: + printf("Setting up TV mode: VESA\n"); + break; + } + + _tvWidth = ps2_mode[mode].w; + _tvHeight = ps2_mode[mode].h; + _tvPitch = ps2_mode[mode].pitch; - // _tvMode = TV_NTSC; - printf("Setting up %s mode\n", (_tvMode == TV_PAL) ? "PAL" : "NTSC"); + printf("Setting up GFX mode: %d x %d\n", _tvWidth, _tvHeight); - // set screen size, 640x512 for pal, 640x448 for ntsc - _tvWidth = 640; - _tvHeight = ((_tvMode == TV_PAL) ? 512 /*544*/ : 448); kFullScreen[0].z = kFullScreen[1].z = 0; kFullScreen[0].x = ORIGIN_X; kFullScreen[0].y = ORIGIN_Y; @@ -176,7 +288,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _texCoords[1].u = SCALE(_width); _texCoords[1].v = SCALE(_height); - uint32 tvFrameSize = _tvWidth * _tvHeight * 4; // 32 bits per pixel + uint32 tvFrameSize = _tvPitch * _tvHeight * 4; // 32 bits per pixel // setup frame buffer pointers _frameBufPtr[0] = 0; @@ -186,7 +298,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _clutPtrs[TEXT] = _clutPtrs[SCREEN] + 0x2000; _texPtrs[SCREEN] = _clutPtrs[SCREEN] + 0x3000; _texPtrs[TEXT] = 0; // these buffers are stored in the alpha gaps of the frame buffers - _texPtrs[MOUSE] = 128 * 256 * 4; + _texPtrs[MOUSE] = 128 * 256 * 4; _texPtrs[PRINTF] = _texPtrs[MOUSE] + M_SIZE * M_SIZE * 4; _showOverlay = false; @@ -202,12 +314,12 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _overlayFormat.rLoss = 3; _overlayFormat.gLoss = 3; _overlayFormat.bLoss = 3; - _overlayFormat.aLoss = 7; + _overlayFormat.aLoss = 8; // 7 _overlayFormat.rShift = 0; _overlayFormat.gShift = 5; _overlayFormat.bShift = 10; - _overlayFormat.aShift = 15; + _overlayFormat.aShift = 0; // 15 // setup hardware now. GS_CSR = CSR_RESET; // Reset GS @@ -215,22 +327,39 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { GS_CSR = 0; GsPutIMR(0x7F00); - uint16 dispPosX, dispPosY; - if (_tvMode == TV_PAL) { - SetGsCrt(GS_INTERLACED, 3, 0); - dispPosX = DEFAULT_PAL_X; - dispPosY = DEFAULT_PAL_Y; - } else { - SetGsCrt(GS_INTERLACED, 2, 0); - dispPosX = DEFAULT_NTSC_X; - dispPosY = DEFAULT_NTSC_Y; + if (biosver < 220 && ps2_mode[mode].mode == 0x53) { // EDTV PAL : mode not in BIOS < 2.20 + // no worries... we work in magic ;-) + /* 720x576p */ + asm ("di"); + asm ("sync.l; sync.p"); + GS_PMODE = 0; + asm ("sync.l; sync.p"); + GS_SMODE1 = 0x1742890504; + asm ("sync.l; sync.p"); + GS_SMODE2 = 0; + GS_SYNCH1 = 0x402E02003C827; + asm ("sync.l; sync.p"); + GS_SYNCH2 = 0x19CA67; + asm ("sync.l; sync.p"); + GS_SYNCV = 0xA9000002700005; + asm ("sync.l; sync.p"); + GS_SRFSH = 4; + asm ("sync.l; sync.p"); + GS_SMODE1 = 0x1742880504; + asm ("sync.l; sync.p"); + asm ("sync.l; sync.p"); + GS_SMODE2 = 0; + asm("ei"); + } + else { // BIOS + SetGsCrt(ps2_mode[mode].interlaced, ps2_mode[mode].mode, 0); // ps2_mode[mode].interlaced); } asm("di"); GS_PMODE = GS_SET_PMODE(1, 0, 1, 1, 0, 255); GS_BGCOLOUR = GS_RGBA(0, 0, 0, 0); - GS_DISPLAY1 = GS_SET_DISPLAY(_tvWidth, _tvHeight, dispPosX, dispPosY); + GS_DISPLAY1 = GS_SET_DISPLAY_MODE(ps2_mode[mode]); asm("ei"); _curDrawBuf = 0; @@ -238,7 +367,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _dmaPipe->setOrigin(ORIGIN_X, ORIGIN_Y); _dmaPipe->setConfig(1, 0, 1); _dmaPipe->setScissorRect(0, 0, _tvWidth - 1, _tvHeight - 1); - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); _dmaPipe->flush(); _clutChanged = _screenChanged = _overlayChanged = true; @@ -249,24 +378,33 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { createAnimTextures(); // create animation thread - ee_thread_t animationThread, thisThread; + #ifdef __NEW_PS2SDK__ + ee_thread_t animThread; + ee_thread_status_t thisThread; + #else + ee_thread_t animThread, thisThread; + #endif ReferThreadStatus(GetThreadId(), &thisThread); - _animStack = malloc(ANIM_STACK_SIZE); - animationThread.initial_priority = thisThread.current_priority - 3; - animationThread.stack = _animStack; - animationThread.stack_size = ANIM_STACK_SIZE; - animationThread.func = (void *)runAnimThread; - animationThread.gp_reg = &_gp; + _animStack = memalign(64, ANIM_STACK_SIZE); + animThread.initial_priority = thisThread.current_priority - 3; + animThread.stack = _animStack; + animThread.stack_size = ANIM_STACK_SIZE; + animThread.func = (void *)runAnimThread; + animThread.gp_reg = &_gp; - _animTid = CreateThread(&animationThread); + _animTid = CreateThread(&animThread); assert(_animTid >= 0); StartThread(_animTid, this); } void Gs2dScreen::quit(void) { _systemQuit = true; + #ifdef __NEW_PS2SDK__ + ee_thread_status_t statAnim; + #else ee_thread_t statAnim; + #endif do { // wait until thread called ExitThread() SignalSema(g_AnimSema); ReferThreadStatus(_animTid, &statAnim); @@ -296,15 +434,15 @@ void Gs2dScreen::createAnimTextures(void) { for (int i = 0; i < 16; i++) { uint32 *destPos = (uint32 *)buf; for (int ch = 15; ch >= 0; ch--) { - const uint32 *src = (const uint32*)(_binaryData + ((_binaryPattern[i] >> ch) & 1) * 4 * 14); + const uint32 *src = (const uint32 *)(_binaryData + ((_binaryPattern[i] >> ch) & 1) * 4 * 14); for (int line = 0; line < 14; line++) destPos[line << 4] = src[line]; destPos++; } if (!(i & 1)) - _dmaPipe->uploadTex( vramDest, 128, 0, 0, GS_PSMT4HH, buf, 128, 16); + _dmaPipe->uploadTex( vramDest, 128, 0, 0, GS_PSMT4HH, buf, 128, 16); else { - _dmaPipe->uploadTex( vramDest, 128, 0, 0, GS_PSMT4HL, buf, 128, 16); + _dmaPipe->uploadTex( vramDest, 128, 0, 0, GS_PSMT4HL, buf, 128, 16); vramDest += 128 * 16 * 4; } _dmaPipe->flush(); @@ -506,10 +644,10 @@ void Gs2dScreen::updateScreen(void) { WaitSema(g_DmacSema); // wait for dma transfer, if there's one running WaitSema(g_VblankSema); // wait if there's already an image waiting for vblank - g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler + g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24); // put it here for dmac/vblank handler _dmaPipe->flush(); _curDrawBuf ^= 1; - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); } else _dmaPipe->flush(); SignalSema(_screenSema); @@ -527,6 +665,7 @@ void Gs2dScreen::hideOverlay(void) { Graphics::PixelFormat Gs2dScreen::getOverlayFormat(void) { return _overlayFormat; + // return Graphics::createPixelFormat<1555>(); } int16 Gs2dScreen::getOverlayWidth(void) { @@ -633,11 +772,11 @@ void Gs2dScreen::setMouseXy(int16 x, int16 y) { _mouseX = x; _mouseY = y; } - +/* uint8 Gs2dScreen::tvMode(void) { return _tvMode; } - +*/ uint16 Gs2dScreen::getWidth(void) { return _width; } @@ -655,7 +794,7 @@ void Gs2dScreen::wantAnim(bool runIt) { #define V 1000 #define Z_TRANSL 65 -void Gs2dScreen::animThread(void) { +void Gs2dScreen::playAnim(void) { // animate zeros and ones while game accesses memory card, etc. g_RunAnim = false; float yPos = 0.0; @@ -750,10 +889,10 @@ void Gs2dScreen::animThread(void) { drawY += LINE_SPACE; } - g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler + g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24); // put it here for dmac/vblank handler _dmaPipe->flush(); _curDrawBuf ^= 1; - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); _dmaPipe->setAlphaBlend(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0); SignalSema(_screenSema); @@ -763,7 +902,7 @@ void Gs2dScreen::animThread(void) { } void runAnimThread(Gs2dScreen *param) { - param->animThread(); + param->playAnim(); } // data for the animated zeros and ones... diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h index be9729b66b..ea2b1e5f78 100644 --- a/backends/platform/ps2/Gs2dScreen.h +++ b/backends/platform/ps2/Gs2dScreen.h @@ -25,6 +25,7 @@ #include "sysdefs.h" #include "backends/base-backend.h" +#include "common/config-manager.h" #include "backends/platform/ps2/DmaPipe.h" #include "graphics/surface.h" @@ -32,7 +33,9 @@ enum TVMode { TV_DONT_CARE = 0, TV_PAL, - TV_NTSC + TV_NTSC, + TV_HDTV, /* internal */ + TV_VESA /* internal */ }; enum GsInterlace { @@ -42,14 +45,14 @@ enum GsInterlace { class Gs2dScreen { public: - Gs2dScreen(uint16 width, uint16 height, TVMode mode); + Gs2dScreen(uint16 width, uint16 height); ~Gs2dScreen(void); void newScreenSize(uint16 width, uint16 height); - uint8 tvMode(void); + // uint8 tvMode(void); uint16 getWidth(void); uint16 getHeight(void); - void copyPrintfOverlay(const uint8* buf); + void copyPrintfOverlay(const uint8 *buf); void clearPrintfOverlay(void); Graphics::Surface *lockScreen(); @@ -75,7 +78,7 @@ public: void setMouseXy(int16 x, int16 y); void setShakePos(int shake); - void animThread(void); + void playAnim(void); void wantAnim(bool runIt); void quit(void); @@ -85,8 +88,10 @@ private: void createAnimTextures(void); DmaPipe *_dmaPipe; + uint8 _gfxMode; uint8 _tvMode; uint16 _tvWidth, _tvHeight; + uint16 _tvPitch; GsVertex _blitCoords[2]; TexVertex _texCoords[2]; diff --git a/backends/platform/ps2/GsDefs.h b/backends/platform/ps2/GsDefs.h index 07e3c50ad8..9adf6acfcc 100644 --- a/backends/platform/ps2/GsDefs.h +++ b/backends/platform/ps2/GsDefs.h @@ -27,16 +27,23 @@ // Gs2dScreen defines: -#define PAL_NTSC_FLAG (*(volatile uint8*)0x1FC7FF52) +#define PAL_NTSC_FLAG (*(volatile uint8 *)0x1FC7FF52) -#define GS_PMODE *((volatile uint64*)0x12000000) -#define GS_CSR *((volatile uint64*)0x12001000) -#define GS_DISPFB1 *((volatile uint64*)0x12000070) -#define GS_DISPLAY1 *((volatile uint64*)0x12000080) -#define GS_BGCOLOUR *((volatile uint64*)0x120000E0) +#define GS_PMODE *((volatile uint64 *)0x12000000) +#define GS_CSR *((volatile uint64 *)0x12001000) +#define GS_DISPFB1 *((volatile uint64 *)0x12000070) +#define GS_DISPLAY1 *((volatile uint64 *)0x12000080) +#define GS_BGCOLOUR *((volatile uint64 *)0x120000E0) + +#define GS_SMODE1 *((volatile uint64 *)0x12000010) +#define GS_SMODE2 *((volatile uint64 *)0x12000020) +#define GS_SYNCH1 *((volatile uint64 *)0x12000040) +#define GS_SYNCH2 *((volatile uint64 *)0x12000050) +#define GS_SYNCV *((volatile uint64 *)0x12000060) +#define GS_SRFSH *((volatile uint64 *)0x12000030) enum GS_CSR_FIELDS { - CSR_SIGNAL = 1 << 0, + CSR_SIGNAL = 1 << 0, CSR_FINISH = 1 << 1, CSR_HSYNC = 1 << 2, CSR_VSYNC = 1 << 3, @@ -44,6 +51,19 @@ enum GS_CSR_FIELDS { CSR_RESET = 1 << 9 }; +typedef struct { + u16 w; + u16 h; + u16 interlaced; + u16 pitch; + u16 mode; + u16 vclk; + u16 magh; + u16 magv; + u16 dx; + u16 dy; +} ps2_mode_t; + #define GS_SET_PMODE(readC1, readC2, alphaSel, alphaOut, alphaBlend, alphaFixed) \ ((readC1) | ((readC2) << 1) | ((alphaSel) << 5) | ((alphaOut) << 6) | ((alphaBlend) << 7) | ((alphaFixed) << 8)) @@ -52,6 +72,10 @@ enum GS_CSR_FIELDS { ((((2560 + (width - 1)) / width) - 1)<<23) | \ (ypos << 12) | (xpos * (2560 / width))) +#define GS_SET_DISPLAY_MODE(mode) \ + (((uint64)(mode.h - 1) << 44) | ((uint64)(mode.vclk - 1) << 32) | \ + ((mode.magh - 1) << 23) | (mode.dy << 12) | (mode.dx << 2)) + #define GS_SET_DISPFB(frameBufPtr, frameBufWidth, psm) \ (((frameBufPtr) / 8192) | (((frameBufWidth) / 64) << 9) | ((psm) << 15)) @@ -61,63 +85,63 @@ enum GS_CSR_FIELDS { //DmaPipe defines: enum GsRegs { - GPR_PRIM = 0x00, // Select and configure current drawing primitive - GPR_RGBAQ, // Setup current vertex color - GPR_ST, // ... - GPR_UV, // Specify Vertex Texture Coordinates - GPR_XYZF2, // Set vertex coordinate - GPR_XYZ2, // Set vertex coordinate and 'kick' drawing - GPR_TEX0_1, // Texture Buffer Setup (Context 1) - GPR_TEX0_2, // Texture Buffer Setup (Context 2) - GPR_CLAMP_1, // ... - GPR_CLAMP_2, // ... - GPR_FOG, // ... - - GPR_XYZF3 = 0x0C, // ... - GPR_XYZ3, // ... - - GPR_TEX1_1 = 0x14, // ... - GPR_TEX1_2, // ... - GPR_TEX2_1, // ... - GPR_TEX2_2, // ... - GPR_XYOFFSET_1, // Mapping from Primitive to Window coordinate system (Context 1) - GPR_XYOFFSET_2, // Mapping from Primitive to Window coordinate system (Context 2) - GPR_PRMODECONT, // ... - GPR_PRMODE, // ... - GPR_TEXCLUT, // ... - - GPR_SCANMSK = 0x22, // ... - - GPR_MIPTBP1_1 = 0x34, // ... - GPR_MIPTBP1_2, // ... - GPR_MIPTBP2_1, // ... - GPR_MIPTBP2_2, // ... - - GPR_TEXA = 0x3b, // ... - - GPR_FOGCOL = 0x3d, // ... - - GPR_TEXFLUSH = 0x3f,// Write to this register before using newly loaded texture - GPR_SCISSOR_1, // Setup clipping rectangle (Context 1) - GPR_SCISSOR_2, // Setup clipping rectangle (Context 2) - GPR_ALPHA_1, // Setup Alpha Blending Parameters (Context 1) - GPR_ALPHA_2, // Setup Alpha Blending Parameters (Context 2) - GPR_DIMX, // ... - GPR_DTHE, // ... - GPR_COLCLAMP, // ... - GPR_TEST_1, // ... - GPR_TEST_2, // ... - GPR_PABE, // ... - GPR_FBA_1, // ... - GPR_FBA_2, // ... - GPR_FRAME_1, // Frame buffer settings (Context 1) - GPR_FRAME_2, // Frame buffer settings (Context 2) - GPR_ZBUF_1, // ... - GPR_ZBUF_2, // ... - GPR_BITBLTBUF, // Setup Image Transfer Between EE and GS - GPR_TRXPOS, // Setup Image Transfer Coordinates - GPR_TRXREG, // Setup Image Transfer Size - GPR_TRXDIR, // Set Image Transfer Directon + Start Transfer + GPR_PRIM = 0x00, // Select and configure current drawing primitive + GPR_RGBAQ, // Setup current vertex color + GPR_ST, // ... + GPR_UV, // Specify Vertex Texture Coordinates + GPR_XYZF2, // Set vertex coordinate + GPR_XYZ2, // Set vertex coordinate and 'kick' drawing + GPR_TEX0_1, // Texture Buffer Setup (Context 1) + GPR_TEX0_2, // Texture Buffer Setup (Context 2) + GPR_CLAMP_1, // ... + GPR_CLAMP_2, // ... + GPR_FOG, // ... + + GPR_XYZF3 = 0x0C, // ... + GPR_XYZ3, // ... + + GPR_TEX1_1 = 0x14, // ... + GPR_TEX1_2, // ... + GPR_TEX2_1, // ... + GPR_TEX2_2, // ... + GPR_XYOFFSET_1, // Mapping from Primitive to Window coordinate system (Context 1) + GPR_XYOFFSET_2, // Mapping from Primitive to Window coordinate system (Context 2) + GPR_PRMODECONT, // ... + GPR_PRMODE, // ... + GPR_TEXCLUT, // ... + + GPR_SCANMSK = 0x22, // ... + + GPR_MIPTBP1_1 = 0x34, // ... + GPR_MIPTBP1_2, // ... + GPR_MIPTBP2_1, // ... + GPR_MIPTBP2_2, // ... + + GPR_TEXA = 0x3b, // ... + + GPR_FOGCOL = 0x3d, // ... + + GPR_TEXFLUSH = 0x3f, // Write to this register before using newly loaded texture + GPR_SCISSOR_1, // Setup clipping rectangle (Context 1) + GPR_SCISSOR_2, // Setup clipping rectangle (Context 2) + GPR_ALPHA_1, // Setup Alpha Blending Parameters (Context 1) + GPR_ALPHA_2, // Setup Alpha Blending Parameters (Context 2) + GPR_DIMX, // ... + GPR_DTHE, // ... + GPR_COLCLAMP, // ... + GPR_TEST_1, // ... + GPR_TEST_2, // ... + GPR_PABE, // ... + GPR_FBA_1, // ... + GPR_FBA_2, // ... + GPR_FRAME_1, // Frame buffer settings (Context 1) + GPR_FRAME_2, // Frame buffer settings (Context 2) + GPR_ZBUF_1, // ... + GPR_ZBUF_2, // ... + GPR_BITBLTBUF, // Setup Image Transfer Between EE and GS + GPR_TRXPOS, // Setup Image Transfer Coordinates + GPR_TRXREG, // Setup Image Transfer Size + GPR_TRXDIR, // Set Image Transfer Directon + Start Transfer GPR_HWREG, GPR_SIGNAL = 0x60, @@ -135,15 +159,15 @@ enum PrimTypes { PR_SPRITE }; -#define GS_PSMCT32 0x00 -#define GS_PSMCT24 0x01 -#define GS_PSMCT16 0x02 -#define GS_PSMCT16S 0x0A -#define GS_PSMT8 0x13 -#define GS_PSMT4 0x14 -#define GS_PSMT4HL 0x24 -#define GS_PSMT4HH 0x2C -#define GS_PSMT8H 0x1B +#define GS_PSMCT32 0x00 +#define GS_PSMCT24 0x01 +#define GS_PSMCT16 0x02 +#define GS_PSMCT16S 0x0A +#define GS_PSMT8 0x13 +#define GS_PSMT4 0x14 +#define GS_PSMT4HL 0x24 +#define GS_PSMT4HH 0x2C +#define GS_PSMT8H 0x1B /*#define GS_SET_BITBLTBUF(sbp, sbw, spsm, dbp, dbw, dpsm) \ ((uint64)(sbp) | ((uint64)(sbw) << 16) | \ @@ -210,7 +234,7 @@ enum AlphaBlendColor { enum AlphaBlendAlpha { SOURCE_ALPHA = 0, DEST_ALPHA, - FIXED_ALPHA + FIXED_ALPHA }; #define GS_SET_ALPHA(a, b, c, d, fix) \ diff --git a/backends/platform/ps2/Makefile.gdb b/backends/platform/ps2/Makefile.gdb deleted file mode 100644 index 8ca47cd9f1..0000000000 --- a/backends/platform/ps2/Makefile.gdb +++ /dev/null @@ -1,104 +0,0 @@ -# $Header: Exp $ - include $(PS2SDK)/Defs.make - -PS2_EXTRA = /works/devel/ps2/sdk-extra -PS2_EXTRA_INCS = /zlib/include /libmad/ee/include /SjPcm/ee/src /tremor -PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /tremor/tremor - -ENABLED=STATIC_PLUGIN - -ENABLE_SCUMM = $(ENABLED) -ENABLE_SCUMM_7_8 = $(ENABLED) -# ENABLE_HE = $(ENABLED) -# ENABLE_AGI = $(ENABLED) -# ENABLE_AGOS = $(ENABLED) -# ENABLE_AGOS2 = $(ENABLED) -# ENABLE_CINE = $(ENABLED) -# ENABLE_CRUISE = $(ENABLED) -# ENABLE_DRACI = $(ENABLED) -# ENABLE_DRASCULA = $(ENABLED) -# ENABLE_GOB = $(ENABLED) -# ENABLE_GROOVIE = $(ENABLED) -## ENABLE_GROOVIE2 = $(ENABLED) -# ENABLE_HUGO = $(ENABLED) -# ENABLE_IHNM = $(ENABLED) -# ENABLE_KYRA = $(ENABLED) -## ENABLE_LOL = $(ENABLED) -# ENABLE_LURE = $(ENABLED) -## ENABLE_M4 = $(ENABLED) -# ENABLE_MADE = $(ENABLED) -# ENABLE_MOHAWK = $(ENABLED) -# ENABLE_PARALLACTION = $(ENABLED) -# ENABLE_QUEEN = $(ENABLED) -# ENABLE_SAGA = $(ENABLED) -# ENABLE_SAGA2 = $(ENABLED) -# ENABLE_SCI = $(ENABLED) -## ENABLE_SCI32 = $(ENABLED) -# ENABLE_SKY = $(ENABLED) -# ENABLE_SWORD1 = $(ENABLED) -# ENABLE_SWORD2 = $(ENABLED) -# ENABLE_TEENAGENT = $(ENABLED) -# ENABLE_TINSEL = $(ENABLED) -# ENABLE_TOON = $(ENABLED) -# ENABLE_TOUCHE = $(ENABLED) -# ENABLE_TUCKER = $(ENABLED) - - -HAVE_GCC3 = true - -CC = ee-gcc -CXX = ee-g++ -AS = ee-gcc -LD = ee-gcc -AR = ee-ar cru -RANLIB = ee-ranlib -STRIP = ee-strip -MKDIR = mkdir -p -RM = rm -f - -srcdir = ../../.. -VPATH = $(srcdir) -INCDIR = ../../../ -# DEPDIR = .deps - -DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -DDISABLE_SAVEGAME_SORTING -D_EE -D__PLAYSTATION2__ -D__PS2_DEBUG__ -g -Wall -Wno-multichar -fno-rtti -fno-exceptions # -DNO_ADAPTOR -# for release builds: -#DEFINES += -DRELEASE_BUILD - -INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) -INCLUDES += -I $(PS2GDB)/ee -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines - -CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP - -TARGET = elf/scummvm.elf - -OBJS := $(srcdir)/backends/platform/ps2/DmaPipe.o \ - $(srcdir)/backends/platform/ps2/Gs2dScreen.o \ - $(srcdir)/backends/platform/ps2/irxboot.o \ - $(srcdir)/backends/platform/ps2/ps2input.o \ - $(srcdir)/backends/platform/ps2/ps2pad.o \ - $(srcdir)/backends/platform/ps2/savefilemgr.o \ - $(srcdir)/backends/platform/ps2/fileio.o \ - $(srcdir)/backends/platform/ps2/asyncfio.o \ - $(srcdir)/backends/platform/ps2/icon.o \ - $(srcdir)/backends/platform/ps2/cd.o \ - $(srcdir)/backends/platform/ps2/eecodyvdfs.o \ - $(srcdir)/backends/platform/ps2/rpckbd.o \ - $(srcdir)/backends/platform/ps2/systemps2.o \ - $(srcdir)/backends/platform/ps2/ps2mutex.o \ - $(srcdir)/backends/platform/ps2/ps2time.o \ - $(srcdir)/backends/platform/ps2/ps2debug.o - -MODULE_DIRS += . - -include $(srcdir)/Makefile.common - -LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile -LDFLAGS += -L $(PS2GDB)/lib -L $(PS2SDK)/ee/lib -L . -LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) -LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lps2gdbStub -lps2ip -ldebug -lkernel -lstdc++ - -all: $(TARGET) - -$(TARGET): $(OBJS) - $(LD) $^ $(LDFLAGS) -o $@ diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2 index d6ce08ae84..3631c653f6 100644 --- a/backends/platform/ps2/Makefile.ps2 +++ b/backends/platform/ps2/Makefile.ps2 @@ -1,107 +1,217 @@ -# $Header: Exp $ - include $(PS2SDK)/Defs.make +# SCUMMVM-PS2 MakeFile -PS2_EXTRA = /works/devel/ps2/sdk-extra -PS2_EXTRA_INCS = /zlib/include /libmad/ee/include /SjPcm/ee/src /tremor -PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /tremor/tremor -ENABLED=STATIC_PLUGIN +# Use only this section to modify how the makefile behaves ------------ -ENABLE_SCUMM = $(ENABLED) -ENABLE_SCUMM_7_8 = $(ENABLED) -ENABLE_HE = $(ENABLED) +# Scummvm engine config: choose which engines are enabled ENABLE_AGI = $(ENABLED) ENABLE_AGOS = $(ENABLED) -ENABLE_AGOS2 = $(ENABLED) +ENABLE_AGOS2 = 1 +# ENABLE_AVALANCHE = $(ENABLED) +ENABLE_CGE = $(ENABLED) ENABLE_CINE = $(ENABLED) +ENABLE_COMPOSER = $(ENABLED) ENABLE_CRUISE = $(ENABLED) ENABLE_DRACI = $(ENABLED) ENABLE_DRASCULA = $(ENABLED) +ENABLE_DREAMWEB = $(ENABLED) +# ENABLE_FULLPIPE = $(ENABLED) ENABLE_GOB = $(ENABLED) ENABLE_GROOVIE = $(ENABLED) # ENABLE_GROOVIE2 = $(ENABLED) +# ENABLE_HOPKINS = $(ENABLED) ENABLE_HUGO = $(ENABLED) -ENABLE_IHNM = $(ENABLED) ENABLE_KYRA = $(ENABLED) -# ENABLE_LOL = $(ENABLED) +ENABLE_LOL = 1 +ENABLE_EOB = 1 +# ENABLE_LASTEXPRESS = $(ENABLED) ENABLE_LURE = $(ENABLED) -# ENABLE_M4 = $(ENABLED) ENABLE_MADE = $(ENABLED) ENABLE_MOHAWK = $(ENABLED) +# ENABLE_CSTIME = $(ENABLED) +# ENABLE_RIVEN = $(ENABLED) +# ENABLE_MYST = $(ENABLED) +ENABLE_MORTEVIELLE = $(ENABLED) +ENABLE_NEVERHOOD = $(ENABLED) ENABLE_PARALLACTION = $(ENABLED) +# ENABLE_PEGASUS = $(ENABLED) ENABLE_QUEEN = $(ENABLED) ENABLE_SAGA = $(ENABLED) +ENABLE_IHNM = 1 # ENABLE_SAGA2 = $(ENABLED) ENABLE_SCI = $(ENABLED) # ENABLE_SCI32 = $(ENABLED) +ENABLE_SCUMM = $(ENABLED) +ENABLE_SCUMM_7_8 = 1 +ENABLE_HE = 1 ENABLE_SKY = $(ENABLED) ENABLE_SWORD1 = $(ENABLED) ENABLE_SWORD2 = $(ENABLED) +# ENABLE_SWORD25 = $(ENABLED) ENABLE_TEENAGENT = $(ENABLED) +# ENABLE_TESTBED = $(ENABLED) ENABLE_TINSEL = $(ENABLED) +ENABLE_TOLTECS = $(ENABLED) +# ENABLE_TONY = $(ENABLED) ENABLE_TOON = $(ENABLED) ENABLE_TOUCHE = $(ENABLED) +ENABLE_TSAGE = $(ENABLED) ENABLE_TUCKER = $(ENABLED) - - -HAVE_GCC3 = true - -CC = ee-gcc -CXX = ee-g++ -AS = ee-gcc -LD = ee-gcc +# ENABLE_WINTERMUTE = $(ENABLED) +# ENABLE_ZVISION = $(ENABLED) + +# Set to 1 to enable seeing the commands to gcc +VERBOSE_BUILD = 0 +# Set to 1 to enable, 0 to disable dynamic modules +DYNAMIC_MODULES = 1 +# Set to 1 to enable debugging +ENABLE_DEBUG = 0 +# Set to 1 to enable profiling +ENABLE_PROFILING = 0 +# Set to 1 to disable HDD+NET +DISABLE_NETWORK = 0 +# Set to 1 to enable, 0 to disable libmad and libogg +USE_LIBMAD = 1 +USE_LIBOGG = 1 + +# --------------------------------------------------------------------- + + +# General variables +srcdir = ../../.. +VPATH = $(srcdir) +TARGET = scummvm.elf +# PS2 SDK location variables +# PS2SDK = /works/tools/devel/ps2/sdk + +# Check PS2SDK presence +ifeq ($(PS2SDK),) +$(error $$(PS2SDK) needs to be set.) +endif + +# Variables for common Scummvm makefile +CC = ee-gcc +CXX = ee-g++ +FLAGS = -pedantic -Wall -W +FLAGS += -Wcast-qual -Wconversion -Wpointer-arith -Wshadow -Wwrite-strings +FLAGS += -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-unused-parameter +CFLAGS = $(FLAGS) -std=c99 +CXXFLAGS = $(FLAGS) -Wnon-virtual-dtor -Wno-reorder -fno-exceptions -fno-rtti + +DEFINES = -D_EE -D__PLAYSTATION2__ -D__NEW_PS2SDK__ -DUSE_ZLIB -DFORCE_RTL -DDATA_PATH=\"host:data\" +DEFINES += -DDISABLE_SAVEGAME_SORTING -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL -DDISABLE_SID -DDISABLE_NES_APU +# DEFINES += -DLOGORRHEIC + +INCDIR := $(PS2SDK)/ee/include $(PS2SDK)/common/include $(PS2SDK)/ports/include . $(srcdir) $(srcdir)/engines +INCLUDES := $(addprefix -I, $(INCDIR)) +DEPDIR = .deps +MODULE_DIRS += ./ +MKDIR = mkdir -p +RM = rm -f +RM_REC = rm -rf AR = ee-ar cru RANLIB = ee-ranlib STRIP = ee-strip -MKDIR = mkdir -p -RM = rm -f - -srcdir = ../../.. -VPATH = $(srcdir) -INCDIR = ../../../ -# DEPDIR = .deps - -DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -DDISABLE_SAVEGAME_SORTING -D_EE -D__PLAYSTATION2__ -G2 -O2 -Wall -Wno-multichar -fno-rtti -fno-exceptions # -DNO_ADAPTOR -# for release builds: -#DEFINES += -DRELEASE_BUILD - -INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) -INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines - -CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP - -TARGET = elf/scummvm.elf +AS = ee-gcc +LD = ee-gcc +HAVE_GCC3 = true +CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP + +# Variables for dynamic plugin building +PLUGIN_PREFIX = +PLUGIN_SUFFIX = .plg +PLUGIN_EXTRA_DEPS = $(TARGET) +PLUGIN_LDFLAGS = -nostartfiles $(srcdir)/backends/plugins/elf/version.o -Wl,-q,--just-symbols,$(TARGET),--retain-symbols-file,$(srcdir)/backends/plugins/elf/plugin.syms +PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/plugin.ld -lstdc++ -lc + +# Test for adding different libs +ifeq ($(USE_LIBMAD),1) +DEFINES += -DUSE_MAD +LIBS += -lmad +endif +ifeq ($(USE_LIBOGG), 1) +DEFINES += -DUSE_VORBIS -DUSE_TREMOR +LIBS += -ltremor +endif + +# Test for dynamic plugins +ifeq ($(DYNAMIC_MODULES),1) +ENABLED = DYNAMIC_PLUGIN +DEFINES += -DDYNAMIC_MODULES -DUSE_ELF_LOADER -DMIPS_TARGET -DUNCACHED_PLUGINS -DPLUGIN_DIRECTORY=\"host:plugins\" +PRE_OBJS_FLAGS = -Wl,--whole-archive +POST_OBJS_FLAGS = -Wl,--no-whole-archive +else +ENABLED = STATIC_PLUGIN +endif + +# Test for debug +ifeq ($(ENABLE_DEBUG),1) +DEFINES += -D__PS2_DEBUG__ +FLAGS += -G2 -g +LIBS += -lps2gdbStub -lps2ip -ldebug +else +DEFINES += -DRELEASE_BUILD +FLAGS += -G2 -O2 -s -Wuninitialized +# LDFLAGS += -s +endif + +# Test for profiling +ifeq ($(ENABLE_PROFILING),1) +DEFINES += -DENABLE_PROFILING +FLAGS += -G2 -pg -g +LDFLAGS += -pg +endif + +# Test for net support +ifeq ($(DISABLE_NETWORK),1) +DEFINES += -DNO_ADAPTOR +endif + +# PS2 LIBS +PS2LIBS = -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lz -lm -lc -lfileXio -lkernel -lstdc++ + +# Add in PS2SDK includes and libraries. +LIBS += $(PS2LIBS) OBJS := $(srcdir)/backends/platform/ps2/DmaPipe.o \ - $(srcdir)/backends/platform/ps2/Gs2dScreen.o \ - $(srcdir)/backends/platform/ps2/irxboot.o \ - $(srcdir)/backends/platform/ps2/ps2input.o \ - $(srcdir)/backends/platform/ps2/ps2pad.o \ - $(srcdir)/backends/platform/ps2/savefilemgr.o \ - $(srcdir)/backends/platform/ps2/fileio.o \ - $(srcdir)/backends/platform/ps2/asyncfio.o \ - $(srcdir)/backends/platform/ps2/icon.o \ - $(srcdir)/backends/platform/ps2/cd.o \ - $(srcdir)/backends/platform/ps2/eecodyvdfs.o \ - $(srcdir)/backends/platform/ps2/rpckbd.o \ - $(srcdir)/backends/platform/ps2/systemps2.o \ - $(srcdir)/backends/platform/ps2/ps2mutex.o \ - $(srcdir)/backends/platform/ps2/ps2time.o \ - $(srcdir)/backends/platform/ps2/ps2debug.o - -MODULE_DIRS += . + $(srcdir)/backends/platform/ps2/Gs2dScreen.o \ + $(srcdir)/backends/platform/ps2/irxboot.o \ + $(srcdir)/backends/platform/ps2/ps2input.o \ + $(srcdir)/backends/platform/ps2/ps2pad.o \ + $(srcdir)/backends/platform/ps2/savefilemgr.o \ + $(srcdir)/backends/platform/ps2/fileio.o \ + $(srcdir)/backends/platform/ps2/asyncfio.o \ + $(srcdir)/backends/platform/ps2/icon.o \ + $(srcdir)/backends/platform/ps2/cd.o \ + $(srcdir)/backends/platform/ps2/eecodyvdfs.o \ + $(srcdir)/backends/platform/ps2/rpckbd.o \ + $(srcdir)/backends/platform/ps2/systemps2.o \ + $(srcdir)/backends/platform/ps2/ps2mutex.o \ + $(srcdir)/backends/platform/ps2/ps2time.o \ + $(srcdir)/backends/platform/ps2/ps2debug.o + +ifeq ($(DYNAMIC_MODULES),1) +OBJS += $(srcdir)/backends/plugins/elf/elf-loader.o \ + $(srcdir)/backends/plugins/elf/elf-provider.o \ + $(srcdir)/backends/plugins/elf/shorts-segment-manager.o \ + $(srcdir)/backends/plugins/elf/memory-manager.o \ + $(srcdir)/backends/plugins/elf/mips-loader.o \ + $(srcdir)/backends/plugins/elf/version.o +endif BACKEND := ps2 +# Include common Scummvm makefile include $(srcdir)/Makefile.common +LDFLAGS += -L$(PS2SDK)/ee/lib -L$(PS2SDK)/ports/lib +ifeq ($(DYNAMIC_MODULES),1) +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/main_prog.ld +else LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile -LDFLAGS += -L $(PS2SDK)/ee/lib -L . -LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) -LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++ -LDFLAGS += -s +endif all: $(TARGET) $(TARGET): $(OBJS) - $(LD) $^ $(LDFLAGS) -o $@ + $(LD) $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LDFLAGS) $(LIBS) -o $@ diff --git a/backends/platform/ps2/Makefile.ps2.dev b/backends/platform/ps2/Makefile.ps2.dev new file mode 100644 index 0000000000..cd9432e2df --- /dev/null +++ b/backends/platform/ps2/Makefile.ps2.dev @@ -0,0 +1,170 @@ +# SCUMMVM-PS2 MakeFile + + +# Use only this section to modify how the makefile behaves ------------ + +# Scummvm engine config: choose which engines are enabled +ENABLE_SCUMM = $(ENABLED) +ENABLE_SCUMM_7_8 = 1 +# ENABLE_HE = 1 +ENABLE_SCI = $(ENABLED) +# ENABLE_SCI32 = $(ENABLED) +# ENABLE_SKY = $(ENABLED) +# ENABLE_SWORD1 = $(ENABLED) +# ENABLE_SWORD2 = $(ENABLED) + +# Set to 1 to enable seeing the commands to gcc +VERBOSE_BUILD = 1 +# Set to 1 to enable, 0 to disable dynamic modules +DYNAMIC_MODULES = 0 +# Set to 1 to enable debugging +ENABLE_DEBUG = 0 +# Set to 1 to enable profiling +ENABLE_PROFILING = 1 +# Set to 1 to disable HDD+NET +DISABLE_NETWORK = 0 +# Set to 1 to enable, 0 to disable libmad and libogg +USE_LIBMAD = 1 +USE_LIBOGG = 1 + +# --------------------------------------------------------------------- + + +# General variables +srcdir = ../../.. +VPATH = $(srcdir) +TARGET = scummvm.elf +# PS2 SDK location variables +# PS2SDK = /works/tools/devel/ps2/sdk + +# Check PS2SDK presence +ifeq ($(PS2SDK),) +$(error $$(PS2SDK) needs to be set.) +endif + +# Variables for common Scummvm makefile +CC = ee-gcc +CXX = ee-g++ +FLAGS = -pedantic -Wall -W +FLAGS += -Wcast-qual -Wconversion -Wpointer-arith -Wshadow -Wwrite-strings +FLAGS += -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-unused-parameter +CFLAGS = $(FLAGS) -std=c99 +CXXFLAGS = $(FLAGS) -Wnon-virtual-dtor -Wno-reorder -fno-exceptions -fno-rtti + +DEFINES = -D_EE -D__PLAYSTATION2__ -D__NEW_PS2SDK__ -DUSE_ZLIB -DFORCE_RTL -DDATA_PATH=\"host:data\" +DEFINES += -DDISABLE_SAVEGAME_SORTING -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL -DDISABLE_SID -DDISABLE_NES_APU +# DEFINES += -DLOGORRHEIC + +INCDIR := $(PS2SDK)/ee/include $(PS2SDK)/common/include $(PS2SDK)/ports/include . $(srcdir) $(srcdir)/engines +INCLUDES := $(addprefix -I, $(INCDIR)) +DEPDIR = .deps +MODULE_DIRS += ./ +MKDIR = mkdir -p +RM = rm -f +RM_REC = rm -rf +AR = ee-ar cru +RANLIB = ee-ranlib +STRIP = ee-strip +AS = ee-gcc +LD = ee-gcc +HAVE_GCC3 = true +CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP + +# Variables for dynamic plugin building +PLUGIN_PREFIX = +PLUGIN_SUFFIX = .plg +PLUGIN_EXTRA_DEPS = $(TARGET) +PLUGIN_LDFLAGS = -nostartfiles $(srcdir)/backends/plugins/elf/version.o -Wl,-q,--just-symbols,$(TARGET),--retain-symbols-file,$(srcdir)/backends/plugins/elf/plugin.syms +PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/plugin.ld -lstdc++ -lc + +# Test for adding different libs +ifeq ($(USE_LIBMAD),1) +DEFINES += -DUSE_MAD +LIBS += -lmad +endif +ifeq ($(USE_LIBOGG), 1) +DEFINES += -DUSE_VORBIS -DUSE_TREMOR +LIBS += -ltremor +endif + +# Test for dynamic plugins +ifeq ($(DYNAMIC_MODULES),1) +ENABLED = DYNAMIC_PLUGIN +DEFINES += -DDYNAMIC_MODULES -DUSE_ELF_LOADER -DMIPS_TARGET -DUNCACHED_PLUGINS -DPLUGIN_DIRECTORY=\"host:plugins\" +PRE_OBJS_FLAGS = -Wl,--whole-archive +POST_OBJS_FLAGS = -Wl,--no-whole-archive +else +ENABLED = STATIC_PLUGIN +endif + +# Test for debug +ifeq ($(ENABLE_DEBUG),1) +DEFINES += -D__PS2_DEBUG__ +FLAGS += -G2 -g +LIBS += -lps2gdbStub -lps2ip -ldebug +else +DEFINES += -DRELEASE_BUILD +FLAGS += -G2 -O2 -s -Wuninitialized +# LDFLAGS += -s +endif + +# Test for profiling +ifeq ($(ENABLE_PROFILING),1) +DEFINES += -DENABLE_PROFILING +FLAGS += -G2 -pg -g +LDFLAGS += -pg +endif + +# Test for net support +ifeq ($(DISABLE_NETWORK),1) +DEFINES += -DNO_ADAPTOR +endif + +# PS2 LIBS +PS2LIBS = -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lz -lm -lc -lfileXio -lkernel -lstdc++ + +# Add in PS2SDK includes and libraries. +LIBS += $(PS2LIBS) + +OBJS := $(srcdir)/backends/platform/ps2/DmaPipe.o \ + $(srcdir)/backends/platform/ps2/Gs2dScreen.o \ + $(srcdir)/backends/platform/ps2/irxboot.o \ + $(srcdir)/backends/platform/ps2/ps2input.o \ + $(srcdir)/backends/platform/ps2/ps2pad.o \ + $(srcdir)/backends/platform/ps2/savefilemgr.o \ + $(srcdir)/backends/platform/ps2/fileio.o \ + $(srcdir)/backends/platform/ps2/asyncfio.o \ + $(srcdir)/backends/platform/ps2/icon.o \ + $(srcdir)/backends/platform/ps2/cd.o \ + $(srcdir)/backends/platform/ps2/eecodyvdfs.o \ + $(srcdir)/backends/platform/ps2/rpckbd.o \ + $(srcdir)/backends/platform/ps2/systemps2.o \ + $(srcdir)/backends/platform/ps2/ps2mutex.o \ + $(srcdir)/backends/platform/ps2/ps2time.o \ + $(srcdir)/backends/platform/ps2/ps2debug.o + +ifeq ($(DYNAMIC_MODULES),1) +OBJS += $(srcdir)/backends/plugins/elf/elf-loader.o \ + $(srcdir)/backends/plugins/elf/elf-provider.o \ + $(srcdir)/backends/plugins/elf/shorts-segment-manager.o \ + $(srcdir)/backends/plugins/elf/memory-manager.o \ + $(srcdir)/backends/plugins/elf/mips-loader.o \ + $(srcdir)/backends/plugins/elf/version.o +endif + +BACKEND := ps2 + +# Include common Scummvm makefile +include $(srcdir)/Makefile.common + +LDFLAGS += -L$(PS2SDK)/ee/lib -L$(PS2SDK)/ports/lib +ifeq ($(DYNAMIC_MODULES),1) +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/main_prog.ld +else +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile +endif + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LDFLAGS) $(LIBS) -o $@ diff --git a/backends/platform/ps2/README.PS2 b/backends/platform/ps2/README.PS2 new file mode 100644 index 0000000000..141a79eaca --- /dev/null +++ b/backends/platform/ps2/README.PS2 @@ -0,0 +1,189 @@ +Dear PS2 ScummVM enthusiast user, + +here you will find the latest and the greatest PS2 backend ever! + + + *** Release Notes *** + +Released 2 builds: SCUMMVM.ELF and SCUMMVM-S.ELF. The latter has engine +modules statically linked into (that's what the "-S" is for), the former +uses dynamic modules (uncached). The dynamic one is much faster to start +and has more resources available for the games. The catch is that games +detection, when you are adding a new one, is painstakingly slow... +(as it needs to load, test, unload the plugins one by one). + +Until we have an optimization for that in place I would suggest you add +new games with "SCUMMVM-S.ELF", and when you are done adding you then +play them with "SCUMMVM.ELF", as this will give you the best of both. + +We no longer have a separate ELF build with hdd & net adapter disabled, +as we now do it in the smart way, allowing users to disable it in their +ScummVM.ini. See under in "Configuration" for details. + +We also have an improved Makefile.ps2 in ps2 folder which will allow +you to create: static, dynamic, profile and debug build version. + +You can now also cleanly compile using "configure" and specifying: + +./configure --backend=ps2 --host=ps2 ... + + + *** Installation *** + +Some media drivers require all capitalized letter, so to be on the +safe side store the files (SCUMMVM.ELF and *.IRX) in upper case. + +Here comes a full list of the required *.IRX (don't worry they are all +provided pre-compiled in the binary release ;-) + + IOMANX.IRX + FILEXIO.IRX + CODYVDFS.IRX + SJPCM.IRX + USBD.IRX + USB_MASS.IRX + PS2MOUSE.IRX + RPCKBD.IRX + POWEROFF.IRX + PS2DEV9.IRX + PS2ATAD.IRX + PS2HDD.IRX + PS2FS.IRX + PS2IP.IRX + PS2SMAP.IRX + PS2HOST.IRX + +Make sure they are all stored in the folder that contains your SCUMMVM.ELF! + +If you are starting ScummVM from CD/DVD then it will look for ScummVM.ini +a ScummVM.ini on the media folder from where you started SCUMMVM.ELF. + +Notes: + + - depending on the media you install Scummvm/PS2 onto, it might be + picky about files cases, so I'd leave those *.IRX uppercase and + scummmodern.zip lower ;0) + + - make sure you selected a save path before you start playing! + + - we added PS2IPS.IRX in case you wanted to test a debug build + (use Makefile.gdb) + + + *** Configuration *** + +There is now a [PlayStation2] section in ScummVM.ini which can be used +to make your wildest dreams come true ;-) + +It accepts these entries: + +tv_mode = [pal] [ntsc] +gfx_mode = [mode number] [*] +hdd_part = [partition name] [disable] +net_addr = [PS2 IP addr] [**] +usb_mass = [0] [disable] + +[*] Currently supported gfx modes are: + + # 1 -> SDTV progressive (NTSC: 224p / PAL: 256p) + # 2 -> SDTV interlaced (NTSC: 448i / PAL: 512i) <- default + # 3 -> EDTV progressive (NTSC: 480p / PAL: 576p) + # 6 -> VESA (640x480@60) + +If no tv_mode is specified it will be autodected based on PS2 model. + +The non-interlaced (progressive) modes look much better and sharper. +You can check the difference starting COMI and choosing About from +the GMM (press "start" then choose "about"). You can easily see the +difference between progressive and interlaced in scrolling text. + +You can use mode 6 (VGA 640x480) if you are connecting your PS2 to +a RGB monitor. Some TVs also supports this signal. + +We also do some bad-ass things, like detecting the BIOS version and +setting the GS registers by hand, for console models where a mode +is not supported ;-) + +If SCUMMVM.ELF hangs at start for you try disabling the adapter by +setting in ScummVM.ini + +hdd_part = 0 +net_addr = 0 + +You can now also choose the hdd partition used for ScummVM games +(default "+ScummVM") passing it as an argument to hdd_part: + +hdd_part = MyPartition (witout the "+") + +If you have an adapter with hdd & net, but you don't use them you +can just set both to 0 to disable, and have a leaner and meaner +ScummVM booting much faster! + +[**] TODO + + *** Remote *** + +You will need "PS2IP.IRX", "PS2SMAP.IRX" and "PS2HOST.IRX" drivers too +in the folder where you are starting SCUMMVM.ELF if you want to use +the remote capability. + +The IP 192.168.1.20 (ps2link default) is hardcoded in the source as +"netArg" in irxboot.cpp, feel free to modify it to match your network +configuration. + +In a future release you will be able to set in ScummVM.ini using + +net_addr = xxx.yyy.zzz.www + +If you are starting SCUMMVM.ELF over the net using ps2client then you +are already set. If you are starting it in any other way, then you +will have to "export" the folder where you are storing ScummVM games +and data by starting ps2client from inside that folder. Eg. from a +terminal: + +> ./ps2client -h [your ps2 ip] listen + +Do this -after- ScummVM is up and running otherwise it will fail to +establish a connection. + + + *** Gamepad *** + +The mapping is: + +Start Button - GMM +R1 - 'y' +L1 - 'n' +R2 - '.' +L2 - Numpad 0 +Triangle - Escape +Square - Enter +Cross - Left mouse button +Circle - Right mouse button + + + *** Bugs *** + +Though we made our best to make this release as bug free as possible +there are still a few bugs left: + + - file handling speed : (not really a bug, but a nuisance) : there + is probably space for some more optimization in the current file + management. The only case when it really bogs me it's when you + try to select a saved game and there is some lag. + + Some game will start faster too when this is optimized. + + - feel free to add your bug, suggestion, secret wish to this list! + + - SCI games have smooth audio and intro, but moving the pointer + and in-game animation speed might be a challenge. + + - it has been reported USB media greater than 8 GB might not work + +Now enough reading, rush to your PlayStation2 and start playing! + +Are you still reading? + +Have a lot of fun, + -Max Lingua diff --git a/backends/platform/ps2/asyncfio.cpp b/backends/platform/ps2/asyncfio.cpp index b49fcbca75..6f15dcc628 100644 --- a/backends/platform/ps2/asyncfio.cpp +++ b/backends/platform/ps2/asyncfio.cpp @@ -33,7 +33,7 @@ AsyncFio::AsyncFio(void) { _runningOp = NULL; - memset((int *)_ioSlots, 0, MAX_HANDLES * sizeof(int)); + memset(const_cast<int *>(_ioSlots), 0, MAX_HANDLES * sizeof(int)); ee_sema_t newSema; newSema.init_count = 1; newSema.max_count = 1; @@ -63,7 +63,7 @@ int AsyncFio::open(const char *name, int ioMode, int mode) { fileXioWaitAsync(FXIO_WAIT, &res); SignalSema(_ioSema); // dbg_printf("FIO: open ext(%s, %d, %d) => %d", name, ioMode, mode, res); - return res; + return res; } void AsyncFio::close(int handle) { @@ -80,7 +80,7 @@ void AsyncFio::close(int handle) { void AsyncFio::checkSync(void) { if (_runningOp) { - fileXioWaitAsync(FXIO_WAIT, (int *)_runningOp); + fileXioWaitAsync(FXIO_WAIT, const_cast<int *>(_runningOp)); _runningOp = NULL; } } @@ -90,7 +90,7 @@ void AsyncFio::read(int fd, void *dest, unsigned int len) { checkSync(); assert(fd < MAX_HANDLES); _runningOp = _ioSlots + fd; - fileXioRead(fd, (unsigned char*)dest, len); + fileXioRead(fd, (unsigned char *)dest, len); SignalSema(_ioSema); } @@ -99,7 +99,7 @@ void AsyncFio::write(int fd, const void *src, unsigned int len) { checkSync(); assert(fd < MAX_HANDLES); _runningOp = _ioSlots + fd; - fileXioWrite(fd, (unsigned char*)src, len); + fileXioWrite(fd, (unsigned char *)const_cast<void *>(src), len); SignalSema(_ioSema); } @@ -210,7 +210,7 @@ bool AsyncFio::poll(int fd) { bool retVal = false; if (PollSema(_ioSema) >= 0) { if (_runningOp == _ioSlots + fd) { - if (fileXioWaitAsync(FXIO_NOWAIT, (int *)_runningOp) == FXIO_COMPLETE) { + if (fileXioWaitAsync(FXIO_NOWAIT, const_cast<int *>(_runningOp)) == FXIO_COMPLETE) { _runningOp = NULL; retVal = true; } else @@ -226,7 +226,7 @@ bool AsyncFio::fioAvail(void) { bool retVal = false; if (PollSema(_ioSema) > 0) { if (_runningOp) { - if (fileXioWaitAsync(FXIO_NOWAIT, (int *)_runningOp) == FXIO_COMPLETE) { + if (fileXioWaitAsync(FXIO_NOWAIT, const_cast<int *>(_runningOp)) == FXIO_COMPLETE) { _runningOp = NULL; retVal = true; } else diff --git a/backends/platform/ps2/asyncfio.h b/backends/platform/ps2/asyncfio.h index 2e39c8667c..6f84742da0 100644 --- a/backends/platform/ps2/asyncfio.h +++ b/backends/platform/ps2/asyncfio.h @@ -23,6 +23,9 @@ #define MAX_HANDLES 32 #include <sys/stat.h> +#undef chdir // we define our own +#undef mkdir + class AsyncFio { public: AsyncFio(void); diff --git a/backends/platform/ps2/cd.c b/backends/platform/ps2/cd.c index cd44b3d034..e08437d34f 100644 --- a/backends/platform/ps2/cd.c +++ b/backends/platform/ps2/cd.c @@ -19,35 +19,35 @@ int cdvdInitialised = 0; void cdvdExit(void) { - cdvdInitialised = 0; + cdvdInitialised = 0; } int cdvdInit(int mode) { int i=0,len=0,ret=0; - u8 *pkt; - - cdvdCd.server = NULL; - - do { - if ((ret = SifBindRpc(&cdvdCd, CDVD_INIT_BIND_RPC, 0)) < 0) { - return -1; - } - if (!cdvdCd.server) { - nopdelay(); - } - } + u8 *pkt; + + cdvdCd.server = NULL; + + do { + if ((ret = SifBindRpc(&cdvdCd, (signed)CDVD_INIT_BIND_RPC, 0)) < 0) { + return -1; + } + if (!cdvdCd.server) { + nopdelay(); + } + } while(!cdvdCd.server); - pkt = sendBuffer; - PUSHDATA( int, pkt, mode, i); - pkt += i; len += i; + pkt = (unsigned char *)sendBuffer; + PUSHDATA(int, pkt, mode, i); + pkt += i; len += i; if ((ret = SifCallRpc(&cdvdCd, 0, 0, sendBuffer, len, NULL, 0, 0, 0)) < 0) - return -1; + return -1; - cdvdInitialised = 1; + cdvdInitialised = 1; - return 0; + return 0; } diff --git a/backends/platform/ps2/eecodyvdfs.h b/backends/platform/ps2/eecodyvdfs.h index ac080873e1..f439c42125 100644 --- a/backends/platform/ps2/eecodyvdfs.h +++ b/backends/platform/ps2/eecodyvdfs.h @@ -40,7 +40,7 @@ struct CdClock { #ifdef __cplusplus extern "C" { #endif - int initCdvdFs(void); + int initCdvdFs(void); void readRTC(struct CdClock *dest); int driveStop(void); int driveStandby(void); diff --git a/backends/platform/ps2/fileio.cpp b/backends/platform/ps2/fileio.cpp index 411e20d3bc..205a688438 100644 --- a/backends/platform/ps2/fileio.cpp +++ b/backends/platform/ps2/fileio.cpp @@ -20,8 +20,9 @@ * */ -// Disable symbol overrides so that we can use system headers. -#define FORBIDDEN_SYMBOL_ALLOW_ALL +// Disable symbol overrides so that we can use "FILE" +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE +#define FORBIDDEN_SYMBOL_EXCEPTION_printf #include "backends/platform/ps2/fileio.h" @@ -78,12 +79,12 @@ Ps2File::~Ps2File() { fio.seek(_fd, 0, SEEK_SET); fio.write(_fd, _cacheBuf, _filePos); w = fio.sync(_fd); - printf("flushed wbuf: %x of %x\n", w, _filePos); + dbg_printf("flushed wbuf: %x of %x\n", w, _filePos); } fio.close(_fd); uint32 r = fio.sync(_fd); - printf("close [%d] - sync'd = %d\n", _fd, r); + dbg_printf("close [%d] - sync'd = %d\n", _fd, r); } free(_cacheBuf); @@ -97,7 +98,7 @@ bool Ps2File::open(const char *name, int mode) { #if 1 _fd = fio.open(name, mode); - printf("open %s [%d]\n", name, _fd); + dbg_printf("open %s [%d]\n", name, _fd); if (_fd >= 0) { _mode = mode; @@ -110,9 +111,9 @@ bool Ps2File::open(const char *name, int mode) { else _fileSize = 0; - printf(" _mode = %x\n", _mode); - printf(" _fileSize = %d\n", _fileSize); - // printf(" _filePos = %d\n", _filePos); + dbg_printf(" _mode = %x\n", _mode); + dbg_printf(" _fileSize = %d\n", _fileSize); + // dbg_printf(" _filePos = %d\n", _filePos); return true; } @@ -130,7 +131,7 @@ bool Ps2File::open(const char *name, int mode) { if (_fileSize && mode != O_RDONLY) { fio.read(_fd, _cacheBuf, _fileSize); r = fio.sync(_fd); - printf(" sz=%d, read=%d\n", _fileSize, r); + dbg_printf(" sz=%d, read=%d\n", _fileSize, r); assert(r == _fileSize); } @@ -141,7 +142,7 @@ bool Ps2File::open(const char *name, int mode) { _fd = fio.open(name, mode); - printf("open %s [%d]\n", name, _fd); + dbg_printf("open %s [%d]\n", name, _fd); if (_fd >= 0) { _mode = mode; @@ -160,16 +161,16 @@ bool Ps2File::open(const char *name, int mode) { if (mode != O_RDONLY) { fio.read(_fd, _cacheBuf, _fileSize); r = fio.sync(_fd); - printf(" sz=%d, read=%d\n", _fileSize, r); + dbg_printf(" sz=%d, read=%d\n", _fileSize, r); assert(r == _fileSize); // _fileSize = fio.seek(_fd, 0, SEEK_END); } #endif } - printf(" _mode = %x\n", _mode); - printf(" _fileSize = %d\n", _fileSize); - printf(" _filePos = %d\n", _filePos); + dbg_printf(" _mode = %x\n", _mode); + dbg_printf(" _fileSize = %d\n", _fileSize); + dbg_printf(" _filePos = %d\n", _filePos); return true; } else @@ -208,7 +209,7 @@ bool Ps2File::eof() { #ifdef __PS2_FILE_SEMA__ SignalSema(_sema); - // printf(" EOF [%d] : %d of %d -> %d\n", _fd, _filePos, _fileSize, res); + // dbg_printf(" EOF [%d] : %d of %d -> %d\n", _fd, _filePos, _fileSize, res); #endif return res; } @@ -255,8 +256,8 @@ int Ps2File::seek(int32 offset, int origin) { _eof = true; } - // printf("seek [%d] %d %d\n", _fd, offset, origin); - // printf(" res = %d\n", res); + // dbg_printf("seek [%d] %d %d\n", _fd, offset, origin); + // dbg_printf(" res = %d\n", res); #ifdef __PS2_FILE_SEMA__ SignalSema(_sema); @@ -338,8 +339,8 @@ uint32 Ps2File::read(void *dest, uint32 len) { #endif #ifdef __PS2_FILE_DEBUG__ - printf("read (1) : _filePos = %d\n", _filePos); - printf("read (1) : _cachePos = %d\n", _cachePos); + dbg_printf("read (1) : _filePos = %d\n", _filePos); + dbg_printf("read (1) : _cachePos = %d\n", _cachePos); #endif if (len == 0) { @@ -409,7 +410,10 @@ uint32 Ps2File::read(void *dest, uint32 len) { break; // EOF } } +#ifndef ENABLE_PROFILING + // doesn't play nice with -pg cacheReadAhead(); +#endif #ifdef __PS2_FILE_SEMA__ SignalSema(_sema); #endif @@ -473,7 +477,7 @@ uint32 PS2FileStream::write(const void *ptr, uint32 len) { } bool PS2FileStream::flush() { - // printf("flush not implemented\n"); + // dbg_printf("flush not implemented\n"); return true; } @@ -481,7 +485,7 @@ bool PS2FileStream::err() const { bool errVal = _handle->getErr(); if (errVal) { - printf("ferror -> %d\n", errVal); + dbg_printf("ferror -> %d\n", errVal); } return errVal; @@ -501,7 +505,7 @@ FILE *ps2_fopen(const char *fname, const char *mode) { Ps2File *file = new Ps2File(); int _mode = O_RDONLY; - printf("fopen(%s, %s)\n", fname, mode); + dbg_printf("fopen(%s, %s)\n", fname, mode); if (mode[0] == 'r' && mode [1] == 'w') _mode = O_RDWR; diff --git a/backends/platform/ps2/fileio.h b/backends/platform/ps2/fileio.h index 27245dc9c9..16eb7f212a 100644 --- a/backends/platform/ps2/fileio.h +++ b/backends/platform/ps2/fileio.h @@ -30,13 +30,13 @@ #include "common/stream.h" enum { - CACHE_SIZE = 2048 * 32, - MAX_READ_STEP = 2048 * 16, - MAX_CACHED_FILES = 6, - CACHE_READ_THRESHOLD = 16 * 2048, - CACHE_FILL_MIN = 2048 * 24, - READ_ALIGN = 64, // align all reads to the size of an EE cache line - READ_ALIGN_MASK = READ_ALIGN - 1 + CACHE_SIZE = 2048 * 32, + MAX_READ_STEP = 2048 * 16, + MAX_CACHED_FILES = 6, + CACHE_READ_THRESHOLD = 16 * 2048, + CACHE_FILL_MIN = 2048 * 24, + READ_ALIGN = 64, // align all reads to the size of an EE cache line + READ_ALIGN_MASK = READ_ALIGN - 1 }; // TODO: Make this a subclass of SeekableReadStream & WriteStream diff --git a/backends/platform/ps2/icon.cpp b/backends/platform/ps2/icon.cpp index df6a165cd4..9319d9f4d9 100644 --- a/backends/platform/ps2/icon.cpp +++ b/backends/platform/ps2/icon.cpp @@ -937,7 +937,7 @@ uint16 PS2Icon::decompressData(uint16 **data) { uint16 inPos = 1; const uint16 *rleData = (const uint16 *)_rleIcoData; uint16 resSize = rleData[0]; - uint16 *resData = (uint16 *)malloc(resSize * sizeof(uint16)); + uint16 *resData = (uint16 *)memalign(64, resSize * sizeof(uint16)); uint16 outPos = 0; while (outPos < resSize) { diff --git a/backends/platform/ps2/iop/CoDyVDfs/common/codyvdirx.h b/backends/platform/ps2/iop/CoDyVDfs/common/codyvdirx.h index 81ef7cb6d0..6ac5a0bb65 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/common/codyvdirx.h +++ b/backends/platform/ps2/iop/CoDyVDfs/common/codyvdirx.h @@ -26,13 +26,13 @@ #define CDVDFS_IRX_ID 0xD004352 // commands: -#define READ_RTC 0 -#define SET_READ_SPEED 1 -#define DRIVE_STOP 2 -#define DRIVE_STANDBY 3 +#define READ_RTC 0 +#define SET_READ_SPEED 1 +#define DRIVE_STOP 2 +#define DRIVE_STANDBY 3 -#define CdTrayOpen 0 -#define CdTrayClose 1 -#define CdTrayCheck 2 +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 #endif // CDVDFS_COMMON_H diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/cdtypes.h b/backends/platform/ps2/iop/CoDyVDfs/iop/cdtypes.h index ae4fd44ce5..d9bd5287c6 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/cdtypes.h +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/cdtypes.h @@ -39,24 +39,24 @@ typedef struct { } ISOPathTableRecord __attribute__ ((packed)); typedef struct { - uint8 year; // Number of years since 1900 - uint8 month; // Month of the year from 1 to 12 - uint8 day; // Day of the Month from 1 to 31 - uint8 hour; // Hour of the day from 0 to 23 - uint8 min; // Minute of the hour from 0 to 59 - uint8 sec; // second of the minute from 0 to 59 - uint8 gmtOff; // Offset from Greenwich Mean Time in number of 15 minute intervals from -48(West) to +52(East) + uint8 year; // Number of years since 1900 + uint8 month; // Month of the year from 1 to 12 + uint8 day; // Day of the Month from 1 to 31 + uint8 hour; // Hour of the day from 0 to 23 + uint8 min; // Minute of the hour from 0 to 59 + uint8 sec; // second of the minute from 0 to 59 + uint8 gmtOff; // Offset from Greenwich Mean Time in number of 15 minute intervals from -48(West) to +52(East) uint8 padding[10]; } ISOTime __attribute__ ((packed)); typedef struct { - uint8 year; // Number of years since 1900 - uint8 month; // Month of the year from 1 to 12 - uint8 day; // Day of the Month from 1 to 31 - uint8 hour; // Hour of the day from 0 to 23 - uint8 min; // Minute of the hour from 0 to 59 - uint8 sec; // second of the minute from 0 to 59 - uint8 gmtOff; // Offset from Greenwich Mean Time in number of 15 minute intervals from -48(West) to +52(East) + uint8 year; // Number of years since 1900 + uint8 month; // Month of the year from 1 to 12 + uint8 day; // Day of the Month from 1 to 31 + uint8 hour; // Hour of the day from 0 to 23 + uint8 min; // Minute of the hour from 0 to 59 + uint8 sec; // second of the minute from 0 to 59 + uint8 gmtOff; // Offset from Greenwich Mean Time in number of 15 minute intervals from -48(West) to +52(East) //uint8 padding[10]; } ISOFileTime __attribute__ ((packed)); @@ -96,38 +96,38 @@ typedef struct { uint8 reserved[6]; uint8 reserved2; uint8 reserved3; -} ISORoot __attribute__((packed)); // 0x22 +} ISORoot __attribute__((packed)); // 0x22 typedef struct { - uint8 type; // 0x00 - char identifier[5]; // 0x01 - uint8 version; // 0x06 - uint8 reserved1; // 0x07 - char systemIdentifier[32]; // 0x08 + uint8 type; // 0x00 + char identifier[5]; // 0x01 + uint8 version; // 0x06 + uint8 reserved1; // 0x07 + char systemIdentifier[32]; // 0x08 char volumeIdentifier[32]; // 0x28 - uint8 reserved2[8]; // 0x48 - uint32 volumeSpaceSize; // 0x50 - uint32 volumeSpaceSizeBE; // 0x54 - char reserved3[32]; // 0x58 - uint32 volumeSetSize; // 0x78 - uint32 volumeSequenceNumber; // 0x7C - uint32 logicalBlockSize; // 0x80 - uint32 pathTableSize; // 0x84 - uint32 pathTableSizeBE; // 0x88 - uint32 pathTablePos; // 0x8C - uint32 pathTable2Pos; // 0x90 - uint32 pathTablePosBE; // 0x94 - uint32 pathTable2PosBE; // 0x98 - ISORoot rootDir; // 0x9C - ISOIds ids; // 0xBE - ISOTime creation; // 0x32D - ISOTime modification; // 0x33E - ISOTime expiration; // 0x34F - ISOTime effective; // 0x360 - uint8 fileStructureVersion; // 0x371 - uint8 reserved4; // 0x372 - uint8 applicationUse[512]; // 0x373 - uint8 reserved5[653]; // 0x573 -} ISOPvd __attribute__ ((packed)); // 0x800 + uint8 reserved2[8]; // 0x48 + uint32 volumeSpaceSize; // 0x50 + uint32 volumeSpaceSizeBE; // 0x54 + char reserved3[32]; // 0x58 + uint32 volumeSetSize; // 0x78 + uint32 volumeSequenceNumber; // 0x7C + uint32 logicalBlockSize; // 0x80 + uint32 pathTableSize; // 0x84 + uint32 pathTableSizeBE; // 0x88 + uint32 pathTablePos; // 0x8C + uint32 pathTable2Pos; // 0x90 + uint32 pathTablePosBE; // 0x94 + uint32 pathTable2PosBE; // 0x98 + ISORoot rootDir; // 0x9C + ISOIds ids; // 0xBE + ISOTime creation; // 0x32D + ISOTime modification; // 0x33E + ISOTime expiration; // 0x34F + ISOTime effective; // 0x360 + uint8 fileStructureVersion; // 0x371 + uint8 reserved4; // 0x372 + uint8 applicationUse[512]; // 0x373 + uint8 reserved5[653]; // 0x573 +} ISOPvd __attribute__ ((packed)); // 0x800 #endif // __CDTYPES_H__ diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.c b/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.c index e55e62853b..2a94560843 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.c +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.c @@ -59,7 +59,7 @@ int verifyDriveReady(void) { return -1; // drive still not ready } } - if (mediaType == DISC_NONE) + if (mediaType == DISC_NONE) return -1; return 0; } @@ -72,14 +72,14 @@ int cacheEnterDir(ISODirectoryRecord *dir) { cachedDirOfs = 0; cacheName = cachedDir + strlen(cachedDir); memcpy(cacheName, dir->name, dir->len_fi); - cacheName[dir->len_fi] = '/'; + cacheName[dir->len_fi] = '/'; cacheName[dir->len_fi + 1] = '\0'; return cdReadSectors(cachedDirLba, 1, cacheBuf, &rmode); } int initRootCache(void) { CdRMode rmode = { 16, 0, CdSect2048, 0 }; - ISODirectoryRecord *root = (ISODirectoryRecord*)cacheBuf; + ISODirectoryRecord *root = (ISODirectoryRecord *)cacheBuf; if (cdReadSectors(fsRootLba, 1, cacheBuf, &rmode) == 0) { cachedDir[0] = '\0'; @@ -104,10 +104,10 @@ ISODirectoryRecord *findEntryInCache(const char *name, int nameLen) { if (i != cachedDirOfs) { if (cdReadSectors(cachedDirLba + i, 1, cacheBuf, &rmode) < 0) return NULL; - cachedDirOfs = i; + cachedDirOfs = i; } - while (entry->len_dr && ((uint8*)entry < cacheBuf + SECTOR_SIZE)) { + while (entry->len_dr && ((uint8 *)entry < cacheBuf + SECTOR_SIZE)) { if ((entry->len_fi > 2) && (entry->name[entry->len_fi - 2] == ';') && (entry->name[entry->len_fi - 1] == '1')) { if ((nameLen == entry->len_fi - 2) && (strnicmp(name, entry->name, entry->len_fi - 2) == 0)) return entry; @@ -115,10 +115,10 @@ ISODirectoryRecord *findEntryInCache(const char *name, int nameLen) { if ((nameLen == entry->len_fi) && (strnicmp(name, entry->name, entry->len_fi) == 0)) return entry; } - entry = (ISODirectoryRecord *)( (uint8*)entry + entry->len_dr ); + entry = (ISODirectoryRecord *)( (uint8 *)entry + entry->len_dr ); } } - return NULL; + return NULL; } ISODirectoryRecord *findPath(const char *path) { @@ -225,12 +225,12 @@ int initDisc(void) { case 1: discType = DISC_MODE1; printf("Disc: Mode1\n"); - pvd = (ISOPvd*)(cacheBuf + 4); + pvd = (ISOPvd *)(cacheBuf + 4); break; case 2: discType = DISC_MODE2; printf("Disc: Mode2\n"); - pvd = (ISOPvd*)(cacheBuf + 12); + pvd = (ISOPvd *)(cacheBuf + 12); break; default: DBG_PRINTF("Unknown Sector Type %02X\n", cacheBuf[3]); @@ -257,7 +257,7 @@ int initDisc(void) { mediaType = discType; DBG_PRINTF("Root directory in sector %d\n", fsRootLba); - return initRootCache(); + return initRootCache(); } } } @@ -290,46 +290,46 @@ int cd_init(iop_device_t *dev) { } iop_device_ops_t FS_ops = { - (void *) cd_init, - (void *) cd_dummy, - (void *) cd_dummy, - (void *) cd_open, - (void *) cd_close, - (void *) cd_read, - (void *) cd_dummy, - (void *) cd_lseek, - (void *) cd_dummy, - (void *) cd_dummy, - (void *) cd_dummy, - (void *) cd_dummy, - (void *) cd_dopen, - (void *) cd_dclose, - (void *) cd_dread, - (void *) cd_dummy, - (void *) cd_dummy, + (void *) cd_init, + (void *) cd_dummy, + (void *) cd_dummy, + (void *) cd_open, + (void *) cd_close, + (void *) cd_read, + (void *) cd_dummy, + (void *) cd_lseek, + (void *) cd_dummy, + (void *) cd_dummy, + (void *) cd_dummy, + (void *) cd_dummy, + (void *) cd_dopen, + (void *) cd_dclose, + (void *) cd_dread, + (void *) cd_dummy, + (void *) cd_dummy, }; #define FS_NAME "cdfs" #define FS_DESC "CD-ROM" iop_device_t fsdriver = { - FS_NAME, - IOP_DT_FS | IOP_DT_FSEXT, - 1, - FS_DESC, - &FS_ops + FS_NAME, + IOP_DT_FS | IOP_DT_FSEXT, + 1, + FS_DESC, + &FS_ops }; int _start(void) { - printf("CoDyVDfs v0.01\n"); + printf("CoDyVDfs v0.01\n"); CdInit(1); - DelDrv(FS_NAME); - AddDrv(&fsdriver); + DelDrv(FS_NAME); + AddDrv(&fsdriver); initRpc(); initFio(); - return(0); + return(0); } int strnicmp(const char *s1, const char *s2, int n) { diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.h b/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.h index d50e89e4f3..cc903ea841 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.h +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/codyvdfs.h @@ -51,20 +51,20 @@ enum ReadModes { }; enum { - CdDiskNone = 0x00, - CdDiskDetect, // 0x01 - CdDiskDetectCD, // 0x02 - CdDiskDetectDVD, // 0x03 - CdDiskDetectUnk = 0x05, - CdDiskCDPS1 = 0x10, - CdDiskCDDAPS1 = 0x11, - CdDiskCDPS2 = 0x12, - CdDiskCDDAPS2 = 0x13, - CdDiskDVDPS2 = 0x14, - CdDiskDVDV2 = 0xFC, - CdDiskCDDA = 0xFD, - CdDiskDVDV = 0xFE, - CdDiskIllegal = 0xFF + CdDiskNone = 0x00, + CdDiskDetect, // 0x01 + CdDiskDetectCD, // 0x02 + CdDiskDetectDVD, // 0x03 + CdDiskDetectUnk = 0x05, + CdDiskCDPS1 = 0x10, + CdDiskCDDAPS1 = 0x11, + CdDiskCDPS2 = 0x12, + CdDiskCDDAPS2 = 0x13, + CdDiskDVDPS2 = 0x14, + CdDiskDVDV2 = 0xFC, + CdDiskCDDA = 0xFD, + CdDiskDVDV = 0xFE, + CdDiskIllegal = 0xFF }; #define DISC_NOT_READY(type) ((type > CdDiskNone) && (type < CdDiskCDPS1) && (type != CdDiskDetectUnk)) diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/fiofs.c b/backends/platform/ps2/iop/CoDyVDfs/iop/fiofs.c index f0a06f927b..611211a715 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/fiofs.c +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/fiofs.c @@ -104,7 +104,7 @@ int cd_open(iop_file_t *handle, const char *name, int mode) { fd->pos = 0; fd->cachedLba = 0; - handle->privdata = (void*)fdSlot; + handle->privdata = (void *)fdSlot; return 0; } @@ -135,7 +135,7 @@ int cd_read(iop_file_t *handle, void *dest, int length) { FioHandle *fd = fioHandles + (int)handle->privdata; CdRMode rmode = { 16, 0, CdSect2048, 0 }; int readLba, readPos, bytesLeft; - uint8 *destPos = (uint8*)dest; + uint8 *destPos = (uint8 *)dest; int doCopy; int numLba; readLba = fd->lba + (fd->pos >> 11); @@ -171,13 +171,13 @@ int cd_read(iop_file_t *handle, void *dest, int length) { numLba = bytesLeft >> 11; if (cdReadSectors(readLba, numLba, destPos, &rmode) != 0) break; - readLba += numLba; + readLba += numLba; fd->pos += numLba << 11; destPos += numLba << 11; bytesLeft &= 0x7FF; } } - return destPos - (uint8*)dest; + return destPos - (uint8 *)dest; } int cd_close(iop_file_t *handle) { @@ -219,7 +219,7 @@ int cd_dopen(iop_file_t *handle, const char *path) { } dioHandles[fdSlot].curOfs = 0; dioHandles[fdSlot].lbaOfs = 0; - handle->privdata = (void*)fdSlot; + handle->privdata = (void *)fdSlot; return fdSlot; } @@ -252,7 +252,7 @@ int cd_dread(iop_file_t *handle, iox_dirent_t *buf) { } } } - return 0; + return 0; } int cd_dclose(iop_file_t *handle) { diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/rpcfs.c b/backends/platform/ps2/iop/CoDyVDfs/iop/rpcfs.c index 5b760faa06..983ae38716 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/rpcfs.c +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/rpcfs.c @@ -69,11 +69,11 @@ void *rpcReadClock(void *data) { void *driveStop(void *data) { if (CdStop() == 1) { if (CdSync(0) == 0) { - *(int*)data = CdGetError(); + *(int *)data = CdGetError(); } else - *(int*)data = -0x100; + *(int *)data = -0x100; } else - *(int*)data = -0x101; + *(int *)data = -0x101; return data; } @@ -81,11 +81,11 @@ void *driveStandby(void *data) { int type; if (CdStandby() == 1) { if (CdSync(0) == 0) { - *(int*)data = CdGetError(); + *(int *)data = CdGetError(); } else - *(int*)data = -0x100; + *(int *)data = -0x100; } else - *(int*)data = -0x101; + *(int *)data = -0x101; do { // wait until drive detected disc type type = CdGetDiskType(); diff --git a/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h index 07d9c3d7f9..6bef7caefa 100644 --- a/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h +++ b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h @@ -87,8 +87,8 @@ typedef struct _kbd_keymap #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 +#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 */ diff --git a/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c index 7266afdce5..838ce9fe85 100644 --- a/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c +++ b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c @@ -1089,7 +1089,7 @@ void *ps2kbd_rpc_server(int fno, void *data, int size) { ps2kbd_rpc_flushbuffer(); break; case KBD_RPC_SETLEDS: - ps2kbd_rpc_setleds(*(u8*) data); + ps2kbd_rpc_setleds(*(u8 *) data); break; case KBD_RPC_RESETKEYMAP: ps2kbd_rpc_resetkeymap(); @@ -1129,7 +1129,7 @@ int ps2kbd_init_rpc(void) { int th; param.attr = 0x02000000; - param.thread = (void*)ps2kbd_start_rpc; + param.thread = (void *)ps2kbd_start_rpc; param.priority = 40; param.stacksize = 0x800; param.option = 0; diff --git a/backends/platform/ps2/irxboot.cpp b/backends/platform/ps2/irxboot.cpp index d3049fcf4b..0e05047c6e 100644 --- a/backends/platform/ps2/irxboot.cpp +++ b/backends/platform/ps2/irxboot.cpp @@ -34,37 +34,65 @@ static const char hddArg[] = "-o" "\0" "8" "\0" "-n" "\0" "20"; static const char pfsArg[] = "-m" "\0" "2" "\0" "-o" "\0" "32" "\0" "-n" "\0" "72"; // "\0" "-debug"; -static const char netArg[] = "192.168.0.10" "\0" "255.255.255.0" "\0" "192.168.0.1"; - -IrxFile irxFiles[] = { - { "SIO2MAN", BIOS, NOTHING, NULL, 0 }, - { "MCMAN", BIOS, NOTHING, NULL, 0 }, - { "MCSERV", BIOS, NOTHING, NULL, 0 }, - { "PADMAN", BIOS, NOTHING, NULL, 0 }, - { "LIBSD", BIOS, NOTHING, NULL, 0 }, - - { "IOMANX.IRX", SYSTEM, NOTHING, NULL, 0 }, - { "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 }, - { "CODYVDFS.IRX", SYSTEM, NOTHING, NULL, 0 }, +static const char netArg[] = "192.168.1.20" "\0" "255.255.255.0" "\0" "192.168.1.1"; // TODO: set in ScummVM.ini + +IrxFile irxCore[] = { // core modules + // Memory Card + { "SIO2MAN", BIOS, NOTHING, NULL, 0 }, + { "MCMAN", BIOS, NOTHING, NULL, 0 }, + { "MCSERV", BIOS, NOTHING, NULL, 0 }, + // Joypad + { "PADMAN", BIOS, NOTHING, NULL, 0 }, + // Sound + { "LIBSD", BIOS, NOTHING, NULL, 0 }, { "SJPCM.IRX", SYSTEM, NOTHING, NULL, 0 }, + // Files I/O + { "IOMANX.IRX", SYSTEM, NOTHING, NULL, 0 }, + { "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 } +}; + +IrxFile irxCdrom[] = { // cdrom modules + // CD-Rom FS + { "CODYVDFS.IRX", SYSTEM, CD_DRIVER, NULL, 0 } +}; +IrxFile irxUSB[] = { // USB mass + // USB drv & key { "USBD.IRX", USB | OPTIONAL | DEPENDANCY, USB_DRIVER, NULL, 0 }, - { "USB_MASS.IRX", USB | OPTIONAL, MASS_DRIVER, NULL, 0 }, + { "USB_MASS.IRX", USB | OPTIONAL, MASS_DRIVER, NULL, 0 } +}; + +IrxFile irxInput[] = { // USB input + // USB mouse & kbd { "PS2MOUSE.IRX", USB | OPTIONAL, MOUSE_DRIVER, NULL, 0 }, - { "RPCKBD.IRX", USB | OPTIONAL, KBD_DRIVER, NULL, 0 }, -#ifndef NO_ADAPTOR + { "RPCKBD.IRX", USB | OPTIONAL, KBD_DRIVER, NULL, 0 } +}; + +IrxFile irxHDD[] = { // modules to support HDD + // hdd modules { "POWEROFF.IRX", HDD | OPTIONAL | NOT_HOST | DEPENDANCY, HDD_DRIVER, NULL, 0 }, { "PS2DEV9.IRX", HDD | OPTIONAL | NOT_HOST | DEPENDANCY, HDD_DRIVER, NULL, 0 }, { "PS2ATAD.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, NULL, 0 }, { "PS2HDD.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, hddArg, sizeof(hddArg) }, - { "PS2FS.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, pfsArg, sizeof(pfsArg) }, + { "PS2FS.IRX", HDD | OPTIONAL | DEPENDANCY, HDD_DRIVER, pfsArg, sizeof(pfsArg) } +}; + +IrxFile irxNet[] = { // modules to support NET + // net modules { "PS2IP.IRX", NET | OPTIONAL | NOT_HOST | DEPENDANCY, NET_DRIVER, NULL, 0 }, { "PS2SMAP.IRX", NET | OPTIONAL | NOT_HOST | DEPENDANCY, NET_DRIVER, netArg, sizeof(netArg) }, { "PS2HOST.IRX", NET | OPTIONAL | NOT_HOST | DEPENDANCY, NET_DRIVER, NULL, 0 } -#endif }; -static const int numIrxFiles = sizeof(irxFiles) / sizeof(irxFiles[0]); +IrxFile *irxType[IRX_MAX] = { irxCore, irxCdrom, irxUSB, irxInput, irxHDD, irxNet }; + +static const int numIrx[IRX_MAX] = { sizeof(irxCore) / sizeof(IrxFile), + sizeof(irxCdrom) / sizeof(IrxFile), + sizeof(irxUSB) / sizeof(IrxFile), + sizeof(irxInput) / sizeof(IrxFile), + sizeof(irxHDD) / sizeof(IrxFile), + sizeof(irxNet) / sizeof(IrxFile) +}; PS2Device detectBootPath(const char *elfPath, char *bootPath) { @@ -113,19 +141,26 @@ PS2Device detectBootPath(const char *elfPath, char *bootPath) { return device; } -int loadIrxModules(int device, const char *irxPath, IrxReference **modules) { +int loadIrxModules(int device, const char *irxPath, IrxReference **modules, IrxType type) { + + IrxReference *resModules; + IrxReference *curModule; + IrxFile *irxFiles; + int numFiles; - IrxReference *resModules = (IrxReference *)malloc(numIrxFiles * sizeof(IrxReference)); - IrxReference *curModule = resModules; + irxFiles = irxType[type]; + numFiles = numIrx[type]; + resModules = (IrxReference *)memalign(64, numFiles * sizeof(IrxReference)); + curModule = resModules; - for (int i = 0; i < numIrxFiles; i++) { + for (int i = 0; i < numFiles; i++) { curModule->fileRef = irxFiles + i; if ((device == HOST_DEV) && (irxFiles[i].flags & NOT_HOST)) continue; if ((irxFiles[i].flags & TYPEMASK) == BIOS) { curModule->loc = IRX_FILE; - curModule->path = (char *)malloc(32); + curModule->path = (char *)memalign(64, 32); sprintf(curModule->path, "rom0:%s", irxFiles[i].name); curModule->buffer = NULL; curModule->size = 0; @@ -134,7 +169,7 @@ int loadIrxModules(int device, const char *irxPath, IrxReference **modules) { curModule->errorCode = 0; } else { curModule->loc = IRX_BUFFER; - curModule->path = (char *)malloc(256); + curModule->path = (char *)memalign(64, 256); sprintf(curModule->path, "%s%s%s", irxPath, irxFiles[i].name, (device == CD_DEV) ? ";1" : ""); int fd = fioOpen(curModule->path, O_RDONLY); @@ -191,7 +226,7 @@ int loadIrxModules(int device, const char *irxPath, IrxReference **modules) { pos++; } // and skip any remaining modules that depend on the missing one, too. - while ((i < numIrxFiles - 1) && ((irxFiles[i + 1].flags & TYPEMASK) == (curModule->fileRef->flags & TYPEMASK))) + while ((i < numFiles - 1) && ((irxFiles[i + 1].flags & TYPEMASK) == (curModule->fileRef->flags & TYPEMASK))) i++; // the module that actually failed (curModule) is kept in the array for displaying an error message } diff --git a/backends/platform/ps2/irxboot.h b/backends/platform/ps2/irxboot.h index 867911da0f..487d335553 100644 --- a/backends/platform/ps2/irxboot.h +++ b/backends/platform/ps2/irxboot.h @@ -25,6 +25,16 @@ #include "common/scummsys.h" +enum IrxType { + IRX_CORE = 0, + IRX_CDROM, + IRX_USB, + IRX_INPUT, + IRX_HDD, + IRX_NET, + IRX_MAX +}; + enum IrxFlags { BIOS = 0, SYSTEM = 1, @@ -40,6 +50,7 @@ enum IrxFlags { enum IrxPurpose { NOTHING, + CD_DRIVER, HDD_DRIVER, USB_DRIVER, MOUSE_DRIVER, @@ -81,6 +92,6 @@ struct IrxReference { int errorCode; }; -int loadIrxModules(int device, const char *irxPath, IrxReference **modules); +int loadIrxModules(int device, const char *irxPath, IrxReference **modules, IrxType type); #endif // __IRXBOOT_H__ diff --git a/backends/platform/ps2/module.mk b/backends/platform/ps2/module.mk index bf95a5501d..7bcc60e58d 100644 --- a/backends/platform/ps2/module.mk +++ b/backends/platform/ps2/module.mk @@ -2,20 +2,20 @@ MODULE := backends/platform/ps2 MODULE_OBJS := \ DmaPipe.o \ - Gs2dScreen.o \ - irxboot.o \ + Gs2dScreen.o \ + irxboot.o \ ps2input.o \ ps2pad.o \ savefilemgr.o \ - fileio.o \ - asyncfio.o \ + fileio.o \ + asyncfio.o \ icon.o \ - cd.o \ - eecodyvdfs.o \ - rpckbd.o \ - systemps2.o \ - ps2mutex.o \ - ps2time.o \ + cd.o \ + eecodyvdfs.o \ + rpckbd.o \ + systemps2.o \ + ps2mutex.o \ + ps2time.o \ ps2debug.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. diff --git a/backends/platform/ps2/ps2debug.cpp b/backends/platform/ps2/ps2debug.cpp index ec1e251583..84c3649faf 100644 --- a/backends/platform/ps2/ps2debug.cpp +++ b/backends/platform/ps2/ps2debug.cpp @@ -22,10 +22,10 @@ #include "ps2debug.h" #include <stdio.h> -#include <stdlib.h> #include <sio.h> void sioprintf(const char *zFormat, ...) { + #if 0 // doesn't seem to work with ps2link... va_list ap; char resStr[2048]; @@ -43,4 +43,5 @@ void sioprintf(const char *zFormat, ...) { sio_putc(*pos); pos++; } + #endif } diff --git a/backends/platform/ps2/ps2debug.h b/backends/platform/ps2/ps2debug.h index b3da749f60..45db850ebf 100644 --- a/backends/platform/ps2/ps2debug.h +++ b/backends/platform/ps2/ps2debug.h @@ -23,7 +23,13 @@ #ifndef __PS2DEBUG_H__ #define __PS2DEBUG_H__ -#define dbg_printf printf +#ifdef LOGORRHEIC + #define FORBIDDEN_SYMBOL_EXCEPTION_printf + // #define dbg_printf sio_printf + #define dbg_printf printf +#else + #define dbg_printf(...) /* ... */ +#endif void sioprintf(const char *zFormat, ...); diff --git a/backends/platform/ps2/ps2input.cpp b/backends/platform/ps2/ps2input.cpp index 6969aef931..636176e06c 100644 --- a/backends/platform/ps2/ps2input.cpp +++ b/backends/platform/ps2/ps2input.cpp @@ -170,7 +170,7 @@ bool Ps2Input::pollEvent(Common::Event *event) { } if (checkPadMouse || checkPadKbd) { // no usb mouse, simulate it using the pad - uint16 buttons; + uint16 buttons; int16 joyh, joyv; _pad->readPad(&buttons, &joyh, &joyv); uint16 btnChange = buttons ^ _padLastButtons; @@ -474,11 +474,11 @@ const Common::KeyCode Ps2Input::_usbToSdlk[0x100] = { /* DD */ Common::KEYCODE_INVALID, /* DE */ Common::KEYCODE_INVALID, /* DF */ Common::KEYCODE_INVALID, - /* E0 */ Common::KEYCODE_LCTRL, + /* E0 */ Common::KEYCODE_LCTRL, /* E1 */ Common::KEYCODE_LSHIFT, /* E2 */ Common::KEYCODE_LALT, /* E3 */ Common::KEYCODE_INVALID, - /* E4 */ Common::KEYCODE_RCTRL, + /* E4 */ Common::KEYCODE_RCTRL, /* E5 */ Common::KEYCODE_RSHIFT, /* E6 */ Common::KEYCODE_RALT, /* E7 */ Common::KEYCODE_INVALID, @@ -509,39 +509,39 @@ const Common::KeyCode Ps2Input::_usbToSdlk[0x100] = { }; const Common::KeyCode Ps2Input::_padCodes[16] = { - Common::KEYCODE_1, // Select - Common::KEYCODE_INVALID, // L3 - Common::KEYCODE_INVALID, // R3 - Common::KEYCODE_F5, // Start - Common::KEYCODE_INVALID, // Up - Common::KEYCODE_INVALID, // Right - Common::KEYCODE_INVALID, // Down - Common::KEYCODE_INVALID, // Left - Common::KEYCODE_KP0, // L2 - Common::KEYCODE_PERIOD, // R2 - Common::KEYCODE_n, // L1 - Common::KEYCODE_y, // R1 - Common::KEYCODE_ESCAPE, // Triangle - Common::KEYCODE_INVALID, // Circle => Right mouse button - Common::KEYCODE_INVALID, // Cross => Left mouse button - Common::KEYCODE_RETURN // Square + Common::KEYCODE_1, // Select + Common::KEYCODE_INVALID, // L3 + Common::KEYCODE_INVALID, // R3 + Common::KEYCODE_F5, // Start + Common::KEYCODE_INVALID, // Up + Common::KEYCODE_INVALID, // Right + Common::KEYCODE_INVALID, // Down + Common::KEYCODE_INVALID, // Left + Common::KEYCODE_KP0, // L2 + Common::KEYCODE_PERIOD, // R2 + Common::KEYCODE_n, // L1 + Common::KEYCODE_y, // R1 + Common::KEYCODE_ESCAPE, // Triangle + Common::KEYCODE_INVALID, // Circle => Right mouse button + Common::KEYCODE_INVALID, // Cross => Left mouse button + Common::KEYCODE_RETURN // Square }; const Common::KeyCode Ps2Input::_padFlags[16] = { - Common::KEYCODE_INVALID, // Select - Common::KEYCODE_INVALID, // L3 - Common::KEYCODE_INVALID, // R3 - Common::KEYCODE_INVALID, // Start - Common::KEYCODE_INVALID, // Up - Common::KEYCODE_INVALID, // Right - Common::KEYCODE_INVALID, // Down - Common::KEYCODE_INVALID, // Left - Common::KEYCODE_INVALID, // L2 - Common::KEYCODE_INVALID, // R2 - Common::KEYCODE_INVALID, // L1 - Common::KEYCODE_INVALID, // R1 - Common::KEYCODE_INVALID, // Triangle - Common::KEYCODE_INVALID, // Circle - Common::KEYCODE_INVALID, // Cross - Common::KEYCODE_INVALID // Square + Common::KEYCODE_INVALID, // Select + Common::KEYCODE_INVALID, // L3 + Common::KEYCODE_INVALID, // R3 + Common::KEYCODE_INVALID, // Start + Common::KEYCODE_INVALID, // Up + Common::KEYCODE_INVALID, // Right + Common::KEYCODE_INVALID, // Down + Common::KEYCODE_INVALID, // Left + Common::KEYCODE_INVALID, // L2 + Common::KEYCODE_INVALID, // R2 + Common::KEYCODE_INVALID, // L1 + Common::KEYCODE_INVALID, // R1 + Common::KEYCODE_INVALID, // Triangle + Common::KEYCODE_INVALID, // Circle + Common::KEYCODE_INVALID, // Cross + Common::KEYCODE_INVALID // Square }; diff --git a/backends/platform/ps2/ps2input.h b/backends/platform/ps2/ps2input.h index 7055b64f4e..af413d262c 100644 --- a/backends/platform/ps2/ps2input.h +++ b/backends/platform/ps2/ps2input.h @@ -44,7 +44,7 @@ private: int mapKey(int key, int mod); bool getKeyEvent(Common::Event *event, uint16 buttonCode, bool down); OSystem_PS2 *_system; - Ps2Pad *_pad; + Ps2Pad *_pad; uint16 _minx, _maxx, _miny, _maxy; diff --git a/backends/platform/ps2/ps2pad.cpp b/backends/platform/ps2/ps2pad.cpp index b59547baca..d990690331 100644 --- a/backends/platform/ps2/ps2pad.cpp +++ b/backends/platform/ps2/ps2pad.cpp @@ -34,7 +34,7 @@ Ps2Pad::Ps2Pad(OSystem_PS2 *system) { _padStatus = STAT_NONE; padInit(0); // initialize library - _port = _slot = 0; // first controller, no multitap + _port = _slot = 0; // first controller, no multitap initPad(); } @@ -51,9 +51,6 @@ void Ps2Pad::initPad(void) { } else { if (checkPadReady(_port, _slot)) { switch (_padStatus) { - case STAT_NONE: - printf("Pad Status is None. Shouldn't happen\n"); - break; case STAT_OPEN: _padStatus = STAT_DETECT; break; @@ -104,7 +101,8 @@ void Ps2Pad::initPad(void) { _padStatus = STAT_OKAY; break; case STAT_OKAY: - // pad is already initialized + case STAT_NONE: + // pad is already initialized (or not there) break; } } else { diff --git a/backends/platform/ps2/ps2time.cpp b/backends/platform/ps2/ps2time.cpp index 647cf0b661..e072ce9483 100644 --- a/backends/platform/ps2/ps2time.cpp +++ b/backends/platform/ps2/ps2time.cpp @@ -30,9 +30,9 @@ #define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF)) -static int g_timeSecs; -static int g_day, g_month, g_year; -static int g_lastTimeCheck; +static int g_timeSecs; +static int g_day, g_month, g_year; +static int g_lastTimeCheck; extern volatile uint32 msecCount; void buildNewDate(int dayDiff) { diff --git a/backends/platform/ps2/rpckbd.c b/backends/platform/ps2/rpckbd.c index 0bb45208f5..e7975ab484 100644 --- a/backends/platform/ps2/rpckbd.c +++ b/backends/platform/ps2/rpckbd.c @@ -17,7 +17,7 @@ #include <string.h> #include "backends/platform/ps2/rpckbd.h" -static int curr_readmode = PS2KBD_READMODE_NORMAL; +static unsigned int curr_readmode = PS2KBD_READMODE_NORMAL; static int kbdRpcSema = -1; static int kbdInitialized = 0; diff --git a/backends/platform/ps2/savefilemgr.cpp b/backends/platform/ps2/savefilemgr.cpp index de03e76892..4fd2b1c72b 100644 --- a/backends/platform/ps2/savefilemgr.cpp +++ b/backends/platform/ps2/savefilemgr.cpp @@ -21,8 +21,6 @@ */ #define FORBIDDEN_SYMBOL_EXCEPTION_printf -#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir -#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h #include "common/config-manager.h" #include "common/zlib.h" @@ -37,6 +35,7 @@ #include "savefilemgr.h" #include "Gs2dScreen.h" #include "ps2temp.h" +#include "ps2debug.h" extern AsyncFio fio; @@ -57,20 +56,20 @@ bool Ps2SaveFileManager::mcCheck(const char *path) { // int res; - printf("mcCheck\n"); + dbg_printf("mcCheck\n"); if (!dir.exists()) { - printf("! exist -> create : "); + dbg_printf("! exist -> create : "); #ifdef __USE_LIBMC__ - printf("%s\n", path+4); + dbg_printf("%s\n", path+4); // WaitSema(_sema); mcSync(0, NULL, NULL); mcMkDir(0 /*port*/, 0 /*slot*/, path+4); mcSync(0, NULL, &res); - printf("sync : %d\n", res); + dbg_printf("sync : %d\n", res); // SignalSema(_sema); #else - printf("%s\n", path); + dbg_printf("%s\n", path); fio.mkdir(path); #endif } @@ -108,7 +107,7 @@ Common::InSaveFile *Ps2SaveFileManager::openForLoading(const Common::String &fil } else { char temp[32]; - printf("MC : filename = %s\n", filename.c_str()); + dbg_printf("MC : filename = %s\n", filename.c_str()); strcpy(temp, filename.c_str()); // mcSplit(temp, game, ext); @@ -149,7 +148,7 @@ Common::OutSaveFile *Ps2SaveFileManager::openForSaving(const Common::String &fil Common::FSNode savePath(ConfMan.get("savepath")); // TODO: is this fast? Common::WriteStream *sf; - printf("openForSaving : %s\n", filename.c_str()); + dbg_printf("openForSaving : %s\n", filename.c_str()); if (!savePath.exists() || !savePath.isDirectory()) return NULL; @@ -166,10 +165,10 @@ Common::OutSaveFile *Ps2SaveFileManager::openForSaving(const Common::String &fil sprintf(path, "mc0:ScummVM/indy4/iq-points"); } // FIXME : hack for bs1 saved games - else if (filename == "SAVEGAME.INF") { - mcCheck("mc0:ScummVM/sword1"); - sprintf(path, "mc0:ScummVM/sword1/SAVEGAME.INF"); - } + else if (filename == "SAVEGAME.INF") { + mcCheck("mc0:ScummVM/sword1"); + sprintf(path, "mc0:ScummVM/sword1/SAVEGAME.INF"); + } else { char temp[32]; strcpy(temp, filename.c_str()); @@ -240,7 +239,7 @@ Common::StringArray Ps2SaveFileManager::listSavefiles(const Common::String &patt if (!savePath.exists() || !savePath.isDirectory()) return Common::StringArray(); - printf("listSavefiles = %s\n", pattern.c_str()); + dbg_printf("listSavefiles = %s\n", pattern.c_str()); if (_mc) { strcpy(temp, pattern.c_str()); @@ -263,7 +262,7 @@ Common::StringArray Ps2SaveFileManager::listSavefiles(const Common::String &patt Common::ArchiveMemberList savefiles; Common::StringArray results; - printf("dir = %s --- reg = %s\n", _dir.c_str(), search.c_str()); + dbg_printf("dir = %s --- reg = %s\n", _dir.c_str(), search.c_str()); if (dir.listMatchingMembers(savefiles, search) > 0) { for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) { @@ -272,11 +271,11 @@ Common::StringArray Ps2SaveFileManager::listSavefiles(const Common::String &patt temp[3] = '\0'; sprintf(path, "%s.%s", game, temp); results.push_back(path); - printf(" --> found = %s -> %s\n", (*file)->getName().c_str(), path); + dbg_printf(" --> found = %s -> %s\n", (*file)->getName().c_str(), path); } else { results.push_back((*file)->getName()); - printf(" --> found = %s\n", (*file)->getName().c_str()); + dbg_printf(" --> found = %s\n", (*file)->getName().c_str()); } } } diff --git a/backends/platform/ps2/sysdefs.h b/backends/platform/ps2/sysdefs.h index 0b0d286189..c886d70eef 100644 --- a/backends/platform/ps2/sysdefs.h +++ b/backends/platform/ps2/sysdefs.h @@ -40,30 +40,30 @@ enum Interrupts { }; // dma 2 registers -#define D2_CHCR (*(volatile uint32*)0x1000A000) -#define D2_QWC (*(volatile uint32*)0x1000A020) -#define D2_TADR (*(volatile uint32*)0x1000A030) -#define D2_MADR (*(volatile uint32*)0x1000A010) -#define D2_ASR1 (*(volatile uint32*)0x1000A050) -#define D2_ASR0 (*(volatile uint32*)0x1000A040) +#define D2_CHCR (*(volatile uint32 *)0x1000A000) +#define D2_QWC (*(volatile uint32 *)0x1000A020) +#define D2_TADR (*(volatile uint32 *)0x1000A030) +#define D2_MADR (*(volatile uint32 *)0x1000A010) +#define D2_ASR1 (*(volatile uint32 *)0x1000A050) +#define D2_ASR0 (*(volatile uint32 *)0x1000A040) -#define D_CTRL (*(volatile uint32*)0x1000E000) -#define D_STAT (*(volatile uint32*)0x1000E010) -#define D_PCR (*(volatile uint32*)0x1000E020) -#define D_SQWC (*(volatile uint32*)0x1000E030) -#define D_RBSR (*(volatile uint32*)0x1000E040) -#define D_RBOR (*(volatile uint32*)0x1000E050) -#define D_STADR (*(volatile uint32*)0x1000E060) +#define D_CTRL (*(volatile uint32 *)0x1000E000) +#define D_STAT (*(volatile uint32 *)0x1000E010) +#define D_PCR (*(volatile uint32 *)0x1000E020) +#define D_SQWC (*(volatile uint32 *)0x1000E030) +#define D_RBSR (*(volatile uint32 *)0x1000E040) +#define D_RBOR (*(volatile uint32 *)0x1000E050) +#define D_STADR (*(volatile uint32 *)0x1000E060) #define CIM2 (1 << 18) #define CIS2 (1 << 2) // timer 0 registers -#define T0_COUNT (*(volatile uint32*)0x10000000) -#define T0_MODE (*(volatile uint32*)0x10000010) -#define T0_COMP (*(volatile uint32*)0x10000020) -#define T0_HOLD (*(volatile uint32*)0x10000030) +#define T0_COUNT (*(volatile uint32 *)0x10000000) +#define T0_MODE (*(volatile uint32 *)0x10000010) +#define T0_COMP (*(volatile uint32 *)0x10000020) +#define T0_HOLD (*(volatile uint32 *)0x10000030) #define TIMER_MODE(clks, gate, gates, gatem, zeroret, cue, cmpe, ovfe, equf, ovff) \ ((clks) | ((gate) << 2) | ((gates) << 3) | ((gatem) << 4) | ((zeroret) << 6) | \ diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index feee73cba7..1aa74b7d9b 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -20,8 +20,9 @@ * */ -// Disable symbol overrides so that we can use system headers. -#define FORBIDDEN_SYMBOL_ALLOW_ALL +// Disable symbol overrides so that we can use "FILE" +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE +#define FORBIDDEN_SYMBOL_EXCEPTION_printf #include <kernel.h> #include <stdio.h> @@ -50,7 +51,6 @@ #include "backends/platform/ps2/cd.h" #include "backends/platform/ps2/fileio.h" #include "backends/platform/ps2/Gs2dScreen.h" -#include "backends/platform/ps2/irxboot.h" #include "backends/platform/ps2/ps2debug.h" #include "backends/platform/ps2/ps2input.h" #include "backends/platform/ps2/savefilemgr.h" @@ -112,7 +112,11 @@ extern "C" int scummvm_main(int argc, char *argv[]); extern "C" int main(int argc, char *argv[]) { SifInitRpc(0); + #ifdef __NEW_PS2SDK__ + ee_thread_status_t thisThread; + #else ee_thread_t thisThread; + #endif int tid = GetThreadId(); ReferThreadStatus(tid, &thisThread); @@ -147,6 +151,10 @@ extern "C" int main(int argc, char *argv[]) { g_systemPs2->quit(); +#ifdef ENABLE_PROFILING + // make sure we can flush "gmon.out" + fileXioSetBlockMode(FXIO_WAIT); +#endif // control never gets here return res; } @@ -184,13 +192,11 @@ void systemSoundThread(OSystem_PS2 *system) { } void gluePowerOffCallback(void *system) { - ((OSystem_PS2*)system)->powerOffCallback(); + ((OSystem_PS2 *)system)->powerOffCallback(); } void OSystem_PS2::startIrxModules(int numModules, IrxReference *modules) { - _usbMassLoaded = _useMouse = _useKbd = _useHdd = _useNet = false; - int res = 0, rv = 0; for (int i = 0; i < numModules; i++) { if (modules[i].loc == IRX_FILE) { @@ -216,6 +222,9 @@ void OSystem_PS2::startIrxModules(int numModules, IrxReference *modules) { case KBD_DRIVER: _useKbd = true; break; + case CD_DRIVER: + _useCd = true; + break; case HDD_DRIVER: _useHdd = true; break; @@ -241,20 +250,79 @@ void OSystem_PS2::startIrxModules(int numModules, IrxReference *modules) { } if (modules[i].buffer) - free(modules[i].buffer); + ; // free(modules[i].buffer); } else { sioprintf("module %d of %d damaged, loc %d, path %s\n", i, numModules, modules[i].loc, modules[i].path); } - free(modules[i].path); + // free(modules[i].path); } - free(modules); + // free(modules); sioprintf("done\n"); sioprintf("UsbMass: %sloaded\n", _usbMassLoaded ? "" : "not "); sioprintf("Mouse: %sloaded\n", _useMouse ? "" : "not "); sioprintf("Kbd: %sloaded\n", _useKbd ? "" : "not "); + sioprintf("Cd: %sloaded\n", _useCd ? "" : "not "); sioprintf("Hdd: %sloaded\n", _useHdd ? "" : "not "); } +bool OSystem_PS2::loadDrivers(IrxType type) +{ + IrxReference *modules; + int numModules; + int res; + + numModules = loadIrxModules(_bootDevice, _bootPath, &modules, type); + // TODO: for IRX_NET allows override IP addr + startIrxModules(numModules, modules); + + switch (type) { + case IRX_CORE: + /* Init I/O */ + if ((res = fileXioInit()) < 0) { + msgPrintf(FOREVER, "FXIO init failed: %d", res); + quit(); + } + /* Init sound */ + if ((res = SjPCM_Init(0)) < 0) { + msgPrintf(FOREVER, "SjPCM bind failed: %d\n", res); + quit(); + } + break; + + case IRX_CDROM: + /* Init CDROM & RTC Clock */ + if ((res = initCdvdFs()) < 0) { + msgPrintf(FOREVER, "CoDyVDfs bind failed: %d", res); + quit(); + } + sioprintf("Reading RTC\n"); + readRtcTime(); /* depends on CDROM driver! */ + break; + + case IRX_HDD: + /* Check HD is available and formatted */ + if ((hddCheckPresent() < 0) || (hddCheckFormatted() < 0)) { + _useHdd = false; + } + else { + poweroffInit(); + poweroffSetCallback(gluePowerOffCallback, this); + } + break; + + case IRX_NET: + if (_bootDevice == HOST_DEV) // net is pre-loaded on host + _useNet = true; // so we need to set by hand + break; + + default: + /* zzz */ + break; + } + + return true; +} + OSystem_PS2::OSystem_PS2(const char *elfPath) { _soundStack = _timerStack = NULL; _printY = 0; @@ -262,20 +330,19 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) { _systemQuit = false; _modeChanged = false; _screenChangeCount = 0; + _mouseVisible = false; - _screen = new Gs2dScreen(320, 200, TV_DONT_CARE); + // _screen = new Gs2dScreen(320, 200, TV_DONT_CARE); // moved to ::initSize sioprintf("Initializing system...\n"); - _screen->wantAnim(true); + // _screen->wantAnim(true); - _bootPath = (char *)malloc(128); + _bootPath = (char *)memalign(64, 128); _bootDevice = detectBootPath(elfPath, _bootPath); - IrxReference *modules; - int numModules = loadIrxModules(_bootDevice, _bootPath, &modules); - if (_bootDevice != HOST_DEV) { + // TODO: reset funx sioprintf("Resetting IOP.\n"); cdvdInit(CDVD_EXIT); cdvdExit(); @@ -298,50 +365,12 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) { // TODO: ps2link 1.46 will stall on "poweroff" init / cb } - startIrxModules(numModules, modules); - - int res; - if ((res = fileXioInit()) < 0) { - msgPrintf(FOREVER, "FXIO Init failed: %d", res); - quit(); - } + _usbMassLoaded = _useMouse = _useKbd = _useCd = _useHdd = _useNet = false; - if ((res = initCdvdFs()) < 0) { - msgPrintf(FOREVER, "CoDyVDfs bind failed: %d", res); - quit(); - } - - if ((res = SjPCM_Init(0)) < 0) { - msgPrintf(FOREVER, "SjPCM Bind failed: %d\n", res); - quit(); - } - - if (_useHdd) { - if ((hddCheckPresent() < 0) || (hddCheckFormatted() < 0)) - _useHdd = false; - - //hddPreparePoweroff(); - poweroffInit(); - - //hddSetUserPoweroffCallback(gluePowerOffCallback, this); - poweroffSetCallback(gluePowerOffCallback, this); - } + loadDrivers(IRX_CORE); + loadDrivers(IRX_CDROM); // consider CDROM as "core", as RTC depends on it fileXioSetBlockMode(FXIO_NOWAIT); - - _mouseVisible = false; - - sioprintf("reading RTC\n"); - readRtcTime(); - - if (_useHdd) { - // TODO : make partition path configurable - if (fio.mount("pfs0:", "hdd0:+ScummVM", 0) >= 0) - printf("Successfully mounted!\n"); - else - _useHdd = false; - } - initMutexes(); } @@ -356,14 +385,67 @@ void OSystem_PS2::init(void) { sioprintf("Starting SavefileManager\n"); _savefileManager = new Ps2SaveFileManager(this, _screen); - sioprintf("Initializing ps2Input\n"); - _input = new Ps2Input(this, _useMouse, _useKbd); - prepMC(); makeConfigPath(); - _screen->wantAnim(false); - fillScreen(0); + // _screen->wantAnim(false); + // fillScreen(0); +} + +void OSystem_PS2::config(void) { + #ifndef NO_ADAPTOR + if (ConfMan.hasKey("hdd_part", "PlayStation2")) { // "hdd" ? + const char *hdd = ConfMan.get("hdd_part", "PlayStation2").c_str(); + + if ( !strcmp(hdd, "0") || !strcmp(hdd, "no") || !strcmp(hdd, "disable") ) { + _useHdd = false; + } + else { + loadDrivers(IRX_HDD); + hddMount(hdd); + } + } + else { // check for HDD and assume partition is +ScummVM + loadDrivers(IRX_HDD); + hddMount("ScummVM"); + } + + if (ConfMan.hasKey("net_addr", "PlayStation2")) { // "net" ? + const char *net = ConfMan.get("net_addr", "PlayStation2").c_str(); + + if ( !strcmp(net, "0") || !strcmp(net, "no") || !strcmp(net, "disable") ) { + _useNet = false; + } + else { + loadDrivers(IRX_NET); + // TODO: netInit("xxx.xxx.xxx.xxx"); + } + } + else { // setup net - IP hardcoded 192.168.1.20 + loadDrivers(IRX_NET); + } + #endif + + // why USB drivers only load correctly post HDD ? + if (ConfMan.hasKey("usb_mass", "PlayStation2")) { // "usb" ? + const char *usb = ConfMan.get("usb_mass", "PlayStation2").c_str(); + + if ( !strcmp(usb, "0") || !strcmp(usb, "no") || !strcmp(usb, "disable") ) { + _usbMassLoaded = false; + } + else { + loadDrivers(IRX_USB); + loadDrivers(IRX_INPUT); + sioprintf("Initializing ps2Input\n"); + _input = new Ps2Input(this, _useMouse, _useKbd); + } + } + else { // load USB drivers (mass & input( + loadDrivers(IRX_USB); + loadDrivers(IRX_INPUT); + sioprintf("Initializing ps2Input\n"); + _input = new Ps2Input(this, _useMouse, _useKbd); + } } OSystem_PS2::~OSystem_PS2(void) { @@ -380,26 +462,40 @@ void OSystem_PS2::initTimer(void) { g_TimerThreadSema = CreateSema(&threadSema); g_SoundThreadSema = CreateSema(&threadSema); assert((g_TimerThreadSema >= 0) && (g_SoundThreadSema >= 0)); - + #ifdef __NEW_PS2SDK__ + ee_thread_t timerThread, soundThread; + ee_thread_status_t thisThread; + #else ee_thread_t timerThread, soundThread, thisThread; + #endif ReferThreadStatus(GetThreadId(), &thisThread); - _timerStack = (uint8 *)malloc(TIMER_STACK_SIZE); - _soundStack = (uint8 *)malloc(SOUND_STACK_SIZE); + _timerStack = (uint8 *)memalign(64, TIMER_STACK_SIZE); + _soundStack = (uint8 *)memalign(64, SOUND_STACK_SIZE); + // gprof doesn't cope with higher thread priority too well + #ifdef ENABLE_PROFILING + timerThread.initial_priority = thisThread.current_priority; + #else // give timer thread a higher priority than main thread timerThread.initial_priority = thisThread.current_priority - 1; + #endif timerThread.stack = _timerStack; timerThread.stack_size = TIMER_STACK_SIZE; timerThread.func = (void *)systemTimerThread; - timerThread.gp_reg = &_gp; + timerThread.gp_reg = &_gp; + // gprof doesn't cope with higher thread priority too well + #ifdef ENABLE_PROFILING + soundThread.initial_priority = thisThread.current_priority; + #else // soundthread's priority is higher than main- and timerthread soundThread.initial_priority = thisThread.current_priority - 2; + #endif soundThread.stack = _soundStack; soundThread.stack_size = SOUND_STACK_SIZE; soundThread.func = (void *)systemSoundThread; - soundThread.gp_reg = &_gp; + soundThread.gp_reg = &_gp; _timerTid = CreateThread(&timerThread); _soundTid = CreateThread(&soundThread); @@ -459,39 +555,39 @@ void OSystem_PS2::soundThreadCallback(void) { // demux data into 2 buffers, L and R __asm__ ( - "move $t2, %1\n\t" // dest buffer right - "move $t3, %0\n\t" // dest buffer left - "lui $t8, 0x7000\n\t" // muxed buffer, fixed at 0x70000000 - "addiu $t9, $0, 100\n\t" // number of loops - "mtsab $0, 2\n\t" // set qword shift = 2 byte + "move $t2, %1\n\t" // dest buffer right + "move $t3, %0\n\t" // dest buffer left + "lui $t8, 0x7000\n\t" // muxed buffer, fixed at 0x70000000 + "addiu $t9, $0, 100\n\t" // number of loops + "mtsab $0, 2\n\t" // set qword shift = 2 byte "loop:\n\t" - " lq $t4, 0($t8)\n\t" // load 8 muxed samples - " lq $t5, 16($t8)\n\t" // load 8 more muxed samples + " lq $t4, 0($t8)\n\t" // load 8 muxed samples + " lq $t5, 16($t8)\n\t" // load 8 more muxed samples - " qfsrv $t6, $0, $t4\n\t" // shift right for second - " qfsrv $t7, $0, $t5\n\t" // packing step (right channel) + " qfsrv $t6, $0, $t4\n\t" // shift right for second + " qfsrv $t7, $0, $t5\n\t" // packing step (right channel) - " ppach $t4, $t5, $t4\n\t" // combine left channel data - " ppach $t6, $t7, $t6\n\t" // right channel data + " ppach $t4, $t5, $t4\n\t" // combine left channel data + " ppach $t6, $t7, $t6\n\t" // right channel data - " sq $t4, 0($t3)\n\t" // write back - " sq $t6, 0($t2)\n\t" // + " sq $t4, 0($t3)\n\t" // write back + " sq $t6, 0($t2)\n\t" // - " addiu $t9, -1\n\t" // decrement loop counter - " addiu $t2, 16\n\t" // increment pointers + " addiu $t9, -1\n\t" // decrement loop counter + " addiu $t2, 16\n\t" // increment pointers " addiu $t3, 16\n\t" " addiu $t8, 32\n\t" - " bnez $t9, loop\n\t" // loop + " bnez $t9, loop\n\t" // loop : // outputs : "r"(soundBufL), "r"(soundBufR) // inputs - // : "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "$t9" // destroyed + // : "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "$t9" // destroyed : "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25" // destroyed ); // and feed it into the SPU // non-blocking call, the function will return before the buffer's content // was transferred. - SjPCM_Enqueue((short int*)soundBufL, (short int*)soundBufR, SMP_PER_BLOCK, 0); + SjPCM_Enqueue((short int *)soundBufL, (short int *)soundBufR, SMP_PER_BLOCK, 0); bufferedSamples += SMP_PER_BLOCK; } } @@ -510,6 +606,10 @@ bool OSystem_PS2::mcPresent(void) { return false; } +bool OSystem_PS2::cdPresent(void) { + return _useCd; +} + bool OSystem_PS2::hddPresent(void) { return _useHdd; } @@ -528,11 +628,39 @@ bool OSystem_PS2::usbMassPresent(void) { } bool OSystem_PS2::netPresent(void) { - return _useNet; + if (_useNet) + return true; + + return false; +} + +bool OSystem_PS2::hddMount(const char *partition) { + char name[64] = "hdd0:+ScummVM"; + + if (partition) + strcpy(name+6, partition); + + if (fio.mount("pfs0:", name, 0) >= 0) { + dbg_printf("Successfully mounted (%s)!\n", name); + return true; + } + else { + dbg_printf("Failed to mount (%s).\n", name); + _useHdd = false; + return false; + } } void OSystem_PS2::initSize(uint width, uint height, const Graphics::PixelFormat *format) { - printf("initializing new size: (%d/%d)...", width, height); + dbg_printf("initializing new size: (%d/%d)...", width, height); + + /* ugly hack: we know we can parse ScummVM.ini now */ + if (!_screenChangeCount) { // first round + config(); + _screen = new Gs2dScreen(width, height); + fillScreen(0); + } + _screen->newScreenSize(width, height); _screen->setMouseXy(width / 2, height / 2); _input->newRange(0, 0, width - 1, height - 1); @@ -543,7 +671,7 @@ void OSystem_PS2::initSize(uint width, uint height, const Graphics::PixelFormat _modeChanged = true; _screenChangeCount++; - printf("done\n"); + dbg_printf("done\n"); } void OSystem_PS2::setPalette(const byte *colors, uint start, uint num) { @@ -555,7 +683,7 @@ void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) { } void OSystem_PS2::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) { - _screen->copyScreenRect((const uint8*)buf, pitch, x, y, w, h); + _screen->copyScreenRect((const uint8 *)buf, pitch, x, y, w, h); } void OSystem_PS2::updateScreen(void) { @@ -568,7 +696,7 @@ void OSystem_PS2::updateScreen(void) { void OSystem_PS2::displayMessageOnOSD(const char *msg) { /* TODO : check */ - printf("displayMessageOnOSD: %s\n", msg); + dbg_printf("displayMessageOnOSD: %s\n", msg); } uint32 OSystem_PS2::getMillis(bool skipRecord) { @@ -666,7 +794,7 @@ void OSystem_PS2::unlockScreen(void) { const OSystem::GraphicsMode OSystem_PS2::_graphicsMode = { NULL, NULL, 0 }; const OSystem::GraphicsMode *OSystem_PS2::getSupportedGraphicsModes(void) const { - return &_graphicsMode; + return &_graphicsMode; } bool OSystem_PS2::setGraphicsMode(int mode) { @@ -735,7 +863,7 @@ void OSystem_PS2::msgPrintf(int millis, const char *format, ...) { Graphics::g_sysfont.drawString(&surf, str, posX, posY, 300 - posX, 1); posY += 14; - lnSta = lnEnd + 1; + lnSta = lnEnd + 1; } uint8 *scrBuf = (uint8 *)memalign(64, 320 * 200); @@ -768,12 +896,14 @@ void OSystem_PS2::powerOffCallback(void) { } void OSystem_PS2::quit(void) { - printf("OSystem_PS2::quit called\n"); + dbg_printf("OSystem_PS2::quit called\n"); if (_bootDevice == HOST_DEV) { - printf("OSystem_PS2::quit (HOST)\n"); + dbg_printf("OSystem_PS2::quit (HOST)\n"); + #ifndef ENABLE_PROFILING SleepThread(); + #endif } else { - printf("OSystem_PS2::quit (bootdev=%d)\n", _bootDevice); + dbg_printf("OSystem_PS2::quit (bootdev=%d)\n", _bootDevice); if (_useHdd) { driveStandby(); fio.umount("pfs0:"); @@ -781,18 +911,22 @@ void OSystem_PS2::quit(void) { //setTimerCallback(NULL, 0); _screen->wantAnim(false); _systemQuit = true; + #ifdef __NEW_PS2SDK__ + ee_thread_status_t statSound, statTimer; + #else ee_thread_t statSound, statTimer; - printf("Waiting for timer and sound thread to end\n"); + #endif + dbg_printf("Waiting for timer and sound thread to end\n"); do { // wait until both threads called ExitThread() ReferThreadStatus(_timerTid, &statTimer); ReferThreadStatus(_soundTid, &statSound); } while ((statSound.status != 0x10) || (statTimer.status != 0x10)); - printf("Done\n"); + dbg_printf("Done\n"); DeleteThread(_timerTid); DeleteThread(_soundTid); free(_timerStack); free(_soundStack); - printf("Stopping timer\n"); + dbg_printf("Stopping timer\n"); DisableIntc(INT_TIMER0); RemoveIntcHandler(INT_TIMER0, _intrId); @@ -801,7 +935,7 @@ void OSystem_PS2::quit(void) { padEnd(); // stop pad library cdvdInit(CDVD_EXIT); - printf("resetting iop\n"); + dbg_printf("resetting iop\n"); SifIopReset(NULL, 0); SifExitRpc(); while (!SifIopSync()); @@ -829,7 +963,7 @@ void OSystem_PS2::quit(void) { " li $3, 0x04;" " syscall;" " nop;" - ); + ); */ /* @@ -839,7 +973,7 @@ void OSystem_PS2::quit(void) { */ #else // reset + load ELF from CD - printf("Restarting ScummVM\n"); + dbg_printf("Restarting ScummVM\n"); LoadExecPS2("cdrom0:\\SCUMMVM.ELF", 0, NULL); #endif } @@ -856,12 +990,12 @@ bool OSystem_PS2::prepMC() { if (!mcPresent()) return prep; - printf("prepMC 0\n"); + dbg_printf("prepMC 0\n"); // Common::String str("mc0:ScummVM/") // Common::FSNode scumDir(str); Common::FSNode scumDir("mc0:ScummVM/"); - printf("prepMC 00\n"); + dbg_printf("prepMC 00\n"); if (!scumDir.exists()) { uint16 *data, size; @@ -869,11 +1003,11 @@ bool OSystem_PS2::prepMC() { PS2Icon _ico; mcIcon icon; - printf("prepMC I\n"); + dbg_printf("prepMC I\n"); size = _ico.decompressData(&data); - printf("prepMC II\n"); + dbg_printf("prepMC II\n"); _ico.setup(&icon); @@ -888,21 +1022,21 @@ bool OSystem_PS2::prepMC() { fio.mkdir("mc0:ScummVM"); f = ps2_fopen("mc0:ScummVM/scummvm.icn", "w"); - printf("f = %p\n", (const void *)f); + dbg_printf("f = %p\n", (const void *)f); ps2_fwrite(data, size, 2, f); ps2_fclose(f); f = ps2_fopen("mc0:ScummVM/icon.sys", "w"); - printf("f = %p\n", (const void *)f); + dbg_printf("f = %p\n", (const void *)f); ps2_fwrite(&icon, sizeof(icon), 1, f); ps2_fclose(f); #endif free(data); - printf("prepMC II\n"); + dbg_printf("prepMC II\n"); prep = true; } @@ -911,7 +1045,7 @@ bool OSystem_PS2::prepMC() { } void OSystem_PS2::makeConfigPath() { - FILE *src, *dst; + FILE *src, *dst; char path[128], *buf; int32 size; @@ -926,7 +1060,7 @@ void OSystem_PS2::makeConfigPath() { src = ps2_fopen("cdfs:ScummVM.ini", "r"); if (src) { size = ((Ps2File *)src)->size(); - buf = (char *)malloc(size); + buf = (char *)memalign(64, size); ps2_fread(buf, size, 1, src); ps2_fclose(src); @@ -970,6 +1104,5 @@ Common::String OSystem_PS2::getDefaultConfigFileName() { } void OSystem_PS2::logMessage(LogMessageType::Type type, const char *message) { - printf("%s", message); - sioprintf("%s", message); + dbg_printf("%s", message); } diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 580eb8b6f2..45b7dfae36 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -25,6 +25,7 @@ #include "common/system.h" #include "backends/base-backend.h" +#include "backends/platform/ps2/irxboot.h" #include "graphics/palette.h" class Gs2dScreen; @@ -51,6 +52,7 @@ public: virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); void init(void); + void config(void); virtual int16 getHeight(void); virtual int16 getWidth(void); @@ -119,14 +121,17 @@ public: void powerOffCallback(void); bool mcPresent(void); + bool cdPresent(void); bool hddPresent(void); bool usbMassPresent(void); bool netPresent(void); + bool hddMount(const char *partition); bool runningFromHost(void); int getBootDevice() { return _bootDevice; } private: + bool loadDrivers(IrxType type); void startIrxModules(int numModules, IrxReference *modules); void initMutexes(void); @@ -136,28 +141,28 @@ private: Audio::MixerImpl *_scummMixer; bool _mouseVisible; - bool _useMouse, _useKbd, _useHdd, _usbMassLoaded, _useNet; + bool _useMouse, _useKbd, _useCd, _useHdd, _usbMassLoaded, _useNet; - Gs2dScreen *_screen; - Ps2Input *_input; - uint16 _oldMouseX, _oldMouseY; - uint32 _msgClearTime; - uint16 _printY; + Gs2dScreen *_screen; + Ps2Input *_input; + uint16 _oldMouseX, _oldMouseY; + uint32 _msgClearTime; + uint16 _printY; bool _modeChanged; int _screenChangeCount; - int _mutexSema; - Ps2Mutex _mutex[MAX_MUTEXES]; + int _mutexSema; + Ps2Mutex _mutex[MAX_MUTEXES]; - uint8 *_timerStack, *_soundStack; - int _timerTid, _soundTid; - int _intrId; + uint8 *_timerStack, *_soundStack; + int _timerTid, _soundTid; + int _intrId; volatile bool _systemQuit; static const GraphicsMode _graphicsMode; - int _bootDevice; - char *_bootPath; - char *_configFile; + int _bootDevice; + char *_bootPath; + char *_configFile; }; #endif // SYSTEMPS2_H diff --git a/backends/platform/tizen/system.cpp b/backends/platform/tizen/system.cpp index 585eb206ea..a235456670 100644 --- a/backends/platform/tizen/system.cpp +++ b/backends/platform/tizen/system.cpp @@ -266,8 +266,8 @@ result TizenSystem::initModules() { return E_OUT_OF_MEMORY; } - _graphicsManager = (GraphicsManager *)new TizenGraphicsManager(_appForm); - if (!_graphicsManager || graphicsManager->Construct() != E_SUCCESS) { + _graphicsManager = new TizenGraphicsManager(_appForm); + if (!_graphicsManager || getGraphics()->Construct() != E_SUCCESS) { return E_OUT_OF_MEMORY; } diff --git a/backends/platform/tizen/system.h b/backends/platform/tizen/system.h index 1974055088..3f668baf34 100644 --- a/backends/platform/tizen/system.h +++ b/backends/platform/tizen/system.h @@ -73,7 +73,7 @@ public: bool isClosing() { return _appForm->isClosing(); } TizenGraphicsManager *getGraphics() { - return (TizenGraphicsManager *)_graphicsManager; + return dynamic_cast<TizenGraphicsManager *>(_graphicsManager); } private: diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index 001cfea31e..bb91242f98 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -717,8 +717,8 @@ void OSystem_Wii::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, u16 *d = (u16 *) tmp; for (u16 y = 0; y < h; ++y) { for (u16 x = 0; x < w; ++x) { - if (*s++ != _mouseKeyColor) - *d++ |= 7 << 12; + if (*s++ == _mouseKeyColor) + *d++ &= ~(7 << 12); else d++; } diff --git a/backends/plugins/elf/version.cpp b/backends/plugins/elf/version.cpp index 48e6acd58d..ac999e1d7c 100644 --- a/backends/plugins/elf/version.cpp +++ b/backends/plugins/elf/version.cpp @@ -23,6 +23,10 @@ #include "backends/plugins/elf/version.h" #ifdef USE_ELF_LOADER -const char *gScummVMPluginBuildDate __attribute__((visibility("hidden"))) = - __DATE__ " " __TIME__ ; + #ifdef __PLAYSTATION2__ + const char *gScummVMPluginBuildDate = "Git Master"; /* ScummVM Git Master */ + #else + const char *gScummVMPluginBuildDate __attribute__((visibility("hidden"))) = + __DATE__ " " __TIME__ ; + #endif #endif diff --git a/base/version.cpp b/base/version.cpp index 999e90a275..fba3554f67 100644 --- a/base/version.cpp +++ b/base/version.cpp @@ -56,9 +56,15 @@ * to properly work in exports (i.e. release tar balls etc.). */ const char *gScummVMVersion = SCUMMVM_VERSION; +#ifdef __PLAYSTATION2__ +const char *gScummVMBuildDate = "Git Master"; /* ScummVM Git Master */ +const char *gScummVMVersionDate = SCUMMVM_VERSION " - PlayStation2"; +const char *gScummVMFullVersion = "ScummVM " SCUMMVM_VERSION " - PlayStation2"; +#else const char *gScummVMBuildDate = __DATE__ " " __TIME__; const char *gScummVMVersionDate = SCUMMVM_VERSION " (" __DATE__ " " __TIME__ ")"; const char *gScummVMFullVersion = "ScummVM " SCUMMVM_VERSION " (" __DATE__ " " __TIME__ ")"; +#endif const char *gScummVMFeatures = "" #ifdef TAINTED_BUILD // TAINTED means the build contains engines/subengines not enabled by default diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp index 84774742c6..30896d7514 100644 --- a/common/EventMapper.cpp +++ b/common/EventMapper.cpp @@ -37,11 +37,17 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { #ifdef ENABLE_VKEYBD else if (ev.kbd.keycode == KEYCODE_F7 && ev.kbd.hasFlags(0)) { mappedEvent.type = EVENT_VIRTUAL_KEYBOARD; + + // Avoid blocking F7 events from engine. + addDelayedEvent(100, ev); } #endif #ifdef ENABLE_KEYMAPPER else if (ev.kbd.keycode == KEYCODE_F8 && ev.kbd.hasFlags(0)) { mappedEvent.type = EVENT_KEYMAPPER_REMAP; + + // Avoid blocking F8 events from engine. + addDelayedEvent(100, ev); } #endif } diff --git a/common/scummsys.h b/common/scummsys.h index 1342b0cde6..c30bc4a52a 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -405,8 +405,13 @@ typedef unsigned int uint32; typedef signed int int32; typedef unsigned int uint; + #ifdef __PLAYSTATION2__ + typedef signed long int64; + typedef unsigned long uint64; + #else typedef signed long long int64; typedef unsigned long long uint64; + #endif #endif diff --git a/common/zlib.cpp b/common/zlib.cpp index 448e1eadd5..c22ea1e660 100644 --- a/common/zlib.cpp +++ b/common/zlib.cpp @@ -27,6 +27,7 @@ #include "common/ptr.h" #include "common/util.h" #include "common/stream.h" +#include "common/debug.h" #include "common/textconsole.h" #if defined(USE_ZLIB) @@ -140,6 +141,10 @@ bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcL return true; } +#ifndef RELEASE_BUILD +static bool _shownBackwardSeekingWarning = false; +#endif + /** * A simple wrapper class which can be used to wrap around an arbitrary * other SeekableReadStream and will then provide on-the-fly decompression support. @@ -159,11 +164,10 @@ protected: uint32 _pos; uint32 _origSize; bool _eos; - bool _shownBackwardSeekingWarning; public: - GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream(), _shownBackwardSeekingWarning(false) { + GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() { assert(w != 0); // Verify file header is correct @@ -263,13 +267,15 @@ public: // from the start of the file. A rather wasteful operation, best // to avoid it. :/ +#ifndef RELEASE_BUILD if (!_shownBackwardSeekingWarning) { // We only throw this warning once per stream, to avoid // getting the console swarmed with warnings when consecutive // seeks are made. - warning("Backward seeking in GZipReadStream detected"); + debug(1, "Backward seeking in GZipReadStream detected"); _shownBackwardSeekingWarning = true; } +#endif _pos = 0; _wrapped->seek(0, SEEK_SET); @@ -967,6 +967,7 @@ Optional Libraries: --with-freetype2-prefix=DIR Prefix where the freetype-config script is installed (optional) + --disable-freetype2 disable freetype2 TTF library usage [autodetect] --with-nasm-prefix=DIR Prefix where nasm executable is installed (optional) --disable-nasm disable assembly language optimizations [autodetect] @@ -1390,6 +1391,9 @@ ps2) _host_os=ps2 _host_cpu=mips64r5900el _host_alias=ee + # PS2 bogus dirs: they actually depend on launch medium + datadir='host:data' + docdir='host:docs' ;; ps3) _host_os=ps3 @@ -2058,6 +2062,8 @@ case $_host_os in # We have to use 'long' for our 4 byte typedef because AmigaOS already typedefs (u)int32 # as (unsigned) long, and consequently we'd get a compiler error otherwise. type_4_byte='long' + # Supress format warnings as the long 4 byte causes noisy warnings. + CXXFLAGS="$CXXFLAGS -Wno-format" add_line_to_config_mk 'AMIGAOS = 1' ;; android) @@ -2310,6 +2316,7 @@ case $_host_os in CXXFLAGS="$CXXFLAGS -G2" DEFINES="$DEFINES -D_EE" DEFINES="$DEFINES -D__PLAYSTATION2__" + DEFINES="$DEFINES -D__NEW_PS2SDK__" ;; ps3) # Force use of SDL and freetype from the ps3 toolchain @@ -2692,6 +2699,8 @@ if test -n "$_host"; then DEFINES="$DEFINES -DDISABLE_DOSBOX_OPL" DEFINES="$DEFINES -DDISABLE_SID" DEFINES="$DEFINES -DDISABLE_NES_APU" + CXXFLAGS="$CXXFLAGS -fno-exceptions" + CXXFLAGS="$CXXFLAGS -fno-rtti" _backend="ps2" _build_scalers=no _mt32emu=no @@ -2699,10 +2708,12 @@ if test -n "$_host"; then # This trick doesn't work for tremor right now, as the PS2 port the resulting library # libtremor, while our code later on expects it to be called libvorbisidec. # TODO: Enable tremor, e.g. by adding -ltremor or by renaming the lib. + _tremor=yes _mad=yes _zlib=yes # HACK to fix compilation of C source files for now. - add_line_to_config_mk 'CC = ee-gcc' + add_line_to_config_mk 'CC := ee-gcc' + add_line_to_config_mk 'CFLAGS := -std=c99 -W -Wno-unused-parameter -Wconversion -pedantic -G2 -s -O2 -Wuninitialized' # HACK to fix linking for now. It seems ee-g++ does not handle linking correctly. LD=ee-gcc @@ -3219,9 +3230,10 @@ POST_OBJS_FLAGS := -Wl,--export-all-symbols -Wl,--no-whole-archive -Wl,--out-im ;; ps2) _elf_loader=yes + DEFINES="$DEFINES -DUNCACHED_PLUGINS" _mak_plugins=' -LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/main_prog.ld -PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/plugin.ld -lstdc++ -lc +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/main_prog.ld +PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backends/plugins/ps2/plugin.ld -lstdc++ -lc ' ;; psp) @@ -3357,6 +3369,8 @@ if test "$_tremor" = yes && test "$_vorbis" = no; then if test "$_tremolo" = yes ; then add_line_to_config_h '#define USE_TREMOLO' LIBS="$LIBS $TREMOR_LIBS -ltremolo" + elif test "$_host" = ps2 ; then + LIBS="-ltremor $LIBS" else LIBS="$LIBS $TREMOR_LIBS -lvorbisidec" fi @@ -4119,6 +4133,10 @@ case $_backend in # without a scummvm sub directory. DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"$libdir\\\"" ;; + ps2) + # PS2 bogus dir: it actually depends on launch medium + DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"host:plugins\\\"" + ;; *) DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"$libdir/scummvm\\\"" ;; diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp index c26fbe3331..392ee08ea1 100644 --- a/engines/agos/midi.cpp +++ b/engines/agos/midi.cpp @@ -235,6 +235,10 @@ void MidiPlayer::startTrack(int track) { _music.parser = parser; // That plugs the power cord into the wall } else if (_music.parser) { if (!_music.parser->setTrack(track)) { + // The Roland MT32 music in Simon the Sorcerer 2 + // is missing the extra tracks in many scenes, + // like the introduction sequence. + stop(); return; } _currentTrack = (byte)track; diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp index 86ca4c8541..451b4a1c68 100644 --- a/engines/avalanche/animation.cpp +++ b/engines/avalanche/animation.cpp @@ -764,7 +764,7 @@ void Animation::catacombMove(byte ped) { spr1->init(5, true); // ...Load Geida. appearPed(1, geidaPed(ped)); spr1->_callEachStepFl = true; - spr1->_eachStepProc = kProcGeida; + spr1->_eachStepProc = kProcFollowAvvy; } } @@ -1121,7 +1121,7 @@ void Animation::spin(Direction dir, byte &tripnum) { } } -void Animation::geidaProcs(byte tripnum) { +void Animation::follow(byte tripnum) { AnimationType *tripSpr = _sprites[tripnum]; AnimationType *avvy = _sprites[0]; @@ -1132,14 +1132,14 @@ void Animation::geidaProcs(byte tripnum) { } if (tripSpr->_y < (avvy->_y - 2)) { - // Geida is further from the screen than Avvy. + // The following NPC is further from the screen than Avvy. spin(kDirDown, tripnum); tripSpr->_moveY = 1; tripSpr->_moveX = 0; takeAStep(tripnum); return; } else if (tripSpr->_y > (avvy->_y + 2)) { - // Avvy is further from the screen than Geida. + // Avvy is further from the screen than the following NPC. spin(kDirUp, tripnum); tripSpr->_moveY = -1; tripSpr->_moveX = 0; @@ -1205,8 +1205,9 @@ void Animation::drawSprites() { * @remarks Originally called 'trippancy_link' */ void Animation::animLink() { - if (_vm->_dropdown->isActive() || _vm->_seeScroll) + if (_vm->_dropdown->isActive() || !_vm->_animationsEnabled) return; + for (int16 i = 0; i < kSpriteNumbMax; i++) { AnimationType *curSpr = _sprites[i]; if (curSpr->_quick && curSpr->_visible) @@ -1235,8 +1236,8 @@ void Animation::animLink() { case kProcGrabAvvy : grabAvvy(i); break; - case kProcGeida : - geidaProcs(i); + case kProcFollowAvvy : + follow(i); break; default: break; diff --git a/engines/avalanche/animation.h b/engines/avalanche/animation.h index 375d117893..d1ee4a3ebd 100644 --- a/engines/avalanche/animation.h +++ b/engines/avalanche/animation.h @@ -102,9 +102,8 @@ public: kProcBackAndForth, kProcFaceAvvy, kProcArrow, - kProcSpludwick, // Unused kProcGrabAvvy, - kProcGeida // Spludwick uses it as well for homing! TODO: Unify it with kProcSpludwick. + kProcFollowAvvy }; AnimationType *_sprites[kSpriteNumbMax]; @@ -167,7 +166,7 @@ private: // Movements for Homing NPCs: Spludwick and Geida. void spin(Direction dir, byte &tripnum); void takeAStep(byte &tripnum); - void geidaProcs(byte tripnum); + void follow(byte tripnum); void drawSprites(); }; diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp index 1bc4c5348d..6cfe4dfdb6 100644 --- a/engines/avalanche/avalanche.cpp +++ b/engines/avalanche/avalanche.cpp @@ -57,6 +57,7 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription * _nim = nullptr; _ghostroom = nullptr; _help = nullptr; + _highscore = nullptr; _platform = gd->desc.platform; initVariables(); @@ -81,6 +82,7 @@ AvalancheEngine::~AvalancheEngine() { delete _nim; delete _ghostroom; delete _help; + delete _highscore; for (int i = 0; i < 31; i++) { for (int j = 0; j < 2; j++) { @@ -142,7 +144,7 @@ void AvalancheEngine::initVariables() { _letMeOut = false; _thinks = 2; _thinkThing = true; - _seeScroll = false; + _animationsEnabled = true; _currentMouse = 177; _holdLeftMouse = false; @@ -165,6 +167,7 @@ Common::ErrorCode AvalancheEngine::initialize() { _nim = new Nim(this); _ghostroom = new GhostRoom(this); _help = new Help(this); + _highscore = new HighScore(this); _graphics->init(); _dialogs->init(); @@ -200,7 +203,7 @@ void AvalancheEngine::synchronize(Common::Serializer &sz) { sz.syncAsByte(_carryNum); for (int i = 0; i < kObjectNum; i++) sz.syncAsByte(_objects[i]); - sz.syncAsSint16LE(_dnascore); + sz.syncAsSint16LE(_score); sz.syncAsSint32LE(_money); sz.syncAsByte(_room); if (sz.isSaving()) @@ -336,8 +339,8 @@ void AvalancheEngine::synchronize(Common::Serializer &sz) { } -bool AvalancheEngine::canSaveGameStateCurrently() { // TODO: Refine these!!! - return (!_seeScroll && _alive); +bool AvalancheEngine::canSaveGameStateCurrently() { + return (_animationsEnabled && _alive); } Common::Error AvalancheEngine::saveGameState(int slot, const Common::String &desc) { @@ -381,8 +384,8 @@ Common::String AvalancheEngine::getSaveFileName(const int slot) { return Common::String::format("%s.%03d", _targetName.c_str(), slot); } -bool AvalancheEngine::canLoadGameStateCurrently() { // TODO: Refine these!!! - return (!_seeScroll); +bool AvalancheEngine::canLoadGameStateCurrently() { + return (_animationsEnabled); } Common::Error AvalancheEngine::loadGameState(int slot) { @@ -432,7 +435,7 @@ bool AvalancheEngine::loadGame(const int16 slot) { _isLoaded = true; - _seeScroll = true; // This prevents display of the new sprites before the new picture is loaded. + _animationsEnabled = false; if (_holdTheDawn) { _holdTheDawn = false; diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h index 146065ad63..6eb5e675cc 100644 --- a/engines/avalanche/avalanche.h +++ b/engines/avalanche/avalanche.h @@ -46,6 +46,7 @@ #include "avalanche/help.h" #include "avalanche/shootemup.h" #include "avalanche/mainmenu.h" +#include "avalanche/highscore.h" #include "common/serializer.h" @@ -91,6 +92,7 @@ public: Nim *_nim; GhostRoom *_ghostroom; Help *_help; + HighScore *_highscore; OSystem *_system; @@ -150,7 +152,7 @@ public: // Former DNA structure byte _carryNum; // How many objects you're carrying... bool _objects[kObjectNum]; // ...and which ones they are. - int16 _dnascore; // your score, of course + int16 _score; // your score, of course int32 _money; // your current amount of dosh Room _room; // your current room bool _wonNim; // Have you *won* Nim? (That's harder.) @@ -210,7 +212,7 @@ public: bool _letMeOut; byte _thinks; bool _thinkThing; - bool _seeScroll; // TODO: maybe this means we're interacting with the toolbar / a scroll? + bool _animationsEnabled; // If set to TRUE, it stops the animation system working. This prevents display of the new sprites before the new picture is loaded or during the display of a scroll. Original name: seescroll. char _objectList[10]; // Called .free() for them in ~Gyro(). diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp index e855c71fcf..c8f5599687 100644 --- a/engines/avalanche/avalot.cpp +++ b/engines/avalanche/avalot.cpp @@ -202,6 +202,8 @@ void AvalancheEngine::setup() { _graphics->drawSoundLight(_sound->_soundFl); + drawToolbar(); + int16 loadSlot = ConfMan.instance().getInt("save_slot"); if (loadSlot >= 0) { _thinks = 2; // You always have money. @@ -218,8 +220,6 @@ void AvalancheEngine::setup() { newGame(); - drawToolbar(); - thinkAbout(kObjectMoney, kThing); _dialogs->displayScrollChain('Q', 83); // Info on the game, etc. @@ -249,8 +249,6 @@ void AvalancheEngine::runAvalot() { _system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight). }; - warning("STUB: run()"); - _closing->exitGame(); } @@ -464,7 +462,7 @@ void AvalancheEngine::findPeople(byte room) { void AvalancheEngine::exitRoom(byte x) { _sound->stopSound(); _background->release(); - _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + _animationsEnabled = false; switch (x) { case kRoomSpludwicks: @@ -487,7 +485,7 @@ void AvalancheEngine::exitRoom(byte x) { } _interrogation = 0; // Leaving the room cancels all the questions automatically. - _seeScroll = false; // Now it can work again! + _animationsEnabled = true; _lastRoom = _room; if (_room != kRoomMap) @@ -534,11 +532,11 @@ void AvalancheEngine::putGeidaAt(byte whichPed, byte ped) { spr1->init(5, false); // load Geida _animation->appearPed(1, whichPed); spr1->_callEachStepFl = true; - spr1->_eachStepProc = Animation::kProcGeida; + spr1->_eachStepProc = Animation::kProcFollowAvvy; } void AvalancheEngine::enterRoom(Room roomId, byte ped) { - _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + _animationsEnabled = false; findPeople(roomId); _room = roomId; @@ -619,7 +617,7 @@ void AvalancheEngine::enterRoom(Room roomId, byte ped) { } spr1->_callEachStepFl = true; - spr1->_eachStepProc = Animation::kProcGeida; + spr1->_eachStepProc = Animation::kProcFollowAvvy; } else _whereIs[kPeopleSpludwick - 150] = kRoomNowhere; break; @@ -922,7 +920,7 @@ void AvalancheEngine::enterRoom(Room roomId, byte ped) { break; } - _seeScroll = false; // Now it can work again! + _animationsEnabled = true; } void AvalancheEngine::thinkAbout(byte object, bool type) { @@ -957,7 +955,7 @@ void AvalancheEngine::drawToolbar() { } void AvalancheEngine::drawScore() { - uint16 score = _dnascore; + uint16 score = _score; int8 numbers[3] = {0, 0, 0}; for (int i = 0; i < 2; i++) { byte divisor = 1; @@ -983,15 +981,14 @@ void AvalancheEngine::drawScore() { void AvalancheEngine::incScore(byte num) { for (int i = 1; i <= num; i++) { - _dnascore++; + _score++; if (_soundFx) { for (int j = 1; j <= 97; j++) - // Length os 2 is a guess, the original doesn't have a delay specified - _sound->playNote(177 + _dnascore * 3, 2); + // Length of 2 is a guess, the original doesn't have a delay specified + _sound->playNote(177 + _score * 3, 2); } } - warning("STUB: points()"); drawScore(); } @@ -1336,7 +1333,7 @@ void AvalancheEngine::resetVariables() { for (int i = 0; i < kObjectNum; i++) _objects[i] = false; - _dnascore = 0; + _score = 0; _money = 0; _room = kRoomNowhere; _saveNum = 0; @@ -1442,7 +1439,7 @@ void AvalancheEngine::newGame() { _thinkThing = true; _thinks = 2; refreshObjectList(); - _seeScroll = false; + _animationsEnabled = true; avvy->appear(300, 117, kDirRight); // Needed to initialize Avalot. //for (gd = 0; gd <= 30; gd++) for (gm = 0; gm <= 1; gm++) also[gd][gm] = nil; diff --git a/engines/avalanche/dialogs.cpp b/engines/avalanche/dialogs.cpp index dc1c277877..e843d17c5b 100644 --- a/engines/avalanche/dialogs.cpp +++ b/engines/avalanche/dialogs.cpp @@ -157,7 +157,7 @@ void Dialogs::scrollModeNormal() { Common::String e = "(c) 1994"; setReadyLight(3); - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; _vm->_graphics->loadMouse(kCurFletch); _vm->_graphics->saveScreen(); @@ -216,10 +216,8 @@ void Dialogs::scrollModeNormal() { #endif setReadyLight(0); - _vm->_seeScroll = false; + _vm->_animationsEnabled = true; _vm->_holdLeftMouse = false; // Used in Lucerna::checkclick(). - - warning("STUB: Scrolls::scrollModeNormal()"); } /** @@ -290,7 +288,7 @@ bool Dialogs::theyMatch(TuneType &played) { */ void Dialogs::scrollModeMusic() { setReadyLight(3); - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; CursorMan.showMouse(false); _vm->_graphics->loadMouse(kCurFletch); @@ -299,7 +297,7 @@ void Dialogs::scrollModeMusic() { played[i] = kPitchInvalid; int8 lastOne = -1, thisOne = -1; // Invalid values. - _vm->_seeScroll = true; + _vm->_animationsEnabled = false; _vm->_graphics->saveScreen(); _vm->_graphics->showScroll(); @@ -363,6 +361,7 @@ void Dialogs::scrollModeMusic() { value = 11; break; default: + error("cannot happen"); break; } @@ -392,7 +391,7 @@ void Dialogs::scrollModeMusic() { _vm->_graphics->restoreScreen(); _vm->_graphics->removeBackup(); - _vm->_seeScroll = false; + _vm->_animationsEnabled = true; CursorMan.showMouse(true); } @@ -645,9 +644,6 @@ void Dialogs::solidify(byte n) { * 'calldriver' and 'display' by using Common::String instead of a private buffer. */ void Dialogs::displayText(Common::String text) { -// bool was_virtual; // Was the mouse cursor virtual on entry to this proc? - warning("STUB: Scrolls::calldrivers()"); - _vm->_sound->stopSound(); setReadyLight(0); diff --git a/engines/avalanche/dropdown.cpp b/engines/avalanche/dropdown.cpp index 7c0529811e..97adfc2581 100644 --- a/engines/avalanche/dropdown.cpp +++ b/engines/avalanche/dropdown.cpp @@ -678,7 +678,7 @@ void DropDownMenu::setup() { _menuBar.draw(); } -void DropDownMenu::update() { // TODO: Optimize it ASAP!!! It really needs it... +void DropDownMenu::update() { _vm->_graphics->saveScreen(); Common::Point cursorPos = _vm->getMousePos(); diff --git a/engines/avalanche/enums.h b/engines/avalanche/enums.h index 998c96a131..0ba39321bc 100644 --- a/engines/avalanche/enums.h +++ b/engines/avalanche/enums.h @@ -30,6 +30,7 @@ namespace Avalanche { +enum MonsterType { kMonsterTypeGhost, kMonsterTypeGlerk }; enum Flavour { kFlavourEga, kFlavourBgi, kFlavourNatural, kFlavourTwo, kFlavourOne }; diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp index 1419a0cbab..16c79fdee0 100644 --- a/engines/avalanche/ghostroom.cpp +++ b/engines/avalanche/ghostroom.cpp @@ -70,6 +70,30 @@ GhostRoom::~GhostRoom() { for (int j = 0; j < 6; j++) _greldet[j][i].free(); } + + if (_wasLoaded) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 2; j++) { + for (int y = 0; y < 66; y++) { + delete[] _ghost[i][j][y]; + } + delete[] _ghost[i][j]; + } + delete[] _ghost[i]; + } + delete[] _ghost; + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 4; j++) { + for (int y = 0; y < 35; y++) { + delete[] _glerk[i][j][y]; + } + delete[] _glerk[i][j]; + } + delete[] _glerk[i]; + } + delete[] _glerk; + } } void GhostRoom::wait(uint16 howLong) { @@ -141,9 +165,13 @@ void GhostRoom::loadPictures() { file.seek(44); // Initializing ghost's array. + _ghost = new byte***[5]; for (int i = 0; i < 5; i++) { + _ghost[i] = new byte**[2]; for (int j = 0; j < 2; j++) { + _ghost[i][j] = new byte*[66]; for (int y = 0; y < 66; y++) { + _ghost[i][j][y] = new byte[26]; for (int x = 0; x < 26; x++) _ghost[i][j][y][x] = 0; } @@ -171,11 +199,14 @@ void GhostRoom::loadPictures() { for (int i = 0; i < 3; i++) _bat[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord); - // Initializing glerk's array. + _glerk = new byte***[6]; for (int i = 0; i < 6; i++) { + _glerk[i] = new byte**[4]; for (int j = 0; j < 4; j++) { + _glerk[i][j] = new byte*[35]; for (int y = 0; y < 35; y++) { + _glerk[i][j][y] = new byte[9]; for (int x = 0; x < 9; x++) _glerk[i][j][y][x] = 0; } @@ -245,7 +276,7 @@ void GhostRoom::run() { if (_glerkStage > 25) break; - _vm->_graphics->ghostDrawGlerk(_glerk[kGlerkFade[_glerkStage]], 456, 14); + _vm->_graphics->ghostDrawMonster(_glerk[kGlerkFade[_glerkStage]], 456, 14, kMonsterTypeGlerk); _glerkStage++; } @@ -263,7 +294,7 @@ void GhostRoom::run() { // Here comes the descending ghost: for (int y = -64; y <= 103; y++) { - _vm->_graphics->ghostDrawGhost(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y); + _vm->_graphics->ghostDrawMonster(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y, kMonsterTypeGhost); if (y > 0) _vm->_graphics->drawFilledRectangle(Common::Rect(0, y - 1, 26 * 8 + 1, y + 1), kColorBlack); _vm->_graphics->refreshScreen(); @@ -277,7 +308,7 @@ void GhostRoom::run() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { _vm->_graphics->drawFilledRectangle(Common::Rect(0, 96, 26 * 8, 170), kColorBlack); - _vm->_graphics->ghostDrawGhost(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j]); + _vm->_graphics->ghostDrawMonster(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j], kMonsterTypeGhost); _aarghCount++; diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h index ebb02f7aac..4c659128ce 100644 --- a/engines/avalanche/ghostroom.h +++ b/engines/avalanche/ghostroom.h @@ -58,11 +58,11 @@ private: static const byte kGreldetFade[18]; Common::Point dummyCoord; - byte _ghost[5][2][66][26]; + byte ****_ghost;// [5][2][66][26] Graphics::Surface _eyes[2]; Graphics::Surface _exclamation; Graphics::Surface _bat[3]; - byte _glerk[6][4][35][9]; + byte ****_glerk; // [6][4][35][9] Graphics::Surface _aargh[6]; Common::Point _aarghWhere[6]; Graphics::Surface _greenEyes[5]; diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp index ae53f3e034..513cd72c8c 100644 --- a/engines/avalanche/graphics.cpp +++ b/engines/avalanche/graphics.cpp @@ -527,64 +527,65 @@ void GraphicManager::nimFree() { _nimLogo.free(); } -void GraphicManager::ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY) { +void GraphicManager::ghostDrawMonster(byte ***picture, uint16 destX, int16 destY, MonsterType type) { + uint16 height = 0; + uint16 width = 0; + // Only for the Ghost: const byte kPlaneToUse[4] = { 0, 0, 0, 1 }; - // Constants from the original code: - uint16 height = 66; - const uint16 width = 26 * 8; - - // We have to mess around with the coords and the sizes since - // the ghost isn't always placed fully on the screen. int yStart = 0; - if (destY < 0) { - yStart = abs(destY); - height -= yStart; - destY = 0; - } - - Graphics::Surface ghostPic; - ghostPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - - for (int y = 0; y < height; y++) { - for (int plane = 0; plane < 4; plane++) { - for (uint16 x = 0; x < width / 8; x ++) { - byte pixel = ghostArr[kPlaneToUse[plane]][y + yStart][x]; - for (int bit = 0; bit < 8; bit++) { - byte pixelBit = (pixel >> bit) & 1; - *(byte *)ghostPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); - } - } + + // Constants from the original code: + switch (type) { + case kMonsterTypeGhost: + height = 66; + width = 208; // 26 * 8 + + // We have to mess around with the coords and the sizes since + // the ghost isn't always placed fully on the screen. + if (destY < 0) { + yStart = abs(destY); + height -= yStart; + destY = 0; } + break; + case kMonsterTypeGlerk: + height = 35; + width = 72; // 9 * 8 + break; + default: + break; } - drawPicture(_surface, ghostPic, destX, destY); - - ghostPic.free(); -} - -void GraphicManager::ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY) { - // Constants from the original code: - const uint16 height = 35; - const uint16 width = 9 * 8; - - Graphics::Surface glerkPic; - glerkPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + Graphics::Surface monsterPicture; + monsterPicture.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); for (int y = 0; y < height; y++) { for (int plane = 0; plane < 4; plane++) { for (uint16 x = 0; x < width / 8; x++) { - byte pixel = glerkArr[plane][y][x]; + byte pixel = 0; + + switch (type) { + case kMonsterTypeGhost: + pixel = picture[kPlaneToUse[plane]][y + yStart][x]; + break; + case kMonsterTypeGlerk: + pixel = picture[plane][y][x]; + break; + default: + break; + } + for (int bit = 0; bit < 8; bit++) { byte pixelBit = (pixel >> bit) & 1; - *(byte *)glerkPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); + *(byte *)monsterPicture.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane); } } } } - drawPicture(_surface, glerkPic, destX, destY); + drawPicture(_surface, monsterPicture, destX, destY); - glerkPic.free(); + monsterPicture.free(); } /** diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h index 7e0ed64b5f..bd8fc6c8ff 100644 --- a/engines/avalanche/graphics.h +++ b/engines/avalanche/graphics.h @@ -97,8 +97,7 @@ public: void drawWinningPic(); // Ghostroom's functions: - void ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY); // Very similar to loadPictureSign(). TODO: Unify the two later if possible. - void ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY); // Very similar to ghostDrawGhost(), but not enough to unify the two. + void ghostDrawMonster(byte ***picture, uint16 destX, int16 destY, MonsterType type); Graphics::Surface ghostLoadPicture(Common::File &file, Common::Point &coord); void ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY); void ghostDrawBackgroundItems(Common::File &file); @@ -106,7 +105,7 @@ public: // Help's function: void helpDrawButton(int y, byte which); void helpDrawHighlight(byte which, Color color); - void helpDrawBigText(const Common::String text, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two. + void helpDrawBigText(const Common::String text, int16 x, int16 y, Color color); // Shoot em' up's functions: void seuDrawTitle(); @@ -199,12 +198,11 @@ private: Graphics::Surface loadPictureSign(Common::File &file, uint16 width, uint16 height); // Reads a tricky type of picture used for the "game over"/"about" scrolls and in the mini-game Nim. void drawText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); - void drawBigText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two. + void drawBigText(Graphics::Surface &surface, const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); void drawPicture(Graphics::Surface &target, const Graphics::Surface picture, uint16 destX, uint16 destY); // Taken from Free Pascal's Procedure InternalEllipseDefault. Used to replace Pascal's procedure arc. // Returns the end point of the arc. (Needed in Clock.) - // TODO: Make it more accurate later. Common::Point drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color); }; diff --git a/engines/avalanche/highscore.cpp b/engines/avalanche/highscore.cpp new file mode 100644 index 0000000000..5f47aeb894 --- /dev/null +++ b/engines/avalanche/highscore.cpp @@ -0,0 +1,110 @@ +/* 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. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#include "avalanche/avalanche.h" +#include "avalanche/highscore.h" + +#include "common/savefile.h" + +namespace Avalanche { + +HighScore::HighScore(AvalancheEngine *vm) { + _vm = vm; +} + +void HighScore::displayHighScores() { + warning("STUB: HighScore::displayHighScores("); +} + +void HighScore::saveHighScores() { + int firstSmaller = 0; + while ((firstSmaller < 12) && (_data[firstSmaller]._score >= _vm->_score)) + firstSmaller++; + + if (firstSmaller < 12) { + // Shift all the lower scores down a space: + for (int i = firstSmaller; i < 11; i++) + _data[i + 1] = _data[i]; + // Set the new high score: + _data[firstSmaller]._name = "Player"; // TODO: Come up with something for that. In the original it wasn't implemented at all... + _data[firstSmaller]._rank = _vm->_parser->rank(); + _data[firstSmaller]._score = _vm->_score; + } + + Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving("scores.avd"); + if (!f) { + warning("Can't create file 'scores.avd', high scores are not saved."); + return; + } + Common::Serializer sz(NULL, f); + syncHighScores(sz); + f->finalize(); + delete f; +} + +void HighScore::loadHighScroes() { + Common::File file; + if (!file.exists("scores.avd")) { + produceDefaultHighScores(); + } else { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading("scores.avd"); + if (!f) + return; + Common::Serializer sz(f, NULL); + syncHighScores(sz); + delete f; + } +} + +void HighScore::produceDefaultHighScores() { + for (int i = 0; i < 12; i++) { + _data[i]._score = 32 - (i + 1) * 2; + _data[i]._rank = "..."; + } + _data[0]._name = "Mike"; + _data[1]._name = "Liz"; + _data[2]._name = "Thomas"; + _data[3]._name = "Mark"; + _data[4]._name = "Mandy"; + _data[5]._name = "Andrew"; + _data[6]._name = "Lucy Tryphena"; + _data[7]._name = "Tammy the dog"; + _data[8]._name = "Avaricius"; + _data[9]._name = "Spellchick"; + _data[10]._name = "Caddelli"; + _data[11]._name = "Spludwick"; +} + +void HighScore::syncHighScores(Common::Serializer &sz) { + for (int i = 0; i < 12; i++) { + sz.syncString(_data[i]._name); + sz.syncAsUint16LE(_data[i]._score); + sz.syncString(_data[i]._rank); + } +} + +} // End of namespace Avalanche diff --git a/engines/avalanche/highscore.h b/engines/avalanche/highscore.h new file mode 100644 index 0000000000..de7ec36ed5 --- /dev/null +++ b/engines/avalanche/highscore.h @@ -0,0 +1,59 @@ +/* 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. +* +*/ + +/* +* This code is based on the original source code of Lord Avalot d'Argent version 1.3. +* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman. +*/ + +#ifndef AVALANCHE_HIGHSCORE_H +#define AVALANCHE_HIGHSCORE_H + +namespace Avalanche { +class AvalancheEngine; + +struct HighScoreData { + Common::String _name; + uint16 _score; + Common::String _rank; +}; + +class HighScore { +public: + HighScore(AvalancheEngine *vm); + + void displayHighScores(); + void saveHighScores(); + void loadHighScroes(); + +private: + AvalancheEngine *_vm; + + HighScoreData _data[12]; + + void produceDefaultHighScores(); + void syncHighScores(Common::Serializer &sz); +}; + +} // End of namespace Avalanche + +#endif // AVALANCHE_HIGHSCORE_H diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk index d31fd0d91a..29bc039b42 100644 --- a/engines/avalanche/module.mk +++ b/engines/avalanche/module.mk @@ -20,7 +20,8 @@ MODULE_OBJS = \ ghostroom.o \ help.o \ shootemup.o \ - mainmenu.o + mainmenu.o \ + highscore.o # This module can be built as a plugin ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN) diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp index 7db0d14890..b152747ab0 100644 --- a/engines/avalanche/parser.cpp +++ b/engines/avalanche/parser.cpp @@ -602,7 +602,7 @@ Common::String Parser::rank() { }; for (int i = 0; i < 8; i++) { - if ((_vm->_dnascore >= ranks[i]._score) && (_vm->_dnascore < ranks[i + 1]._score)) + if ((_vm->_score >= ranks[i]._score) && (_vm->_score < ranks[i + 1]._score)) return Common::String(ranks[i]._title); } return ""; @@ -2021,8 +2021,7 @@ void Parser::doThat() { break; case 55: if (_vm->_room == kRoomArgentPub) - // play_nim(); - warning("STUB: Parser::doThat() - case kVerbCodeplay - play_nim()"); + _vm->_nim->playNim(); else _vm->_dialogs->displayText(kWhat); break; @@ -2307,7 +2306,7 @@ void Parser::doThat() { break; case kVerbCodeScore: { Common::String tmpStr = Common::String::format("Your score is %d,%c%cout of a possible 128.%c%c " \ - "This gives you a rank of %s.%c%c%s", _vm->_dnascore, kControlCenter, kControlNewLine, kControlNewLine, + "This gives you a rank of %s.%c%c%s", _vm->_score, kControlCenter, kControlNewLine, kControlNewLine, kControlNewLine, rank().c_str(), kControlNewLine, kControlNewLine, totalTime().c_str()); _vm->_dialogs->displayText(tmpStr); } diff --git a/engines/avalanche/parser.h b/engines/avalanche/parser.h index 6a15fb2387..6133c41442 100644 --- a/engines/avalanche/parser.h +++ b/engines/avalanche/parser.h @@ -72,13 +72,11 @@ public: byte _wearing; // what you're wearing Parser(AvalancheEngine *vm); - void init(); void parse(); void doThat(); void verbOpt(byte verb, Common::String &answer, char &ansKey); void drink(); - void handleInputText(const Common::Event &event); void handleBackspace(); void handleReturn(); @@ -89,7 +87,7 @@ public: void tryDropdown(); int16 getPos(const Common::String &crit, const Common::String &src); void doVerb(VerbCode id); - + Common::String rank(); void resetVariables(); void synchronize(Common::Serializer &sz); @@ -112,10 +110,7 @@ private: byte wordNum(Common::String word); void replace(Common::String oldChars, byte newChar); - - Common::String rank(); Common::String totalTime(); - void clearWords(); void cheatParse(Common::String codes); void stripPunctuation(Common::String &word); diff --git a/engines/avalanche/shootemup.cpp b/engines/avalanche/shootemup.cpp index 8d61316daa..cabd19d6f9 100644 --- a/engines/avalanche/shootemup.cpp +++ b/engines/avalanche/shootemup.cpp @@ -95,7 +95,7 @@ ShootEmUp::ShootEmUp(AvalancheEngine *vm) { _gotOut = false; } -void ShootEmUp::run() { +uint16 ShootEmUp::run() { CursorMan.showMouse(false); _vm->_graphics->saveScreen(); _vm->fadeOut(); @@ -142,12 +142,14 @@ void ShootEmUp::run() { if (delay <= 55) _vm->_system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight). }; - + _vm->fadeOut(); _vm->_graphics->restoreScreen(); _vm->_graphics->removeBackup(); _vm->fadeIn(); CursorMan.showMouse(true); + + return _score; } bool ShootEmUp::overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y) { diff --git a/engines/avalanche/shootemup.h b/engines/avalanche/shootemup.h index 4c010aa71e..3cdcc1d5cd 100644 --- a/engines/avalanche/shootemup.h +++ b/engines/avalanche/shootemup.h @@ -35,7 +35,7 @@ class ShootEmUp { public: ShootEmUp(AvalancheEngine *vm); - void run(); + uint16 run(); private: struct Sprite { diff --git a/engines/avalanche/timer.cpp b/engines/avalanche/timer.cpp index 7b6e1ee1ce..a9753b3cce 100644 --- a/engines/avalanche/timer.cpp +++ b/engines/avalanche/timer.cpp @@ -333,12 +333,11 @@ void Timer::hangAround2() { // We don't need the ShootEmUp during the whole game, it's only playable once. ShootEmUp *shootemup = new ShootEmUp(_vm); - shootemup->run(); + _shootEmUpScore = shootemup->run(); delete shootemup; } void Timer::afterTheShootemup() { - // Only placed this here to replace the minigame. TODO: Remove it when the shoot em' up is implemented! _vm->flipRoom(_vm->_room, 1); _vm->_animation->_sprites[0]->init(0, true); // Avalot. @@ -347,27 +346,15 @@ void Timer::afterTheShootemup() { _vm->_objects[kObjectCrossbow - 1] = true; _vm->refreshObjectList(); - // Same as the added line above: TODO: Remove it later!!! - _vm->_dialogs->displayText(Common::String("P.S.: There should have been the mini-game called \"shoot em' up\", " \ - "but I haven't implemented it yet: you get the crossbow automatically.") + kControlNewLine + kControlNewLine + "Peter (uruk)"); - -#if 0 - byte shootscore, gain; - - shootscore = mem[storage_seg * storage_ofs]; - gain = (shootscore + 5) / 10; // Rounding up. - - display(string("\6Your score was ") + strf(shootscore) + '.' + "\r\rYou gain (" + - strf(shootscore) + " 0xF6 10) = " + strf(gain) + " points."); + byte gain = (_shootEmUpScore + 5) / 10; // Rounding up. + _vm->_dialogs->displayText(Common::String::format("%cYour score was %d.%c%cYou gain (%d \xf6 10) = %d points.", kControlItalic, _shootEmUpScore, kControlNewLine, kControlNewLine, _shootEmUpScore, gain)); if (gain > 20) { - display("But we won't let you have more than 20 points!"); - points(20); + _vm->_dialogs->displayText("But we won't let you have more than 20 points!"); + _vm->incScore(20); } else - points(gain); -#endif + _vm->incScore(gain); - warning("STUB: Timer::after_the_shootemup()"); _vm->_dialogs->displayScrollChain('Q', 70); } @@ -712,6 +699,8 @@ void Timer::resetVariables() { _times[i]._action = 0; _times[i]._reason = 0; } + + _shootEmUpScore = 0; } } // End of namespace Avalanche. diff --git a/engines/avalanche/timer.h b/engines/avalanche/timer.h index fd51544fd1..ad6ac0eae6 100644 --- a/engines/avalanche/timer.h +++ b/engines/avalanche/timer.h @@ -170,7 +170,7 @@ public: private: AvalancheEngine *_vm; - + byte _shootEmUpScore; }; } // End of namespace Avalanche. diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp index c63be30f77..80fb0e8a02 100644 --- a/engines/cruise/font.cpp +++ b/engines/cruise/font.cpp @@ -148,8 +148,6 @@ void initSystem() { preloadData[i].nofree = 0; } - lowMemory = 0; - doFade = 0; fadeFlag = 0; scroll = 0; diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index e727ac73cb..7af6b73238 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -606,7 +606,7 @@ int16 Op_InitializeState() { } int16 Op_GetlowMemory() { - return lowMemory; + return 0; } int16 Op_AniDir() { diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index a991c29583..a734db4b3b 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -182,11 +182,13 @@ static void syncFilesDatabase(Common::Serializer &s) { s.syncAsUint16LE(fe.resType); s.syncAsUint16LE(fe.height); - // TODO: Have a look at the saving/loading of this pointer + // Remember whether this file database was open or not. + // Upon loading, loadSavegameData uses this information + // in order to re-open the file databases accordingly. tmp = (fe.subData.ptr) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { - fe.subData.ptr = (uint8 *)tmp; + fe.subData.ptr = tmp ? (uint8 *)1 : 0; } s.syncAsSint16LE(fe.subData.index); @@ -195,11 +197,11 @@ static void syncFilesDatabase(Common::Serializer &s) { s.syncAsSint16LE(fe.subData.transparency); - // TODO: Have a look at the saving/loading of this pointer + // Treat fe.subData.ptrMask the same as fe.subData.ptr. tmp = (fe.subData.ptrMask) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { - fe.subData.ptrMask = (uint8 *)tmp; + fe.subData.ptrMask = tmp ? (uint8 *)1 : 0; } s.syncAsUint16LE(fe.subData.resourceType); @@ -806,7 +808,6 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) } Common::Error loadSavegameData(int saveGameIdx) { - int lowMemorySave; Common::String saveName; cellStruct *currentcellHead; @@ -878,20 +879,19 @@ Common::Error loadSavegameData(int saveGameIdx) { lastAni[0] = 0; - lowMemorySave = lowMemory; - for (int i = 0; i < NUM_FILE_ENTRIES; i++) { if (filesDatabase[i].subData.ptr) { int j; int k; - for (j = i + 1; j < NUM_FILE_ENTRIES && filesDatabase[j].subData.ptr && !strcmp(filesDatabase[i].subData.name, filesDatabase[j].subData.name) && (filesDatabase[j].subData.index == (j - i)); j++) + for (j = i + 1; j < NUM_FILE_ENTRIES && + filesDatabase[j].subData.ptr && + !strcmp(filesDatabase[i].subData.name, filesDatabase[j].subData.name) && + (filesDatabase[j].subData.index == (j - i)); + j++) ; for (k = i; k < j; k++) { - if (filesDatabase[k].subData.ptrMask) - lowMemory = 0; - filesDatabase[k].subData.ptr = NULL; filesDatabase[k].subData.ptrMask = NULL; } @@ -908,7 +908,6 @@ Common::Error loadSavegameData(int saveGameIdx) { } i = j - 1; - lowMemory = lowMemorySave; } } diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index f7c74c8e6d..9a59c8a714 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -31,7 +31,6 @@ uint8 selectColor = 3; uint8 titleColor = 2; uint8 subColor = 5; -int16 lowMemory; int16 scroll; int16 switchPal; char cmdLine[90]; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index 8bfcdc57d4..fe3f7d6303 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -59,7 +59,6 @@ extern uint8 selectColor; extern uint8 titleColor; extern uint8 subColor; -extern int16 lowMemory; extern int16 scroll; extern int16 switchPal; extern char cmdLine[90]; diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 65840ae174..8498e50b8d 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -217,6 +217,11 @@ void MainMenuDialog::reflowLayout() { void MainMenuDialog::save() { int slot = _saveDialog->runModalWithCurrentTarget(); + #if defined(__PLAYSTATION2__) && defined(DYNAMIC_MODULES) + char pokeme[32]; + snprintf(pokeme,32,"hack"); + #endif + if (slot >= 0) { Common::String result(_saveDialog->getResultString()); if (result.empty()) { diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index e5ff1f079a..3a335f249a 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -72,6 +72,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _fadePhases = 0; _fadePhase = 0; _fadeTick = 0; + _isFadeOut = 1; _mouseChangeTick = 0; _enableQuickHero = 0; _wantQuickHero = 0; @@ -216,6 +217,7 @@ void Game::start() { // init scripts. This flag was turned on to skip the rest of // those programs. Don't call loop(), because the // location may have changed. + fadePalette(true); continue; } @@ -478,6 +480,7 @@ void Game::handleDialogueLoop() { } void Game::fadePalette(bool fading_out) { + _isFadeOut = fading_out; const byte *startPal = NULL; const byte *endPal = _currentRoom._palette >= 0 ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data @@ -551,6 +554,19 @@ void Game::advanceAnimationsAndTestLoopExit() { _vm->_anims->drawScene(_vm->_screen->getSurface()); _vm->_screen->copyToScreen(); _vm->_system->delayMillis(kTimeUnit); + if(_isFadeOut) { + fadePalette(false); + // Set cursor state + // Need to do this after we set the palette since the cursors use it + if (_currentRoom._mouseOn) { + debugC(6, kDraciLogicDebugLevel, "Mouse: ON"); + _vm->_mouse->cursorOn(); + _vm->_mouse->setCursorType(kNormalCursor); + } else { + debugC(6, kDraciLogicDebugLevel, "Mouse: OFF"); + _vm->_mouse->cursorOff(); + } + } // If the hero has arrived at his destination, after even the last // phase was correctly animated, run the callback. @@ -598,6 +614,8 @@ void Game::loop(LoopSubstatus substatus, bool shouldExit) { break; } + advanceAnimationsAndTestLoopExit(); + if (_vm->_mouse->isCursorOn()) { // Find animation under cursor and the game object // corresponding to it @@ -629,8 +647,6 @@ void Game::loop(LoopSubstatus substatus, bool shouldExit) { } } - advanceAnimationsAndTestLoopExit(); - } while (!shouldExitLoop()); setLoopSubstatus(kOuterLoop); @@ -926,10 +942,12 @@ void Game::inventoryDraw() { void Game::inventoryReload() { // Make sure all items are loaded into memory (e.g., after loading a // savegame) by re-putting them on the same spot in the inventory. + GameItem *tempItem = _currentItem; for (uint i = 0; i < kInventorySlots; ++i) { putItem(_inventory[i], i); } setPreviousItemPosition(0); + _currentItem = tempItem; } void Game::inventorySwitch(int keycode) { @@ -1433,7 +1451,6 @@ void Game::enterNewRoom() { _vm->_screen->setPalette(NULL, 0, kNumColors); _vm->_anims->drawScene(_vm->_screen->getSurface()); _vm->_screen->copyToScreen(); - fadePalette(false); // Run the program for the gate the dragon came through debugC(6, kDraciLogicDebugLevel, "Running program for gate %d", _newGate); @@ -1446,17 +1463,6 @@ void Game::enterNewRoom() { // Don't immediately switch to the map or inventory even if the mouse // position tell us to. _mouseChangeTick = kMouseDoNotSwitch; - - // Set cursor state - // Need to do this after we set the palette since the cursors use it - if (_currentRoom._mouseOn) { - debugC(6, kDraciLogicDebugLevel, "Mouse: ON"); - _vm->_mouse->cursorOn(); - _vm->_mouse->setCursorType(kNormalCursor); - } else { - debugC(6, kDraciLogicDebugLevel, "Mouse: OFF"); - _vm->_mouse->cursorOff(); - } } void Game::positionAnimAsHero(Animation *anim) { @@ -1572,7 +1578,7 @@ Game::~Game() { delete[] _items; } -void Game::DoSync(Common::Serializer &s) { +void Game::DoSync(Common::Serializer &s, uint8 saveVersion) { s.syncAsUint16LE(_currentRoom._roomNum); for (uint i = 0; i < _info._numObjects; ++i) { @@ -1603,6 +1609,25 @@ void Game::DoSync(Common::Serializer &s) { s.syncAsSint16LE(_dialogueVars[i]); } + if(saveVersion >= 2) { + setPositionLoaded(true); + if (s.isSaving()) { + s.syncAsSint16LE(_hero.x); + s.syncAsSint16LE(_hero.y); + + int handItemID = _currentItem ? _currentItem->_absNum : -1; + s.syncAsSint16LE(handItemID); + } else { + s.syncAsSint16LE(_heroLoading.x); + s.syncAsSint16LE(_heroLoading.y); + + int handItemID = -1; + s.syncAsSint16LE(handItemID); + _currentItem = getItem(handItemID); + } + } else { + _currentItem = 0; + } } static double real_to_double(byte real[6]) { diff --git a/engines/draci/game.h b/engines/draci/game.h index 4a8f3de269..638c979d61 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -215,6 +215,7 @@ public: void walkHero(int x, int y, SightDirection dir); // start walking and leave callback as is void setHeroPosition(const Common::Point &p); const Common::Point &getHeroPosition() const { return _hero; } + const Common::Point &getHeroLoadingPosition() const { return _heroLoading; } void positionAnimAsHero(Animation *anim); void positionHeroAsAnim(Animation *anim); @@ -290,6 +291,8 @@ public: void setExitLoop(bool exit) { _shouldExitLoop = exit; } bool isReloaded() const { return _isReloaded; } void setIsReloaded(bool value) { _isReloaded = value; } + bool isPositionLoaded() { return _isPositionLoaded; } + void setPositionLoaded(bool value) { _isPositionLoaded = value; } void setSpeechTiming(uint tick, uint duration); void shiftSpeechAndFadeTick(int delta); @@ -327,7 +330,7 @@ public: void setEnableSpeedText(bool value) { _enableSpeedText = value; } bool getEnableSpeedText() const { return _enableSpeedText; } - void DoSync(Common::Serializer &s); + void DoSync(Common::Serializer &s, uint8 saveVersion); private: void updateOrdinaryCursor(); @@ -352,6 +355,7 @@ private: GameInfo _info; Common::Point _hero; + Common::Point _heroLoading; int *_variables; Person *_persons; @@ -395,6 +399,7 @@ private: bool _shouldQuit; bool _shouldExitLoop; bool _isReloaded; + bool _isPositionLoaded; uint _speechTick; uint _speechDuration; @@ -408,6 +413,7 @@ private: int _fadePhases; int _fadePhase; uint _fadeTick; + bool _isFadeOut; int _mouseChangeTick; bool _enableQuickHero; diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp index 31ac63b791..3e7f8651c1 100644 --- a/engines/draci/saveload.cpp +++ b/engines/draci/saveload.cpp @@ -45,7 +45,8 @@ bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) { return false; header.version = in->readByte(); - if (header.version != DRACI_SAVEGAME_VERSION) + // Version 1 is compatible with Version 2 + if (header.version > DRACI_SAVEGAME_VERSION) return false; // Read in the string @@ -106,7 +107,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, } else { // Create the remainder of the savegame Common::Serializer s(NULL, f); - vm._game->DoSync(s); + vm._game->DoSync(s, header.version); f->finalize(); delete f; @@ -140,7 +141,7 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) { // Synchronise the remaining data of the savegame Common::Serializer s(f, NULL); - vm->_game->DoSync(s); + vm->_game->DoSync(s, header.version); delete f; // Post-processing diff --git a/engines/draci/saveload.h b/engines/draci/saveload.h index 8b38ccb94f..6f951a3409 100644 --- a/engines/draci/saveload.h +++ b/engines/draci/saveload.h @@ -29,7 +29,7 @@ namespace Draci { -#define DRACI_SAVEGAME_VERSION 1 +#define DRACI_SAVEGAME_VERSION 2 struct DraciSavegameHeader { uint8 version; diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index 97dde39809..09c74f5e0d 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -634,8 +634,16 @@ void Script::stayOn(const Common::Array<int> ¶ms) { return; } - int x = params[0]; - int y = params[1]; + int x, y; + Common::Point afterLoadingPos = _vm->_game->getHeroLoadingPosition(); + if(_vm->_game->isPositionLoaded() == true) { + x = afterLoadingPos.x; + y = afterLoadingPos.y; + } + else { + x = params[0]; + y = params[1]; + } SightDirection dir = static_cast<SightDirection> (params[2]); // Jumps into the given position regardless of the walking map. @@ -670,6 +678,11 @@ void Script::walkOnPlay(const Common::Array<int> ¶ms) { return; } + if(_vm->_game->isPositionLoaded() == true) { + _vm->_game->setPositionLoaded(false); + return; + } + int x = params[0]; int y = params[1]; SightDirection dir = static_cast<SightDirection> (params[2]); @@ -687,6 +700,10 @@ void Script::newRoom(const Common::Array<int> ¶ms) { return; } + if(_vm->_game->isPositionLoaded() == true) { + _vm->_game->setPositionLoaded(false); + } + int room = params[0] - 1; int gate = params[1] - 1; diff --git a/engines/fullpipe/behavior.cpp b/engines/fullpipe/behavior.cpp index 2e3a4e2e44..14e9c33bdf 100644 --- a/engines/fullpipe/behavior.cpp +++ b/engines/fullpipe/behavior.cpp @@ -83,7 +83,7 @@ void BehaviorManager::updateBehaviors() { if (!_isActive) return; - debug(0, "BehaviorManager::updateBehaviors()"); + debug(4, "BehaviorManager::updateBehaviors()"); for (uint i = 0; i < _behaviors.size(); i++) { BehaviorInfo *beh = _behaviors[i]; @@ -122,7 +122,7 @@ void BehaviorManager::updateBehaviors() { } void BehaviorManager::updateBehavior(BehaviorInfo *behaviorInfo, BehaviorEntry *entry) { - debug(0, "BehaviorManager::updateBehavior() %d", entry->_itemsCount); + debug(4, "BehaviorManager::updateBehavior() %d", entry->_itemsCount); for (int i = 0; i < entry->_itemsCount; i++) { BehaviorEntryInfo *bhi = entry->_items[i]; if (!(bhi->_flags & 1)) { @@ -144,7 +144,7 @@ void BehaviorManager::updateBehavior(BehaviorInfo *behaviorInfo, BehaviorEntry * } void BehaviorManager::updateStaticAniBehavior(StaticANIObject *ani, int delay, BehaviorEntry *bhe) { - debug(0, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName)); + debug(4, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName)); MessageQueue *mq = 0; @@ -236,7 +236,7 @@ void BehaviorInfo::clear() { } void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) { - debug(0, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName)); + debug(4, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); _itemsCount = 1; @@ -260,7 +260,7 @@ void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) { } void BehaviorInfo::initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani) { - debug(0, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName)); + debug(4, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h index 9062fe949d..f76a12fb2b 100644 --- a/engines/fullpipe/constants.h +++ b/engines/fullpipe/constants.h @@ -43,6 +43,8 @@ namespace Fullpipe { #define MV_LFT_OPEN 1048 #define MV_MAN_GOLADDER 451 #define MV_MAN_GOLADDER2 2844 +#define MV_MAN_HMRKICK 1028 +#define MV_MAN_HMRKICK_COINLESS 1445 #define MV_MAN_LIFTDOWN 1052 #define MV_MAN_LIFTUP 1051 #define MV_MAN_LOOKUP 4773 @@ -219,8 +221,11 @@ namespace Fullpipe { #define SC_MAINMENU 4620 #define SC_MAP 5222 #define SC_TITLES 5166 +#define SND_CMN_015 3139 #define SND_CMN_031 3516 #define SND_CMN_032 3517 +#define SND_CMN_054 4762 +#define SND_CMN_055 4763 #define SND_CMN_060 4921 #define SND_CMN_061 4922 #define SND_CMN_070 5199 @@ -266,6 +271,27 @@ namespace Fullpipe { #define TrubaLeft 474 #define TrubaUp 680 +// Main Menu +#define PIC_MNU_AUTHORS_L 4624 +#define PIC_MNU_CONTINUE_L 4626 +#define PIC_MNU_DEBUG_L 4632 +#define PIC_MNU_EXIT_L 4622 +#define PIC_MNU_LOAD_L 4628 +#define PIC_MNU_MUSICSLIDER_D 4914 +#define PIC_MNU_MUSICSLIDER_L 4915 +#define PIC_MNU_RESTART_L 5299 +#define PIC_MNU_SAVE_L 4630 +#define PIC_MNU_SLIDER_D 4913 +#define PIC_MNU_SLIDER_L 4912 + +// Query dialog +#define PIC_MEX_BGR 5300 +#define PIC_MEX_CANCEL 5302 +#define PIC_MEX_OK 5301 +#define PIC_MOV_BGR 5343 +#define PIC_MOV_CANCEL 5345 +#define PIC_MOV_OK 5344 + // Intro #define ANI_IN1MAN 5110 #define MSG_INTR_ENDINTRO 5139 @@ -1276,6 +1302,65 @@ namespace Fullpipe { #define QU_SC28_WMN_START 3452 #define ST_MAN28_RIGHT 4249 +// Scene 29 +#define ANI_ASS 2120 +#define ANI_PORTER 2082 +#define ANI_SHELL_GREEN 2116 +#define ANI_SHELL_RED 2130 +#define ANI_SHOOTER1 2108 +#define ANI_SHOOTER2 2111 +#define MSG_SC29_DISABLEPORTER 2097 +#define MSG_SC29_DISABLERIDEBACK 2106 +#define MSG_SC29_ENABLEPORTER 2096 +#define MSG_SC29_ENABLERIDEBACK 2105 +#define MSG_SC29_LAUGH 4760 +#define MSG_SC29_SHOOTGREEN 2119 +#define MSG_SC29_SHOOTRED 2137 +#define MSG_SC29_SHOWLASTGREEN 2730 +#define MSG_SC29_SHOWLASTRED 2731 +#define MSG_SC29_STOPRIDE 2107 +#define MV_ASS_HITGREEN 2138 +#define MV_ASS_HITRED 2139 +#define MV_BRDCMN_GOR 4735 +#define MV_MAN29_BEND 2091 +#define MV_MAN29_HIT 2088 +#define MV_MAN29_JUMP 2090 +#define MV_MAN29_RUN 2095 +#define MV_MAN29_STANDUP 2092 +#define MV_MAN29_STANDUP_NORM 2093 +#define MV_PTR_MOVEFAST 2102 +#define MV_SHG_HITASS 2151 +#define MV_SHG_HITMAN 2147 +#define MV_SHG_NORM 2117 +#define MV_SHR_HITASS 2152 +#define MV_SHR_HITMAN 2149 +#define MV_SHR_NORM 2131 +#define MV_STR1_SHOOT 2109 +#define MV_STR2_SHOOT 2112 +#define PIC_SC29_LTRUBA 2081 +#define QU_SC29_BRD1 4741 +#define QU_SC29_BRD2 4742 +#define QU_SC29_BRDOUT1 4743 +#define QU_SC29_BRDOUT2 4744 +#define QU_SC29_ESCAPE 2129 +#define QU_SC29_MANFROM_L 2101 +#define QU_SC29_MANFROM_R 2104 +#define QU_SC29_MANTO_L 2103 +#define QU_SC29_MANTO_R 2100 +#define SND_29_014 4348 +#define SND_29_027 4757 +#define SND_29_028 4758 +#define SND_29_029 4759 +#define ST_ASS_NORM 2122 +#define ST_BRDCMN_GOR 4734 +#define ST_BRDCMN_RIGHT 4732 +#define ST_MAN29_RUNR 2140 +#define ST_MAN29_SITR 2141 +#define ST_STR1_RIGHT 2143 +#define ST_STR2_RIGHT 2144 +#define ST_STR1_STAND 2110 +#define ST_STR2_STAND 2113 + // Scene 30 #define ANI_LEG 2322 #define MSG_SC30_UPDATEPATH 2358 diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index 4446af7b60..5369c05de7 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -71,6 +71,7 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) _flgSoundList = true; _sfxVolume = 0; + _musicVolume = 0; _inputController = 0; _inputDisabled = false; @@ -95,6 +96,7 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) _gamePaused = false; _inputArFlag = false; _recordEvents = false; + _mainMenu_debugEnabled = false; _flgGameIsRunning = true; @@ -102,6 +104,18 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) _musicAllowed = -1; _musicGameVar = 0; + _musicMinDelay = 0; + _musicMaxDelay = 0; + _musicLocal = 0; + _trackStartDelay = 0; + + memset(_sceneTracks, 0, sizeof(_sceneTracks)); + memset(_trackName, 0, sizeof(_trackName)); + memset(_sceneTracksCurrentTrack, 0, sizeof(_sceneTracksCurrentTrack)); + + _numSceneTracks = 0; + _sceneTrackHasSequence = false; + _sceneTrackIsPlaying = false; _aniMan = 0; _aniMan2 = 0; @@ -190,6 +204,10 @@ void FullpipeEngine::initialize() { _mgm = new MGM; } +void FullpipeEngine::restartGame() { + warning("STUB: FullpipeEngine::restartGame()"); +} + Common::Error FullpipeEngine::run() { const Graphics::PixelFormat format(2, 5, 6, 5, 0, 11, 5, 0, 0); // Initialize backend diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 17a771bd5d..27505252ab 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -91,6 +91,7 @@ public: GUI::Debugger *getDebugger() { return _console; } void initialize(); + void restartGame(); void setMusicAllowed(int val) { _musicAllowed = val; } @@ -125,6 +126,7 @@ public: bool _flgGameIsRunning; bool _inputArFlag; bool _recordEvents; + bool _mainMenu_debugEnabled; Common::Rect _sceneRect; int _sceneWidth; @@ -149,18 +151,32 @@ public: int _currSoundListCount; bool _soundEnabled; bool _flgSoundList; + char _sceneTracks[10][260]; + int _numSceneTracks; + bool _sceneTrackHasSequence; + int _musicMinDelay; + int _musicMaxDelay; + int _musicLocal; + char _trackName[2600]; + int _trackStartDelay; + char _sceneTracksCurrentTrack[260]; + bool _sceneTrackIsPlaying; void stopAllSounds(); void toggleMute(); void playSound(int id, int flag); void playTrack(GameVar *sceneVar, const char *name, bool delayed); + int getSceneTrack(); void startSceneTrack(); + void startSoundStream1(char *trackName); void stopSoundStream2(); void stopAllSoundStreams(); void stopAllSoundInstances(int id); void updateSoundVolume(); + void setMusicVolume(int vol); int _sfxVolume; + int _musicVolume; GlobalMessageQueueList *_globalMessageQueueList; MessageHandler *_messageHandlers; @@ -296,6 +312,7 @@ public: GameVar *_musicGameVar; Audio::SoundHandle _sceneTrackHandle; + public: bool _isSaveAllowed; diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 137af86f48..7c66a9a747 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -90,7 +90,16 @@ Background::Background() { } Background::~Background() { - warning("STUB: Background::~Background()"); + _picObjList.clear(); + + for (int i = 0; i < _bigPictureArray1Count; i++) { + for (int j = 0; j < _bigPictureArray2Count; j++) + delete _bigPictureArray[i][j]; + + free(_bigPictureArray[i]); + } + + free(_bigPictureArray); } bool Background::load(MfcArchive &file) { @@ -159,7 +168,9 @@ PictureObject::PictureObject() { } PictureObject::~PictureObject() { - warning("STUB: PictureObject::~PictureObject()"); + delete _picture; + _pictureObject2List->clear(); + delete _pictureObject2List; } PictureObject::PictureObject(PictureObject *src) : GameObject(src) { diff --git a/engines/fullpipe/input.cpp b/engines/fullpipe/input.cpp index 0678d15368..7c97461a24 100644 --- a/engines/fullpipe/input.cpp +++ b/engines/fullpipe/input.cpp @@ -275,6 +275,8 @@ void FullpipeEngine::updateCursorCommon() { } void FullpipeEngine::initArcadeKeys(const char *varname) { + _arcadeKeys.clear(); + GameVar *var = getGameLoaderGameVar()->getSubVarByName(varname)->getSubVarByName("KEYPOS"); if (!var) @@ -294,6 +296,37 @@ void FullpipeEngine::initArcadeKeys(const char *varname) { } } +void FullpipeEngine::processArcade(ExCommand *cmd) { + if (!g_fp->_aniMan2) + return; + + int idx; + + if (cmd->_sceneClickX <= g_fp->_aniMan2->_ox) { + for (idx = (int)_arcadeKeys.size() - 1; idx >= 0; idx--) { + if (_arcadeKeys[idx]->x < g_fp->_aniMan2->_ox) + break; + } + + if (idx < 0) + return; + } else { + for (idx = 0; idx < (int)_arcadeKeys.size(); idx++) { + if (_arcadeKeys[idx]->x > g_fp->_aniMan2->_ox) + break; + } + + if (idx >= (int)_arcadeKeys.size()) + return; + } + + cmd->_sceneClickX = _arcadeKeys[idx]->x; + cmd->_sceneClickY = _arcadeKeys[idx]->y; + + cmd->_x = cmd->_sceneClickX - g_fp->_sceneRect.left; + cmd->_y = cmd->_sceneClickY - g_fp->_sceneRect.top; +} + void FullpipeEngine::setArcadeOverlay(int picId) { Common::Point point; Common::Point point2; diff --git a/engines/fullpipe/interaction.cpp b/engines/fullpipe/interaction.cpp index 6b6ceb6eeb..84e9688e30 100644 --- a/engines/fullpipe/interaction.cpp +++ b/engines/fullpipe/interaction.cpp @@ -56,7 +56,9 @@ bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId) { } InteractionController::~InteractionController() { - warning("STUB: InteractionController::~InteractionController()"); + _interactions.clear(); + + removeMessageHandler(124, -1); } bool InteractionController::load(MfcArchive &file) { @@ -427,7 +429,14 @@ Interaction::Interaction() { } Interaction::~Interaction() { - warning("STUB: Interaction::~Interaction()"); + if (_messageQueue) { + while (_messageQueue->getExCommandByIndex(0)) + _messageQueue->deleteExCommandByIndex(0, 1); + } + + delete _messageQueue; + + free(_actionName); } bool Interaction::load(MfcArchive &file) { diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp index cfe8adf86f..e79f9c54df 100644 --- a/engines/fullpipe/inventory.cpp +++ b/engines/fullpipe/inventory.cpp @@ -447,6 +447,15 @@ int Inventory2::getHoveredItem(Common::Point *point) { return 0; } +void Inventory2::clear() { + unselectItem(0); + + for (uint i = 0; i < _inventoryItems.size(); i++) + getInventoryPoolItemFieldCById(_inventoryItems[i]->itemId); + + _inventoryItems.clear(); +} + void FullpipeEngine::getAllInventory() { Inventory2 *inv = getGameLoaderInventory(); diff --git a/engines/fullpipe/inventory.h b/engines/fullpipe/inventory.h index 833cccc355..46b55c5669 100644 --- a/engines/fullpipe/inventory.h +++ b/engines/fullpipe/inventory.h @@ -129,6 +129,8 @@ class Inventory2 : public Inventory { bool unselectItem(bool flag); void draw(); + + void clear(); }; } // End of namespace Fullpipe diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp index b8e7b5c1db..15aa78d342 100644 --- a/engines/fullpipe/messagehandlers.cpp +++ b/engines/fullpipe/messagehandlers.cpp @@ -34,11 +34,69 @@ namespace Fullpipe { void global_messageHandler_KickStucco() { - warning("STUB: global_messageHandler_KickStucco()"); + Movement *mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK); + int end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + bool flip = false; + + for (int i = 0; i < end; i++) { + ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand; + + if (ex) + if (ex->_messageKind == 35) + if (ex->_messageNum == SND_CMN_015) { + if (flip) { + ex->_messageNum = SND_CMN_055; + } else { + ex->_messageNum = SND_CMN_054; + flip = true; + } + } + } + + mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK_COINLESS); + end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + flip = false; + + for (int i = 0; i < end; i++) { + ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand; + + if (ex) + if (ex->_messageKind == 35) + if (ex->_messageNum == SND_CMN_015) { + if (flip) { + ex->_messageNum = SND_CMN_055; + } else { + ex->_messageNum = SND_CMN_054; + flip = true; + } + } + } } void global_messageHandler_KickMetal() { - warning("STUB: global_messageHandler_KickMetal()"); + Movement *mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK); + int end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + + for (int i = 0; i < end; i++) { + ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand; + + if (ex) + if (ex->_messageKind == 35) + if (ex->_messageNum == SND_CMN_054 || ex->_messageNum == SND_CMN_055) + ex->_messageNum = SND_CMN_015; + } + + mov = g_fp->_aniMan->getMovementById(MV_MAN_HMRKICK_COINLESS); + end = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + + for (int i = 0; i < end; i++) { + ExCommand *ex = mov->getDynamicPhaseByIndex(i)->_exCommand; + + if (ex) + if (ex->_messageKind == 35) + if (ex->_messageNum == SND_CMN_054 || ex->_messageNum == SND_CMN_055) + ex->_messageNum = SND_CMN_015; + } } int global_messageHandler1(ExCommand *cmd) { @@ -528,9 +586,9 @@ int global_messageHandler4(ExCommand *cmd) { ExCommand2 *cmd2 = (ExCommand2 *)cmd; if (cmd->_excFlags & 1) { - ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags); + ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } else { - ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize >> 3, flags); + ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } break; } diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index 9c8f5ac4e2..8257d1459f 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -699,6 +699,10 @@ void GlobalMessageQueueList::addMessageQueue(MessageQueue *msg) { push_back(msg); } +void clearGlobalMessageQueueList() { + g_fp->_globalMessageQueueList->clear(); +} + void clearGlobalMessageQueueList1() { clearMessages(); diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h index da579d58c0..e6f7f05150 100644 --- a/engines/fullpipe/messages.h +++ b/engines/fullpipe/messages.h @@ -193,6 +193,7 @@ void clearMessageHandlers(); void processMessages(); void updateGlobalMessageQueue(int id, int objid); void clearMessages(); +void clearGlobalMessageQueueList(); void clearGlobalMessageQueueList1(); bool chainQueue(int queueId, int flags); diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index 603aaff026..459c714984 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -21,12 +21,13 @@ */ #include "fullpipe/fullpipe.h" -#include "fullpipe/modal.h" #include "fullpipe/messages.h" #include "fullpipe/constants.h" #include "fullpipe/motion.h" #include "fullpipe/scenes.h" #include "fullpipe/gameloader.h" +#include "fullpipe/statics.h" +#include "fullpipe/modal.h" #include "fullpipe/constants.h" @@ -718,7 +719,7 @@ bool ModalCredits::init(int counterdiff) { g_fp->_modalObject = menu; - menu->_field_34 = 1; + menu->_mfield_34 = 1; } return true; @@ -750,9 +751,513 @@ void ModalCredits::update() { } ModalMainMenu::ModalMainMenu() { - warning("STUB: ModalMainMenu::ModalMainMenu()"); + _areas.clear(); + + _lastArea = 0; + _hoverAreaId = 0; + _mfield_34 = 0; + _scene = g_fp->accessScene(SC_MAINMENU); + _debugKeyCount = 0; + _sliderOffset = 0; + _screct.left = g_fp->_sceneRect.left; + _screct.top = g_fp->_sceneRect.top; + _screct.right = g_fp->_sceneRect.right; + _screct.bottom = g_fp->_sceneRect.bottom; + + if (g_fp->_currentScene) { + _bgX = g_fp->_currentScene->_x; + _bgY = g_fp->_currentScene->_y; + } else { + _bgX = 0; + _bgY = 0; + } + + g_fp->_sceneRect.top = 0; + g_fp->_sceneRect.left = 0; + g_fp->_sceneRect.right = 800; + g_fp->_sceneRect.bottom = 600; + + MenuArea *area; + + area = new MenuArea(); + area->picIdL = PIC_MNU_EXIT_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + + area = new MenuArea(); + area->picIdL = PIC_MNU_CONTINUE_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + + if (isSaveAllowed()) { + area = new MenuArea(); + area->picIdL = PIC_MNU_SAVE_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + } + + area = new MenuArea(); + area->picIdL = PIC_MNU_LOAD_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + + area = new MenuArea(); + area->picIdL = PIC_MNU_RESTART_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + + area = new MenuArea(); + area->picIdL = PIC_MNU_AUTHORS_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + + area = new MenuArea(); + area->picIdL = PIC_MNU_SLIDER_L; + area->picObjD = _scene->getPictureObjectById(PIC_MNU_SLIDER_D, 0); + area->picObjD->_flags |= 4; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + _menuSliderIdx = _areas.size() - 1; + + area = new MenuArea(); + area->picIdL = PIC_MNU_MUSICSLIDER_L; + area->picObjD = _scene->getPictureObjectById(PIC_MNU_MUSICSLIDER_D, 0); + area->picObjD->_flags |= 4; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); + _musicSliderIdx = _areas.size() - 1; + + if (g_fp->_mainMenu_debugEnabled) + enableDebugMenuButton(); + + setSliderPos(); +} - _field_34 = 0; +void ModalMainMenu::update() { + _scene->draw(); +} + +bool ModalMainMenu::handleMessage(ExCommand *message) { + if (message->_messageKind != 17) + return false; + + Common::Point point; + + if (message->_messageNum == 29) { + point.x = message->_x; + point.y = message->_y; + + int numarea = checkHover(point); + + if (numarea >= 0) { + if (numarea == _menuSliderIdx) { + _lastArea = _areas[_menuSliderIdx]; + _sliderOffset = _lastArea->picObjL->_ox - point.x; + + return false; + } + + if (numarea == _musicSliderIdx) { + _lastArea = _areas[_musicSliderIdx]; + _sliderOffset = _lastArea->picObjL->_ox - point.x; + + return false; + } + + _hoverAreaId = _areas[numarea]->picIdL; + } + + return false; + } + + if (message->_messageNum == 30) { + if (_lastArea) + _lastArea = 0; + + return false; + } + + if (message->_messageNum != 36) + return false; + + if (message->_keyCode == 27) + _hoverAreaId = PIC_MNU_CONTINUE_L; + else + enableDebugMenu(message->_keyCode); + + return false; +} + +bool ModalMainMenu::init(int counterdiff) { + switch (_hoverAreaId) { + case PIC_MNU_RESTART_L: + g_fp->restartGame(); + + if (this == g_fp->_modalObject) + return false; + + delete this; + break; + + case PIC_MNU_EXIT_L: + { + ModalQuery *mq = new ModalQuery(); + + g_fp->_modalObject = mq; + + mq->_parentObj = this; + mq->create(_scene, (PictureObject *)_scene->_picObjList[0], PIC_MEX_BGR); + + _hoverAreaId = 0; + + return true; + } + + case PIC_MNU_DEBUG_L: + g_fp->_gameLoader->unloadScene(SC_MAINMENU); + g_fp->_sceneRect = _screct; + + if (!g_fp->_currentScene) + error("ModalMainMenu::init: Bad state"); + + g_fp->_currentScene->_x = _bgX; + g_fp->_currentScene->_y = _bgY; + + g_fp->_gameLoader->preloadScene(g_fp->_currentScene->_sceneId, SC_DBGMENU); + + return false; + + case PIC_MNU_CONTINUE_L: + if (!_mfield_34) { + g_fp->_gameLoader->unloadScene(SC_MAINMENU); + g_fp->_sceneRect = _screct; + + if (g_fp->_currentScene) { + g_fp->_currentScene->_x = _bgX; + g_fp->_currentScene->_y = _bgY; + } + + return false; + } + + g_fp->restartGame(); + + if (this == g_fp->_modalObject) + return false; + + delete this; + break; + + case PIC_MNU_AUTHORS_L: + g_fp->_modalObject = new ModalCredits(); + g_fp->_modalObject->_parentObj = this; + + _hoverAreaId = 0; + + return true; + + case PIC_MNU_SAVE_L: + case PIC_MNU_LOAD_L: + { + ModalSaveGame *sg = new ModalSaveGame(); + + g_fp->_modalObject = sg; + g_fp->_modalObject->_parentObj = _parentObj; + + int mode = 0; + if (_hoverAreaId == PIC_MNU_SAVE_L) + mode = 1; + + sg->setup(g_fp->accessScene(SC_MAINMENU), mode); + sg->setScene(g_fp->accessScene(SC_MAINMENU)); + + sg->_rect = _screct; + sg->_oldBgX = _bgX; + sg->_oldBgY = _bgY; + + delete this; + } + + break; + + default: + if (_lastArea) { + updateSliderPos(); + } else { + g_fp->_cursorId = PIC_CSR_DEFAULT; + + int idx = checkHover(g_fp->_mouseScreenPos); + + if (idx < 0) + goto LABEL_40; + + g_fp->_cursorId = PIC_CSR_DEFAULT; + + if (idx != this->_menuSliderIdx && idx != this->_musicSliderIdx ) + goto LABEL_40; + } + + g_fp->_cursorId = PIC_CSR_LIFT; + + LABEL_40: + g_fp->setCursor(g_fp->_cursorId); + + updateVolume(); + + return true; + } + + return true; +} + +void ModalMainMenu::updateVolume() { + if (g_fp->_soundEnabled ) { + for (int s = 0; s < g_fp->_currSoundListCount; s++) + for (int i = 0; i < g_fp->_currSoundList1[s]->getCount(); i++) { + updateSoundVolume(g_fp->_currSoundList1[s]->getSoundByIndex(i)); + } + } +} + +void ModalMainMenu::updateSoundVolume(Sound *snd) { + if (!snd->_objectId) + return; + + StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(snd->_objectId, -1); + if (!ani) + return; + + int a, b; + + if (ani->_ox >= _screct.left) { + int par, pan; + + if (ani->_ox <= _screct.right) { + int dx; + + if (ani->_oy <= _screct.bottom) { + if (ani->_oy >= _screct.top) { + snd->setPanAndVolume(g_fp->_sfxVolume, 0); + + return; + } + dx = _screct.top - ani->_oy; + } else { + dx = ani->_oy - _screct.bottom; + } + + par = 0; + + if (dx > 800) { + snd->setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } else { + int dx = ani->_ox - _screct.right; + + if (dx > 800) { + snd->setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + par = dx * (-3500) / -800; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } + + int32 pp = b * a; //(0x51EB851F * b * a) >> 32) >> 8; // TODO FIXME + + snd->setPanAndVolume(pan + (pp >> 31) + pp, par); + + return; + } + + int dx = _screct.left - ani->_ox; + if (dx <= 800) { + int32 s = 0x51EB851F * (800 - dx) * (g_fp->_sfxVolume - (-3500)); // TODO FIXME + int32 p = -3500 + (s >> 31) + (s >> 8); + + if (p > g_fp->_sfxVolume) + p = g_fp->_sfxVolume; + + snd->setPanAndVolume(p, dx * (-3500) / 800); + } else { + snd->setPanAndVolume(-3500, 0); + } + + warning("STUB: ModalMainMenu::updateSoundVolume()"); +} + +void ModalMainMenu::updateSliderPos() { + if (_lastArea->picIdL == PIC_MNU_SLIDER_L) { + int x = g_fp->_mouseScreenPos.x + _sliderOffset; + + if (x >= 65) { + if (x > 238) + x = 238; + } else { + x = 65; + } + + _lastArea->picObjD->setOXY(x, _lastArea->picObjD->_oy); + _lastArea->picObjL->setOXY(x, _lastArea->picObjD->_oy); + + int vol = 1000 * (3 * x - 195); + g_fp->_sfxVolume = vol / 173 - 3000; + + if (!(vol / 173)) + g_fp->_sfxVolume = -10000; + + g_fp->updateSoundVolume(); + } else if (_lastArea->picIdL == PIC_MNU_MUSICSLIDER_L) { + int x = g_fp->_mouseScreenPos.x + _sliderOffset; + + if (x >= 65) { + if (x > 238) + x = 238; + } else { + x = 65; + } + + _lastArea->picObjD->setOXY(x, _lastArea->picObjD->_oy); + _lastArea->picObjL->setOXY(x, _lastArea->picObjD->_oy); + + g_fp->setMusicVolume(255 * (x - 65) / 173); + } +} + +int ModalMainMenu::checkHover(Common::Point &point) { + for (uint i = 0; i < _areas.size(); i++) { + if (_areas[i]->picObjL->isPixelHitAtPos(point.x, point.y)) { + _areas[i]->picObjL->_flags |= 4; + + return i; + } else { + _areas[i]->picObjL->_flags &= 0xFFFB; + } + } + + if (isOverArea(_areas[_menuSliderIdx]->picObjL, &point)) { + _areas[_menuSliderIdx]->picObjL->_flags |= 4; + + return _menuSliderIdx; + } + + if (isOverArea(_areas[_musicSliderIdx]->picObjL, &point)) { + _areas[_musicSliderIdx]->picObjL->_flags |= 4; + + return _musicSliderIdx; + } + + return -1; +} + +bool ModalMainMenu::isOverArea(PictureObject *obj, Common::Point *point) { + Common::Point p; + + obj->getDimensions(&p); + + int left = point->x - 8; + int right = point->x + 12; + int down = point->y - 11; + int up = point->y + 9; + + if (left >= obj->_ox && right < obj->_ox + p.x && down >= obj->_oy && up < obj->_oy + p.y) + return true; + + return false; +} + +bool ModalMainMenu::isSaveAllowed() { + if (!g_fp->_isSaveAllowed) + return false; + + if (g_fp->_aniMan->_flags & 0x100) + return false; + + for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) { + if (!(*s)->_isFinished && ((*s)->getFlags() & 1)) + return false; + } + + return true; +} + +void ModalMainMenu::enableDebugMenu(char c) { + const char deb[] = "DEBUGER"; + + if (c == deb[_debugKeyCount]) { + _debugKeyCount++; + + if (deb[_debugKeyCount] ) + return; + + enableDebugMenuButton(); + } + + _debugKeyCount = 0; +} + +void ModalMainMenu::enableDebugMenuButton() { + MenuArea *area; + + for (uint i = 0; i < _areas.size(); i++) + if (_areas[i]->picIdL == PIC_MNU_DEBUG_L) + return; + + area = new MenuArea(); + area->picIdL = PIC_MNU_DEBUG_L; + area->picObjD = 0; + area->picObjL = _scene->getPictureObjectById(area->picIdL, 0); + area->picObjL->_flags &= 0xFFFB; + _areas.push_back(area); +} + +void ModalMainMenu::setSliderPos() { + int x = 173 * (g_fp->_sfxVolume + 3000) / 3000 + 65; + PictureObject *obj = _areas[_menuSliderIdx]->picObjD; + + if (x >= 65) { + if (x > 238) + x = 238; + } else { + x = 65; + } + + obj->setOXY(x, obj->_oy); + _areas[_menuSliderIdx]->picObjL->setOXY(x, obj->_oy); + + x = 173 * g_fp->_musicVolume / 255 + 65; + obj = _areas[_musicSliderIdx]->picObjD; + + if (x >= 65) { + if (x > 238) + x = 238; + } else { + x = 65; + } + + obj->setOXY(x, obj->_oy); + _areas[_musicSliderIdx]->picObjL->setOXY(x, obj->_oy); } ModalHelp::ModalHelp() { @@ -816,6 +1321,222 @@ void ModalHelp::launch() { } } +ModalQuery::ModalQuery() { + _picObjList = 0; + _bg = 0; + _okBtn = 0; + _cancelBtn = 0; + _queryResult = -1; +} + +ModalQuery::~ModalQuery() { + _bg->_flags &= 0xFFFB; + _cancelBtn->_flags &= 0xFFFB; + _okBtn->_flags &= 0xFFFB; +} + +bool ModalQuery::create(Scene *sc, PictureObject *picObjList, int id) { + if (id == PIC_MEX_BGR) { + _bg = sc->getPictureObjectById(PIC_MEX_BGR, 0); + + if (!_bg) + return false; + + _okBtn = sc->getPictureObjectById(PIC_MEX_OK, 0); + + if (!_okBtn) + return false; + + _cancelBtn = sc->getPictureObjectById(PIC_MEX_CANCEL, 0); + + if (!_cancelBtn) + return 0; + } else { + if (id != PIC_MOV_BGR) + return false; + + _bg = sc->getPictureObjectById(PIC_MOV_BGR, 0); + + if (!_bg) + return false; + + _okBtn = sc->getPictureObjectById(PIC_MOV_OK, 0); + + if (!_okBtn) + return false; + + _cancelBtn = sc->getPictureObjectById(PIC_MOV_CANCEL, 0); + + if (!_cancelBtn) + return false; + } + + _queryResult = -1; + _picObjList = picObjList; + + return true; +} + +void ModalQuery::update() { + if (_picObjList) + _picObjList->draw(); + + _bg->draw(); + + if (_okBtn->_flags & 4) + _okBtn->draw(); + + if (_cancelBtn->_flags & 4) + _cancelBtn->draw(); +} + +bool ModalQuery::handleMessage(ExCommand *cmd) { + if (cmd->_messageKind == 17) { + if (cmd->_messageNum == 29) { + if (_okBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) { + _queryResult = 1; + + return false; + } + + if (_cancelBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _queryResult = 0; + } else if (cmd->_messageNum == 36 && cmd->_keyCode == 27) { + _queryResult = 0; + + return false; + } + } + + return false; +} + +bool ModalQuery::init(int counterdiff) { + if (_okBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _okBtn->_flags |= 4; + else + _okBtn->_flags &= 0xFFFB; + + if (_cancelBtn->isPointInside(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _cancelBtn->_flags |= 4; + else + _cancelBtn->_flags &= 0xFFFB; + + if (_queryResult == -1) { + return true; + } else { + if (_bg->_id == PIC_MEX_BGR) { + _cancelBtn->_flags &= 0xFFFB; + _okBtn->_flags &= 0xFFFB; + + if (_queryResult == 1) { + warning("STUB: ModalQuery::init()"); + //sceneFade(g_vrtDrawHandle, (Scene *)this->_picObjList, 0); + + //if (inputArFlag) { + // g_needRestart = 1; + // return 0; + //} + //SendMessageA(hwndCallback, WM_DESTROY, 0, 0); + } + } + } + + return false; +} + +ModalSaveGame::ModalSaveGame() { + _oldBgX = 0; + _oldBgY = 0; + + _bgr = 0; + _okD = 0; + _okL = 0; + _cancelD = 0; + _cancelL = 0; + _emptyD = 0; + _emptyL = 0; + _queryRes = -1; + _rect = g_fp->_sceneRect; + _queryDlg = 0; + _mode = 1; +} + +ModalSaveGame::~ModalSaveGame() { + g_fp->_sceneRect = _rect; + + _arrayD.clear(); + _arrayL.clear(); + + for (uint i = 0; i < _filenames.size(); i++) + free(_filenames[i]); + + _filenames.clear(); +} + +void ModalSaveGame::setScene(Scene *sc) { + _queryRes = -1; + _menuScene = sc; +} + +void ModalSaveGame::processKey(int key) { + if (key == 27) + _queryRes = 0; +} + +bool ModalSaveGame::init(int counterdiff) { + if (_queryDlg) { + if (!_queryDlg->init(counterdiff)) { + if (!_queryDlg->getQueryResult()) + _queryRes = -1; + + delete _queryDlg; + _queryDlg = 0; + } + + return true; + } + + if (_queryRes == -1) + return true; + + g_fp->_sceneRect = _rect; + + if (g_fp->_currentScene) { + g_fp->_currentScene->_x = _oldBgX; + g_fp->_currentScene->_y = _oldBgY; + } + + if (!_queryRes) { + ModalMainMenu *m = new ModalMainMenu; + + g_fp->_modalObject = m; + + m->_parentObj = _parentObj; + m->_screct = _rect; + m->_bgX = _oldBgX; + m->_bgY = _oldBgY; + + delete this; + + return true; + } + + return false; +} + +void ModalSaveGame::setup(Scene *sc, int mode) { + warning("STUB: ModalSaveGame::setup()"); +} + +char *ModalSaveGame::getSaveName() { + if (_queryRes < 0) + return 0; + + return _filenames[_queryRes]; +} + + void FullpipeEngine::openHelp() { if (!_modalObject) { ModalHelp *help = new ModalHelp; diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h index 7ed433b125..e2962ab595 100644 --- a/engines/fullpipe/modal.h +++ b/engines/fullpipe/modal.h @@ -27,6 +27,7 @@ namespace Fullpipe { class PictureObject; class Picture; +class Sound; class BaseModalObject { public: @@ -147,19 +148,47 @@ class ModalCredits : public BaseModalObject { virtual void saveload() {} }; +struct MenuArea { + int picIdL; + PictureObject *picObjD; + PictureObject *picObjL; +}; + class ModalMainMenu : public BaseModalObject { public: - int _field_34; + Scene *_scene; + int _hoverAreaId; + Common::Array<MenuArea *> _areas; + int _menuSliderIdx; + int _musicSliderIdx; + MenuArea *_lastArea; + int _sliderOffset; + int _mfield_34; + Common::Rect _screct; + int _bgX; + int _bgY; + int _debugKeyCount; public: ModalMainMenu(); virtual ~ModalMainMenu() {} virtual bool pollEvent() { return true; } - virtual bool handleMessage(ExCommand *message) { return false; } - virtual bool init(int counterdiff) { return true; } - virtual void update() {} + virtual bool handleMessage(ExCommand *message); + virtual bool init(int counterdiff); + virtual void update(); virtual void saveload() {} + +private: + bool isSaveAllowed(); + void enableDebugMenuButton(); + void setSliderPos(); + void enableDebugMenu(char c); + int checkHover(Common::Point &point); + void updateVolume(); + void updateSoundVolume(Sound *snd); + void updateSliderPos(); + bool isOverArea(PictureObject *obj, Common::Point *point); }; class ModalHelp : public BaseModalObject { @@ -187,25 +216,63 @@ public: class ModalQuery : public BaseModalObject { public: ModalQuery(); - virtual ~ModalQuery() {} + virtual ~ModalQuery(); virtual bool pollEvent() { return true; } - virtual bool handleMessage(ExCommand *message) { return false; } - virtual bool init(int counterdiff) { return true; } - virtual void update() {} + virtual bool handleMessage(ExCommand *message); + virtual bool init(int counterdiff); + virtual void update(); virtual void saveload() {} + + bool create(Scene *sc, PictureObject *picObjList, int picId); + int getQueryResult() { return _queryResult; } + + +private: + PictureObject *_picObjList; + PictureObject *_bg; + PictureObject *_okBtn; + PictureObject *_cancelBtn; + int _queryResult; + }; class ModalSaveGame : public BaseModalObject { public: ModalSaveGame(); - virtual ~ModalSaveGame() {} + virtual ~ModalSaveGame(); virtual bool pollEvent() { return true; } virtual bool handleMessage(ExCommand *message) { return false; } - virtual bool init(int counterdiff) { return true; } + virtual bool init(int counterdiff); virtual void update() {} virtual void saveload() {} + + void setScene(Scene *sc); + void setup(Scene *sc, int mode); + void processKey(int key); + + char *getSaveName(); + + Common::Rect _rect; + int _oldBgX; + int _oldBgY; + PictureObject *_bgr; + PictureObject *_okD; + PictureObject *_okL; + PictureObject *_cancelD; + PictureObject *_cancelL; + PictureObject *_emptyD; + PictureObject *_emptyL; + PictureObject *_fullD; + PictureObject *_fullL; + Scene *_menuScene; + int _mode; + ModalQuery *_queryDlg; + Common::Array <char *> _filenames; + Common::Array <PictureObject *> _arrayL; + Common::Array <PictureObject *> _arrayD; + int _queryRes; }; diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk index db97fa202b..3962fe64ba 100644 --- a/engines/fullpipe/module.mk +++ b/engines/fullpipe/module.mk @@ -52,6 +52,7 @@ MODULE_OBJS = \ scenes/scene26.o \ scenes/scene27.o \ scenes/scene28.o \ + scenes/scene29.o \ scenes/scene30.o \ scenes/scene31.o \ scenes/scene32.o \ diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 0881a19692..35da154570 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -159,10 +159,72 @@ void MctlCompound::freeItems() { _motionControllers[i]->_motionControllerObj->freeItems(); } -MessageQueue *MctlCompound::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - warning("STUB: MctlCompound::method34()"); +MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sourceY, int fuzzyMatch, int staticsId) { + int idx = -1; + int sourceIdx = -1; - return 0; + if (!ani) + return 0; + + for (uint i = 0; i < _motionControllers.size(); i++) { + if (_motionControllers[i]->_movGraphReactObj) { + if (_motionControllers[i]->_movGraphReactObj->pointInRegion(ani->_ox, ani->_oy)) { + idx = i; + break; + } + } + } + + for (uint i = 0; i < _motionControllers.size(); i++) { + if (_motionControllers[i]->_movGraphReactObj) { + if (_motionControllers[i]->_movGraphReactObj->pointInRegion(sourceX, sourceY)) { + sourceIdx = i; + break; + } + } + } + + if (idx == -1) + return 0; + + if (sourceIdx == -1) + return 0; + + if (idx == sourceIdx) + return _motionControllers[idx]->_motionControllerObj->method34(ani, sourceX, sourceY, fuzzyMatch, staticsId); + + MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &sourceIdx); + + if (!cp) + return 0; + + MessageQueue *mq = _motionControllers[idx]->_motionControllerObj->doWalkTo(ani, cp->_connectionX, cp->_connectionY, 1, cp->_field_14); + + if (!mq) + return 0; + + for (uint i = 0; i < cp->_messageQueueObj->getCount(); i++) { + ExCommand *ex = new ExCommand(cp->_messageQueueObj->getExCommandByIndex(i)); + + ex->_excFlags |= 2; + + mq->addExCommandToEnd(ex); + } + + ExCommand *ex = new ExCommand(ani->_id, 51, 0, sourceX, sourceY, 0, 1, 0, 0, 0); + + ex->_excFlags |= 2; + ex->_field_20 = fuzzyMatch; + ex->_keyCode = ani->_okeyCode; + + mq->addExCommandToEnd(ex); + + if (!mq->chain(ani)) { + delete mq; + return 0; + } + + return mq; } MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { @@ -598,6 +660,14 @@ void MovGraph::calcNodeDistancesAndAngles() { } } +int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) { + for (uint i = 0; i < _items.size(); i++) + if (_items[i]->ani == ani) + return i; + + return -1; +} + int MovGraph2::getItemIndexByGameObjectId(int objectId) { for (uint i = 0; i < _items2.size(); i++) if (_items2[i]->_objectId == objectId) @@ -1754,6 +1824,89 @@ void MGM::clear() { _items.clear(); } +MessageQueue *MGM::genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr) { + int idx = getItemIndexById(ani->_id); + + if (idx == -1) + return 0; + + int stid = staticsId; + + if (!staticsId) { + if (ani->_movement) { + stid = ani->_movement->_staticsObj2->_staticsId; + } else { + if (!ani->_statics) + return 0; + + stid = ani->_statics->_staticsId; + } + } + + if (stid == staticsIndex) + return new MessageQueue(g_fp->_globalMessageQueueList->compact()); + + int startidx = getStaticsIndexById(idx, stid); + int endidx = getStaticsIndexById(idx, staticsIndex); + int subidx = startidx + endidx * _items[idx]->statics.size(); + + if (!_items[idx]->subItems[subidx]->movement) { + clearMovements2(idx); + recalcOffsets(idx, startidx, endidx, 0, 1); + } + + if (!_items[idx]->subItems[subidx]->movement) + return 0; + + MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); + Common::Point point; + ExCommand *ex; + + int i = 0; + do { + subidx = startidx + endidx * _items[idx]->statics.size(); + + _items[idx]->subItems[subidx]->movement->calcSomeXY(point, 0); + + if (pointArr) { + int sz; + + if (_items[idx]->subItems[subidx]->movement->_currMovement) + sz = _items[idx]->subItems[subidx]->movement->_currMovement->_dynamicPhases.size(); + else + sz = _items[idx]->subItems[subidx]->movement->_dynamicPhases.size(); + + ex = new ExCommand2(20, ani->_id, &pointArr[i], sz); + + ex->_messageNum = _items[idx]->subItems[subidx]->movement->_id; + } else { + ex = new ExCommand(ani->_id, 1, _items[idx]->subItems[subidx]->movement->_id, 0, 0, 0, 1, 0, 0, 0); + } + + ex->_keyCode = ani->_okeyCode; + ex->_field_3C = 1; + ex->_field_24 = 1; + + mq->addExCommandToEnd(ex); + + if (resStatId) + *resStatId = _items[idx]->subItems[subidx]->movement->_id; + + startidx = _items[idx]->subItems[subidx]->staticsIndex; + + uint step; + + if (_items[idx]->subItems[subidx]->movement->_currMovement) + step = _items[idx]->subItems[subidx]->movement->_currMovement->_dynamicPhases.size(); + else + step = _items[idx]->subItems[subidx]->movement->_dynamicPhases.size(); + + i += step; + } while (startidx != endidx); + + return mq; +} + MGMItem::MGMItem() { objId = 0; } @@ -1811,15 +1964,10 @@ int MGM::getItemIndexById(int objId) { } MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { - warning("STUB: MGM::genMovement()"); - - return 0; - -#if 0 if (!mgminfo->ani) return 0; - mov = mgminfo->ani->_movement; + Movement *mov = mgminfo->ani->_movement; if (!mov && !mgminfo->ani->_statics) return 0; @@ -1831,14 +1979,17 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId; } + Common::Point point; + if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) { int nx = mgminfo->ani->_ox; int ny = mgminfo->ani->_oy; if (mgminfo->ani->_movement) { - mgminfo->ani->calcNextStep(&point2); - nx += point2.x; - ny += point2.y; + mgminfo->ani->calcNextStep(&point); + + nx += point.x; + ny += point.y; } if (!(mgminfo->flags & 0x10)) @@ -1853,40 +2004,37 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { if (!mov) return 0; - itemIdx = getItemIndexById(mgminfo->ani->_id); - subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1); - st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId); - st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId); - subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2); + int itemIdx = getItemIndexById(mgminfo->ani->_id); + int subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1); + int st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId); + int st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId); + int subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2); clearMovements2(itemIdx); recalcOffsets(itemIdx, subIdx, st2idx, 0, 1); clearMovements2(itemIdx); recalcOffsets(itemIdx, st1idx, subOffset, 0, 1); - v71 = (Message *)(28 * itemIdx); - v16 = items[itemIdx].objId; - v17 = *(_DWORD *)(v16 + offsetof(MGMItem, staticsListCount)); - off = *(_DWORD *)(v16 + offsetof(MGMItem, subItems)); - v18 = (MGMSubItem *)(off + 24 * (subIdx + st2idx * v17)); - x1 = (int)&v18->movement->go.CObject.vmt; - v19 = (MGMSubItem *)(off + 24 * (st1idx + subOffset * v17)); - v69 = (LONG)&v19->movement->go.CObject.vmt; + MGMSubItem *sub1 = _items[itemIdx]->subItems[subIdx + st2idx * _items[itemIdx]->statics.size()]; + MGMSubItem *sub2 = _items[itemIdx]->subItems[st1idx + subOffset * _items[itemIdx]->statics.size()]; - if (subIdx != st2idx && !x1) + if (subIdx != st2idx && !sub1->movement) return 0; - if (st1idx != subOffset && !v69) + if (st1idx != subOffset && !sub2->movement) return 0; - int n1x = mgminfo->x1 - mgminfo->x2 - v18->x - v19->x; - int n1y = mgminfo->y1 - mgminfo->y2 - v18->y - v19->y; + int n1x = mgminfo->x1 - mgminfo->x2 - sub1->x - sub2->x; + int n1y = mgminfo->y1 - mgminfo->y2 - sub1->y - sub2->y; - mov->calcSomeXY(&point1, 0); + Common::Point point1; + + mov->calcSomeXY(point1, 0); int n2x = point1.x; int n2y = point1.y; int mult; + int len; if (mgminfo->flags & 0x40) { mult = mgminfo->field_10; @@ -1903,20 +2051,20 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { len = -1; n2x = mult * point1.x; n1x = mult * point1.x; - mgminfo->x1 = mgminfo->x2 + mult * point1.x + v18->x + v19->x; + mgminfo->x1 = mgminfo->x2 + mult * point1.x + sub1->x + sub2->x; } if (!(mgminfo->flags & 4)) { n2y = mult * point1.y; n1y = mult * point1.y; len = -1; - mgminfo->y1 = mgminfo->y2 + mult * point1.y + v18->y + v19->y; + mgminfo->y1 = mgminfo->y2 + mult * point1.y + sub1->y + sub2->y; } int px = 0; int py = 0; - if (x1) { + if (sub1->movement) { px = countPhases(itemIdx, subIdx, st2idx, 1); py = countPhases(itemIdx, subIdx, st2idx, 2); } @@ -1931,13 +2079,14 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { py += mov->countPhasesWithFlag(len, 2); } - if (v69) { + if (sub2->movement) { px += countPhases(itemIdx, st1idx, subOffset, 1); py += countPhases(itemIdx, st1idx, subOffset, 2); } int dx1 = n1x - n2x; int dy1 = n1y - n2y; + int x1, y1; if (px) { x1 = (int)((double)dx1 / (double)px); @@ -1951,6 +2100,8 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { y1 = 0; } + Common::Point x2, y2; + y2.x = dx1 - px * x1; y2.y = dy1 - py * y1; @@ -1967,16 +2118,19 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); ExCommand2 *ex2; - for (v42 = subIdx; v42 != st2idx; v42 = v43->staticsIndex) { - v43 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[v42 + st2idx * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)]; - ex2 = buildExCommand2(v43->movement, mgminfo->ani->go._id, x1, y1, &x2, &y2, -1); + for (int i = subIdx; i != st2idx;) { + MGMSubItem *s = _items[itemIdx]->subItems[i + subOffset * _items[itemIdx]->statics.size()]; + + ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); ex2->_parId = mq->_id; ex2->_keyCode = mgminfo->ani->_okeyCode; mq->addExCommandToEnd(ex2); + + i = s->staticsIndex; } - for (i = 0; i < mult; ++i) { + for (int i = 0; i < mult; ++i) { int plen; if (i == mult - 1) @@ -1991,14 +2145,16 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { mq->addExCommandToEnd(ex2); } - for (j = st1idx; j != subOffset; j = v50->staticsIndex) { - v50 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[j + subOffset * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)]; + for (int j = st1idx; j != subOffset;) { + MGMSubItem *s = _items[itemIdx]->subItems[j + subOffset * _items[itemIdx]->statics.size()]; - ex2 = buildExCommand2(v50->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); + ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); ex2->_parId = mq->_id; ex2->_keyCode = mgminfo->ani->_okeyCode; mq->addExCommandToEnd(ex2); + + j = s->staticsIndex; } ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0); @@ -2011,9 +2167,25 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { mq->addExCommandToEnd(ex); return mq; -#endif } +int MGM::countPhases(int idx, int subIdx, int endIdx, int flag) { + int res = 0; + + if (endIdx < 0) + return 0; + + while (subIdx != endIdx) { + if (subIdx < 0) + break; + + res += _items[idx]->subItems[subIdx + endIdx * _items[idx]->statics.size()]->movement->countPhasesWithFlag(-1, flag); + + subIdx = _items[idx]->subItems[subIdx + 6 * endIdx * _items[idx]->statics.size()]->staticsIndex; + } + + return res; +} void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) { if (getItemIndexById(ani->_id) == -1) return; @@ -2112,9 +2284,99 @@ void MGM::clearMovements2(int idx) { } int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { - warning("STUB: MGM::recalcOffsets()"); + MGMItem *item = _items[idx]; + int subIdx = st1idx + st2idx * item->statics.size(); - return 0; + if (st1idx == st2idx) { + memset(&item->subItems[subIdx], 0, sizeof(item->subItems[subIdx])); + return 0; + } + + if (item->subItems[subIdx]) + return item->subItems[subIdx]->field_8; + + Common::Point point; + + for (uint i = 0; i < item->movements1.size(); i++) { + Movement *mov = item->movements1[i]; + + if (mov->_staticsObj1 == item->statics[st1idx]) { + if (!item->movements2[i] && (!flop || mov->_field_50)) { + item->movements2[i] = 1; + + int stidx = getStaticsIndex(idx, item->movements1[i]->_staticsObj2); + int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop); + int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + int newsz = sz + item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->field_C; + + if (recalc >= 0) { + if (!item->subItems[subIdx]->movement || item->subItems[subIdx]->field_8 > recalc + 1 || + (item->subItems[subIdx]->field_8 == recalc + 1 && item->subItems[subIdx]->field_C > newsz)) { + item->subItems[subIdx]->movement = mov; + item->subItems[subIdx]->staticsIndex = stidx; + item->subItems[subIdx]->field_8 = recalc + 1; + item->subItems[subIdx]->field_C = newsz; + + mov->calcSomeXY(point, 0); + + item->subItems[subIdx]->x = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->x + point.x; + item->subItems[subIdx]->y = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->y + point.y; + } + } + } + } else if (flip) { + if (mov->_staticsObj2 == item->statics[st1idx]) { + if (!item->movements2[i] && (!flop || mov->_field_50)) { + item->movements2[i] = 1; + + int stidx = getStaticsIndex(idx, mov->_staticsObj1); + int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop); + + if (recalc >= 0) { + if (!item->subItems[subIdx]->movement || item->subItems[subIdx]->field_8 > recalc + 1) { + item->subItems[subIdx]->movement = mov; + item->subItems[subIdx]->staticsIndex = stidx; + item->subItems[subIdx]->field_8 = recalc + 1; + + int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + + item->subItems[subIdx]->field_C = sz + item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->field_C; + + mov->calcSomeXY(point, 0); + + item->subItems[subIdx]->x = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->x - point.x; + item->subItems[subIdx]->y = item->subItems[stidx + 6 * st2idx * _items[idx]->statics.size()]->y - point.y; + } + } + } + } + } + } + + if (item->subItems[subIdx]->movement) + return item->subItems[subIdx]->field_8; + + return -1; +} + +int MGM::refreshOffsets(int objectId, int idx1, int idx2) { + int idx = getItemIndexById(objectId); + + if (idx != -1) { + int from = getStaticsIndexById(idx, idx1); + int to = getStaticsIndexById(idx, idx2); + + MGMSubItem *sub = _items[idx]->subItems[from + to * _items[idx]->statics.size()]; + + if (sub->movement) { + idx = sub->field_8; + } else { + clearMovements2(idx); + idx = recalcOffsets(idx, from, to, 0, 1); + } + } + + return idx; } Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) { diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index a9695e8094..4d92fd7fed 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -138,7 +138,7 @@ struct MGMItem { Common::Array<MGMSubItem *> subItems; Common::Array<Statics *> statics; Common::Array<Movement *> movements1; - Common::Array<Movement *> movements2; + Common::Array<int> movements2; MGMItem(); }; @@ -178,6 +178,9 @@ public: int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop); Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag); ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len); + MessageQueue *genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr); + int countPhases(int idx, int subIdx, int subOffset, int flag); + int refreshOffsets(int objectId, int idx1, int idx2); }; struct MctlLadderMovementVars { @@ -347,6 +350,7 @@ public: double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch); void calcNodeDistancesAndAngles(); MovGraphNode *calcOffset(int ox, int oy); + int getItemIndexByStaticAni(StaticANIObject *ani); }; class Movement; diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 147961b519..7420c1b1cf 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -378,6 +378,23 @@ Vars::Vars() { scene28_headBeardedFlipper = false; scene28_lift6inside = false; + scene29_porter = 0; + scene29_shooter1 = 0; + scene29_shooter2 = 0; + scene29_ass = 0; + scene29_manIsRiding = false; + scene29_arcadeIsOn = false; + scene29_reachedFarRight = false; + scene29_rideBackEnabled = false; + scene29_shootCountdown = 0; + scene29_shootDistance = 75; + scene29_manIsHit = 0; + scene29_scrollSpeed = 0; + scene29_scrollingDisabled = 0; + scene29_hitBall = 0; + scene29_manX = 0; + scene29_manY = 0; + scene30_leg = 0; scene30_liftFlag = 1; @@ -942,7 +959,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { _updateCursorCallback = scene28_updateCursor; break; -#if 0 case SC_29: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_29"); scene->preloadMovements(sceneVar); @@ -953,7 +969,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { addMessageHandler(sceneHandler29, 2); _updateCursorCallback = scene29_updateCursor; break; -#endif case SC_30: sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_30"); @@ -1091,10 +1106,6 @@ int defaultUpdateCursor() { return g_fp->_cursorId; } -void FullpipeEngine::processArcade(ExCommand *ex) { - warning("STUB: FullpipeEngine::processArcade()"); -} - void FullpipeEngine::updateMapPiece(int mapId, int update) { for (int i = 0; i < 200; i++) { int hiWord = (_mapTable[i] >> 16) & 0xffff; @@ -1450,5 +1461,31 @@ Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { return pTail; } +void BallChain::removeBall(Ball *ball) { + if (ball == pHead) + pHead = ball->p0; + else + ball->p1->p0 = ball->p0; + + if (ball == field_8) + field_8 = ball->p1; + else + ball->p0->p1 = ball->p1; + + ball->p0 = pTail; + pTail = ball; + + numBalls--; + + if (!numBalls) { + numBalls = 0; + pTail = 0; + field_8 = 0; + pHead = 0; + free(cPlex); + cPlex = 0; + } +} + } // End of namespace Fullpipe diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h index f99e76d157..0b7c4e7c8f 100644 --- a/engines/fullpipe/scenes.h +++ b/engines/fullpipe/scenes.h @@ -33,6 +33,7 @@ class MctlLadder; struct Ring; class StaticANIObject; struct Swinger; +struct WalkingBearder; int defaultUpdateCursor(); @@ -163,6 +164,10 @@ void scene28_initScene(Scene *sc); int sceneHandler28(ExCommand *ex); int scene28_updateCursor(); +int scene29_updateCursor(); +void scene29_initScene(Scene *sc); +int sceneHandler29(ExCommand *cmd); + int scene30_updateCursor(); void scene30_initScene(Scene *sc, int flag); int sceneHandler30(ExCommand *cmd); @@ -227,6 +232,7 @@ struct BallChain { void init(Ball **ball); Ball *sub04(Ball *ballP, Ball *ballN); + void removeBall(Ball *ball); void reset() { pHead = 0; pTail = 0; field_8 = 0; numBalls = 0; free(cPlex); cPlex = 0; cPlexLen = 0; } }; @@ -585,6 +591,29 @@ public: bool scene28_headBeardedFlipper; bool scene28_lift6inside; + StaticANIObject *scene29_porter; + StaticANIObject *scene29_shooter1; + StaticANIObject *scene29_shooter2; + StaticANIObject *scene29_ass; + BallChain scene29_balls; + BallChain scene29_redBalls; + BallChain scene29_flyingRedBalls; + BallChain scene29_greenBalls; + bool scene29_manIsRiding; + bool scene29_arcadeIsOn; + bool scene29_reachedFarRight; + bool scene29_rideBackEnabled; + int scene29_shootCountdown; + int scene29_shootDistance; + int scene29_manIsHit; + int scene29_scrollSpeed; + bool scene29_scrollingDisabled; + int scene29_hitBall; + Common::Array<WalkingBearder *> scene29_bearders; + int scene29_manX; + int scene29_manY; + MGM scene29_mgm; + StaticANIObject *scene30_leg; int scene30_liftFlag; diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp index 644b137d78..2d5127137d 100644 --- a/engines/fullpipe/scenes/scene29.cpp +++ b/engines/fullpipe/scenes/scene29.cpp @@ -36,213 +36,510 @@ namespace Fullpipe { +struct WalkingBearder { + StaticANIObject *ani; + int wbflag; + int wbcounter; +}; + void scene29_initScene(Scene *sc) { - g_vars->scene29_var01 = 300; - g_vars->scene29_var02 = 200; - g_vars->scene29_var03 = 400; - g_vars->scene29_var04 = 300; g_vars->scene29_porter = sc->getStaticANIObject1ById(ANI_PORTER, -1); g_vars->scene29_shooter1 = sc->getStaticANIObject1ById(ANI_SHOOTER1, -1); g_vars->scene29_shooter2 = sc->getStaticANIObject1ById(ANI_SHOOTER2, -1); g_vars->scene29_ass = sc->getStaticANIObject1ById(ANI_ASS, -1); - v2 = g_vars->scene29_var05.pHead; - if (g_vars->scene29_var05.pHead) { - do - v2 = v2->p0; - while ( v2 ); - } + g_vars->scene29_balls.numBalls = 0; + g_vars->scene29_balls.pTail = 0; + g_vars->scene29_balls.field_8 = 0; + g_vars->scene29_balls.pHead = 0; - g_vars->scene29_var05.numBalls = 0; - g_vars->scene29_var05.pTail = 0; - g_vars->scene29_var05.field_8 = 0; - g_vars->scene29_var05.pHead = 0; - CPlex::FreeDataChain(g_vars->scene29_var05.cPlex); - v3 = g_vars->scene29_var08.pHead; - g_vars->scene29_var05.cPlex = 0; - - if (g_vars->scene29_var08.pHead) { - do - v3 = v3->p0; - while (v3); - } + free(g_vars->scene29_balls.cPlex); + g_vars->scene29_balls.cPlex = 0; + + StaticANIObject *ani; + + g_vars->scene29_greenBalls.numBalls = 0; + g_vars->scene29_greenBalls.pTail = 0; + g_vars->scene29_greenBalls.field_8 = 0; + g_vars->scene29_greenBalls.pHead = 0; - g_vars->scene29_var08.numBalls = 0; - g_vars->scene29_var08.pTail = 0; - g_vars->scene29_var08.field_8 = 0; - g_vars->scene29_var08.pHead = 0; - CPlex::FreeDataChain(g_vars->scene29_var08.cPlex); - g_vars->scene29_var08.cPlex = 0; - v4 = Scene_getStaticANIObject1ById(sc, ANI_SHELL_GREEN, -1); - v5 = BallChain_sub04(&g_vars->scene29_var05, g_vars->scene29_var05.field_8, 0); - v5->ani = v4; - - if (g_vars->scene29_var05.field_8) - g_vars->scene29_var05.field_8->p0 = v5; + free(g_vars->scene29_greenBalls.cPlex); + g_vars->scene29_greenBalls.cPlex = 0; + + ani = sc->getStaticANIObject1ById(ANI_SHELL_GREEN, -1); + Ball *b = g_vars->scene29_balls.sub04(g_vars->scene29_balls.field_8, 0); + b->ani = ani; + + if (g_vars->scene29_balls.field_8) + g_vars->scene29_balls.field_8->p0 = b; else - g_vars->scene29_var05.pHead = v5; - g_vars->scene29_var05.field_8 = v5; - - v22 = 2; - do { - v7 = StaticANIObject_ctorCopy(v6, v4); - Scene_addStaticANIObject(sc, v7, 1); - v8 = BallChain_sub04(&g_vars->scene29_var05, g_vars->scene29_var05.field_8, 0); - v8->ani = v7; - - if (g_vars->scene29_var05.field_8) - g_vars->scene29_var05.field_8->p0 = v8; + g_vars->scene29_balls.pHead = b; + + g_vars->scene29_balls.field_8 = b; + + for (int i = 0; i < 2; i++) { + StaticANIObject *newani = new StaticANIObject(ani); + + sc->addStaticANIObject(newani, 1); + + b = g_vars->scene29_balls.sub04(g_vars->scene29_balls.field_8, 0); + b->ani = ani; + + if (g_vars->scene29_balls.field_8) + g_vars->scene29_balls.field_8->p0 = b; else - g_vars->scene29_var05.pHead = v8; - g_vars->scene29_var05.field_8 = v8; - --v22; - } while (v22); - - v9 = g_vars->scene29_var06.pHead; - if (g_vars->scene29_var06.pHead) { - do - v9 = v9->p0; - while (v9); - } + g_vars->scene29_balls.pHead = b; - g_vars->scene29_var06.numBalls = 0; - g_vars->scene29_var06.pTail = 0; - g_vars->scene29_var06.field_8 = 0; - g_vars->scene29_var06.pHead = 0; - CPlex::FreeDataChain(g_vars->scene29_var06.cPlex); - v10 = g_vars->scene29_var07.pHead; - g_vars->scene29_var06.cPlex = 0; - - if (g_vars->scene29_var07.pHead) { - do - v10 = v10->p0; - while (v10); + g_vars->scene29_balls.field_8 = b; } - g_vars->scene29_var07.numBalls = 0; - g_vars->scene29_var07.pTail = 0; - g_vars->scene29_var07.field_8 = 0; - g_vars->scene29_var07.pHead = 0; - CPlex::FreeDataChain(g_vars->scene29_var07.cPlex); - g_vars->scene29_var07.cPlex = 0; + g_vars->scene29_redBalls.numBalls = 0; + g_vars->scene29_redBalls.pTail = 0; + g_vars->scene29_redBalls.field_8 = 0; + g_vars->scene29_redBalls.pHead = 0; + + free(g_vars->scene29_redBalls.cPlex); + g_vars->scene29_redBalls.cPlex = 0; - v11 = Scene_getStaticANIObject1ById(sc, ANI_SHELL_RED, -1); - v12 = BallChain_sub04(&g_vars->scene29_var06, g_vars->scene29_var06.field_8, 0); - v12->ani = v11; + g_vars->scene29_flyingRedBalls.numBalls = 0; + g_vars->scene29_flyingRedBalls.pTail = 0; + g_vars->scene29_flyingRedBalls.field_8 = 0; + g_vars->scene29_flyingRedBalls.pHead = 0; - if (g_vars->scene29_var06.field_8) - g_vars->scene29_var06.field_8->p0 = v12; + free(g_vars->scene29_flyingRedBalls.cPlex); + g_vars->scene29_flyingRedBalls.cPlex = 0; + + ani = sc->getStaticANIObject1ById(ANI_SHELL_RED, -1); + + b = g_vars->scene29_redBalls.sub04(g_vars->scene29_redBalls.field_8, 0); + b->ani = ani; + + if (g_vars->scene29_redBalls.field_8) + g_vars->scene29_redBalls.field_8->p0 = b; else - g_vars->scene29_var06.pHead = v12; + g_vars->scene29_redBalls.pHead = b; + + g_vars->scene29_redBalls.field_8 = b; - g_vars->scene29_var06.field_8 = v12; + for (int i = 0; i < 2; i++) { + StaticANIObject *newani = new StaticANIObject(ani); - v23 = 2; + sc->addStaticANIObject(newani, 1); - do { - v14 = StaticANIObject_ctorCopy(v13, v11); - Scene_addStaticANIObject(sc, v14, 1); - v15 = BallChain_sub04(&g_vars->scene29_var06, g_vars->scene29_var06.field_8, 0); - v15->ani = v14; - if (g_vars->scene29_var06.field_8 ) - g_vars->scene29_var06.field_8->p0 = v15; + b = g_vars->scene29_redBalls.sub04(g_vars->scene29_redBalls.field_8, 0); + b->ani = ani; + + if (g_vars->scene29_redBalls.field_8) + g_vars->scene29_redBalls.field_8->p0 = b; else - g_vars->scene29_var06.pHead = v15; - g_vars->scene29_var06.field_8 = v15; - --v23; - } while ( v23 ); + g_vars->scene29_redBalls.pHead = b; + + g_vars->scene29_redBalls.field_8 = b; + } - ObArray_SetSize_0x0C((ObArray *)&g_vars->scene29_var19, 0, -1); + g_vars->scene29_bearders.clear(); - StaticANIObject *ani = new StaticANIObject(accessScene(SC_COMMON)->getStaticANIObject1ById(ANI_BEARDED_CMN, -1)); + ani = new StaticANIObject(g_fp->accessScene(SC_COMMON)->getStaticANIObject1ById(ANI_BEARDED_CMN, -1)); ani->_statics = ani->getStaticsById(ST_BRDCMN_EMPTY); sc->addStaticANIObject(ani, 1); - v20 = g_vars->scene29_var19.m_nSize; - ObArray_SetSize_0x0C((ObArray *)&g_vars->scene29_var19, g_vars->scene29_var19.m_nSize + 1, -1); - v21 = &g_vars->scene29_var19.m_pData[v20]; - v21->ani = v19; - v21->wbflag = 0; - v21->wbcounter = 0; - - g_vars->scene29_var09 = 0; - g_vars->scene29_var10 = 0; - g_vars->scene29_var11 = 0; - g_vars->scene29_var12 = 0; - g_vars->scene29_var13 = 0; - g_vars->scene29_var14 = 75; - g_vars->scene29_var15 = 0; - g_vars->scene29_var16 = 0; - g_vars->scene29_var17 = 0; - g_vars->scene29_var18 = 0; + WalkingBearder *wb = new WalkingBearder; + + wb->ani = ani; + wb->wbflag = 0; + wb->wbcounter = 0; + + g_vars->scene29_bearders.push_back(wb); + + g_vars->scene29_manIsRiding = false; + g_vars->scene29_arcadeIsOn = false; + g_vars->scene29_reachedFarRight = false; + g_vars->scene29_rideBackEnabled = false; + g_vars->scene29_shootCountdown = 0; + g_vars->scene29_shootDistance = 75; + g_vars->scene29_manIsHit = false; + g_vars->scene29_scrollSpeed = 0; + g_vars->scene29_scrollingDisabled = false; + g_vars->scene29_hitBall = 0; g_fp->setArcadeOverlay(PIC_CSR_ARCADE8); } void sceneHandler29_winArcade() { - warning("STUB: sceneHandler29_winArcade()"); + if (g_vars->scene29_shooter2->_flags & 4) { + g_vars->scene29_shootCountdown = 0; + + g_vars->scene29_shooter1->changeStatics2(ST_STR1_STAND); + g_vars->scene29_shooter2->changeStatics2(ST_STR2_STAND); + + g_vars->scene29_shooter2->_flags &= 0xFFFB; + + StaticANIObject *ani; + Ball *newball, *ball, *oldp0; + + while (g_vars->scene29_greenBalls.numBalls) { + ball = g_vars->scene29_greenBalls.pHead; + ani = g_vars->scene29_greenBalls.pHead->ani; + oldp0 = g_vars->scene29_greenBalls.pHead->p0; + g_vars->scene29_greenBalls.pHead = g_vars->scene29_greenBalls.pHead->p0; + + if (g_vars->scene29_greenBalls.pHead) + oldp0->p1 = 0; + else + g_vars->scene29_greenBalls.field_8 = 0; + + ball->p0 = g_vars->scene29_greenBalls.pTail; + g_vars->scene29_greenBalls.pTail = ball; + g_vars->scene29_greenBalls.numBalls--; + + if (!g_vars->scene29_greenBalls.numBalls) + g_vars->scene29_greenBalls.reset(); + + ani->hide(); + + newball = g_vars->scene29_balls.sub04(g_vars->scene29_balls.field_8, 0); + newball->ani = ani; + + if (g_vars->scene29_balls.field_8) + g_vars->scene29_balls.field_8->p0 = newball; + else + g_vars->scene29_balls.pHead = newball; + + g_vars->scene29_balls.field_8 = newball; + } + + while (g_vars->scene29_flyingRedBalls.numBalls) { + ball = g_vars->scene29_flyingRedBalls.pHead; + ani = g_vars->scene29_flyingRedBalls.pHead->ani; + oldp0 = g_vars->scene29_flyingRedBalls.pHead->p0; + g_vars->scene29_flyingRedBalls.pHead = g_vars->scene29_flyingRedBalls.pHead->p0; + + if (g_vars->scene29_flyingRedBalls.pHead) + oldp0->p1 = 0; + else + g_vars->scene29_flyingRedBalls.field_8 = 0; + + ball->p0 = g_vars->scene29_flyingRedBalls.pTail; + g_vars->scene29_flyingRedBalls.pTail = ball; + g_vars->scene29_flyingRedBalls.numBalls--; + + if (!g_vars->scene29_flyingRedBalls.numBalls) { + g_vars->scene29_flyingRedBalls.numBalls = 0; + g_vars->scene29_flyingRedBalls.pTail = 0; + g_vars->scene29_flyingRedBalls.field_8 = 0; + g_vars->scene29_flyingRedBalls.pHead = 0; + + free(g_vars->scene29_flyingRedBalls.cPlex); + + g_vars->scene29_flyingRedBalls.cPlex = 0; + } + + ani->hide(); + + newball = g_vars->scene29_redBalls.sub04(g_vars->scene29_redBalls.field_8, 0); + newball->ani = ani; + + if (g_vars->scene29_redBalls.field_8) + g_vars->scene29_redBalls.field_8->p0 = newball; + else + g_vars->scene29_redBalls.pHead = newball; + + g_vars->scene29_redBalls.field_8 = newball; + } + + g_vars->scene29_ass->queueMessageQueue(0); + g_vars->scene29_ass->_flags &= 0xFFFB; + + chainQueue(QU_SC29_ESCAPE, 1); + } + + g_fp->setObjectState(sO_LeftPipe_29, g_fp->getObjectEnumState(sO_LeftPipe_29, sO_IsOpened)); } void sceneHandler29_shootGreen() { - warning("STUB: sceneHandler29_shootGreen()"); + if (g_vars->scene29_balls.numBalls) { + int x = g_vars->scene29_shooter1->_ox - 113; + int y = g_vars->scene29_shooter1->_oy - 48; + StaticANIObject *ani = g_vars->scene29_balls.pHead->ani; + Ball *oldhead = g_vars->scene29_balls.pHead; + Ball *oldp0 = g_vars->scene29_balls.pHead->p0; + + g_vars->scene29_balls.pHead = g_vars->scene29_balls.pHead->p0; + + if (g_vars->scene29_balls.pHead) + oldp0->p1 = 0; + else + g_vars->scene29_balls.field_8 = 0; + + oldhead->p0 = g_vars->scene29_balls.pTail; + + g_vars->scene29_balls.pTail = oldhead; + g_vars->scene29_balls.numBalls--; + + if (!g_vars->scene29_balls.numBalls) { + g_vars->scene29_balls.numBalls = 0; + g_vars->scene29_balls.pTail = 0; + g_vars->scene29_balls.field_8 = 0; + g_vars->scene29_balls.pHead = 0; + + free(g_vars->scene29_balls.cPlex); + g_vars->scene29_balls.cPlex = 0; + } + + ani->show1(x, y, MV_SHG_NORM, 0); + ani->_priority = 5; + + Ball *runPtr = g_vars->scene29_greenBalls.pTail; + Ball *lastP = g_vars->scene29_greenBalls.field_8; + + if (!g_vars->scene29_greenBalls.pTail) { + g_vars->scene29_greenBalls.cPlex = (byte *)calloc(g_vars->scene29_greenBalls.cPlexLen, sizeof(Ball)); + + byte *p1 = g_vars->scene29_greenBalls.cPlex + (g_vars->scene29_greenBalls.cPlexLen - 1) * sizeof(Ball); + + if (g_vars->scene29_greenBalls.cPlexLen - 1 < 0) { + runPtr = g_vars->scene29_greenBalls.pTail; + } else { + runPtr = g_vars->scene29_greenBalls.pTail; + + for (int j = 0; j < g_vars->scene29_greenBalls.cPlexLen; j++) { + ((Ball *)p1)->p1 = runPtr; + runPtr = (Ball *)p1; + + p1 -= sizeof(Ball); + } + + g_vars->scene29_greenBalls.pTail = runPtr; + } + } + g_vars->scene29_greenBalls.pTail = runPtr->p0; + runPtr->p1 = lastP; + runPtr->p0 = 0; + runPtr->ani = ani; + + g_vars->scene29_greenBalls.numBalls++; + + if (g_vars->scene29_greenBalls.field_8) { + g_vars->scene29_greenBalls.field_8->p0 = runPtr; + g_vars->scene29_greenBalls.field_8 = runPtr; + } else { + g_vars->scene29_greenBalls.pHead = runPtr; + g_vars->scene29_greenBalls.field_8 = runPtr; + } + } } void sceneHandler29_shootRed() { - warning("STUB: sceneHandler29_shootRed()"); -} + if (g_vars->scene29_balls.numBalls) { + int x = g_vars->scene29_shooter1->_ox - 101; + int y = g_vars->scene29_shooter1->_oy - 14; + StaticANIObject *ani = g_vars->scene29_balls.pHead->ani; + Ball *oldhead = g_vars->scene29_balls.pHead; + Ball *oldp0 = g_vars->scene29_balls.pHead->p0; -void sceneHandler29_clickPorter(ExCommand *cmd) { - warning("STUB: sceneHandler29_clickPorter()"); + g_vars->scene29_balls.pHead = g_vars->scene29_balls.pHead->p0; + + if (g_vars->scene29_balls.pHead) + oldp0->p1 = 0; + else + g_vars->scene29_balls.field_8 = 0; + + oldhead->p0 = g_vars->scene29_balls.pTail; + + g_vars->scene29_balls.pTail = oldhead; + g_vars->scene29_balls.numBalls--; + + if (!g_vars->scene29_balls.numBalls) { + g_vars->scene29_balls.numBalls = 0; + g_vars->scene29_balls.pTail = 0; + g_vars->scene29_balls.field_8 = 0; + g_vars->scene29_balls.pHead = 0; + + free(g_vars->scene29_balls.cPlex); + g_vars->scene29_balls.cPlex = 0; + } + + ani->show1(x, y, MV_SHR_NORM, 0); + ani->_priority = 5; + + Ball *runPtr = g_vars->scene29_flyingRedBalls.pTail; + Ball *lastP = g_vars->scene29_flyingRedBalls.field_8; + + if (!g_vars->scene29_flyingRedBalls.pTail) { + g_vars->scene29_flyingRedBalls.cPlex = (byte *)calloc(g_vars->scene29_flyingRedBalls.cPlexLen, sizeof(Ball)); + + byte *p1 = g_vars->scene29_flyingRedBalls.cPlex + (g_vars->scene29_flyingRedBalls.cPlexLen - 1) * sizeof(Ball); + + if (g_vars->scene29_flyingRedBalls.cPlexLen - 1 < 0) { + runPtr = g_vars->scene29_flyingRedBalls.pTail; + } else { + runPtr = g_vars->scene29_flyingRedBalls.pTail; + + for (int j = 0; j < g_vars->scene29_flyingRedBalls.cPlexLen; j++) { + ((Ball *)p1)->p1 = runPtr; + runPtr = (Ball *)p1; + + p1 -= sizeof(Ball); + } + + g_vars->scene29_flyingRedBalls.pTail = runPtr; + } + } + g_vars->scene29_flyingRedBalls.pTail = runPtr->p0; + runPtr->p1 = lastP; + runPtr->p0 = 0; + runPtr->ani = ani; + + g_vars->scene29_flyingRedBalls.numBalls++; + + if (g_vars->scene29_flyingRedBalls.field_8) { + g_vars->scene29_flyingRedBalls.field_8->p0 = runPtr; + g_vars->scene29_flyingRedBalls.field_8 = runPtr; + } else { + g_vars->scene29_flyingRedBalls.pHead = runPtr; + g_vars->scene29_flyingRedBalls.field_8 = runPtr; + } + } } void sceneHandler29_manJump() { if (!g_fp->_aniMan->_movement || g_fp->_aniMan->_movement->_id == MV_MAN29_RUN || g_fp->_aniMan->_movement->_id == MV_MAN29_STANDUP) { - g_vars->scene29_var12 = 0; - g_vars->scene29_var15 = 0; - g_vars->scene29_var11 = 1; + g_vars->scene29_rideBackEnabled = false; + g_vars->scene29_manIsHit = false; + g_vars->scene29_reachedFarRight = true; g_fp->_aniMan->changeStatics2(ST_MAN29_RUNR); g_fp->_aniMan->startAnim(MV_MAN29_JUMP, 0, -1); } - g_vars->scene29_var20 = g_fp->_aniMan->_ox; - g_vars->scene29_var21 = g_fp->_aniMan->_oy; + g_vars->scene29_manX = g_fp->_aniMan->_ox; + g_vars->scene29_manY = g_fp->_aniMan->_oy; } void sceneHandler29_manBend() { if (!g_fp->_aniMan->_movement || g_fp->_aniMan->_movement->_id == MV_MAN29_RUN || g_fp->_aniMan->_movement->_id == MV_MAN29_STANDUP) { - g_vars->scene29_var12 = 0; - g_vars->scene29_var15 = 0; - g_vars->scene29_var11 = 1; + g_vars->scene29_rideBackEnabled = false; + g_vars->scene29_manIsHit = false; + g_vars->scene29_reachedFarRight = true; g_fp->_aniMan->changeStatics2(ST_MAN29_RUNR); g_fp->_aniMan->startAnim(MV_MAN29_BEND, 0, -1); } - g_vars->scene29_var20 = g_fp->_aniMan->_ox; - g_vars->scene29_var21 = g_fp->_aniMan->_oy; + g_vars->scene29_manX = g_fp->_aniMan->_ox; + g_vars->scene29_manY = g_fp->_aniMan->_oy; } -void sceneHandler29_sub03() { - warning("STUB: sceneHandler29_sub03()"); -} +bool sceneHandler29_checkRedBallHit(StaticANIObject *ani, int maxx) { + if (!g_vars->scene29_arcadeIsOn || g_vars->scene29_manIsHit) + return false; -void sceneHandler29_manFromL() { - warning("STUB: sceneHandler29_manFromL()"); + if ((ani->_ox >= g_vars->scene29_manX + 42 || ani->_ox <= g_vars->scene29_manX + 8) + && (ani->_ox < g_vars->scene29_manX + 8 || maxx > g_vars->scene29_manX + 27)) + return false; + + if (!g_fp->_aniMan->_movement) + return true; + + int phase = g_fp->_aniMan->_movement->_currDynamicPhaseIndex; + + if (g_fp->_aniMan->_movement->_id != MV_MAN29_BEND && g_fp->_aniMan->_movement->_id != MV_MAN29_RUN + && (g_fp->_aniMan->_movement->_id != MV_MAN29_JUMP || (phase >= 3 && phase <= 6))) + return false; + else + return true; } -void sceneHandler29_sub05() { - warning("STUB: sceneHandler29_sub05()"); +bool sceneHandler29_checkGreenBallHit(StaticANIObject *ani, int maxx) { + if (!g_vars->scene29_arcadeIsOn || g_vars->scene29_manIsHit) + return false; + + if (ani->_ox >= g_vars->scene29_manX + 40) { + if (maxx > g_vars->scene29_manX + 27) + return false; + } else { + if (ani->_ox <= g_vars->scene29_manX + 10) { + if (ani->_ox < g_vars->scene29_manX + 40) + return false; + + if (maxx > g_vars->scene29_manX + 27) + return false; + } + } + + if (!g_fp->_aniMan->_movement) + return true; + + if (g_fp->_aniMan->_movement->_id == MV_MAN29_JUMP) + return true; + + if (g_fp->_aniMan->_movement->_id == MV_MAN29_RUN) + return true; + + if (g_fp->_aniMan->_movement->_id == MV_MAN29_BEND) { + if (g_fp->_aniMan->_movement->_currDynamicPhaseIndex < 1 || g_fp->_aniMan->_movement->_currDynamicPhaseIndex > 5) + return true; + } + + return false; } -void sceneHandler29_shootersEscape() { - warning("STUB: sceneHandler29_shootersEscape()"); +void sceneHandler29_manHit() { + MGMInfo mgminfo; + + g_vars->scene29_manIsHit = true; + + g_fp->_aniMan->changeStatics2(ST_MAN29_RUNR); + g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY); + + mgminfo.ani = g_fp->_aniMan; + mgminfo.staticsId2 = ST_MAN29_SITR; + mgminfo.y1 = 463; + mgminfo.x1 = g_vars->scene29_manX <= 638 ? 351 : 0; + mgminfo.field_1C = 10; + mgminfo.field_10 = 1; + mgminfo.flags = (g_vars->scene29_manX <= 638 ? 2 : 0) | 0x44; + mgminfo.movementId = MV_MAN29_HIT; + + MessageQueue *mq = g_vars->scene29_mgm.genMovement(&mgminfo); + ExCommand *ex; + + if (mq) { + if (g_vars->scene29_manX <= 638) { + ex = new ExCommand(ANI_MAN, 1, MV_MAN29_STANDUP_NORM, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags = 2; + ex->_keyCode = g_fp->_aniMan->_okeyCode; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(0, 17, MSG_SC29_STOPRIDE, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags = 2; + mq->addExCommandToEnd(ex); + + g_vars->scene29_manIsRiding = false; + g_vars->scene29_arcadeIsOn = false; + g_vars->scene29_reachedFarRight = false; + g_vars->scene29_rideBackEnabled = false; + } else { + ex = new ExCommand(ANI_MAN, 1, MV_MAN29_STANDUP, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags = 2; + ex->_keyCode = g_fp->_aniMan->_okeyCode; + mq->addExCommandToEnd(ex); + } + + mq->setFlags(mq->getFlags() | 1); + + if (!mq->chain(g_fp->_aniMan)) + delete mq; + } } -void sceneHandler29_sub07() { - warning("STUB: sceneHandler29_sub07()"); +void sceneHandler29_assHitRed() { + if (g_vars->scene29_ass->_statics->_staticsId == ST_ASS_NORM) { + g_vars->scene29_ass->changeStatics2(ST_ASS_NORM); + g_vars->scene29_ass->startAnim(MV_ASS_HITRED, 0, -1); + } } void sceneHandler29_assHitGreen() { @@ -252,19 +549,405 @@ void sceneHandler29_assHitGreen() { } } -void sceneHandler29_assHitRed() { - if (g_vars->scene29_ass->_statics->_staticsId == ST_ASS_NORM) { - g_vars->scene29_ass->changeStatics2(ST_ASS_NORM); - g_vars->scene29_ass->startAnim(MV_ASS_HITRED, 0, -1); +void sceneHandler29_ballHitCheck() { + Ball *ball = g_vars->scene29_greenBalls.pHead; + Ball *newball; + int x, y; + + while (ball) { + x = ball->ani->_ox - 30; + y = ball->ani->_oy; + + if (x >= 186) { + if (sceneHandler29_checkGreenBallHit(ball->ani, x)) { + newball = g_vars->scene29_balls.sub04(g_vars->scene29_balls.field_8, 0); + newball->ani = ball->ani; + + if (g_vars->scene29_balls.field_8) + g_vars->scene29_balls.field_8->p0 = newball; + else + g_vars->scene29_balls.pHead = newball; + + g_vars->scene29_balls.field_8 = newball; + + if (ball == g_vars->scene29_greenBalls.pHead) + g_vars->scene29_greenBalls.pHead = ball->p0; + else + ball->p1->p0 = ball->p0; + + if (ball == g_vars->scene29_greenBalls.field_8) + g_vars->scene29_greenBalls.field_8 = ball->p1; + else + ball->p0->p1 = ball->p1; + + g_vars->scene29_greenBalls.init(&ball); + + sceneHandler29_manHit(); + + g_fp->playSound(SND_29_014, 0); + + ball->ani->startAnim(MV_SHG_HITMAN, 0, -1); + + g_vars->scene29_hitBall = ball->ani->_id; + } else { + ball->ani->setOXY(x, y); + } + } else { + newball = g_vars->scene29_balls.sub04(g_vars->scene29_balls.field_8, 0); + newball->ani = ball->ani; + + if (g_vars->scene29_balls.field_8) + g_vars->scene29_balls.field_8->p0 = newball; + else + g_vars->scene29_balls.pHead = newball; + + g_vars->scene29_balls.field_8 = newball; + + ball->ani->hide(); + + if (ball == g_vars->scene29_greenBalls.pHead) + g_vars->scene29_greenBalls.pHead = ball->p0; + else + ball->p1->p0 = ball->p0; + + if (ball == g_vars->scene29_greenBalls.field_8) + g_vars->scene29_greenBalls.field_8 = ball->p1; + else + ball->p0->p1 = ball->p1; + + g_vars->scene29_greenBalls.init(&ball); + + sceneHandler29_assHitGreen(); + } + + ball = ball->p0; + } + + ball = g_vars->scene29_flyingRedBalls.pHead; + + while (ball) { + x = ball->ani->_ox - 30; + y = ball->ani->_oy; + + if (x >= 147) { + if (sceneHandler29_checkRedBallHit(ball->ani, x)) { + newball = g_vars->scene29_redBalls.sub04(g_vars->scene29_redBalls.field_8, 0); + newball->ani = ball->ani; + + if (g_vars->scene29_redBalls.field_8) + g_vars->scene29_redBalls.field_8->p0 = newball; + else + g_vars->scene29_redBalls.pHead = newball; + + g_vars->scene29_redBalls.field_8 = newball; + + g_vars->scene29_flyingRedBalls.removeBall(ball); + + sceneHandler29_manHit(); + + g_fp->playSound(SND_29_027, 0); + + ball->ani->startAnim(MV_SHR_HITMAN, 0, -1); + + g_vars->scene29_hitBall = ball->ani->_id; + } else { + ball->ani->setOXY(x, y); + } + } else { + newball = g_vars->scene29_redBalls.sub04(g_vars->scene29_redBalls.field_8, 0); + newball->ani = ball->ani; + + if (g_vars->scene29_redBalls.field_8) + g_vars->scene29_redBalls.field_8->p0 = newball; + else + g_vars->scene29_redBalls.pHead = newball; + + g_vars->scene29_redBalls.field_8 = newball; + + ball->ani->hide(); + + if (ball == g_vars->scene29_flyingRedBalls.pHead) + g_vars->scene29_flyingRedBalls.pHead = ball->p0; + else + ball->p1->p0 = ball->p0; + + if (ball == g_vars->scene29_flyingRedBalls.field_8) + g_vars->scene29_flyingRedBalls.field_8 = ball->p1; + else + ball->p0->p1 = ball->p1; + + g_vars->scene29_flyingRedBalls.init(&ball); + + sceneHandler29_assHitRed(); + } + + ball = ball->p0; + } +} + +void sceneHandler29_manFromL() { + if (g_vars->scene29_manX < 497 && !g_vars->scene29_scrollingDisabled) { + getCurrSceneSc2MotionController()->setEnabled(); + getGameLoaderInteractionController()->enableFlag24(); + + g_fp->_aniMan->changeStatics2(ST_MAN_RIGHT | 0x4000); + chainQueue(QU_SC29_MANFROM_L, 1); + + g_vars->scene29_scrollingDisabled = true; + + g_fp->_scrollSpeed = g_vars->scene29_scrollSpeed; } } +void sceneHandler29_manFromR() { + getCurrSceneSc2MotionController()->setEnabled(); + getGameLoaderInteractionController()->enableFlag24(); + + chainQueue(QU_SC29_MANFROM_R, 1); + + g_vars->scene29_arcadeIsOn = false; + g_vars->scene29_rideBackEnabled = false; +} + +int sceneHandler29_updateScreenCallback() { + int res; + + res = g_fp->drawArcadeOverlay(g_vars->scene29_arcadeIsOn); + + if (!res) + g_fp->_updateScreenCallback = 0; + + return res; +} + +void sceneHandler29_manToL() { + getCurrSceneSc2MotionController()->clearEnabled(); + getGameLoaderInteractionController()->disableFlag24(); + + chainQueue(QU_SC29_MANTO_L, 1); + + g_vars->scene29_arcadeIsOn = true; + + g_vars->scene29_mgm.addItem(g_fp->_aniMan->_id); + + g_fp->_updateScreenCallback = sceneHandler29_updateScreenCallback; + + g_fp->_msgY = -1; + g_fp->_msgX = -1; +} + +void sceneHandler29_manToR() { + getCurrSceneSc2MotionController()->clearEnabled(); + getGameLoaderInteractionController()->disableFlag24(); + + chainQueue(QU_SC29_MANTO_R, 1); + + g_vars->scene29_manIsRiding = true; + g_fp->_msgY = -1; + g_fp->_msgX = -1; + + g_vars->scene29_scrollingDisabled = false; + + g_vars->scene29_scrollSpeed = g_fp->_scrollSpeed; + g_fp->_scrollSpeed = 4; +} + +void sceneHandler29_clickPorter(ExCommand *cmd) { + if (!g_fp->_aniMan->isIdle() || g_fp->_aniMan->_flags & 0x100) { + cmd->_messageKind = 0; + + return; + } + + if (g_vars->scene29_manX <= g_vars->scene29_porter->_ox) { + if (ABS(351 - g_vars->scene29_manX) > 1 || ABS(443 - g_vars->scene29_manY) > 1 + || g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) { + if (g_fp->_msgX != 351 || g_fp->_msgY != 443) { + MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 351, 443, 1, ST_MAN_RIGHT); + + if (mq) { + mq->addExCommandToEnd(cmd->createClone()); + + postExCommand(g_fp->_aniMan->_id, 2, 351, 443, 0, -1); + } + } + } else { + sceneHandler29_manToL(); + } + } else { + g_vars->scene29_manX = g_fp->_aniMan->_ox; + g_vars->scene29_manY = g_fp->_aniMan->_oy; + + if (ABS(1582 - g_vars->scene29_manX) > 1 || ABS(445 - g_fp->_aniMan->_oy) > 1 + || g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != (0x4000 | ST_MAN_RIGHT)) { + if (g_fp->_msgX != 1582 || g_fp->_msgY != 445) { + MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 1582, 445, 1, (0x4000 | ST_MAN_RIGHT)); + + if (mq) { + mq->addExCommandToEnd(cmd->createClone()); + + postExCommand(g_fp->_aniMan->_id, 2, 1582, 445, 0, -1); + } + } + } else { + sceneHandler29_manToR(); + } + } +} + +void sceneHandler29_shootersProcess() { + if (g_fp->_aniMan->_statics->_staticsId == ST_MAN29_RUNR) { + if (g_vars->scene29_manX > 1436) { + sceneHandler29_manFromR(); + } else { + g_vars->scene29_shootDistance = (1310 - g_vars->scene29_manX) * 5213 / 100000 + 25; + + if (!g_vars->scene29_manIsHit) + g_fp->_aniMan->startAnim(MV_MAN29_RUN, 0, -1); + } + } + + g_vars->scene29_manX = g_fp->_aniMan->_ox; + g_vars->scene29_manY = g_fp->_aniMan->_oy; +} + +void sceneHandler29_shootersEscape() { + if (g_vars->scene29_arcadeIsOn) { + g_vars->scene29_manX += 2; + + g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY); + + if (g_vars->scene29_manX > 1310 && !g_vars->scene29_shooter1->_movement && !g_vars->scene29_shooter2->_movement + && g_vars->scene29_shooter1->_statics->_staticsId == ST_STR1_RIGHT) { + g_vars->scene29_shootCountdown = 0; + + g_vars->scene29_shooter1->changeStatics2(ST_STR1_STAND); + g_vars->scene29_shooter2->changeStatics2(ST_STR2_STAND); + + chainQueue(QU_SC29_ESCAPE, 1); + + g_vars->scene29_ass->queueMessageQueue(0); + g_vars->scene29_ass->hide(); + + g_fp->setObjectState(sO_LeftPipe_29, g_fp->getObjectEnumState(sO_LeftPipe_29, sO_IsOpened)); + } + } else if (g_vars->scene29_manIsRiding) { + g_vars->scene29_manX -= 4; + + g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY); + } +} + +void sceneHandler29_manRideBack() { + g_vars->scene29_manX -= 2; + + g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY); +} + void sceneHandler29_shoot() { - warning("STUB: sceneHandler29_shoot()"); + if (g_vars->scene29_arcadeIsOn && g_vars->scene29_manX < 1310) { + if (g_fp->_rnd->getRandomNumber(1) || g_vars->scene29_shooter1->_movement || g_vars->scene29_shooter1->_statics->_staticsId != ST_STR1_RIGHT) { + if (!g_vars->scene29_shooter2->_movement && g_vars->scene29_shooter2->_statics->_staticsId == ST_STR2_RIGHT) { + if (g_vars->scene29_shooter2->_flags & 4) { + g_vars->scene29_shooter2->startAnim(MV_STR2_SHOOT, 0, -1); + + g_vars->scene29_shootCountdown = 0; + } + } + } else { + g_vars->scene29_shooter1->startAnim(MV_STR1_SHOOT, 0, -1); + + g_vars->scene29_shootCountdown = 0; + } + } } void sceneHandler29_animBearded() { - warning("STUB: sceneHandler29_animBearded()"); + MessageQueue *mq; + + for (uint i = 0; i < g_vars->scene29_bearders.size(); i++) { + StaticANIObject *ani = g_vars->scene29_bearders[i]->ani; + + if (g_vars->scene29_bearders[i]->wbflag) { + int x = ani->_ox; + int y = ani->_oy; + + if (!ani->_movement && ani->_statics->_staticsId == (ST_BRDCMN_RIGHT | 0x4000)) { + x -= 4; + + if (x - g_vars->scene29_manX < 100 || !g_vars->scene29_arcadeIsOn) { + mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC29_BRDOUT1), 0, 1); + + mq->replaceKeyCode(-1, ani->_okeyCode); + mq->chain(0); + + g_vars->scene29_bearders[i]->wbflag = 0; + g_vars->scene29_bearders[i]->wbcounter = 0; + } + } + + if (!ani->_movement && ani->_statics->_staticsId == ST_BRDCMN_GOR) + ani->startAnim(MV_BRDCMN_GOR, 0, -1); + + if (ani->_movement) { + if (ani->_movement->_id == MV_BRDCMN_GOR) { + x -= 4; + + if (g_vars->scene29_manX - x < 60 || x - g_vars->scene29_manX < -260 || !g_vars->scene29_arcadeIsOn) { + ani->changeStatics2(ST_BRDCMN_RIGHT); + + mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC29_BRDOUT2), 0, 1); + + mq->replaceKeyCode(-1, ani->_okeyCode); + mq->chain(0); + + g_vars->scene29_bearders[i]->wbflag = 0; + g_vars->scene29_bearders[i]->wbcounter = 0; + } + } + } + + ani->setOXY(x, y); + continue; + } + + if (g_vars->scene29_arcadeIsOn && g_vars->scene29_bearders[i]->wbcounter > 30) { + int newx; + + if (g_fp->_rnd->getRandomNumber(1)) + goto dostuff; + + if (g_vars->scene29_manX <= 700) { + g_vars->scene29_bearders[i]->wbcounter++; + continue; + } + + if (g_vars->scene29_manX >= 1100) { + dostuff: + if (g_vars->scene29_manX <= 700 || g_vars->scene29_manX >= 1350) { + g_vars->scene29_bearders[i]->wbcounter++; + continue; + } + + mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC29_BRD2), 0, 1); + + newx = g_vars->scene29_manX - 200; + } else { + mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC29_BRD1), 0, 1); + + newx = g_vars->scene29_manX + 350; + } + + mq->getExCommandByIndex(0)->_x = newx; + mq->replaceKeyCode(-1, ani->_okeyCode); + mq->chain(0); + + g_vars->scene29_bearders[i]->wbflag = 1; + g_vars->scene29_bearders[i]->wbcounter = 0; + } + + g_vars->scene29_bearders[i]->wbcounter++; + } } @@ -279,19 +962,19 @@ int sceneHandler29(ExCommand *cmd) { break; case MSG_SC29_LAUGH: - if (g_vars->scene29_var18 == ANI_SHELL_GREEN) { - playSound(SND_29_028, 0); + if (g_vars->scene29_hitBall == ANI_SHELL_GREEN) { + g_fp->playSound(SND_29_028, 0); break; } - playSound(SND_29_029, 0); + g_fp->playSound(SND_29_029, 0); break; case MSG_SC29_SHOWLASTRED: - if (g_vars->scene29_var05.numBalls) { - g_vars->scene29_var06.field_8->ani->show1(-1, -1, -1, 0); - g_vars->scene29_var06.field_8->ani->startAnim(MV_SHR_HITASS, 0, -1); + if (g_vars->scene29_balls.numBalls) { + g_vars->scene29_redBalls.field_8->ani->show1(-1, -1, -1, 0); + g_vars->scene29_redBalls.field_8->ani->startAnim(MV_SHR_HITASS, 0, -1); } break; @@ -305,46 +988,48 @@ int sceneHandler29(ExCommand *cmd) { break; case MSG_SC29_SHOWLASTGREEN: - if (g_vars->scene29_var05.numBalls) { - g_vars->scene29_var05.field_8->ani->show1(-1, -1, (Objects)-1, 0); - g_vars->scene29_var05.field_8->ani->startAnim(MV_SHG_HITASS, 0, -1); + if (g_vars->scene29_balls.numBalls) { + g_vars->scene29_balls.field_8->ani->show1(-1, -1, -1, 0); + g_vars->scene29_balls.field_8->ani->startAnim(MV_SHG_HITASS, 0, -1); } break; case MSG_SC29_STOPRIDE: - g_vars->scene29_var09 = 0; - g_vars->scene29_var10 = 0; - g_vars->scene29_var11 = 0; - g_vars->scene29_var12 = 0; + g_vars->scene29_manIsRiding = false; + g_vars->scene29_arcadeIsOn = false; + g_vars->scene29_reachedFarRight = false; + g_vars->scene29_rideBackEnabled = false; getCurrSceneSc2MotionController()->setEnabled(); getGameLoaderInteractionController()->enableFlag24(); break; - case MSG_SC29_STOPRIDE: - g_vars->scene29_var12 = 0; + case MSG_SC29_DISABLERIDEBACK: + g_vars->scene29_rideBackEnabled = false; break; - case MSG_SC29_DISABLERIDEBACK: - g_vars->scene29_var12 = 1; - // fall through + case MSG_SC29_ENABLERIDEBACK: + g_vars->scene29_rideBackEnabled = true; + g_vars->scene29_reachedFarRight = false; + break; case MSG_SC29_DISABLEPORTER: - g_vars->scene29_var11 = 0; + g_vars->scene29_reachedFarRight = false; break; case MSG_SC29_ENABLEPORTER: - g_vars->scene29_var11 = 1; - g_vars->scene29_var12 = 0; - g_vars->scene29_var15 = 0; + g_vars->scene29_reachedFarRight = true; + g_vars->scene29_rideBackEnabled = false; + g_vars->scene29_manIsHit = false; break; case 29: - if (!g_vars->scene29_var09 || g_vars->scene29_var10) { - if (!g_vars->scene29_var10) { - v6 = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y); - if (v6 && v6 == g_vars->scene29_porter) { + if (!g_vars->scene29_manIsRiding || g_vars->scene29_arcadeIsOn) { + if (!g_vars->scene29_arcadeIsOn) { + StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y); + + if (ani && ani == g_vars->scene29_porter) { sceneHandler29_clickPorter(cmd); cmd->_messageKind = 0; @@ -361,61 +1046,56 @@ int sceneHandler29(ExCommand *cmd) { break; case 107: - if (g_vars->scene29_var10) + if (g_vars->scene29_arcadeIsOn) sceneHandler29_manBend(); break; case 33: - if (g_vars->scene29_var10) { - v5 = g_vars->scene29_var20; - if (g_vars->scene29_var20 > g_fp->_sceneRect.right - 500) { - g_fp->_currentScene->_x = g_fp->_sceneRect.right - g_vars->scene29_var20 - 350; - v5 = g_vars->scene29_var20; - } + if (g_vars->scene29_arcadeIsOn) { + if (g_vars->scene29_manX > g_fp->_sceneRect.right - 500) + g_fp->_currentScene->_x = g_fp->_sceneRect.right - g_vars->scene29_manX - 350; - if (v5 < g_sceneRect.left + 100) - g_fp->_currentScene->_x = v5 - g_fp->_sceneRect.left - 100; + if (g_vars->scene29_manX < g_fp->_sceneRect.left + 100) + g_fp->_currentScene->_x = g_vars->scene29_manX - g_fp->_sceneRect.left - 100; } else if (g_fp->_aniMan2) { int x = g_fp->_aniMan2->_ox; - if (x < g_fp->_sceneRect.left + g_vars->scene29_var01) - g_fp->_currentScene->_x = x - g_vars->scene29_var03 - g_fp->_sceneRect.left; + if (x < g_fp->_sceneRect.left + 300) + g_fp->_currentScene->_x = x - 400 - g_fp->_sceneRect.left; - if (x > g_fp->_sceneRect.right - g_vars->scene29_var01) - g_fp->_currentScene->_x = x + g_vars->scene29_var03 - g_fp->_sceneRect.right; + if (x > g_fp->_sceneRect.right - 300) + g_fp->_currentScene->_x = x + 400 - g_fp->_sceneRect.right; } - g_vars->scene29_var20 = g_fp->_aniMan->_ox; - g_vars->scene29_var21 = g_fp->_aniMan->_oy; + g_vars->scene29_manX = g_fp->_aniMan->_ox; + g_vars->scene29_manY = g_fp->_aniMan->_oy; - sceneHandler29_sub03(); + sceneHandler29_ballHitCheck(); if (!g_vars->scene29_porter->_movement) g_vars->scene29_porter->startAnim(MV_PTR_MOVEFAST, 0, -1); - if (g_vars->scene29_var09) { + if (g_vars->scene29_manIsRiding) sceneHandler29_manFromL(); + else if (g_vars->scene29_arcadeIsOn && !g_fp->_aniMan->_movement) + sceneHandler29_shootersProcess(); - } else if (g_vars->scene29_var10 && !g_aniMan->_movement) { - sceneHandler29_sub05(); - } - - if (g_vars->scene29_var11) + if (g_vars->scene29_reachedFarRight) sceneHandler29_shootersEscape(); - else if (g_vars->scene29_var12) - sceneHandler29_sub07(); + else if (g_vars->scene29_rideBackEnabled) + sceneHandler29_manRideBack(); - g_vars->scene29_var13++; + g_vars->scene29_shootCountdown++; - if (g_vars->scene29_var13 > g_vars->scene29_var14) + if (g_vars->scene29_shootCountdown > g_vars->scene29_shootDistance) sceneHandler29_shoot(); sceneHandler29_animBearded(); g_fp->_behaviorManager->updateBehaviors(); - startSceneTrack(); + g_fp->startSceneTrack(); break; } @@ -423,4 +1103,23 @@ int sceneHandler29(ExCommand *cmd) { return 0; } +int scene29_updateCursor() { + g_fp->updateCursorCommon(); + + if (g_vars->scene29_arcadeIsOn) { + if (g_fp->_cursorId != PIC_CSR_DEFAULT_INV && g_fp->_cursorId != PIC_CSR_ITN_INV) + g_fp->_cursorId = -1; + } else if (g_vars->scene29_manIsRiding) { + if (g_fp->_cursorId != PIC_CSR_DEFAULT_INV && g_fp->_cursorId != PIC_CSR_ITN_INV) + g_fp->_cursorId = PIC_CSR_DEFAULT; + } else if (g_fp->_objectIdAtCursor == ANI_PORTER) { + if (g_fp->_cursorId == PIC_CSR_DEFAULT) + g_fp->_cursorId = PIC_CSR_ITN; + } else { + if (g_fp->_objectIdAtCursor == PIC_SC29_LTRUBA && g_fp->_cursorId == PIC_CSR_ITN) + g_fp->_cursorId = PIC_CSR_GOL; + } + return g_fp->_cursorId; +} + } // End of namespace Fullpipe diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index bb6aabd2b5..3c13bad854 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -26,6 +26,7 @@ #include "fullpipe/scene.h" #include "fullpipe/sound.h" #include "fullpipe/ngiarchive.h" +#include "fullpipe/messages.h" #include "common/memstream.h" #include "audio/audiostream.h" #include "audio/decoders/vorbis.h" @@ -73,6 +74,18 @@ bool SoundList::loadFile(const char *fname, char *libname) { return load(archive, libname); } +Sound *SoundList::getSoundItemById(int id) { + if (_soundItemsCount == 0) { + return _soundItems[0]->getId() != id ? 0 : _soundItems[0]; + } + + for (int i = 0; i < _soundItemsCount; i++) { + if (_soundItems[i]->getId() == id) + return _soundItems[i]; + } + return NULL; +} + Sound::Sound() { _id = 0; _directSoundBuffer = 0; @@ -80,10 +93,13 @@ Sound::Sound() { _objectId = 0; memset(_directSoundBuffers, 0, sizeof(_directSoundBuffers)); _description = 0; + _volume = 100; } Sound::~Sound() { - warning("STUB: Sound::~Sound()"); + freeSound(); + + free(_description); } bool Sound::load(MfcArchive &file, NGIArchive *archive) { @@ -119,24 +135,157 @@ void Sound::setPanAndVolumeByStaticAni() { debug(3, "STUB Sound::setPanAndVolumeByStaticAni()"); } -void FullpipeEngine::setSceneMusicParameters(GameVar *var) { +void Sound::setPanAndVolume(int vol, int pan) { + g_fp->_mixer->setChannelVolume(_handle, vol / 39); // 0..10000 + g_fp->_mixer->setChannelBalance(_handle, pan / 78); // -10000..10000 +} + +void Sound::play(int flag) { + Audio::SoundHandle handle = getHandle(); + + if (g_fp->_mixer->isSoundHandleActive(handle)) + return; + + byte *soundData = loadData(); + Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(soundData, getDataSize()); + Audio::RewindableAudioStream *wav = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES); + Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(wav, (flag == 1) ? 0 : 1); + + g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, audioStream); +} + +void Sound::freeSound() { + stop(); + + free(_soundData); +} + +int Sound::getVolume() { + return g_fp->_mixer->getChannelVolume(_handle) * 39; // 0..10000 +} + +void Sound::stop() { + g_fp->_mixer->stopHandle(_handle); +} + +void FullpipeEngine::setSceneMusicParameters(GameVar *gvar) { warning("STUB: FullpipeEngine::setSceneMusicParameters()"); - // TODO: Finish this (MINDELAY, MAXDELAY, LOCAL, SEQUENCE, STARTDELAY etc) - stopAllSoundStreams(); +#if 0 + stopSoundStream2(); + + if (soundStream3) + FSOUND_Stream_Stop(soundStream4); +#endif + + if (_musicLocal) + stopAllSoundStreams(); + + GameVar *var = gvar->getSubVarByName("MUSIC"); + + memset(_sceneTracks, 0, sizeof(_sceneTracks)); + + _numSceneTracks = 0; + _sceneTrackHasSequence = false; + + if (!var) + return; + _musicGameVar = var; + + GameVar *tr = var->getSubVarByName("TRACKS"); + if (tr) { + GameVar *sub = tr->_subVars; + + while (sub) { + if (_musicAllowed & sub->_value.intValue) { + strcpy(_sceneTracks[_numSceneTracks], sub->_varName); + + _numSceneTracks++; + } + + sub = sub->_nextVarObj; + } + } + + _musicMinDelay = var->getSubVarAsInt("MINDELAY"); + _musicMaxDelay = var->getSubVarAsInt("MAXDELAY"); + _musicLocal = var->getSubVarAsInt("LOCAL"); + + GameVar *seq = var->getSubVarByName("SEQUENCE"); + + if (seq) { + _sceneTrackHasSequence = true; + + strcpy(_trackName, seq->_value.stringValue); + } + + if (_musicLocal) + stopAllSoundStreams(); + + if (!_sceneTrackIsPlaying || _musicLocal) + _trackStartDelay = var->getSubVarAsInt("STARTDELAY"); } void FullpipeEngine::startSceneTrack() { - // TODO: Finish this -#ifdef USE_VORBIS - if (g_fp->_mixer->isSoundHandleActive(_sceneTrackHandle)) - return; + if (!_sceneTrackIsPlaying && _numSceneTracks > 0) { + if (_trackStartDelay > 0) { + _trackStartDelay--; + } else { + int trackNum = getSceneTrack(); + + if (trackNum == -1) { + strcpy(_sceneTracksCurrentTrack, "silence"); + + _trackStartDelay = 2880; + _sceneTrackIsPlaying = 0; + } else { + strcpy(_sceneTracksCurrentTrack, _sceneTracks[trackNum]); + + startSoundStream1(_sceneTracksCurrentTrack); + + _sceneTrackIsPlaying = true; + } + } + } +} + +int FullpipeEngine::getSceneTrack() { + int res; + + if (_sceneTrackHasSequence) { + int num = _musicGameVar->getSubVarAsInt("TRACKS"); + + if (_trackName[num + 1] == 's') { // 'silence' + res = -1; + } else { + res = _trackName[num + 1] - '0'; + + if (res < 0 || res >= _numSceneTracks) + res = 0; + } - GameVar *musicTrackVar = _musicGameVar->getSubVarByName("MUSIC")->getSubVarByName("TRACKS")->_subVars; - if (!musicTrackVar) + int track = num + 1; + + if (!_trackName[num + 2]) + track = 0; + + _musicGameVar->setSubVarAsInt("TRACKS", track); + } else { + res = _numSceneTracks * (_updateTicks % 10) / 10; + } + + return res; +} + +void FullpipeEngine::startSoundStream1(char *trackName) { + warning("STUB: FullpipeEngine::startSoundStream1(%s)", trackName); + + stopAllSoundStreams(); + +#ifdef USE_VORBIS + if (_mixer->isSoundHandleActive(_sceneTrackHandle)) return; - char *trackName = musicTrackVar->_varName; Common::File *track = new Common::File(); if (!track->open(trackName)) { warning("Could not open %s", trackName); @@ -144,40 +293,130 @@ void FullpipeEngine::startSceneTrack() { return; } Audio::RewindableAudioStream *ogg = Audio::makeVorbisStream(track, DisposeAfterUse::YES); - g_fp->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_sceneTrackHandle, ogg); + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_sceneTrackHandle, ogg); #endif } void FullpipeEngine::stopAllSounds() { // TODO: Differences from stopAllSoundStreams() - g_fp->_mixer->stopAll(); + _mixer->stopAll(); } void FullpipeEngine::toggleMute() { - warning("STUB: FullpipeEngine::toggleMute()"); + if (_soundEnabled) { + _sfxVolume = _sfxVolume != -10000 ? -10000 : 0; + + updateSoundVolume(); + } } void FullpipeEngine::playSound(int id, int flag) { - SoundList *soundList = g_fp->_currentScene->_soundList; - Sound *sound = soundList->getSoundById(id); + Sound *sound = 0; + + for (int i = 0; i < _currSoundListCount; i++) { + sound = _currSoundList1[i]->getSoundItemById(id); + + if (sound) + break; + } + if (!sound) { warning("playSound: Can't find sound with ID %d", id); return; } - byte *soundData = sound->loadData(); - Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(soundData, sound->getDataSize()); - Audio::RewindableAudioStream *wav = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES); - Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(wav, (flag == 1) ? 0 : 1); - Audio::SoundHandle handle = sound->getHandle(); - g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, audioStream); + + sound->play(flag); } void FullpipeEngine::playTrack(GameVar *sceneVar, const char *name, bool delayed) { warning("STUB: FullpipeEngine::playTrack(var, %s, %d)", name, delayed); +#if 0 + stopSoundStream2(); + + if (soundStream3) + FSOUND_Stream_Stop(soundStream4); +#endif + + if (_musicLocal) + stopAllSoundStreams(); + + GameVar *var = sceneVar->getSubVarByName(name); + + memset(_sceneTracks, 0, sizeof(_sceneTracks)); + + _numSceneTracks = 0; + _sceneTrackHasSequence = false; + + if (!var) + return; + + _musicGameVar = var; + + GameVar *tr = var->getSubVarByName("TRACKS"); + if (tr) { + GameVar *sub = tr->_subVars; + + while (sub) { + if (_musicAllowed & sub->_value.intValue) { + strcpy(_sceneTracks[_numSceneTracks], sub->_varName); + + _numSceneTracks++; + } + + sub = sub->_nextVarObj; + } + } + + _musicMinDelay = var->getSubVarAsInt("MINDELAY"); + _musicMaxDelay = var->getSubVarAsInt("MAXDELAY"); + _musicLocal = var->getSubVarAsInt("LOCAL"); + + GameVar *seq = var->getSubVarByName("SEQUENCE"); + + if (seq) { + _sceneTrackHasSequence = true; + + strcpy(_trackName, seq->_value.stringValue); + } + + if (delayed) { + if (_sceneTrackIsPlaying && _numSceneTracks == 1) { + if (strcmp(_sceneTracksCurrentTrack, _sceneTracks[0])) + stopAllSoundStreams(); + } + + _trackStartDelay = var->getSubVarAsInt("STARTDELAY"); + } } void global_messageHandler_handleSound(ExCommand *cmd) { - debug(0, "STUB: global_messageHandler_handleSound()"); + if (!g_fp->_soundEnabled) + return; + + Sound *snd = 0; + + for (int i = 0; i < g_fp->_currSoundListCount; i++) + snd = g_fp->_currSoundList1[i]->getSoundItemById(cmd->_messageNum); + + if (!snd) + return; + + if (cmd->_field_14 & 1) { + if (!g_fp->_flgSoundList && (cmd->_field_14 & 4)) + snd->freeSound(); + + snd->updateVolume(); + + if (snd->_objectId && g_fp->_currentScene->getStaticANIObject1ById(snd->_objectId, -1)) + snd->setPanAndVolumeByStaticAni(); + else + snd->setPanAndVolume(g_fp->_sfxVolume, 0); + + if (snd->getVolume() > -3500) + snd->play(cmd->_keyCode); + } else if (cmd->_field_14 & 2) { + snd->stop(); + } } void FullpipeEngine::stopSoundStream2() { @@ -186,21 +425,29 @@ void FullpipeEngine::stopSoundStream2() { void FullpipeEngine::stopAllSoundStreams() { // TODO: Differences from stopAllSounds() - g_fp->_mixer->stopAll(); + _mixer->stopAll(); } void FullpipeEngine::stopAllSoundInstances(int id) { - SoundList *soundList = g_fp->_currentScene->_soundList; - for (int i = 0; i < soundList->getCount(); i++) { - Sound *sound = soundList->getSoundByIndex(i); - if (sound->getId() == id) { - g_fp->_mixer->stopHandle(sound->getHandle()); - } + for (int i = 0; i < _currSoundListCount; i++) { + Sound *sound = _currSoundList1[i]->getSoundItemById(id); + + if (sound) + sound->stop(); } } void FullpipeEngine::updateSoundVolume() { - debug(3, "STUB FullpipeEngine::updateSoundVolume()"); + for (int i = 0; i < _currSoundListCount; i++) + for (int j = 0; i < _currSoundList1[i]->getCount(); j++) { + _currSoundList1[i]->getSoundByIndex(j)->setPanAndVolume(_sfxVolume, 0); + } +} + +void FullpipeEngine::setMusicVolume(int vol) { + _musicVolume = vol; + + debug(3, "STUB FullpipeEngine::setMusicVolume()"); } } // End of namespace Fullpipe diff --git a/engines/fullpipe/sound.h b/engines/fullpipe/sound.h index 8ddfc753ce..14e766f5bb 100644 --- a/engines/fullpipe/sound.h +++ b/engines/fullpipe/sound.h @@ -28,11 +28,14 @@ namespace Fullpipe { class Sound : public MemoryObject { int _id; char *_description; - int16 _objectId; int _directSoundBuffer; int _directSoundBuffers[7]; byte *_soundData; Audio::SoundHandle _handle; + int _volume; + +public: + int16 _objectId; public: Sound(); @@ -44,7 +47,13 @@ public: int getId() const { return _id; } Audio::SoundHandle getHandle() const { return _handle; } + void play(int flag); + void freeSound(); + int getVolume(); + void stop(); + void setPanAndVolumeByStaticAni(); + void setPanAndVolume(int vol, int pan); }; class SoundList : public CObject { @@ -60,13 +69,7 @@ class SoundList : public CObject { int getCount() { return _soundItemsCount; } Sound *getSoundByIndex(int idx) { return _soundItems[idx]; } - Sound *getSoundById(int id) { - for (int i = 0; i < _soundItemsCount; i++) { - if (_soundItems[i]->getId() == id) - return _soundItems[i]; - } - return NULL; - } + Sound *getSoundItemById(int id); }; } // End of namespace Fullpipe diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 75c1c7d1ea..f1abac5778 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -105,6 +105,19 @@ bool StepArray::gotoNextPoint() { } } +void StepArray::insertPoints(Common::Point **points, int pointsCount) { + if (_currPointIndex + pointsCount >= _pointsCount) + _points = (Common::Point **)realloc(_points, sizeof(Common::Point *) * (_currPointIndex + pointsCount)); + + _maxPointIndex = _currPointIndex + pointsCount; + + for (int i = 0; i < pointsCount; i++) { + _points[_currPointIndex + i] = new Common::Point; + + *_points[_currPointIndex + i] = *points[i]; + } +} + StaticANIObject::StaticANIObject() { _shadowsOn = 1; _field_30 = 0; @@ -264,8 +277,11 @@ void StaticANIObject::deleteFromGlobalMessageQueue() { } } -void StaticANIObject::queueMessageQueue(MessageQueue *mq) { - if (isIdle() && !(_flags & 0x80)) { +bool StaticANIObject::queueMessageQueue(MessageQueue *mq) { + if (_flags & 0x80) + return false; + + if (isIdle()) { deleteFromGlobalMessageQueue(); _messageQueueId = 0; _messageNum = 0; @@ -283,6 +299,8 @@ void StaticANIObject::queueMessageQueue(MessageQueue *mq) { _messageQueueId = 0; } } + + return true; } void StaticANIObject::restartMessageQueue(MessageQueue *mq) { @@ -330,7 +348,35 @@ bool StaticANIObject::trySetMessageQueue(int msgNum, int qId) { } void StaticANIObject::startMQIfIdle(int qId, int flag) { - warning("STUB: StaticANIObject::startMQIfIdle()"); + MessageQueue *msg = g_fp->_currentScene->getMessageQueueById(qId); + + if (msg && isIdle() && !(_flags & 0x100)) { + MessageQueue *mq = new MessageQueue(msg, 0, 0); + + mq->setFlags(mq->getFlags() | flag); + + ExCommand *ex = mq->getExCommandByIndex(0); + + if (ex) { + while (ex->_messageKind != 1 || ex->_parentId != _id) { + ex->_parId = 0; + ex->_excFlags |= 2; + ex->handleMessage(); + + mq->deleteExCommandByIndex(0, 0); + + ex = mq->getExCommandByIndex(0); + + if (!ex) + return; + } + + if (ex) { + startAnim(ex->_messageNum, mq->_id, -1); + mq->deleteExCommandByIndex(0, 1); + } + } + } } bool StaticANIObject::isIdle() { @@ -978,9 +1024,26 @@ void StaticANIObject::adjustSomeXY() { } MessageQueue *StaticANIObject::changeStatics1(int msgNum) { - warning("STUB: StaticANIObject::changeStatics1(%d)", msgNum); + g_fp->_mgm->addItem(_id); - return 0; + MessageQueue *mq = g_fp->_mgm->genMQ(this, msgNum, 0, 0, 0); + + if (!mq) + return 0; + + if (mq->getCount() <= 0) { + g_fp->_globalMessageQueueList->addMessageQueue(mq); + + if (_flags & 1) + _messageQueueId = mq->_id; + } else { + if (!queueMessageQueue(mq)) + return 0; + + g_fp->_globalMessageQueueList->addMessageQueue(mq); + } + + return mq; } void StaticANIObject::changeStatics2(int objId) { @@ -1060,7 +1123,47 @@ void StaticANIObject::show1(int x, int y, int movId, int mqId) { } void StaticANIObject::show2(int x, int y, int movementId, int mqId) { - warning("STUB: StaticANIObject::show2(%d, %d, %d, %d)", x, y, movementId, mqId); + if (movementId == -1) { + _flags |= 4u; + return; + } + + if (!_messageQueueId) { + _messageQueueId = mqId; + + Movement *mov = getMovementById(movementId); + + if (mov) { + _statics = mov->_staticsObj1; + _movement = mov; + mov->gotoLastFrame(); + mov->setOXY(x, y); + mov->gotoFirstFrame(); + + Common::Point point; + + mov->getCurrDynamicPhaseXY(point); + _statics->_x = mov->_ox - point.x - mov->_mx; + _statics->_y = mov->_oy - point.y - mov->_my; + + _statics->getSomeXY(point); + _flags |= 4; + _ox = _statics->_x + point.x; + _oy = _statics->_y + point.y; + + if (mov->_currMovement) { + _flags |= 8; + } else { + if (_flags & 8) + _flags ^= 8; + } + + if (_flags & 1) + _flags ^= 1; + + _flags |= 0x20; + } + } } void StaticANIObject::playIdle() { @@ -1069,7 +1172,85 @@ void StaticANIObject::playIdle() { } void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x, int y, Common::Point **points, int pointsCount, int someDynamicPhaseIndex) { - warning("STUB: StaticANIObject::startAnimSteps()"); + Movement *mov = 0; + + if (!(_flags & 0x80)) { + if (!_messageQueueId) + for (uint i = 0; i < _movements.size(); i++) { + if (((Movement *)_movements[i])->_id == movementId) { + mov = (Movement *)_movements[i]; + break; + } + } + } + + if (!mov) { + updateGlobalMessageQueue(messageQueueId, _id); + + return; + } + + + if (_movement || !_statics) + return; + + Common::Point point; + + _statics->getSomeXY(point); + + int newx = _ox - point.x; + int newy = _oy - point.y; + + _movement = mov; + + if (_flags & 0x40) + _movement->gotoLastFrame(); + else + _movement->gotoFirstFrame(); + + _stepArray.clear(); + _stepArray.insertPoints(points, pointsCount); + + if (!(_flags & 0x40)) { + if (!_movement->_currDynamicPhaseIndex) { + _stepArray.getCurrPoint(&point); + newx += point.x + _movement->_mx; + newy += point.y + _movement->_my; + _stepArray.gotoNextPoint(); + + ExCommand *ex = _movement->_currDynamicPhase->getExCommand(); + + if (ex) { + if (ex->_messageKind == 35) { + ExCommand *newEx = ex->createClone(); + + newEx->_excFlags |= 2u; + newEx->sendMessage(); + } + } + } + } + + _movement->getCurrDynamicPhaseXY(point); + setOXY(point.x + newx, point.y + newy); + + if ((_movement->_staticsObj2->_staticsId >> 8) & 0x40) + _flags |= 8; + else + _flags &= 0xFFF7; + + _flags |= 1; + _messageQueueId = messageQueueId; + _movement->_currDynamicPhase->_countdown = _movement->_currDynamicPhase->_initialCountdown; + _movement->_counter = 0; + _counter = _initialCounter; + _someDynamicPhaseIndex = someDynamicPhaseIndex; + + ExCommand *ex = new ExCommand(_id, 17, 23, 0, 0, movementId, 1, 0, 0, 0); + + ex->_keyCode = _okeyCode; + ex->_excFlags = 2; + ex->postMessage(); } bool StaticANIObject::startAnimEx(int movid, int parId, int flag1, int flag2) { @@ -1188,6 +1369,31 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase return true; } +Common::Point *StaticANIObject::calcStepLen(Common::Point *p) { + if (_movement) { + Common::Point point; + + _movement->calcSomeXY(point, 0); + + p->x = point.x; + p->y = point.y; + + int idx = _stepArray.getCurrPointIndex() - _movement->_currDynamicPhaseIndex - 1; + + if (idx >= 0) { + _stepArray.getPoint(&point, idx, _movement->_currDynamicPhaseIndex + 2); + + p->x += point.x; + p->y += point.y; + } + } else { + p->x = 0; + p->y = 0; + } + + return p; +} + Statics::Statics() { _staticsId = 0; _picture = 0; diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h index 8328e7679b..d678957163 100644 --- a/engines/fullpipe/statics.h +++ b/engines/fullpipe/statics.h @@ -47,6 +47,7 @@ class StepArray : public CObject { Common::Point *getCurrPoint(Common::Point *point); Common::Point *getPoint(Common::Point *point, int index, int offset); bool gotoNextPoint(); + void insertPoints(Common::Point **points, int pointsCount); }; class StaticPhase : public Picture { @@ -216,7 +217,7 @@ public: void setAlpha(int alpha); void deleteFromGlobalMessageQueue(); - void queueMessageQueue(MessageQueue *msg); + bool queueMessageQueue(MessageQueue *msg); void restartMessageQueue(MessageQueue *msg); MessageQueue *getMessageQueue(); bool trySetMessageQueue(int msgNum, int qId); @@ -245,6 +246,7 @@ public: void draw2(); MovTable *countMovements(); + Common::Point *calcStepLen(Common::Point *p); void setSpeed(int speed); void updateStepPos(); diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index cbaa992596..2776a0455d 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -43,8 +43,9 @@ namespace Groovie { -ROQPlayer::ROQPlayer(GroovieEngine *vm) : VideoPlayer(vm), _codingTypeCount(0), _bg(&_vm->_graphicsMan->_background) { - // _fg = &_vm->_graphicsMan->_foreground; +ROQPlayer::ROQPlayer(GroovieEngine *vm) : + VideoPlayer(vm), _codingTypeCount(0), + _bg(&_vm->_graphicsMan->_background) { // Create the work surfaces _currBuf = new Graphics::Surface(); diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h index b5e63c2b4a..cd5e91c82b 100644 --- a/engines/groovie/roq.h +++ b/engines/groovie/roq.h @@ -75,7 +75,6 @@ private: byte _codebook4[256 * 4]; // Buffers - // Graphics::Surface *_fg, *_thirdBuf; Graphics::Surface *_bg; Graphics::Surface *_currBuf, *_prevBuf; void buildShowBuf(); diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 10cbc49c7c..725dedae3f 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -538,7 +538,8 @@ bool SoundTownsPC98_v2::init() { // check if we have access to CD audio. Resource *r = _vm->resource(); if (_musicEnabled && - (r->exists("track1.mp3") || r->exists("track1.ogg") || r->exists("track1.flac") || r->exists("track1.fla"))) + (r->exists("track1.mp3") || r->exists("track1.ogg") || r->exists("track1.flac") || r->exists("track1.fla") + || r->exists("track01.mp3") || r->exists("track01.ogg") || r->exists("track01.flac") || r->exists("track01.fla"))) _musicEnabled = 2; else _musicEnabled = 1; diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp index 9c8cc202aa..148854e04d 100644 --- a/engines/lastexpress/data/animation.cpp +++ b/engines/lastexpress/data/animation.cpp @@ -39,7 +39,7 @@ namespace LastExpress { -Animation::Animation() : _stream(NULL), _currentChunk(NULL), _overlay(NULL), _background1(NULL), _background2(NULL), _backgroundCurrent(0), _audio(NULL), _startTime(0), _changed(false), _flag(0) { +Animation::Animation() : _stream(NULL), _currentChunk(NULL), _overlay(NULL), _background1(NULL), _background2(NULL), _backgroundCurrent(0), _audio(NULL), _startTime(0), _changed(false) { } Animation::~Animation() { diff --git a/engines/lastexpress/data/animation.h b/engines/lastexpress/data/animation.h index 7f6922866a..9523cddb78 100644 --- a/engines/lastexpress/data/animation.h +++ b/engines/lastexpress/data/animation.h @@ -113,7 +113,6 @@ private: uint32 _startTime; bool _changed; - int _flag; }; } // End of namespace LastExpress diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp index c7073b560c..f43e2afdef 100644 --- a/engines/lastexpress/data/sequence.cpp +++ b/engines/lastexpress/data/sequence.cpp @@ -76,7 +76,7 @@ void FrameInfo::read(Common::SeekableReadStream *in, bool isSequence) { // AnimFrame -AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f, bool ignoreSubtype) : _palette(NULL), _ignoreSubtype(ignoreSubtype) { +AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f, bool /* ignoreSubtype */) : _palette(NULL) { _palSize = 1; // TODO: use just the needed rectangle _image.create(640, 480, Graphics::PixelFormat::createFormatCLUT8()); diff --git a/engines/lastexpress/data/sequence.h b/engines/lastexpress/data/sequence.h index dbb08a0c07..fd8b3cd27b 100644 --- a/engines/lastexpress/data/sequence.h +++ b/engines/lastexpress/data/sequence.h @@ -147,7 +147,6 @@ private: uint16 _palSize; uint16 *_palette; Common::Rect _rect; - bool _ignoreSubtype; }; class Sequence { diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp index f9033a9dbe..6618cb3ab0 100644 --- a/engines/neverhood/modules/module2200.cpp +++ b/engines/neverhood/modules/module2200.cpp @@ -885,7 +885,7 @@ void Scene2205::update() { } else if (_isLightOn && !getGlobalVar(V_LIGHTS_ON)) { _palette->addPalette(0xD00A028D, 0, 256, 0); changeBackground(0xD00A028D); - _ssLightSwitch->setFileHashes(0x2D339030, 0xDAC86E84); + _ssLightSwitch->setFileHashes(0xD6C86E84, 0xDAC86E84); sendMessage(_ssDoorFrame, 0x2000, 0); changeMouseCursor(0xA0289D08); _isKlaymenInLight = true; diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp index c0edc95873..68ae07f2bb 100644 --- a/engines/neverhood/modules/module2300.cpp +++ b/engines/neverhood/modules/module2300.cpp @@ -31,14 +31,14 @@ static const uint32 kModule2300SoundList[] = { }; Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { + : Module(vm, parentModule), _waterfallSoundVolume(0) { _vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList); _vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150); - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; - if (_isWallBroken) { + if (_isWaterfallRunning) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); } else { @@ -78,8 +78,8 @@ void Module2300::createScene(int sceneNum, int which) { case 1: _vm->gameState().sceneNum = 1; createNavigationScene(0x004B67E8, which); - if (_isWallBroken) { - _soundVolume = 15; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 15; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 15); } break; @@ -92,10 +92,10 @@ void Module2300::createScene(int sceneNum, int which) { if (getGlobalVar(V_WALL_BROKEN)) createNavigationScene(0x004B68F0, which); else { - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); createNavigationScene(0x004B68A8, which); - if (_isWallBroken) { - _soundVolume = 87; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 87; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 87); } } @@ -161,10 +161,10 @@ void Module2300::updateScene() { } else { switch (_sceneNum) { case 1: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && + if (_isWaterfallRunning && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && navigationScene()->getFrameNumber() % 2) { - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && navigationScene()->getFrameNumber() == 50) { @@ -174,9 +174,9 @@ void Module2300::updateScene() { } break; case 3: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + if (_isWaterfallRunning && navigationScene()->isWalkingForward() && navigationScene()->getFrameNumber() % 2) { + _waterfallSoundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } break; } diff --git a/engines/neverhood/modules/module2300.h b/engines/neverhood/modules/module2300.h index 57235986d9..58bffb710c 100644 --- a/engines/neverhood/modules/module2300.h +++ b/engines/neverhood/modules/module2300.h @@ -37,8 +37,8 @@ public: virtual ~Module2300(); protected: int _sceneNum; - bool _isWallBroken; - int _soundVolume; + int _waterfallSoundVolume; + bool _isWaterfallRunning; void createScene(int sceneNum, int which); void updateScene(); }; diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp index 59b2df260e..d4809611ad 100644 --- a/engines/neverhood/modules/module3000.cpp +++ b/engines/neverhood/modules/module3000.cpp @@ -39,7 +39,7 @@ static const uint32 kModule3000SoundList[] = { }; Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundVolume(0) { + : Module(vm, parentModule), _waterfallSoundVolume(0) { _vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList); _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150); @@ -48,9 +48,9 @@ Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; - if (!_isWallBroken) { + if (_isWaterfallRunning) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); } @@ -78,12 +78,11 @@ void Module3000::createScene(int sceneNum, int which) { static const byte kNavigationTypes06[] = {5}; debug(1, "Module3000::createScene(%d, %d)", sceneNum, which); _vm->gameState().sceneNum = sceneNum; - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; switch (_vm->gameState().sceneNum) { case 1: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { createNavigationScene(0x004B7C80, which); - } else if (_isWallBroken) { + } else if (getGlobalVar(V_WALL_BROKEN)) { createNavigationScene(0x004B7CE0, which); } else { createNavigationScene(0x004B7CB0, which); @@ -91,11 +90,11 @@ void Module3000::createScene(int sceneNum, int which) { break; case 2: _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - if (!_isWallBroken) { - _soundVolume = 90; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 90; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 90); } - if (_isWallBroken) { + if (getGlobalVar(V_WALL_BROKEN)) { createNavigationScene(0x004B7D58, which); } else { createNavigationScene(0x004B7D10, which); @@ -104,7 +103,7 @@ void Module3000::createScene(int sceneNum, int which) { case 3: if (getGlobalVar(V_STAIRS_DOWN)) createNavigationScene(0x004B7E60, which); - else if (_isWallBroken) + else if (getGlobalVar(V_WALL_BROKEN)) createNavigationScene(0x004B7DA0, which); else createNavigationScene(0x004B7E00, which); @@ -152,12 +151,12 @@ void Module3000::createScene(int sceneNum, int which) { // NOTE: Newly introduced sceneNums case 1001: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) - if (_isWallBroken) + if (getGlobalVar(V_WALL_BROKEN)) createSmackerScene(0x00940021, true, true, false); else createSmackerScene(0x01140021, true, true, false); else - if (_isWallBroken) + if (getGlobalVar(V_WALL_BROKEN)) createSmackerScene(0x001011B1, true, true, false); else createSmackerScene(0x001021B1, true, true, false); @@ -195,8 +194,8 @@ void Module3000::updateScene() { break; case 2: _vm->_soundMan->playTwoSounds(0x81293110, 0x41861371, 0x43A2507F, 0); - if (_isWallBroken) { - _soundVolume = 0; + if (_isWaterfallRunning) { + _waterfallSoundVolume = 0; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); } if (_moduleResult == 0) { @@ -240,7 +239,7 @@ void Module3000::updateScene() { createScene(8, -1); break; case 8: - _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; + _isWaterfallRunning = getGlobalVar(V_WALL_BROKEN) != 1; if (_moduleResult != 1) { _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 0, 0, 0, 0); createScene(4, 1); @@ -301,12 +300,12 @@ void Module3000::updateScene() { } else if (frameNumber == 10) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (_isWaterfallRunning && _waterfallSoundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) - _soundVolume = 40; + _waterfallSoundVolume = 40; else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } } } @@ -315,9 +314,9 @@ void Module3000::updateScene() { if (navigationScene()->isWalkingForward()) { uint32 frameNumber = navigationScene()->getFrameNumber(); int navigationIndex = navigationScene()->getNavigationIndex(); - if (!_isWallBroken && _soundVolume > 1 && frameNumber % 2) { - _soundVolume--; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + if (_isWaterfallRunning && _waterfallSoundVolume > 1 && frameNumber % 2) { + _waterfallSoundVolume--; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } if (navigationIndex == 0) { if (frameNumber == 35) { @@ -340,12 +339,12 @@ void Module3000::updateScene() { if (frameNumber == 40) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (_isWaterfallRunning && _waterfallSoundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) - _soundVolume = 40; + _waterfallSoundVolume = 40; else - _soundVolume++; - _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); + _waterfallSoundVolume++; + _vm->_soundMan->setSoundVolume(0x90F0D1C3, _waterfallSoundVolume); } } } diff --git a/engines/neverhood/modules/module3000.h b/engines/neverhood/modules/module3000.h index e5c251f828..3d895b8d8a 100644 --- a/engines/neverhood/modules/module3000.h +++ b/engines/neverhood/modules/module3000.h @@ -34,8 +34,8 @@ public: Module3000(NeverhoodEngine *vm, Module *parentModule, int which); virtual ~Module3000(); protected: - int _soundVolume; - bool _isWallBroken; + int _waterfallSoundVolume; + bool _isWaterfallRunning; void createScene(int sceneNum, int which); void updateScene(); }; diff --git a/engines/parallaction/saveload.h b/engines/parallaction/saveload.h index dbbbb42066..c9b724e69d 100644 --- a/engines/parallaction/saveload.h +++ b/engines/parallaction/saveload.h @@ -71,12 +71,12 @@ public: }; class SaveLoad_br : public SaveLoad { - Parallaction_br *_vm; +// Parallaction_br *_vm; virtual void doLoadGame(uint16 slot); virtual void doSaveGame(uint16 slot, const char* name); public: - SaveLoad_br(Parallaction_br *vm, Common::SaveFileManager *saveFileMan) : SaveLoad(saveFileMan, "bra"), _vm(vm) { } + SaveLoad_br(Parallaction_br *vm, Common::SaveFileManager *saveFileMan) : SaveLoad(saveFileMan, "bra") { } virtual void getGamePartProgress(bool *complete, int size); virtual void setPartComplete(const char *part); diff --git a/engines/pegasus/ai/ai_area.cpp b/engines/pegasus/ai/ai_area.cpp index 5ac8af8812..9cab568d66 100644 --- a/engines/pegasus/ai/ai_area.cpp +++ b/engines/pegasus/ai/ai_area.cpp @@ -234,6 +234,7 @@ void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSigna vm->_cursor->hide(); while (_middleAreaMovie.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -258,6 +259,7 @@ void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSigna vm->_cursor->hide(); while (_rightAreaMovie.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp index be9d205360..40e54afb89 100644 --- a/engines/pegasus/energymonitor.cpp +++ b/engines/pegasus/energymonitor.cpp @@ -269,6 +269,7 @@ void EnergyMonitor::calibrateEnergyBar() { // Make sure warning light is hidden... _energyLight.hide(); while (getCurrentEnergy() != (int32)kMaxJMPEnergy) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/fader.cpp b/engines/pegasus/fader.cpp index a2bbf22944..80ce8ef5dc 100644 --- a/engines/pegasus/fader.cpp +++ b/engines/pegasus/fader.cpp @@ -94,6 +94,7 @@ void Fader::startFaderSync(const FaderMoveSpec &spec) { start(); while (isFading()) { + InputDevice.pumpEvents(); ((PegasusEngine *)g_engine)->checkCallBacks(); useIdleTime(); } diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp index b74e4a4c45..283d55421f 100644 --- a/engines/pegasus/input.cpp +++ b/engines/pegasus/input.cpp @@ -81,9 +81,7 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) { // (ie. if one uses enter to access the restore menu, we never receive // the key up event, which leads to bad things) // This is to closely emulate what the GetKeys() function did on Mac OS - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; + pumpEvents(); // Now create the bitfield InputBits currentBits = 0; @@ -206,6 +204,13 @@ bool InputDeviceManager::notifyEvent(const Common::Event &event) { return false; } +void InputDeviceManager::pumpEvents() { + // Just poll for events. notifyEvent() will pick up on them. + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) + ; +} + int operator==(const Input &arg1, const Input &arg2) { return arg1._inputState == arg2._inputState; } diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h index 3e938fa42a..ba6f11dba0 100644 --- a/engines/pegasus/input.h +++ b/engines/pegasus/input.h @@ -50,6 +50,8 @@ public: void waitInput(const InputBits); + void pumpEvents(); + protected: friend class Common::Singleton<SingletonBaseType>; diff --git a/engines/pegasus/interface.cpp b/engines/pegasus/interface.cpp index f2429bf36a..f8ae6a0752 100644 --- a/engines/pegasus/interface.cpp +++ b/engines/pegasus/interface.cpp @@ -604,6 +604,7 @@ void Interface::raiseInventoryDrawerSync() { raiseInventoryDrawer(false); while (_inventoryLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -613,6 +614,7 @@ void Interface::raiseInventoryDrawerSync() { inventoryLidOpen(false); while (_inventoryPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -628,6 +630,7 @@ void Interface::lowerInventoryDrawerSync() { lowerInventoryDrawer(false); while (_inventoryPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -637,6 +640,7 @@ void Interface::lowerInventoryDrawerSync() { inventoryDrawerDown(false); while (_inventoryLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -652,6 +656,7 @@ void Interface::raiseBiochipDrawerSync() { raiseBiochipDrawer(false); while (_biochipLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -661,6 +666,7 @@ void Interface::raiseBiochipDrawerSync() { biochipLidOpen(false); while (_biochipPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -676,6 +682,7 @@ void Interface::lowerBiochipDrawerSync() { lowerBiochipDrawer(false); while (_biochipPush.isFading()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); @@ -685,6 +692,7 @@ void Interface::lowerBiochipDrawerSync() { biochipDrawerDown(false); while (_biochipLid.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/items/inventorypicture.cpp b/engines/pegasus/items/inventorypicture.cpp index fc812faae2..bfdc382f5d 100644 --- a/engines/pegasus/items/inventorypicture.cpp +++ b/engines/pegasus/items/inventorypicture.cpp @@ -331,6 +331,7 @@ void InventoryItemsPicture::playEndMessage(DisplayElement *pushElement) { endMessage.start(); while (endMessage.isRunning()) { + InputDevice.pumpEvents(); vm->checkCallBacks(); vm->refreshDisplay(); g_system->delayMillis(10); diff --git a/engines/pegasus/items/item.cpp b/engines/pegasus/items/item.cpp index 8089f2b93d..830d3f2f34 100644 --- a/engines/pegasus/items/item.cpp +++ b/engines/pegasus/items/item.cpp @@ -39,9 +39,9 @@ namespace Pegasus { Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) { - _itemNeighborhood = neighborhood; - _itemRoom = room; - _itemDirection = direction; + _originalNeighborhood = _itemNeighborhood = neighborhood; + _originalRoom = _itemRoom = room; + _originalDirection = _itemDirection = direction; _itemWeight = 1; _itemOwnerID = kNoActorID; _itemState = 0; @@ -131,6 +131,14 @@ Item::~Item() { delete[] _itemExtras.entries; } +void Item::reset() { + _itemNeighborhood = _originalNeighborhood; + _itemRoom = _originalRoom; + _itemDirection = _originalDirection; + _itemOwnerID = kNoActorID; + _itemState = 0; +} + void Item::writeToStream(Common::WriteStream *stream) { stream->writeUint16BE(_itemNeighborhood); stream->writeUint16BE(_itemRoom); diff --git a/engines/pegasus/items/item.h b/engines/pegasus/items/item.h index a1451b2a58..26cccf043c 100644 --- a/engines/pegasus/items/item.h +++ b/engines/pegasus/items/item.h @@ -339,6 +339,9 @@ public: void findItemExtra(const uint32 extraID, ItemExtraEntry &entry); + // Reset to its original state at the beginning of the game + void reset(); + protected: NeighborhoodID _itemNeighborhood; RoomID _itemRoom; @@ -347,6 +350,10 @@ protected: WeightType _itemWeight; ItemState _itemState; + NeighborhoodID _originalNeighborhood; + RoomID _originalRoom; + DirectionConstant _originalDirection; + JMPItemInfo _itemInfo; ItemStateInfo _sharedAreaInfo; ItemExtraInfo _itemExtras; diff --git a/engines/pegasus/items/itemlist.cpp b/engines/pegasus/items/itemlist.cpp index ff8cae546b..4b58d9ad78 100644 --- a/engines/pegasus/items/itemlist.cpp +++ b/engines/pegasus/items/itemlist.cpp @@ -64,4 +64,9 @@ Item *ItemList::findItemByID(const ItemID id) { return 0; } +void ItemList::resetAllItems() { + for (ItemIterator it = begin(); it != end(); it++) + (*it)->reset(); +} + } // End of namespace Pegasus diff --git a/engines/pegasus/items/itemlist.h b/engines/pegasus/items/itemlist.h index 9b59206ab3..22bef2c96e 100644 --- a/engines/pegasus/items/itemlist.h +++ b/engines/pegasus/items/itemlist.h @@ -48,6 +48,7 @@ public: virtual void readFromStream(Common::ReadStream *stream); Item *findItemByID(const ItemID id); + void resetAllItems(); }; typedef ItemList::iterator ItemIterator; diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp index e55c006f86..4bbda8fd93 100644 --- a/engines/pegasus/menu.cpp +++ b/engines/pegasus/menu.cpp @@ -227,6 +227,7 @@ MainMenu::MainMenu() : GameMenu(kMainMenuID), _menuBackground(0), _overviewButto _menuLoop.attachFader(&_menuFader); _menuLoop.initFromAIFFFile("Sounds/Main Menu.aiff"); + _menuFader.setMasterVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); updateDisplay(); } @@ -736,6 +737,7 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d _largeSelect.startDisplaying(); } else { _triumphSound.initFromQuickTime("Sounds/Caldoria/Galactic Triumph"); + _triumphSound.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); _triumphSound.playSound(); } diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp index 0707a83e87..9d2d6723a9 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp @@ -196,6 +196,8 @@ void Caldoria::start() { if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie")) error("Could not load pullback movie"); + pullbackMovie->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF)); + // Draw the first frame so we can fade to it const Graphics::Surface *frame = pullbackMovie->decodeNextFrame(); assert(frame); @@ -907,7 +909,7 @@ void Caldoria::arriveAtCaldoria49() { setCurrentAlternate(kAltCaldoriaNormal); // Need to force the loop to play. - if (GameState.getCurrentDirection() == kNorth) { + if (GameState.getCurrentDirection() == kNorth && !GameState.getCaldoriaSinclairShot()) { GameState.setCaldoriaFuseTimeLimit(kSinclairShootsTimeLimit); startExtraSequence(kCa49NorthVoiceAnalysis, kExtraCompletedFlag, kFilterNoInput); } @@ -1916,10 +1918,13 @@ uint Caldoria::getNumHints() { numHints = 1; } break; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): numHints = 1; break; +#endif case MakeRoomView(kCaldoria49, kNorth): numHints = 1; break; @@ -1950,9 +1955,12 @@ Common::String Caldoria::getHintMovie(uint hintNum) { } return "Images/AI/Globals/XGLOB1A"; +#if 0 + // The hint file is missing case MakeRoomView(kCaldoria49, kEast): case MakeRoomView(kCaldoria54, kEast): return "Images/AI/Caldoria/X49E"; +#endif case MakeRoomView(kCaldoria49, kNorth): return "Images/AI/Caldoria/X49NB2"; } diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp index abf34d3863..c964e3458b 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp @@ -1167,6 +1167,18 @@ CaldoriaBomb::~CaldoriaBomb() { delete[] _bombLevel[i]; } +void CaldoriaBomb::setSoundFXLevel(const uint16) { + // The transition sounds between levels are ambience, so overwrite what + // Neighborhood::setSoundFXLevel does and keep using the ambience volume level + if (_timer.isRunning()) + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); +} + +void CaldoriaBomb::setAmbienceLevel(const uint16 level) { + if (_timer.isRunning()) + _owner->_navMovie.setVolume(level); +} + void CaldoriaBomb::openInteraction() { _grid.moveElementTo(kCaldoriaBombGridLeft, kCaldoriaBombGridTop); _grid.setDisplayOrder(kCaldoriaBombGridOrder); @@ -1234,6 +1246,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific _timer.start(); _currentLevel = 0; _lastVertex = -1; + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getAmbienceLevel()); startBombAmbient("Sounds/Caldoria/BmbLoop1.22K.AIFF"); break; case kCaldoria56BombStage2: @@ -1258,6 +1271,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific _grid.hide(); _timer.stop(); _timer.hide(); + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _owner->loadLoopSound1(""); _owner->playDeathExtra(kCaldoria56BombExplodes, kDeathNuclearExplosion); } @@ -1411,6 +1425,7 @@ void CaldoriaBomb::handleInput(const Input &input, const Hotspot *hotspot) { _timer.stop(); _grid.hide(); _timer.hide(); + _owner->_navMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput); break; } diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h index 5bb39b4122..ba6d1e8998 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h +++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h @@ -122,6 +122,9 @@ public: CaldoriaBomb(Neighborhood *, NotificationManager *); virtual ~CaldoriaBomb(); + void setSoundFXLevel(const uint16); + void setAmbienceLevel(const uint16); + long getNumHints(); Common::String getHintMovie(uint); void doSolve(); diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp index a3ce97d438..2ae990d775 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp @@ -24,6 +24,7 @@ */ #include "pegasus/gamestate.h" +#include "pegasus/pegasus.h" #include "pegasus/neighborhood/neighborhood.h" #include "pegasus/neighborhood/caldoria/caldoria.h" #include "pegasus/neighborhood/caldoria/caldoriamessages.h" @@ -45,6 +46,10 @@ void CaldoriaMessages::openInteraction() { _messageNumber = 1; } +void CaldoriaMessages::setSoundFXLevel(const uint16 fxLevel) { + _messageMovie.setVolume(fxLevel); +} + void CaldoriaMessages::initInteraction() { GameInteraction::_owner->startExtraSequence(kCaBedroomVidPhone, kExtraCompletedFlag, kFilterNoInput); } @@ -101,6 +106,7 @@ void CaldoriaMessages::play1Message(uint messageNumber) { GameState.setCaldoriaSeenMessages(true); } + _messageMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _messageMovie.moveElementTo(kCaldoriaMessageLeft, kCaldoriaMessageTop); _messageMovie.setDisplayOrder(kCaldoriaMessagesOrder); _messageMovie.startDisplaying(); diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h index 955fe10ce9..b2fc7c3bf9 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h +++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h @@ -41,6 +41,8 @@ public: CaldoriaMessages(Neighborhood *, const NotificationID, NotificationManager *); virtual ~CaldoriaMessages() {} + void setSoundFXLevel(const uint16); + protected: void openInteraction(); void initInteraction(); diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index 435bcd4c9e..df5a75541c 100644 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -535,6 +535,10 @@ void Mars::doorOpened() { } void Mars::setUpReactorEnergyDrain() { + // If there's no energy monitor, there's nothing to do + if (!g_energyMonitor) + return; + switch (GameState.getCurrentRoomAndView()) { case MakeRoomView(kMars51, kEast): if (GameState.isCurrentDoorOpen()) { @@ -2398,6 +2402,8 @@ void Mars::doCanyonChase() { if (!video->loadFile("Images/Mars/M44ESA.movie")) error("Could not load interface->shuttle transition video"); + video->setVolume(MIN<uint>(_vm->getSoundFXLevel(), 0xFF)); + video->start(); while (!_vm->shouldQuit() && !video->endOfVideo()) { @@ -2476,6 +2482,7 @@ void Mars::doCanyonChase() { _shuttleEnergyMeter.initShuttleEnergyMeter(); _shuttleEnergyMeter.powerUpMeter(); while (_shuttleEnergyMeter.isFading()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); g_system->updateScreen(); @@ -2607,6 +2614,7 @@ void Mars::startUpFromFinishedSpaceChase() { kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2645,6 +2653,7 @@ void Mars::startUpFromFinishedSpaceChase() { initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder, kShuttleWindowLeft, kShuttleWindowTop, true); + _canyonChaseMovie.setVolume(_vm->getSoundFXLevel()); _canyonChaseMovie.setTime(_canyonChaseMovie.getDuration()); _canyonChaseMovie.redrawMovieWorld(); } @@ -2720,6 +2729,7 @@ void Mars::startUpFromSpaceChase() { kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2783,6 +2793,10 @@ void Mars::startUpFromSpaceChase() { void Mars::setSoundFXLevel(const uint16 level) { Neighborhood::setSoundFXLevel(level); + if (GameState.getCurrentRoomAndView() == MakeRoomView(kMars48, kEast) && + !GameState.getMarsAvoidedReactorRobot()) + _loop2Fader.setMasterVolume(level); + if (_canyonChaseMovie.isMovieValid()) _canyonChaseMovie.setVolume(level); @@ -2812,6 +2826,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { GameState.setScoringEnteredLaunchTube(); while (_canyonChaseMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2836,6 +2851,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft, kShuttleJunkTop, false); initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false); + _explosions.setVolume(_vm->getSoundFXLevel()); _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes); _energyBeam.initShuttleWeapon(); @@ -2945,6 +2961,7 @@ void Mars::marsTimerExpired(MarsTimerEvent &event) { showBigExplosion(r, kShuttleAlienShipOrder); while (_explosions.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); g_system->delayMillis(10); @@ -3138,6 +3155,7 @@ void Mars::spaceChaseClick(const Input &input, const HotSpotID id) { _shuttleEnergyMeter.drainForTractorBeam(); while (_shuttleEnergyMeter.isFading()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -3167,11 +3185,13 @@ void Mars::spaceChaseClick(const Input &input, const HotSpotID id) { // Shameless reuse of a variable :P initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder, kShuttleWindowLeft, kShuttleWindowTop, true); + _canyonChaseMovie.setVolume(_vm->getSoundFXLevel()); _canyonChaseMovie.redrawMovieWorld(); playMovieSegment(&_canyonChaseMovie, 0, _canyonChaseMovie.getDuration()); // wait here until any junk clears... while (_junk.junkFlying()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp index 3116bd7978..c9be349694 100644 --- a/engines/pegasus/neighborhood/neighborhood.cpp +++ b/engines/pegasus/neighborhood/neighborhood.cpp @@ -470,6 +470,7 @@ void Neighborhood::requestSpotSound(const TimeValue in, const TimeValue out, con void Neighborhood::playSpotSoundSync(const TimeValue in, const TimeValue out) { // Let the action queue play out first... while (!actionQueueEmpty()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->checkNotifications(); @@ -480,6 +481,7 @@ void Neighborhood::playSpotSoundSync(const TimeValue in, const TimeValue out) { _spotSounds.playSoundSegment(in, out); while (_spotSounds.isPlaying()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -1105,6 +1107,7 @@ void Neighborhood::startTurnPush(const TurnDirection turnDirection, const TimeVa _turnPush.continueFader(); do { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -1492,7 +1495,15 @@ void Neighborhood::loadLoopSound2(const Common::String &soundName, uint16 volume if (!_loop2SoundString.empty()) { _soundLoop2.initFromAIFFFile(_loop2SoundString); _soundLoop2.loopSound(); - _loop2Fader.setMasterVolume(_vm->getAmbienceLevel()); + // HACK: Some ambient loops are actually sound effects, like Ares waiting at + // the reactor and Poseidon at the launch console. Detect these and use the + // SFX volume instead of ambience. + if (soundName == "Sounds/Mars/Robot Loop.aiff" || + soundName == "Sounds/Norad/Breathing Typing.22K.AIFF" || + soundName == "Sounds/Norad/N54NAS.32K.AIFF") + _loop2Fader.setMasterVolume(_vm->getSoundFXLevel()); + else + _loop2Fader.setMasterVolume(_vm->getAmbienceLevel()); _loop2Fader.setFaderValue(0); faderMove.makeTwoKnotFaderSpec(fadeScale, 0, 0, fadeIn, volume); _loop2Fader.startFaderSync(faderMove); @@ -1577,6 +1588,7 @@ void Neighborhood::closeCroppedMovie() { void Neighborhood::playCroppedMovieOnce(const Common::String &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) { openCroppedMovie(movieName, left, top); + _croppedMovie.setVolume(_vm->getSoundFXLevel()); _croppedMovie.redrawMovieWorld(); _croppedMovie.start(); @@ -1616,6 +1628,7 @@ void Neighborhood::playMovieSegment(Movie *movie, TimeValue startTime, TimeValue movie->start(); while (movie->isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h index 3c1c5eac92..f7f2b038c6 100644 --- a/engines/pegasus/neighborhood/neighborhood.h +++ b/engines/pegasus/neighborhood/neighborhood.h @@ -91,6 +91,7 @@ struct QueueRequest { bool operator==(const QueueRequest &arg1, const QueueRequest &arg2); bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2); +class CaldoriaBomb; class GameInteraction; class Item; class Neighborhood; @@ -109,6 +110,7 @@ protected: typedef Common::Queue<QueueRequest> NeighborhoodActionQueue; class Neighborhood : public IDObject, public NotificationReceiver, public InputHandler, public Idler { +friend class CaldoriaBomb; friend class StriderCallBack; public: diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.cpp b/engines/pegasus/neighborhood/norad/delta/globegame.cpp index 0b95e9bc2b..5c321a8e8a 100644 --- a/engines/pegasus/neighborhood/norad/delta/globegame.cpp +++ b/engines/pegasus/neighborhood/norad/delta/globegame.cpp @@ -453,8 +453,13 @@ GlobeGame::GlobeGame(Neighborhood *handler) : GameInteraction(kNoradGlobeGameInt _neighborhoodNotification = handler->getNeighborhoodNotification(); } +void GlobeGame::setSoundFXLevel(const uint16 fxLevel) { + _monitorMovie.setVolume(fxLevel); +} + void GlobeGame::openInteraction() { _monitorMovie.initFromMovieFile("Images/Norad Delta/N79 Left Monitor"); + _monitorMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel()); _monitorMovie.moveElementTo(kGlobeMonitorLeft, kGlobeMonitorTop); _monitorMovie.setDisplayOrder(kGlobeMonitorLayer); _monitorMovie.startDisplaying(); diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.h b/engines/pegasus/neighborhood/norad/delta/globegame.h index 73ed48866f..93235a1784 100644 --- a/engines/pegasus/neighborhood/norad/delta/globegame.h +++ b/engines/pegasus/neighborhood/norad/delta/globegame.h @@ -98,6 +98,8 @@ public: GlobeGame(Neighborhood *); virtual ~GlobeGame() {} + void setSoundFXLevel(const uint16); + void handleInput(const Input &, const Hotspot *); void clickInHotspot(const Input &, const Hotspot *); void activateHotspots(); diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp index 1eea2f0156..ee047d72b2 100644 --- a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp +++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp @@ -514,6 +514,17 @@ void NoradDelta::openDoor() { } } +void NoradDelta::cantMoveThatWay(CanOpenDoorReason reason) { + // WORKAROUND: The door outside the launch console room isn't treated as a door, + // so play the correct sound. + if (reason == kCantMoveBlocked && GameState.getCurrentRoomAndView() == MakeRoomView(kNorad67, kNorth)) { + cantOpenDoor(kCantOpenLocked); + return; + } + + Neighborhood::cantMoveThatWay(reason); +} + void NoradDelta::activateHotspots() { Norad::activateHotspots(); @@ -863,6 +874,13 @@ void NoradDelta::doSolve() { } } +void NoradDelta::setSoundFXLevel(const uint16 level) { + Neighborhood::setSoundFXLevel(level); + + if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad54North, kNorth)) + _loop2Fader.setMasterVolume(level); +} + Common::String NoradDelta::getSoundSpotsName() { return "Sounds/Norad/Norad Delta Spots"; } diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.h b/engines/pegasus/neighborhood/norad/delta/noraddelta.h index 11065f2c9d..591fd691a2 100644 --- a/engines/pegasus/neighborhood/norad/delta/noraddelta.h +++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.h @@ -68,6 +68,8 @@ public: bool canSolve(); void doSolve(); + void setSoundFXLevel(const uint16); + void doorOpened(); protected: @@ -90,6 +92,7 @@ protected: void arriveAtNorad79West(); TimeValue getViewTime(const RoomID, const DirectionConstant); void openDoor(); + void cantMoveThatWay(CanMoveForwardReason); void activateHotspots(); void clickInHotspot(const Input &, const Hotspot *); void receiveNotification(Notification *, const NotificationFlags); diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp index 75f652ad56..92b79c038e 100644 --- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp +++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp @@ -1692,7 +1692,9 @@ void FullTSA::initializeTBPMonitor(const int newMode, const ExtraID highlightExt releaseSprites(); } - _interruptionFilter = kFilterAllInput; + // Only allow input if we're not in the middle of series of queue requests. + if (actionQueueEmpty()) + _interruptionFilter = kFilterAllInput; } void FullTSA::startUpComparisonMonitor() { @@ -2643,6 +2645,7 @@ void FullTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp index 0326c7f2ee..c808325b0f 100644 --- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp +++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp @@ -327,6 +327,7 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification GameState.setMarsReadyForShuttleTransport(false); GameState.setMarsFinishedCanyonChase(false); GameState.setMarsThreadedMaze(false); + GameState.setMarsSawRobotLeave(false); break; case kPlayerOnWayToWSC: _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest); diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp index 09e2a48a52..f009b35cdc 100644 --- a/engines/pegasus/neighborhood/wsc/wsc.cpp +++ b/engines/pegasus/neighborhood/wsc/wsc.cpp @@ -2029,6 +2029,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { _moleculesMovie.start(); while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2063,6 +2064,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { _moleculesMovie.start(); while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); @@ -2076,6 +2078,7 @@ void WSC::moleculeGameClick(const HotSpotID id) { while (_moleculesMovie.isRunning()) { + InputDevice.pumpEvents(); _vm->checkCallBacks(); _vm->refreshDisplay(); _vm->_system->delayMillis(10); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index c5edd34a01..0010180d8d 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -36,6 +36,7 @@ #include "backends/keymapper/keymapper.h" #include "base/plugins.h" #include "base/version.h" +#include "gui/message.h" #include "gui/saveload.h" #include "video/theora_decoder.h" #include "video/qt_decoder.h" @@ -306,6 +307,7 @@ void PegasusEngine::runIntro() { Video::VideoDecoder *video = new Video::QuickTimeDecoder(); if (video->loadFile(_introDirectory + "/BandaiLogo.movie")) { + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); video->start(); while (!shouldQuit() && !video->endOfVideo() && !skipped) { @@ -337,6 +339,8 @@ void PegasusEngine::runIntro() { if (!video->loadFile(_introDirectory + "/Big Movie.movie")) error("Could not load intro movie"); + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); + video->seek(Audio::Timestamp(0, 10 * 600, 600)); video->start(); @@ -379,20 +383,21 @@ Common::Error PegasusEngine::showSaveDialog() { int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); - Common::Error result; + if (slot >= 0) + return saveGameState(slot, slc.getResultString()); - if (slot >= 0) { - if (saveGameState(slot, slc.getResultString()).getCode() == Common::kNoError) - result = Common::kNoError; - else - result = Common::kUnknownError; - } else { - result = Common::kUserCanceled; - } + return Common::kUserCanceled; +} - return result; +void PegasusEngine::showSaveFailedDialog(const Common::Error &status) { + Common::String failMessage = Common::String::format(_("Gamestate save failed (%s)! " + "Please consult the README for basic information, and for " + "instructions on how to obtain further assistance."), status.getDesc().c_str()); + GUI::MessageDialog dialog(failMessage); + dialog.runModal(); } + GUI::Debugger *PegasusEngine::getDebugger() { return _console; } @@ -792,6 +797,8 @@ void PegasusEngine::introTimerExpired() { if (!video->loadFile(_introDirectory + "/LilMovie.movie")) error("Failed to load little movie"); + video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF)); + bool saveAllowed = swapSaveAllowed(false); bool openAllowed = swapLoadAllowed(false); @@ -834,6 +841,7 @@ void PegasusEngine::delayShell(TimeValue time, TimeScale scale) { uint32 timeInMillis = time * 1000 / scale; while (g_system->getMillis() < startTime + timeInMillis) { + InputDevice.pumpEvents(); checkCallBacks(); _gfx->updateDisplay(); } @@ -938,6 +946,8 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { if (!video->loadFile(_introDirectory + "/Closing.movie")) error("Could not load closing movie"); + video->setVolume(MIN<uint>(getSoundFXLevel(), 0xFF)); + uint16 x = (640 - video->getWidth() * 2) / 2; uint16 y = (480 - video->getHeight() * 2) / 2; @@ -969,8 +979,14 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { resetIntroTimer(); break; case kMenuCmdPauseSave: - if (showSaveDialog().getCode() != Common::kUserCanceled) + result = showSaveDialog(); + + if (result.getCode() != Common::kUserCanceled) { + if (result.getCode() != Common::kNoError) + showSaveFailedDialog(result); + pauseMenu(false); + } break; case kMenuCmdPauseContinue: pauseMenu(false); @@ -1021,7 +1037,12 @@ void PegasusEngine::handleInput(const Input &input, const Hotspot *cursorSpot) { // Can only save during a game and not in the demo if (g_neighborhood && !isDemo()) { pauseEngine(true); - showSaveDialog(); + + Common::Error result = showSaveDialog(); + + if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled) + showSaveFailedDialog(result); + pauseEngine(false); } } @@ -1669,6 +1690,9 @@ void PegasusEngine::startNewGame() { removeAllItemsFromInventory(); removeAllItemsFromBiochips(); + // Properly reset all items to their original state + g_allItems.resetAllItems(); + BiochipItem *biochip = (BiochipItem *)_allItems.findItemByID(kAIBiochip); addItemToBiochips(biochip); @@ -2159,6 +2183,7 @@ void PegasusEngine::autoDragItemIntoRoom(Item *item, Sprite *draggingSprite) { _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale); while (_autoDragger.isDragging()) { + InputDevice.pumpEvents(); checkCallBacks(); refreshDisplay(); _system->delayMillis(10); @@ -2192,6 +2217,7 @@ void PegasusEngine::autoDragItemIntoInventory(Item *, Sprite *draggingSprite) { _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale); while (_autoDragger.isDragging()) { + InputDevice.pumpEvents(); checkCallBacks(); refreshDisplay(); _system->delayMillis(10); @@ -2268,10 +2294,7 @@ void PegasusEngine::doSubChase() { drawScaledFrame(frame, 0, 0); } - Common::Event event; - while (_eventMan->pollEvent(event)) - ; - + InputDevice.pumpEvents(); _system->delayMillis(10); } diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index fb66eb7586..d88545a4d1 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -257,6 +257,7 @@ private: bool _saveAllowed, _loadAllowed; // It's so nice that this was in the original code already :P Common::Error showLoadDialog(); Common::Error showSaveDialog(); + void showSaveFailedDialog(const Common::Error &status); bool _saveRequested, _loadRequested; // Misc. diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp index 96fa81488f..3706806ac2 100644 --- a/engines/queen/debug.cpp +++ b/engines/queen/debug.cpp @@ -21,6 +21,7 @@ */ #include "common/scummsys.h" +#include "common/util.h" #include "queen/debug.h" @@ -57,8 +58,17 @@ void Debugger::postEnter() { _vm->graphics()->setupMouseCursor(); } +static bool isNumeric(const char *arg) { + const char *str = arg; + bool retVal = true; + while (retVal && (*str != '\0')) { + retVal = Common::isDigit(*str++); + } + return retVal; +} + bool Debugger::Cmd_Asm(int argc, const char **argv) { - if (argc == 2) { + if (argc == 2 && isNumeric(argv[1])) { uint16 sm = atoi(argv[1]); _vm->logic()->executeSpecialMove(sm); return false; @@ -75,12 +85,17 @@ bool Debugger::Cmd_Areas(int argc, const char **argv) { } bool Debugger::Cmd_Bob(int argc, const char **argv) { - if (argc >= 3) { + if (argc >= 3 && isNumeric(argv[1])) { int bobNum = atoi(argv[1]); if (bobNum >= Graphics::MAX_BOBS_NUMBER) { DebugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER); } else { - int param = (argc > 3) ? atoi(argv[3]) : 0; + int param = 0; + if (argc > 3 && isNumeric(argv[3])) { + param = atoi(argv[3]); + } else { + DebugPrintf("Invalid parameter for bob command '%s'\n", argv[2]); + } BobSlot *bob = _vm->graphics()->bob(bobNum); if (!strcmp(argv[2], "toggle")) { bob->active = !bob->active; @@ -109,22 +124,21 @@ bool Debugger::Cmd_Bob(int argc, const char **argv) { bool Debugger::Cmd_GameState(int argc, const char **argv) { uint16 slot; - switch (argc) { - case 2: - slot = atoi(argv[1]); - DebugPrintf("GAMESTATE[%d] ", slot); - DebugPrintf("is %d\n", _vm->logic()->gameState(slot)); - break; - case 3: + if ((argc == 2 || argc == 3) && isNumeric(argv[1])) { slot = atoi(argv[1]); DebugPrintf("GAMESTATE[%d] ", slot); - DebugPrintf("was %d ", _vm->logic()->gameState(slot)); - _vm->logic()->gameState(slot, atoi(argv[2])); - DebugPrintf("now %d\n", _vm->logic()->gameState(slot)); - break; - default: - DebugPrintf("Usage: %s slotnum value\n", argv[0]); - break; + DebugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot)); + + if (argc == 3) { + if (isNumeric(argv[1])) { + _vm->logic()->gameState(slot, atoi(argv[2])); + DebugPrintf("now %d\n", _vm->logic()->gameState(slot)); + } else { + DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); + } + } + } else { + DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); } return true; } @@ -164,7 +178,7 @@ bool Debugger::Cmd_PrintBobs(int argc, const char**argv) { } bool Debugger::Cmd_Room(int argc, const char **argv) { - if (argc == 2) { + if (argc == 2 && isNumeric(argv[1])) { uint16 roomNum = atoi(argv[1]); _vm->logic()->joePos(0, 0); _vm->logic()->newRoom(roomNum); @@ -180,7 +194,7 @@ bool Debugger::Cmd_Room(int argc, const char **argv) { } bool Debugger::Cmd_Song(int argc, const char **argv) { - if (argc == 2) { + if (argc == 2 && isNumeric(argv[1])) { int16 songNum = atoi(argv[1]); _vm->sound()->playSong(songNum); DebugPrintf("Playing song %d\n", songNum); diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 29e29722d2..65acdbcdf5 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -37,6 +37,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" +#include "sci/sound/audio.h" #include "sci/console.h" namespace Sci { @@ -494,6 +495,21 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { Common::String str = s->_segMan->getString(argv[1]); debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); + // Handle sciAudio calls in fanmade games here. sciAudio is an + // external .NET library for playing MP3 files in fanmade games. + // It runs in the background, and obtains sound commands from the + // currently running game via text files (called "conductor files"). + // We skip creating these files, and instead handle the calls + // directly. Since the sciAudio calls are only creating text files, + // this is probably the most straightforward place to handle them. + if (handle == 0xFFFF && str.hasPrefix("(sciAudio")) { + Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin(); + iter--; // sciAudio + iter--; // sciAudio child + g_sci->_audio->handleFanmadeSciAudio(iter->sendp, s->_segMan); + return NULL_REG; + } + #ifdef ENABLE_SCI32 if (handle == VIRTUALFILE_HANDLE) { s->_virtualIndexFile->write(str.c_str(), str.size()); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index a405ee5c7c..b4d245197b 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -2668,8 +2668,8 @@ void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable, bool uint16 curWord; uint16 curCommand; uint32 curValue; - byte byte1; - byte byte2; + byte byte1 = 0; + byte byte2 = 0; int patchEntryCount = 0; // Count entries and allocate runtime data diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 3147fbda09..8e35d6b055 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -61,6 +61,62 @@ void AudioPlayer::stopAllAudio() { audioCdStop(); } +/** + * Handles the sciAudio calls in fanmade games. + * sciAudio is an external .NET library for playing MP3 files in fanmade games. + * It runs in the background, and obtains sound commands from the + * currently running game via text files (called "conductor files"). + * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0 + */ +void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) { + // TODO: This is a bare bones implementation. Only the play/playx and stop commands + // are handled for now - the other commands haven't been observed in any fanmade game + // yet. All the volume related and fading functionality is currently missing. + + Kernel *kernel = g_sci->getKernel(); + + reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command")); + Common::String command = segMan->getString(commandReg); + + if (command == "play" || command == "playx") { +#ifdef USE_MAD + reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName")); + Common::String fileName = segMan->getString(fileNameReg); + + int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount")); + // When loopCount is -1, we treat it as infinite looping, else no looping is done. + // This is observed by game scripts, which can set loopCount to all sorts of random values. + // Adjust loopCount for ScummVM's LoopingAudioStream semantics + loopCount = (loopCount == -1) ? 0 : 1; + + // Determine sound type + Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType; + if (fileName.hasPrefix("music")) + soundType = Audio::Mixer::kMusicSoundType; + else if (fileName.hasPrefix("speech")) + soundType = Audio::Mixer::kSpeechSoundType; + + Common::File *sciAudio = new Common::File(); + // Replace backwards slashes + for (uint i = 0; i < fileName.size(); i++) { + if (fileName[i] == '\\') + fileName.setChar('/', i); + } + sciAudio->open("sciAudio/" + fileName); + + Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES); + + // We only support one audio handle + _mixer->playStream(soundType, &_audioHandle, + Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount)); +#endif + } else if (command == "stop") { + _mixer->stopHandle(_audioHandle); + } else { + warning("Unhandled sciAudio command: %s", command.c_str()); + } +} + int AudioPlayer::startAudio(uint16 module, uint32 number) { int sampleLen; Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h index 545d35b2ee..9e65d6e0c8 100644 --- a/engines/sci/sound/audio.h +++ b/engines/sci/sound/audio.h @@ -75,6 +75,8 @@ public: void pauseAudio(); void resumeAudio(); + void handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan); + void setSoundSync(ResourceId id, reg_t syncObjAddr, SegManager *segMan); void doSoundSync(reg_t syncObjAddr, SegManager *segMan); void stopSoundSync(); diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index bb1a7ffaf1..1d1b6b4f13 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -380,7 +380,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int int size; assert(height >= 0); - assert(slot >= 0 && slot < 4); + assert((int)slot >= 0 && (int)slot < 4); if (_game.version >= 7) { if (slot == kMainVirtScreen && (_roomHeight != 0)) diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 8d278f6ddf..0aaff4c094 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -1242,7 +1242,9 @@ void ScummEngine::saveOrLoad(Serializer *s) { } s->saveUint16(0xFFFF); // End marker } else { - while ((type = (ResType)s->loadUint16()) != 0xFFFF) { + uint16 tmp; + while ((tmp = s->loadUint16()) != 0xFFFF) { + type = (ResType)tmp; while ((idx = s->loadUint16()) != 0xFFFF) { assert(idx < _res->_types[type].size()); loadResource(s, type, idx); @@ -1430,7 +1432,9 @@ void ScummEngine::saveOrLoad(Serializer *s) { } s->saveByte(0xFF); } else { - while ((type = (ResType)s->loadByte()) != 0xFF) { + uint8 tmp; + while ((tmp = s->loadByte()) != 0xFF) { + type = (ResType)tmp; idx = s->loadUint16(); _res->lock(type, idx); } diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp index a417bc2ece..63da42eec2 100644 --- a/engines/sky/debug.cpp +++ b/engines/sky/debug.cpp @@ -1108,6 +1108,15 @@ void Debugger::postEnter() { _mouse->resetCursor(); } +static bool isNumeric(const char *arg) { + const char *str = arg; + bool retVal = true; + while (retVal && (*str != '\0')) { + retVal = Common::isDigit(*str++); + } + return retVal; +} + bool Debugger::Cmd_ShowGrid(int argc, const char **argv) { _showGrid = !_showGrid; DebugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); @@ -1299,22 +1308,20 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { } bool Debugger::Cmd_Section(int argc, const char **argv) { - if (argc < 2) { - DebugPrintf("Example: %s 4\n", argv[0]); - return true; - } - - const int baseId[] = { START_ONE, START_S6, START_29, START_SC31, START_SC66, START_SC90, START_SC81 }; - int section = atoi(argv[1]); + if (argc == 2 && isNumeric(argv[1])) { + const int baseId[] = { START_ONE, START_S6, START_29, START_SC31, START_SC66, START_SC90, START_SC81 }; + int section = atoi(argv[1]); - if (section >= 0 && section <= 6) { - _logic->fnEnterSection(section == 6 ? 4 : section, 0, 0); - _logic->fnAssignBase(ID_FOSTER, baseId[section], 0); - _skyCompact->fetchCpt(ID_FOSTER)->megaSet = 0; + if (section >= 0 && section <= 6) { + _logic->fnEnterSection(section == 6 ? 4 : section, 0, 0); + _logic->fnAssignBase(ID_FOSTER, baseId[section], 0); + _skyCompact->fetchCpt(ID_FOSTER)->megaSet = 0; + } else { + DebugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6); + } } else { - DebugPrintf("Unknown section '%s'\n", argv[1]); + DebugPrintf("Example: %s 4\n", argv[0]); } - return true; } diff --git a/engines/sword25/util/lua/loslib.cpp b/engines/sword25/util/lua/loslib.cpp index 25bfa2d1b5..055dfdf19e 100644 --- a/engines/sword25/util/lua/loslib.cpp +++ b/engines/sword25/util/lua/loslib.cpp @@ -113,6 +113,9 @@ static int getfield (lua_State *L, const char *key, int d) { static int os_date (lua_State *L) { + #ifdef __PLAYSTATION2__ // missing: gmtime & strftime + lua_pushnil(L); + #else const char *s = luaL_optstring(L, 1, "%c"); // FIXME: Rewrite the code below to use OSystem::getTimeAndDate // Alternatively, remove it, if sword25 does not use it. @@ -160,6 +163,7 @@ static int os_date (lua_State *L) { } luaL_pushresult(&b); } + #endif return 1; } @@ -167,6 +171,9 @@ static int os_date (lua_State *L) { static int os_time (lua_State *L) { // FIXME: Rewrite the code below to use OSystem::getTimeAndDate. // Alternatively, remove it, if sword25 does not use it. + #ifdef __PLAYSTATION2__ // missing: mktime + lua_pushnil(L); + #else time_t t; if (lua_isnoneornil(L, 1)) /* called without args? */ t = time(NULL); /* get current time */ @@ -187,6 +194,7 @@ static int os_time (lua_State *L) { lua_pushnil(L); else lua_pushnumber(L, (lua_Number)t); + #endif return 1; } @@ -195,8 +203,10 @@ static int os_difftime (lua_State *L) { // FIXME: difftime is not portable, unfortunately. // So we either have to replace this code, or just remove it, // depending on whether sword25 actually uses it. + #ifndef __PLAYSTATION2__ // missing: difftime lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), (time_t)(luaL_optnumber(L, 2, 0)))); + #endif return 1; } diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp index 95f8c85efe..3f32503fdf 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp @@ -5048,6 +5048,7 @@ void Scene3700::signal() { Scene3800::Scene3800() { _desertDirection = 0; + _skylineRect.set(0, 0, 320, 87); } void Scene3800::synchronize(Serializer &s) { @@ -5220,7 +5221,8 @@ void Scene3800::initExits() { } void Scene3800::enterArea() { - R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.disableControl(CURSOR_WALK); + switch (_desertDirection) { case 0: R2_GLOBALS._player.postInit(); @@ -5346,7 +5348,6 @@ void Scene3800::postInit(SceneObjectList *OwnerList) { _westExit.setDetails(Rect(0, 87, 14, 168), EXITCURSOR_W, 3800); _westExit.setDest(Common::Point(7, 145)); - _skylineRect.set(0, 0, 320, 87); _background.setDetails(Rect(0, 0, 320, 200), 3800, 0, 1, 2, 1, (SceneItem *) NULL); enterArea(); diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp index 03ea4d3252..9a3c6d00ff 100644 --- a/engines/voyeur/events.cpp +++ b/engines/voyeur/events.cpp @@ -266,18 +266,18 @@ void EventsManager::pollEvents() { } return; case Common::EVENT_LBUTTONDOWN: - _vm->_eventsManager->_newLeftClick = true; - _vm->_eventsManager->_newMouseClicked = true; + _newLeftClick = true; + _newMouseClicked = true; return; case Common::EVENT_RBUTTONDOWN: - _vm->_eventsManager->_newRightClick = true; - _vm->_eventsManager->_newMouseClicked = true; + _newRightClick = true; + _newMouseClicked = true; return; case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONUP: - _vm->_eventsManager->_newMouseClicked = false; - _vm->_eventsManager->_newLeftClick = false; - _vm->_eventsManager->_newRightClick = false; + _newMouseClicked = false; + _newLeftClick = false; + _newRightClick = false; return; case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; @@ -574,13 +574,13 @@ void EventsManager::getMouseInfo() { } } - _vm->_eventsManager->_mouseClicked = _vm->_eventsManager->_newMouseClicked; - _vm->_eventsManager->_leftClick = _vm->_eventsManager->_newLeftClick; - _vm->_eventsManager->_rightClick = _vm->_eventsManager->_newRightClick; + _mouseClicked = _newMouseClicked; + _leftClick = _newLeftClick; + _rightClick = _newRightClick; - _vm->_eventsManager->_newMouseClicked = false; - _vm->_eventsManager->_newLeftClick = false; - _vm->_eventsManager->_newRightClick = false; + _newMouseClicked = false; + _newLeftClick = false; + _newRightClick = false; } void EventsManager::startCursorBlink() { diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index c5a1e91ef5..df9a8648db 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -625,6 +625,8 @@ bool BaseFontTT::initFont() { warning("Looking for %s", fontName.c_str()); _font = FontMan.getFontByName(fontName); } +#else + warning("BaseFontTT::InitFont - FreeType2-support not compiled in, TTF-fonts will not be loaded"); #endif // USE_FREETYPE2 // Fallback4: Just use the Big GUI-font. (REALLY undesireable) diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 48c75f634d..a659c434d0 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -107,11 +107,11 @@ public: } } // Prefix to avoid collisions with actually known games - name = "wmefan-" + name; + name = "wmeunk-" + name; Common::strlcpy(s_fallbackGameIdBuf, name.c_str(), sizeof(s_fallbackGameIdBuf) - 1); s_fallbackDesc.gameid = s_fallbackGameIdBuf; if (caption != name) { - caption += " (fangame) "; + caption += " (unknown version) "; char *offset = s_fallbackGameIdBuf + name.size() + 1; uint32 remainingLength = (sizeof(s_fallbackGameIdBuf) - 1) - (name.size() + 1); Common::strlcpy(offset, caption.c_str(), remainingLength); diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 0bf9fff4f3..6556d3b34a 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -38,6 +38,7 @@ static const PlainGameDescriptor wintermuteGames[] = { {"carolreed8", "Carol Reed 8 - Amber's Blood"}, {"carolreed9", "Carol Reed 9 - Cold Case Summer"}, {"chivalry", "Chivalry is Not Dead"}, + {"corrosion", "Corrosion: Cold Winter Waiting"}, {"deadcity", "Dead City"}, {"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"}, {"dirtysplit", "Dirty Split"}, @@ -58,6 +59,8 @@ static const PlainGameDescriptor wintermuteGames[] = { {"projectdoom", "Project: Doom"}, {"reversion1", "Reversion: The Escape"}, {"reversion2", "Reversion: The Meeting"}, + {"rhiannon", "Rhiannon: Curse of the four Branches"}, + {"ritter", "1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde"}, {"rosemary", "Rosemary"}, {"securanote", "Securanote"}, {"shaban", "Shaban"}, @@ -125,6 +128,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Bickadoodle (download from http://aethericgames.com/games/bickadoodle/download-bickadoodle/) + { + "bickadoodle", + "", + AD_ENTRY1s("data.dcp", "1584d83577c32add0fce27fae91141a2", 35337728), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Book of Gron Part One { "bookofgron", @@ -238,6 +251,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_TESTING, GUIO0() }, + // Corrosion: Cold Winter Waiting + { + "corrosion", + "", + AD_ENTRY1s("data.dcp", "ae885b1a8faa0b27f43c0e8f0df02fc9", 525931618), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_TESTING, + GUIO0() + }, // Dead City (Czech) { "deadcity", @@ -429,7 +452,21 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, - // Ghosts in the Sheet + // Ghost in the Sheet + { + "ghostsheet", + "", + { + {"english.dcp", 0, "e6d0aad2c89996bcabe416105a3d6d3a", 12221017}, + {"data.dcp", 0, "b2f8b05328e4881e15e98e845b63f451", 168003}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, + // Ghost in the Sheet (Demo) { "ghostsheet", "Demo", @@ -531,6 +568,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // J.U.L.I.A. (English, Bundle in a box-version) + { + "julia", + "Version 1.2", + AD_ENTRY1s("data.dcp", "fe90023ccc22f35185b40b910e0d03a2", 10101373), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // J.U.L.I.A. (English) (Demo) { "julia", @@ -997,6 +1044,56 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Reversion: The Meeting Version 2.0.2412 (Chinese) + { + "reversion2", + "Version 2.0.2412", + { + {"data.dcp", 0, "f4ffc4df24b7bebad56a24930f33a2bc", 255766600}, + {"xlanguage_nz.dcp", 0, "17c79af4928e24484bee77a7e807cc2a", 10737127}, + {"Linux.dcp", 0, "21858bd77dc86b03f701fd47900e2f51", 984535}, + AD_LISTEND + }, + Common::ZH_CNA, + Common::kPlatformLinux, + ADGF_UNSTABLE, + GUIO0() + }, + // Reversion: The Meeting Version 2.0.2412 (English) + { + "reversion2", + "Version 2.0.2412", + { + {"data.dcp", 0, "f4ffc4df24b7bebad56a24930f33a2bc", 255766600}, + {"xlanguage_en.dcp", 0, "0598bf752ce93b42bcaf1094df537c7b", 8533057}, + {"Linux.dcp", 0, "21858bd77dc86b03f701fd47900e2f51", 984535}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformLinux, + ADGF_UNSTABLE, + GUIO0() + }, + // Rhiannon: Curse of the four Branches + { + "rhiannon", + "", + AD_ENTRY1s("data.dcp", "870f348900b735f1cc79c0608ce32b0e", 1046169851), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, + // 1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde + { + "ritter", + "", + AD_ENTRY1s("data.dcp", "5ac416cee605d3a30f4d59687b1cdab2", 364260278), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Rosemary { "rosemary", diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp index b0c469c440..e1553580ec 100644 --- a/engines/wintermute/video/video_theora_player.cpp +++ b/engines/wintermute/video/video_theora_player.cpp @@ -127,6 +127,7 @@ bool VideoTheoraPlayer::initialize(const Common::String &filename, const Common: #if defined (USE_THEORADEC) _theoraDecoder = new Video::TheoraDecoder(); #else + warning("VideoTheoraPlayer::initialize - Theora support not compiled in, video will be skipped: %s", filename.c_str()); return STATUS_FAILED; #endif _theoraDecoder->loadStream(_file); diff --git a/engines/zvision/fonts/truetype_font.cpp b/engines/zvision/fonts/truetype_font.cpp index 03520f18b6..ba4d72bde8 100644 --- a/engines/zvision/fonts/truetype_font.cpp +++ b/engines/zvision/fonts/truetype_font.cpp @@ -39,12 +39,9 @@ namespace ZVision { TruetypeFont::TruetypeFont(ZVision *engine, int32 fontHeight) - : _engine(engine), - _fontHeight(fontHeight), + : _fontHeight(fontHeight), _font(0), - _lineHeight(0), - _maxCharWidth(0), - _maxCharHeight(0) { + _lineHeight(0) { } TruetypeFont::~TruetypeFont(void) { diff --git a/engines/zvision/fonts/truetype_font.h b/engines/zvision/fonts/truetype_font.h index 3b5805db14..64f53a2c3b 100644 --- a/engines/zvision/fonts/truetype_font.h +++ b/engines/zvision/fonts/truetype_font.h @@ -43,12 +43,12 @@ public: ~TruetypeFont(); private: - ZVision *_engine; +// ZVision *_engine; Graphics::Font *_font; int _lineHeight; - size_t _maxCharWidth; - size_t _maxCharHeight; +// size_t _maxCharWidth; +// size_t _maxCharHeight; public: int32 _fontHeight; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index ec392a877a..fa4e508494 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -250,7 +250,18 @@ void Dialog::handleKeyDown(Common::KeyState state) { close(); } - // TODO: tab/shift-tab should focus the next/previous focusable widget + if (state.keycode == Common::KEYCODE_TAB) { + // TODO: Maybe add Tab behaviours for all widgets too. + // searches through widgets on screen for tab widget + Widget *w = _firstWidget; + while (w) { + if (w->_type == kTabWidget) + if (w->handleKeyDown(state)) + return; + + w = w->_next; + } + } } void Dialog::handleKeyUp(Common::KeyState state) { diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp index a8b3f5450d..756781a04b 100644 --- a/gui/widgets/tab.cpp +++ b/gui/widgets/tab.cpp @@ -183,6 +183,7 @@ void TabWidget::setActiveTab(int tabID) { } _activeTab = tabID; _firstWidget = _tabs[tabID].firstWidget; + _boss->draw(); } } @@ -226,12 +227,34 @@ void TabWidget::handleMouseDown(int x, int y, int button, int clickCount) { } bool TabWidget::handleKeyDown(Common::KeyState state) { - // TODO: maybe there should be a way to switch between tabs - // using the keyboard? E.g. Alt-Shift-Left/Right-Arrow or something - // like that. + if (state.hasFlags(Common::KBD_SHIFT) && state.keycode == Common::KEYCODE_TAB) + adjustTabs(kTabBackwards); + else if (state.keycode == Common::KEYCODE_TAB) + adjustTabs(kTabForwards); + return Widget::handleKeyDown(state); } +void TabWidget::adjustTabs(int value) { + // Determine which tab is next + int tabID = _activeTab + value; + if (tabID >= (int)_tabs.size()) + tabID = 0; + else if (tabID < 0) + tabID = ((int)_tabs.size() - 1); + + // Slides _firstVisibleTab forward to the correct tab + int maxTabsOnScreen = (_w / _tabWidth); + if (tabID >= maxTabsOnScreen && (_firstVisibleTab + maxTabsOnScreen) < (int)_tabs.size()) + _firstVisibleTab++; + + // Slides _firstVisibleTab backwards to the correct tab + while (tabID < _firstVisibleTab) + _firstVisibleTab--; + + setActiveTab(tabID); +} + void TabWidget::reflowLayout() { Widget::reflowLayout(); diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h index 38aa089eb5..a01ee2d9dc 100644 --- a/gui/widgets/tab.h +++ b/gui/widgets/tab.h @@ -28,6 +28,11 @@ #include "common/array.h" namespace GUI { + +enum { + kTabForwards = 1, + kTabBackwards = -1 +}; class TabWidget : public Widget { typedef Common::String String; @@ -109,6 +114,8 @@ protected: virtual void drawWidget(); virtual Widget *findWidget(int x, int y); + + virtual void adjustTabs(int value); }; } // End of namespace GUI diff --git a/test/common/util.h b/test/common/util.h index cd65307612..e195f13a84 100644 --- a/test/common/util.h +++ b/test/common/util.h @@ -115,7 +115,7 @@ class UtilTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(Common::isAlnum('Z'), 1); TS_ASSERT_EQUALS(Common::isAlnum('1'), 1); TS_ASSERT_EQUALS(Common::isAlnum('0'), 1); - TS_ASSERT_EQUALS(Common::isAlnum('§'), 0); + TS_ASSERT_EQUALS(Common::isAlnum('\xA7'), 0); TS_ASSERT_EQUALS(Common::isAlnum('$'), 0); TS_ASSERT_EQUALS(Common::isAlnum(' '), 0); TS_ASSERT_EQUALS(Common::isAlnum('\n'), 0); @@ -136,7 +136,7 @@ class UtilTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(Common::isAlpha('Z'), 1); TS_ASSERT_EQUALS(Common::isAlpha('1'), 0); TS_ASSERT_EQUALS(Common::isAlpha('0'), 0); - TS_ASSERT_EQUALS(Common::isAlpha('§'), 0); + TS_ASSERT_EQUALS(Common::isAlpha('\xA7'), 0); TS_ASSERT_EQUALS(Common::isAlpha('$'), 0); TS_ASSERT_EQUALS(Common::isAlpha(' '), 0); TS_ASSERT_EQUALS(Common::isAlpha('\n'), 0); @@ -157,7 +157,7 @@ class UtilTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(Common::isDigit('Z'), 0); TS_ASSERT_EQUALS(Common::isDigit('1'), 1); TS_ASSERT_EQUALS(Common::isDigit('0'), 1); - TS_ASSERT_EQUALS(Common::isDigit('§'), 0); + TS_ASSERT_EQUALS(Common::isDigit('\xA7'), 0); TS_ASSERT_EQUALS(Common::isDigit('$'), 0); TS_ASSERT_EQUALS(Common::isDigit(' '), 0); TS_ASSERT_EQUALS(Common::isDigit('\n'), 0); @@ -178,7 +178,7 @@ class UtilTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(Common::isLower('Z'), 0); TS_ASSERT_EQUALS(Common::isLower('1'), 0); TS_ASSERT_EQUALS(Common::isLower('0'), 0); - TS_ASSERT_EQUALS(Common::isLower('§'), 0); + TS_ASSERT_EQUALS(Common::isLower('\xA7'), 0); TS_ASSERT_EQUALS(Common::isLower('$'), 0); TS_ASSERT_EQUALS(Common::isLower(' '), 0); TS_ASSERT_EQUALS(Common::isLower('\n'), 0); @@ -200,7 +200,7 @@ class UtilTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(Common::isUpper('Z'), 1); TS_ASSERT_EQUALS(Common::isUpper('1'), 0); TS_ASSERT_EQUALS(Common::isUpper('0'), 0); - TS_ASSERT_EQUALS(Common::isUpper('§'), 0); + TS_ASSERT_EQUALS(Common::isUpper('\xA7'), 0); TS_ASSERT_EQUALS(Common::isUpper('$'), 0); TS_ASSERT_EQUALS(Common::isUpper(' '), 0); TS_ASSERT_EQUALS(Common::isUpper('\n'), 0); diff --git a/test/cxxtest_mingw.h b/test/cxxtest_mingw.h index f407105bfe..380f638640 100644 --- a/test/cxxtest_mingw.h +++ b/test/cxxtest_mingw.h @@ -8,4 +8,4 @@ #undef main #endif // main -#endif // CXXTEST_MINGW
\ No newline at end of file +#endif // CXXTEST_MINGW diff --git a/video/flic_decoder.cpp b/video/flic_decoder.cpp index 5d27aa0a59..994f47cea8 100644 --- a/video/flic_decoder.cpp +++ b/video/flic_decoder.cpp @@ -176,7 +176,7 @@ const Graphics::Surface *FlicDecoder::FlicVideoTrack::decodeNextFrame() { uint16 newWidth = _fileStream->readUint16LE(); uint16 newHeight = _fileStream->readUint16LE(); - if ((newWidth != 0) && (newHeight != 0)) { + if ((newWidth != 0) || (newHeight != 0)) { if (newWidth == 0) newWidth = _surface->w; if (newHeight == 0) |