scummvm/engines/cge/cge_main.cpp

1876 lines
40 KiB
C++
Raw Normal View History

/* 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 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 Soltys source code
* Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon
*/
#include "common/scummsys.h"
#include "cge/general.h"
#include "cge/sound.h"
#include "cge/startup.h"
#include "cge/config.h"
#include "cge/vga13h.h"
#include "cge/snail.h"
#include "cge/text.h"
#include "cge/game.h"
#include "cge/events.h"
#include "cge/cfile.h"
#include "cge/vol.h"
#include "cge/talk.h"
#include "cge/vmenu.h"
#include "cge/gettext.h"
#include "cge/mixer.h"
#include "cge/cge_main.h"
#include "cge/cge.h"
#include "common/str.h"
2011-06-10 20:57:09 +00:00
namespace CGE {
#define STACK_SIZ (K(2))
2011-07-02 16:20:41 +00:00
#define SVGCHKSUM (1956 + _now + _oldLev + _game + _music + _demoText)
#define SVG0NAME ("{{INIT}}" SVG_EXT)
#define SVG0FILE INI_FILE
2011-07-03 04:55:49 +00:00
uint16 _stklen = (STACK_SIZ * 2);
2011-06-20 21:40:22 +00:00
VGA *Vga;
Heart *_heart;
2011-06-20 21:40:22 +00:00
WALK *Hero;
SYSTEM *Sys;
Sprite *_pocLight;
EventManager *_eventManager;
Keyboard *_keyboard;
MOUSE *_mouse;
Sprite *_pocket[POCKET_NX];
Sprite *_sprite;
Sprite *_miniCave;
Sprite *_shadow;
Sprite *_horzLine;
2011-07-03 09:28:22 +00:00
InfoLine *_infoLine;
Sprite *_cavLight;
2011-07-03 09:28:22 +00:00
InfoLine *_debugLine;
BMP_PTR MB[2];
BMP_PTR HL[2];
BMP_PTR MC[3];
BMP_PTR PR[2];
BMP_PTR SP[3];
BMP_PTR LI[5];
2011-06-19 22:55:47 +00:00
2011-07-02 16:20:41 +00:00
Snail *_snail;
Snail *_snail_;
// 0.75 - 17II95 - full sound support
// 0.76 - 18II95 - small MiniEMS in DEMO,
// unhide CavLight in SNLEVEL
// keyclick suppress in startup
// keyclick on key service in: SYSTEM, GET_TEXT
// 1.01 - 17VII95 - default savegame with sound ON
// coditionals EVA for 2-month evaluation version
2011-07-03 09:28:22 +00:00
static char _usrFnam[15] = "\0ɱ%^<5E><>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>";
2011-07-02 16:20:41 +00:00
static int _oldLev = 0;
static int _demoText = DEMO_TEXT;
//--------------------------------------------------------------------------
2011-07-03 09:28:22 +00:00
bool _jbw = false;
//-------------------------------------------------------------------------
2011-07-03 09:28:22 +00:00
int _pocPtr = 0;
2011-07-03 09:28:22 +00:00
static EMS *_mini = _miniEmm.alloc((uint16)MINI_EMM_SIZE);
static BMP_PTR *_miniShpList = NULL;
static BMP_PTR _miniShp[] = { NULL, NULL };
static bool _finis = false;
static int _startup = 1;
int _offUseCount;
uint16 *_intStackPtr = false;
2011-07-02 16:20:41 +00:00
Hxy _heroXY[CAVE_MAX] = {{0, 0}};
Bar _barriers[1 + CAVE_MAX] = { { 0xFF, 0xFF } };
2011-07-02 16:20:41 +00:00
extern int findPocket(Sprite *);
extern Dac _stdPal[58];
2011-07-02 16:20:41 +00:00
void feedSnail(Sprite *spr, SNLIST snq); // defined in SNAIL
uint8 Cluster::_map[MAP_ZCNT][MAP_XCNT];
2011-07-03 09:28:22 +00:00
uint8 &Cluster::cell() {
2011-07-01 06:37:40 +00:00
return _map[_b][_a];
}
2011-07-01 06:37:40 +00:00
bool Cluster::Protected(void) {
2011-06-13 09:57:24 +00:00
/*
2011-07-02 16:20:41 +00:00
if (A == Barriers[Now]._vert || B == Barriers[Now]._horz)
2011-06-13 09:57:24 +00:00
return true;
2011-06-13 09:57:24 +00:00
_DX = (MAP_ZCNT << 8) + MAP_XCNT;
_BX = (uint16) this;
2011-06-13 09:57:24 +00:00
asm mov ax,1
asm mov cl,[bx].(COUPLE)A
asm mov ch,[bx].(COUPLE)B
asm test cx,0x8080 // (A < 0) || (B < 0)
asm jnz xit
2011-06-13 09:57:24 +00:00
asm cmp cl,dl
asm jge xit
asm cmp ch,dh
asm jge xit
2011-06-13 09:57:24 +00:00
// if (A < 0 || A >= MAP_XCNT || B < 0 || B >= MAP_ZCNT) return true;
2011-06-13 09:57:24 +00:00
asm mov al,dl
asm mul ch
asm xor ch,ch
asm add ax,cx
asm mov bx,ax
_BX += (uint16) Map;
//asm add bx,offset CLUSTER::Map
asm mov al,[bx]
asm and ax,0xFF
asm jz xit
asm mov ax,1
2011-06-13 09:57:24 +00:00
// return Map[B][A] != 0;
2011-06-13 09:57:24 +00:00
xit: return _AX;
*/
2011-06-13 09:57:24 +00:00
warning("STUB: CLUSTER::Protected()");
return true;
}
2011-07-01 06:37:40 +00:00
Cluster XZ(int x, int y) {
2011-06-13 09:57:24 +00:00
if (y < MAP_TOP)
y = MAP_TOP;
2011-06-13 09:57:24 +00:00
if (y > MAP_TOP + MAP_HIG - MAP_ZGRID)
y = MAP_TOP + MAP_HIG - MAP_ZGRID;
2011-07-01 06:37:40 +00:00
return Cluster(x / MAP_XGRID, (y - MAP_TOP) / MAP_ZGRID);
}
2011-07-01 06:37:40 +00:00
Cluster XZ(Couple xy) {
2011-06-13 09:57:24 +00:00
signed char x, y;
2011-07-01 06:37:40 +00:00
xy.split(x, y);
2011-06-13 09:57:24 +00:00
return XZ(x, y);
}
2011-07-02 16:20:41 +00:00
int _pocref[POCKET_NX];
uint8 _volume[2];
struct SavTab {
2011-06-13 09:57:24 +00:00
void *Ptr;
int Len;
uint8 Flg;
};
SavTab _savTab[] = {
2011-07-02 16:20:41 +00:00
{ &_now, sizeof(_now), 1 },
{ &_oldLev, sizeof(_oldLev), 1 },
{ &_demoText, sizeof(_demoText), 1 },
{ &_game, sizeof(_game), 1 },
{ &_game, sizeof(_game), 1 }, // spare 1
{ &_game, sizeof(_game), 1 }, // spare 2
{ &_game, sizeof(_game), 1 }, // spare 3
{ &_game, sizeof(_game), 1 }, // spare 4
// { &VGA::Mono, sizeof(VGA::Mono), 0 },
2011-07-02 16:20:41 +00:00
{ &_music, sizeof(_music), 1 },
{ _volume, sizeof(_volume), 1 },
{ _flag, sizeof(_flag), 1 },
{ _heroXY, sizeof(_heroXY), 1 },
{ _barriers, sizeof(_barriers), 1 },
{ _pocref, sizeof(_pocref), 1 },
2011-06-13 09:57:24 +00:00
{ NULL, 0, 0 }
};
2011-07-01 06:37:40 +00:00
void CGEEngine::loadGame(XFile &file, bool tiny = false) {
SavTab *st;
Sprite *spr;
2011-06-13 09:57:24 +00:00
int i;
for (st = _savTab; st->Ptr; st++) {
2011-07-01 06:37:40 +00:00
if (file._error)
2011-06-13 09:57:24 +00:00
error("Bad SVG");
2011-06-30 06:30:23 +00:00
file.read((uint8 *)((tiny || st->Flg) ? st->Ptr : &i), st->Len);
2011-06-13 09:57:24 +00:00
}
2011-06-30 06:30:23 +00:00
file.read((uint8 *) &i, sizeof(i));
2011-06-13 09:57:24 +00:00
if (i != SVGCHKSUM)
2011-07-03 09:28:22 +00:00
error("%s", _text->getText(BADSVG_TEXT));
2011-07-03 09:28:22 +00:00
if (Startup::_core < CORE_HIG)
2011-07-02 16:20:41 +00:00
_music = false;
2011-07-03 09:28:22 +00:00
if (Startup::_soundOk == 1 && Startup::_mode == 0) {
_sndDrvInfo.Vol2._d = _volume[0];
_sndDrvInfo.Vol2._m = _volume[1];
sndSetVolume();
}
2011-06-13 09:57:24 +00:00
if (! tiny) { // load sprites & pocket
2011-07-01 06:37:40 +00:00
while (!file._error) {
Sprite S(this, NULL);
2011-06-30 06:30:23 +00:00
uint16 n = file.read((uint8 *) &S, sizeof(S));
2011-06-13 09:57:24 +00:00
if (n != sizeof(S))
break;
2011-06-29 14:13:17 +00:00
S._prev = S._next = NULL;
2011-07-01 23:02:14 +00:00
spr = (scumm_stricmp(S._file + 2, "MUCHA") == 0) ? new Fly(this, NULL)
: new Sprite(this, NULL);
2011-06-13 09:57:24 +00:00
if (spr == NULL)
error("No core");
*spr = S;
2011-07-03 09:28:22 +00:00
Vga->_spareQ->append(spr);
2011-06-13 09:57:24 +00:00
}
for (i = 0; i < POCKET_NX; i++) {
2011-07-02 16:20:41 +00:00
register int r = _pocref[i];
2011-07-03 09:28:22 +00:00
_pocket[i] = (r < 0) ? NULL : Vga->_spareQ->locate(r);
2011-06-13 09:57:24 +00:00
}
}
}
2011-06-13 09:57:24 +00:00
static void SaveSound(void) {
2011-07-03 09:28:22 +00:00
CFile cfg(usrPath(progName(CFG_EXT)), WRI);
2011-07-01 06:37:40 +00:00
if (!cfg._error)
2011-07-03 09:28:22 +00:00
cfg.write(&_sndDrvInfo, sizeof(_sndDrvInfo) - sizeof(_sndDrvInfo.Vol2));
}
2011-07-01 06:37:40 +00:00
static void SaveGame(XFile &file) {
SavTab *st;
Sprite *spr;
2011-06-13 09:57:24 +00:00
int i;
for (i = 0; i < POCKET_NX; i++) {
register Sprite *s = _pocket[i];
2011-07-02 16:20:41 +00:00
_pocref[i] = (s) ? s->_ref : -1;
2011-06-13 09:57:24 +00:00
}
2011-07-03 09:28:22 +00:00
_volume[0] = _sndDrvInfo.Vol2._d;
_volume[1] = _sndDrvInfo.Vol2._m;
for (st = _savTab; st->Ptr; st++) {
2011-07-01 06:37:40 +00:00
if (file._error)
2011-06-13 09:57:24 +00:00
error("Bad SVG");
2011-06-30 06:30:23 +00:00
file.write((uint8 *) st->Ptr, st->Len);
2011-06-13 09:57:24 +00:00
}
2011-06-30 06:30:23 +00:00
file.write((uint8 *) & (i = SVGCHKSUM), sizeof(i));
2011-07-03 09:28:22 +00:00
for (spr = Vga->_spareQ->first(); spr; spr = spr->_next)
if (spr->_ref >= 1000)
2011-07-01 06:37:40 +00:00
if (!file._error)
2011-06-30 06:30:23 +00:00
file.write((uint8 *)spr, sizeof(*spr));
}
2011-06-13 09:57:24 +00:00
static void HeroCover(int cvr) {
SNPOST(SNCOVER, 1, cvr, NULL);
}
2011-07-03 09:28:22 +00:00
static void trouble(int seq, int txt) {
2011-07-01 06:37:40 +00:00
Hero->park();
2011-06-13 09:57:24 +00:00
SNPOST(SNWAIT, -1, -1, Hero);
SNPOST(SNSEQ, -1, seq, Hero);
SNPOST(SNSOUND, -1, 2, Hero);
SNPOST(SNWAIT, -1, -1, Hero);
SNPOST(SNSAY, 1, txt, Hero);
}
2011-07-03 09:28:22 +00:00
static void offUse() {
trouble(OFF_USE, OFF_USE_TEXT + new_random(_offUseCount));
}
2011-07-03 09:28:22 +00:00
static void tooFar() {
trouble(TOO_FAR, TOO_FAR_TEXT);
2011-06-13 09:57:24 +00:00
}
// Used in stubbed function, do not remove!
2011-07-01 06:37:40 +00:00
static void noWay() {
2011-07-03 09:28:22 +00:00
trouble(NO_WAY, NO_WAY_TEXT);
}
2011-07-03 09:28:22 +00:00
static void loadHeroXY() {
2011-07-01 23:02:14 +00:00
INI_FILE cf(progName(".HXY"));
2011-07-02 16:20:41 +00:00
memset(_heroXY, 0, sizeof(_heroXY));
2011-07-01 06:37:40 +00:00
if (!cf._error)
2011-07-02 16:20:41 +00:00
cf.CFREAD(&_heroXY);
2011-06-13 09:57:24 +00:00
}
2011-07-03 09:28:22 +00:00
static void loadMapping() {
2011-07-02 16:20:41 +00:00
if (_now <= CAVE_MAX) {
2011-07-01 23:02:14 +00:00
INI_FILE cf(progName(".TAB"));
2011-07-01 06:37:40 +00:00
if (!cf._error) {
memset(Cluster::_map, 0, sizeof(Cluster::_map));
2011-07-02 16:20:41 +00:00
cf.seek((_now - 1) * sizeof(Cluster::_map));
2011-07-01 06:37:40 +00:00
cf.read((uint8 *) Cluster::_map, sizeof(Cluster::_map));
2011-06-13 09:57:24 +00:00
}
}
}
2011-07-01 06:37:40 +00:00
Cluster Trace[MAX_FIND_LEVEL];
2011-06-13 09:57:24 +00:00
int FindLevel;
WALK::WALK(CGEEngine *vm, BMP_PTR *shpl)
2011-07-01 06:37:40 +00:00
: Sprite(vm, shpl), Dir(NO_DIR), _tracePtr(-1), _vm(vm) {
}
2011-07-01 06:37:40 +00:00
void WALK::tick() {
2011-06-29 14:13:17 +00:00
if (_flags._hide)
2011-06-13 09:57:24 +00:00
return;
2011-07-01 06:37:40 +00:00
_here = XZ(_x + _w / 2, _y + _h);
2011-06-13 09:57:24 +00:00
if (Dir != NO_DIR) {
Sprite *spr;
2011-06-20 21:40:22 +00:00
Sys->FunTouch();
2011-07-03 09:28:22 +00:00
for (spr = Vga->_showQ->first(); spr; spr = spr->_next) {
2011-07-01 06:37:40 +00:00
if (distance(spr) < 2) {
2011-06-29 14:13:17 +00:00
if (!spr->_flags._near) {
2011-07-02 16:20:41 +00:00
feedSnail(spr, NEAR);
2011-06-29 14:13:17 +00:00
spr->_flags._near = true;
2011-06-13 09:57:24 +00:00
}
2011-06-29 14:13:17 +00:00
} else {
spr->_flags._near = false;
}
2011-06-13 09:57:24 +00:00
}
}
2011-07-01 06:37:40 +00:00
if (_flags._hold || _tracePtr < 0)
park();
2011-06-13 09:57:24 +00:00
else {
2011-07-01 06:37:40 +00:00
if (_here == Trace[_tracePtr]) {
if (--_tracePtr < 0)
park();
2011-06-13 09:57:24 +00:00
} else {
signed char dx, dz;
2011-07-01 06:37:40 +00:00
(Trace[_tracePtr] - _here).split(dx, dz);
2011-06-13 09:57:24 +00:00
DIR d = (dx) ? ((dx > 0) ? EE : WW) : ((dz > 0) ? SS : NN);
2011-07-01 06:37:40 +00:00
turn(d);
2011-06-13 09:57:24 +00:00
}
}
2011-07-01 23:02:14 +00:00
step();
2011-06-29 14:13:17 +00:00
if ((Dir == WW && _x <= 0) ||
(Dir == EE && _x + _w >= SCR_WID) ||
(Dir == SS && _y + _w >= WORLD_HIG - 2))
2011-07-01 06:37:40 +00:00
park();
2011-06-13 09:57:24 +00:00
else {
signed char x; // dummy var
2011-07-01 06:37:40 +00:00
_here.split(x, _z); // take current Z position
2011-06-13 09:57:24 +00:00
SNPOST_(SNZTRIM, -1, 0, this); // update Hero's pos in show queue
}
}
2011-07-01 06:37:40 +00:00
int WALK::distance(Sprite *spr) {
2011-06-13 09:57:24 +00:00
int dx, dz;
2011-06-29 14:13:17 +00:00
dx = spr->_x - (_x + _w - WALKSIDE);
2011-06-13 09:57:24 +00:00
if (dx < 0)
2011-06-29 14:13:17 +00:00
dx = (_x + WALKSIDE) - (spr->_x + spr->_w);
2011-06-13 09:57:24 +00:00
if (dx < 0)
dx = 0;
2011-06-13 09:57:24 +00:00
dx /= MAP_XGRID;
2011-06-29 14:13:17 +00:00
dz = spr->_z - _z;
2011-06-13 09:57:24 +00:00
if (dz < 0)
dz = - dz;
2011-06-13 09:57:24 +00:00
dx = dx * dx + dz * dz;
for (dz = 1; dz * dz < dx; dz++)
2011-06-13 09:57:24 +00:00
;
2011-06-13 09:57:24 +00:00
return dz - 1;
}
2011-07-01 06:37:40 +00:00
void WALK::turn(DIR d) {
2011-06-13 09:57:24 +00:00
DIR dir = (Dir == NO_DIR) ? SS : Dir;
if (d != Dir) {
2011-07-01 23:02:14 +00:00
step((d == dir) ? (1 + dir + dir) : (9 + 4 * dir + d));
2011-06-13 09:57:24 +00:00
Dir = d;
}
}
2011-07-01 06:37:40 +00:00
void WALK::park(void) {
2011-06-29 14:13:17 +00:00
if (_time == 0)
++_time;
2011-06-13 09:57:24 +00:00
if (Dir != NO_DIR) {
2011-07-01 23:02:14 +00:00
step(9 + 4 * Dir + Dir);
2011-06-13 09:57:24 +00:00
Dir = NO_DIR;
2011-07-01 06:37:40 +00:00
_tracePtr = -1;
2011-06-13 09:57:24 +00:00
}
}
2011-07-01 06:37:40 +00:00
void WALK::findWay(Cluster c) {
warning("STUB: WALK::findWay");
2011-06-13 09:57:24 +00:00
/*
bool Find1Way(void);
extern uint16 Target;
if (c != Here) {
for (FindLevel = 1; FindLevel <= MAX_FIND_LEVEL; FindLevel++) {
2011-06-13 09:57:24 +00:00
signed char x, z;
Here.Split(x, z);
Target = (z << 8) | x;
c.Split(x, z);
_CX = (z << 8) | x;
if (Find1Way())
break;
}
TracePtr = (FindLevel > MAX_FIND_LEVEL) ? -1 : (FindLevel - 1);
if (TracePtr < 0)
NoWay();
Time = 1;
}
*/
}
2011-07-01 06:37:40 +00:00
void WALK::findWay(Sprite *spr) {
2011-06-13 09:57:24 +00:00
if (spr && spr != this) {
2011-06-29 14:13:17 +00:00
int x = spr->_x;
int z = spr->_z;
if (spr->_flags._east)
x += spr->_w + _w / 2 - WALKSIDE;
2011-06-13 09:57:24 +00:00
else
2011-06-29 14:13:17 +00:00
x -= _w / 2 - WALKSIDE;
2011-07-01 06:37:40 +00:00
findWay(Cluster((x / MAP_XGRID),
2011-06-13 09:57:24 +00:00
((z < MAP_ZCNT - MAX_DISTANCE) ? (z + 1)
: (z - 1))));
}
}
2011-07-01 06:37:40 +00:00
bool WALK::lower(Sprite *spr) {
2011-06-29 14:13:17 +00:00
return (spr->_y > _y + (_h * 3) / 5);
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void WALK::reach(Sprite *spr, int mode) {
2011-06-13 09:57:24 +00:00
if (spr) {
2011-07-01 06:37:40 +00:00
Hero->findWay(spr);
2011-06-13 09:57:24 +00:00
if (mode < 0) {
2011-06-29 14:13:17 +00:00
mode = spr->_flags._east;
2011-07-01 06:37:40 +00:00
if (lower(spr))
2011-06-13 09:57:24 +00:00
mode += 2;
}
}
2011-06-13 09:57:24 +00:00
// note: insert SNAIL commands in reverse order
SNINSERT(SNPAUSE, -1, 64, NULL);
SNINSERT(SNSEQ, -1, TSEQ + mode, this);
if (spr) {
SNINSERT(SNWAIT, -1, -1, Hero); /////--------$$$$$$$
//SNINSERT(SNWALK, -1, -1, spr);
}
2011-06-13 09:57:24 +00:00
// sequence is not finished,
// now it is just at sprite appear (disappear) point
}
class SQUARE : public Sprite {
2011-06-13 09:57:24 +00:00
public:
SQUARE(CGEEngine *vm);
virtual void touch(uint16 mask, int x, int y);
private:
CGEEngine *_vm;
2011-06-13 09:57:24 +00:00
};
SQUARE::SQUARE(CGEEngine *vm)
: Sprite(vm, MB), _vm(vm) {
2011-06-29 14:13:17 +00:00
_flags._kill = true;
_flags._bDel = false;
}
void SQUARE::touch(uint16 mask, int x, int y) {
2011-07-01 23:02:14 +00:00
Sprite::touch(mask, x, y);
2011-06-13 09:57:24 +00:00
if (mask & L_UP) {
2011-07-01 06:37:40 +00:00
XZ(_x + x, _y + y).cell() = 0;
2011-06-13 09:57:24 +00:00
SNPOST_(SNKILL, -1, 0, this);
}
}
2011-07-01 06:37:40 +00:00
void CGEEngine::setMapBrick(int x, int z) {
SQUARE *s = new SQUARE(this);
2011-06-13 09:57:24 +00:00
if (s) {
static char n[] = "00:00";
2011-07-01 23:02:14 +00:00
s->gotoxy(x * MAP_XGRID, MAP_TOP + z * MAP_ZGRID);
2011-06-13 09:57:24 +00:00
wtom(x, n + 0, 10, 2);
wtom(z, n + 3, 10, 2);
2011-07-01 06:37:40 +00:00
Cluster::_map[z][x] = 1;
2011-07-01 23:02:14 +00:00
s->setName(n);
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(s, Vga->_showQ->first());
2011-06-13 09:57:24 +00:00
}
}
2011-06-13 09:57:24 +00:00
static void SwitchColorMode(void);
static void SwitchDebug(void);
2011-06-13 09:57:24 +00:00
static void SwitchMusic(void);
static void KillSprite(void);
static void PushSprite(void);
static void PullSprite(void);
static void NextStep(void);
static void SaveMapping(void);
2011-06-13 09:57:24 +00:00
static void KeyClick(void) {
SNPOST_(SNSOUND, -1, 5, NULL);
}
2011-07-01 06:37:40 +00:00
void CGEEngine::resetQSwitch() {
2011-06-13 09:57:24 +00:00
SNPOST_(SNSEQ, 123, 0, NULL);
KeyClick();
}
2011-07-01 06:37:40 +00:00
void CGEEngine::quit() {
static CHOICE QuitMenu[] = {
2011-07-01 06:37:40 +00:00
{ NULL, &CGEEngine::startCountDown },
{ NULL, &CGEEngine::resetQSwitch },
{ NULL, &CGEEngine::dummy }
2011-06-13 09:57:24 +00:00
};
2011-07-02 16:20:41 +00:00
if (_snail->idle() && ! Hero->_flags._hide) {
2011-06-13 09:57:24 +00:00
if (VMENU::Addr) {
SNPOST_(SNKILL, -1, 0, VMENU::Addr);
2011-07-01 06:37:40 +00:00
resetQSwitch();
2011-06-13 09:57:24 +00:00
} else {
2011-07-03 09:28:22 +00:00
QuitMenu[0].Text = _text->getText(QUIT_TEXT);
QuitMenu[1].Text = _text->getText(NOQUIT_TEXT);
(new VMENU(this, QuitMenu, -1, -1))->setName(_text->getText(QUIT_TITLE));
2011-06-13 09:57:24 +00:00
SNPOST_(SNSEQ, 123, 1, NULL);
KeyClick();
}
}
}
2011-07-03 09:28:22 +00:00
static void AltCtrlDel() {
2011-06-13 09:57:24 +00:00
SNPOST_(SNSAY, -1, A_C_D_TEXT, Hero);
}
// Used in stubbed function, do not remove!
2011-07-01 06:37:40 +00:00
static void miniStep(int stp) {
2011-06-13 09:57:24 +00:00
if (stp < 0)
2011-06-29 14:13:17 +00:00
_miniCave->_flags._hide = true;
2011-06-13 09:57:24 +00:00
else {
2011-07-03 09:28:22 +00:00
&*_mini;
*_miniShp[0] = *_miniShpList[stp];
2011-07-02 16:20:41 +00:00
if (_fx.Current)
&*(_fx.Current->EAddr());
2011-06-29 14:13:17 +00:00
_miniCave->_flags._hide = false;
2011-06-13 09:57:24 +00:00
}
}
2011-06-13 09:57:24 +00:00
static void PostMiniStep(int stp) {
//static int recent = -2;
2011-06-13 09:57:24 +00:00
//TODO Change the SNPOST message send to a special way to send function pointer
//if (MiniCave && stp != recent) SNPOST_(SNEXEC, -1, recent = stp, (void *)&MiniStep);
warning("STUB: PostMiniStep()");
}
2011-06-13 09:57:24 +00:00
void SYSTEM::SetPal(void) {
uint i;
2011-07-01 06:37:40 +00:00
Dac *p = VGA::SysPal + 256 - ArrayCount(_stdPal);
for (i = 0; i < ArrayCount(_stdPal); i++) {
p[i]._r = _stdPal[i]._r >> 2;
p[i]._g = _stdPal[i]._g >> 2;
p[i]._b = _stdPal[i]._b >> 2;
2011-06-13 09:57:24 +00:00
}
}
2011-06-13 09:57:24 +00:00
void SYSTEM::FunTouch(void) {
uint16 n = (PAIN) ? HEROFUN1 : HEROFUN0;
2011-07-03 09:28:22 +00:00
if (_talk == NULL || n > FunDel)
2011-06-13 09:57:24 +00:00
FunDel = n;
}
2011-06-13 09:57:24 +00:00
static void ShowBak(int ref) {
2011-07-03 09:28:22 +00:00
Sprite *spr = Vga->_spareQ->locate(ref);
2011-06-13 09:57:24 +00:00
if (spr) {
2011-06-30 06:30:23 +00:00
Bitmap::_pal = VGA::SysPal;
2011-07-01 23:02:14 +00:00
spr->expand();
2011-06-30 06:30:23 +00:00
Bitmap::_pal = NULL;
2011-07-01 23:02:14 +00:00
spr->show(2);
Vga->CopyPage(1, 2);
2011-06-20 21:40:22 +00:00
Sys->SetPal();
2011-07-01 23:02:14 +00:00
spr->contract();
}
}
2011-07-01 06:37:40 +00:00
static void caveUp() {
2011-07-02 16:20:41 +00:00
int BakRef = 1000 * _now;
if (_music)
LoadMIDI(_now);
2011-06-13 09:57:24 +00:00
ShowBak(BakRef);
2011-07-03 09:28:22 +00:00
loadMapping();
_text->preload(BakRef, BakRef + 1000);
Sprite *spr = Vga->_spareQ->first();
2011-06-13 09:57:24 +00:00
while (spr) {
2011-06-29 14:13:17 +00:00
Sprite *n = spr->_next;
2011-07-02 16:20:41 +00:00
if (spr->_cave == _now || spr->_cave == 0)
if (spr->_ref != BakRef) {
2011-06-29 14:13:17 +00:00
if (spr->_flags._back)
2011-07-01 23:02:14 +00:00
spr->backShow();
2011-06-13 09:57:24 +00:00
else
ExpandSprite(spr);
}
spr = n;
}
2011-07-03 09:28:22 +00:00
if (_sndDrvInfo._dDev) {
2011-07-02 16:20:41 +00:00
_sound.Stop();
_fx.Clear();
_fx.Preload(0);
_fx.Preload(BakRef);
2011-06-13 09:57:24 +00:00
}
2011-06-13 09:57:24 +00:00
if (Hero) {
2011-07-02 16:20:41 +00:00
Hero->gotoxy(_heroXY[_now - 1]._x, _heroXY[_now - 1]._y);
2011-06-13 09:57:24 +00:00
// following 2 lines trims Hero's Z position!
2011-07-01 23:02:14 +00:00
Hero->tick();
2011-06-29 14:13:17 +00:00
Hero->_time = 1;
Hero->_flags._hide = false;
2011-06-13 09:57:24 +00:00
}
2011-07-02 16:20:41 +00:00
if (!_dark)
Vga->Sunset();
Vga->CopyPage(0, 1);
2011-07-02 16:20:41 +00:00
selectPocket(-1);
2011-06-13 09:57:24 +00:00
if (Hero)
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(Vga->_showQ->remove(Hero));
if (_shadow) {
2011-07-03 09:28:22 +00:00
Vga->_showQ->remove(_shadow);
2011-07-01 23:02:14 +00:00
_shadow->makeXlat(glass(VGA::SysPal, 204, 204, 204));
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(_shadow, Hero);
2011-06-29 14:13:17 +00:00
_shadow->_z = Hero->_z;
2011-06-13 09:57:24 +00:00
}
2011-07-03 09:28:22 +00:00
feedSnail(Vga->_showQ->locate(BakRef + 999), TAKE);
Vga->Show();
Vga->CopyPage(1, 0);
Vga->Show();
Vga->Sunrise(VGA::SysPal);
2011-07-02 16:20:41 +00:00
_dark = false;
2011-07-03 09:28:22 +00:00
if (!_startup)
_mouse->On();
_heart->_enable = true;
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::caveDown() {
Sprite *spr;
2011-06-29 14:13:17 +00:00
if (!_horzLine->_flags._hide)
2011-07-01 06:37:40 +00:00
switchMapping();
2011-07-03 09:28:22 +00:00
for (spr = Vga->_showQ->first(); spr;) {
2011-06-29 14:13:17 +00:00
Sprite *n = spr->_next;
if (spr->_ref >= 1000 /*&& spr->_cave*/) {
if (spr->_ref % 1000 == 999)
2011-07-02 16:20:41 +00:00
feedSnail(spr, TAKE);
2011-07-03 09:28:22 +00:00
Vga->_spareQ->append(Vga->_showQ->remove(spr));
2011-06-13 09:57:24 +00:00
}
spr = n;
}
2011-07-03 09:28:22 +00:00
_text->clear(1000);
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::xCave() {
caveDown();
caveUp();
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::qGame() {
caveDown();
2011-07-02 16:20:41 +00:00
_oldLev = _lev;
2011-06-13 09:57:24 +00:00
SaveSound();
2011-07-03 09:28:22 +00:00
CFile file = CFile(usrPath(_usrFnam), WRI, RCrypt);
2011-06-13 09:57:24 +00:00
SaveGame(file);
Vga->Sunset();
2011-07-03 09:28:22 +00:00
_finis = true;
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::switchCave(int cav) {
2011-07-02 16:20:41 +00:00
if (cav != _now) {
_heart->_enable = false;
2011-06-13 09:57:24 +00:00
if (cav < 0) {
SNPOST(SNLABEL, -1, 0, NULL); // wait for repaint
//TODO Change the SNPOST message send to a special way to send function pointer
//SNPOST(SNEXEC, -1, 0, (void *)&QGame); // switch cave
warning("SwitchCave() - SNPOST");
} else {
2011-07-02 16:20:41 +00:00
_now = cav;
_mouse->Off();
2011-06-13 09:57:24 +00:00
if (Hero) {
2011-07-01 06:37:40 +00:00
Hero->park();
2011-07-01 23:02:14 +00:00
Hero->step(0);
if (!_isDemo)
2011-06-13 09:57:24 +00:00
///// protection: auto-destruction on! ----------------------
2011-07-03 09:28:22 +00:00
Vga->_spareQ->_show = Startup::_summa * (cav <= CAVE_MAX);
2011-06-13 09:57:24 +00:00
/////--------------------------------------------------------
}
2011-07-02 16:20:41 +00:00
_cavLight->gotoxy(CAVE_X + ((_now - 1) % CAVE_NX) * CAVE_DX + CAVE_SX,
CAVE_Y + ((_now - 1) / CAVE_NX) * CAVE_DY + CAVE_SY);
2011-07-03 09:28:22 +00:00
killText();
if (!_startup)
KeyClick();
2011-06-13 09:57:24 +00:00
SNPOST(SNLABEL, -1, 0, NULL); // wait for repaint
//TODO Change the SNPOST message send to a special way to send function pointer
//SNPOST(SNEXEC, 0, 0, (void *)&XCave); // switch cave
warning("SwitchCave() - SNPOST");
}
}
}
SYSTEM::SYSTEM(CGEEngine *vm) : Sprite(vm, NULL), _vm(vm) {
2011-06-20 21:40:22 +00:00
FunDel = HEROFUN0;
SetPal();
Tick();
}
void SYSTEM::touch(uint16 mask, int x, int y) {
2011-06-13 09:57:24 +00:00
static int pp = 0;
2011-06-13 09:57:24 +00:00
FunTouch();
if (mask & KEYB) {
int pp0;
KeyClick();
2011-07-03 09:28:22 +00:00
killText();
if (_startup == 1) {
2011-06-13 09:57:24 +00:00
SNPOST(SNCLEAR, -1, 0, NULL);
return;
}
pp0 = pp;
switch (x) {
case Del:
if (_keyboard->_key[ALT] && _keyboard->_key[CTRL])
AltCtrlDel();
else
KillSprite();
break;
2011-06-13 09:57:24 +00:00
case 'F':
if (_keyboard->_key[ALT]) {
2011-07-03 09:28:22 +00:00
Sprite *m = Vga->_showQ->locate(17001);
2011-06-13 09:57:24 +00:00
if (m) {
2011-07-01 23:02:14 +00:00
m->step(1);
2011-06-29 14:13:17 +00:00
m->_time = 216; // 3s
2011-06-13 09:57:24 +00:00
}
}
break;
case PgUp:
PushSprite();
break;
case PgDn:
PullSprite();
break;
case '+':
NextStep();
break;
case '`':
if (_keyboard->_key[ALT])
2011-06-13 09:57:24 +00:00
SaveMapping();
else
2011-07-01 06:37:40 +00:00
_vm->switchMapping();
2011-06-13 09:57:24 +00:00
break;
case F1:
SwitchDebug();
break;
case F3:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 4);
2011-06-13 09:57:24 +00:00
break;
case F4:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 5);
2011-06-13 09:57:24 +00:00
break;
case F5:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 0);
2011-06-13 09:57:24 +00:00
break;
case F6:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 1);
2011-06-13 09:57:24 +00:00
break;
case F7:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 2);
2011-06-13 09:57:24 +00:00
break;
case F8:
2011-07-01 23:02:14 +00:00
Hero->step(TSEQ + 3);
2011-06-13 09:57:24 +00:00
break;
case F9:
2011-06-20 21:40:22 +00:00
Sys->FunDel = 1;
2011-06-13 09:57:24 +00:00
break;
case 'X':
if (_keyboard->_key[ALT])
2011-07-03 09:28:22 +00:00
_finis = true;
2011-06-13 09:57:24 +00:00
break;
case '0':
case '1':
case '2':
case '3':
case '4':
if (_keyboard->_key[ALT]) {
2011-06-13 09:57:24 +00:00
SNPOST(SNLEVEL, -1, x - '0', NULL);
break;
}
case '5':
case '6':
case '7':
case '8':
case '9':
if (_sprite)
2011-07-01 23:02:14 +00:00
_sprite->step(x - '0');
2011-06-13 09:57:24 +00:00
break;
case F10 :
2011-07-02 16:20:41 +00:00
if (_snail->idle() && ! Hero->_flags._hide)
2011-07-01 06:37:40 +00:00
_vm->startCountDown();
2011-06-13 09:57:24 +00:00
break;
case 'J':
if (pp == 0)
++pp;
break;
case 'B':
if (pp == 1)
++pp;
break;
case 'W':
if (pp == 2)
2011-07-03 09:28:22 +00:00
_jbw = !_jbw;
2011-06-13 09:57:24 +00:00
break;
}
if (pp == pp0)
pp = 0;
} else {
2011-07-03 09:28:22 +00:00
if (_startup)
2011-06-13 09:57:24 +00:00
return;
int cav = 0;
2011-07-03 09:28:22 +00:00
_infoLine->update(NULL);
2011-06-13 09:57:24 +00:00
if (y >= WORLD_HIG) {
if (x < BUTTON_X) { // select cave?
if (y >= CAVE_Y && y < CAVE_Y + CAVE_NY * CAVE_DY &&
2011-07-02 16:20:41 +00:00
x >= CAVE_X && x < CAVE_X + CAVE_NX * CAVE_DX && !_game) {
2011-06-13 09:57:24 +00:00
cav = ((y - CAVE_Y) / CAVE_DY) * CAVE_NX + (x - CAVE_X) / CAVE_DX + 1;
2011-07-02 16:20:41 +00:00
if (cav > _maxCave)
2011-06-13 09:57:24 +00:00
cav = 0;
} else {
cav = 0;
}
} else if (mask & L_UP) {
if (y >= POCKET_Y && y < POCKET_Y + POCKET_NY * POCKET_DY &&
x >= POCKET_X && x < POCKET_X + POCKET_NX * POCKET_DX) {
int n = ((y - POCKET_Y) / POCKET_DY) * POCKET_NX + (x - POCKET_X) / POCKET_DX;
2011-07-02 16:20:41 +00:00
selectPocket(n);
2011-06-13 09:57:24 +00:00
}
}
}
2011-06-13 09:57:24 +00:00
PostMiniStep(cav - 1);
2011-06-13 09:57:24 +00:00
if (mask & L_UP) {
2011-07-02 16:20:41 +00:00
if (cav && _snail->idle() && Hero->_tracePtr < 0)
2011-07-01 06:37:40 +00:00
_vm->switchCave(cav);
2011-06-29 14:13:17 +00:00
if (!_horzLine->_flags._hide) {
2011-06-13 09:57:24 +00:00
if (y >= MAP_TOP && y < MAP_TOP + MAP_HIG) {
int8 x1, z1;
2011-07-01 06:37:40 +00:00
XZ(x, y).split(x1, z1);
Cluster::_map[z1][x1] = 1;
_vm->setMapBrick(x1, z1);
2011-06-13 09:57:24 +00:00
}
} else
{
2011-07-03 09:28:22 +00:00
if (!_talk && _snail->idle() && Hero
2011-07-02 16:20:41 +00:00
&& y >= MAP_TOP && y < MAP_TOP + MAP_HIG && !_game) {
2011-07-01 06:37:40 +00:00
Hero->findWay(XZ(x, y));
2011-06-13 09:57:24 +00:00
}
}
}
}
}
2011-06-13 09:57:24 +00:00
void SYSTEM::Tick(void) {
2011-07-03 09:28:22 +00:00
if (!_startup)
if (--FunDel == 0) {
killText();
2011-07-02 16:20:41 +00:00
if (_snail->idle()) {
2011-06-13 09:57:24 +00:00
if (PAIN)
HeroCover(9);
2011-07-03 09:28:22 +00:00
else if (Startup::_core >= CORE_MID) {
2011-06-13 09:57:24 +00:00
int n = new_random(100);
if (n > 96)
2011-06-29 14:13:17 +00:00
HeroCover(6 + (Hero->_x + Hero->_w / 2 < SCR_WID / 2));
2011-06-13 09:57:24 +00:00
else {
if (n > 90)
HeroCover(5);
else {
if (n > 60)
HeroCover(4);
else
HeroCover(3);
}
}
}
}
FunTouch();
}
2011-06-29 14:13:17 +00:00
_time = SYSTIMERATE;
2011-06-13 09:57:24 +00:00
}
2011-06-13 09:57:24 +00:00
/*
static void SpkOpen(void) {
asm in al,0x61
asm or al,0x03
asm out 0x61,al
asm mov al,0x90
asm out 0x43,al
}
2011-06-13 09:57:24 +00:00
static void SpkClose(void) {
asm in al,0x61
asm and al,0xFC
asm out 0x61,al
}
2011-06-13 09:57:24 +00:00
*/
2011-06-13 09:57:24 +00:00
static void SwitchColorMode(void) {
SNPOST_(SNSEQ, 121, Vga->Mono = !Vga->Mono, NULL);
2011-06-13 09:57:24 +00:00
KeyClick();
Vga->SetColors(VGA::SysPal, 64);
2011-06-13 09:57:24 +00:00
}
2011-06-13 09:57:24 +00:00
static void SwitchMusic(void) {
if (_keyboard->_key[ALT]) {
2011-06-13 09:57:24 +00:00
if (VMENU::Addr)
SNPOST_(SNKILL, -1, 0, VMENU::Addr);
else {
2011-07-02 16:20:41 +00:00
SNPOST_(SNSEQ, 122, (_music = false), NULL);
2011-06-13 09:57:24 +00:00
//TODO Change the SNPOST message send to a special way to send function pointer
2011-07-01 06:37:40 +00:00
// SNPOST(SNEXEC, -1, 0, (void *)&selectSound);
2011-06-13 09:57:24 +00:00
warning("SwitchMusic() - SNPOST");
}
} else {
2011-07-03 09:28:22 +00:00
if (Startup::_core < CORE_HIG)
2011-06-13 09:57:24 +00:00
SNPOST(SNINF, -1, NOMUSIC_TEXT, NULL);
else {
2011-07-02 16:20:41 +00:00
SNPOST_(SNSEQ, 122, (_music = !_music), NULL);
2011-06-13 09:57:24 +00:00
KeyClick();
}
}
2011-07-02 16:20:41 +00:00
if (_music)
LoadMIDI(_now);
2011-06-13 09:57:24 +00:00
else
KillMIDI();
}
2011-07-01 06:37:40 +00:00
void CGEEngine::startCountDown() {
2011-06-13 09:57:24 +00:00
//SNPOST(SNSEQ, 123, 0, NULL);
2011-07-01 06:37:40 +00:00
switchCave(-1);
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::takeName() {
2011-07-01 23:02:14 +00:00
if (GetText::_ptr)
SNPOST_(SNKILL, -1, 0, GetText::_ptr);
2011-06-13 09:57:24 +00:00
else {
2011-07-03 09:28:22 +00:00
GetText *tn = new GetText(this, _text->getText(GETNAME_PROMPT), _usrFnam, 8, KeyClick);
2011-06-13 09:57:24 +00:00
if (tn) {
2011-07-03 09:28:22 +00:00
tn->setName(_text->getText(GETNAME_TITLE));
2011-07-01 23:02:14 +00:00
tn->center();
tn->gotoxy(tn->_x, tn->_y - 10);
2011-06-29 14:13:17 +00:00
tn->_z = 126;
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(tn);
2011-06-13 09:57:24 +00:00
}
}
}
2011-07-01 06:37:40 +00:00
void CGEEngine::switchMapping() {
2011-06-29 14:13:17 +00:00
if (_horzLine->_flags._hide) {
2011-06-13 09:57:24 +00:00
int i;
for (i = 0; i < MAP_ZCNT; i++) {
2011-06-13 09:57:24 +00:00
int j;
for (j = 0; j < MAP_XCNT; j++) {
2011-07-01 06:37:40 +00:00
if (Cluster::_map[i][j])
setMapBrick(j, i);
2011-06-13 09:57:24 +00:00
}
}
} else {
Sprite *s;
2011-07-03 09:28:22 +00:00
for (s = Vga->_showQ->first(); s; s = s->_next)
2011-06-29 14:13:17 +00:00
if (s->_w == MAP_XGRID && s->_h == MAP_ZGRID)
2011-06-13 09:57:24 +00:00
SNPOST_(SNKILL, -1, 0, s);
}
2011-06-29 14:13:17 +00:00
_horzLine->_flags._hide = !_horzLine->_flags._hide;
2011-06-13 09:57:24 +00:00
}
2011-06-13 09:57:24 +00:00
static void KillSprite(void) {
2011-06-29 14:13:17 +00:00
_sprite->_flags._kill = true;
_sprite->_flags._bDel = true;
SNPOST_(SNKILL, -1, 0, _sprite);
_sprite = NULL;
}
2011-06-13 09:57:24 +00:00
static void PushSprite(void) {
2011-06-29 14:13:17 +00:00
Sprite *spr = _sprite->_prev;
2011-06-13 09:57:24 +00:00
if (spr) {
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(Vga->_showQ->remove(_sprite), spr);
2011-06-29 14:13:17 +00:00
while (_sprite->_z > _sprite->_next->_z)
_sprite->_z--;
2011-06-13 09:57:24 +00:00
} else
SNPOST_(SNSOUND, -1, 2, NULL);
}
2011-06-13 09:57:24 +00:00
static void PullSprite(void) {
bool ok = false;
2011-06-29 14:13:17 +00:00
Sprite *spr = _sprite->_next;
2011-06-13 09:57:24 +00:00
if (spr) {
2011-06-29 14:13:17 +00:00
spr = spr->_next;
2011-06-13 09:57:24 +00:00
if (spr)
2011-06-29 14:13:17 +00:00
ok = (!spr->_flags._slav);
2011-06-13 09:57:24 +00:00
}
if (ok) {
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(Vga->_showQ->remove(_sprite), spr);
2011-06-29 14:13:17 +00:00
if (_sprite->_prev)
while (_sprite->_z < _sprite->_prev->_z)
_sprite->_z++;
2011-06-13 09:57:24 +00:00
} else
SNPOST_(SNSOUND, -1, 2, NULL);
}
2011-06-13 09:57:24 +00:00
static void NextStep(void) {
SNPOST_(SNSTEP, 0, 0, _sprite);
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
static void SaveMapping() {
{
2011-07-01 23:02:14 +00:00
IoHand cf(progName(".TAB"), UPD);
2011-07-01 06:37:40 +00:00
if (!cf._error) {
2011-07-02 16:20:41 +00:00
cf.seek((_now - 1) * sizeof(Cluster::_map));
2011-07-01 06:37:40 +00:00
cf.write((uint8 *) Cluster::_map, sizeof(Cluster::_map));
2011-06-13 09:57:24 +00:00
}
}
{
2011-07-01 23:02:14 +00:00
IoHand cf(progName(".HXY"), WRI);
2011-07-01 06:37:40 +00:00
if (!cf._error) {
2011-07-02 16:20:41 +00:00
_heroXY[_now - 1]._x = Hero->_x;
_heroXY[_now - 1]._y = Hero->_y;
cf.write((uint8 *) _heroXY, sizeof(_heroXY));
2011-06-13 09:57:24 +00:00
}
}
}
2011-06-13 09:57:24 +00:00
// 1111111111222222222233333333 334444444444555555555566666666667777777777
// 01234567890123456789012345678901234567 890123456789012345678901234567890123456789
static char DebugText[] = " N=00000 F=000000 X=000 Y=000 FPS=0000\0S=00:00 000:000:000 000:000 00 ";
#define NFRE (DebugText + 3)
#define FFRE (DebugText + 11)
#define ABSX (DebugText + 20)
#define ABSY (DebugText + 26)
#define FRPS (DebugText + 34)
#define XSPR (DebugText + 38)
#define SP_N (DebugText + 41)
#define SP_S (DebugText + 44)
#define SP_X (DebugText + 47)
#define SP_Y (DebugText + 51)
#define SP_Z (DebugText + 55)
#define SP_W (DebugText + 59)
#define SP_H (DebugText + 63)
#define SP_F (DebugText + 67)
#define SP__ (DebugText + 70)
2011-07-03 09:28:22 +00:00
static void sayDebug() {
if (!_debugLine->_flags._hide) {
2011-06-13 09:57:24 +00:00
static long t = -1L;
2011-07-01 23:02:14 +00:00
long t1 = timer();
2011-06-13 09:57:24 +00:00
if (t1 - t >= 18) {
static uint32 old = 0L;
uint32 now = Vga->FrmCnt;
2011-06-13 09:57:24 +00:00
dwtom(now - old, FRPS, 10, 4);
old = now;
t = t1;
}
dwtom(_mouse->_x, ABSX, 10, 3);
dwtom(_mouse->_y, ABSY, 10, 3);
2011-06-13 09:57:24 +00:00
// dwtom(coreleft(), NFRE, 10, 5);
// dwtom(farcoreleft(), FFRE, 10, 6);
// sprite queue size
uint16 n = 0;
Sprite *spr;
2011-07-03 09:28:22 +00:00
for (spr = Vga->_showQ->first(); spr; spr = spr->_next) {
2011-06-13 09:57:24 +00:00
++ n;
if (spr == _sprite) {
2011-06-13 09:57:24 +00:00
*XSPR = ' ';
dwtom(n, SP_N, 10, 2);
2011-06-29 14:13:17 +00:00
dwtom(_sprite->_x, SP_X, 10, 3);
dwtom(_sprite->_y, SP_Y, 10, 3);
dwtom(_sprite->_z, SP_Z, 10, 3);
dwtom(_sprite->_w, SP_W, 10, 3);
dwtom(_sprite->_h, SP_H, 10, 3);
dwtom(*(uint16 *)(&_sprite->_flags), SP_F, 16, 2);
2011-06-13 09:57:24 +00:00
}
}
dwtom(n, SP_S, 10, 2);
// *SP__ = (heapcheck() < 0) ? '!' : ' ';
2011-07-03 09:28:22 +00:00
_debugLine->update(DebugText);
2011-06-13 09:57:24 +00:00
}
}
2011-06-13 09:57:24 +00:00
static void SwitchDebug(void) {
2011-07-03 09:28:22 +00:00
_debugLine->_flags._hide = !_debugLine->_flags._hide;
}
2011-07-01 06:37:40 +00:00
void CGEEngine::optionTouch(int opt, uint16 mask) {
2011-06-13 09:57:24 +00:00
switch (opt) {
case 1 :
if (mask & L_UP)
SwitchColorMode();
break;
case 2 :
if (mask & L_UP)
SwitchMusic();
else if (mask & R_UP)
2011-07-01 23:02:14 +00:00
if (!Mixer::_appear) {
Mixer::_appear = true;
new Mixer(this, BUTTON_X, BUTTON_Y);
2011-06-13 09:57:24 +00:00
}
break;
case 3 :
if (mask & L_UP)
2011-07-01 06:37:40 +00:00
quit();
2011-06-13 09:57:24 +00:00
break;
}
}
2011-06-13 09:57:24 +00:00
#pragma argsused
2011-07-01 23:02:14 +00:00
void Sprite::touch(uint16 mask, int x, int y) {
2011-06-20 21:40:22 +00:00
Sys->FunTouch();
2011-06-13 09:57:24 +00:00
if ((mask & ATTN) == 0) {
2011-07-03 09:28:22 +00:00
_infoLine->update(name());
2011-06-13 09:57:24 +00:00
if (mask & (R_DN | L_DN))
_sprite = this;
if (_ref / 10 == 12) {
2011-07-01 06:37:40 +00:00
_vm->optionTouch(_ref % 10, mask);
2011-06-13 09:57:24 +00:00
return;
}
2011-06-29 14:13:17 +00:00
if (_flags._syst)
2011-06-13 09:57:24 +00:00
return; // cannot access system sprites
2011-07-02 16:20:41 +00:00
if (_game) if (mask & L_UP) {
2011-06-13 09:57:24 +00:00
mask &= ~L_UP;
mask |= R_UP;
}
2011-07-02 16:20:41 +00:00
if ((mask & R_UP) && _snail->idle()) {
2011-07-03 09:28:22 +00:00
Sprite *ps = (_pocLight->_seqPtr) ? _pocket[_pocPtr] : NULL;
2011-06-13 09:57:24 +00:00
if (ps) {
2011-07-01 06:37:40 +00:00
if (_flags._kept || Hero->distance(this) < MAX_DISTANCE) {
2011-07-01 23:02:14 +00:00
if (works(ps)) {
2011-07-02 16:20:41 +00:00
feedSnail(ps, TAKE);
2011-06-13 11:07:45 +00:00
} else
2011-07-03 09:28:22 +00:00
offUse();
2011-07-02 16:20:41 +00:00
selectPocket(-1);
2011-06-13 11:07:45 +00:00
} else
2011-07-03 09:28:22 +00:00
tooFar();
2011-06-13 09:57:24 +00:00
} else {
2011-06-29 14:13:17 +00:00
if (_flags._kept)
2011-06-13 09:57:24 +00:00
mask |= L_UP;
else {
2011-07-01 06:37:40 +00:00
if (Hero->distance(this) < MAX_DISTANCE) {
2011-06-13 09:57:24 +00:00
///
2011-06-29 14:13:17 +00:00
if (_flags._port) {
2011-07-02 16:20:41 +00:00
if (findPocket(NULL) < 0)
pocFul();
2011-06-13 09:57:24 +00:00
else {
SNPOST(SNREACH, -1, -1, this);
SNPOST(SNKEEP, -1, -1, this);
2011-06-29 14:13:17 +00:00
_flags._port = false;
2011-06-13 09:57:24 +00:00
}
} else {
2011-07-01 23:02:14 +00:00
if (_takePtr != NO_PTR) {
2011-07-02 16:20:41 +00:00
if (snList(TAKE)[_takePtr]._com == SNNEXT)
2011-07-03 09:28:22 +00:00
offUse();
2011-06-13 11:07:45 +00:00
else
2011-07-02 16:20:41 +00:00
feedSnail(this, TAKE);
2011-06-13 11:07:45 +00:00
} else
2011-07-03 09:28:22 +00:00
offUse();
2011-06-13 09:57:24 +00:00
}
}///
2011-06-13 11:07:45 +00:00
else
2011-07-03 09:28:22 +00:00
tooFar();
2011-06-13 09:57:24 +00:00
}
}
}
2011-07-02 16:20:41 +00:00
if ((mask & L_UP) && _snail->idle()) {
2011-06-29 14:13:17 +00:00
if (_flags._kept) {
2011-06-13 09:57:24 +00:00
int n;
for (n = 0; n < POCKET_NX; n++) {
if (_pocket[n] == this) {
2011-07-02 16:20:41 +00:00
selectPocket(n);
2011-06-13 09:57:24 +00:00
break;
}
}
2011-06-13 11:07:45 +00:00
} else
2011-06-13 09:57:24 +00:00
SNPOST(SNWALK, -1, -1, this); // Hero->FindWay(this);
}
}
}
2011-07-01 06:37:40 +00:00
void CGEEngine::loadSprite(const char *fname, int ref, int cav, int col = 0, int row = 0, int pos = 0) {
2011-06-13 09:57:24 +00:00
static const char *Comd[] = { "Name", "Type", "Phase", "East",
"Left", "Right", "Top", "Bottom",
"Seq", "Near", "Take",
"Portable", "Transparent",
NULL
};
static const char *Type[] = { "DEAD", "AUTO", "WALK", "NEWTON", "LISSAJOUS",
"FLY", NULL
};
char line[LINE_MAX];
int shpcnt = 0;
int type = 0; // DEAD
bool east = false;
bool port = false;
bool tran = false;
int i, lcnt = 0;
uint16 len;
2011-07-01 23:02:14 +00:00
mergeExt(line, fname, SPR_EXT);
2011-06-30 06:30:23 +00:00
if (INI_FILE::exist(line)) { // sprite description file exist
2011-06-13 09:57:24 +00:00
INI_FILE sprf(line);
2011-07-01 06:37:40 +00:00
if (sprf._error)
2011-06-13 09:57:24 +00:00
error("Bad SPR [%s]", line);
2011-06-30 06:30:23 +00:00
while ((len = sprf.read((uint8 *)line)) != 0) {
2011-06-13 09:57:24 +00:00
++ lcnt;
2011-06-13 11:07:45 +00:00
if (len && line[len - 1] == '\n')
2011-06-13 09:57:24 +00:00
line[-- len] = '\0';
2011-06-13 11:07:45 +00:00
if (len == 0 || *line == '.')
2011-06-13 09:57:24 +00:00
continue;
2011-07-01 23:02:14 +00:00
if ((i = takeEnum(Comd, strtok(line, " =\t"))) < 0)
error("Bad line %d [%s]", lcnt, fname);
2011-06-13 09:57:24 +00:00
switch (i) {
case 0 : // Name - will be taken in Expand routine
break;
case 1 : // Type
2011-07-01 23:02:14 +00:00
if ((type = takeEnum(Type, strtok(NULL, " \t,;/"))) < 0)
error("Bad line %d [%s]", lcnt, fname);
2011-06-13 09:57:24 +00:00
break;
case 2 : // Phase
++ shpcnt;
break;
case 3 : // East
east = (atoi(strtok(NULL, " \t,;/")) != 0);
break;
case 11 : // Portable
port = (atoi(strtok(NULL, " \t,;/")) != 0);
break;
case 12 : // Transparent
tran = (atoi(strtok(NULL, " \t,;/")) != 0);
break;
}
}
2011-06-13 09:57:24 +00:00
if (! shpcnt)
error("No shapes [%s]", fname);
} else { // no sprite description: mono-shaped sprite with only .BMP file
++shpcnt;
}
2011-06-13 09:57:24 +00:00
// make sprite of choosen type
switch (type) {
case 1 : { // AUTO
_sprite = new Sprite(this, NULL);
if (_sprite) {
2011-07-01 23:02:14 +00:00
_sprite->gotoxy(col, row);
2011-06-13 09:57:24 +00:00
//Sprite->Time = 1;//-----------$$$$$$$$$$$$$$$$
}
break;
}
2011-06-13 09:57:24 +00:00
case 2 : { // WALK
WALK *w = new WALK(this, NULL);
2011-06-13 09:57:24 +00:00
if (w && ref == 1) {
2011-07-01 23:02:14 +00:00
w->gotoxy(col, row);
2011-06-13 09:57:24 +00:00
if (Hero)
error("2nd HERO [%s]", fname);
Hero = w;
}
_sprite = w;
2011-06-13 09:57:24 +00:00
break;
}
2011-06-13 09:57:24 +00:00
/*
case 3 : // NEWTON
NEWTON * n = new NEWTON(NULL);
if (n)
{
2011-06-13 09:57:24 +00:00
n->Ay = (bottom-n->H);
n->By = 90;
n->Cy = 3;
n->Bx = 99;
n->Cx = 3;
n->Goto(col, row);
}
_sprite = n;
2011-06-13 09:57:24 +00:00
break;
*/
case 4 : { // LISSAJOUS
error("Bad type [%s]", fname);
/*
LISSAJOUS * l = new LISSAJOUS(NULL);
if (l)
{
l->Ax = SCR_WID/2;
l->Ay = SCR_HIG/2;
l->Bx = 7;
l->By = 13;
l->Cx = 300;
l->Cy = 500;
*(long *) &l->Dx = 0; // movex * cnt
2011-06-13 09:57:24 +00:00
l->Goto(col, row);
}
_sprite = l;
2011-06-13 09:57:24 +00:00
*/
break;
}
2011-06-13 09:57:24 +00:00
case 5 : { // FLY
2011-07-01 06:37:40 +00:00
Fly *f = new Fly(this, NULL);
_sprite = f;
2011-06-13 09:57:24 +00:00
//////Sprite->Time = 1;//-----------$$$$$$$$$$$$$$
break;
}
2011-06-13 09:57:24 +00:00
default: { // DEAD
_sprite = new Sprite(this, NULL);
if (_sprite)
2011-07-01 23:02:14 +00:00
_sprite->gotoxy(col, row);
2011-06-13 09:57:24 +00:00
break;
}
}
if (_sprite) {
_sprite->_ref = ref;
_sprite->_cave = cav;
2011-06-29 14:13:17 +00:00
_sprite->_z = pos;
_sprite->_flags._east = east;
_sprite->_flags._port = port;
_sprite->_flags._tran = tran;
_sprite->_flags._kill = true;
_sprite->_flags._bDel = true;
// Extract the filename, without the extension
2011-07-01 23:02:14 +00:00
strcpy(_sprite->_file, fname);
char *p = strchr(_sprite->_file, '.');
if (p)
*p = '\0';
2011-06-13 09:57:24 +00:00
2011-06-29 14:13:17 +00:00
_sprite->_shpCnt = shpcnt;
2011-07-03 09:28:22 +00:00
Vga->_spareQ->append(_sprite);
}
}
2011-07-01 06:37:40 +00:00
void CGEEngine::loadScript(const char *fname) {
2011-06-13 09:57:24 +00:00
char line[LINE_MAX];
char *SpN;
int SpI, SpA, SpX, SpY, SpZ;
bool BkG = false;
INI_FILE scrf(fname);
int lcnt = 0;
bool ok = true;
2011-07-01 06:37:40 +00:00
if (scrf._error)
2011-06-13 09:57:24 +00:00
return;
2011-06-30 06:30:23 +00:00
while (scrf.read((uint8 *)line) != 0) {
2011-06-13 09:57:24 +00:00
char *p;
2011-07-01 06:37:40 +00:00
lcnt++;
2011-06-13 11:07:45 +00:00
if (*line == 0 || *line == '\n' || *line == '.')
2011-06-13 09:57:24 +00:00
continue;
2011-06-13 09:57:24 +00:00
ok = false; // not OK if break
// sprite ident number
2011-06-13 11:07:45 +00:00
if ((p = strtok(line, " \t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
SpI = atoi(p);
// sprite file name
2011-06-13 11:07:45 +00:00
if ((SpN = strtok(NULL, " ,;/\t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
// sprite cave
2011-06-13 11:07:45 +00:00
if ((p = strtok(NULL, " ,;/\t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
SpA = atoi(p);
// sprite column
2011-06-13 11:07:45 +00:00
if ((p = strtok(NULL, " ,;/\t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
SpX = atoi(p);
// sprite row
2011-06-13 11:07:45 +00:00
if ((p = strtok(NULL, " ,;/\t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
SpY = atoi(p);
// sprite Z pos
2011-06-13 11:07:45 +00:00
if ((p = strtok(NULL, " ,;/\t\n")) == NULL)
break;
2011-06-13 09:57:24 +00:00
SpZ = atoi(p);
// sprite life
2011-06-13 11:07:45 +00:00
if ((p = strtok(NULL, " ,;/\t\n")) == NULL)
2011-06-13 09:57:24 +00:00
break;
BkG = atoi(p) == 0;
2011-06-13 09:57:24 +00:00
ok = true; // no break: OK
_sprite = NULL;
2011-07-01 06:37:40 +00:00
loadSprite(SpN, SpI, SpA, SpX, SpY, SpZ);
if (_sprite && BkG)
2011-06-29 14:13:17 +00:00
_sprite->_flags._back = true;
2011-06-13 09:57:24 +00:00
}
if (! ok)
error("Bad INI line %d [%s]", lcnt, fname);
2011-06-13 09:57:24 +00:00
}
#define GAME_FRAME_DELAY (1000 / 50)
2011-07-01 06:37:40 +00:00
void CGEEngine::mainLoop() {
2011-07-03 09:28:22 +00:00
sayDebug();
2011-06-13 09:57:24 +00:00
if (_isDemo) {
// static uint32 tc = 0;
2011-07-03 09:28:22 +00:00
if (/* FIXME: TimerCount - tc >= ((182L * 6L) * 5L) && */ _talk == NULL && _snail->idle()) {
if (_text->getText(_demoText)) {
SNPOST(SNSOUND, -1, 4, NULL); // drumla
2011-07-02 16:20:41 +00:00
SNPOST(SNINF, -1, _demoText, NULL);
SNPOST(SNLABEL, -1, -1, NULL);
2011-07-03 09:28:22 +00:00
if (_text->getText(++_demoText) == NULL)
2011-07-02 16:20:41 +00:00
_demoText = DEMO_TEXT + 1;
}
//FIXME: tc = TimerCount;
2011-06-13 09:57:24 +00:00
}
}
Vga->Show();
2011-07-02 16:20:41 +00:00
_snail_->runCom();
_snail->runCom();
// Game frame delay
uint32 millis = g_system->getMillis();
while (!_eventManager->_quitFlag && (millis < (_lastFrame + GAME_FRAME_DELAY))) {
// Handle any pending events
_eventManager->poll();
// Slight delay
g_system->delayMillis(10);
millis = g_system->getMillis();
}
_lastFrame = millis;
2011-07-03 10:20:01 +00:00
// Dispatch the tick to any active objects
tick();
2011-06-13 09:57:24 +00:00
}
2011-07-03 10:20:01 +00:00
void CGEEngine::tick() {
2011-07-03 10:23:19 +00:00
for (Sprite *spr = Vga->_showQ->first(); spr; spr = spr->_next) {
2011-07-03 10:20:01 +00:00
if (spr->_time) {
if (!spr->_flags._hide) {
if (--spr->_time == 0)
spr->tick();
}
}
}
}
2011-06-13 09:57:24 +00:00
2011-07-01 06:37:40 +00:00
void CGEEngine::loadUser() {
2011-06-13 09:57:24 +00:00
// set scene
2011-07-03 09:28:22 +00:00
if (Startup::_mode == 0) { // user .SVG file found
CFile cfile = CFile(usrPath(_usrFnam), REA, RCrypt);
2011-07-01 06:37:40 +00:00
loadGame(cfile);
2011-06-13 09:57:24 +00:00
} else {
2011-07-03 09:28:22 +00:00
if (Startup::_mode == 1) {
2011-06-13 09:57:24 +00:00
SVG0FILE file = SVG0FILE(SVG0NAME);
2011-07-01 06:37:40 +00:00
loadGame(file);
2011-06-13 09:57:24 +00:00
} else {
2011-07-01 23:02:14 +00:00
loadScript(progName(INI_EXT));
2011-07-02 16:20:41 +00:00
_music = true;
2011-06-30 06:30:23 +00:00
CFile file = CFile(SVG0NAME, WRI);
2011-06-13 09:57:24 +00:00
SaveGame(file);
error("Ok [%s]", SVG0NAME);
}
}
2011-07-01 23:02:14 +00:00
loadScript(progName(IN0_EXT));
}
2011-07-01 06:37:40 +00:00
void CGEEngine::runGame() {
if (_eventManager->_quitFlag)
return;
2011-07-03 09:28:22 +00:00
_text->clear();
_text->preload(100, 1000);
loadHeroXY();
2011-06-29 14:13:17 +00:00
_cavLight->_flags._tran = true;
2011-07-03 09:28:22 +00:00
Vga->_showQ->append(_cavLight);
2011-06-29 14:13:17 +00:00
_cavLight->_flags._hide = true;
static Seq pocSeq[] = { { 0, 0, 0, 0, 20 },
2011-06-13 09:57:24 +00:00
{ 1, 2, 0, 0, 4 },
{ 2, 3, 0, 0, 4 },
{ 3, 4, 0, 0, 16 },
{ 2, 5, 0, 0, 4 },
{ 1, 6, 0, 0, 4 },
{ 0, 1, 0, 0, 16 },
};
2011-07-01 23:02:14 +00:00
_pocLight->setSeq(pocSeq);
2011-06-29 14:13:17 +00:00
_pocLight->_flags._tran = true;
_pocLight->_time = 1;
_pocLight->_z = 120;
2011-07-03 09:28:22 +00:00
Vga->_showQ->append(_pocLight);
2011-07-02 16:20:41 +00:00
selectPocket(-1);
// FIXME: Allow ScummVM to handle mouse display
// Vga->ShowQ->Append(Mouse);
// ___________
2011-07-01 06:37:40 +00:00
loadUser();
// ~~~~~~~~~~~
2011-07-03 09:28:22 +00:00
if ((_sprite = Vga->_spareQ->locate(121)) != NULL)
SNPOST_(SNSEQ, -1, Vga->Mono, _sprite);
2011-07-03 09:28:22 +00:00
if ((_sprite = Vga->_spareQ->locate(122)) != NULL)
2011-07-02 16:20:41 +00:00
_sprite->step(_music);
SNPOST_(SNSEQ, -1, _music, _sprite);
if (!_music)
2011-06-13 09:57:24 +00:00
KillMIDI();
2011-07-03 09:28:22 +00:00
if (_mini && INI_FILE::exist("MINI.SPR")) {
uint8 *ptr = (uint8 *) &*_mini;
2011-06-13 09:57:24 +00:00
if (ptr != NULL) {
2011-07-01 06:37:40 +00:00
loadSprite("MINI", -1, 0, MINI_X, MINI_Y);
ExpandSprite(_miniCave = _sprite); // NULL is ok
if (_miniCave) {
2011-06-29 14:13:17 +00:00
_miniCave->_flags._hide = true;
2011-07-01 23:02:14 +00:00
_miniCave->moveShapes(ptr);
2011-07-03 09:28:22 +00:00
_miniShp[0] = new Bitmap(*_miniCave->shp());
_miniShpList = _miniCave->setShapeList(_miniShp);
2011-06-13 09:57:24 +00:00
PostMiniStep(-1);
}
}
}
2011-06-13 09:57:24 +00:00
if (Hero) {
ExpandSprite(Hero);
2011-07-02 16:20:41 +00:00
Hero->gotoxy(_heroXY[_now - 1]._x, _heroXY[_now - 1]._y);
2011-06-30 06:30:23 +00:00
if (INI_FILE::exist("00SHADOW.SPR")) {
2011-07-01 06:37:40 +00:00
loadSprite("00SHADOW", -1, 0, Hero->_x + 14, Hero->_y + 51);
if ((_shadow = _sprite) != NULL) {
_shadow->_ref = 2;
2011-06-29 14:13:17 +00:00
_shadow->_flags._tran = true;
Hero->_flags._shad = true;
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(Vga->_spareQ->remove(_shadow), Hero);
2011-06-13 09:57:24 +00:00
}
}
}
2011-07-03 09:28:22 +00:00
_infoLine->gotoxy(INFO_X, INFO_Y);
_infoLine->_flags._tran = true;
_infoLine->update(NULL);
Vga->_showQ->insert(_infoLine);
2011-07-03 09:28:22 +00:00
_debugLine->_z = 126;
Vga->_showQ->insert(_debugLine);
2011-06-29 14:13:17 +00:00
_horzLine->_y = MAP_TOP - (MAP_TOP > 0);
_horzLine->_z = 126;
2011-07-03 09:28:22 +00:00
Vga->_showQ->insert(_horzLine);
2011-07-03 09:28:22 +00:00
_mouse->Busy = Vga->_spareQ->locate(BUSY_REF);
if (_mouse->Busy)
ExpandSprite(_mouse->Busy);
2011-07-03 09:28:22 +00:00
_startup = 0;
2011-07-02 16:20:41 +00:00
SNPOST(SNLEVEL, -1, _oldLev, &_cavLight);
_cavLight->gotoxy(CAVE_X + ((_now - 1) % CAVE_NX) * CAVE_DX + CAVE_SX,
CAVE_Y + ((_now - 1) / CAVE_NX) * CAVE_DY + CAVE_SY);
2011-07-01 06:37:40 +00:00
caveUp();
_keyboard->setClient(Sys);
2011-06-13 09:57:24 +00:00
// main loop
2011-07-03 09:28:22 +00:00
while (!_finis && !_eventManager->_quitFlag) {
2011-06-13 09:57:24 +00:00
//TODO Change the SNPOST message send to a special way to send function pointer
// if (FINIS) SNPOST(SNEXEC, -1, 0, (void *)&QGame);
warning("RunGame: problematic use of SNPOST");
2011-07-01 06:37:40 +00:00
mainLoop();
2011-06-13 09:57:24 +00:00
}
_keyboard->setClient(NULL);
_heart->_enable = false;
2011-06-13 09:57:24 +00:00
SNPOST(SNCLEAR, -1, 0, NULL);
SNPOST_(SNCLEAR, -1, 0, NULL);
_mouse->Off();
2011-07-03 09:28:22 +00:00
Vga->_showQ->clear();
Vga->_spareQ->clear();
2011-06-13 09:57:24 +00:00
Hero = NULL;
_shadow = NULL;
2011-06-13 09:57:24 +00:00
}
2011-07-01 06:37:40 +00:00
void CGEEngine::movie(const char *ext) {
if (_eventManager->_quitFlag)
return;
2011-07-01 23:02:14 +00:00
const char *fn = progName(ext);
2011-06-30 06:30:23 +00:00
if (INI_FILE::exist(fn)) {
2011-07-01 06:37:40 +00:00
loadScript(fn);
2011-07-03 09:28:22 +00:00
ExpandSprite(Vga->_spareQ->locate(999));
feedSnail(Vga->_showQ->locate(999), TAKE);
// FIXME: Allow ScummVM to handle mouse display
//Vga->ShowQ->Append(Mouse);
_heart->_enable = true;
_keyboard->setClient(Sys);
2011-07-02 16:20:41 +00:00
while (!_snail->idle() && !_eventManager->_quitFlag)
2011-07-01 06:37:40 +00:00
mainLoop();
_keyboard->setClient(NULL);
_heart->_enable = false;
2011-06-13 09:57:24 +00:00
SNPOST(SNCLEAR, -1, 0, NULL);
SNPOST_(SNCLEAR, -1, 0, NULL);
2011-07-03 09:28:22 +00:00
Vga->_showQ->clear();
Vga->_spareQ->clear();
}
}
2011-07-01 06:37:40 +00:00
bool CGEEngine::showTitle(const char *name) {
if (_eventManager->_quitFlag)
return false;
2011-06-30 06:30:23 +00:00
Bitmap::_pal = VGA::SysPal;
BMP_PTR LB[] = { new Bitmap(name, true), NULL };
Bitmap::_pal = NULL;
2011-06-13 09:57:24 +00:00
bool usr_ok = false;
Sprite D(this, LB);
2011-06-29 14:13:17 +00:00
D._flags._kill = true;
D._flags._bDel = true;
2011-07-01 23:02:14 +00:00
D.center();
D.show(2);
2011-07-03 09:28:22 +00:00
if (Startup::_mode == 2) {
2011-07-01 06:37:40 +00:00
inf(SVG0NAME);
2011-07-03 09:28:22 +00:00
_talk->show(2);
2011-06-13 09:57:24 +00:00
}
Vga->Sunset();
Vga->CopyPage(1, 2);
Vga->CopyPage(0, 1);
2011-07-02 16:20:41 +00:00
selectPocket(-1);
Vga->Sunrise(VGA::SysPal);
2011-06-13 09:57:24 +00:00
2011-07-03 09:28:22 +00:00
if (Startup::_mode < 2 && !Startup::_soundOk) {
Vga->CopyPage(1, 2);
Vga->CopyPage(0, 1);
2011-07-03 09:28:22 +00:00
Vga->_showQ->append(_mouse);
_heart->_enable = true;
_mouse->On();
2011-07-02 16:20:41 +00:00
for (selectSound(); !_snail->idle() || VMENU::Addr;) {
2011-07-01 06:37:40 +00:00
mainLoop();
if (_eventManager->_quitFlag)
return false;
}
_mouse->Off();
_heart->_enable = false;
2011-07-03 09:28:22 +00:00
Vga->_showQ->clear();
Vga->CopyPage(0, 2);
2011-07-03 09:28:22 +00:00
Startup::_soundOk = 2;
2011-07-02 16:20:41 +00:00
if (_music)
2011-06-13 09:57:24 +00:00
LoadMIDI(0);
}
2011-07-03 09:28:22 +00:00
if (Startup::_mode < 2) {
if (_isDemo) {
2011-07-03 09:28:22 +00:00
strcpy(_usrFnam, progName(SVG_EXT));
usr_ok = true;
} else {
//-----------------------------------------
2011-06-13 09:57:24 +00:00
#ifndef EVA
#ifdef CD
2011-07-03 09:28:22 +00:00
Startup::_summa |= (0xC0 + (DriveCD(0) << 6)) & 0xFF;
2011-06-13 09:57:24 +00:00
#else
// At this point the game originally read the boot sector to get
// the serial number for it's copy protection check
2011-06-13 09:57:24 +00:00
#endif
//-----------------------------------------
2011-07-01 06:37:40 +00:00
movie("X00"); // paylist
Vga->CopyPage(1, 2);
Vga->CopyPage(0, 1);
2011-07-03 09:28:22 +00:00
Vga->_showQ->append(_mouse);
//Mouse.On();
_heart->_enable = true;
for (takeName(); GetText::_ptr;) {
2011-07-01 06:37:40 +00:00
mainLoop();
if (_eventManager->_quitFlag)
return false;
}
_heart->_enable = false;
2011-07-03 09:28:22 +00:00
if (_keyboard->last() == Enter && *_usrFnam)
usr_ok = true;
if (usr_ok)
2011-07-03 09:28:22 +00:00
strcat(_usrFnam, SVG_EXT);
//Mouse.Off();
2011-07-03 09:28:22 +00:00
Vga->_showQ->clear();
Vga->CopyPage(0, 2);
2011-06-13 09:57:24 +00:00
#endif
}
2011-07-03 09:28:22 +00:00
if (usr_ok && Startup::_mode == 0) {
const char *n = usrPath(_usrFnam);
2011-06-30 06:30:23 +00:00
if (CFile::exist(n)) {
CFile file = CFile(n, REA, RCrypt);
2011-07-01 06:37:40 +00:00
loadGame(file, true); // only system vars
Vga->SetColors(VGA::SysPal, 64);
Vga->Update();
2011-06-13 09:57:24 +00:00
if (FINIS) {
2011-07-03 09:28:22 +00:00
Startup::_mode++;
2011-06-13 09:57:24 +00:00
FINIS = false;
}
2011-06-13 11:07:45 +00:00
} else
2011-07-03 09:28:22 +00:00
Startup::_mode++;
}
}
2011-07-03 09:28:22 +00:00
if (Startup::_mode < 2)
2011-07-01 06:37:40 +00:00
movie("X01"); // wink
Vga->CopyPage(0, 2);
if (_isDemo)
return true;
else
2011-07-03 09:28:22 +00:00
return (Startup::_mode == 2 || usr_ok);
}
/*
void StkDump (void) {
CFILE f("!STACK.DMP", BFW);
f.Write((uint8 *) (intStackPtr-STACK_SIZ/2), STACK_SIZ*2);
}
*/
void CGEEngine::cge_main(void) {
2011-06-13 09:57:24 +00:00
uint16 intStack[STACK_SIZ / 2];
2011-07-03 09:28:22 +00:00
_intStackPtr = intStack;
2011-06-13 09:57:24 +00:00
//Debug( memset((void *) (-K(2)), 0, K(1)); )
//Debug( memset((void *) (-K(4)), 0, K(1)); )
2011-07-02 16:20:41 +00:00
memset(_barriers, 0xFF, sizeof(_barriers));
if (!_mouse->Exist)
2011-07-03 09:28:22 +00:00
error("%s", _text->getText(NO_MOUSE_TEXT));
2011-06-30 06:30:23 +00:00
if (!SVG0FILE::exist(SVG0NAME))
2011-07-03 09:28:22 +00:00
Startup::_mode = 2;
2011-06-13 09:57:24 +00:00
2011-07-03 09:28:22 +00:00
_debugLine->_flags._hide = true;
2011-06-29 14:13:17 +00:00
_horzLine->_flags._hide = true;
2011-06-13 09:57:24 +00:00
//srand((uint16) Timer());
Sys = new SYSTEM(this);
2011-06-13 09:57:24 +00:00
2011-07-03 09:28:22 +00:00
if (_music && Startup::_soundOk)
2011-06-13 09:57:24 +00:00
LoadMIDI(0);
2011-07-03 09:28:22 +00:00
if (Startup::_mode < 2)
2011-07-01 06:37:40 +00:00
movie(LGO_EXT);
2011-07-01 06:37:40 +00:00
if (showTitle("WELCOME")) {
2011-07-03 09:28:22 +00:00
if ((!_isDemo) && (Startup::_mode == 1))
2011-07-01 06:37:40 +00:00
movie("X02"); // intro
runGame();
2011-07-03 09:28:22 +00:00
_startup = 2;
2011-06-13 11:07:45 +00:00
if (FINIS)
2011-07-01 06:37:40 +00:00
movie("X03");
2011-06-13 11:07:45 +00:00
} else
Vga->Sunset();
}
2011-06-10 20:57:09 +00:00
} // End of namespace CGE