diff options
Diffstat (limited to 'engines/scumm')
-rw-r--r-- | engines/scumm/charset.cpp | 109 | ||||
-rw-r--r-- | engines/scumm/detection.cpp | 7 | ||||
-rw-r--r-- | engines/scumm/detection_tables.h | 4 | ||||
-rw-r--r-- | engines/scumm/gfx.cpp | 317 | ||||
-rwxr-xr-x | engines/scumm/gfxARM.s | 120 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse.cpp | 47 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse.h | 2 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse_script.cpp | 10 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse_sndmgr.cpp | 284 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse_sndmgr.h | 70 | ||||
-rw-r--r-- | engines/scumm/imuse_digi/dimuse_track.cpp | 31 | ||||
-rw-r--r-- | engines/scumm/input.cpp | 5 | ||||
-rw-r--r-- | engines/scumm/module.mk | 5 | ||||
-rw-r--r-- | engines/scumm/scumm-md5.h | 6 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 28 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 4 | ||||
-rw-r--r-- | engines/scumm/smush/smush_player.cpp | 7 | ||||
-rw-r--r-- | engines/scumm/sound.cpp | 15 | ||||
-rw-r--r-- | engines/scumm/string.cpp | 16 |
19 files changed, 742 insertions, 345 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 28012e5759..2271bf53a1 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -48,6 +48,11 @@ better separation of the various modules. void ScummEngine::loadCJKFont() { Common::File fp; _useCJKMode = false; + _textSurfaceMultiplier = 1; + + if (_game.platform == Common::kPlatformSegaCD) + return; + if (_language == Common::JA_JPN && _game.version <= 5) { // FM-TOWNS v3 / v5 Kanji int numChar = 256 * 32; _2byteWidth = 16; @@ -60,6 +65,7 @@ void ScummEngine::loadCJKFont() { fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); fp.close(); } + _textSurfaceMultiplier = 2; } else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) { int numChar = 0; const char *fontFile = NULL; @@ -76,7 +82,7 @@ void ScummEngine::loadCJKFont() { case Common::ZH_TWN: if (_game.id == GID_CMI) { fontFile = "chinese.fnt"; - numChar = 1; //FIXME + numChar = 13630; } break; default: @@ -85,9 +91,26 @@ void ScummEngine::loadCJKFont() { if (fontFile && fp.open(fontFile)) { debug(2, "Loading CJK Font"); _useCJKMode = true; - fp.seek(2, SEEK_CUR); - _2byteWidth = fp.readByte(); - _2byteHeight = fp.readByte(); + _textSurfaceMultiplier = 1; // No multiplication here + + switch (_language) { + case Common::KO_KOR: + fp.seek(2, SEEK_CUR); + _2byteWidth = fp.readByte(); + _2byteHeight = fp.readByte(); + break; + case Common::JA_JPN: + _2byteWidth = 16; + _2byteHeight = 16; + break; + case Common::ZH_TWN: + _2byteWidth = 16; + _2byteHeight = 15; + // 0xFE -> 0x21. also compared with 0x0d. perhaps a newline + break; + default: + break; + } _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); @@ -183,7 +206,7 @@ static int SJIStoFMTChunk(int f, int s) { //converts sjis code to fmt font offse } byte *ScummEngine::get2byteCharPtr(int idx) { - switch (_language) { + switch (_language) { case Common::KO_KOR: idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; break; @@ -191,6 +214,43 @@ byte *ScummEngine::get2byteCharPtr(int idx) { idx = SJIStoFMTChunk((idx % 256), (idx / 256)); break; case Common::ZH_TWN: + { + int base = 0; + byte low = idx % 256; + int high = 0; + + if (low >= 0x20 && low <= 0x7e) { + base = (low + low * 2 + 81012) * 5; + } else { + if (low >= 0xa1 && low <= 0xa3) { + base = 392820; + low += 0x5f; + } else if (low >= 0xa4 && low <= 0xc6) { + base = 0; + low += 0x5c; + } else if (low >= 0xc9 && low <= 0xf9) { + base = 162030; + low += 0x37; + } else { + base = 392820; + low = 0xff; + } + + if (low != 0xff) { + high = idx / 256; + if (high >= 0x40 && high <= 0x7e) { + high -= 0x40; + } else { + high -= 0x62; + } + + base += (low * 0x9d + high) * 30; + } + } + + return _2byteFontPtr + base; + break; + } default: idx = 0; } @@ -311,7 +371,7 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) { break; } } else { - if (chr == '@') + if (chr == '@' && _vm->_language != Common::ZH_TWN) continue; if (chr == 255 || (_vm->_game.version <= 6 && chr == 254)) { chr = text[pos++]; @@ -337,6 +397,15 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) { continue; } } + + // Some localizations may override colors + // See credits in Chinese COMI + if (chr == '^' && pos == 1) { + if (text[pos] == 'c') { + pos += 4; + chr = text[pos++]; + } + } } if ((chr & 0x80) && _vm->_useCJKMode) { pos++; @@ -1257,18 +1326,18 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } - if (ignoreCharsetMask || !vs->hasTwoBuffers) { + if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) { dst = vs->getPixels(_left, drawTop); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { - dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left; + dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier); drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight); } if (_str.left > _left) _str.left = _left; - _left += origWidth; + _left += origWidth / _vm->_textSurfaceMultiplier; if (_str.right < _left) { _str.right = _left; @@ -1276,8 +1345,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { _str.right++; } - if (_str.bottom < _top + height) - _str.bottom = _top + height; + if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier) + _str.bottom = _top + height / _vm->_textSurfaceMultiplier; } void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) { @@ -1391,8 +1460,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { _top += offsY; _left += offsX; - if (_left + origWidth > _right + 1 || _left < 0) { - _left += origWidth; + if (_left + origWidth / _vm->_textSurfaceMultiplier > _right + 1 || _left < 0) { + _left += origWidth / _vm->_textSurfaceMultiplier; _top -= offsY; return; } @@ -1424,7 +1493,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask); - _left += origWidth; + _left += origWidth / _vm->_textSurfaceMultiplier; if (_str.right < _left) { _str.right = _left; @@ -1432,8 +1501,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { _str.right++; } - if (_str.bottom < _top + height) - _str.bottom = _top + height; + if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier) + _str.bottom = _top + height / _vm->_textSurfaceMultiplier; _top -= offsY; } @@ -1473,12 +1542,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, } else { Graphics::Surface dstSurface; Graphics::Surface backSurface; - if (ignoreCharsetMask || !vs->hasTwoBuffers) { + if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) { dstSurface = *vs; dstPtr = vs->getPixels(_left, drawTop); } else { dstSurface = _vm->_textSurface; - dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch + _left; + dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier; } if (_blitAlso && vs->hasTwoBuffers) { @@ -1717,6 +1786,10 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) { if (_str.left > _left) _str.left = _left; + // Original keeps glyph width and character dimensions separately + if (_vm->_language == Common::ZH_TWN && width == 16) + width = 17; + _left += width; if (_str.right < shadow.right) diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index e9430337ff..be830cab64 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -231,14 +231,21 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) { switch (size) { case 439080: // 2daf3db71d23d99d19fc9a544fcf6431 return Common::EN_ANY; + case 322602: // caba99f4f5a0b69963e5a4d69e6f90af + return Common::ZH_TWN; case 493252: // 5d59594b24f3f1332e7d7e17455ed533 return Common::DE_DEU; case 461746: // 35bbe0e4d573b318b7b2092c331fd1fa return Common::FR_FRA; case 443439: // 4689d013f67aabd7c35f4fd7c4b4ad69 return Common::IT_ITA; + case 398613: // d1f5750d142d34c4c8f1f330a1278709 + return Common::KO_KOR; case 440586: // 5a1d0f4fa00917bdbfe035a72a6bba9d return Common::PT_BRA; + case 454457: // 0e5f450ec474a30254c0e36291fb4ebd + case 394083: // ad684ca14c2b4bf4c21a81c1dbed49bc + return Common::RU_RUS; case 449787: // 64f3fe479d45b52902cf88145c41d172 return Common::ES_ESP; } diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 246126611e..acde4e5ad0 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -79,6 +79,7 @@ static const PlainGameDescriptor gameDescriptions[] = { { "comi", "The Curse of Monkey Island" }, #endif + { "brstorm", "Bear Stormin'" }, { "fbear", "Fatty Bear's Birthday Surprise" }, { "fbpack", "Fatty Bear's Fun Pack" }, { "funpack", "Putt-Putt's Fun Pack" }, @@ -248,6 +249,7 @@ static const GameSettings gameVariantsTable[] = { {"funpack", 0, 0, GID_FUNPACK, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, {"fbpack", 0, 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, + {"brstorm", 0, 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, {"fbear", "HE 61", 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, {"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows}, @@ -461,6 +463,8 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "fbpack", "fbpack", kGenHEPC, UNK_LANG, UNK, 0 }, { "funpack", "funpack", kGenHEPC, UNK_LANG, UNK, 0 }, + { "brstorm", "brstorm", kGenHEPC, UNK_LANG, UNK, 0 }, + { "fbear", "fbear", kGenHEPC, UNK_LANG, UNK, 0 }, { "fbear", "fbdemo", kGenHEPC, UNK_LANG, UNK, 0 }, { "fbear", "Fatty Bear Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 }, diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 3547986ce3..c1e06609b9 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -35,9 +35,12 @@ #include "scumm/usage_bits.h" #include "scumm/he/wiz_he.h" #include "scumm/util.h" -#ifdef __DS__ -#include "blitters.h" -#endif + +#ifdef USE_ARM_GFX_ASM +extern "C" void DrawStripToScreenARM(int height, int width, byte const* text, byte const* src, byte* dst, + int vsPitch, int vmScreenWidth, int textSurfacePitch); +extern "C" void Copy8ColARM(byte* dst, int dstPitch, const byte* src, int height); +#endif /* USE_ARM_GFX_ASM */ namespace Scumm { @@ -47,6 +50,7 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h); static void copy8Col(byte *dst, int dstPitch, const byte *src, int height); static void clear8Col(byte *dst, int dstPitch, int height); +static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height); struct StripTable { int offsets[160]; @@ -535,21 +539,18 @@ void ScummEngine::updateDirtyScreen(VirtScreenNumber slot) { */ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) { - if (bottom <= top) + // Short-circuit if nothing has to be drawn + if (bottom <= top || top >= vs->h) return; - if (top >= vs->h) - return; - - assert(top >= 0 && bottom <= vs->h); // Paranoia checks + // Some paranoia checks + assert(top >= 0 && bottom <= vs->h); assert(x >= 0 && width <= vs->pitch); assert(_textSurface.pixels); - assert(_compositeBuf); + // Perform some clipping if (width > vs->w - x) width = vs->w - x; - - // Clip to the visible part of the scene if (top < _screenTop) top = _screenTop; if (bottom > _screenTop + _screenHeight) @@ -559,64 +560,112 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i int y = vs->topline + top - _screenTop; int height = bottom - top; - if (height <= 0 || width <= 0) + if (width <= 0 || height <= 0) return; - // Compute screen etc. buffer pointers const byte *src = vs->getPixels(x, top); - byte *dst = _compositeBuf + x + y * _screenWidth; + int m = _textSurfaceMultiplier; + byte *dst; + int vsPitch; + int pitch = vs->pitch; + + if (_useCJKMode && _textSurfaceMultiplier == 2) { + dst = _fmtownsBuf; + + scale2x(dst, _screenWidth * m, src, vs->pitch, width, height); + src = dst; + vsPitch = _screenWidth * m - width * m; + + } else { + vsPitch = vs->pitch - width; + } + + dst = _compositeBuf; + if (_game.version < 7) { - // Handle the text mask in older games; newer (V7/V8) games do not use it anymore. - const byte *text = (byte *)_textSurface.getBasePtr(x, y); - -#ifdef __DS__ - DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, _screenWidth, _textSurface.pitch); -#else + // For The Dig, FT and COMI, we just blit everything to the screen at once. + // For older games, things are more complicated. First off, we need to + // deal with the _textSurface, which needs to be composited over the + // screen contents. Secondly, a rendering mode might be active, which + // means a filter has to be applied. + + // Compute pointer to the text surface + assert(_compositeBuf); + const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m); + + // The values x, width, etc. are all multiples of 8 at this point, + // so loop unrolloing might be a good idea... + assert(0 == ((long)text & 3)); + assert(0 == (width & 3)); + // Compose the text over the game graphics - for (int h = 0; h < height; ++h) { - for (int w = 0; w < width; ++w) { - if (text[w] == CHARSET_MASK_TRANSPARENCY) - dst[w] = src[w]; - else - dst[w] = text[w]; + + // TODO: Optimize this code. There are several things that come immediately to mind: + // (1) Loop unrolling: We could read 4 or even 8 pixels at once, since everything is + // a multiple of 8 here. + // (2) More ASM versions (in particular, the ARM code for the NDS could be used on + // all ARM systems, couldn't it?) + // (3) Better encoding of the text surface data. This is the one with the biggest + // potential. + // (a) Keep an "isEmpty" marker for each pixel row in the _textSurface. The idea + // is that most rows won't contain any text data, so we can just use memcpy. + // (b) RLE encode the _textSurface row-wise. This is an improved variant of (a), + // but also more complicated to implement, and incurs a bigger overhead when + // writing to the text surface. +#ifdef ARM_USE_GFX_ASM + DrawStripToScreenARM(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch); +#else + for (int h = 0; h < height * m; ++h) { + for (int w = 0; w < width * m; ++w) { + byte tmp = *text++; + if (tmp == CHARSET_MASK_TRANSPARENCY) + tmp = *src; + *dst++ = tmp; + src++; } - src += vs->pitch; - dst += _screenWidth; - text += _textSurface.pitch; + src += vsPitch; + text += _textSurface.pitch - width * m; } #endif - } else { - // Just do a simple blit in V7/V8 games. - blit(dst, _screenWidth, src, vs->pitch, width, height); - } - - if (_renderMode == Common::kRenderCGA) - ditherCGA(_compositeBuf + x + y * _screenWidth, _screenWidth, x, y, width, height); + src = _compositeBuf; + pitch = width; + + if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { + ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height); + + src = _herculesBuf + x + y * Common::kHercW; + pitch = Common::kHercW; + + // center image on the screen + x += (Common::kHercW - _screenWidth * 2) / 2; // (720 - 320*2)/2 = 40 + } else if (_useCJKMode && m == 2) { + pitch *= m; + x *= m; + y *= m; + width *= m; + height *= m; + } else { + if (_renderMode == Common::kRenderCGA) + ditherCGA(_compositeBuf, width, x, y, width, height); + + // HACK: This is dirty hack which renders narrow NES rooms centered + // NES can address negative number strips and that poses problem for + // our code. So instead of adding zillions of fixes and potentially + // breaking other games, we shift it right at the rendering stage. + if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) { + x += 16; + while (x + width >= _screenWidth) + width -= 16; + if (width < 0) + return; + } - if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { - ditherHerc(_compositeBuf + x + y * _screenWidth, _herculesBuf, _screenWidth, &x, &y, &width, &height); - // center image on the screen - _system->copyRectToScreen(_herculesBuf + x + y * Common::kHercW, - Common::kHercW, x + (Common::kHercW - _screenWidth * 2) / 2, y, width, height); - } else { - // Finally blit the whole thing to the screen - int x1 = x; - - // HACK: This is dirty hack which renders narrow NES rooms centered - // NES can address negative number strips and that poses problem for - // our code. So instead of adding zillions of fixes and potentially - // breaking other games, we shift it right at the rendering stage. - if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) { - x += 16; - while (x + width >= _screenWidth) - width -= 16; - if (width < 0) - return; } - - _system->copyRectToScreen(_compositeBuf + x1 + y * _screenWidth, _screenWidth, x, y, width, height); } + + // Finally blit the whole thing to the screen + _system->copyRectToScreen(src, pitch, x, y, width, height); } // CGA @@ -644,10 +693,10 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in for (int y1 = 0; y1 < height; y1++) { ptr = dst + y1 * dstPitch; - idx1 = (y + y1) % 2; - if (_game.version == 2) idx1 = 0; + else + idx1 = (y + y1) % 2; for (int x1 = 0; x1 < width; x1++) { idx2 = (x + x1) % 2; @@ -666,39 +715,52 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in // dd cccc0 // cccc1 // dddd0 -void ScummEngine::ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const { +void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) { byte *srcptr, *dstptr; - int xo = *x, yo = *y, widtho = *width, heighto = *height; - int idx1, idx2, dsty = 0, y1; + const int xo = *x, yo = *y, widtho = *width, heighto = *height; + int dsty = yo*2 - yo/4; - // calculate dsty - for (y1 = 0; y1 < yo; y1++) { - dsty += 2; - if (y1 % 4 == 3) - dsty--; - } - *y = dsty; - *x *= 2; - *width *= 2; - *height = 0; + for (int y1 = 0; y1 < heighto;) { + assert(dsty < Common::kHercH); - for (y1 = 0; y1 < heighto;) { srcptr = src + y1 * srcPitch; dstptr = hercbuf + dsty * Common::kHercW + xo * 2; - assert(dstptr < hercbuf + Common::kHercW * Common::kHercH + widtho * 2); - - idx1 = (dsty % 7) % 2; + const int idx1 = (dsty % 7) % 2; for (int x1 = 0; x1 < widtho; x1++) { - idx2 = (xo + x1) % 2; - *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] >> 1; - *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] & 0x1; + const int idx2 = (xo + x1) % 2; + const byte tmp = cgaDither[idx1][idx2][*srcptr & 0xF]; + *dstptr++ = tmp >> 1; + *dstptr++ = tmp & 0x1; srcptr++; } if (idx1 || dsty % 7 == 6) y1++; dsty++; - (*height)++; + } + + *x *= 2; + *y = yo*2 - yo/4; + *width *= 2; + *height = dsty - *y; +} + +void ScummEngine::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) { + byte *dstL1 = dst; + byte *dstL2 = dst + dstPitch; + + int dstAdd = dstPitch * 2 - w * 2; + int srcAdd = srcPitch - w; + + while (h--) { + for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) { + uint16 col = *src++; + col |= col << 8; + *(uint16*)(dstL1) = col; + *(uint16*)(dstL2) = col; + } + dstL1 += dstAdd; dstL2 += dstAdd; + src += srcAdd; } } @@ -1004,11 +1066,14 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) { } } +#ifdef ARM_USE_GFX_ASM + +#define copy8Col(A,B,C,D) copy8ColARM(A,B,C,D) + +#else + static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) { -#ifndef __DS__ - - do { #if defined(SCUMM_NEED_ALIGNMENT) memcpy(dst, src, 8); @@ -1019,12 +1084,10 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) { dst += dstPitch; src += dstPitch; } while (--height); -#else - DS::asmCopy8Col(dst, dstPitch, src, height); -#endif - } +#endif /* ARM_USE_GFX_ASM */ + static void clear8Col(byte *dst, int dstPitch, int height) { do { #if defined(SCUMM_NEED_ALIGNMENT) @@ -1098,8 +1161,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) { error("can only copy bg to main window"); blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height); if (_charset->_hasMask) { - byte *mask = (byte *)_textSurface.getBasePtr(x, y - _screenTop); - fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); + byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier); + fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier); } } else if (_game.heversion >= 71) { // Flags are used for different methods in HE games @@ -3343,7 +3406,17 @@ void ScummEngine::dissolveEffect(int width, int height) { for (i = 0; i < w * h; i++) { x = offsets[i] % vs->pitch; y = offsets[i] / vs->pitch; - _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height); + + if (_useCJKMode && _textSurfaceMultiplier == 2) { + int m = _textSurfaceMultiplier; + byte *dst = _fmtownsBuf + x * m + y * m * _screenWidth * m; + scale2x(dst, _screenWidth * m, vs->getPixels(x, y), vs->pitch, width, height); + + _system->copyRectToScreen(dst, _screenWidth * m, x * m, (y + vs->topline) * m, width * m, height * m); + } else { + _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height); + } + if (++blits >= blits_before_refresh) { blits = 0; @@ -3372,16 +3445,30 @@ void ScummEngine::scrollEffect(int dir) { step = (step * delay) / kScrolltime; + byte *src; + int m = _textSurfaceMultiplier; + int vsPitch = vs->pitch; + switch (dir) { case 0: //up y = 1 + step; while (y < vs->h) { moveScreen(0, -step, vs->h); - _system->copyRectToScreen(vs->getPixels(0, y - step), - vs->pitch, - 0, vs->h - step, - vs->w, step); + + src = vs->getPixels(0, y - step); + if (_useCJKMode && m == 2) { + int x1 = 0, y1 = vs->h - step; + byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; + scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); + src = dst; + vsPitch = _screenWidth * 2; + } + + _system->copyRectToScreen(src, + vsPitch, + 0 * m, (vs->h - step) * m, + vs->w * m, step * m); _system->updateScreen(); waitForTimer(delay); @@ -3393,10 +3480,18 @@ void ScummEngine::scrollEffect(int dir) { y = 1 + step; while (y < vs->h) { moveScreen(0, step, vs->h); - _system->copyRectToScreen(vs->getPixels(0, vs->h - y), - vs->pitch, + src = vs->getPixels(0, vs->h - y); + if (_useCJKMode && m == 2) { + int x1 = 0, y1 = 0; + byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; + scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); + src = dst; + vsPitch = _screenWidth * 2; + } + _system->copyRectToScreen(src, + vsPitch, 0, 0, - vs->w, step); + vs->w * m, step * m); _system->updateScreen(); waitForTimer(delay); @@ -3408,10 +3503,18 @@ void ScummEngine::scrollEffect(int dir) { x = 1 + step; while (x < vs->w) { moveScreen(-step, 0, vs->h); - _system->copyRectToScreen(vs->getPixels(x - step, 0), - vs->pitch, - vs->w - step, 0, - step, vs->h); + src = vs->getPixels(x - step, 0); + if (_useCJKMode && m == 2) { + int x1 = vs->w - step, y1 = 0; + byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; + scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); + src = dst; + vsPitch = _screenWidth * 2; + } + _system->copyRectToScreen(src, + vsPitch, + (vs->w - step) * m, 0, + step * m, vs->h * m); _system->updateScreen(); waitForTimer(delay); @@ -3423,8 +3526,16 @@ void ScummEngine::scrollEffect(int dir) { x = 1 + step; while (x < vs->w) { moveScreen(step, 0, vs->h); - _system->copyRectToScreen(vs->getPixels(vs->w - x, 0), - vs->pitch, + src = vs->getPixels(vs->w - x, 0); + if (_useCJKMode && m == 2) { + int x1 = 0, y1 = 0; + byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; + scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); + src = dst; + vsPitch = _screenWidth * 2; + } + _system->copyRectToScreen(src, + vsPitch, 0, 0, step, vs->h); _system->updateScreen(); diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s new file mode 100755 index 0000000000..fa2457fb29 --- /dev/null +++ b/engines/scumm/gfxARM.s @@ -0,0 +1,120 @@ +@ ScummVM Scumm Interpreter +@ Copyright (C) 2007 The ScummVM project +@ +@ This program is free software@ you can redistribute it and/or +@ modify it under the terms of the GNU General Public License +@ as published by the Free Software Foundation@ either version 2 +@ of the License, or (at your option) any later version. +@ +@ This program is distributed in the hope that it will be useful, +@ but WITHOUT ANY WARRANTY; without even the implied warranty of +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@ GNU General Public License for more details. +@ +@ You should have received a copy of the GNU General Public License +@ along with this program@ if not, write to the Free Software +@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +@ +@ $URL: $ +@ $Id: $ +@ +@ @author Robin Watts (robin@wss.co.uk) + + .text + + .global asmDrawStripToScreen + + @ ARM implementation of asmDrawStripToScreen. + @ + @ C prototype would be: + @ + @ extern "C" void asmDrawStripToScreen(int height, + @ int width, + @ byte const *text, + @ byte const *src, + @ byte *dst, + @ int vsPitch, + @ int vsScreenWidth, + @ int textSurfacePitch); + @ + @ In addition, we assume that text, src and dst are all word (4 byte) + @ aligned. This is the same assumption that the old 'inline' version + @ made. +asmDrawStripToScreen: + @ r0 = height + @ r1 = width + @ r2 = text + @ r3 = src + MOV r12,r13 + STMFD r13!,{r4-r7,r9-r11,R14} + LDMIA r12,{r4,r5,r6,r7} + @ r4 = dst + @ r5 = vsPitch + @ r6 = vmScreenWidth + @ r7 = textSurfacePitch + + CMP r0,#0 @ If height<=0 + MOVLE r0,#1 @ height=1 + CMP r1,#4 @ If width<4 + BLT end @ return + + @ Width &= ~4 ? What's that about then? Width &= ~3 I could have + @ understood... + BIC r1,r1,#4 + + SUB r5,r5,r1 @ vsPitch -= width + SUB r6,r6,r1 @ vmScreenWidth -= width + SUB r7,r7,r1 @ textSurfacePitch -= width + MOV r10,#253 + ORR r10,r10,r10,LSL #8 + ORR r10,r10,r10,LSL #16 @ r10 = mask +yLoop: + MOV r14,r1 @ r14 = width +xLoop: + LDR r12,[r2],#4 @ r12 = [text] + LDR r11,[r3],#4 @ r11 = [src] + CMP r12,r10 + BNE singleByteCompare + SUBS r14,r14,#4 + STR r11,[r4], #4 @ r4 = [dst] + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop + LDMFD r13!,{r4-r7,r9-r11,PC} + +singleByteCompare: + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + STR r12,[r4],#4 + SUBS r14,r14,#4 + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop +end: + LDMFD r13!,{r4-r7,r9-r11,PC} diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 0221657966..6d2e7dd217 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -166,10 +166,10 @@ void IMuseDigital::saveOrLoad(Serializer *ser) { continue; } - track->soundHandle = _sound->openSound(track->soundId, + track->soundDesc = _sound->openSound(track->soundId, track->soundName, track->soundType, track->volGroupId, -1); - if (!track->soundHandle) { + if (!track->soundDesc) { warning("IMuseDigital::saveOrLoad: Can't open sound so will not be resumed, propably on diffrent CD"); track->streamSou = NULL; track->stream = NULL; @@ -180,14 +180,14 @@ void IMuseDigital::saveOrLoad(Serializer *ser) { if (track->sndDataExtComp) { track->regionOffset = 0; } - track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle); + track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc); if (track->sndDataExtComp) { track->regionOffset = 0; } - track->dataOffset = _sound->getRegionOffset(track->soundHandle, track->curRegion); - int bits = _sound->getBits(track->soundHandle); - int channels = _sound->getChannels(track->soundHandle); - int freq = _sound->getFreq(track->soundHandle); + track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion); + int bits = _sound->getBits(track->soundDesc); + int channels = _sound->getChannels(track->soundDesc); + int freq = _sound->getFreq(track->soundDesc); track->feedSize = freq * channels; track->mixerFlags = 0; if (channels == 2) @@ -221,6 +221,7 @@ void IMuseDigital::saveOrLoad(Serializer *ser) { type = Audio::Mixer::kMusicSoundType; _mixer->playInputStream(type, &track->mixChanHandle, track->stream, -1, vol, pan, false); + _mixer->pauseHandle(track->mixChanHandle, true); } } } @@ -284,8 +285,8 @@ void IMuseDigital::callback() { continue; } - int bits = _sound->getBits(track->soundHandle); - int channels = _sound->getChannels(track->soundHandle); + int bits = _sound->getBits(track->soundDesc); + int channels = _sound->getChannels(track->soundDesc); int32 feedSize = track->feedSize / _callbackFps; @@ -316,12 +317,12 @@ void IMuseDigital::callback() { track->dataMod12Bit = feedSize - tmpLength12Bits; int32 tmpOffset = (track->regionOffset * 3) / 4; - int tmpFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits); + int tmpFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits); curFeedSize = BundleCodecs::decode12BitsSample(tmpPtr, &tmpSndBufferPtr, tmpFeedSize); free(tmpPtr); } else if (bits == 16) { - curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); + curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); if (channels == 1) { curFeedSize &= ~1; } @@ -329,7 +330,7 @@ void IMuseDigital::callback() { curFeedSize &= ~3; } } else if (bits == 8) { - curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); + curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); if (channels == 2) { curFeedSize &= ~1; } @@ -346,7 +347,7 @@ void IMuseDigital::callback() { } else delete[] tmpSndBufferPtr; - if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) { + if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) { switchToNextRegion(track); if (track->toBeRemoved) break; @@ -379,7 +380,7 @@ void IMuseDigital::switchToNextRegion(Track *track) { return; } - int num_regions = _sound->getNumRegions(track->soundHandle); + int num_regions = _sound->getNumRegions(track->soundDesc); if (++track->curRegion == num_regions) { track->toBeRemoved = true; @@ -387,22 +388,22 @@ void IMuseDigital::switchToNextRegion(Track *track) { return; } - ImuseDigiSndMgr::soundStruct *soundHandle = track->soundHandle; - int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId); + ImuseDigiSndMgr::SoundDesc *soundDesc = track->soundDesc; + int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId); if (jumpId == -1) - jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0); + jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0); if (jumpId != -1) { - int region = _sound->getRegionIdByJumpId(soundHandle, jumpId); + int region = _sound->getRegionIdByJumpId(soundDesc, jumpId); assert(region != -1); - int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId); + int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId); assert(sampleHookId != -1); - int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000; + int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000; if (sampleHookId != 0) { if (track->curHookId == sampleHookId) { if (fadeDelay != 0) { Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay); if (fadeTrack) { - fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion); + fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion); fadeTrack->regionOffset = 0; debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId); fadeTrack->curHookId = 0; @@ -416,7 +417,7 @@ void IMuseDigital::switchToNextRegion(Track *track) { if (fadeDelay != 0) { Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay); if (fadeTrack) { - fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion); + fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion); fadeTrack->regionOffset = 0; debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId); } @@ -427,7 +428,7 @@ void IMuseDigital::switchToNextRegion(Track *track) { } debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", track->soundId, track->curRegion, track->curHookId); - track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion); + track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion); track->regionOffset = 0; } diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h index 1b088298df..dca9baac60 100644 --- a/engines/scumm/imuse_digi/dimuse.h +++ b/engines/scumm/imuse_digi/dimuse.h @@ -98,7 +98,7 @@ private: int32 dataMod12Bit; // value used between all callback to align 12 bit source of data int32 mixerFlags; // flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagReverseStereo, kFlagUnsigned, kFlagLittleEndian) - ImuseDigiSndMgr::soundStruct *soundHandle; // sound handle used by iMuse sound manager + ImuseDigiSndMgr::SoundDesc *soundDesc; // sound handle used by iMuse sound manager Audio::SoundHandle mixChanHandle; // sound mixer's channel handle Audio::AppendableAudioStream *stream; // sound mixer's audio stream handle for *.la1 and *.bun Audio::AudioStream *streamSou; // sound mixer's audio stream handle for *.sou diff --git a/engines/scumm/imuse_digi/dimuse_script.cpp b/engines/scumm/imuse_digi/dimuse_script.cpp index 186d04483e..ddc0cd5107 100644 --- a/engines/scumm/imuse_digi/dimuse_script.cpp +++ b/engines/scumm/imuse_digi/dimuse_script.cpp @@ -179,8 +179,8 @@ void IMuseDigital::flushTracks() { _mixer->stopHandle(track->mixChanHandle); delete track->stream; track->stream = NULL; - _sound->closeSound(track->soundHandle); - track->soundHandle = NULL; + _sound->closeSound(track->soundDesc); + track->soundDesc = NULL; track->used = false; } } else if (track->streamSou) { @@ -245,7 +245,7 @@ void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { Track *track = _track[l]; if ((track->soundId == soundId) && track->used && !track->toBeRemoved) { - _sound->getSyncSizeAndPtrById(track->soundHandle, syncId, sync_size, &sync_ptr); + _sound->getSyncSizeAndPtrById(track->soundDesc, syncId, sync_size, &sync_ptr); if ((sync_size != 0) && (sync_ptr != NULL)) { sync_size /= 4; while (sync_size--) { @@ -396,8 +396,8 @@ void IMuseDigital::stopAllSounds() { _mixer->stopHandle(track->mixChanHandle); delete track->stream; track->stream = NULL; - _sound->closeSound(track->soundHandle); - track->soundHandle = NULL; + _sound->closeSound(track->soundDesc); + track->soundDesc = NULL; } else if (track->streamSou) { _mixer->stopHandle(track->mixChanHandle); delete track->streamSou; diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp index ce963eaeea..be80cb73e8 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/util.h" +#include "sound/flac.h" #include "sound/voc.h" #include "sound/vorbis.h" #include "sound/mp3.h" @@ -40,7 +41,7 @@ namespace Scumm { ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) { for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { - memset(&_sounds[l], 0, sizeof(soundStruct)); + memset(&_sounds[l], 0, sizeof(SoundDesc)); } _vm = scumm; _disk = 0; @@ -88,7 +89,7 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i } while (tag != MKID_BE('DATA')); } -void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size) { +void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size) { int l; file->seek(offset, SEEK_SET); @@ -104,11 +105,11 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun sound->numRegions = file->readUint32BE(); sound->numJumps = file->readUint32BE(); sound->numSyncs = file->readUint32BE(); - sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions); + sound->region = new Region[sound->numRegions]; assert(sound->region); - sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps); + sound->jump = new Jump[sound->numJumps]; assert(sound->jump); - sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs); + sound->sync = new Sync[sound->numSyncs]; assert(sound->sync); for (l = 0; l < sound->numRegions; l++) { sound->region[l].offset = file->readUint32BE(); @@ -127,7 +128,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun } } -void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) { +void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) { bool quit = false; int len; @@ -135,10 +136,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) { int32 offset = READ_LE_UINT16(ptr + 20); int16 code = READ_LE_UINT16(ptr + 24); - sound->region = (_region *)malloc(sizeof(_region) * 70); + sound->numRegions = 0; + sound->region = new Region[70]; assert(sound->region); - sound->jump = (_jump *)malloc(sizeof(_jump)); + + sound->numJumps = 0; + sound->jump = new Jump[1]; assert(sound->jump); + + sound->numSyncs = 0; + sound->resPtr = ptr; sound->bits = 8; sound->channels = 1; @@ -205,11 +212,11 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) { sound->numJumps = 0; sound->numSyncs = 0; countElements(ptr, sound->numRegions, sound->numJumps, sound->numSyncs); - sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions); + sound->region = new Region[sound->numRegions]; assert(sound->region); - sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps); + sound->jump = new Jump[sound->numJumps]; assert(sound->jump); - sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs); + sound->sync = new Sync[sound->numSyncs]; assert(sound->sync); do { @@ -260,7 +267,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) { } } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() { +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::allocSlot() { for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { if (!_sounds[l].inUse) { _sounds[l].inUse = true; @@ -271,7 +278,7 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() { return NULL; } -bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) { +bool ImuseDigiSndMgr::openMusicBundle(SoundDesc *sound, int disk) { bool result = false; sound->bundle = new BundleMgr(_cacheBundleDir); @@ -306,7 +313,7 @@ bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) { return result; } -bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) { +bool ImuseDigiSndMgr::openVoiceBundle(SoundDesc *sound, int disk) { bool result = false; sound->bundle = new BundleMgr(_cacheBundleDir); @@ -341,11 +348,11 @@ bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) { return result; } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) { +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) { assert(soundId >= 0); assert(soundType); - soundStruct *sound = allocSlot(); + SoundDesc *sound = allocSlot(); if (!sound) { error("ImuseDigiSndMgr::openSound() can't alloc free sound slot"); } @@ -423,99 +430,97 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch return sound; } -void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); +void ImuseDigiSndMgr::closeSound(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); - if (soundHandle->resPtr) { + if (soundDesc->resPtr) { bool found = false; for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { - if ((_sounds[l].soundId == soundHandle->soundId) && (&_sounds[l] != soundHandle)) + if ((_sounds[l].soundId == soundDesc->soundId) && (&_sounds[l] != soundDesc)) found = true; } if (!found) - _vm->_res->unlock(rtSound, soundHandle->soundId); + _vm->_res->unlock(rtSound, soundDesc->soundId); } - if (soundHandle->compressedStream) - delete soundHandle->compressedStream; - - delete soundHandle->bundle; + delete soundDesc->compressedStream; + delete soundDesc->bundle; - for (int r = 0; r < soundHandle->numSyncs; r++) - free(soundHandle->sync[r].ptr); - free(soundHandle->region); - free(soundHandle->jump); - free(soundHandle->sync); - memset(soundHandle, 0, sizeof(soundStruct)); + for (int r = 0; r < soundDesc->numSyncs; r++) + free(soundDesc->sync[r].ptr); + delete[] soundDesc->region; + delete[] soundDesc->jump; + delete[] soundDesc->sync; + memset(soundDesc, 0, sizeof(SoundDesc)); } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::cloneSound(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::cloneSound(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); - return openSound(soundHandle->soundId, soundHandle->name, soundHandle->type, soundHandle->volGroupId, soundHandle->disk); + return openSound(soundDesc->soundId, soundDesc->name, soundDesc->type, soundDesc->volGroupId, soundDesc->disk); } -bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) { - if (!soundHandle) +bool ImuseDigiSndMgr::checkForProperHandle(SoundDesc *soundDesc) { + if (!soundDesc) return false; for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { - if (soundHandle == &_sounds[l]) + if (soundDesc == &_sounds[l]) return true; } return false; } -bool ImuseDigiSndMgr::isSndDataExtComp(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->compressed; +bool ImuseDigiSndMgr::isSndDataExtComp(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->compressed; } -int ImuseDigiSndMgr::getFreq(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->freq; +int ImuseDigiSndMgr::getFreq(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->freq; } -int ImuseDigiSndMgr::getBits(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->bits; +int ImuseDigiSndMgr::getBits(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->bits; } -int ImuseDigiSndMgr::getChannels(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->channels; +int ImuseDigiSndMgr::getChannels(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->channels; } -bool ImuseDigiSndMgr::isEndOfRegion(soundStruct *soundHandle, int region) { - assert(checkForProperHandle(soundHandle)); - assert(region >= 0 && region < soundHandle->numRegions); - return soundHandle->endFlag; +bool ImuseDigiSndMgr::isEndOfRegion(SoundDesc *soundDesc, int region) { + assert(checkForProperHandle(soundDesc)); + assert(region >= 0 && region < soundDesc->numRegions); + return soundDesc->endFlag; } -int ImuseDigiSndMgr::getNumRegions(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->numRegions; +int ImuseDigiSndMgr::getNumRegions(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->numRegions; } -int ImuseDigiSndMgr::getNumJumps(soundStruct *soundHandle) { - assert(checkForProperHandle(soundHandle)); - return soundHandle->numJumps; +int ImuseDigiSndMgr::getNumJumps(SoundDesc *soundDesc) { + assert(checkForProperHandle(soundDesc)); + return soundDesc->numJumps; } -int ImuseDigiSndMgr::getRegionOffset(soundStruct *soundHandle, int region) { +int ImuseDigiSndMgr::getRegionOffset(SoundDesc *soundDesc, int region) { debug(5, "getRegionOffset() region:%d", region); - assert(checkForProperHandle(soundHandle)); - assert(region >= 0 && region < soundHandle->numRegions); - return soundHandle->region[region].offset; + assert(checkForProperHandle(soundDesc)); + assert(region >= 0 && region < soundDesc->numRegions); + return soundDesc->region[region].offset; } -int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId) { +int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId) { debug(5, "getJumpIdByRegionAndHookId() region:%d, hookId:%d", region, hookId); - assert(checkForProperHandle(soundHandle)); - assert(region >= 0 && region < soundHandle->numRegions); - int32 offset = soundHandle->region[region].offset; - for (int l = 0; l < soundHandle->numJumps; l++) { - if (offset == soundHandle->jump[l].offset) { - if (soundHandle->jump[l].hookId == hookId) + assert(checkForProperHandle(soundDesc)); + assert(region >= 0 && region < soundDesc->numRegions); + int32 offset = soundDesc->region[region].offset; + for (int l = 0; l < soundDesc->numJumps; l++) { + if (offset == soundDesc->jump[l].offset) { + if (soundDesc->jump[l].hookId == hookId) return l; } } @@ -523,25 +528,25 @@ int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int re return -1; } -void ImuseDigiSndMgr::getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr) { - assert(checkForProperHandle(soundHandle)); +void ImuseDigiSndMgr::getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr) { + assert(checkForProperHandle(soundDesc)); assert(number >= 0); - if (number < soundHandle->numSyncs) { - sync_size = soundHandle->sync[number].size; - *sync_ptr = soundHandle->sync[number].ptr; + if (number < soundDesc->numSyncs) { + sync_size = soundDesc->sync[number].size; + *sync_ptr = soundDesc->sync[number].ptr; } else { sync_size = 0; *sync_ptr = NULL; } } -int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) { +int ImuseDigiSndMgr::getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId) { debug(5, "getRegionIdByJumpId() jumpId:%d", jumpId); - assert(checkForProperHandle(soundHandle)); - assert(jumpId >= 0 && jumpId < soundHandle->numJumps); - int32 dest = soundHandle->jump[jumpId].dest; - for (int l = 0; l < soundHandle->numRegions; l++) { - if (dest == soundHandle->region[l].offset) { + assert(checkForProperHandle(soundDesc)); + assert(jumpId >= 0 && jumpId < soundDesc->numJumps); + int32 dest = soundDesc->jump[jumpId].dest; + for (int l = 0; l < soundDesc->numRegions; l++) { + if (dest == soundDesc->region[l].offset) { return l; } } @@ -549,89 +554,110 @@ int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) { return -1; } -int ImuseDigiSndMgr::getJumpHookId(soundStruct *soundHandle, int number) { +int ImuseDigiSndMgr::getJumpHookId(SoundDesc *soundDesc, int number) { debug(5, "getJumpHookId() number:%d", number); - assert(checkForProperHandle(soundHandle)); - assert(number >= 0 && number < soundHandle->numJumps); - return soundHandle->jump[number].hookId; + assert(checkForProperHandle(soundDesc)); + assert(number >= 0 && number < soundDesc->numJumps); + return soundDesc->jump[number].hookId; } -int ImuseDigiSndMgr::getJumpFade(soundStruct *soundHandle, int number) { +int ImuseDigiSndMgr::getJumpFade(SoundDesc *soundDesc, int number) { debug(5, "getJumpFade() number:%d", number); - assert(checkForProperHandle(soundHandle)); - assert(number >= 0 && number < soundHandle->numJumps); - return soundHandle->jump[number].fadeDelay; + assert(checkForProperHandle(soundDesc)); + assert(number >= 0 && number < soundDesc->numJumps); + return soundDesc->jump[number].fadeDelay; } -int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) { - debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundHandle->numRegions); - assert(checkForProperHandle(soundHandle)); +int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size) { + debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundDesc->numRegions); + assert(checkForProperHandle(soundDesc)); assert(buf && offset >= 0 && size >= 0); - assert(region >= 0 && region < soundHandle->numRegions); + assert(region >= 0 && region < soundDesc->numRegions); - int32 region_offset = soundHandle->region[region].offset; - int32 region_length = soundHandle->region[region].length; - int32 offset_data = soundHandle->offsetData; + int32 region_offset = soundDesc->region[region].offset; + int32 region_length = soundDesc->region[region].length; + int32 offset_data = soundDesc->offsetData; int32 start = region_offset - offset_data; if (offset + size + offset_data > region_length) { size = region_length - offset; - soundHandle->endFlag = true; + soundDesc->endFlag = true; } else { - soundHandle->endFlag = false; + soundDesc->endFlag = false; } - int header_size = soundHandle->offsetData; + int header_size = soundDesc->offsetData; bool header_outside = ((_vm->_game.id == GID_CMI) && !(_vm->_game.features & GF_DEMO)); - if ((soundHandle->bundle) && (!soundHandle->compressed)) { - size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside); - } else if (soundHandle->resPtr) { + if ((soundDesc->bundle) && (!soundDesc->compressed)) { + size = soundDesc->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside); + } else if (soundDesc->resPtr) { *buf = new byte[size]; assert(*buf); - memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size); - } else if ((soundHandle->bundle) && (soundHandle->compressed)) { + memcpy(*buf, soundDesc->resPtr + start + offset + header_size, size); + } else if ((soundDesc->bundle) && (soundDesc->compressed)) { *buf = new byte[size]; assert(*buf); char fileName[24]; - sprintf(fileName, "%s_reg%03d", soundHandle->name, region); - if (scumm_stricmp(fileName, soundHandle->lastFileName) != 0) { + sprintf(fileName, "%s_reg%03d", soundDesc->name, region); + if (scumm_stricmp(fileName, soundDesc->lastFileName) != 0) { int32 offs = 0, len = 0; Common::File *cmpFile; - bool oggMode = false; - sprintf(fileName, "%s_reg%03d.mp3", soundHandle->name, region); - cmpFile = soundHandle->bundle->getFile(fileName, offs, len); -#ifndef USE_MAD - if (len) - error("Mad library compiled support needed!"); + uint8 soundMode = 0; + + sprintf(fileName, "%s_reg%03d.fla", soundDesc->name, region); + cmpFile = soundDesc->bundle->getFile(fileName, offs, len); + if (len) { +#ifndef USE_FLAC + error("FLAC library compiled support needed!"); #endif + soundMode = 3; + } if (!len) { - sprintf(fileName, "%s_reg%03d.ogg", soundHandle->name, region); - cmpFile = soundHandle->bundle->getFile(fileName, offs, len); + sprintf(fileName, "%s_reg%03d.ogg", soundDesc->name, region); + cmpFile = soundDesc->bundle->getFile(fileName, offs, len); + if (len) { #ifndef USE_VORBIS - if (len) error("Vorbis library compiled support needed!"); #endif - assert(len); - oggMode = true; + soundMode = 2; + } + } + if (!len) { + sprintf(fileName, "%s_reg%03d.mp3", soundDesc->name, region); + cmpFile = soundDesc->bundle->getFile(fileName, offs, len); + if (len) { +#ifndef USE_MAD + error("Mad library compiled support needed!"); +#endif + soundMode = 1; + } } - if (!soundHandle->compressedStream) { + assert(len); + + if (!soundDesc->compressedStream) { + Common::MemoryReadStream *tmp = cmpFile->readStream(len); + assert(tmp); +#ifdef USE_FLAC + if (soundMode == 3) + soundDesc->compressedStream = Audio::makeFlacStream(tmp, true); +#endif #ifdef USE_VORBIS - if (oggMode) - soundHandle->compressedStream = Audio::makeVorbisStream(cmpFile, len); + if (soundMode == 2) + soundDesc->compressedStream = Audio::makeVorbisStream(tmp, true); #endif #ifdef USE_MAD - if (!oggMode) - soundHandle->compressedStream = Audio::makeMP3Stream(cmpFile, len); + if (soundMode == 1) + soundDesc->compressedStream = Audio::makeMP3Stream(tmp, true); #endif - assert(soundHandle->compressedStream); + assert(soundDesc->compressedStream); } - strcpy(soundHandle->lastFileName, fileName); + strcpy(soundDesc->lastFileName, fileName); } - size = soundHandle->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2; - if (soundHandle->compressedStream->endOfData()) { - delete soundHandle->compressedStream; - soundHandle->compressedStream = NULL; - soundHandle->lastFileName[0] = 0; + size = soundDesc->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2; + if (soundDesc->compressedStream->endOfData()) { + delete soundDesc->compressedStream; + soundDesc->compressedStream = NULL; + soundDesc->lastFileName[0] = 0; } } diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.h b/engines/scumm/imuse_digi/dimuse_sndmgr.h index 5d2f8c88ba..e4e2e795a2 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.h +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.h @@ -48,35 +48,39 @@ public: #define IMUSE_VOLGRP_MUSIC 3 private: - struct _region { + struct Region { int32 offset; // offset of region int32 length; // lenght of region }; - struct _jump { + struct Jump { int32 offset; // jump offset position int32 dest; // jump to dest position byte hookId; // id of hook int16 fadeDelay; // fade delay in ms }; - struct _sync { + struct Sync { int32 size; // size of sync byte *ptr; // pointer to sync }; public: - struct soundStruct { + struct SoundDesc { uint16 freq; // frequency byte channels; // stereo or mono byte bits; // 8, 12, 16 + int numJumps; // number of Jumps + Region *region; + int numRegions; // number of Regions + Jump *jump; + int numSyncs; // number of Syncs - _region *region; - _jump *jump; - _sync *sync; + Sync *sync; + bool endFlag; bool inUse; byte *allData; @@ -95,19 +99,19 @@ public: private: - soundStruct _sounds[MAX_IMUSE_SOUNDS]; + SoundDesc _sounds[MAX_IMUSE_SOUNDS]; - bool checkForProperHandle(soundStruct *soundHandle); - soundStruct *allocSlot(); - void prepareSound(byte *ptr, soundStruct *sound); - void prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size); + bool checkForProperHandle(SoundDesc *soundDesc); + SoundDesc *allocSlot(); + void prepareSound(byte *ptr, SoundDesc *sound); + void prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size); ScummEngine *_vm; byte _disk; BundleDirCache *_cacheBundleDir; - bool openMusicBundle(soundStruct *sound, int disk); - bool openVoiceBundle(soundStruct *sound, int disk); + bool openMusicBundle(SoundDesc *sound, int disk); + bool openVoiceBundle(SoundDesc *sound, int disk); void countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs); @@ -116,25 +120,25 @@ public: ImuseDigiSndMgr(ScummEngine *scumm); ~ImuseDigiSndMgr(); - soundStruct *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk); - void closeSound(soundStruct *soundHandle); - soundStruct *cloneSound(soundStruct *soundHandle); - - bool isSndDataExtComp(soundStruct *soundHandle); - int getFreq(soundStruct *soundHandle); - int getBits(soundStruct *soundHandle); - int getChannels(soundStruct *soundHandle); - bool isEndOfRegion(soundStruct *soundHandle, int region); - int getNumRegions(soundStruct *soundHandle); - int getNumJumps(soundStruct *soundHandle); - int getRegionOffset(soundStruct *soundHandle, int region); - int getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId); - int getRegionIdByJumpId(soundStruct *soundHandle, int jumpId); - int getJumpHookId(soundStruct *soundHandle, int number); - int getJumpFade(soundStruct *soundHandle, int number); - void getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr); - - int32 getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size); + SoundDesc *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk); + void closeSound(SoundDesc *soundDesc); + SoundDesc *cloneSound(SoundDesc *soundDesc); + + bool isSndDataExtComp(SoundDesc *soundDesc); + int getFreq(SoundDesc *soundDesc); + int getBits(SoundDesc *soundDesc); + int getChannels(SoundDesc *soundDesc); + bool isEndOfRegion(SoundDesc *soundDesc, int region); + int getNumRegions(SoundDesc *soundDesc); + int getNumJumps(SoundDesc *soundDesc); + int getRegionOffset(SoundDesc *soundDesc, int region); + int getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId); + int getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId); + int getJumpHookId(SoundDesc *soundDesc, int number); + int getJumpFade(SoundDesc *soundDesc, int number); + void getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr); + + int32 getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size); }; } // End of namespace Scumm diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp index 75dde5e60f..987e1bc3c9 100644 --- a/engines/scumm/imuse_digi/dimuse_track.cpp +++ b/engines/scumm/imuse_digi/dimuse_track.cpp @@ -117,20 +117,20 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, track->feedSize = 0; track->souStreamUsed = true; track->soundName[0] = 0; - track->soundHandle = NULL; + track->soundDesc = NULL; } else { track->souStreamUsed = false; strcpy(track->soundName, soundName); - track->soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId, -1); + track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, -1); - if (track->soundHandle == NULL) + if (track->soundDesc == NULL) return; - track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle); + track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc); - bits = _sound->getBits(track->soundHandle); - channels = _sound->getChannels(track->soundHandle); - freq = _sound->getFreq(track->soundHandle); + bits = _sound->getBits(track->soundDesc); + channels = _sound->getChannels(track->soundDesc); + freq = _sound->getFreq(track->soundDesc); if ((soundId == kTalkSoundID) && (soundType == IMUSE_BUNDLE)) { if (_vm->_actorToPrintStrFor != 0xFF && _vm->_actorToPrintStrFor != 0) { @@ -325,15 +325,12 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f // Clone the settings of the given track memcpy(fadeTrack, track, sizeof(Track)); - // Clone the soundhandle - // FIXME: Shouldn't we check here whether track->soundHandle is NULL, resp. whether stream2 - // is being used (as in, we are using compressed data)... - // - // -- aquadran -- nope :) this is called only for bundle files and sound data in *.la1 - // from switchToNextRegion and fadeOutMusic func. - // stream2 is used only for sou VOICE type sound data (FT) -- - fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle); - assert(fadeTrack->soundHandle); + // Clone the sound. + // According to aquadran, this is only called for bundle files and sound + // data in *.la1 from switchToNextRegion and fadeOutMusic func. Henc we + // know that track->soundDesc != NULL. + fadeTrack->soundDesc = _sound->cloneSound(track->soundDesc); + assert(fadeTrack->soundDesc); // Set the volume fading parameters to indicate a fade out fadeTrack->volFadeDelay = fadeDelay; @@ -357,7 +354,7 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f type = Audio::Mixer::kPlainSoundType; break; } - fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), makeMixerFlags(fadeTrack->mixerFlags)); + fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags)); _mixer->playInputStream(type, &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false); fadeTrack->mixerStreamRunning = true; diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index ffcb7d03f2..6647e9fe8d 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -162,8 +162,11 @@ void ScummEngine::parseEvents() { if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { _mouse.x -= (Common::kHercW - _screenWidth * 2) / 2; - _mouse.x /= 2; + _mouse.x >>= 1; _mouse.y = _mouse.y * 4 / 7; + } else if (_useCJKMode && _textSurfaceMultiplier == 2) { + _mouse.x >>= 1; + _mouse.y >>= 1; } break; case Common::EVENT_LBUTTONUP: diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index d8ef669410..a340f564b3 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -90,6 +90,11 @@ endif endif +ifdef USE_ARM_GFX_ASM +MODULE_OBJS += \ + gfxARM.o +endif + ifndef DISABLE_HE MODULE_OBJS += \ he/animation_he.o \ diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index cd48ef4d02..4f6b2477c6 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Mon Jul 2 22:44:41 2007 + This file was generated by the md5table tool on Fri Jul 20 21:25:14 2007 DO NOT EDIT MANUALLY! */ @@ -25,10 +25,12 @@ static const MD5Table md5table[] = { { "04687cdf7f975a89d2474929f7b80946", "indy3", "FM-TOWNS", "", 7552, Common::EN_ANY, Common::kPlatformFMTowns }, { "0557df19f046a84c2fdc63507c6616cb", "farm", "HE 72", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, + { "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD }, { "0650e8ab1432564607cd651c0fa3f344", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine }, { "06b187468113f9ae5a400b148a847fac", "atlantis", "", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh }, { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, { "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "07a1eefd8ca95d77310311446c0f53d0", "brstorm", "", "Demo", 5433, Common::EN_ANY, Common::kPlatformUnknown }, { "07b810e37be7489263f7bc7627d4765d", "freddi4", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows }, { "084ed0fa98a6d1e9368d67fe9cfbd417", "freddi", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "0855496dde35356b1a9691e22ba84cdc", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, @@ -320,6 +322,7 @@ static const MD5Table md5table[] = { { "86be8ada36371d4fdc35659d0e912a26", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC }, { "86c9902b7bec1a17926d4dae85beaa45", "airport", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "870d1e3c86bc50846d808d14a36b4e08", "monkey", "VGA", "VGA", -1, Common::ES_ESP, Common::kPlatformAmiga }, + { "8776caed014c321272af407c1502a2df", "monkey", "CD", "", 8955, Common::EN_ANY, Common::kPlatformMacintosh }, { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC }, { "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, { "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, @@ -444,6 +447,7 @@ static const MD5Table md5table[] = { { "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "c8aac5e3e701874e2fa4117896f9e1b1", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "c8c5baadcbfc8d0372ed4335abace8a7", "pajama3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, + { "c9717ee6059f1e43b768b464493d2fba", "fbpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO }, { "cb1559e8405d17a5a278a6b5ad9338d1", "freddi3", "", "Demo", 22718, Common::EN_ANY, Common::kPlatformUnknown }, { "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "", "CD", 282467632, Common::EN_ANY, Common::kPlatformMacintosh }, { "cc8ba2b0df2f9c450bcf055fe2711979", "samnmax", "", "Demo", 7485, Common::DE_DEU, Common::kPlatformPC }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 2140b15544..e54060c9e1 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -480,7 +480,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _renderMode = Common::kRenderDefault; } - // Do some render mode restirctions + // Check some render mode restrictions if (_game.version <= 1) _renderMode = Common::kRenderDefault; @@ -521,7 +521,11 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _screenHeight = 200; } - _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight); + // Allocate gfx compositing buffer (not needed for V7/V8 games). + if (_game.version < 7) + _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight); + else + _compositeBuf = 0; _herculesBuf = 0; if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { @@ -583,6 +587,7 @@ ScummEngine::~ScummEngine() { free(_compositeBuf); free(_herculesBuf); + free(_fmtownsBuf); delete _debugger; @@ -1074,12 +1079,19 @@ int ScummEngine::init() { _fileHandle = new ScummFile(); } + // Load CJK font, if present + // Load it earlier so _useCJKMode variable could be set + loadCJKFont(); + // Initialize backend _system->beginGFXTransaction(); bool defaultTo1XScaler = false; if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { _system->initSize(Common::kHercW, Common::kHercH); defaultTo1XScaler = true; + } else if (_useCJKMode) { + _system->initSize(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier); + defaultTo1XScaler = true; } else { _system->initSize(_screenWidth, _screenHeight); defaultTo1XScaler = (_screenWidth > 320); @@ -1131,14 +1143,11 @@ void ScummEngine::setupScumm() { // Load localization data, if present loadLanguageBundle(); - // Load CJK font, if present - loadCJKFont(); - // Create the charset renderer setupCharsetRenderer(); // Create and clear the text surface - _textSurface.create(_screenWidth, _screenHeight, 1); + _textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 1); clearTextSurface(); // Create the costume renderer @@ -1206,6 +1215,13 @@ void ScummEngine::setupScumm() { #if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) Graphics::initfonts(); #endif + + _fmtownsBuf = 0; + if (_game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { + _fmtownsBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier); + } + + _compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier); } #ifndef DISABLE_SCUMM_7_8 diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 4146846856..18c2275029 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -1026,11 +1026,12 @@ protected: // Screen rendering byte *_compositeBuf; byte *_herculesBuf; + byte *_fmtownsBuf; virtual void drawDirtyScreenParts(); void updateDirtyScreen(VirtScreenNumber slot); void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b); void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const; - void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const; + void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); public: VirtScreen *findVirtScreen(int y); @@ -1152,6 +1153,7 @@ public: * drawStripToScreen() composits it over the game graphics. */ Graphics::Surface _textSurface; + int _textSurfaceMultiplier; protected: byte _charsetColor; diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 2c744a16e2..ce39302e25 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -1178,12 +1178,15 @@ void SmushPlayer::tryCmpFile(const char *filename) { char fname[260]; #endif Common::File *file = new Common::File(); + + // FIXME: How about using AudioStream::openStreamFile instead of the code below? + #ifdef USE_VORBIS memcpy(fname, filename, i - filename); strcpy(fname + (i - filename), ".ogg"); if (file->open(fname)) { _compressedFileMode = true; - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true, 0, 0)); + _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true)); return; } #endif @@ -1192,7 +1195,7 @@ void SmushPlayer::tryCmpFile(const char *filename) { strcpy(fname + (i - filename), ".mp3"); if (file->open(fname)) { _compressedFileMode = true; - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true, 0, 0)); + _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true)); return; } #endif diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index e5720a013f..62f65c22c1 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -607,24 +607,31 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle if (!_soundsPaused && _mixer->isReady()) { Audio::AudioStream *input = NULL; + Common::MemoryReadStream *tmp = NULL; switch (_soundMode) { case kMP3Mode: #ifdef USE_MAD assert(size > 0); - input = Audio::makeMP3Stream(_sfxFile, size); + tmp = _sfxFile->readStream(size); + assert(tmp); + input = Audio::makeMP3Stream(tmp, true); #endif break; case kVorbisMode: #ifdef USE_VORBIS assert(size > 0); - input = Audio::makeVorbisStream(_sfxFile, size); + tmp = _sfxFile->readStream(size); + assert(tmp); + input = Audio::makeVorbisStream(tmp, true); #endif break; case kFlacMode: #ifdef USE_FLAC assert(size > 0); - input = Audio::makeFlacStream(_sfxFile, size); + tmp = _sfxFile->readStream(size); + assert(tmp); + input = Audio::makeFlacStream(tmp, true); #endif break; default: @@ -831,7 +838,7 @@ void Sound::soundKludge(int *list, int num) { } void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) { - if (_vm->_game.version >= 6 && ConfMan.getBool("speech_mute")) + if (_vm->_game.version >= 5 && ConfMan.getBool("speech_mute")) return; if (mode == 1) { diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index 44e727b5d3..32fdf0e04e 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -172,6 +172,20 @@ void ScummEngine_v6::drawBlastTexts() { if (c == 0x0B) continue; + // Some localizations may override colors + // See credits in Chinese COMI + if (c == '^' && (buf == _blastTextQueue[i].text + 1)) { + int color; + switch (*buf) { + case 'c': + color = buf[3] - '0' + 10 *(buf[2] - '0'); + _charset->setColor(color); + + buf += 4; + c = *buf++; + } + } + if (c != 0 && c != 0xFF && c != '\n') { if (c & 0x80 && _useCJKMode) { if (_language == Common::JA_JPN && !checkSJISCode(c)) { @@ -1060,7 +1074,7 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize) num += (_game.version == 8) ? 4 : 2; } } else { - if (!(chr == '@' && _game.heversion <= 71)) { + if (!(chr == '@' && _game.heversion <= 71) || _language == Common::ZH_TWN) { *dst++ = chr; } } |