Ticket #8869: dump.patch

File dump.patch, 103.0 KB (added by SF/next_ghost, 16 years ago)

Renderer rewrite, seqList rewrite and decompileScript() fix

  • engines/cine/script_fw.cpp

     
    4141ScriptVars globalVars(NUM_MAX_VAR);
    4242
    4343uint16 compareVars(int16 a, int16 b);
    44 void palRotate(byte a, byte b, byte c);
    45 void removeSeq(uint16 param1, uint16 param2, uint16 param3);
    46 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
    47 void addGfxElementA0(int16 param1, int16 param2);
    48 void removeGfxElementA0(int16 idx, int16 param);
    4944
    5045const Opcode FWScript::_opcodeTable[] = {
    5146        /* 00 */
     
    12991294        const char *param = getNextString();
    13001295
    13011296        debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
    1302         loadCt(param);
     1297        loadCtFW(param);
    13031298        return 0;
    13041299}
    13051300
     
    13551350        debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
    13561351        // TODO: use real code
    13571352
    1358         drawOverlays();
    1359         fadeRequired = true;
    1360         flip();
    1361 
    13621353//      fadeFromBlack();
     1354
     1355        renderer->reloadPalette();
    13631356        return 0;
    13641357}
    13651358
    13661359int FWScript::o1_fadeToBlack() {
    13671360        debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
    13681361
    1369         fadeToBlack();
     1362        renderer->fadeToBlack();
    13701363        return 0;
    13711364}
    13721365
    13731366int FWScript::o1_transformPaletteRange() {
    13741367        byte startColor = getNextByte();
    13751368        byte numColor = getNextByte();
    1376         uint16 r = getNextWord();
    1377         uint16 g = getNextWord();
    1378         uint16 b = getNextWord();
     1369        int16 r = getNextWord();
     1370        int16 g = getNextWord();
     1371        int16 b = getNextWord();
    13791372
    13801373        debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
    13811374
    1382         transformPaletteRange(startColor, numColor, r, g, b);
     1375        renderer->transformPalette(startColor, numColor, r, g, b);
    13831376        return 0;
    13841377}
    13851378
     
    13871380        byte param = getNextByte();
    13881381
    13891382        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
    1390         defaultMenuBoxColor2 = param;
     1383
     1384        renderer->_messageBg = param;
    13911385        return 0;
    13921386}
    13931387
     
    13971391        byte c = getNextByte();
    13981392
    13991393        debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
    1400         palRotate(a, b, c);
     1394
     1395        renderer->rotatePalette(a, b, c);
    14011396        return 0;
    14021397}
    14031398
     
    14751470
    14761471                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
    14771472
    1478                 if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) {       // TODO: fix
    1479                         _compare = 1;
    1480                 } else {
    1481                         _compare = compareVars(_globalVars[varIdx], value);
    1482                 }
     1473                _compare = compareVars(_globalVars[varIdx], value);
    14831474        }
    14841475
    14851476        return 0;
     
    15581549        byte param = getNextByte();
    15591550
    15601551        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
    1561         defaultMenuBoxColor = param;
     1552
     1553        renderer->_cmdY = param;
    15621554        return 0;
    15631555}
    15641556
     
    17281720
    17291721//-----------------------------------------------------------------------
    17301722
    1731 void palRotate(byte a, byte b, byte c) {
    1732         if (c == 1) {
    1733                 uint16 currentColor = c_palette[b];
    1734 
    1735                 for (int16 i = b; i > a; i--) {
    1736                         c_palette[i] = c_palette[i - 1];
    1737                 }
    1738 
    1739                 c_palette[a] = currentColor;
    1740         }
    1741 }
    1742 
    17431723void addScriptToList0(uint16 idx) {
    17441724        ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
    17451725        assert(tmp);
     
    18631843        }
    18641844}
    18651845
    1866 void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx) {
     1846void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx) {
    18671847        char lineBuffer[256];
    1868         byte *localScriptPtr = scriptPtr;
     1848        const byte *localScriptPtr = scriptPtr;
    18691849        uint16 exitScript;
    18701850        uint32 position = 0;
    18711851
    18721852        assert(scriptPtr);
    1873         // assert(stackPtr);
    18741853
    18751854        exitScript = 0;
    18761855
     
    22922271                                        sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position);
    22932272                                }
    22942273
    2295                                 position += strlen((char *)localScriptPtr + position) + 1;
     2274                                position += strlen((const char *)localScriptPtr + position) + 1;
    22962275                                break;
    22972276                        }
    22982277                case 0x40:
     
    23092288
    23102289                                sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position);
    23112290
    2312                                 position += strlen((char *)localScriptPtr + position) + 1;
     2291                                position += strlen((const char *)localScriptPtr + position) + 1;
    23132292                                break;
    23142293                        }
    23152294                case OP_requestCheckPendingDataLoad:    // nop
     
    24612440                        {
    24622441                                sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position);
    24632442
    2464                                 position += strlen((char *)localScriptPtr + position);
     2443                                position += strlen((const char *)localScriptPtr + position);
    24652444                                break;
    24662445                        }
    24672446                case 0x5A:
     
    25402519                        {
    25412520                                sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position);
    25422521
    2543                                 position += strlen((char *)localScriptPtr + position) + 1;
     2522                                position += strlen((const char *)localScriptPtr + position) + 1;
    25442523                                break;
    25452524                        }
    25462525                case 0x6E:      // nop
     
    28012780
    28022781                                sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position);
    28032782
    2804                                 position += strlen((char *)localScriptPtr + position);
     2783                                position += strlen((const char *)localScriptPtr + position);
    28052784
    28062785                                break;
    28072786                        }
     
    28252804
    28262805                                sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position);
    28272806
    2828                                 position += strlen((char *)localScriptPtr + position);
     2807                                position += strlen((const char *)localScriptPtr + position);
    28292808
    28302809                                break;
    28312810                        }
  • engines/cine/script.h

     
    230230        int o1_unloadMask5();
    231231
    232232        // pointers to member functions in C++ suck...
     233        int o2_loadCt();
    233234        int o2_loadPart();
    234235        int o2_addSeqListElement();
    235236        int o2_removeSeq();
     
    362363
    363364void setupOpcodes();
    364365
    365 void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx);
     366void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx);
    366367void dumpScript(char *dumpName);
    367368
    368369#define OP_loadPart                     0x3F
  • engines/cine/pal.cpp

     
    2828
    2929namespace Cine {
    3030
    31 uint16 tempPalette[256];
    32 
    3331uint16 palEntriesCount;
    3432
    3533PalEntry *palPtr = NULL;
     
    113111        }
    114112}
    115113
     114void palRotate(uint16 *pal, byte a, byte b, byte c) {
     115        assert(pal);
     116
     117        if (c == 1) {
     118                uint16 currentColor = pal[b];
     119
     120                for (int i = b; i > a; i--) {
     121                        pal[i] = pal[i - 1];
     122                }
     123
     124                pal[a] = currentColor;
     125        }
     126}
     127
     128void palRotate(byte *pal, byte a, byte b, byte c) {
     129        assert(pal);
     130
     131        if (c == 1) {
     132                byte currentR = pal[3 * b + 0];
     133                byte currentG = pal[3 * b + 1];
     134                byte currentB = pal[3 * b + 2];
     135
     136                for (int i = b; i > a; i--) {
     137                        pal[3 * i + 0] = pal[3 * (i - 1) + 0];
     138                        pal[3 * i + 1] = pal[3 * (i - 1) + 1];
     139                        pal[3 * i + 2] = pal[3 * (i - 1) + 2];
     140                }
     141
     142                pal[3 * a + 0] = currentR;
     143                pal[3 * a + 1] = currentG;
     144                pal[3 * a + 2] = currentB;
     145        }
     146}
     147
     148uint16 transformColor(uint16 baseColor, int r, int g, int b) {
     149        int8 oriR = CLIP( (baseColor & 0x007)       + b, 0, 7);
     150        int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7);
     151        int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7);
     152
     153        return oriR | (oriG << 4) | (oriB << 8);
     154}
     155
     156void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) {
     157        assert(srcPal && dstPal);
     158
     159        for (int i = startColor; i <= stopColor; i++) {
     160                dstPal[i] = transformColor(srcPal[i], r, g, b);
     161        }
     162}
     163
     164void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) {
     165        assert(srcPal && dstPal);
     166
     167        for (int i = startColor; i <= stopColor; i++) {
     168                dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 32, 0, 255);
     169                dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 32, 0, 255);
     170                dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 32, 0, 255);
     171        }
     172}
     173
    116174} // End of namespace Cine
  • engines/cine/rel.cpp

     
    8181                char buffer[256];
    8282
    8383                for (s = 0; s < numEntry; s++) {
    84                         if (relTable[s].size) {
     84                        if (relTable[s]->_size) {
    8585                                sprintf(buffer, "%s_%03d.txt", pRelName, s);
    8686
    87                                 decompileScript(relTable[s].data, NULL, relTable[s].size, s);
     87                                decompileScript((const byte *)relTable[s]->getString(0), relTable[s]->_size, s);
    8888                                dumpScript(buffer);
    8989                        }
    9090                }
  • engines/cine/bg_list.cpp

     
    4040
    4141/*! \brief Add masked sprite to the background
    4242 * \param objIdx Sprite description
    43  * \param addList Add sprite to incrust list if true
    44  * \todo Fix incrust objects on CT background. Always drawing incrust elements
    45  * on CT background breaks game zones
    4643 */
    47 void addToBGList(int16 objIdx, bool addList) {
    48         int16 x = objectTable[objIdx].x;
    49         int16 y = objectTable[objIdx].y;
    50         int16 width = animDataTable[objectTable[objIdx].frame]._var1;
    51         int16 height = animDataTable[objectTable[objIdx].frame]._height;
    52         const byte *data = animDataTable[objectTable[objIdx].frame].data();
    53         const byte *mask = animDataTable[objectTable[objIdx].frame].mask();
    54 //      int16 part = objectTable[objIdx].part;
     44void addToBGList(int16 objIdx) {
     45        renderer->incrustSprite(objectTable[objIdx]);
    5546
    56         // Operation Stealth may switch among multiple backgrounds
    57         if (g_cine->getGameType() == GType_OS) {
    58                 for (int i = 0; i < 8; i++) {
    59                         if (additionalBgTable[i]) {
    60                                 drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y);
    61                         }
    62                 }
    63         } else {
    64                 drawSpriteRaw(data, mask, width, height, page2Raw, x, y);
    65         }
    66 
    67         if (addList)
    68                 createBgIncrustListElement(objIdx, 0);
     47        createBgIncrustListElement(objIdx, 0);
    6948}
    7049
    7150/*! \brief Add filled sprite to the background
    7251 * \param objIdx Sprite description
    73  * \param addList Add sprite to incrust list if true
    74  * \todo Fix incrust objects on CT background. Always drawing incrust elements
    75  * on CT background breaks game zones
    7652 */
    77 void addSpriteFilledToBGList(int16 objIdx, bool addList) {
    78         int16 x = objectTable[objIdx].x;
    79         int16 y = objectTable[objIdx].y;
    80         int16 width = animDataTable[objectTable[objIdx].frame]._realWidth;
    81         int16 height = animDataTable[objectTable[objIdx].frame]._height;
    82         const byte *data = animDataTable[objectTable[objIdx].frame].data();
     53void addSpriteFilledToBGList(int16 objIdx) {
     54        renderer->incrustMask(objectTable[objIdx]);
    8355
    84         if (data) {
    85                 // Operation Stealth may switch among multiple backgrounds
    86                 if (g_cine->getGameType() == GType_OS) {
    87                         for (int i = 0; i < 8; i++) {
    88                                 if (additionalBgTable[i]) {
    89                                         gfxFillSprite(data, width, height, additionalBgTable[i], x, y);
    90                                 }
    91                         }
    92                 } else {
    93                         gfxFillSprite(data, width, height, page2Raw, x, y);
    94                 }
    95         }
    96 
    97         if (addList)
    98                 createBgIncrustListElement(objIdx, 1);
     56        createBgIncrustListElement(objIdx, 1);
    9957}
    10058
    10159/*! \brief Add new element to incrust list
     
    11573        bgIncrustList.push_back(tmp);
    11674}
    11775
    118 /*! \brief Reset var8 (probably something related to bgIncrustList
     76/*! \brief Reset var8 (probably something related to bgIncrustList)
    11977 */
    12078void resetBgIncrustList(void) {
    12179        var8 = 0;
     
    142100                bgIncrustList.push_back(tmp);
    143101
    144102                if (tmp.param == 0) {
    145                         addToBGList(tmp.objIdx, false);
     103                        renderer->incrustSprite(objectTable[tmp.objIdx]);
    146104                } else {
    147                         addSpriteFilledToBGList(tmp.objIdx, false);
     105                        renderer->incrustMask(objectTable[tmp.objIdx]);
    148106                }
    149107        }
    150108}
  • engines/cine/anim.cpp

     
    5353
    5454static const AnimDataEntry transparencyData[] = {
    5555        {"ALPHA", 0xF},
     56        {"TITRE", 0xF},
    5657        {"TITRE2", 0xF},
    5758        {"ET", 0xC},
    5859        {"L311", 0x3},
  • engines/cine/various.cpp

     
    8787char newRelName[20];
    8888char newObjectName[20];
    8989char newMsgName[20];
    90 char currentBgName[8][15];
    9190char currentCtName[15];
    9291char currentPartName[15];
    9392char currentDatName[30];
     
    9695
    9796byte isInPause = 0;
    9897
    99 uint16 defaultMenuBoxColor;
    100 
    10198byte inputVar1 = 0;
    10299uint16 inputVar2 = 0, inputVar3 = 0;
    103100
     
    114111int16 objListTab[20];
    115112
    116113uint16 exitEngine;
    117 uint16 defaultMenuBoxColor2;
    118114uint16 zoneData[NUM_MAX_ZONE];
    119115
    120116
     
    140136        tmp.type = 3;
    141137
    142138        overlayList.push_back(tmp);
     139        waitForPlayerClick = 1;
    143140}
    144141
    145142int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
     
    393390        return broken;
    394391}
    395392
     393/*! \todo Implement Operation Stealth loading, this is obviously Future Wars only
     394 */
    396395bool CineEngine::makeLoad(char *saveName) {
    397396        int16 i;
    398397        int16 size;
    399398        bool broken;
    400399        Common::InSaveFile *fHandle;
     400        char bgName[13];
    401401
    402402        fHandle = g_saveFileMan->openForLoading(saveName);
    403403
     
    440440        strcpy(newRelName, "");
    441441        strcpy(newObjectName, "");
    442442        strcpy(newMsgName, "");
    443         strcpy(currentBgName[0], "");
    444443        strcpy(currentCtName, "");
    445444
    446445        allowPlayerInput = 0;
     
    455454
    456455        fadeRequired = false;
    457456
    458         for (i = 0; i < 16; i++) {
    459                 c_palette[i] = 0;
    460         }
     457        renderer->clear();
    461458
    462459        checkForPendingDataLoadSwitch = 0;
    463460
     
    473470        fHandle->read(currentPrcName, 13);
    474471        fHandle->read(currentRelName, 13);
    475472        fHandle->read(currentMsgName, 13);
    476         fHandle->read(currentBgName[0], 13);
     473        fHandle->read(bgName, 13);
    477474        fHandle->read(currentCtName, 13);
    478475
    479476        checkDataDisk(currentDisk);
     
    490487                loadRel(currentRelName);
    491488        }
    492489
    493         if (strlen(currentBgName[0])) {
    494                 loadBg(currentBgName[0]);
     490        if (strlen(bgName)) {
     491                loadBg(bgName);
    495492        }
    496493
    497494        if (strlen(currentCtName)) {
    498                 loadCt(currentCtName);
     495                loadCtFW(currentCtName);
    499496        }
    500497
    501498        fHandle->readUint16BE();
     
    511508                objectTable[i].part = fHandle->readUint16BE();
    512509        }
    513510
    514         for (i = 0; i < 16; i++) {
    515                 c_palette[i] = fHandle->readUint16BE();
    516         }
     511        renderer->restorePalette(*fHandle);
    517512
    518         for (i = 0; i < 16; i++) {
    519                 tempPalette[i] = fHandle->readUint16BE();
    520         }
    521 
    522513        globalVars.load(*fHandle, NUM_MAX_VAR - 1);
    523514
    524515        for (i = 0; i < 16; i++) {
     
    530521        }
    531522
    532523        fHandle->read(commandBuffer, 0x50);
     524        renderer->setCommand(commandBuffer);
    533525
    534         defaultMenuBoxColor = fHandle->readUint16BE();
     526        renderer->_cmdY = fHandle->readUint16BE();
     527
    535528        bgVar0 = fHandle->readUint16BE();
    536529        allowPlayerInput = fHandle->readUint16BE();
    537530        playerCommand = fHandle->readSint16BE();
     
    542535        var3 = fHandle->readUint16BE();
    543536        var2 = fHandle->readUint16BE();
    544537        commandVar2 = fHandle->readSint16BE();
    545         defaultMenuBoxColor2 = fHandle->readUint16BE();
    546538
     539        renderer->_messageBg = fHandle->readUint16BE();
     540
    547541        fHandle->readUint16BE();
    548542        fHandle->readUint16BE();
    549543
     
    615609        fHandle->write(currentPrcName, 13);
    616610        fHandle->write(currentRelName, 13);
    617611        fHandle->write(currentMsgName, 13);
    618         fHandle->write(currentBgName[0], 13);
     612        renderer->saveBg(*fHandle);
    619613        fHandle->write(currentCtName, 13);
    620614
    621615        fHandle->writeUint16BE(0xFF);
     
    631625                fHandle->writeUint16BE(objectTable[i].part);
    632626        }
    633627
    634         for (i = 0; i < 16; i++) {
    635                 fHandle->writeUint16BE(c_palette[i]);
    636         }
     628        renderer->savePalette(*fHandle);
    637629
    638         for (i = 0; i < 16; i++) {
    639                 fHandle->writeUint16BE(tempPalette[i]);
    640         }
    641 
    642630        globalVars.save(*fHandle, NUM_MAX_VAR - 1);
    643631
    644632        for (i = 0; i < 16; i++) {
     
    651639
    652640        fHandle->write(commandBuffer, 0x50);
    653641
    654         fHandle->writeUint16BE(defaultMenuBoxColor);
     642        fHandle->writeUint16BE(renderer->_cmdY);
     643
    655644        fHandle->writeUint16BE(bgVar0);
    656645        fHandle->writeUint16BE(allowPlayerInput);
    657646        fHandle->writeUint16BE(playerCommand);
     
    662651        fHandle->writeUint16BE(var3);
    663652        fHandle->writeUint16BE(var2);
    664653        fHandle->writeUint16BE(commandVar2);
    665         fHandle->writeUint16BE(defaultMenuBoxColor2);
    666654
     655        fHandle->writeUint16BE(renderer->_messageBg);
     656
    667657        fHandle->writeUint16BE(0xFF);
    668658        fHandle->writeUint16BE(0x1E);
    669659
     
    864854        }
    865855}
    866856
    867 int drawChar(byte character, int16 x, int16 y) {
    868         if (character == ' ') {
    869                 x += 5;
    870         } else {
    871                 byte characterWidth = fontParamTable[character].characterWidth;
    872 
    873                 if (characterWidth) {
    874                         byte characterIdx = fontParamTable[character].characterIdx;
    875                         if (g_cine->getGameType() == Cine::GType_OS) {
    876                                 drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y);
    877                         } else {
    878                                 drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
    879                         }
    880                         x += characterWidth + 1;
    881                 }
    882         }
    883 
    884         return x;
    885 }
    886 
    887857void drawMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 offset, int16 color, byte* page) {
    888858        gfxDrawLine(x + offset, y + offset, x + width - offset, y + offset, color, page);       // top
    889859        gfxDrawLine(x + offset, currentY + 4 - offset, x + width - offset, currentY + 4 - offset, color, page); // bottom
     
    896866        drawMessageBox(x, y, width, currentY, 0, color, page);
    897867}
    898868
    899 void makeTextEntry(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width) {
    900         byte color = 2;
    901         byte color2 = defaultMenuBoxColor2;
    902         int16 paramY = (height * 9) + 10;
    903         int16 currentX, currentY;
    904         int16 i;
    905         uint16 j;
    906         byte currentChar;
    907 
    908         if (X + width > 319) {
    909                 X = 319 - width;
    910         }
    911 
    912         if (Y + paramY > 199) {
    913                 Y = 199 - paramY;
    914         }
    915 
    916         hideMouse();
    917         blitRawScreen(page1Raw);
    918 
    919         gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw);
    920 
    921         currentX = X + 4;
    922         currentY = Y + 4;
    923 
    924         for (i = 0; i < height; i++) {
    925                 gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw);
    926                 currentX = X + 4;
    927 
    928                 for (j = 0; j < strlen(commandList[i]); j++) {
    929                         currentChar = commandList[i][j];
    930                         currentX = drawChar(currentChar, currentX, currentY);
    931                 }
    932 
    933                 currentY += 9;
    934         }
    935 
    936         gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw);     // bottom part
    937         drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw);
    938 
    939         blitRawScreen(page1Raw);
    940 }
    941 
    942869void processInventory(int16 x, int16 y) {
    943870        int16 listSize = buildObjectListCommand(-2);
    944871        uint16 button;
     
    946873        if (!listSize)
    947874                return;
    948875
    949         makeTextEntry(objectListCommand, listSize, x, y, 140);
     876        renderer->drawMenu(objectListCommand, listSize, x, y, 140, -1);
     877        renderer->blit();
    950878
    951879        do {
    952880                manageEvents();
     
    10851013        }
    10861014
    10871015        if (!disableSystemMenu) {
    1088                 isDrawCommandEnabled = 1;
     1016                renderer->setCommand(commandBuffer);
    10891017        }
    10901018}
    10911019
     
    10941022uint16 menuVar4 = 0;
    10951023uint16 menuVar5 = 0;
    10961024
    1097 int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y,
    1098     uint16 width, bool recheckValue) {
    1099         byte color = 2;
    1100         byte color2 = defaultMenuBoxColor2;
     1025int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, bool recheckValue) {
    11011026        int16 paramY;
    1102         int16 currentX, currentY;
    1103         int16 i;
    11041027        uint16 button;
    11051028        int16 var_A;
    11061029        int16 di;
     
    11101033        int16 var_14;
    11111034        int16 currentSelection, oldSelection;
    11121035        int16 var_4;
    1113         byte currentChar;
    11141036
    11151037        if (disableSystemMenu)
    11161038                return -1;
     
    11251047                Y = 199 - paramY;
    11261048        }
    11271049
    1128         hideMouse();
    1129         blitRawScreen(page1Raw);
     1050        renderer->drawMenu(commandList, height, X, Y, width, -1);
     1051        renderer->blit();
    11301052
    1131         gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw);
    1132 
    1133         currentX = X + 4;
    1134         currentY = Y + 4;
    1135 
    1136         for (i = 0; i < height; i++) {
    1137                 gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw);
    1138                 currentX = X + 4;
    1139 
    1140                 for (j = 0; j < strlen(commandList[i]); j++) {
    1141                         currentChar = commandList[i][j];
    1142                         currentX = drawChar(currentChar, currentX, currentY);
    1143                 }
    1144 
    1145                 currentY += 9;
    1146         }
    1147 
    1148         gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw);     // bottom part
    1149         drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw);
    1150 
    1151         blitRawScreen(page1Raw);
    1152 
    11531053        do {
    11541054                manageEvents();
    11551055                getMouseData(mouseUpdateStatus, &button, &dummyU16, &dummyU16);
     
    11601060        currentSelection = 0;
    11611061
    11621062        di = currentSelection * 9 + Y + 4;
    1163         gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw);  // draw black box behind selection
    1164         currentX = X + 4;
    11651063
    1166         for (j = 0; j < strlen(commandList[currentSelection]); j++) {
    1167                 currentChar = commandList[currentSelection][j];
    1168                 currentX = drawChar(currentChar, currentX, di);
    1169         }
     1064        renderer->drawMenu(commandList, height, X, Y, width, currentSelection);
     1065        renderer->blit();
    11701066
    1171         blitRawScreen(page1Raw);
    1172 
    11731067        manageEvents();
    11741068        getMouseData(mouseUpdateStatus, &button, (uint16 *)&mouseX, (uint16 *)&mouseY);
    11751069
     
    12191113                                hideMouse();
    12201114                        }
    12211115
    1222                         di = oldSelection * 9 + Y + 4;
    1223 
    1224                         gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, color2, page1Raw);     // restore color
    1225 
    1226                         currentX = X + 4;
    1227 
    1228                         for (j = 0; j < strlen(commandList[oldSelection]); j++) {
    1229                                 currentChar = commandList[oldSelection][j];
    1230                                 currentX = drawChar(currentChar, currentX, di);
    1231                         }
    1232 
    12331116                        di = currentSelection * 9 + Y + 4;
    12341117
    1235                         gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw);  // black new
     1118                        renderer->drawMenu(commandList, height, X, Y, width, currentSelection);
     1119                        renderer->blit();
    12361120
    1237                         currentX = X + 4;
    1238 
    1239                         for (j = 0; j < strlen(commandList[currentSelection]); j++) {
    1240                                 currentChar = commandList[currentSelection][j];
    1241                                 currentX = drawChar(currentChar, currentX, di);
    1242                         }
    1243 
    1244                         blitRawScreen(page1Raw);
    1245 
    12461121//                      if (needMouseSave) {
    12471122//                              gfxRedrawMouseCursor();
    12481123//                      }
     
    12711146        return currentSelection;
    12721147}
    12731148
    1274 void drawMenuBox(char *command, int16 x, int16 y) {
    1275         byte j;
    1276         byte lColor = 2;
    1277 
    1278         hideMouse();
    1279 
    1280         gfxDrawPlainBoxRaw(x, y, x + 300, y + 10, 0, page2Raw);
    1281 
    1282         drawMessageBox(x, y, 300, y + 6, -1, lColor, page2Raw);
    1283 
    1284         x += 2;
    1285         y += 2;
    1286 
    1287         for (j = 0; j < strlen(command); j++) {
    1288                 byte currentChar = command[j];
    1289 
    1290                 if (currentChar == ' ') {
    1291                         x += 5;
    1292                 } else {
    1293                         byte characterWidth = fontParamTable[currentChar].characterWidth;
    1294 
    1295                         if (characterWidth) {
    1296                                 byte characterIdx = fontParamTable[currentChar].characterIdx;
    1297                                 drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page2Raw, x, y);
    1298                                 x += characterWidth + 1;
    1299                         }
    1300                 }
    1301         }
    1302 
    1303 //      gfxRedrawMouseCursor();
    1304 }
    1305 
    13061149void makeActionMenu(void) {
    13071150        uint16 mouseButton;
    13081151        uint16 mouseX;
     
    13421185        }
    13431186
    13441187        if (allowPlayerInput) {
    1345                 if (isDrawCommandEnabled) {
    1346                         drawMenuBox(commandBuffer, 10, defaultMenuBoxColor);
    1347                         isDrawCommandEnabled = 0;
    1348                 }
    1349 
    13501188                getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY);
    13511189
    13521190                while (mouseButton && currentEntry < 200) {
     
    13931231                                                if (choiceResultTable[playerCommand] == commandVar1) {
    13941232                                                        int16 relEntry;
    13951233
    1396                                                         drawMenuBox(commandBuffer, 10, defaultMenuBoxColor);
    13971234                                                        SelectedObjStruct obj;
    13981235                                                        obj.idx = commandVar3[0];
    13991236                                                        obj.param = commandVar3[1];
     
    14101247
    14111248                                                        commandVar1 = 0;
    14121249                                                        strcpy(commandBuffer, "");
     1250                                                        renderer->setCommand("");
    14131251                                                }
    14141252                                        } else {
    14151253                                                globalVars[VAR_MOUSE_X_POS] = mouseX;
    14161254                                                globalVars[VAR_MOUSE_Y_POS] = mouseY;
    14171255                                        }
    14181256                                }
     1257                        } else if (mouseButton & 2) {
     1258                                if (mouseButton & 1) {
     1259                                        g_cine->makeSystemMenu();
     1260                                }
     1261
     1262                                makeActionMenu();
     1263                                makeCommandLine();
    14191264                        } else {
    1420                                 if (mouseButton & 2) {
    1421                                         if (mouseButton & 1) {
    1422                                                 g_cine->makeSystemMenu();
    1423                                         }
     1265                                int16 objIdx;
    14241266
    1425                                         makeActionMenu();
    1426                                         makeCommandLine();
    1427                                 } else {
    1428                                         int16 objIdx;
     1267                                objIdx = getObjectUnderCursor(mouseX, mouseY);
    14291268
    1430                                         objIdx = getObjectUnderCursor(mouseX, mouseY);
     1269                                if (commandVar2 != objIdx) {
     1270                                        if (objIdx != -1) {
     1271                                                char command[256];
    14311272
    1432                                         if (commandVar2 != objIdx) {
    1433                                                 if (objIdx != -1) {
    1434                                                         char command[256];
     1273                                                strcpy(command, commandBuffer);
     1274                                                strcat(command, " ");
     1275                                                strcat(command, objectTable[objIdx].name);
    14351276
    1436                                                         strcpy(command, commandBuffer);
    1437                                                         strcat(command, " ");
    1438                                                         strcat(command, objectTable[objIdx].name);
    1439 
    1440                                                         drawMenuBox(command, 10, defaultMenuBoxColor);
    1441                                                 } else {
    1442                                                         isDrawCommandEnabled = 1;
    1443                                                 }
     1277                                                renderer->setCommand(command);
     1278                                        } else {
     1279                                                isDrawCommandEnabled = 1;
    14441280                                        }
    1445 
    1446                                         commandVar2 = objIdx;
    14471281                                }
     1282
     1283                                commandVar2 = objIdx;
    14481284                        }
    14491285                } else {
    14501286                        if (mouseButton & 2) {
     
    16531489        free(msk);
    16541490}
    16551491
    1656 int16 additionalBgVScroll = 0;
    1657 
    1658 void backupOverlayPage(void) {
    1659         byte *scrollBg;
    1660         byte *bgPage = additionalBgTable[currentAdditionalBgIdx];
    1661 
    1662         if (bgPage) {
    1663                 if (!additionalBgVScroll) {
    1664                         memcpy(page1Raw, bgPage, 320 * 200);
    1665                 } else {
    1666                         scrollBg = additionalBgTable[currentAdditionalBgIdx2];
    1667 
    1668                         for (int16 i = additionalBgVScroll; i < 200 + additionalBgVScroll; i++) {
    1669                                 if (i > 200) {
    1670                                         memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320);
    1671                                 } else {
    1672                                         memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320);
    1673                                 }
    1674                         }
    1675                 }
    1676         }
    1677 }
    1678 
    1679 void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 color) {
    1680         byte color2 = 2;
    1681         byte endOfMessageReached = 0;
    1682         int16 localX, localY, localWidth;
    1683         uint16 messageLength = 0, numWords = 0, messageWidth = 0;
    1684         uint16 lineResult, fullLineWidth;
    1685         uint16 interWordSize, interWordSizeRemain;
    1686         const char *endOfMessagePtr;
    1687         byte currentChar; //, characterWidth;
    1688 
    1689         gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw);
    1690 
    1691         localX = x + 4;
    1692         localY = y + 4;
    1693         localWidth = width - 8;
    1694 
    1695         do {
    1696                 messageLength = 0;
    1697 
    1698                 while (messagePtr[messageLength] == ' ') {
    1699                         messageLength++;
    1700                 }
    1701 
    1702                 messagePtr += messageLength;
    1703 
    1704                 messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult);
    1705 
    1706                 endOfMessagePtr = messagePtr + messageLength;
    1707 
    1708                 if (lineResult) {
    1709                         fullLineWidth = localWidth - messageWidth;
    1710 
    1711                         if (numWords) {
    1712                                 interWordSize = fullLineWidth / numWords;
    1713                                 interWordSizeRemain = fullLineWidth % numWords;
    1714                         } else {
    1715                                 interWordSize = 5;
    1716                                 interWordSizeRemain = 0;
    1717                         }
    1718                 } else {
    1719                         interWordSize = 5;
    1720                         interWordSizeRemain = 0;
    1721                 }
    1722 
    1723                 gfxDrawPlainBoxRaw(x, localY, x + width, localY + 9, color, page1Raw);
    1724 
    1725                 do {
    1726                         currentChar = *(messagePtr++);
    1727 
    1728                         if (currentChar == 0) {
    1729                                 endOfMessageReached = 1;
    1730                         } else if (currentChar == ' ') {
    1731                                 localX += interWordSizeRemain + interWordSize;
    1732 
    1733                                 if (interWordSizeRemain)
    1734                                         interWordSizeRemain = 0;
    1735                         } else {
    1736                                 localX = drawChar(currentChar, localX, localY);
    1737                         }
    1738                 } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
    1739 
    1740                 localX = x + 4;
    1741                 localY += 9;
    1742         } while (!endOfMessageReached);
    1743 
    1744         gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color, page1Raw);
    1745 
    1746         drawDoubleMessageBox(x, y, width, localY, color2, page1Raw);
    1747 }
    1748 
    1749 void drawDialogueMessage(byte msgIdx, int16 x, int16 y, int16 width, int16 color) {
    1750         if (msgIdx >= messageTable.size()) {
    1751 //              removeOverlay(msgIdx, 2);
    1752                 return;
    1753         }
    1754 
    1755         _messageLen += messageTable[msgIdx].size();
    1756         drawMessage(messageTable[msgIdx].c_str(), x, y, width, color);
    1757 
    1758         // this invalidates the iterator in drawOverlays()
    1759 //      removeOverlay(msgIdx, 2);
    1760 }
    1761 
    1762 void drawFailureMessage(byte cmd) {
    1763         byte msgIdx = cmd * 4 + g_cine->_rnd.getRandomNumber(3);
    1764 
    1765         const char *messagePtr = failureMessages[msgIdx];
    1766         int len = strlen(messagePtr);
    1767 
    1768         _messageLen += len;
    1769 
    1770         int16 width = 6 * len + 20;
    1771 
    1772         if (width > 300)
    1773                 width = 300;
    1774 
    1775         int16 x = (320 - width) / 2;
    1776         int16 y = 80;
    1777         int16 color = 4;
    1778 
    1779         drawMessage(messagePtr, x, y, width, color);
    1780 
    1781         // this invalidates the iterator in drawOverlays()
    1782 //      removeOverlay(cmd, 3);
    1783 }
    1784 
    1785 void drawOverlays(void) {
    1786         uint16 width, height;
    1787         AnimData *pPart;
    1788         int16 x, y;
    1789         objectStruct *objPtr;
    1790         byte messageIdx;
     1492void removeMessages() {
    17911493        Common::List<overlay>::iterator it;
    17921494
    1793         backupOverlayPage();
    1794 
    1795         _messageLen = 0;
    1796 
    1797         for (it = overlayList.begin(); it != overlayList.end(); ++it) {
    1798                 switch (it->type) {
    1799                 case 0: // sprite
    1800                         assert(it->objIdx < NUM_MAX_OBJECT);
    1801 
    1802                         objPtr = &objectTable[it->objIdx];
    1803                         x = objPtr->x;
    1804                         y = objPtr->y;
    1805 
    1806                         if (objPtr->frame < 0) {
    1807                                 continue;
    1808                         }
    1809 
    1810                         pPart = &animDataTable[objPtr->frame];
    1811                         width = pPart->_realWidth;
    1812                         height = pPart->_height;
    1813 
    1814                         if (!pPart->data()) {
    1815                                 continue;
    1816                         }
    1817 
    1818                         // drawSprite ignores masks of Operation Stealth sprites
    1819                         drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y);
    1820                         break;
    1821 
    1822                 case 2: // text
    1823                         // gfxWaitVSync();
    1824                         // hideMouse();
    1825 
    1826                         messageIdx = it->objIdx;
    1827                         x = it->x;
    1828                         y = it->y;
    1829                         width = it->width;
    1830                         height = it->color;
    1831 
    1832                         blitRawScreen(page1Raw);
    1833 
    1834                         drawDialogueMessage(messageIdx, x, y, width, height);
    1835 
    1836                         // blitScreen(page0, NULL);
    1837                         // gfxRedrawMouseCursor();
    1838 
    1839                         waitForPlayerClick = 1;
    1840 
    1841                         break;
    1842 
    1843                 case 3:
    1844                         // gfxWaitSync()
    1845                         // hideMouse();
    1846 
    1847                         blitRawScreen(page1Raw);
    1848 
    1849                         drawFailureMessage(it->objIdx);
    1850 
    1851                         // blitScreen(page0, NULL);
    1852                         // gfxRedrawMouseCursor();
    1853 
    1854                         waitForPlayerClick = 1;
    1855 
    1856                         break;
    1857 
    1858                 case 4:
    1859                         assert(it->objIdx < NUM_MAX_OBJECT);
    1860 
    1861                         objPtr = &objectTable[it->objIdx];
    1862                         x = objPtr->x;
    1863                         y = objPtr->y;
    1864 
    1865                         if (objPtr->frame < 0) {
    1866                                 continue;
    1867                         }
    1868 
    1869                         assert(objPtr->frame < NUM_MAX_ANIMDATA);
    1870 
    1871                         pPart = &animDataTable[objPtr->frame];
    1872 
    1873                         width = pPart->_realWidth;
    1874                         height = pPart->_height;
    1875 
    1876                         if (!pPart->data()) {
    1877                                 continue;
    1878                         }
    1879 
    1880                         gfxFillSprite(pPart->data(), width, height, page1Raw, x, y);
    1881                         break;
    1882 
    1883                 case 20:
    1884                         assert(it->objIdx < NUM_MAX_OBJECT);
    1885 
    1886                         objPtr = &objectTable[it->objIdx];
    1887                         x = objPtr->x;
    1888                         y = objPtr->y;
    1889                         var5 = it->x;
    1890 
    1891                         if (objPtr->frame < 0 || var5 > 8 || !additionalBgTable[var5] || animDataTable[objPtr->frame]._bpp != 1) {
    1892                                 continue;
    1893                         }
    1894 
    1895                         width = animDataTable[objPtr->frame]._realWidth;
    1896                         height = animDataTable[objPtr->frame]._height;
    1897 
    1898                         if (!animDataTable[objPtr->frame].data()) {
    1899                                 continue;
    1900                         }
    1901 
    1902                         maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y);
    1903                         break;
    1904                 }
    1905         }
    1906 
    19071495        for (it = overlayList.begin(); it != overlayList.end(); ) {
    19081496                if (it->type == 2 || it->type == 3) {
    19091497                        it = overlayList.erase(it);
     
    19781566        tmp.color = param5;
    19791567
    19801568        overlayList.push_back(tmp);
     1569        waitForPlayerClick = 1;
    19811570}
    19821571
    1983 SeqListElement seqList;
     1572Common::List<SeqListElement> seqList;
    19841573
    19851574void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
    1986         SeqListElement *currentHead = &seqList;
    1987         SeqListElement *tempHead = currentHead;
     1575        Common::List<SeqListElement>::iterator it;
    19881576
    1989         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    1990                 tempHead = currentHead;
    1991                 currentHead = tempHead->next;
     1577        for (it = seqList.begin(); it != seqList.end(); ++it) {
     1578                if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
     1579                        it->var4 = -1;
     1580                        break;
     1581                }
    19921582        }
    1993 
    1994         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    1995                 currentHead->var4 = -1;
    1996         }
    19971583}
    19981584
    19991585uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
    2000         SeqListElement *currentHead = &seqList;
    2001         SeqListElement *tempHead = currentHead;
     1586        Common::List<SeqListElement>::iterator it;
    20021587
    2003         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    2004                 tempHead = currentHead;
    2005                 currentHead = tempHead->next;
     1588        for (it = seqList.begin(); it != seqList.end(); ++it) {
     1589                if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) {
     1590                        return 1;
     1591                }
    20061592        }
    20071593
    2008         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    2009                 return 1;
    2010         }
    2011 
    20121594        return 0;
    20131595}
    20141596
    2015 void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) {
    2016         SeqListElement *currentHead = &seqList;
    2017         SeqListElement *tempHead = currentHead;
    2018         SeqListElement *newElement;
     1597void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) {
     1598        Common::List<SeqListElement>::iterator it;
     1599        SeqListElement tmp;
    20191600
    2020         currentHead = tempHead->next;
     1601        for (it = seqList.begin(); it != seqList.end() && it->varE < param7; ++it) ;
    20211602
    2022         while (currentHead && currentHead->varE < param7) {
    2023                 tempHead = currentHead;
    2024                 currentHead = tempHead->next;
    2025         }
     1603        tmp.objIdx = objIdx;
     1604        tmp.var4 = param1;
     1605        tmp.var8 = param2;
     1606        tmp.frame = frame;
     1607        tmp.varC = param4;
     1608        tmp.var14 = 0;
     1609        tmp.var16 = 0;
     1610        tmp.var18 = param5;
     1611        tmp.var1A = param6;
     1612        tmp.varE = param7;
     1613        tmp.var10 = param8;
     1614        tmp.var12 = param8;
     1615        tmp.var1C = 0;
     1616        tmp.var1E = 0;
    20261617
    2027         newElement = new SeqListElement;
    2028 
    2029         newElement->next = tempHead->next;
    2030         tempHead->next = newElement;
    2031 
    2032         newElement->var6 = param0;
    2033         newElement->var4 = param1;
    2034         newElement->var8 = param2;
    2035         newElement->varA = param3;
    2036         newElement->varC = param4;
    2037         newElement->var14 = 0;
    2038         newElement->var16 = 0;
    2039         newElement->var18 = param5;
    2040         newElement->var1A = param6;
    2041         newElement->varE = param7;
    2042         newElement->var10 = param8;
    2043         newElement->var12 = param8;
    2044         newElement->var1C = 0;
    2045         newElement->var1E = 0;
     1618        seqList.insert(it, tmp);
    20461619}
    20471620
    2048 void resetSeqList() {
    2049         seqList.next = NULL;
    2050 }
    2051 
    2052 void computeMove1(SeqListElement *element, int16 x, int16 y, int16 param1,
     1621void computeMove1(SeqListElement &element, int16 x, int16 y, int16 param1,
    20531622    int16 param2, int16 x2, int16 y2) {
    2054         element->var16 = 0;
    2055         element->var14 = 0;
     1623        element.var16 = 0;
     1624        element.var14 = 0;
    20561625
    20571626        if (y2) {
    20581627                if (y - param2 > y2) {
    2059                         element->var16 = 2;
     1628                        element.var16 = 2;
    20601629                }
    20611630
    20621631                if (y + param2 < y2) {
    2063                         element->var16 = 1;
     1632                        element.var16 = 1;
    20641633                }
    20651634        }
    20661635
    20671636        if (x2) {
    20681637                if (x - param1 > x2) {
    2069                         element->var14 = 2;
     1638                        element.var14 = 2;
    20701639                }
    20711640
    20721641                if (x + param1 < x2) {
    2073                         element->var14 = 1;
     1642                        element.var14 = 1;
    20741643                }
    20751644        }
    20761645}
    20771646
    2078 uint16 computeMove2(SeqListElement *element) {
     1647uint16 computeMove2(SeqListElement &element) {
    20791648        int16 returnVar = 0;
    20801649
    2081         if (element->var16 == 1) {
     1650        if (element.var16 == 1) {
    20821651                returnVar = 4;
    2083         } else if (element->var16 == 2) {
     1652        } else if (element.var16 == 2) {
    20841653                returnVar = 3;
    20851654        }
    20861655
    2087         if (element->var14 == 1) {
     1656        if (element.var14 == 1) {
    20881657                returnVar = 1;
    2089         } else if (element->var14 == 2) {
     1658        } else if (element.var14 == 2) {
    20901659                returnVar = 2;
    20911660        }
    20921661
     
    21651734#endif
    21661735}
    21671736
    2168 uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
     1737uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &element, uint16 param3, int16 *param4) {
    21691738        const byte *currentPtr = ptr;
    21701739        const byte *ptrData;
    21711740        const byte *ptr2;
    21721741        int16 di;
    21731742
    21741743        assert(ptr);
    2175         assert(element);
    21761744        assert(param4);
    21771745
    21781746        dummyU16 = READ_BE_UINT16((currentPtr + param1 * 2) + 8);
     
    21811749
    21821750        assert(*ptrData);
    21831751
    2184         di = (objectTable[param2].costume + 1) % (*ptrData);
     1752        di = (objectTable[objIdx].costume + 1) % (*ptrData);
    21851753        ptr2 = (ptrData + (di * 8)) + 1;
    21861754
    2187         if ((checkCollision(param2, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) {
     1755        if ((checkCollision(objIdx, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) {
    21881756                return 0;
    21891757        }
    21901758
    2191         objectTable[param2].x += (int8)ptr2[4];
    2192         objectTable[param2].y += (int8)ptr2[5];
    2193         objectTable[param2].mask += (int8)ptr2[6];
     1759        objectTable[objIdx].x += (int8)ptr2[4];
     1760        objectTable[objIdx].y += (int8)ptr2[5];
     1761        objectTable[objIdx].mask += (int8)ptr2[6];
    21941762
    2195         if (objectTable[param2].frame) {
    2196                 resetGfxEntityEntry(param2);
     1763        if (objectTable[objIdx].frame) {
     1764                resetGfxEntityEntry(objIdx);
    21971765        }
    21981766
    2199         objectTable[param2].frame = ptr2[7] + element->var8;
     1767        objectTable[objIdx].frame = ptr2[7] + element.var8;
    22001768
    2201         if (param3 || !element->var14) {
    2202                 objectTable[param2].costume = di;
     1769        if (param3 || !element.var14) {
     1770                objectTable[objIdx].costume = di;
    22031771        } else {
    22041772                *param4 = di;
    22051773        }
     
    22071775        return 1;
    22081776}
    22091777
    2210 void processSeqListElement(SeqListElement *element) {
    2211         int16 x = objectTable[element->var6].x;
    2212         int16 y = objectTable[element->var6].y;
    2213         const byte *ptr1 = animDataTable[element->varA].data();
     1778void processSeqListElement(SeqListElement &element) {
     1779        int16 x = objectTable[element.objIdx].x;
     1780        int16 y = objectTable[element.objIdx].y;
     1781        const byte *ptr1 = animDataTable[element.frame].data();
    22141782        int16 var_10;
    22151783        int16 var_4;
    22161784        int16 var_2;
    22171785
    2218         if (element->var12 < element->var10) {
    2219                 element->var12++;
     1786        if (element.var12 < element.var10) {
     1787                element.var12++;
    22201788                return;
    22211789        }
    22221790
    2223         element->var12 = 0;
     1791        element.var12 = 0;
    22241792
    22251793        if (ptr1) {
    22261794                uint16 param1 = ptr1[1];
    22271795                uint16 param2 = ptr1[2];
    22281796
    2229                 if (element->varC != 255) {
     1797                if (element.varC != 255) {
    22301798                        // FIXME: Why is this here? Fingolfin gets lots of these
    22311799                        // in his copy of Operation Stealth (value 0 or 236) under
    22321800                        // Mac OS X. Maybe it's a endian issue? At least the graphics
    22331801                        // in the copy protection screen are partially messed up.
    2234                         warning("processSeqListElement: varC = %d", element->varC);
     1802                        warning("processSeqListElement: varC = %d", element.varC);
    22351803                }
    22361804
    22371805                if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) {
    22381806                        computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]);
    22391807                } else {
    2240                         element->var16 = 0;
    2241                         element->var14 = 0;
     1808                        element.var16 = 0;
     1809                        element.var14 = 0;
    22421810                }
    22431811
    22441812                var_10 = computeMove2(element);
    22451813
    22461814                if (var_10) {
    2247                         element->var1C = var_10;
    2248                         element->var1E = var_10;
     1815                        element.var1C = var_10;
     1816                        element.var1E = var_10;
    22491817                }
    22501818
    22511819                var_4 = -1;
    22521820
    2253                 if ((element->var16 == 1
    2254                         && !addAni(3, element->var6, ptr1, element, 0, &var_4)) || (element->var16 == 2 && !addAni(2, element->var6, ptr1, element, 0,
     1821                if ((element.var16 == 1
     1822                        && !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0,
    22551823                            &var_4))) {
    2256                         if (element->varC == 255) {
     1824                        if (element.varC == 255) {
    22571825                                globalVars[VAR_MOUSE_Y_POS] = 0;
    22581826                        }
    22591827                }
    22601828
    2261                 if ((element->var14 == 1
    2262                         && !addAni(0, element->var6, ptr1, element, 1, &var_2))) {
    2263                         if (element->varC == 255) {
     1829                if ((element.var14 == 1
     1830                        && !addAni(0, element.objIdx, ptr1, element, 1, &var_2))) {
     1831                        if (element.varC == 255) {
    22641832                                globalVars[VAR_MOUSE_X_POS] = 0;
    22651833
    22661834                                if (var_4 != -1) {
    2267                                         objectTable[element->var6].costume = var_4;
     1835                                        objectTable[element.objIdx].costume = var_4;
    22681836                                }
    22691837                        }
    22701838                }
    22711839
    2272                 if ((element->var14 == 2 && !addAni(1, element->var6, ptr1, element, 1, &var_2))) {
    2273                         if (element->varC == 255) {
     1840                if ((element.var14 == 2 && !addAni(1, element.objIdx, ptr1, element, 1, &var_2))) {
     1841                        if (element.varC == 255) {
    22741842                                globalVars[VAR_MOUSE_X_POS] = 0;
    22751843
    22761844                                if (var_4 != -1) {
    2277                                         objectTable[element->var6].costume = var_4;
     1845                                        objectTable[element.objIdx].costume = var_4;
    22781846                                }
    22791847                        }
    22801848                }
    22811849
    2282                 if (element->var16 + element->var14) {
    2283                         if (element->var1C) {
    2284                                 if (element->var1E) {
    2285                                         objectTable[element->var6].costume = 0;
    2286                                         element->var1E = 0;
     1850                if (element.var16 + element.var14) {
     1851                        if (element.var1C) {
     1852                                if (element.var1E) {
     1853                                        objectTable[element.objIdx].costume = 0;
     1854                                        element.var1E = 0;
    22871855                                }
    22881856
    2289                                 addAni(element->var1C + 3, element->var6, ptr1, element, 1, (int16 *) & var2);
     1857                                addAni(element.var1C + 3, element.objIdx, ptr1, element, 1, (int16 *) & var2);
    22901858
    22911859                        }
    22921860                }
     
    22951863}
    22961864
    22971865void processSeqList(void) {
    2298         SeqListElement *currentHead = &seqList;
    2299         SeqListElement *tempHead = currentHead;
     1866        Common::List<SeqListElement>::iterator it;
    23001867
    2301         currentHead = tempHead->next;
    2302 
    2303         while (currentHead) {
    2304                 if (currentHead->var4 != -1) {
    2305                         processSeqListElement(currentHead);
     1868        for (it = seqList.begin(); it != seqList.end(); ++it) {
     1869                if (it->var4 == -1) {
     1870                        continue;
    23061871                }
    23071872
    2308                 tempHead = currentHead;
    2309                 currentHead = tempHead->next;
     1873                processSeqListElement(*it);
    23101874        }
    23111875}
    23121876
    23131877
    23141878bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxLength, int y) {
    2315         int16 color = 2;
    2316         byte color2 = defaultMenuBoxColor2;
    2317         byte endOfMessageReached = 0;
    2318         int16 localX, localY, localWidth;
    2319         int margins = 16;
    23201879        int len = strlen(messagePtr);
    23211880        int16 width = 6 * len + 20;
    2322         uint16 messageLength = 0, numWords = 0, messageWidth = 0;
    2323         uint16 lineResult, fullLineWidth;
    2324         uint16 interWordSize, interWordSizeRemain;
    2325         const char *endOfMessagePtr;
    2326         byte currentChar, characterWidth;
    23271881
    23281882        width = CLIP((int)width, 180, 250);
    23291883
    23301884        int16 x = (320 - width) / 2;
    23311885
    2332         gfxDrawPlainBoxRaw(x - margins, y, x + width + margins, y + 4, color2, page1Raw);
    2333 
    2334         localX = x + 4;
    2335         localY = y + 4;
    2336         localWidth = width;
    2337 
    23381886        getKeyData(); // clear input key
    23391887
    2340         do {
    2341                 messageLength = 0;
    2342 
    2343                 while (messagePtr[messageLength] == ' ') {
    2344                         messageLength++;
    2345                 }
    2346 
    2347                 messagePtr += messageLength;
    2348 
    2349                 messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult);
    2350 
    2351                 endOfMessagePtr = messagePtr + messageLength;
    2352 
    2353                 if (lineResult) {
    2354                         fullLineWidth = localWidth - messageWidth;
    2355 
    2356                         if (numWords) {
    2357                                 interWordSize = fullLineWidth / numWords;
    2358                                 interWordSizeRemain = fullLineWidth % numWords;
    2359                         } else {
    2360                                 interWordSize = 5;
    2361                                 interWordSizeRemain = 0;
    2362                         }
    2363                 } else {
    2364                         interWordSize = 5;
    2365                         interWordSizeRemain = 0;
    2366                 }
    2367 
    2368                 gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw);
    2369 
    2370                 do {
    2371                         currentChar = *(messagePtr++);
    2372 
    2373                         if (currentChar == 0) {
    2374                                 endOfMessageReached = 1;
    2375                         } else if (currentChar == ' ') {
    2376                                 localX += interWordSizeRemain + interWordSize;
    2377 
    2378                                 if (interWordSizeRemain)
    2379                                         interWordSizeRemain = 0;
    2380                         } else {
    2381                                 characterWidth = fontParamTable[currentChar].characterWidth;
    2382 
    2383                                 if (characterWidth) {
    2384                                         byte characterIdx = fontParamTable[currentChar].characterIdx;
    2385                                         drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY);
    2386                                         localX += characterWidth + 1;
    2387                                 }
    2388                         }
    2389                 } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
    2390 
    2391                 localX = x + 4;
    2392                 localY += 9;
    2393         } while (!endOfMessageReached);
    2394 
    2395         // Input string
    2396         gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw);
    2397         localY += 9;
    2398 
    2399         x -= margins;
    2400         width += margins * 2;
    2401 
    2402         gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color2, page1Raw);
    2403 
    2404         drawDoubleMessageBox(x, y, width, localY, color, page1Raw);
    2405 
    2406         x += margins;
    2407         width -= margins * 2;
    2408         localY -= 9;
    2409 
    2410 
    24111888        int quit = 0;
    24121889        bool redraw = true;
    24131890        CommandeType tempString;
     
    24161893
    24171894        while (!quit) {
    24181895                if (redraw) {
    2419                         gfxDrawPlainBoxRaw(x, localY - 1, x + width, localY + 8, 0, page1Raw);
    2420 
    2421                         int currentX = x + 4;
    2422 
    2423                         for (uint j = 0; j < strlen(inputString); j++) {
    2424                                 currentChar = inputString[j];
    2425                                 currentX = drawChar(currentChar, currentX, localY);
    2426 
    2427                                 // draw cursor here
    2428                                 if (inputPos == (int)(j + 2))
    2429                                         gfxDrawLine(currentX, localY - 1, currentX, localY + 8, color, page1Raw);
    2430 
    2431                         }
    2432 
    2433                         if (strlen(inputString) == 0 || inputPos == 1) // cursor wasn't yet drawn
    2434                                 gfxDrawLine(x + 4, localY - 1, x + 4, localY + 8, color, page1Raw);
    2435 
    2436                         blitRawScreen(page1Raw);
     1896                        renderer->drawInputBox(messagePtr, inputString, inputPos, x - 16, y, width + 32);
     1897                        renderer->blit();
    24371898                        redraw = false;
    24381899                }
    24391900
  • engines/cine/gfx.h

     
    2626#ifndef CINE_GFX_H
    2727#define CINE_GFX_H
    2828
     29#include "common/noncopyable.h"
     30#include "cine/object.h"
     31
    2932namespace Cine {
    3033
     34/*! \brief Background with palette
     35 */
     36struct palBg {
     37        byte *bg; ///< Background data
     38        byte *hiPal; ///< 256 color palette
     39        uint16 *lowPal; ///< 16 color palette
     40        char name[15]; ///< Background filename
     41};
     42
     43/*! \brief Future Wars renderer
     44 *
     45 * Screen backbuffer is not cleared between frames, you can draw menus etc.
     46 * without calling drawFrame() all the time
     47 */
     48class FWRenderer : public Common::NonCopyable {
     49private:
     50        byte *_background; ///< Current background
     51        char _bgName[13]; ///< Background filename
     52        uint16 *_palette; ///< 16 color backup palette
     53
     54        Common::String _cmd; ///< Player command string
     55
     56protected:
     57        static const int _screenSize = 320 * 200; ///< Screen size
     58        static const int _screenWidth = 320; ///< Screen width
     59        static const int _screenHeight = 200; ///< Screen height
     60        static const int _lowPalSize = 16; ///< 16 color palette size
     61
     62        byte *_backBuffer; ///< Screen backbuffer
     63        uint16 *_activeLowPal; ///< Active 16 color palette
     64        int _changePal; ///< Load active palette to video backend on next frame
     65
     66        void fillSprite(const objectStruct &obj, uint8 color = 0);
     67        void drawMaskedSprite(const objectStruct &obj, const byte *mask);
     68        virtual void drawSprite(const objectStruct &obj);
     69
     70        void drawCommand();
     71        void drawMessage(const char *str, int x, int y, int width, byte color);
     72        void drawPlainBox(int x, int y, int width, int height, byte color);
     73        void drawBorder(int x, int y, int width, int height, byte color);
     74        void drawDoubleBorder(int x, int y, int width, int height, byte color);
     75        virtual int drawChar(char character, int x, int y);
     76        void drawLine(int x, int y, int width, int height, byte color);
     77        void remaskSprite(byte *mask, Common::List<overlay>::iterator it);
     78        virtual void drawBackground();
     79
     80        virtual void renderOverlay(const Common::List<overlay>::iterator &it);
     81        void drawOverlays();
     82
     83public:
     84        uint16 _messageBg; ///< Message box background color
     85        uint16 _cmdY; ///< Player command string position on screen
     86
     87        FWRenderer();
     88        virtual ~FWRenderer();
     89
     90        /*! \brief Test if renderer is ready to draw */
     91        virtual bool ready() { return _background != NULL; }
     92
     93        virtual void clear();
     94
     95        void drawFrame();
     96        void blit();
     97        void setCommand(const char *cmd);
     98
     99        virtual void incrustMask(const objectStruct &obj, uint8 color = 0);
     100        virtual void incrustSprite(const objectStruct &obj);
     101
     102        virtual void loadBg16(const byte *bg, const char *name);
     103        virtual void loadBg16(const byte *bg, const char *name, unsigned int idx);
     104        virtual void loadCt16(const byte *ct, const char *name);
     105        virtual void loadBg256(const byte *bg, const char *name);
     106        virtual void loadBg256(const byte *bg, const char *name, unsigned int idx);
     107        virtual void loadCt256(const byte *ct, const char *name);
     108        virtual void selectBg(unsigned int idx);
     109        virtual void selectScrollBg(unsigned int idx);
     110        virtual void setScroll(unsigned int shift);
     111        virtual void removeBg(unsigned int idx);
     112        void saveBg(Common::OutSaveFile &fHandle);
     113
     114        virtual void refreshPalette();
     115        virtual void reloadPalette();
     116        void restorePalette(Common::InSaveFile &fHandle);
     117        void savePalette(Common::OutSaveFile &fHandle);
     118        virtual void rotatePalette(int a, int b, int c);
     119        virtual void transformPalette(int first, int last, int r, int g, int b);
     120
     121        void drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected);
     122        void drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width);
     123
     124        virtual void fadeToBlack();
     125};
     126
     127/*! \brief Operation Stealth renderer
     128 */
     129class OSRenderer : public FWRenderer {
     130private:
     131        palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer
     132        byte *_activeHiPal; ///< Active 256 color palette
     133        unsigned int _currentBg; ///< Current background
     134        unsigned int _scrollBg; ///< Current scroll background
     135        unsigned int _bgShift; ///< Background shift
     136
     137protected:
     138        static const int _hiPalSize = 256 * 3; ///< 256 color palette size
     139
     140        void drawSprite(const objectStruct &obj);
     141        int drawChar(char character, int x, int y);
     142        void drawBackground();
     143        void renderOverlay(const Common::List<overlay>::iterator &it);
     144
     145public:
     146        OSRenderer();
     147        ~OSRenderer();
     148
     149        /*! \brief Test if renderer is ready to draw */
     150        bool ready() { return _bgTable[_currentBg].bg != NULL; }
     151
     152        void clear();
     153
     154        void incrustMask(const objectStruct &obj, uint8 color = 0);
     155        void incrustSprite(const objectStruct &obj);
     156
     157        void loadBg16(const byte *bg, const char *name);
     158        void loadBg16(const byte *bg, const char *name, unsigned int idx);
     159        void loadCt16(const byte *ct, const char *name);
     160        void loadBg256(const byte *bg, const char *name);
     161        void loadBg256(const byte *bg, const char *name, unsigned int idx);
     162        void loadCt256(const byte *ct, const char *name);
     163        void selectBg(unsigned int idx);
     164        void selectScrollBg(unsigned int idx);
     165        void setScroll(unsigned int shift);
     166        void removeBg(unsigned int idx);
     167
     168        void refreshPalette();
     169        void reloadPalette();
     170        void rotatePalette(int a, int b, int c);
     171        void transformPalette(int first, int last, int r, int g, int b);
     172
     173        void fadeToBlack();
     174};
     175
    31176void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy);
    32177
    33 extern byte *page1Raw;
    34 extern byte *page2Raw;
    35178extern byte *page3Raw;
     179extern FWRenderer *renderer;
    36180
    37 extern uint16 c_palette[256];
    38 extern byte colorMode256;
    39 extern byte palette256[256 * 3];
    40 extern byte newPalette[256 * 3];
    41 extern byte newColorMode;
    42 extern byte ctColorMode;
    43 extern byte bgColorMode;
    44 
    45 void gfxInit();
    46 void gfxDestroy();
    47181void setMouseCursor(int cursor);
    48182void gfxCopyPage(byte *source, byte *dest);
    49183
  • engines/cine/bg.h

     
    2727#define CINE_BG_H
    2828
    2929namespace Cine {
    30 struct bgData {
    31         byte *data;
    32         byte colorMode;
    33         byte *highPalette;
    34         uint16 *lowPalette;
    35 };
    36 
    3730byte loadBg(const char *bgName);
    38 byte loadCt(const char *bgName);
     31byte loadCtFW(const char *bgName);
     32byte loadCtOS(const char *bgName);
    3933
    40 //extern bgData additionalBgTable[9];
    41 extern byte *additionalBgTable[9];
    42 extern byte currentAdditionalBgIdx;
    43 extern byte currentAdditionalBgIdx2;
    44 
    4534void addBackground(const char *bgName, uint16 bgIdx);
    4635
    4736extern uint16 bgVar0;
  • engines/cine/texte.h

     
    5656void loadPoldatDat(const char *fname);
    5757void freePoldatDat(void);
    5858
    59 uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult);
     59int fitLine(const char *ptr, int maxWidth, int &words, int &width);
    6060
    6161} // End of namespace Cine
    6262
  • engines/cine/xref.txt

     
    1 script.cpp:
     1script_fw.cpp:
    22setupOpcodes() - replaced with FWScript/OSScript class members
    33getNextByte() - replaced with RawScript/FWScript class members
    44getNextWord() - replaced with RawScript/FWScript class members
     
    8989o1_loadMask5() - replaced with FWScript::o1_loadMask5()
    9090o1_unloadMask5() - replaced with FWScript::o1_unloadMask5()
    9191
     92palRotate() - modified and moved to pal.cpp
     93
     94script_os.cpp:
    9295o2_loadPart() - replaced with FWScript::o2_loadPart()
    9396o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement()
    9497o2_removeSeq() - replaced with FWScript::o2_removeSeq()
     
    134137various.cpp:
    135138setupScriptList() - removed (obsoleted by new makeLoad() and
    136139        loadScriptFromSave() implementation)
     140drawChar() - removed (obsoleted by FWRenderer::drawChar())
     141makeTextEntry() - removed (obsoleted by FWRenderer::drawMenu())
     142drawMenuBox() - removed (obsoleted by FWRenderer::drawCommand())
     143backupOverlayPage() - removed (obsoleted by FWRenderer::drawBackground())
     144drawMessage() - removed (obsoleted by FWRenderer::drawMessage())
     145drawDialogueMessage() - removed (obsoleted by FWRenderer::renderOverlay())
     146drawFailureMessage() - removed (obsoleted by FWRenderer::renderOverlay())
     147drawOverlays() - removed (obsoleted by FWRenderer::drawOverlays())
     148resetSeqList() - removed (obsoleted by Common::List)
    137149
    138150anim.cpp:
    139151freeAnimData() - replaced with animData::clear()
    140152allocFrame() - replaced with animData::load()
    141153reserveFrame() - replaced with animData::load()
    142154
    143 bg_list.cpp
     155bg_list.cpp:
    144156reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
    145157        loadBgIncrustFromSave() implementation)
    146158freeBgIncrustList() - removed (obsoleted by Common::List::clear())
    147159
    148 object.cpp
     160object.cpp:
    149161unloadAllMasks() - removed (obsoleted by Common::List::clear())
    150162resetMessageHead() - removed (obsoleted by Common::List)
    151163freeOverlay() - removed (duplicate of removeOverlay)
    152164removeOverlayElement() - renamed to removeOverlay
    153165loadOverlayElement() - renamed to addOverlay
     166
     167gfx.cpp:
     168gfxInit() - removed (obsoleted by FWRenderer)
     169gfxDestroy() - removed (obsoleted by FWRenderer)
     170transformColor() - moved to pal.cpp
     171transformPaletteRange() - modified and moved to pal.cpp
     172gfxCopyRawPage() - removed (obsoleted by FWRenderer)
     173gfxFlipRawPage() - removed (obsoleted by FWRenderer::blit() and
     174        FWRenderer::refreshPalette())
     175fadeToBlack() - removed (obsoleted by FWRenderer::fadeToBlack())
     176blitRawScreen() - removed (obsoleted by FWRenderer)
     177flip() - removed (obsoleted by FWRenderer::reloadPalette())
     178
     179bg.cpp:
     180loadCt() - split into loadCtFW() and loadCtOS()
     181loadBgHigh() - removed (obsoleted by OSRenderer::loadBg256())
     182
     183texte.cpp:
     184computeMessageLength() - replaced with fitLine()
  • engines/cine/script_os.cpp

     
    116116        { &FWScript::o1_loadAnim, "s" },
    117117        /* 3C */
    118118        { &FWScript::o1_loadBg, "s" },
    119         { &FWScript::o1_loadCt, "s" },
     119        { &FWScript::o2_loadCt, "s" },
    120120        { 0, 0 },
    121121        { &FWScript::o2_loadPart, "s" },
    122122        /* 40 */
     
    365365// OPERATION STEALTH opcodes
    366366// ------------------------------------------------------------------------
    367367
     368int FWScript::o2_loadCt() {
     369        const char *param = getNextString();
     370
     371        debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
     372        loadCtOS(param);
     373        return 0;
     374}
     375
    368376int FWScript::o2_loadPart() {
    369377        const char *param = getNextString();
    370378
     
    615623
    616624        debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
    617625
    618         if (additionalBgTable[param]) {
    619                 free(additionalBgTable[param]);
    620                 additionalBgTable[param] = NULL;
    621         }
    622 
    623         if (currentAdditionalBgIdx == param) {
    624                 currentAdditionalBgIdx = 0;
    625         }
    626 
    627         if (currentAdditionalBgIdx2 == param) {
    628                 currentAdditionalBgIdx2 = 0;
    629         }
    630 
    631         strcpy(currentBgName[param], "");
     626        renderer->removeBg(param);
    632627        return 0;
    633628}
    634629
     
    644639int FWScript::o2_loadBg() {
    645640        byte param = getNextByte();
    646641
    647         assert(param <= 8);
     642        assert(param < 9);
    648643
    649644        debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
    650645
    651         if (additionalBgTable[param]) {
    652                 currentAdditionalBgIdx = param;
    653                 if (param == 8) {
    654                         newColorMode = 3;
    655                 } else {
    656                         newColorMode = bgColorMode + 1;
    657                 }
    658                 //if (_screenNeedFadeOut == 0) {
    659                 //      adBgVar1 = 1;
    660                 //}
    661                 fadeRequired = true;
    662         }
     646        renderer->selectBg(param);
    663647        return 0;
    664648}
    665649
     
    699683int FWScript::o2_useBgScroll() {
    700684        byte param = getNextByte();
    701685
    702         assert(param <= 8);
     686        assert(param < 9);
    703687
    704688        debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
    705689
    706         if (additionalBgTable[param]) {
    707                 currentAdditionalBgIdx2 = param;
    708         }
     690        renderer->selectScrollBg(param);
    709691        return 0;
    710692}
    711693
     
    716698                byte param2 = getNextByte();
    717699
    718700                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
    719                 additionalBgVScroll = _localVars[param2];
     701                renderer->setScroll(_localVars[param2]);
    720702        } else {
    721703                uint16 param2 = getNextWord();
    722704
    723705                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
    724                 additionalBgVScroll = param2;
     706                renderer->setScroll(param2);
    725707        }
    726708        return 0;
    727709}
  • engines/cine/object.cpp

     
    236236        return compareResult;
    237237}
    238238
     239/*! \bug In Operation Stealth, if you try to go downstairs to the sea in the
     240 * location between bank and hotel, getObjectParam is called with paramIdx 16
     241 * and crashes
     242 */
    239243int16 getObjectParam(uint16 objIdx, uint16 paramIdx) {
    240244        assert(objIdx <= NUM_MAX_OBJECT);
    241245
  • engines/cine/main_loop.cpp

     
    182182void CineEngine::mainLoop(int bootScriptIdx) {
    183183        bool playerAction;
    184184        uint16 quitFlag;
    185         uint16 i;
    186185        byte di;
    187186        uint16 mouseButton;
    188187
    189188        quitFlag = 0;
    190189
    191190        if (_preLoad == false) {
    192                 resetSeqList();
    193191                resetBgIncrustList();
    194192
    195193                setTextWindow(0, 0, 20, 200);
     
    223221                        globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
    224222                }
    225223
    226                 for (i = 0; i < 16; i++) {
    227                         c_palette[i] = 0;
    228                 }
    229 
    230                 _paletteNeedUpdate = true;
    231 
    232224                strcpy(newPrcName, "");
    233225                strcpy(newRelName, "");
    234226                strcpy(newObjectName, "");
    235227                strcpy(newMsgName, "");
    236                 strcpy(currentBgName[0], "");
    237228                strcpy(currentCtName, "");
    238229                strcpy(currentPartName, "");
    239230
     
    257248                        setMouseCursor(MOUSE_CURSOR_CROSS);
    258249                }
    259250
    260                 drawOverlays();
    261                 flip();
     251                if (renderer->ready()) {
     252                        renderer->drawFrame();
     253                }
    262254
    263255                if (waitForPlayerClick) {
    264256                        playerAction = false;
     
    289281                        } while (mouseButton != 0);
    290282
    291283                        waitForPlayerClick = 0;
     284
     285                        removeMessages();
    292286                }
    293287
    294288                if (checkForPendingDataLoadSwitch) {
  • engines/cine/cine.cpp

     
    9595int CineEngine::go() {
    9696        CursorMan.showMouse(true);
    9797        mainLoop(1);
    98         gfxDestroy();
     98
     99        delete renderer;
     100        delete[] page3Raw;
    99101        delete g_sound;
    100102        return 0;
    101103}
     
    105107        setupOpcodes();
    106108
    107109        initLanguage(g_cine->getLanguage());
    108         gfxInit();
    109110
     111        if (g_cine->getGameType() == Cine::GType_OS) {
     112                renderer = new OSRenderer;
     113        } else {
     114                renderer = new FWRenderer;
     115        }
     116
     117        page3Raw = new byte[320 * 200];
    110118        textDataPtr = (byte *)malloc(8000);
    111119
    112120        partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer));
  • engines/cine/pal.h

     
    3636
    3737void loadPal(const char *fileName);
    3838
    39 extern uint16 tempPalette[256];
    40 
    4139void loadRelatedPalette(const char *fileName);
    4240
     41void palRotate(uint16 *pal, byte a, byte b, byte c);
     42void palRotate(byte *pal, byte a, byte b, byte c);
     43uint16 transformColor(uint16 baseColor, int r, int g, int b);
     44void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b);
     45void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b);
     46
    4347} // End of namespace Cine
    4448
    4549#endif
  • engines/cine/gfx.cpp

     
    2727#include "cine/bg.h"
    2828#include "cine/bg_list.h"
    2929#include "cine/various.h"
     30#include "cine/pal.h"
    3031
    3132#include "common/endian.h"
    3233#include "common/system.h"
     
    3536
    3637namespace Cine {
    3738
    38 uint16 c_palette[256];
    39 byte colorMode256 = 0;
    40 byte palette256[256 * 3];
    41 byte newPalette[256 * 3];
    42 byte newColorMode = 0;
    43 byte ctColorMode = 0;
    44 byte bgColorMode = 0;
    45 
    46 byte *screenBuffer;
    47 byte *page1Raw;
    48 byte *page2Raw;
    4939byte *page3Raw;
     40FWRenderer *renderer = NULL;
    5041
    5142static const byte mouseCursorNormal[] = {
    5243        0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00,
     
    9687        0xff, 0xff, 0xff, 0xff
    9788};
    9889
    99 void gfxInit() {
    100         screenBuffer = (byte *)malloc(320 * 200);
    101         page1Raw = (byte *)malloc(320 * 200);
    102         page2Raw = (byte *)malloc(320 * 200);
    103         page3Raw = (byte *)malloc(320 * 200);
    104         if (!screenBuffer || !page1Raw || !page2Raw || !page3Raw) {
    105                 error("Unable to allocate offscreen buffers");
     90/*! \brief Initialize renderer
     91 */
     92FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""),
     93        _cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]),
     94        _activeLowPal(NULL), _changePal(0) {
     95
     96        assert(_backBuffer);
     97
     98        memset(_backBuffer, 0, _screenSize);
     99        memset(_bgName, 0, sizeof (_bgName));
     100}
     101
     102/* \brief Destroy renderer
     103 */
     104FWRenderer::~FWRenderer() {
     105        delete[] _background;
     106        delete[] _palette;
     107        delete[] _backBuffer;
     108        delete[] _activeLowPal;
     109}
     110
     111/* \brief Reset renderer state
     112 */
     113void FWRenderer::clear() {
     114        delete[] _background;
     115        delete[] _palette;
     116        delete[] _activeLowPal;
     117
     118        _background = NULL;
     119        _palette = NULL;
     120        _activeLowPal = NULL;
     121
     122        memset(_backBuffer, 0, _screenSize);
     123
     124        _cmd = "";
     125        _cmdY = 0;
     126        _messageBg = 0;
     127        _changePal = 0;
     128}
     129
     130/*! \brief Draw 1bpp sprite using selected color
     131 * \param obj Object info
     132 * \param fillColor Sprite color
     133 */
     134void FWRenderer::fillSprite(const objectStruct &obj, uint8 color) {
     135        const byte *data = animDataTable[obj.frame].data();
     136        int x, y, width, height;
     137
     138        x = obj.x;
     139        y = obj.y;
     140        width = animDataTable[obj.frame]._realWidth;
     141        height = animDataTable[obj.frame]._height;
     142
     143        gfxFillSprite(data, width, height, _backBuffer, x, y, color);
     144}
     145
     146/*! \brief Draw 1bpp sprite using selected color on background
     147 * \param obj Object info
     148 * \param fillColor Sprite color
     149 */
     150void FWRenderer::incrustMask(const objectStruct &obj, uint8 color) {
     151        const byte *data = animDataTable[obj.frame].data();
     152        int x, y, width, height;
     153
     154        x = obj.x;
     155        y = obj.y;
     156        width = animDataTable[obj.frame]._realWidth;
     157        height = animDataTable[obj.frame]._height;
     158
     159        gfxFillSprite(data, width, height, _background, x, y, color);
     160}
     161
     162/*! \brief Draw color sprite using with external mask
     163 * \param obj Object info
     164 * \param mask External mask
     165 */
     166void FWRenderer::drawMaskedSprite(const objectStruct &obj, const byte *mask) {
     167        const byte *data = animDataTable[obj.frame].data();
     168        int x, y, width, height;
     169
     170        x = obj.x;
     171        y = obj.y;
     172        width = animDataTable[obj.frame]._realWidth;
     173        height = animDataTable[obj.frame]._height;
     174
     175        assert(mask);
     176
     177        drawSpriteRaw(data, mask, width, height, _backBuffer, x, y);
     178}
     179
     180/*! \brief Draw color sprite
     181 * \param obj Object info
     182 */
     183void FWRenderer::drawSprite(const objectStruct &obj) {
     184        const byte *mask = animDataTable[obj.frame].mask();
     185        drawMaskedSprite(obj, mask);
     186}
     187
     188/*! \brief Draw color sprite on background
     189 * \param obj Object info
     190 */
     191void FWRenderer::incrustSprite(const objectStruct &obj) {
     192        const byte *data = animDataTable[obj.frame].data();
     193        const byte *mask = animDataTable[obj.frame].mask();
     194        int x, y, width, height;
     195
     196        x = obj.x;
     197        y = obj.y;
     198        width = animDataTable[obj.frame]._realWidth;
     199        height = animDataTable[obj.frame]._height;
     200
     201        assert(mask);
     202
     203        drawSpriteRaw(data, mask, width, height, _background, x, y);
     204}
     205
     206/*! \brief Draw command box on screen
     207 */
     208void FWRenderer::drawCommand() {
     209        unsigned int i;
     210        int x = 10, y = _cmdY;
     211
     212        drawPlainBox(x, y, 301, 11, 0);
     213        drawBorder(x - 1, y - 1, 302, 12, 2);
     214
     215        x += 2;
     216        y += 2;
     217
     218        for (i = 0; i < _cmd.size(); i++) {
     219                x = drawChar(_cmd[i], x, y);
    106220        }
    107         memset(page1Raw, 0, 320 * 200);
    108         memset(page2Raw, 0, 320 * 200);
    109         memset(page3Raw, 0, 320 * 200);
     221}
    110222
    111         memset(additionalBgTable, 0, sizeof(additionalBgTable));
    112         additionalBgTable[0] = page2Raw;
    113         additionalBgTable[8] = page3Raw;
     223/*! \brief Draw message in a box
     224 * \param str Message to draw
     225 * \param x Top left message box corner coordinate
     226 * \param y Top left message box corner coordinate
     227 * \param width Message box width
     228 * \param color Message box background color
     229 */
     230void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte color) {
     231        int i, tx, ty, tw;
     232        int line = 0, words = 0, cw = 0;
     233        int space = 0, extraSpace = 0;
     234
     235        drawPlainBox(x, y, width, 4, color);
     236        tx = x + 4;
     237        ty = str[0] ? y - 5 : y + 4;
     238        tw = width - 8;
     239
     240        for (i = 0; str[i]; i++, line--) {
     241                // Fit line of text into textbox
     242                if (!line) {
     243                        while (str[i] == ' ') i++;
     244                        line = fitLine(str + i, tw, words, cw);
     245
     246                        if ( str[i + line] != '\0' && str[i + line] != 0x7C && words) {
     247                                space = (tw - cw) / words;
     248                                extraSpace = (tw - cw) % words;
     249                        } else {
     250                                space = 5;
     251                                extraSpace = 0;
     252                        }
     253
     254                        ty += 9;
     255                        drawPlainBox(x, ty, width, 9, color);
     256                        tx = x + 4;
     257                }
     258
     259                // draw characters
     260                if (str[i] == ' ') {
     261                        tx += space + extraSpace;
     262
     263                        if (extraSpace) {
     264                                extraSpace = 0;
     265                        }
     266                } else {
     267                        tx = drawChar(str[i], tx, ty);
     268                }
     269        }
     270
     271        ty += 9;
     272        drawPlainBox(x, ty, width, 4, color);
     273        drawDoubleBorder(x, y, width, ty - y + 4, 2);
    114274}
    115275
    116 void gfxDestroy() {
    117         free(screenBuffer);
    118         free(page1Raw);
    119         free(page2Raw);
    120         free(page3Raw);
     276/*! \brief Draw rectangle on screen
     277 * \param x Top left corner coordinate
     278 * \param y Top left corner coordinate
     279 * \param width Rectangle width
     280 * \param height Rectangle height
     281 * \param color Fill color
     282 */
     283void FWRenderer::drawPlainBox(int x, int y, int width, int height, byte color) {
     284        int i;
     285        byte *dest = _backBuffer + y * 320 + x;
     286
     287        if (width < 0) {
     288                x += width;
     289                width = -width;
     290        }
     291
     292        if (height < 0) {
     293                y += height;
     294                height = -height;
     295        }
     296
     297        for (i = 0; i < height; i++) {
     298                memset(dest + i * 320, color, width);
     299        }
    121300}
    122301
     302/*! \brief Draw empty rectangle
     303 * \param x Top left corner coordinate
     304 * \param y Top left corner coordinate
     305 * \param width Rectangle width
     306 * \param height Rectangle height
     307 * \param color Line color
     308 */
     309void FWRenderer::drawBorder(int x, int y, int width, int height, byte color) {
     310        drawLine(x, y, width, 1, color);
     311        drawLine(x, y + height, width, 1, color);
     312        drawLine(x, y, 1, height, color);
     313        drawLine(x + width, y, 1, height + 1, color);
     314}
     315
     316/*! \brief Draw empty 2 color rectangle (inner line color is black)
     317 * \param x Top left corner coordinate
     318 * \param y Top left corner coordinate
     319 * \param width Rectangle width
     320 * \param height Rectangle height
     321 * \param color Outter line color
     322 */
     323void FWRenderer::drawDoubleBorder(int x, int y, int width, int height, byte color) {
     324        drawBorder(x + 1, y + 1, width - 2, height - 2, 0);
     325        drawBorder(x, y, width, height, color);
     326}
     327
     328/*! \brief Draw text character on screen
     329 * \param character Character to draw
     330 * \param x Character coordinate
     331 * \param y Character coordinate
     332 */
     333int FWRenderer::drawChar(char character, int x, int y) {
     334        int width, idx;
     335
     336        if (character == ' ') {
     337                x += 5;
     338        } else if ((width = fontParamTable[character].characterWidth)) {
     339                idx = fontParamTable[character].characterIdx;
     340                drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y);
     341                x += width + 1;
     342        }
     343
     344        return x;
     345}
     346
     347/*! \brief Draw Line
     348 * \param x Line end coordinate
     349 * \param y Line end coordinate
     350 * \param width Horizontal line length
     351 * \param height Vertical line length
     352 * \param color Line color
     353 * \note Either width or height must be equal to 1
     354 */
     355void FWRenderer::drawLine(int x, int y, int width, int height, byte color) {
     356        // this line is a special case of rectangle ;-)
     357        drawPlainBox(x, y, width, height, color);
     358}
     359
     360/*! \brief Hide invisible parts of the sprite
     361 * \param[in,out] mask Mask to be updated
     362 * \param it Overlay info from overlayList
     363 */
     364void FWRenderer::remaskSprite(byte *mask, Common::List<overlay>::iterator it) {
     365        AnimData &sprite = animDataTable[objectTable[it->objIdx].frame];
     366        int x, y, width, height, idx;
     367        int mx, my, mw, mh;
     368
     369        x = objectTable[it->objIdx].x;
     370        y = objectTable[it->objIdx].y;
     371        width = sprite._realWidth;
     372        height = sprite._height;
     373
     374        for (++it; it != overlayList.end(); ++it) {
     375                if (it->type != 5) {
     376                        continue;
     377                }
     378
     379                idx = ABS(objectTable[it->objIdx].frame);
     380                mx = objectTable[it->objIdx].x;
     381                my = objectTable[it->objIdx].y;
     382                mw = animDataTable[idx]._realWidth;
     383                mh = animDataTable[idx]._height;
     384
     385                gfxUpdateSpriteMask(mask, x, y, width, height, animDataTable[idx].data(), mx, my, mw, mh);
     386        }
     387}
     388
     389/*! \brief Draw background to backbuffer
     390 */
     391void FWRenderer::drawBackground() {
     392        assert(_background);
     393        memcpy(_backBuffer, _background, _screenSize);
     394}
     395
     396/*! \brief Draw one overlay
     397 * \param it Overlay info
     398 */
     399void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
     400        int idx, len, width;
     401        objectStruct *obj;
     402        AnimData *sprite;
     403        byte *mask;
     404
     405        switch (it->type) {
     406        // color sprite
     407        case 0:
     408                sprite = animDataTable + objectTable[it->objIdx].frame;
     409                len = sprite->_realWidth * sprite->_height;
     410                mask = new byte[len];
     411                memcpy(mask, sprite->mask(), len);
     412                remaskSprite(mask, it);
     413                drawMaskedSprite(objectTable[it->objIdx], mask);
     414                delete[] mask;
     415                break;
     416
     417        // game message
     418        case 2:
     419                if (it->objIdx >= messageTable.size()) {
     420                        return;
     421                }
     422
     423                _messageLen += messageTable[it->objIdx].size();
     424                drawMessage(messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color);
     425                break;
     426
     427        // action failure message
     428        case 3:
     429                idx = it->objIdx * 4 + g_cine->_rnd.getRandomNumber(3);
     430                len = strlen(failureMessages[idx]);
     431                _messageLen += len;
     432                width = 6 * len + 20;
     433                width = width > 300 ? 300 : width;
     434
     435                drawMessage(failureMessages[idx], (320 - width) / 2, 80, width, 4);
     436                break;
     437
     438        // bitmap
     439        case 4:
     440                assert(it->objIdx < NUM_MAX_OBJECT);
     441                obj = objectTable + it->objIdx;
     442
     443                if (obj->frame < 0) {
     444                        return;
     445                }
     446
     447                if (!animDataTable[obj->frame].data()) {
     448                        return;
     449                }
     450
     451                fillSprite(*obj);
     452                break;
     453        }
     454}
     455
     456/*! \brief Draw overlays
     457 */
     458void FWRenderer::drawOverlays() {
     459        Common::List<overlay>::iterator it;
     460
     461        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     462                renderOverlay(it);
     463        }
     464}
     465
     466/*! \brief Draw another frame
     467 */
     468void FWRenderer::drawFrame() {
     469        drawBackground();
     470        drawOverlays();
     471
     472        if (!_cmd.empty()) {
     473                drawCommand();
     474        }
     475
     476        if (_changePal) {
     477                refreshPalette();
     478        }
     479
     480        blit();
     481}
     482
     483/*! \brief Update screen
     484 */
     485void FWRenderer::blit() {
     486        g_system->copyRectToScreen(_backBuffer, 320, 0, 0, 320, 200);
     487}
     488
     489/*! \brief Set player command string
     490 * \param cmd New command string
     491 */
     492void FWRenderer::setCommand(const char *cmd) {
     493        _cmd = cmd;
     494}
     495
     496/*! \brief Refresh current palette
     497 */
     498void FWRenderer::refreshPalette() {
     499        int i;
     500        byte pal[16*4];
     501
     502        assert(_activeLowPal);
     503
     504        for (i = 0; i < 16; i++) {
     505                // This seems to match the output from DOSbox.
     506                pal[i * 4 + 2] = ((_activeLowPal[i] & 0x00f) >> 0) * 32;
     507                pal[i * 4 + 1] = ((_activeLowPal[i] & 0x0f0) >> 4) * 32;
     508                pal[i * 4 + 0] = ((_activeLowPal[i] & 0xf00) >> 8) * 32;
     509                pal[i * 4 + 3] = 0;
     510        }
     511
     512        g_system->setPalette(pal, 0, 16);
     513        _changePal = 0;
     514}
     515
     516/*! \brief Load palette of current background
     517 */
     518void FWRenderer::reloadPalette() {
     519        assert(_palette);
     520
     521        if (!_activeLowPal) {
     522                _activeLowPal = new uint16[_lowPalSize];
     523        }
     524
     525        assert(_activeLowPal);
     526
     527        memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16));
     528        _changePal = 1;
     529}
     530
     531/*! \brief Load background into renderer
     532 * \param bg Raw background data
     533 */
     534void FWRenderer::loadBg16(const byte *bg, const char *name) {
     535        int i;
     536
     537        if (!_background) {
     538                _background = new byte[_screenSize];
     539        }
     540
     541        if (!_palette) {
     542                _palette = new uint16[_lowPalSize];
     543        }
     544
     545        assert(_background && _palette);
     546
     547        strcpy(_bgName, name);
     548
     549        for (i = 0; i < _lowPalSize; i++, bg += 2) {
     550                _palette[i] = READ_BE_UINT16(bg);
     551        }
     552
     553        gfxConvertSpriteToRaw(_background, bg, 160, 200);
     554}
     555
     556/*! \brief Placeholder for Operation Stealth implementation
     557 */
     558void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
     559        error("Future Wars renderer doesn't support multiple backgrounds");
     560}
     561
     562/*! \brief Placeholder for Operation Stealth implementation
     563 */
     564void FWRenderer::loadCt16(const byte *ct, const char *name) {
     565        error("Future Wars renderer doesn't support multiple backgrounds");
     566}
     567
     568/*! \brief Placeholder for Operation Stealth implementation
     569 */
     570void FWRenderer::loadBg256(const byte *bg, const char *name) {
     571        error("Future Wars renderer doesn't support 256 color mode");
     572}
     573
     574/*! \brief Placeholder for Operation Stealth implementation
     575 */
     576void FWRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
     577        error("Future Wars renderer doesn't support multiple backgrounds");
     578}
     579
     580/*! \brief Placeholder for Operation Stealth implementation
     581 */
     582void FWRenderer::loadCt256(const byte *ct, const char *name) {
     583        error("Future Wars renderer doesn't support multiple backgrounds");
     584}
     585
     586/*! \brief Placeholder for Operation Stealth implementation
     587 */
     588void FWRenderer::selectBg(unsigned int idx) {
     589        error("Future Wars renderer doesn't support multiple backgrounds");
     590}
     591
     592/*! \brief Placeholder for Operation Stealth implementation
     593 */
     594void FWRenderer::selectScrollBg(unsigned int idx) {
     595        error("Future Wars renderer doesn't support multiple backgrounds");
     596}
     597
     598/*! \brief Placeholder for Operation Stealth implementation
     599 */
     600void FWRenderer::setScroll(unsigned int shift) {
     601        error("Future Wars renderer doesn't support multiple backgrounds");
     602}
     603
     604/*! \brief Placeholder for Operation Stealth implementation
     605 */
     606void FWRenderer::removeBg(unsigned int idx) {
     607        error("Future Wars renderer doesn't support multiple backgrounds");
     608}
     609
     610void FWRenderer::saveBg(Common::OutSaveFile &fHandle) {
     611        fHandle.write(_bgName, 13);
     612}
     613
     614/*! \brief Restore active and backup palette from save
     615 * \param fHandle Savefile open for reading
     616 */
     617void FWRenderer::restorePalette(Common::InSaveFile &fHandle) {
     618        int i;
     619
     620        if (!_palette) {
     621                _palette = new uint16[_lowPalSize];
     622        }
     623
     624        if (!_activeLowPal) {
     625                _activeLowPal = new uint16[_lowPalSize];
     626        }
     627
     628        assert(_palette && _activeLowPal);
     629
     630        for (i = 0; i < _lowPalSize; i++) {
     631                _activeLowPal[i] = fHandle.readUint16BE();
     632        }
     633
     634        for (i = 0; i < _lowPalSize; i++) {
     635                _palette[i] = fHandle.readUint16BE();
     636        }
     637
     638        _changePal = 1;
     639}
     640
     641/*! \brief Write active and backup palette to save
     642 * \param fHandle Savefile open for writing
     643 */
     644void FWRenderer::savePalette(Common::OutSaveFile &fHandle) {
     645        int i;
     646
     647        assert(_palette && _activeLowPal);
     648
     649        for (i = 0; i < _lowPalSize; i++) {
     650                fHandle.writeUint16BE(_activeLowPal[i]);
     651        }
     652
     653        for (i = 0; i < _lowPalSize; i++) {
     654                fHandle.writeUint16BE(_palette[i]);
     655        }
     656}
     657
     658/*! \brief Rotate active palette
     659 * \param a First color to rotate
     660 * \param b Last color to rotate
     661 * \param c Possibly rotation step, must be equal to 1 at the moment
     662 */
     663void FWRenderer::rotatePalette(int a, int b, int c) {
     664        palRotate(_activeLowPal, a, b, c);
     665        refreshPalette();
     666}
     667
     668/*! \brief Copy part of backup palette to active palette and transform
     669 * \param first First color to transform
     670 * \param last Last color to transform
     671 * \param r Red channel transformation
     672 * \param g Green channel transformation
     673 * \param b Blue channel transformation
     674 */
     675void FWRenderer::transformPalette(int first, int last, int r, int g, int b) {
     676        if (!_activeLowPal) {
     677                _activeLowPal = new uint16[_lowPalSize];
     678                memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
     679        }
     680
     681        transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b);
     682        refreshPalette();
     683}
     684
     685/*! \brief Draw menu box, one item per line with possible highlight
     686 * \param items Menu items
     687 * \param height Item count
     688 * \param x Top left menu corner coordinate
     689 * \param y Top left menu corner coordinate
     690 * \param width Menu box width
     691 * \param selected Index of highlighted item (no highlight if less than 0)
     692 */
     693void FWRenderer::drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected) {
     694        int tx, ty, th = height * 9 + 10;
     695        unsigned int i, j;
     696
     697        if (x + width > 319) {
     698                x = 319 - width;
     699        }
     700
     701        if (y + th > 199) {
     702                y = 199 - th;
     703        }
     704
     705        drawPlainBox(x, y, width, 4, _messageBg);
     706
     707        ty = y + 4;
     708
     709        for (i = 0; i < height; i++, ty += 9) {
     710                drawPlainBox(x, ty, width, 9, (int)i == selected ? 0 : _messageBg);
     711                tx = x + 4;
     712
     713                for (j = 0; items[i][j]; j++) {
     714                        tx = drawChar(items[i][j], tx, ty);
     715                }
     716        }
     717
     718        drawPlainBox(x, ty, width, 4, _messageBg);
     719        drawDoubleBorder(x, y, width, ty - y + 4, 2);
     720}
     721
     722/*! \brief Draw text input box
     723 * \param info Input box message
     724 * \param input Text entered in the input area
     725 * \param cursor Cursor position in the input area
     726 * \param x Top left input box corner coordinate
     727 * \param y Top left input box corner coordinate
     728 * \param width Input box width
     729 */
     730void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width) {
     731        int i, tx, ty, tw;
     732        int line = 0, words = 0, cw = 0;
     733        int space = 0, extraSpace = 0;
     734
     735        drawPlainBox(x, y, width, 4, _messageBg);
     736        tx = x + 4;
     737        ty = info[0] ? y - 5 : y + 4;
     738        tw = width - 8;
     739
     740        // input box info message
     741        for (i = 0; info[i]; i++, line--) {
     742                // fit line of text
     743                if (!line) {
     744                        line = fitLine(info + i, tw, words, cw);
     745
     746                        if ( info[i + line] != '\0' && words) {
     747                                space = (tw - cw) / words;
     748                                extraSpace = (tw - cw) % words;
     749                        } else {
     750                                space = 5;
     751                                extraSpace = 0;
     752                        }
     753
     754                        ty += 9;
     755                        drawPlainBox(x, ty, width, 9, _messageBg);
     756                        tx = x + 4;
     757                }
     758
     759                // draw characters
     760                if (info[i] == ' ') {
     761                        tx += space + extraSpace;
     762
     763                        if (extraSpace) {
     764                                extraSpace = 0;
     765                        }
     766                } else {
     767                        tx = drawChar(info[i], tx, ty);
     768                }
     769        }
     770
     771        // input area background
     772        ty += 9;
     773        drawPlainBox(x, ty, width, 9, _messageBg);
     774        drawPlainBox(x + 16, ty - 1, width - 32, 9, 0);
     775        tx = x + 20;
     776
     777        // text in input area
     778        for (i = 0; input[i]; i++) {
     779                tx = drawChar(input[i], tx, ty);
     780
     781                if (cursor == i + 2) {
     782                        drawLine(tx, ty - 1, 1, 9, 2);
     783                }
     784        }
     785
     786        if (!input[0] || cursor == 1) {
     787                drawLine(x + 20, ty - 1, 1, 9, 2);
     788        }
     789
     790        ty += 9;
     791        drawPlainBox(x, ty, width, 4, _messageBg);
     792        drawDoubleBorder(x, y, width, ty - y + 4, 2);
     793}
     794
     795/*! \brief Fade to black
     796 */
     797void FWRenderer::fadeToBlack() {
     798        assert(_activeLowPal);
     799
     800        for (int i = 0; i < 8; i++) {
     801                for (int j = 0; j < 16; j++) {
     802                        _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1);
     803                }
     804
     805                refreshPalette();
     806                g_system->updateScreen();
     807                g_system->delayMillis(50);
     808        }
     809}
     810
     811/*! \brief Initialize Operation Stealth renderer
     812 */
     813OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0),
     814        _bgShift(0) {
     815
     816        int i;
     817        for (i = 0; i < 9; i++) {
     818                _bgTable[i].bg = NULL;
     819                _bgTable[i].lowPal = NULL;
     820                _bgTable[i].hiPal = NULL;
     821                memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
     822        }
     823}
     824
     825/*! \brief Destroy Operation Stealth renderer
     826 */
     827OSRenderer::~OSRenderer() {
     828        delete[] _activeHiPal;
     829
     830        for (int i = 0; i < 9; i++) {
     831                delete[] _bgTable[i].bg;
     832                delete[] _bgTable[i].lowPal;
     833                delete[] _bgTable[i].hiPal;
     834        }
     835}
     836
     837/*! \brief Reset Operation Stealth renderer state
     838 */
     839void OSRenderer::clear() {
     840        delete[] _activeHiPal;
     841        _activeHiPal = NULL;
     842
     843        for (int i = 0; i < 9; i++) {
     844                delete[] _bgTable[i].bg;
     845                delete[] _bgTable[i].lowPal;
     846                delete[] _bgTable[i].hiPal;
     847
     848                _bgTable[i].bg = NULL;
     849                _bgTable[i].lowPal = NULL;
     850                _bgTable[i].hiPal = NULL;
     851                memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name));
     852        }
     853
     854        _currentBg = 0;
     855        _scrollBg = 0;
     856        _bgShift = 0;
     857
     858        FWRenderer::clear();
     859}
     860
     861/*! \brief Draw 1bpp sprite using selected color on backgrounds
     862 * \param obj Object info
     863 * \param fillColor Sprite color
     864 */
     865void OSRenderer::incrustMask(const objectStruct &obj, uint8 color) {
     866        const byte *data = animDataTable[obj.frame].data();
     867        int x, y, width, height, i;
     868
     869        x = obj.x;
     870        y = obj.y;
     871        width = animDataTable[obj.frame]._realWidth;
     872        height = animDataTable[obj.frame]._height;
     873
     874        for (i = 0; i < 8; i++) {
     875                if (!_bgTable[i].bg) {
     876                        continue;
     877                }
     878
     879                gfxFillSprite(data, width, height, _bgTable[i].bg, x, y, color);
     880        }
     881}
     882
     883/*! \brief Draw color sprite
     884 * \param obj Object info
     885 */
     886void OSRenderer::drawSprite(const objectStruct &obj) {
     887        const byte *data = animDataTable[obj.frame].data();
     888        int x, y, width, height, transColor;
     889
     890        x = obj.x;
     891        y = obj.y;
     892        transColor = obj.part;
     893        width = animDataTable[obj.frame]._realWidth;
     894        height = animDataTable[obj.frame]._height;
     895
     896        drawSpriteRaw2(data, transColor, width, height, _backBuffer, x, y);
     897}
     898
     899/*! \brief Draw color sprite
     900 * \param obj Object info
     901 */
     902void OSRenderer::incrustSprite(const objectStruct &obj) {
     903        const byte *data = animDataTable[obj.frame].data();
     904        int x, y, width, height, transColor, i;
     905
     906        x = obj.x;
     907        y = obj.y;
     908        transColor = obj.part;
     909        width = animDataTable[obj.frame]._realWidth;
     910        height = animDataTable[obj.frame]._height;
     911
     912        for (i = 0; i < 8; i++) {
     913                if (!_bgTable[i].bg) {
     914                        continue;
     915                }
     916
     917                drawSpriteRaw2(data, transColor, width, height, _bgTable[i].bg, x, y);
     918        }
     919}
     920
     921/*! \brief Draw text character on screen
     922 * \param character Character to draw
     923 * \param x Character coordinate
     924 * \param y Character coordinate
     925 */
     926int OSRenderer::drawChar(char character, int x, int y) {
     927        int width, idx;
     928
     929        if (character == ' ') {
     930                x += 5;
     931        } else if ((width = fontParamTable[character].characterWidth)) {
     932                idx = fontParamTable[character].characterIdx;
     933                drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
     934                x += width + 1;
     935        }
     936
     937        return x;
     938}
     939
     940/*! \brief Draw background to backbuffer
     941 */
     942void OSRenderer::drawBackground() {
     943        byte *main;
     944
     945        main = _bgTable[_currentBg].bg;
     946        assert(main);
     947
     948        if (!_bgShift) {
     949                memcpy(_backBuffer, main, _screenSize);
     950        } else {
     951                byte *scroll = _bgTable[_scrollBg].bg;
     952                int mainShift = _bgShift * _screenWidth;
     953                int mainSize = _screenSize - mainShift;
     954
     955                assert(scroll);
     956
     957                memcpy(_backBuffer, main + mainShift, mainSize);
     958                memcpy(_backBuffer + mainSize, scroll, mainShift);
     959        }
     960}
     961
     962/*! \brief Draw one overlay
     963 * \param it Overlay info
     964 */
     965void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
     966        int len;
     967        objectStruct *obj;
     968        AnimData *sprite;
     969        byte *mask;
     970
     971        switch (it->type) {
     972        // color sprite
     973        case 0:
     974                sprite = animDataTable + objectTable[it->objIdx].frame;
     975                len = sprite->_realWidth * sprite->_height;
     976                mask = new byte[len];
     977                generateMask(sprite->data(), mask, len, objectTable[it->objIdx].part);
     978                remaskSprite(mask, it);
     979                drawMaskedSprite(objectTable[it->objIdx], mask);
     980                delete[] mask;
     981                break;
     982
     983        // masked background
     984        case 20:
     985                assert(it->objIdx < NUM_MAX_OBJECT);
     986                obj = objectTable + it->objIdx;
     987                sprite = animDataTable + obj->frame;
     988
     989                if (obj->frame < 0 || it->x > 8 || !_bgTable[it->x].bg || sprite->_bpp != 1) {
     990                        break;
     991                }
     992
     993                maskBgOverlay(_bgTable[it->x].bg, sprite->data(), sprite->_realWidth, sprite->_height, _backBuffer, obj->x, obj->y);
     994                break;
     995
     996        // something else
     997        default:
     998                FWRenderer::renderOverlay(it);
     999                break;
     1000        }
     1001}
     1002
     1003/*! \brief Refresh current palette
     1004 */
     1005void OSRenderer::refreshPalette() {
     1006        if (!_activeHiPal) {
     1007                FWRenderer::refreshPalette();
     1008                return;
     1009        }
     1010
     1011        int i;
     1012        byte pal[256*4];
     1013
     1014        for (i = 0; i < 256; i++) {
     1015                pal[i * 4 + 0] = _activeHiPal[i * 3 + 0];
     1016                pal[i * 4 + 1] = _activeHiPal[i * 3 + 1];
     1017                pal[i * 4 + 2] = _activeHiPal[i * 3 + 2];
     1018                pal[i * 4 + 3] = 0;
     1019        }
     1020
     1021        g_system->setPalette(pal, 0, 256);
     1022        _changePal = 0;
     1023}
     1024
     1025/*! \brief Load palette of current background
     1026 */
     1027void OSRenderer::reloadPalette() {
     1028        // selected background in plane takeoff scene has swapped colors 12
     1029        // and 14, shift background has it right
     1030        palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
     1031
     1032        assert(bg->lowPal || bg->hiPal);
     1033
     1034        if (bg->lowPal) {
     1035                if (!_activeLowPal) {
     1036                        _activeLowPal = new uint16[_lowPalSize];
     1037                }
     1038
     1039                assert(_activeLowPal);
     1040
     1041                delete[] _activeHiPal;
     1042                _activeHiPal = NULL;
     1043
     1044                memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16));
     1045        } else {
     1046                if (!_activeHiPal) {
     1047                        _activeHiPal = new byte[_hiPalSize];
     1048                }
     1049
     1050                assert(_activeHiPal);
     1051
     1052                delete[] _activeLowPal;
     1053                _activeLowPal = NULL;
     1054
     1055                memcpy(_activeHiPal, bg->hiPal, _hiPalSize);
     1056        }
     1057        _changePal = 1;
     1058}
     1059
     1060/*! \brief Rotate active palette
     1061 * \param a First color to rotate
     1062 * \param b Last color to rotate
     1063 * \param c Possibly rotation step, must be equal to 1 at the moment
     1064 */
     1065void OSRenderer::rotatePalette(int a, int b, int c) {
     1066        if (_activeLowPal) {
     1067                FWRenderer::rotatePalette(a, b, c);
     1068                return;
     1069        }
     1070
     1071        palRotate(_activeHiPal, a, b, c);
     1072        refreshPalette();
     1073}
     1074
     1075/*! \brief Copy part of backup palette to active palette and transform
     1076 * \param first First color to transform
     1077 * \param last Last color to transform
     1078 * \param r Red channel transformation
     1079 * \param g Green channel transformation
     1080 * \param b Blue channel transformation
     1081 */
     1082void OSRenderer::transformPalette(int first, int last, int r, int g, int b) {
     1083        palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg];
     1084
     1085        if (!bg->lowPal) {
     1086                if (!_activeHiPal) {
     1087                        _activeHiPal = new byte[_hiPalSize];
     1088                        memset(_activeHiPal, 0, _hiPalSize);
     1089                }
     1090
     1091                delete[] _activeLowPal;
     1092                _activeLowPal = NULL;
     1093
     1094                transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b);
     1095        } else {
     1096                if (!_activeLowPal) {
     1097                        _activeLowPal = new uint16[_lowPalSize];
     1098                        memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16));
     1099                }
     1100
     1101                delete[] _activeHiPal;
     1102                _activeHiPal = NULL;
     1103
     1104                transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b);
     1105        }
     1106
     1107        refreshPalette();
     1108}
     1109
     1110/*! \brief Load 16 color background into renderer
     1111 * \param bg Raw background data
     1112 * \param name Background filename
     1113 */
     1114void OSRenderer::loadBg16(const byte *bg, const char *name) {
     1115        loadBg16(bg, name, 0);
     1116}
     1117
     1118/*! \brief Load 16 color background into renderer
     1119 * \param bg Raw background data
     1120 * \param name Background filename
     1121 * \param pos Background index
     1122 */
     1123void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) {
     1124        int i;
     1125        assert(idx < 9);
     1126
     1127        if (!_bgTable[idx].bg) {
     1128                _bgTable[idx].bg = new byte[_screenSize];
     1129        }
     1130
     1131        if (!_bgTable[idx].lowPal) {
     1132                _bgTable[idx].lowPal = new uint16[_lowPalSize];
     1133        }
     1134
     1135        assert(_bgTable[idx].bg && _bgTable[idx].lowPal);
     1136
     1137        delete[] _bgTable[idx].hiPal;
     1138        _bgTable[idx].hiPal = NULL;
     1139
     1140        strcpy(_bgTable[idx].name, name);
     1141
     1142        for (i = 0; i < _lowPalSize; i++, bg += 2) {
     1143                _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg);
     1144        }
     1145
     1146        gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200);
     1147}
     1148
     1149/*! \brief Load 16 color CT data as background into renderer
     1150 * \param ct Raw CT data
     1151 * \param name Background filename
     1152 */
     1153void OSRenderer::loadCt16(const byte *ct, const char *name) {
     1154        loadBg16(ct, name, 8);
     1155}
     1156
     1157/*! \brief Load 256 color background into renderer
     1158 * \param bg Raw background data
     1159 * \param name Background filename
     1160 */
     1161void OSRenderer::loadBg256(const byte *bg, const char *name) {
     1162        loadBg256(bg, name, 0);
     1163}
     1164
     1165/*! \brief Load 256 color background into renderer
     1166 * \param bg Raw background data
     1167 * \param name Background filename
     1168 * \param pos Background index
     1169 */
     1170void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) {
     1171        assert(idx < 9);
     1172
     1173        if (!_bgTable[idx].bg) {
     1174                _bgTable[idx].bg = new byte[_screenSize];
     1175        }
     1176
     1177        if (!_bgTable[idx].hiPal) {
     1178                _bgTable[idx].hiPal = new byte[_hiPalSize];
     1179        }
     1180
     1181        assert(_bgTable[idx].bg && _bgTable[idx].hiPal);
     1182
     1183        delete[] _bgTable[idx].lowPal;
     1184        _bgTable[idx].lowPal = NULL;
     1185
     1186        strcpy(_bgTable[idx].name, name);
     1187        memcpy(_bgTable[idx].hiPal, bg, _hiPalSize);
     1188        memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize);
     1189}
     1190
     1191/*! \brief Load 256 color CT data as background into renderer
     1192 * \param ct Raw CT data
     1193 * \param name Background filename
     1194 */
     1195void OSRenderer::loadCt256(const byte *ct, const char *name) {
     1196        loadBg256(ct, name, 8);
     1197}
     1198
     1199/*! \brief Select active background and load its palette
     1200 * \param idx Background index
     1201 */
     1202void OSRenderer::selectBg(unsigned int idx) {
     1203        assert(idx < 9 && _bgTable[idx].bg);
     1204        assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal);
     1205
     1206        _currentBg = idx;
     1207        reloadPalette();
     1208}
     1209
     1210/*! \brief Select scroll background
     1211 * \param idx Scroll background index
     1212 */
     1213void OSRenderer::selectScrollBg(unsigned int idx) {
     1214        assert(idx < 9);
     1215
     1216        if (_bgTable[idx].bg) {
     1217                _scrollBg = idx;
     1218        }
     1219        reloadPalette();
     1220}
     1221
     1222/*! \brief Set background scroll
     1223 * \param shift Background scroll in pixels
     1224 */
     1225void OSRenderer::setScroll(unsigned int shift) {
     1226        assert(shift <= 200);
     1227
     1228        _bgShift = shift;
     1229}
     1230
     1231/*! \brief Unload background from renderer
     1232 * \param idx Background to unload
     1233 */
     1234void OSRenderer::removeBg(unsigned int idx) {
     1235        assert(idx > 0 && idx < 9);
     1236
     1237        if (_currentBg == idx) {
     1238                _currentBg = 0;
     1239        }
     1240
     1241        if (_scrollBg == idx) {
     1242                _scrollBg = 0;
     1243        }
     1244
     1245        delete[] _bgTable[idx].bg;
     1246        delete[] _bgTable[idx].lowPal;
     1247        delete[] _bgTable[idx].hiPal;
     1248        _bgTable[idx].bg = NULL;
     1249        _bgTable[idx].lowPal = NULL;
     1250        _bgTable[idx].hiPal = NULL;
     1251        memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name));
     1252}
     1253
     1254/*! \brief Fade to black
     1255 * \bug Operation Stealth sometimes seems to fade to black using
     1256 * transformPalette resulting in double fadeout
     1257 */
     1258void OSRenderer::fadeToBlack() {
     1259        if (!_activeHiPal) {
     1260                FWRenderer::fadeToBlack();
     1261                return;
     1262        }
     1263
     1264        for (int i = 0; i < 8; i++) {
     1265                for (int j = 0; j < _hiPalSize; j++) {
     1266                        _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255);
     1267                }
     1268
     1269                refreshPalette();
     1270                g_system->updateScreen();
     1271                g_system->delayMillis(50);
     1272        }
     1273}
     1274
    1231275void setMouseCursor(int cursor) {
    1241276        static int currentMouseCursor = -1;
    1251277        assert(cursor >= 0 && cursor < 3);
     
    1471299        }
    1481300}
    1491301
    150 static uint16 transformColor(uint16 baseColor, int8 r, int8 g, int8 b) {
    151         int8 oriR = CLIP( (baseColor & 0x007)       + r, 0, 7);
    152         int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7);
    153         int8 oriB = CLIP(((baseColor & 0x700) >> 8) + b, 0, 7);
    154 
    155         return oriR | (oriG << 4) | (oriB << 8);
    156 }
    157 
    158 void transformPaletteRange(byte startColor, byte stopColor, int8 r, int8 g, int8 b) {
    159         for (byte i = startColor; i <= stopColor; i++) {
    160                 c_palette[i] = transformColor(tempPalette[i], b, g, r);
    161         }
    162         //gfxFlipPage(page2);
    163 }
    164 
    1651302void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
    1661303        int16 i, j;
    1671304
     
    1701307                destPtr += i * 320;
    1711308
    1721309                for (j = 0; j < width; j++) {
    173                         if (x + j >= 0 && x + j < 320 && i + y >= 0
    174                             && i + y < 200) {
    175                                 if (!*(spritePtr++)) {
    176                                         *(destPtr++) = fillColor;
    177                                 } else {
    178                                         destPtr++;
    179                                 }
    180                         } else {
    181                                 destPtr++;
    182                                 spritePtr++;
     1310                        if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && !*spritePtr) {
     1311                                *destPtr = fillColor;
    1831312                        }
     1313
     1314                        destPtr++;
     1315                        spritePtr++;
    1841316                }
    1851317        }
    1861318}
     
    3601492        }
    3611493}
    3621494
    363 void gfxCopyRawPage(byte *source, byte *dest) {
    364         memcpy(dest, source, 320 * 200);
    365 }
    366 
    367 void gfxFlipRawPage(byte *frontBuffer) {
    368         byte *page = frontBuffer;
    369         int x, y, i;
    370         byte *pixels = (byte *) screenBuffer;
    371         byte c;
    372         byte pal[256 * 4];
    373 
    374         for (y = 0; y < 200; y++) {
    375                 for (x = 0; x < 320; x++) {
    376                         c = *(page++);
    377 
    378                         if (!colorMode256) {
    379                                 c = c & 15;
    380                         }
    381 
    382                         pixels[x + 0 + y * 320] = c;
    383                 }
    384         }
    385 
    386         if (colorMode256) {
    387                 for (i = 0; i < 256; i++) {
    388                         pal[i * 4 + 0] = palette256[i * 3 + 0];
    389                         pal[i * 4 + 1] = palette256[i * 3 + 1];
    390                         pal[i * 4 + 2] = palette256[i * 3 + 2];
    391                         pal[i * 4 + 3] = 0;
    392                 }
    393                 g_system->setPalette(pal, 0, 256);
    394         } else {
    395                 for (i = 0; i < 16; i++) {
    396                         // This seems to match the output from DOSbox.
    397                         pal[i * 4 + 2] = ((c_palette[i] & 0x00f) >> 0) * 32;
    398                         pal[i * 4 + 1] = ((c_palette[i] & 0x0f0) >> 4) * 32;
    399                         pal[i * 4 + 0] = ((c_palette[i] & 0xf00) >> 8) * 32;
    400                         pal[i * 4 + 3] = 0;
    401                 }
    402                 g_system->setPalette(pal, 0, 16);
    403         }
    404 
    405         g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200);
    406 }
    407 
    408 void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height,
    409                                    byte *page, int16 x, int16 y) {
     1495void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y) {
    4101496        int16 i, j;
    4111497
    4121498        // FIXME: Is it a bug if maskPtr == NULL?
     
    4171503                byte *destPtr = page + x + y * 320;
    4181504                destPtr += i * 320;
    4191505
    420                 for (j = 0; j < width * 8; j++) {
    421                         if (((g_cine->getGameType() == Cine::GType_FW && (!maskPtr || !(*maskPtr))) || (g_cine->getGameType() == Cine::GType_OS)) && (x + j >= 0
    422                                         && x + j < 320 && i + y >= 0 && i + y < 200)) {
     1506                for (j = 0; j < width; j++) {
     1507                        if ((!maskPtr || !(*maskPtr)) && x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200) {
    4231508                                *(destPtr++) = *(spritePtr++);
    4241509                        } else {
    4251510                                destPtr++;
     
    4321517        }
    4331518}
    4341519
    435 void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height,
    436                                         byte *page, int16 x, int16 y) {
     1520void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y) {
    4371521        int16 i, j;
    4381522
    4391523        for (i = 0; i < height; i++) {
    4401524                byte *destPtr = page + x + y * 320;
    4411525                destPtr += i * 320;
    4421526
    443                 for (j = 0; j < width * 8; j++) {
    444                         if ((*(spritePtr) != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) {
    445                                 *(destPtr++) = *(spritePtr++);
    446                         } else {
    447                                 destPtr++;
    448                                 spritePtr++;
     1527                for (j = 0; j < width; j++) {
     1528                        if ((*spritePtr != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) {
     1529                                *destPtr = *spritePtr;
    4491530                        }
     1531                        destPtr++;
     1532                        spritePtr++;
    4501533                }
    4511534        }
    4521535}
     
    4991582        }
    5001583}
    5011584
    502 /*! \todo Fix rendering to prevent fadein artifacts
    503  */
    504 void fadeFromBlack() {
    505         int i, j;
    506         int r, g, b, tr, tg, tb;
    507         if (newColorMode == 2) {
    508                 colorMode256 = 1;
    509                 memset(palette256, 0, 256*3);
    510         } else if (newColorMode == 1) {
    511                 colorMode256 = 0;
    512                 memset(c_palette, 0, 16 * sizeof(uint16));
    513         }
    514 
    515         for (i = 0; i < 8; i++ ) {
    516                 gfxFlipRawPage(page1Raw);
    517                 g_system->updateScreen();
    518                 g_system->delayMillis(50);
    519 
    520                 if (colorMode256) {
    521                         for (j = 0; j < 256*3; j++) {
    522                                 r = palette256[j] + (newPalette[j] + 7) / 8;
    523                                 palette256[j] = CLIP(r, 0, (int)newPalette[j]);
    524                         }
    525                 } else {
    526                         for (j = 0; j < 16; j++) {
    527                                 r = c_palette[j] & 0xf;
    528                                 g = (c_palette[j] & 0xf0) >> 4;
    529                                 b = (c_palette[j] & 0xf00) >> 8;
    530 
    531                                 tr = tempPalette[j] & 0xf;
    532                                 tg = (tempPalette[j] & 0xf0) >> 4;
    533                                 tb = (tempPalette[j] & 0xf00) >> 8;
    534 
    535                                 r = CLIP(r + (tr + 7) / 8, 0, tr);
    536                                 g = CLIP(g + (tg + 7) / 8, 0, tg);
    537                                 b = CLIP(b + (tb + 7) / 8, 0, tb);
    538 
    539                                 c_palette[j] = r | (g << 4) | (b << 8);
    540                         }
    541 
    542                 }
    543         }
    544 
    545         if (colorMode256) {
    546                 memcpy(palette256, newPalette, 256*3);
    547         } else {
    548                 memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
    549         }
    550 }
    551 
    552 void fadeToBlack() {
    553         for (int i = 0; i < 8; i++) {
    554                 if (colorMode256) {
    555                         for (int j = 0; j < 256*3; j++) {
    556                                 palette256[j] = CLIP(palette256[j] - 32, 0, 255);
    557                         }
    558                 } else {
    559                         for (int j = 0; j < 16; j++) {
    560                                 c_palette[j] = transformColor(c_palette[j], -1, -1, -1);
    561                         }
    562                 }
    563                 gfxFlipRawPage(page1Raw);
    564                 g_system->updateScreen();
    565                 g_system->delayMillis(50);
    566         }
    567 }
    568 
    569 void blitRawScreen(byte *frontBuffer) {
    570         gfxFlipRawPage(frontBuffer);
    571 }
    572 
    573 void flip(void) {
    574         blitRawScreen(page1Raw);
    575         if (fadeRequired) {
    576                 if (newColorMode == 3) {
    577                         newColorMode = ctColorMode + 1;
    578                 }
    579 
    580                 if (newColorMode == 2) {
    581                         colorMode256 = 1;
    582                         memcpy(palette256, newPalette, 256*3);
    583                 } else {
    584                         colorMode256 = 0;
    585                         memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
    586                 }
    587                 fadeRequired = false;
    588         }
    589 }
    590 
    5911585} // End of namespace Cine
  • engines/cine/prc.cpp

     
    9898                char buffer[256];
    9999
    100100                for (s = 0; s < numScripts; s++) {
    101                         if (scriptTable[s].size) {
     101                        if (scriptTable[s]->_size) {
    102102                                sprintf(buffer, "%s_%03d.txt", pPrcName, s);
    103103
    104                                 decompileScript(scriptTable[s].ptr, scriptTable[s].stack, scriptTable[s].size, s);
     104                                decompileScript((const byte *)scriptTable[s]->getString(0), scriptTable[s]->_size, s);
    105105                                dumpScript(buffer);
    106106                        }
    107107                }
  • engines/cine/bg.cpp

     
    3737byte *additionalBgTable[9];
    3838byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
    3939
    40 byte loadCt(const char *ctName) {
     40byte loadCtFW(const char *ctName) {
    4141        uint16 header[32];
    4242        byte *ptr, *dataPtr;
    4343
     
    4646
    4747        ptr = dataPtr = readBundleFile(findFileInBundle(ctName));
    4848
    49         if (g_cine->getGameType() == Cine::GType_OS) {
    50                 uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
    51                 if (bpp == 8) {
    52                         ctColorMode = 1;
    53                         memcpy(newPalette, ptr, 256 * 3);
    54                         ptr += 3 * 256;
    55                         memcpy(page3Raw, ptr, 320 * 200);
    56                 } else {
    57                         ctColorMode = 0;
    58                         for (int i = 0; i < 16; i++) {
    59                                 tempPalette[i] = READ_BE_UINT16(ptr);
    60                                 ptr += 2;
    61                         }
     49        loadRelatedPalette(ctName);
    6250
    63                         gfxResetRawPage(page3Raw);
    64                         gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200);
    65                 }
    66         } else {
    67                 loadRelatedPalette(ctName);
     51        assert(strstr(ctName, ".NEO"));
    6852
    69                 assert(strstr(ctName, ".NEO"));
     53        Common::MemoryReadStream readS(ptr, 32);
    7054
    71                 Common::MemoryReadStream readS(ptr, 32);
    72 
    73                 for (int i = 0; i < 16; i++) {
    74                         header[i] = readS.readUint16BE();
    75                 }
    76 
    77                 gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200);
     55        for (int i = 0; i < 16; i++) {
     56                header[i] = readS.readUint16BE();
    7857        }
    7958
     59        gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200);
     60
    8061        free(dataPtr);
    8162        return 0;
    8263}
    8364
    84 void loadBgHigh(const char *currentPtr) {
    85         memcpy(newPalette, currentPtr, 256 * 3);
    86         currentPtr += 256 * 3;
     65byte loadCtOS(const char *ctName) {
     66        byte *ptr, *dataPtr;
    8767
    88         memcpy(page2Raw, currentPtr, 320 * 200);
     68        if (currentCtName != ctName)
     69                strcpy(currentCtName, ctName);
    8970
    90         newColorMode = 2;
    91         bgColorMode = 1;
     71        ptr = dataPtr = readBundleFile(findFileInBundle(ctName));
    9272
     73        uint16 bpp = READ_BE_UINT16(ptr);
     74        ptr += 2;
     75
     76        if (bpp == 8) {
     77                memcpy(page3Raw, ptr + 256 * 3, 320 * 200);
     78                renderer->loadCt256(ptr, ctName);
     79        } else {
     80                gfxConvertSpriteToRaw(page3Raw, ptr + 32, 160, 200);
     81                renderer->loadCt16(ptr, ctName);
     82        }
     83
     84        free(dataPtr);
     85        return 0;
    9386}
    9487
    9588byte loadBg(const char *bgName) {
    9689        byte *ptr, *dataPtr;
    9790
    98         if (currentBgName[0] != bgName)
    99                 strcpy(currentBgName[0], bgName);
    100 
    10191        byte fileIdx = findFileInBundle(bgName);
    10292        ptr = dataPtr = readBundleFile(fileIdx);
    10393
    104         uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
     94        uint16 bpp = READ_BE_UINT16(ptr);
     95        ptr += 2;
     96
    10597        if (bpp == 8) {
    106                 loadBgHigh((const char *)ptr);
     98                renderer->loadBg256(ptr, bgName);
    10799        } else {
    108                 newColorMode = 1;
    109                 bgColorMode = 0;
    110 
    111                 for (int i = 0; i < 16; i++) {
    112                         tempPalette[i] = READ_BE_UINT16(ptr);
    113                         ptr += 2;
    114                 }
    115 
    116100                if (g_cine->getGameType() == Cine::GType_FW) {
    117101                        loadRelatedPalette(bgName);
    118102                }
    119103
    120                 gfxResetRawPage(page2Raw);
    121                 gfxConvertSpriteToRaw(page2Raw, ptr, 160, 200);
     104                renderer->loadBg16(ptr, bgName);
    122105        }
    123106        free(dataPtr);
    124107        return 0;
     
    127110void addBackground(const char *bgName, uint16 bgIdx) {
    128111        byte *ptr, *dataPtr;
    129112
    130         strcpy(currentBgName[bgIdx], bgName);
    131 
    132113        byte fileIdx = findFileInBundle(bgName);
    133114        ptr = dataPtr = readBundleFile(fileIdx);
    134115
    135         additionalBgTable[bgIdx] = (byte *) malloc(320 * 200);
    136 
    137116        uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
    138117
    139118        if (bpp == 8) {
    140                 bgColorMode = 1;
    141                 memcpy(newPalette, ptr, 256 * 3);
    142                 ptr += 3 * 256;
    143                 memcpy(additionalBgTable[bgIdx], ptr, 320 * 200);
     119                renderer->loadBg256(ptr, bgName, bgIdx);
    144120        } else {
    145                 bgColorMode = 0;
    146                 for (int i = 0; i < 16; i++) {
    147                         tempPalette[i] = READ_BE_UINT16(ptr);
    148                         ptr += 2;
    149                 }
    150 
    151                 gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200);
     121                renderer->loadBg16(ptr, bgName, bgIdx);
    152122        }
    153123        free(dataPtr);
    154124}
  • engines/cine/bg_list.h

     
    4646extern Common::List<BGIncrust> bgIncrustList;
    4747extern uint32 var8;
    4848
    49 void addToBGList(int16 objIdx, bool addList = true);
    50 void addSpriteFilledToBGList(int16 idx, bool addList = true);
     49void addToBGList(int16 objIdx);
     50void addSpriteFilledToBGList(int16 idx);
    5151
    5252void createBgIncrustListElement(int16 objIdx, int16 param);
    5353void resetBgIncrustList(void);
  • engines/cine/texte.cpp

     
    611611        fontParamTable = 0;
    612612}
    613613
    614 uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult) {
    615         const byte *localPtr = ptr;
     614/*! \brief Fit a substring of text into one line of fixed width text box
     615 * \param str Text to fit
     616 * \param maxWidth Text box width
     617 * \param[out] words Number of words that fit
     618 * \param[out] width Total width of nonblank characters that fit
     619 * \return Length of substring which fits
     620 */
     621int fitLine(const char *str, int maxWidth, int &words, int &width) {
     622        int i, bkpWords = 0, bkpWidth = 0, bkpLen = 0;
     623        int charWidth = 0, fullWidth = 0;
    616624
    617         uint16 var_2 = 0;
    618         uint16 localLineResult = 0;
    619         uint16 var_6 = 0;
    620         uint16 var_8 = 0;
    621         uint16 localMessageWidth = 0;
    622         uint16 var_16 = 0;
    623         uint16 finished = 0;
    624         uint16 si = 0;
    625         uint16 di = 0;
     625        words = 0;
     626        width = 0;
    626627
    627         while (!finished) {
    628                 byte character = *(localPtr++);
    629 
    630                 if (character == ' ') {
    631                         var_8 = var_16;
    632                         var_6 = localMessageWidth;
    633                         localLineResult = si;
    634                         var_2 = di;
    635 
    636                         if (si + 5 < width) {
    637                                 var_16++;
    638                                 si += 5;
    639                         } else {
    640                                 finished = 1;
    641                         }
    642                 } else if (character == 0x7C || character == 0) {
    643                         finished = 1;
    644                         si = 0;
     628        for (i = 0; str[i]; i++) {
     629                if (str[i] == 0x7C) {
     630                        i++;
     631                        break;
     632                } else if (str[i] == ' ') {
     633                        charWidth = 5;
     634                        bkpWords = words++;
     635                        bkpWidth = width;
     636                        bkpLen = i + 1;
    645637                } else {
    646                         if (fontParamTable[character].characterWidth) {
    647                                 uint16 var_C = fontParamTable[character].characterWidth + 1;
     638                        charWidth = fontParamTable[str[i]].characterWidth + 1;
     639                        width += charWidth;
     640                }
    648641
    649                                 if (si + var_C < width) {
    650                                         si += var_C;
    651                                         localMessageWidth += var_C;
    652                                 } else {
    653                                         finished = 1;
    654 
    655                                         if (localLineResult) {
    656                                                 var_16 = var_8;
    657                                                 localMessageWidth = var_6;
    658                                                 si = localLineResult;
    659                                                 di = var_2;
    660                                         }
    661                                 }
    662                         }
     642                if (!charWidth) {
     643                        continue;
    663644                }
    664645
    665                 di++;
     646                if (fullWidth + charWidth < maxWidth) {
     647                        fullWidth += charWidth;
     648                } else if (fullWidth) {
     649                        words = bkpWords;
     650                        width = bkpWidth;
     651                        i = bkpLen;
     652                        break;
     653                }
    666654        }
    667655
    668         *numWords = var_16;
    669         *messageWidth = localMessageWidth;
    670         *lineResult = si;
    671 
    672         return di;
     656        return i;
    673657}
    674658
    675659} // End of namespace Cine
  • engines/cine/various.h

     
    4343extern bool inMenu;
    4444
    4545struct SeqListElement {
    46         struct SeqListElement *next;
    4746        int16 var4;
    48         int16 var6;
     47        uint16 objIdx;
    4948        int16 var8;
    50         int16 varA;
     49        int16 frame;
    5150        int16 varC;
    5251        int16 varE;
    5352        int16 var10;
     
    6059        int16 var1E;
    6160};
    6261
    63 extern SeqListElement seqList;
     62extern Common::List<SeqListElement> seqList;
    6463
    6564extern uint16 var2;
    6665extern uint16 var3;
     
    9796extern char newObjectName[20];
    9897extern char newMsgName[20];
    9998
    100 extern char currentBgName[8][15];
    10199extern char currentCtName[15];
    102100extern char currentPartName[15];
    103101
     
    130128        int16 param;
    131129};
    132130
    133 extern uint16 defaultMenuBoxColor;
    134 extern uint16 defaultMenuBoxColor2;
    135 
    136131#define NUM_MAX_ZONE 16
    137132extern uint16 zoneData[NUM_MAX_ZONE];
    138133
    139134void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5);
    140135
    141 extern int16 additionalBgVScroll;
     136void removeMessages();
    142137
    143138void removeSeq(uint16 param1, uint16 param2, uint16 param3);
    144139uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
    145 void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
    146 void resetSeqList();
     140void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
    147141void processSeqList(void);
    148142
    149143bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y);