Initial commit
This commit is contained in:
756
engines/kyra/gui/debugger.cpp
Normal file
756
engines/kyra/gui/debugger.cpp
Normal file
@@ -0,0 +1,756 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/gui/debugger.h"
|
||||
#include "kyra/engine/kyra_lok.h"
|
||||
#include "kyra/engine/kyra_hof.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/engine/lol.h"
|
||||
#include "kyra/engine/eobcommon.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
Debugger::Debugger(KyraEngine_v1 *vm)
|
||||
: ::GUI::Debugger(), _vm(vm) {
|
||||
}
|
||||
|
||||
void Debugger::initialize() {
|
||||
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
|
||||
registerCmd("screen_debug_mode", WRAP_METHOD(Debugger, cmdSetScreenDebug));
|
||||
registerCmd("load_palette", WRAP_METHOD(Debugger, cmdLoadPalette));
|
||||
registerCmd("facings", WRAP_METHOD(Debugger, cmdShowFacings));
|
||||
registerCmd("gamespeed", WRAP_METHOD(Debugger, cmdGameSpeed));
|
||||
registerCmd("flags", WRAP_METHOD(Debugger, cmdListFlags));
|
||||
registerCmd("toggleflag", WRAP_METHOD(Debugger, cmdToggleFlag));
|
||||
registerCmd("queryflag", WRAP_METHOD(Debugger, cmdQueryFlag));
|
||||
registerCmd("timers", WRAP_METHOD(Debugger, cmdListTimers));
|
||||
registerCmd("settimercountdown", WRAP_METHOD(Debugger, cmdSetTimerCountdown));
|
||||
}
|
||||
|
||||
bool Debugger::cmdSetScreenDebug(int argc, const char **argv) {
|
||||
if (argc > 1) {
|
||||
if (scumm_stricmp(argv[1], "enable") == 0)
|
||||
_vm->screen()->enableScreenDebug(true);
|
||||
else if (scumm_stricmp(argv[1], "disable") == 0)
|
||||
_vm->screen()->enableScreenDebug(false);
|
||||
else
|
||||
debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
|
||||
} else {
|
||||
debugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled"));
|
||||
debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdLoadPalette(int argc, const char **argv) {
|
||||
Palette palette(_vm->screen()->getPalette(0).getNumColors());
|
||||
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Use load_palette <file> [start_col] [end_col]\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) {
|
||||
uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)];
|
||||
if (!buffer) {
|
||||
debugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer);
|
||||
_vm->screen()->loadBitmap(argv[1], 5, 5, nullptr);
|
||||
palette.copy(_vm->screen()->getCPagePtr(5), 0, 256);
|
||||
_vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer);
|
||||
|
||||
delete[] buffer;
|
||||
} else if (!_vm->screen()->loadPalette(argv[1], palette)) {
|
||||
debugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int startCol = 0;
|
||||
int endCol = palette.getNumColors();
|
||||
if (argc > 2)
|
||||
startCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[2])));
|
||||
if (argc > 3)
|
||||
endCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[3])));
|
||||
|
||||
if (startCol > 0)
|
||||
palette.copy(_vm->screen()->getPalette(0), 0, startCol);
|
||||
if (endCol < palette.getNumColors())
|
||||
palette.copy(_vm->screen()->getPalette(0), endCol);
|
||||
|
||||
_vm->screen()->setScreenPalette(palette);
|
||||
_vm->screen()->updateScreen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdShowFacings(int argc, const char **argv) {
|
||||
debugPrintf("Facing directions:\n");
|
||||
debugPrintf("7 0 1\n");
|
||||
debugPrintf(" \\ | / \n");
|
||||
debugPrintf("6--*--2\n");
|
||||
debugPrintf(" / | \\\n");
|
||||
debugPrintf("5 4 3\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdGameSpeed(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int val = atoi(argv[1]);
|
||||
|
||||
if (val < 1 || val > 1000) {
|
||||
debugPrintf("speed must lie between 1 and 1000 (default: 60)\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->_tickLength = (uint8)(1000.0 / val);
|
||||
} else {
|
||||
debugPrintf("Syntax: gamespeed <value>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdListFlags(int argc, const char **argv) {
|
||||
for (int i = 0, p = 0; i < (int)sizeof(_vm->_flagsTable) * 8; i++, ++p) {
|
||||
debugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i));
|
||||
if (p == 5) {
|
||||
debugPrintf("\n");
|
||||
p -= 6;
|
||||
}
|
||||
}
|
||||
debugPrintf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdToggleFlag(int argc, const char **argv) {
|
||||
if (argc > 1) {
|
||||
uint flag = atoi(argv[1]);
|
||||
if (_vm->queryGameFlag(flag))
|
||||
_vm->resetGameFlag(flag);
|
||||
else
|
||||
_vm->setGameFlag(flag);
|
||||
debugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag));
|
||||
} else {
|
||||
debugPrintf("Syntax: toggleflag <flag>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdQueryFlag(int argc, const char **argv) {
|
||||
if (argc > 1) {
|
||||
uint flag = atoi(argv[1]);
|
||||
debugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag));
|
||||
} else {
|
||||
debugPrintf("Syntax: queryflag <flag>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdListTimers(int argc, const char **argv) {
|
||||
debugPrintf("Current time: %-8u\n", g_system->getMillis());
|
||||
for (int i = 0; i < _vm->timer()->count(); i++)
|
||||
debugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmdSetTimerCountdown(int argc, const char **argv) {
|
||||
if (argc > 2) {
|
||||
uint timer = atoi(argv[1]);
|
||||
uint countdown = atoi(argv[2]);
|
||||
_vm->timer()->setCountdown(timer, countdown);
|
||||
debugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer));
|
||||
} else {
|
||||
debugPrintf("Syntax: settimercountdown <timer> <countdown>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm)
|
||||
: Debugger(vm), _vm(vm) {
|
||||
}
|
||||
|
||||
void Debugger_LoK::initialize() {
|
||||
registerCmd("enter", WRAP_METHOD(Debugger_LoK, cmdEnterRoom));
|
||||
registerCmd("scenes", WRAP_METHOD(Debugger_LoK, cmdListScenes));
|
||||
registerCmd("give", WRAP_METHOD(Debugger_LoK, cmdGiveItem));
|
||||
registerCmd("birthstones", WRAP_METHOD(Debugger_LoK, cmdListBirthstones));
|
||||
Debugger::initialize();
|
||||
}
|
||||
|
||||
bool Debugger_LoK::cmdEnterRoom(int argc, const char **argv) {
|
||||
uint direction = 0;
|
||||
if (argc > 1) {
|
||||
int room = atoi(argv[1]);
|
||||
|
||||
// game will crash if entering a non-existent room
|
||||
if (room >= _vm->_roomTableSize) {
|
||||
debugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
direction = atoi(argv[2]);
|
||||
} else {
|
||||
if (_vm->_roomTable[room].northExit != 0xFFFF)
|
||||
direction = 3;
|
||||
else if (_vm->_roomTable[room].eastExit != 0xFFFF)
|
||||
direction = 4;
|
||||
else if (_vm->_roomTable[room].southExit != 0xFFFF)
|
||||
direction = 1;
|
||||
else if (_vm->_roomTable[room].westExit != 0xFFFF)
|
||||
direction = 2;
|
||||
}
|
||||
|
||||
_vm->_system->hideOverlay();
|
||||
_vm->_currentCharacter->facing = direction;
|
||||
|
||||
_vm->enterNewScene(room, _vm->_currentCharacter->facing, 0, 0, 1);
|
||||
while (!_vm->_screen->isMouseVisible())
|
||||
_vm->_screen->showMouse();
|
||||
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
|
||||
debugPrintf("Syntax: room <roomnum> <direction>\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_LoK::cmdListScenes(int argc, const char **argv) {
|
||||
for (int i = 0; i < _vm->_roomTableSize; i++) {
|
||||
debugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]);
|
||||
if (!(i % 8))
|
||||
debugPrintf("\n");
|
||||
}
|
||||
debugPrintf("\n");
|
||||
debugPrintf("Current room: %i\n", _vm->_currentRoom);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_LoK::cmdGiveItem(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int item = atoi(argv[1]);
|
||||
|
||||
// Kyrandia 1 has only 108 items (-1 to 106), otherwise it will crash
|
||||
if (item < -1 || item > 106) {
|
||||
debugPrintf("'itemid' must be any value between (including) -1 and 106\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->setMouseItem(item);
|
||||
_vm->_itemInHand = item;
|
||||
} else {
|
||||
debugPrintf("Syntax: give <itemid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) {
|
||||
debugPrintf("Needed birthstone gems:\n");
|
||||
for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i)
|
||||
debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]);
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) {
|
||||
}
|
||||
|
||||
void Debugger_v2::initialize() {
|
||||
registerCmd("character_info", WRAP_METHOD(Debugger_v2, cmdCharacterInfo));
|
||||
registerCmd("enter", WRAP_METHOD(Debugger_v2, cmdEnterScene));
|
||||
registerCmd("scenes", WRAP_METHOD(Debugger_v2, cmdListScenes));
|
||||
registerCmd("scene_info", WRAP_METHOD(Debugger_v2, cmdSceneInfo));
|
||||
registerCmd("scene_to_facing", WRAP_METHOD(Debugger_v2, cmdSceneToFacing));
|
||||
registerCmd("give", WRAP_METHOD(Debugger_v2, cmdGiveItem));
|
||||
Debugger::initialize();
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdEnterScene(int argc, const char **argv) {
|
||||
uint direction = 0;
|
||||
if (argc > 1) {
|
||||
int scene = atoi(argv[1]);
|
||||
|
||||
// game will crash if entering a non-existent scene
|
||||
if (scene >= _vm->_sceneListSize) {
|
||||
debugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
direction = atoi(argv[2]);
|
||||
} else {
|
||||
if (_vm->_sceneList[scene].exit1 != 0xFFFF)
|
||||
direction = 4;
|
||||
else if (_vm->_sceneList[scene].exit2 != 0xFFFF)
|
||||
direction = 6;
|
||||
else if (_vm->_sceneList[scene].exit3 != 0xFFFF)
|
||||
direction = 0;
|
||||
else if (_vm->_sceneList[scene].exit4 != 0xFFFF)
|
||||
direction = 2;
|
||||
}
|
||||
|
||||
_vm->_system->hideOverlay();
|
||||
_vm->_mainCharacter.facing = direction;
|
||||
|
||||
_vm->enterNewScene(scene, _vm->_mainCharacter.facing, 0, 0, 1);
|
||||
while (!_vm->screen_v2()->isMouseVisible())
|
||||
_vm->screen_v2()->showMouse();
|
||||
|
||||
detach();
|
||||
return false;
|
||||
}
|
||||
|
||||
debugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdListScenes(int argc, const char **argv) {
|
||||
int shown = 1;
|
||||
for (int i = 0; i < _vm->_sceneListSize; ++i) {
|
||||
if (_vm->_sceneList[i].filename1[0]) {
|
||||
debugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1);
|
||||
if (!(shown % 5))
|
||||
debugPrintf("\n");
|
||||
++shown;
|
||||
}
|
||||
}
|
||||
debugPrintf("\n");
|
||||
debugPrintf("Current scene: %i\n", _vm->_currentScene);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) {
|
||||
debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1);
|
||||
debugPrintf("\n");
|
||||
debugPrintf("Exit information:\n");
|
||||
debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1);
|
||||
debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2);
|
||||
debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3);
|
||||
debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4);
|
||||
debugPrintf("Special exit information:\n");
|
||||
if (!_vm->_specialExitCount) {
|
||||
debugPrintf("No special exits.\n");
|
||||
} else {
|
||||
debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount);
|
||||
for (int i = 0; i < _vm->_specialExitCount; ++i) {
|
||||
debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i,
|
||||
_vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i],
|
||||
_vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdCharacterInfo(int argc, const char **argv) {
|
||||
debugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1);
|
||||
debugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1);
|
||||
debugPrintf("Facing: %d\n", _vm->_mainCharacter.facing);
|
||||
debugPrintf("Inventory:\n");
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
debugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i]));
|
||||
if (i == 9 || i == 19)
|
||||
debugPrintf("\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdSceneToFacing(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int facing = atoi(argv[1]);
|
||||
int16 exit = -1;
|
||||
|
||||
switch (facing) {
|
||||
case 0: case 1: case 7:
|
||||
exit = _vm->_sceneList[_vm->_currentScene].exit1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
exit = _vm->_sceneList[_vm->_currentScene].exit2;
|
||||
break;
|
||||
|
||||
case 3: case 4: case 5:
|
||||
exit = _vm->_sceneList[_vm->_currentScene].exit3;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
exit = _vm->_sceneList[_vm->_currentScene].exit4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
debugPrintf("Exit to facing %d leads to room %d.\n", facing, exit);
|
||||
} else {
|
||||
debugPrintf("Usage: %s <facing>\n", argv[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_v2::cmdGiveItem(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int item = atoi(argv[1]);
|
||||
|
||||
if (item < -1 || item > _vm->engineDesc().maxItemId) {
|
||||
debugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId);
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->setHandItem(item);
|
||||
} else {
|
||||
debugPrintf("Syntax: give <itemid>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) {
|
||||
}
|
||||
|
||||
void Debugger_HoF::initialize() {
|
||||
registerCmd("pass_codes", WRAP_METHOD(Debugger_HoF, cmdPasscodes));
|
||||
Debugger_v2::initialize();
|
||||
}
|
||||
|
||||
bool Debugger_HoF::cmdPasscodes(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int val = atoi(argv[1]);
|
||||
|
||||
if (val < 0 || val > 1) {
|
||||
debugPrintf("value must be either 1 (on) or 0 (off)\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->_dbgPass = val;
|
||||
} else {
|
||||
debugPrintf("Syntax: pass_codes <0/1>\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
Debugger_LoL::Debugger_LoL(LoLEngine *vm) : Debugger(vm), _vm(vm) {
|
||||
}
|
||||
#endif // ENABLE_LOL
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) {
|
||||
}
|
||||
|
||||
void Debugger_EoB::initialize() {
|
||||
registerCmd("import_savefile", WRAP_METHOD(Debugger_EoB, cmdImportSaveFile));
|
||||
registerCmd("save_original", WRAP_METHOD(Debugger_EoB, cmdSaveOriginal));
|
||||
registerCmd("list_monsters", WRAP_METHOD(Debugger_EoB, cmdListMonsters));
|
||||
registerCmd("show_position", WRAP_METHOD(Debugger_EoB, cmdShowPosition));
|
||||
registerCmd("set_position", WRAP_METHOD(Debugger_EoB, cmdSetPosition));
|
||||
registerCmd("print_map", WRAP_METHOD(Debugger_EoB, cmdPrintMap));
|
||||
registerCmd("open_door", WRAP_METHOD(Debugger_EoB, cmdOpenDoor));
|
||||
registerCmd("close_door", WRAP_METHOD(Debugger_EoB, cmdCloseDoor));
|
||||
registerCmd("list_flags", WRAP_METHOD(Debugger_EoB, cmdListFlags));
|
||||
registerCmd("set_flag", WRAP_METHOD(Debugger_EoB, cmdSetFlag));
|
||||
registerCmd("clear_flag", WRAP_METHOD(Debugger_EoB, cmdClearFlag));
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) {
|
||||
if (!_vm->_allowImport) {
|
||||
debugPrintf("This command only works from the main menu.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
int slot = atoi(argv[1]);
|
||||
if (slot < -1 || slot > 989) {
|
||||
debugPrintf("slot must be between (including) -1 and 989 \n");
|
||||
return true;
|
||||
}
|
||||
|
||||
debugPrintf(_vm->importOriginalSaveFile(slot, Common::Path(argv[2], Common::Path::kNativeSeparator)) ? "Success.\n" : "Failure.\n");
|
||||
_vm->loadItemDefs();
|
||||
} else {
|
||||
debugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
|
||||
if (_vm->gameFlags().platform == Common::kPlatformSegaCD) {
|
||||
debugPrintf("Command not supported for this version.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_vm->_runFlag) {
|
||||
debugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Path dir = ConfMan.getPath("savepath");
|
||||
|
||||
Common::FSNode nd(dir);
|
||||
if (!nd.isDirectory())
|
||||
return false;
|
||||
|
||||
if (_vm->game() == GI_EOB1) {
|
||||
if (argc == 1) {
|
||||
if (_vm->saveAsOriginalSaveFile()) {
|
||||
Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV"));
|
||||
if (nf.isReadable())
|
||||
debugPrintf("Saved to file: %s\n\n", nf.getPath().toString(Common::Path::kNativeSeparator).c_str());
|
||||
else
|
||||
debugPrintf("Failure.\n");
|
||||
} else {
|
||||
debugPrintf("Failure.\n");
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the original game executable.)\n\n");
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (argc == 2) {
|
||||
int slot = atoi(argv[1]);
|
||||
if (slot < 0 || slot > 5) {
|
||||
debugPrintf("Slot must be between (including) 0 and 5.\n");
|
||||
} else if (_vm->saveAsOriginalSaveFile(slot)) {
|
||||
Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot));
|
||||
if (nf.isReadable())
|
||||
debugPrintf("Saved to file: %s\n\n", nf.getPath().toString(Common::Path::kNativeSeparator).c_str());
|
||||
else
|
||||
debugPrintf("Failure.\n");
|
||||
} else {
|
||||
debugPrintf("Failure.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the original game executable.\n A save slot between 0 and 5 must be specified.)\n\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdListMonsters(int, const char **) {
|
||||
debugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel);
|
||||
debugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
EoBMonsterInPlay *m = &_vm->_monsters[i];
|
||||
debugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags);
|
||||
}
|
||||
|
||||
debugPrintf("\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdShowPosition(int, const char **) {
|
||||
debugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdSetPosition(int argc, const char **argv) {
|
||||
if (argc == 4) {
|
||||
_vm->_currentBlock = atoi(argv[3]);
|
||||
int sub = atoi(argv[2]);
|
||||
int level = atoi(argv[1]);
|
||||
|
||||
int maxLevel = (_vm->game() == GI_EOB1) ? 12 : 16;
|
||||
if (level < 1 || level > maxLevel) {
|
||||
debugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (level != _vm->_currentLevel || sub != _vm->_currentSub) {
|
||||
_vm->completeDoorOperations();
|
||||
_vm->generateTempData();
|
||||
_vm->txt()->removePageBreakFlag();
|
||||
_vm->screen()->setScreenDim(7);
|
||||
|
||||
_vm->loadLevel(level, sub);
|
||||
|
||||
if (_vm->_dialogueField)
|
||||
_vm->restoreAfterDialogueSequence();
|
||||
}
|
||||
|
||||
_vm->moveParty(_vm->_currentBlock);
|
||||
|
||||
_vm->_sceneUpdateRequired = true;
|
||||
_vm->gui_drawAllCharPortraitsWithStats();
|
||||
debugPrintf("Success.\n\n");
|
||||
|
||||
} else {
|
||||
debugPrintf("Syntax: set_position <level>, <sub level>, <block>\n");
|
||||
debugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdPrintMap(int, const char **) {
|
||||
const uint8 illusion1 = _vm->gameFlags().gameID == GI_EOB1 ? 67 : 46;
|
||||
const uint8 illusion2 = _vm->gameFlags().gameID == GI_EOB1 ? 64 : 46;
|
||||
const uint8 plate1 = _vm->gameFlags().gameID == GI_EOB1 ? 28 : 35;
|
||||
const uint8 plate2 = _vm->gameFlags().gameID == GI_EOB1 ? 28 : 36;
|
||||
const uint8 hole = _vm->gameFlags().gameID == GI_EOB1 ? 27 : 38;
|
||||
const uint8 stairsUp = 23;
|
||||
const uint8 stairsDown = 24;
|
||||
const uint8 types[] = { _vm->_teleporterWallId, illusion1, illusion2, stairsUp, stairsDown, hole, plate1, plate2 };
|
||||
const uint8 signs[] = { 'T', 'i', 'i', 'U', 'D', 215, 'O', 'O', 'k' };
|
||||
|
||||
for (int i = 0; i < 1024; ++i) {
|
||||
if (!(i % 0x20))
|
||||
debugPrintf("\n");
|
||||
LevelBlockProperty *bl = &_vm->_levelBlockProperties[i];
|
||||
uint8 f = _vm->_wllWallFlags[bl->walls[0]] | _vm->_wllWallFlags[bl->walls[1]] | _vm->_wllWallFlags[bl->walls[2]] | _vm->_wllWallFlags[bl->walls[3]];
|
||||
uint8 s = _vm->_specialWallTypes[bl->walls[0]] | _vm->_specialWallTypes[bl->walls[1]] | _vm->_specialWallTypes[bl->walls[2]] | _vm->_specialWallTypes[bl->walls[3]];
|
||||
uint8 c = ' ';
|
||||
if (s == 3 || s == 4)
|
||||
c = '/';
|
||||
else if (s == 2 || s == 8)
|
||||
c = 176;
|
||||
else if (f & 8)
|
||||
c = 216;
|
||||
else if (f & 1)
|
||||
c = 35;
|
||||
|
||||
bool key = false;
|
||||
for (int t = bl->drawObjects; t; ) {
|
||||
const EoBItem *itm = &_vm->_items[t];
|
||||
if (itm->type == 38)
|
||||
key = true;
|
||||
t = (itm->next != bl->drawObjects) ? itm->next : 0;
|
||||
}
|
||||
|
||||
if (_vm->_currentBlock == i) {
|
||||
c = 'X';
|
||||
} else if (key) {
|
||||
c = signs[8];
|
||||
} else {
|
||||
for (int ii = 0; ii < ARRAYSIZE(types); ++ii) {
|
||||
if (bl->walls[0] == types[ii] || bl->walls[1] == types[ii] || bl->walls[2] == types[ii] || bl->walls[3] == types[ii]) {
|
||||
c = signs[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugPrintf("%c", c);
|
||||
}
|
||||
debugPrintf("\n\nParty Position: %c Door: %c Stairs Up/Down: %c/%c Plate: %c Hole: %c\nSwitch: %c Clickable Object: %c Illusion Wall: %c Teleporter: %c Key: %c\n\n", 'X', 216, signs[3], signs[4], signs[6], signs[5], '/', 176, signs[1], signs[0], signs[8]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdOpenDoor(int, const char **) {
|
||||
uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
|
||||
uint8 v = _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] | _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[1]];
|
||||
int flg = (_vm->_flags.gameID == GI_EOB1) ? 1 : 0x10;
|
||||
if (!(v & 8)) {
|
||||
debugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n");
|
||||
} else if (v & flg) {
|
||||
debugPrintf("The door seems to be already open.\n\n");
|
||||
} else {
|
||||
_vm->openDoor(block);
|
||||
debugPrintf("Trying to open door at block %d.\n\n", block);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdCloseDoor(int, const char **) {
|
||||
uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
|
||||
uint8 v = _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] | _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[1]];
|
||||
if (!(v & 8)) {
|
||||
debugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n");
|
||||
} else if ((_vm->_flags.gameID == GI_EOB1 && !(v & 1)) || (_vm->_flags.gameID == GI_EOB2 && (v & 0x20))) {
|
||||
debugPrintf("The door seems to be already closed.\n\n");
|
||||
} else {
|
||||
_vm->closeDoor(block);
|
||||
debugPrintf("Trying to close door at block %d.\n\n", block);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdListFlags(int, const char **) {
|
||||
debugPrintf("Flag Status\n----------------------\n\n");
|
||||
for (int i = 0; i < 32; i++) {
|
||||
uint32 flag = 1 << i;
|
||||
debugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE");
|
||||
}
|
||||
debugPrintf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdSetFlag(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("Syntax: set_flag <flag>\n\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
int flag = atoi(argv[1]);
|
||||
if (flag < 0 || flag > 31) {
|
||||
debugPrintf("<flag> must be a value from 0 to 31.\n\n");
|
||||
} else {
|
||||
_vm->setScriptFlags(1 << flag);
|
||||
debugPrintf("Flag '%.2d' has been set.\n\n", flag);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger_EoB::cmdClearFlag(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("Syntax: clear_flag <flag>\n\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
int flag = atoi(argv[1]);
|
||||
if (flag < 0 || flag > 31) {
|
||||
debugPrintf("<flag> must be a value from 0 to 31.\n\n");
|
||||
} else {
|
||||
_vm->clearScriptFlags(1 << flag);
|
||||
debugPrintf("Flag '%.2d' has been cleared.\n\n", flag);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ENABLE_EOB
|
||||
|
||||
} // End of namespace Kyra
|
||||
135
engines/kyra/gui/debugger.h
Normal file
135
engines/kyra/gui/debugger.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_DEBUGGER_H
|
||||
#define KYRA_DEBUGGER_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class KyraEngine_v1;
|
||||
class KyraEngine_LoK;
|
||||
class KyraEngine_v2;
|
||||
class KyraEngine_HoF;
|
||||
|
||||
class Debugger : public ::GUI::Debugger {
|
||||
public:
|
||||
Debugger(KyraEngine_v1 *vm);
|
||||
|
||||
virtual void initialize();
|
||||
|
||||
protected:
|
||||
KyraEngine_v1 *_vm;
|
||||
|
||||
bool cmdSetScreenDebug(int argc, const char **argv);
|
||||
bool cmdLoadPalette(int argc, const char **argv);
|
||||
bool cmdShowFacings(int argc, const char **argv);
|
||||
bool cmdGameSpeed(int argc, const char **argv);
|
||||
bool cmdListFlags(int argc, const char **argv);
|
||||
bool cmdToggleFlag(int argc, const char **argv);
|
||||
bool cmdQueryFlag(int argc, const char **argv);
|
||||
bool cmdListTimers(int argc, const char **argv);
|
||||
bool cmdSetTimerCountdown(int argc, const char **argv);
|
||||
};
|
||||
|
||||
class Debugger_LoK : public Debugger {
|
||||
public:
|
||||
Debugger_LoK(KyraEngine_LoK *vm);
|
||||
|
||||
void initialize() override;
|
||||
protected:
|
||||
KyraEngine_LoK *_vm;
|
||||
|
||||
bool cmdEnterRoom(int argc, const char **argv);
|
||||
bool cmdListScenes(int argc, const char **argv);
|
||||
bool cmdGiveItem(int argc, const char **argv);
|
||||
bool cmdListBirthstones(int argc, const char **argv);
|
||||
};
|
||||
|
||||
class Debugger_v2 : public Debugger {
|
||||
public:
|
||||
Debugger_v2(KyraEngine_v2 *vm);
|
||||
~Debugger_v2() override {}
|
||||
|
||||
void initialize() override;
|
||||
protected:
|
||||
KyraEngine_v2 *_vm;
|
||||
|
||||
bool cmdEnterScene(int argc, const char **argv);
|
||||
bool cmdListScenes(int argc, const char **argv);
|
||||
bool cmdSceneInfo(int argc, const char **argv);
|
||||
bool cmdCharacterInfo(int argc, const char **argv);
|
||||
bool cmdSceneToFacing(int argc, const char **argv);
|
||||
bool cmdGiveItem(int argc, const char **argv);
|
||||
};
|
||||
|
||||
class Debugger_HoF : public Debugger_v2 {
|
||||
public:
|
||||
Debugger_HoF(KyraEngine_HoF *vm);
|
||||
|
||||
void initialize() override;
|
||||
protected:
|
||||
KyraEngine_HoF *_vm;
|
||||
|
||||
bool cmdPasscodes(int argc, const char **argv);
|
||||
};
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
class LoLEngine;
|
||||
|
||||
class Debugger_LoL : public Debugger {
|
||||
public:
|
||||
Debugger_LoL(LoLEngine *vm);
|
||||
|
||||
protected:
|
||||
LoLEngine *_vm;
|
||||
};
|
||||
#endif // ENABLE_LOL
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
class EoBCoreEngine;
|
||||
|
||||
class Debugger_EoB : public Debugger {
|
||||
public:
|
||||
Debugger_EoB(EoBCoreEngine *vm);
|
||||
|
||||
void initialize() override;
|
||||
protected:
|
||||
EoBCoreEngine *_vm;
|
||||
|
||||
bool cmdImportSaveFile(int argc, const char **argv);
|
||||
bool cmdSaveOriginal(int argc, const char **argv);
|
||||
bool cmdListMonsters(int argc, const char **argv);
|
||||
bool cmdShowPosition(int argc, const char **argv);
|
||||
bool cmdSetPosition(int argc, const char **argv);
|
||||
bool cmdPrintMap(int argc, const char **argv);
|
||||
bool cmdOpenDoor(int argc, const char **argv);
|
||||
bool cmdCloseDoor(int argc, const char **argv);
|
||||
bool cmdListFlags(int argc, const char **argv);
|
||||
bool cmdSetFlag(int argc, const char **argv);
|
||||
bool cmdClearFlag(int argc, const char **argv);
|
||||
};
|
||||
#endif // ENABLE_EOB
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
137
engines/kyra/gui/gui.cpp
Normal file
137
engines/kyra/gui/gui.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "kyra/gui/gui.h"
|
||||
#include "kyra/kyra_v1.h"
|
||||
#include "kyra/engine/util.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
GUI::GUI(KyraEngine_v1 *kyra) : _vm(kyra), _screen(kyra ? kyra->screen() : nullptr) {
|
||||
_saveSlotsListUpdateNeeded = true;
|
||||
_savegameListSize = 0;
|
||||
_savegameList = nullptr;
|
||||
}
|
||||
|
||||
GUI::~GUI() {
|
||||
if (_savegameList) {
|
||||
for (int i = 0; i < _savegameListSize; i++)
|
||||
delete[] _savegameList[i];
|
||||
delete[] _savegameList;
|
||||
_savegameList = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::updateSaveFileList(Common::String targetName, bool excludeQuickSaves) {
|
||||
Common::String pattern = targetName + ".###";
|
||||
Common::StringArray saveFileList = _vm->_saveFileMan->listSavefiles(pattern);
|
||||
_saveSlots.clear();
|
||||
|
||||
for (Common::StringArray::const_iterator i = saveFileList.begin(); i != saveFileList.end(); ++i) {
|
||||
// The last 3 digits of the filename correspond to the save slot.
|
||||
const int slotNum = atoi(i->c_str() + i->size() - 3);
|
||||
if (excludeQuickSaves && slotNum >= 990)
|
||||
continue;
|
||||
_saveSlots.push_back(slotNum);
|
||||
}
|
||||
|
||||
if (_saveSlots.begin() == _saveSlots.end())
|
||||
return;
|
||||
|
||||
sortSaveSlots();
|
||||
}
|
||||
|
||||
void GUI::sortSaveSlots() {
|
||||
Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Less<int>());
|
||||
if (_saveSlots.size() > 2)
|
||||
Common::sort(_saveSlots.begin() + 1, _saveSlots.end(), Common::Greater<int>());
|
||||
}
|
||||
|
||||
int GUI::getNextSavegameSlot() {
|
||||
Common::InSaveFile *in;
|
||||
|
||||
int start = _vm->game() == GI_LOL ? 0 : 1;
|
||||
|
||||
for (int i = start; i < 990; i++) {
|
||||
if ((in = _vm->_saveFileMan->openForLoading(_vm->getSavegameFilename(i))))
|
||||
delete in;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
warning("Didn't save: Ran out of saveGame filenames");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GUI::updateSaveSlotsList(Common::String targetName, bool force) {
|
||||
if (!_saveSlotsListUpdateNeeded && !force)
|
||||
return;
|
||||
|
||||
_saveSlotsListUpdateNeeded = false;
|
||||
|
||||
if (_savegameList) {
|
||||
for (int i = 0; i < _savegameListSize; i++)
|
||||
delete[] _savegameList[i];
|
||||
delete[] _savegameList;
|
||||
}
|
||||
|
||||
updateSaveFileList(targetName, true);
|
||||
int numSaves = _savegameListSize = _saveSlots.size();
|
||||
bool allowEmptySlots = (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2);
|
||||
|
||||
if (_savegameListSize) {
|
||||
if (allowEmptySlots)
|
||||
_savegameListSize = 990;
|
||||
|
||||
KyraEngine_v1::SaveHeader header;
|
||||
Common::InSaveFile *in;
|
||||
|
||||
_savegameList = new char*[_savegameListSize]();
|
||||
|
||||
for (int i = 0; i < numSaves; i++) {
|
||||
in = _vm->openSaveForReading(_vm->getSavegameFilename(targetName, _saveSlots[i]).c_str(), header, targetName == _vm->_targetName);
|
||||
char **listEntry = &_savegameList[allowEmptySlots ? _saveSlots[i] : i];
|
||||
if (in) {
|
||||
uint buffSize = header.description.size() + 1;
|
||||
*listEntry = new char[buffSize];
|
||||
Common::strlcpy(*listEntry, header.description.c_str(), buffSize);
|
||||
// Ingame auto-generated Japanese EOB SegaCD savegame descriptions have a special 1-byte encoding that
|
||||
// does not survive this conversion. And the rest of the characters in these descriptions do not require it.
|
||||
if (!(_vm->gameFlags().platform == Common::kPlatformSegaCD && _vm->gameFlags().lang == Common::JA_JPN && Common::String(*listEntry).contains('\r')))
|
||||
Util::convertString_GUItoKYRA(*listEntry, buffSize,
|
||||
_vm->gameFlags().lang == Common::ZH_TWN ? Common::CodePage::kBig5 : Common::CodePage::kDos850);
|
||||
delete in;
|
||||
} else {
|
||||
*listEntry = nullptr;
|
||||
error("GUI::updateSavegameList(): Unexpected missing save file for slot: %d.", _saveSlots[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_savegameList = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
135
engines/kyra/gui/gui.h
Normal file
135
engines/kyra/gui/gui.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_H
|
||||
#define KYRA_GUI_H
|
||||
|
||||
#include "kyra/kyra_v1.h"
|
||||
#include "kyra/graphics/screen.h"
|
||||
|
||||
#include "common/ptr.h"
|
||||
#include "common/array.h"
|
||||
#include "common/func.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
#define BUTTON_FUNCTOR(type, x, y) Button::Callback(new Common::Functor1Mem<Button *, int, type>(x, y))
|
||||
|
||||
struct Button {
|
||||
typedef Common::Functor1<Button *, int> CallbackFunctor;
|
||||
typedef Common::SharedPtr<CallbackFunctor> Callback;
|
||||
|
||||
Button() : nextButton(0), index(0), keyCode(0), keyCode2(0), data0Val1(0), data1Val1(0), data2Val1(0), data3Val1(0), flags(0),
|
||||
data0ShapePtr(0), data1ShapePtr(0), data2ShapePtr(0), data0Callback(), data1Callback(), data2Callback(),
|
||||
dimTableIndex(0), x(0), y(0), width(0), height(0), data0Val2(0), data0Val3(0), data1Val2(0), data1Val3(0),
|
||||
data2Val2(0), data2Val3(0), data3Val2(0), data3Val3(0), flags2(0), mouseWheel(0), buttonCallback(), extButtonDef(0), arg(0) {}
|
||||
|
||||
Button *nextButton;
|
||||
uint16 index;
|
||||
|
||||
uint16 keyCode;
|
||||
uint16 keyCode2;
|
||||
|
||||
byte data0Val1;
|
||||
byte data1Val1;
|
||||
byte data2Val1;
|
||||
byte data3Val1;
|
||||
|
||||
uint16 flags;
|
||||
|
||||
const uint8 *data0ShapePtr;
|
||||
const uint8 *data1ShapePtr;
|
||||
const uint8 *data2ShapePtr;
|
||||
Callback data0Callback;
|
||||
Callback data1Callback;
|
||||
Callback data2Callback;
|
||||
|
||||
uint16 dimTableIndex;
|
||||
|
||||
int16 x, y;
|
||||
uint16 width, height;
|
||||
|
||||
uint8 data0Val2;
|
||||
uint8 data0Val3;
|
||||
|
||||
uint8 data1Val2;
|
||||
uint8 data1Val3;
|
||||
|
||||
uint8 data2Val2;
|
||||
uint8 data2Val3;
|
||||
|
||||
uint8 data3Val2;
|
||||
uint8 data3Val3;
|
||||
|
||||
uint16 flags2;
|
||||
|
||||
int8 mouseWheel;
|
||||
|
||||
Callback buttonCallback;
|
||||
|
||||
const void *extButtonDef;
|
||||
|
||||
uint16 arg;
|
||||
};
|
||||
|
||||
class Screen;
|
||||
class TextDisplayer;
|
||||
|
||||
class GUI {
|
||||
public:
|
||||
GUI(KyraEngine_v1 *vm);
|
||||
virtual ~GUI();
|
||||
|
||||
// button specific
|
||||
virtual void processButton(Button *button) = 0;
|
||||
virtual int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) = 0;
|
||||
|
||||
// utilities for thumbnail creation
|
||||
virtual void createScreenThumbnail(Graphics::Surface &dst) = 0;
|
||||
|
||||
void notifyUpdateSaveSlotsList() { _saveSlotsListUpdateNeeded = true; }
|
||||
|
||||
protected:
|
||||
KyraEngine_v1 *_vm;
|
||||
Screen *_screen;
|
||||
|
||||
// The engine expects a list of contiguous savegame indices.
|
||||
// Since ScummVM's savegame indices aren't, we re-index them.
|
||||
// The integers stored in _saveSlots are ScummVM savegame indices.
|
||||
Common::Array<int> _saveSlots;
|
||||
void updateSaveFileList(Common::String targetName, bool excludeQuickSaves = false);
|
||||
int getNextSavegameSlot();
|
||||
void updateSaveSlotsList(Common::String targetName, bool force = false);
|
||||
|
||||
virtual void sortSaveSlots();
|
||||
|
||||
char **_savegameList;
|
||||
int _savegameListSize;
|
||||
bool _saveSlotsListUpdateNeeded;
|
||||
|
||||
Common::KeyState _keyPressed;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
4976
engines/kyra/gui/gui_eob.cpp
Normal file
4976
engines/kyra/gui/gui_eob.cpp
Normal file
File diff suppressed because it is too large
Load Diff
208
engines/kyra/gui/gui_eob.h
Normal file
208
engines/kyra/gui/gui_eob.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
|
||||
|
||||
#ifndef KYRA_GUI_EOB_H
|
||||
#define KYRA_GUI_EOB_H
|
||||
|
||||
#include "kyra/gui/gui.h"
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
struct EoBRect16 {
|
||||
int16 x1;
|
||||
int16 y1;
|
||||
uint16 x2;
|
||||
uint16 y2;
|
||||
};
|
||||
|
||||
class DarkMoonEngine;
|
||||
class Screen_EoB;
|
||||
|
||||
class GUI_EoB : public GUI {
|
||||
friend class EoBCoreEngine;
|
||||
friend class CharacterGenerator;
|
||||
public:
|
||||
GUI_EoB(EoBCoreEngine *vm);
|
||||
~GUI_EoB() override;
|
||||
|
||||
void initStaticData() {}
|
||||
|
||||
// button specific
|
||||
void processButton(Button *button) override;
|
||||
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) override;
|
||||
|
||||
// Non button based menu handling (main menu, character generation)
|
||||
void simpleMenu_setup(int sd, int maxItem, const char *const *strings, int32 menuItemsMask, int itemOffset, int lineSpacing, int textColor, int highlightColor, int shadowColor);
|
||||
int simpleMenu_process(int sd, const char *const *strings, void *b, int32 menuItemsMask, int itemOffset);
|
||||
void simpleMenu_unselect(int sd, const char *const *strings, void *b, int32 menuItemsMask, int itemOffset);
|
||||
|
||||
// Button based menus (camp menu, load menu)
|
||||
virtual void runCampMenu();
|
||||
virtual bool runLoadMenu(int x, int y, bool fromMainMenu = false);
|
||||
|
||||
bool confirmDialogue2(int dim, int id, int deflt);
|
||||
void messageDialog(int dim, int id, int buttonTextCol);
|
||||
void messageDialog2(int dim, int id, int buttonTextCol);
|
||||
|
||||
void updateBoxFrameHighLight(int box);
|
||||
|
||||
int getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor);
|
||||
|
||||
// Transfer party
|
||||
void transferWaitBox();
|
||||
Common::String transferTargetMenu(Common::Array<Common::String> &targets);
|
||||
bool transferFileMenu(Common::String &targetName, Common::String &selection);
|
||||
|
||||
// utilities for thumbnail creation
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override;
|
||||
|
||||
protected:
|
||||
const char *getMenuString(int id);
|
||||
Button *initMenu(int id);
|
||||
void releaseButtons(Button *list);
|
||||
virtual int mapPointToEntry(const Common::Point &p) const;
|
||||
|
||||
int8 *_numAssignedSpellsOfType;
|
||||
char** _saveSlotStringsTemp;
|
||||
int16 _saveSlotX;
|
||||
int16 _saveSlotY;
|
||||
int _menuCur;
|
||||
|
||||
int _clickableCharactersPage;
|
||||
char _csjis[3];
|
||||
|
||||
Screen_EoB *_screen;
|
||||
|
||||
private:
|
||||
int simpleMenu_getMenuItem(int index, int32 menuItemsMask, int itemOffset);
|
||||
void simpleMenu_flashSelection(const char *str, int x, int y, int color1, int color2, int color3);
|
||||
void simpleMenu_initMenuItemsMask(int menuId, int maxItem, int32 menuItemsMask, int unk);
|
||||
void simpleMenu_printButton(int sd, int num, const char *title, bool isHighlight, bool isInitial);
|
||||
Common::Point simpleMenu_getTextPoint(int num, int *col = nullptr);
|
||||
int simpleMenu_getMouseItem(int sd);
|
||||
|
||||
bool runSaveMenu(int x, int y);
|
||||
int selectSaveSlotDialog(int x, int y, int id);
|
||||
virtual void drawSaveSlotDialog(int x, int y, int id);
|
||||
void runMemorizePrayMenu(int charIndex, int spellType);
|
||||
void scribeScrollDialogue();
|
||||
bool restParty();
|
||||
|
||||
virtual void drawCampMenu() {}
|
||||
virtual void initMemorizePrayMenu(int) {}
|
||||
virtual void initScribeScrollMenu() {}
|
||||
virtual void printScribeScrollSpellString(const int16 *menuItems, int id, bool highlight);
|
||||
virtual bool confirmDialogue(int id);
|
||||
int selectCharacterDialogue(int id);
|
||||
virtual void displayTextBox(int id, int textColor = 0xFF, bool wait = true);
|
||||
|
||||
virtual void drawMenuButton(Button *b, bool clicked, bool highlight, bool noFill);
|
||||
void drawMenuButtonBox(int x, int y, int w, int h, bool clicked, bool noFill);
|
||||
void drawTextBox(int dim, int id);
|
||||
virtual void drawSaveSlotButton(int slot, int redrawBox, bool highlight);
|
||||
virtual void memorizePrayMenuPrintString(int spellId, int bookPageIndex, int spellType, bool noFill, bool highLight);
|
||||
virtual void updateOptionsStrings();
|
||||
|
||||
Button *linkButton(Button *list, Button *newbt);
|
||||
|
||||
void setupSaveMenuSlots();
|
||||
virtual int getHighlightSlot();
|
||||
void sortSaveSlots() override;
|
||||
|
||||
virtual void restParty_updateRestTime(int hours, bool init);
|
||||
|
||||
char **_menuStringsPrefsTemp;
|
||||
int16 *_saveSlotIdTemp;
|
||||
int _savegameOffset;
|
||||
const int _numSlotsVisible;
|
||||
|
||||
EoBCoreEngine *_vm;
|
||||
|
||||
Button *_specialProcessButton;
|
||||
Button *_backupButtonList;
|
||||
uint16 _flagsMouseLeft;
|
||||
uint16 _flagsMouseRight;
|
||||
uint16 _flagsModifier;
|
||||
uint16 _progress;
|
||||
uint16 _prcButtonUnk3;
|
||||
uint16 _cflag;
|
||||
|
||||
int _menuLineSpacing;
|
||||
int _menuLastInFlags;
|
||||
int _menuTextColor;
|
||||
int _menuHighlightColor;
|
||||
int _menuShadowColor;
|
||||
int _menuLines[2];
|
||||
int _menuColumnWidth[2];
|
||||
int _menuColumnOffset[2];
|
||||
bool _menuOverflow[20];
|
||||
int _menuColumns;
|
||||
Common::Point _menuPoint;
|
||||
|
||||
uint8 _numPages;
|
||||
uint8 _numVisPages;
|
||||
uint32 _clericSpellAvltyFlags;
|
||||
uint32 _paladinSpellAvltyFlags;
|
||||
bool _needRest;
|
||||
|
||||
int _menuNumItems;
|
||||
bool _charSelectRedraw;
|
||||
|
||||
int _updateBoxIndex;
|
||||
int _updateBoxColorIndex;
|
||||
const uint8 *_highLightColorTable;
|
||||
uint32 _highLightBoxTimer;
|
||||
|
||||
const bool _textInputForceUppercase;
|
||||
const int _textInputHeight;
|
||||
const int _textInputShadowOffset;
|
||||
|
||||
const Screen::FontId _menuFont;
|
||||
const Screen::FontId _menuFont2;
|
||||
const int _dlgButtonHeight1;
|
||||
const int _dlgButtonHeight2;
|
||||
const int _dlgButtonLabelYOffs;
|
||||
|
||||
const EoBRect16 *_highlightFrames;
|
||||
static const EoBRect16 _highlightFramesDefault[20];
|
||||
static const EoBRect16 _highlightFramesTransferZH[6];
|
||||
static const uint8 _highlightColorTableVGA[];
|
||||
static const uint8 _highlightColorTableEGA[];
|
||||
static const uint8 _highlightColorTableAmiga[];
|
||||
static const uint8 _highlightColorTablePC98[];
|
||||
static const uint8 _highlightColorTableSegaCD[];
|
||||
|
||||
// FM-Towns / SegaCD specific
|
||||
virtual uint16 checkClickableCharactersSelection();
|
||||
virtual void printClickableCharacters(int page);
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_EOB
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_EOB || ENABLE_LOL
|
||||
1096
engines/kyra/gui/gui_eob_segacd.cpp
Normal file
1096
engines/kyra/gui/gui_eob_segacd.cpp
Normal file
File diff suppressed because it is too large
Load Diff
80
engines/kyra/gui/gui_eob_segacd.h
Normal file
80
engines/kyra/gui/gui_eob_segacd.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
#ifndef KYRA_GUI_EOB_SEGACD_H
|
||||
#define KYRA_GUI_EOB_SEGACD_H
|
||||
|
||||
#include "kyra/gui/gui_eob.h"
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class GUI_EoB_SegaCD : public GUI_EoB {
|
||||
public:
|
||||
GUI_EoB_SegaCD(EoBEngine *vm);
|
||||
~GUI_EoB_SegaCD() override;
|
||||
|
||||
protected:
|
||||
int mapPointToEntry(const Common::Point &p) const override;
|
||||
|
||||
private:
|
||||
void drawCampMenu() override;
|
||||
void initMemorizePrayMenu(int spellType) override;
|
||||
void initScribeScrollMenu() override;
|
||||
void printScribeScrollSpellString(const int16 *menuItems, int id, bool highlight) override;
|
||||
void drawSaveSlotDialog(int x, int y, int id) override;
|
||||
bool confirmDialogue(int id) override;
|
||||
void displayTextBox(int id, int textColor, bool wait) override;
|
||||
void drawMenuButton(Button *b, bool clicked, bool highlight, bool noFill) override;
|
||||
void drawSaveSlotButton(int slot, int redrawBox, bool highlight) override;
|
||||
int getHighlightSlot() override;
|
||||
void memorizePrayMenuPrintString(int spellId, int bookPageIndex, int spellType, bool noFill, bool highLight) override;
|
||||
void updateOptionsStrings() override;
|
||||
void restParty_updateRestTime(int hours, bool init) override;
|
||||
|
||||
uint16 checkClickableCharactersSelection() override;
|
||||
void printClickableCharacters(int page) override;
|
||||
void printClickableCharacter(int id, int col);
|
||||
char fetchClickableCharacter(int id) const;
|
||||
|
||||
const int _clickableCharactersNumPages;
|
||||
const uint8 *_campMenu;
|
||||
Button* _saveLoadCancelButton;
|
||||
EoBEngine *_vm;
|
||||
|
||||
struct MenuButtonTiles {
|
||||
uint16 nameTbl;
|
||||
uint16 srcOffs;
|
||||
};
|
||||
|
||||
static const MenuButtonTiles _menuButtonTiles[40];
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_EOB
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_EOB || ENABLE_LOL
|
||||
1202
engines/kyra/gui/gui_hof.cpp
Normal file
1202
engines/kyra/gui/gui_hof.cpp
Normal file
File diff suppressed because it is too large
Load Diff
86
engines/kyra/gui/gui_hof.h
Normal file
86
engines/kyra/gui/gui_hof.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_HOF_H
|
||||
#define KYRA_GUI_HOF_H
|
||||
|
||||
#include "kyra/gui/gui_v2.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class KyraEngine_HoF;
|
||||
class Screen_HoF;
|
||||
|
||||
class GUI_HoF : public GUI_v2 {
|
||||
friend class KyraEngine_HoF;
|
||||
public:
|
||||
GUI_HoF(KyraEngine_HoF *engine);
|
||||
|
||||
void initStaticData() override;
|
||||
|
||||
int optionsButton(Button *button);
|
||||
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override;
|
||||
private:
|
||||
Common::String getMenuTitle(const Menu &menu) override;
|
||||
Common::String getMenuItemTitle(const MenuItem &menuItem) override;
|
||||
Common::String getMenuItemLabel(const MenuItem &menuItem) override;
|
||||
|
||||
uint8 defaultColor1() const override { return 0xCF; }
|
||||
uint8 defaultColor2() const override { return 0xF8; }
|
||||
uint8 menuItemLabelColor() const override { return 0xFC; }
|
||||
|
||||
uint8 textFieldColor1() const override { return 0xFD; }
|
||||
uint8 textFieldColor2() const override { return 0xFA; }
|
||||
uint8 textFieldColor3() const override { return 0xFE; }
|
||||
|
||||
void setupPalette() override;
|
||||
void restorePalette() override;
|
||||
|
||||
void resetState(int item);
|
||||
|
||||
Common::String getTableString(int id, bool decode) override;
|
||||
|
||||
KyraEngine_HoF *_vm;
|
||||
Screen_HoF *_screen;
|
||||
|
||||
int quitGame(Button *caller);
|
||||
int loadMenu(Button *caller);
|
||||
int audioOptions(Button *caller);
|
||||
int gameOptions(Button *caller);
|
||||
int gameOptionsTalkie(Button *caller);
|
||||
|
||||
int changeLanguage(Button *caller);
|
||||
|
||||
void setupOptionsButtons() override;
|
||||
|
||||
int sliderHandler(Button *caller) override;
|
||||
void drawSliderBar(int slider, const uint8 *shape);
|
||||
|
||||
static const uint16 _menuStringsTalkie[];
|
||||
static const uint16 _menuStringsOther[];
|
||||
|
||||
static const char *const _saveLoadStringsZH[2];
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
1225
engines/kyra/gui/gui_lok.cpp
Normal file
1225
engines/kyra/gui/gui_lok.cpp
Normal file
File diff suppressed because it is too large
Load Diff
194
engines/kyra/gui/gui_lok.h
Normal file
194
engines/kyra/gui/gui_lok.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_LOK_H
|
||||
#define KYRA_GUI_LOK_H
|
||||
|
||||
#include "kyra/gui/gui_v1.h"
|
||||
#include "kyra/graphics/screen_lok.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
#define GUI_V1_BUTTON(button, a, b, c, d, e, f, g, h, i, j, k) \
|
||||
do { \
|
||||
button.nextButton = 0; \
|
||||
button.index = a; \
|
||||
button.keyCode = button.keyCode2 = 0; \
|
||||
button.data0Val1 = b; \
|
||||
button.data1Val1 = c; \
|
||||
button.data2Val1 = d; \
|
||||
button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \
|
||||
button.flags = e; \
|
||||
button.dimTableIndex = f; \
|
||||
button.x = g; \
|
||||
button.y = h; \
|
||||
button.width = i; \
|
||||
button.height = j; \
|
||||
button.flags2 = k; \
|
||||
button.mouseWheel = 0; \
|
||||
button.arg = 0; \
|
||||
} while (0)
|
||||
|
||||
#define GUI_V1_MENU(menu, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
do { \
|
||||
menu.x = a; \
|
||||
menu.y = b; \
|
||||
menu.width = c; \
|
||||
menu.height = d; \
|
||||
menu.bkgdColor = e; \
|
||||
menu.color1 = f; \
|
||||
menu.color2 = g; \
|
||||
menu.menuNameString = h; \
|
||||
menu.textColor = i; \
|
||||
menu.titleX = j; \
|
||||
menu.titleY = k; \
|
||||
menu.highlightedItem = l; \
|
||||
menu.numberOfItems = m; \
|
||||
menu.scrollUpButtonX = n; \
|
||||
menu.scrollUpButtonY = o; \
|
||||
menu.scrollDownButtonX = p; \
|
||||
menu.scrollDownButtonY = q; \
|
||||
} while (0)
|
||||
|
||||
#define GUI_V1_MENU_ITEM(item, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) \
|
||||
do { \
|
||||
item.enabled = a; \
|
||||
item.itemString = ""; \
|
||||
item.x = e; \
|
||||
item.y = g; \
|
||||
item.width = h; \
|
||||
item.height = i; \
|
||||
item.textColor = j; \
|
||||
item.highlightColor = k; \
|
||||
item.titleX = l; \
|
||||
item.bkgdColor = n; \
|
||||
item.color1 = o; \
|
||||
item.color2 = p; \
|
||||
item.saveSlot = q; \
|
||||
item.labelString = r; \
|
||||
item.labelX = s; \
|
||||
item.labelY = t; \
|
||||
item.keyCode = v; \
|
||||
} while (0)
|
||||
|
||||
class KyraEngine_LoK;
|
||||
|
||||
class GUI_LoK : public GUI_v1 {
|
||||
friend class KyraEngine_LoK;
|
||||
public:
|
||||
GUI_LoK(KyraEngine_LoK *vm, Screen_LoK *screen);
|
||||
~GUI_LoK() override;
|
||||
|
||||
void processButton(Button *button) override;
|
||||
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) override;
|
||||
|
||||
int buttonMenuCallback(Button *caller);
|
||||
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override;
|
||||
private:
|
||||
void initStaticResource();
|
||||
|
||||
Button _menuButtonData[6];
|
||||
Button _scrollUpButton;
|
||||
Button _scrollDownButton;
|
||||
Button *getButtonListData() override { return _menuButtonData; }
|
||||
Button *getScrollUpButton() override { return &_scrollUpButton; }
|
||||
Button *getScrollDownButton() override { return &_scrollDownButton; }
|
||||
|
||||
Menu *_menu;
|
||||
|
||||
bool _pressFlag;
|
||||
|
||||
void setGUILabels();
|
||||
|
||||
void setupSavegames(Menu &menu, int num);
|
||||
|
||||
int resumeGame(Button *button);
|
||||
int loadGameMenu(Button *button);
|
||||
int saveGameMenu(Button *button);
|
||||
int gameControlsMenu(Button *button);
|
||||
int quitPlaying(Button *button);
|
||||
int quitConfirmYes(Button *button);
|
||||
int quitConfirmNo(Button *button);
|
||||
int loadGame(Button *button);
|
||||
int saveGame(Button *button);
|
||||
int savegameConfirm(Button *button);
|
||||
int cancelSubMenu(Button *button);
|
||||
int scrollUp(Button *button);
|
||||
int scrollDown(Button *button);
|
||||
int controlsChangeMusic(Button *button);
|
||||
int controlsChangeSounds(Button *button);
|
||||
int controlsChangeWalk(Button *button);
|
||||
int controlsChangeText(Button *button);
|
||||
int controlsChangeVoice(Button *button);
|
||||
int controlsApply(Button *button);
|
||||
|
||||
bool quitConfirm(const char *str);
|
||||
void getInput();
|
||||
void updateSavegameString();
|
||||
void redrawTextfield();
|
||||
void fadePalette();
|
||||
void restorePalette();
|
||||
void setupControls(Menu &menu);
|
||||
|
||||
uint8 defaultColor1() const override { return 12; }
|
||||
uint8 defaultColor2() const override { return 248; }
|
||||
uint8 menuItemLabelColor() const override { return 253; }
|
||||
|
||||
Common::String getMenuTitle(const Menu &menu) override { return menu.menuNameString; }
|
||||
Common::String getMenuItemTitle(const MenuItem &menuItem) override { return menuItem.itemString; }
|
||||
Common::String getMenuItemLabel(const MenuItem &menuItem) override { return menuItem.labelString; }
|
||||
|
||||
KyraEngine_LoK *_vm;
|
||||
Screen_LoK *_screen;
|
||||
|
||||
bool _menuRestoreScreen;
|
||||
uint8 _toplevelMenu;
|
||||
int _savegameOffset;
|
||||
char _savegameName[35 * 4]; // allow extra space, since the string can be UTF-8, temporarily
|
||||
char _savegameNames[5][35 * 4];
|
||||
const char *_specialSavegameString;
|
||||
bool _resetHanInput;
|
||||
|
||||
int _inputType;
|
||||
// The purpose of these variables is improved handling of backspace character deletion for
|
||||
// Hangul input. The original allows "deconstruction" of the last glyph, so why shouldn't we...
|
||||
uint8 _inputState;
|
||||
uint16 _backupChars[4];
|
||||
|
||||
int _saveLoadNumSlots;
|
||||
|
||||
Button::Callback _scrollUpFunctor;
|
||||
Button::Callback _scrollDownFunctor;
|
||||
Button::Callback getScrollUpButtonHandler() const override { return _scrollUpFunctor; }
|
||||
Button::Callback getScrollDownButtonHandler() const override { return _scrollDownFunctor; }
|
||||
|
||||
const char *_voiceTextString;
|
||||
const char *_textSpeedString;
|
||||
const char *_onString;
|
||||
const char *_offString;
|
||||
const char *_confMusicMenuStrings[3];
|
||||
uint8 _confMusicMenuMod;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
2949
engines/kyra/gui/gui_lol.cpp
Normal file
2949
engines/kyra/gui/gui_lol.cpp
Normal file
File diff suppressed because it is too large
Load Diff
180
engines/kyra/gui/gui_lol.h
Normal file
180
engines/kyra/gui/gui_lol.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
|
||||
#ifndef KYRA_GUI_LOL_H
|
||||
#define KYRA_GUI_LOL_H
|
||||
|
||||
#include "kyra/gui/gui_v1.h"
|
||||
|
||||
namespace Kyra {
|
||||
#define GUI_LOL_MENU(menu, a, b, c, d, e, f, g, i) \
|
||||
do { \
|
||||
const ScreenDim *dim = _screen->getScreenDim(a); \
|
||||
menu.x = (dim->sx << 3); \
|
||||
menu.y = (dim->sy); \
|
||||
menu.width = (dim->w << 3); \
|
||||
menu.height = (dim->h); \
|
||||
if (_vm->gameFlags().use16ColorMode) { \
|
||||
menu.bkgdColor = 0xCC; \
|
||||
menu.color1 = 0xFF; \
|
||||
menu.color2 = 0xDD; \
|
||||
} else { \
|
||||
menu.bkgdColor = 225; \
|
||||
menu.color1 = 223; \
|
||||
menu.color2 = 227; \
|
||||
} \
|
||||
menu.menuNameId = b; \
|
||||
menu.highlightedItem = c; \
|
||||
menu.numberOfItems = d; \
|
||||
menu.titleX = (dim->sx << 3) + (dim->w << 2); \
|
||||
menu.titleY = 6; \
|
||||
menu.textColor = _vm->gameFlags().use16ColorMode ? 0xE1 : 254; \
|
||||
menu.scrollUpButtonX = e; \
|
||||
menu.scrollUpButtonY = f; \
|
||||
menu.scrollDownButtonX = g; \
|
||||
menu.scrollDownButtonY = i; \
|
||||
} while (0)
|
||||
|
||||
#define GUI_LOL_MENU_ITEM(item, a, b, c, d, e, f, g) \
|
||||
do { \
|
||||
item.enabled = 1; \
|
||||
item.itemId = a; \
|
||||
item.itemString = ""; \
|
||||
item.useItemString = false; \
|
||||
item.x = b; \
|
||||
item.y = c; \
|
||||
item.width = d; \
|
||||
item.height = e; \
|
||||
item.textColor = _vm->gameFlags().use16ColorMode ? 0xC1 : 204; \
|
||||
item.highlightColor = _vm->gameFlags().use16ColorMode ? 0xE1 : 254; \
|
||||
item.titleX = -1; \
|
||||
if (_vm->gameFlags().use16ColorMode) { \
|
||||
item.bkgdColor = 0xCC; \
|
||||
item.color1 = 0xFF; \
|
||||
item.color2 = 0xDD; \
|
||||
} else { \
|
||||
item.bkgdColor = 225; \
|
||||
item.color1 = 223; \
|
||||
item.color2 = 227; \
|
||||
} \
|
||||
item.saveSlot = 0; \
|
||||
item.labelId = f; \
|
||||
item.labelString = 0; \
|
||||
item.labelX = 0; \
|
||||
item.labelY = 0; \
|
||||
item.keyCode = g; \
|
||||
} while (0)
|
||||
|
||||
class LoLEngine;
|
||||
class Screen_LoL;
|
||||
|
||||
class GUI_LoL : public GUI_v1 {
|
||||
friend class LoLEngine;
|
||||
public:
|
||||
GUI_LoL(LoLEngine *vm);
|
||||
|
||||
void initStaticData();
|
||||
|
||||
// button specific
|
||||
void processButton(Button *button) override;
|
||||
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) override;
|
||||
|
||||
int redrawShadedButtonCallback(Button *button) override;
|
||||
int redrawButtonCallback(Button *button) override;
|
||||
|
||||
int runMenu(Menu &menu);
|
||||
|
||||
// utilities for thumbnail creation
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override;
|
||||
|
||||
private:
|
||||
void backupPage0();
|
||||
void restorePage0();
|
||||
|
||||
void setupSaveMenuSlots(Menu &menu, int num);
|
||||
|
||||
void printMenuText(const Common::String &str, int x, int y, uint8 c0, uint8 c1, uint8 flags) override;
|
||||
int getMenuCenterStringX(const Common::String &str, int x1, int x2) override;
|
||||
|
||||
int getInput();
|
||||
|
||||
int clickedMainMenu(Button *button);
|
||||
int clickedLoadMenu(Button *button);
|
||||
int clickedSaveMenu(Button *button);
|
||||
int clickedDeleteMenu(Button *button);
|
||||
int clickedOptionsMenu(Button *button);
|
||||
int clickedAudioMenu(Button *button);
|
||||
int clickedDeathMenu(Button *button);
|
||||
int clickedSavenameMenu(Button *button);
|
||||
int clickedChoiceMenu(Button *button);
|
||||
|
||||
int scrollUp(Button *button);
|
||||
int scrollDown(Button *button);
|
||||
|
||||
Button *getButtonListData() override { return _menuButtons; }
|
||||
Button *getScrollUpButton() override { return &_scrollUpButton; }
|
||||
Button *getScrollDownButton() override { return &_scrollDownButton; }
|
||||
|
||||
|
||||
Button::Callback getScrollUpButtonHandler() const override { return _scrollUpFunctor; }
|
||||
Button::Callback getScrollDownButtonHandler() const override { return _scrollDownFunctor; }
|
||||
|
||||
uint8 defaultColor1() const override { return 0xFE; }
|
||||
uint8 defaultColor2() const override { return 0x00; }
|
||||
uint8 menuItemLabelColor() const override { return 0xCC; }
|
||||
|
||||
Common::String getMenuTitle(const Menu &menu) override;
|
||||
Common::String getMenuItemTitle(const MenuItem &menuItem) override;
|
||||
Common::String getMenuItemLabel(const MenuItem &menuItem) override;
|
||||
|
||||
Button _menuButtons[10];
|
||||
Button _scrollUpButton;
|
||||
Button _scrollDownButton;
|
||||
Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _deleteMenu, _savenameMenu, _deathMenu;
|
||||
Menu *_currentMenu, *_lastMenu, *_newMenu;
|
||||
int _menuResult;
|
||||
char *_saveDescription;
|
||||
|
||||
LoLEngine *_vm;
|
||||
Screen_LoL *_screen;
|
||||
|
||||
bool _pressFlag;
|
||||
|
||||
Button *_specialProcessButton;
|
||||
Button *_backUpButtonList;
|
||||
uint16 _flagsModifier;
|
||||
|
||||
int _savegameOffset;
|
||||
int _sliderSfx;
|
||||
|
||||
Button::Callback _scrollUpFunctor;
|
||||
Button::Callback _scrollDownFunctor;
|
||||
|
||||
void sortSaveSlots() override;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_LOL
|
||||
1701
engines/kyra/gui/gui_mr.cpp
Normal file
1701
engines/kyra/gui/gui_mr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
engines/kyra/gui/gui_mr.h
Normal file
89
engines/kyra/gui/gui_mr.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_MR_H
|
||||
#define KYRA_GUI_MR_H
|
||||
|
||||
#include "kyra/gui/gui_v2.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class KyraEngine_MR;
|
||||
class Screen_MR;
|
||||
|
||||
class GUI_MR : public GUI_v2 {
|
||||
friend class KyraEngine_MR;
|
||||
public:
|
||||
GUI_MR(KyraEngine_MR *engine);
|
||||
|
||||
void initStaticData() override;
|
||||
|
||||
void flagButtonEnable(Button *button);
|
||||
void flagButtonDisable(Button *button);
|
||||
|
||||
int redrawShadedButtonCallback(Button *button) override;
|
||||
int redrawButtonCallback(Button *button) override;
|
||||
|
||||
int optionsButton(Button *button);
|
||||
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override;
|
||||
private:
|
||||
Common::String getMenuTitle(const Menu &menu) override;
|
||||
Common::String getMenuItemTitle(const MenuItem &menuItem) override;
|
||||
Common::String getMenuItemLabel(const MenuItem &menuItem) override;
|
||||
Common::String getTableString(int id, bool) override;
|
||||
|
||||
uint8 textFieldColor1() const override { return 0xFF; }
|
||||
uint8 textFieldColor2() const override { return 0xCF; }
|
||||
uint8 textFieldColor3() const override { return 0xBA; }
|
||||
|
||||
uint8 defaultColor1() const override { return 0xF0; }
|
||||
uint8 defaultColor2() const override { return 0xD0; }
|
||||
uint8 menuItemLabelColor() const override { return 0xFF; }
|
||||
|
||||
void resetState(int item);
|
||||
|
||||
int quitGame(Button *button);
|
||||
int loadMenu(Button *button);
|
||||
int loadSecondChance(Button *button);
|
||||
|
||||
int gameOptions(Button *button);
|
||||
void setupOptionsButtons() override;
|
||||
void resizeMenu(Menu &menu, int menuHeight, int menuTitleY, int menuItemYstart, int menuItemYinc, int menuItemHeight, int menuItemYend, int labelYstart, int labelYend);
|
||||
void fontBasedMenuResize();
|
||||
|
||||
int audioOptions(Button *button);
|
||||
|
||||
int sliderHandler(Button *caller) override;
|
||||
void drawSliderBar(int slider, const uint8 *shape);
|
||||
|
||||
int changeLanguage(Button *caller);
|
||||
int toggleStudioSFX(Button *caller);
|
||||
int toggleSkipSupport(Button *caller);
|
||||
int toggleHeliumMode(Button *caller);
|
||||
|
||||
KyraEngine_MR *_vm;
|
||||
Screen_MR *_screen;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
134
engines/kyra/gui/gui_rpg.cpp
Normal file
134
engines/kyra/gui/gui_rpg.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
|
||||
|
||||
#include "kyra/engine/kyra_rpg.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
void KyraRpgEngine::removeInputTop() {
|
||||
if (!_eventList.empty()) {
|
||||
if (_eventList.begin()->event.type == Common::EVENT_LBUTTONDOWN)
|
||||
_mouseClick = 1;
|
||||
else if (_eventList.begin()->event.type == Common::EVENT_RBUTTONDOWN)
|
||||
_mouseClick = 2;
|
||||
else
|
||||
_mouseClick = 0;
|
||||
|
||||
_eventList.erase(_eventList.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::gui_drawBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor) {
|
||||
w--;
|
||||
h--;
|
||||
|
||||
if (fillColor != -1)
|
||||
screen()->fillRect(x + 1, y + 1, x + w - 1, y + h - 1, fillColor);
|
||||
|
||||
screen()->drawClippedLine(x + 1, y, x + w, y, frameColor2);
|
||||
screen()->drawClippedLine(x + w, y, x + w, y + h - 1, frameColor2);
|
||||
screen()->drawClippedLine(x, y, x, y + h, frameColor1);
|
||||
screen()->drawClippedLine(x, y + h, x + w, y + h, frameColor1);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 cur, int32 max, int col1, int col2) {
|
||||
if (max < 1)
|
||||
return;
|
||||
if (cur < 0)
|
||||
cur = 0;
|
||||
|
||||
int32 e = MIN(cur, max);
|
||||
|
||||
if (!--w)
|
||||
return;
|
||||
if (!--h)
|
||||
return;
|
||||
|
||||
int32 t = (e * w) / max;
|
||||
|
||||
if (!t && e)
|
||||
t++;
|
||||
|
||||
if (t)
|
||||
screen()->fillRect(x, y, x + t - 1, y + h, col1);
|
||||
|
||||
if (t < w && col2)
|
||||
screen()->fillRect(x + t, y, x + w - 1, y + h, col2);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::gui_initButtonsFromList(const uint8 *list) {
|
||||
while (*list != 0xFF)
|
||||
gui_initButton(*list++);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::gui_resetButtonList() {
|
||||
for (uint i = 0; i < ARRAYSIZE(_activeButtonData); ++i)
|
||||
_activeButtonData[i].nextButton = 0;
|
||||
|
||||
gui_notifyButtonListChanged();
|
||||
_activeButtons = 0;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::gui_notifyButtonListChanged() {
|
||||
if (gui()) {
|
||||
if (!_buttonListChanged && !_preserveEvents)
|
||||
removeInputTop();
|
||||
_buttonListChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool KyraRpgEngine::clickedShape(int shapeIndex) {
|
||||
if (_clickedSpecialFlag != 0x40)
|
||||
return true;
|
||||
|
||||
for (; shapeIndex; shapeIndex = _levelDecorationProperties[shapeIndex].next) {
|
||||
if (_flags.gameID != GI_LOL)
|
||||
shapeIndex--;
|
||||
|
||||
uint16 s = _levelDecorationProperties[shapeIndex].shapeIndex[1];
|
||||
|
||||
if (s == 0xFFFF)
|
||||
continue;
|
||||
|
||||
int w = _flags.gameID == GI_LOL ? _levelDecorationShapes[s][3] : (_levelDecorationShapes[s][2] << 3);
|
||||
int h = _levelDecorationShapes[s][_flags.gameID == GI_LOL ? 2 : 1];
|
||||
int x = _levelDecorationProperties[shapeIndex].shapeX[1] + _clickedShapeXOffs;
|
||||
int y = _levelDecorationProperties[shapeIndex].shapeY[1] + _clickedShapeYOffs;
|
||||
|
||||
if (_levelDecorationProperties[shapeIndex].flags & 1) {
|
||||
if (_flags.gameID == GI_LOL)
|
||||
w <<= 1;
|
||||
else
|
||||
x = 176 - x - w;
|
||||
}
|
||||
|
||||
if (posWithinRect(_mouseX, _mouseY, x - 4, y - 4, x + w + 8, y + h + 8))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // defined(ENABLE_EOB) || defined(ENABLE_LOL)
|
||||
631
engines/kyra/gui/gui_v1.cpp
Normal file
631
engines/kyra/gui/gui_v1.cpp
Normal file
@@ -0,0 +1,631 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/gui/gui_v1.h"
|
||||
|
||||
#include "kyra/text/text.h"
|
||||
#include "kyra/graphics/wsamovie.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
GUI_v1::GUI_v1(KyraEngine_v1 *kyra) : GUI(kyra), _text(kyra->text()) {
|
||||
_menuButtonList = nullptr;
|
||||
_menuLabelYOffset = (kyra->game() == GI_LOL || kyra->gameFlags().lang == Common::KO_KOR) ? 3 : 2;
|
||||
|
||||
_redrawButtonFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::redrawButtonCallback);
|
||||
_redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::redrawShadedButtonCallback);
|
||||
|
||||
_displayMenu = _displaySubMenu = _cancelSubMenu = false;
|
||||
_lastScreenUpdate = 0;
|
||||
}
|
||||
|
||||
Button *GUI_v1::addButtonToList(Button *list, Button *newButton) {
|
||||
if (!newButton)
|
||||
return list;
|
||||
|
||||
newButton->nextButton = nullptr;
|
||||
|
||||
if (list) {
|
||||
Button *cur = list;
|
||||
while (cur->nextButton)
|
||||
cur = cur->nextButton;
|
||||
cur->nextButton = newButton;
|
||||
} else {
|
||||
list = newButton;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void GUI_v1::initMenuLayout(Menu &menu) {
|
||||
if (menu.x == -1)
|
||||
menu.x = (320 - menu.width) >> 1;
|
||||
if (menu.y == -1)
|
||||
menu.y = (200 - menu.height) >> 1;
|
||||
|
||||
for (int i = 0; i < menu.numberOfItems; ++i) {
|
||||
if (menu.item[i].x == -1)
|
||||
menu.item[i].x = (menu.width - menu.item[i].width) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_v1::initMenu(Menu &menu) {
|
||||
_menuButtonList = nullptr;
|
||||
|
||||
int textX;
|
||||
int textY;
|
||||
|
||||
int menu_x2 = menu.width + menu.x - 1;
|
||||
int menu_y2 = menu.height + menu.y - 1;
|
||||
|
||||
_screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bkgdColor);
|
||||
_screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2);
|
||||
|
||||
if (menu.titleX != -1)
|
||||
textX = menu.titleX;
|
||||
else
|
||||
textX = getMenuCenterStringX(getMenuTitle(menu), menu.x, menu_x2);
|
||||
|
||||
textY = menu.y + menu.titleY;
|
||||
|
||||
if (_vm->game() == GI_LOL) {
|
||||
printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9);
|
||||
} else {
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0);
|
||||
printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0);
|
||||
}
|
||||
|
||||
assert (menu.numberOfItems <= ARRAYSIZE(menu.item));
|
||||
|
||||
int x1, y1, x2, y2;
|
||||
for (int i = 0; i < menu.numberOfItems; ++i) {
|
||||
if (!menu.item[i].enabled)
|
||||
continue;
|
||||
|
||||
x1 = menu.x + menu.item[i].x;
|
||||
y1 = menu.y + menu.item[i].y;
|
||||
|
||||
x2 = x1 + menu.item[i].width - 1;
|
||||
y2 = y1 + menu.item[i].height - 1;
|
||||
|
||||
Button *menuButtonData = getButtonListData() + i;
|
||||
menuButtonData->nextButton = nullptr;
|
||||
menuButtonData->x = x1;
|
||||
menuButtonData->y = y1;
|
||||
menuButtonData->width = menu.item[i].width - 1;
|
||||
menuButtonData->height = menu.item[i].height - 1;
|
||||
menuButtonData->buttonCallback = menu.item[i].callback;
|
||||
menuButtonData->keyCode = menu.item[i].keyCode;
|
||||
menuButtonData->keyCode2 = 0;
|
||||
menuButtonData->arg = menu.item[i].itemId;
|
||||
|
||||
_menuButtonList = addButtonToList(_menuButtonList, menuButtonData);
|
||||
|
||||
_screen->fillRect(x1, y1, x2, y2, menu.item[i].bkgdColor);
|
||||
_screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2);
|
||||
|
||||
if (!getMenuItemTitle(menu.item[i]).empty()) {
|
||||
if (menu.item[i].titleX != -1)
|
||||
textX = x1 + menu.item[i].titleX + 3;
|
||||
else
|
||||
textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
||||
|
||||
textY = y1 + _menuLabelYOffset;
|
||||
if (_vm->game() == GI_LOL) {
|
||||
if (i == menu.highlightedItem)
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8);
|
||||
else
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8);
|
||||
} else {
|
||||
Screen::FontId of = _screen->_currentFont;
|
||||
if (menu.item[i].saveSlot > 0)
|
||||
_screen->setFont((_vm->gameFlags().lang == Common::ZH_CHN || _vm->gameFlags().lang == Common::ZH_TWN) ? Screen::FID_CHINESE_FNT : (_vm->gameFlags().lang == Common::KO_KOR ? Screen::FID_KOREAN_FNT : Screen::FID_8_FNT));
|
||||
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
||||
|
||||
if (i == menu.highlightedItem)
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
|
||||
else
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
|
||||
|
||||
_screen->setFont(of);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < menu.numberOfItems; ++i) {
|
||||
if (!getMenuItemLabel(menu.item[i]).empty()) {
|
||||
if (_vm->game() == GI_LOL) {
|
||||
menu.item[i].labelX = menu.item[i].x - 1;
|
||||
menu.item[i].labelY = menu.item[i].y + 3;
|
||||
printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10);
|
||||
} else {
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0);
|
||||
printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menuItemLabelColor(), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (menu.scrollUpButtonX != -1) {
|
||||
Button *scrollUpButton = getScrollUpButton();
|
||||
scrollUpButton->x = menu.scrollUpButtonX + menu.x;
|
||||
scrollUpButton->y = menu.scrollUpButtonY + menu.y;
|
||||
scrollUpButton->buttonCallback = getScrollUpButtonHandler();
|
||||
scrollUpButton->nextButton = nullptr;
|
||||
scrollUpButton->mouseWheel = -1;
|
||||
|
||||
_menuButtonList = addButtonToList(_menuButtonList, scrollUpButton);
|
||||
updateMenuButton(scrollUpButton);
|
||||
|
||||
Button *scrollDownButton = getScrollDownButton();
|
||||
scrollDownButton->x = menu.scrollDownButtonX + menu.x;
|
||||
scrollDownButton->y = menu.scrollDownButtonY + menu.y;
|
||||
scrollDownButton->buttonCallback = getScrollDownButtonHandler();
|
||||
scrollDownButton->nextButton = nullptr;
|
||||
scrollDownButton->mouseWheel = 1;
|
||||
|
||||
_menuButtonList = addButtonToList(_menuButtonList, scrollDownButton);
|
||||
updateMenuButton(scrollDownButton);
|
||||
}
|
||||
|
||||
_screen->updateScreen();
|
||||
}
|
||||
|
||||
void GUI_v1::processHighlights(Menu &menu) {
|
||||
int x1, y1, x2, y2;
|
||||
Common::Point p = _vm->getMousePos();
|
||||
int mouseX = p.x;
|
||||
int mouseY = p.y;
|
||||
|
||||
if (_vm->game() == GI_LOL && menu.highlightedItem != 255) {
|
||||
// LoL doesn't have default highlighted items.
|
||||
// We use a highlightedItem value of 255 for this.
|
||||
|
||||
// With LoL no highlighting should take place unless the
|
||||
// mouse cursor moves over a button. The highlighting should end
|
||||
// when the mouse cursor leaves the button.
|
||||
if (menu.item[menu.highlightedItem].enabled)
|
||||
redrawText(menu);
|
||||
}
|
||||
|
||||
for (int i = 0; i < menu.numberOfItems; ++i) {
|
||||
if (!menu.item[i].enabled)
|
||||
continue;
|
||||
|
||||
x1 = menu.x + menu.item[i].x;
|
||||
y1 = menu.y + menu.item[i].y;
|
||||
|
||||
x2 = x1 + menu.item[i].width;
|
||||
y2 = y1 + menu.item[i].height;
|
||||
|
||||
if (mouseX > x1 && mouseX < x2 &&
|
||||
mouseY > y1 && mouseY < y2) {
|
||||
|
||||
if (menu.highlightedItem != i || _vm->game() == GI_LOL) {
|
||||
if (_vm->game() != GI_LOL) {
|
||||
if (menu.item[menu.highlightedItem].enabled)
|
||||
redrawText(menu);
|
||||
}
|
||||
|
||||
menu.highlightedItem = i;
|
||||
redrawHighlight(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_screen->updateScreen();
|
||||
}
|
||||
|
||||
void GUI_v1::redrawText(const Menu &menu) {
|
||||
int textX;
|
||||
int i = menu.highlightedItem;
|
||||
|
||||
int x1 = menu.x + menu.item[i].x;
|
||||
int y1 = menu.y + menu.item[i].y;
|
||||
|
||||
int x2 = x1 + menu.item[i].width - 1;
|
||||
|
||||
if (menu.item[i].titleX >= 0)
|
||||
textX = x1 + menu.item[i].titleX + 3;
|
||||
else
|
||||
textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
||||
|
||||
int textY = y1 + _menuLabelYOffset;
|
||||
if (_vm->game() == GI_LOL) {
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8);
|
||||
} else {
|
||||
Screen::FontId of = _screen->_currentFont;
|
||||
if (menu.item[i].saveSlot > 0)
|
||||
_screen->setFont((_vm->gameFlags().lang == Common::ZH_CHN || _vm->gameFlags().lang == Common::ZH_TWN) ? Screen::FID_CHINESE_FNT : (_vm->gameFlags().lang == Common::KO_KOR ? Screen::FID_KOREAN_FNT : Screen::FID_8_FNT));
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
|
||||
_screen->setFont(of);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_v1::redrawHighlight(const Menu &menu) {
|
||||
int textX;
|
||||
int i = menu.highlightedItem;
|
||||
|
||||
int x1 = menu.x + menu.item[i].x;
|
||||
int y1 = menu.y + menu.item[i].y;
|
||||
|
||||
int x2 = x1 + menu.item[i].width - 1;
|
||||
|
||||
if (menu.item[i].titleX != -1)
|
||||
textX = x1 + menu.item[i].titleX + 3;
|
||||
else
|
||||
textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
||||
|
||||
int textY = y1 + _menuLabelYOffset;
|
||||
|
||||
if (_vm->game() == GI_LOL) {
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8);
|
||||
} else {
|
||||
Screen::FontId of = _screen->_currentFont;
|
||||
if (menu.item[i].saveSlot > 0)
|
||||
_screen->setFont((_vm->gameFlags().lang == Common::ZH_CHN || _vm->gameFlags().lang == Common::ZH_TWN) ? Screen::FID_CHINESE_FNT : (_vm->gameFlags().lang == Common::KO_KOR ? Screen::FID_KOREAN_FNT : Screen::FID_8_FNT));
|
||||
if (_vm->gameFlags().platform != Common::kPlatformAmiga)
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
||||
printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
|
||||
_screen->setFont(of);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_v1::updateAllMenuButtons() {
|
||||
for (Button *cur = _menuButtonList; cur; cur = cur->nextButton)
|
||||
updateMenuButton(cur);
|
||||
}
|
||||
|
||||
void GUI_v1::updateMenuButton(Button *button) {
|
||||
if (!_displayMenu)
|
||||
return;
|
||||
|
||||
updateButton(button);
|
||||
}
|
||||
|
||||
void GUI_v1::updateButton(Button *button) {
|
||||
if (!button || (button->flags & 8))
|
||||
return;
|
||||
|
||||
if (button->flags2 & 1)
|
||||
button->flags2 &= 0xFFF7;
|
||||
else
|
||||
button->flags2 |= 8;
|
||||
|
||||
button->flags2 &= 0xFFFC;
|
||||
|
||||
if (button->flags2 & 4)
|
||||
button->flags2 |= 0x10;
|
||||
else
|
||||
button->flags2 &= 0xEEEF;
|
||||
|
||||
button->flags2 &= 0xFFFB;
|
||||
|
||||
processButton(button);
|
||||
}
|
||||
|
||||
int GUI_v1::redrawButtonCallback(Button *button) {
|
||||
if (!_displayMenu)
|
||||
return 0;
|
||||
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 17);
|
||||
else
|
||||
_screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xF8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v1::redrawShadedButtonCallback(Button *button) {
|
||||
if (!_displayMenu)
|
||||
return 0;
|
||||
|
||||
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
||||
_screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 31, 18);
|
||||
else
|
||||
_screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xF9, 0xFA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GUI_v1::checkTextfieldInput() {
|
||||
Common::Event event;
|
||||
|
||||
uint32 now = _vm->_system->getMillis();
|
||||
|
||||
bool running = true;
|
||||
int keys = 0;
|
||||
while (_vm->_eventMan->pollEvent(event) && running) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYDOWN:
|
||||
if (event.kbd.keycode == Common::KEYCODE_q && event.kbd.hasFlags(Common::KBD_CTRL))
|
||||
_vm->quitGame();
|
||||
else
|
||||
_keyPressed = event.kbd;
|
||||
running = false;
|
||||
break;
|
||||
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_LBUTTONUP: {
|
||||
Common::Point pos = _vm->getMousePos();
|
||||
_vm->_mouseX = pos.x;
|
||||
_vm->_mouseY = pos.y;
|
||||
keys = event.type == Common::EVENT_LBUTTONDOWN ? 199 : (200 | 0x800);
|
||||
running = false;
|
||||
} break;
|
||||
|
||||
case Common::EVENT_MOUSEMOVE: {
|
||||
Common::Point pos = _vm->getMousePos();
|
||||
_vm->_mouseX = pos.x;
|
||||
_vm->_mouseY = pos.y;
|
||||
|
||||
_screen->updateBackendScreen(true);
|
||||
_lastScreenUpdate = now;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (now - _lastScreenUpdate > 50) {
|
||||
_screen->updateBackendScreen(true);
|
||||
_lastScreenUpdate = now;
|
||||
}
|
||||
|
||||
processButtonList(_menuButtonList, keys | 0x8000, 0);
|
||||
_vm->_system->delayMillis(3);
|
||||
}
|
||||
|
||||
void GUI_v1::printMenuText(const Common::String &str, int x, int y, uint8 c0, uint8 c1, uint8 c2) {
|
||||
_text->printText(str.c_str(), x, y, c0, c1, c2);
|
||||
}
|
||||
|
||||
int GUI_v1::getMenuCenterStringX(const Common::String &str, int x1, int x2) {
|
||||
return _text->getCenterStringX(str.c_str(), x1, x2);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(nullptr) {
|
||||
_screen = _vm->screen();
|
||||
_nextUpdate = 0;
|
||||
_system = g_system;
|
||||
memset(&_static, 0, sizeof(_static));
|
||||
memset(&_animIntern, 0, sizeof(_animIntern));
|
||||
}
|
||||
|
||||
void MainMenu::init(StaticData data, Animation anim) {
|
||||
_static = data;
|
||||
_anim = anim;
|
||||
_animIntern.curFrame = _anim.startFrame;
|
||||
_animIntern.direction = 1;
|
||||
}
|
||||
|
||||
void MainMenu::updateAnimation() {
|
||||
if (_anim.anim) {
|
||||
uint32 now = _system->getMillis();
|
||||
if (now > _nextUpdate) {
|
||||
_nextUpdate = now + _anim.delay * _vm->tickLength();
|
||||
|
||||
_anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0, 0, nullptr, nullptr);
|
||||
_animIntern.curFrame += _animIntern.direction;
|
||||
if (_animIntern.curFrame < _anim.startFrame) {
|
||||
_animIntern.curFrame = _anim.startFrame;
|
||||
_animIntern.direction = 1;
|
||||
} else if (_animIntern.curFrame > _anim.endFrame) {
|
||||
_animIntern.curFrame = _anim.endFrame;
|
||||
_animIntern.direction = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_screen->updateScreen();
|
||||
}
|
||||
|
||||
bool MainMenu::getInput() {
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _vm->getEventManager();
|
||||
|
||||
bool updateScreen = false;
|
||||
|
||||
while (eventMan->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
return true;
|
||||
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
updateScreen = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateScreen)
|
||||
_screen->updateBackendScreen(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
int MainMenu::handle(int dim) {
|
||||
int command = -1;
|
||||
|
||||
uint8 colorMap[16];
|
||||
memset(colorMap, 0, sizeof(colorMap));
|
||||
_screen->setTextColorMap(colorMap);
|
||||
|
||||
Screen::FontId oldFont = _screen->setFont(_static.font);
|
||||
int charWidthBackUp = _screen->_charSpacing;
|
||||
|
||||
if (_vm->game() != GI_LOL)
|
||||
_screen->_charSpacing = -2;
|
||||
_screen->setScreenDim(dim);
|
||||
|
||||
int backUpX = _screen->_curDim->sx;
|
||||
int backUpY = _screen->_curDim->sy;
|
||||
int backUpWidth = _screen->_curDim->w;
|
||||
int backUpHeight = _screen->_curDim->h;
|
||||
_screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3);
|
||||
|
||||
int x = _screen->_curDim->sx << 3;
|
||||
int y = _screen->_curDim->sy;
|
||||
int width = _screen->_curDim->w << 3;
|
||||
int height = _screen->_curDim->h;
|
||||
|
||||
if (_static.boxCoords) {
|
||||
x = _static.boxCoords[0];
|
||||
y = _static.boxCoords[1];
|
||||
width = _static.boxCoords[2];
|
||||
height = _static.boxCoords[3];
|
||||
}
|
||||
|
||||
drawBox(x, y, width, height, 1);
|
||||
drawBox(x + 1, y + 1, width - 2, height - 2, 0);
|
||||
|
||||
int selected = 0;
|
||||
|
||||
draw(selected);
|
||||
|
||||
while (!_screen->isMouseVisible())
|
||||
_screen->showMouse();
|
||||
|
||||
int fh = _screen->getFontHeight() + _static.lineSpacingAdjust;
|
||||
int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;
|
||||
|
||||
Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * _static.menuTable[3]);
|
||||
|
||||
while (!_vm->shouldQuit()) {
|
||||
updateAnimation();
|
||||
bool mousePressed = getInput();
|
||||
|
||||
Common::Point mouse = _vm->getMousePos();
|
||||
if (menuRect.contains(mouse)) {
|
||||
int item = (mouse.y - menuRect.top) / fh;
|
||||
|
||||
if (item != selected) {
|
||||
printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5, _static.strings[selected]);
|
||||
printString("%s", textPos, menuRect.top + item * fh, _static.menuTable[6], 0, 5, _static.strings[item]);
|
||||
|
||||
selected = item;
|
||||
}
|
||||
|
||||
if (mousePressed) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5, _static.strings[selected]);
|
||||
_screen->updateScreen();
|
||||
_system->delayMillis(50);
|
||||
printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[6], 0, 5, _static.strings[selected]);
|
||||
_screen->updateScreen();
|
||||
_system->delayMillis(50);
|
||||
}
|
||||
command = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_system->delayMillis(10);
|
||||
}
|
||||
|
||||
if (_vm->shouldQuit())
|
||||
command = -1;
|
||||
|
||||
_screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0);
|
||||
_screen->_charSpacing = charWidthBackUp;
|
||||
_screen->setFont(oldFont);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
void MainMenu::draw(int select) {
|
||||
int top = _static.boxCoords ? _static.boxCoords[1] : _screen->_curDim->sy;
|
||||
top += _static.menuTable[1];
|
||||
int fh = _screen->getFontHeight() + _static.lineSpacingAdjust;
|
||||
|
||||
for (int i = 0; i < _static.menuTable[3]; ++i) {
|
||||
int curY = top + i * fh;
|
||||
int color = (i == select) ? _static.menuTable[6] : _static.menuTable[5];
|
||||
printString("%s", ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5, _static.strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::drawBox(int x, int y, int w, int h, int fill) {
|
||||
--w; --h;
|
||||
|
||||
if (fill)
|
||||
_screen->fillRect(x, y, x + w, y + h, _static.colorTable[0]);
|
||||
|
||||
_screen->drawClippedLine(x, y + h, x + w, y + h, _static.colorTable[1]);
|
||||
_screen->drawClippedLine(x + w, y, x + w, y + h, _static.colorTable[1]);
|
||||
_screen->drawClippedLine(x, y, x + w, y, _static.colorTable[2]);
|
||||
_screen->drawClippedLine(x, y, x, y + h, _static.colorTable[2]);
|
||||
|
||||
_screen->setPagePixel(_screen->_curPage, x, y + h, _static.colorTable[3]);
|
||||
_screen->setPagePixel(_screen->_curPage, x + w, y, _static.colorTable[3]);
|
||||
}
|
||||
|
||||
void MainMenu::printString(const char *format, int x, int y, int col1, int col2, int flags, ...) {
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
va_list vaList;
|
||||
va_start(vaList, flags);
|
||||
Common::String string = Common::String::vformat(format, vaList);
|
||||
va_end(vaList);
|
||||
|
||||
Common::String revBuffer;
|
||||
const char *cstr = string.c_str();
|
||||
if (_vm->gameFlags().lang == Common::HE_ISR) {
|
||||
for (int i = string.size() - 1; i >= 0; --i)
|
||||
revBuffer += string[i];
|
||||
cstr = revBuffer.c_str();
|
||||
}
|
||||
|
||||
if (flags & 1)
|
||||
x -= _screen->getTextWidth(cstr) >> 1;
|
||||
|
||||
if (flags & 2)
|
||||
x -= _screen->getTextWidth(cstr);
|
||||
|
||||
if (_vm->gameFlags().use16ColorMode)
|
||||
flags &= 3;
|
||||
|
||||
if (flags & 4) {
|
||||
_screen->printText(cstr, x - 1, y, _static.altColor, col2);
|
||||
_screen->printText(cstr, x, y + 1, _static.altColor, col2);
|
||||
}
|
||||
|
||||
if (flags & 8) {
|
||||
_screen->printText(cstr, x - 1, y, 227, col2);
|
||||
_screen->printText(cstr, x, y + 1, 227, col2);
|
||||
}
|
||||
|
||||
_screen->printText(cstr, x, y, col1, col2);
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
203
engines/kyra/gui/gui_v1.h
Normal file
203
engines/kyra/gui/gui_v1.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_V1_H
|
||||
#define KYRA_GUI_V1_H
|
||||
|
||||
#include "kyra/gui/gui.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
struct MenuItem {
|
||||
bool enabled;
|
||||
|
||||
Common::String itemString;
|
||||
uint16 itemId;
|
||||
bool useItemString;
|
||||
|
||||
int16 x, y;
|
||||
uint16 width, height;
|
||||
|
||||
uint8 textColor, highlightColor;
|
||||
|
||||
int16 titleX;
|
||||
|
||||
uint8 color1, color2;
|
||||
uint8 bkgdColor;
|
||||
|
||||
Button::Callback callback;
|
||||
|
||||
int16 saveSlot;
|
||||
|
||||
const char *labelString;
|
||||
uint16 labelId;
|
||||
int16 labelX, labelY;
|
||||
|
||||
uint16 keyCode;
|
||||
};
|
||||
|
||||
struct Menu {
|
||||
int16 x, y;
|
||||
uint16 width, height;
|
||||
|
||||
uint8 bkgdColor;
|
||||
uint8 color1, color2;
|
||||
|
||||
const char *menuNameString;
|
||||
uint16 menuNameId;
|
||||
|
||||
uint8 textColor;
|
||||
int16 titleX, titleY;
|
||||
|
||||
uint8 highlightedItem;
|
||||
|
||||
uint8 numberOfItems;
|
||||
|
||||
int16 scrollUpButtonX, scrollUpButtonY;
|
||||
int16 scrollDownButtonX, scrollDownButtonY;
|
||||
|
||||
MenuItem item[7];
|
||||
};
|
||||
|
||||
class TextDisplayer;
|
||||
|
||||
class GUI_v1 : public GUI {
|
||||
public:
|
||||
GUI_v1(KyraEngine_v1 *vm);
|
||||
~GUI_v1() override {}
|
||||
|
||||
// button specific
|
||||
virtual Button *addButtonToList(Button *list, Button *newButton);
|
||||
|
||||
void processButton(Button *button) override = 0;
|
||||
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) override = 0;
|
||||
|
||||
virtual int redrawShadedButtonCallback(Button *button);
|
||||
virtual int redrawButtonCallback(Button *button);
|
||||
|
||||
// menu specific
|
||||
virtual void initMenuLayout(Menu &menu);
|
||||
void initMenu(Menu &menu);
|
||||
|
||||
void processHighlights(Menu &menu);
|
||||
|
||||
// utilities for thumbnail creation
|
||||
void createScreenThumbnail(Graphics::Surface &dst) override = 0;
|
||||
|
||||
protected:
|
||||
TextDisplayer *_text;
|
||||
|
||||
Button *_menuButtonList;
|
||||
bool _displayMenu;
|
||||
bool _displaySubMenu;
|
||||
bool _cancelSubMenu;
|
||||
|
||||
virtual void printMenuText(const Common::String &str, int x, int y, uint8 c0, uint8 c1, uint8 c2);
|
||||
virtual int getMenuCenterStringX(const Common::String &str, int x1, int x2);
|
||||
|
||||
Button::Callback _redrawShadedButtonFunctor;
|
||||
Button::Callback _redrawButtonFunctor;
|
||||
|
||||
virtual Button *getButtonListData() = 0;
|
||||
virtual Button *getScrollUpButton() = 0;
|
||||
virtual Button *getScrollDownButton() = 0;
|
||||
|
||||
virtual Button::Callback getScrollUpButtonHandler() const = 0;
|
||||
virtual Button::Callback getScrollDownButtonHandler() const = 0;
|
||||
|
||||
virtual uint8 defaultColor1() const = 0;
|
||||
virtual uint8 defaultColor2() const = 0;
|
||||
virtual uint8 menuItemLabelColor() const = 0;
|
||||
|
||||
virtual Common::String getMenuTitle(const Menu &menu) = 0;
|
||||
virtual Common::String getMenuItemTitle(const MenuItem &menuItem) = 0;
|
||||
virtual Common::String getMenuItemLabel(const MenuItem &menuItem) = 0;
|
||||
|
||||
void updateAllMenuButtons();
|
||||
void updateMenuButton(Button *button);
|
||||
virtual void updateButton(Button *button);
|
||||
|
||||
void redrawText(const Menu &menu);
|
||||
void redrawHighlight(const Menu &menu);
|
||||
|
||||
uint32 _lastScreenUpdate;
|
||||
void checkTextfieldInput();
|
||||
|
||||
int _menuLabelYOffset;
|
||||
};
|
||||
|
||||
class Movie;
|
||||
|
||||
class MainMenu {
|
||||
public:
|
||||
MainMenu(KyraEngine_v1 *vm);
|
||||
virtual ~MainMenu() {}
|
||||
|
||||
struct Animation {
|
||||
Animation() : anim(0), startFrame(0), endFrame(0), delay(0) {}
|
||||
|
||||
Movie *anim;
|
||||
int startFrame;
|
||||
int endFrame;
|
||||
int delay;
|
||||
};
|
||||
|
||||
struct StaticData {
|
||||
const char *strings[5];
|
||||
|
||||
uint8 menuTable[7];
|
||||
uint8 colorTable[4];
|
||||
const uint8 *boxCoords;
|
||||
|
||||
Screen::FontId font;
|
||||
int8 lineSpacingAdjust;
|
||||
|
||||
uint8 altColor;
|
||||
};
|
||||
|
||||
void init(StaticData data, Animation anim);
|
||||
int handle(int dim);
|
||||
private:
|
||||
KyraEngine_v1 *_vm;
|
||||
Screen *_screen;
|
||||
OSystem *_system;
|
||||
|
||||
StaticData _static;
|
||||
struct AnimIntern {
|
||||
int curFrame;
|
||||
int direction;
|
||||
};
|
||||
Animation _anim;
|
||||
AnimIntern _animIntern;
|
||||
|
||||
uint32 _nextUpdate;
|
||||
|
||||
void updateAnimation();
|
||||
void draw(int select);
|
||||
void drawBox(int x, int y, int w, int h, int fill);
|
||||
bool getInput();
|
||||
|
||||
void printString(const char *string, int x, int y, int col1, int col2, int flags, ...) GCC_PRINTF(2, 8);
|
||||
};
|
||||
|
||||
} // end of namesapce Kyra
|
||||
|
||||
#endif
|
||||
911
engines/kyra/gui/gui_v2.cpp
Normal file
911
engines/kyra/gui/gui_v2.cpp
Normal file
@@ -0,0 +1,911 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/gui/gui_v2.h"
|
||||
#include "kyra/graphics/screen_v2.h"
|
||||
#include "kyra/text/text.h"
|
||||
#include "kyra/engine/util.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
GUI_v2::GUI_v2(KyraEngine_v2 *vm) : GUI_v1(vm), _vm(vm), _screen(vm->screen_v2()) {
|
||||
_backUpButtonList = _specialProcessButton = nullptr;
|
||||
_buttonListChanged = false;
|
||||
_flagsModifier = 0;
|
||||
|
||||
_currentMenu = nullptr;
|
||||
_isDeathMenu = false;
|
||||
_isSaveMenu = false;
|
||||
_isLoadMenu = false;
|
||||
_scrollUpFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollUpButton);
|
||||
_scrollDownFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollDownButton);
|
||||
_sliderHandlerFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::sliderHandler);
|
||||
_savegameOffset = 0;
|
||||
_isDeleteMenu = false;
|
||||
_saveMenuFont = Screen::FID_8_FNT;
|
||||
_saveMenuCursor = Common::Rect(1, 1, 7, 8);
|
||||
_saveLoadNumSlots = 5;
|
||||
_isChoiceMenu = _isOptionsMenu = _madeSave = _loadedSave = _restartGame = _reloadTemporarySave = false;
|
||||
_noLoadProcess = _noSaveProcess = _choice = _finishNameInput = _cancelNameInput = false;
|
||||
_saveSlot = _slotToDelete = 0;
|
||||
|
||||
if (vm->game() == GI_KYRA2 && vm->gameFlags().lang == Common::ZH_TWN) {
|
||||
_saveMenuFont = Screen::FID_CHINESE_FNT;
|
||||
_saveMenuCursor = Common::Rect(0, 0, 8, 14);
|
||||
_saveLoadNumSlots = 4;
|
||||
}
|
||||
|
||||
if (vm->gameFlags().lang == Common::Language::ZH_TWN && vm->game() == GI_LOL) {
|
||||
_saveMenuFont = Screen::FID_CHINESE_FNT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button *GUI_v2::addButtonToList(Button *list, Button *newButton) {
|
||||
list = GUI_v1::addButtonToList(list, newButton);
|
||||
_buttonListChanged = true;
|
||||
return list;
|
||||
}
|
||||
|
||||
void GUI_v2::processButton(Button *button) {
|
||||
if (!button)
|
||||
return;
|
||||
|
||||
if (button->flags & 8) {
|
||||
if (button->flags & 0x10) {
|
||||
// XXX
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int entry = button->flags2 & 5;
|
||||
|
||||
byte val1 = 0, val2 = 0, val3 = 0;
|
||||
const uint8 *dataPtr = nullptr;
|
||||
Button::Callback callback;
|
||||
if (entry == 1) {
|
||||
val1 = button->data1Val1;
|
||||
dataPtr = button->data1ShapePtr;
|
||||
callback = button->data1Callback;
|
||||
val2 = button->data1Val2;
|
||||
val3 = button->data1Val3;
|
||||
} else if (entry == 4 || entry == 5) {
|
||||
val1 = button->data2Val1;
|
||||
dataPtr = button->data2ShapePtr;
|
||||
callback = button->data2Callback;
|
||||
val2 = button->data2Val2;
|
||||
val3 = button->data2Val3;
|
||||
} else {
|
||||
val1 = button->data0Val1;
|
||||
dataPtr = button->data0ShapePtr;
|
||||
callback = button->data0Callback;
|
||||
val2 = button->data0Val2;
|
||||
val3 = button->data0Val3;
|
||||
}
|
||||
|
||||
int x = 0, y = 0, x2 = 0, y2 = 0;
|
||||
|
||||
x = button->x;
|
||||
if (x < 0)
|
||||
x += _screen->getScreenDim(button->dimTableIndex)->w << 3;
|
||||
x += _screen->getScreenDim(button->dimTableIndex)->sx << 3;
|
||||
x2 = x + button->width - 1;
|
||||
|
||||
y = button->y;
|
||||
if (y < 0)
|
||||
y += _screen->getScreenDim(button->dimTableIndex)->h << 3;
|
||||
y += _screen->getScreenDim(button->dimTableIndex)->sy << 3;
|
||||
y2 = y + button->height - 1;
|
||||
|
||||
switch (val1 - 1) {
|
||||
case 0:
|
||||
_screen->drawShape(_screen->_curPage, dataPtr, x, y, button->dimTableIndex, 0x10);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_screen->printText((const char *)dataPtr, x, y, val2, val3);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (callback)
|
||||
(*callback)(button);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
_screen->drawBox(x, y, x2, y2, val2);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
_screen->fillRect(x, y, x2, y2, val2, -1, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWheel) {
|
||||
if (!buttonList)
|
||||
return inputFlag & 0x7FFF;
|
||||
|
||||
if (_backUpButtonList != buttonList || _buttonListChanged) {
|
||||
_specialProcessButton = nullptr;
|
||||
//flagsModifier |= 0x2200;
|
||||
_backUpButtonList = buttonList;
|
||||
_buttonListChanged = false;
|
||||
|
||||
while (buttonList) {
|
||||
processButton(buttonList);
|
||||
buttonList = buttonList->nextButton;
|
||||
}
|
||||
}
|
||||
|
||||
Common::Point p = _vm->getMousePos();
|
||||
int mouseX = _vm->_mouseX = p.x;
|
||||
int mouseY = _vm->_mouseY = p.y;
|
||||
|
||||
uint16 flags = 0;
|
||||
|
||||
if (1/*!_screen_cursorDisable*/) {
|
||||
uint16 inFlags = inputFlag & 0xFF;
|
||||
uint16 temp = 0;
|
||||
|
||||
// HACK: inFlags == 200 is our left button (up)
|
||||
if (inFlags == 199 || inFlags == 200)
|
||||
temp = 0x1000;
|
||||
if (inFlags == 198)
|
||||
temp = 0x100;
|
||||
|
||||
if (inputFlag & 0x800)
|
||||
temp <<= 2;
|
||||
|
||||
flags |= temp;
|
||||
|
||||
_flagsModifier &= ~((temp & 0x4400) >> 1);
|
||||
_flagsModifier |= (temp & 0x1100) * 2;
|
||||
flags |= _flagsModifier;
|
||||
flags |= (_flagsModifier << 2) ^ 0x8800;
|
||||
}
|
||||
|
||||
buttonList = _backUpButtonList;
|
||||
if (_specialProcessButton) {
|
||||
buttonList = _specialProcessButton;
|
||||
if (_specialProcessButton->flags & 8)
|
||||
_specialProcessButton = nullptr;
|
||||
}
|
||||
|
||||
int returnValue = 0;
|
||||
while (buttonList) {
|
||||
if (buttonList->flags & 8) {
|
||||
buttonList = buttonList->nextButton;
|
||||
continue;
|
||||
}
|
||||
buttonList->flags2 &= ~0x18;
|
||||
buttonList->flags2 |= (buttonList->flags2 & 3) << 3;
|
||||
|
||||
int x = buttonList->x;
|
||||
if (x < 0)
|
||||
x += _screen->getScreenDim(buttonList->dimTableIndex)->w << 3;
|
||||
x += _screen->getScreenDim(buttonList->dimTableIndex)->sx << 3;
|
||||
|
||||
int y = buttonList->y;
|
||||
if (y < 0)
|
||||
y += _screen->getScreenDim(buttonList->dimTableIndex)->h;
|
||||
y += _screen->getScreenDim(buttonList->dimTableIndex)->sy;
|
||||
|
||||
bool progress = false;
|
||||
|
||||
if (mouseX >= x && mouseY >= y && mouseX <= x + buttonList->width && mouseY <= y + buttonList->height)
|
||||
progress = true;
|
||||
|
||||
buttonList->flags2 &= ~0x80;
|
||||
uint16 inFlags = inputFlag & 0x7FFF;
|
||||
if (inFlags) {
|
||||
if (buttonList->keyCode == inFlags) {
|
||||
progress = true;
|
||||
flags = buttonList->flags & 0x0F00;
|
||||
buttonList->flags2 |= 0x80;
|
||||
inputFlag = 0;
|
||||
_specialProcessButton = buttonList;
|
||||
} else if (buttonList->keyCode2 == inFlags) {
|
||||
flags = buttonList->flags & 0xF000;
|
||||
if (!flags)
|
||||
flags = buttonList->flags & 0x0F00;
|
||||
progress = true;
|
||||
buttonList->flags2 |= 0x80;
|
||||
inputFlag = 0;
|
||||
_specialProcessButton = buttonList;
|
||||
}
|
||||
}
|
||||
|
||||
bool unk1 = false;
|
||||
|
||||
if (mouseWheel && buttonList->mouseWheel == mouseWheel) {
|
||||
progress = true;
|
||||
unk1 = true;
|
||||
}
|
||||
|
||||
if (!progress)
|
||||
buttonList->flags2 &= ~6;
|
||||
|
||||
if ((flags & 0x3300) && (buttonList->flags & 4) && progress && (buttonList == _specialProcessButton || !_specialProcessButton)) {
|
||||
buttonList->flags |= 6;
|
||||
if (!_specialProcessButton)
|
||||
_specialProcessButton = buttonList;
|
||||
} else if ((flags & 0x8800) && !(buttonList->flags & 4) && progress) {
|
||||
buttonList->flags2 |= 6;
|
||||
} else {
|
||||
buttonList->flags2 &= ~6;
|
||||
}
|
||||
|
||||
bool progressSwitch = false;
|
||||
if (!_specialProcessButton) {
|
||||
progressSwitch = progress;
|
||||
} else {
|
||||
if (_specialProcessButton->flags & 0x40)
|
||||
progressSwitch = (_specialProcessButton == buttonList);
|
||||
else
|
||||
progressSwitch = progress;
|
||||
}
|
||||
|
||||
if (progressSwitch) {
|
||||
if ((flags & 0x1100) && progress && !_specialProcessButton) {
|
||||
inputFlag = 0;
|
||||
_specialProcessButton = buttonList;
|
||||
}
|
||||
|
||||
if ((buttonList->flags & flags) && (progress || !(buttonList->flags & 1))) {
|
||||
uint16 combinedFlags = (buttonList->flags & flags);
|
||||
combinedFlags = ((combinedFlags & 0xF000) >> 4) | (combinedFlags & 0x0F00);
|
||||
combinedFlags >>= 8;
|
||||
|
||||
static const uint16 flagTable[] = {
|
||||
0x000, 0x100, 0x200, 0x100, 0x400, 0x100, 0x400, 0x100, 0x800, 0x100,
|
||||
0x200, 0x100, 0x400, 0x100, 0x400, 0x100
|
||||
};
|
||||
|
||||
assert(combinedFlags < ARRAYSIZE(flagTable));
|
||||
|
||||
switch (flagTable[combinedFlags]) {
|
||||
case 0x400:
|
||||
if (!(buttonList->flags & 1) || ((buttonList->flags & 1) && _specialProcessButton == buttonList)) {
|
||||
buttonList->flags2 ^= 1;
|
||||
returnValue = buttonList->index | 0x8000;
|
||||
unk1 = true;
|
||||
}
|
||||
|
||||
if (!(buttonList->flags & 4)) {
|
||||
buttonList->flags2 &= ~4;
|
||||
buttonList->flags2 &= ~2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x800:
|
||||
if (!(buttonList->flags & 4)) {
|
||||
buttonList->flags2 |= 4;
|
||||
buttonList->flags2 |= 2;
|
||||
}
|
||||
|
||||
if (!(buttonList->flags & 1))
|
||||
unk1 = true;
|
||||
break;
|
||||
|
||||
case 0x200:
|
||||
if (buttonList->flags & 4) {
|
||||
buttonList->flags2 |= 4;
|
||||
buttonList->flags2 |= 2;
|
||||
}
|
||||
|
||||
if (!(buttonList->flags & 1))
|
||||
unk1 = true;
|
||||
break;
|
||||
|
||||
case 0x100:
|
||||
default:
|
||||
buttonList->flags2 ^= 1;
|
||||
returnValue = buttonList->index | 0x8000;
|
||||
unk1 = true;
|
||||
if (buttonList->flags & 4) {
|
||||
buttonList->flags2 |= 4;
|
||||
buttonList->flags2 |= 2;
|
||||
}
|
||||
_specialProcessButton = buttonList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool unk2 = false;
|
||||
if ((flags & 0x2200) && progress) {
|
||||
buttonList->flags2 |= 6;
|
||||
if (!(buttonList->flags & 4) && !(buttonList->flags2 & 1)) {
|
||||
unk2 = true;
|
||||
buttonList->flags2 |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & 0x8800) == 0x8800) {
|
||||
_specialProcessButton = nullptr;
|
||||
if (!progress || (buttonList->flags & 4))
|
||||
buttonList->flags2 &= ~6;
|
||||
}
|
||||
|
||||
if (!progress && buttonList == _specialProcessButton && !(buttonList->flags & 0x40))
|
||||
_specialProcessButton = nullptr;
|
||||
|
||||
if ((buttonList->flags2 & 0x18) != ((buttonList->flags2 & 3) << 3))
|
||||
processButton(buttonList);
|
||||
|
||||
if (unk2)
|
||||
buttonList->flags2 &= ~1;
|
||||
|
||||
if (unk1) {
|
||||
buttonList->flags2 &= 0xFF;
|
||||
buttonList->flags2 |= flags;
|
||||
|
||||
if (buttonList->buttonCallback) {
|
||||
_vm->removeInputTop();
|
||||
if ((*buttonList->buttonCallback)(buttonList))
|
||||
break;
|
||||
}
|
||||
|
||||
if (buttonList->flags & 0x20)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_specialProcessButton == buttonList && (buttonList->flags & 0x40))
|
||||
break;
|
||||
|
||||
buttonList = buttonList->nextButton;
|
||||
}
|
||||
|
||||
if (!returnValue)
|
||||
returnValue = inputFlag & 0x7FFF;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void GUI_v2::updateButton(Button *button) {
|
||||
if (!button || (button->flags & 8))
|
||||
return;
|
||||
|
||||
if (button->flags2 & 1)
|
||||
button->flags2 |= 8;
|
||||
else
|
||||
button->flags2 |= ~8;
|
||||
|
||||
button->flags2 &= ~1;
|
||||
|
||||
if (button->flags2 & 4)
|
||||
button->flags2 |= 0x10;
|
||||
else
|
||||
button->flags2 &= ~0x10;
|
||||
|
||||
button->flags2 &= ~4;
|
||||
|
||||
processButton(button);
|
||||
}
|
||||
|
||||
void GUI_v2::getInput() {
|
||||
if (!_displayMenu)
|
||||
return;
|
||||
|
||||
_vm->checkInput(_menuButtonList);
|
||||
_vm->removeInputTop();
|
||||
if (_vm->shouldQuit()) {
|
||||
_displayMenu = false;
|
||||
_isLoadMenu = false;
|
||||
_isSaveMenu = false;
|
||||
_isOptionsMenu = false;
|
||||
_isDeleteMenu = false;
|
||||
}
|
||||
|
||||
_vm->delay(10);
|
||||
}
|
||||
|
||||
void GUI_v2::renewHighlight(Menu &menu) {
|
||||
if (!_displayMenu)
|
||||
return;
|
||||
|
||||
MenuItem &item = menu.item[menu.highlightedItem];
|
||||
int x = item.x + menu.x; int y = item.y + menu.y;
|
||||
int x2 = x + item.width - 1; int y2 = y + item.height - 1;
|
||||
redrawText(menu);
|
||||
_screen->fillRect(x + 2, y + 2, x2 - 2, y2 - 2, item.bkgdColor);
|
||||
redrawHighlight(menu);
|
||||
_screen->updateScreen();
|
||||
}
|
||||
|
||||
void GUI_v2::backUpPage1(uint8 *buffer) {
|
||||
_screen->copyRegionToBuffer(1, 0, 0, 320, 200, buffer);
|
||||
}
|
||||
|
||||
void GUI_v2::restorePage1(const uint8 *buffer) {
|
||||
_screen->copyBlockToPage(1, 0, 0, 320, 200, buffer);
|
||||
}
|
||||
|
||||
void GUI_v2::setupSavegameNames(Menu &menu, int num) {
|
||||
for (int i = 0; i < num; ++i) {
|
||||
menu.item[i].useItemString = true;
|
||||
menu.item[i].itemString = "";
|
||||
menu.item[i].saveSlot = -1;
|
||||
menu.item[i].enabled = false;
|
||||
}
|
||||
|
||||
int startSlot = 0;
|
||||
if (_isSaveMenu && _savegameOffset == 0)
|
||||
startSlot = 1;
|
||||
|
||||
KyraEngine_v2::SaveHeader header;
|
||||
Common::InSaveFile *in;
|
||||
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) {
|
||||
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != nullptr) {
|
||||
Common::String s = header.description;
|
||||
s = Util::convertString_GUItoKYRA(s);
|
||||
|
||||
if (_vm->gameFlags().lang == Common::JA_JPN || _vm->gameFlags().lang == Common::ZH_CHN || _vm->gameFlags().lang == Common::ZH_TWN) {
|
||||
// Strip special characters from GMM save dialog which might get misinterpreted as 2-byte characters
|
||||
for (Common::String::iterator ii = s.begin(); ii != s.end(); ++ii) {
|
||||
if (*ii < 32) // due to the signed char type this will also clean up everything >= 0x80
|
||||
*ii = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
// Trim long GMM save descriptions to fit our save slots
|
||||
_screen->_charSpacing = -2;
|
||||
int fC = _screen->getTextWidth(s.c_str());
|
||||
while (!s.empty() && fC > 240) {
|
||||
s.deleteLastChar();
|
||||
fC = _screen->getTextWidth(s.c_str());
|
||||
}
|
||||
_screen->_charSpacing = 0;
|
||||
|
||||
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
|
||||
menu.item[i].enabled = true;
|
||||
menu.item[i].useItemString = true;
|
||||
menu.item[i].itemString = Common::move(s);
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
|
||||
if (_savegameOffset == 0) {
|
||||
if (_isSaveMenu) {
|
||||
menu.item[0].saveSlot = -2;
|
||||
menu.item[0].enabled = true;
|
||||
menu.item[0].useItemString = true;
|
||||
menu.item[0].itemString = getTableString(_vm->gameFlags().isTalkie ? 10 : 18);
|
||||
} else {
|
||||
menu.item[0].useItemString = true;
|
||||
menu.item[0].itemString = getTableString(_vm->gameFlags().isTalkie ? 34 : 42, _vm->gameFlags().lang == Common::RU_RUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GUI_v2::scrollUpButton(Button *button) {
|
||||
updateMenuButton(button);
|
||||
|
||||
if (_savegameOffset == (_isDeleteMenu ? 1 : 0))
|
||||
return 0;
|
||||
|
||||
--_savegameOffset;
|
||||
if (_isLoadMenu) {
|
||||
setupSavegameNames(_loadMenu, _saveLoadNumSlots);
|
||||
// original calls something different here...
|
||||
initMenu(_loadMenu);
|
||||
} else if (_isSaveMenu || _isDeleteMenu) {
|
||||
setupSavegameNames(_saveMenu, _saveLoadNumSlots);
|
||||
// original calls something different here...
|
||||
initMenu(_saveMenu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::scrollDownButton(Button *button) {
|
||||
updateMenuButton(button);
|
||||
++_savegameOffset;
|
||||
|
||||
if (uint(_savegameOffset + _saveLoadNumSlots) >= _saveSlots.size())
|
||||
_savegameOffset = MAX<int>(_saveSlots.size() - _saveLoadNumSlots, _isDeleteMenu ? 1 : 0);
|
||||
|
||||
if (_isLoadMenu) {
|
||||
setupSavegameNames(_loadMenu, _saveLoadNumSlots);
|
||||
// original calls something different here...
|
||||
initMenu(_loadMenu);
|
||||
} else if (_isSaveMenu || _isDeleteMenu) {
|
||||
setupSavegameNames(_saveMenu, _saveLoadNumSlots);
|
||||
// original calls something different here...
|
||||
initMenu(_saveMenu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::resumeGame(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_displayMenu = false;
|
||||
if (!(_vm->game() == GI_KYRA2 && _vm->gameFlags().lang == Common::ZH_TWN))
|
||||
_screen->setFontStyles(_screen->_currentFont, Font::kStyleBorder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::quitOptionsMenu(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_isOptionsMenu = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::toggleWalkspeed(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
if (_vm->_configWalkspeed == 5)
|
||||
_vm->_configWalkspeed = 3;
|
||||
else
|
||||
_vm->_configWalkspeed = 5;
|
||||
_vm->setWalkspeed(_vm->_configWalkspeed);
|
||||
setupOptionsButtons();
|
||||
renewHighlight(_gameOptions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::toggleText(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
|
||||
if (_vm->textEnabled()) {
|
||||
if (_vm->speechEnabled())
|
||||
_vm->_configVoice = 1;
|
||||
else
|
||||
_vm->_configVoice = 3;
|
||||
} else {
|
||||
if (_vm->speechEnabled())
|
||||
_vm->_configVoice = 2;
|
||||
else
|
||||
_vm->_configVoice = 0;
|
||||
}
|
||||
|
||||
setupOptionsButtons();
|
||||
renewHighlight(_gameOptions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::clickLoadSlot(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
|
||||
int index = caller->index - _menuButtons[0].index;
|
||||
assert(index >= 0 && index <= 6);
|
||||
MenuItem &item = _loadMenu.item[index];
|
||||
|
||||
if (item.saveSlot >= 0) {
|
||||
_vm->_gameToLoad = item.saveSlot;
|
||||
_isLoadMenu = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::cancelLoadMenu(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_isLoadMenu = false;
|
||||
_noLoadProcess = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::saveMenu(Button *caller) {
|
||||
updateSaveFileList(_vm->_targetName);
|
||||
|
||||
updateMenuButton(caller);
|
||||
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
|
||||
_isSaveMenu = true;
|
||||
_noSaveProcess = false;
|
||||
_saveSlot = -1;
|
||||
_savegameOffset = 0;
|
||||
setupSavegameNames(_saveMenu, _saveLoadNumSlots);
|
||||
initMenu(_saveMenu);
|
||||
|
||||
updateAllMenuButtons();
|
||||
|
||||
while (_isSaveMenu) {
|
||||
processHighlights(_saveMenu);
|
||||
getInput();
|
||||
}
|
||||
|
||||
if (_noSaveProcess) {
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
initMenu(*_currentMenu);
|
||||
updateAllMenuButtons();
|
||||
return 0;
|
||||
} else if (_saveSlot <= -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
restorePalette();
|
||||
|
||||
Graphics::Surface thumb;
|
||||
createScreenThumbnail(thumb);
|
||||
_vm->updatePlayTimer();
|
||||
Util::convertString_KYRAtoGUI(_saveDescription, 81);
|
||||
_vm->saveGameStateIntern(_saveSlot, _saveDescription, &thumb);
|
||||
thumb.free();
|
||||
|
||||
_displayMenu = false;
|
||||
if (!(_vm->game() == GI_KYRA2 && _vm->gameFlags().lang == Common::ZH_TWN))
|
||||
_screen->setFontStyles(_screen->_currentFont, Font::kStyleBorder);
|
||||
_madeSave = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::clickSaveSlot(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
|
||||
int index = caller->index - _menuButtons[0].index;
|
||||
assert(index >= 0 && index <= 6);
|
||||
MenuItem &item = _saveMenu.item[index];
|
||||
|
||||
if (item.saveSlot >= 0) {
|
||||
if (_isDeleteMenu) {
|
||||
_slotToDelete = item.saveSlot;
|
||||
_isDeleteMenu = false;
|
||||
return 0;
|
||||
} else {
|
||||
_saveSlot = item.saveSlot;
|
||||
Common::strlcpy(_saveDescription, item.itemString.c_str(), sizeof(_saveDescription));
|
||||
}
|
||||
} else if (item.saveSlot == -2) {
|
||||
_saveSlot = getNextSavegameSlot();
|
||||
memset(_saveDescription, 0, sizeof(_saveDescription));
|
||||
}
|
||||
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
|
||||
initMenu(_savenameMenu);
|
||||
_screen->fillRect(0x26, 0x5B, 0x11F, _vm->gameFlags().lang == Common::ZH_TWN ? 0x6b : 0x66, textFieldColor2());
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
||||
const char *desc = nameInputProcess(_saveDescription, 0x27, 0x5C, textFieldColor1(), textFieldColor2(), textFieldColor3(), 0x50);
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
if (desc) {
|
||||
_isSaveMenu = false;
|
||||
_isDeleteMenu = false;
|
||||
} else {
|
||||
initMenu(_saveMenu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::cancelSaveMenu(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_isSaveMenu = false;
|
||||
_isDeleteMenu = false;
|
||||
_noSaveProcess = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::deleteMenu(Button *caller) {
|
||||
updateSaveFileList(_vm->_targetName);
|
||||
|
||||
updateMenuButton(caller);
|
||||
if (_saveSlots.size() < 2) {
|
||||
_vm->snd_playSoundEffect(0x0D);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
_savegameOffset = 1;
|
||||
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 35 : 1;
|
||||
setupSavegameNames(_saveMenu, _saveLoadNumSlots);
|
||||
initMenu(_saveMenu);
|
||||
_isDeleteMenu = true;
|
||||
_slotToDelete = -1;
|
||||
updateAllMenuButtons();
|
||||
|
||||
while (_isDeleteMenu) {
|
||||
processHighlights(_saveMenu);
|
||||
getInput();
|
||||
}
|
||||
|
||||
if (_slotToDelete < 1) {
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
initMenu(*_currentMenu);
|
||||
updateAllMenuButtons();
|
||||
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 9 : 17;
|
||||
return 0;
|
||||
}
|
||||
} while (choiceDialog(_vm->gameFlags().isTalkie ? 0x24 : 2, 1) == 0);
|
||||
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
initMenu(*_currentMenu);
|
||||
updateAllMenuButtons();
|
||||
_vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(_slotToDelete));
|
||||
Common::Array<int>::iterator i = Common::find(_saveSlots.begin(), _saveSlots.end(), _slotToDelete);
|
||||
while (i != _saveSlots.end()) {
|
||||
++i;
|
||||
if (i == _saveSlots.end())
|
||||
break;
|
||||
// We are only renaming all savefiles until we get some slots missing
|
||||
// Also not rename quicksave slot filenames
|
||||
if (*(i - 1) != *i || *i >= 990)
|
||||
break;
|
||||
Common::String oldName = _vm->getSavegameFilename(*i);
|
||||
Common::String newName = _vm->getSavegameFilename(*i - 1);
|
||||
_vm->_saveFileMan->renameSavefile(oldName, newName);
|
||||
}
|
||||
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 9 : 17;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 c2, uint8 c3, int bufferSize) {
|
||||
bool running = true;
|
||||
int curPos = strlen(buffer);
|
||||
uint8 keyLim = (_vm->gameFlags().lang == Common::JA_JPN || _vm->gameFlags().lang == Common::ZH_TWN) ? 128 : 226;
|
||||
int x2 = x, y2 = y;
|
||||
|
||||
Screen::FontId of = _screen->setFont(_saveMenuFont);
|
||||
_text->printText(buffer, x, y, c1, c2, c2);
|
||||
|
||||
for (int i = 0; i < curPos; ++i)
|
||||
x2 += getCharWidth(buffer[i]);
|
||||
|
||||
drawTextfieldBlock(x2, y2, c3);
|
||||
_screen->setFont(of);
|
||||
|
||||
_keyPressed.reset();
|
||||
_cancelNameInput = _finishNameInput = false;
|
||||
while (running && !_vm->shouldQuit()) {
|
||||
of = _screen->setFont(_saveMenuFont);
|
||||
checkTextfieldInput();
|
||||
_screen->setFont(of);
|
||||
processHighlights(_savenameMenu);
|
||||
|
||||
char inputKey = _keyPressed.ascii;
|
||||
Util::convertISOToDOS(inputKey);
|
||||
|
||||
if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER || _finishNameInput) {
|
||||
if (checkSavegameDescription(buffer, curPos)) {
|
||||
buffer[curPos] = 0;
|
||||
running = false;
|
||||
} else {
|
||||
_finishNameInput = false;
|
||||
}
|
||||
} else if (_keyPressed.keycode == Common::KEYCODE_ESCAPE || _cancelNameInput) {
|
||||
running = false;
|
||||
return nullptr;
|
||||
} else if ((_keyPressed.keycode == Common::KEYCODE_BACKSPACE || _keyPressed.keycode == Common::KEYCODE_DELETE) && curPos > 0) {
|
||||
drawTextfieldBlock(x2, y2, c2);
|
||||
--curPos;
|
||||
x2 -= getCharWidth(buffer[curPos]);
|
||||
drawTextfieldBlock(x2, y2, c3);
|
||||
_screen->updateScreen();
|
||||
_lastScreenUpdate = _vm->_system->getMillis();
|
||||
} else if ((uint8)inputKey > 31 && (uint8)inputKey < keyLim && curPos < bufferSize) {
|
||||
of = _screen->setFont(_saveMenuFont);
|
||||
if (x2 + getCharWidth(inputKey) + 7 < 0x11F) {
|
||||
buffer[curPos] = inputKey;
|
||||
const char text[2] = { buffer[curPos], 0 };
|
||||
if (_saveMenuFont == Screen::FID_CHINESE_FNT) {
|
||||
drawTextfieldBlock(x2, y2, c2);
|
||||
_text->printText(text, x2, y2, c1, c2, 0);
|
||||
} else {
|
||||
_text->printText(text, x2, y2, c1, c2, c2);
|
||||
}
|
||||
x2 += getCharWidth(inputKey);
|
||||
drawTextfieldBlock(x2, y2, c3);
|
||||
++curPos;
|
||||
_screen->updateScreen();
|
||||
_lastScreenUpdate = _vm->_system->getMillis();
|
||||
}
|
||||
_screen->setFont(of);
|
||||
}
|
||||
|
||||
_keyPressed.reset();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int GUI_v2::finishSavename(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_finishNameInput = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::cancelSavename(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_cancelNameInput = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GUI_v2::checkSavegameDescription(const char *buffer, int size) {
|
||||
if (!buffer || !size)
|
||||
return false;
|
||||
if (buffer[0] == 0)
|
||||
return false;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (buffer[i] != ' ')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int GUI_v2::getCharWidth(uint8 c) {
|
||||
Screen::FontId old = _screen->setFont(_saveMenuFont);
|
||||
_screen->_charSpacing = -2;
|
||||
int width = _screen->getCharWidth(c);
|
||||
_screen->_charSpacing = 0;
|
||||
_screen->setFont(old);
|
||||
return width;
|
||||
}
|
||||
|
||||
void GUI_v2::drawTextfieldBlock(int x, int y, uint8 c) {
|
||||
_screen->fillRect(x + _saveMenuCursor.left, y + _saveMenuCursor.top, x + _saveMenuCursor.right, y + _saveMenuCursor.bottom, c);
|
||||
}
|
||||
|
||||
bool GUI_v2::choiceDialog(int name, bool type) {
|
||||
_choiceMenu.highlightedItem = 0;
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
if (type)
|
||||
_choiceMenu.numberOfItems = 2;
|
||||
else
|
||||
_choiceMenu.numberOfItems = 1;
|
||||
_choiceMenu.menuNameId = name;
|
||||
|
||||
initMenu(_choiceMenu);
|
||||
_isChoiceMenu = true;
|
||||
_choice = false;
|
||||
|
||||
while (_isChoiceMenu) {
|
||||
processHighlights(_choiceMenu);
|
||||
getInput();
|
||||
}
|
||||
|
||||
restorePage1(_vm->_screenBuffer);
|
||||
backUpPage1(_vm->_screenBuffer);
|
||||
return _choice;
|
||||
}
|
||||
|
||||
int GUI_v2::choiceYes(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_choice = true;
|
||||
_isChoiceMenu = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_v2::choiceNo(Button *caller) {
|
||||
updateMenuButton(caller);
|
||||
_choice = false;
|
||||
_isChoiceMenu = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
238
engines/kyra/gui/gui_v2.h
Normal file
238
engines/kyra/gui/gui_v2.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_GUI_V2_H
|
||||
#define KYRA_GUI_V2_H
|
||||
|
||||
#include "kyra/gui/gui_v1.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
#define GUI_V2_BUTTON(button, a, b, c, d, e, f, h, i, j, k, l, m, n, o, p, q, r, s, t) \
|
||||
do { \
|
||||
button.nextButton = 0; \
|
||||
button.index = a; \
|
||||
button.keyCode = b; \
|
||||
button.keyCode2 = c; \
|
||||
button.data0Val1 = d; \
|
||||
button.data1Val1 = e; \
|
||||
button.data2Val1 = f; \
|
||||
button.flags = h; \
|
||||
button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \
|
||||
button.dimTableIndex = i; \
|
||||
button.x = j; \
|
||||
button.y = k; \
|
||||
button.width = l; \
|
||||
button.height = m; \
|
||||
button.data0Val2 = n; \
|
||||
button.data0Val3 = o; \
|
||||
button.data1Val2 = p; \
|
||||
button.data1Val3 = q; \
|
||||
button.data2Val2 = r; \
|
||||
button.data2Val3 = s; \
|
||||
button.flags2 = t; \
|
||||
button.mouseWheel = 0; \
|
||||
button.arg = 0; \
|
||||
} while (0)
|
||||
|
||||
#define GUI_V2_MENU(menu, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
do { \
|
||||
menu.x = a; \
|
||||
menu.y = b; \
|
||||
menu.width = c; \
|
||||
menu.height = d; \
|
||||
menu.bkgdColor = e; \
|
||||
menu.color1 = f; \
|
||||
menu.color2 = g; \
|
||||
menu.menuNameId = h; \
|
||||
menu.textColor = i; \
|
||||
menu.titleX = j; \
|
||||
menu.titleY = k; \
|
||||
menu.highlightedItem = l; \
|
||||
menu.numberOfItems = m; \
|
||||
menu.scrollUpButtonX = n; \
|
||||
menu.scrollUpButtonY = o; \
|
||||
menu.scrollDownButtonX = p; \
|
||||
menu.scrollDownButtonY = q; \
|
||||
} while (0)
|
||||
|
||||
#define GUI_V2_MENU_ITEM(item, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
do { \
|
||||
item.enabled = a; \
|
||||
item.itemId = b; \
|
||||
item.useItemString = false; \
|
||||
item.x = c; \
|
||||
item.y = d; \
|
||||
item.width = e; \
|
||||
item.height = f; \
|
||||
item.textColor = g; \
|
||||
item.highlightColor = h; \
|
||||
item.titleX = i; \
|
||||
item.bkgdColor = j; \
|
||||
item.color1 = k; \
|
||||
item.color2 = l; \
|
||||
item.saveSlot = m; \
|
||||
item.labelId = n; \
|
||||
item.labelX = o; \
|
||||
item.labelY = p; \
|
||||
item.keyCode = q; \
|
||||
} while (0)
|
||||
|
||||
class KyraEngine_v2;
|
||||
class Screen_v2;
|
||||
|
||||
class GUI_v2 : public GUI_v1 {
|
||||
public:
|
||||
GUI_v2(KyraEngine_v2 *vm);
|
||||
|
||||
virtual void initStaticData() = 0;
|
||||
|
||||
Button *addButtonToList(Button *list, Button *newButton) override;
|
||||
|
||||
void processButton(Button *button) override;
|
||||
int processButtonList(Button *button, uint16 inputFlag, int8 mouseWheel) override;
|
||||
|
||||
protected:
|
||||
void updateButton(Button *button) override;
|
||||
|
||||
KyraEngine_v2 *_vm;
|
||||
Screen_v2 *_screen;
|
||||
|
||||
bool _buttonListChanged;
|
||||
Button *_backUpButtonList;
|
||||
Button *_specialProcessButton;
|
||||
uint16 _flagsModifier;
|
||||
|
||||
protected:
|
||||
virtual void setupPalette() {}
|
||||
virtual void restorePalette() {}
|
||||
|
||||
virtual Common::String getTableString(int id, bool decode = false) = 0;
|
||||
|
||||
virtual uint8 textFieldColor1() const = 0;
|
||||
virtual uint8 textFieldColor2() const = 0;
|
||||
virtual uint8 textFieldColor3() const = 0;
|
||||
protected:
|
||||
virtual void getInput();
|
||||
|
||||
Button _menuButtons[7];
|
||||
Button _scrollUpButton;
|
||||
Button _scrollDownButton;
|
||||
Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _savenameMenu, _deathMenu;
|
||||
|
||||
Button *getButtonListData() override { return _menuButtons; }
|
||||
|
||||
Button *getScrollUpButton() override { return &_scrollUpButton; }
|
||||
Button *getScrollDownButton() override { return &_scrollDownButton; }
|
||||
|
||||
int scrollUpButton(Button *button);
|
||||
int scrollDownButton(Button *button);
|
||||
Button::Callback _scrollUpFunctor;
|
||||
Button::Callback _scrollDownFunctor;
|
||||
Button::Callback getScrollUpButtonHandler() const override { return _scrollUpFunctor; }
|
||||
Button::Callback getScrollDownButtonHandler() const override { return _scrollDownFunctor; }
|
||||
|
||||
Button _sliderButtons[3][4];
|
||||
|
||||
void renewHighlight(Menu &menu);
|
||||
|
||||
void backUpPage1(uint8 *buffer);
|
||||
void restorePage1(const uint8 *buffer);
|
||||
|
||||
Menu *_currentMenu;
|
||||
bool _isLoadMenu;
|
||||
bool _isDeathMenu;
|
||||
bool _isSaveMenu;
|
||||
bool _isDeleteMenu;
|
||||
bool _isChoiceMenu;
|
||||
bool _isOptionsMenu;
|
||||
bool _madeSave;
|
||||
bool _loadedSave;
|
||||
bool _restartGame;
|
||||
bool _reloadTemporarySave;
|
||||
|
||||
int _savegameOffset;
|
||||
|
||||
void setupSavegameNames(Menu &menu, int num);
|
||||
|
||||
// main menu
|
||||
int resumeGame(Button *caller);
|
||||
|
||||
// audio menu
|
||||
static const int _sliderBarsPosition[];
|
||||
|
||||
// load menu
|
||||
bool _noLoadProcess;
|
||||
int clickLoadSlot(Button *caller);
|
||||
int cancelLoadMenu(Button *caller);
|
||||
|
||||
// save menu
|
||||
bool _noSaveProcess;
|
||||
int _saveSlot;
|
||||
char _saveDescription[0x51];
|
||||
|
||||
int saveMenu(Button *caller);
|
||||
int clickSaveSlot(Button *caller);
|
||||
int cancelSaveMenu(Button *caller);
|
||||
|
||||
int _saveLoadNumSlots;
|
||||
|
||||
// delete menu
|
||||
int _slotToDelete;
|
||||
int deleteMenu(Button *caller);
|
||||
|
||||
// options menu
|
||||
int quitOptionsMenu(Button *caller);
|
||||
|
||||
int toggleWalkspeed(Button *caller);
|
||||
int toggleText(Button *caller);
|
||||
|
||||
virtual void setupOptionsButtons() = 0;
|
||||
|
||||
// audio options
|
||||
Button::Callback _sliderHandlerFunctor;
|
||||
virtual int sliderHandler(Button *caller) = 0;
|
||||
|
||||
// savename menu
|
||||
bool _finishNameInput, _cancelNameInput;
|
||||
|
||||
const char *nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 c2, uint8 c3, int bufferSize);
|
||||
int finishSavename(Button *caller);
|
||||
int cancelSavename(Button *caller);
|
||||
|
||||
bool checkSavegameDescription(const char *buffer, int size);
|
||||
int getCharWidth(uint8 c);
|
||||
void drawTextfieldBlock(int x, int y, uint8 c);
|
||||
|
||||
Screen::FontId _saveMenuFont;
|
||||
Common::Rect _saveMenuCursor;
|
||||
|
||||
// choice menu
|
||||
bool _choice;
|
||||
|
||||
bool choiceDialog(int name, bool type);
|
||||
int choiceYes(Button *caller);
|
||||
int choiceNo(Button *caller);
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
300
engines/kyra/gui/saveload.cpp
Normal file
300
engines/kyra/gui/saveload.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/kyra_v1.h"
|
||||
#include "kyra/engine/util.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#define CURRENT_SAVE_VERSION 24
|
||||
|
||||
#define GF_FLOPPY (1 << 0)
|
||||
#define GF_TALKIE (1 << 1)
|
||||
#define GF_FMTOWNS (1 << 2)
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
WARN_UNUSED_RESULT KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) {
|
||||
uint32 type = in->readUint32BE();
|
||||
header.originalSave = false;
|
||||
header.oldHeader = false;
|
||||
header.flags = 0;
|
||||
|
||||
if (type == MKTAG('K', 'Y', 'R', 'A') || type == MKTAG('A', 'R', 'Y', 'K')) { // old Kyra1 header ID
|
||||
header.gameID = GI_KYRA1;
|
||||
header.oldHeader = true;
|
||||
} else if (type == MKTAG('H', 'O', 'F', 'S')) { // old Kyra2 header ID
|
||||
header.gameID = GI_KYRA2;
|
||||
header.oldHeader = true;
|
||||
} else if (type == MKTAG('W', 'W', 'S', 'V')) {
|
||||
header.gameID = in->readByte();
|
||||
} else {
|
||||
// try checking for original save header
|
||||
const int descriptionSize[3] = { 30, 80, 60 };
|
||||
char descriptionBuffer[81];
|
||||
|
||||
bool saveOk = false;
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(descriptionSize) && !saveOk; ++i) {
|
||||
if (in->size() < descriptionSize[i] + 6)
|
||||
continue;
|
||||
|
||||
in->seek(0, SEEK_SET);
|
||||
in->read(descriptionBuffer, descriptionSize[i]);
|
||||
descriptionBuffer[descriptionSize[i]] = 0;
|
||||
|
||||
Util::convertString_KYRAtoGUI(descriptionBuffer, 81);
|
||||
|
||||
type = in->readUint32BE();
|
||||
header.version = in->readUint16LE();
|
||||
if (type == MKTAG('M', 'B', 'L', '3') && header.version == 100) {
|
||||
saveOk = true;
|
||||
header.description = descriptionBuffer;
|
||||
header.gameID = GI_KYRA2;
|
||||
break;
|
||||
} else if (type == MKTAG('M', 'B', 'L', '4') && header.version == 102) {
|
||||
saveOk = true;
|
||||
header.description = descriptionBuffer;
|
||||
header.gameID = GI_KYRA3;
|
||||
break;
|
||||
} else if (type == MKTAG('C','D','0','4')) {
|
||||
header.version = in->readUint32BE();
|
||||
// We don't check the minor version, since the original doesn't do that either and it isn't required.
|
||||
if (header.version != MKTAG(' ','C','D','1'))
|
||||
continue;
|
||||
saveOk = true;
|
||||
header.description = descriptionBuffer;
|
||||
header.gameID = GI_LOL;
|
||||
in->seek(6, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (saveOk) {
|
||||
header.originalSave = true;
|
||||
header.description = descriptionBuffer;
|
||||
return kRSHENoError;
|
||||
} else {
|
||||
return kRSHEInvalidType;
|
||||
}
|
||||
}
|
||||
|
||||
header.version = in->readUint32BE();
|
||||
if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKTAG('A', 'R', 'Y', 'K') && header.version > 3))
|
||||
return kRSHEInvalidVersion;
|
||||
|
||||
// Versions prior to 9 are using a fixed length description field
|
||||
if (header.version <= 8) {
|
||||
char buffer[31];
|
||||
in->read(buffer, 31);
|
||||
// WORKAROUND: Old savegames could contain a missing termination 0 at the
|
||||
// end so we manually add it.
|
||||
buffer[30] = 0;
|
||||
header.description = buffer;
|
||||
} else {
|
||||
header.description = "";
|
||||
for (char c = 0; (c = in->readByte()) != 0;)
|
||||
header.description += c;
|
||||
}
|
||||
|
||||
if (header.version < 20)
|
||||
header.description = Util::convertISOToUTF8(header.description);
|
||||
|
||||
if (header.version >= 2)
|
||||
header.flags = in->readUint32BE();
|
||||
|
||||
if (header.version >= 14) {
|
||||
if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
|
||||
if (!skipThumbnail)
|
||||
return kRSHEIoError;
|
||||
}
|
||||
} else {
|
||||
header.thumbnail = nullptr;
|
||||
}
|
||||
|
||||
if (header.version >= 21) {
|
||||
header.timeDate.tm_sec = in->readSint32BE();
|
||||
header.timeDate.tm_min = in->readSint32BE();
|
||||
header.timeDate.tm_hour = in->readSint32BE();
|
||||
header.timeDate.tm_mday = in->readSint32BE();
|
||||
header.timeDate.tm_mon = in->readSint32BE();
|
||||
header.timeDate.tm_year = in->readSint32BE();
|
||||
header.timeDate.tm_wday = in->readSint32BE();
|
||||
header.totalPlaySecs = in->readUint32BE();
|
||||
} else {
|
||||
header.totalPlaySecs = 0;
|
||||
memset(&header.timeDate, 0, sizeof(TimeDate));
|
||||
}
|
||||
|
||||
return ((in->err() || in->eos()) ? kRSHEIoError : kRSHENoError);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filename, SaveHeader &header, bool checkID) {
|
||||
Common::SeekableReadStream *in = nullptr;
|
||||
if (!(in = _saveFileMan->openForLoading(filename)))
|
||||
return nullptr;
|
||||
|
||||
ReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header);
|
||||
if (errorCode != kRSHENoError) {
|
||||
if (errorCode == kRSHEInvalidType)
|
||||
warning("No ScummVM Kyra engine savefile header");
|
||||
else if (errorCode == kRSHEInvalidVersion)
|
||||
warning("Savegame is not the right version (%u, '%s')", header.version, header.oldHeader ? "true" : "false");
|
||||
else if (errorCode == kRSHEIoError)
|
||||
warning("Load failed '%s'", filename);
|
||||
|
||||
delete in;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!header.originalSave) {
|
||||
if (!header.oldHeader) {
|
||||
if (header.gameID != _flags.gameID && checkID) {
|
||||
warning("Trying to load saved game from other game (saved game: %u, running game: %u)", header.gameID, _flags.gameID);
|
||||
delete in;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (header.version < 2) {
|
||||
warning("Make sure your savefile was from this version! (too old savefile version to detect that)");
|
||||
} else if (checkID) {
|
||||
if ((header.flags & GF_FLOPPY) && (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) {
|
||||
warning("Can not load DOS Floppy savefile for this (non DOS Floppy) gameversion");
|
||||
delete in;
|
||||
return nullptr;
|
||||
} else if ((header.flags & GF_TALKIE) && !(_flags.isTalkie)) {
|
||||
warning("Can not load DOS CD-ROM savefile for this (non DOS CD-ROM) gameversion");
|
||||
delete in;
|
||||
return nullptr;
|
||||
} else if ((header.flags & GF_FMTOWNS) && !(_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) {
|
||||
warning("Can not load FM-TOWNS/PC98 savefile for this (non FM-TOWNS/PC98) gameversion");
|
||||
delete in;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const {
|
||||
if (shouldQuit())
|
||||
return nullptr;
|
||||
|
||||
Common::WriteStream *out = nullptr;
|
||||
if (!(out = _saveFileMan->openForSaving(filename))) {
|
||||
warning("Can't create file '%s', game not saved", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Savegame version
|
||||
out->writeUint32BE(MKTAG('W', 'W', 'S', 'V'));
|
||||
out->writeByte(_flags.gameID);
|
||||
out->writeUint32BE(CURRENT_SAVE_VERSION);
|
||||
out->write(saveName, strlen(saveName) + 1);
|
||||
if (_flags.isTalkie)
|
||||
out->writeUint32BE(GF_TALKIE);
|
||||
else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
|
||||
out->writeUint32BE(GF_FMTOWNS);
|
||||
else
|
||||
out->writeUint32BE(GF_FLOPPY);
|
||||
|
||||
if (out->err()) {
|
||||
warning("Can't write file '%s'. (Disk full?)", filename);
|
||||
delete out;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Graphics::Surface *genThumbnail = nullptr;
|
||||
if (!thumbnail)
|
||||
thumbnail = genThumbnail = generateSaveThumbnail();
|
||||
|
||||
if (thumbnail)
|
||||
Graphics::saveThumbnail(*out, *thumbnail);
|
||||
else
|
||||
Graphics::saveThumbnail(*out);
|
||||
|
||||
if (genThumbnail) {
|
||||
genThumbnail->free();
|
||||
delete genThumbnail;
|
||||
}
|
||||
|
||||
TimeDate td;
|
||||
_system->getTimeAndDate(td);
|
||||
|
||||
out->writeSint32BE(td.tm_sec);
|
||||
out->writeSint32BE(td.tm_min);
|
||||
out->writeSint32BE(td.tm_hour);
|
||||
out->writeSint32BE(td.tm_mday);
|
||||
out->writeSint32BE(td.tm_mon);
|
||||
out->writeSint32BE(td.tm_year);
|
||||
out->writeSint32BE(td.tm_wday);
|
||||
|
||||
out->writeUint32BE(_totalPlaySecs);
|
||||
|
||||
return new Common::OutSaveFile(out);
|
||||
}
|
||||
|
||||
const char *KyraEngine_v1::getSavegameFilename(int num) {
|
||||
_savegameFilename = getSavegameFilename(_targetName, num);
|
||||
return _savegameFilename.c_str();
|
||||
}
|
||||
|
||||
Common::String KyraEngine_v1::getSavegameFilename(const Common::String &target, int num) {
|
||||
assert(num >= 0 && num <= 999);
|
||||
return target + Common::String::format(".%03d", num);
|
||||
}
|
||||
|
||||
bool KyraEngine_v1::saveFileLoadable(int slot) {
|
||||
if (slot < 0 || slot > 999)
|
||||
return false;
|
||||
|
||||
SaveHeader header;
|
||||
Common::SeekableReadStream *in = openSaveForReading(getSavegameFilename(slot), header);
|
||||
|
||||
if (in) {
|
||||
delete in;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void KyraEngine_v1::loadGameStateCheck(int slot) {
|
||||
// FIXME: Instead of throwing away the error returned by
|
||||
// loadGameState, we should use it / augment it.
|
||||
if (loadGameState(slot).getCode() != Common::kNoError) {
|
||||
const char *filename = getSavegameFilename(slot);
|
||||
Common::String errorMessage = "Could not load savegame: '";
|
||||
errorMessage += filename;
|
||||
errorMessage += "'";
|
||||
|
||||
GUIErrorMessage(errorMessage);
|
||||
error("%s", errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
1480
engines/kyra/gui/saveload_eob.cpp
Normal file
1480
engines/kyra/gui/saveload_eob.cpp
Normal file
File diff suppressed because it is too large
Load Diff
334
engines/kyra/gui/saveload_hof.cpp
Normal file
334
engines/kyra/gui/saveload_hof.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/engine/kyra_hof.h"
|
||||
#include "kyra/graphics/screen_v2.h"
|
||||
#include "kyra/sound/sound.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
Common::Error KyraEngine_HoF::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
|
||||
if (!out)
|
||||
return _saveFileMan->getError();
|
||||
|
||||
_timer->saveDataToFile(*out);
|
||||
|
||||
out->writeUint32BE(sizeof(_flagsTable));
|
||||
out->write(_flagsTable, sizeof(_flagsTable));
|
||||
|
||||
// usually we have to save the flag set by opcode 10 here
|
||||
//out->writeUint16BE(word_2AB05);
|
||||
out->writeSint16BE(_lastMusicCommand);
|
||||
out->writeByte(_newChapterFile);
|
||||
out->writeByte(_characterShapeFile);
|
||||
out->writeByte(_cauldronState);
|
||||
out->writeByte(_colorCodeFlag1);
|
||||
out->writeByte(_colorCodeFlag2);
|
||||
out->writeByte(_bookCurPage);
|
||||
out->writeByte(_bookMaxPage);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
out->writeByte(_presetColorCode[i]);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
out->writeByte(_inputColorCode[i]);
|
||||
for (int i = 0; i < 25; ++i)
|
||||
out->writeSint16BE(_cauldronTable[i]);
|
||||
for (int i = 0; i < 20; ++i)
|
||||
out->writeSint16BE(_hiddenItems[i]);
|
||||
for (int i = 0; i < 19; ++i)
|
||||
out->write(_conversationState[i], 14);
|
||||
out->write(_newSceneDlgState, 32);
|
||||
out->writeSint16BE(_cauldronUseCount);
|
||||
|
||||
out->writeUint16BE(_mainCharacter.sceneId);
|
||||
out->writeSint16BE(_mainCharacter.dlgIndex);
|
||||
out->writeByte(_mainCharacter.height);
|
||||
out->writeByte(_mainCharacter.facing);
|
||||
out->writeUint16BE(_mainCharacter.animFrame);
|
||||
for (int i = 0; i < 20; ++i)
|
||||
out->writeUint16BE(_mainCharacter.inventory[i]);
|
||||
out->writeSint16BE(_mainCharacter.x1);
|
||||
out->writeSint16BE(_mainCharacter.y1);
|
||||
out->writeSint16BE(_mainCharacter.x2);
|
||||
out->writeSint16BE(_mainCharacter.y2);
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
out->writeSint16BE(_itemList[i].id);
|
||||
out->writeUint16BE(_itemList[i].sceneId);
|
||||
out->writeSint16BE(_itemList[i].x);
|
||||
out->writeByte(_itemList[i].y);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 72; ++i) {
|
||||
out->write(_talkObjectList[i].filename, 13);
|
||||
out->writeByte(_talkObjectList[i].scriptId);
|
||||
out->writeSint16BE(_talkObjectList[i].x);
|
||||
out->writeSint16BE(_talkObjectList[i].y);
|
||||
out->writeByte(_talkObjectList[i].color);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 86; ++i) {
|
||||
out->write(_sceneList[i].filename1, 10);
|
||||
out->writeUint16BE(_sceneList[i].exit1);
|
||||
out->writeUint16BE(_sceneList[i].exit2);
|
||||
out->writeUint16BE(_sceneList[i].exit3);
|
||||
out->writeUint16BE(_sceneList[i].exit4);
|
||||
out->writeByte(_sceneList[i].flags);
|
||||
out->writeByte(_sceneList[i].sound);
|
||||
}
|
||||
|
||||
out->writeSint16BE(_itemInHand);
|
||||
out->writeUint16BE(_sceneExit1);
|
||||
out->writeUint16BE(_sceneExit2);
|
||||
out->writeUint16BE(_sceneExit3);
|
||||
out->writeUint16BE(_sceneExit4);
|
||||
|
||||
out->finalize();
|
||||
|
||||
// check for errors
|
||||
if (out->err()) {
|
||||
warning("Can't write file '%s'. (Disk full?)", fileName);
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
|
||||
}
|
||||
|
||||
delete out;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error KyraEngine_HoF::loadGameState(int slot) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
SaveHeader header;
|
||||
Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
|
||||
if (!saveFile) {
|
||||
showMessageFromCCode(0x35, 0x84, 0);
|
||||
snd_playSoundEffect(0x0D);
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");
|
||||
|
||||
bool setFlag1EE = (queryGameFlag(0x1EE) != 0);
|
||||
|
||||
_deathHandler = -1;
|
||||
if (!_unkSceneScreenFlag1) {
|
||||
_sound->beginFadeOut();
|
||||
_system->delayMillis(5 * _tickLength);
|
||||
_lastMusicCommand = -1;
|
||||
}
|
||||
|
||||
int loadedZTable = _characterShapeFile;
|
||||
|
||||
Common::SeekableReadStreamEndianWrapper in(saveFile, !header.originalSave, DisposeAfterUse::YES);
|
||||
|
||||
_screen->hideMouse();
|
||||
_screen->fadeToBlack(10);
|
||||
_screen->fillRect(0, 0, 319, 143, 0, 0);
|
||||
|
||||
if (!header.originalSave) {
|
||||
_timer->loadDataFromFile(in, header.version);
|
||||
|
||||
uint32 flagsSize = in.readUint32BE();
|
||||
assert(flagsSize <= sizeof(_flagsTable));
|
||||
in.read(_flagsTable, flagsSize);
|
||||
}
|
||||
|
||||
// usually we have to save the flag set by opcode 10 here
|
||||
//word_2AB05 = in.readUint16();
|
||||
if (header.originalSave)
|
||||
in.readUint16();
|
||||
_lastMusicCommand = in.readSint16();
|
||||
_newChapterFile = in.readByte();
|
||||
_characterShapeFile = in.readByte();
|
||||
_cauldronState = in.readByte();
|
||||
_colorCodeFlag1 = in.readByte();
|
||||
_colorCodeFlag2 = in.readByte();
|
||||
_bookCurPage = in.readByte();
|
||||
_bookMaxPage = in.readByte();
|
||||
for (int i = 0; i < 7; ++i)
|
||||
_presetColorCode[i] = in.readByte();
|
||||
for (int i = 0; i < 7; ++i)
|
||||
_inputColorCode[i] = in.readByte();
|
||||
for (int i = 0; i < 25; ++i)
|
||||
_cauldronTable[i] = in.readSint16();
|
||||
for (int i = 0; i < 20; ++i)
|
||||
_hiddenItems[i] = in.readSint16();
|
||||
|
||||
if (header.originalSave) {
|
||||
assert(sizeof(_flagsTable) >= 0x41);
|
||||
in.read(_flagsTable, 0x41);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 19; ++i)
|
||||
in.read(_conversationState[i], 14);
|
||||
|
||||
if (!header.originalSave) {
|
||||
in.read(_newSceneDlgState, 32);
|
||||
} else {
|
||||
for (int i = 0; i < 31; ++i)
|
||||
_newSceneDlgState[i] = in.readUint16();
|
||||
}
|
||||
|
||||
_cauldronUseCount = in.readSint16();
|
||||
|
||||
if (header.originalSave)
|
||||
in.seek(6, SEEK_CUR);
|
||||
|
||||
_mainCharacter.sceneId = in.readUint16();
|
||||
_mainCharacter.dlgIndex = in.readSint16();
|
||||
_mainCharacter.height = in.readByte();
|
||||
_mainCharacter.facing = in.readByte();
|
||||
_mainCharacter.animFrame = in.readUint16();
|
||||
|
||||
if (header.version <= 10 || header.originalSave)
|
||||
in.seek(3, SEEK_CUR);
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
_mainCharacter.inventory[i] = in.readUint16();
|
||||
_mainCharacter.x1 = in.readSint16();
|
||||
_mainCharacter.y1 = in.readSint16();
|
||||
_mainCharacter.x2 = in.readSint16();
|
||||
_mainCharacter.y2 = in.readSint16();
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
_itemList[i].id = in.readSint16();
|
||||
_itemList[i].sceneId = in.readUint16();
|
||||
_itemList[i].x = in.readSint16();
|
||||
_itemList[i].y = in.readByte();
|
||||
if (header.version <= 9 || header.originalSave)
|
||||
in.readUint16();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 72; ++i) {
|
||||
in.read(_talkObjectList[i].filename, 13);
|
||||
_talkObjectList[i].scriptId = in.readByte();
|
||||
_talkObjectList[i].x = in.readSint16();
|
||||
_talkObjectList[i].y = in.readSint16();
|
||||
_talkObjectList[i].color = in.readByte();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 86; ++i) {
|
||||
if (!header.originalSave) {
|
||||
in.read(_sceneList[i].filename1, 10);
|
||||
} else {
|
||||
in.read(_sceneList[i].filename1, 9);
|
||||
_sceneList[i].filename1[9] = 0;
|
||||
}
|
||||
|
||||
_sceneList[i].exit1 = in.readUint16();
|
||||
_sceneList[i].exit2 = in.readUint16();
|
||||
_sceneList[i].exit3 = in.readUint16();
|
||||
_sceneList[i].exit4 = in.readUint16();
|
||||
_sceneList[i].flags = in.readByte();
|
||||
_sceneList[i].sound = in.readByte();
|
||||
}
|
||||
|
||||
_itemInHand = in.readSint16();
|
||||
|
||||
if (header.originalSave) {
|
||||
uint32 currentTime = _system->getMillis();
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_timer->setDelay(i, in.readSint32LE());
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (in.readUint16LE())
|
||||
_timer->enable(i);
|
||||
else
|
||||
_timer->disable(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength));
|
||||
|
||||
_timer->resetNextRun();
|
||||
}
|
||||
|
||||
_sceneExit1 = in.readUint16();
|
||||
_sceneExit2 = in.readUint16();
|
||||
_sceneExit3 = in.readUint16();
|
||||
_sceneExit4 = in.readUint16();
|
||||
|
||||
if (saveFile->err() || saveFile->eos()) {
|
||||
warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
|
||||
}
|
||||
|
||||
if (loadedZTable != _characterShapeFile)
|
||||
loadCharacterShapes(_characterShapeFile);
|
||||
|
||||
_screen->loadBitmap("_PLAYFLD.CPS", 3, 3, nullptr);
|
||||
if (!queryGameFlag(1))
|
||||
_screen->copyRegion(0xCE, 0x90, 0xCE, 0x90, 0x2C, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
if (!queryGameFlag(2))
|
||||
_screen->copyRegion(0xFA, 0x90, 0xFA, 0x90, 0x46, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
_screen->loadBitmap("_PLAYALL.CPS", 3, 3, nullptr);
|
||||
if (queryGameFlag(1))
|
||||
_screen->copyRegion(0xCE, 0x90, 0xCE, 0x90, 0x2C, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
if (queryGameFlag(2))
|
||||
_screen->copyRegion(0xFA, 0x90, 0xFA, 0x90, 0x46, 0x2C, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
|
||||
redrawInventory(0);
|
||||
int cauldronUseCount = _cauldronUseCount;
|
||||
setCauldronState(_cauldronState, 0);
|
||||
_cauldronUseCount = cauldronUseCount;
|
||||
_mainCharX = _mainCharacter.x2 = _mainCharacter.x1;
|
||||
_mainCharY = _mainCharacter.y2 = _mainCharacter.y1;
|
||||
_mainCharacter.facing = 4;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
setHandItem(_itemInHand);
|
||||
|
||||
if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
|
||||
snd_playWanderScoreViaMap(_lastMusicCommand, 1);
|
||||
|
||||
while (!_screen->isMouseVisible())
|
||||
_screen->showMouse();
|
||||
|
||||
setTimer1DelaySecs(7);
|
||||
_shownMessage = " ";
|
||||
_fadeMessagePalette = false;
|
||||
|
||||
if (setFlag1EE)
|
||||
setGameFlag(0x1EE);
|
||||
|
||||
// We didn't explicitly set the walk speed, but it's saved as part of
|
||||
// the _timers array, so we need to re-sync it with _configWalkspeed.
|
||||
setWalkspeed(_configWalkspeed);
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
326
engines/kyra/gui/saveload_lok.cpp
Normal file
326
engines/kyra/gui/saveload_lok.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/engine/kyra_lok.h"
|
||||
#include "kyra/graphics/animator_lok.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/sound/sound.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
Common::Error KyraEngine_LoK::loadGameState(int slot) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
SaveHeader header;
|
||||
Common::InSaveFile *in = openSaveForReading(fileName, header);
|
||||
if (!in)
|
||||
return _saveFileMan->getError();
|
||||
|
||||
if (header.originalSave) {
|
||||
// no support for original savefile in Kyrandia 1 (yet)
|
||||
delete in;
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
snd_playSoundEffect(0x0A);
|
||||
snd_playWanderScoreViaMap(0, 1);
|
||||
|
||||
// unloading the current voice file should fix some problems with voices
|
||||
if (_currentRoom != 0xFFFF && _flags.isTalkie) {
|
||||
assert(_currentRoom < _roomTableSize);
|
||||
int tableId = _roomTable[_currentRoom].nameIndex;
|
||||
assert(tableId < _roomFilenameTableSize);
|
||||
_res->unloadPakFile(Common::String(_roomFilenameTable[tableId]) + ".VRM");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 11; i++) {
|
||||
_characterList[i].sceneId = in->readUint16BE();
|
||||
_characterList[i].height = in->readByte();
|
||||
_characterList[i].facing = in->readByte();
|
||||
_characterList[i].currentAnimFrame = in->readUint16BE();
|
||||
//_characterList[i].unk6 = in->readUint32BE();
|
||||
in->read(_characterList[i].inventoryItems, 10);
|
||||
_characterList[i].x1 = in->readSint16BE();
|
||||
_characterList[i].y1 = in->readSint16BE();
|
||||
_characterList[i].x2 = in->readSint16BE();
|
||||
_characterList[i].y2 = in->readSint16BE();
|
||||
//_characterList[i].field_20 = in->readUint16BE();
|
||||
//_characterList[i].field_23 = in->readUint16BE();
|
||||
}
|
||||
|
||||
_marbleVaseItem = in->readSint16BE();
|
||||
_itemInHand = (int8)in->readByte();
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_birthstoneGemTable[i] = in->readByte();
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_idolGemsTable[i] = in->readByte();
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_foyerItemTable[i] = in->readByte();
|
||||
_cauldronState = in->readByte();
|
||||
for (int i = 0; i < 2; ++i)
|
||||
_crystalState[i] = in->readByte();
|
||||
|
||||
_brandonStatusBit = in->readUint16BE();
|
||||
_brandonStatusBit0x02Flag = in->readByte();
|
||||
_brandonStatusBit0x20Flag = in->readByte();
|
||||
in->read(_brandonPoisonFlagsGFX, 256);
|
||||
_brandonInvFlag = in->readSint16BE();
|
||||
_poisonDeathCounter = in->readByte();
|
||||
_animator->_brandonDrawFrame = in->readUint16BE();
|
||||
|
||||
_timer->loadDataFromFile(*in, header.version);
|
||||
|
||||
memset(_flagsTable, 0, sizeof(_flagsTable));
|
||||
uint32 flagsSize = in->readUint32BE();
|
||||
assert(flagsSize <= sizeof(_flagsTable));
|
||||
in->read(_flagsTable, flagsSize);
|
||||
|
||||
for (int i = 0; i < _roomTableSize; ++i) {
|
||||
for (int item = 0; item < 12; ++item) {
|
||||
_roomTable[i].itemsTable[item] = kItemNone;
|
||||
_roomTable[i].itemsXPos[item] = 0xFFFF;
|
||||
_roomTable[i].itemsYPos[item] = 0xFF;
|
||||
_roomTable[i].needInit[item] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 sceneId = 0;
|
||||
|
||||
while (true) {
|
||||
sceneId = in->readUint16BE();
|
||||
if (sceneId == 0xFFFF)
|
||||
break;
|
||||
assert(sceneId < _roomTableSize);
|
||||
_roomTable[sceneId].nameIndex = in->readByte();
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
_roomTable[sceneId].itemsTable[i] = in->readByte();
|
||||
_roomTable[sceneId].itemsXPos[i] = in->readUint16BE();
|
||||
_roomTable[sceneId].itemsYPos[i] = in->readUint16BE();
|
||||
_roomTable[sceneId].needInit[i] = in->readByte();
|
||||
}
|
||||
}
|
||||
|
||||
_sound->selectAudioResourceSet(kMusicIngame);
|
||||
closeFinalWsa();
|
||||
|
||||
int lastMusicCommand = _lastMusicCommand = -1;
|
||||
if (header.version >= 3)
|
||||
lastMusicCommand = in->readSint16BE();
|
||||
|
||||
// Version 4 stored settings in the savegame. As of version 5, they are
|
||||
// handled by the config manager.
|
||||
|
||||
if (header.version == 4) {
|
||||
in->readByte(); // Text speed
|
||||
in->readByte(); // Walk speed
|
||||
in->readByte(); // Music
|
||||
in->readByte(); // Sound
|
||||
in->readByte(); // Voice
|
||||
}
|
||||
|
||||
if (header.version >= 7) {
|
||||
_curSfxFile = in->readByte();
|
||||
|
||||
// In the first version when this entry was introduced,
|
||||
// it wasn't made sure that _curSfxFile was initialized
|
||||
// so if it's out of bounds we just set it to 0.
|
||||
if (_flags.platform == Common::kPlatformFMTowns) {
|
||||
if (!_sound->hasSoundFile(_curSfxFile))
|
||||
_curSfxFile = 0;
|
||||
_sound->loadSoundFile(_curSfxFile);
|
||||
}
|
||||
}
|
||||
|
||||
loadMainScreen(8);
|
||||
|
||||
if (queryGameFlag(0x2D)) {
|
||||
_screen->loadBitmap("AMULET3.CPS", 10, 10, nullptr);
|
||||
if (!queryGameFlag(0xF1)) {
|
||||
for (int i = 0x55; i <= 0x5A; ++i) {
|
||||
if (queryGameFlag(i))
|
||||
seq_createAmuletJewel(i - 0x55, 10, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
_screen->copyRegion(8, 8, 8, 8, 304, 212, 10, 0);
|
||||
}
|
||||
|
||||
setHandItem(_itemInHand);
|
||||
|
||||
// Will-O-Wisp uses a different shape size than Brandon's usual
|
||||
// shape, thus we need to setup the correct size depending on
|
||||
// his state over here. This fixes graphics glitches when loading
|
||||
// saves, where Brandon is transformed into the Will-O-Wisp.
|
||||
if (_brandonStatusBit & 2)
|
||||
_animator->setBrandonAnimSeqSize(5, 48);
|
||||
else
|
||||
_animator->setBrandonAnimSeqSize(3, 48);
|
||||
|
||||
redrawInventory(0);
|
||||
|
||||
// Original hardcoded Brandon position for certain scenes:
|
||||
// - SceneId 7 ("A ruined bridge") and flag 0x39 set, which seems
|
||||
// to indicate that Herman is still in the scene.
|
||||
// - SceneId 2 ("Inside the temple") and flag 0x2D not set, which
|
||||
// indicates that the amulet is not obtained yet and thus Brynn
|
||||
// is still inside the temple
|
||||
if (_currentCharacter->sceneId == 7 && queryGameFlag(0x39)) {
|
||||
_currentCharacter->x1 = 282;
|
||||
_currentCharacter->y1 = 108;
|
||||
_currentCharacter->facing = 5;
|
||||
} else if (_currentCharacter->sceneId == 2 && !queryGameFlag(0x2D)) {
|
||||
_currentCharacter->x1 = 294;
|
||||
_currentCharacter->y1 = 132;
|
||||
_currentCharacter->facing = 5;
|
||||
}
|
||||
|
||||
_brandonPosX = _currentCharacter->x2 = _currentCharacter->x1;
|
||||
_brandonPosY = _currentCharacter->y2 = _currentCharacter->y1;
|
||||
|
||||
// We need to reset the "_noDrawShapesFlag" flag of Animator_LoK
|
||||
// over here. Else in certain cases restoring a savegame might
|
||||
// result in no shapes being drawn at all. See bug report
|
||||
// #4625 "KYRA1: Invisible Brandon" for an example of this.
|
||||
_animator->_noDrawShapesFlag = 0;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
|
||||
|
||||
// Check if _lastMusicCommand changed during enterNewScene(). If it didn't (no song was
|
||||
// started from script) and we do have the last song id from our savegame, then we start that...
|
||||
// This way we avoid the "stuttering" we used to have from restarting the saved song and
|
||||
// then the same song again directly afterwards from script...
|
||||
if (_lastMusicCommand == -1 && lastMusicCommand != -1)
|
||||
snd_playWanderScoreViaMap(lastMusicCommand, 1);
|
||||
|
||||
_animator->animRefreshNPC(0);
|
||||
_animator->restoreAllObjectBackgrounds();
|
||||
_animator->preserveAnyChangedBackgrounds();
|
||||
_animator->prepDrawAllObjects();
|
||||
_animator->copyChangedObjectsForward(0);
|
||||
_screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
|
||||
_screen->updateScreen();
|
||||
|
||||
setMousePos(_currentCharacter->x1, _currentCharacter->y1);
|
||||
|
||||
if (in->err() || in->eos()) {
|
||||
warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
|
||||
}
|
||||
|
||||
// We didn't explicitly set the walk speed, but it's saved as part of
|
||||
// the _timers array, so we need to re-sync it with _configWalkspeed.
|
||||
setWalkspeed(_configWalkspeed);
|
||||
|
||||
delete in;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error KyraEngine_LoK::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
if (shouldQuit())
|
||||
return Common::kNoError;
|
||||
|
||||
Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
|
||||
if (!out)
|
||||
return _saveFileMan->getError();
|
||||
|
||||
for (int i = 0; i < 11; i++) {
|
||||
out->writeUint16BE(_characterList[i].sceneId);
|
||||
out->writeByte(_characterList[i].height);
|
||||
out->writeByte(_characterList[i].facing);
|
||||
out->writeUint16BE(_characterList[i].currentAnimFrame);
|
||||
//out->writeUint32BE(_characterList[i].unk6);
|
||||
out->write(_characterList[i].inventoryItems, 10);
|
||||
out->writeSint16BE(_characterList[i].x1);
|
||||
out->writeSint16BE(_characterList[i].y1);
|
||||
out->writeSint16BE(_characterList[i].x2);
|
||||
out->writeSint16BE(_characterList[i].y2);
|
||||
//out->writeUint16BE(_characterList[i].field_20);
|
||||
//out->writeUint16BE(_characterList[i].field_23);
|
||||
}
|
||||
|
||||
out->writeSint16BE(_marbleVaseItem);
|
||||
out->writeByte(_itemInHand);
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
out->writeByte(_birthstoneGemTable[i]);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
out->writeByte(_idolGemsTable[i]);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
out->writeByte(_foyerItemTable[i]);
|
||||
out->writeByte(_cauldronState);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
out->writeByte(_crystalState[i]);
|
||||
|
||||
out->writeUint16BE(_brandonStatusBit);
|
||||
out->writeByte(_brandonStatusBit0x02Flag);
|
||||
out->writeByte(_brandonStatusBit0x20Flag);
|
||||
out->write(_brandonPoisonFlagsGFX, 256);
|
||||
out->writeSint16BE(_brandonInvFlag);
|
||||
out->writeByte(_poisonDeathCounter);
|
||||
out->writeUint16BE(_animator->_brandonDrawFrame);
|
||||
|
||||
_timer->saveDataToFile(*out);
|
||||
|
||||
out->writeUint32BE(sizeof(_flagsTable));
|
||||
out->write(_flagsTable, sizeof(_flagsTable));
|
||||
|
||||
for (uint16 i = 0; i < _roomTableSize; i++) {
|
||||
out->writeUint16BE(i);
|
||||
out->writeByte(_roomTable[i].nameIndex);
|
||||
for (int a = 0; a < 12; a++) {
|
||||
out->writeByte(_roomTable[i].itemsTable[a]);
|
||||
out->writeUint16BE(_roomTable[i].itemsXPos[a]);
|
||||
out->writeUint16BE(_roomTable[i].itemsYPos[a]);
|
||||
out->writeByte(_roomTable[i].needInit[a]);
|
||||
}
|
||||
}
|
||||
// room table terminator
|
||||
out->writeUint16BE(0xFFFF);
|
||||
|
||||
out->writeSint16BE(_lastMusicCommand);
|
||||
|
||||
out->writeByte(_curSfxFile);
|
||||
|
||||
out->finalize();
|
||||
|
||||
// check for errors
|
||||
if (out->err()) {
|
||||
warning("Can't write file '%s'. (Disk full?)", fileName);
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
|
||||
}
|
||||
|
||||
delete out;
|
||||
return Common::kNoError;
|
||||
}
|
||||
} // End of namespace Kyra
|
||||
584
engines/kyra/gui/saveload_lol.cpp
Normal file
584
engines/kyra/gui/saveload_lol.cpp
Normal file
@@ -0,0 +1,584 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
|
||||
#include "kyra/engine/lol.h"
|
||||
#include "kyra/graphics/screen_lol.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
Common::Error LoLEngine::loadGameState(int slot) {
|
||||
const uint16 *cdf[] = { _charDefsMan, _charDefsWoman, _charDefsKieran, _charDefsMan, _charDefsAkshel };
|
||||
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
SaveHeader header;
|
||||
Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
|
||||
if (!saveFile) {
|
||||
_txt->printMessage(2, "%s", getLangString(0x425D));
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");
|
||||
|
||||
_screen->fadeClearSceneWindow(10);
|
||||
completeDoorOperations();
|
||||
_screen->fillRect(112, 0, 287, 119, 0, 0);
|
||||
_screen->updateScreen();
|
||||
|
||||
Common::SeekableReadStreamEndianWrapper in(saveFile, !header.originalSave, DisposeAfterUse::YES);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LoLCharacter *c = &_characters[i];
|
||||
c->flags = in.readUint16();
|
||||
in.read(c->name, 11);
|
||||
c->raceClassSex = in.readByte();
|
||||
c->id = in.readSint16();
|
||||
c->curFaceFrame = in.readByte();
|
||||
c->tempFaceFrame = in.readByte();
|
||||
c->screamSfx = in.readByte();
|
||||
if (header.originalSave)
|
||||
in.skip(4);
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
c->itemsMight[ii] = in.readUint16();
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
c->protectionAgainstItems[ii] = in.readUint16();
|
||||
c->itemProtection = in.readUint16();
|
||||
c->hitPointsCur = in.readSint16();
|
||||
c->hitPointsMax = in.readUint16();
|
||||
c->magicPointsCur = in.readSint16();
|
||||
c->magicPointsMax = in.readUint16();
|
||||
c->field_41 = in.readByte();
|
||||
c->damageSuffered = in.readUint16();
|
||||
c->weaponHit = in.readUint16();
|
||||
c->totalMightModifier = in.readUint16();
|
||||
c->totalProtectionModifier = in.readUint16();
|
||||
c->might = in.readUint16();
|
||||
c->protection = in.readUint16();
|
||||
c->nextAnimUpdateCountdown = in.readSint16();
|
||||
for (int ii = 0; ii < 11; ii++)
|
||||
c->items[ii] = in.readUint16();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->skillLevels[ii] = in.readByte();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->skillModifiers[ii] = in.readSByte();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->experiencePts[ii] = in.readUint32();
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
c->characterUpdateEvents[ii] = in.readByte();
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
c->characterUpdateDelay[ii] = in.readByte();
|
||||
|
||||
if (c->flags & 1) {
|
||||
loadCharFaceShapes(i, c->id);
|
||||
c->defaultModifiers = cdf[c->raceClassSex];
|
||||
}
|
||||
}
|
||||
|
||||
if (header.version < 17)
|
||||
in.skip(80);
|
||||
|
||||
_currentBlock = in.readUint16();
|
||||
_partyPosX = in.readUint16();
|
||||
_partyPosY = in.readUint16();
|
||||
_updateFlags = in.readUint16();
|
||||
_scriptDirection = in.readByte();
|
||||
_selectedSpell = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(2);
|
||||
|
||||
_sceneDefaultUpdate = in.readByte();
|
||||
_compassBroken = in.readByte();
|
||||
_drainMagic = in.readByte();
|
||||
_currentDirection = in.readUint16();
|
||||
_compassDirection = in.readUint16();
|
||||
_selectedCharacter = in.readSByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(1);
|
||||
|
||||
_currentLevel = in.readByte();
|
||||
for (int i = 0; i < 48; i++)
|
||||
_inventory[i] = in.readSint16();
|
||||
_inventoryCurItem = in.readSint16();
|
||||
_itemInHand = in.readSint16();
|
||||
_lastMouseRegion = in.readSint16();
|
||||
|
||||
if (header.originalSave || header.version <= 15) {
|
||||
uint16 flags[40];
|
||||
memset(flags, 0, sizeof(flags));
|
||||
|
||||
if (header.version == 14) {
|
||||
for (int i = 0; i < 16; i++)
|
||||
flags[i] = in.readUint16();
|
||||
flags[26] = in.readUint16();
|
||||
flags[36] = in.readUint16();
|
||||
} else if (header.originalSave || header.version == 15) {
|
||||
for (int i = 0; i < 40; i++)
|
||||
flags[i] = in.readUint16();
|
||||
}
|
||||
|
||||
memset(_flagsTable, 0, sizeof(_flagsTable));
|
||||
for (uint i = 0; i < ARRAYSIZE(flags); ++i) {
|
||||
for (uint k = 0; k < 16; ++k) {
|
||||
if (flags[i] & (1 << k))
|
||||
setGameFlag(((i << 4) & 0xFFF0) | (k & 0x000F));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32 flagsSize = in.readUint32();
|
||||
assert(flagsSize <= sizeof(_flagsTable));
|
||||
in.read(_flagsTable, flagsSize);
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(120);
|
||||
|
||||
for (int i = 0; i < 24; i++)
|
||||
_globalScriptVars[i] = in.readUint16();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(152);
|
||||
|
||||
_brightness = in.readByte();
|
||||
_lampOilStatus = in.readByte();
|
||||
_lampEffect = in.readSByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(1);
|
||||
|
||||
_credits = in.readUint16();
|
||||
for (int i = 0; i < 8; i++)
|
||||
_globalScriptVars2[i] = in.readUint16();
|
||||
in.read(_availableSpells, 7);
|
||||
_hasTempDataFlags = in.readUint32();
|
||||
|
||||
uint8 *origCmp = 0;
|
||||
if (header.originalSave) {
|
||||
in.skip(6);
|
||||
origCmp = new uint8[2496];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 400; i++) {
|
||||
LoLItem *t = &_itemsInPlay[i];
|
||||
t->nextAssignedObject = in.readUint16();
|
||||
t->nextDrawObject = in.readUint16();
|
||||
t->flyingHeight = in.readByte();
|
||||
t->block = in.readUint16();
|
||||
t->x = in.readUint16();
|
||||
t->y = in.readUint16();
|
||||
t->level = in.readSByte();
|
||||
t->itemPropertyIndex = in.readUint16();
|
||||
t->shpCurFrame_flg = in.readUint16();
|
||||
if (header.version < 17)
|
||||
in.skip(4);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
LevelBlockProperty *l = &_levelBlockProperties[i];
|
||||
l->assignedObjects = l->drawObjects = 0;
|
||||
l->direction = 5;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
if (!(_hasTempDataFlags & (1 << i))) {
|
||||
if (header.originalSave) {
|
||||
if (in.size() - in.pos() >= 2500)
|
||||
in.skip(2500);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_lvlTempData[i]) {
|
||||
delete[] _lvlTempData[i]->wallsXorData;
|
||||
delete[] _lvlTempData[i]->flags;
|
||||
releaseMonsterTempData(_lvlTempData[i]);
|
||||
releaseFlyingObjectTempData(_lvlTempData[i]);
|
||||
releaseWallOfForceTempData(_lvlTempData[i]);
|
||||
delete _lvlTempData[i];
|
||||
}
|
||||
|
||||
_lvlTempData[i] = new LevelTempData;
|
||||
_lvlTempData[i]->wallsXorData = new uint8[4096];
|
||||
_lvlTempData[i]->flags = new uint16[1024];
|
||||
LoLMonster *lm = new LoLMonster[30];
|
||||
_lvlTempData[i]->monsters = lm;
|
||||
FlyingObject *lf = new FlyingObject[_numFlyingObjects];
|
||||
_lvlTempData[i]->flyingObjects = lf;
|
||||
LevelTempData *l = _lvlTempData[i];
|
||||
|
||||
uint32 next = in.pos() + 2500;
|
||||
|
||||
if (header.originalSave) {
|
||||
in.skip(4);
|
||||
in.read(origCmp, in.readUint16());
|
||||
_screen->decodeFrame4(origCmp, _tempBuffer5120, 5120);
|
||||
memcpy(l->wallsXorData, _tempBuffer5120, 4096);
|
||||
for (int ii = 0; ii < 1024; ii++)
|
||||
l->flags[ii] = _tempBuffer5120[4096 + ii];
|
||||
} else {
|
||||
in.read(l->wallsXorData, 4096);
|
||||
for (int ii = 0; ii < 1024; ii++)
|
||||
l->flags[ii] = in.readByte();
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
l->monsterDifficulty = in.readUint16();
|
||||
|
||||
for (int ii = 0; ii < 30; ii++) {
|
||||
LoLMonster *m = &lm[ii];
|
||||
m->nextAssignedObject = in.readUint16();
|
||||
m->nextDrawObject = in.readUint16();
|
||||
m->flyingHeight = in.readByte();
|
||||
m->block = in.readUint16();
|
||||
m->x = in.readUint16();
|
||||
m->y = in.readUint16();
|
||||
m->shiftStep = in.readSByte();
|
||||
m->destX = in.readUint16();
|
||||
m->destY = in.readUint16();
|
||||
m->destDirection = in.readByte();
|
||||
m->hitOffsX = in.readSByte();
|
||||
m->hitOffsY = in.readSByte();
|
||||
m->currentSubFrame = in.readByte();
|
||||
m->mode = in.readByte();
|
||||
m->fightCurTick = in.readSByte();
|
||||
m->id = in.readByte();
|
||||
m->direction = in.readByte();
|
||||
m->facing = in.readByte();
|
||||
m->flags = in.readUint16();
|
||||
m->damageReceived = in.readUint16();
|
||||
m->hitPoints = in.readSint16();
|
||||
m->speedTick = in.readByte();
|
||||
m->type = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(4);
|
||||
|
||||
m->numDistAttacks = in.readByte();
|
||||
m->curDistWeapon = in.readByte();
|
||||
m->distAttackTick = in.readSByte();
|
||||
m->assignedItems = in.readUint16();
|
||||
m->properties = &_monsterProperties[m->type];
|
||||
in.read(m->equipmentShapes, 4);
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < _numFlyingObjects; ii++) {
|
||||
FlyingObject *m = &lf[ii];
|
||||
m->enable = in.readByte();
|
||||
m->objectType = in.readByte();
|
||||
m->attackerId = in.readUint16();
|
||||
m->item = in.readSint16();
|
||||
m->x = in.readUint16();
|
||||
m->y = in.readUint16();
|
||||
m->flyingHeight = in.readByte();
|
||||
m->direction = in.readByte();
|
||||
m->distance = in.readByte();
|
||||
m->field_D = in.readSByte();
|
||||
m->c = in.readByte();
|
||||
m->flags = in.readByte();
|
||||
m->wallFlags = in.readByte();
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
in.seek(next, SEEK_SET);
|
||||
else
|
||||
l->monsterDifficulty = in.readByte();
|
||||
}
|
||||
|
||||
delete[] origCmp;
|
||||
|
||||
calcCharPortraitXpos();
|
||||
memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight));
|
||||
int t = _credits;
|
||||
_credits = 0;
|
||||
giveCredits(t, 0);
|
||||
setHandItem(_itemInHand);
|
||||
loadLevel(_currentLevel);
|
||||
gui_drawPlayField();
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
timerSpecialCharacterUpdate(0);
|
||||
_flagsTable[73] |= 0x08;
|
||||
|
||||
while (!_screen->isMouseVisible())
|
||||
_screen->showMouse();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail);
|
||||
if (!out)
|
||||
return _saveFileMan->getError();
|
||||
|
||||
completeDoorOperations();
|
||||
generateTempData();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LoLCharacter *c = &_characters[i];
|
||||
out->writeUint16BE(c->flags);
|
||||
out->write(c->name, 11);
|
||||
out->writeByte(c->raceClassSex);
|
||||
out->writeSint16BE(c->id);
|
||||
out->writeByte(c->curFaceFrame);
|
||||
out->writeByte(c->tempFaceFrame);
|
||||
out->writeByte(c->screamSfx);
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
out->writeUint16BE(c->itemsMight[ii]);
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
out->writeUint16BE(c->protectionAgainstItems[ii]);
|
||||
out->writeUint16BE(c->itemProtection);
|
||||
out->writeSint16BE(c->hitPointsCur);
|
||||
out->writeUint16BE(c->hitPointsMax);
|
||||
out->writeSint16BE(c->magicPointsCur);
|
||||
out->writeUint16BE(c->magicPointsMax);
|
||||
out->writeByte(c->field_41);
|
||||
out->writeUint16BE(c->damageSuffered);
|
||||
out->writeUint16BE(c->weaponHit);
|
||||
out->writeUint16BE(c->totalMightModifier);
|
||||
out->writeUint16BE(c->totalProtectionModifier);
|
||||
out->writeUint16BE(c->might);
|
||||
out->writeUint16BE(c->protection);
|
||||
out->writeSint16BE(c->nextAnimUpdateCountdown);
|
||||
for (int ii = 0; ii < 11; ii++)
|
||||
out->writeUint16BE(c->items[ii]);
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
out->writeByte(c->skillLevels[ii]);
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
out->writeSByte(c->skillModifiers[ii]);
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
out->writeUint32BE(c->experiencePts[ii]);
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
out->writeByte(c->characterUpdateEvents[ii]);
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
out->writeByte(c->characterUpdateDelay[ii]);
|
||||
}
|
||||
|
||||
out->writeUint16BE(_currentBlock);
|
||||
out->writeUint16BE(_partyPosX);
|
||||
out->writeUint16BE(_partyPosY);
|
||||
out->writeUint16BE(_updateFlags);
|
||||
out->writeByte(_scriptDirection);
|
||||
out->writeByte(_selectedSpell);
|
||||
out->writeByte(_sceneDefaultUpdate);
|
||||
out->writeByte(_compassBroken);
|
||||
out->writeByte(_drainMagic);
|
||||
out->writeUint16BE(_currentDirection);
|
||||
out->writeUint16BE(_compassDirection);
|
||||
out->writeSByte(_selectedCharacter);
|
||||
out->writeByte(_currentLevel);
|
||||
for (int i = 0; i < 48; i++)
|
||||
out->writeSint16BE(_inventory[i]);
|
||||
out->writeSint16BE(_inventoryCurItem);
|
||||
out->writeSint16BE(_itemInHand);
|
||||
out->writeSint16BE(_lastMouseRegion);
|
||||
out->writeUint32BE(ARRAYSIZE(_flagsTable));
|
||||
out->write(_flagsTable, ARRAYSIZE(_flagsTable));
|
||||
for (int i = 0; i < 24; i++)
|
||||
out->writeUint16BE(_globalScriptVars[i]);
|
||||
out->writeByte(_brightness);
|
||||
out->writeByte(_lampOilStatus);
|
||||
out->writeSByte(_lampEffect);
|
||||
out->writeUint16BE(_credits);
|
||||
for (int i = 0; i < 8; i++)
|
||||
out->writeUint16BE(_globalScriptVars2[i]);
|
||||
out->write(_availableSpells, 7);
|
||||
out->writeUint32BE(_hasTempDataFlags);
|
||||
|
||||
resetItems(0);
|
||||
|
||||
for (int i = 0; i < 400; i++) {
|
||||
LoLItem *t = &_itemsInPlay[i];
|
||||
out->writeUint16BE(t->nextAssignedObject);
|
||||
out->writeUint16BE(t->nextDrawObject);
|
||||
out->writeByte(t->flyingHeight);
|
||||
out->writeUint16BE(t->block);
|
||||
out->writeUint16BE(t->x);
|
||||
out->writeUint16BE(t->y);
|
||||
out->writeSByte(t->level);
|
||||
out->writeUint16BE(t->itemPropertyIndex);
|
||||
out->writeUint16BE(t->shpCurFrame_flg);
|
||||
}
|
||||
|
||||
addLevelItems();
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
LevelTempData *l = _lvlTempData[i];
|
||||
if (!l || !(_hasTempDataFlags & (1 << i)))
|
||||
continue;
|
||||
|
||||
out->write(l->wallsXorData, 4096);
|
||||
for (int ii = 0; ii < 1024; ii++)
|
||||
out->writeByte(l->flags[ii] & 0xFF);
|
||||
|
||||
LoLMonster *lm = (LoLMonster *)_lvlTempData[i]->monsters;
|
||||
FlyingObject *lf = (FlyingObject *)_lvlTempData[i]->flyingObjects;
|
||||
|
||||
for (int ii = 0; ii < 30; ii++) {
|
||||
LoLMonster *m = &lm[ii];
|
||||
out->writeUint16BE(m->nextAssignedObject);
|
||||
out->writeUint16BE(m->nextDrawObject);
|
||||
out->writeByte(m->flyingHeight);
|
||||
out->writeUint16BE(m->block);
|
||||
out->writeUint16BE(m->x);
|
||||
out->writeUint16BE(m->y);
|
||||
out->writeSByte(m->shiftStep);
|
||||
out->writeUint16BE(m->destX);
|
||||
out->writeUint16BE(m->destY);
|
||||
out->writeByte(m->destDirection);
|
||||
out->writeSByte(m->hitOffsX);
|
||||
out->writeSByte(m->hitOffsY);
|
||||
out->writeByte(m->currentSubFrame);
|
||||
out->writeByte(m->mode);
|
||||
out->writeSByte(m->fightCurTick);
|
||||
out->writeByte(m->id);
|
||||
out->writeByte(m->direction);
|
||||
out->writeByte(m->facing);
|
||||
out->writeUint16BE(m->flags);
|
||||
out->writeUint16BE(m->damageReceived);
|
||||
out->writeSint16BE(m->hitPoints);
|
||||
out->writeByte(m->speedTick);
|
||||
out->writeByte(m->type);
|
||||
out->writeByte(m->numDistAttacks);
|
||||
out->writeByte(m->curDistWeapon);
|
||||
out->writeSByte(m->distAttackTick);
|
||||
out->writeUint16BE(m->assignedItems);
|
||||
out->write(m->equipmentShapes, 4);
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < _numFlyingObjects; ii++) {
|
||||
FlyingObject *m = &lf[ii];
|
||||
out->writeByte(m->enable);
|
||||
out->writeByte(m->objectType);
|
||||
out->writeUint16BE(m->attackerId);
|
||||
out->writeSint16BE(m->item);
|
||||
out->writeUint16BE(m->x);
|
||||
out->writeUint16BE(m->y);
|
||||
out->writeByte(m->flyingHeight);
|
||||
out->writeByte(m->direction);
|
||||
out->writeByte(m->distance);
|
||||
out->writeSByte(m->field_D);
|
||||
out->writeByte(m->c);
|
||||
out->writeByte(m->flags);
|
||||
out->writeByte(m->wallFlags);
|
||||
}
|
||||
out->writeByte(l->monsterDifficulty);
|
||||
}
|
||||
|
||||
out->finalize();
|
||||
|
||||
// check for errors
|
||||
if (out->err()) {
|
||||
warning("Can't write file '%s'. (Disk full?)", fileName);
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
|
||||
}
|
||||
|
||||
delete out;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Graphics::Surface *LoLEngine::generateSaveThumbnail() const {
|
||||
if (_flags.platform != Common::kPlatformPC98)
|
||||
return 0;
|
||||
|
||||
uint8 *screenPal = new uint8[16 * 3];
|
||||
assert(screenPal);
|
||||
_screen->getRealPalette(0, screenPal);
|
||||
|
||||
uint8 *screenBuf = new uint8[Screen::SCREEN_W * Screen::SCREEN_H];
|
||||
assert(screenBuf);
|
||||
|
||||
Graphics::Surface *dst = new Graphics::Surface();
|
||||
assert(dst);
|
||||
|
||||
_screen->copyRegionToBuffer(0, 0, 0, 320, 200, screenBuf);
|
||||
Screen_LoL::convertPC98Gfx(screenBuf, Screen::SCREEN_W, Screen::SCREEN_H, Screen::SCREEN_W);
|
||||
::createThumbnail(dst, screenBuf, Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
|
||||
|
||||
delete[] screenBuf;
|
||||
delete[] screenPal;
|
||||
return dst;
|
||||
}
|
||||
|
||||
void LoLEngine::restoreBlockTempData(int levelIndex) {
|
||||
memset(_tempBuffer5120, 0, 5120);
|
||||
KyraRpgEngine::restoreBlockTempData(levelIndex);
|
||||
restoreTempDataAdjustMonsterStrength(levelIndex - 1);
|
||||
}
|
||||
|
||||
void *LoLEngine::generateMonsterTempData(LevelTempData *tmp) {
|
||||
LoLMonster *m = new LoLMonster[30];
|
||||
memcpy(m, _monsters, sizeof(LoLMonster) * 30);
|
||||
tmp->monsterDifficulty = _monsterDifficulty;
|
||||
return m;
|
||||
}
|
||||
|
||||
void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) {
|
||||
if (_lvlTempData[index]->monsterDifficulty == _monsterDifficulty)
|
||||
return;
|
||||
|
||||
uint16 d = (_monsterModifiers1[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers1[_monsterDifficulty];
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
|
||||
continue;
|
||||
|
||||
_monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
|
||||
if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
|
||||
_monsters[i].hitPoints++;
|
||||
if (_monsters[i].hitPoints == 0)
|
||||
_monsters[i].hitPoints = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void LoLEngine::restoreMonsterTempData(LevelTempData *tmp) {
|
||||
memcpy(_monsters, tmp->monsters, sizeof(LoLMonster) * 30);
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
if (_monsters[i].block) {
|
||||
_monsters[i].block = 0;
|
||||
_monsters[i].properties = &_monsterProperties[_monsters[i].type];
|
||||
placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoLEngine::releaseMonsterTempData(LevelTempData *tmp) {
|
||||
LoLMonster *p = (LoLMonster *)tmp->monsters;
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_LOL
|
||||
330
engines/kyra/gui/saveload_mr.cpp
Normal file
330
engines/kyra/gui/saveload_mr.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "kyra/engine/kyra_mr.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
Common::Error KyraEngine_MR::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
|
||||
if (!out)
|
||||
return _saveFileMan->getError();
|
||||
|
||||
_timer->saveDataToFile(*out);
|
||||
|
||||
out->writeUint32BE(sizeof(_flagsTable));
|
||||
out->write(_flagsTable, sizeof(_flagsTable));
|
||||
|
||||
out->writeSint16BE(_lastMusicCommand);
|
||||
out->writeByte(_currentChapter);
|
||||
out->writeByte(_characterShapeFile);
|
||||
out->writeByte(_album.curPage);
|
||||
out->writeSint16BE(_score);
|
||||
out->writeSint16BE(_scoreMax);
|
||||
out->writeByte(_malcolmsMood);
|
||||
for (int i = 0; i < 30; ++i)
|
||||
out->write(_conversationState[i], 30);
|
||||
out->write(_newSceneDlgState, 40);
|
||||
for (int i = 0; i < 100; ++i)
|
||||
out->writeSint16BE(_hiddenItems[i]);
|
||||
out->write(_scoreFlagTable, 26);
|
||||
|
||||
out->writeUint16BE(_mainCharacter.sceneId);
|
||||
out->writeSint16BE(_mainCharacter.dlgIndex);
|
||||
out->writeByte(_mainCharacter.height);
|
||||
out->writeByte(_mainCharacter.facing);
|
||||
out->writeUint16BE(_mainCharacter.animFrame);
|
||||
out->writeByte(_mainCharacter.walkspeed);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
out->writeUint16BE(_mainCharacter.inventory[i]);
|
||||
out->writeSint16BE(_mainCharacter.x1);
|
||||
out->writeSint16BE(_mainCharacter.y1);
|
||||
out->writeSint16BE(_mainCharacter.x2);
|
||||
out->writeSint16BE(_mainCharacter.y2);
|
||||
out->writeSint16BE(_mainCharacter.x3);
|
||||
out->writeSint16BE(_mainCharacter.y3);
|
||||
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
out->writeSint16BE(_itemList[i].id);
|
||||
out->writeUint16BE(_itemList[i].sceneId);
|
||||
out->writeSint16BE(_itemList[i].x);
|
||||
out->writeSint16BE(_itemList[i].y);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 88; ++i) {
|
||||
out->write(_talkObjectList[i].filename, 13);
|
||||
out->writeByte(_talkObjectList[i].sceneAnim);
|
||||
out->writeByte(_talkObjectList[i].sceneScript);
|
||||
out->writeSint16BE(_talkObjectList[i].x);
|
||||
out->writeSint16BE(_talkObjectList[i].y);
|
||||
out->writeByte(_talkObjectList[i].color);
|
||||
out->writeByte(_talkObjectList[i].sceneId);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 98; ++i) {
|
||||
out->write(_sceneList[i].filename1, 10);
|
||||
out->write(_sceneList[i].filename2, 10);
|
||||
out->writeUint16BE(_sceneList[i].exit1);
|
||||
out->writeUint16BE(_sceneList[i].exit2);
|
||||
out->writeUint16BE(_sceneList[i].exit3);
|
||||
out->writeUint16BE(_sceneList[i].exit4);
|
||||
out->writeByte(_sceneList[i].flags);
|
||||
out->writeByte(_sceneList[i].sound);
|
||||
}
|
||||
|
||||
out->writeSint16BE(_itemInHand);
|
||||
out->writeUint16BE(_sceneExit1);
|
||||
out->writeUint16BE(_sceneExit2);
|
||||
out->writeUint16BE(_sceneExit3);
|
||||
out->writeUint16BE(_sceneExit4);
|
||||
|
||||
out->finalize();
|
||||
|
||||
// check for errors
|
||||
if (out->err()) {
|
||||
warning("Can't write file '%s'. (Disk full?)", fileName);
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
|
||||
}
|
||||
|
||||
delete out;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error KyraEngine_MR::loadGameState(int slot) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
|
||||
SaveHeader header;
|
||||
Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
|
||||
if (!saveFile) {
|
||||
showMessageFromCCode(17, 0xB3, 0);
|
||||
snd_playSoundEffect(0x0D, 0xC8);
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");
|
||||
|
||||
if (_inventoryState) {
|
||||
updateCharacterAnim(0);
|
||||
restorePage3();
|
||||
drawAnimObjects();
|
||||
_inventoryState = true;
|
||||
refreshAnimObjects(0);
|
||||
hideInventory();
|
||||
}
|
||||
|
||||
_deathHandler = -1;
|
||||
if (!_unkSceneScreenFlag1)
|
||||
_lastMusicCommand = -1;
|
||||
|
||||
int curShapes = _characterShapeFile;
|
||||
|
||||
Common::SeekableReadStreamEndianWrapper in(saveFile, !header.originalSave, DisposeAfterUse::YES);
|
||||
|
||||
_screen->hideMouse();
|
||||
|
||||
if (!header.originalSave) {
|
||||
_timer->loadDataFromFile(in, header.version);
|
||||
|
||||
uint32 flagsSize = in.readUint32BE();
|
||||
assert(flagsSize <= sizeof(_flagsTable));
|
||||
in.read(_flagsTable, flagsSize);
|
||||
}
|
||||
|
||||
_lastMusicCommand = in.readSint16();
|
||||
_currentChapter = in.readByte();
|
||||
_characterShapeFile = in.readByte();
|
||||
|
||||
if (header.version >= 12 || header.originalSave)
|
||||
_album.curPage = in.readByte();
|
||||
if (header.originalSave)
|
||||
in.readByte();
|
||||
|
||||
_score = in.readSint16();
|
||||
_scoreMax = in.readSint16();
|
||||
_malcolmsMood = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.seek(8, SEEK_CUR);
|
||||
|
||||
for (int i = 0; i < 30; ++i)
|
||||
in.read(_conversationState[i], 30);
|
||||
|
||||
if (!header.originalSave) {
|
||||
in.read(_newSceneDlgState, 40);
|
||||
} else {
|
||||
for (int i = 0; i < 40; ++i)
|
||||
_newSceneDlgState[i] = in.readUint16();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
_hiddenItems[i] = in.readSint16();
|
||||
|
||||
if (header.originalSave)
|
||||
in.read(_flagsTable, 69);
|
||||
in.read(_scoreFlagTable, 26);
|
||||
|
||||
_mainCharacter.sceneId = in.readUint16();
|
||||
_mainCharacter.dlgIndex = in.readSint16();
|
||||
_mainCharacter.height = in.readByte();
|
||||
_mainCharacter.facing = in.readByte();
|
||||
_mainCharacter.animFrame = in.readUint16();
|
||||
if (!header.originalSave) {
|
||||
_mainCharacter.walkspeed = in.readByte();
|
||||
} else {
|
||||
in.seek(2, SEEK_CUR);
|
||||
_mainCharacter.walkspeed = in.readUint32();
|
||||
}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
_mainCharacter.inventory[i] = in.readUint16();
|
||||
_mainCharacter.x1 = in.readSint16();
|
||||
_mainCharacter.y1 = in.readSint16();
|
||||
_mainCharacter.x2 = in.readSint16();
|
||||
_mainCharacter.y2 = in.readSint16();
|
||||
_mainCharacter.x3 = in.readSint16();
|
||||
_mainCharacter.y3 = in.readSint16();
|
||||
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
_itemList[i].id = in.readSint16();
|
||||
_itemList[i].sceneId = in.readUint16();
|
||||
_itemList[i].x = in.readSint16();
|
||||
_itemList[i].y = in.readSint16();
|
||||
if (header.version <= 9 || header.originalSave)
|
||||
in.readUint16();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 88; ++i) {
|
||||
in.read(_talkObjectList[i].filename, 13);
|
||||
_talkObjectList[i].sceneAnim = in.readByte();
|
||||
_talkObjectList[i].sceneScript = in.readByte();
|
||||
_talkObjectList[i].x = in.readSint16();
|
||||
_talkObjectList[i].y = in.readSint16();
|
||||
_talkObjectList[i].color = in.readByte();
|
||||
if (header.version >= 13 || header.originalSave)
|
||||
_talkObjectList[i].sceneId = in.readByte();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 98; ++i) {
|
||||
if (!header.originalSave) {
|
||||
in.read(_sceneList[i].filename1, 10);
|
||||
} else {
|
||||
in.read(_sceneList[i].filename1, 9);
|
||||
_sceneList[i].filename1[9] = 0;
|
||||
}
|
||||
|
||||
if (!header.originalSave) {
|
||||
in.read(_sceneList[i].filename2, 10);
|
||||
} else {
|
||||
in.read(_sceneList[i].filename2, 9);
|
||||
_sceneList[i].filename2[9] = 0;
|
||||
}
|
||||
|
||||
_sceneList[i].exit1 = in.readUint16();
|
||||
_sceneList[i].exit2 = in.readUint16();
|
||||
_sceneList[i].exit3 = in.readUint16();
|
||||
_sceneList[i].exit4 = in.readUint16();
|
||||
_sceneList[i].flags = in.readByte();
|
||||
_sceneList[i].sound = in.readByte();
|
||||
}
|
||||
|
||||
_itemInHand = in.readSint16();
|
||||
|
||||
if (header.originalSave) {
|
||||
uint32 currentTime = _system->getMillis();
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_timer->setDelay(i, in.readSint32LE());
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (in.readUint16LE())
|
||||
_timer->enable(i);
|
||||
else
|
||||
_timer->disable(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
_timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength));
|
||||
|
||||
_timer->resetNextRun();
|
||||
}
|
||||
|
||||
_sceneExit1 = in.readUint16();
|
||||
_sceneExit2 = in.readUint16();
|
||||
_sceneExit3 = in.readUint16();
|
||||
_sceneExit4 = in.readUint16();
|
||||
|
||||
if (saveFile->err() || saveFile->eos()) {
|
||||
warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
|
||||
return Common::kUnknownError;
|
||||
} else {
|
||||
debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
|
||||
}
|
||||
|
||||
_loadingState = true;
|
||||
updateCharacterAnim(0);
|
||||
_loadingState = false;
|
||||
|
||||
if (curShapes != _characterShapeFile)
|
||||
loadCharacterShapes(_characterShapeFile);
|
||||
|
||||
_mainCharX = _mainCharacter.x2 = _mainCharacter.x1;
|
||||
_mainCharY = _mainCharacter.y2 = _mainCharacter.y1;
|
||||
_mainCharacter.facing = 4;
|
||||
_badConscienceShown = false;
|
||||
_badConsciencePosition = false;
|
||||
_goodConscienceShown = false;
|
||||
_goodConsciencePosition = false;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
setHandItem(_itemInHand);
|
||||
|
||||
if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1)
|
||||
snd_playWanderScoreViaMap(_lastMusicCommand, 1);
|
||||
else if (_lastMusicCommand == -1)
|
||||
snd_playWanderScoreViaMap(28, 1);
|
||||
|
||||
while (!_screen->isMouseVisible())
|
||||
_screen->showMouse();
|
||||
|
||||
setCommandLineRestoreTimer(7);
|
||||
_shownMessage = " ";
|
||||
_restoreCommandLine = false;
|
||||
|
||||
// We didn't explicitly set the walk speed, but it's saved as part of
|
||||
// the _timers array, so we need to re-sync it with _configWalkspeed.
|
||||
setWalkspeed(_configWalkspeed);
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
126
engines/kyra/gui/saveload_rpg.cpp
Normal file
126
engines/kyra/gui/saveload_rpg.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
|
||||
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/script/script_eob.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
void KyraRpgEngine::generateTempData() {
|
||||
int l = _currentLevel - 1;
|
||||
if (_lvlTempData[l]) {
|
||||
delete[] _lvlTempData[l]->wallsXorData;
|
||||
delete[] _lvlTempData[l]->flags;
|
||||
releaseMonsterTempData(_lvlTempData[l]);
|
||||
releaseFlyingObjectTempData(_lvlTempData[l]);
|
||||
releaseWallOfForceTempData(_lvlTempData[l]);
|
||||
delete _lvlTempData[l];
|
||||
}
|
||||
|
||||
_lvlTempData[l] = new LevelTempData;
|
||||
|
||||
_lvlTempData[l]->wallsXorData = new uint8[4096];
|
||||
_lvlTempData[l]->flags = new uint16[1024];
|
||||
|
||||
const uint8 *p = getBlockFileData(_currentLevel);
|
||||
uint16 len = READ_LE_UINT16(p + 4);
|
||||
p += 6;
|
||||
|
||||
memset(_lvlTempData[l]->wallsXorData, 0, 4096);
|
||||
memset(_lvlTempData[l]->flags, 0, 1024 * sizeof(uint16));
|
||||
uint8 *d = _lvlTempData[l]->wallsXorData;
|
||||
uint16 *df = _lvlTempData[l]->flags;
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
for (int ii = 0; ii < 4; ii++)
|
||||
*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
|
||||
*df++ = _levelBlockProperties[i].flags;
|
||||
}
|
||||
|
||||
_lvlTempData[l]->monsters = generateMonsterTempData(_lvlTempData[l]);
|
||||
_lvlTempData[l]->flyingObjects = generateFlyingObjectTempData(_lvlTempData[l]);
|
||||
_lvlTempData[l]->wallsOfForce = generateWallOfForceTempData(_lvlTempData[l]);
|
||||
|
||||
_hasTempDataFlags |= (1 << l);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::restoreBlockTempData(int levelIndex) {
|
||||
int l = levelIndex - 1;
|
||||
const uint8 *p = getBlockFileData(levelIndex);
|
||||
uint16 len = READ_LE_UINT16(p + 4);
|
||||
p += 6;
|
||||
|
||||
memset(_levelBlockProperties, 0, 1024 * sizeof(LevelBlockProperty));
|
||||
|
||||
uint8 *t = _lvlTempData[l]->wallsXorData;
|
||||
uint16 *t2 = _lvlTempData[l]->flags;
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
for (int ii = 0; ii < 4; ii++)
|
||||
_levelBlockProperties[i].walls[ii] = p[i * len + ii] ^ *t++;
|
||||
_levelBlockProperties[i].flags = *t2++;
|
||||
}
|
||||
|
||||
restoreMonsterTempData(_lvlTempData[l]);
|
||||
restoreFlyingObjectTempData(_lvlTempData[l]);
|
||||
restoreWallOfForceTempData(_lvlTempData[l]);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::releaseTempData() {
|
||||
for (int i = 0; i < 29; i++) {
|
||||
if (_lvlTempData[i]) {
|
||||
delete[] _lvlTempData[i]->wallsXorData;
|
||||
delete[] _lvlTempData[i]->flags;
|
||||
releaseMonsterTempData(_lvlTempData[i]);
|
||||
releaseFlyingObjectTempData(_lvlTempData[i]);
|
||||
releaseWallOfForceTempData(_lvlTempData[i]);
|
||||
delete _lvlTempData[i];
|
||||
_lvlTempData[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *KyraRpgEngine::generateFlyingObjectTempData(LevelTempData *tmp) {
|
||||
assert(_flyingObjectStructSize == sizeof(EoBFlyingObject));
|
||||
EoBFlyingObject *f = new EoBFlyingObject[_numFlyingObjects];
|
||||
memcpy(f, _flyingObjectsPtr, sizeof(EoBFlyingObject) * _numFlyingObjects);
|
||||
return f;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::restoreFlyingObjectTempData(LevelTempData *tmp) {
|
||||
assert(_flyingObjectStructSize == sizeof(EoBFlyingObject));
|
||||
memcpy(_flyingObjectsPtr, tmp->flyingObjects, sizeof(EoBFlyingObject) * _numFlyingObjects);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::releaseFlyingObjectTempData(LevelTempData *tmp) {
|
||||
EoBFlyingObject *p = (EoBFlyingObject *)tmp->flyingObjects;
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_EOB || ENABLE_LOL
|
||||
Reference in New Issue
Block a user