diff options
Diffstat (limited to 'sky')
-rw-r--r-- | sky/control.cpp | 405 | ||||
-rw-r--r-- | sky/control.h | 44 | ||||
-rw-r--r-- | sky/grid.cpp | 28 | ||||
-rw-r--r-- | sky/logic.cpp | 25 | ||||
-rw-r--r-- | sky/logic.h | 14 | ||||
-rw-r--r-- | sky/screen.cpp | 36 | ||||
-rw-r--r-- | sky/screen.h | 3 | ||||
-rw-r--r-- | sky/sky.cpp | 15 |
8 files changed, 503 insertions, 67 deletions
diff --git a/sky/control.cpp b/sky/control.cpp index 4f2a1249ad..0126255f94 100644 --- a/sky/control.cpp +++ b/sky/control.cpp @@ -115,15 +115,17 @@ void SkyTextResource::drawToScreen(bool doMask) { _system->copy_rect(_screen + _y * GAME_SCREEN_WIDTH + _x, GAME_SCREEN_WIDTH, _x, _y, cpWidth, PAN_CHAR_HEIGHT); } -SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, OSystem *system, const char *savePath) { +SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, OSystem *system, const char *savePath) { _skyScreen = screen; _skyDisk = disk; _skyMouse = mouse; _skyText = text; _skyMusic = music; + _skyLogic = logic; _system = system; _savePath = savePath; + _memListRoot = NULL; } SkyConResource *SkyControl::createResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, int16 pX, int16 pY, uint32 pText, uint8 pOnClick, uint8 panelType) { @@ -351,20 +353,24 @@ uint16 SkyControl::handleClick(SkyConResource *pButton) { return 0; case REST_GAME_PANEL: + if (SkyState::_systemVars.systemFlags & SF_CHOOSING) + return CANCEL_PRESSED; // can't save/restore while choosing animClick(pButton); return saveRestorePanel(false); // texts can't be edited case SAVE_GAME_PANEL: + if (SkyState::_systemVars.systemFlags & SF_CHOOSING) + return CANCEL_PRESSED; // can't save/restore while choosing animClick(pButton); return saveRestorePanel(true); // texts can be edited case SAVE_A_GAME: animClick(pButton); - return GAME_SAVED; + return saveGameToFile(); case RESTORE_A_GAME: animClick(pButton); - return GAME_RESTORED; + return restoreGameFromFile(); case SP_CANCEL: animClick(pButton); @@ -577,14 +583,15 @@ uint16 SkyControl::shiftUp(uint8 speed) { return SHIFTED; } -uint16 SkyControl::saveRestorePanel(bool allowEdit) { +uint16 SkyControl::saveRestorePanel(bool allowSave) { + _keyPressed = 0; buttonControl(NULL); _text->drawToScreen(WITH_MASK); // flush text restore buffer SkyConResource **lookList; uint16 cnt; - if (allowEdit) lookList = _savePanLookList; + if (allowSave) lookList = _savePanLookList; else lookList = _restorePanLookList; uint8 *saveGameTexts = (uint8*)malloc(MAX_SAVE_GAMES * MAX_TEXT_LEN); @@ -594,15 +601,15 @@ uint16 SkyControl::saveRestorePanel(bool allowEdit) { _savePanel->drawToScreen(NO_MASK); _quitButton->drawToScreen(NO_MASK); - loadSaveDescriptions(saveGameTexts); - uint16 selectedGame = 0; + loadDescriptions(saveGameTexts); + _selectedGame = 0; bool quitPanel = false; bool refreshNames = true; uint16 clickRes = 0; while (!quitPanel) { if (refreshNames) { - setUpGameSprites(saveGameTexts, textSprites, _firstText); + setUpGameSprites(saveGameTexts, textSprites, _firstText, _selectedGame, allowSave); showSprites(textSprites); refreshNames = false; } @@ -615,6 +622,10 @@ uint16 SkyControl::saveRestorePanel(bool allowEdit) { _mouseClicked = false; clickRes = CANCEL_PRESSED; quitPanel = true; + } else if (allowSave && _keyPressed) { + handleKeyPress(_keyPressed, _selectedGame * MAX_TEXT_LEN + saveGameTexts); + refreshNames = true; + _keyPressed = 0; } bool haveButton = false; @@ -628,11 +639,19 @@ uint16 SkyControl::saveRestorePanel(bool allowEdit) { clickRes = handleClick(lookList[cnt]); - if ((clickRes == CANCEL_PRESSED) || (clickRes == GAME_SAVED) || - (clickRes == GAME_RESTORED) || (clickRes == NO_DISK_SPACE)) - quitPanel = true; - if (clickRes == SHIFTED) + if (clickRes == SHIFTED) { + _selectedGame = _firstText; refreshNames = true; + } + if ((clickRes == CANCEL_PRESSED) || (clickRes == NO_DISK_SPACE) || + (clickRes == GAME_RESTORED)) + quitPanel = true; + + if (clickRes == GAME_SAVED) { + saveDescriptions(saveGameTexts); + quitPanel = true; + } + } } @@ -640,7 +659,8 @@ uint16 SkyControl::saveRestorePanel(bool allowEdit) { if ((_mouseX >= GAME_NAME_X) && (_mouseX <= GAME_NAME_X + PAN_LINE_WIDTH) && (_mouseY >= GAME_NAME_Y) && (_mouseY <= GAME_NAME_Y + PAN_CHAR_HEIGHT * MAX_ON_SCREEN)) { - selectedGame = (_mouseY - GAME_NAME_Y) / PAN_CHAR_HEIGHT + _firstText; + _selectedGame = (_mouseY - GAME_NAME_Y) / PAN_CHAR_HEIGHT + _firstText; + refreshNames = true; } } if (!haveButton) buttonControl(NULL); @@ -654,14 +674,59 @@ uint16 SkyControl::saveRestorePanel(bool allowEdit) { return clickRes; } -void SkyControl::setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum) { +bool SkyControl::checkKeyList(uint8 key) { + static const uint8 charList[14] = " ,().='-&+!?\""; + for (uint chCnt = 0; chCnt < ARRAYSIZE(charList); chCnt++) + if (charList[chCnt] == key) return true; + return false; +} + +void SkyControl::handleKeyPress(uint8 key, uint8 *textBuf) { + + if (key == 8) { // backspace + for (uint8 cnt = 0; cnt < 6; cnt++) + if (!textBuf[cnt]) return; + + while (textBuf[1]) + textBuf++; + textBuf[0] = 0; + } else { + if (((key >= 'A') && (key <= 'Z')) || ((key >= 'a') && (key <= 'z')) || + ((key >= '0') && (key <= '9')) || checkKeyList(key)) { + uint8 strLen = 0; + while (textBuf[0]) { + textBuf++; + strLen++; + } + if (strLen < MAX_TEXT_LEN) { + textBuf[0] = key; + textBuf[1] = 0; + } + } + } +} + +void SkyControl::setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum, uint16 selectedGame, bool allowSave) { nameBuf += firstNum * MAX_TEXT_LEN; for (uint16 cnt = 0; cnt < MAX_ON_SCREEN; cnt++) { - displayText_t textSpr = _skyText->displayText((char*)nameBuf, NULL, false, PAN_LINE_WIDTH, 37); + displayText_t textSpr; + if (firstNum + cnt == selectedGame) { + char tmpLine[MAX_TEXT_LEN + 2]; + memcpy(tmpLine, nameBuf, MAX_TEXT_LEN); + if (allowSave) + strcat(tmpLine,"_"); + textSpr = _skyText->displayText(tmpLine, NULL, false, PAN_LINE_WIDTH, 0); + } else { + textSpr = _skyText->displayText((char*)nameBuf, NULL, false, PAN_LINE_WIDTH, 37); + } nameBuf += MAX_TEXT_LEN; nameSprites[cnt] = (dataFileHeader*)textSpr.textData; + if (firstNum + cnt == selectedGame) + nameSprites[cnt]->flag = 1; + else + nameSprites[cnt]->flag = 0; } } @@ -671,17 +736,23 @@ void SkyControl::showSprites(dataFileHeader **nameSprites) { for (uint16 cnt = 0; cnt < MAX_ON_SCREEN; cnt++) { drawResource->setSprite(nameSprites[cnt]); drawResource->setXY(GAME_NAME_X, GAME_NAME_Y + cnt * PAN_CHAR_HEIGHT); - drawResource->drawToScreen(NO_MASK); + if (nameSprites[cnt]->flag) { // name is highlighted + for (uint16 cnty = GAME_NAME_Y + cnt * PAN_CHAR_HEIGHT; cnty < GAME_NAME_Y + (cnt + 1) * PAN_CHAR_HEIGHT - 1; cnty++) + memset(_screenBuf + cnty * GAME_SCREEN_WIDTH + GAME_NAME_X, 37, PAN_LINE_WIDTH); + drawResource->drawToScreen(WITH_MASK); + _system->copy_rect(_screenBuf + (GAME_NAME_Y + cnt * PAN_CHAR_HEIGHT) * GAME_SCREEN_WIDTH + GAME_NAME_X, GAME_SCREEN_WIDTH, GAME_NAME_X, GAME_NAME_Y + cnt * PAN_CHAR_HEIGHT, PAN_LINE_WIDTH, PAN_CHAR_HEIGHT); + } else + drawResource->drawToScreen(NO_MASK); } delete drawResource; } -void SkyControl::loadSaveDescriptions(uint8 *destBuf) { +void SkyControl::loadDescriptions(uint8 *destBuf) { memset(destBuf, 0, MAX_SAVE_GAMES * MAX_TEXT_LEN); File *inf = new File(); - inf->open("SKY.SAV",_savePath); + inf->open("SKY-VM.SAV",_savePath); if (inf->isOpen()) { uint8 *tmpBuf = (uint8*)malloc(inf->size()); inf->read(tmpBuf, inf->size()); @@ -706,15 +777,42 @@ void SkyControl::loadSaveDescriptions(uint8 *destBuf) { } } -uint16 SkyControl::saveGameToFile(char *fName) { +void SkyControl::saveDescriptions(uint8 *srcBuf) { + + uint8 *tmpBuf = (uint8*)malloc(MAX_SAVE_GAMES * MAX_TEXT_LEN); + uint8 *tmpPos = tmpBuf; + uint8 *srcPos = srcBuf; + for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) { + uint8 namePos = 5; + while (srcPos[namePos]) { + if (srcPos[namePos] != '_') { + *tmpPos = srcPos[namePos]; + tmpPos++; + } + namePos++; + } + *tmpPos = 0; + tmpPos++; + srcPos += MAX_TEXT_LEN; + } + File *outf = new File(); + outf->open("SKY-VM.SAV", _savePath, File::kFileWriteMode); + outf->write(tmpBuf, tmpPos - tmpBuf); + outf->close(); + free(tmpBuf); +} +uint16 SkyControl::saveGameToFile(void) { + + char fName[20]; + sprintf(fName,"SKY-VM.%03d", _selectedGame); File *outf = new File(); if (!outf->open(fName, _savePath, File::kFileWriteMode)) { delete outf; return NO_DISK_SPACE; } - uint8 *saveData = (uint8*)malloc(0x20000); + uint8 *saveData = (uint8*)malloc(0x50000); uint32 fSize = prepareSaveData(saveData); if (outf->write(saveData, fSize) != fSize) { @@ -739,6 +837,23 @@ void SkyControl::stosMegaSet(uint8 **destPos, MegaSet *mega) { // anims, stands, turnTable } +void SkyControl::stosStr(uint8 **destPos, uint16 *src, bool isGraf) { + uint16 strLen = 0; + if (isGraf) { + while (src[strLen] || src[strLen+2]) + strLen++; + strLen += 3; + } else { + while (src[strLen]) + strLen++; + strLen++; + } + STOSW(*destPos, strLen); + for (uint16 cnt = 0; cnt < strLen; cnt++) { + STOSW(*destPos, src[cnt]); + } +} + void SkyControl::stosCompact(uint8 **destPos, Compact *cpt) { uint16 saveType = 0; if (cpt->extCompact) { @@ -747,8 +862,17 @@ void SkyControl::stosCompact(uint8 **destPos, Compact *cpt) { if (cpt->extCompact->megaSet1) saveType |= SAVE_MEGA1; if (cpt->extCompact->megaSet2) saveType |= SAVE_MEGA2; if (cpt->extCompact->megaSet3) saveType |= SAVE_MEGA3; + if (cpt->extCompact->turnProg) saveType |= SAVE_TURNP; } + if (cpt->grafixProg) saveType |= SAVE_GRAFX; + STOSW(*destPos, saveType); + + if (saveType & SAVE_GRAFX) + stosStr(destPos, cpt->grafixProg, true); + if (saveType & SAVE_TURNP) + stosStr(destPos, cpt->extCompact->turnProg, false); + STOSW(*destPos, cpt->logic); STOSW(*destPos, cpt->status); STOSW(*destPos, cpt->sync); @@ -815,21 +939,13 @@ void SkyControl::stosCompact(uint8 **destPos, Compact *cpt) { } } -void SkyControl::stosAR(uint8 **destPos, uint8 *arData) { - - uint16 *data = (uint16*)arData; - for (uint8 cnt = 0; cnt < 32; cnt++) - STOSW(*destPos, TO_LE_16(data[cnt])); -} - uint32 SkyControl::prepareSaveData(uint8 *destBuf) { uint32 cnt; memset(destBuf, 0, 4); // space for data size uint8 *destPos = destBuf + 4; - memcpy(destPos, SAVE_HEADER, sizeof(SAVE_HEADER)); - destPos += sizeof(SAVE_HEADER); - //STOSD(destPos, SkyLogic::_scriptVariables[CUR_SECTION]); + STOSD(destPos, SAVE_FILE_REVISION); + STOSD(destPos, _skyMusic->giveCurrentMusic()); //TODO: save queued sfx @@ -846,9 +962,6 @@ uint32 SkyControl::prepareSaveData(uint8 *destBuf) { for (cnt = 0; cnt < ARRAYSIZE(_saveLoadCpts); cnt++) stosCompact(&destPos, _saveLoadCpts[cnt]); - for (cnt = 0; cnt < ARRAYSIZE(_saveLoadARs); cnt++) - stosAR(&destPos, _saveLoadARs[cnt]); - for (cnt = 0; cnt < 3; cnt++) STOSW(destPos, SkyCompact::park_table[cnt]); @@ -862,6 +975,232 @@ uint32 SkyControl::prepareSaveData(uint8 *destBuf) { #undef STOSD #undef STOSW +void SkyControl::appendMemList(uint16 *pMem) { + AllocedMem *newMem = new AllocedMem; + newMem->mem = pMem; + newMem->next = _memListRoot; + _memListRoot = newMem; +} + +void SkyControl::freeMemList(void) { + AllocedMem *block = _memListRoot; + AllocedMem *temp; + while (block) { + temp = block; + free(block->mem); + block = block->next; + delete temp; + } + _memListRoot = NULL; +} + + +#define LODSD(strPtr, val) { val = READ_LE_UINT32(strPtr); (strPtr) += 4; } +#define LODSW(strPtr, val) { val = READ_LE_UINT16(strPtr); (strPtr) += 2; } + +void SkyControl::lodsMegaSet(uint8 **srcPos, MegaSet *mega) { + LODSW(*srcPos, mega->gridWidth); + LODSW(*srcPos, mega->colOffset); + LODSW(*srcPos, mega->colWidth); + LODSW(*srcPos, mega->lastChr); + // anims, stands, turnTable +} + +void SkyControl::lodsCompact(uint8 **srcPos, Compact *cpt) { + + uint16 saveType, cnt; + LODSW(*srcPos, saveType); + if ((saveType & (SAVE_EXT | SAVE_TURNP)) && (cpt->extCompact == NULL)) + error("Can't restore! SaveData is SAVE_EXT for Compact"); + if ((saveType & SAVE_MEGA0) && (cpt->extCompact->megaSet0 == NULL)) + error("Can't restore! SaveData is SAVE_MEGA0 for Compact"); + if ((saveType & SAVE_MEGA1) && (cpt->extCompact->megaSet1 == NULL)) + error("Can't restore! SaveData is SAVE_MEGA1 for Compact"); + if ((saveType & SAVE_MEGA2) && (cpt->extCompact->megaSet2 == NULL)) + error("Can't restore! SaveData is SAVE_MEGA2 for Compact"); + if ((saveType & SAVE_MEGA3) && (cpt->extCompact->megaSet3 == NULL)) + error("Can't restore! SaveData is SAVE_MEGA3 for Compact"); + + if (saveType & SAVE_GRAFX) { + uint16 grafxLen; + LODSW(*srcPos, grafxLen); + cpt->grafixProg = (uint16*)malloc(grafxLen << 1); + appendMemList(cpt->grafixProg); + for (cnt = 0; cnt < grafxLen; cnt++) { + LODSW(*srcPos, cpt->grafixProg[cnt]); + } + } else + cpt->grafixProg = NULL; + + if (saveType & SAVE_TURNP) { + uint16 turnLen; + LODSW(*srcPos, turnLen); + cpt->extCompact->turnProg = (uint16*)malloc(turnLen << 1); + appendMemList(cpt->extCompact->turnProg); + for (cnt = 0; cnt < turnLen; cnt++) + LODSW(*srcPos, cpt->extCompact->turnProg[cnt]); + } else if (cpt->extCompact) + cpt->extCompact->turnProg = NULL; + + LODSW(*srcPos, cpt->logic); + LODSW(*srcPos, cpt->status); + LODSW(*srcPos, cpt->sync); + LODSW(*srcPos, cpt->screen); + LODSW(*srcPos, cpt->place); + // getToTable + LODSW(*srcPos, cpt->xcood); + LODSW(*srcPos, cpt->ycood); + LODSW(*srcPos, cpt->frame); + LODSW(*srcPos, cpt->cursorText); + LODSW(*srcPos, cpt->mouseOn); + LODSW(*srcPos, cpt->mouseOff); + LODSW(*srcPos, cpt->mouseClick); + LODSW(*srcPos, cpt->mouseRelX); + LODSW(*srcPos, cpt->mouseRelY); + LODSW(*srcPos, cpt->mouseSizeX); + LODSW(*srcPos, cpt->mouseSizeY); + LODSW(*srcPos, cpt->actionScript); + LODSW(*srcPos, cpt->upFlag); + LODSW(*srcPos, cpt->downFlag); + LODSW(*srcPos, cpt->getToFlag); + LODSW(*srcPos, cpt->flag); + LODSW(*srcPos, cpt->mood); + // grafixProg + LODSW(*srcPos, cpt->offset); + LODSW(*srcPos, cpt->mode); + LODSW(*srcPos, cpt->baseSub); + LODSW(*srcPos, cpt->baseSub_off); + if (saveType & SAVE_EXT) { + LODSW(*srcPos, cpt->extCompact->actionSub); + LODSW(*srcPos, cpt->extCompact->actionSub_off); + LODSW(*srcPos, cpt->extCompact->getToSub); + LODSW(*srcPos, cpt->extCompact->getToSub_off); + LODSW(*srcPos, cpt->extCompact->extraSub); + LODSW(*srcPos, cpt->extCompact->extraSub_off); + LODSW(*srcPos, cpt->extCompact->dir); + LODSW(*srcPos, cpt->extCompact->stopScript); + LODSW(*srcPos, cpt->extCompact->miniBump); + LODSW(*srcPos, cpt->extCompact->leaving); + LODSW(*srcPos, cpt->extCompact->atWatch); + LODSW(*srcPos, cpt->extCompact->atWas); + LODSW(*srcPos, cpt->extCompact->alt); + LODSW(*srcPos, cpt->extCompact->request); + LODSW(*srcPos, cpt->extCompact->spWidth_xx); + LODSW(*srcPos, cpt->extCompact->spColour); + LODSW(*srcPos, cpt->extCompact->spTextId); + LODSW(*srcPos, cpt->extCompact->spTime); + LODSW(*srcPos, cpt->extCompact->arAnimIndex); + // turnProg + LODSW(*srcPos, cpt->extCompact->waitingFor); + LODSW(*srcPos, cpt->extCompact->arTargetX); + LODSW(*srcPos, cpt->extCompact->arTargetY); + // animScratch + LODSW(*srcPos, cpt->extCompact->megaSet); + + if (saveType & SAVE_MEGA0) + lodsMegaSet(srcPos, cpt->extCompact->megaSet0); + if (saveType & SAVE_MEGA1) + lodsMegaSet(srcPos, cpt->extCompact->megaSet1); + if (saveType & SAVE_MEGA2) + lodsMegaSet(srcPos, cpt->extCompact->megaSet2); + if (saveType & SAVE_MEGA3) + lodsMegaSet(srcPos, cpt->extCompact->megaSet3); + } +} + +uint16 SkyControl::parseSaveData(uint8 *srcBuf) { + + uint32 reloadList[60]; + uint32 oldSection = SkyLogic::_scriptVariables[CUR_SECTION]; + + uint32 cnt; + uint8 *srcPos = srcBuf; + uint32 size; + uint32 saveRev; + + LODSD(srcPos, size); + LODSD(srcPos, saveRev); + if (saveRev != SAVE_FILE_REVISION) { + warning("Unknown save file revision (%d)",saveRev); + return RESTORE_FAILED; + } + + freeMemList(); // memory from last restore isn't needed anymore + + uint32 music, charSet, mouseType, palette; + LODSD(srcPos, music); + LODSD(srcPos, charSet); + LODSD(srcPos, mouseType); + LODSD(srcPos, palette); + + for (cnt = 0; cnt < 838; cnt++) + LODSD(srcPos, SkyLogic::_scriptVariables[cnt]); + + for (cnt = 0; cnt < 60; cnt++) + LODSD(srcPos, reloadList[cnt]); + + for (cnt = 0; cnt < ARRAYSIZE(_saveLoadCpts); cnt++) + lodsCompact(&srcPos, _saveLoadCpts[cnt]); + + for (cnt = 0; cnt < 3; cnt++) + LODSW(srcPos, SkyCompact::park_table[cnt]); + + for (cnt = 0; cnt < 13; cnt++) + LODSW(srcPos, SkyCompact::high_floor_table[cnt]); + + if (srcPos - srcBuf != size) + error("Restore failed! Savegame data = %d bytes. Expected size: %d.\n", srcPos-srcBuf, size); + + _skyLogic->fnLeaveSection(oldSection, 0, 0); + _skyLogic->fnEnterSection(SkyLogic::_scriptVariables[CUR_SECTION], 0, 0); + _skyDisk->refreshFilesList(reloadList); + _skyMusic->startMusic((uint16)music); + _skyText->fnSetFont(charSet); + _skyMouse->spriteMouse((uint16)mouseType, 0, 0); + SkyState::_systemVars.currentPalette = palette; // will be set when doControlPanel ends + SkyState::_systemVars.systemFlags |= SF_GAME_RESTORED; // what's that for? + + return GAME_RESTORED; +} + +#undef LODSD +#undef LODSW + +uint16 SkyControl::restoreGameFromFile(void) { + + char fName[20]; + sprintf(fName,"SKY-VM.%03d", _selectedGame); + File *inf = new File(); + if (!inf->open(fName, _savePath)) { + delete inf; + return RESTORE_FAILED; + } + + uint32 fSize = inf->size(); + uint8 *saveData = (uint8*)malloc(fSize); + uint32 infSize = inf->readUint32LE(); + inf->seek(0, SEEK_SET); + + if (fSize != infSize) { + warning("File size doesn't match expected data size!"); + delete inf; + free(saveData); + return RESTORE_FAILED; + } + if (inf->read(saveData, fSize) != fSize) { + warning("Can't read from file!"); + delete inf; + free(saveData); + return RESTORE_FAILED; + } + + uint16 res = parseSaveData(saveData); + inf->close(); + delete inf; + free(saveData); + return res; +} + void SkyControl::delay(unsigned int amount) { OSystem::Event event; diff --git a/sky/control.h b/sky/control.h index 62ccdc604d..ab025fbb0f 100644 --- a/sky/control.h +++ b/sky/control.h @@ -29,6 +29,7 @@ #include "sky/screen.h" #include "sky/disk.h" #include "sky/mouse.h" +#include "sky/logic.h" #define MAX_SAVE_GAMES 999 #define MAX_TEXT_LEN 80 @@ -48,8 +49,6 @@ #define MAX_ON_SCREEN ((SP_HEIGHT - SP_TOP_GAP - SP_BOT_GAP) / PAN_CHAR_HEIGHT) // no of save games on screen #define CP_PANEL 60400 // main panel sprite -#define CHARACTER_LIST " ,().='-&+!?\"" // list of allowed characters - #define MAINPANEL 0 #define SAVEPANEL 1 @@ -100,8 +99,15 @@ #define SAVE_MEGA1 4 #define SAVE_MEGA2 8 #define SAVE_MEGA3 16 +#define SAVE_GRAFX 32 +#define SAVE_TURNP 64 + +#define SAVE_FILE_REVISION 1 -#define SAVE_HEADER "(C) Revolution Software Ltd 1993.\x00System 2 written by David Sykes and Tony Warriner\x0D\x0APortable implementation done by the ScummVM team\x0D\x0ASave File Revision 1\x00" +struct AllocedMem { + uint16 *mem; + AllocedMem *next; +}; class SkyConResource { public: @@ -135,7 +141,7 @@ private: class SkyControl { public: - SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, OSystem *system, const char *savePath); + SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, OSystem *system, const char *savePath); void doControlPanel(void); void showGameQuitMsg(bool useScreen = true); @@ -145,9 +151,14 @@ private: void drawMainPanel(void); void delay(unsigned int amount); void buttonControl(SkyConResource *pButton); - void loadSaveDescriptions(uint8 *destBuf); - void setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum); + + void loadDescriptions(uint8 *destBuf); + void saveDescriptions(uint8 *srcBuf); + void setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum, uint16 selectedGame, bool allowSave); void showSprites(dataFileHeader **nameSprites); + bool checkKeyList(uint8 key); + void handleKeyPress(uint8 key, uint8 *textBuf); + void animClick(SkyConResource *pButton); bool getYesNo(void); uint16 doMusicSlide(void); @@ -159,22 +170,33 @@ private: uint16 shiftUp(uint8 speed); const char *_savePath; - uint16 saveGameToFile(char *fName); + void appendMemList(uint16 *pMem); + void freeMemList(void); + + uint16 _selectedGame; + uint16 saveGameToFile(void); void stosMegaSet(uint8 **destPos, MegaSet *mega); void stosCompact(uint8 **destPos, Compact *cpt); - void stosAR(uint8 **destPos, uint8 *arData); + void stosStr(uint8 **destPos, uint16 *src, bool isGraph); uint32 prepareSaveData(uint8 *destBuf); - uint16 restoreGameFromFile(char *fName); + + uint16 restoreGameFromFile(void); + void lodsMegaSet(uint8 **srcPos, MegaSet *mega); + void lodsCompact(uint8 **srcPos, Compact *cpt); + void lodsStr(uint8 **srcPos, uint16 *src); + uint16 parseSaveData(uint8 *srcBuf); + static Compact *_saveLoadCpts[833]; // \ moved to sky/compacts/savedata.cpp static uint8 *_saveLoadARs[18]; // / - uint16 saveRestorePanel(bool allowEdit); + uint16 saveRestorePanel(bool allowSave); SkyScreen *_skyScreen; SkyDisk *_skyDisk; SkyMouse *_skyMouse; SkyText *_skyText; SkyMusicBase *_skyMusic; + SkyLogic *_skyLogic; OSystem *_system; int _mouseX, _mouseY; bool _mouseClicked; @@ -195,6 +217,8 @@ private: uint8 *musicBodge; } _sprites; + AllocedMem *_memListRoot; + uint8 *_screenBuf; int _lastButton; uint32 _curButtonText; diff --git a/sky/grid.cpp b/sky/grid.cpp index db08bfa9fc..4f4e4886b0 100644 --- a/sky/grid.cpp +++ b/sky/grid.cpp @@ -161,23 +161,25 @@ bool SkyGrid::getGridValues(uint32 x, uint32 y, uint32 width, Compact *cpt, uint if (y < TOP_LEFT_Y) return false; // off screen y -= TOP_LEFT_Y; y >>= 3; // convert to blocks - if (y >= GRID_Y) return false; // off screen + if (y >= GAME_SCREEN_HEIGHT >> 3) return false; // off screen bitPos = y * 40; width++; x >>= 3; // convert to blocks - int32 x_signed = (x - (TOP_LEFT_X >> 3)); - if (x_signed < 0) { // at least partially off screen - if (x_signed + width <= 0) return false; // completely off screen - else width += x_signed; // adjust width to visible part and continue - // x_signed is negative, so it's += - } - if ((GAME_SCREEN_WIDTH >> 3) <= x_signed) return false; // off screen - if ((GAME_SCREEN_WIDTH >> 3) < x_signed + width) { // at least partially of screen - if ((uint32)((GAME_SCREEN_WIDTH >> 3) - x_signed) >= width) return false; // off screen - else width -= (GAME_SCREEN_WIDTH >> 3) - x_signed; // adjust width - } - bitPos += x_signed; + if (x < (TOP_LEFT_X >> 3)) { // at least partially off screen + if (x + width < (TOP_LEFT_X >> 3)) return false; // completely off screen + else { + width -= (TOP_LEFT_X >> 3) - x; + x = 0; + } + } else + x -= TOP_LEFT_X >> 3; + + if ((GAME_SCREEN_WIDTH >> 3) <= x) return false; // off screen + if ((GAME_SCREEN_WIDTH >> 3) < x + width) // partially off screen + width = (GAME_SCREEN_WIDTH >> 3) - x; + + bitPos += x; int32 screenGridOfs = _gridConvertTable[cpt->screen] * GRID_SIZE; bitPos += (screenGridOfs << 3); // convert to bits uint32 tmpBits = 0x1F - (bitPos&0x1F); diff --git a/sky/logic.cpp b/sky/logic.cpp index c18ca5b6ec..e8a0684c0f 100644 --- a/sky/logic.cpp +++ b/sky/logic.cpp @@ -2237,8 +2237,29 @@ bool SkyLogic::fnLookAt(uint32 a, uint32 b, uint32 c) { return true; } -bool SkyLogic::fnLincTextModule(uint32 a, uint32 b, uint32 c) { - error("Stub: fnLincTextModule"); +bool SkyLogic::fnLincTextModule(uint32 textPos, uint32 textNo, uint32 buttonAction) { + + uint16 cnt; + if (buttonAction & 0x8000) + for (cnt = LINC_DIGIT_0; cnt <= LINC_DIGIT_9; cnt++) + _scriptVariables[cnt] = 0; + buttonAction &= 0x7FFF; + if (buttonAction < 10) + _scriptVariables[LINC_DIGIT_0 + buttonAction] = textNo; + + lowTextManager_t text = _skyText->lowTextManager(textNo, 220, 0, 215, false); + + Compact *textCpt = SkyState::fetchCompact(text.compactNum); + + if (textPos < 20) { // line number (for text) + textCpt->xcood = 152; + textCpt->ycood = (uint16)textPos * 13 + 170; + } else if (textPos > 20) { // x coordinate (for numbers) + textCpt->xcood = (uint16)textPos; + textCpt->ycood = 214; + } else warning("::fnLincTextModule: textPos == 20"); + textCpt->getToFlag = (uint16)textNo; + return true; } bool SkyLogic::fnTextKill2(uint32 a, uint32 b, uint32 c) { diff --git a/sky/logic.h b/sky/logic.h index 1167bda185..96349e3f2b 100644 --- a/sky/logic.h +++ b/sky/logic.h @@ -64,7 +64,17 @@ enum scriptVariableOffsets { MENU = 102, RND = 115, CUR_SECTION = 143, - REICH_DOOR_FLAG = 470 + REICH_DOOR_FLAG = 470, + LINC_DIGIT_0 = 646, + LINC_DIGIT_1 = 647, + LINC_DIGIT_2 = 648, + LINC_DIGIT_3 = 649, + LINC_DIGIT_4 = 650, + LINC_DIGIT_5 = 651, + LINC_DIGIT_6 = 651, + LINC_DIGIT_7 = 653, + LINC_DIGIT_8 = 654, + LINC_DIGIT_9 = 655, }; class SkyAutoRoute; @@ -215,6 +225,7 @@ public: void stdSpeak(Compact *target, uint32 textNum, uint32 animNum, uint32 base); static uint32 _scriptVariables[838]; + SkyGrid *_skyGrid; protected: void push(uint32); @@ -241,7 +252,6 @@ protected: SkyScreen *_skyScreen; SkyDisk *_skyDisk; - SkyGrid *_skyGrid; SkyText *_skyText; SkyMusicBase *_skyMusic; SkySound *_skySound; diff --git a/sky/screen.cpp b/sky/screen.cpp index 324ed0500e..f10a9e3757 100644 --- a/sky/screen.cpp +++ b/sky/screen.cpp @@ -300,9 +300,7 @@ void SkyScreen::fnFadeUp(uint32 palNum, uint32 scroll) { //_currentScreen points to new screen, //_scrollScreen points to graphic showing old room - if (scroll == 13) scroll = 123; // script bug (?) in lower area - if ((scroll != 123) && (scroll != 321) && (scroll)) { - warning("unknown scroll parameter %d",scroll); + if ((scroll != 123) && (scroll != 321)) { scroll = 0; } @@ -728,3 +726,35 @@ void SkyScreen::verticalMask(void) { } } +void SkyScreen::paintBox(uint16 x, uint16 y) { + + uint8 *screenPos = _currentScreen + y * GAME_SCREEN_WIDTH + x; + memset(screenPos, 255, 8); + for (uint8 cnt = 1; cnt < 8; cnt++) { + *(screenPos + cnt * GAME_SCREEN_WIDTH) = 255; + *(screenPos + cnt * GAME_SCREEN_WIDTH + 7) = 255; + } + memset(screenPos + 7 * GAME_SCREEN_WIDTH, 255, 7); +} + +void SkyScreen::showGrid(uint8 *gridBuf) { + + uint32 gridData = 0; + uint8 bitsLeft = 0; + for (uint16 cnty = 0; cnty < GAME_SCREEN_HEIGHT >> 3; cnty++) { + for (uint16 cntx = 0; cntx < GAME_SCREEN_WIDTH >> 3; cntx++) { + if (!bitsLeft) { + bitsLeft = 32; + gridData = *(uint32*)gridBuf; + gridBuf += 4; + } + if (gridData & 0x80000000) + paintBox(cntx << 3, cnty << 3); + bitsLeft--; + gridData <<= 1; + } + } + _system->copy_rect(_currentScreen, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT); + +} + diff --git a/sky/screen.h b/sky/screen.h index 53348ccac3..8b76de246b 100644 --- a/sky/screen.h +++ b/sky/screen.h @@ -81,6 +81,9 @@ public: void spriteEngine(void); + void paintBox(uint16 x, uint16 y); + void showGrid(uint8 *gridBuf); + private: OSystem *_system; SkyDisk *_skyDisk; diff --git a/sky/sky.cpp b/sky/sky.cpp index 1f32882c08..c62064ed18 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -105,15 +105,22 @@ void SkyState::go() { while (1) { delay(_systemVars.gameSpeed); + /*if (_key_pressed == 'g') { + warning("loading grid"); + _skyLogic->_skyGrid->loadGrids(); + _key_pressed = 0; + }*/ if ((_key_pressed == 27) || (_key_pressed == 63)) { // 27 = escape, 63 = F5 _key_pressed = 0; _skyControl->doControlPanel(); } _skyMouse->mouseEngine((uint16)_sdl_mouse_x, (uint16)_sdl_mouse_y); _skyLogic->engine(); + //_skyScreen->forceRefresh(); _skyScreen->recreate(); _skyScreen->spriteEngine(); _skyScreen->flip(); + //_skyScreen->showGrid(_skyLogic->_skyGrid->giveGrid(SkyLogic::_scriptVariables[SCREEN])); _system->update_screen(); } } @@ -127,13 +134,13 @@ void SkyState::initialise(void) { if (_detector->getMidiDriverType() == MD_ADLIB) { _systemVars.systemFlags |= SF_SBLASTER; - _skyMusic = new SkyAdlibMusic(_mixer, _skyDisk); + _skyMusic = new SkyAdlibMusic(_mixer, _skyDisk, _system); } else { _systemVars.systemFlags |= SF_ROLAND; if (_detector->_native_mt32) - _skyMusic = new SkyMT32Music(_detector->createMidi(), _skyDisk); + _skyMusic = new SkyMT32Music(_detector->createMidi(), _skyDisk, _system); else - _skyMusic = new SkyGmMusic(_detector->createMidi(), _skyDisk); + _skyMusic = new SkyGmMusic(_detector->createMidi(), _skyDisk, _system); } if (isCDVersion()) _systemVars.systemFlags |= SF_ALLOW_SPEECH; @@ -156,7 +163,7 @@ void SkyState::initialise(void) { _timer = Engine::_timer; // initialize timer *after* _skyScreen has been initialized. _timer->installProcedure(&timerHandler, 1000000 / 50); //call 50 times per second - _skyControl = new SkyControl(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _system, getSavePath()); + _skyControl = new SkyControl(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _system, getSavePath()); } void SkyState::initItemList() { |