scummvm/engines/mortevielle/menu.cpp
2012-04-06 08:21:45 +02:00

522 lines
11 KiB
C++

/* 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 re_distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on original Mortville Manor DOS source code
* Copyright (c) 1988-1989 Lankhor
*/
#include "common/scummsys.h"
#include "common/str.h"
#include "common/textconsole.h"
#include "mortevielle/level15.h"
#include "mortevielle/menu.h"
#include "mortevielle/mortevielle.h"
#include "mortevielle/mouse.h"
#include "mortevielle/outtext.h"
#include "mortevielle/ovd1.h"
#include "mortevielle/var_mor.h"
namespace Mortevielle {
/* NIVEAU 14*/
/**
* Setup a menu's contents
*/
void Menu::menut(int no, Common::String nom) {
byte h = hi(no);
byte l = lo(no);
Common::String s = nom;
if (! tesok)
g_vm->quitGame();
while (s.size() < 20)
s += ' ';
switch (h) {
case invent:
if (l != 7) {
_inv[l] = s;
_inv[l].insertChar(' ', 0);
}
break;
case MENU_MOVE:
_dep[l] = s;
break;
case action:
_act[l] = s;
break;
case saction:
_self[l] = s;
break;
case MENU_DISCUSS:
_dis[l] = s;
break;
default:
break;
}
}
/**
* _disable a menu item
* @param no Hi byte represents menu number, lo byte reprsents item index
*/
void Menu::disableMenuItem(int no) {
byte h = hi(no);
byte l = lo(no);
switch (h) {
case invent:
if (l > 6) {
_inv[l].setChar('<', 0);
_inv[l].setChar('>', 21);
} else
_inv[l].setChar('*', 0);
break;
case MENU_MOVE:
_dep[l].setChar('*', 0);
break;
case action:
_act[l].setChar('*', 0);
break;
case saction:
_self[l].setChar('*', 0);
break;
case MENU_DISCUSS:
_dis[l].setChar('*', 0);
break;
default:
break;
}
}
/**
* Enable a menu item
* @param no Hi byte represents menu number, lo byte reprsents item index
*/
void Menu::enableMenuItem(int no) {
byte h = hi(no);
byte l = lo(no);
switch (h) {
case invent :
_inv[l].setChar(' ', 0);
_inv[l].setChar(' ', 21);
break;
case MENU_MOVE:
_dep[l].setChar(' ', 0);
break;
case action:
_act[l].setChar(' ', 0);
break;
case saction:
_self[l].setChar(' ', 0);
_self[l].setChar(' ', 0);
break;
case MENU_DISCUSS:
_dis[l].setChar(' ', 0);
break;
default:
break;
}
}
void Menu::menu_aff() {
int ind_tabl, k, col;
int pt, x, y, color, msk, num_letr;
hideMouse();
g_vm->_screenSurface.fillRect(7, Common::Rect(0, 0, 639, 10));
col = 28 * res;
if (_currGraphicalDevice == MODE_CGA)
color = 1;
else
color = 9;
num_letr = 0;
do { // One character after the other
++num_letr;
ind_tabl = 0;
y = 1;
do { // One column after the other
k = 0;
x = col;
do { // One line after the other
msk = 0x80;
for (pt = 0; pt <= 7; ++pt) {
if ((lettres[num_letr - 1][ind_tabl] & msk) != 0) {
g_vm->_screenSurface.setPixel(Common::Point(x + 1, y + 1), 0);
g_vm->_screenSurface.setPixel(Common::Point(x, y + 1), 0);
g_vm->_screenSurface.setPixel(Common::Point(x, y), color);
}
msk = (uint)msk >> 1;
++x;
}
++ind_tabl;
++k;
} while (!(k == 3));
++y;
} while (!(y == 9));
col += 48 * res;
} while (!(num_letr == 6));
showMouse();
}
/**
* Show the menu
*/
void Menu::drawMenu() {
menu_aff();
_menuActive = true;
msg4 = OPCODE_NONE;
msg3 = OPCODE_NONE;
choisi = false;
g_vm->setMouseClick(false);
test0 = false;
}
void Menu::invers(int ix) {
Common::String s;
if (msg4 == OPCODE_NONE)
return;
g_vm->_screenSurface.putxy(don[msg3][1] << 3, (lo(msg4) + 1) << 3);
switch (msg3) {
case 1:
s = _inv[lo(msg4)];
break;
case 2:
s = _dep[lo(msg4)];
break;
case 3:
s = _act[lo(msg4)];
break;
case 4:
s = _self[lo(msg4)];
break;
case 5:
s = _dis[lo(msg4)];
break;
case 6:
s = g_vm->getString(S_SAVE_LOAD + lo(msg4));
break;
case 7:
s = g_vm->getString(S_SAVE_LOAD + 1);
s += ' ';
s += (char)(48 + lo(msg4));
break;
case 8:
if (lo(msg4) == 1) {
s = g_vm->getString(S_RESTART);
} else {
s = g_vm->getString(S_SAVE_LOAD + 2);
s += ' ';
s += (char)(47 + lo(msg4));
}
break;
default:
break;
}
if ((s[0] != '*') && (s[0] != '<'))
g_vm->_screenSurface.writeg(s, ix);
else
msg4 = OPCODE_NONE;
}
void Menu::util(int x, int y) {
int ymx = (don[msg3][4] << 3) + 16;
int dxcar = don[msg3][3];
int xmn = (don[msg3][1] << 2) * res;
int ix;
if (res == 1)
ix = 5;
else
ix = 3;
int xmx = dxcar * ix * res + xmn + 2;
if ((x > xmn) && (x < xmx) && (y < ymx) && (y > 15)) {
ix = (((uint)y >> 3) - 1) + (msg3 << 8);
if (ix != msg4) {
invers(1);
msg4 = ix;
invers(0);
}
} else if (msg4 != OPCODE_NONE) {
invers(1);
msg4 = OPCODE_NONE;
}
}
/**
* Draw a menu
*/
void Menu::menuDown(int ii) {
int cx, xcc;
int xco, nb_lig;
/* debug('menuDown'); */
// Make a copy of the current screen surface for later restore
g_vm->_backgroundSurface.copyFrom(g_vm->_screenSurface);
// Draw the menu
xco = don[ii][1];
nb_lig = don[ii][4];
hideMouse();
sauvecr(10, (don[ii][2] + 1) << 1);
xco = xco << 3;
if (res == 1)
cx = 10;
else
cx = 6;
xcc = xco + (don[ii][3] * cx) + 6;
g_vm->_screenSurface.fillRect(15, Common::Rect(xco, 12, xcc, 10 + (don[ii][2] << 1)));
g_vm->_screenSurface.fillRect(0, Common::Rect(xcc, 12, xcc + 4, 10 + (don[ii][2] << 1)));
g_vm->_screenSurface.fillRect(0, Common::Rect(xco, 8 + (don[ii][2] << 1), xcc + 4, 12 + (don[ii][2] << 1)));
g_vm->_screenSurface.putxy(xco, 16);
cx = 0;
do {
++cx;
switch (ii) {
case 1:
if (_inv[cx][0] != '*')
g_vm->_screenSurface.writeg(_inv[cx], 4);
break;
case 2:
if (_dep[cx][0] != '*')
g_vm->_screenSurface.writeg(_dep[cx], 4);
break;
case 3:
if (_act[cx][0] != '*')
g_vm->_screenSurface.writeg(_act[cx], 4);
break;
case 4:
if (_self[cx][0] != '*')
g_vm->_screenSurface.writeg(_self[cx], 4);
break;
case 5:
if (_dis[cx][0] != '*')
g_vm->_screenSurface.writeg(_dis[cx], 4);
break;
case 6:
g_vm->_screenSurface.writeg(g_vm->getString(S_SAVE_LOAD + cx), 4);
break;
case 7: {
Common::String s = g_vm->getString(S_SAVE_LOAD + 1);
s += ' ';
s += (char)(48 + cx);
g_vm->_screenSurface.writeg(s, 4);
}
break;
case 8:
if (cx == 1)
g_vm->_screenSurface.writeg(g_vm->getString(S_RESTART), 4);
else {
Common::String s = g_vm->getString(S_SAVE_LOAD + 2);
s += ' ';
s += (char)(47 + cx);
g_vm->_screenSurface.writeg(s, 4);
}
break;
default:
break;
}
g_vm->_screenSurface.putxy(xco, g_vm->_screenSurface._textPos.y + 8);
} while (!(cx == nb_lig));
test0 = true;
showMouse();
}
/**
* Menu is being removed, so restore the previous background area.
*/
void Menu::menuUp(int xx) {
/* debug('menuUp'); */
if (test0) {
charecr(10, (don[xx][2] + 1) << 1);
/* Restore the background area */
assert(g_vm->_screenSurface.pitch == g_vm->_backgroundSurface.pitch);
// Get a pointer to the source and destination of the area to restore
const byte *pSrc = (const byte *)g_vm->_backgroundSurface.getBasePtr(0, 10);
Graphics::Surface destArea = g_vm->_screenSurface.lockArea(Common::Rect(0, 10, SCREEN_WIDTH, SCREEN_HEIGHT));
byte *pDest = (byte *)destArea.getBasePtr(0, 0);
// Copy the data
Common::copy(pSrc, pSrc + (400 - 10) * SCREEN_WIDTH, pDest);
test0 = false;
}
}
/**
* Erase the menu
*/
void Menu::eraseMenu() {
/* debug('eraseMenu'); */
_menuActive = false;
g_vm->setMouseClick(false);
menuUp(msg3);
}
/**
* Handle updates to the menu
*/
void Menu::mdn() {
//int x, y, c, a, ix;
int x, y, ix;
bool tes;
/* debug('mdn'); */
if (!_menuActive)
return;
x = x_s;
y = y_s;
if (!g_vm->getMouseClick()) {
if ((x == xprec) && (y == yprec))
return;
else {
xprec = x;
yprec = y;
}
tes = (y < 11)
&& ((x >= (28 * res) && x <= (28 * res + 24))
|| (x >= (76 * res) && x <= (76 * res + 24))
|| ((x > 124 * res) && (x < 124 * res + 24))
|| ((x > 172 * res) && (x < 172 * res + 24))
|| ((x > 220 * res) && (x < 220 * res + 24))
|| ((x > 268 * res) && (x < 268 * res + 24)));
if (tes) {
if (x < 76 * res)
ix = invent;
else if (x < 124 * res)
ix = MENU_MOVE;
else if (x < 172 * res)
ix = action;
else if (x < 220 * res)
ix = saction;
else if (x < 268 * res)
ix = MENU_DISCUSS;
else
ix = fichier;
if ((ix != msg3) || (! test0))
if (!((ix == fichier) && ((msg3 == sauve) || (msg3 == charge)))) {
menuUp(msg3);
menuDown(ix);
msg3 = ix;
msg4 = OPCODE_NONE;
}
} else { // Not in the MenuTitle line
if ((y > 11) && (test0))
util(x, y);
}
} else { // There was a click
if ((msg3 == fichier) && (msg4 != OPCODE_NONE)) {
// Another menu to be _displayed
g_vm->setMouseClick(false);
menuUp(msg3);
if (lo(msg4) == 1)
msg3 = 7;
else
msg3 = 8;
menuDown(msg3);
g_vm->setMouseClick(false);
} else {
// A menu was clicked on
choisi = (test0) && (msg4 != OPCODE_NONE);
menuUp(msg3);
msg[4] = msg4;
msg[3] = msg3;
msg3 = OPCODE_NONE;
msg4 = OPCODE_NONE;
g_vm->setMouseClick(false);
}
}
}
void Menu::initMenu() {
int i, tai;
char st[1410];
Common::File f;
if (!f.open("menufr.mor"))
error("Missing file - menufr.mor");
f.read(lettres, 7 * 24);
f.close();
// Ask to swap floppy
dem2();
for (i = 1; i <= 8; ++i)
_inv[i] = "* ";
_inv[7] = "< -*-*-*-*-*-*-*-*-*- ";
for (i = 1; i <= 7; ++i)
_dep[i] = "* ";
i = 1;
do {
deline(i + c_action, st, tai);
_act[i] = delig;
while (_act[i].size() < 10)
_act[i] += ' ';
if (i < 9) {
if (i < 6) {
deline(i + c_saction, st, tai);
_self[i] = delig;
while (_self[i].size() < 10)
_self[i] += ' ';
}
deline(i + c_dis, st, tai);
_dis[i] = delig + ' ';
}
++i;
} while (!(i == 22));
for (i = 1; i <= 8; ++i) {
_disc[i] = 0x500 + i;
if (i < 8)
_depl[i] = 0x200 + i;
_invt[i] = 0x100 + i;
if (i > 6)
g_vm->_menu.disableMenuItem(_invt[i]);
}
msg3 = OPCODE_NONE;
msg4 = OPCODE_NONE;
msg[3] = OPCODE_NONE;
msg[4] = OPCODE_NONE;
g_vm->setMouseClick(false);
}
} // End of namespace Mortevielle