aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/agi/agi.cpp14
-rw-r--r--engines/agi/agi.h3
-rw-r--r--engines/agi/keyboard.h7
-rw-r--r--engines/agi/savegame.cpp161
4 files changed, 143 insertions, 42 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index b19040ed0a..f13c905411 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -52,11 +52,6 @@ namespace Agi {
static uint32 g_tickTimer;
struct Mouse g_mouse;
-#define keyEnqueue(k) do { _keyQueue[_keyQueueEnd++] = (k); \
- _keyQueueEnd %= KEY_QUEUE_SIZE; } while (0)
-#define keyDequeue(k) do { (k) = _keyQueue[_keyQueueStart++]; \
- _keyQueueStart %= KEY_QUEUE_SIZE; } while (0)
-
void AgiEngine::processEvents() {
OSystem::Event event;
int key = 0;
@@ -82,6 +77,14 @@ void AgiEngine::processEvents() {
g_mouse.x = event.mouse.x;
g_mouse.y = event.mouse.y;
break;
+ case OSystem::EVENT_WHEELUP:
+ key = WHEEL_UP;
+ keyEnqueue(key);
+ break;
+ case OSystem::EVENT_WHEELDOWN:
+ key = WHEEL_DOWN;
+ keyEnqueue(key);
+ break;
case OSystem::EVENT_MOUSEMOVE:
g_mouse.x = event.mouse.x;
g_mouse.y = event.mouse.y;
@@ -557,6 +560,7 @@ AgiEngine::AgiEngine(OSystem *syst) : Engine(syst) {
_oldMode = -1;
_searchTreeRoot = 0;
+ _firstSlot = 0;
}
void AgiEngine::initialize() {
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 8170fd356f..c3788209f5 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -524,6 +524,8 @@ private:
uint32 matchVersion(uint32 crc);
+ int _firstSlot;
+
public:
AgiGame _game;
AgiObject *_objects; /* objects in the game */
@@ -535,6 +537,7 @@ public:
Common::RandomSource *_rnd;
const char *getSavegameFilename(int num);
+ void getSavegameDescription(int num, char *buf);
int selectSlot();
int saveGame(const char *fileName, const char *saveName);
int saveGameDialog();
diff --git a/engines/agi/keyboard.h b/engines/agi/keyboard.h
index 8a905127e3..0220db41c5 100644
--- a/engines/agi/keyboard.h
+++ b/engines/agi/keyboard.h
@@ -29,6 +29,11 @@
namespace Agi {
+#define keyEnqueue(k) do { _keyQueue[_keyQueueEnd++] = (k); \
+ _keyQueueEnd %= KEY_QUEUE_SIZE; } while (0)
+#define keyDequeue(k) do { (k) = _keyQueue[_keyQueueStart++]; \
+ _keyQueueStart %= KEY_QUEUE_SIZE; } while (0)
+
/* QNX4 has a KEY_DOWN defined which we don't need to care about */
#undef KEY_DOWN
@@ -67,6 +72,8 @@ namespace Agi {
#define BUTTON_LEFT 0xF101 /* Left mouse button */
#define BUTTON_RIGHT 0xF202 /* Right mouse button */
+#define WHEEL_UP 0xF203 /* Mouse wheel up */
+#define WHEEL_DOWN 0xF204 /* Mouse wheel down */
#define KEY_SCAN(k) (k >> 8)
#define KEY_ASCII(k) (k & 0xff)
diff --git a/engines/agi/savegame.cpp b/engines/agi/savegame.cpp
index 1dd63ee66a..30b5bf0b21 100644
--- a/engines/agi/savegame.cpp
+++ b/engines/agi/savegame.cpp
@@ -451,45 +451,50 @@ int AgiEngine::loadGame(const char *fileName) {
return errOK;
}
-#define NUM_SLOTS 12
+#define NUM_SLOTS 100
+#define NUM_VISIBLE_SLOTS 12
const char *AgiEngine::getSavegameFilename(int num) {
static char saveLoadSlot[12];
- sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num);
+ sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num + _firstSlot);
return saveLoadSlot;
}
+
+void AgiEngine::getSavegameDescription(int num, char *buf) {
+ char fileName[MAX_PATH];
+ Common::InSaveFile *in;
+
+ debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Current game id is %s", _targetName.c_str());
+ sprintf(fileName, "%s", getSavegameFilename(num));
+ if (!(in = _saveFileMan->openForLoading(fileName))) {
+ debugC(4, kDebugLevelMain | kDebugLevelSavegame, "File %s does not exist", fileName);
+ strcpy(buf, " (empty slot)");
+ } else {
+ debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName);
+ uint32 type = in->readUint32BE();
+ if (type == AGIflag) {
+ debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start");
+ in->read(buf, 31);
+ } else {
+ warning("This doesn't appear to be an AGI savegame");
+ strcpy(buf, "(corrupt file)");
+ }
+
+ delete in;
+ }
+}
int AgiEngine::selectSlot() {
int i, key, active = 0;
int rc = -1;
- int hm = 2, vm = 3; /* box margins */
+ int hm = 1, vm = 3; /* box margins */
int xmin, xmax, slotClicked;
- char desc[NUM_SLOTS][40];
+ char desc[NUM_VISIBLE_SLOTS][40];
int textCentre, buttonLength, buttonX[2], buttonY;
const char *buttonText[] = { " OK ", "Cancel", NULL };
- for (i = 0; i < NUM_SLOTS; i++) {
- char fileName[MAX_PATH];
- Common::InSaveFile *in;
-
- debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Current game id is %s", _targetName.c_str());
- sprintf(fileName, "%s", getSavegameFilename(i));
- if (!(in = _saveFileMan->openForLoading(fileName))) {
- debugC(4, kDebugLevelMain | kDebugLevelSavegame, "File %s does not exist", fileName);
- strcpy(desc[i], " (empty slot)");
- } else {
- debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName);
- uint32 type = in->readUint32BE();
- if (type == AGIflag) {
- debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start");
- in->read(desc[i], 31);
- } else {
- warning("This doesn't appear to be an AGI savegame");
- strcpy(desc[i], "(corrupt file)");
- }
-
- delete in;
- }
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
+ getSavegameDescription(i, desc[i]);
}
textCentre = GFX_WIDTH / CHAR_LINES / 2;
@@ -499,16 +504,31 @@ int AgiEngine::selectSlot() {
buttonY = (vm + 17) * CHAR_LINES;
for (i = 0; i < 2; i++)
- _gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ _gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
for (;;) {
char dstr[64];
- for (i = 0; i < NUM_SLOTS; i++) {
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
sprintf(dstr, "[%-32.32s]", desc[i]);
printText(dstr, 0, hm + 1, vm + 4 + i,
(40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
}
+
+ char upArrow[] = "^";
+ char downArrow[] = "v";
+ char scrollBar[] = " ";
+
+ int sbPos = 1 + (_firstSlot * (NUM_VISIBLE_SLOTS - 2)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS);
+ if (sbPos > NUM_VISIBLE_SLOTS - 2)
+ sbPos = NUM_VISIBLE_SLOTS - 2;
+
+ for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
+ printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
+
+ printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
+ printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
+ printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
_gfx->pollTimer(); /* msdos driver -> does nothing */
key = doPollKeyboard();
@@ -530,22 +550,89 @@ int AgiEngine::selectSlot() {
rc = -1;
goto getout;
}
+ slotClicked = ((int)g_mouse.y-1)/CHAR_COLS-(vm+4);
xmin = (hm + 1) * CHAR_COLS;
xmax = xmin + CHAR_COLS * 34;
if ((int)g_mouse.x >= xmin && (int)g_mouse.x <= xmax) {
- slotClicked = ((int)g_mouse.y-1)/CHAR_COLS-(vm+4);
- if (slotClicked >= 0 && slotClicked < NUM_SLOTS)
+ if (slotClicked >= 0 && slotClicked < NUM_VISIBLE_SLOTS)
active = slotClicked;
}
+ xmin = (hm + 36) * CHAR_COLS;
+ xmax = xmin + CHAR_COLS;
+ if ((int)g_mouse.x >= xmin && (int)g_mouse.x <= xmax) {
+ if (slotClicked >= 0 && slotClicked < NUM_VISIBLE_SLOTS) {
+ if (slotClicked == 0)
+ keyEnqueue(KEY_UP);
+ else if (slotClicked == NUM_VISIBLE_SLOTS - 1)
+ keyEnqueue(KEY_DOWN);
+ else if (slotClicked < sbPos)
+ keyEnqueue(KEY_UP_RIGHT);
+ else if (slotClicked > sbPos)
+ keyEnqueue(KEY_DOWN_RIGHT);
+ }
+ }
break;
case KEY_DOWN:
active++;
- active %= NUM_SLOTS;
+ if (active >= NUM_VISIBLE_SLOTS) {
+ if (_firstSlot + NUM_VISIBLE_SLOTS < NUM_SLOTS) {
+ _firstSlot++;
+ for (i = 1; i < NUM_VISIBLE_SLOTS; i++)
+ memcpy(desc[i - 1], desc[i], sizeof(desc[0]));
+ getSavegameDescription(NUM_VISIBLE_SLOTS - 1, desc[NUM_VISIBLE_SLOTS - 1]);
+ }
+ active = NUM_VISIBLE_SLOTS - 1;
+ }
break;
case KEY_UP:
active--;
- if (active < 0)
- active = NUM_SLOTS - 1;
+ if (active < 0) {
+ active = 0;
+ if (_firstSlot > 0) {
+ _firstSlot--;
+ for (i = NUM_VISIBLE_SLOTS - 1; i > 0; i--)
+ memcpy(desc[i], desc[i - 1], sizeof(desc[0]));
+ getSavegameDescription(0, desc[0]);
+ }
+ }
+ break;
+
+ // Page Up/Down and mouse wheel scrolling all leave 'active'
+ // unchanged so that a visible slot will remain selected.
+
+ case WHEEL_DOWN:
+ if (_firstSlot < NUM_SLOTS - NUM_VISIBLE_SLOTS) {
+ _firstSlot++;
+ for (i = 1; i < NUM_VISIBLE_SLOTS; i++)
+ memcpy(desc[i - 1], desc[i], sizeof(desc[0]));
+ getSavegameDescription(NUM_VISIBLE_SLOTS - 1, desc[NUM_VISIBLE_SLOTS - 1]);
+ }
+ break;
+ case WHEEL_UP:
+ if (_firstSlot > 0) {
+ _firstSlot--;
+ for (i = NUM_VISIBLE_SLOTS - 1; i > 0; i--)
+ memcpy(desc[i], desc[i - 1], sizeof(desc[0]));
+ getSavegameDescription(0, desc[0]);
+ }
+ break;
+ case KEY_DOWN_RIGHT:
+ // This is probably triggered by Page Down.
+ _firstSlot += NUM_VISIBLE_SLOTS;
+ if (_firstSlot > NUM_SLOTS - NUM_VISIBLE_SLOTS) {
+ _firstSlot = NUM_SLOTS - NUM_VISIBLE_SLOTS;
+ }
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++)
+ getSavegameDescription(i, desc[i]);
+ break;
+ case KEY_UP_RIGHT:
+ // This is probably triggered by Page Up.
+ _firstSlot -= NUM_VISIBLE_SLOTS;
+ if (_firstSlot < 0) {
+ _firstSlot = 0;
+ }
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++)
+ getSavegameDescription(i, desc[i]);
break;
}
_gfx->doUpdate();
@@ -568,7 +655,7 @@ int AgiEngine::saveGameDialog() {
int hm, vm, hp, vp;
int w;
- hm = 2;
+ hm = 1;
vm = 3;
hp = hm * CHAR_COLS;
vp = vm * CHAR_LINES;
@@ -577,7 +664,7 @@ int AgiEngine::saveGameDialog() {
sprintf(fileName, "%s", getSavegameFilename(slot));
drawWindow(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);
- printText("Select a slot in which you wish to save the game:",
+ printText("Select a slot in which you wish to\nsave the game:",
0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR);
slot = selectSlot();
@@ -602,7 +689,7 @@ int AgiEngine::saveGameDialog() {
desc = _game.strings[MAX_STRINGS];
sprintf(dstr, "Are you sure you want to save the game "
- "described as:\n\n%s\n\nin slot %d?\n\n\n", desc, slot);
+ "described as:\n\n%s\n\nin slot %d?\n\n\n", desc, slot + _firstSlot);
rc = selectionBox(dstr, buttons);
@@ -636,7 +723,7 @@ int AgiEngine::loadGameDialog() {
int hm, vm, hp, vp; /* box margins */
int w;
- hm = 2;
+ hm = 1;
vm = 3;
hp = hm * CHAR_COLS;
vp = vm * CHAR_LINES;