From 732774fd8de3cb6cebcd78730813d26e0330e66e Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 7 Apr 2008 20:24:40 +0000 Subject: Patch #1913862: "CinE Script system" svn-id: r31444 --- engines/cine/anim.cpp | 693 ++++++----- engines/cine/anim.h | 45 +- engines/cine/bg.cpp | 37 +- engines/cine/bg.h | 7 + engines/cine/bg_list.cpp | 165 ++- engines/cine/bg_list.h | 10 +- engines/cine/cine.cpp | 26 +- engines/cine/gfx.cpp | 107 +- engines/cine/gfx.h | 22 +- engines/cine/main_loop.cpp | 7 - engines/cine/object.cpp | 8 +- engines/cine/object.h | 2 +- engines/cine/part.cpp | 1 - engines/cine/part.h | 18 - engines/cine/prc.cpp | 53 +- engines/cine/prc.h | 18 +- engines/cine/rel.cpp | 64 +- engines/cine/rel.h | 17 +- engines/cine/script.cpp | 2739 ++++++++++++++++++++++++++------------------ engines/cine/script.h | 428 +++++-- engines/cine/sound.cpp | 4 +- engines/cine/texte.cpp | 2 +- engines/cine/various.cpp | 549 ++++----- engines/cine/xref.txt | 146 +++ 24 files changed, 3075 insertions(+), 2093 deletions(-) create mode 100644 engines/cine/xref.txt (limited to 'engines/cine') diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp index 698022cc1b..0d1bd20e7a 100644 --- a/engines/cine/anim.cpp +++ b/engines/cine/anim.cpp @@ -23,6 +23,9 @@ * */ +/*! \file + * \todo Make resource manager class and make load* functions its members + */ #include "common/endian.h" #include "common/stream.h" @@ -46,11 +49,9 @@ struct AnimHeader2Struct { uint16 field_E; }; -static uint16 animDataCount = 0; - -AnimHeaderStruct animHeader; +AnimData animDataTable[NUM_MAX_ANIMDATA]; -static const AnimDataEntry animData[] = { +static const AnimDataEntry transparencyData[] = { {"ALPHA", 0xF}, {"TITRE2", 0xF}, {"ET", 0xC}, @@ -184,135 +185,250 @@ static const AnimDataEntry animData[] = { {"FIN", 0x9}, }; -static void freeAnimData(byte idx) { - assert(idx < NUM_MAX_ANIMDATA); - if (animDataTable[idx].ptr1) { - free(animDataTable[idx].ptr1); - free(animDataTable[idx].ptr2); - memset(&animDataTable[idx], 0, sizeof(AnimData)); - animDataTable[idx].fileIdx = -1; - animDataTable[idx].frameIdx = -1; - if (animDataCount > 0) - animDataCount--; - } -} +void convertMask(byte *dest, const byte *source, int16 width, int16 height); +void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency); +void convert8BBP(byte *dest, const byte *source, int16 width, int16 height); +void convert8BBP2(byte *dest, byte *source, int16 width, int16 height); -void freeAnimDataRange(byte startIdx, byte numIdx) { - for (byte i = 0; i < numIdx; i++) { - freeAnimData(i + startIdx); - } -} +AnimData::AnimData() : _width(0), _height(0), _bpp(0), _var1(0), _data(NULL), + _mask(NULL), _fileIdx(-1), _frameIdx(-1), _realWidth(0), _size(0) { -void freeAnimDataTable() { - freeAnimDataRange(0, NUM_MAX_ANIMDATA); + memset(_name, 0, 10); } -static byte getAnimTransparentColor(const char *animName) { - char name[15]; - - removeExtention(name, animName); - - for (int i = 0; i < ARRAYSIZE(animData); i++) { - if (!strcmp(name, animData[i].name)) { - return animData[i].color; - } +/*! \brief Copy constructor + */ +AnimData::AnimData(const AnimData &src) : _width(src._width), + _height(src._height), _bpp(src._bpp), _var1(src._var1), + _data(NULL), _mask(NULL), _fileIdx(src._fileIdx), + _frameIdx(src._frameIdx), _realWidth(src._realWidth), _size(src._size) { + + if (src._data) { + _data = new byte[_size]; + assert(_data); + memcpy(_data, src._data, _size*sizeof(byte)); } - return 0; -} -int16 allocFrame(uint16 width, uint16 height, int8 isMask) { - uint16 i; - uint32 frameSize; - - for (i = 0; i < NUM_MAX_ANIMDATA; i++) { - if (!animDataTable[i].ptr1) - break; + if(src._mask) { + _mask = new byte[_size]; + assert(_mask); + memcpy(_mask, src._mask, _size*sizeof(byte)); } - if (i == NUM_MAX_ANIMDATA) - return -1; + memset(_name, 0, 10); + strcpy(_name, src._name); +} - if (!isMask) { // sprite + generated mask - frameSize = width * height; +/*! \brief Destructor + */ +AnimData::~AnimData() { + clear(); +} - animDataTable[i].ptr1 = (byte *)malloc(frameSize); - animDataTable[i].ptr2 = (byte *)malloc(frameSize); - } else { - // mask - frameSize = width * height * 8; +/*! \brief Assingment operator + */ +AnimData &AnimData::operator=(const AnimData &src) { + AnimData tmp = src; + byte *ptr; - animDataTable[i].ptr1 = (byte *)malloc(frameSize); - animDataTable[i].ptr2 = NULL; - } + _width = tmp._width; + _height = tmp._height; + _bpp = tmp._bpp; + _var1 = tmp._var1; - animDataTable[i].width = width; - animDataTable[i].var1 = width >> 3; - animDataTable[i].bpp = 4; - animDataTable[i].height = height; + ptr = _data; + _data = tmp._data; + tmp._data = ptr; - animDataTable[i].fileIdx = -1; - animDataTable[i].frameIdx = -1; + ptr = _mask; + _mask = tmp._mask; + tmp._mask = ptr; - animDataCount++; + _fileIdx = tmp._fileIdx; + _frameIdx = tmp._frameIdx; + memset(_name, 0, 10); + strcpy(_name, tmp._name); + _realWidth = tmp._realWidth; + _size = tmp._size; - return i; + return *this; } -int16 reserveFrame(uint16 width, uint16 height, uint16 type, int16 idx) { - uint16 i; - uint32 frameSize; +byte AnimData::getColor(int x, int y) { + assert(_data); + assert(x >= 0 && x < _realWidth && y >= 0 && y <= _height); + assert(x + y * _realWidth < _size); - if (idx >= 0) { - i = (uint16) idx; - } else { - for (i = 0; i < NUM_MAX_ANIMDATA; i++) { - if (!animDataTable[i].ptr1) - break; - } + return _data[x + y * _realWidth]; +} - if (i == NUM_MAX_ANIMDATA) - return -1; - } +/*! \brief Load and decode image frame + * \param d Encoded image data + * \param type Encoding type + * \param w Image width + * \param h Image height + * \param file Data file index in bundle + * \param frame Image frame index + * \param n Part name + * \param transparent Transparent color (for ANIM_MASKSPRITE) + */ +void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file, + int16 frame, const char *n, byte transparent) { - frameSize = width * height; + assert(d); - if (type == 4) { // 256 color sprites - frameSize *= 2; - type = 8; - width *= 2; + if (_data) { + clear(); } - if (type == 5) { - frameSize += 16; + _width = w * 2; + _height = h; + _var1 = _width >> 3; + _data = NULL; + _mask = NULL; + _fileIdx = file; + _frameIdx = frame; + memset(_name, 0, 10); + strcpy(_name, n); + _realWidth = w; + + switch (type) { + case ANIM_RAW: + _width = w; + _var1 = w >> 3; + _bpp = 4; + _size = w * h; + _data = new byte[_size]; + assert(_data); + memcpy(_data, d, _size*sizeof(byte)); + break; + + case ANIM_MASK: + _bpp = 1; + _size = w * h * 8; + _data = new byte[_size]; + _realWidth = w * 8; + assert(_data); + convertMask(_data, d, w, h); + break; + + case ANIM_SPRITE: + _bpp = 4; + _size = w * h * 2; + _data = new byte[_size]; + _realWidth = w * 2; + assert(_data); + gfxConvertSpriteToRaw(_data, d, w, h); + break; + + case ANIM_MASKSPRITE: + _bpp = 4; + _size = w * h * 2; + _data = new byte[_size]; + _mask = new byte[_size]; + _realWidth = w * 2; + assert(_data && _mask); + gfxConvertSpriteToRaw(_data, d, w, h); + generateMask(_data, _mask, _size, transparent); + break; + + case ANIM_PALSPRITE: + _bpp = 5; + _size = w * h * 2; + _data = new byte[_size]; + _realWidth = w * 2; + assert(_data); + convert8BBP(_data, d, w, h); + break; + + case ANIM_FULLSPRITE: + _bpp = 8; + _var1 = _width >> 4; + _size = w * h; + _data = new byte[_size]; + assert(_data); + convert8BBP2(_data, d, w, h); + break; + + default: + error("AnimData::load: unknown image type"); } +} - frameSize *= 2; - - animDataTable[i].ptr1 = (byte *)malloc(frameSize); - - assert(animDataTable[i].ptr1); +/*! \brief Reset image + */ +void AnimData::clear() { + delete[] _data; + delete [] _mask; + + _width = 0; + _height = 0; + _bpp = 0; + _var1 = 0; + _data = NULL; + _mask = NULL; + _fileIdx = -1; + _frameIdx = -1; + memset(_name, 0, 10); + _size = 0; +} - animDataTable[i].width = width; +/*! \brief Write image identifiers to savefile + * \param fHandle Savefile open for writing + */ +void AnimData::save(Common::OutSaveFile &fHandle) const { + fHandle.writeUint16BE(_width); + fHandle.writeUint16BE(_var1); + fHandle.writeUint16BE(_bpp); + fHandle.writeUint16BE(_height); + // Just because I write pointers to a file doesn't mean + // anyone should actually read those values back! + fHandle.writeUint32BE((uint32)_data); + fHandle.writeUint32BE((uint32)_mask); + fHandle.writeUint16BE(_fileIdx); + fHandle.writeUint16BE(_frameIdx); + fHandle.write(_name, 10); +} - if (type == 5) { - animDataTable[i].var1 = width / 8; - } else { - animDataTable[i].var1 = width / 16; +/*! \brief Clear part of animDataTable + * \param startIdx First image frame to be cleared + * \param numIdx Number of image frames to be cleared + */ +void freeAnimDataRange(byte startIdx, byte numIdx) { + for (byte i = 0; i < numIdx; i++) { + animDataTable[startIdx + i].clear(); } +} - animDataTable[i].bpp = type; - - animDataTable[i].height = height; +/*! \brief Clear whole animDataTable + */ +void freeAnimDataTable() { + freeAnimDataRange(0, NUM_MAX_ANIMDATA); +} - animDataTable[i].fileIdx = -1; - animDataTable[i].frameIdx = -1; +/*! \brief Find transparent color index for image + * \brief animName Image file name + */ +static byte getAnimTransparentColor(const char *animName) { + char name[15]; - animDataCount++; + removeExtention(name, animName); - return i; + for (int i = 0; i < ARRAYSIZE(transparencyData); i++) { + if (!strcmp(name, transparencyData[i].name)) { + return transparencyData[i].color; + } + } + return 0; } -void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) { +/*! \brief Generate mask for image + * \param[in] sprite Image data + * \param[out] mask Image mask + * \param size Image data length + * \param transparency Transparent color index + */ +void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency) { for (uint16 i = 0; i < size; i++) { if (*(sprite++) != transparency) { *(mask++) = 0; @@ -322,7 +438,13 @@ void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) { } } -void convertMask(byte * dest, byte * source, int16 width, int16 height) { +/*! \brief Decode 1bpp mask + * \param[out] dest Decoded mask + * \param[in] source Encoded mask + * \param width Mask width + * \param height Mask height + */ +void convertMask(byte *dest, const byte *source, int16 width, int16 height) { int16 i, j; byte maskEntry; @@ -335,7 +457,13 @@ void convertMask(byte * dest, byte * source, int16 width, int16 height) { } } -void convert4BBP(byte * dest, byte * source, int16 width, int16 height) { +/*! \brief Decode 4bpp sprite + * \param[out] dest Decoded image + * \param[in] source Encoded image + * \param width Image width + * \param height Image height + */ +void convert4BBP(byte *dest, const byte *source, int16 width, int16 height) { byte maskEntry; for (int16 i = 0; i < width * height; i++) { @@ -345,7 +473,11 @@ void convert4BBP(byte * dest, byte * source, int16 width, int16 height) { } } -void loadAnimHeader(Common::MemoryReadStream readS) { +/*! \brief Read image header + * \param[out] animHeader Image header reference + * \param readS Input stream open for reading + */ +void loadAnimHeader(AnimHeaderStruct &animHeader, Common::MemoryReadStream readS) { animHeader.field_0 = readS.readByte(); animHeader.field_1 = readS.readByte(); animHeader.field_2 = readS.readByte(); @@ -366,115 +498,109 @@ void loadAnimHeader(Common::MemoryReadStream readS) { animHeader.field_14 = readS.readUint16BE(); } +/*! \brief Find next empty space animDataTable + * \param start First index to check + */ +int emptyAnimSpace(int start = 0) { + for (; start < NUM_MAX_ANIMDATA; start++) { + if (!animDataTable[start].data()) { + return start; + } + } + + return -1; +} + +/*! \brief Load SPL data into animDataTable + * \param resourceName SPL filename + * \param idx Target index in animDataTable + */ void loadSpl(const char *resourceName, int16 idx) { int16 foundFileIdx = findFileInBundle(resourceName); - int16 entry; - byte *dataPtr = readBundleFile(foundFileIdx); + int entry; - if (idx >= 0) { - entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx); - memcpy(animDataTable[entry].ptr1, dataPtr, partBuffer[foundFileIdx].unpackedSize); - } else { - entry = allocFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, -1); - assert(entry != -1); - memcpy(animDataTable[entry].ptr1, dataPtr, (uint16) partBuffer[foundFileIdx].unpackedSize); - - animDataTable[entry].fileIdx = foundFileIdx; - animDataTable[entry].frameIdx = 0; - strcpy(animDataTable[entry].name, currentPartName); + if (foundFileIdx < 0) { + return; } + byte *dataPtr = readBundleFile(foundFileIdx); + + entry = idx < 0 ? emptyAnimSpace() : idx; + assert(entry >= 0); + animDataTable[entry].load(dataPtr, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName); + free(dataPtr); } +/*! \brief Load 1bpp mask + * \param resourceName Mask filename + */ void loadMsk(const char *resourceName) { int16 foundFileIdx = findFileInBundle(resourceName); - int16 entry; + int entry = 0; byte *dataPtr = readBundleFile(foundFileIdx); byte *ptr; + AnimHeaderStruct animHeader; Common::MemoryReadStream readS(dataPtr, 0x16); - loadAnimHeader(readS); + loadAnimHeader(animHeader, readS); ptr = dataPtr + 0x16; - for (int16 i = 0; i < animHeader.numFrames; i++) { - entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 1); - - assert(entry != -1); - - convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth, animHeader.frameHeight); + for (int16 i = 0; i < animHeader.numFrames; i++, entry++) { + entry = emptyAnimSpace(entry); + assert(entry >= 0); + animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName); ptr += animHeader.frameWidth * animHeader.frameHeight; - - animDataTable[entry].fileIdx = foundFileIdx; - animDataTable[entry].frameIdx = i; - strcpy(animDataTable[entry].name, currentPartName); } free(dataPtr); } +/*! \brief Load animation + * \param resourceName Animation filename + */ void loadAni(const char *resourceName) { int16 foundFileIdx = findFileInBundle(resourceName); - int16 entry; + int entry = 0; byte *dataPtr = readBundleFile(foundFileIdx); - byte *ptr, *animPtr; + byte *ptr; byte transparentColor; - uint32 fullSize; + AnimHeaderStruct animHeader; Common::MemoryReadStream readS(dataPtr, 0x16); - loadAnimHeader(readS); + loadAnimHeader(animHeader, readS); ptr = dataPtr + 0x16; transparentColor = getAnimTransparentColor(resourceName); - fullSize = animHeader.frameWidth * animHeader.frameHeight; - - for (int16 i = 0; i < animHeader.numFrames; i++) { - entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 0); - - assert(entry != -1); + for (int16 i = 0; i < animHeader.numFrames; i++, entry++) { + entry = emptyAnimSpace(entry); + assert(entry >= 0); // special case transparency handling if (!strcmp(resourceName, "L2202.ANI")) { - if (i < 2) { - transparentColor = 0; - } else { - transparentColor = 7; - } - } - - if (!strcmp(resourceName, "L4601.ANI")) { - if (i < 1) { - transparentColor = 0xE; - } else { - transparentColor = 0; - } + transparentColor = i < 2 ? 0 : 7; + } else if (!strcmp(resourceName, "L4601.ANI")) { + transparentColor = i < 1 ? 0xE : 0; } - animPtr = (byte *)malloc(fullSize); - - memcpy(animPtr, ptr, fullSize); - ptr += fullSize; - - gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr, animHeader.frameWidth, animHeader.frameHeight); - - generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2, animHeader.frameWidth * 2 * animHeader.frameHeight, transparentColor); - - free(animPtr); - - animDataTable[entry].fileIdx = foundFileIdx; - animDataTable[entry].frameIdx = i; - strcpy(animDataTable[entry].name, currentPartName); + animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor); + ptr += animHeader.frameWidth * animHeader.frameHeight; } free(dataPtr); } -void convert8BBP(byte * dest, byte * source, int16 width, int16 height) { - byte table[16]; +/*! \brief Decode 16 color image with palette + * \param[out] dest Decoded image + * \param[in] source Encoded image + * \param width Image width + * \param height Image height + */ +void convert8BBP(byte *dest, const byte *source, int16 width, int16 height) { + const byte *table = source; byte color; - memcpy(table, source, 16); source += 16; for (uint16 i = 0; i < width * height; i++) { @@ -485,16 +611,24 @@ void convert8BBP(byte * dest, byte * source, int16 width, int16 height) { } } -void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) { - uint16 i, j, k, m; +/*! \brief Decode 8bit image + * \param[out] dest Decoded image + * \param[in] source Encoded image + * \param width Image width + * \param height Image height + * \attention Data in source are destroyed during decoding + */ +void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) { + uint16 i, j; + int k, m; byte color; for (j = 0; j < (width * height) / 16; j++) { // m = 0: even bits, m = 1: odd bits - for (m = 0; m < 2; m++) { + for (m = 0; m <= 1; m++) { for (i = 0; i < 8; i++) { color = 0; - for (k = 14 + m; k >= 0 + m; k = k - 2) { + for (k = 14 + m; k >= 0; k -= 2) { color |= ((*(source + k) & 0x080) >> 7); *(source + k) <<= 1; if (k > 0 + m) @@ -508,14 +642,17 @@ void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) { } // end j } +/*! \brief Load image set + * \param resourceName Image set filename + * \param idx Target index in animDataTable + */ void loadSet(const char *resourceName, int16 idx) { AnimHeader2Struct header2; - uint32 fullSize; uint16 numSpriteInAnim; int16 foundFileIdx = findFileInBundle(resourceName); - int16 entry, typeParam; + int16 entry = idx >= 0 ? idx : 0; byte *ptr, *startOfDataPtr, *dataPtr, *origDataPtr; - byte table[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + int type; origDataPtr = dataPtr = readBundleFile(foundFileIdx); assert(!memcmp(dataPtr, "SET", 3)); @@ -526,9 +663,7 @@ void loadSet(const char *resourceName, int16 idx) { startOfDataPtr = ptr + numSpriteInAnim * 0x10; - for (int16 i = 0; i < numSpriteInAnim; i++) { - typeParam = 0; - + for (int16 i = 0; i < numSpriteInAnim; i++, entry++) { Common::MemoryReadStream readS(ptr, 0x10); header2.field_0 = readS.readUint32BE(); @@ -541,56 +676,37 @@ void loadSet(const char *resourceName, int16 idx) { ptr += 0x10; - fullSize = header2.width * header2.height; - - if (header2.type == 5) { - fullSize += 16; - } - - if (header2.type == 4) { - header2.type = 5; - typeParam = 1; - } - - if (idx >= 0) - entry = reserveFrame(header2.width * 2, header2.height, header2.type, idx + i); - else - entry = reserveFrame(header2.width * 2, header2.height, header2.type, -1); - - assert(entry != -1); + entry = idx < 0 ? emptyAnimSpace(entry) : idx + i; + assert(entry >= 0); dataPtr = startOfDataPtr + header2.field_0; - if (typeParam) { - memcpy(animDataTable[entry].ptr1, table, 0x10); - gfxConvertSpriteToRaw(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height); - //memcpy(animDataTable[entry].ptr1 + 0x10, dataPtr, fullSize); + if (header2.type == 1) { + type = ANIM_MASK; + } else if (header2.type == 4) { + type = ANIM_SPRITE; + } else if (header2.type == 5) { + type = ANIM_PALSPRITE; } else { - if (header2.type == 1) { - convert4BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height); - } else if (header2.type == 5) { - convert8BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height); - } else if (header2.type == 4) { - error("loadSet: header2.type == 4"); - } else { - convert8BBP2(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height); - } + type = ANIM_FULLSPRITE; } - animDataTable[entry].fileIdx = foundFileIdx; - animDataTable[entry].frameIdx = i; - strcpy(animDataTable[entry].name, currentPartName); + animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName); } free(origDataPtr); } +/*! \brief Load SEQ data into animDataTable + * \param resourceName SEQ data filename + * \param idx Target index in animDataTable + */ void loadSeq(const char *resourceName, int16 idx) { int16 foundFileIdx = findFileInBundle(resourceName); byte *dataPtr = readBundleFile(foundFileIdx); - int16 entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx); + int entry = idx < 0 ? emptyAnimSpace() : idx; - memcpy(animDataTable[entry].ptr1, dataPtr + 0x16, (uint16) partBuffer[foundFileIdx].unpackedSize - 0x16); + animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName); free(dataPtr); } @@ -624,6 +740,8 @@ void loadResource(const char *resourceName) { error("loadResource: Cannot determine type for '%s'", resourceName); } +/*! \todo There seems to be some additional resource file that is not loaded + */ void loadAbs(const char *resourceName, uint16 idx) { /* byte isMask = 0; */ /* byte isSpl = 0; */ @@ -632,6 +750,7 @@ void loadAbs(const char *resourceName, uint16 idx) { loadSet(resourceName, idx); return; } else if (strstr(resourceName, ".H32")) { + warning("Ignoring file %s (load at %d)", resourceName, idx); return; } else if (strstr(resourceName, ".SEQ")) { loadSeq(resourceName, idx); @@ -640,116 +759,108 @@ void loadAbs(const char *resourceName, uint16 idx) { loadSpl(resourceName, idx); return; } else if (strstr(resourceName, ".AMI")) { + warning("Ignoring file %s (load at %d)", resourceName, idx); return; } else if (strstr(resourceName, ".ANI")) { + warning("Ignoring file %s (load at %d)", resourceName, idx); return; } error("loadAbs: Cannot determine type for '%s'", resourceName); } -void loadResourcesFromSave() { - int16 currentAnim, foundFileIdx, fullSize, entry, i; +/*! \brief Load animDataTable from save + * \param fHandle Savefile open for reading + * \param broken Broken/correct file format switch + * \todo Add Operation Stealth savefile support + * + * Unlike the old code, this one actually rebuilds the table one frame + * at a time. + */ +void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) { + int16 currentAnim, foundFileIdx; int8 isMask = 0, isSpl = 0; - byte *dataPtr, *ptr, *animPtr; - char animName[256], part[256]; + byte *dataPtr, *ptr; + char *animName, part[256]; byte transparentColor; AnimData *currentPtr; + AnimHeaderStruct animHeader; + + uint16 width, height, bpp, var1; + int16 frame; + char name[10]; + int type; strcpy(part, currentPartName); for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim++) { currentPtr = &animDataTable[currentAnim]; - if (currentPtr->refresh && currentPtr->fileIdx != -1) { - if (strcmp(currentPartName, currentPtr->name)) { - closePart(); - loadPart(currentPtr->name); + + width = fHandle.readUint16BE(); + var1 = fHandle.readUint16BE(); + bpp = fHandle.readUint16BE(); + height = fHandle.readUint16BE(); + + if (!broken) { + if (!fHandle.readUint32BE()) { + fHandle.skip(18); + continue; } + fHandle.readUint32BE(); + } - foundFileIdx = currentPtr->fileIdx; + foundFileIdx = fHandle.readSint16BE(); + frame = fHandle.readSint16BE(); + fHandle.read(name, 10); - strcpy(animName, partBuffer[foundFileIdx].partName); - ptr = dataPtr = readBundleFile(foundFileIdx); + if (foundFileIdx < 0 || (broken && !fHandle.readByte())) { + continue; + } - isSpl = (strstr(animName, ".SPL")) ? 1 : 0; - isMask = (strstr(animName, ".MSK")) ? 1 : 0; + if (strcmp(currentPartName, name)) { + closePart(); + loadPart(name); + } - if (isSpl) { - animHeader.frameWidth = (uint16) partBuffer[foundFileIdx].unpackedSize; - animHeader.frameHeight = 1; - animHeader.numFrames = 1; - isMask = -1; - } else { - Common::MemoryReadStream readS(ptr, 0x22); + animName = partBuffer[foundFileIdx].partName; + ptr = dataPtr = readBundleFile(foundFileIdx); - loadAnimHeader(readS); + isSpl = (strstr(animName, ".SPL")) ? 1 : 0; + isMask = (strstr(animName, ".MSK")) ? 1 : 0; - ptr += 0x16; - } + if (isSpl) { + width = (uint16) partBuffer[foundFileIdx].unpackedSize; + height = 1; + frame = 0; + type = ANIM_RAW; + } else { + Common::MemoryReadStream readS(ptr, 0x16); + loadAnimHeader(animHeader, readS); + ptr += 0x16; - { - fullSize = animHeader.frameWidth * animHeader.frameHeight; + width = animHeader.frameWidth; + height = animHeader.frameHeight; - loadRelatedPalette(animName); + if (isMask) { + type = ANIM_MASK; + } else { + type = ANIM_MASKSPRITE; + loadRelatedPalette(animName); transparentColor = getAnimTransparentColor(animName); - for (i = 0; i < animHeader.numFrames; i++) { // load all the frames - // special case transparency handling - if (!strcmp(animName, "L2202.ANI")) { - if (i < 2) { - transparentColor = 0; - } else { - transparentColor = 7; - } - } - - if (!strcmp(animName, "L4601.ANI")) { - if (i < 1) { - transparentColor = 0xE; - } else { - transparentColor = 0; - } - } - - currentPtr[i].ptr1 = NULL; - entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, isMask); - - currentPtr->fileIdx = foundFileIdx; - - assert(entry != -1); - - if (isSpl) { - memcpy(animDataTable[entry].ptr1, ptr, fullSize); - ptr += fullSize; - } else { - if (!isMask) { - animPtr = (byte *)malloc(fullSize); - memcpy(animPtr, ptr, fullSize); - ptr += fullSize; - - gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr, - animHeader.frameWidth, animHeader.frameHeight); - generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2, - animHeader.frameWidth * 2 *animHeader.frameHeight, transparentColor); - - free(animPtr); - } else { - convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth, - animHeader.frameHeight); - ptr += fullSize; - } - } - - //animDataTable[entry].fileIdx = foundFileIdx; // Only when reading from bundles - - animDataTable[entry].frameIdx = i; - strcpy(animDataTable[entry].name, currentPartName); + // special case transparency handling + if (!strcmp(animName, "L2202.ANI")) { + transparentColor = (frame < 2) ? 0 : 7; + } else if (!strcmp(animName, "L4601.ANI")) { + transparentColor = (frame < 1) ? 0xE : 0; } } - - free(dataPtr); } + + ptr += frame * width * height; + currentPtr->load(ptr, type, width, height, foundFileIdx, frame, name, transparentColor); + free(dataPtr); } loadPart(part); diff --git a/engines/cine/anim.h b/engines/cine/anim.h index 92dbb2aaea..c15ab2eabd 100644 --- a/engines/cine/anim.h +++ b/engines/cine/anim.h @@ -54,11 +54,54 @@ struct AnimDataEntry { byte color; }; +#define ANIM_RAW 0 // memcpy +#define ANIM_MASK 1 // convertMask +#define ANIM_SPRITE 2 // gfxConvertSpriteToRaw +#define ANIM_MASKSPRITE 3 // gfxConvertSpriteToRaw + generateMask +#define ANIM_PALSPRITE 5 // convert8BBP +#define ANIM_FULLSPRITE 8 // convert8BBP2 + +class AnimData { +private: + byte *_data; ///< Image data + byte *_mask; ///< Image mask (may be NULL) + int16 _fileIdx; ///< Source file index in bundle + int16 _frameIdx; ///< Frame number in animation + char _name[10]; ///< Part filename + int _size; ///< _data/_mask size, internal only + +public: + uint16 _width; ///< Image width (ussually twice the real size) + uint16 _height; ///< Image height + uint16 _bpp; ///< Bit depth/type information + uint16 _var1; ///< Something related to width + int _realWidth; ///< Real image width in bytes + + AnimData(); + AnimData(const AnimData &src); + ~AnimData(); + + AnimData &operator=(const AnimData &src); + + const byte *data() const { return _data; } ///< Image data + const byte *mask() const { return _mask; } ///< Image mask (may be NULL) + byte getColor(int x, int y); + + void load(byte *d, int type, uint16 w, uint16 h, int16 file, int16 frame, const char *n, byte transparent = 0); + void clear(); + + void save(Common::OutSaveFile &fHandle) const; +}; + +#define NUM_MAX_ANIMDATA 255 + +extern AnimData animDataTable[NUM_MAX_ANIMDATA]; + void freeAnimDataTable(void); void freeAnimDataRange(byte startIdx, byte numIdx); void loadResource(const char *animName); void loadAbs(const char *resourceName, uint16 idx); -void loadResourcesFromSave(); +void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken); } // End of namespace Cine diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp index f5b64573af..351a633b5e 100644 --- a/engines/cine/bg.cpp +++ b/engines/cine/bg.cpp @@ -29,6 +29,7 @@ #include "cine/cine.h" #include "cine/various.h" +#include "cine/bg.h" namespace Cine { @@ -36,10 +37,6 @@ uint16 bgVar0; byte *additionalBgTable[9]; byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0; -void loadCtHigh(byte * currentPtr) { - memcpy(page3Raw, currentPtr, 320 * 200); -} - byte loadCt(const char *ctName) { uint16 header[32]; byte *ptr, *dataPtr; @@ -52,10 +49,17 @@ byte loadCt(const char *ctName) { if (g_cine->getGameType() == Cine::GType_OS) { uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; if (bpp == 8) { + ctColorMode = 1; + memcpy(newPalette, ptr, 256*3); ptr += 3 * 256; - loadCtHigh(ptr); + memcpy(page3Raw, ptr, 320 * 200); } else { - ptr += 32; + ctColorMode = 0; + for (int i = 0; i < 16; i++) { + tempPalette[i] = READ_BE_UINT16(ptr); + ptr += 2; + } + gfxResetRawPage(page3Raw); gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200); } @@ -78,12 +82,14 @@ byte loadCt(const char *ctName) { } void loadBgHigh(const char *currentPtr) { - memcpy(palette256, currentPtr, 256 * 3); + memcpy(newPalette, currentPtr, 256 * 3); currentPtr += 256 * 3; memcpy(page2Raw, currentPtr, 320 * 200); - colorMode256 = 1; + newColorMode = 2; + bgColorMode = 1; + } byte loadBg(const char *bgName) { @@ -99,7 +105,8 @@ byte loadBg(const char *bgName) { if (bpp == 8) { loadBgHigh((const char *)ptr); } else { - colorMode256 = 0; + newColorMode = 1; + bgColorMode = 0; for (int i = 0; i < 16; i++) { tempPalette[i] = READ_BE_UINT16(ptr); @@ -127,12 +134,22 @@ void addBackground(const char *bgName, uint16 bgIdx) { additionalBgTable[bgIdx] = (byte *) malloc(320 * 200); + debug("addBackground %d", bgIdx); + uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; + if (bpp == 8) { + bgColorMode = 1; + memcpy(newPalette, ptr, 256*3); ptr += 3 * 256; memcpy(additionalBgTable[bgIdx], ptr, 320 * 200); } else { - ptr += 32; + bgColorMode = 0; + for (int i = 0; i < 16; i++) { + tempPalette[i] = READ_BE_UINT16(ptr); + ptr += 2; + } + gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200); } free(dataPtr); diff --git a/engines/cine/bg.h b/engines/cine/bg.h index 7145af467a..ca5c222131 100644 --- a/engines/cine/bg.h +++ b/engines/cine/bg.h @@ -27,10 +27,17 @@ #define CINE_BG_H namespace Cine { +struct bgData { + byte *data; + byte colorMode; + byte *highPalette; + uint16 *lowPalette; +}; byte loadBg(const char *bgName); byte loadCt(const char *bgName); +//extern bgData additionalBgTable[9]; extern byte *additionalBgTable[9]; extern byte currentAdditionalBgIdx; extern byte currentAdditionalBgIdx2; diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp index 1d69407c8a..7d35f9981e 100644 --- a/engines/cine/bg_list.cpp +++ b/engines/cine/bg_list.cpp @@ -36,129 +36,116 @@ namespace Cine { uint32 var8; -BGIncrustList *bgIncrustList; +Common::List bgIncrustList; +/*! \brief Add masked sprite to the background + * \param objIdx Sprite description + * \param addList Add sprite to incrust list if true + * \todo Fix incrust objects on CT background. Always drawing incrust elements + * on CT background breaks game zones + */ void addToBGList(int16 objIdx, bool addList) { int16 x = objectTable[objIdx].x; int16 y = objectTable[objIdx].y; - int16 width = animDataTable[objectTable[objIdx].frame].var1; - int16 height = animDataTable[objectTable[objIdx].frame].height; + int16 width = animDataTable[objectTable[objIdx].frame]._var1; + int16 height = animDataTable[objectTable[objIdx].frame]._height; + const byte *data = animDataTable[objectTable[objIdx].frame].data(); + const byte *mask = animDataTable[objectTable[objIdx].frame].mask(); // int16 part = objectTable[objIdx].part; + // Operation Stealth may switch among multiple backgrounds if (g_cine->getGameType() == GType_OS) { - drawSpriteRaw2(animDataTable[objectTable[objIdx].frame].ptr1, objectTable[objIdx].part, width, height, page2Raw, x, y); + for (int i = 0; i < 8; i++) { + if (additionalBgTable[i]) { + drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y); + } + } } else { - drawSpriteRaw(animDataTable[objectTable[objIdx].frame].ptr1, animDataTable[objectTable[objIdx].frame].ptr2, width, height, page2Raw, x, y); + drawSpriteRaw(data, mask, width, height, page2Raw, x, y); } if (addList) createBgIncrustListElement(objIdx, 0); } +/*! \brief Add filled sprite to the background + * \param objIdx Sprite description + * \param addList Add sprite to incrust list if true + * \todo Fix incrust objects on CT background. Always drawing incrust elements + * on CT background breaks game zones + */ void addSpriteFilledToBGList(int16 objIdx, bool addList) { int16 x = objectTable[objIdx].x; int16 y = objectTable[objIdx].y; - int16 width = animDataTable[objectTable[objIdx].frame].width; - int16 height = animDataTable[objectTable[objIdx].frame].height; - - if (animDataTable[objectTable[objIdx].frame].ptr1) { - gfxFillSprite(animDataTable[objectTable[objIdx].frame].ptr1, width / 2, height, page2Raw, x, y); + int16 width = animDataTable[objectTable[objIdx].frame]._width; + int16 height = animDataTable[objectTable[objIdx].frame]._height; + const byte *data = animDataTable[objectTable[objIdx].frame].data(); + + if (data) { + // Operation Stealth may switch among multiple backgrounds + if (g_cine->getGameType() == GType_OS) { + for (int i = 0; i < 8; i++) { + if (additionalBgTable[i]) { + gfxFillSprite(data, width / 2, height, additionalBgTable[i], x, y); + } + } + } else { + gfxFillSprite(data, width / 2, height, page2Raw, x, y); + } } if (addList) createBgIncrustListElement(objIdx, 1); } +/*! \brief Add new element to incrust list + * \param objIdx Element description + * \param param Type of element + */ void createBgIncrustListElement(int16 objIdx, int16 param) { - BGIncrustList *bgIncrustPtr = bgIncrustList; - BGIncrustList *bgIncrustPtrP = 0; - - // Find first empty element - while (bgIncrustPtr) { - bgIncrustPtrP = bgIncrustPtr; - bgIncrustPtr = bgIncrustPtr->next; - } - - bgIncrustPtr = new BGIncrustList; - if (bgIncrustPtrP) - bgIncrustPtrP->next = bgIncrustPtr; - else - bgIncrustList = bgIncrustPtr; - - bgIncrustPtr->next = 0; - - bgIncrustPtr->objIdx = objIdx; - bgIncrustPtr->param = param; - bgIncrustPtr->x = objectTable[objIdx].x; - bgIncrustPtr->y = objectTable[objIdx].y; - bgIncrustPtr->frame = objectTable[objIdx].frame; - bgIncrustPtr->part = objectTable[objIdx].part; -} + BGIncrust tmp; -void freeBgIncrustList(void) { - BGIncrustList *bgIncrustPtr = bgIncrustList; - BGIncrustList *bgIncrustPtrN; + tmp.objIdx = objIdx; + tmp.param = param; + tmp.x = objectTable[objIdx].x; + tmp.y = objectTable[objIdx].y; + tmp.frame = objectTable[objIdx].frame; + tmp.part = objectTable[objIdx].part; - while (bgIncrustPtr) { - bgIncrustPtrN = bgIncrustPtr->next; - delete bgIncrustPtr; - bgIncrustPtr = bgIncrustPtrN; - } - - resetBgIncrustList(); + bgIncrustList.push_back(tmp); } +/*! \brief Reset var8 (probably something related to bgIncrustList + */ void resetBgIncrustList(void) { - bgIncrustList = NULL; var8 = 0; } -void loadBgIncrustFromSave(Common::InSaveFile *fHandle) { - BGIncrustList *bgIncrustPtr = bgIncrustList; - BGIncrustList *bgIncrustPtrP = 0; - - // Find first empty element - while (bgIncrustPtr) { - bgIncrustPtrP = bgIncrustPtr; - bgIncrustPtr = bgIncrustPtr->next; - } - - bgIncrustPtr = new BGIncrustList; - if (bgIncrustPtrP) - bgIncrustPtrP->next = bgIncrustPtr; - else - bgIncrustList = bgIncrustPtr; - - bgIncrustPtr->next = 0; - - fHandle->readUint32BE(); - fHandle->readUint32BE(); - - bgIncrustPtr->objIdx = fHandle->readUint16BE(); - bgIncrustPtr->param = fHandle->readUint16BE(); - bgIncrustPtr->x = fHandle->readUint16BE(); - bgIncrustPtr->y = fHandle->readUint16BE(); - bgIncrustPtr->frame = fHandle->readUint16BE(); - bgIncrustPtr->part = fHandle->readUint16BE(); -} - -void reincrustAllBg(void) { - BGIncrustList *bgIncrustPtr = bgIncrustList; - - while (bgIncrustPtr) { -#if 0 - objectTable[bgIncrustPtr->objIdx].x = bgIncrustPtr->x; - objectTable[bgIncrustPtr->objIdx].y = bgIncrustPtr->y; - objectTable[bgIncrustPtr->objIdx].frame = bgIncrustPtr->frame; - objectTable[bgIncrustPtr->objIdx].part = bgIncrustPtr->part; -#endif - if (bgIncrustPtr->param == 0) { - addToBGList(bgIncrustPtr->objIdx, false); +/*! \brief Restore incrust list from savefile + * \param fHandle Savefile open for reading + */ +void loadBgIncrustFromSave(Common::InSaveFile &fHandle) { + BGIncrust tmp; + int size = fHandle.readSint16BE(); + + for (int i = 0; i < size; i++) { + fHandle.readUint32BE(); + fHandle.readUint32BE(); + + tmp.objIdx = fHandle.readUint16BE(); + tmp.param = fHandle.readUint16BE(); + tmp.x = fHandle.readUint16BE(); + tmp.y = fHandle.readUint16BE(); + tmp.frame = fHandle.readUint16BE(); + tmp.part = fHandle.readUint16BE(); + + bgIncrustList.push_back(tmp); + + if (tmp.param == 0) { + addToBGList(tmp.objIdx, false); } else { - addSpriteFilledToBGList(bgIncrustPtr->objIdx, false); + addSpriteFilledToBGList(tmp.objIdx, false); } - - bgIncrustPtr = bgIncrustPtr->next; } } diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h index a4b8b44a4c..9ceae0acf5 100644 --- a/engines/cine/bg_list.h +++ b/engines/cine/bg_list.h @@ -29,11 +29,11 @@ #include "common/scummsys.h" #include "common/savefile.h" +#include "common/list.h" namespace Cine { -struct BGIncrustList { - struct BGIncrustList *next; +struct BGIncrust { byte *unkPtr; int16 objIdx; int16 param; @@ -43,17 +43,15 @@ struct BGIncrustList { int16 part; }; -extern BGIncrustList *bgIncrustList; +extern Common::List bgIncrustList; extern uint32 var8; void addToBGList(int16 objIdx, bool addList = true); void addSpriteFilledToBGList(int16 idx, bool addList = true); void createBgIncrustListElement(int16 objIdx, int16 param); -void freeBgIncrustList(void); void resetBgIncrustList(void); -void loadBgIncrustFromSave(Common::InSaveFile *fHandle); -void reincrustAllBg(void); +void loadBgIncrustFromSave(Common::InSaveFile &fHandle); } // End of namespace Cine diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index 8037502b96..ffcbfbaa82 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -111,8 +111,6 @@ void CineEngine::initialize() { partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer)); - animDataTable = (AnimData *)malloc(NUM_MAX_ANIMDATA * sizeof(AnimData)); - if (g_cine->getGameType() == Cine::GType_OS) { readVolCnf(); } @@ -124,30 +122,24 @@ void CineEngine::initialize() { loadErrmessDat("errmess.dat"); } + // in case ScummVM engines can be restarted in the future + scriptTable.clear(); + relTable.clear(); + objectScripts.clear(); + globalScripts.clear(); + bgIncrustList.clear(); + freeAnimDataTable(); + memset(objectTable, 0, sizeof(objectTable)); - memset(scriptTable, 0, sizeof(scriptTable)); memset(messageTable, 0, sizeof(messageTable)); - memset(relTable, 0, sizeof(relTable)); - - for (int i = 0; i < NUM_MAX_ANIMDATA; i++) { - animDataTable[i].ptr1 = animDataTable[i].ptr2 = NULL; - } overlayHead.next = overlayHead.previous = NULL; var8 = 0; - bgIncrustList = NULL; - - objScriptList.next = NULL; - objScriptList.scriptPtr = NULL; - - globalScriptsHead.next = NULL; - globalScriptsHead.scriptPtr = NULL; +// bgIncrustList = NULL; var2 = var3 = var4 = var5 = 0; - freePrcLinkedList(); - _preLoad = false; if (ConfMan.hasKey("save_slot")) { char saveNameBuffer[256]; diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index c76f62cdd7..8db4456485 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -37,6 +37,10 @@ namespace Cine { uint16 c_palette[256]; byte colorMode256 = 0; byte palette256[256 * 3]; +byte newPalette[256 * 3]; +byte newColorMode = 0; +byte ctColorMode = 0; +byte bgColorMode = 0; byte *screenBuffer; byte *page1Raw; @@ -157,7 +161,7 @@ void transformPaletteRange(byte startColor, byte stopColor, int8 r, int8 g, int8 //gfxFlipPage(page2); } -void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) { +void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) { int16 i, j; for (i = 0; i < height; i++) { @@ -180,7 +184,7 @@ void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int } } -void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) { +void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) { int16 i, j; for (i = 0; i < height; i++) { @@ -198,7 +202,7 @@ void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 he } } -void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr, +void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr, int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx) { int16 i, j, d, spritePitch, maskPitch; @@ -299,8 +303,8 @@ void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte } } -int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width) { - byte *ptrToData = (ptr) + y * width + x; +int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width) { + const byte *ptrToData = (ptr) + y * width + x; if (x > width) { return 0; @@ -379,7 +383,7 @@ void gfxFlipRawPage(byte *frontBuffer) { g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200); } -void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, +void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y) { int16 i, j; @@ -406,7 +410,7 @@ void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, } } -void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height, +void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y) { int16 i, j; @@ -425,11 +429,84 @@ void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height, } } +void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 height, + byte *page, int16 x, int16 y) { + int16 i, j; + + for (i = 0; i < height; i++) { + byte *destPtr = page + x + y * 320; + const byte *srcPtr = bgPtr + x + y * 320; + destPtr += i * 320; + srcPtr += i * 320; + + for (j = 0; j < width * 8; j++) { + if ((!maskPtr || !(*maskPtr)) && (x + j >= 0 + && x + j < 320 && i + y >= 0 && i + y < 200)) { + *destPtr = *srcPtr; + } + + destPtr++; + srcPtr++; + maskPtr++; + } + } +} + +/*! \todo Fix rendering to prevent fadein artifacts + */ +void fadeFromBlack() { + int i, j; + int r, g, b, tr, tg, tb; + if (newColorMode == 2) { + colorMode256 = 1; + memset(palette256, 0, 256*3); + } else if (newColorMode == 1) { + colorMode256 = 0; + memset(c_palette, 0, 16 * sizeof(uint16)); + } + + for (i = 0; i < 8; i++ ) { + gfxFlipRawPage(page1Raw); + g_system->updateScreen(); + g_system->delayMillis(50); + + if (colorMode256) { + for (j = 0; j < 256*3; j++) { + r = palette256[j] + (newPalette[j] + 7) / 8; + palette256[j] = CLIP(r, 0, (int)newPalette[j]); + } + } else { + for (j = 0; j < 16; j++) { + r = c_palette[j] & 0xf; + g = (c_palette[j] & 0xf0) >> 4; + b = (c_palette[j] & 0xf00) >> 8; + + tr = tempPalette[j] & 0xf; + tg = (tempPalette[j] & 0xf0) >> 4; + tb = (tempPalette[j] & 0xf00) >> 8; + + r = CLIP(r + (tr + 7) / 8, 0, tr); + g = CLIP(g + (tg + 7) / 8, 0, tg); + b = CLIP(b + (tb + 7) / 8, 0, tb); + + c_palette[j] = r | (g << 4) | (b << 8); + } + + } + } + + if (colorMode256) { + memcpy(palette256, newPalette, 256*3); + } else { + memcpy(c_palette, tempPalette, sizeof(uint16) * 16); + } +} + void fadeToBlack() { for (int i = 0; i < 8; i++) { if (colorMode256) { - for (int j = 0; j < 256; j++) { - palette256[j] = transformColor(palette256[j], -1, -1, -1); + for (int j = 0; j < 256*3; j++) { + palette256[j] = CLIP(palette256[j] - 32, 0, 255); } } else { for (int j = 0; j < 16; j++) { @@ -449,7 +526,17 @@ void blitRawScreen(byte *frontBuffer) { void flip(void) { blitRawScreen(page1Raw); if (fadeRequired) { - memcpy(c_palette, tempPalette, sizeof(uint16) * 16); + if (newColorMode == 3) { + newColorMode = ctColorMode + 1; + } + + if (newColorMode == 2) { + colorMode256 = 1; + memcpy(palette256, newPalette, 256*3); + } else { + colorMode256 = 0; + memcpy(c_palette, tempPalette, sizeof(uint16) * 16); + } fadeRequired = false; } } diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index b2dc70f360..9e03f351f9 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -37,6 +37,10 @@ extern byte *page3Raw; extern uint16 c_palette[256]; extern byte colorMode256; extern byte palette256[256 * 3]; +extern byte newPalette[256 * 3]; +extern byte newColorMode; +extern byte ctColorMode; +extern byte bgColorMode; void gfxInit(); void gfxDestroy(); @@ -46,10 +50,10 @@ void gfxCopyPage(byte *source, byte *dest); void transformPaletteRange(byte startColor, byte numColor, int8 r, int8 g, int8 b); void gfxFlipPage(void); -void gfxDrawMaskedSprite(byte *ptr, byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y); -void gfxFillSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0); +void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y); +void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0); -void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr, +void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr, int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx); void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page); @@ -57,19 +61,23 @@ void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color); void gfxResetPage(byte *pagePtr); -int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width); +int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width); +byte gfxGetColor(int16 x, int16 y, const byte *ptr, int16 width); void gfxResetRawPage(byte *pageRaw); void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h); void gfxCopyRawPage(byte *source, byte * dest); void gfxFlipRawPage(byte *frontBuffer); -void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y); +void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y); void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page); -void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y); +void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y); +void maskBgOverlay(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y); +void fadeFromBlack(void); void fadeToBlack(void); -void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5); +// wtf?! +//void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5); void gfxWaitVBL(void); void gfxRedrawMouseCursor(void); diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index 263a5a2e49..c74dde0310 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -189,11 +189,8 @@ void CineEngine::mainLoop(int bootScriptIdx) { quitFlag = 0; if (_preLoad == false) { - freeAnimDataTable(); resetMessageHead(); resetSeqList(); - resetglobalScriptsHead(); - resetObjectScriptHead(); resetBgIncrustList(); setTextWindow(0, 0, 20, 200); @@ -318,14 +315,10 @@ void CineEngine::mainLoop(int bootScriptIdx) { hideMouse(); g_sound->stopMusic(); - freeAnimDataTable(); unloadAllMasks(); - freePrcLinkedList(); - releaseObjectScripts(); // if (g_cine->getGameType() == Cine::GType_OS) { // freeUnkList(); // } - freeBgIncrustList(); closePart(); } diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 59adae6fc9..bba1c094f1 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -231,7 +231,9 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) { objectTable[objIdx].frame = newValue; break; case 4: - if (newValue == -1) { + // is it really in Future Wars? it breaks the newspaper machine + // on the airport in Operation Stealth + if (newValue == -1 && g_cine->getGameType() != Cine::GType_OS) { objectTable[objIdx].costume = globalVars[0]; } else { objectTable[objIdx].costume = newValue; @@ -243,8 +245,8 @@ void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) { } } -byte compareObjectParam(byte objIdx, byte type, int16 value) { - byte compareResult = 0; +uint16 compareObjectParam(byte objIdx, byte type, int16 value) { + uint16 compareResult = 0; int16 objectParam = getObjectParam(objIdx, type); if (objectParam > value) { diff --git a/engines/cine/object.h b/engines/cine/object.h index 92b3111841..e4ab1377ff 100644 --- a/engines/cine/object.h +++ b/engines/cine/object.h @@ -74,7 +74,7 @@ int16 freeOverlay(uint16 objIdx, uint16 param); void addObjectParam(byte objIdx, byte paramIdx, int16 newValue); void subObjectParam(byte objIdx, byte paramIdx, int16 newValue); -byte compareObjectParam(byte objIdx, byte param1, int16 param2); +uint16 compareObjectParam(byte objIdx, byte param1, int16 param2); } // End of namespace Cine diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index 369ca8759d..43656460c5 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -33,7 +33,6 @@ namespace Cine { uint16 numElementInPart; -AnimData *animDataTable; PartBuffer *partBuffer; void loadPart(const char *partName) { diff --git a/engines/cine/part.h b/engines/cine/part.h index fae044afb1..2a979e4879 100644 --- a/engines/cine/part.h +++ b/engines/cine/part.h @@ -35,26 +35,8 @@ struct PartBuffer { uint32 unpackedSize; }; -struct AnimData { - uint16 width; - uint16 var1; - uint16 bpp; - uint16 height; - - byte *ptr1; - byte *ptr2; - int16 fileIdx; - int16 frameIdx; - char name[10]; - - // Not part of the data, but used when saving/restoring it. - bool refresh; -}; - #define NUM_MAX_PARTDATA 255 -#define NUM_MAX_ANIMDATA 255 -extern AnimData *animDataTable; extern PartBuffer *partBuffer; void loadPart(const char *partName); diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp index a8a14cc013..0f068a197e 100644 --- a/engines/cine/prc.cpp +++ b/engines/cine/prc.cpp @@ -33,34 +33,14 @@ namespace Cine { -prcLinkedListStruct globalScriptsHead; -prcLinkedListStruct objScriptList; +ScriptList globalScripts; +ScriptList objectScripts; //char currentPrcName[20]; -void resetglobalScriptsHead(void) { - globalScriptsHead.next = NULL; - globalScriptsHead.scriptIdx = -1; -} - -void freePrcLinkedList(void) { - prcLinkedListStruct *currentHead = globalScriptsHead.next; - - while (currentHead) { - prcLinkedListStruct *temp; - - assert(currentHead); - - temp = currentHead->next; - - delete currentHead; - - currentHead = temp; - } - - resetglobalScriptsHead(); -} - +/*! \todo Is script size of 0 valid? + * \todo Fix script dump code + */ void loadPrc(const char *pPrcName) { byte i; uint16 numScripts; @@ -68,14 +48,8 @@ void loadPrc(const char *pPrcName) { assert(pPrcName); - for (i = 0; i < NUM_MAX_SCRIPT; i++) { - if (scriptTable[i].ptr) { - assert(scriptTable[i].ptr); - free(scriptTable[i].ptr); - scriptTable[i].ptr = NULL; - scriptTable[i].size = 0; - } - } + globalScripts.clear(); + scriptTable.clear(); // This is copy protection. Used to hang the machine if (!scumm_stricmp(pPrcName, "L201.ANI")) { @@ -100,17 +74,18 @@ void loadPrc(const char *pPrcName) { assert(numScripts <= NUM_MAX_SCRIPT); for (i = 0; i < numScripts; i++) { - scriptTable[i].size = READ_BE_UINT16(scriptPtr); scriptPtr += 2; + RawScriptPtr tmp(new RawScript(READ_BE_UINT16(scriptPtr))); + scriptPtr += 2; + assert(tmp); + scriptTable.push_back(tmp); } for (i = 0; i < numScripts; i++) { - uint16 size = scriptTable[i].size; + uint16 size = scriptTable[i]->_size; + // TODO: delete the test? if (size) { - scriptTable[i].ptr = (byte *) malloc(size); - assert(scriptTable[i].ptr); - memcpy(scriptTable[i].ptr, scriptPtr, size); + scriptTable[i]->setData(*scriptInfo, scriptPtr); scriptPtr += size; - computeScriptStack(scriptTable[i].ptr, scriptTable[i].stack, size); } } diff --git a/engines/cine/prc.h b/engines/cine/prc.h index 2ec4ed6f95..f5129d28b1 100644 --- a/engines/cine/prc.h +++ b/engines/cine/prc.h @@ -28,21 +28,9 @@ namespace Cine { -struct prcLinkedListStruct { - struct prcLinkedListStruct *next; - int16 stack[SCRIPT_STACK_SIZE]; - ScriptVars localVars; - uint16 compareResult; - uint16 scriptPosition; - byte *scriptPtr; - int16 scriptIdx; -}; - -extern prcLinkedListStruct globalScriptsHead; -extern prcLinkedListStruct objScriptList; - -void resetglobalScriptsHead(void); -void freePrcLinkedList(void); +extern ScriptList globalScripts; +extern ScriptList objectScripts; + void loadPrc(const char *pPrcName); } // End of namespace Cine diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp index c9c5755ac6..f550efed27 100644 --- a/engines/cine/rel.cpp +++ b/engines/cine/rel.cpp @@ -31,45 +31,21 @@ namespace Cine { -RelObjectScript relTable[NUM_MAX_REL]; - -void resetObjectScriptHead(void) { - objScriptList.next = NULL; - objScriptList.scriptIdx = -1; -} - -void releaseObjectScripts(void) { - prcLinkedListStruct *currentHead = objScriptList.next; - - while (currentHead) { - prcLinkedListStruct *temp; - - assert(currentHead); - - temp = currentHead->next; - - delete currentHead; - - currentHead = temp; - } - - resetObjectScriptHead(); -} +RawObjectScriptArray relTable; ///< Object script bytecode table +/*! \todo Is script size of 0 valid? + * \todo Fix script dump code + */ void loadRel(char *pRelName) { uint16 numEntry; uint16 i; + uint16 size, p1, p2, p3; byte *ptr, *dataPtr; checkDataDisk(-1); - for (i = 0; i < NUM_MAX_REL; i++) { - if (relTable[i].data) { - free(relTable[i].data); - relTable[i].data = NULL; - relTable[i].size = 0; - } - } + objectScripts.clear(); + relTable.clear(); ptr = dataPtr = readBundleFile(findFileInBundle(pRelName)); @@ -77,24 +53,22 @@ void loadRel(char *pRelName) { numEntry = READ_BE_UINT16(ptr); ptr += 2; - assert(numEntry <= NUM_MAX_REL); - for (i = 0; i < numEntry; i++) { - relTable[i].size = READ_BE_UINT16(ptr); ptr += 2; - relTable[i].obj1Param1 = READ_BE_UINT16(ptr); ptr += 2; - relTable[i].obj1Param2 = READ_BE_UINT16(ptr); ptr += 2; - relTable[i].obj2Param = READ_BE_UINT16(ptr); ptr += 2; - relTable[i].runCount = 0; + size = READ_BE_UINT16(ptr); ptr += 2; + p1 = READ_BE_UINT16(ptr); ptr += 2; + p2 = READ_BE_UINT16(ptr); ptr += 2; + p3 = READ_BE_UINT16(ptr); ptr += 2; + RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3)); + assert(tmp); + relTable.push_back(tmp); } for (i = 0; i < numEntry; i++) { - if (relTable[i].size) { - relTable[i].data = (byte *)malloc(relTable[i].size); - - assert(relTable[i].data); - - memcpy(relTable[i].data, ptr, relTable[i].size); - ptr += relTable[i].size; + size = relTable[i]->_size; + // TODO: delete the test? + if (size) { + relTable[i]->setData(*scriptInfo, ptr); + ptr += size; } } diff --git a/engines/cine/rel.h b/engines/cine/rel.h index 3e8332a55e..84926f76c4 100644 --- a/engines/cine/rel.h +++ b/engines/cine/rel.h @@ -26,23 +26,10 @@ #ifndef CINE_REL_H #define CINE_REL_H +#include "cine/script.h" namespace Cine { -struct RelObjectScript { - byte *data; - uint16 size; - uint16 obj1Param1; - uint16 obj1Param2; - uint16 obj2Param; - uint16 runCount; -}; - -#define NUM_MAX_REL 255 - -extern RelObjectScript relTable[NUM_MAX_REL]; - -void releaseObjectScripts(void); -void resetObjectScriptHead(void); +extern RawObjectScriptArray relTable; void loadRel(char *pRelName); diff --git a/engines/cine/script.cpp b/engines/cine/script.cpp index c1bfee317a..8ccd0ce3a1 100644 --- a/engines/cine/script.cpp +++ b/engines/cine/script.cpp @@ -23,6 +23,9 @@ * */ +/*! \file + * Script interpreter file + */ #include "common/endian.h" @@ -31,435 +34,423 @@ #include "cine/object.h" #include "cine/sound.h" #include "cine/various.h" +#include "cine/script.h" namespace Cine { -prcLinkedListStruct *_currentScriptElement; -byte *_currentScriptPtr; -uint16 _currentScriptParams; -uint16 _currentPosition; -uint16 _currentLine; -uint16 _closeScript; - -struct Opcode { - void (*proc)(); - const char *args; +uint16 compareVars(int16 a, int16 b); +void palRotate(byte a, byte b, byte c); +void removeSeq(uint16 param1, uint16 param2, uint16 param3); +uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); +void addGfxElementA0(int16 param1, int16 param2); +void removeGfxElementA0(int16 idx, int16 param); + +const Opcode FWScript::_opcodeTable[] = { + /* 00 */ + { &FWScript::o1_modifyObjectParam, "bbw" }, + { &FWScript::o1_getObjectParam, "bbb" }, + { &FWScript::o1_addObjectParam, "bbw" }, + { &FWScript::o1_subObjectParam, "bbw" }, + /* 04 */ + { &FWScript::o1_add2ObjectParam, "bbw" }, + { &FWScript::o1_sub2ObjectParam, "bbw" }, + { &FWScript::o1_compareObjectParam, "bbw" }, + { &FWScript::o1_setupObject, "bwwww" }, + /* 08 */ + { &FWScript::o1_checkCollision, "bwwww" }, + { &FWScript::o1_loadVar, "bc" }, + { &FWScript::o1_addVar, "bc" }, + { &FWScript::o1_subVar, "bc" }, + /* 0C */ + { &FWScript::o1_mulVar, "bc" }, + { &FWScript::o1_divVar, "bc" }, + { &FWScript::o1_compareVar, "bc" }, + { &FWScript::o1_modifyObjectParam2, "bbb" }, + /* 10 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_loadMask0, "b" }, + /* 14 */ + { &FWScript::o1_unloadMask0, "b" }, + { &FWScript::o1_addToBgList, "b" }, + { &FWScript::o1_loadMask1, "b" }, + { &FWScript::o1_unloadMask1, "b" }, + /* 18 */ + { &FWScript::o1_loadMask4, "b" }, + { &FWScript::o1_unloadMask4, "b" }, + { &FWScript::o1_addSpriteFilledToBgList, "b" }, + { &FWScript::o1_op1B, "" }, + /* 1C */ + { 0, 0 }, + { &FWScript::o1_label, "l" }, + { &FWScript::o1_goto, "b" }, + { &FWScript::o1_gotoIfSup, "b" }, + /* 20 */ + { &FWScript::o1_gotoIfSupEqu, "b" }, + { &FWScript::o1_gotoIfInf, "b" }, + { &FWScript::o1_gotoIfInfEqu, "b" }, + { &FWScript::o1_gotoIfEqu, "b" }, + /* 24 */ + { &FWScript::o1_gotoIfDiff, "b" }, + { &FWScript::o1_removeLabel, "b" }, + { &FWScript::o1_loop, "bb" }, + { 0, 0 }, + /* 28 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 2C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 30 */ + { 0, 0 }, + { &FWScript::o1_startGlobalScript, "b" }, + { &FWScript::o1_endGlobalScript, "b" }, + { 0, 0 }, + /* 34 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 38 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_loadAnim, "s" }, + /* 3C */ + { &FWScript::o1_loadBg, "s" }, + { &FWScript::o1_loadCt, "s" }, + { 0, 0 }, + { &FWScript::o1_loadPart, "s" }, + /* 40 */ + { &FWScript::o1_closePart, "" }, + { &FWScript::o1_loadNewPrcName, "bs" }, + { &FWScript::o1_requestCheckPendingDataLoad, "" }, + { 0, 0 }, + /* 44 */ + { 0, 0 }, + { &FWScript::o1_blitAndFade, "" }, + { &FWScript::o1_fadeToBlack, "" }, + { &FWScript::o1_transformPaletteRange, "bbwww" }, + /* 48 */ + { 0, 0 }, + { &FWScript::o1_setDefaultMenuColor2, "b" }, + { &FWScript::o1_palRotate, "bbb" }, + { 0, 0 }, + /* 4C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_break, "" }, + /* 50 */ + { &FWScript::o1_endScript, "x" }, + { &FWScript::o1_message, "bwwww" }, + { &FWScript::o1_loadGlobalVar, "bc" }, + { &FWScript::o1_compareGlobalVar, "bc" }, + /* 54 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 58 */ + { 0, 0 }, + { &FWScript::o1_declareFunctionName, "s" }, + { &FWScript::o1_freePartRange, "bb" }, + { &FWScript::o1_unloadAllMasks, "" }, + // 5C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 60 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_setScreenDimensions, "wwww" }, + /* 64 */ + { &FWScript::o1_displayBackground, "" }, + { &FWScript::o1_initializeZoneData, "" }, + { &FWScript::o1_setZoneDataEntry, "bw" }, + { &FWScript::o1_getZoneDataEntry, "bb" }, + /* 68 */ + { &FWScript::o1_setDefaultMenuColor, "b" }, + { &FWScript::o1_allowPlayerInput, "" }, + { &FWScript::o1_disallowPlayerInput, "" }, + { &FWScript::o1_changeDataDisk, "b" }, + /* 6C */ + { 0, 0 }, + { &FWScript::o1_loadMusic, "s" }, + { &FWScript::o1_playMusic, "" }, + { &FWScript::o1_fadeOutMusic, "" }, + /* 70 */ + { &FWScript::o1_stopSample, "" }, + { &FWScript::o1_op71, "bw" }, + { &FWScript::o1_op72, "wbw" }, + { &FWScript::o1_op73, "wbw" }, + /* 74 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_playSample, "bbwbww" }, + /* 78 */ + { &FWScript::o1_playSample, "bbwbww" }, + { &FWScript::o1_disableSystemMenu, "b" }, + { &FWScript::o1_loadMask5, "b" }, + { &FWScript::o1_unloadMask5, "b" } }; +const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable); + + +const Opcode OSScript::_opcodeTable[] = { + /* 00 */ + { &FWScript::o1_modifyObjectParam, "bbw" }, + { &FWScript::o1_getObjectParam, "bbb" }, + { &FWScript::o1_addObjectParam, "bbw" }, + { &FWScript::o1_subObjectParam, "bbw" }, + /* 04 */ + { &FWScript::o1_add2ObjectParam, "bbw" }, + { &FWScript::o1_sub2ObjectParam, "bbw" }, + { &FWScript::o1_compareObjectParam, "bbw" }, + { &FWScript::o1_setupObject, "bwwww" }, + /* 08 */ + { &FWScript::o1_checkCollision, "bwwww" }, + { &FWScript::o1_loadVar, "bc" }, + { &FWScript::o1_addVar, "bc" }, + { &FWScript::o1_subVar, "bc" }, + /* 0C */ + { &FWScript::o1_mulVar, "bc" }, + { &FWScript::o1_divVar, "bc" }, + { &FWScript::o1_compareVar, "bc" }, + { &FWScript::o1_modifyObjectParam2, "bbb" }, + /* 10 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_loadMask0, "b" }, + /* 14 */ + { &FWScript::o1_unloadMask0, "b" }, + { &FWScript::o1_addToBgList, "b" }, + { &FWScript::o1_loadMask1, "b" }, + { &FWScript::o1_unloadMask1, "b" }, + /* 18 */ + { &FWScript::o1_loadMask4, "b" }, + { &FWScript::o1_unloadMask4, "b" }, + { &FWScript::o1_addSpriteFilledToBgList, "b" }, + { &FWScript::o1_op1B, "" }, + /* 1C */ + { 0, 0 }, + { &FWScript::o1_label, "l" }, + { &FWScript::o1_goto, "b" }, + { &FWScript::o1_gotoIfSup, "b" }, + /* 20 */ + { &FWScript::o1_gotoIfSupEqu, "b" }, + { &FWScript::o1_gotoIfInf, "b" }, + { &FWScript::o1_gotoIfInfEqu, "b" }, + { &FWScript::o1_gotoIfEqu, "b" }, + /* 24 */ + { &FWScript::o1_gotoIfDiff, "b" }, + { &FWScript::o1_removeLabel, "b" }, + { &FWScript::o1_loop, "bb" }, + { 0, 0 }, + /* 28 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 2C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 30 */ + { 0, 0 }, + { &FWScript::o1_startGlobalScript, "b" }, + { &FWScript::o1_endGlobalScript, "b" }, + { 0, 0 }, + /* 34 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 38 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_loadAnim, "s" }, + /* 3C */ + { &FWScript::o1_loadBg, "s" }, + { &FWScript::o1_loadCt, "s" }, + { 0, 0 }, + { &FWScript::o2_loadPart, "s" }, + /* 40 */ + { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */ + { &FWScript::o1_loadNewPrcName, "bs" }, + { &FWScript::o1_requestCheckPendingDataLoad, "" }, + { 0, 0 }, + /* 44 */ + { 0, 0 }, + { &FWScript::o1_blitAndFade, "" }, + { &FWScript::o1_fadeToBlack, "" }, + { &FWScript::o1_transformPaletteRange, "bbwww" }, + /* 48 */ + { 0, 0 }, + { &FWScript::o1_setDefaultMenuColor2, "b" }, + { &FWScript::o1_palRotate, "bbb" }, + { 0, 0 }, + /* 4C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_break, "" }, + /* 50 */ + { &FWScript::o1_endScript, "x" }, + { &FWScript::o1_message, "bwwww" }, + { &FWScript::o1_loadGlobalVar, "bc" }, + { &FWScript::o1_compareGlobalVar, "bc" }, + /* 54 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 58 */ + { 0, 0 }, + { &FWScript::o1_declareFunctionName, "s" }, + { &FWScript::o1_freePartRange, "bb" }, + { &FWScript::o1_unloadAllMasks, "" }, + // 5C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + /* 60 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o1_setScreenDimensions, "wwww" }, + /* 64 */ + { &FWScript::o1_displayBackground, "" }, + { &FWScript::o1_initializeZoneData, "" }, + { &FWScript::o1_setZoneDataEntry, "bw" }, + { &FWScript::o1_getZoneDataEntry, "bb" }, + /* 68 */ + { &FWScript::o1_setDefaultMenuColor, "b" }, + { &FWScript::o1_allowPlayerInput, "" }, + { &FWScript::o1_disallowPlayerInput, "" }, + { &FWScript::o1_changeDataDisk, "b" }, + /* 6C */ + { 0, 0 }, + { &FWScript::o1_loadMusic, "s" }, + { &FWScript::o1_playMusic, "" }, + { &FWScript::o1_fadeOutMusic, "" }, + /* 70 */ + { &FWScript::o1_stopSample, "" }, + { &FWScript::o1_op71, "bw" }, + { &FWScript::o1_op72, "wbw" }, + { &FWScript::o1_op72, "wbw" }, + /* 74 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_playSample, "bbwbww" }, + /* 78 */ + { &FWScript::o2_playSampleAlt, "bbwbww" }, + { &FWScript::o1_disableSystemMenu, "b" }, + { &FWScript::o1_loadMask5, "b" }, + { &FWScript::o1_unloadMask5, "b" }, + /* 7C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_addSeqListElement, "bbbbwww" }, + /* 80 */ + { &FWScript::o2_removeSeq, "bb" }, + { &FWScript::o2_op81, "" }, + { &FWScript::o2_op82, "bbw" }, + { &FWScript::o2_isSeqRunning, "bb" }, + /* 84 */ + { &FWScript::o2_gotoIfSupNearest, "b" }, + { &FWScript::o2_gotoIfSupEquNearest, "b" }, + { &FWScript::o2_gotoIfInfNearest, "b" }, + { &FWScript::o2_gotoIfInfEquNearest, "b" }, + /* 88 */ + { &FWScript::o2_gotoIfEquNearest, "b" }, + { &FWScript::o2_gotoIfDiffNearest, "b" }, + { 0, 0 }, + { &FWScript::o2_startObjectScript, "b" }, + /* 8C */ + { &FWScript::o2_stopObjectScript, "b" }, + { &FWScript::o2_op8D, "wwwwwwww" }, + { &FWScript::o2_addBackground, "bs" }, + { &FWScript::o2_removeBackground, "b" }, + /* 90 */ + { &FWScript::o2_loadAbs, "bs" }, + { &FWScript::o2_loadBg, "b" }, + { 0, 0 }, + { 0, 0 }, + /* 94 */ + { 0, 0 }, + { &FWScript::o1_changeDataDisk, "b" }, + { 0, 0 }, + { 0, 0 }, + /* 98 */ + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_wasZoneChecked, "" }, + { &FWScript::o2_op9B, "wwwwwwww" }, + /* 9C */ + { &FWScript::o2_op9C, "wwww" }, + { &FWScript::o2_useBgScroll, "b" }, + { &FWScript::o2_setAdditionalBgVScroll, "c" }, + { &FWScript::o2_op9F, "ww" }, + /* A0 */ + { &FWScript::o2_addGfxElementA0, "ww" }, + { &FWScript::o2_removeGfxElementA0, "ww" }, + { &FWScript::o2_opA2, "ww" }, + { &FWScript::o2_opA3, "ww" }, + /* A4 */ + { &FWScript::o2_loadMask22, "b" }, + { &FWScript::o2_unloadMask22, "b" }, + { 0, 0 }, + { 0, 0 }, + /* A8 */ + { 0, 0 }, + { &FWScript::o1_changeDataDisk, "b" } +}; +const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable); -const Opcode *_opcodeTable; -int _numOpcodes; +FWScriptInfo *scriptInfo; ///< Script factory +RawScriptArray scriptTable; ///< Table of script bytecode +/*! \todo: replace with script subsystem + */ void setupOpcodes() { - static const Opcode opcodeTableFW[] = { - /* 00 */ - { o1_modifyObjectParam, "bbw" }, - { o1_getObjectParam, "bbb" }, - { o1_addObjectParam, "bbw" }, - { o1_subObjectParam, "bbw" }, - /* 04 */ - { o1_add2ObjectParam, "bbw" }, - { o1_sub2ObjectParam, "bbw" }, - { o1_compareObjectParam, "bbw" }, - { o1_setupObject, "bwwww" }, - /* 08 */ - { o1_checkCollision, "bwwww" }, - { o1_loadVar, "bc" }, - { o1_addVar, "bc" }, - { o1_subVar, "bc" }, - /* 0C */ - { o1_mulVar, "bc" }, - { o1_divVar, "bc" }, - { o1_compareVar, "bc" }, - { o1_modifyObjectParam2, "bbb" }, - /* 10 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadMask0, "b" }, - /* 14 */ - { o1_unloadMask0, "b" }, - { o1_addToBgList, "b" }, - { o1_loadMask1, "b" }, - { o1_unloadMask1, "b" }, - /* 18 */ - { o1_loadMask4, "b" }, - { o1_unloadMask4, "b" }, - { o1_addSpriteFilledToBgList, "b" }, - { o1_op1B, "" }, - /* 1C */ - { 0, 0 }, - { o1_label, "l" }, - { o1_goto, "b" }, - { o1_gotoIfSup, "b" }, - /* 20 */ - { o1_gotoIfSupEqu, "b" }, - { o1_gotoIfInf, "b" }, - { o1_gotoIfInfEqu, "b" }, - { o1_gotoIfEqu, "b" }, - /* 24 */ - { o1_gotoIfDiff, "b" }, - { o1_removeLabel, "b" }, - { o1_loop, "bb" }, - { 0, 0 }, - /* 28 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 2C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 30 */ - { 0, 0 }, - { o1_startGlobalScript, "b" }, - { o1_endGlobalScript, "b" }, - { 0, 0 }, - /* 34 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 38 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadAnim, "s" }, - /* 3C */ - { o1_loadBg, "s" }, - { o1_loadCt, "s" }, - { 0, 0 }, - { o1_loadPart, "s" }, - /* 40 */ - { o1_closePart, "" }, - { o1_loadNewPrcName, "bs" }, - { o1_requestCheckPendingDataLoad, "" }, - { 0, 0 }, - /* 44 */ - { 0, 0 }, - { o1_blitAndFade, "" }, - { o1_fadeToBlack, "" }, - { o1_transformPaletteRange, "bbwww" }, - /* 48 */ - { 0, 0 }, - { o1_setDefaultMenuColor2, "b" }, - { o1_palRotate, "bbb" }, - { 0, 0 }, - /* 4C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_break, "" }, - /* 50 */ - { o1_endScript, "x" }, - { o1_message, "bwwww" }, - { o1_loadGlobalVar, "bc" }, - { o1_compareGlobalVar, "bc" }, - /* 54 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 58 */ - { 0, 0 }, - { o1_declareFunctionName, "s" }, - { o1_freePartRange, "bb" }, - { o1_unloadAllMasks, "" }, - // 5C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 60 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_setScreenDimensions, "wwww" }, - /* 64 */ - { o1_displayBackground, "" }, - { o1_initializeZoneData, "" }, - { o1_setZoneDataEntry, "bw" }, - { o1_getZoneDataEntry, "bb" }, - /* 68 */ - { o1_setDefaultMenuColor, "b" }, - { o1_allowPlayerInput, "" }, - { o1_disallowPlayerInput, "" }, - { o1_changeDataDisk, "b" }, - /* 6C */ - { 0, 0 }, - { o1_loadMusic, "s" }, - { o1_playMusic, "" }, - { o1_fadeOutMusic, "" }, - /* 70 */ - { o1_stopSample, "" }, - { o1_op71, "bw" }, - { o1_op72, "wbw" }, - { o1_op73, "wbw" }, - /* 74 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_playSample, "bbwbww" }, - /* 78 */ - { o1_playSample, "bbwbww" }, - { o1_disableSystemMenu, "b" }, - { o1_loadMask5, "b" }, - { o1_unloadMask5, "b" } - }; - - // TODO: We need to verify the Operation Stealth opcodes. - - static const Opcode opcodeTableOS[] = { - /* 00 */ - { o1_modifyObjectParam, "bbw" }, - { o1_getObjectParam, "bbb" }, - { o1_addObjectParam, "bbw" }, - { o1_subObjectParam, "bbw" }, - /* 04 */ - { o1_add2ObjectParam, "bbw" }, - { o1_sub2ObjectParam, "bbw" }, - { o1_compareObjectParam, "bbw" }, - { o1_setupObject, "bwwww" }, - /* 08 */ - { o1_checkCollision, "bwwww" }, - { o1_loadVar, "bc" }, - { o1_addVar, "bc" }, - { o1_subVar, "bc" }, - /* 0C */ - { o1_mulVar, "bc" }, - { o1_divVar, "bc" }, - { o1_compareVar, "bc" }, - { o1_modifyObjectParam2, "bbb" }, - /* 10 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadMask0, "b" }, - /* 14 */ - { o1_unloadMask0, "b" }, - { o1_addToBgList, "b" }, - { o1_loadMask1, "b" }, - { o1_unloadMask1, "b" }, - /* 18 */ - { o1_loadMask4, "b" }, - { o1_unloadMask4, "b" }, - { o1_addSpriteFilledToBgList, "b" }, - { o1_op1B, "" }, - /* 1C */ - { 0, 0 }, - { o1_label, "l" }, - { o1_goto, "b" }, - { o1_gotoIfSup, "b" }, - /* 20 */ - { o1_gotoIfSupEqu, "b" }, - { o1_gotoIfInf, "b" }, - { o1_gotoIfInfEqu, "b" }, - { o1_gotoIfEqu, "b" }, - /* 24 */ - { o1_gotoIfDiff, "b" }, - { o1_removeLabel, "b" }, - { o1_loop, "bb" }, - { 0, 0 }, - /* 28 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 2C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 30 */ - { 0, 0 }, - { o1_startGlobalScript, "b" }, - { o1_endGlobalScript, "b" }, - { 0, 0 }, - /* 34 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 38 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadAnim, "s" }, - /* 3C */ - { o1_loadBg, "s" }, - { o1_loadCt, "s" }, - { 0, 0 }, - { o2_loadPart, "s" }, - /* 40 */ - { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */ - { o1_loadNewPrcName, "bs" }, - { o1_requestCheckPendingDataLoad, "" }, - { 0, 0 }, - /* 44 */ - { 0, 0 }, - { o1_blitAndFade, "" }, - { o1_fadeToBlack, "" }, - { o1_transformPaletteRange, "bbwww" }, - /* 48 */ - { 0, 0 }, - { o1_setDefaultMenuColor2, "b" }, - { o1_palRotate, "bbb" }, - { 0, 0 }, - /* 4C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_break, "" }, - /* 50 */ - { o1_endScript, "x" }, - { o1_message, "bwwww" }, - { o1_loadGlobalVar, "bc" }, - { o1_compareGlobalVar, "bc" }, - /* 54 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 58 */ - { 0, 0 }, - { o1_declareFunctionName, "s" }, - { o1_freePartRange, "bb" }, - { o1_unloadAllMasks, "" }, - // 5C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 60 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_setScreenDimensions, "wwww" }, - /* 64 */ - { o1_displayBackground, "" }, - { o1_initializeZoneData, "" }, - { o1_setZoneDataEntry, "bw" }, - { o1_getZoneDataEntry, "bb" }, - /* 68 */ - { o1_setDefaultMenuColor, "b" }, - { o1_allowPlayerInput, "" }, - { o1_disallowPlayerInput, "" }, - { o1_changeDataDisk, "b" }, - /* 6C */ - { 0, 0 }, - { o1_loadMusic, "s" }, - { o1_playMusic, "" }, - { o1_fadeOutMusic, "" }, - /* 70 */ - { o1_stopSample, "" }, - { o1_op71, "bw" }, - { o1_op72, "wbw" }, - { o1_op72, "wbw" }, - /* 74 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o2_playSample, "bbwbww" }, - /* 78 */ - { o2_playSampleAlt, "bbwbww" }, - { o1_disableSystemMenu, "b" }, - { o1_loadMask5, "b" }, - { o1_unloadMask5, "b" }, - /* 7C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o2_addSeqListElement, "bbbbwww" }, - /* 80 */ - { o2_removeSeq, "bb" }, - { o2_op81, "" }, - { o2_op82, "bbw" }, - { o2_isSeqRunning, "bb" }, - /* 84 */ - { o2_gotoIfSupNearest, "b" }, - { o2_gotoIfSupEquNearest, "b" }, - { o2_gotoIfInfNearest, "b" }, - { o2_gotoIfInfEquNearest, "b" }, - /* 88 */ - { o2_gotoIfEquNearest, "b" }, - { o2_gotoIfDiffNearest, "b" }, - { 0, 0 }, - { o2_startObjectScript, "b" }, - /* 8C */ - { o2_stopObjectScript, "b" }, - { o2_op8D, "wwwwwwww" }, - { o2_addBackground, "bs" }, - { o2_removeBackground, "b" }, - /* 90 */ - { o2_loadAbs, "bs" }, - { o2_loadBg, "b" }, - { 0, 0 }, - { 0, 0 }, - /* 94 */ - { 0, 0 }, - { o1_changeDataDisk, "b" }, - { 0, 0 }, - { 0, 0 }, - /* 98 */ - { 0, 0 }, - { 0, 0 }, - { o2_wasZoneChecked, "" }, - { o2_op9B, "wwwwwwww" }, - /* 9C */ - { o2_op9C, "wwww" }, - { o2_useBgScroll, "b" }, - { o2_setAdditionalBgVScroll, "c" }, - { o2_op9F, "ww" }, - /* A0 */ - { o2_addGfxElementA0, "ww" }, - { o2_opA1, "ww" }, - { o2_opA2, "ww" }, - { o2_opA3, "ww" }, - /* A4 */ - { o2_loadMask22, "b" }, - { o2_unloadMask22, "b" }, - { 0, 0 }, - { 0, 0 }, - /* A8 */ - { 0, 0 }, - { o1_changeDataDisk, "b" } - }; - + static FWScriptInfo fw; + static OSScriptInfo os; if (g_cine->getGameType() == Cine::GType_FW) { - _opcodeTable = opcodeTableFW; - _numOpcodes = ARRAYSIZE(opcodeTableFW); + scriptInfo = &fw; } else { - _opcodeTable = opcodeTableOS; - _numOpcodes = ARRAYSIZE(opcodeTableOS); + scriptInfo = &os; } } -byte getNextByte() { - byte val = *(_currentScriptPtr + _currentPosition); - _currentPosition++; - return val; -} - -uint16 getNextWord() { - uint16 val = READ_BE_UINT16(_currentScriptPtr + _currentPosition); - _currentPosition += 2; - return val; -} - -const char *getNextString() { - const char *val = (const char *)(_currentScriptPtr + _currentPosition); - _currentPosition += strlen(val) + 1; - return val; -} - -// empty array +/*! \brief Allocate empty array + * \param len Size of array + * + * Explicit to prevent var=0 instead of var[i]=0 typos. + */ ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) { assert(_vars); reset(); } -// read game save, for later use +/*! \brief Allocate array and read contents from savefile + * \param fHandle Savefile open for reading + * \param len Size of array + */ ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len) : _size(len), _vars(new int16[len]) { @@ -468,16 +459,21 @@ ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len) load(fHandle); } -// copy constructor +/*! \brief Copy constructor + */ ScriptVars::ScriptVars(const ScriptVars &src) : _size(src._size), _vars(new int16[_size]) { assert(_vars); memcpy(_vars, src._vars, _size * sizeof(int16)); } +/*! \brief Destructor + */ ScriptVars::~ScriptVars(void) { delete[] _vars; } +/*! \brief Assignment operator + */ ScriptVars &ScriptVars::operator=(const ScriptVars &src) { ScriptVars tmp(src); int16 *tmpvars = _vars; @@ -489,462 +485,708 @@ ScriptVars &ScriptVars::operator=(const ScriptVars &src) { return *this; } -// array access +/*! \brief Direct array item access + * \param idx Item index + * \return Reference to item + */ int16 &ScriptVars::operator[](unsigned int idx) { - debugN(5, "assert(%d < %d)", idx, _size); + debug(6, "assert(%d < %d)", idx, _size); assert(idx < _size); return _vars[idx]; } +/*! \brief Direct read-only array item access + * \param idx Item index + * \return Copy of item + */ int16 ScriptVars::operator[](unsigned int idx) const { - debugN(5, "assert(%d < %d)\n", idx, _size); + debug(6, "assert(%d < %d)", idx, _size); assert(idx < _size); return _vars[idx]; } -// dump to savefile -void ScriptVars::save(Common::OutSaveFile &fHandle) { +/*! \brief Savefile writer + * \param fHandle Savefile open for writing + */ +void ScriptVars::save(Common::OutSaveFile &fHandle) const { save(fHandle, _size); } -// globalVars[255] is not written to savefiles... -void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) { - debugN(5, "assert(%d <= %d)\n", len, _size); +/*! \brief Savefile writer with data length limit + * \param fHandle Savefile open for writing + * \param len Length of data to be written (len <= _size) + */ +void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const { + debug(6, "assert(%d <= %d)", len, _size); assert(len <= _size); for (unsigned int i = 0; i < len; i++) { fHandle.writeUint16BE(_vars[i]); } } -// read from savefile +/*! \brief Restore array from savefile + * \param fHandle Savefile open for reading + */ void ScriptVars::load(Common::InSaveFile &fHandle) { load(fHandle, _size); } +/*! \brief Restore part of array from savefile + * \param fHandle Savefile open for reading + * \param len Length of data to be read + */ void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) { - debugN(5, "assert(%d <= %d)\n", len, _size); + debug(6, "assert(%d <= %d)", len, _size); assert(len <= _size); for (unsigned int i = 0; i < len; i++) { _vars[i] = fHandle.readUint16BE(); } } +/*! \brief Reset all values to 0 + */ void ScriptVars::reset(void) { memset( _vars, 0, _size * sizeof(int16)); } -void addGfxElementA0(int16 param1, int16 param2) { - overlayHeadElement *currentHead = &overlayHead; - overlayHeadElement *tempHead = currentHead; - overlayHeadElement *newElement; - - currentHead = tempHead->next; - - while (currentHead) { - if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) { - if (currentHead->type == 2 || currentHead->objIdx == 3) { - break; - } - } - - tempHead = currentHead; - currentHead = currentHead->next; - } - - if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2) - return; - - newElement = new overlayHeadElement; - - newElement->next = tempHead->next; - tempHead->next = newElement; - - newElement->objIdx = param1; - newElement->type = 20; - - newElement->x = param2; - newElement->y = 0; - newElement->width = 0; - newElement->color = 0; - - if (!currentHead) - currentHead = &overlayHead; +/*! \brief Constructor for partial loading + * \param s Size of bytecode which will be added later + * + * This constructor _MUST_ be followed by setdata() method call before the + * instance can be used. It leaves the instance in partially invalid state. + */ +RawScript::RawScript(uint16 s) : _size(s), _data(NULL), + _labels(SCRIPT_STACK_SIZE) { } - newElement->previous = currentHead->previous; +/*! \brief Complete constructor + * \param data Script bytecode + * \param s Bytecode length + */ +RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) : + _size(s), _data(NULL), _labels(SCRIPT_STACK_SIZE) { - currentHead->previous = newElement; + setData(info, data); } -void removeSeq(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } +/*! \brief Copy constructor + */ +RawScript::RawScript(const RawScript &src) : _size(src._size), + _data(new byte[_size+1]), _labels(src._labels) { - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - currentHead->var4 = -1; - } + assert(_data); + memcpy(_data, src._data, _size+1); } -uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } - - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - return 1; - } - - return 0; +/*! \brief Destructor + */ +RawScript::~RawScript(void) { + delete[] _data; } -ScriptStruct scriptTable[NUM_MAX_SCRIPT]; - -void stopGlobalScript(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \brief Assignment operator + */ +RawScript &RawScript::operator=(const RawScript &src) { + assert(src._data); + byte *tmp = new byte[src._size+1]; - currentHead = tempHead->next; + assert(tmp); + _labels = src._labels; + _size = src._size; - while (currentHead && (currentHead->scriptIdx != scriptIdx)) { - tempHead = currentHead; - currentHead = tempHead->next; - } + delete[] _data; + _data = tmp; + memcpy(_data, src._data, _size); + _data[_size] = 0; - if (!currentHead) { - return; - } + return *this; +} - if (currentHead->scriptIdx != scriptIdx) { - return; - } +/*! \brief Get the next label in bytecode + * \param info Script info instance + * \param offset Starting offset + * \return Index of the next label in bytecode or _size on end of bytecode + * + * computeScriptStackSub replacement + */ +int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const { + assert(_data); + int pos = offset; - currentHead->scriptIdx = -1; -} + assert(pos >= 0); -uint16 computeScriptStackSub(bool computeAllLabels, byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, byte labelIndex, uint16 startOffset) { - uint16 position; + while (pos < _size) { + uint8 opcode = _data[pos++]; + const char *ptr = info.opcodeInfo(opcode); - if (computeAllLabels) { - for (int i = 0; i < SCRIPT_STACK_SIZE; i++) { - stackPtr[i] = -1; - } - position = 0; - } else { - position = startOffset; - } - while (position < scriptSize) { - uint8 opcode = scriptPtr[position]; - position++; - if (opcode == 0 || opcode > _numOpcodes) { - continue; - } - if (!_opcodeTable[opcode - 1].args) { - warning("Undefined opcode 0x%02X in computeScriptStackSub", opcode - 1); + if (!ptr) { continue; } - for (const char *p = _opcodeTable[opcode - 1].args; *p; ++p) { - switch (*p) { + + for (; *ptr; ++ptr) { + switch (*ptr) { case 'b': // byte - position++; + pos++; break; case 'w': // word - position += 2; + pos += 2; break; case 'c': { // byte != 0 ? byte : word - uint8 test = scriptPtr[position]; - position++; + uint8 test = _data[pos]; + pos++; if (test) { - position++; + pos++; } else { - position += 2; - } - } - break; - case 'l': { // label - uint8 index = scriptPtr[position]; - position++; - if (computeAllLabels) { - stackPtr[index] = position; - } else { - if (labelIndex == index) { - return position; - } + pos += 2; } } break; + case 'l': // label + return pos; case 's': // string - while (scriptPtr[position++] != 0); + while (_data[pos++] != 0); break; case 'x': // exit script - return position; + return -pos-1; } } } - return position; + return _size; } -void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) { - computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0); -} +/*! \brief Calculate initial script labels + * \param info Script info instance + * + * computeScriptStack replacement + */ +void RawScript::computeLabels(const FWScriptInfo &info) { + assert(_data); + int pos = 0; + int i; + + // reset labels + for (i = 0; i < SCRIPT_STACK_SIZE; i++) { + _labels[i] = -1; + } -uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) { - return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition); + // parse bytecode + while ((pos = getNextLabel(info, pos)) >= 0) { + i = _data[pos]; + _labels[i] = ++pos; + } } -void palRotate(byte a, byte b, byte c) { - if (c == 1) { - uint16 currentColor = c_palette[b]; +/*! \brief find the next label from current position + * \param info Script info instance + * \param index Label index to look for + * \param offset Current position in script + * \return Position of next instruction following the label + * + * computeScriptStackFromScript replacement + */ +uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset) + const { - for (int16 i = b; i > a; i--) { - c_palette[i] = c_palette[i - 1]; - } + assert(_data); + int pos = offset; - c_palette[a] = currentColor; + while ((pos = getNextLabel(info, pos)) >= 0) { + if (_data[pos++] == index) { + return pos; + } } + + return -pos - 1; } -void addScriptToList0(uint16 idx) { - uint16 i; - prcLinkedListStruct *pNewElement; - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \brief Copy bytecode and calculate labels + * \param data Bytecode to copy, must be _size long + */ +void RawScript::setData(const FWScriptInfo &info, const byte *data) { + assert(!_data); // this function should be called only once per instance + _data = new byte[_size+1]; - assert(idx <= NUM_MAX_SCRIPT); + assert(data && _data); + memcpy(_data, data, _size * sizeof(byte)); + _data[_size] = 0; - currentHead = tempHead->next; + computeLabels(info); +} - while (currentHead) { - tempHead = currentHead; +/*! \brief Initial script labels + * \return Precalculated script labels + */ +const ScriptVars &RawScript::labels(void) const { + assert(_data); + return _labels; +} - assert(tempHead); +/*! \brief One byte of bytecode + * \param pos Index in bytecode + * \return Byte from bytecode + */ +byte RawScript::getByte(unsigned int pos) const { + assert(_data && pos < _size); - currentHead = tempHead->next; - } + return _data[pos]; +} - pNewElement = new prcLinkedListStruct; +/*! \brief One word of bytecode + * \param pos Index of the first byte in bytecode + * \return Word of bytecode + */ +uint16 RawScript::getWord(unsigned int pos) const { + assert(_data && pos+1 < _size); - assert(pNewElement); + return READ_BE_UINT16(_data + pos); +} - pNewElement->next = tempHead->next; - tempHead->next = pNewElement; +/*! \brief String in bytecode + * \param pos Index of the first char in string + * \return Pointer to part of bytecode + */ +const char *RawScript::getString(unsigned int pos) const { + assert(_data && pos < _size); - // copy the stack into the script instance - for (i = 0; i < SCRIPT_STACK_SIZE; i++) { - pNewElement->stack[i] = scriptTable[idx].stack[i]; - } + return (const char*)(_data+pos); +} - pNewElement->compareResult = 0; - pNewElement->scriptPosition = 0; +/*! \brief Constructor for partial loading + * \param size Size of bytecode which will be added later + * \param p1 First object script parameter + * \param p2 Second object script parameter + * \param p3 Third object script parameter + * + * This constructor _MUST_ be followed by setdata() method call before the + * instance can be used. It leaves the instance in partially invalid state. + */ +RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3) + : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3) +{ } + +/*! \brief Complete constructor + * \param data Script bytecode + * \param s Bytecode length + * \param p1 First object script parameter + * \param p2 Second object script parameter + * \param p3 Third object script parameter + */ +RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data, + uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s), + _runCount(0), _param1(p1), _param2(p2), _param3(p3) { } - pNewElement->scriptPtr = scriptTable[idx].ptr; - pNewElement->scriptIdx = idx; -} +/*! \brief Contructor for global scripts + * \param script Script bytecode reference + * \param idx Script bytecode index + */ +FWScript::FWScript(const RawScript &script, int16 idx) : _script(script), + _pos(0), _line(0), _compare(0), _index(idx), + _labels(script.labels()), _localVars(LOCAL_VARS_SIZE), + _globalVars(globalVars), _info(new FWScriptInfo) { } -int16 endScript0(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \brief Copy constructor + */ +FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos), + _line(src._line), _compare(src._compare), _index(src._index), + _labels(src._labels), _localVars(src._localVars), + _globalVars(src._globalVars), _info(new FWScriptInfo) { } + +/*! \brief Contructor for global scripts in derived classes + * \param script Script bytecode reference + * \param idx Script bytecode index + */ +FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) : + _script(script), _pos(0), _line(0), _compare(0), _index(idx), + _labels(script.labels()), _localVars(LOCAL_VARS_SIZE), + _globalVars(globalVars), _info(info) { } + +/*! \brief Constructor for object scripts in derived classes + * \param script Script bytecode reference + * \param idx Script bytecode index + */ +FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) : + _script(script), _pos(0), _line(0), _compare(0), _index(idx), + _labels(script.labels()), _localVars(LOCAL_VARS_SIZE), + _globalVars(globalVars), _info(info) { - //assert(scriptIdx <= NUM_MAX_SCRIPT); + _localVars[0] = script.run(); +} - currentHead = tempHead->next; +/*! \brief Copy constructor for derived classes + */ +FWScript::FWScript(const FWScript &src, FWScriptInfo *info) : + _script(src._script), _pos(src._pos), _line(src._line), + _compare(src._compare), _index(src._index), _labels(src._labels), + _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { } - while (currentHead && currentHead->scriptIdx != scriptIdx) { - tempHead = currentHead; - currentHead = tempHead->next; - } +FWScript::~FWScript(void) { + delete _info; +} - if (!currentHead) { - return -1; - } +/*! \brief Read next byte from bytecode + * \return Byte from bytecode + */ +byte FWScript::getNextByte() { + byte val = _script.getByte(_pos); + _pos++; + return val; +} - if (currentHead->scriptIdx != scriptIdx) { - return -1; - } +/*! \brief Read next word from bytecode + * \return Word from bytecode + */ +uint16 FWScript::getNextWord() { + uint16 val = _script.getWord(_pos); + _pos += 2; + return val; +} - currentHead->scriptIdx = -1; +/*! \brief Read next string from bytecode + * \return Pointer to string + */ +const char *FWScript::getNextString() { + const char *val = _script.getString(_pos); + _pos += strlen(val) + 1; + return val; +} - return 0; +/*! \brief Restore script state from savefile + * \param labels Restored script labels + * \param local Restored local script variables + * \param compare Restored last comparison result + * \param pos Restored script position + */ +void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) { + assert(pos < _script._size); + _labels = labels; + _localVars = local; + _compare = compare; + _pos = _line = pos; } -int16 endScript1(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &objScriptList; - prcLinkedListStruct *tempHead = currentHead; +/*! \brief Execute script + * \return <0 on script termination, >0 on script pause + * + * executeScript replacement. + * Instruction handler must return 0 if the script should continue or + * nonzero with the same meaning as return value of this function + */ +int FWScript::execute() { + int ret = 0; - currentHead = tempHead->next; + while (!ret) { + _line = _pos; + byte opcode = getNextByte(); + opFunc handler = _info->opcodeHandler(opcode); - while (currentHead && currentHead->scriptIdx != scriptIdx) { - tempHead = currentHead; - currentHead = tempHead->next; + if (handler) { + ret = (this->*handler)(); + } } - if (!currentHead) { - return -1; - } + return ret; +} - if (currentHead->scriptIdx != scriptIdx) { - return -1; +/*! \brief Save script to savefile + * \param fHandle Savefile handle + */ +void FWScript::save(Common::OutSaveFile &fHandle) const { + _labels.save(fHandle); + _localVars.save(fHandle); + fHandle.writeUint16BE(_compare); + fHandle.writeUint16BE(_pos); + // data order sucks... + fHandle.writeUint16BE(_index); +} + +/*! \brief Contructor for global scripts + * \param script Script bytecode reference + * \param idx Script bytecode index + */ +OSScript::OSScript(const RawScript &script, int16 idx) : + FWScript(script, idx, new OSScriptInfo) {} + +/*! \brief Constructor for object scripts + * \param script Script bytecode reference + * \param idx Script bytecode index + */ +OSScript::OSScript(RawObjectScript &script, int16 idx) : + FWScript(script, idx, new OSScriptInfo) {} + +/*! \brief Copy constructor + */ +OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {} + +/*! \brief Restore script state from savefile + * \param labels Restored script labels + * \param local Restored local script variables + * \param compare Restored last comparison result + * \param pos Restored script position + */ +void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) { + FWScript::load(labels, local, compare, pos); +} +/*! \brief Get opcode info string + * \param opcode Opcode to look for in opcode table + */ +const char *FWScriptInfo::opcodeInfo(byte opcode) const { + if (opcode == 0 || opcode > FWScript::_numOpcodes) { + return NULL; } - currentHead->scriptIdx = -1; + if (!FWScript::_opcodeTable[opcode - 1].args) { + warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1); + return NULL; + } - return 0; + return FWScript::_opcodeTable[opcode - 1].args; } -int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) { - byte *ptr = page + (y * width) + x / 2; - byte zoneVar; +/*! \brief Get opcode handler pointer + * \param opcode Opcode to look for in opcode table + */ +opFunc FWScriptInfo::opcodeHandler(byte opcode) const { + if (opcode == 0 || opcode > FWScript::_numOpcodes) { + return NULL; + } - if (!(x % 2)) { - zoneVar = (*(ptr) >> 4) & 0xF; - } else { - zoneVar = (*(ptr)) & 0xF; + if (!FWScript::_opcodeTable[opcode - 1].proc) { + warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1); + return NULL; } - return zoneVar; + return FWScript::_opcodeTable[opcode - 1].proc; } -int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { - byte *ptr = page + (y * width) + x; - byte zoneVar; +/*! \brief Create new FWScript instance + * \param script Script bytecode + * \param index Bytecode index + */ +FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const { + return new FWScript(script, index); +} - zoneVar = (*(ptr)) & 0xF; +/*! \brief Create new FWScript instance + * \param script Object script bytecode + * \param index Bytecode index + */ +FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const { + return new FWScript(script, index); +} - return zoneVar; +/*! \brief Load saved FWScript instance + * \param script Script bytecode + * \param index Bytecode index + * \param local Local variables + * \param labels Script labels + * \param compare Last compare result + * \param pos Position in script + */ +FWScript *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const { + FWScript *tmp = new FWScript(script, index); + assert(tmp); + tmp->load(labels, local, compare, pos); + return tmp; +} + +/*! \brief Load saved FWScript instance + * \param script Object script bytecode + * \param index Bytecode index + * \param local Local variables + * \param labels Script labels + * \param compare Last compare result + * \param pos Position in script + */ +FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const { + FWScript *tmp = new FWScript(script, index); + assert(tmp); + tmp->load(labels, local, compare, pos); + return tmp; } -int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) { - int16 lx = objectTable[objIdx].x + x; - int16 ly = objectTable[objIdx].y + y; - int16 idx; +/*! \brief Get opcode info string + * \param opcode Opcode to look for in opcode table + */ +const char *OSScriptInfo::opcodeInfo(byte opcode) const { + if (opcode == 0 || opcode > OSScript::_numOpcodes) { + return NULL; + } - for (int16 i = 0; i < numZones; i++) { - idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); + if (!OSScript::_opcodeTable[opcode - 1].args) { + warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1); + return NULL; + } - assert(idx >= 0 && idx <= NUM_MAX_ZONE); + return OSScript::_opcodeTable[opcode - 1].args; +} - if (zoneData[idx] == zoneIdx) { - return 1; - } +/*! \brief Get opcode handler pointer + * \param opcode Opcode to look for in opcode table + */ +opFunc OSScriptInfo::opcodeHandler(byte opcode) const { + if (opcode == 0 || opcode > OSScript::_numOpcodes) { + return NULL; } - return 0; + if (!OSScript::_opcodeTable[opcode - 1].proc) { + warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1); + return NULL; + } + + return OSScript::_opcodeTable[opcode - 1].proc; } -uint16 compareVars(int16 a, int16 b) { - uint16 flag = 0; +/*! \brief Create new OSScript instance + * \param script Script bytecode + * \param index Bytecode index + */ +FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const { + return new OSScript(script, index); +} - if (a == b) { - flag |= kCmpEQ; - } else if (a > b) { - flag |= kCmpGT; - } else if (a < b) { - flag |= kCmpLT; - } +/*! \brief Create new OSScript instance + * \param script Object script bytecode + * \param index Bytecode index + */ +FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const { + return new OSScript(script, index); +} - return flag; +/*! \brief Load saved OSScript instance + * \param script Script bytecode + * \param index Bytecode index + * \param local Local variables + * \param labels Script labels + * \param compare Last compare result + * \param pos Position in script + */ +FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const { + OSScript *tmp = new OSScript(script, index); + assert(tmp); + tmp->load(labels, local, compare, pos); + return tmp; +} + +/*! \brief Load saved OSScript instance + * \param script Object script bytecode + * \param index Bytecode index + * \param local Local variables + * \param labels Script labels + * \param compare Last compare result + * \param pos Position in script + */ +FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const { + OSScript *tmp = new OSScript(script, index); + assert(tmp); + tmp->load(labels, local, compare, pos); + return tmp; } // ------------------------------------------------------------------------ // FUTURE WARS opcodes // ------------------------------------------------------------------------ -void o1_modifyObjectParam() { +int FWScript::o1_modifyObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); modifyObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_getObjectParam() { +int FWScript::o1_getObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); byte newValue = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue); - _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx); + _localVars[newValue] = getObjectParam(objIdx, paramIdx); + return 0; } -void o1_addObjectParam() { +int FWScript::o1_addObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); addObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_subObjectParam() { +int FWScript::o1_subObjectParam() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); int16 newValue = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); subObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_add2ObjectParam() { - getNextByte(); - getNextByte(); - getNextWord(); - warning("STUB: o1_add2ObjectParam()"); +/*! \todo Implement this instruction + */ +int FWScript::o1_add2ObjectParam() { + uint16 a = getNextByte(); + uint16 b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c); + return 0; } -void o1_sub2ObjectParam() { - getNextByte(); - getNextByte(); - getNextWord(); - warning("STUB: o1_sub2ObjectParam()"); +/*! \todo Implement this instruction + */ +int FWScript::o1_sub2ObjectParam() { + uint16 a = getNextByte(); + uint16 b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c); + return 0; } -void o1_compareObjectParam() { +int FWScript::o1_compareObjectParam() { byte objIdx = getNextByte(); byte param1 = getNextByte(); int16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2); - _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2); + _compare = compareObjectParam(objIdx, param1, param2); + return 0; } -void o1_setupObject() { +int FWScript::o1_setupObject() { byte objIdx = getNextByte(); int16 param1 = getNextWord(); int16 param2 = getNextWord(); int16 param3 = getNextWord(); int16 param4 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4); + debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4); setupObject(objIdx, param1, param2, param3, param4); + return 0; } -void o1_checkCollision() { +int FWScript::o1_checkCollision() { byte objIdx = getNextByte(); int16 param1 = getNextWord(); int16 param2 = getNextWord(); int16 param3 = getNextWord(); int16 param4 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4); + debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4); - _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4); + _compare = checkCollision(objIdx, param1, param2, param3, param4); + return 0; } -void o1_loadVar() { +int FWScript::o1_loadVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); @@ -954,34 +1196,34 @@ void o1_loadVar() { switch (varType) { case 1: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx]; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] = _localVars[dataIdx]; break; case 2: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = globalVars[dataIdx]; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] = _globalVars[dataIdx]; break; case 3: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _currentLine, varIdx); - getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, (uint16 *)&dummyU16); - _currentScriptElement->localVars[varIdx] = var; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx); + getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16); + _localVars[varIdx] = var; break; case 4: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _currentLine, varIdx); - getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&dummyU16, (uint16 *)&var); - _currentScriptElement->localVars[varIdx] = var; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx); + getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var); + _localVars[varIdx] = var; break; case 5: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1); + debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx); + _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1); break; case 8: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx); + _localVars[varIdx] = partBuffer[dataIdx].packedSize; break; case 9: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx); + _localVars[varIdx] = partBuffer[dataIdx].unpackedSize; break; default: error("executeScript: o1_loadVar: Unknown variable type %d", varType); @@ -989,352 +1231,413 @@ void o1_loadVar() { } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] = value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value); + _localVars[varIdx] = value; } + + return 0; } -void o1_addVar() { +int FWScript::o1_addVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx]; + if (varType == 1) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] += _localVars[dataIdx]; + } else if (varType == 2) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] += _globalVars[dataIdx]; + } } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] += value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value); + _localVars[varIdx] += value; } + + return 0; } -void o1_subVar() { +int FWScript::o1_subVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx]; + if (varType == 1) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] -= _localVars[dataIdx]; + } else if (varType == 2) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] -= _globalVars[dataIdx]; + } + } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] -= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value); + _localVars[varIdx] -= value; } + + return 0; } -void o1_mulVar() { +int FWScript::o1_mulVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx]; + if (varType == 1) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] *= _localVars[dataIdx]; + } else if (varType == 2) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] *= _globalVars[dataIdx]; + } } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] *= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value); + _localVars[varIdx] *= value; } + + return 0; } -void o1_divVar() { +int FWScript::o1_divVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx]; + if (varType == 1) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] /= _localVars[dataIdx]; + } else if (varType == 2) { + debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx); + _localVars[varIdx] /= _globalVars[dataIdx]; + } } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] /= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value); + _localVars[varIdx] /= value; } + + return 0; } -void o1_compareVar() { +int FWScript::o1_compareVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - // printf("Val: %d\n", dataIdx); - if (varType == 1) { - assert(varIdx < 50); - assert(dataIdx < 50); - - debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], _currentScriptElement->localVars[dataIdx]); + debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx); + _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]); } else if (varType == 2) { - assert(varIdx < 50); - - debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], globalVars[dataIdx]); + debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx); + _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]); } } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value); + debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value); + _compare = compareVars(_localVars[varIdx], value); } + + return 0; } -void o1_modifyObjectParam2() { +int FWScript::o1_modifyObjectParam2() { byte objIdx = getNextByte(); byte paramIdx = getNextByte(); byte newValue = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue); - modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]); + modifyObjectParam(objIdx, paramIdx, _localVars[newValue]); + return 0; } -void o1_loadMask0() { +int FWScript::o1_loadMask0() { // OP_loadV7Element byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param); loadOverlayElement(param, 0); + return 0; } -void o1_unloadMask0() { +int FWScript::o1_unloadMask0() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param); freeOverlay(param, 0); + return 0; } -void o1_addToBgList() { +int FWScript::o1_addToBgList() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param); addToBGList(param); + return 0; } -void o1_loadMask1() { +int FWScript::o1_loadMask1() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param); loadOverlayElement(param, 1); + return 0; } -void o1_unloadMask1() { +int FWScript::o1_unloadMask1() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param); freeOverlay(param, 1); + return 0; } -void o1_loadMask4() { +int FWScript::o1_loadMask4() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param); loadOverlayElement(param, 4); + return 0; } -void o1_unloadMask4() { +int FWScript::o1_unloadMask4() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param); freeOverlay(param, 4); + return 0; } -void o1_addSpriteFilledToBgList() { +int FWScript::o1_addSpriteFilledToBgList() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param); addSpriteFilledToBGList(param); + return 0; } -void o1_op1B() { - debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine); - freeBgIncrustList(); +int FWScript::o1_op1B() { + debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line); + bgIncrustList.clear(); + return 0; } -void o1_label() { +int FWScript::o1_label() { byte labelIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx); - _currentScriptElement->stack[labelIdx] = _currentPosition; + debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx); + _labels[labelIdx] = _pos; + return 0; } -void o1_goto() { +int FWScript::o1_goto() { byte labelIdx = getNextByte(); - assert(_currentScriptElement->stack[labelIdx] != -1); + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx); + _pos = _labels[labelIdx]; + return 0; } -void o1_gotoIfSup() { +int FWScript::o1_gotoIfSup() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpGT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpGT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfSupEqu() { +int FWScript::o1_gotoIfSupEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpGT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfInf() { +int FWScript::o1_gotoIfInf() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpLT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpLT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfInfEqu() { +int FWScript::o1_gotoIfInfEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpLT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfEqu() { +int FWScript::o1_gotoIfEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfDiff() { +int FWScript::o1_gotoIfDiff() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult != kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare != kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_removeLabel() { +int FWScript::o1_removeLabel() { byte labelIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx); - _currentScriptElement->stack[labelIdx] = -1; + debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx); + _labels[labelIdx] = -1; + return 0; } -void o1_loop() { +int FWScript::o1_loop() { byte varIdx = getNextByte(); byte labelIdx = getNextByte(); - _currentScriptElement->localVars[varIdx]--; + _localVars[varIdx]--; - if (_currentScriptElement->localVars[varIdx] >= 0) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_localVars[varIdx] >= 0) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx); } + return 0; } -void o1_startGlobalScript() { +int FWScript::o1_startGlobalScript() { // OP_startScript byte param = getNextByte(); assert(param < NUM_MAX_SCRIPT); - debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param); addScriptToList0(param); + return 0; } -void o1_endGlobalScript() { +int FWScript::o1_endGlobalScript() { byte scriptIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx); - stopGlobalScript(scriptIdx); + debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx); + + ScriptList::iterator it = globalScripts.begin(); + + for (; it != globalScripts.end(); ++it) { + if ((*it)->_index == scriptIdx) { + (*it)->_index = -1; + } + } + + return 0; } -void o1_loadAnim() { +int FWScript::o1_loadAnim() { // OP_loadResource const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param); loadResource(param); + return 0; } -void o1_loadBg() { +int FWScript::o1_loadBg() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param); loadBg(param); - freeBgIncrustList(); + bgIncrustList.clear(); bgVar0 = 0; + return 0; } -void o1_loadCt() { +int FWScript::o1_loadCt() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param); loadCt(param); + return 0; } -void o1_loadPart() { +int FWScript::o1_loadPart() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param); loadPart(param); + return 0; } -void o1_closePart() { - debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine); +int FWScript::o1_closePart() { + debugC(5, kCineDebugScript, "Line: %d: closePart", _line); closePart(); + return 0; } -void o1_loadNewPrcName() { +int FWScript::o1_loadNewPrcName() { // OP_loadData byte param1 = getNextByte(); const char *param2 = getNextString(); @@ -1343,104 +1646,113 @@ void o1_loadNewPrcName() { switch (param1) { case 0: - debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2); strcpy(newPrcName, param2); break; case 1: - debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2); strcpy(newRelName, param2); break; case 2: - debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2); strcpy(newObjectName, param2); break; case 3: - debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2); strcpy(newMsgName, param2); break; } + return 0; } -void o1_requestCheckPendingDataLoad() { - debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine); +int FWScript::o1_requestCheckPendingDataLoad() { + debugC(5, kCineDebugScript, "Line: %d: request data load", _line); checkForPendingDataLoadSwitch = 1; + return 0; } -void o1_blitAndFade() { - debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine); +int FWScript::o1_blitAndFade() { + debugC(5, kCineDebugScript, "Line: %d: request fadein", _line); // TODO: use real code drawOverlays(); fadeRequired = true; flip(); + +// fadeFromBlack(); + return 0; } -void o1_fadeToBlack() { - debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine); +int FWScript::o1_fadeToBlack() { + debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line); fadeToBlack(); + return 0; } -void o1_transformPaletteRange() { +int FWScript::o1_transformPaletteRange() { byte startColor = getNextByte(); byte numColor = getNextByte(); uint16 r = getNextWord(); uint16 g = getNextWord(); uint16 b = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _currentLine, startColor, numColor, r, g, b); + debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b); transformPaletteRange(startColor, numColor, r, g, b); + return 0; } -void o1_setDefaultMenuColor2() { +int FWScript::o1_setDefaultMenuColor2() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param); defaultMenuBoxColor2 = param; + return 0; } -void o1_palRotate() { +int FWScript::o1_palRotate() { byte a = getNextByte(); byte b = getNextByte(); byte c = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c); + debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c); palRotate(a, b, c); + return 0; } -void o1_break() { - debugC(5, kCineDebugScript, "Line: %d: break", _currentLine); +/*!\brief Pause script + * \todo Make sure it works + */ +int FWScript::o1_break() { + debugC(5, kCineDebugScript, "Line: %d: break", _line); - _currentScriptElement->scriptPosition = _currentPosition; - _closeScript = 1; + return 1; } -void o1_endScript() { - debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine); - - if (_currentScriptParams == 0) { - endScript0(_currentScriptElement->scriptIdx); - } else { - endScript1(_currentScriptElement->scriptIdx); - } +/*! \brief Terminate script + * \todo Make sure it works + */ +int FWScript::o1_endScript() { + debugC(5, kCineDebugScript, "Line: %d: endScript", _line); - _closeScript = 1; + return -1; } -void o1_message() { +int FWScript::o1_message() { byte param1 = getNextByte(); uint16 param2 = getNextWord(); uint16 param3 = getNextWord(); uint16 param4 = getNextWord(); uint16 param5 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5); + debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5); addMessage(param1, param2, param3, param4, param5); + return 0; } -void o1_loadGlobalVar() { +int FWScript::o1_loadGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); @@ -1448,169 +1760,207 @@ void o1_loadGlobalVar() { byte dataIdx = getNextByte(); if (varType == 1) { - debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx); - globalVars[varIdx] = _currentScriptElement->localVars[dataIdx]; + debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx); + _globalVars[varIdx] = _localVars[dataIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx); - globalVars[varIdx] = globalVars[dataIdx]; + debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx); + _globalVars[varIdx] = _globalVars[dataIdx]; } } else { uint16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value); - globalVars[varIdx] = value; + debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value); + _globalVars[varIdx] = value; } + + return 0; } -void o1_compareGlobalVar() { +int FWScript::o1_compareGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte value = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value); - _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]); + if (varType == 1) { + debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value); + _compare = compareVars(_globalVars[varIdx], _localVars[value]); + } else { + debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and globalVars[%d]", _line, varIdx, value); + _compare = compareVars(_globalVars[varIdx], _globalVars[value]); + } } else { uint16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value); + debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value); if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix - _currentScriptElement->compareResult = 1; + _compare = 1; } else { - _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value); + _compare = compareVars(_globalVars[varIdx], value); } } + + return 0; } -void o1_declareFunctionName() { +int FWScript::o1_declareFunctionName() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param); + return 0; } -void o1_freePartRange() { +int FWScript::o1_freePartRange() { byte startIdx = getNextByte(); byte numIdx = getNextByte(); assert(startIdx + numIdx <= NUM_MAX_ANIMDATA); - debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx); + debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx); freeAnimDataRange(startIdx, numIdx); + return 0; } -void o1_unloadAllMasks() { - debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine); +int FWScript::o1_unloadAllMasks() { + debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line); unloadAllMasks(); + return 0; } -void o1_setScreenDimensions() { - warning("STUB: o1_setScreenDimensions()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o1_setScreenDimensions() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + uint16 c = getNextWord(); + uint16 d = getNextWord(); + warning("STUB: o1_setScreenDimensions(%x, %x, %x, %x)", a, b, c, d); // setupScreenParam + return 0; } -void o1_displayBackground() { +/*! \todo Implement this instruction + */ +int FWScript::o1_displayBackground() { warning("STUB: o1_displayBackground()"); + return 0; } -void o1_initializeZoneData() { - debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine); +int FWScript::o1_initializeZoneData() { + debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line); for (int i = 0; i < NUM_MAX_ZONE; i++) { zoneData[i] = i; } + return 0; } -void o1_setZoneDataEntry() { +int FWScript::o1_setZoneDataEntry() { byte zoneIdx = getNextByte(); uint16 var = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var); + debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var); zoneData[zoneIdx] = var; + return 0; } -void o1_getZoneDataEntry() { +int FWScript::o1_getZoneDataEntry() { byte zoneIdx = getNextByte(); byte var = getNextByte(); - _currentScriptElement->localVars[var] = zoneData[zoneIdx]; + _localVars[var] = zoneData[zoneIdx]; + return 0; } -void o1_setDefaultMenuColor() { +int FWScript::o1_setDefaultMenuColor() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param); defaultMenuBoxColor = param; + return 0; } -void o1_allowPlayerInput() { - debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine); +int FWScript::o1_allowPlayerInput() { + debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line); allowPlayerInput = 1; + return 0; } -void o1_disallowPlayerInput() { - debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine); +int FWScript::o1_disallowPlayerInput() { + debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line); allowPlayerInput = 0; + return 0; } -void o1_changeDataDisk() { +int FWScript::o1_changeDataDisk() { byte newDisk = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk); + debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk); checkDataDisk(newDisk); + return 0; } -void o1_loadMusic() { +int FWScript::o1_loadMusic() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param); g_sound->loadMusic(param); + return 0; } -void o1_playMusic() { - debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine); +int FWScript::o1_playMusic() { + debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line); g_sound->playMusic(); + return 0; } -void o1_fadeOutMusic() { - debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine); +int FWScript::o1_fadeOutMusic() { + debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line); g_sound->fadeOutMusic(); + return 0; } -void o1_stopSample() { - debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine); +int FWScript::o1_stopSample() { + debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line); g_sound->stopMusic(); + return 0; } -void o1_op71() { - warning("STUB: o1_op71()"); - getNextByte(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o1_op71() { + byte a = getNextByte(); + uint16 b = getNextWord(); + warning("STUB: o1_op71(%x, %x)", a, b); + return 0; } -void o1_op72() { - warning("STUB: o1_op72()"); - getNextWord(); - getNextByte(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o1_op72() { + uint16 a = getNextWord(); + byte b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o1_op72(%x, %x, %x)", a, b, c); + return 0; } -void o1_op73() { +/*! \todo Implement this instruction + */ +int FWScript::o1_op73() { // I believe this opcode is identical to o1_op72(). In fact, Operation // Stealth doesn't even have it. It uses o1_op72() instead. - warning("STUB: o1_op73()"); - getNextWord(); - getNextByte(); - getNextWord(); + uint16 a = getNextWord(); + byte b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o1_op72(%x, %x, %x)", a, b, c); + return 0; } -void o1_playSample() { - debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine); +int FWScript::o1_playSample() { + debugC(5, kCineDebugScript, "Line: %d: playSample()", _line); byte anim = getNextByte(); byte channel = getNextByte(); @@ -1621,13 +1971,15 @@ void o1_playSample() { int16 volume = getNextWord(); uint16 size = getNextWord(); - if (!animDataTable[anim].ptr1) { - return; + const byte *data = animDataTable[anim].data(); + + if (!data) { + return 0; } if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) { if (size == 0xFFFF) { - size = animDataTable[anim].width * animDataTable[anim].height; + size = animDataTable[anim]._width * animDataTable[anim]._height; } if (channel < 10) { // || _currentOpcode == 0x78 int channel1, channel2; @@ -1638,14 +1990,14 @@ void o1_playSample() { channel1 = 2; channel2 = 3; } - g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat); - g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size, 1, volume, 0, repeat); + g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat); + g_sound->playSound(channel2, freq, data, size, 1, volume, 0, repeat); } else { channel -= 10; if (volume > 63) { volume = 63; } - g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat); + g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat); } } else { if (volume > 63 || volume < 0) { @@ -1658,49 +2010,54 @@ void o1_playSample() { volume = 50; } if (g_cine->getGameType() == Cine::GType_OS && size == 0) { - return; + return 0; } g_sound->stopMusic(); if (size == 0xFFFF) { - g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0); + g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0); } else { g_sound->stopSound(channel); } } + return 0; } -void o1_disableSystemMenu() { +int FWScript::o1_disableSystemMenu() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param); disableSystemMenu = (param != 0); + return 0; } -void o1_loadMask5() { +int FWScript::o1_loadMask5() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param); loadOverlayElement(param, 5); + return 0; } -void o1_unloadMask5() { +int FWScript::o1_unloadMask5() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param); freeOverlay(param, 5); + return 0; } // ------------------------------------------------------------------------ // OPERATION STEALTH opcodes // ------------------------------------------------------------------------ -void o2_loadPart() { +int FWScript::o2_loadPart() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param); + return 0; } -void o2_playSample() { +int FWScript::o2_playSample() { if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) { // no-op in these versions getNextByte(); @@ -1709,12 +2066,12 @@ void o2_playSample() { getNextByte(); getNextWord(); getNextWord(); - return; + return 0; } - o1_playSample(); + return o1_playSample(); } -void o2_playSampleAlt() { +int FWScript::o2_playSampleAlt() { byte num = getNextByte(); byte channel = getNextByte(); uint16 frequency = getNextWord(); @@ -1723,21 +2080,22 @@ void o2_playSampleAlt() { uint16 size = getNextWord(); if (size == 0xFFFF) { - size = animDataTable[num].width * animDataTable[num].height; + size = animDataTable[num]._width * animDataTable[num]._height; } - if (animDataTable[num].ptr1) { + if (animDataTable[num].data()) { if (g_cine->getPlatform() == Common::kPlatformPC) { // if speaker output is available, play sound on it // if it's another device, don't play anything // TODO: implement this, it's used in the introduction for example // on each letter displayed } else { - g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0); + g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0); } } + return 0; } -void o2_addSeqListElement() { +int FWScript::o2_addSeqListElement() { byte param1 = getNextByte(); byte param2 = getNextByte(); byte param3 = getNextByte(); @@ -1746,162 +2104,201 @@ void o2_addSeqListElement() { uint16 param6 = getNextWord(); uint16 param7 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7); + debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7); addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7); + return 0; } -void o2_removeSeq() { +int FWScript::o2_removeSeq() { byte a = getNextByte(); byte b = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b); + debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b); removeSeq(a, 0, b); + return 0; } -void o2_op81() { +/*! \todo Implement this instruction + */ +int FWScript::o2_op81() { warning("STUB: o2_op81()"); // freeUnkList(); + return 0; } -void o2_op82() { - warning("STUB: o2_op82()"); - getNextByte(); - getNextByte(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op82() { + byte a = getNextByte(); + byte b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o2_op82(%x, %x, %x)", a, b, c); + return 0; } -void o2_isSeqRunning() { +int FWScript::o2_isSeqRunning() { byte a = getNextByte(); byte b = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b); + debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b); if (isSeqRunning(a, 0, b)) { - _currentScriptElement->compareResult = 1; + _compare = 1; } else { - _currentScriptElement->compareResult = 0; + _compare = 0; } + return 0; } -void o2_gotoIfSupNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfSupNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpGT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpGT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfSupEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfSupEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpGT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfInfNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfInfNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpLT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpLT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfInfEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfInfEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpLT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfDiffNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfDiffNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult != kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare != kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx); + _pos = _script.getLabel(*_info, labelIdx, _pos); } else { - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_startObjectScript() { +int FWScript::o2_startObjectScript() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param); runObjectScript(param); + return 0; } -void o2_stopObjectScript() { +int FWScript::o2_stopObjectScript() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param); - stopObjectScript(param); + debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param); + ScriptList::iterator it = objectScripts.begin(); + + for (; it != objectScripts.end(); ++it) { + if ((*it)->_index == param) { + (*it)->_index = -1; + } + } + return 0; } -void o2_op8D() { - warning("STUB: o2_op8D()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op8D() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + uint16 c = getNextWord(); + uint16 d = getNextWord(); + uint16 e = getNextWord(); + uint16 f = getNextWord(); + uint16 g = getNextWord(); + uint16 h = getNextWord(); + warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h); // _currentScriptElement->compareResult = ... + return 0; } -void o2_addBackground() { +int FWScript::o2_addBackground() { byte param1 = getNextByte(); const char *param2 = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1); + debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1); addBackground(param2, param1); + return 0; } -void o2_removeBackground() { +int FWScript::o2_removeBackground() { byte param = getNextByte(); assert(param); - debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param); if (additionalBgTable[param]) { free(additionalBgTable[param]); @@ -1917,192 +2314,358 @@ void o2_removeBackground() { } strcpy(currentBgName[param], ""); + return 0; } -void o2_loadAbs() { +int FWScript::o2_loadAbs() { byte param1 = getNextByte(); const char *param2 = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2); loadAbs(param2, param1); + return 0; } -void o2_loadBg() { +int FWScript::o2_loadBg() { byte param = getNextByte(); assert(param <= 8); - debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param); if (additionalBgTable[param]) { currentAdditionalBgIdx = param; + if (param == 8) { + newColorMode = 3; + } else { + newColorMode = bgColorMode + 1; + } //if (_screenNeedFadeOut == 0) { // adBgVar1 = 1; //} fadeRequired = true; } + return 0; } -void o2_wasZoneChecked() { +/*! \todo Implement this instruction + */ +int FWScript::o2_wasZoneChecked() { warning("STUB: o2_wasZoneChecked()"); + return 0; } -void o2_op9B() { - warning("STUB: o2_op9B()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op9B() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + uint16 c = getNextWord(); + uint16 d = getNextWord(); + uint16 e = getNextWord(); + uint16 f = getNextWord(); + uint16 g = getNextWord(); + uint16 h = getNextWord(); + warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h); + return 0; } -void o2_op9C() { - warning("STUB: o2_op9C()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op9C() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + uint16 c = getNextWord(); + uint16 d = getNextWord(); + warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d); + return 0; } -void o2_useBgScroll() { +int FWScript::o2_useBgScroll() { byte param = getNextByte(); assert(param <= 8); - debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param); if (additionalBgTable[param]) { currentAdditionalBgIdx2 = param; } + return 0; } -void o2_setAdditionalBgVScroll() { +int FWScript::o2_setAdditionalBgVScroll() { byte param1 = getNextByte(); if (param1) { byte param2 = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2); - additionalBgVScroll = _currentScriptElement->localVars[param2]; + debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2); + additionalBgVScroll = _localVars[param2]; } else { uint16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2); additionalBgVScroll = param2; } + return 0; } -void o2_op9F() { +/*! \todo Implement this instruction + */ +int FWScript::o2_op9F() { warning("o2_op9F()"); getNextWord(); getNextWord(); + return 0; } -void o2_addGfxElementA0() { +int FWScript::o2_addGfxElementA0() { uint16 param1 = getNextWord(); uint16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2); addGfxElementA0(param1, param2); + return 0; } -void o2_opA1() { - warning("STUB: o2_opA1()"); - getNextWord(); - getNextWord(); - // removeGfxElementA0( ... ); +/*! \todo Implement this instruction + */ +int FWScript::o2_removeGfxElementA0() { + uint16 idx = getNextWord(); + uint16 param = getNextWord(); + warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param); + removeGfxElementA0(idx, param); + return 0; } -void o2_opA2() { - warning("STUB: o2_opA2()"); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_opA2() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + warning("STUB: o2_opA2(%x, %x)", a, b); // addGfxElementA2(); + return 0; } -void o2_opA3() { - warning("STUB: o2_opA3()"); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_opA3() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + warning("STUB: o2_opA3(%x, %x)", a, b); // removeGfxElementA2(); + return 0; } -void o2_loadMask22() { +int FWScript::o2_loadMask22() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param); loadOverlayElement(param, 22); + return 0; } -void o2_unloadMask22() { +int FWScript::o2_unloadMask22() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param); freeOverlay(param, 22); + return 0; } -// ------------------------------------------------------------------------ +//----------------------------------------------------------------------- + +void addGfxElementA0(int16 param1, int16 param2) { + overlayHeadElement *currentHead = &overlayHead; + overlayHeadElement *tempHead = currentHead; + overlayHeadElement *newElement; + + currentHead = tempHead->next; + + while (currentHead) { + if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) { + if (currentHead->type == 2 || currentHead->objIdx == 3) { + break; + } + } -void executeScript(prcLinkedListStruct *scriptElement, uint16 params) { - assert(scriptElement); + tempHead = currentHead; + currentHead = currentHead->next; + } - if (scriptElement->scriptIdx == -1) { + if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2) return; + + newElement = new overlayHeadElement; + + newElement->next = tempHead->next; + tempHead->next = newElement; + + newElement->objIdx = param1; + newElement->type = 20; + + newElement->x = param2; + newElement->y = 0; + newElement->width = 0; + newElement->color = 0; + + if (!currentHead) + currentHead = &overlayHead; + + newElement->previous = currentHead->previous; + + currentHead->previous = newElement; +} + +/*! \todo Check that it works + */ +void removeGfxElementA0(int16 idx, int16 param) { + overlayHeadElement *parent = &overlayHead; + overlayHeadElement *head = overlayHead.next; + overlayHeadElement *tmp; + + while (head) { + if (head->objIdx == idx && head->x == param) { + parent->next = head->next; + tmp = head->next ? head->next : &overlayHead; + tmp->previous = parent; + delete head; + return; + } + + parent = head; + head = head->next; } +} - assert(scriptElement->scriptPtr); +void removeSeq(uint16 param1, uint16 param2, uint16 param3) { + SeqListElement *currentHead = &seqList; + SeqListElement *tempHead = currentHead; - _currentScriptElement = scriptElement; - _currentScriptParams = params; - _currentScriptPtr = scriptElement->scriptPtr; - _currentPosition = scriptElement->scriptPosition; + while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { + tempHead = currentHead; + currentHead = tempHead->next; + } - _closeScript = 0; + if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { + currentHead->var4 = -1; + } +} - while (!_closeScript) { - _currentLine = _currentPosition; +uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { + SeqListElement *currentHead = &seqList; + SeqListElement *tempHead = currentHead; - byte opcode = getNextByte(); + while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { + tempHead = currentHead; + currentHead = tempHead->next; + } + + if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { + return 1; + } - if (opcode && opcode < _numOpcodes) { - if (_opcodeTable[opcode - 1].proc) - (_opcodeTable[opcode - 1].proc) (); - else - warning("Undefined opcode 0x%02X in executeScript", opcode - 1); + return 0; +} + +void palRotate(byte a, byte b, byte c) { + if (c == 1) { + uint16 currentColor = c_palette[b]; + + for (int16 i = b; i > a; i--) { + c_palette[i] = c_palette[i - 1]; } + + c_palette[a] = currentColor; } } -void executeList1(void) { - prcLinkedListStruct *currentHead = objScriptList.next; +void addScriptToList0(uint16 idx) { + ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx)); + assert(tmp); + globalScripts.push_back(tmp); +} - while (currentHead) { - prcLinkedListStruct *tempHead; +int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) { + byte *ptr = page + (y * width) + x / 2; + byte zoneVar; + + if (!(x % 2)) { + zoneVar = (*(ptr) >> 4) & 0xF; + } else { + zoneVar = (*(ptr)) & 0xF; + } + + return zoneVar; +} + +int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { + byte *ptr = page + (y * width) + x; + byte zoneVar; + + zoneVar = (*(ptr)) & 0xF; + + return zoneVar; +} + +int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) { + int16 lx = objectTable[objIdx].x + x; + int16 ly = objectTable[objIdx].y + y; + int16 idx; - tempHead = currentHead->next; + for (int16 i = 0; i < numZones; i++) { + idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); - executeScript(currentHead, 1); + assert(idx >= 0 && idx <= NUM_MAX_ZONE); - currentHead = tempHead; + if (zoneData[idx] == zoneIdx) { + return 1; + } } + + return 0; } -void executeList0(void) { - prcLinkedListStruct *currentHead = globalScriptsHead.next; +uint16 compareVars(int16 a, int16 b) { + uint16 flag = 0; - while (currentHead) { - prcLinkedListStruct *tempHead; + if (a == b) { + flag |= kCmpEQ; + } else if (a > b) { + flag |= kCmpGT; + } else if (a < b) { + flag |= kCmpLT; + } - executeScript(currentHead, 0); + return flag; +} + +void executeList1(void) { + ScriptList::iterator it = objectScripts.begin(); + for (; it != objectScripts.end();) { + if ((*it)->_index < 0 || (*it)->execute() < 0) { + it = objectScripts.erase(it); + } else { + ++it; + } + } +} - tempHead = currentHead->next; - currentHead = tempHead; +void executeList0(void) { + ScriptList::iterator it = globalScripts.begin(); + for (; it != globalScripts.end();) { + if ((*it)->_index < 0 || (*it)->execute() < 0) { + it = globalScripts.erase(it); + } else { + ++it; + } } } +/*! \todo objectScripts.clear()? + */ void purgeList1(void) { } @@ -2463,7 +3026,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 } case 0x1B: { - sprintf(lineBuffer, "freeBgIncrustList()\n"); + sprintf(lineBuffer, "bgIncrustList.clear()\n"); break; } case 0x1D: @@ -2804,7 +3367,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "disallowPlayerInput()\n"); break; } - case OP_changeDataDisk: + case 0x6B: { byte newDisk; @@ -2878,7 +3441,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 if (opcode - 1 == 0x77) { sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6); - else if (opcode - 1 == 0x78) { + } else if (opcode - 1 == 0x78) { sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6); } diff --git a/engines/cine/script.h b/engines/cine/script.h index b6f3c79219..4bcf4b6ccb 100644 --- a/engines/cine/script.h +++ b/engines/cine/script.h @@ -27,17 +27,39 @@ #define CINE_SCRIPT_H #include "common/savefile.h" +#include "common/array.h" +#include "common/list.h" +#include "common/ptr.h" namespace Cine { #define SCRIPT_STACK_SIZE 50 +#define LOCAL_VARS_SIZE 50 +/*! \brief Fixed size array of script variables. + * + * Array size can be set in constructors, once the instance is created, + * it cannot be changed directly. + */ + +class FWScript; + +typedef int (FWScript::*opFunc)(); + +struct Opcode { + opFunc proc; + const char *args; +}; + +/*! \brief Fixed size array for script variables + */ class ScriptVars { private: - unsigned int _size; - int16 *_vars; + unsigned int _size; ///< Size of array + int16 *_vars; ///< Variable values public: + // Explicit to prevent var=0 instead of var[i]=0 typos. explicit ScriptVars(unsigned int len = 50); ScriptVars(Common::InSaveFile &fHandle, unsigned int len = 50); ScriptVars(const ScriptVars &src); @@ -47,26 +69,298 @@ public: int16 &operator[](unsigned int idx); int16 operator[](unsigned int idx) const; - void save(Common::OutSaveFile &fHandle); - void save(Common::OutSaveFile &fHandle, unsigned int len); + void save(Common::OutSaveFile &fHandle) const; + void save(Common::OutSaveFile &fHandle, unsigned int len) const; void load(Common::InSaveFile &fHandle); void load(Common::InSaveFile &fHandle, unsigned int len); void reset(void); }; -struct ScriptStruct { - byte *ptr; - uint16 size; - int16 stack[SCRIPT_STACK_SIZE]; +class FWScriptInfo; + +/*! \brief Script bytecode and initial labels, ScriptStruct replacement. + * + * _data is one byte longer to make sure strings in bytecode are properly + * terminated + */ +class RawScript { +private: + byte *_data; ///< Script bytecode + ScriptVars _labels; ///< Initial script labels + +protected: + void computeLabels(const FWScriptInfo &info); + int getNextLabel(const FWScriptInfo &info, int offset) const; + +public: + uint16 _size; ///< Bytecode length + + explicit RawScript(uint16 size); + RawScript(const FWScriptInfo &info, const byte *data, uint16 size); + RawScript(const RawScript &src); + ~RawScript(void); + + RawScript &operator=(const RawScript &src); + + void setData(const FWScriptInfo &info, const byte *data); + /*! \brief Size of script + * \return Size of script + */ + const ScriptVars &labels(void) const; + byte getByte(unsigned int pos) const; + uint16 getWord(unsigned int pos) const; + const char *getString(unsigned int pos) const; + uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const; +}; + +/*! \brief Object script class, RelObjectScript replacement + * + * Script parameters are not used, this class is required by different + * script initialization of object scripts + */ +class RawObjectScript : public RawScript { +public: + int16 _runCount; ///< How many times the script was used + uint16 _param1; ///< Additional parameter not used at the moment + uint16 _param2; ///< Additional parameter not used at the moment + uint16 _param3; ///< Additional parameter not used at the moment + + RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3); + RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3); + + /// \brief Run the script one more time + /// \return Run count before incrementation + int16 run(void) { return _runCount++; } }; +/*! \brief Future Wars script, prcLinkedListStruct replacement + * \todo Rewrite _globalVars initialization + */ +class FWScript { +private: + const RawScript &_script; ///< Script bytecode reference + uint16 _pos; ///< Current position in script + uint16 _line; ///< Current opcode index in bytecode for debugging + uint16 _compare; ///< Last compare result + ScriptVars _labels; ///< Current script labels + ScriptVars _localVars; ///< Local script variables + ScriptVars &_globalVars; ///< Global variables reference + FWScriptInfo *_info; ///< Script info + + static const Opcode _opcodeTable[]; + static const unsigned int _numOpcodes; + +protected: + int o1_modifyObjectParam(); + int o1_getObjectParam(); + int o1_addObjectParam(); + int o1_subObjectParam(); + int o1_add2ObjectParam(); + int o1_sub2ObjectParam(); + int o1_compareObjectParam(); + int o1_setupObject(); + int o1_checkCollision(); + int o1_loadVar(); + int o1_addVar(); + int o1_subVar(); + int o1_mulVar(); + int o1_divVar(); + int o1_compareVar(); + int o1_modifyObjectParam2(); + int o1_loadMask0(); + int o1_unloadMask0(); + int o1_addToBgList(); + int o1_loadMask1(); + int o1_unloadMask1(); + int o1_loadMask4(); + int o1_unloadMask4(); + int o1_addSpriteFilledToBgList(); + int o1_op1B(); + int o1_label(); + int o1_goto(); + int o1_gotoIfSup(); + int o1_gotoIfSupEqu(); + int o1_gotoIfInf(); + int o1_gotoIfInfEqu(); + int o1_gotoIfEqu(); + int o1_gotoIfDiff(); + int o1_removeLabel(); + int o1_loop(); + int o1_startGlobalScript(); + int o1_endGlobalScript(); + int o1_loadAnim(); + int o1_loadBg(); + int o1_loadCt(); + int o1_loadPart(); + int o1_closePart(); + int o1_loadNewPrcName(); + int o1_requestCheckPendingDataLoad(); + int o1_blitAndFade(); + int o1_fadeToBlack(); + int o1_transformPaletteRange(); + int o1_setDefaultMenuColor2(); + int o1_palRotate(); + int o1_break(); + int o1_endScript(); + int o1_message(); + int o1_loadGlobalVar(); + int o1_compareGlobalVar(); + int o1_declareFunctionName(); + int o1_freePartRange(); + int o1_unloadAllMasks(); + int o1_setScreenDimensions(); + int o1_displayBackground(); + int o1_initializeZoneData(); + int o1_setZoneDataEntry(); + int o1_getZoneDataEntry(); + int o1_setDefaultMenuColor(); + int o1_allowPlayerInput(); + int o1_disallowPlayerInput(); + int o1_changeDataDisk(); + int o1_loadMusic(); + int o1_playMusic(); + int o1_fadeOutMusic(); + int o1_stopSample(); + int o1_op71(); + int o1_op72(); + int o1_op73(); + int o1_playSample(); + int o1_disableSystemMenu(); + int o1_loadMask5(); + int o1_unloadMask5(); + + // pointers to member functions in C++ suck... + int o2_loadPart(); + int o2_addSeqListElement(); + int o2_removeSeq(); + int o2_playSample(); + int o2_playSampleAlt(); + int o2_op81(); + int o2_op82(); + int o2_isSeqRunning(); + int o2_gotoIfSupNearest(); + int o2_gotoIfSupEquNearest(); + int o2_gotoIfInfNearest(); + int o2_gotoIfInfEquNearest(); + int o2_gotoIfEquNearest(); + int o2_gotoIfDiffNearest(); + int o2_startObjectScript(); + int o2_stopObjectScript(); + int o2_op8D(); + int o2_addBackground(); + int o2_removeBackground(); + int o2_loadAbs(); + int o2_loadBg(); + int o2_wasZoneChecked(); + int o2_op9B(); + int o2_op9C(); + int o2_useBgScroll(); + int o2_setAdditionalBgVScroll(); + int o2_op9F(); + int o2_addGfxElementA0(); + int o2_removeGfxElementA0(); + int o2_opA2(); + int o2_opA3(); + int o2_loadMask22(); + int o2_unloadMask22(); + + byte getNextByte(); + uint16 getNextWord(); + const char *getNextString(); + + void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos); + + FWScript(const RawScript &script, int16 index, FWScriptInfo *info); + FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info); + FWScript(const FWScript &src, FWScriptInfo *info); + +public: + int16 _index; ///< Index in script table + + FWScript(const RawScript &script, int16 index); +// FWScript(const RawObjectScript &script, int16 index); + FWScript(const FWScript &src); + ~FWScript(void); + + int execute(); + void save(Common::OutSaveFile &fHandle) const; + + friend class FWScriptInfo; + + // workaround for bug in g++ which prevents protected member functions + // of FWScript from being used in OSScript::_opcodeTable[] + // initialization ("error: protected within this context") + friend class OSScript; +}; + +/*! \brief Operation Stealth script, prcLinkedListStruct replacement + */ +class OSScript : public FWScript { +private: + static const Opcode _opcodeTable[]; + static const unsigned int _numOpcodes; + +protected: + void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos); + +public: + OSScript(const RawScript &script, int16 index); + OSScript(RawObjectScript &script, int16 index); + OSScript(const OSScript &src); + + friend class OSScriptInfo; +}; + +/*! \brief Future Wars script factory and info + */ +class FWScriptInfo { +protected: + virtual opFunc opcodeHandler(byte opcode) const; + +public: + virtual ~FWScriptInfo() {} + + virtual const char *opcodeInfo(byte opcode) const; + virtual FWScript *create(const RawScript &script, int16 index) const; + virtual FWScript *create(const RawObjectScript &script, int16 index) const; + virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; + virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; + + friend class FWScript; +}; + +/*! \brief Operation Stealth script factory and info + */ +class OSScriptInfo : public FWScriptInfo { +protected: + virtual opFunc opcodeHandler(byte opcode) const; + +public: + virtual ~OSScriptInfo() {} + + virtual const char *opcodeInfo(byte opcode) const; + virtual FWScript *create(const RawScript &script, int16 index) const; + virtual FWScript *create(const RawObjectScript &script, int16 index) const; + virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; + virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; + + friend class FWScript; +}; + +typedef Common::SharedPtr ScriptPtr; +typedef Common::SharedPtr RawScriptPtr; +typedef Common::SharedPtr RawObjectScriptPtr; +typedef Common::List ScriptList; +typedef Common::Array RawScriptArray; +typedef Common::Array RawObjectScriptArray; + #define NUM_MAX_SCRIPT 50 -extern ScriptStruct scriptTable[NUM_MAX_SCRIPT]; +extern RawScriptArray scriptTable; +extern FWScriptInfo *scriptInfo; void setupOpcodes(); -void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize); void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx); void dumpScript(char *dumpName); @@ -79,7 +373,6 @@ void addScriptToList0(uint16 idx); int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx); void runObjectScript(int16 entryIdx); -int16 stopObjectScript(int16 entryIdx); void executeList1(void); void executeList0(void); @@ -87,119 +380,6 @@ void executeList0(void); void purgeList1(void); void purgeList0(void); -void o1_modifyObjectParam(); -void o1_getObjectParam(); -void o1_addObjectParam(); -void o1_subObjectParam(); -void o1_add2ObjectParam(); -void o1_sub2ObjectParam(); -void o1_compareObjectParam(); -void o1_setupObject(); -void o1_checkCollision(); -void o1_loadVar(); -void o1_addVar(); -void o1_subVar(); -void o1_mulVar(); -void o1_divVar(); -void o1_compareVar(); -void o1_modifyObjectParam2(); -void o1_loadMask0(); -void o1_unloadMask0(); -void o1_addToBgList(); -void o1_loadMask1(); -void o1_unloadMask1(); -void o1_loadMask4(); -void o1_unloadMask4(); -void o1_addSpriteFilledToBgList(); -void o1_op1B(); -void o1_label(); -void o1_goto(); -void o1_gotoIfSup(); -void o1_gotoIfSupEqu(); -void o1_gotoIfInf(); -void o1_gotoIfInfEqu(); -void o1_gotoIfEqu(); -void o1_gotoIfDiff(); -void o1_removeLabel(); -void o1_loop(); -void o1_startGlobalScript(); -void o1_endGlobalScript(); -void o1_loadAnim(); -void o1_loadBg(); -void o1_loadCt(); -void o1_loadPart(); -void o1_closePart(); -void o1_loadNewPrcName(); -void o1_requestCheckPendingDataLoad(); -void o1_blitAndFade(); -void o1_fadeToBlack(); -void o1_transformPaletteRange(); -void o1_setDefaultMenuColor2(); -void o1_palRotate(); -void o1_break(); -void o1_endScript(); -void o1_message(); -void o1_loadGlobalVar(); -void o1_compareGlobalVar(); -void o1_declareFunctionName(); -void o1_freePartRange(); -void o1_unloadAllMasks(); -void o1_setScreenDimensions(); -void o1_displayBackground(); -void o1_initializeZoneData(); -void o1_setZoneDataEntry(); -void o1_getZoneDataEntry(); -void o1_setDefaultMenuColor(); -void o1_allowPlayerInput(); -void o1_disallowPlayerInput(); -void o1_changeDataDisk(); -void o1_loadMusic(); -void o1_playMusic(); -void o1_fadeOutMusic(); -void o1_stopSample(); -void o1_op71(); -void o1_op72(); -void o1_op73(); -void o1_playSample(); -void o1_playSample(); -void o1_disableSystemMenu(); -void o1_loadMask5(); -void o1_unloadMask5(); - -void o2_loadPart(); -void o2_addSeqListElement(); -void o2_removeSeq(); -void o2_playSample(); -void o2_playSampleAlt(); -void o2_op81(); -void o2_op82(); -void o2_isSeqRunning(); -void o2_gotoIfSupNearest(); -void o2_gotoIfSupEquNearest(); -void o2_gotoIfInfNearest(); -void o2_gotoIfInfEquNearest(); -void o2_gotoIfEquNearest(); -void o2_gotoIfDiffNearest(); -void o2_startObjectScript(); -void o2_stopObjectScript(); -void o2_op8D(); -void o2_addBackground(); -void o2_removeBackground(); -void o2_loadAbs(); -void o2_loadBg(); -void o2_wasZoneChecked(); -void o2_op9B(); -void o2_op9C(); -void o2_useBgScroll(); -void o2_setAdditionalBgVScroll(); -void o2_op9F(); -void o2_addGfxElementA0(); -void o2_opA1(); -void o2_opA2(); -void o2_opA3(); -void o2_loadMask22(); -void o2_unloadMask22(); - } // End of namespace Cine #endif diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp index 7f303a1b79..e808de6922 100644 --- a/engines/cine/sound.cpp +++ b/engines/cine/sound.cpp @@ -602,9 +602,9 @@ bool PCSoundFxPlayer::load(const char *song) { for (int i = 0; i < NUM_INSTRUMENTS; ++i) { _instrumentsData[i] = NULL; - char instrument[13]; + char instrument[64]; memcpy(instrument, _sfxData + 20 + i * 30, 12); - instrument[12] = '\0'; + instrument[63] = '\0'; if (strlen(instrument) != 0) { char *dot = strrchr(instrument, '.'); diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp index 066eab48e3..e41626cad1 100644 --- a/engines/cine/texte.cpp +++ b/engines/cine/texte.cpp @@ -40,7 +40,7 @@ const CommandeType *confirmMenu; const char **otherMessages; const char *commandPrepositionOn; -void generateMask(byte *sprite, byte *mask, uint16 size, byte transparency); +void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency); void loadTextData(const char *pFileName, byte *pDestinationBuffer) { Common::File pFileHandle; diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 50846f7321..38c5677569 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -124,64 +124,10 @@ void stopMusicAfterFadeOut(void) { // } } -int16 stopObjectScript(int16 entryIdx) { - prcLinkedListStruct *currentHead = &objScriptList; - prcLinkedListStruct *tempHead = currentHead; - - currentHead = tempHead->next; - - while (currentHead) { - if (currentHead->scriptIdx == entryIdx) { - currentHead->scriptIdx = -1; - return 0; - } - - currentHead = currentHead->next; - } - - return -1; -} - void runObjectScript(int16 entryIdx) { - uint16 i; - prcLinkedListStruct *pNewElement; - prcLinkedListStruct *currentHead = &objScriptList; - prcLinkedListStruct *tempHead = currentHead; - - currentHead = tempHead->next; - - while (currentHead) { - tempHead = currentHead; - - assert(tempHead); - - currentHead = tempHead->next; - } - - pNewElement = new prcLinkedListStruct; - - assert(pNewElement); - - pNewElement->next = tempHead->next; - tempHead->next = pNewElement; - - // copy the stack into the script instance - for (i = 0; i < SCRIPT_STACK_SIZE; i++) { - pNewElement->stack[i] = 0; - } - - pNewElement->compareResult = 0; - pNewElement->scriptPosition = 0; - - pNewElement->scriptPtr = (byte *)relTable[entryIdx].data; - pNewElement->scriptIdx = entryIdx; - - if (g_cine->getGameType() == Cine::GType_OS) { - pNewElement->localVars[0] = relTable[entryIdx].runCount; - ++relTable[entryIdx].runCount; - } - - computeScriptStack(pNewElement->scriptPtr, pNewElement->stack, relTable[entryIdx].size); + ScriptPtr tmp(scriptInfo->create(*relTable[entryIdx], entryIdx)); + assert(tmp); + objectScripts.push_back(tmp); } void addPlayerCommandMessage(int16 cmd) { @@ -214,30 +160,31 @@ void addPlayerCommandMessage(int16 cmd) { int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) { int16 i; - int16 di = -1; + int16 found = -1; - for (i = 0; i < NUM_MAX_REL; i++) { - if (relTable[i].data && relTable[i].obj1Param1 == param1 && relTable[i].obj1Param2 == pSelectedObject->idx) { + for (i = 0; i < (int16)relTable.size(); i++) { + if (relTable[i]->_param1 == param1 && relTable[i]->_param2 == pSelectedObject->idx) { if (param2 == 1) { - di = i; + found = i; } else if (param2 == 2) { - if (relTable[i].obj2Param == pSelectedObject->param) { - di = i; + if (relTable[i]->_param3 == pSelectedObject->param) { + found = i; } } } - if (di != -1) + if (found != -1) break; } - return di; + return found; } int16 getObjectUnderCursor(uint16 x, uint16 y) { overlayHeadElement *currentHead = overlayHead.previous; int16 objX, objY, frame, part, threshold, height, xdif, ydif; + int width; while (currentHead) { if (currentHead->type < 2) { @@ -250,27 +197,29 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) { part = objectTable[currentHead->objIdx].part; if (currentHead->type == 0) { - threshold = animDataTable[frame].var1; + threshold = animDataTable[frame]._var1; } else { - threshold = animDataTable[frame].width / 2; + threshold = animDataTable[frame]._width / 2; } - height = animDataTable[frame].height; + height = animDataTable[frame]._height; + width = animDataTable[frame]._realWidth; xdif = x - objX; ydif = y - objY; if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) { - if (animDataTable[frame].ptr1) { - if (g_cine->getGameType() == Cine::GType_OS) - return currentHead->objIdx; - - if (currentHead->type == 0) { // use generated mask - if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr2, animDataTable[frame].width)) { + if (animDataTable[frame].data()) { + if (g_cine->getGameType() == Cine::GType_OS) { + if(xdif < width && (currentHead->type == 1 || animDataTable[frame].getColor(xdif, ydif) != objectTable[currentHead->objIdx].part)) { + return currentHead->objIdx; + } + } else if (currentHead->type == 0) { // use generated mask + if (gfxGetBit(x - objX, y - objY, animDataTable[frame].mask(), animDataTable[frame]._width)) { return currentHead->objIdx; } } else if (currentHead->type == 1) { // is mask - if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr1, animDataTable[frame].width * 4)) { + if (gfxGetBit(x - objX, y - objY, animDataTable[frame].data(), animDataTable[frame]._width * 4)) { return currentHead->objIdx; } } @@ -302,38 +251,38 @@ bool CineEngine::loadSaveDirectory(void) { return true; } +/*! \brief Restore script list item from savefile + * \param fHandle Savefile handlem open for reading + * \param isGlobal Restore object or global script? + */ void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) { - int16 i; + ScriptVars localVars, labels; + uint16 compare, pos; + int16 idx; - prcLinkedListStruct *newElement; - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; + labels.load(*fHandle); + localVars.load(*fHandle); - currentHead = tempHead->next; + compare = fHandle->readUint16BE(); + pos = fHandle->readUint16BE(); + idx = fHandle->readUint16BE(); - while (currentHead) { - tempHead = currentHead; - currentHead = tempHead->next; + // no way to reinitialize these + if (idx < 0) { + return; } - newElement = new prcLinkedListStruct; - - newElement->next = tempHead->next; - tempHead->next = newElement; - - for (i = 0; i < SCRIPT_STACK_SIZE; i++) - newElement->stack[i] = fHandle->readUint16BE(); - - newElement->localVars.load(*fHandle); - - newElement->compareResult = fHandle->readUint16BE(); - newElement->scriptPosition = fHandle->readUint16BE(); - newElement->scriptIdx = fHandle->readUint16BE(); - - if (isGlobal) - newElement->scriptPtr = scriptTable[newElement->scriptIdx].ptr; - else - newElement->scriptPtr = (byte *)relTable[newElement->scriptIdx].data; + // original code loaded everything into globalScripts, this should be + // the correct behavior + if (isGlobal) { + ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx, labels, localVars, compare, pos)); + assert(tmp); + globalScripts.push_back(tmp); + } else { + ScriptPtr tmp(scriptInfo->create(*relTable[idx], idx, labels, localVars, compare, pos)); + assert(tmp); + objectScripts.push_back(tmp); + } } void loadOverlayFromSave(Common::InSaveFile *fHandle) { @@ -370,26 +319,106 @@ void loadOverlayFromSave(Common::InSaveFile *fHandle) { currentHead->previous = newElement; } -void setupScriptList(bool isGlobal) { - prcLinkedListStruct *currentHead; - - if (isGlobal) - currentHead = globalScriptsHead.next; - else - currentHead = objScriptList.next; - - while (currentHead) { - if (isGlobal) - currentHead->scriptPtr = scriptTable[currentHead->scriptIdx].ptr; - else - currentHead->scriptPtr = (byte *)relTable[currentHead->scriptIdx].data; - currentHead = currentHead->next; - } +/*! \brief Savefile format tester + * \param fHandle Savefile to check + * + * This function seeks through savefile and tries to guess if it's the original + * savegame format or broken format from ScummVM 0.10/0.11 + * The test is incomplete but this should cover 99.99% of cases. + * If anyone makes a savefile which could confuse this test, assert will + * report it + */ +bool brokenSave(Common::InSaveFile &fHandle) { + // Backward seeking not supported in compressed savefiles + // if you really want it, finish it yourself + return false; + + // fixed size part: 14093 bytes (12308 bytes in broken save) + // animDataTable begins at byte 6431 + + int filesize = fHandle.size(); + int startpos = fHandle.pos(); + int pos, tmp; + bool correct = false, broken = false; + + // check for correct format + while (filesize > 14093) { + pos = 14093; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 206; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 206; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 20; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 20; + + if (pos == filesize) correct = true; + break; + } + debug(5, "brokenSave: correct format check %s: size=%d, pos=%d", + correct ? "passed" : "failed", filesize, pos); + + // check for broken format + while (filesize > 12308) { + pos = 12308; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 206; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 206; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 20; + if (pos >= filesize) break; + + fHandle.seek(pos); + tmp = fHandle.readUint16BE(); + pos += 2 + tmp * 20; + + if (pos == filesize) broken = true; + break; + } + debug(5, "brokenSave: broken format check %s: size=%d, pos=%d", + broken ? "passed" : "failed", filesize, pos); + + // there's a very small chance that both cases will match + // if anyone runs into it, you'll have to walk through + // the animDataTable and try to open part file for each entry + if (!correct && !broken) { + error("brokenSave: file format check failed"); + } else if (correct && broken) { + error("brokenSave: both file formats seem to apply"); + } + + fHandle.seek(startpos); + debug(5, "brokenSave: detected %s file format", + correct ? "correct" : "broken"); + + return broken; } bool CineEngine::makeLoad(char *saveName) { int16 i; int16 size; + bool broken; Common::InSaveFile *fHandle; fHandle = g_saveFileMan->openForLoading(saveName); @@ -408,29 +437,13 @@ bool CineEngine::makeLoad(char *saveName) { // if (g_cine->getGameType() == Cine::GType_OS) { // freeUnkList(); // } - freePrcLinkedList(); - releaseObjectScripts(); - freeBgIncrustList(); + bgIncrustList.clear(); closePart(); - for (i = 0; i < NUM_MAX_REL; i++) { - if (relTable[i].data) { - free(relTable[i].data); - relTable[i].data = NULL; - relTable[i].size = 0; - relTable[i].obj1Param1 = 0; - relTable[i].obj1Param2 = 0; - relTable[i].obj2Param = 0; - } - } - - for (i = 0; i < NUM_MAX_SCRIPT; i++) { - if (scriptTable[i].ptr) { - free(scriptTable[i].ptr); - scriptTable[i].ptr = NULL; - scriptTable[i].size = 0; - } - } + objectScripts.clear(); + globalScripts.clear(); + relTable.clear(); + scriptTable.clear(); for (i = 0; i < NUM_MAX_MESSAGE; i++) { messageTable[i].len = 0; @@ -478,6 +491,8 @@ bool CineEngine::makeLoad(char *saveName) { checkForPendingDataLoadSwitch = 0; + broken = brokenSave(*fHandle); + currentDisk = fHandle->readUint16BE(); fHandle->read(currentPartName, 13); @@ -491,6 +506,28 @@ bool CineEngine::makeLoad(char *saveName) { fHandle->read(currentBgName[0], 13); fHandle->read(currentCtName, 13); + checkDataDisk(currentDisk); + + if (strlen(currentPartName)) { + loadPart(currentPartName); + } + + if (strlen(currentPrcName)) { + loadPrc(currentPrcName); + } + + if (strlen(currentRelName)) { + loadRel(currentRelName); + } + + if (strlen(currentBgName[0])) { + loadBg(currentBgName[0]); + } + + if (strlen(currentCtName)) { + loadCt(currentCtName); + } + fHandle->readUint16BE(); fHandle->readUint16BE(); @@ -540,18 +577,7 @@ bool CineEngine::makeLoad(char *saveName) { fHandle->readUint16BE(); fHandle->readUint16BE(); - for (i = 0; i < NUM_MAX_ANIMDATA; i++) { - animDataTable[i].width = fHandle->readUint16BE(); - animDataTable[i].var1 = fHandle->readUint16BE(); - animDataTable[i].bpp = fHandle->readUint16BE(); - animDataTable[i].height = fHandle->readUint16BE(); - animDataTable[i].ptr1 = NULL; - animDataTable[i].ptr2 = NULL; - animDataTable[i].fileIdx = fHandle->readSint16BE(); - animDataTable[i].frameIdx = fHandle->readSint16BE(); - fHandle->read(animDataTable[i].name, 10); - animDataTable[i].refresh = (fHandle->readByte() != 0); - } + loadResourcesFromSave(*fHandle, broken); // TODO: handle screen params (really required ?) fHandle->readUint16BE(); @@ -576,44 +602,14 @@ bool CineEngine::makeLoad(char *saveName) { loadOverlayFromSave(fHandle); } - size = fHandle->readSint16BE(); - for (i = 0; i < size; i++) { - loadBgIncrustFromSave(fHandle); - } + loadBgIncrustFromSave(*fHandle); delete fHandle; - checkDataDisk(currentDisk); - - if (strlen(currentPartName)) { - loadPart(currentPartName); - } - - if (strlen(currentPrcName)) { - loadPrc(currentPrcName); - setupScriptList(true); - } - - if (strlen(currentRelName)) { - loadRel(currentRelName); - setupScriptList(false); - } - if (strlen(currentMsgName)) { loadMsg(currentMsgName); } - if (strlen(currentBgName[0])) { - loadBg(currentBgName[0]); - } - - if (strlen(currentCtName)) { - loadCt(currentCtName); - } - - loadResourcesFromSave(); - reincrustAllBg(); - setMouseCursor(MOUSE_CURSOR_NORMAL); if (strlen(currentDatName)) { @@ -702,21 +698,7 @@ void makeSave(char *saveFileName) { fHandle->writeUint16BE(0x1E); for (i = 0; i < NUM_MAX_ANIMDATA; i++) { - fHandle->writeUint16BE(animDataTable[i].width); - fHandle->writeUint16BE(animDataTable[i].var1); - fHandle->writeUint16BE(animDataTable[i].bpp); - fHandle->writeUint16BE(animDataTable[i].height); - fHandle->writeSint16BE(animDataTable[i].fileIdx); - fHandle->writeSint16BE(animDataTable[i].frameIdx); - fHandle->write(animDataTable[i].name, 10); - - // Horrifyingly, cinE used to dump the entire struct to the - // save file, including the data pointers. While these pointers - // would be invalid after loading, the loadResourcesFromSave() - // function would still test if ptr1 was non-NULL, presumably - // to see if the object was present in the room. - - fHandle->writeByte(animDataTable[i].ptr1 ? 1 : 0); + animDataTable[i].save(*fHandle); } fHandle->writeUint16BE(0); // Screen params, unhandled @@ -727,60 +709,15 @@ void makeSave(char *saveFileName) { fHandle->writeUint16BE(0); { - int16 numScript = 0; - prcLinkedListStruct *currentHead = globalScriptsHead.next; - - while (currentHead) { - numScript++; - currentHead = currentHead->next; - } - - fHandle->writeUint16BE(numScript); - - // actual save - currentHead = globalScriptsHead.next; - - while (currentHead) { - for (i = 0; i < SCRIPT_STACK_SIZE; i++) { - fHandle->writeUint16BE(currentHead->stack[i]); - } - - currentHead->localVars.save(*fHandle); - - fHandle->writeUint16BE(currentHead->compareResult); - fHandle->writeUint16BE(currentHead->scriptPosition); - fHandle->writeUint16BE(currentHead->scriptIdx); - - currentHead = currentHead->next; - } - } - - { - int16 numScript = 0; - prcLinkedListStruct *currentHead = objScriptList.next; - - while (currentHead) { - numScript++; - currentHead = currentHead->next; + ScriptList::iterator it; + fHandle->writeUint16BE(globalScripts.size()); + for (it = globalScripts.begin(); it != globalScripts.end(); ++it) { + (*it)->save(*fHandle); } - fHandle->writeUint16BE(numScript); - - // actual save - currentHead = objScriptList.next; - - while (currentHead) { - for (i = 0; i < SCRIPT_STACK_SIZE; i++) { - fHandle->writeUint16BE(currentHead->stack[i]); - } - - currentHead->localVars.save(*fHandle); - - fHandle->writeUint16BE(currentHead->compareResult); - fHandle->writeUint16BE(currentHead->scriptPosition); - fHandle->writeUint16BE(currentHead->scriptIdx); - - currentHead = currentHead->next; + fHandle->writeUint16BE(objectScripts.size()); + for (it = objectScripts.begin(); it != objectScripts.end(); ++it) { + (*it)->save(*fHandle); } } @@ -812,6 +749,20 @@ void makeSave(char *saveFileName) { } } + Common::List::iterator it; + fHandle->writeUint16BE(bgIncrustList.size()); + + for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) { + fHandle->writeUint32BE(0); // next + fHandle->writeUint32BE(0); // unkPtr + fHandle->writeUint16BE(it->objIdx); + fHandle->writeUint16BE(it->param); + fHandle->writeUint16BE(it->x); + fHandle->writeUint16BE(it->y); + fHandle->writeUint16BE(it->frame); + fHandle->writeUint16BE(it->part); + } +/* int numBgIncrustList = 0; BGIncrustList *bgIncrustPtr = bgIncrustList; @@ -834,6 +785,7 @@ void makeSave(char *saveFileName) { bgIncrustPtr = bgIncrustPtr->next; } +*/ delete fHandle; @@ -985,7 +937,11 @@ int drawChar(byte character, int16 x, int16 y) { if (characterWidth) { byte characterIdx = fontParamTable[character].characterIdx; - drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y); + if (g_cine->getGameType() == Cine::GType_OS) { + drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y); + } else { + drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y); + } x += characterWidth + 1; } } @@ -1726,8 +1682,8 @@ uint16 executePlayerInput(void) { return var_5E; } -void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr, - byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) { +void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr, + const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) { byte *ptr = NULL; byte *msk = NULL; byte i = 0; @@ -1754,11 +1710,11 @@ void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr, maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame; - maskWidth = animDataTable[maskSpriteIdx].width / 2; - maskHeight = animDataTable[maskSpriteIdx].height; - gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++); + maskWidth = animDataTable[maskSpriteIdx]._width / 2; + maskHeight = animDataTable[maskSpriteIdx]._height; + gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++); #ifdef DEBUG_SPRITE_MASK - gfxFillSprite(animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, page, maskX, maskY, 1); + gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1); #endif } @@ -1790,7 +1746,7 @@ void backupOverlayPage(void) { if (i > 200) { memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320); } else { - memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i) * 320, 320); + memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320); } } } @@ -1805,7 +1761,7 @@ void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 co uint16 lineResult, fullLineWidth; uint16 interWordSize, interWordSizeRemain; const char *endOfMessagePtr; - byte currentChar, characterWidth; + byte currentChar; //, characterWidth; gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw); @@ -1854,13 +1810,7 @@ void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 co if (interWordSizeRemain) interWordSizeRemain = 0; } else { - characterWidth = fontParamTable[currentChar].characterWidth; - - if (characterWidth) { - byte characterIdx = fontParamTable[currentChar].characterIdx; - drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY); - localX += characterWidth + 1; - } + localX = drawChar(currentChar, localX, localY); } } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached); @@ -1910,6 +1860,10 @@ void drawFailureMessage(byte cmd) { freeOverlay(cmd, 3); } +/*! \todo Fix Operation Stealth logo in intro (the green text after the plane + * takes off). Each letter should slowly grow top-down, it has something to + * do with object 10 (some mask or something) + */ void drawOverlays(void) { uint16 partVar1, partVar2; AnimData *pPart; @@ -1942,12 +1896,13 @@ void drawOverlays(void) { if (g_cine->getGameType() == Cine::GType_OS) { pPart = &animDataTable[objPtr->frame]; - partVar1 = pPart->var1; - partVar2 = pPart->height; + partVar1 = pPart->_var1; + partVar2 = pPart->_height; - if (pPart->ptr1) { - // NOTE: is the mask supposed to be in ptr1? Shouldn't that be ptr2, like below? - drawSprite(currentOverlay, pPart->ptr1, pPart->ptr1, partVar1, partVar2, page1Raw, x, y); + if (pPart->data()) { + // NOTE: is the mask supposed to be in data()? Shouldn't that be mask(), like below? + // OS sprites don't use masks, see drawSprite() -- next_ghost + drawSprite(currentOverlay, pPart->data(), pPart->data(), partVar1, partVar2, page1Raw, x, y); } } else { part = objPtr->part; @@ -1956,11 +1911,11 @@ void drawOverlays(void) { pPart = &animDataTable[objPtr->frame]; - partVar1 = pPart->var1; - partVar2 = pPart->height; + partVar1 = pPart->_var1; + partVar2 = pPart->_height; - if (pPart->ptr1) { - drawSprite(currentOverlay, pPart->ptr1, pPart->ptr2, partVar1, partVar2, page1Raw, x, y); + if (pPart->data()) { + drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y); } } } @@ -2013,6 +1968,7 @@ void drawOverlays(void) { x = objPtr->x; y = objPtr->y; + if (objPtr->frame >= 0) { part = objPtr->part; @@ -2020,11 +1976,11 @@ void drawOverlays(void) { pPart = &animDataTable[objPtr->frame]; - partVar1 = pPart->width / 2; - partVar2 = pPart->height; + partVar1 = pPart->_width / 2; + partVar2 = pPart->_height; - if (pPart->ptr1) { - gfxFillSprite(pPart->ptr1, partVar1, partVar2, page1Raw, x, y); + if (pPart->data()) { + gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y); } } break; @@ -2040,22 +1996,15 @@ void drawOverlays(void) { var5 = currentOverlay->x; - if (objPtr->frame >= 0) { - if (var5 <= 8) { - if (additionalBgTable[var5]) { - if (animDataTable[objPtr->frame].bpp == 1) { - int16 x2; - int16 y2; - - x2 = animDataTable[objPtr->frame].width / 2; - y2 = animDataTable[objPtr->frame].height; - - if (animDataTable[objPtr->frame].ptr1) { - // drawSpriteRaw(animDataTable[objPtr->frame].ptr1, animDataTable[objPtr->frame].ptr1, x2, y2, - // additionalBgTable[currentAdditionalBgIdx], x, y); - } - } - } + if (objPtr->frame >= 0 && var5 <= 8 && additionalBgTable[var5] && animDataTable[objPtr->frame]._bpp == 1) { + int16 x2; + int16 y2; + + x2 = animDataTable[objPtr->frame]._width / 2; + y2 = animDataTable[objPtr->frame]._height; + + if (animDataTable[objPtr->frame].data()) { + maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), x2, y2, page1Raw, x, y); } } break; @@ -2075,9 +2024,6 @@ void mainLoopSub6(void) { void checkForPendingDataLoad(void) { if (newPrcName[0] != 0) { - freePrcLinkedList(); - resetglobalScriptsHead(); - loadPrc(newPrcName); strcpy(currentPrcName, newPrcName); @@ -2087,9 +2033,6 @@ void checkForPendingDataLoad(void) { } if (newRelName[0] != 0) { - releaseObjectScripts(); - resetObjectScriptHead(); - loadRel(newRelName); strcpy(currentRelName, newRelName); @@ -2315,10 +2258,10 @@ void resetGfxEntityEntry(uint16 objIdx) { #endif } -uint16 addAni(uint16 param1, uint16 param2, byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) { - byte *currentPtr = ptr; - byte *ptrData; - byte *ptr2; +uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) { + const byte *currentPtr = ptr; + const byte *ptrData; + const byte *ptr2; int16 di; assert(ptr); @@ -2360,7 +2303,7 @@ uint16 addAni(uint16 param1, uint16 param2, byte *ptr, SeqListElement *element, void processSeqListElement(SeqListElement *element) { int16 x = objectTable[element->var6].x; int16 y = objectTable[element->var6].y; - byte *ptr1 = animDataTable[element->varA].ptr1; + const byte *ptr1 = animDataTable[element->varA].data(); int16 var_10; int16 var_4; int16 var_2; diff --git a/engines/cine/xref.txt b/engines/cine/xref.txt new file mode 100644 index 0000000000..fd76f7eaaf --- /dev/null +++ b/engines/cine/xref.txt @@ -0,0 +1,146 @@ +script.cpp: +setupOpcodes() - replaced with FWScript/OSScript class members +getNextByte() - replaced with RawScript/FWScript class members +getNextWord() - replaced with RawScript/FWScript class members +getNextString() - replaced with RawScript/FWScript class members +computeScriptStackSub() - replaced with RawScript::getNextLabel() +computeScriptStack() - replaced with RawScript::computeLabels() +computeScriptStackFromScript() - replaced with RawScript::getLabel() +executeScript() - replaced with FWScript::execute() +endScript0() - removed (obsoleted by new executeList0() implementation) +endScript1() - removed (obsoleted by new executeList1() implementation) + +o1_modifyObjectParam() - replaced with FWScript::o1_modifyObjectParam() +o1_getObjectParam() - replaced with FWScript::o1_getObjectParam() +o1_addObjectParam() - replaced with FWScript::o1_addObjectParam() +o1_subObjectParam() - replaced with FWScript::o1_subObjectParam() +o1_add2ObjectParam() - replaced with FWScript::o1_add2ObjectParam() +o1_sub2ObjectParam() - replaced with FWScript::o1_sub2ObjectParam() +o1_compareObjectParam() - replaced with FWScript::o1_compareObjectParam() +o1_setupObject() - replaced with FWScript::o1_setupObject() +o1_checkCollision() - replaced with FWScript::o1_checkCollision() +o1_loadVar() - replaced with FWScript::o1_loadVar() +o1_addVar() - replaced with FWScript::o1_addVar() +o1_subVar() - replaced with FWScript::o1_subVar() +o1_mulVar() - replaced with FWScript::o1_mulVar() +o1_divVar() - replaced with FWScript::o1_divVar() +o1_compareVar() - replaced with FWScript::o1_compareVar() +o1_modifyObjectParam2() - replaced with FWScript::o1_modifyObjectParam2() +o1_loadMask0() - replaced with FWScript::o1_loadMask0() +o1_unloadMask0() - replaced with FWScript::o1_unloadMask0() +o1_addToBgList() - replaced with FWScript::o1_addToBgList() +o1_loadMask1() - replaced with FWScript::o1_loadMask1() +o1_unloadMask1() - replaced with FWScript::o1_unloadMask1() +o1_loadMask4() - replaced with FWScript::o1_loadMask4() +o1_unloadMask4() - replaced with FWScript::o1_unloadMask4() +o1_addSpriteFilledToBgList() - replaced with FWScript::o1_addSpriteFilledToBgList() +o1_op1B() - replaced with FWScript::o1_op1B() +o1_label() - replaced with FWScript::o1_label() +o1_goto() - replaced with FWScript::o1_goto() +o1_gotoIfSup() - replaced with FWScript::o1_gotoIfSup() +o1_gotoIfSupEqu() - replaced with FWScript::o1_gotoIfSupEqu() +o1_gotoIfInf() - replaced with FWScript::o1_gotoIfInf() +o1_gotoIfInfEqu() - replaced with FWScript::o1_gotoIfInfEqu() +o1_gotoIfEqu() - replaced with FWScript::o1_gotoIfEqu() +o1_gotoIfDiff() - replaced with FWScript::o1_gotoIfDiff() +o1_removeLabel() - replaced with FWScript::o1_removeLabel() +o1_loop() - replaced with FWScript::o1_loop() +o1_startGlobalScript() - replaced with FWScript::o1_startGlobalScript() +o1_endGlobalScript() - replaced with FWScript::o1_endGlobalScript() +o1_loadAnim() - replaced with FWScript::o1_loadAnim() +o1_loadBg() - replaced with FWScript::o1_loadBg() +o1_loadCt() - replaced with FWScript::o1_loadCt() +o1_loadPart() - replaced with FWScript::o1_loadPart() +o1_closePart() - replaced with FWScript::o1_closePart() +o1_loadNewPrcName() - replaced with FWScript::o1_loadNewPrcName() +o1_requestCheckPendingDataLoad() - replaced with FWScript::o1_requestCheckPendingDataLoad() +o1_blitAndFade() - replaced with FWScript::o1_blitAndFade() +o1_fadeToBlack() - replaced with FWScript::o1_fadeToBlack() +o1_transformPaletteRange() - replaced with FWScript::o1_transformPaletteRange() +o1_setDefaultMenuColor2() - replaced with FWScript::o1_setDefaultMenuColor2() +o1_palRotate() - replaced with FWScript::o1_palRotate() +o1_break() - replaced with FWScript::o1_break() +o1_endScript() - replaced with FWScript::o1_endScript() +o1_message() - replaced with FWScript::o1_message() +o1_loadGlobalVar() - replaced with FWScript::o1_loadGlobalVar() +o1_compareGlobalVar() - replaced with FWScript::o1_compareGlobalVar() +o1_declareFunctionName() - replaced with FWScript::o1_declareFunctionName() +o1_freePartRange() - replaced with FWScript::o1_freePartRange() +o1_unloadAllMasks() - replaced with FWScript::o1_unloadAllMasks() +o1_setScreenDimensions() - replaced with FWScript::o1_setScreenDimensions() +o1_displayBackground() - replaced with FWScript::o1_displayBackground() +o1_initializeZoneData() - replaced with FWScript::o1_initializeZoneData() +o1_setZoneDataEntry() - replaced with FWScript::o1_setZoneDataEntry() +o1_getZoneDataEntry() - replaced with FWScript::o1_getZoneDataEntry() +o1_setDefaultMenuColor() - replaced with FWScript::o1_setDefaultMenuColor() +o1_allowPlayerInput() - replaced with FWScript::o1_allowPlayerInput() +o1_disallowPlayerInput() - replaced with FWScript::o1_disallowPlayerInput() +o1_changeDataDisk() - replaced with FWScript::o1_changeDataDisk() +o1_loadMusic() - replaced with FWScript::o1_loadMusic() +o1_playMusic() - replaced with FWScript::o1_playMusic() +o1_fadeOutMusic() - replaced with FWScript::o1_fadeOutMusic() +o1_stopSample() - replaced with FWScript::o1_stopSample() +o1_op71() - replaced with FWScript::o1_op71() +o1_op72() - replaced with FWScript::o1_op72() +o1_op73() - replaced with FWScript::o1_op73() +o1_playSample() - replaced with FWScript::o1_playSample() +o1_playSample() - replaced with FWScript::o1_playSample() +o1_disableSystemMenu() - replaced with FWScript::o1_disableSystemMenu() +o1_loadMask5() - replaced with FWScript::o1_loadMask5() +o1_unloadMask5() - replaced with FWScript::o1_unloadMask5() + +o2_loadPart() - replaced with FWScript::o2_loadPart() +o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement() +o2_removeSeq() - replaced with FWScript::o2_removeSeq() +o2_playSample() - replaced with FWScript::o2_playSample() +o2_playSampleAlt() - replaced with FWScript::o2_playSampleAlt() +o2_op81() - replaced with FWScript::o2_op81() +o2_op82() - replaced with FWScript::o2_op82() +o2_isSeqRunning() - replaced with FWScript::o2_isSeqRunning() +o2_gotoIfSupNearest() - replaced with FWScript::o2_gotoIfSupNearest() +o2_gotoIfSupEquNearest() - replaced with FWScript::o2_gotoIfSupEquNearest() +o2_gotoIfInfNearest() - replaced with FWScript::o2_gotoIfInfNearest() +o2_gotoIfInfEquNearest() - replaced with FWScript::o2_gotoIfInfEquNearest() +o2_gotoIfEquNearest() - replaced with FWScript::o2_gotoIfEquNearest() +o2_gotoIfDiffNearest() - replaced with FWScript::o2_gotoIfDiffNearest() +o2_startObjectScript() - replaced with FWScript::o2_startObjectScript() +o2_stopObjectScript() - replaced with FWScript::o2_stopObjectScript() +o2_op8D() - replaced with FWScript::o2_op8D() +o2_addBackground() - replaced with FWScript::o2_addBackground() +o2_removeBackground() - replaced with FWScript::o2_removeBackground() +o2_loadAbs() - replaced with FWScript::o2_loadAbs() +o2_loadBg() - replaced with FWScript::o2_loadBg() +o2_wasZoneChecked() - replaced with FWScript::o2_wasZoneChecked() +o2_op9B() - replaced with FWScript::o2_op9B() +o2_op9C() - replaced with FWScript::o2_op9C() +o2_useBgScroll() - replaced with FWScript::o2_useBgScroll() +o2_setAdditionalBgVScroll() - replaced with FWScript::o2_setAdditionalBgVScroll() +o2_op9F() - replaced with FWScript::o2_op9F() +o2_addGfxElementA0() - replaced with FWScript::o2_addGfxElementA0() +o2_opA1() - replaced with FWScript::o2_opA1() +o2_opA2() - replaced with FWScript::o2_opA2() +o2_opA3() - replaced with FWScript::o2_opA3() +o2_loadMask22() - replaced with FWScript::o2_loadMask22() +o2_unloadMask22() - replaced with FWScript::o2_unloadMask22() + +prc.cpp: +resetGlobalScriptsHead() - removed (obsoleted by Common::List) +freePrcLinkedList(void) - removed (obsoleted by Common::List::clear()) + +rel.cpp: +resetObjectScriptHead() - removed (obsoleted by Common::List) +releaseObjectScripts() - removed (obsoleted by Common::List::clear()) + +various.cpp: +setupScriptList() - removed (obsoleted by new makeLoad() and + loadScriptFromSave() implementation) + +anim.cpp: +freeAnimData() - replaced with animData::clear() +allocFrame() - replaced with animData::load() +reserveFrame() - replaced with animData::load() + +bg_list.cpp +reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and + loadBgIncrustFromSave() implementation) +freeBgIncrustList() - removed (obsoleted by Common::List::clear()) -- cgit v1.2.3