[Scummvm-git-logs] scummvm master -> e370442b5498e03f9a53f12752791da9ebcff495
sev-
noreply at scummvm.org
Thu Sep 21 19:41:28 UTC 2023
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
8b3f16e923 SWORD1: Rewrite main menu code
7fc2afce99 SWORD1: Change save slot names to byte[]
214a8a3d49 SWORD1: Add proper support for death font for russian versions
e370442b54 SWORD1: Fix US/Localized versions crashing at startup after running UK/Demo
Commit: 8b3f16e9231df78d53d5d121325a17af008353a2
https://github.com/scummvm/scummvm/commit/8b3f16e9231df78d53d5d121325a17af008353a2
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-21T21:41:22+02:00
Commit Message:
SWORD1: Rewrite main menu code
This now matches the source code and the executable;
this fixes a lot of inaccuracies, implements the tombstone
"death font", implements the Speed setting.
The askForCd() routine is now more accurate as well.
Changed paths:
engines/sword1/control.cpp
engines/sword1/control.h
engines/sword1/logic.cpp
engines/sword1/metaengine.cpp
engines/sword1/resman.cpp
engines/sword1/resman.h
engines/sword1/screen.cpp
engines/sword1/screen.h
engines/sword1/sword1.cpp
engines/sword1/sword1.h
engines/sword1/sworddefs.h
engines/sword1/swordres.h
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 808da56b365..71baa6157da 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -70,162 +70,118 @@ enum LangStrings {
STR_DRIVE_FULL
};
-enum ButtonIds {
- BUTTON_DONE = 1,
- BUTTON_MAIN_PANEL,
- BUTTON_SAVE_PANEL,
- BUTTON_RESTORE_PANEL,
- BUTTON_RESTART,
- BUTTON_QUIT,
- BUTTON_SPEED,
- BUTTON_VOLUME_PANEL,
- BUTTON_TEXT,
- BUTTON_CONFIRM,
-//-
- BUTTON_SCROLL_UP_FAST,
- BUTTON_SCROLL_UP_SLOW,
- BUTTON_SCROLL_DOWN_SLOW,
- BUTTON_SCROLL_DOWN_FAST,
- BUTTON_SAVE_SELECT1,
- BUTTON_SAVE_SELECT2,
- BUTTON_SAVE_SELECT3,
- BUTTON_SAVE_SELECT4,
- BUTTON_SAVE_SELECT5,
- BUTTON_SAVE_SELECT6,
- BUTTON_SAVE_SELECT7,
- BUTTON_SAVE_SELECT8,
- BUTTON_SAVE_RESTORE_OKAY,
- BUTTON_SAVE_CANCEL,
-//-
- CONFIRM_OKAY,
- CONFIRM_CANCEL
+const Button Control::panelButtons[8] = {
+ { 145, 188, 165, 214 },
+ { 145, 224, 165, 250 },
+ { 145, 260, 165, 286 },
+ { 145, 296, 165, 322 },
+ { 475, 188, 495, 214 },
+ { 475, 224, 495, 250 },
+ { 475, 260, 495, 286 },
+ { 475, 332, 495, 358 }
};
-enum TextModes {
- TEXT_LEFT_ALIGN = 0,
- TEXT_CENTER,
- TEXT_RIGHT_ALIGN,
- TEXT_RED_FONT = 128
-};
-
-ControlButton::ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, uint8 flag, ResMan *pResMan, uint8 *screenBuf, OSystem *system) {
- _x = x;
- _y = y;
- _id = id;
- _flag = flag;
- _resId = resId;
- _resMan = pResMan;
- _frameIdx = 0;
- _resMan->resOpen(_resId);
- FrameHeader *tmp = _resMan->fetchFrame(_resMan->fetchRes(_resId), 0);
- _width = _resMan->getUint16(tmp->width);
- _width = (_width > SCREEN_WIDTH) ? SCREEN_WIDTH : _width;
- _height = _resMan->getUint16(tmp->height);
- if ((x == 0) && (y == 0)) { // center the frame (used for panels);
- _x = (((640 - _width) / 2) < 0) ? 0 : ((640 - _width) / 2);
- _y = (((480 - _height) / 2) < 0) ? 0 : ((480 - _height) / 2);
- }
- _dstBuf = screenBuf + _y * SCREEN_WIDTH + _x;
- _system = system;
-}
-
-ControlButton::~ControlButton() {
- _resMan->resClose(_resId);
-}
-
-bool ControlButton::isSaveslot() {
- return ((_resId >= SR_SLAB1) && (_resId <= SR_SLAB4));
-}
-
-void ControlButton::draw() {
- FrameHeader *fHead = _resMan->fetchFrame(_resMan->fetchRes(_resId), _frameIdx);
- uint8 *src = (uint8 *)fHead + sizeof(FrameHeader);
- uint8 *dst = _dstBuf;
+const Button Control::deathButtons[8] = {
+ { 0, 0, 0, 0 },
+ { 250, 224, 270, 250 },
+ { 250, 260, 270, 286 },
+ { 250, 296, 270, 322 },
- if (SwordEngine::isPsx() && _resId) {
- uint8 *HIFbuf = (uint8 *)malloc(_resMan->readUint16(&fHead->height) * _resMan->readUint16(&fHead->width));
- memset(HIFbuf, 0, _resMan->readUint16(&fHead->height) * _resMan->readUint16(&fHead->width));
- Screen::decompressHIF(src, HIFbuf);
- src = HIFbuf;
-
- if (_resMan->readUint16(&fHead->width) < 300)
- for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
- for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
- if (src[cntx])
- dst[cntx] = src[cntx];
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 }
+};
- dst += SCREEN_WIDTH;
- for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
- if (src[cntx])
- dst[cntx] = src[cntx];
+const Button Control::confirmButtons[2] = {
+ { 260, 192, 284, 216 },
+ { 260, 256, 284, 280 }
+};
- dst += SCREEN_WIDTH;
- src += _resMan->readUint16(&fHead->width);
- }
- else if (_resId == SR_DEATHPANEL) { // Check for death panel psx version (which is 1/3 of original width)
- for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height) / 2; cnt++) {
- //Stretched panel is bigger than 640px, check we don't draw outside screen
- for (uint16 cntx = 0; (cntx < (_resMan->readUint16(&fHead->width)) / 3) && (cntx < (SCREEN_WIDTH - 3)); cntx++)
- if (src[cntx]) {
- dst[cntx * 3] = src[cntx];
- dst[cntx * 3 + 1] = src[cntx];
- dst[cntx * 3 + 2] = src[cntx];
- }
- dst += SCREEN_WIDTH;
+const Button Control::speedButtons[3] = {
+ { 240, 136, 264, 160 },
+ { 240, 200, 264, 224 },
+ { 380, 256, 404, 280 }
+};
- for (uint16 cntx = 0; cntx < (_resMan->readUint16(&fHead->width)) / 3; cntx++)
- if (src[cntx]) {
- dst[cntx * 3] = src[cntx];
- dst[cntx * 3 + 1] = src[cntx];
- dst[cntx * 3 + 2] = src[cntx];
- }
- dst += SCREEN_WIDTH;
- src += _resMan->readUint16(&fHead->width) / 3;
- }
- } else { //save slots needs to be multiplied by 2 in height
- for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
- for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width) / 2; cntx++)
- if (src[cntx]) {
- dst[cntx * 2] = src[cntx];
- dst[cntx * 2 + 1] = src[cntx];
- }
+const Button Control::saveButtons[SAVEBUTTONS] = {
+ { 114, 32, 490, 67 },
+ { 114, 68, 490, 103 },
+ { 114, 104, 490, 139 },
+ { 114, 140, 490, 175 },
+ { 114, 176, 490, 211 },
+ { 114, 212, 490, 247 },
+ { 114, 248, 490, 283 },
+ { 114, 284, 490, 319 },
+
+ { 516, 25, 532, 40 },
+ { 516, 45, 532, 60 },
+ { 516, 289, 532, 305 },
+ { 516, 310, 532, 325 },
+
+ { 125, 338, 149, 366 },
+ { 462, 338, 485, 366 }
+};
- dst += SCREEN_WIDTH;
- for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width) / 2; cntx++)
- if (src[cntx]) {
- dst[cntx * 2] = src[cntx];
- dst[cntx * 2 + 1] = src[cntx];
- }
+const Button Control::restoreButtons[SAVEBUTTONS] = {
+ { 110, 100, SCREEN_FULL_DEPTH, 140 },
- dst += SCREEN_WIDTH;
- src += _resMan->readUint16(&fHead->width) / 2;
- }
- }
+ { 516, 45, 532, 60 },
+ { 516, 25, 532, 40 },
+ { 516, 289, 532, 305 },
+ { 516, 310, 532, 325 },
- free(HIFbuf);
- } else
- for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
- for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
- if (src[cntx])
- dst[cntx] = src[cntx];
+ { 125, 338, 149, 366 },
+ { 462, 338, 485, 366 },
- dst += SCREEN_WIDTH;
- src += _resMan->readUint16(&fHead->width);
- }
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 }
+};
- _system->copyRectToScreen(_dstBuf, SCREEN_WIDTH, _x, _y, _width, _height);
-}
+const Button Control::volumeButtons[25] = {
+
+ { VD1X + 30, VDY, VD1X + 60, VDY + 30 },
+ { VD1X + 60, VDY + 10, VD1X + 80, VDY + 30 },
+ { VD1X + 60, VDY + 30, VD1X + 90, VDY + 60 },
+ { VD1X + 60, VDY + 60, VD1X + 80, VDY + 80 },
+ { VD1X + 30, VDY + 60, VD1X + 60, VDY + 90 },
+ { VD1X + 10, VDY + 60, VD1X + 30, VDY + 80 },
+ { VD1X + 0, VDY + 30, VD1X + 30, VDY + 60 },
+ { VD1X + 10, VDY + 10, VD1X + 30, VDY + 30 },
+
+ { VD2X + 30, VDY, VD2X + 60, VDY + 30 },
+ { VD2X + 60, VDY + 10, VD2X + 80, VDY + 30 },
+ { VD2X + 60, VDY + 30, VD2X + 90, VDY + 60 },
+ { VD2X + 60, VDY + 60, VD2X + 80, VDY + 80 },
+ { VD2X + 30, VDY + 60, VD2X + 60, VDY + 90 },
+ { VD2X + 10, VDY + 60, VD2X + 30, VDY + 80 },
+ { VD2X + 0, VDY + 30, VD2X + 30, VDY + 60 },
+ { VD2X + 10, VDY + 10, VD2X + 30, VDY + 30 },
+
+ { VD3X + 30, VDY, VD3X + 60, VDY + 30 },
+ { VD3X + 60, VDY + 10, VD3X + 80, VDY + 30 },
+ { VD3X + 60, VDY + 30, VD3X + 90, VDY + 60 },
+ { VD3X + 60, VDY + 60, VD3X + 80, VDY + 80 },
+ { VD3X + 30, VDY + 60, VD3X + 60, VDY + 90 },
+ { VD3X + 10, VDY + 60, VD3X + 30, VDY + 80 },
+ { VD3X + 0, VDY + 30, VD3X + 30, VDY + 60 },
+ { VD3X + 10, VDY + 10, VD3X + 30, VDY + 30 },
+
+ { 472, 340, 496, 364 }
-bool ControlButton::wasClicked(uint16 mouseX, uint16 mouseY) {
- if ((_x <= mouseX) && (_y <= mouseY) && (_x + _width >= mouseX) && (_y + _height >= mouseY))
- return true;
- else
- return false;
-}
+};
-void ControlButton::setSelected(uint8 selected) {
- _frameIdx = selected;
- draw();
+static int volToBalance(int volL, int volR) {
+ if (volL + volR == 0) {
+ return 50;
+ } else {
+ return (100 * volL / (volL + volR));
+ }
}
Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic) {
@@ -244,674 +200,2652 @@ Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *
_selectedButton = 255;
_panelShown = false;
_tempThumbnail = 0;
-}
-void Control::askForCd() {
- _screenBuf = (uint8 *)malloc(640 * 480);
- uint32 fontId = SR_FONT;
- if (SwordEngine::_systemVars.language == BS1_CZECH)
- fontId = CZECH_SR_FONT;
- _font = (uint8 *)_resMan->openFetchRes(fontId);
- uint8 *pal = (uint8 *)_resMan->openFetchRes(SR_PALETTE);
- uint8 *palOut = (uint8 *)malloc(256 * 3);
- for (uint16 cnt = 1; cnt < 256; cnt++) {
- palOut[cnt * 3 + 0] = pal[cnt * 3 + 0] << 2;
- palOut[cnt * 3 + 1] = pal[cnt * 3 + 1] << 2;
- palOut[cnt * 3 + 2] = pal[cnt * 3 + 2] << 2;
- }
- palOut[0] = palOut[1] = palOut[2] = 0;
- _resMan->resClose(SR_PALETTE);
- _system->getPaletteManager()->setPalette(palOut, 0, 256);
- free(palOut);
-
- char fName[10];
- uint8 textA[50];
- Common::sprintf_s(fName, "cd%d.id", SwordEngine::_systemVars.currentCD);
- Common::sprintf_s(textA, "%s%d", _lStrings[STR_INSERT_CD_A], SwordEngine::_systemVars.currentCD);
- bool notAccepted = true;
- bool refreshText = true;
- do {
- if (refreshText) {
- memset(_screenBuf, 0, 640 * 480);
- renderText(textA, 320, 220, TEXT_CENTER);
- renderText(_lStrings[STR_INSERT_CD_B], 320, 240, TEXT_CENTER);
- _system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
- }
- delay(300);
- if (_keyPressed.keycode) {
- if (!Common::File::exists(fName)) {
- memset(_screenBuf, 0, 640 * 480);
- renderText(_lStrings[STR_INCORRECT_CD], 320, 230, TEXT_CENTER);
- _system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
- delay(2000);
- refreshText = true;
- } else {
- notAccepted = false;
- }
- }
- } while (notAccepted && (!Engine::shouldQuit()));
+ for (int i = 0; i < ARRAYSIZE(_slabs); i++) {
+ _slabs[i] = nullptr;
+ }
+}
- _resMan->resClose(fontId);
- free(_screenBuf);
+bool Control::savegamesExist() {
+ Common::String pattern = "sword1.???";
+ Common::StringArray saveNames = _saveFileMan->listSavefiles(pattern);
+ return saveNames.size() > 0;
}
-static int volToBalance(int volL, int volR) {
- if (volL + volR == 0) {
- return 50;
- } else {
- return (100 * volL / (volL + volR));
- }
+bool Control::isPanelShown() {
+ return _panelShown;
}
-uint8 Control::runPanel() {
- // Make a thumbnail of the screen before displaying the menu in case we want to save
- // the game from the menu.
+void Control::getPlayerOptions() {
+ debug(1, "Control::getPlayerOptions(): Entering Control Panel");
+ _panelShown = true;
+
+ _screenBuf = (uint8 *)malloc(SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+ // Make a thumbnail of the screen before displaying the menu
+ // in case we want to save the game from the menu.
_tempThumbnail = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
Graphics::saveThumbnail(*_tempThumbnail);
+ // Reset because it was previously used when 'F5' or 'ESC' were pressed
+ SwordEngine::_systemVars.saveGameFlag = SGF_DONE;
+
_logic->fnWipeHands(nullptr, 0, 0, 0, 0, 0, 0, 0);
_logic->fnEndMenu(nullptr, 0, 0, 0, 0, 0, 0, 0);
- // Fade video and sounds down
+ int safeCurrentMusic = Logic::_scriptVars[CURRENT_MUSIC];
+
+ // Play music only if we actually have a music file to run..
+ if (!SwordEngine::_systemVars.runningFromCd || SwordEngine::_systemVars.currentCD)
+ _logic->fnPlayMusic(nullptr, 0, 61, LOOPED, 0, 0, 0, 0); // Control panel music ("2m29")
+
+ Logic::_scriptVars[CURRENT_MUSIC] = safeCurrentMusic;
+
_screen->startFadePaletteDown(1);
_vm->waitForFade();
_sound->quitScreen();
+ _keyPressed.reset();
- int previousMusic = Logic::_scriptVars[CURRENT_MUSIC];
- _logic->fnPlayMusic(nullptr, 0, 61, LOOPED, 0, 0, 0, 0);
- Logic::_scriptVars[CURRENT_MUSIC] = previousMusic;
+ while (SwordEngine::_systemVars.snrStatus != SNR_BLANK && !Engine::shouldQuit()) {
+ delay(DEFAULT_FRAME_TIME / 2);
+
+ // TODO: audio
+ // SetCrossFadeIncrement();
+
+ _mouse->animate();
+ // TODO: audio
+ // UpdateSampleStreaming(); // stream music
+ saveRestoreScreen();
+ }
- _panelShown = true;
- _mouseDown = false;
- _restoreBuf = NULL;
_keyPressed.reset();
- _numButtons = 0;
- // Clear the whole screen
- _screenBuf = (uint8 *)malloc(640 * 480);
- memset(_screenBuf, 0, 640 * 480);
- _system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
+ saveRestoreScreen();
- // Gather font resources
- uint32 fontId = SR_FONT, redFontId = SR_REDFONT;
- if (SwordEngine::_systemVars.language == BS1_CZECH) {
- fontId = CZECH_SR_FONT;
- redFontId = CZECH_SR_REDFONT;
+ debug(1, "Control::getPlayerOptions(): Returning from Control Panel: saveGameFlag = %d",
+ SwordEngine::_systemVars.saveGameFlag);
+
+ // Stop music now, if we're not returning to any in-game music...
+ bool wontReloadMusic =
+ SwordEngine::_systemVars.saveGameFlag == SGF_RESTORE ||
+ SwordEngine::_systemVars.saveGameFlag == SGF_RESTART ||
+ SwordEngine::_systemVars.saveGameFlag == SGF_QUIT;
+
+ if (wontReloadMusic || (Logic::_scriptVars[CURRENT_MUSIC] == 0)) {
+ _logic->fnStopMusic(nullptr, 0, 0, 0, 0, 0, 0, 0);
}
- _font = (uint8 *)_resMan->openFetchRes(fontId);
- _redFont = (uint8 *)_resMan->openFetchRes(redFontId);
- // Set up mouse
- _mouse->controlPanel(true);
+ _screen->startFadePaletteDown(1);
+ _vm->waitForFade();
- uint8 mode = BUTTON_MAIN_PANEL, newMode = 0;
- bool fullRefresh = false;
- uint8 retVal = CONTROL_NOTHING_DONE;
+ _logic->fnNormalMouse(nullptr, 0, 0, 0, 0, 0, 0, 0);
+ Logic::_scriptVars[NEW_PALETTE] = 1;
- // Set up the image and the correct palette for fading up
- if (SwordEngine::isPsx())
- destroyButtons();
- setupMainPanel();
+ if (SwordEngine::_systemVars.saveGameFlag == SGF_SAVE) {
+ saveGame();
+ } else if (SwordEngine::_systemVars.saveGameFlag == SGF_QUIT) {
+ // TODO: audio
+ // FadeMusicDown(1);
- _screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
- _screen->fnSetFadeTargetPalette(0, 1, 0, true);
+ Engine::quitGame();
+ }
- // Fade up
- _screen->startFadePaletteUp(1);
- _vm->waitForFade();
+ // Reset again (because it may have been set in fnDeathScreen())
+ SwordEngine::_systemVars.controlPanelMode = CP_NORMAL;
- do {
- if (newMode) {
- mode = newMode;
- fullRefresh = true;
- destroyButtons();
- memset(_screenBuf, 0, 640 * 480);
- if (mode != BUTTON_SAVE_PANEL)
- _cursorVisible = false;
- }
- switch (mode) {
- case BUTTON_MAIN_PANEL:
- if (fullRefresh)
- setupMainPanel();
+ // If DONE or SAVE was selected, try restoring audio...
+ if (SwordEngine::_systemVars.saveGameFlag == SGF_DONE || SwordEngine::_systemVars.saveGameFlag == SGF_SAVE) {
+ // Restore sound effects...
+ for (int j = 0; j < TOTAL_FX_PER_ROOM; j++) {
+ if (int32 fxNo = Sound::_roomsFixedFx[Logic::_scriptVars[SCREEN]][j]) { // search the room's fixed fx list (see 'fx_list.c')
+ if (Sound::_fxList[fxNo].type == FX_LOOP)
+ _logic->fnPlayFx(nullptr, 0, fxNo, 0, 0, 0, 0, 0);
+ } else {
+ break; // Drop out as soon as we come across a zero, rather than searching the whole list...
+ }
+ }
+ // Restore in-game music...
+ if (Logic::_scriptVars[CURRENT_MUSIC]) {
+ _logic->fnPlayMusic(nullptr, 0, Logic::_scriptVars[CURRENT_MUSIC], LOOPED, 0, 0, 0, 0);
+ }
+ }
+
+ _screen->clearScreen();
+ free(_screenBuf);
+
+ debug(1, "Control::getPlayerOptions(): Finished getPlayerOptions()");
+ _panelShown = false;
+
+ // Was being set to true in initialiseControlPanel(),
+ // but we have to wait until here to set it to false
+ _mouse->controlPanel(false);
+
+ // Delete the temporary thumbnail
+ delete _tempThumbnail;
+ _tempThumbnail = nullptr;
+}
+
+void Control::askForCdMessage(uint32 needCD, bool incorrectCDPhase) {
+ uint8 buf[255];
+ _screenBuf = (uint8 *)malloc(SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+ if (!_screenBuf)
+ return;
+
+ if (!incorrectCDPhase) {
+ //ScreenOpen(640 / XBLOCKSIZE, 400 / YBLOCKSIZE); // sets up global structure screenDef
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_DEPTH);
+
+ Common::sprintf_s(buf, "%s%d", _lStrings[STR_INSERT_CD_A], needCD);
+ renderText(buf, (640 - getTextLength(buf, true)) / 2, 190, true);
+
+ Common::sprintf_s(buf, "%s", _lStrings[STR_INSERT_CD_B]);
+ renderText(buf, (640 - getTextLength(buf, true)) / 2, 210, true);
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ } else {
+ //if (displayInfo.backBuffer == 0) {
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_DEPTH);
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ //}
+
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_DEPTH);
+
+ Common::sprintf_s(buf, "%s", _lStrings[STR_INCORRECT_CD]);
+ renderText(buf, (640 - getTextLength(buf, true)) / 2, 160, true);
+
+ Common::sprintf_s(buf, "%s%d", _lStrings[STR_INSERT_CD_A], needCD);
+ renderText(buf, (640 - getTextLength(buf, true)) / 2, 190, true);
+
+ Common::sprintf_s(buf, "%s", _lStrings[STR_INSERT_CD_B]);
+ renderText(buf, (640 - getTextLength(buf, true)) / 2, 210, true);
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ }
+ free(_screenBuf);
+}
+
+void Control::saveRestoreScreen() {
+ int32 rv;
+
+ if (_oldSnrStatus != SwordEngine::_systemVars.snrStatus) {
+ // Tidy up after snr section
+ if (_oldSnrStatus == SNR_BLANK) {
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+ _newPal = true;
+ }
+
+ switch (_oldSnrStatus) {
+ case SNR_BLANK:
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+ break;
+ case SNR_MAINPANEL:
+ removeControlPanel();
+ setVolumes();
+ break;
+ case SNR_SAVE:
+ removeSave();
+ break;
+ case SNR_RESTORE:
+ removeRestore();
+ break;
+ case SNR_RESTART:
+ case SNR_QUIT:
+ removeConfirmation();
+ break;
+ case SNR_SPEED:
+ removeSpeed();
break;
- case BUTTON_SAVE_PANEL:
- if (fullRefresh) {
- setupSaveRestorePanel(true);
+ case SNR_VOLUME:
+ removeVolume();
+ setVolumes();
+ break;
+ case SNR_DRIVEFULL:
+ removeConfirmation();
+ break;
+ }
+
+ // Initialise new snr section
+ switch (SwordEngine::_systemVars.snrStatus) {
+ case SNR_BLANK:
+ releaseResources();
+ break;
+ case SNR_MAINPANEL:
+ if (_oldSnrStatus == SNR_BLANK) {
+ initialiseResources();
}
- if (_selectedSavegame < 255) {
- _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
- bool visible = _cursorVisible;
- _cursorTick++;
- if (_cursorTick == 7)
- _cursorVisible = true;
- else if (_cursorTick == 14) {
- _cursorVisible = false;
- _cursorTick = 0;
- }
- if (_keyPressed.keycode)
- handleSaveKey(_keyPressed);
- else if (_cursorVisible != visible)
- showSavegameNames();
+
+ //GetVolumes();
+ initialiseControlPanel();
+ break;
+ case SNR_SAVE:
+ initialiseSave();
+ break;
+ case SNR_RESTORE:
+ initialiseRestore();
+ break;
+ case SNR_RESTART:
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NEWGAME) {
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
} else {
- _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+ initialiseConfirmation(_lStrings[STR_RESTART]);
}
+
break;
- case BUTTON_RESTORE_PANEL:
- if (fullRefresh)
- setupSaveRestorePanel(false);
+ case SNR_QUIT:
+ initialiseConfirmation(_lStrings[STR_QUIT]);
break;
- case BUTTON_VOLUME_PANEL:
- if (fullRefresh)
- setupVolumePanel();
+ case SNR_SPEED:
+ initialiseSpeed();
break;
- default:
+ case SNR_VOLUME:
+ //GetVolumes();
+ initialiseVolume();
+ break;
+ case SNR_DRIVEFULL:
+ initialiseConfirmation(_lStrings[STR_DRIVE_FULL]);
break;
}
- if (fullRefresh) {
- fullRefresh = false;
- _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, 480);
+
+ _oldSnrStatus = SwordEngine::_systemVars.snrStatus;
+ }
+
+ // Implement snr section
+
+ switch (SwordEngine::_systemVars.snrStatus) {
+ case SNR_BLANK:
+ break;
+ case SNR_MAINPANEL:
+ implementControlPanel();
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+
+ if (_newPal) {
+ _newPal = false;
+ _screen->startFadePaletteUp(1);
}
- delay(DEFAULT_FRAME_TIME);
- newMode = getClicks(mode, &retVal);
- } while ((newMode != BUTTON_DONE) && (retVal == 0) && (!Engine::shouldQuit()));
- if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
- uint8 volL, volR;
- _music->giveVolume(&volL, &volR);
- int vol = (int)((volR + volL) / 2);
- int volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("music_volume"))
- ConfMan.setInt("music_volume", vol);
- if (volBalance != ConfMan.getInt("music_balance"))
- ConfMan.setInt("music_balance", volBalance);
-
- _sound->giveSpeechVol(&volL, &volR);
- vol = (int)((volR + volL) / 2);
- volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("speech_volume"))
- ConfMan.setInt("speech_volume", vol);
- if (volBalance != ConfMan.getInt("speech_balance"))
- ConfMan.setInt("speech_balance", volBalance);
-
- _sound->giveSfxVol(&volL, &volR);
- vol = (int)((volR + volL) / 2);
- volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("sfx_volume"))
- ConfMan.setInt("sfx_volume", vol);
- if (volBalance != ConfMan.getInt("sfx_balance"))
- ConfMan.setInt("sfx_balance", volBalance);
-
- if (SwordEngine::_systemVars.showText != ConfMan.getBool("subtitles"))
- ConfMan.setBool("subtitles", SwordEngine::_systemVars.showText);
- ConfMan.flushToDisk();
- }
-
- // Fade out video and sounds
- bool didRestoreRestartOrQuit =
- Engine::shouldQuit() ||
- (retVal & CONTROL_RESTART_GAME) ||
- (retVal & CONTROL_GAME_RESTORED);
-
- if (didRestoreRestartOrQuit || (Logic::_scriptVars[CURRENT_MUSIC] == 0)) {
- _logic->fnStopMusic(nullptr, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case SNR_SAVE:
+ implementSave();
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+
+ break;
+ case SNR_RESTORE:
+ implementRestore();
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+
+ break;
+ case SNR_RESTART:
+ rv = implementConfirmation();
+ if (rv) {
+ if (rv == 1) {
+ SwordEngine::_systemVars.saveGameFlag = SGF_RESTART;
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ } else {
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ }
+ }
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+
+ break;
+ case SNR_QUIT:
+ rv = implementConfirmation();
+ if (rv) {
+ if (rv == 1) {
+ SwordEngine::_systemVars.saveGameFlag = SGF_QUIT;
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ } else {
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ }
+ }
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+
+ break;
+ case SNR_SPEED:
+ implementSpeed();
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ break;
+ case SNR_VOLUME:
+ implementVolume();
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ break;
+ case SNR_SUBTITLES:
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ break;
+ case SNR_DONE:
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ break;
+ case SNR_DRIVEFULL:
+ rv = implementConfirmation();
+
+ if (rv == 1) {
+ SwordEngine::_systemVars.snrStatus = SNR_SAVE;
+ }
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ break;
}
+}
- _screen->startFadePaletteDown(1);
- _vm->waitForFade();
+void Control::renderSlab(int32 start, int32 i) {
+ uint8 *src, *dst;
+ FrameHeader *f;
- _logic->fnNormalMouse(nullptr, 0, 0, 0, 0, 0, 0, 0);
- Logic::_scriptVars[NEW_PALETTE] = 1;
+ if (start + 1 == _slabSelected) {
+ f = (FrameHeader *)((uint8 *)_slabs[start] + _resMan->getUint32(_slabs[start]->spriteOffset[1]));
+ } else {
+ f = (FrameHeader *)((uint8 *)_slabs[start] + _resMan->getUint32(_slabs[start]->spriteOffset[0]));
+ }
- // Clear the control panel resources and the free the temp screen buffer
- destroyButtons();
- _resMan->resClose(fontId);
- _resMan->resClose(redFontId);
- memset(_screenBuf, 0, 640 * 480);
- _system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
- free(_screenBuf);
+ src = (uint8 *)f + sizeof(FrameHeader);
- // Restore mouse
- _mouse->controlPanel(false);
+ if (start + 1 == _slabSelected) {
+ dst = _screenBuf + saveButtons[i].x1 + SCREEN_WIDTH * (saveButtons[i].y1 - 1);
+ } else {
+ dst = _screenBuf + saveButtons[i].x1 + SCREEN_WIDTH * saveButtons[i].y1;
+ }
- // If DONE or SAVE was selected, try restoring audio
- if (!didRestoreRestartOrQuit) {
- // Restore sound effects...
- for (int j = 0; j < TOTAL_FX_PER_ROOM; j++) {
- if (int fxNo = Sound::_roomsFixedFx[Logic::_scriptVars[SCREEN]][j]) {
- if (Sound::_fxList[fxNo].type == FX_LOOP)
- _logic->fnPlayFx(nullptr, 0, fxNo, 0, 0, 0, 0, 0);
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_SLAB, src, dst, f);
+ } else {
+ for (int j = 0; j < _resMan->getUint16(f->height); j++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::renderSlabs() {
+ uint8 *src, *dst;
+ int32 start;
+ FrameHeader *f;
+
+ start = _firstDescription;
+ while (start >= (SAVEBUTTONS - 6))
+ start -= (SAVEBUTTONS - 6);
+
+ for (int i = 0; i < SAVEBUTTONS - 6; i++) {
+ if (i + 1 == _slabSelected)
+ continue;
+
+ f = (FrameHeader *)((uint8 *)_slabs[start] + _resMan->getUint32(_slabs[start]->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + saveButtons[i].x1 + SCREEN_WIDTH * saveButtons[i].y1;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_SLAB, src, dst, f);
+ } else {
+ for (int j = 0; j < _resMan->getUint16(f->height); j++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ start += 1;
+ if (start == SAVEBUTTONS - 6)
+ start = 0;
+ }
+
+ if (_slabSelected) {
+ start = _firstDescription;
+ while (start >= (SAVEBUTTONS - 6))
+ start -= (SAVEBUTTONS - 6);
+
+ start += (_slabSelected - 1);
+ if (start >= (SAVEBUTTONS - 6))
+ start -= (SAVEBUTTONS - 6);
+
+ f = (FrameHeader *)((uint8 *)_slabs[start] + _resMan->getUint32(_slabs[start]->spriteOffset[1]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + saveButtons[_slabSelected - 1].x1 + SCREEN_WIDTH * (saveButtons[_slabSelected - 1].y1 - 1);
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_SLAB, src, dst, f);
+ } else {
+ for (int j = 0; j < _resMan->getUint16(f->height); j++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+ }
+}
+
+void Control::renderText(const uint8 *str, int32 x, int32 y, bool useSpeechFont) {
+ uint8 *src, *dst;
+ int32 i, l;
+ FrameHeader *f;
+ Sprite *srFont;
+
+ if (useSpeechFont) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_GAME_FONT);
+ } else {
+ srFont = (Sprite *)_resMan->fetchRes(GAME_FONT);
+ }
+ } else {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_SR_DEATHFONT);
} else {
- break; // Drop out as soon as we come across a zero, rather than searching the whole list...
+ srFont = (Sprite *)_resMan->fetchRes(_resMan->getDeathFontId());
+ }
+ } else {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_SR_FONT);
+ } else {
+ srFont = (Sprite *)_resMan->fetchRes(SR_FONT);
}
}
+ }
- // Restore in-game music...
- if (Logic::_scriptVars[CURRENT_MUSIC]) {
- _logic->fnPlayMusic(nullptr, 0, Logic::_scriptVars[CURRENT_MUSIC], LOOPED, 0, 0, 0, 0);
+ i = 0;
+ l = 0;
+
+ while (str[i] != 0) {
+ f = (FrameHeader *)((uint8 *)srFont + _resMan->getUint32(srFont->spriteOffset[str[i] - 32]));
+ dst = _screenBuf + SCREEN_WIDTH * y + x + l;
+ src = (uint8 *)f + sizeof(FrameHeader);
+
+ if (SwordEngine::isPsx()) {
+ src = decompressPsxGfx(src, f);
+ uint8 *initialPtr = src;
+
+ for (int k = 0; k < _resMan->getUint16(f->height); k++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++) {
+ if (src[j])
+ dst[j] = src[j];
+ }
+
+ // On PSX version we need to double horizontal lines
+ if (SwordEngine::isPsx()) {
+ dst += SCREEN_WIDTH;
+ for (int j = 0; j < _resMan->getUint16(f->width); j++)
+ if (src[j])
+ dst[j] = src[j];
+ }
+
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+
+ free(initialPtr);
+ } else {
+ // Copy the data onto the sprite
+ for (int k = 0; k < _resMan->getUint16(f->height); k++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++) {
+ if (*src) {
+ *dst = *src;
+ }
+
+ dst += 1;
+ src += 1;
+ }
+
+ dst += SCREEN_WIDTH - _resMan->getUint16(f->width);
+ }
+ }
+
+ l += _resMan->getUint16(f->width);
+ l -= useSpeechFont ? SP_OVERLAP : OVERLAP;
+ i += 1;
+ }
+}
+
+void Control::renderRedText(const uint8 *str, int32 x, int32 y) {
+ uint8 *src, *dst;
+ int32 i, l;
+ FrameHeader *f;
+ Sprite *srRedfont;
+
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srRedfont = (Sprite *)_resMan->fetchRes(CZECH_SR_REDFONT);
+ } else {
+ srRedfont = (Sprite *)_resMan->fetchRes(SR_REDFONT);
+ }
+
+ i = 0;
+ l = 0;
+ while (str[i] != 0) {
+ f = (FrameHeader *)((uint8 *)srRedfont + _resMan->getUint32(srRedfont->spriteOffset[str[i] - 32]));
+ dst = _screenBuf + SCREEN_WIDTH * y + x + l;
+ src = (uint8 *)f + sizeof(FrameHeader);
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_TEXT, src, dst, f);
+ } else {
+ // Copy the data onto the sprite
+ for (int k = 0; k < _resMan->getUint16(f->height); k++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++) {
+ if (*src) {
+ *dst = *src;
+ }
+ dst += 1;
+ src += 1;
+ }
+ dst += SCREEN_WIDTH - _resMan->getUint16(f->width);
+ }
+ }
+
+ l += (_resMan->getUint16(f->width) - OVERLAP);
+ i += 1;
+ }
+}
+
+void Control::renderTexts() {
+ char string[40];
+
+ for (int i = 0; i < SAVEBUTTONS - 6; i++) {
+ Common::sprintf_s(string, "%d", _firstDescription + i + 1);
+ if (_slabSelected == i + 1) {
+ renderRedText((const uint8 *)string, saveButtons[i].x1 + 12, saveButtons[i].y1 + 5);
+ renderRedText((const uint8 *)_fileDescriptions[_firstDescription + i], saveButtons[i].x1 + 42, saveButtons[i].y1 + 5);
+ } else {
+ renderText((const uint8 *)string, saveButtons[i].x1 + 12, saveButtons[i].y1 + 5);
+ renderText((const uint8 *)_fileDescriptions[_firstDescription + i], saveButtons[i].x1 + 42, saveButtons[i].y1 + 5);
+ }
+ }
+}
+
+int32 Control::getTextLength(const uint8 *str, bool useSpeechFont) {
+ int32 i;
+ int32 l;
+ FrameHeader *f;
+ Sprite *srFont;
+
+ if (useSpeechFont) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_GAME_FONT);
+ } else {
+ srFont = (Sprite *)_resMan->fetchRes(GAME_FONT);
+ }
+ } else {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_SR_DEATHFONT);
+ } else {
+ srFont = (Sprite *)_resMan->fetchRes(_resMan->getDeathFontId());
+ }
+ } else {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ srFont = (Sprite *)_resMan->fetchRes(CZECH_SR_FONT);
+ } else {
+ srFont = (Sprite *)_resMan->fetchRes(SR_FONT);
+ }
+ }
+ }
+
+ i = 0;
+ l = 0;
+
+ while (str[i] != 0) {
+ f = (FrameHeader *)((uint8 *)srFont + _resMan->getUint32(srFont->spriteOffset[str[i] - 32]));
+ l += _resMan->getUint16(f->width);
+ l -= useSpeechFont ? SP_OVERLAP : OVERLAP;
+ i += 1;
+ }
+
+ return l;
+}
+
+void Control::putButton(int32 x, int32 y, int32 index) {
+ uint8 *src, *dst;
+ FrameHeader *f;
+ Sprite *srButton;
+
+ srButton = (Sprite *)_resMan->fetchRes(SR_BUTTON);
+
+ f = (FrameHeader *)((uint8 *)srButton + _resMan->getUint32(srButton->spriteOffset[index]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + SCREEN_WIDTH * y + x;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++)
+ if (*(src + j))
+ *(dst + j) = *(src + j);
+
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::putSpriteButton(Sprite *spr, int32 x, int32 y, int32 index) {
+ uint8 *src, *dst;
+ FrameHeader *f;
+
+ f = (FrameHeader *)((uint8 *)spr + _resMan->getUint32(spr->spriteOffset[index]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + SCREEN_WIDTH * y + x;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++)
+ if (*(src + j))
+ *(dst + j) = *(src + j);
+
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::putTextButton(int32 index) {
+ uint8 *src, *dst;
+ int32 x, y;
+ FrameHeader *f;
+ Sprite *srTextButton;
+
+ srTextButton = (Sprite *)_resMan->fetchRes(SR_TEXT_BUTTON);
+
+ x = 475;
+ y = 260;
+
+ f = (FrameHeader *)((uint8 *)srTextButton + _resMan->getUint32(srTextButton->spriteOffset[index]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + SCREEN_WIDTH * y + x;
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+int32 Control::getCurrentButton(const Button b[]) {
+ for (int i = 0; i < _numButtons; i++) {
+ if ((_mouseCoord.x > b[i].x1) && (_mouseCoord.y - 40 > b[i].y1) &&
+ (_mouseCoord.x < b[i].x2) && (_mouseCoord.y - 40 < b[i].y2)) {
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+void Control::initialiseConfirmation(const uint8 *title) {
+ uint8 *src, *dst;
+ FrameHeader *f;
+ Sprite *srConfirm;
+
+ srConfirm = (Sprite *)_resMan->openFetchRes(SR_CONFIRM);
+
+ f = (FrameHeader *)((uint8 *)srConfirm + _resMan->getUint32(srConfirm->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf +
+ ((SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2) +
+ (SCREEN_WIDTH * ((SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2));
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_CONFIRM, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ _resMan->resClose(SR_CONFIRM);
+
+ renderText(title, (SCREEN_WIDTH - getTextLength(title)) / 2, 120);
+
+ if (SwordEngine::_systemVars.snrStatus == SNR_DRIVEFULL) {
+ _numButtons = 1; // only top (OK) button used
+ } else {
+ _numButtons = 2;
+ }
+
+ for (int i = 0; i < _numButtons; i++)
+ putButton(confirmButtons[i].x1, confirmButtons[i].y1, 0);
+
+ renderText(_lStrings[STR_OK], SCREEN_WIDTH - confirmButtons[0].x1 - getTextLength(_lStrings[STR_OK]), confirmButtons[0].y1);
+
+ if (SwordEngine::_systemVars.snrStatus != SNR_DRIVEFULL)
+ renderText(_lStrings[STR_CANCEL], SCREEN_WIDTH - confirmButtons[1].x1 - getTextLength(_lStrings[STR_CANCEL]), confirmButtons[1].y1);
+}
+
+int32 Control::implementConfirmation() {
+ _currentButton = getCurrentButton(&confirmButtons[0]);
+
+ if ((_buttonPressed) && (!_currentButton)) {
+ // Reset button pressed
+ putButton(confirmButtons[_buttonPressed - 1].x1, confirmButtons[_buttonPressed - 1].y1, 0);
+ _buttonPressed = 0;
+ }
+
+ if (_mouseState != 0) {
+ if ((_mouseState & BS1L_BUTTON_DOWN) && (_currentButton)) {
+ // Set button pressed
+ _buttonPressed = _currentButton;
+ putButton(confirmButtons[_buttonPressed - 1].x1, confirmButtons[_buttonPressed - 1].y1, 1);
+ }
+
+ if ((_mouseState & BS1L_BUTTON_UP) && (_buttonPressed)) {
+ if (_buttonPressed == 1) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void Control::removeConfirmation() {
+ // Dummy in the original
+}
+
+void Control::renderVolumeLight(int32 i) {
+ // TODO: This function has been mangled to accomodate the current
+ // audio engine, which will partly get rewritten in the immediate
+ // future :)
+
+ uint8 *src, *dst;
+ uint8 vol[2] = { 0, 0 };
+ int32 x;
+ FrameHeader *f;
+ Sprite *srVlight;
+
+ switch (i) {
+ case 0: //music
+ _music->giveVolume(&vol[0], &vol[1]);
+ //vol[0] = volMusic[0];
+ //vol[1] = volMusic[1];
+ x = 158;
+ break;
+ case 1: //speech
+ _sound->giveSpeechVol(&vol[0], &vol[1]);
+ //vol[0] = volSpeech[0];
+ //vol[1] = volSpeech[1];
+ x = 291;
+ break;
+ case 2: //fx
+ _sound->giveSfxVol(&vol[0], &vol[1]);
+ //vol[0] = volFX[0];
+ //vol[1] = volFX[1];
+ x = 424;
+ break;
+ default:
+ x = 0;
+ break;
+ }
+
+ srVlight = (Sprite *)_resMan->fetchRes(SR_VLIGHT);
+
+ // Render left light
+ f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[0] >> 4]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + x + 211 * SCREEN_WIDTH;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int y = 0; y < _resMan->getUint16(f->height); y++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ // Render right light
+ f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[1] >> 4]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + x + 32 + 211 * SCREEN_WIDTH;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int y = 0; y < _resMan->getUint16(f->height); y++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::setVolumes() {
+ // TODO: This function has been mangled to accomodate the current
+ // audio engine, which will partly get rewritten in the immediate
+ // future :)
+
+ uint8 volL, volR;
+ _music->giveVolume(&volL, &volR);
+ int vol = (int)((volR + volL) / 2);
+ int volBalance = volToBalance(volL, volR);
+ if (vol != ConfMan.getInt("music_volume"))
+ ConfMan.setInt("music_volume", vol);
+ if (volBalance != ConfMan.getInt("music_balance"))
+ ConfMan.setInt("music_balance", volBalance);
+
+ _sound->giveSpeechVol(&volL, &volR);
+ vol = (int)((volR + volL) / 2);
+ volBalance = volToBalance(volL, volR);
+ if (vol != ConfMan.getInt("speech_volume"))
+ ConfMan.setInt("speech_volume", vol);
+ if (volBalance != ConfMan.getInt("speech_balance"))
+ ConfMan.setInt("speech_balance", volBalance);
+
+ _sound->giveSfxVol(&volL, &volR);
+ vol = (int)((volR + volL) / 2);
+ volBalance = volToBalance(volL, volR);
+ if (vol != ConfMan.getInt("sfx_volume"))
+ ConfMan.setInt("sfx_volume", vol);
+ if (volBalance != ConfMan.getInt("sfx_balance"))
+ ConfMan.setInt("sfx_balance", volBalance);
+
+ if (SwordEngine::_systemVars.showText != ConfMan.getBool("subtitles"))
+ ConfMan.setBool("subtitles", SwordEngine::_systemVars.showText);
+ ConfMan.flushToDisk();
+}
+
+void Control::volUp(int32 i, int32 j) {
+ // TODO: This function has been mangled to accomodate the current
+ // audio engine, which will partly get rewritten in the immediate
+ // future :)
+
+ uint32 vol[2] = { 0, 0 };
+
+ switch (i) {
+ case 0:
+ _music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volMusic[j];
+ break;
+ case 1:
+ _sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volSpeech[j];
+ break;
+ case 2:
+ _sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volFX[j];
+ break;
+ }
+
+ if ((vol[j] >> 4) < 16)
+ vol[j] += 1 << 4;
+
+ vol[j] = CLIP<uint32>(vol[j], 0, 255);
+
+ switch (i) {
+ case 0:
+ _music->setVolume((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volMusic[j];
+ break;
+ case 1:
+ _sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volSpeech[j];
+ break;
+ case 2:
+ _sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volFX[j];
+ break;
+ }
+}
+
+void Control::volDown(int32 i, int32 j) {
+ // TODO: This function has been mangled to accomodate the current
+ // audio engine, which will partly get rewritten in the immediate
+ // future :)
+
+ uint32 vol[2] = {0, 0};
+
+ switch (i) {
+ case 0:
+ _music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volMusic[j];
+ break;
+ case 1:
+ _sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volSpeech[j];
+ break;
+ case 2:
+ _sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
+ //vol = &volFX[j];
+ break;
+ }
+
+ if (vol[j] > 1 << 4)
+ vol[j] -= 1 << 4;
+
+ vol[j] = CLIP<uint32>(vol[j], 0, 255);
+
+ switch (i) {
+ case 0:
+ _music->setVolume((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volMusic[j];
+ break;
+ case 1:
+ _sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volSpeech[j];
+ break;
+ case 2:
+ _sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
+ //vol = &volFX[j];
+ break;
+ }
+}
+
+void Control::renderVolumeDisc(int32 i, int32 j) {
+ uint8 *src, *dst;
+ int32 x = 0;
+ FrameHeader *f;
+ Sprite *srVnob;
+
+ switch (i) {
+ case 0:
+ x = VD1X;
+ break;
+ case 1:
+ x = VD2X;
+ break;
+ case 2:
+ x = VD3X;
+ break;
+ default:
+ break;
+ }
+
+ srVnob = (Sprite *)_resMan->fetchRes(SR_VKNOB);
+
+ // Render the disc
+ f = (FrameHeader *)((uint8 *)srVnob + _resMan->getUint32(srVnob->spriteOffset[j]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + x + VDY * SCREEN_WIDTH;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_BUTTON, src, dst, f);
+ } else {
+ for (int y = 0; y < _resMan->getUint16(f->height); y++) {
+ for (int z = 0; z < _resMan->getUint16(f->width); z++)
+ if (*(src + z))
+ *(dst + z) = *(src + z);
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::initialiseVolume() {
+ uint8 *src, *dst;
+ FrameHeader *f;
+ Sprite *srVolume;
+
+ _resMan->resOpen(SR_VLIGHT);
+ _resMan->resOpen(SR_VKNOB);
+
+ srVolume = (Sprite *)_resMan->openFetchRes(SR_VOLUME);
+ f = (FrameHeader *)((uint8 *)srVolume + _resMan->getUint32(srVolume->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf +
+ ((SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2) +
+ (SCREEN_WIDTH * ((SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2));
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_PANEL, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ _resMan->resClose(SR_VOLUME);
+
+ renderText(_lStrings[STR_MUSIC], 149, 39);
+ renderText(_lStrings[STR_SPEECH], (SCREEN_WIDTH - getTextLength(_lStrings[STR_SPEECH])) / 2, 39);
+ renderText(_lStrings[STR_FX], 438, 39);
+ _numButtons = 25;
+ putButton(volumeButtons[24].x1, volumeButtons[24].y1, 0);
+
+ renderText(_lStrings[STR_DONE], (volumeButtons[24].x1 - getTextLength(_lStrings[STR_DONE]) - 20), volumeButtons[24].y1);
+
+ renderVolumeLight(0);
+ renderVolumeLight(1);
+ renderVolumeLight(2);
+
+ renderVolumeDisc(0, 0);
+ renderVolumeDisc(1, 0);
+ renderVolumeDisc(2, 0);
+}
+
+void Control::implementVolume() {
+ int32 i, j;
+
+ _currentButton = getCurrentButton(&volumeButtons[0]);
+
+ if (_buttonPressed) {
+ if (!_currentButton) {
+ // Reset button pressed
+ if (_buttonPressed == 25)
+ putButton(volumeButtons[_buttonPressed - 1].x1, volumeButtons[_buttonPressed - 1].y1, 0);
+
+ _buttonPressed = 0;
+ } else {
+ if (_buttonPressed != 25) {
+ if (--_buttonHold == 0) {
+ _buttonHold = 4;
+ i = (_buttonPressed - 1) / 8;
+ j = _buttonPressed - i * 8;
+
+ switch (j) {
+ case 1:
+ volUp(i, 0);
+ volUp(i, 1);
+ break;
+ case 2:
+ volUp(i, 1);
+ break;
+ case 3:
+ volDown(i, 0);
+ volUp(i, 1);
+ break;
+ case 4:
+ volDown(i, 1);
+ break;
+ case 5:
+ volDown(i, 0);
+ volDown(i, 1);
+ break;
+ case 6:
+ volDown(i, 0);
+ break;
+ case 7:
+ volUp(i, 0);
+ volDown(i, 1);
+ break;
+ case 8:
+ volUp(i, 0);
+ break;
+ default:
+ break;
+ }
+
+ renderVolumeLight(i);
+ }
+ }
+ }
+ }
+
+ if (_mouseState) {
+ if ((_mouseState & BS1L_BUTTON_DOWN) && (_currentButton)) {
+ // Set button pressed
+ _buttonPressed = _currentButton;
+ _buttonHold = 15;
+
+ if (_buttonPressed == 25) {
+ putButton(volumeButtons[_buttonPressed - 1].x1, volumeButtons[_buttonPressed - 1].y1, 1);
+ } else {
+ i = (_buttonPressed - 1) / 8;
+ j = _buttonPressed - i * 8;
+ renderVolumeDisc(i, _buttonPressed - i * 8);
+
+ switch (j) {
+ case 1:
+ volUp(i, 0);
+ volUp(i, 1);
+ break;
+ case 2:
+ volUp(i, 1);
+ break;
+ case 3:
+ volDown(i, 0);
+ volUp(i, 1);
+ break;
+ case 4:
+ volDown(i, 1);
+ break;
+ case 5:
+ volDown(i, 0);
+ volDown(i, 1);
+ break;
+ case 6:
+ volDown(i, 0);
+ break;
+ case 7:
+ volUp(i, 0);
+ volDown(i, 1);
+ break;
+ case 8:
+ volUp(i, 0);
+ break;
+ default:
+ break;
+ }
+
+ renderVolumeLight(i);
+ }
+ }
+
+ if (_mouseState & BS1L_BUTTON_UP) {
+ if (_buttonPressed) {
+ if (_buttonPressed == 25) {
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ } else {
+ i = (_buttonPressed - 1) / 8;
+ renderVolumeDisc(i, 0);
+ }
+
+ _buttonPressed = 0;
+ } else {
+ // Avoid stuck volume discs
+ renderVolumeDisc(0, 0);
+ renderVolumeDisc(1, 0);
+ renderVolumeDisc(2, 0);
+ }
+ }
+ }
+}
+
+void Control::removeVolume() {
+ _resMan->resClose(SR_VLIGHT);
+ _resMan->resClose(SR_VKNOB);
+}
+
+void Control::renderScrolls() {
+ uint8 *src, *dst;
+ FrameHeader *f;
+ Sprite *srScroll1, *srScroll2;
+
+ srScroll1 = (Sprite *)_resMan->fetchRes(SR_SCROLL1);
+ srScroll2 = (Sprite *)_resMan->fetchRes(SR_SCROLL2);
+
+ f = (FrameHeader *)((uint8 *)srScroll1 + _resMan->getUint32(srScroll1->spriteOffset[_scrollIndex[0]]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + SCROLL1X + SCREEN_WIDTH * SCROLL1Y;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_CONFIRM, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ f = (FrameHeader *)((uint8 *)srScroll2 + _resMan->getUint32(srScroll2->spriteOffset[_scrollIndex[1]]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf + SCROLL2X + SCREEN_WIDTH * SCROLL2Y;
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_CONFIRM, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+}
+
+void Control::initialiseSpeed() {
+ uint8 *src, *dst;
+ FrameHeader *f;
+ Sprite *srSpeed;
+
+ _resMan->resOpen(SR_SCROLL1);
+ _resMan->resOpen(SR_SCROLL2);
+
+ srSpeed = (Sprite *)_resMan->openFetchRes(SR_SPEED);
+
+ f = (FrameHeader *)((uint8 *)srSpeed + _resMan->getUint32(srSpeed->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf +
+ ((SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2) +
+ (SCREEN_WIDTH * ((SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2));
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_PANEL, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ _resMan->resClose(SR_SPEED);
+
+ _scrollIndex[0] = 0;
+ _scrollIndex[1] = 0;
+
+ renderText(_lStrings[STR_SPEED], 216, 100);
+ _numButtons = 3;
+ putButton(speedButtons[0].x1, speedButtons[0].y1, _speedFlag);
+ putButton(speedButtons[1].x1, speedButtons[1].y1, 1 - _speedFlag);
+ putButton(speedButtons[2].x1, speedButtons[2].y1, 0);
+
+ renderText(_lStrings[STR_DONE], (speedButtons[2].x1 - getTextLength(_lStrings[STR_DONE]) - 20), speedButtons[2].y1);
+ renderScrolls();
+}
+
+void Control::implementSpeed() {
+ Sprite *srScroll1, *srScroll2;
+
+ srScroll1 = (Sprite *)_resMan->fetchRes(SR_SCROLL1);
+ srScroll2 = (Sprite *)_resMan->fetchRes(SR_SCROLL2);
+
+ if (++_scrollIndex[0] == (int32)_resMan->getUint32(srScroll1->totalSprites))
+ _scrollIndex[0] = 0;
+ if (++_scrollIndex[1] == (int32)_resMan->getUint32(srScroll2->totalSprites))
+ _scrollIndex[1] = 0;
+
+ renderScrolls();
+
+ _currentButton = getCurrentButton(&speedButtons[0]);
+
+ if ((_buttonPressed == 3) && (!_currentButton)) {
+ //Reset button pressed
+ putButton(speedButtons[_buttonPressed - 1].x1, speedButtons[_buttonPressed - 1].y1, 0);
+ _buttonPressed = 0;
+ }
+
+ if (_mouseState) {
+ if ((_mouseState & BS1L_BUTTON_DOWN) && (_currentButton)) {
+ //Set button pressed
+ _buttonPressed = _currentButton;
+ if (_buttonPressed == 3) {
+ putButton(speedButtons[2].x1, speedButtons[2].y1, 1);
+ } else {
+ if (_speedFlag == _buttonPressed - 1) {
+ _speedFlag = 2 - _buttonPressed;
+ putButton(speedButtons[0].x1, speedButtons[0].y1, _speedFlag);
+ putButton(speedButtons[1].x1, speedButtons[1].y1, 1 - _speedFlag);
+ }
+ }
+ }
+
+ if ((_mouseState & BS1L_BUTTON_UP) && (_buttonPressed)) {
+ if (_buttonPressed == 3) {
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ }
+
+ _buttonPressed = 0;
+ }
+ }
+}
+
+void Control::removeSpeed() {
+ _resMan->resClose(SR_SCROLL1);
+ _resMan->resClose(SR_SCROLL2);
+
+ SwordEngine::_systemVars.parallaxOn = 1 - _speedFlag;
+}
+
+int16 Control::readFileDescriptions() {
+ char saveName[40];
+ Common::String pattern = "sword1.???";
+ Common::StringArray filenames = _saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically...)
+
+ int16 totalFiles = 0;
+ int slotNum = 0;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ slotNum = atoi(file->c_str() + file->size() - 3);
+
+ while (totalFiles < slotNum) {
+ Common::strcpy_s(_fileDescriptions[totalFiles], 1, "");
+ totalFiles++;
+ }
+
+ if (slotNum >= 0 && slotNum < MAXSAVEGAMES) {
+ Common::InSaveFile *in = _saveFileMan->openForLoading(*file);
+ if (in) {
+ in->readUint32LE(); // header
+ in->read(saveName, 40);
+ Common::strcpy_s(_fileDescriptions[totalFiles], sizeof(_fileDescriptions[totalFiles]), saveName);
+ delete in;
+ }
+
+ totalFiles++;
+ }
+ }
+
+ for (int i = totalFiles; i < MAXSAVEGAMES; i++)
+ Common::strcpy_s(_fileDescriptions[i], 1, "");
+
+ return totalFiles;
+}
+
+void Control::setEditDescription(int32 line) {
+ _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+
+ _editingDescription = line;
+ _textCursor = 0;
+ _curCharCount = 1;
+
+ Common::strcpy_s(_oldString, sizeof(_oldString), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ _slabSelected = line;
+}
+
+bool Control::driveSpaceAvailable() {
+ char fName[15];
+ int slot = _firstDescription + _editingDescription - 1;
+ Common::sprintf_s(fName, "sword1.%03d", slot);
+
+ // We are going to write a fake savegame file, to see if
+ // we are actually able to write anything with that size.
+ // Why are we even doing this? Can't we save right now?
+ // Turns out: no; we need to save at the end of getPlayerOptions(),
+ // after some clean-up operations are carried out. Right now,
+ // we only want to know if we are even able to save.
+ Common::OutSaveFile *outf;
+ outf = _saveFileMan->openForSaving(fName, false);
+ if (!outf) {
+ return false;
+ }
+
+ int sizeOfFakeSavegame = 30000;
+ outf->writeUint32LE(SAVEGAME_HEADER);
+ outf->write(_fileDescriptions[slot], 40);
+ outf->writeByte(SAVEGAME_VERSION);
+
+ for (int i = 0; i < sizeOfFakeSavegame; i++)
+ outf->writeByte(i % 256);
+
+ outf->finalize();
+
+ if (outf->err())
+ return false;
+
+ return true;
+}
+
+bool Control::attemptSave() {
+ // If this slot already has a savegame, or there's enough space for a new savegame
+ if (strlen(_oldString) || driveSpaceAvailable()) {
+ _selectedSavegame = _firstDescription + _editingDescription - 1;
+ if (_firstDescription + _editingDescription > _gamesSaved)
+ _gamesSaved = _firstDescription + _editingDescription;
+
+ uneditDescription();
+
+ SwordEngine::_systemVars.saveGameFlag = SGF_SAVE;
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Control::editDescription() {
+ char string[40];
+ int32 len;
+ int32 index;
+
+ if (_keyPressed.keycode) {
+ uint16 ch = _keyPressed.ascii;
+ _keyPressed.reset();
+
+ index = _editingDescription + _firstDescription - 1;
+ len = Common::strnlen(_fileDescriptions[index], sizeof(_fileDescriptions[index]));
+ if ((ch != CR) && (ch != ESCAPE)) {
+ if ((ch >= FIRSTFONTCHAR) && (ch <= LASTFONTCHAR)) {
+ if ((len < 32) && (getTextLength((const uint8 *)_fileDescriptions[index]) < 310)) {
+ _fileDescriptions[index][len] = ch;
+ _fileDescriptions[index][len + 1] = '\0';
+ _curCharCount = 1;
+ }
+ }
+ }
+
+ if (ch == BACKSPACE) {
+ if (len) {
+ _fileDescriptions[index][len - 1] = '\0';
+ _curCharCount = 1;
+ }
+ }
+
+ if ((ch == ESCAPE) || (ch == CR)) {
+ if ((ch == ESCAPE) || ((ch == CR) && (len == 0))) {
+ _textCursor = 1;
+ _curCharCount = 10;
+ Common::strcpy_s(_fileDescriptions[index], sizeof(_fileDescriptions[index]), _oldString);
+ uneditDescription();
+ } else {
+ if (!attemptSave())
+ SwordEngine::_systemVars.snrStatus = SNR_DRIVEFULL;
+ }
+ }
+ }
+
+ if (SwordEngine::_systemVars.snrStatus != SNR_BLANK) {
+ if (--_curCharCount == 0) {
+ _curCharCount = 10;
+ _textCursor ^= 1;
+ if (_textCursor) {
+ // Add cursor to line
+ Common::strcpy_s(string, sizeof(string), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ len = strlen(string);
+ string[len] = '_';
+ string[len + 1] = '\0';
+ } else {
+ // Remove cursor from line
+ Common::strcpy_s(string, sizeof(string), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ }
+
+ renderSlab(_slabSelected - 1, _editingDescription - 1);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 42, saveButtons[_editingDescription - 1].y1 + 5);
+ Common::sprintf_s(string, sizeof(string), "%d", _firstDescription + _editingDescription);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 12, saveButtons[_editingDescription - 1].y1 + 5);
+ }
+ }
+}
+
+void Control::restoreSelected() {
+ if (_keyPressed.keycode) {
+ char ch = _keyPressed.ascii;
+ _keyPressed.reset();
+
+ if ((ch == ESCAPE) || (ch == CR)) {
+ if (ch == ESCAPE) {
+ uneditDescription();
+ } else {
+ // Restore the game here
+ _selectedSavegame = _editingDescription + _firstDescription - 1;
+ uneditDescription();
+ SwordEngine::_systemVars.saveGameFlag = SGF_RESTORE;
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ }
+ }
+ }
+}
+
+void Control::uneditDescription(void) {
+ _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+
+ _slabSelected = 0;
+
+ renderSlabs();
+ renderTexts();
+ _textCursor = 0;
+ _editingDescription = 0;
+}
+
+bool Control::saveGame() {
+ if (Common::strnlen(_fileDescriptions[_selectedSavegame], sizeof(_fileDescriptions[_selectedSavegame]) > 0)) {
+ saveGameToFile(_selectedSavegame);
+ return true;
+ }
+
+ return false;
+}
+
+void Control::initialiseSave() {
+ uint8 *src, *dst;
+ int32 size;
+ FrameHeader *f;
+ Sprite *srWindow;
+ Sprite *srButuf, *srButus, *srButds, *srButdf;
+ Sprite *srSlab1, *srSlab2, *srSlab3, *srSlab4;
+
+ if (SwordEngine::_systemVars.language == BS1_CZECH)
+ _resMan->resOpen(CZECH_SR_REDFONT);
+ else
+ _resMan->resOpen(SR_REDFONT);
+
+ srWindow = (Sprite *)_resMan->openFetchRes(SR_WINDOW);
+
+ f = (FrameHeader *)((uint8 *)srWindow + _resMan->getUint32(srWindow->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf +
+ ((SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2) +
+ (SCREEN_WIDTH * ((SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2));
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_PANEL, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ _resMan->resClose(SR_WINDOW);
+
+ _numButtons = SAVEBUTTONS;
+ putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 2].y1, 0);
+ putButton(saveButtons[SAVEBUTTONS - 1].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+
+ renderText(_lStrings[STR_SAVE], saveButtons[SAVEBUTTONS - 2].x1 + 40, saveButtons[SAVEBUTTONS - 2].y1);
+ renderText(_lStrings[STR_CANCEL], saveButtons[SAVEBUTTONS - 1].x1 - 15 - getTextLength(_lStrings[STR_CANCEL]), saveButtons[SAVEBUTTONS - 1].y1);
+
+ _gamesSaved = readFileDescriptions();
+
+ // Create the slabs here
+ srSlab1 = (Sprite *)_resMan->openFetchRes(SR_SLAB1);
+
+ if (SwordEngine::isPsx()) {
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[0]));
+ size = sizeof(Sprite) + sizeof(FrameHeader) + _resMan->getUint16(f->width) / 2 * _resMan->getUint16(f->height);
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[1]));
+ size += (sizeof(FrameHeader) + _resMan->getUint16(f->width) / 2 * _resMan->getUint16(f->height));
+ } else {
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[0]));
+ size = sizeof(Sprite) + sizeof(FrameHeader) + _resMan->getUint16(f->width) * _resMan->getUint16(f->height);
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[1]));
+ size += (sizeof(FrameHeader) + _resMan->getUint16(f->width) * _resMan->getUint16(f->height));
+ }
+
+ for (int i = 0; i < SAVEBUTTONS - 6; i++) {
+ _slabs[i] = (Sprite *)malloc(size);
+ }
+
+ memcpy((uint8 *)_slabs[0], (uint8 *)srSlab1, size);
+ memcpy((uint8 *)_slabs[4], (uint8 *)srSlab1, size);
+ _resMan->resClose(SR_SLAB1);
+
+ srSlab2 = (Sprite *)_resMan->openFetchRes(SR_SLAB2);
+ memcpy((uint8 *)_slabs[1], (uint8 *)srSlab2, size);
+ memcpy((uint8 *)_slabs[5], (uint8 *)srSlab2, size);
+ _resMan->resClose(SR_SLAB2);
+
+ srSlab3 = (Sprite *)_resMan->openFetchRes(SR_SLAB3);
+ memcpy((uint8 *)_slabs[2], (uint8 *)srSlab3, size);
+ memcpy((uint8 *)_slabs[6], (uint8 *)srSlab3, size);
+ _resMan->resClose(SR_SLAB3);
+
+ srSlab4 = (Sprite *)_resMan->openFetchRes(SR_SLAB4);
+ memcpy((uint8 *)_slabs[3], (uint8 *)srSlab4, size);
+ memcpy((uint8 *)_slabs[7], (uint8 *)srSlab4, size);
+ _resMan->resClose(SR_SLAB4);
+
+ renderSlabs();
+ renderTexts();
+}
+
+void Control::implementSave() {
+ Sprite *srButuf, *srButus, *srButds, *srButdf;
+
+ _currentButton = getCurrentButton(&saveButtons[0]);
+
+ if ((_buttonPressed) && (!_currentButton)) {
+ // Reset button pressed
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 4):
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 3):
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 1):
+ case (SAVEBUTTONS):
+ putButton(saveButtons[_buttonPressed - 1].x1, saveButtons[_buttonPressed - 1].y1, 0);
+ break;
+ }
+ }
+
+ _buttonPressed = 0;
+ }
+
+ // Enhancement! Scrollable savegames list! :-)
+ bool useWheelScroll = false;
+ if (_mouseState && _currentButton >= 1 && _currentButton <= 8) {
+ if (_mouseState & BS1_WHEEL_DOWN) {
+ _buttonPressed = (SAVEBUTTONS - 3);
+ useWheelScroll = true;
+ } else if (_mouseState & BS1_WHEEL_UP) {
+ _buttonPressed = (SAVEBUTTONS - 4);
+ useWheelScroll = true;
+ }
+ }
+
+ if (_mouseState) {
+ if ((useWheelScroll || (_mouseState & BS1L_BUTTON_DOWN)) && (_currentButton)) {
+ // Set button pressed
+ if (!useWheelScroll)
+ _buttonPressed = _currentButton;
+
+ if (_buttonPressed) {
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 1);
+ _resMan->resClose(SR_BUTUF);
+
+ if (!_editingDescription) {
+ _scroll = 1;
+ _scrollCount = 10;
+ if (_firstDescription > 0) {
+ if (_firstDescription - (SAVEBUTTONS - 6) < 0)
+ _firstDescription = 0;
+ else
+ _firstDescription -= (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ }
+
+ break;
+ case (SAVEBUTTONS - 4):
+ // Don't render the button as pressed when using wheel scrolling
+ if (!useWheelScroll) {
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 1);
+ _resMan->resClose(SR_BUTUS);
+ }
+
+ if (!_editingDescription) {
+ _scroll = 2;
+ _scrollCount = 10;
+ if (_firstDescription > 0) {
+ _firstDescription -= 1;
+ renderSlabs();
+ renderTexts();
+ }
+ }
+
+ break;
+ case (SAVEBUTTONS - 3):
+ // Don't render the button as pressed when using wheel scrolling
+ if (!useWheelScroll) {
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 1);
+ _resMan->resClose(SR_BUTDS);
+ }
+
+ if (!_editingDescription) {
+ _scroll = 3;
+ _scrollCount = 10;
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ _firstDescription += 1;
+ renderSlabs();
+ renderTexts();
+ }
+ }
+
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 1);
+ _resMan->resClose(SR_BUTDF);
+
+ if (!_editingDescription) {
+ _scroll = 4;
+ _scrollCount = 10;
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ if (_firstDescription + (SAVEBUTTONS - 6) > MAXSAVEGAMES - (SAVEBUTTONS - 6))
+ _firstDescription = MAXSAVEGAMES - (SAVEBUTTONS - 6);
+ else
+ _firstDescription += (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ }
+
+ break;
+ case (SAVEBUTTONS - 1):
+ case (SAVEBUTTONS):
+ putButton(saveButtons[_buttonPressed - 1].x1, saveButtons[_buttonPressed - 1].y1, 1);
+ break;
+ }
+ } else {
+ if (_editingDescription) {
+ if (_buttonPressed != _editingDescription) {
+ Common::strcpy_s(
+ _fileDescriptions[_editingDescription + _firstDescription - 1],
+ sizeof(_fileDescriptions[_editingDescription + _firstDescription - 1]),
+ _oldString);
+ _slabSelected = 0;
+ uneditDescription();
+
+ setEditDescription(_buttonPressed);
+ }
+ } else {
+ setEditDescription(_buttonPressed);
+ }
+ }
+ }
+ }
+
+ if ((_mouseState & BS1L_BUTTON_UP) && (_buttonPressed)) {
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 4):
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 3):
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 1):
+ putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+ if ((_editingDescription) && (strlen(_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
+ if (!attemptSave())
+ SwordEngine::_systemVars.snrStatus = SNR_DRIVEFULL;
+ }
+ break;
+ case (SAVEBUTTONS):
+ putButton(saveButtons[SAVEBUTTONS - 1].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+ if (_editingDescription)
+ uneditDescription();
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ break;
+ }
+ }
+
+ _buttonPressed = 0;
+ }
+ }
+
+ if (_scroll) {
+ if (--_scrollCount == 0) {
+
+ _scrollCount = 2;
+
+ switch (_scroll) {
+ case 1:
+ if (_firstDescription > 0) {
+ if (_firstDescription - (SAVEBUTTONS - 6) < 0)
+ _firstDescription = 0;
+ else
+ _firstDescription -= (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 2:
+ if (_firstDescription > 0) {
+ _firstDescription -= 1;
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 3:
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ _firstDescription += 1;
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 4:
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ if (_firstDescription + (SAVEBUTTONS - 6) > MAXSAVEGAMES - (SAVEBUTTONS - 6))
+ _firstDescription = MAXSAVEGAMES - (SAVEBUTTONS - 6);
+ else
+ _firstDescription += (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ }
+ }
+ }
+
+ if (_editingDescription)
+ editDescription();
+}
+
+void Control::removeSave() {
+ for (int i = 0; i < ARRAYSIZE(_slabs); i++) {
+ free(_slabs[i]);
+ _slabs[i] = nullptr;
+ }
+
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resClose(CZECH_SR_REDFONT);
+ } else {
+ _resMan->resClose(SR_REDFONT);
+ }
+
+ setVolumes();
+}
+
+bool Control::restoreGame() {
+ if (_selectedSavegame < MAXSAVEGAMES) {
+ restoreGameFromFile(_selectedSavegame);
+ doRestore();
+
+ return true;
+ }
+
+ return false;
+}
+
+void Control::initialiseRestore() {
+ uint8 *src, *dst;
+ int32 size;
+ FrameHeader *f;
+ Sprite *srWindow;
+ Sprite *srButuf, *srButus, *srButds, *srButdf;
+ Sprite *srSlab1, *srSlab2, *srSlab3, *srSlab4;
+
+ if (SwordEngine::_systemVars.language == BS1_CZECH)
+ _resMan->resOpen(CZECH_SR_REDFONT);
+ else
+ _resMan->resOpen(SR_REDFONT);
+
+ srWindow = (Sprite *)_resMan->openFetchRes(SR_WINDOW);
+
+ f = (FrameHeader *)((uint8 *)srWindow + _resMan->getUint32(srWindow->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+ dst = _screenBuf +
+ ((SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2) +
+ (SCREEN_WIDTH * ((SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2));
+
+ if (SwordEngine::isPsx()) {
+ drawPsxComponent(PSX_PANEL, src, dst, f);
+ } else {
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ src += _resMan->getUint16(f->width);
+ dst += SCREEN_WIDTH;
+ }
+ }
+
+ _resMan->resClose(SR_WINDOW);
+
+ _numButtons = SAVEBUTTONS;
+ putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 2].y1, 0);
+ putButton(saveButtons[SAVEBUTTONS - 1].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+
+ renderText(_lStrings[STR_RESTORE], saveButtons[SAVEBUTTONS - 2].x1 + 40, saveButtons[SAVEBUTTONS - 2].y1);
+ renderText(_lStrings[STR_CANCEL], saveButtons[SAVEBUTTONS - 1].x1 - 15 - getTextLength(_lStrings[STR_CANCEL]), saveButtons[SAVEBUTTONS - 1].y1);
+
+ _gamesSaved = readFileDescriptions();
+
+ // Create the slabs here
+ srSlab1 = (Sprite *)_resMan->openFetchRes(SR_SLAB1);
+
+ if (SwordEngine::isPsx()) {
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[0]));
+ size = sizeof(Sprite) + sizeof(FrameHeader) + _resMan->getUint16(f->width) / 2 * _resMan->getUint16(f->height);
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[1]));
+ size += (sizeof(FrameHeader) + _resMan->getUint16(f->width) / 2 * _resMan->getUint16(f->height));
+ } else {
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[0]));
+ size = sizeof(Sprite) + sizeof(FrameHeader) + _resMan->getUint16(f->width) * _resMan->getUint16(f->height);
+ f = (FrameHeader *)((uint8 *)srSlab1 + _resMan->getUint32(srSlab1->spriteOffset[1]));
+ size += (sizeof(FrameHeader) + _resMan->getUint16(f->width) * _resMan->getUint16(f->height));
+ }
+
+ for (int i = 0; i < SAVEBUTTONS - 6; i++) {
+ _slabs[i] = (Sprite *)malloc(size);
+ }
+
+ memcpy((uint8 *)_slabs[0], (uint8 *)srSlab1, size);
+ memcpy((uint8 *)_slabs[4], (uint8 *)srSlab1, size);
+ _resMan->resClose(SR_SLAB1);
+
+ srSlab2 = (Sprite *)_resMan->openFetchRes(SR_SLAB2);
+ memcpy((uint8 *)_slabs[1], (uint8 *)srSlab2, size);
+ memcpy((uint8 *)_slabs[5], (uint8 *)srSlab2, size);
+ _resMan->resClose(SR_SLAB2);
+
+ srSlab3 = (Sprite *)_resMan->openFetchRes(SR_SLAB3);
+ memcpy((uint8 *)_slabs[2], (uint8 *)srSlab3, size);
+ memcpy((uint8 *)_slabs[6], (uint8 *)srSlab3, size);
+ _resMan->resClose(SR_SLAB3);
+
+ srSlab4 = (Sprite *)_resMan->openFetchRes(SR_SLAB4);
+ memcpy((uint8 *)_slabs[3], (uint8 *)srSlab4, size);
+ memcpy((uint8 *)_slabs[7], (uint8 *)srSlab4, size);
+ _resMan->resClose(SR_SLAB4);
+
+ renderSlabs();
+ renderTexts();
+}
+
+void Control::implementRestore() {
+ char string[40];
+
+ Sprite *srButuf, *srButus, *srButds, *srButdf;
+
+ _currentButton = getCurrentButton(&saveButtons[0]);
+
+ if ((_buttonPressed) && (!_currentButton)) {
+ //Reset button pressed
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 4):
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 3):
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 1):
+ case (SAVEBUTTONS):
+ putButton(saveButtons[_buttonPressed - 1].x1, saveButtons[_buttonPressed - 1].y1, 0);
+ break;
+ }
+ }
+
+ _buttonPressed = 0;
+ }
+
+ // Enhancement! Scrollable savegames list! :-)
+ bool useWheelScroll = false;
+ if (_mouseState && _currentButton >= 1 && _currentButton <= 8) {
+ if (_mouseState & BS1_WHEEL_DOWN) {
+ _buttonPressed = (SAVEBUTTONS - 3);
+ useWheelScroll = true;
+ } else if (_mouseState & BS1_WHEEL_UP) {
+ _buttonPressed = (SAVEBUTTONS - 4);
+ useWheelScroll = true;
+ }
+ }
+
+ if (_mouseState) {
+ if ((useWheelScroll || (_mouseState & BS1L_BUTTON_DOWN)) && (_currentButton)) {
+ // Set button pressed
+ if (!useWheelScroll)
+ _buttonPressed = _currentButton;
+
+ if (_buttonPressed) {
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 1);
+ _resMan->resClose(SR_BUTUF);
+
+ if (_editingDescription) {
+ uneditDescription();
+ }
+
+ _scroll = 1;
+ _scrollCount = 10;
+ if (_firstDescription > 0) {
+ if (_firstDescription - (SAVEBUTTONS - 6) < 0)
+ _firstDescription = 0;
+ else
+ _firstDescription -= (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+
+ break;
+ case (SAVEBUTTONS - 4):
+ // Don't render the button as pressed when using wheel scrolling
+ if (!useWheelScroll) {
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 1);
+ _resMan->resClose(SR_BUTUS);
+ }
+
+ if (_editingDescription) {
+ uneditDescription();
+ }
+
+ _scroll = 2;
+ _scrollCount = 10;
+ if (_firstDescription > 0) {
+ _firstDescription -= 1;
+ renderSlabs();
+ renderTexts();
+ }
+
+ break;
+ case (SAVEBUTTONS - 3):
+ // Don't render the button as pressed when using wheel scrolling
+ if (!useWheelScroll) {
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 1);
+ _resMan->resClose(SR_BUTDS);
+ }
+
+ if (_editingDescription) {
+ uneditDescription();
+ }
+
+ _scroll = 3;
+ _scrollCount = 10;
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ _firstDescription += 1;
+ renderSlabs();
+ renderTexts();
+ }
+
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 1);
+ _resMan->resClose(SR_BUTDF);
+
+ if (_editingDescription) {
+ uneditDescription();
+ }
+
+ _scroll = 4;
+ _scrollCount = 10;
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ if (_firstDescription + (SAVEBUTTONS - 6) > MAXSAVEGAMES - (SAVEBUTTONS - 6))
+ _firstDescription = MAXSAVEGAMES - (SAVEBUTTONS - 6);
+ else
+ _firstDescription += (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+
+ break;
+ case (SAVEBUTTONS - 1):
+ case (SAVEBUTTONS):
+ putButton(saveButtons[_buttonPressed - 1].x1, saveButtons[_buttonPressed - 1].y1, 1);
+ break;
+ }
+ } else {
+ if (_editingDescription) {
+ if ((_buttonPressed != _editingDescription) && (strlen(_fileDescriptions[_buttonPressed + _firstDescription - 1]))) {
+ Common::strcpy_s(_fileDescriptions[_editingDescription + _firstDescription - 1], _oldString);
+ _slabSelected = 0;
+ uneditDescription();
+
+ setEditDescription(_buttonPressed);
+
+ renderSlab(_slabSelected - 1, _editingDescription - 1);
+ Common::strcpy_s(string, _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 42, saveButtons[_editingDescription - 1].y1 + 5);
+ Common::sprintf_s(string, "%d", _firstDescription + _editingDescription);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 12, saveButtons[_editingDescription - 1].y1 + 5);
+ }
+ } else {
+ if (strlen(_fileDescriptions[_buttonPressed + _firstDescription - 1])) {
+ setEditDescription(_buttonPressed);
+ renderSlab(_slabSelected - 1, _editingDescription - 1);
+ Common::strcpy_s(string, _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 42, saveButtons[_editingDescription - 1].y1 + 5);
+ Common::sprintf_s(string, "%d", _firstDescription + _editingDescription);
+ renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 12, saveButtons[_editingDescription - 1].y1 + 5);
+ }
+ }
+ }
+ }
+ }
+
+ if ((_mouseState & BS1L_BUTTON_UP) && (_buttonPressed)) {
+ if (_buttonPressed > SAVEBUTTONS - 6) {
+ switch (_buttonPressed) {
+ case (SAVEBUTTONS - 5):
+ srButuf = (Sprite *)_resMan->openFetchRes(SR_BUTUF);
+ putSpriteButton(srButuf, saveButtons[SAVEBUTTONS - 6].x1, saveButtons[SAVEBUTTONS - 6].y1, 0);
+ _resMan->resClose(SR_BUTUF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 4):
+ srButus = (Sprite *)_resMan->openFetchRes(SR_BUTUS);
+ putSpriteButton(srButus, saveButtons[SAVEBUTTONS - 5].x1, saveButtons[SAVEBUTTONS - 5].y1, 0);
+ _resMan->resClose(SR_BUTUS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 3):
+ srButds = (Sprite *)_resMan->openFetchRes(SR_BUTDS);
+ putSpriteButton(srButds, saveButtons[SAVEBUTTONS - 4].x1, saveButtons[SAVEBUTTONS - 4].y1, 0);
+ _resMan->resClose(SR_BUTDS);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 2):
+ srButdf = (Sprite *)_resMan->openFetchRes(SR_BUTDF);
+ putSpriteButton(srButdf, saveButtons[SAVEBUTTONS - 3].x1, saveButtons[SAVEBUTTONS - 3].y1, 0);
+ _resMan->resClose(SR_BUTDF);
+ _scroll = 0;
+ break;
+ case (SAVEBUTTONS - 1):
+ putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+ if ((_editingDescription) && (strlen(_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
+ //Restore game here
+ _selectedSavegame = _firstDescription + _editingDescription - 1;
+ //Common::sprintf_s(saveFilename, "savegame.%.3d", _firstDescription + _editingDescription - 1);
+ uneditDescription();
+ SwordEngine::_systemVars.saveGameFlag = SGF_RESTORE;
+ SwordEngine::_systemVars.snrStatus = SNR_BLANK;
+ }
+ break;
+ case (SAVEBUTTONS):
+ putButton(saveButtons[SAVEBUTTONS - 1].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
+ if (_editingDescription)
+ uneditDescription();
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
+ break;
+ }
+ }
+
+ _buttonPressed = 0;
+ }
+ }
+
+ if (_scroll) {
+ if (--_scrollCount == 0) {
+ _scrollCount = 2;
+
+ switch (_scroll) {
+ case 1:
+ if (_firstDescription > 0) {
+ if (_firstDescription - (SAVEBUTTONS - 6) < 0)
+ _firstDescription = 0;
+ else
+ _firstDescription -= (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 2:
+ if (_firstDescription > 0) {
+ _firstDescription -= 1;
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 3:
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ _firstDescription += 1;
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ case 4:
+ if (_firstDescription < MAXSAVEGAMES - (SAVEBUTTONS - 6)) {
+ if (_firstDescription + (SAVEBUTTONS - 6) > MAXSAVEGAMES - (SAVEBUTTONS - 6))
+ _firstDescription = MAXSAVEGAMES - (SAVEBUTTONS - 6);
+ else
+ _firstDescription += (SAVEBUTTONS - 6);
+ renderSlabs();
+ renderTexts();
+ }
+ break;
+ }
+ }
+ }
+
+ if (_editingDescription)
+ restoreSelected();
+}
+
+void Control::removeRestore() {
+ for (int i = 0; i < ARRAYSIZE(_slabs); i++) {
+ free(_slabs[i]);
+ _slabs[i] = nullptr;
+ }
+
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resClose(CZECH_SR_REDFONT);
+ } else {
+ _resMan->resClose(SR_REDFONT);
+ }
+
+ setVolumes();
+}
+
+void Control::initialiseControlPanel() {
+ uint8 *src;
+ uint8 *dst;
+ FrameHeader *f;
+ Sprite *srPanel = nullptr;
+
+ _resMan->resOpen(SR_TEXT_BUTTON);
+ _mouse->controlPanel(true);
+
+ // Clear the render buffer and copy the control panel into it
+ memset(_screenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_FULL_DEPTH);
+
+ if (SwordEngine::_systemVars.controlPanelMode != CP_DEATHSCREEN) { // NOT THE DEATH SCREEN ie. start game panel, normal control panel, or end of game
+ switch (SwordEngine::_systemVars.language) {
+ case BS1_ENGLISH:
+ if (SwordEngine::_systemVars.realLanguage == Common::EN_USA) {
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_AMERICAN);
+ } else {
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_ENGLISH);
+ }
+
+ break;
+ case BS1_FRENCH:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_FRENCH);
+ break;
+ case BS1_GERMAN:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_GERMAN);
+ break;
+ case BS1_ITALIAN:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_ITALIAN);
+ break;
+ case BS1_SPANISH:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_SPANISH);
+ break;
+ case BS1_CZECH:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_SPANISH);
+ break;
+ case BS1_PORT:
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_PANEL_SPANISH);
+ break;
+ default:
+ break;
+ }
+ } else {
+ srPanel = (Sprite *)_resMan->openFetchRes(SR_DEATHPANEL);
+ }
+
+ if (srPanel) {
+ f = (FrameHeader *)((uint8 *)srPanel + _resMan->getUint32(srPanel->spriteOffset[0]));
+ src = (uint8 *)f + sizeof(FrameHeader);
+
+ if (SwordEngine::isPsx()) {
+ int component = SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN ? PSX_DEATHPANEL : PSX_PANEL;
+ dst = _screenBuf +
+ SCREEN_WIDTH * (SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2 +
+ (SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2;
+
+ if (component == PSX_DEATHPANEL)
+ dst = _screenBuf;
+
+ drawPsxComponent(component, src, dst, f);
+ } else {
+ dst = _screenBuf + SCREEN_WIDTH * (SCREEN_DEPTH - _resMan->getUint16(f->height)) / 2 + (SCREEN_WIDTH - _resMan->getUint16(f->width)) / 2;
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ memcpy(dst, src, _resMan->getUint16(f->width));
+ dst += SCREEN_WIDTH;
+ src += _resMan->getUint16(f->width);
+ }
+ }
+
+ _system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 40, SCREEN_WIDTH, SCREEN_DEPTH);
+ }
+
+ if (SwordEngine::_systemVars.controlPanelMode != CP_DEATHSCREEN) {
+ switch (SwordEngine::_systemVars.language) {
+ case BS1_ENGLISH:
+ if (SwordEngine::_systemVars.realLanguage == Common::EN_USA) {
+ _resMan->resClose(SR_PANEL_AMERICAN);
+ } else {
+ _resMan->resClose(SR_PANEL_ENGLISH);
+ }
+
+ break;
+ case BS1_FRENCH:
+ _resMan->resClose(SR_PANEL_FRENCH);
+ break;
+ case BS1_GERMAN:
+ _resMan->resClose(SR_PANEL_GERMAN);
+ break;
+ case BS1_ITALIAN:
+ _resMan->resClose(SR_PANEL_ITALIAN);
+ break;
+ case BS1_SPANISH:
+ _resMan->resClose(SR_PANEL_SPANISH);
+ break;
+ case BS1_CZECH:
+ _resMan->resClose(SR_PANEL_SPANISH);
+ break;
+ case BS1_PORT:
+ _resMan->resClose(SR_PANEL_SPANISH);
+ break;
+ default:
+ break;
+ }
+ } else {
+ _resMan->resClose(SR_DEATHPANEL);
+ }
+
+ // Draw the buttons...
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ _numButtons = 8;
+
+ for (int i = 0; i < _numButtons; i++) {
+ putButton(panelButtons[i].x1, panelButtons[i].y1, 0);
+ }
+
+ putTextButton(SwordEngine::_systemVars.showText ? 1 : 0);
+ } else {
+ _numButtons = 4;
+
+ for (int i = 1; i < _numButtons; i++) {
+ putButton(deathButtons[i].x1, deathButtons[i].y1, 0);
}
}
- // Delete the temporary thumbnail
- delete _tempThumbnail;
- _tempThumbnail = 0;
+ // Render text elements...
+ if (SwordEngine::_systemVars.controlPanelMode == CP_THEEND)
+ renderText(_lStrings[STR_THE_END], (SCREEN_WIDTH - getTextLength(_lStrings[STR_THE_END])) / 2, 188);
- _panelShown = false;
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ renderText(_lStrings[STR_SAVE], 180, 188);
+ renderText(_lStrings[STR_DONE], 460 - getTextLength(_lStrings[STR_DONE]), 332);
+
+ renderText(_lStrings[STR_RESTORE], 180, 224);
+ renderText(_lStrings[STR_RESTART], 180, 260);
+ renderText(_lStrings[STR_QUIT], 180, 296);
+ } else { // Start-game panel, death panel & end-game panel
+ renderText(_lStrings[STR_RESTORE], 285, 224);
+
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NEWGAME) { // Start-game panel
+ renderText(_lStrings[STR_START], 285, 260);
+ } else {
+ renderText(_lStrings[STR_RESTART], 285, 260);
+ }
+
+ renderText(_lStrings[STR_QUIT], 285, 296);
+ }
- return retVal;
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ renderText(_lStrings[STR_SPEED], 460 - getTextLength(_lStrings[STR_SPEED]), 188);
+ renderText(_lStrings[STR_VOLUME], 460 - getTextLength(_lStrings[STR_VOLUME]), 224);
+ renderText(_lStrings[STR_TEXT], 460 - getTextLength(_lStrings[STR_TEXT]), 260);
+ }
}
-uint8 Control::getClicks(uint8 mode, uint8 *retVal) {
- uint8 checkButtons = _numButtons;
- if (mode == BUTTON_VOLUME_PANEL) {
- handleVolumeClicks();
- checkButtons = 1;
- }
-
- uint8 flag = 0;
- if (_keyPressed.keycode == Common::KEYCODE_ESCAPE)
- flag = kButtonCancel;
- else if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER)
- flag = kButtonOk;
-
- if (flag) {
- for (uint8 cnt = 0; cnt < checkButtons; cnt++)
- if (_buttons[cnt]->_flag == flag)
- return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
- }
-
- if (!_mouseState)
- return 0;
- if (_mouseState & BS1L_BUTTON_DOWN)
- for (uint8 cnt = 0; cnt < checkButtons; cnt++)
- if (_buttons[cnt]->wasClicked(_mouseCoord.x, _mouseCoord.y)) {
- _selectedButton = cnt;
- _buttons[cnt]->setSelected(1);
- if (_buttons[cnt]->isSaveslot())
- showSavegameNames();
+void Control::implementControlPanel() {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ _currentButton = getCurrentButton(&panelButtons[0]);
+ } else {
+ _currentButton = getCurrentButton(&deathButtons[0]);
+ }
+
+ if ((_buttonPressed) && (!_currentButton)) {
+ // Reset button pressed
+ if (_buttonPressed != TEXTBUTTONID) {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ putButton(panelButtons[_buttonPressed - 1].x1, panelButtons[_buttonPressed - 1].y1, 0);
+ } else {
+ putButton(deathButtons[_buttonPressed - 1].x1, deathButtons[_buttonPressed - 1].y1, 0);
}
- if (_mouseState & BS1L_BUTTON_UP) {
- for (uint8 cnt = 0; cnt < checkButtons; cnt++)
- if (_buttons[cnt]->wasClicked(_mouseCoord.x, _mouseCoord.y))
- if (_selectedButton == cnt) {
- // saveslots stay selected after clicking
- if (!_buttons[cnt]->isSaveslot())
- _buttons[cnt]->setSelected(0);
- _selectedButton = 255;
- return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
- }
- if (_selectedButton < checkButtons) {
- _buttons[_selectedButton]->setSelected(0);
- if (_buttons[_selectedButton]->isSaveslot())
- showSavegameNames();
}
- _selectedButton = 255;
- }
- if (_mouseState & BS1_WHEEL_UP) {
- for (uint8 cnt = 0; cnt < checkButtons; cnt++)
- if (_buttons[cnt]->_id == BUTTON_SCROLL_UP_SLOW)
- return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
- }
- if (_mouseState & BS1_WHEEL_DOWN) {
- for (uint8 cnt = 0; cnt < checkButtons; cnt++)
- if (_buttons[cnt]->_id == BUTTON_SCROLL_DOWN_SLOW)
- return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
+
+ _buttonPressed = 0;
}
- return 0;
-}
-uint8 Control::handleButtonClick(uint8 id, uint8 mode, uint8 *retVal) {
- switch (mode) {
- case BUTTON_MAIN_PANEL:
- if (id == BUTTON_RESTART) {
- if (SwordEngine::_systemVars.controlPanelMode) // if player is dead or has just started, don't ask for confirmation
- *retVal |= CONTROL_RESTART_GAME;
- else if (getConfirm(_lStrings[STR_RESTART]))
- *retVal |= CONTROL_RESTART_GAME;
- else
- return mode;
- } else if ((id == BUTTON_RESTORE_PANEL) || (id == BUTTON_SAVE_PANEL) ||
- (id == BUTTON_DONE) || (id == BUTTON_VOLUME_PANEL))
- return id;
- else if (id == BUTTON_TEXT) {
- SwordEngine::_systemVars.showText = !SwordEngine::_systemVars.showText;
- _buttons[5]->setSelected(SwordEngine::_systemVars.showText ? 1 : 0);
- } else if (id == BUTTON_QUIT) {
- if (getConfirm(_lStrings[STR_QUIT]))
- Engine::quitGame();
- return mode;
- }
- break;
- case BUTTON_SAVE_PANEL:
- case BUTTON_RESTORE_PANEL:
- if ((id >= BUTTON_SCROLL_UP_FAST) && (id <= BUTTON_SCROLL_DOWN_FAST))
- saveNameScroll(id, mode == BUTTON_SAVE_PANEL);
- else if ((id >= BUTTON_SAVE_SELECT1) && (id <= BUTTON_SAVE_SELECT8))
- saveNameSelect(id, mode == BUTTON_SAVE_PANEL);
- else if (id == BUTTON_SAVE_RESTORE_OKAY) {
- if (mode == BUTTON_SAVE_PANEL) {
- _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
- if (saveToFile()) // don't go back to main panel if save fails.
- return BUTTON_DONE;
- } else {
- if (restoreFromFile()) { // don't go back to main panel if restore fails.
- *retVal |= CONTROL_GAME_RESTORED;
- return BUTTON_MAIN_PANEL;
+ if (_mouseState) {
+ if ((_mouseState & BS1L_BUTTON_DOWN) && (_currentButton)) {
+ // Set button pressed
+ _buttonPressed = _currentButton;
+ if (_buttonPressed != TEXTBUTTONID) {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) {
+ putButton(panelButtons[_buttonPressed - 1].x1, panelButtons[_buttonPressed - 1].y1, 1);
+ } else {
+ putButton(deathButtons[_buttonPressed - 1].x1, deathButtons[_buttonPressed - 1].y1, 1);
}
+ } else {
+ SwordEngine::_systemVars.showText = !SwordEngine::_systemVars.showText;
+ putTextButton(SwordEngine::_systemVars.showText ? 1 : 0);
}
- } else if (id == BUTTON_SAVE_CANCEL) {
- _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
- return BUTTON_MAIN_PANEL; // mode down to main panel
}
- break;
- case BUTTON_VOLUME_PANEL:
- return id;
- default:
- break;
+
+ if ((_mouseState & BS1L_BUTTON_UP) && (_buttonPressed)) {
+ SwordEngine::_systemVars.snrStatus = _buttonPressed + 1;
+ _buttonPressed = 0;
+ }
}
- return 0;
}
-void Control::deselectSaveslots() {
- for (uint8 cnt = 0; cnt < 8; cnt++)
- _buttons[cnt]->setSelected(0);
+void Control::removeControlPanel() {
+ _resMan->resClose(SR_TEXT_BUTTON);
}
-void Control::setupMainPanel() {
- uint32 panelId;
-
- if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN)
- panelId = SR_DEATHPANEL;
- else {
- if (SwordEngine::_systemVars.realLanguage == Common::EN_USA)
- panelId = SR_PANEL_AMERICAN;
- else if (SwordEngine::_systemVars.language <= BS1_SPANISH)
- panelId = SR_PANEL_ENGLISH + SwordEngine::_systemVars.language;
- else
- panelId = SR_PANEL_ENGLISH;
- }
-
- ControlButton *panel = new ControlButton(0, 0, panelId, 0, 0, _resMan, _screenBuf, _system);
- panel->draw();
- delete panel;
-
- if (SwordEngine::_systemVars.controlPanelMode != CP_NORMAL)
- createButtons(_deathButtons, 3);
- else {
- createButtons(_panelButtons, 7);
- _buttons[5]->setSelected(SwordEngine::_systemVars.showText ? 1 : 0);
+void Control::initialiseResources() {
+ if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resOpen(CZECH_SR_DEATHFONT);
+ } else {
+ _resMan->resOpen(_resMan->getDeathFontId());
+ }
+ } else {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resOpen(CZECH_SR_FONT);
+ } else {
+ _resMan->resOpen(SR_FONT);
+ }
}
- if (SwordEngine::_systemVars.controlPanelMode == CP_THEEND) // end of game
- renderText(_lStrings[STR_THE_END], 480, 188 + 40, TEXT_RIGHT_ALIGN);
+ _resMan->resOpen(SR_BUTTON);
- if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) { // normal panel
- renderText(_lStrings[STR_SAVE], 180, 188 + 40, TEXT_LEFT_ALIGN);
- renderText(_lStrings[STR_DONE], 460, 332 + 40, TEXT_RIGHT_ALIGN);
- renderText(_lStrings[STR_RESTORE], 180, 224 + 40, TEXT_LEFT_ALIGN);
- renderText(_lStrings[STR_RESTART], 180, 260 + 40, TEXT_LEFT_ALIGN);
- renderText(_lStrings[STR_QUIT], 180, 296 + 40, TEXT_LEFT_ALIGN);
-
- renderText(_lStrings[STR_VOLUME], 460, 188 + 40, TEXT_RIGHT_ALIGN);
- renderText(_lStrings[STR_TEXT], 460, 224 + 40, TEXT_RIGHT_ALIGN);
- } else {
- renderText(_lStrings[STR_RESTORE], 285, 224 + 40, TEXT_LEFT_ALIGN);
- if (SwordEngine::_systemVars.controlPanelMode == CP_NEWGAME) // just started game
- renderText(_lStrings[STR_START], 285, 260 + 40, TEXT_LEFT_ALIGN);
- else
- renderText(_lStrings[STR_RESTART], 285, 260 + 40, TEXT_LEFT_ALIGN);
- renderText(_lStrings[STR_QUIT], 285, 296 + 40, TEXT_LEFT_ALIGN);
- }
+ _screen->fnSetFadeTargetPalette(0, 256, SR_PALETTE);
+ _screen->fnSetFadeTargetPalette(0, 1, 0, BORDER_BLACK);
}
-void Control::setupSaveRestorePanel(bool saving) {
- readSavegameDescriptions();
+void Control::releaseResources() {
+ _resMan->resClose(SR_BUTTON);
- FrameHeader *savePanel = _resMan->fetchFrame(_resMan->openFetchRes(SR_WINDOW), 0);
- uint16 panelX = (640 - _resMan->getUint16(savePanel->width)) / 2;
- uint16 panelY = (480 - _resMan->getUint16(savePanel->height)) / 2;
- ControlButton *panel = new ControlButton(panelX, panelY, SR_WINDOW, 0, 0, _resMan, _screenBuf, _system);
- panel->draw();
- delete panel;
- _resMan->resClose(SR_WINDOW);
- createButtons(_saveButtons, 14);
- renderText(_lStrings[STR_CANCEL], _saveButtons[13].x - 10, _saveButtons[13].y, TEXT_RIGHT_ALIGN);
- if (saving) {
- renderText(_lStrings[STR_SAVE], _saveButtons[12].x + 30, _saveButtons[13].y, TEXT_LEFT_ALIGN);
+ if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN) {
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resClose(CZECH_SR_DEATHFONT);
+ } else {
+ _resMan->resClose(_resMan->getDeathFontId());
+ }
} else {
- renderText(_lStrings[STR_RESTORE], _saveButtons[12].x + 30, _saveButtons[13].y, TEXT_LEFT_ALIGN);
+ if (SwordEngine::_systemVars.language == BS1_CZECH) {
+ _resMan->resClose(CZECH_SR_FONT);
+ } else {
+ _resMan->resClose(SR_FONT);
+ }
}
- readSavegameDescriptions();
- _selectedSavegame = 255;
- showSavegameNames();
}
-void Control::setupVolumePanel() {
- ControlButton *panel = new ControlButton(0, 0, SR_VOLUME, 0, 0, _resMan, _screenBuf, _system);
- panel->draw();
- delete panel;
+void Control::delay(uint32 msecs) {
+ Common::Event event;
+
+ uint32 now = _system->getMillis();
+ uint32 endTime = now + msecs;
+ _keyPressed.reset();
+ _mouseState = 0;
- renderText(_lStrings[STR_MUSIC], 149, 39 + 40, TEXT_LEFT_ALIGN);
- renderText(_lStrings[STR_SPEECH], 320, 39 + 40, TEXT_CENTER);
- renderText(_lStrings[STR_FX], 449, 39 + 40, TEXT_CENTER);
+ do {
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _keyPressed = event.kbd;
+ // we skip the rest of the delay and return immediately
+ // to handle keyboard input
+ return;
+ case Common::EVENT_MOUSEMOVE:
+ _mouseCoord = event.mouse;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ _mouseState |= BS1L_BUTTON_DOWN;
+ _mouseCoord = event.mouse;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ _mouseState |= BS1L_BUTTON_UP;
+ _mouseCoord = event.mouse;
+ break;
+ case Common::EVENT_WHEELUP:
+ _mouseState |= BS1_WHEEL_UP;
+ _mouseCoord = event.mouse;
+ break;
+ case Common::EVENT_WHEELDOWN:
+ _mouseState |= BS1_WHEEL_DOWN;
+ break;
+ default:
+ break;
+ }
+ }
- createButtons(_volumeButtons, 4);
- renderText(_lStrings[STR_DONE], _volumeButtons[0].x - 10, _volumeButtons[0].y, TEXT_RIGHT_ALIGN);
+ _system->updateScreen();
+ _system->delayMillis(10);
+ } while (_system->getMillis() < endTime);
+}
- uint8 volL, volR;
- _music->giveVolume(&volL, &volR);
- renderVolumeBar(1, volL, volR);
- _sound->giveSpeechVol(&volL, &volR);
- renderVolumeBar(2, volL, volR);
- _sound->giveSfxVol(&volL, &volR);
- renderVolumeBar(3, volL, volR);
+uint8 *Control::decompressPsxGfx(uint8 *src, FrameHeader *f) {
+ uint8 *dst = (uint8 *)malloc(_resMan->getUint16(f->height) * _resMan->getUint16(f->width));
+ memset(dst, 0, _resMan->getUint16(f->height) * _resMan->getUint16(f->width));
+ Screen::decompressHIF(src, dst);
+ return dst;
}
-void Control::handleVolumeClicks() {
- if (_mouseDown) {
- uint8 clickedId = 0;
- for (uint8 cnt = 1; cnt < 4; cnt++)
- if (_buttons[cnt]->wasClicked(_mouseCoord.x, _mouseCoord.y))
- clickedId = cnt;
- if (clickedId) { // these are circle shaped, so check again if it was clicked.
- uint8 clickDest = 0;
- int16 mouseDiffX = _mouseCoord.x - (_volumeButtons[clickedId].x + 48);
- int16 mouseDiffY = _mouseCoord.y - (_volumeButtons[clickedId].y + 48);
- int16 mouseOffs = (int16)sqrt((double)(mouseDiffX * mouseDiffX + mouseDiffY * mouseDiffY));
- // check if the player really hit the button (but not the center).
- if ((mouseOffs <= 42) && (mouseOffs >= 8)) {
- if (mouseDiffX > 8) { // right part
- if (mouseDiffY < -8) // upper right
- clickDest = 2;
- else if (ABS(mouseDiffY) <= 8) // right
- clickDest = 3;
- else // lower right
- clickDest = 4;
- } else if (mouseDiffX < -8) { // left part
- if (mouseDiffY < -8) // upper left
- clickDest = 8;
- else if (ABS(mouseDiffY) <= 8) // left
- clickDest = 7;
- else // lower left
- clickDest = 6;
- } else { // middle
- if (mouseDiffY < -8)
- clickDest = 1; // upper
- else if (mouseDiffY > 8)
- clickDest = 5; // lower
+void Control::drawPsxComponent(int componentType, uint8 *src, uint8 *dst, FrameHeader *f) {
+ src = decompressPsxGfx(src, f);
+ uint8 *initialPtr = src;
+
+ switch (componentType) {
+ case PSX_PANEL:
+ case PSX_SLAB:
+ // Draw the source image at double the resolution
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ for (int j = 0; j < _resMan->getUint16(f->width) / 2; j++) {
+ if (src[j]) {
+ dst[j * 2] = src[j];
+ dst[j * 2 + 1] = src[j];
}
}
- _buttons[clickedId]->setSelected(clickDest);
- changeVolume(clickedId, clickDest);
- }
- } else if (_mouseState & BS1L_BUTTON_UP) {
- _buttons[1]->setSelected(0);
- _buttons[2]->setSelected(0);
- _buttons[3]->setSelected(0);
- }
-}
-void Control::changeVolume(uint8 id, uint8 action) {
- // ids: 1 = music, 2 = speech, 3 = sfx
- uint8 volL = 0, volR = 0;
- if (id == 1)
- _music->giveVolume(&volL, &volR);
- else if (id == 2)
- _sound->giveSpeechVol(&volL, &volR);
- else if (id == 3)
- _sound->giveSfxVol(&volL, &volR);
-
- int8 direction = 0;
- if ((action >= 4) && (action <= 6)) // lower part of the button => decrease volume
- direction = -1;
- else if ((action == 8) || (action == 1) || (action == 2)) // upper part => increase volume
- direction = 1;
- else if ((action == 3) || (action == 7)) // middle part => pan volume
- direction = 1;
- int8 factorL = 8, factorR = 8;
- if ((action >= 6) && (action <= 8)) { // left part => left pan
- factorL = 8;
- factorR = (action == 7) ? -8 : 0;
- } else if ((action >= 2) && (action <= 4)) { // right part
- factorR = 8;
- factorL = (action == 3) ? -8 : 0;
- }
- int16 resVolL = volL + direction * factorL;
- int16 resVolR = volR + direction * factorR;
-
- volL = (uint8)MAX((int16)0, MIN(resVolL, (int16)255));
- volR = (uint8)MAX((int16)0, MIN(resVolR, (int16)255));
-
- if (id == 1)
- _music->setVolume(volL, volR);
- else if (id == 2)
- _sound->setSpeechVol(volL, volR);
- else if (id == 3)
- _sound->setSfxVol(volL, volR);
-
- renderVolumeBar(id, volL, volR);
-}
+ dst += SCREEN_WIDTH;
-bool Control::getConfirm(const uint8 *title) {
- ControlButton *panel = new ControlButton(0, 0, SR_CONFIRM, 0, 0, _resMan, _screenBuf, _system);
- panel->draw();
- delete panel;
- renderText(title, 320, 160, TEXT_CENTER);
- ControlButton *buttons[2];
- buttons[0] = new ControlButton(260, 192 + 40, SR_BUTTON, 0, 0, _resMan, _screenBuf, _system);
- renderText(_lStrings[STR_OK], 640 - 260, 192 + 40, TEXT_RIGHT_ALIGN);
- buttons[1] = new ControlButton(260, 256 + 40, SR_BUTTON, 0, 0, _resMan, _screenBuf, _system);
- renderText(_lStrings[STR_CANCEL], 640 - 260, 256 + 40, TEXT_RIGHT_ALIGN);
- uint8 retVal = 0;
- uint8 clickVal = 0;
- do {
- buttons[0]->draw();
- buttons[1]->draw();
- delay(1000 / 12);
- if (_keyPressed.keycode == Common::KEYCODE_ESCAPE)
- retVal = 2;
- else if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER)
- retVal = 1;
- if (_mouseState & BS1L_BUTTON_DOWN) {
- if (buttons[0]->wasClicked(_mouseCoord.x, _mouseCoord.y))
- clickVal = 1;
- else if (buttons[1]->wasClicked(_mouseCoord.x, _mouseCoord.y))
- clickVal = 2;
- else
- clickVal = 0;
- if (clickVal)
- buttons[clickVal - 1]->setSelected(1);
- }
- if ((_mouseState & BS1L_BUTTON_UP) && (clickVal)) {
- if (buttons[clickVal - 1]->wasClicked(_mouseCoord.x, _mouseCoord.y))
- retVal = clickVal;
- else
- buttons[clickVal - 1]->setSelected(0);
- clickVal = 0;
- }
- } while (!retVal);
- delete buttons[0];
- delete buttons[1];
- return retVal == 1;
-}
+ for (int j = 0; j < _resMan->getUint16(f->width) / 2; j++) {
+ if (src[j]) {
+ dst[j * 2] = src[j];
+ dst[j * 2 + 1] = src[j];
+ }
+ }
-bool Control::keyAccepted(uint16 ascii) {
- static const char allowedSpecials[] = ",.:-()?! \"\'";
- if (((ascii >= 'A') && (ascii <= 'Z')) ||
- ((ascii >= 'a') && (ascii <= 'z')) ||
- ((ascii >= '0') && (ascii <= '9')) ||
- strchr(allowedSpecials, ascii))
- return true;
- else
- return false;
-}
+ dst += SCREEN_WIDTH;
-void Control::handleSaveKey(Common::KeyState kbd) {
- if (_selectedSavegame < 255) {
- uint8 len = _saveNames[_selectedSavegame].size();
- if ((kbd.keycode == Common::KEYCODE_BACKSPACE) && len) // backspace
- _saveNames[_selectedSavegame].deleteLastChar();
- else if (kbd.ascii && keyAccepted(kbd.ascii) && (len < 31)) {
- _saveNames[_selectedSavegame].insertChar(kbd.ascii, len);
+ src += _resMan->getUint16(f->width) / 2;
}
- showSavegameNames();
- }
-}
-bool Control::saveToFile() {
- if ((_selectedSavegame == 255) || _saveNames[_selectedSavegame].size() == 0)
- return false; // no saveslot selected or no name entered
- saveGameToFile(_selectedSavegame);
- return true;
-}
+ break;
+ case PSX_DEATHPANEL:
+ // The PSX death panel is 1/3 of the original width, so adjust for that...
+ for (int i = 0; i < _resMan->getUint16(f->height) / 2; i++) {
+ for (int j = 0; (j < (_resMan->getUint16(f->width)) / 3) && (j < (SCREEN_WIDTH - 3)); j++) {
+ if (src[j]) {
+ dst[j * 3] = src[j];
+ dst[j * 3 + 1] = src[j];
+ dst[j * 3 + 2] = src[j];
+ }
+ }
-bool Control::restoreFromFile() {
- if (_selectedSavegame < 255) {
- return restoreGameFromFile(_selectedSavegame);
- } else
- return false;
-}
+ dst += SCREEN_WIDTH;
-void Control::readSavegameDescriptions() {
- char saveName[40];
- Common::String pattern = "sword1.???";
- Common::StringArray filenames = _saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+ for (int j = 0; j < (_resMan->getUint16(f->width)) / 3; j++) {
+ if (src[j]) {
+ dst[j * 3] = src[j];
+ dst[j * 3 + 1] = src[j];
+ dst[j * 3 + 2] = src[j];
+ }
+ }
- _saveNames.clear();
+ dst += SCREEN_WIDTH;
+ src += _resMan->getUint16(f->width) / 3;
+ }
- int num = 0;
- int slotNum = 0;
- for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
- // Obtain the last 3 digits of the filename, since they correspond to the save slot
- slotNum = atoi(file->c_str() + file->size() - 3);
+ break;
+ case PSX_TEXT:
+ case PSX_BUTTON:
+ case PSX_CONFIRM:
+ case PSX_SCROLL:
+ for (int i = 0; i < _resMan->getUint16(f->height); i++) {
+ for (int j = 0; j < _resMan->getUint16(f->width); j++) {
+ if (src[j])
+ dst[j] = src[j];
+ }
- while (num < slotNum) {
- _saveNames.push_back("");
- num++;
- }
+ dst += SCREEN_WIDTH;
- if (slotNum >= 0 && slotNum <= 999) {
- num++;
- Common::InSaveFile *in = _saveFileMan->openForLoading(*file);
- if (in) {
- in->readUint32LE(); // header
- in->read(saveName, 40);
- _saveNames.push_back(saveName);
- delete in;
+ for (int j = 0; j < _resMan->getUint16(f->width); j++) {
+ if (src[j])
+ dst[j] = src[j];
}
- }
- }
- for (int i = _saveNames.size(); i < 1000; i++)
- _saveNames.push_back("");
+ dst += SCREEN_WIDTH;
+ src += _resMan->getUint16(f->width);
+ }
- _saveScrollPos = 0;
- _selectedSavegame = 255;
- _saveFiles = _numSaves = _saveNames.size();
-}
+ break;
+ default:
+ break;
+ };
-bool Control::isPanelShown() {
- return _panelShown;
+ free(initialPtr);
}
int Control::displayMessage(const char *altButton, const char *message, ...) {
@@ -928,12 +2862,6 @@ int Control::displayMessage(const char *altButton, const char *message, ...) {
return result;
}
-bool Control::savegamesExist() {
- Common::String pattern = "sword1.???";
- Common::StringArray saveNames = _saveFileMan->listSavefiles(pattern);
- return saveNames.size() > 0;
-}
-
void Control::checkForOldSaveGames() {
Common::InSaveFile *inf = _saveFileMan->openForLoading("SAVEGAME.INF");
@@ -981,194 +2909,6 @@ void Control::checkForOldSaveGames() {
_saveFileMan->removeSavefile("SAVEGAME.INF");
}
-void Control::showSavegameNames() {
- for (uint8 cnt = 0; cnt < 8; cnt++) {
- _buttons[cnt]->draw();
- uint8 textMode = TEXT_LEFT_ALIGN;
- uint16 ycoord = _saveButtons[cnt].y + 2;
- Common::String savegameNameStr = Common::String::format("%d. %s", cnt + _saveScrollPos + 1, _saveNames[cnt + _saveScrollPos].c_str());
- if (cnt + _saveScrollPos == _selectedSavegame) {
- textMode |= TEXT_RED_FONT;
- ycoord += 2;
- if (_cursorVisible) {
- savegameNameStr += "_";
- }
- }
- renderText((const uint8*)savegameNameStr.c_str(), _saveButtons[cnt].x + 6, ycoord, textMode);
- }
-}
-
-void Control::saveNameSelect(uint8 id, bool saving) {
- deselectSaveslots();
- _buttons[id - BUTTON_SAVE_SELECT1]->setSelected(1);
- uint8 num = (id - BUTTON_SAVE_SELECT1) + _saveScrollPos;
- if (saving && (_selectedSavegame != 255)) // the player may have entered something, clear it again
- _saveNames[_selectedSavegame] = _oldName;
- if (num < _saveFiles) {
- _selectedSavegame = num;
- _oldName = _saveNames[num]; // save for later
- } else {
- if (!saving)
- _buttons[id - BUTTON_SAVE_SELECT1]->setSelected(0); // no save in slot, deselect it
- else {
- if (_saveFiles <= num)
- _saveFiles = num + 1;
- _selectedSavegame = num;
- _oldName.clear();
- }
- }
- if (_selectedSavegame < 255)
- _cursorTick = 0;
- showSavegameNames();
-}
-
-void Control::saveNameScroll(uint8 scroll, bool saving) {
- uint16 maxScroll;
- if (saving)
- maxScroll = 64;
- else
- maxScroll = _saveFiles; // for loading, we can only scroll as far as there are savegames
- if (scroll == BUTTON_SCROLL_UP_FAST) {
- if (_saveScrollPos >= 8)
- _saveScrollPos -= 8;
- else
- _saveScrollPos = 0;
- } else if (scroll == BUTTON_SCROLL_UP_SLOW) {
- if (_saveScrollPos >= 1)
- _saveScrollPos--;
- } else if (scroll == BUTTON_SCROLL_DOWN_SLOW) {
- if (_saveScrollPos + 8 < maxScroll)
- _saveScrollPos++;
- } else if (scroll == BUTTON_SCROLL_DOWN_FAST) {
- if (_saveScrollPos + 16 < maxScroll)
- _saveScrollPos += 8;
- else {
- if (maxScroll >= 8)
- _saveScrollPos = maxScroll - 8;
- else
- _saveScrollPos = 0;
- }
- }
- _selectedSavegame = 255; // deselect savegame
- deselectSaveslots();
- showSavegameNames();
-}
-
-void Control::createButtons(const ButtonInfo *buttons, uint8 num) {
- for (uint8 cnt = 0; cnt < num; cnt++) {
- _buttons[cnt] = new ControlButton(buttons[cnt].x, buttons[cnt].y, buttons[cnt].resId, buttons[cnt].id, buttons[cnt].flag, _resMan, _screenBuf, _system);
- _buttons[cnt]->draw();
- }
- _numButtons = num;
-}
-
-void Control::destroyButtons() {
- for (uint8 cnt = 0; cnt < _numButtons; cnt++)
- delete _buttons[cnt];
- _numButtons = 0;
-}
-
-uint16 Control::getTextWidth(const uint8 *str) {
- uint16 width = 0;
- while (*str) {
- width += _resMan->getUint16(_resMan->fetchFrame(_font, *str - 32)->width) - 3;
- str++;
- }
- return width;
-}
-
-void Control::renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode) {
- uint8 *font = _font;
- if (mode & TEXT_RED_FONT) {
- mode &= ~TEXT_RED_FONT;
- font = _redFont;
- }
-
- if (mode == TEXT_RIGHT_ALIGN) // negative x coordinate means right-aligned.
- x -= getTextWidth(str);
- else if (mode == TEXT_CENTER)
- x -= getTextWidth(str) / 2;
-
- uint16 destX = x;
- while (*str) {
- uint8 *dst = _screenBuf + y * SCREEN_WIDTH + destX;
-
- FrameHeader *chSpr = _resMan->fetchFrame(font, *str - 32);
- uint8 *sprData = (uint8 *)chSpr + sizeof(FrameHeader);
- uint8 *HIFbuf = NULL;
-
- if (SwordEngine::isPsx()) { //Text fonts are compressed in psx version
- HIFbuf = (uint8 *)malloc(_resMan->getUint16(chSpr->height) * _resMan->getUint16(chSpr->width));
- memset(HIFbuf, 0, _resMan->getUint16(chSpr->height) * _resMan->getUint16(chSpr->width));
- Screen::decompressHIF(sprData, HIFbuf);
- sprData = HIFbuf;
- }
-
- for (uint16 cnty = 0; cnty < _resMan->getUint16(chSpr->height); cnty++) {
- for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++) {
- if (sprData[cntx])
- dst[cntx] = sprData[cntx];
- }
-
- if (SwordEngine::isPsx()) { //On PSX version we need to double horizontal lines
- dst += SCREEN_WIDTH;
- for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++)
- if (sprData[cntx])
- dst[cntx] = sprData[cntx];
- }
-
- sprData += _resMan->getUint16(chSpr->width);
- dst += SCREEN_WIDTH;
- }
- destX += _resMan->getUint16(chSpr->width) - 3;
- str++;
-
- free(HIFbuf);
- }
-
- _system->copyRectToScreen(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
-}
-
-void Control::renderVolumeBar(uint8 id, uint8 volL, uint8 volR) {
- uint16 destX = _volumeButtons[id].x + 20;
- uint16 destY = _volumeButtons[id].y + 116;
-
- for (uint8 chCnt = 0; chCnt < 2; chCnt++) {
- uint8 vol = (chCnt == 0) ? volL : volR;
- FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4);
- uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX;
- uint8 *srcMem = (uint8 *)frHead + sizeof(FrameHeader);
- uint16 barHeight = _resMan->getUint16(frHead->height);
- uint8 *psxVolBuf = NULL;
-
- if (SwordEngine::isPsx()) {
- psxVolBuf = (uint8 *)malloc(_resMan->getUint16(frHead->height) / 2 * _resMan->getUint16(frHead->width));
- memset(psxVolBuf, 0, _resMan->getUint16(frHead->height) / 2 * _resMan->getUint16(frHead->width));
- Screen::decompressHIF(srcMem, psxVolBuf);
- srcMem = psxVolBuf;
- barHeight /= 2;
- }
-
- for (uint16 cnty = 0; cnty < barHeight; cnty++) {
- memcpy(destMem, srcMem, _resMan->getUint16(frHead->width));
-
- if (SwordEngine::isPsx()) { //linedoubling
- destMem += SCREEN_WIDTH;
- memcpy(destMem, srcMem, _resMan->getUint16(frHead->width));
- }
-
- srcMem += _resMan->getUint16(frHead->width);
- destMem += SCREEN_WIDTH;
- }
-
- _system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, _resMan->getUint16(frHead->width), _resMan->getUint16(frHead->height));
- _resMan->resClose(SR_VLIGHT);
- destX += 32;
-
- free(psxVolBuf);
- }
-}
-
void Control::saveGameToFile(uint8 slot) {
char fName[15];
uint16 cnt;
@@ -1183,7 +2923,7 @@ void Control::saveGameToFile(uint8 slot) {
}
outf->writeUint32LE(SAVEGAME_HEADER);
- outf->write(_saveNames[slot].c_str(), 40);
+ outf->write(_fileDescriptions[slot], 40);
outf->writeByte(SAVEGAME_VERSION);
// Saving can occur either delayed from the GMM (in which case the panel is now shown and we can make
@@ -1410,97 +3150,6 @@ void Control::doRestore() {
Logic::_scriptVars[PLAYINGDEMO] = 1;
}
-void Control::delay(uint32 msecs) {
- Common::Event event;
-
- uint32 now = _system->getMillis();
- uint32 endTime = now + msecs;
- _keyPressed.reset();
- _mouseState = 0;
-
- do {
- Common::EventManager *eventMan = _system->getEventManager();
- while (eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- _keyPressed = event.kbd;
- // we skip the rest of the delay and return immediately
- // to handle keyboard input
- return;
- case Common::EVENT_MOUSEMOVE:
- _mouseCoord = event.mouse;
- break;
- case Common::EVENT_LBUTTONDOWN:
- _mouseDown = true;
- _mouseState |= BS1L_BUTTON_DOWN;
- _mouseCoord = event.mouse;
- break;
- case Common::EVENT_LBUTTONUP:
- _mouseDown = false;
- _mouseState |= BS1L_BUTTON_UP;
- _mouseCoord = event.mouse;
- break;
- case Common::EVENT_WHEELUP:
- _mouseDown = false;
- _mouseState |= BS1_WHEEL_UP;
- _mouseCoord = event.mouse;
- break;
- case Common::EVENT_WHEELDOWN:
- _mouseDown = false;
- _mouseState |= BS1_WHEEL_DOWN;
- break;
- default:
- break;
- }
- }
-
- _system->updateScreen();
- _system->delayMillis(10);
- } while (_system->getMillis() < endTime);
-}
-
-const ButtonInfo Control::_deathButtons[3] = {
- {250, 224 + 40, SR_BUTTON, BUTTON_RESTORE_PANEL, 0 },
- {250, 260 + 40, SR_BUTTON, BUTTON_RESTART, kButtonOk },
- {250, 296 + 40, SR_BUTTON, BUTTON_QUIT, kButtonCancel }
-};
-
-const ButtonInfo Control::_panelButtons[7] = {
- {145, 188 + 40, SR_BUTTON, BUTTON_SAVE_PANEL, 0 },
- {145, 224 + 40, SR_BUTTON, BUTTON_RESTORE_PANEL, 0 },
- {145, 260 + 40, SR_BUTTON, BUTTON_RESTART, 0 },
- {145, 296 + 40, SR_BUTTON, BUTTON_QUIT, kButtonCancel },
- {475, 188 + 40, SR_BUTTON, BUTTON_VOLUME_PANEL, 0 },
- {475, 224 + 40, SR_TEXT_BUTTON, BUTTON_TEXT, 0 },
- {475, 332 + 40, SR_BUTTON, BUTTON_DONE, kButtonOk }
-};
-
-const ButtonInfo Control::_saveButtons[16] = {
- {114, 32 + 40, SR_SLAB1, BUTTON_SAVE_SELECT1, 0 },
- {114, 68 + 40, SR_SLAB2, BUTTON_SAVE_SELECT2, 0 },
- {114, 104 + 40, SR_SLAB3, BUTTON_SAVE_SELECT3, 0 },
- {114, 140 + 40, SR_SLAB4, BUTTON_SAVE_SELECT4, 0 },
- {114, 176 + 40, SR_SLAB1, BUTTON_SAVE_SELECT5, 0 },
- {114, 212 + 40, SR_SLAB2, BUTTON_SAVE_SELECT6, 0 },
- {114, 248 + 40, SR_SLAB3, BUTTON_SAVE_SELECT7, 0 },
- {114, 284 + 40, SR_SLAB4, BUTTON_SAVE_SELECT8, 0 },
-
- {516, 25 + 40, SR_BUTUF, BUTTON_SCROLL_UP_FAST, 0 },
- {516, 45 + 40, SR_BUTUS, BUTTON_SCROLL_UP_SLOW, 0 },
- {516, 289 + 40, SR_BUTDS, BUTTON_SCROLL_DOWN_SLOW, 0 },
- {516, 310 + 40, SR_BUTDF, BUTTON_SCROLL_DOWN_FAST, 0 },
-
- {125, 338 + 40, SR_BUTTON, BUTTON_SAVE_RESTORE_OKAY, kButtonOk},
- {462, 338 + 40, SR_BUTTON, BUTTON_SAVE_CANCEL, kButtonCancel }
-};
-
-const ButtonInfo Control::_volumeButtons[4] = {
- { 478, 338 + 40, SR_BUTTON, BUTTON_MAIN_PANEL, kButtonOk },
- { 138, 135, SR_VKNOB, 0, 0 },
- { 273, 135, SR_VKNOB, 0, 0 },
- { 404, 135, SR_VKNOB, 0, 0 },
-};
-
bool Control::loadCustomStrings(const char *filename) {
Common::File f;
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index f4fde4ac26e..538f77e8d4b 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -35,6 +35,38 @@ class MemoryWriteStreamDynamic;
namespace Sword1 {
+enum SNRStatus {
+ SNR_BLANK = 0,
+ SNR_MAINPANEL,
+ SNR_SAVE,
+ SNR_RESTORE,
+ SNR_RESTART,
+ SNR_QUIT,
+ SNR_SPEED,
+ SNR_VOLUME,
+ SNR_SUBTITLES,
+ SNR_DONE,
+ SNR_DRIVEFULL = 99
+};
+
+enum SaveGameFlags {
+ SGF_DONE = 0,
+ SGF_SAVE,
+ SGF_RESTORE,
+ SGF_RESTART,
+ SGF_QUIT
+};
+
+enum PsxComponents {
+ PSX_PANEL = 0,
+ PSX_DEATHPANEL,
+ PSX_CONFIRM,
+ PSX_BUTTON,
+ PSX_TEXT,
+ PSX_SLAB,
+ PSX_SCROLL
+};
+
class SwordEngine;
class ObjectMan;
class ResMan;
@@ -47,106 +79,126 @@ class Logic;
#define SAVEGAME_HEADER MKTAG('B','S','_','1')
#define SAVEGAME_VERSION 2
-#define MAX_BUTTONS 16
+#define FIRSTFONTCHAR ' '
+#define LASTFONTCHAR (32 + 137)
+#define CR 13
+#define LF 10
+#define ESCAPE 27
+#define BACKSPACE 8
#define CONTROL_NOTHING_DONE 0
#define CONTROL_GAME_RESTORED 1
#define CONTROL_RESTART_GAME 2
-class ControlButton {
-public:
- ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, uint8 flag, ResMan *pResMan, uint8 *screenBuf, OSystem *system);
- ~ControlButton();
- void draw();
- bool wasClicked(uint16 mouseX, uint16 mouseY);
- void setSelected(uint8 selected);
- bool isSaveslot();
- uint8 _id;
- uint8 _flag;
-private:
- int _frameIdx;
- uint16 _x, _y;
- uint16 _width, _height;
- uint32 _resId;
- ResMan *_resMan;
- uint8 *_dstBuf;
- OSystem *_system;
-};
+#define VD1X 139
+#define VD2X 273
+#define VD3X 404
+#define VDY 94
-enum {
- kButtonOk = 1,
- kButtonCancel = 2
-};
+#define SCROLL1X 311
+#define SCROLL1Y 124
+#define SCROLL2X 311
+#define SCROLL2Y 188
+
+#define SAVEBUTTONS 14
+#define MAXSAVEGAMES 1000
+#define OVERLAP 3
+#define SP_OVERLAP 2
+#define TEXTBUTTONID 7
-struct ButtonInfo {
- uint16 x, y;
- uint32 resId, id;
- uint8 flag;
+struct Button {
+ int32 x1;
+ int32 y1;
+ int32 x2;
+ int32 y2;
};
class Control {
public:
Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic);
- uint8 runPanel();
+
+ void getPlayerOptions();
+ void askForCdMessage(uint32 needCD, bool incorrectCDPhase);
void doRestore();
- void askForCd();
bool savegamesExist();
- void readSavegameDescriptions();
void saveGameToFile(uint8 slot);
bool restoreGameFromFile(uint8 slot);
+ bool restoreGame();
void checkForOldSaveGames();
bool isPanelShown();
void setSaveDescription(int slot, const char *desc) {
- _saveNames[slot] = desc;
+ Common::strcpy_s(_fileDescriptions[slot], sizeof(_fileDescriptions[slot]), desc);
}
private:
- int displayMessage(const char *altButton, MSVC_PRINTF const char *message, ...) GCC_PRINTF(3, 4);
+ void saveRestoreScreen();
+
+ void renderSlab(int32 start, int32 i);
+ void renderSlabs();
+ void renderText(const uint8 *str, int32 x, int32 y, bool useSpeechFont = false);
+ void renderRedText(const uint8 *str, int32 x, int32 y);
+ void renderTexts();
+ int32 getTextLength(const uint8 *str, bool useSpeechFont = false);
+
+ void putButton(int32 x, int32 y, int32 index);
+ void putSpriteButton(Sprite *spr, int32 x, int32 y, int32 index);
+ void putTextButton(int32 index);
+ int32 getCurrentButton(const Button b[]);
+
+ void initialiseConfirmation(const uint8 *title);
+ int32 implementConfirmation();
+ void removeConfirmation();
+
+ void setVolumes();
+ void volUp(int32 i, int32 j);
+ void volDown(int32 i, int32 j);
+ void renderVolumeLight(int32 i);
+ void renderVolumeDisc(int32 i, int32 j);
+ void initialiseVolume();
+ void implementVolume();
+ void removeVolume();
+
+ void renderScrolls();
+ void initialiseSpeed();
+ void implementSpeed();
+ void removeSpeed();
+
+ int16 readFileDescriptions();
+ void setEditDescription(int32 line);
+ bool driveSpaceAvailable();
+ bool attemptSave();
+ bool saveGame();
+ void editDescription();
+ void restoreSelected();
+ void uneditDescription();
+ void initialiseSave();
+ void implementSave();
+ void removeSave();
+
+ void initialiseRestore();
+ void implementRestore();
+ void removeRestore();
+
+ void initialiseControlPanel();
+ void implementControlPanel();
+ void removeControlPanel();
+
+ void initialiseResources();
+ void releaseResources();
+
+ uint8 *decompressPsxGfx(uint8 *src, FrameHeader *f);
+ void drawPsxComponent(int componentType, uint8 *src, uint8 *dst, FrameHeader *f);
bool convertSaveGame(uint8 slot, char *desc);
- void showSavegameNames();
- void deselectSaveslots();
- uint8 *_restoreBuf;
- uint8 _saveFiles;
- uint8 _numSaves;
- uint8 _saveScrollPos;
- uint8 _selectedSavegame;
- Common::StringArray _saveNames;
- Common::String _oldName;
- uint8 _cursorTick;
- bool _cursorVisible;
- bool _panelShown;
- Common::MemoryWriteStreamDynamic *_tempThumbnail;
- uint8 getClicks(uint8 mode, uint8 *retVal);
- uint8 handleButtonClick(uint8 id, uint8 mode, uint8 *retVal);
- void handleVolumeClicks();
- void changeVolume(uint8 id, uint8 action);
-
- void setupMainPanel();
- void setupSaveRestorePanel(bool saving);
- void setupVolumePanel();
- bool getConfirm(const uint8 *title);
-
- void saveNameScroll(uint8 scroll, bool saving);
- void saveNameSelect(uint8 id, bool saving);
- bool saveToFile();
- bool restoreFromFile();
- bool keyAccepted(uint16 ascii);
- void handleSaveKey(Common::KeyState kbd);
-
- void renderVolumeBar(uint8 id, uint8 volL, uint8 volR);
- uint16 getTextWidth(const uint8 *str);
- void renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode);
- uint8 _numButtons;
- uint8 _selectedButton;
- void createButtons(const ButtonInfo *buttons, uint8 num);
- void destroyButtons();
- ControlButton *_buttons[MAX_BUTTONS];
- static const ButtonInfo _deathButtons[3], _panelButtons[7], _saveButtons[16], _volumeButtons[4];
+ void delay(uint32 msecs);
+ bool loadCustomStrings(const char *filename);
+
+ int displayMessage(const char *altButton, MSVC_PRINTF const char *message, ...) GCC_PRINTF(3, 4);
+
+ Common::MemoryWriteStreamDynamic *_tempThumbnail;
static const uint8 _languageStrings[8 * 20][43];
- bool loadCustomStrings(const char* filename);
uint8 _customStrings[20][43];
const uint8(*_lStrings)[43];
SwordEngine *_vm;
@@ -159,13 +211,47 @@ private:
Sound *_sound;
Screen *_screen;
Logic *_logic;
- uint8 *_font, *_redFont;
uint8 *_screenBuf;
Common::KeyState _keyPressed;
- void delay(uint32 msecs);
+
Common::Point _mouseCoord;
uint16 _mouseState;
- bool _mouseDown;
+
+ int _oldSnrStatus = SNR_BLANK;
+ bool _newPal = false;
+ Sprite *_slabs[SAVEBUTTONS - 6];
+ int32 _scrollIndex[2] = { 0, 0 };
+ int32 _speedFlag = 0;
+
+ int32 _currentButton = 0;
+ int32 _buttonPressed = 0;
+ int32 _buttonHold = 0;
+ int32 _slabSelected = 0;
+ int32 _firstDescription = 0;
+ char _fileDescriptions[MAXSAVEGAMES][40];
+ int32 _editingDescription = 0;
+ int32 _gamesSaved = 0;
+ int32 _textCursor;
+ int32 _curCharCount;
+ char _oldString[40];
+ int32 _scroll = 0;
+ int32 _scrollCount = 0;
+
+ uint8 *_restoreBuf;
+ uint32 _selectedSavegame = 0;
+ uint8 _numButtons = 0;
+ uint8 _selectedButton = 0;
+ bool _panelShown = false;
+
+ static const Button panelButtons[8];
+ // We want the death screen buttons to have
+ // the same numbers as the panel buttons
+ static const Button deathButtons[8];
+ static const Button confirmButtons[2];
+ static const Button speedButtons[3];
+ static const Button saveButtons[SAVEBUTTONS];
+ static const Button restoreButtons[SAVEBUTTONS];
+ static const Button volumeButtons[25];
};
} // End of namespace Sword1
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index c7e7bf3ac5b..19ed23c4758 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -36,6 +36,7 @@
#include "sword1/music.h"
#include "sword1/swordres.h"
#include "sword1/animation.h"
+#include "sword1/control.h"
#include "sword1/debug.h"
@@ -947,8 +948,8 @@ int Logic::fnSetWholePalette(Object *cpt, int32 id, int32 spritePal, int32 d, in
}
int Logic::fnSetFadeTargetPalette(Object *cpt, int32 id, int32 spritePal, int32 d, int32 e, int32 f, int32 z, int32 x) {
- _screen->fnSetFadeTargetPalette(0, 184, spritePal, false);
- _screen->fnSetFadeTargetPalette(0, 1, 0, true);
+ _screen->fnSetFadeTargetPalette(0, 184, spritePal);
+ _screen->fnSetFadeTargetPalette(0, 1, 0, BORDER_BLACK);
return SCRIPT_CONT;
}
@@ -1653,7 +1654,7 @@ int Logic::fnCheckCD(Object *cpt, int32 id, int32 screen, int32 b, int32 c, int3
}
int Logic::fnRestartGame(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d, int32 z, int32 x) {
- SwordEngine::_systemVars.forceRestart = true;
+ SwordEngine::_systemVars.saveGameFlag = SGF_RESTART;
cpt->o_logic = LOGIC_quit;
return SCRIPT_STOP;
}
@@ -1669,6 +1670,8 @@ int Logic::fnQuitGame(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d,
}
int Logic::fnDeathScreen(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d, int32 z, int32 x) {
+ SwordEngine::_systemVars.saveGameFlag = SGF_SAVE;
+ SwordEngine::_systemVars.snrStatus = SNR_MAINPANEL;
if (_scriptVars[FINALE_OPTION_FLAG] == 4) // successful end of game!
SwordEngine::_systemVars.controlPanelMode = CP_THEEND;
diff --git a/engines/sword1/metaengine.cpp b/engines/sword1/metaengine.cpp
index 9e27a479c1f..464c6011b0b 100644
--- a/engines/sword1/metaengine.cpp
+++ b/engines/sword1/metaengine.cpp
@@ -182,7 +182,6 @@ SaveStateDescriptor SwordMetaEngine::querySaveMetaInfos(const char *target, int
namespace Sword1 {
Common::Error SwordEngine::loadGameState(int slot) {
- _systemVars.forceRestart = false;
_systemVars.controlPanelMode = CP_NORMAL;
_control->restoreGameFromFile(slot);
reinitialize();
diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp
index 690df258e00..96c36766791 100644
--- a/engines/sword1/resman.cpp
+++ b/engines/sword1/resman.cpp
@@ -25,6 +25,7 @@
#include "sword1/memman.h"
#include "sword1/resman.h"
+#include "sword1/sword1.h"
#include "sword1/swordres.h"
#include "gui/message.h"
@@ -187,6 +188,7 @@ void ResMan::flush() {
void *ResMan::fetchRes(uint32 id) {
MemHandle *memHandle = resHandle(id);
+
if (!memHandle) {
warning("fetchRes:: resource %d out of bounds", id);
return NULL;
@@ -247,6 +249,7 @@ void *ResMan::cptResOpen(uint32 id) {
void ResMan::resOpen(uint32 id) { // load resource ID into memory
MemHandle *memHandle = resHandle(id);
+
if (!memHandle)
return;
if (memHandle->cond == MEM_FREED) { // memory has been freed
@@ -496,6 +499,31 @@ void ResMan::openScriptResourceLittleEndian(uint32 id) {
}
}
+uint32 ResMan::getDeathFontId() {
+ // At some point in the releases (as evidenced by the disasms of all
+ // known executables, and by the source code in our possession), Revolution
+ // changed the resource offsets for some files. I have tried EVERYTHING to
+ // try and discern which file we are dealing with and spectacularly failed.
+ // The only choice which seems to work correctly is to check the file size,
+ // as the newer GENERAL.CLU file is bigger. Sorry.
+ if (SwordEngine::isPsx())
+ return SR_FONT;
+
+ Common::File fp;
+ if (fp.open(SwordEngine::isMac() ? "GENERAL.CLM" : "GENERAL.CLU")) {
+ fp.seek(0, SEEK_END);
+ int64 fileSize = fp.pos();
+
+ if (fileSize < 6295679) {
+ return SR_DEATHFONT;
+ } else {
+ return SR_DEATHFONT_ALT;
+ }
+ }
+
+ return 0;
+}
+
uint32 ResMan::_srIdList[29] = { // the file numbers differ for the control panel file IDs, so we need this array
OTHER_SR_FONT, // SR_FONT
@@ -526,7 +554,7 @@ uint32 ResMan::_srIdList[29] = { // the file numbers differ for the control pane
0x04050017, // SR_BUTDS
0x04050018, // SR_BUTDF
0x04050019, // SR_DEATHPANEL
- 0,
+ SR_DEATHFONT,
};
} // End of namespace Sword1
diff --git a/engines/sword1/resman.h b/engines/sword1/resman.h
index 9ca89bcf6b3..1d539c59dbc 100644
--- a/engines/sword1/resman.h
+++ b/engines/sword1/resman.h
@@ -103,6 +103,7 @@ public:
return (_isBigEndian) ? TO_BE_32(value) : TO_LE_32(value);
}
+ uint32 getDeathFontId();
private:
uint32 resLength(uint32 id);
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 4e2e8ee22d5..f3b15c7ca7a 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -198,11 +198,11 @@ void Screen::fnSetPalette(uint8 start, uint16 length, uint32 id) {
_system->getPaletteManager()->setPalette(_targetPalette + 3 * start, start, length);
}
-void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack) {
+void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, int singleColor) {
const uint8 *rgbData = nullptr;
- if (toBlack) {
- rgbData = _black;
+ if (singleColor != -1) {
+ rgbData = singleColor == TEXT_WHITE ? _white : _black;
} else {
rgbData = (const uint8 *) _resMan->openFetchRes(id);
}
@@ -215,7 +215,7 @@ void Screen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool
memcpy(_currentPalette + (start * 3), rgbData, length * 3);
}
- if (!toBlack) {
+ if (singleColor == -1) {
_resMan->resClose(id);
}
}
@@ -309,10 +309,10 @@ void Screen::updateScreen() {
if (_updatePalette) {
fnSetFadeTargetPalette(0, 184, _roomDefTable[_currentScreen].palettes[0]);
fnSetFadeTargetPalette(184, 72, _roomDefTable[_currentScreen].palettes[1]);
- fnSetFadeTargetPalette(0, 1, 0, true);
+ fnSetFadeTargetPalette(0, 1, 0, BORDER_BLACK);
// Bug #8636: Force color 255 to black
if (SwordEngine::isMac())
- fnSetFadeTargetPalette(255, 1, 0, true);
+ fnSetFadeTargetPalette(255, 1, 0, BORDER_BLACK);
startFadePaletteUp(1);
_updatePalette = false;
@@ -538,22 +538,24 @@ void Screen::draw() {
for (cnt = 0; cnt < _sortLength; cnt++)
processImage(_sortList[cnt].id);
- if ((_currentScreen != 54) && _parallax[0])
- renderParallax(_parallax[0]); // screens other than 54 have FOREGROUND parallax layer in parallax[0]
- if (_parallax[1])
- renderParallax(_parallax[1]);
-
- // PSX version has parallax layer for this room in an external file (TRAIN.PLX)
- if (SwordEngine::isPsx() && _currentScreen == 63) {
- // FIXME: this should be handled in a cleaner way...
- if (!_psxCache.extPlxCache) {
- Common::File parallax;
- parallax.open("TRAIN.PLX");
- _psxCache.extPlxCache = (uint8 *)malloc(parallax.size());
- parallax.read(_psxCache.extPlxCache, parallax.size());
- parallax.close();
+ if (SwordEngine::_systemVars.parallaxOn) {
+ if ((_currentScreen != 54) && _parallax[0])
+ renderParallax(_parallax[0]); // screens other than 54 have FOREGROUND parallax layer in parallax[0]
+ if (_parallax[1])
+ renderParallax(_parallax[1]);
+
+ // PSX version has parallax layer for this room in an external file (TRAIN.PLX)
+ if (SwordEngine::isPsx() && _currentScreen == 63) {
+ // FIXME: this should be handled in a cleaner way...
+ if (!_psxCache.extPlxCache) {
+ Common::File parallax;
+ parallax.open("TRAIN.PLX");
+ _psxCache.extPlxCache = (uint8 *)malloc(parallax.size());
+ parallax.read(_psxCache.extPlxCache, parallax.size());
+ parallax.close();
+ }
+ renderParallax(_psxCache.extPlxCache);
}
- renderParallax(_psxCache.extPlxCache);
}
for (cnt = 0; cnt < _foreLength; cnt++)
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index ab2fb152a58..19a27fc58cc 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -63,6 +63,7 @@ struct PSXDataCache { // Cache for PSX screen, to avoid decompressing background
#define BORDER_GREEN 3
#define BORDER_PURPLE 4
#define BORDER_BLACK 5
+#define TEXT_WHITE 6
class ResMan;
class ObjectMan;
@@ -88,7 +89,7 @@ public:
void startFadePaletteUp(int speed);
void fadePalette();
void fnSetPalette(uint8 start, uint16 length, uint32 id);
- void fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, bool toBlack = false);
+ void fnSetFadeTargetPalette(uint8 start, uint16 length, uint32 id, int singleColor = -1);
int16 stillFading();
void fullRefresh(bool soft = false);
@@ -102,15 +103,17 @@ public:
static void decompressHIF(uint8 *src, uint8 *dest);
private:
- // The original values are 6-bit RGB numbers, so they have to be shifted
- const uint8 _white[3] = { 63 << 2, 63 << 2, 63 << 2};
- const uint8 _red[3] = { 63 << 2, 0 << 2, 0 << 2};
- const uint8 _blue[3] = { 0 << 2, 0 << 2, 63 << 2};
- const uint8 _yellow[3] = { 63 << 2, 63 << 2, 0 << 2};
- const uint8 _green[3] = { 0 << 2, 63 << 2, 0 << 2};
- const uint8 _purple[3] = { 32 << 2, 0 << 2, 32 << 2};
- const uint8 _black[3] = { 0 << 2, 0 << 2, 0 << 2};
- //const uint8 _grey[3] = { 32 << 2, 32 << 2, 32 << 2};
+ // The original values are 6-bit RGB numbers, so they have to be shifted,
+ // except for white, which for some reason has to stay unshifted in order
+ // to work correctly.
+ const uint8 _white[3] = { 63, 63, 63 };
+ const uint8 _red[3] = { 63 << 2, 0 << 2, 0 << 2 };
+ const uint8 _blue[3] = { 0 << 2, 0 << 2, 63 << 2 };
+ const uint8 _yellow[3] = { 63 << 2, 63 << 2, 0 << 2 };
+ const uint8 _green[3] = { 0 << 2, 63 << 2, 0 << 2 };
+ const uint8 _purple[3] = { 32 << 2, 0 << 2, 32 << 2 };
+ const uint8 _black[3] = { 0 << 2, 0 << 2, 0 << 2 };
+ //const uint8 _grey[3] = { 32 << 2, 32 << 2, 32 << 2 };
struct PaletteFadeInfo {
int16 paletteStatus;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 60b62242b73..4edc687ac05 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -112,13 +112,15 @@ Common::Error SwordEngine::init() {
_systemVars.justRestoredGame = 0;
_systemVars.currentCD = 0;
_systemVars.controlPanelMode = CP_NEWGAME;
- _systemVars.forceRestart = false;
+ _systemVars.saveGameFlag = SGF_DONE;
+ _systemVars.snrStatus = SNR_BLANK;
_systemVars.wantFade = true;
_systemVars.realLanguage = Common::parseLanguage(ConfMan.get("language"));
_systemVars.isLangRtl = false;
_systemVars.debugMode = (gDebugLevel >= 0);
_systemVars.slowMode = false;
_systemVars.fastMode = false;
+ _systemVars.parallaxOn = true;
switch (_systemVars.realLanguage) {
case Common::DE_DEU:
@@ -250,67 +252,57 @@ void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
}
}
-uint8 SwordEngine::checkKeys() {
- uint8 retCode = 0;
- if (_systemVars.forceRestart) {
- retCode = CONTROL_RESTART_GAME;
- } else {
+void SwordEngine::checkKeys() {
+ switch (_keyPressed.keycode) {
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_ESCAPE:
+ if ((Logic::_scriptVars[MOUSE_STATUS] & 1) && (Logic::_scriptVars[GEORGE_HOLDING_PIECE] == 0)) {
+ _systemVars.saveGameFlag = SGF_SAVE;
+ _systemVars.snrStatus = SNR_MAINPANEL;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ // Debug keys!
+ if (!_systemVars.isDemo && _systemVars.debugMode) {
switch (_keyPressed.keycode) {
- case Common::KEYCODE_F5:
- case Common::KEYCODE_ESCAPE:
- if ((Logic::_scriptVars[MOUSE_STATUS] & 1) && (Logic::_scriptVars[GEORGE_HOLDING_PIECE] == 0)) {
- retCode = _control->runPanel();
- if (retCode == CONTROL_NOTHING_DONE) {
- _screen->fullRefresh(true);
- Logic::_scriptVars[NEW_PALETTE] = 1;
+ case Common::KEYCODE_1: // Slow mode
+ {
+ if (_systemVars.slowMode) {
+ _systemVars.slowMode = false;
+ _targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
+ } else {
+ _systemVars.slowMode = true;
+ _targetFrameTime = SLOW_FRAME_TIME; // 2Hz
}
+ _systemVars.fastMode = false; // For good measure...
+
+ _rate = _targetFrameTime / 10;
}
break;
- default:
- break;
- }
-
- // Debug keys!
- if (!_systemVars.isDemo && _systemVars.debugMode) {
- switch (_keyPressed.keycode) {
- case Common::KEYCODE_1: // Slow mode
- {
- if (_systemVars.slowMode) {
- _systemVars.slowMode = false;
- _targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
- } else {
- _systemVars.slowMode = true;
- _targetFrameTime = SLOW_FRAME_TIME; // 2Hz
- }
-
- _systemVars.fastMode = false; // For good measure...
-
- _rate = _targetFrameTime / 10;
+ case Common::KEYCODE_4: // Fast mode
+ {
+ if (_systemVars.fastMode) {
+ _systemVars.fastMode = false;
+ _targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
+ } else {
+ _systemVars.fastMode = true;
+ _targetFrameTime = FAST_FRAME_TIME; // 100Hz
}
- break;
- case Common::KEYCODE_4: // Fast mode
- {
- if (_systemVars.fastMode) {
- _systemVars.fastMode = false;
- _targetFrameTime = DEFAULT_FRAME_TIME; // 12.5Hz
- } else {
- _systemVars.fastMode = true;
- _targetFrameTime = FAST_FRAME_TIME; // 100Hz
- }
-
- _systemVars.slowMode = false; // For good measure...
-
- _rate = _targetFrameTime / 10;
- }
- break;
- default:
- break;
+
+ _systemVars.slowMode = false; // For good measure...
+
+ _rate = _targetFrameTime / 10;
}
+ break;
+ default:
+ break;
}
}
-
- return retCode;
}
static const char *const errorMsgs[] = {
@@ -647,8 +639,9 @@ Common::Error SwordEngine::go() {
_screen->initFadePaletteServer();
installTimerRoutines();
+ bool startedFromGMM = false;
uint16 startPos = ConfMan.getInt("boot_param");
- _control->readSavegameDescriptions();
+
if (startPos) {
_logic->startPositions(startPos);
} else {
@@ -657,31 +650,41 @@ Common::Error SwordEngine::go() {
// but their filenames are numbered starting from 0.
if (saveSlot >= 0 && _control->savegamesExist() && _control->restoreGameFromFile(saveSlot)) {
_control->doRestore();
+ startedFromGMM = true;
+ _systemVars.controlPanelMode = CP_NORMAL;
} else if (_control->savegamesExist()) {
+ _systemVars.snrStatus = SNR_MAINPANEL;
_systemVars.controlPanelMode = CP_NEWGAME;
- if (_control->runPanel() == CONTROL_GAME_RESTORED)
- _control->doRestore();
- else if (!shouldQuit())
- _logic->startPositions(0);
- } else {
- // no savegames, start new game.
- _logic->startPositions(0);
+ _control->getPlayerOptions();
+
+ // If player clicked on "Start" (Restart)
+ // just ignore it - so game can start from 'startPos'
+ // (which will be '0' for normal game anyway)
+ if (_systemVars.saveGameFlag == SGF_RESTART)
+ _systemVars.saveGameFlag = SGF_DONE;
}
}
- _systemVars.controlPanelMode = CP_NORMAL;
while (!shouldQuit()) {
- uint8 action = mainLoop();
+ if (_systemVars.saveGameFlag == SGF_RESTORE) {
+ debug(1, "SwordEngine::go(): Restoring game");
+ if (!_control->restoreGame())
+ warning("SwordEngine::go(): Couldn't restore game");
+
+ } else if (_systemVars.saveGameFlag == SGF_RESTART) {
+ debug(1, "SwordEngine::go(): Restarting game");
+ startPos = 0;
+ _logic->startPositions(startPos);
+ } else if (!startedFromGMM) { // START GAME
+ _logic->startPositions(startPos);
+ startPos = 0;
+ }
+
+ mainLoop();
if (!shouldQuit()) {
// the mainloop was left, we have to reinitialize.
reinitialize();
- if (action == CONTROL_GAME_RESTORED)
- _control->doRestore();
- else if (action == CONTROL_RESTART_GAME)
- _logic->startPositions(1);
- _systemVars.forceRestart = false;
- _systemVars.controlPanelMode = CP_NORMAL;
}
}
@@ -696,13 +699,13 @@ void SwordEngine::checkCd() {
if (needCd == 0) { // needCd == 0 means we can use either CD1 or CD2.
if (_systemVars.currentCD == 0) {
_systemVars.currentCD = 1; // if there is no CD currently inserted, ask for CD1.
- _control->askForCd();
+ askForCd();
} // else: there is already a cd inserted and we don't care if it's cd1 or cd2.
} else if (needCd != _systemVars.currentCD) { // we need a different CD than the one in drive.
_music->startMusic(0, 0); //
_sound->closeCowSystem(); // close music and sound files before changing CDs
_systemVars.currentCD = needCd; // askForCd will ask the player to insert _systemVars.currentCd,
- _control->askForCd(); // so it has to be updated before calling it.
+ askForCd(); // so it has to be updated before calling it.
}
} else { // we're running from HDD, we don't have to care about music files and Sound will take care of
if (needCd) // switching sound.clu files on Sound::newScreen by itself, so there's nothing to be done.
@@ -712,11 +715,78 @@ void SwordEngine::checkCd() {
}
}
+void SwordEngine::askForCd() {
+ char buf[255];
+
+ _control->askForCdMessage(SwordEngine::_systemVars.currentCD, false);
+
+ _screen->fnSetFadeTargetPalette(0, 1, 0, BORDER_BLACK); // Set colour 0 to black - for screen borders
+ _screen->fnSetFadeTargetPalette(193, 1, 0, TEXT_WHITE); // Set colours 193 to white - for letters
+
+ while (!shouldQuit()) {
+ _screen->startFadePaletteUp(1);
+
+ uint32 startTime = _system->getMillis();
+ while (_screen->stillFading()) {
+ if (_vblCount >= _rate)
+ _vblCount = 0;
+
+ pollInput(0);
+
+ // In the remote event that this wait cycle gets
+ // stuck during debugging, trigger a timeout
+ if (_system->getMillis() - startTime > 1000)
+ break;
+ }
+
+ while (_keyPressed.keycode == Common::KEYCODE_INVALID && !shouldQuit()) {
+ pollInput(0);
+ }
+
+ _screen->startFadePaletteDown(1);
+
+ startTime = _system->getMillis();
+ while (_screen->stillFading()) {
+ if (_vblCount >= _rate)
+ _vblCount = 0;
+
+ pollInput(0);
+
+ // In the remote event that this wait cycle gets
+ // stuck during debugging, trigger a timeout
+ if (_system->getMillis() - startTime > 1000)
+ break;
+ }
+
+ startTime = _system->getMillis();
+ while (_system->getMillis() - startTime < 500) {
+ pollInput(0);
+ };
+
+ _keyPressed.reset();
+
+ // At this point the original code sets colors 1 to 180 to grey;
+ // the only visible effect of this is that the screen flashes when
+ // loading a save state. It's not clear what the original wanted to do.
+ // for (int i = 1; i < 180; i++) {
+ // SetPalette(i, 1, _grey);
+ // }
+
+ Common::sprintf_s(buf, "cd%d.id", SwordEngine::_systemVars.currentCD);
+ if (Common::File::exists(buf))
+ break;
+
+ _control->askForCdMessage(SwordEngine::_systemVars.currentCD, true);
+ }
+}
+
uint8 SwordEngine::mainLoop() {
- uint8 retCode = 0;
_keyPressed.reset();
- while ((retCode == 0) && (!shouldQuit())) {
+ do {
+ if (shouldQuit())
+ break;
+
// do we need the section45-hack from sword.c here?
checkCd();
@@ -731,6 +801,8 @@ uint8 SwordEngine::mainLoop() {
bool scrollFrameShown = false;
+ _systemVars.saveGameFlag = SGF_DONE;
+
_logic->engine();
_logic->updateScreenParams(); // sets scrolling
@@ -756,14 +828,21 @@ uint8 SwordEngine::mainLoop() {
_mouse->engine(_mouseCoord.x, _mouseCoord.y, _mouseState);
- retCode = checkKeys();
+ checkKeys();
+
+ if (_systemVars.saveGameFlag == SGF_SAVE) {
+ _control->getPlayerOptions();
+ debug(1, "SwordEngine::mainLoop(): Returned to mainloop() from getPlayerOptions()");
+ }
_mouseState = 0;
_keyPressed.reset();
- } while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) && (retCode == 0) && (!shouldQuit()));
+ } while ((Logic::_scriptVars[SCREEN] == Logic::_scriptVars[NEW_SCREEN]) &&
+ (_systemVars.saveGameFlag == SGF_DONE || _systemVars.saveGameFlag == SGF_SAVE) &&
+ (!shouldQuit()));
- if ((retCode == 0) && (Logic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade && (!shouldQuit())) {
+ if ((Logic::_scriptVars[SCREEN] != 53) && !shouldQuit()) {
_screen->startFadePaletteDown(1);
}
@@ -773,8 +852,9 @@ uint8 SwordEngine::mainLoop() {
_sound->quitScreen(); // Purge the sound AFTER they've been faded
_objectMan->closeSection(Logic::_scriptVars[SCREEN]); // Close the section that PLAYER has just left, if it's empty now
- }
- return retCode;
+ } while ((_systemVars.saveGameFlag < SGF_RESTORE) && (!shouldQuit()));
+
+ return 0;
}
void SwordEngine::waitForFade() {
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index e4a95b87c91..40017f8a72f 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -65,7 +65,8 @@ struct SystemVars {
uint32 currentCD; // starts at zero, then either 1 or 2 depending on section being played
uint32 justRestoredGame; // see main() in sword.c & New_screen() in gtm_core.c
uint8 controlPanelMode; // 1 death screen version of the control panel, 2 = successful end of game, 3 = force restart
- bool forceRestart;
+ uint8 saveGameFlag;
+ int snrStatus;
bool wantFade; // when true => fade during scene change, else cut.
bool playSpeech;
bool showText;
@@ -78,11 +79,13 @@ struct SystemVars {
bool debugMode;
bool slowMode;
bool fastMode;
+ bool parallaxOn;
};
class SwordEngine : public Engine {
friend class SwordConsole;
friend class Screen;
+ friend class Control;
public:
SwordEngine(OSystem *syst, const ADGameDescription *gameDesc);
@@ -135,10 +138,12 @@ protected:
}
private:
void pollInput(uint32 delay);
- uint8 checkKeys();
+ void checkKeys();
void checkCdFiles();
void checkCd();
+ void askForCd();
+
void showFileErrorMsg(uint8 type, bool *fileExists);
void flagsToBool(bool *dest, uint8 flags);
diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h
index ecafdb9f4fa..52cba1c6440 100644
--- a/engines/sword1/sworddefs.h
+++ b/engines/sword1/sworddefs.h
@@ -26,8 +26,7 @@
namespace Sword1 {
-#define LOOPED 1
-
+#define LOOPED 1
#define DEFAULT_FRAME_TIME 80 // 80ms, for exactly 12.5Hz
#define FAST_FRAME_TIME 10 // 10ms, for 100Hz
#define SLOW_FRAME_TIME 500 // 500ms, for 2Hz
@@ -38,6 +37,7 @@ namespace Sword1 {
#define PALETTE_FADE_USEC 16667
#define SCREEN_WIDTH 640
#define SCREEN_DEPTH 400
+#define SCREEN_FULL_DEPTH 480 // Including top and bottom 40+40 px spaces for menu bars
#define SCREEN_LEFT_EDGE 128
#define SCREEN_RIGHT_EDGE (128+SCREEN_WIDTH-1)
#define SCREEN_TOP_EDGE 128
@@ -138,6 +138,12 @@ struct WalkGridHeader {
int32 numNodes;
} PACKED_STRUCT;
+struct Sprite {
+ Header header;
+ int32 totalSprites;
+ uint32 spriteOffset[2];
+} PACKED_STRUCT;
+
#include "common/pack-end.h" // END STRUCT PACKING
enum fileTypes {
diff --git a/engines/sword1/swordres.h b/engines/sword1/swordres.h
index 53504e91021..eb2b4ab929c 100644
--- a/engines/sword1/swordres.h
+++ b/engines/sword1/swordres.h
@@ -765,7 +765,7 @@ namespace Sword1 {
#define GAME_FONT 0x04000000
#define OTHER_SR_FONT 0x04000001
#define OTHER_SR_REDFONT 0x04000002
-#define SR_DEATHFONT 0x04000003
+#define SR_DEATHFONT_ALT 0x04000003
#define CZECH_GAME_FONT 0x04000004
#define CZECH_SR_FONT 0x04000005
#define CZECH_SR_REDFONT 0x04000006
@@ -1026,6 +1026,8 @@ namespace Sword1 {
#define SR_BUTDS 0x04050019
#define SR_BUTDF 0x0405001A
#define SR_DEATHPANEL 0x0405001B // 0x04050019
+#define SR_DEATHFONT 0x0405001C
+
// 26 entities in TXTs, 29 in datafiles.
// george
#define GEORGE_MEGA 0x04060000
Commit: 7fc2afce99b0a805e7bea67228915e6f60424416
https://github.com/scummvm/scummvm/commit/7fc2afce99b0a805e7bea67228915e6f60424416
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-21T21:41:22+02:00
Commit Message:
SWORD1: Change save slot names to byte[]
Quoting -sev: "Some chars on some platforms are signed"
Changed paths:
engines/sword1/control.cpp
engines/sword1/control.h
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 71baa6157da..bd33a6e8612 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -1498,7 +1498,7 @@ int16 Control::readFileDescriptions() {
slotNum = atoi(file->c_str() + file->size() - 3);
while (totalFiles < slotNum) {
- Common::strcpy_s(_fileDescriptions[totalFiles], 1, "");
+ Common::strcpy_s((char *)_fileDescriptions[totalFiles], 1, "");
totalFiles++;
}
@@ -1507,7 +1507,7 @@ int16 Control::readFileDescriptions() {
if (in) {
in->readUint32LE(); // header
in->read(saveName, 40);
- Common::strcpy_s(_fileDescriptions[totalFiles], sizeof(_fileDescriptions[totalFiles]), saveName);
+ Common::strcpy_s((char *)_fileDescriptions[totalFiles], sizeof(_fileDescriptions[totalFiles]), saveName);
delete in;
}
@@ -1516,7 +1516,7 @@ int16 Control::readFileDescriptions() {
}
for (int i = totalFiles; i < MAXSAVEGAMES; i++)
- Common::strcpy_s(_fileDescriptions[i], 1, "");
+ Common::strcpy_s((char *)_fileDescriptions[i], 1, "");
return totalFiles;
}
@@ -1528,7 +1528,7 @@ void Control::setEditDescription(int32 line) {
_textCursor = 0;
_curCharCount = 1;
- Common::strcpy_s(_oldString, sizeof(_oldString), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ Common::strcpy_s(_oldString, sizeof(_oldString), (const char *)_fileDescriptions[_editingDescription + _firstDescription - 1]);
_slabSelected = line;
}
@@ -1593,7 +1593,7 @@ void Control::editDescription() {
_keyPressed.reset();
index = _editingDescription + _firstDescription - 1;
- len = Common::strnlen(_fileDescriptions[index], sizeof(_fileDescriptions[index]));
+ len = Common::strnlen((char *)_fileDescriptions[index], sizeof(_fileDescriptions[index]));
if ((ch != CR) && (ch != ESCAPE)) {
if ((ch >= FIRSTFONTCHAR) && (ch <= LASTFONTCHAR)) {
if ((len < 32) && (getTextLength((const uint8 *)_fileDescriptions[index]) < 310)) {
@@ -1615,7 +1615,7 @@ void Control::editDescription() {
if ((ch == ESCAPE) || ((ch == CR) && (len == 0))) {
_textCursor = 1;
_curCharCount = 10;
- Common::strcpy_s(_fileDescriptions[index], sizeof(_fileDescriptions[index]), _oldString);
+ Common::strcpy_s((char *)_fileDescriptions[index], sizeof(_fileDescriptions[index]), _oldString);
uneditDescription();
} else {
if (!attemptSave())
@@ -1630,13 +1630,13 @@ void Control::editDescription() {
_textCursor ^= 1;
if (_textCursor) {
// Add cursor to line
- Common::strcpy_s(string, sizeof(string), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ Common::strcpy_s(string, sizeof(string), (const char *)_fileDescriptions[_editingDescription + _firstDescription - 1]);
len = strlen(string);
string[len] = '_';
string[len + 1] = '\0';
} else {
// Remove cursor from line
- Common::strcpy_s(string, sizeof(string), _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ Common::strcpy_s(string, sizeof(string), (const char *)_fileDescriptions[_editingDescription + _firstDescription - 1]);
}
renderSlab(_slabSelected - 1, _editingDescription - 1);
@@ -1678,7 +1678,7 @@ void Control::uneditDescription(void) {
}
bool Control::saveGame() {
- if (Common::strnlen(_fileDescriptions[_selectedSavegame], sizeof(_fileDescriptions[_selectedSavegame]) > 0)) {
+ if (Common::strnlen((char *)_fileDescriptions[_selectedSavegame], sizeof(_fileDescriptions[_selectedSavegame]) > 0)) {
saveGameToFile(_selectedSavegame);
return true;
}
@@ -1935,7 +1935,7 @@ void Control::implementSave() {
if (_editingDescription) {
if (_buttonPressed != _editingDescription) {
Common::strcpy_s(
- _fileDescriptions[_editingDescription + _firstDescription - 1],
+ (char *)_fileDescriptions[_editingDescription + _firstDescription - 1],
sizeof(_fileDescriptions[_editingDescription + _firstDescription - 1]),
_oldString);
_slabSelected = 0;
@@ -1979,7 +1979,7 @@ void Control::implementSave() {
break;
case (SAVEBUTTONS - 1):
putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
- if ((_editingDescription) && (strlen(_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
+ if ((_editingDescription) && (strlen((char *)_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
if (!attemptSave())
SwordEngine::_systemVars.snrStatus = SNR_DRIVEFULL;
}
@@ -2328,7 +2328,7 @@ void Control::implementRestore() {
}
} else {
if (_editingDescription) {
- if ((_buttonPressed != _editingDescription) && (strlen(_fileDescriptions[_buttonPressed + _firstDescription - 1]))) {
+ if ((_buttonPressed != _editingDescription) && (strlen((char *)_fileDescriptions[_buttonPressed + _firstDescription - 1]))) {
Common::strcpy_s(_fileDescriptions[_editingDescription + _firstDescription - 1], _oldString);
_slabSelected = 0;
uneditDescription();
@@ -2336,16 +2336,16 @@ void Control::implementRestore() {
setEditDescription(_buttonPressed);
renderSlab(_slabSelected - 1, _editingDescription - 1);
- Common::strcpy_s(string, _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ Common::strcpy_s(string, (char *)_fileDescriptions[_editingDescription + _firstDescription - 1]);
renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 42, saveButtons[_editingDescription - 1].y1 + 5);
Common::sprintf_s(string, "%d", _firstDescription + _editingDescription);
renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 12, saveButtons[_editingDescription - 1].y1 + 5);
}
} else {
- if (strlen(_fileDescriptions[_buttonPressed + _firstDescription - 1])) {
+ if (strlen((char *)_fileDescriptions[_buttonPressed + _firstDescription - 1])) {
setEditDescription(_buttonPressed);
renderSlab(_slabSelected - 1, _editingDescription - 1);
- Common::strcpy_s(string, _fileDescriptions[_editingDescription + _firstDescription - 1]);
+ Common::strcpy_s(string, (char *)_fileDescriptions[_editingDescription + _firstDescription - 1]);
renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 42, saveButtons[_editingDescription - 1].y1 + 5);
Common::sprintf_s(string, "%d", _firstDescription + _editingDescription);
renderRedText((const uint8 *)string, saveButtons[_editingDescription - 1].x1 + 12, saveButtons[_editingDescription - 1].y1 + 5);
@@ -2384,7 +2384,7 @@ void Control::implementRestore() {
break;
case (SAVEBUTTONS - 1):
putButton(saveButtons[SAVEBUTTONS - 2].x1, saveButtons[SAVEBUTTONS - 1].y1, 0);
- if ((_editingDescription) && (strlen(_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
+ if ((_editingDescription) && (strlen((char *)_fileDescriptions[_editingDescription + _firstDescription - 1]))) {
//Restore game here
_selectedSavegame = _firstDescription + _editingDescription - 1;
//Common::sprintf_s(saveFilename, "savegame.%.3d", _firstDescription + _editingDescription - 1);
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 538f77e8d4b..3cc8c75e0e0 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -128,7 +128,7 @@ public:
bool isPanelShown();
void setSaveDescription(int slot, const char *desc) {
- Common::strcpy_s(_fileDescriptions[slot], sizeof(_fileDescriptions[slot]), desc);
+ Common::strcpy_s((char *)_fileDescriptions[slot], sizeof(_fileDescriptions[slot]), desc);
}
private:
@@ -228,7 +228,7 @@ private:
int32 _buttonHold = 0;
int32 _slabSelected = 0;
int32 _firstDescription = 0;
- char _fileDescriptions[MAXSAVEGAMES][40];
+ byte _fileDescriptions[MAXSAVEGAMES][40];
int32 _editingDescription = 0;
int32 _gamesSaved = 0;
int32 _textCursor;
Commit: 214a8a3d49b6d82d68b33d5ca42cbf39895ff5f7
https://github.com/scummvm/scummvm/commit/214a8a3d49b6d82d68b33d5ca42cbf39895ff5f7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-21T21:41:22+02:00
Commit Message:
SWORD1: Add proper support for death font for russian versions
Changed paths:
engines/sword1/resman.cpp
diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp
index 96c36766791..242c4cffdaa 100644
--- a/engines/sword1/resman.cpp
+++ b/engines/sword1/resman.cpp
@@ -514,7 +514,21 @@ uint32 ResMan::getDeathFontId() {
fp.seek(0, SEEK_END);
int64 fileSize = fp.pos();
- if (fileSize < 6295679) {
+ if (SwordEngine::_systemVars.realLanguage == Common::RU_RUS) {
+ switch (fileSize) {
+ case 6081261: // Akella
+ return SR_DEATHFONT;
+ case 6354790: // Mediahauz
+ return SR_FONT;
+ case 6350630: // Novy Disk
+ return SR_DEATHFONT_ALT;
+ default:
+ warning("ResMan::getDeathFontId(): Unrecognized version of russian GENERAL.CLU, size %d", (int)fileSize);
+ break;
+ }
+
+ return SR_FONT;
+ } else if (fileSize < 6295679) {
return SR_DEATHFONT;
} else {
return SR_DEATHFONT_ALT;
Commit: e370442b5498e03f9a53f12752791da9ebcff495
https://github.com/scummvm/scummvm/commit/e370442b5498e03f9a53f12752791da9ebcff495
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-09-21T21:41:22+02:00
Commit Message:
SWORD1: Fix US/Localized versions crashing at startup after running UK/Demo
This bug has apparently been here since forever. We can't use the static
keyword on the _srIdList[] if it gets edited during the Demo or the UK version
and then never brought back the way it was before when either the US or
the localized versions are started up.
This is caused by those families of versions having different resource IDs
for the menu elements (and a different number of resources...).
Changed paths:
engines/sword1/resman.cpp
engines/sword1/resman.h
diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp
index 242c4cffdaa..1e4885bc7bc 100644
--- a/engines/sword1/resman.cpp
+++ b/engines/sword1/resman.cpp
@@ -538,37 +538,4 @@ uint32 ResMan::getDeathFontId() {
return 0;
}
-
-uint32 ResMan::_srIdList[29] = { // the file numbers differ for the control panel file IDs, so we need this array
- OTHER_SR_FONT, // SR_FONT
- 0x04050000, // SR_BUTTON
- OTHER_SR_REDFONT, // SR_REDFONT
- 0x04050001, // SR_PALETTE
- 0x04050002, // SR_PANEL_ENGLISH
- 0x04050003, // SR_PANEL_FRENCH
- 0x04050004, // SR_PANEL_GERMAN
- 0x04050005, // SR_PANEL_ITALIAN
- 0x04050006, // SR_PANEL_SPANISH
- 0x04050007, // SR_PANEL_AMERICAN
- 0x04050008, // SR_TEXT_BUTTON
- 0x04050009, // SR_SPEED
- 0x0405000A, // SR_SCROLL1
- 0x0405000B, // SR_SCROLL2
- 0x0405000C, // SR_CONFIRM
- 0x0405000D, // SR_VOLUME
- 0x0405000E, // SR_VLIGHT
- 0x0405000F, // SR_VKNOB
- 0x04050010, // SR_WINDOW
- 0x04050011, // SR_SLAB1
- 0x04050012, // SR_SLAB2
- 0x04050013, // SR_SLAB3
- 0x04050014, // SR_SLAB4
- 0x04050015, // SR_BUTUF
- 0x04050016, // SR_BUTUS
- 0x04050017, // SR_BUTDS
- 0x04050018, // SR_BUTDF
- 0x04050019, // SR_DEATHPANEL
- SR_DEATHFONT,
-};
-
} // End of namespace Sword1
diff --git a/engines/sword1/resman.h b/engines/sword1/resman.h
index 1d539c59dbc..bc0e8594bfe 100644
--- a/engines/sword1/resman.h
+++ b/engines/sword1/resman.h
@@ -23,6 +23,7 @@
#define SWORD1_RESMAN_H
#include "sword1/memman.h"
+#include "sword1/swordres.h"
#include "common/file.h"
#include "sword1/sworddefs.h"
#include "common/endian.h"
@@ -121,10 +122,42 @@ private:
Prj _prj;
MemMan *_memMan;
static const uint32 _scriptList[TOTAL_SECTIONS]; //a table of resource tags
- static uint32 _srIdList[29];
Clu *_openCluStart, *_openCluEnd;
int _openClus;
bool _isBigEndian;
+
+ uint32 _srIdList[29] = {
+ // the file numbers differ for the control panel file IDs, so we need this array
+ OTHER_SR_FONT, // SR_FONT
+ 0x04050000, // SR_BUTTON
+ OTHER_SR_REDFONT, // SR_REDFONT
+ 0x04050001, // SR_PALETTE
+ 0x04050002, // SR_PANEL_ENGLISH
+ 0x04050003, // SR_PANEL_FRENCH
+ 0x04050004, // SR_PANEL_GERMAN
+ 0x04050005, // SR_PANEL_ITALIAN
+ 0x04050006, // SR_PANEL_SPANISH
+ 0x04050007, // SR_PANEL_AMERICAN
+ 0x04050008, // SR_TEXT_BUTTON
+ 0x04050009, // SR_SPEED
+ 0x0405000A, // SR_SCROLL1
+ 0x0405000B, // SR_SCROLL2
+ 0x0405000C, // SR_CONFIRM
+ 0x0405000D, // SR_VOLUME
+ 0x0405000E, // SR_VLIGHT
+ 0x0405000F, // SR_VKNOB
+ 0x04050010, // SR_WINDOW
+ 0x04050011, // SR_SLAB1
+ 0x04050012, // SR_SLAB2
+ 0x04050013, // SR_SLAB3
+ 0x04050014, // SR_SLAB4
+ 0x04050015, // SR_BUTUF
+ 0x04050016, // SR_BUTUS
+ 0x04050017, // SR_BUTDS
+ 0x04050018, // SR_BUTDF
+ 0x04050019, // SR_DEATHPANEL
+ SR_DEATHFONT,
+ };
};
} // End of namespace Sword1
More information about the Scummvm-git-logs
mailing list