Initial commit
This commit is contained in:
103
engines/m4/adv_r/adv.h
Normal file
103
engines/m4/adv_r/adv.h
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_H
|
||||
#define M4_ADV_R_ADV_H
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "m4/adv_r/adv_hotspot.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define MAX_SCENES 180
|
||||
#define MAXRAILNODES 32
|
||||
#define PATH_END 0xffff
|
||||
#define MAX_PLYR_STRING_LEN 40
|
||||
|
||||
#define STR_FADEPAL "fade palette"
|
||||
#define STR_RAILNODE "rail node"
|
||||
#define STR_PATH_NODE "path node"
|
||||
|
||||
enum {
|
||||
INSTALL_SOUND_DRIVERS = 1,
|
||||
INSTALL_PLAYER_BEEN_INIT = 2,
|
||||
INSTALL_RAIL_SYSTEM = 4,
|
||||
INSTALL_INVENTORY_SYSTEM = 8,
|
||||
INSTALL_INVERSE_PALETTE = 0x10,
|
||||
INSTALL_MININUM = 0,
|
||||
INSTALL_ALL = 0x1f
|
||||
};
|
||||
|
||||
enum {
|
||||
UNKNOWN_OBJECT = 997,
|
||||
BACKPACK = 998,
|
||||
NOWHERE = 999
|
||||
};
|
||||
#define GLOBAL_SCENE 999
|
||||
|
||||
enum KernelTriggerType {
|
||||
KT_PARSE = 1,
|
||||
KT_DAEMON, KT_PREPARSE, KT_EXPIRE, KT_LOOP
|
||||
};
|
||||
|
||||
struct pathNode {
|
||||
pathNode *next = nullptr;
|
||||
byte nodeID = 0;
|
||||
};
|
||||
|
||||
struct noWalkRect {
|
||||
noWalkRect *next = nullptr;
|
||||
noWalkRect *prev = nullptr;
|
||||
int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||
int32 alternateWalkToNode = 0;
|
||||
int32 walkAroundNode1 = 0;
|
||||
int32 walkAroundNode2 = 0;
|
||||
int32 walkAroundNode3 = 0;
|
||||
int32 walkAroundNode4 = 0;
|
||||
};
|
||||
|
||||
struct SceneDef {
|
||||
char art_base[MAX_FILENAME_SIZE] = { 0 };
|
||||
char picture_base[MAX_FILENAME_SIZE] = { 0 };
|
||||
|
||||
int32 num_hotspots = 0; // # of hotspots
|
||||
HotSpotRec *hotspots = nullptr;
|
||||
int32 num_parallax = 0;
|
||||
HotSpotRec *parallax = nullptr;
|
||||
int32 num_props = 0;
|
||||
HotSpotRec *props = nullptr;
|
||||
|
||||
int32 front_y = 400, back_y = 100; // Player scaling baselines
|
||||
int32 front_scale = 100, back_scale = 85; // Player scaling factors
|
||||
|
||||
int16 depth_table[16]; // Player sprite depth table
|
||||
int32 numRailNodes = 0; // # of rails
|
||||
|
||||
SceneDef() {
|
||||
Common::fill(depth_table, depth_table + 16, 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
||||
68
engines/m4/adv_r/adv_background.cpp
Normal file
68
engines/m4/adv_r/adv_background.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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 "m4/adv_r/adv_background.h"
|
||||
#include "m4/adv_r/adv_file.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void adv_freeCodes() {
|
||||
if (_G(screenCodeBuff)) {
|
||||
delete _G(screenCodeBuff);
|
||||
_G(screenCodeBuff) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void adv_freeBackground() {
|
||||
if (_G(game_bgBuff)) {
|
||||
delete _G(game_bgBuff);
|
||||
_G(game_bgBuff) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool adv_restoreBackground() {
|
||||
RGB8 myPalette[256];
|
||||
SysFile sysFile(_G(currBackgroundFN));
|
||||
|
||||
if (load_background(&sysFile, &_G(game_bgBuff), myPalette)) {
|
||||
sysFile.close();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool adv_restoreCodes() {
|
||||
SysFile sysFile(_G(currCodeFN));
|
||||
|
||||
_G(screenCodeBuff) = load_codes(&sysFile);
|
||||
if (_G(screenCodeBuff)) {
|
||||
sysFile.close();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
37
engines/m4/adv_r/adv_background.h
Normal file
37
engines/m4/adv_r/adv_background.h
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_BACKGROUND_H
|
||||
#define M4_ADV_R_ADV_BACKGROUND_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void adv_freeCodes();
|
||||
void adv_freeBackground();
|
||||
bool adv_restoreBackground();
|
||||
bool adv_restoreCodes();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
106
engines/m4/adv_r/adv_been.cpp
Normal file
106
engines/m4/adv_r/adv_been.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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 "m4/adv_r/adv_been.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/mem/memman.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define TOTAL_SCENES 180
|
||||
|
||||
bool player_been_init(int16 num_scenes) {
|
||||
assert(num_scenes == TOTAL_SCENES);
|
||||
_G(scene_list).table = (int16 *)mem_alloc(sizeof(int16) * num_scenes, "been_scenes");
|
||||
|
||||
if (!_G(scene_list).table)
|
||||
error_show(FL, 'OOM!', "player_been_init");
|
||||
|
||||
_G(scene_list).total_scenes = num_scenes;
|
||||
player_reset_been();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void player_been_shutdown() {
|
||||
mem_free(_G(scene_list).table);
|
||||
}
|
||||
|
||||
void player_reset_been() {
|
||||
Common::fill(_G(scene_list).table, _G(scene_list).table + TOTAL_SCENES, 180);
|
||||
_G(scene_list).total_scenes = TOTAL_SCENES;
|
||||
_G(scene_list).tail = 0;
|
||||
}
|
||||
|
||||
void player_been_sync(Common::Serializer &s) {
|
||||
// Handle number of scenes
|
||||
int count = _G(scene_list).total_scenes;
|
||||
s.syncAsUint32LE(count);
|
||||
assert(s.isSaving() || count == _G(scene_list).total_scenes);
|
||||
|
||||
// Handle current tail
|
||||
s.syncAsUint32LE(_G(scene_list).tail);
|
||||
|
||||
// Handle table
|
||||
for (int i = 0; i < count; ++i)
|
||||
s.syncAsSint16LE(_G(scene_list).table[i]);
|
||||
}
|
||||
|
||||
bool player_been_here(int16 scene_num) {
|
||||
for (int i = 0; i < _G(scene_list).tail; i++)
|
||||
if (_G(scene_list).table[i] == scene_num)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool player_enters_scene(int16 scene_num) {
|
||||
if (player_been_here(scene_num))
|
||||
return true;
|
||||
|
||||
_G(scene_list).table[_G(scene_list).tail] = scene_num;
|
||||
++_G(scene_list).tail;
|
||||
|
||||
if (_G(scene_list).tail > _G(scene_list).total_scenes)
|
||||
error_show(FL, 'SLTS');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void player_forgets_scene(int16 scene_num) {
|
||||
// Check the list
|
||||
for (int i = 0; i < _G(scene_list).tail; i++) {
|
||||
// Found a match
|
||||
if (_G(scene_list).table[i] == scene_num) {
|
||||
// Close the table
|
||||
for (int j = i; j < _G(scene_list).tail; j++) {
|
||||
_G(scene_list).table[j] = _G(scene_list).table[j + 1];
|
||||
}
|
||||
|
||||
// One less scene
|
||||
--_G(scene_list).tail;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
81
engines/m4/adv_r/adv_been.h
Normal file
81
engines/m4/adv_r/adv_been.h
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_BEEN_H
|
||||
#define M4_ADV_R_ADV_BEEN_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/stream.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct Scene_list {
|
||||
int32 total_scenes = 0;
|
||||
int32 tail = 0;
|
||||
int16 *table = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes player_been information, allocates memory for a list of scenes
|
||||
*
|
||||
* Takes the number of scenes to allocate space for
|
||||
* @returns True if successfully allocated
|
||||
*/
|
||||
bool player_been_init(int16 num_scenes);
|
||||
|
||||
/**
|
||||
* Shuts down player_been system. Deallocates some memory
|
||||
*/
|
||||
void player_been_shutdown();
|
||||
|
||||
/**
|
||||
* Resets the player_been system
|
||||
*/
|
||||
void player_reset_been(void);
|
||||
|
||||
/**
|
||||
* Saves/loads player_been information
|
||||
*/
|
||||
void player_been_sync(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Called whenever player enters a scene
|
||||
* @param scene_num Takes the scene to be entered
|
||||
* @returns True if the player has been there before, or false otherwise
|
||||
*/
|
||||
bool player_enters_scene(int16 scene_num);
|
||||
|
||||
/**
|
||||
* Called if the apps programmer wants the player to forget about being in
|
||||
* a room
|
||||
*/
|
||||
void player_forgets_scene(int16 scene_num);
|
||||
|
||||
/**
|
||||
* Checks whether player has been in specified scene before
|
||||
*/
|
||||
bool player_been_here(int16 scene_num);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
146
engines/m4/adv_r/adv_chk.cpp
Normal file
146
engines/m4/adv_r/adv_chk.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/* 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 "m4/adv_r/adv_chk.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/fileio/sys_file.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
static HotSpotRec *read_hotspots(SysFile *fpdef, HotSpotRec *h, int32 num) {
|
||||
int32 str_len;
|
||||
char s[MAX_FILENAME_SIZE];
|
||||
int32 x1, x2, y1, y2;
|
||||
HotSpotRec *head = nullptr;
|
||||
|
||||
for (int32 i = 0; i < num; i++) {
|
||||
x1 = fpdef->readSint32LE();
|
||||
y1 = fpdef->readSint32LE();
|
||||
x2 = fpdef->readSint32LE();
|
||||
y2 = fpdef->readSint32LE();
|
||||
|
||||
h = hotspot_new(x1, y1, x2, y2);
|
||||
if (!head)
|
||||
head = h;
|
||||
else
|
||||
head = hotspot_add(head, h, false);
|
||||
|
||||
h->feet_x = fpdef->readSint32LE();
|
||||
h->feet_y = fpdef->readSint32LE();
|
||||
h->facing = fpdef->readSByte();
|
||||
h->active = fpdef->readSByte();
|
||||
h->cursor_number = fpdef->readSByte();
|
||||
h->syntax = fpdef->readSByte();
|
||||
h->vocabID = fpdef->readSint32LE();
|
||||
h->verbID = fpdef->readSint32LE();
|
||||
|
||||
// -------
|
||||
|
||||
str_len = fpdef->readSint32LE();
|
||||
|
||||
if (str_len) {
|
||||
if (!fpdef->read((byte *)s, str_len))
|
||||
error_show(FL, 0, "Could not read vocab");
|
||||
hotspot_newVocab(h, s);
|
||||
}
|
||||
|
||||
str_len = fpdef->readSint32LE();
|
||||
|
||||
if (str_len) {
|
||||
if (!fpdef->read((byte *)s, str_len))
|
||||
error_show(FL, 0, "Could not read verb");
|
||||
hotspot_newVerb(h, s);
|
||||
}
|
||||
|
||||
str_len = fpdef->readSint32LE();
|
||||
|
||||
if (str_len) {
|
||||
if (!fpdef->read((byte *)s, str_len))
|
||||
error_show(FL, 0, "Could not read prep");
|
||||
hotspot_newPrep(h, s);
|
||||
}
|
||||
|
||||
str_len = fpdef->readSint32LE();
|
||||
|
||||
if (str_len) {
|
||||
if (!fpdef->read((byte *)s, str_len))
|
||||
error_show(FL, 0, "Could not read sprite");
|
||||
hotspot_new_sprite(h, s);
|
||||
}
|
||||
|
||||
h->hash = fpdef->readSint16LE();
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
static void load_def(SysFile *fpdef) {
|
||||
int32 x, y;
|
||||
char s[MAX_FILENAME_SIZE];
|
||||
|
||||
fpdef->read((byte *)s, MAX_FILENAME_SIZE);
|
||||
Common::strlcpy(_G(myDef)->art_base, s, MAX_FILENAME_SIZE);
|
||||
|
||||
fpdef->read((byte *)s, MAX_FILENAME_SIZE);
|
||||
Common::strlcpy(_G(myDef)->picture_base, s, MAX_FILENAME_SIZE);
|
||||
|
||||
_G(myDef)->num_hotspots = fpdef->readSint32LE();
|
||||
_G(myDef)->num_parallax = fpdef->readSint32LE();
|
||||
_G(myDef)->num_props = fpdef->readSint32LE();
|
||||
_G(myDef)->front_y = fpdef->readSint32LE();
|
||||
_G(myDef)->back_y = fpdef->readSint32LE();
|
||||
_G(myDef)->front_scale = fpdef->readSint32LE();
|
||||
_G(myDef)->back_scale = fpdef->readSint32LE();
|
||||
|
||||
for (int32 i = 0; i < 16; i++) {
|
||||
_G(myDef)->depth_table[i] = fpdef->readSint16LE();
|
||||
}
|
||||
|
||||
_G(myDef)->numRailNodes = fpdef->readSint32LE();
|
||||
|
||||
for (int32 i = 0; i < _G(myDef)->numRailNodes; i++) {
|
||||
x = fpdef->readSint32LE();
|
||||
y = fpdef->readSint32LE();
|
||||
|
||||
if (AddRailNode(x, y, nullptr, true) < 0)
|
||||
error_show(FL, 0, "more than %d (defn. in intrrail.h) nodes", MAXRAILNODES);
|
||||
}
|
||||
|
||||
_G(myDef)->hotspots = read_hotspots(fpdef, nullptr, _G(myDef)->num_hotspots);
|
||||
_G(myDef)->parallax = read_hotspots(fpdef, nullptr, _G(myDef)->num_parallax);
|
||||
_G(myDef)->props = read_hotspots(fpdef, nullptr, _G(myDef)->num_props);
|
||||
}
|
||||
|
||||
int db_def_chk_read(int16 room_code, SceneDef *rdef) {
|
||||
_G(myDef) = rdef;
|
||||
|
||||
_G(def_filename) = Common::String::format("%03d.chk", room_code);
|
||||
SysFile fpdef(_G(def_filename));
|
||||
|
||||
load_def(&fpdef);
|
||||
fpdef.close();
|
||||
|
||||
return -1; // everything happy code
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
40
engines/m4/adv_r/adv_chk.h
Normal file
40
engines/m4/adv_r/adv_chk.h
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_CHK_H
|
||||
#define M4_ADV_R_ADV_CHK_H
|
||||
|
||||
#include "m4/adv_r/adv.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
/**
|
||||
* Reads the .DEF file for the specified room into the "room" structure.
|
||||
* @param room_code room number
|
||||
* @param rdef Output def to populate
|
||||
* @returns Returns 0 if successful, or -1 for error
|
||||
*/
|
||||
int db_def_chk_read(int16 room_code, SceneDef *rdef);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
212
engines/m4/adv_r/adv_control.cpp
Normal file
212
engines/m4/adv_r/adv_control.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/* 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 "m4/adv_r/adv_control.h"
|
||||
#include "m4/adv_r/adv_interface.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/mouse.h"
|
||||
#include "m4/gui/hotkeys.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/mem/memman.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
#include "m4/vars.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
bool kernel_section_startup() {
|
||||
_G(game).previous_section = _G(game).section_id;
|
||||
_G(game).section_id = _G(game).new_section;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void player_set_commands_allowed(bool t_or_f) {
|
||||
_G(set_commands_allowed_since_last_checked) = true;
|
||||
_G(player).comm_allowed = t_or_f;
|
||||
|
||||
if (t_or_f) {
|
||||
// OK to do something
|
||||
mouse_set_sprite(kArrowCursor);
|
||||
intr_cancel_sentence();
|
||||
track_hotspots_refresh();
|
||||
|
||||
} else {
|
||||
// Hour glass
|
||||
_GI().showWaitCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void game_pause(bool flag) {
|
||||
if (flag) {
|
||||
_G(kernel).pause = true;
|
||||
pauseEngines();
|
||||
} else {
|
||||
_G(kernel).pause = false;
|
||||
unpauseEngines();
|
||||
}
|
||||
}
|
||||
|
||||
void player_hotspot_walk_override(int32 x, int32 y, int32 facing, int32 trigger) {
|
||||
_G(player).walk_x = x;
|
||||
_G(player).walk_y = y;
|
||||
_G(player).walk_facing = facing;
|
||||
_G(player).walker_trigger = trigger;
|
||||
_G(player).ready_to_walk = true;
|
||||
_G(player).need_to_walk = true;
|
||||
}
|
||||
|
||||
void player_hotspot_walk_override_just_face(int32 facing, int32 trigger) {
|
||||
player_update_info(_G(my_walker), &_G(player_info));
|
||||
player_hotspot_walk_override(_G(player_info).x, _G(player_info).y, facing, trigger);
|
||||
}
|
||||
|
||||
void adv_kill_digi_between_rooms(bool true_or_false) {
|
||||
_G(shut_down_digi_tracks_between_rooms) = true_or_false;
|
||||
}
|
||||
|
||||
bool this_is_a_walkcode(int32 x, int32 y) {
|
||||
if (!_G(screenCodeBuff))
|
||||
return false;
|
||||
|
||||
Buffer *walkCodes;
|
||||
byte *ptr;
|
||||
bool result;
|
||||
|
||||
walkCodes = _G(screenCodeBuff)->get_buffer();
|
||||
if (!walkCodes)
|
||||
return false;
|
||||
|
||||
// Verify params
|
||||
if (x < 0 || y < 0 || x >= walkCodes->w || y >= walkCodes->h)
|
||||
return false;
|
||||
|
||||
ptr = gr_buffer_pointer(walkCodes, x, y);
|
||||
result = ((*ptr) & 0x10) ? true : false;
|
||||
|
||||
_G(screenCodeBuff)->release();
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 get_screen_depth(int32 x, int32 y) {
|
||||
Buffer *walkCodes;
|
||||
byte *ptr;
|
||||
int32 myDepth;
|
||||
|
||||
if (!_G(screenCodeBuff))
|
||||
return 0;
|
||||
|
||||
walkCodes = _G(screenCodeBuff)->get_buffer();
|
||||
if (!walkCodes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify params
|
||||
if (x < 0 || y < 0 || x >= walkCodes->w || y >= walkCodes->h) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = gr_buffer_pointer(walkCodes, x, y);
|
||||
myDepth = (*ptr) & 0x0f;
|
||||
|
||||
_G(screenCodeBuff)->release();
|
||||
return myDepth;
|
||||
}
|
||||
|
||||
int32 get_screen_color(int32 x, int32 y) {
|
||||
Buffer *game_buff;
|
||||
byte *ptr;
|
||||
int32 myColor;
|
||||
|
||||
game_buff = _G(gameDrawBuff)->get_buffer();
|
||||
if (!game_buff) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//verify params
|
||||
if (x < 0 || y < 0 || x >= game_buff->w || y >= game_buff->h) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = gr_buffer_pointer(game_buff, x, y);
|
||||
myColor = *ptr;
|
||||
|
||||
_G(gameDrawBuff)->release();
|
||||
return myColor;
|
||||
}
|
||||
|
||||
void update_mouse_pos_dialog() {
|
||||
int32 status;
|
||||
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
assert(game_buff_ptr);
|
||||
|
||||
if (_G(my_walker) != nullptr) {
|
||||
if (!_G(my_walker)->myAnim8)
|
||||
error_show(FL, 'W:-(');
|
||||
player_get_info();
|
||||
}
|
||||
|
||||
char tempStr1[MAX_STRING_LEN], tempStr2[MAX_STRING_LEN];
|
||||
|
||||
Common::sprintf_s(tempStr1, "%d From: %d", _G(game).room_id, _G(game).previous_room);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 1);
|
||||
|
||||
int32 xxx = _G(MouseState).CursorColumn;
|
||||
int32 yyy = _G(MouseState).CursorRow;
|
||||
|
||||
int32 scrnDepth = get_screen_depth(xxx - game_buff_ptr->x1, yyy - game_buff_ptr->y1);
|
||||
int32 palColor = get_screen_color(xxx - game_buff_ptr->x1, yyy - game_buff_ptr->y1);
|
||||
|
||||
if (this_is_a_walkcode(xxx - game_buff_ptr->x1, yyy - game_buff_ptr->y1)) {
|
||||
Common::sprintf_s(tempStr1, "WC %d, %d PAL: %d", xxx, yyy, palColor);
|
||||
Common::sprintf_s(tempStr2, "WC %d, %d D: %d", xxx - game_buff_ptr->x1, yyy - game_buff_ptr->y1, scrnDepth);
|
||||
} else {
|
||||
Common::sprintf_s(tempStr1, " %d, %d PAL: %d", xxx, yyy, palColor);
|
||||
Common::sprintf_s(tempStr2, " %d, %d D: %d", xxx - game_buff_ptr->x1, yyy - game_buff_ptr->y1, scrnDepth);
|
||||
}
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 2);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr2, nullptr, 3);
|
||||
|
||||
if (this_is_a_walkcode(_G(player_info).x, _G(player_info).y)) {
|
||||
Common::sprintf_s(tempStr1, "WC %d, %d", _G(player_info).x + game_buff_ptr->x1, _G(player_info).y + game_buff_ptr->y1);
|
||||
Common::sprintf_s(tempStr2, "WC %d, %d", _G(player_info).x, _G(player_info).y);
|
||||
} else {
|
||||
Common::sprintf_s(tempStr1, " %d, %d", _G(player_info).x + game_buff_ptr->x1, _G(player_info).y + game_buff_ptr->y1);
|
||||
Common::sprintf_s(tempStr2, " %d, %d", _G(player_info).x, _G(player_info).y);
|
||||
}
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 4);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr2, nullptr, 5);
|
||||
|
||||
Common::sprintf_s(tempStr1, "%d", _G(player_info).scale);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 6);
|
||||
|
||||
Common::sprintf_s(tempStr1, "%x", _G(player_info).depth);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 7);
|
||||
|
||||
Common::sprintf_s(tempStr1, "%d, %d", game_buff_ptr->x1, game_buff_ptr->y1);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 8);
|
||||
|
||||
Common::sprintf_s(tempStr1, "%d", _G(player_info).facing);
|
||||
Dialog_Change_Item_Prompt(_G(mousePosDialog), tempStr1, nullptr, 10);
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
41
engines/m4/adv_r/adv_control.h
Normal file
41
engines/m4/adv_r/adv_control.h
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_CONTROL_H
|
||||
#define M4_ADV_R_ADV_CONTROL_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
extern bool kernel_section_startup();
|
||||
extern void player_set_commands_allowed(bool t_or_f);
|
||||
extern void game_pause(bool flag);
|
||||
extern bool this_is_a_walkcode(int32 x, int32 y);
|
||||
extern int32 get_screen_depth(int32 x, int32 y);
|
||||
extern int32 get_screen_color(int32 x, int32 y);
|
||||
extern void update_mouse_pos_dialog();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
406
engines/m4/adv_r/adv_file.cpp
Normal file
406
engines/m4/adv_r/adv_file.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/* 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/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/util.h"
|
||||
#include "m4/adv_r/adv_file.h"
|
||||
#include "m4/adv_r/adv_chk.h"
|
||||
#include "m4/adv_r/adv_walk.h"
|
||||
#include "m4/adv_r/db_env.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/fileio/extensions.h"
|
||||
#include "m4/fileio/info.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/gui/gui_buffer.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/platform/tile/tile_read.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
static Common::String get_background_filename(const SceneDef *rdef);
|
||||
static Common::String get_attribute_filename(const SceneDef *rdef);
|
||||
static void recreate_animation_draw_screen(GrBuff **loadBuf);
|
||||
static void troll_for_colors(RGB8 *newPal, uint8 minPalEntry, uint8 maxPalEntry);
|
||||
|
||||
void kernel_unload_room(SceneDef *rdef, GrBuff **code_data, GrBuff **loadBuffer) {
|
||||
term_message("Unloading scene %d", _G(game).room_id);
|
||||
|
||||
if (_G(gameDrawBuff)) {
|
||||
gui_buffer_deregister((Buffer *)_G(gameDrawBuff));
|
||||
delete _G(gameDrawBuff);
|
||||
_G(gameDrawBuff) = nullptr;
|
||||
}
|
||||
|
||||
if (*code_data)
|
||||
delete *code_data;
|
||||
*code_data = nullptr;
|
||||
|
||||
if (*loadBuffer)
|
||||
delete *loadBuffer;
|
||||
*loadBuffer = nullptr;
|
||||
|
||||
if (!rdef)
|
||||
return;
|
||||
|
||||
// Must we deallocate existing hot spots?
|
||||
if (rdef->hotspots != nullptr) {
|
||||
hotspot_delete_all(rdef->hotspots);
|
||||
rdef->hotspots = nullptr;
|
||||
}
|
||||
rdef->num_hotspots = 0;
|
||||
|
||||
// Must we deallocate existing parallax?
|
||||
if (rdef->parallax != nullptr) {
|
||||
hotspot_delete_all(rdef->parallax);
|
||||
rdef->parallax = nullptr;
|
||||
}
|
||||
rdef->num_parallax = 0;
|
||||
|
||||
// Must we deallocate existing props?
|
||||
if (rdef->props != nullptr) {
|
||||
hotspot_delete_all(rdef->props);
|
||||
rdef->props = nullptr;
|
||||
}
|
||||
rdef->num_props = 0;
|
||||
|
||||
ClearRails();
|
||||
}
|
||||
|
||||
|
||||
bool kernel_load_room(int minPalEntry, int maxPalEntry, SceneDef *rdef, GrBuff **scr_orig_data, GrBuff **scr_orig) {
|
||||
if (!scr_orig_data || !scr_orig) {
|
||||
error_show(FL, 'BUF!', "load_picture_and_codes");
|
||||
}
|
||||
|
||||
term_message("Reading scene %d", _G(game).new_room);
|
||||
|
||||
if (_G(game).previous_room != KERNEL_RESTORING_GAME) {
|
||||
_G(game).previous_room = _G(game).room_id;
|
||||
}
|
||||
|
||||
// Read DEF file
|
||||
if (db_def_chk_read(_G(game).new_room, rdef) != -1) {
|
||||
error_show(FL, 'DF:(', "trying to find %d.CHK", (uint32)_G(game).new_room);
|
||||
}
|
||||
|
||||
set_walker_scaling(rdef);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Select background picture
|
||||
|
||||
_G(currBackgroundFN) = get_background_filename(rdef);
|
||||
|
||||
char *tempName = env_find(_G(currBackgroundFN));
|
||||
if (tempName) {
|
||||
// In normal rooms.db mode
|
||||
_G(currBackgroundFN) = f_extension_new(tempName, "TT");
|
||||
} else {
|
||||
// In concat hag mode
|
||||
_G(currBackgroundFN) = f_extension_new(_G(currBackgroundFN), "TT");
|
||||
}
|
||||
|
||||
SysFile *pic_file = new SysFile(_G(currBackgroundFN));
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Select attributes code file
|
||||
|
||||
_G(currCodeFN) = get_attribute_filename(rdef);
|
||||
|
||||
tempName = env_find(_G(currCodeFN));
|
||||
if (tempName) {
|
||||
// In normal rooms.db mode
|
||||
_G(currCodeFN) = f_extension_new(tempName, "COD");
|
||||
} else {
|
||||
// In concat hag mode
|
||||
_G(currCodeFN) = f_extension_new(_G(currCodeFN), "COD");
|
||||
}
|
||||
|
||||
SysFile *code_file = new SysFile(_G(currCodeFN));
|
||||
if (!code_file->exists()) {
|
||||
delete code_file;
|
||||
code_file = nullptr;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Load background picture
|
||||
|
||||
term_message("load background");
|
||||
RGB8 newPal[256];
|
||||
load_background(pic_file, scr_orig, newPal);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Load attributes code file
|
||||
|
||||
term_message("load codes");
|
||||
*scr_orig_data = load_codes(code_file);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Prepare buffers for display
|
||||
|
||||
recreate_animation_draw_screen(scr_orig);
|
||||
troll_for_colors(newPal, minPalEntry, maxPalEntry);
|
||||
|
||||
gr_pal_reset_ega_colors(&_G(master_palette)[0]);
|
||||
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
pic_file->close();
|
||||
delete pic_file;
|
||||
|
||||
if (code_file) {
|
||||
code_file->close();
|
||||
delete code_file;
|
||||
}
|
||||
|
||||
if (*scr_orig_data) {
|
||||
Buffer *scr_orig_data_buffer = (**scr_orig_data).get_buffer();
|
||||
RestoreEdgeList(scr_orig_data_buffer);
|
||||
(**scr_orig_data).release();
|
||||
} else
|
||||
RestoreEdgeList(nullptr);
|
||||
|
||||
_G(game).room_id = _G(game).new_room;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kernel_load_variant(const char *variant) {
|
||||
SceneDef &sceneDef = _G(currentSceneDef);
|
||||
GrBuff *codeBuff = _G(screenCodeBuff);
|
||||
Common::String filename;
|
||||
|
||||
if (!codeBuff)
|
||||
return false;
|
||||
|
||||
if (_G(kernel).hag_mode) {
|
||||
filename = f_extension_new(variant, "COD");
|
||||
} else {
|
||||
char *base = env_find(sceneDef.art_base);
|
||||
char *dotPos = nullptr;
|
||||
if (base)
|
||||
dotPos = strchr(base, '.');
|
||||
|
||||
if (!dotPos)
|
||||
return false;
|
||||
|
||||
filename = f_extension_new(base, "COD");
|
||||
|
||||
if (!f_info_exists(Common::Path(filename)))
|
||||
return false;
|
||||
}
|
||||
|
||||
SysFile code_file(filename);
|
||||
if (!code_file.exists())
|
||||
error("Failed to load variant %s", filename.c_str());
|
||||
|
||||
// TODO: This is just copied from the room loading code,
|
||||
// rather than disassembling the reset of the original method.
|
||||
// Need to determine whether this is correct or not,
|
||||
// then modified to clean screenCodeBuff and the edges.
|
||||
|
||||
GrBuff *scr_orig_data = load_codes(&code_file);
|
||||
|
||||
code_file.close();
|
||||
|
||||
if (scr_orig_data) {
|
||||
_G(screenCodeBuff)->release();
|
||||
free _G(screenCodeBuff);
|
||||
RestoreEdgeList(nullptr);
|
||||
|
||||
Buffer *scr_orig_data_buffer = scr_orig_data->get_buffer();
|
||||
RestoreEdgeList(scr_orig_data_buffer);
|
||||
|
||||
_G(screenCodeBuff) = scr_orig_data;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GrBuff *load_codes(SysFile *code_file) {
|
||||
// No this is not a cheat to allow bugs to live,
|
||||
// if there is no code file, then we don't need a code buffer, either.
|
||||
// it's perfectly acceptable, so there, NYAH!
|
||||
if (!code_file)
|
||||
return nullptr;
|
||||
|
||||
const int16 x_size = code_file->readSint16LE();
|
||||
const int16 y_size = code_file->readSint16LE();
|
||||
|
||||
GrBuff *temp = new GrBuff(x_size, y_size);
|
||||
Buffer *myBuff = temp->get_buffer();
|
||||
byte *bufferHandle = myBuff->data;
|
||||
|
||||
for (int i = 0; i < y_size; i++) {
|
||||
code_file->read(bufferHandle, x_size);
|
||||
bufferHandle += myBuff->stride;
|
||||
}
|
||||
|
||||
// Let the memory float
|
||||
temp->release();
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool load_background(SysFile *pic_file, GrBuff **loadBuffer, RGB8 *palette) {
|
||||
int32 num_x_tiles, num_y_tiles, tile_x, tile_y, file_x, file_y;
|
||||
int32 count = 0;
|
||||
|
||||
tt_read_header(pic_file, &file_x, &file_y,
|
||||
&num_x_tiles, &num_y_tiles, &tile_x, &tile_y, palette);
|
||||
|
||||
*loadBuffer = new GrBuff(file_x, file_y);
|
||||
|
||||
if (!*loadBuffer)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
Buffer *theBuff = (**loadBuffer).get_buffer();
|
||||
|
||||
for (int i = 0; i < num_y_tiles; i++) {
|
||||
for (int j = 0; j < num_x_tiles; j++) {
|
||||
Buffer *out = tt_read(pic_file, count, tile_x, tile_y);
|
||||
count++;
|
||||
|
||||
if (out && (out->data)) {
|
||||
const int32 x_end = imath_min(file_x, (1 + j) * tile_x);
|
||||
const int32 y_end = imath_min(file_y, (1 + i) * tile_y);
|
||||
gr_buffer_rect_copy_2(out, theBuff, 0, 0, j * tile_x, i * tile_y,
|
||||
x_end - (j * tile_x), y_end - (i * tile_y));
|
||||
mem_free(out->data);
|
||||
}
|
||||
|
||||
if (out)
|
||||
mem_free(out);
|
||||
}
|
||||
}
|
||||
|
||||
(**loadBuffer).release();
|
||||
return true;
|
||||
}
|
||||
|
||||
static Common::SeekableReadStream *openForLoading(int slot) {
|
||||
const Common::String slotName = g_engine->getSaveStateName(slot);
|
||||
return g_system->getSavefileManager()->openForLoading(slotName);
|
||||
}
|
||||
|
||||
bool kernel_save_game_exists(int32 slot) {
|
||||
Common::SeekableReadStream *save = openForLoading(slot);
|
||||
const bool result = save != nullptr;
|
||||
delete save;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int kernel_save_game(int slot, const char *desc, int32 sizeofDesc, M4sprite *thumbNail, int32 sizeofThumbData) {
|
||||
return g_engine->saveGameState(slot, desc, slot == 0).getCode() == Common::kNoError ? 0 : 1;
|
||||
}
|
||||
|
||||
bool kernel_load_game(int slot) {
|
||||
return g_engine->loadGameStateDoIt(slot).getCode() == Common::kNoError;
|
||||
}
|
||||
|
||||
int32 extract_room_num(const Common::String &name) {
|
||||
if ((name[0] == 'C' || name[0] == 'c') &&
|
||||
(name[1] == 'O' || name[1] == 'o') &&
|
||||
(name[2] == 'M' || name[2] == 'm'))
|
||||
return _G(global_sound_room);
|
||||
|
||||
if (Common::isDigit(name[0]) && Common::isDigit(name[1]) && Common::isDigit(name[2])) {
|
||||
return ((int32)(name[0] - '0')) * 100 + ((int32)(name[1] - '0')) * 10 + ((int32)(name[2] - '0'));
|
||||
}
|
||||
|
||||
return _G(game).room_id;
|
||||
}
|
||||
|
||||
static Common::String get_background_filename(const SceneDef *rdef) {
|
||||
if (_G(art_base_override) != nullptr) {
|
||||
return _G(art_base_override);
|
||||
}
|
||||
|
||||
return rdef->art_base;
|
||||
}
|
||||
|
||||
static Common::String get_attribute_filename(const SceneDef *rdef) {
|
||||
if (_G(art_base_override) == nullptr || !_G(use_alternate_attribute_file)) {
|
||||
return rdef->art_base;
|
||||
}
|
||||
|
||||
return _G(art_base_override);
|
||||
}
|
||||
|
||||
static void recreate_animation_draw_screen(GrBuff **loadBuf) {
|
||||
// Remove previous animation draw screen
|
||||
if (_G(gameDrawBuff)) {
|
||||
gui_buffer_deregister((Buffer *)_G(gameDrawBuff));
|
||||
delete _G(gameDrawBuff);
|
||||
_G(gameDrawBuff) = nullptr;
|
||||
_G(game_buff_ptr) = nullptr;
|
||||
}
|
||||
_G(gameDrawBuff) = new GrBuff((**loadBuf).w, (**loadBuf).h);
|
||||
gui_GrBuff_register(_G(kernel).letter_box_x, _G(kernel).letter_box_y, _G(gameDrawBuff), SF_BACKGRND | SF_GET_ALL | SF_BLOCK_NONE, nullptr);
|
||||
gui_buffer_activate((Buffer *)_G(gameDrawBuff));
|
||||
vmng_screen_to_back((void *)_G(gameDrawBuff));
|
||||
_G(game_buff_ptr) = vmng_screen_find(_G(gameDrawBuff), nullptr);
|
||||
|
||||
Buffer *theBuff = (**loadBuf).get_buffer();
|
||||
Buffer *game_buff = (*_G(gameDrawBuff)).get_buffer();
|
||||
gr_buffer_rect_copy_2(theBuff, game_buff, 0, 0, 0, 0,
|
||||
imath_min((**loadBuf).w, game_buff->w), imath_min((**loadBuf).h, game_buff->h));
|
||||
|
||||
(**loadBuf).release();
|
||||
(*_G(gameDrawBuff)).release();
|
||||
}
|
||||
|
||||
static void troll_for_colors(RGB8 *newPal, uint8 minPalEntry, uint8 maxPalEntry) {
|
||||
bool gotOne = false;
|
||||
for (int16 pal_iter = minPalEntry; pal_iter <= maxPalEntry; pal_iter++) { // accept any colors that came with the background
|
||||
if (gotOne || (newPal[pal_iter].r | newPal[pal_iter].g | newPal[pal_iter].b)) {
|
||||
gotOne = true;
|
||||
// colors are 6 bit...
|
||||
_G(master_palette)[pal_iter].r = newPal[pal_iter].r << 2;
|
||||
_G(master_palette)[pal_iter].g = newPal[pal_iter].g << 2;
|
||||
_G(master_palette)[pal_iter].b = newPal[pal_iter].b << 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (gotOne) {
|
||||
gr_pal_interface(&_G(master_palette)[0]); // enforce interface colors
|
||||
}
|
||||
}
|
||||
|
||||
Common::String expand_name_2_RAW(const Common::String &name, int32 room_num) {
|
||||
Common::String tempName = f_extension_new(name, "RAW");
|
||||
|
||||
if (!_G(kernel).hag_mode) {
|
||||
if (room_num == -1)
|
||||
room_num = extract_room_num(name);
|
||||
|
||||
return Common::String::format("%d\\%s", room_num, tempName.c_str());
|
||||
}
|
||||
|
||||
return tempName;
|
||||
}
|
||||
|
||||
Common::String expand_name_2_HMP(const Common::String &name, int32 room_num) {
|
||||
return f_extension_new(name, "HMP");
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
62
engines/m4/adv_r/adv_file.h
Normal file
62
engines/m4/adv_r/adv_file.h
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_FILE_H
|
||||
#define M4_ADV_R_ADV_FILE_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/fileio/sys_file.h"
|
||||
#include "m4/graphics/gr_buff.h"
|
||||
#include "m4/gui/gui.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
extern M4sprite *kernel_CreateThumbnail(int32 *spriteSize);
|
||||
extern bool kernel_CreateSSFromGrBuff(GrBuff *myBuff, RGB8 *myPalette, bool completePal, const char *ssName);
|
||||
|
||||
extern bool kernel_load_room(int minPalEntry, int maxPalEntry, SceneDef *rdef, GrBuff **scr_orig_data, GrBuff **scr_orig);
|
||||
extern void kernel_unload_room(SceneDef *rdef, GrBuff **code_data, GrBuff **loadBuffer);
|
||||
|
||||
extern int kernel_save_game(int slot, const char *desc, int32 sizeofDesc, M4sprite *thumbNail, int32 sizeofThumbData);
|
||||
extern bool kernel_load_game(int slot);
|
||||
extern bool kernel_save_game_exists(int32 slot);
|
||||
extern int32 extract_room_num(const Common::String &name);
|
||||
|
||||
extern bool kernel_load_variant(const char *variant);
|
||||
extern GrBuff *load_codes(SysFile *code_file);
|
||||
extern bool load_background(SysFile *pic_file, GrBuff **loadBuffer, RGB8 *palette);
|
||||
|
||||
extern bool load_picture_and_codes(SysFile *pic_file, SysFile *code_file, GrBuff **loadBuf, GrBuff **code_data, uint8 minPalEntry, uint8 maxPalEntry);
|
||||
|
||||
extern bool kernel_load_code_variant(SceneDef *rdef, char *variant, GrBuff **codeData);
|
||||
|
||||
extern void kernel_current_background_name(char *result);
|
||||
extern void kernel_current_codes_name(char *result);
|
||||
extern void screen_capture(RGB8 *masterPalette);
|
||||
extern Common::String expand_name_2_RAW(const Common::String &name, int32 room_num);
|
||||
extern Common::String expand_name_2_HMP(const Common::String &name, int32 room_num);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
53
engines/m4/adv_r/adv_game.h
Normal file
53
engines/m4/adv_r/adv_game.h
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_GAME_H
|
||||
#define M4_ADV_R_ADV_GAME_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct GameControl {
|
||||
int16 room_id = 0;
|
||||
int16 new_room = 0;
|
||||
int16 previous_section = 0;
|
||||
int16 section_id = 0;
|
||||
int16 new_section = 0;
|
||||
int16 previous_room = 0;
|
||||
|
||||
bool camera_pan_instant = false;
|
||||
|
||||
/**
|
||||
* Shortcut for setting new room and section
|
||||
*/
|
||||
void setRoom(int newRoom) {
|
||||
new_room = newRoom;
|
||||
new_section = newRoom / 100;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
345
engines/m4/adv_r/adv_hotspot.cpp
Normal file
345
engines/m4/adv_r/adv_hotspot.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
/* 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 "m4/adv_r/adv_hotspot.h"
|
||||
#include "m4/core/cstring.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/term.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/mem/mem.h"
|
||||
#include "m4/mem/memman.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define STR_HOT_SPOT "hot spot"
|
||||
#define _MAXPOSINT 0x7fffffff
|
||||
|
||||
void HotSpotRec::clear() {
|
||||
ul_x = ul_y = lr_x = lr_y = 0;
|
||||
feet_x = feet_y = 0;
|
||||
facing = 0;
|
||||
active = false;
|
||||
cursor_number = kArrowCursor;
|
||||
syntax = 0;
|
||||
vocabID = verbID = 0;
|
||||
vocab = verb = prep = nullptr;
|
||||
sprite = nullptr;
|
||||
hash = 0;
|
||||
next = nullptr;
|
||||
}
|
||||
|
||||
void hotspot_new_sprite(HotSpotRec *h, const char *sprite) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
if (h->sprite)
|
||||
mem_free(h->sprite);
|
||||
|
||||
h->sprite = mem_strdup(sprite);
|
||||
}
|
||||
|
||||
void hotspot_newVerb(HotSpotRec *h, const char *verb) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
if (h->verb)
|
||||
mem_free(h->verb);
|
||||
|
||||
h->verb = mem_strdup(verb);
|
||||
}
|
||||
|
||||
void hotspot_newVocab(HotSpotRec *h, const char *vocab) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
if (h->vocab)
|
||||
mem_free(h->vocab);
|
||||
|
||||
h->vocab = mem_strdup(vocab);
|
||||
}
|
||||
|
||||
void hotspot_newPrep(HotSpotRec *h, const char *prep) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
if (h->prep)
|
||||
mem_free(h->prep);
|
||||
|
||||
h->prep = mem_strdup(prep);
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_new(int x1, int y1, int x2, int y2) {
|
||||
HotSpotRec *newSpot = (HotSpotRec *)mem_alloc(sizeof(HotSpotRec), STR_HOT_SPOT);
|
||||
if (!newSpot)
|
||||
return newSpot;
|
||||
|
||||
newSpot->ul_x = x1;
|
||||
newSpot->ul_y = y1;
|
||||
newSpot->lr_x = x2;
|
||||
newSpot->lr_y = y2;
|
||||
newSpot->sprite = nullptr;
|
||||
newSpot->vocab = nullptr;
|
||||
newSpot->verb = nullptr;
|
||||
newSpot->prep = nullptr;
|
||||
newSpot->syntax = 0; // Unused field
|
||||
newSpot->cursor_number = kArrowCursor;
|
||||
newSpot->facing = 5;
|
||||
newSpot->feet_x = 32767;
|
||||
newSpot->feet_y = 32767;
|
||||
newSpot->next = nullptr;
|
||||
newSpot->active = true;
|
||||
return newSpot;
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_duplicate(HotSpotRec *dupMe) {
|
||||
HotSpotRec *newSpot = (HotSpotRec *)mem_alloc(sizeof(HotSpotRec), STR_HOT_SPOT);
|
||||
if (!newSpot)
|
||||
return newSpot;
|
||||
|
||||
newSpot->ul_x = dupMe->ul_x;
|
||||
newSpot->ul_y = dupMe->ul_y;
|
||||
newSpot->lr_x = dupMe->lr_x;
|
||||
newSpot->lr_y = dupMe->lr_y;
|
||||
newSpot->sprite = mem_strdup(dupMe->sprite);
|
||||
newSpot->vocab = mem_strdup(dupMe->vocab);
|
||||
newSpot->verb = mem_strdup(dupMe->verb);
|
||||
newSpot->prep = mem_strdup(dupMe->prep);
|
||||
newSpot->syntax = dupMe->syntax;
|
||||
newSpot->cursor_number = dupMe->cursor_number;
|
||||
newSpot->facing = dupMe->facing;
|
||||
newSpot->feet_x = dupMe->feet_x;
|
||||
newSpot->feet_y = dupMe->feet_y;
|
||||
newSpot->next = nullptr;
|
||||
return newSpot;
|
||||
}
|
||||
|
||||
static int32 hotspot_area(HotSpotRec *h) {
|
||||
if (!h)
|
||||
return _MAXPOSINT;
|
||||
|
||||
return (h->lr_x - h->ul_x) * (h->lr_y - h->ul_y);
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_add(HotSpotRec *head, HotSpotRec *h, bool new_head) {
|
||||
const int hArea = hotspot_area(h);
|
||||
|
||||
// Is head nullptr?
|
||||
if (!head)
|
||||
return h;
|
||||
|
||||
// Is the incoming spot the new head?
|
||||
if (new_head || hArea < hotspot_area(head)) {
|
||||
h->next = head;
|
||||
return h;
|
||||
}
|
||||
|
||||
HotSpotRec *i = head;
|
||||
while (i) {
|
||||
const int iArea = hotspot_area(i->next);
|
||||
if (hArea < iArea) {
|
||||
h->next = i->next;
|
||||
i->next = h;
|
||||
i = nullptr;
|
||||
} else
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_add_dynamic(const char *verb, const char *noun,
|
||||
int32 x1, int32 y1, int32 x2, int32 y2, int32 cursor,
|
||||
bool new_head, int32 walkto_x, int32 walkto_y, int32 facing) {
|
||||
int32 status;
|
||||
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
y2 = MIN(y2, sc->y2);
|
||||
|
||||
HotSpotRec *hotspot = hotspot_new(x1, y1, x2, y2);
|
||||
if (!hotspot)
|
||||
error("hotspot_new failed");
|
||||
|
||||
hotspot_newVocab(hotspot, noun);
|
||||
hotspot_newVerb(hotspot, verb);
|
||||
hotspot->feet_x = walkto_x;
|
||||
hotspot->feet_y = walkto_y;
|
||||
hotspot->cursor_number = cursor;
|
||||
hotspot->facing = facing;
|
||||
|
||||
_G(currentSceneDef).hotspots = hotspot_add(_G(currentSceneDef).hotspots,
|
||||
hotspot, new_head);
|
||||
|
||||
return hotspot;
|
||||
}
|
||||
|
||||
void kill_hotspot_node(HotSpotRec *h) {
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
if (h->vocab)
|
||||
mem_free(h->vocab);
|
||||
if (h->verb)
|
||||
mem_free(h->verb);
|
||||
if (h->sprite)
|
||||
mem_free(h->sprite);
|
||||
if (h->prep)
|
||||
mem_free(h->prep);
|
||||
mem_free(h);
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_delete_record(HotSpotRec *head, HotSpotRec *h) {
|
||||
HotSpotRec *i;
|
||||
|
||||
if (!h || !head)
|
||||
return head;
|
||||
|
||||
// Are we deleting the head node?
|
||||
if (head == h) {
|
||||
head = h->next;
|
||||
kill_hotspot_node(h);
|
||||
return head; // This will of course be nullptr if the head was the only thing in the list.
|
||||
}
|
||||
|
||||
// Find parent of current selection
|
||||
for (i = head; i; i = i->next)
|
||||
if (i->next == h)
|
||||
break;
|
||||
|
||||
if (i)
|
||||
i->next = h->next;
|
||||
|
||||
kill_hotspot_node(h);
|
||||
return head;
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_unlink(HotSpotRec *head, HotSpotRec *h) {
|
||||
HotSpotRec *i;
|
||||
|
||||
if (!h || !head)
|
||||
return head;
|
||||
|
||||
// Are we deleting the head node?
|
||||
if (head == h) {
|
||||
head = h->next;
|
||||
return (head); // This will of course be nullptr if the head was the only thing in the list.
|
||||
}
|
||||
|
||||
// Find parent of current selection
|
||||
for (i = head; i; i = i->next)
|
||||
if (i->next == h)
|
||||
break;
|
||||
|
||||
if (i)
|
||||
i->next = h->next;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
void hotspot_delete_all(HotSpotRec *head) {
|
||||
HotSpotRec *next;
|
||||
|
||||
for (HotSpotRec *i = head; i; i = next) {
|
||||
next = i->next;
|
||||
kill_hotspot_node(i);
|
||||
}
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_which(HotSpotRec *head, int x, int y) {
|
||||
for (HotSpotRec *i = head; i; i = i->next)
|
||||
if ((x >= i->ul_x) && (x <= i->lr_x) && (y >= i->ul_y) && (y <= i->lr_y) && i->active)
|
||||
return i;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HotSpotRec *hotspot_which(int x, int y) {
|
||||
return hotspot_which(_G(currentSceneDef).hotspots, x, y);
|
||||
}
|
||||
|
||||
void hotspot_set_active(HotSpotRec *head, const char *name, bool active_or_not) {
|
||||
char name_str[MAX_FILENAME_SIZE];
|
||||
bool hotspot_found = false;
|
||||
|
||||
cstrncpy(name_str, name, MAX_FILENAME_SIZE);
|
||||
cstrupr(name_str);
|
||||
|
||||
for (HotSpotRec *i = head; i; i = i->next) {
|
||||
if (i->vocab && !scumm_strnicmp(i->vocab, name_str, MAX_FILENAME_SIZE)) {
|
||||
i->active = active_or_not;
|
||||
hotspot_found = true;
|
||||
}
|
||||
}
|
||||
if (hotspot_found != true)
|
||||
term_message("hotspot '%s' not found!", name_str);
|
||||
}
|
||||
|
||||
void hotspot_set_active(const char *name, bool active_or_not) {
|
||||
hotspot_set_active(_G(currentSceneDef).hotspots, name, active_or_not);
|
||||
}
|
||||
|
||||
void hotspot_set_active_xy(HotSpotRec *head, const char *name, int32 x, int32 y, bool active_or_not) {
|
||||
char name_str[MAX_FILENAME_SIZE];
|
||||
|
||||
cstrncpy(name_str, name, MAX_FILENAME_SIZE);
|
||||
|
||||
cstrupr(name_str);
|
||||
|
||||
for (HotSpotRec *i = head; i; i = i->next)
|
||||
if (!scumm_strnicmp(i->vocab, name_str, MAX_FILENAME_SIZE))
|
||||
if ((x >= i->ul_x) && (x <= i->lr_x) && (y >= i->ul_y) && (y <= i->lr_y))
|
||||
i->active = active_or_not;
|
||||
}
|
||||
|
||||
void hotspot_set_active_xy(const char *name, int32 x, int32 y, bool active_or_not) {
|
||||
hotspot_set_active_xy(_G(currentSceneDef).hotspots, name, x, y, active_or_not);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
static HotSpotRec *saved_hotspots = nullptr;
|
||||
|
||||
void hotspot_hide_all() {
|
||||
if (saved_hotspots)
|
||||
error_show(FL, 'HNST');
|
||||
|
||||
saved_hotspots = _G(currentSceneDef).hotspots;
|
||||
_G(currentSceneDef).hotspots = nullptr;
|
||||
}
|
||||
|
||||
void hotspot_restore_all() {
|
||||
if (!saved_hotspots) {
|
||||
error_show(FL, 'HNON');
|
||||
}
|
||||
|
||||
if (_G(currentSceneDef).hotspots)
|
||||
hotspot_delete_all(_G(currentSceneDef).hotspots);
|
||||
|
||||
_G(currentSceneDef).hotspots = saved_hotspots;
|
||||
saved_hotspots = nullptr;
|
||||
}
|
||||
|
||||
void hotspot_unhide_and_dump() {
|
||||
if (saved_hotspots) {
|
||||
hotspot_restore_all();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
110
engines/m4/adv_r/adv_hotspot.h
Normal file
110
engines/m4/adv_r/adv_hotspot.h
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_HOTSPOT_H
|
||||
#define M4_ADV_R_ADV_HOTSPOT_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct HotSpotRec {
|
||||
int32 ul_x, ul_y, lr_x, lr_y; // Hotspot screen coordinates
|
||||
int32 feet_x, feet_y; // Walk-to target for player
|
||||
int8 facing; // Direction player should face
|
||||
bool active; // Flag if hotspot is active
|
||||
byte cursor_number; // Mouse cursor number
|
||||
byte syntax; // Word syntax
|
||||
int32 vocabID, verbID; // ids of name and verb
|
||||
char *vocab; // Vocabulary name of hotspot
|
||||
char *verb; // Vocabulary default verb name
|
||||
char *prep; // Preposition
|
||||
char *sprite; // Sprite name
|
||||
int16 hash; // woodscript sprite hash (runtime only)
|
||||
HotSpotRec *next;
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
HotSpotRec *hotspot_add_dynamic(
|
||||
const char *verb, const char *noun,
|
||||
int32 x1, int32 y1, int32 x2, int32 y2,
|
||||
int32 cursor,
|
||||
bool new_head = true,
|
||||
int32 walkto_x = 32767, int32 walkto_y = 32767, int32 facing = 0);
|
||||
|
||||
/**
|
||||
* Creates a new hot spot, doesn't add it to any list. Takes coords, sets everything
|
||||
* else to default values.
|
||||
* @returns The new hotspot
|
||||
*/
|
||||
HotSpotRec *hotspot_new(int x1, int y1, int x2, int y2);
|
||||
|
||||
/**
|
||||
* Given a list and a hotspot to insert in that list, inserts the spot ordered by size,
|
||||
* unless new_head is true, in which case the hotspot is the head regardless of size.
|
||||
* @returns The new head of the list.
|
||||
*/
|
||||
HotSpotRec *hotspot_add(HotSpotRec *head, HotSpotRec *h, bool new_head);
|
||||
HotSpotRec *hotspot_duplicate(HotSpotRec *dupMe);
|
||||
|
||||
/**
|
||||
* Takes the head of a list of hot spots, and a pointer to a spot to delete.
|
||||
* @returns The new head of the list.
|
||||
*/
|
||||
HotSpotRec *hotspot_delete_record(HotSpotRec *head, HotSpotRec *h);
|
||||
|
||||
/**
|
||||
* Takes the head of a list of hot spots, and a pointer to a spot to unlink.
|
||||
* @returns The new head of the list.
|
||||
*/
|
||||
HotSpotRec *hotspot_unlink(HotSpotRec *head, HotSpotRec *h);
|
||||
void hotspot_delete_all(HotSpotRec *head);
|
||||
|
||||
void hotspot_set_active(HotSpotRec *head, const char *name, bool active_or_not);
|
||||
void hotspot_set_active(const char *name, bool active_or_not);
|
||||
void hotspot_set_active_xy(HotSpotRec *head, const char *name, int32 x, int32 y, bool active_or_not);
|
||||
void hotspot_set_active_xy(const char *name, int32 x, int32 y, bool active_or_not);
|
||||
#define kernel_flip_hotspot(aa,bb) (hotspot_set_active(currentSceneDef.hotspots,aa,bb))
|
||||
#define kernel_flip_hotspot_xy(aa,bb,xx,yy) (hotspot_set_active_xy(currentSceneDef.hotspots,aa,xx,yy,bb))
|
||||
#define kernel_flip_hotspot_loc(aa,bb,xx,yy) (hotspot_set_active_xy(currentSceneDef.hotspots,aa,xx,yy,bb))
|
||||
|
||||
void hotspot_new_sprite(HotSpotRec *h, const char *verb);
|
||||
void hotspot_newVerb(HotSpotRec *h, const char *verb);
|
||||
void hotspot_newVocab(HotSpotRec *h, const char *vocab);
|
||||
void hotspot_newPrep(HotSpotRec *h, const char *prep);
|
||||
|
||||
/**
|
||||
* Given a list of spots to check, and an x,y coordinate pair,
|
||||
* @returns A pointer to the hotspot we're inside, or nullptr if there's nothing.
|
||||
*/
|
||||
HotSpotRec *hotspot_which(HotSpotRec *head, int x, int y);
|
||||
HotSpotRec *hotspot_which(int x, int y);
|
||||
void kill_hotspot_node(HotSpotRec *h);
|
||||
|
||||
void hotspot_restore_all();
|
||||
void hotspot_hide_all();
|
||||
void hotspot_unhide_and_dump();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
87
engines/m4/adv_r/adv_interface.cpp
Normal file
87
engines/m4/adv_r/adv_interface.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 "m4/adv_r/adv_interface.h"
|
||||
#include "m4/gui/gui_buffer.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
bool Interface::init(int arrow, int wait, int look, int grab, int use) {
|
||||
_arrow = arrow;
|
||||
_wait = wait;
|
||||
_look = look;
|
||||
_grab = grab;
|
||||
_use = use;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Interface::showWaitCursor() {
|
||||
mouse_set_sprite(_wait);
|
||||
}
|
||||
|
||||
void Interface::show() {
|
||||
if (!_shown) {
|
||||
gui_GrBuff_register(_x1, _y1, _G(gameInterfaceBuff),
|
||||
SF_DRIFTER | SF_GET_KEY | SF_GET_MOUSE | SF_IMMOVABLE,
|
||||
intr_EventHandler);
|
||||
_shown = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::hide() {
|
||||
if (_shown) {
|
||||
vmng_screen_hide(_G(gameInterfaceBuff));
|
||||
_visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_hide() {
|
||||
_GI().hide();
|
||||
}
|
||||
|
||||
void interface_show() {
|
||||
_GI().show();
|
||||
}
|
||||
|
||||
void track_hotspots_refresh() {
|
||||
_GI().track_hotspots_refresh();
|
||||
}
|
||||
|
||||
bool intr_EventHandler(void *bufferPtr, int32 eventType, int32 event, int32 x, int32 y, bool *z) {
|
||||
return _GI().eventHandler(bufferPtr, eventType, event, x, y, z);
|
||||
}
|
||||
|
||||
void intr_cancel_sentence() {
|
||||
_GI().cancel_sentence();
|
||||
}
|
||||
|
||||
void intr_freshen_sentence() {
|
||||
_GI().freshen_sentence();
|
||||
}
|
||||
|
||||
void intr_freshen_sentence(int cursor) {
|
||||
mouse_set_sprite(cursor);
|
||||
_GI().freshen_sentence();
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
88
engines/m4/adv_r/adv_interface.h
Normal file
88
engines/m4/adv_r/adv_interface.h
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_INTERFACE_H
|
||||
#define M4_ADV_R_ADV_INTERFACE_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define INTERFACE_SPRITES 22
|
||||
|
||||
class Interface {
|
||||
public:
|
||||
bool _shown = false;
|
||||
bool _visible = false;
|
||||
int _x1 = 0, _y1 = 0, _x2 = 0, _y2 = 0;
|
||||
|
||||
int _arrow = 0;
|
||||
int _wait = 0;
|
||||
int _look = 0;
|
||||
int _grab = 0;
|
||||
int _use = 0;
|
||||
|
||||
public:
|
||||
virtual ~Interface() {
|
||||
}
|
||||
|
||||
virtual bool init(int arrow, int wait, int look, int grab, int use);
|
||||
|
||||
virtual void cancel_sentence() = 0;
|
||||
|
||||
virtual void freshen_sentence() = 0;
|
||||
|
||||
virtual bool set_interface_palette(RGB8 *myPalette) = 0;
|
||||
|
||||
virtual bool eventHandler(void *bufferPtr, int32 eventType, int32 event, int32 x, int32 y, bool *z) = 0;
|
||||
|
||||
virtual void track_hotspots_refresh() = 0;
|
||||
|
||||
/**
|
||||
* Show the interface
|
||||
*/
|
||||
virtual void show();
|
||||
|
||||
/**
|
||||
* Hide the interface
|
||||
*/
|
||||
void hide();
|
||||
|
||||
/**
|
||||
* Show the wait cursor
|
||||
*/
|
||||
void showWaitCursor();
|
||||
};
|
||||
|
||||
void interface_hide();
|
||||
void interface_show();
|
||||
|
||||
void track_hotspots_refresh();
|
||||
bool intr_EventHandler(void *bufferPtr, int32 eventType, int32 event, int32 x, int32 y, bool *z);
|
||||
|
||||
void intr_cancel_sentence();
|
||||
void intr_freshen_sentence();
|
||||
void intr_freshen_sentence(int cursor);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
248
engines/m4/adv_r/adv_inv.cpp
Normal file
248
engines/m4/adv_r/adv_inv.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/* 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/str.h"
|
||||
#include "m4/adv_r/adv_inv.h"
|
||||
#include "m4/core/cstring.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/mem/mem.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define MAX_NAME_LENGTH 40
|
||||
|
||||
static char *inv_get_name(const Common::String &itemName);
|
||||
|
||||
InventoryBase::~InventoryBase() {
|
||||
for (int i = 0; i < _tail; i++) {
|
||||
mem_free(_objects[i]->name);
|
||||
mem_free(_objects[i]->verbs);
|
||||
|
||||
mem_free_to_stash((void *)_objects[i], _G(inv_obj_mem_type));
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryBase::syncGame(Common::Serializer &s) {
|
||||
char invName[MAX_NAME_LENGTH];
|
||||
|
||||
uint32 inv_size = _tail * (MAX_NAME_LENGTH + sizeof(uint32));
|
||||
s.syncAsUint32LE(inv_size);
|
||||
if (s.isLoading()) {
|
||||
assert((inv_size % (MAX_NAME_LENGTH + sizeof(uint32))) == 0);
|
||||
_tail = inv_size / (MAX_NAME_LENGTH + sizeof(uint32));
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < _tail; ++i) {
|
||||
char *objName = _G(inventory)->_objects[i]->name;
|
||||
uint32 scene = _G(inventory)->_objects[i]->scene;
|
||||
|
||||
if (s.isLoading()) {
|
||||
s.syncBytes((byte *)invName, MAX_NAME_LENGTH);
|
||||
char *item = inv_get_name(invName);
|
||||
assert(item);
|
||||
|
||||
s.syncAsUint32LE(scene);
|
||||
inv_put_thing_in(item, scene);
|
||||
|
||||
} else {
|
||||
Common::strcpy_s(invName, MAX_NAME_LENGTH, objName);
|
||||
s.syncBytes((byte *)invName, MAX_NAME_LENGTH);
|
||||
s.syncAsUint32LE(scene);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool inv_init(int32 num_objects) {
|
||||
term_message("Fluffing up the backpack", nullptr);
|
||||
_G(inventory)->_objects.resize(num_objects);
|
||||
|
||||
if (!mem_register_stash_type(&_G(inv_obj_mem_type), sizeof(InvObj), num_objects, "obj"))
|
||||
error_show(FL, 'OOM!', "fail to mem_register_stash_type for inv_obj");
|
||||
|
||||
for (int i = 0; i < num_objects; i++) {
|
||||
_G(inventory)->_objects[i] = (InvObj *)mem_get_from_stash(_G(inv_obj_mem_type), "obj");
|
||||
if (!_G(inventory)->_objects[i])
|
||||
error_show(FL, 'OOM!', "%d bytes", (int32)sizeof(InvObj));
|
||||
}
|
||||
|
||||
_G(inventory)->_tail = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool inv_register_thing(const Common::String &itemName, const Common::String &itemVerbs,
|
||||
int32 scene, int32 cel, int32 cursor) {
|
||||
char *s_name = mem_strdup(itemName.c_str());
|
||||
char *s_verbs = mem_strdup(itemVerbs.c_str());
|
||||
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->name = nullptr;
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->verbs = nullptr;
|
||||
|
||||
if (s_name) {
|
||||
cstrupr(s_name);
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->name = s_name;
|
||||
}
|
||||
|
||||
if (s_verbs) {
|
||||
cstrupr(s_verbs);
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->verbs = s_verbs;
|
||||
}
|
||||
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->scene = scene;
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->cel = cel;
|
||||
_G(inventory)->_objects[_G(inventory)->_tail]->cursor = cursor;
|
||||
|
||||
_G(inventory)->_tail++;
|
||||
|
||||
if (scene == BACKPACK) {
|
||||
_G(inventory)->add(s_name, s_verbs, cel, cursor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
int32 inv_where_is(const Common::String &itemName) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
return _G(inventory)->_objects[i]->scene;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN_OBJECT;
|
||||
}
|
||||
|
||||
bool inv_player_has(const Common::String &itemName) {
|
||||
return (inv_where_is(itemName) == BACKPACK);
|
||||
}
|
||||
|
||||
bool inv_put_thing_in(const Common::String &itemName, int32 scene) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
// Remove object from backpack?
|
||||
if (_G(inventory)->_objects[i]->scene == BACKPACK && scene != BACKPACK) {
|
||||
_G(inventory)->remove(name);
|
||||
}
|
||||
_G(inventory)->_objects[i]->scene = scene;
|
||||
|
||||
// Put object in backpack?
|
||||
if (scene == BACKPACK) {
|
||||
_G(inventory)->add(name, _G(inventory)->_objects[i]->verbs, _G(inventory)->_objects[i]->cel, _G(inventory)->_objects[i]->cursor);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 inv_get_cursor(const Common::String &itemName) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
return _G(inventory)->_objects[i]->cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN_OBJECT;
|
||||
}
|
||||
|
||||
int32 inv_get_cel(const Common::String &itemName) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
return _G(inventory)->_objects[i]->cel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UNKNOWN_OBJECT;
|
||||
}
|
||||
|
||||
const char *inv_get_verbs(const Common::String &itemName) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
return _G(inventory)->_objects[i]->verbs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is provided so that when restoring a game from a save file,
|
||||
// we store a pointer to the registered name, not to an unmanaged
|
||||
// memory pointer.
|
||||
|
||||
static char *inv_get_name(const Common::String &itemName) {
|
||||
Common::String name = itemName;
|
||||
name.toUppercase();
|
||||
|
||||
for (int i = 0; i < _G(inventory)->_tail; i++) {
|
||||
if (_G(inventory)->_objects[i]->name) {
|
||||
if (name.equals(_G(inventory)->_objects[i]->name)) {
|
||||
return _G(inventory)->_objects[i]->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void inv_give_to_player(const Common::String &itemName) {
|
||||
inv_put_thing_in(itemName, BACKPACK);
|
||||
}
|
||||
|
||||
void inv_move_object(const Common::String &itemName, int32 scene) {
|
||||
inv_put_thing_in(itemName, scene);
|
||||
}
|
||||
|
||||
bool inv_object_is_here(const Common::String &itemName) {
|
||||
return (inv_where_is(itemName) == _G(game).room_id);
|
||||
}
|
||||
|
||||
bool inv_object_in_scene(const Common::String &itemName, int32 scene) {
|
||||
return (inv_where_is(itemName) == scene);
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
82
engines/m4/adv_r/adv_inv.h
Normal file
82
engines/m4/adv_r/adv_inv.h
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_INV_H
|
||||
#define M4_ADV_R_ADV_INV_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct InvObj {
|
||||
char *name = nullptr;
|
||||
char *verbs = nullptr;
|
||||
int32 scene = 0, cel = 0, cursor = 0;
|
||||
};
|
||||
|
||||
struct InventoryBase {
|
||||
Common::Array<InvObj *> _objects;
|
||||
int32 _tail = 0;
|
||||
|
||||
InventoryBase() {}
|
||||
virtual ~InventoryBase();
|
||||
|
||||
void syncGame(Common::Serializer &s);
|
||||
|
||||
virtual void add(const Common::String &name, const Common::String &verb, int32 sprite, int32 cursor) = 0;
|
||||
virtual void set_scroll(int32 scroll) = 0;
|
||||
virtual void remove(const Common::String &name) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Init the system, preferably in game_systems_initialize
|
||||
*/
|
||||
bool inv_init(int32 num_objects);
|
||||
|
||||
/**
|
||||
* Register things during init of the game
|
||||
* @param itemName Name of the object as it should appear as a sentence is built
|
||||
* @param itemVerbs Verbs should have this format: verbs = "slit,peel,fricasee,examine"
|
||||
* There can be any number of verbs in the string.
|
||||
* @param scene The place for the thing to appear initially (BACKPACK is one place)
|
||||
* @param cel Index into the inventory sprite series for use when displaying inventory
|
||||
* @param cursor Cel index into the cursor sprite series when the player is "holding" a thing
|
||||
*/
|
||||
bool inv_register_thing(const Common::String &itemName, const Common::String &itemVerbs, int32 scene, int32 cel, int32 cursor);
|
||||
|
||||
int32 inv_where_is(const Common::String &itemName);
|
||||
bool inv_player_has(const Common::String &itemName);
|
||||
bool inv_put_thing_in(const Common::String &itemName, int32 scene);
|
||||
int32 inv_get_cursor(const Common::String &itemName);
|
||||
int32 inv_get_cel(const Common::String &itemName);
|
||||
const char *inv_get_verbs(const Common::String &itemName);
|
||||
void inv_give_to_player(const Common::String &itemName);
|
||||
void inv_move_object(const Common::String &itemName, int32 scene);
|
||||
bool inv_object_is_here(const Common::String &itemName);
|
||||
bool inv_object_in_scene(const Common::String &itemName, int32 scene);
|
||||
|
||||
void inv_sync_game(Common::Serializer &s);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
246
engines/m4/adv_r/adv_player.cpp
Normal file
246
engines/m4/adv_r/adv_player.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/* 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 "m4/adv_r/adv_player.h"
|
||||
#include "m4/adv_r/adv_walk.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/gui/gui_vmng_core.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void Player::syncGame(Common::Serializer &s) {
|
||||
s.skip(12);
|
||||
s.syncBytes((byte *)verb, MAX_PLYR_STRING_LEN);
|
||||
s.syncBytes((byte *)noun, MAX_PLYR_STRING_LEN);
|
||||
s.syncBytes((byte *)object, MAX_PLYR_STRING_LEN);
|
||||
s.syncBytes((byte *)prep, MAX_PLYR_STRING_LEN);
|
||||
s.skip(64);
|
||||
|
||||
s.syncAsSint16LE(walker_type);
|
||||
s.syncAsSint16LE(shadow_type);
|
||||
s.skip(4);
|
||||
s.syncAsByte(need_to_walk);
|
||||
s.syncAsByte(ready_to_walk);
|
||||
s.syncAsByte(waiting_for_walk);
|
||||
s.syncAsByte(comm_allowed);
|
||||
s.syncAsUint32LE(command_ready);
|
||||
s.syncAsByte(walker_visible);
|
||||
s.skip(1);
|
||||
s.syncAsByte(been_here_before);
|
||||
s.syncAsByte(walker_reload_palette);
|
||||
s.syncAsByte(disable_hyperwalk);
|
||||
s.syncAsByte(walker_loads_first);
|
||||
s.syncAsByte(walker_in_this_scene);
|
||||
s.syncAsSint32LE(walker_trigger);
|
||||
s.syncAsSint32LE(walk_x);
|
||||
s.syncAsSint32LE(walk_y);
|
||||
s.syncAsSint32LE(walk_facing);
|
||||
s.syncAsSint32LE(click_x);
|
||||
s.syncAsSint32LE(click_y);
|
||||
}
|
||||
|
||||
void Player::resetWalk() {
|
||||
need_to_walk = false;
|
||||
ready_to_walk = true;
|
||||
waiting_for_walk = false;
|
||||
}
|
||||
|
||||
void PlayerInfo::syncGame(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(x);
|
||||
s.syncAsSint32LE(y);
|
||||
s.syncAsSint32LE(facing);
|
||||
s.syncAsSint32LE(scale);
|
||||
s.syncAsSint32LE(depth);
|
||||
s.syncAsSint32LE(camera_x);
|
||||
s.syncAsSint32LE(camera_y);
|
||||
}
|
||||
|
||||
|
||||
bool player_said(const char *w0, const char *w1, const char *w2) {
|
||||
const char *ptrs[3] = { w0, w1, w2 };
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (ptrs[i])
|
||||
if ((scumm_strnicmp(_G(player).noun, ptrs[i], MAX_PLYR_STRING_LEN))
|
||||
&& (scumm_strnicmp(_G(player).object, ptrs[i], MAX_PLYR_STRING_LEN))
|
||||
&& (scumm_strnicmp(_G(player).verb, ptrs[i], MAX_PLYR_STRING_LEN)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool player_said_any(const char *w0, const char *w1, const char *w2,
|
||||
const char *w3, const char *w4, const char *w5, const char *w6,
|
||||
const char *w7, const char *w8, const char *w9) {
|
||||
const char *ptrs[10] = { w0, w1, w2, w3, w4, w5, w6, w7, w8, w9 };
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (ptrs[i]) {
|
||||
if (!scumm_strnicmp(_G(player).noun, ptrs[i], MAX_PLYR_STRING_LEN))
|
||||
return true;
|
||||
if (!scumm_strnicmp(_G(player).object, ptrs[i], MAX_PLYR_STRING_LEN))
|
||||
return true;
|
||||
if (!scumm_strnicmp(_G(player).verb, ptrs[i], MAX_PLYR_STRING_LEN))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void player_inform_walker_new_scale(int32 frontY, int32 backY, int32 frontS, int32 backS) {
|
||||
_G(globals)[GLB_MIN_Y] = backY << 16;
|
||||
_G(globals)[GLB_MAX_Y] = frontY << 16;
|
||||
_G(globals)[GLB_MIN_SCALE] = FixedDiv(backS << 16, 100 << 16);
|
||||
_G(globals)[GLB_MAX_SCALE] = FixedDiv(frontS << 16, 100 << 16);
|
||||
if (_G(globals)[GLB_MIN_Y] == _G(globals)[GLB_MAX_Y])
|
||||
_G(globals)[GLB_SCALER] = 0;
|
||||
else
|
||||
_G(globals)[GLB_SCALER] = FixedDiv(_G(globals)[GLB_MAX_SCALE] - _G(globals)[GLB_MIN_SCALE], _G(globals)[GLB_MAX_Y] - _G(globals)[GLB_MIN_Y]);
|
||||
}
|
||||
|
||||
|
||||
// This routine must also load shadow animations
|
||||
|
||||
bool player_load_series(const char *walkerName, const char *shadowName, bool load_palette) {
|
||||
int i;
|
||||
int32 thatRoomCode;
|
||||
char assetPath[MAX_FILENAME_SIZE];
|
||||
char *tempPtr;
|
||||
|
||||
// Load walker
|
||||
db_rmlst_get_asset_room_path(walkerName, assetPath, &thatRoomCode);
|
||||
tempPtr = strrchr(assetPath, '.');
|
||||
if (!tempPtr)
|
||||
return false;
|
||||
|
||||
tempPtr--;
|
||||
if ((*tempPtr < '0') || (*tempPtr > '9'))
|
||||
return false;
|
||||
|
||||
for (i = 1; i <= 5; i++) {
|
||||
*tempPtr = (char)((int32)'0' + i);
|
||||
AddWSAssetCELS(assetPath, i - 1, load_palette ? _G(master_palette) : nullptr);
|
||||
}
|
||||
|
||||
// Load walker shadow
|
||||
db_rmlst_get_asset_room_path(shadowName, assetPath, &thatRoomCode);
|
||||
tempPtr = strrchr(assetPath, '.');
|
||||
if (!tempPtr)
|
||||
return false;
|
||||
|
||||
tempPtr--;
|
||||
if ((*tempPtr < '0') || (*tempPtr > '9'))
|
||||
return false;
|
||||
|
||||
for (i = 1; i <= 5; i++) {
|
||||
*tempPtr = (char)((int32)'0' + i);
|
||||
AddWSAssetCELS(assetPath, i + 4, nullptr);
|
||||
}
|
||||
|
||||
sendWSMessage(0, 0, nullptr, 6, nullptr, 1); // Hash 6 is the shadow machine
|
||||
return true;
|
||||
}
|
||||
|
||||
void player_first_walk(int32 x1, int32 y1, int32 f1, int32 x2, int32 y2, int32 f2, bool /*enable_commands_at_destination*/) {
|
||||
ws_demand_location(x1, y1, f1);
|
||||
ws_walk(x2, y2, nullptr, -1, f2);
|
||||
}
|
||||
|
||||
void player_set_defaults() {
|
||||
_G(player).walker_visible = false;
|
||||
_G(player).disable_hyperwalk = false;
|
||||
_G(player).walker_loads_first = true;
|
||||
_G(player).walker_reload_palette = true;
|
||||
_G(player).walker_in_this_scene = true;
|
||||
}
|
||||
|
||||
bool player_commands_allowed() {
|
||||
return _G(player).comm_allowed;
|
||||
}
|
||||
|
||||
PlayerInfo *player_update_info(machine *myWalker, PlayerInfo *player_info) {
|
||||
if (!myWalker)
|
||||
return nullptr;
|
||||
|
||||
ws_get_walker_info(myWalker, &player_info->x, &player_info->y,
|
||||
&player_info->scale, &player_info->depth, &player_info->facing);
|
||||
|
||||
int32 status;
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
player_info->camera_x = game_buff_ptr->x1;
|
||||
player_info->camera_y = game_buff_ptr->y1;
|
||||
return player_info;
|
||||
}
|
||||
|
||||
PlayerInfo *player_update_info() {
|
||||
return player_update_info(_G(my_walker), &_G(player_info));
|
||||
}
|
||||
|
||||
void player_set_facing_hotspot(int trigger) {
|
||||
player_set_facing_at(_G(player).click_x, _G(player).click_y, trigger);
|
||||
}
|
||||
|
||||
void player_set_facing_at(int x, int y, int trigger) {
|
||||
player_hotspot_walk_override_just_face(calc_facing(x, y), trigger);
|
||||
}
|
||||
|
||||
int calc_facing(int x, int y) {
|
||||
player_update_info(_G(my_walker), &_G(player_info));
|
||||
|
||||
if (!x) {
|
||||
return -_G(player_info).y < -y;
|
||||
} else {
|
||||
double slope = (double)(y - _G(player_info).y) / (double)(x - _G(player_info).x);
|
||||
term_message("click (%d,%d) player (%d,%d) slope = %f",
|
||||
x, -y, _G(player_info).x, -_G(player_info).y);
|
||||
|
||||
if (_G(player_info).x < x) {
|
||||
if (slope >= 1.25)
|
||||
return 1;
|
||||
else if (slope >= 0.1)
|
||||
return 2;
|
||||
else if (slope >= -0.1)
|
||||
return 3;
|
||||
else if (slope >= -0.4)
|
||||
return 4;
|
||||
else
|
||||
return 5;
|
||||
} else {
|
||||
if (slope >= 0.4)
|
||||
return 7;
|
||||
else if (slope >= 0.1)
|
||||
return 8;
|
||||
else if (slope >= -0.1)
|
||||
return 9;
|
||||
else if (slope >= -1.25)
|
||||
return 10;
|
||||
else
|
||||
return 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
127
engines/m4/adv_r/adv_player.h
Normal file
127
engines/m4/adv_r/adv_player.h
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_PLAYER_H
|
||||
#define M4_ADV_R_ADV_PLAYER_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define MAX_PLYR_STRING_LEN 40
|
||||
|
||||
struct Player {
|
||||
int32 x = 0, y = 0; // Player's current screen location
|
||||
int32 facing = 0; // Player's current directional facing
|
||||
|
||||
char verb[MAX_PLYR_STRING_LEN] = { 0 };
|
||||
char noun[MAX_PLYR_STRING_LEN] = { 0 };
|
||||
char prep[MAX_PLYR_STRING_LEN] = { 0 };
|
||||
char object[MAX_PLYR_STRING_LEN] = { 0 };
|
||||
char ws_asset_name[32] = { 0 }; // Name of the walker sprite series holder
|
||||
char ws_shadow_name[32] = { 0 }; // Name of the walker sprite series shadow holder
|
||||
int16 walker_type = 0; // Type of walker (ripley, mei_chin, safari, etc.)
|
||||
int16 shadow_type = 0; // Type of walker (ripley shadow, candleman shadow, etc.)
|
||||
|
||||
// If he walks off edge, this holds the number of the room he goes to
|
||||
int32 walk_off_edge_to_room = 0; // Player should walk off edge unless told otherwise
|
||||
|
||||
// If False player won't walk - totally aborts a walk
|
||||
bool need_to_walk = false; // Player needs to walk somewhere
|
||||
|
||||
// If False player won't walk yet - walk suspended until TRUE
|
||||
bool ready_to_walk = false; // Player is ready to perform that walk
|
||||
|
||||
bool waiting_for_walk = false;
|
||||
|
||||
// Default True for every room
|
||||
// Flag if accepting player input
|
||||
bool comm_allowed = false;
|
||||
|
||||
// Means a parser command is ready. When apps programmer finishes
|
||||
// parsing command, the programmer must set this to FALSE. If this
|
||||
// doesn't get set, the command falls through to the error handling code.
|
||||
int32 command_ready = 0;
|
||||
|
||||
// Default True, if set to FALSE walker disappears instantly, and vv
|
||||
bool walker_visible = false; // Flag if player's sprite is visible
|
||||
|
||||
// If True, then apps programmer must display look messages
|
||||
bool look_around = false; // Flag for special "look around" command
|
||||
|
||||
// Tested by the apps programmer to check if player has been here before
|
||||
bool been_here_before = false;
|
||||
|
||||
// Walker sprites dumped on switching scenes if TRUE in room preload code
|
||||
bool walker_reload_palette = false;
|
||||
bool disable_hyperwalk = false;
|
||||
bool walker_loads_first = false;
|
||||
bool walker_in_this_scene = false;
|
||||
|
||||
int32 walker_trigger = 0;
|
||||
|
||||
int32 walk_x = 0, walk_y = 0; // Where to walk to when player.ready_to_walk
|
||||
int32 walk_facing = 0;
|
||||
|
||||
int32 click_x = 0, click_y = 0;
|
||||
|
||||
void syncGame(Common::Serializer &s);
|
||||
|
||||
void resetWalk();
|
||||
};
|
||||
|
||||
struct PlayerInfo {
|
||||
int32 x = 0, y = 0, facing = 0;
|
||||
int32 scale = 0, depth = 0;
|
||||
int32 camera_x = 0, camera_y = 0;
|
||||
|
||||
void syncGame(Common::Serializer &s);
|
||||
};
|
||||
|
||||
bool player_said(const char *w0, const char *w1 = nullptr, const char *w2 = nullptr);
|
||||
bool player_said_any(const char *w0, const char *w1 = nullptr, const char *w2 = nullptr,
|
||||
const char *w3 = nullptr, const char *w4 = nullptr, const char *w5 = nullptr, const char *w6 = nullptr,
|
||||
const char *w7 = nullptr, const char *w8 = nullptr, const char *w9 = nullptr);
|
||||
|
||||
void player_inform_walker_new_scale(int32 frontY, int32 backY, int32 frontS, int32 backS);
|
||||
|
||||
bool player_load_series(const char *walkerName, const char *shadowName, bool load_palette);
|
||||
void player_first_walk(int32 x1, int32 y1, int32 f1, int32 x2, int32 y2, int32 f2, bool enable_commands_at_destination);
|
||||
void player_set_defaults();
|
||||
|
||||
void player_hotspot_walk_override(int32 x, int32 y, int32 facing = -1, int32 trigger = -1);
|
||||
void player_hotspot_walk_override_just_face(int32 facing, int32 trigger = -1);
|
||||
|
||||
bool player_commands_allowed();
|
||||
PlayerInfo *player_update_info(machine *myWalker, PlayerInfo *player_info);
|
||||
PlayerInfo *player_update_info();
|
||||
void adv_kill_digi_between_rooms(bool true_or_false);
|
||||
|
||||
void player_set_facing_hotspot(int trigger = -1);
|
||||
void player_set_facing_at(int x, int y, int trigger = -1);
|
||||
int calc_facing(int x, int y);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
1038
engines/m4/adv_r/adv_rails.cpp
Normal file
1038
engines/m4/adv_r/adv_rails.cpp
Normal file
File diff suppressed because it is too large
Load Diff
71
engines/m4/adv_r/adv_rails.h
Normal file
71
engines/m4/adv_r/adv_rails.h
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_RAILS_H
|
||||
#define M4_ADV_R_ADV_RAILS_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct Rails_Globals {
|
||||
railNode **myNodes = nullptr;
|
||||
int16 *myEdges = nullptr;
|
||||
|
||||
railNode **stackBottom = nullptr, **stackTop = nullptr;
|
||||
noWalkRect *noWalkRectList = nullptr;
|
||||
|
||||
int32 memtypePATHN = 0;
|
||||
};
|
||||
|
||||
bool InitRails();
|
||||
void rail_system_shutdown();
|
||||
void ClearRails();
|
||||
noWalkRect *intr_add_no_walk_rect(int32 x1, int32 y1, int32 x2, int32 y2, int32 altX, int32 altY, Buffer *walkCodes);
|
||||
noWalkRect *intr_add_no_walk_rect(int32 x1, int32 y1, int32 x2, int32 y2, int32 altX, int32 altY);
|
||||
void intr_move_no_walk_rect(noWalkRect *myRect, int32 new_x1, int32 new_y1,
|
||||
int32 new_x2, int32 new_y2, int32 new_altX, int32 new_altY, Buffer *walkCodes);
|
||||
void intr_remove_no_walk_rect(noWalkRect *myRect, Buffer *walkCodes);
|
||||
void intr_remove_no_walk_rect(noWalkRect *myRect);
|
||||
void CreateEdge(int32 node1, int32 node2, Buffer *walkCodes);
|
||||
void RestoreNodeEdges(int32 nodeID, Buffer *walkCodes);
|
||||
void RestoreEdgeList(Buffer *walkCodes);
|
||||
int32 AddRailNode(int32 x, int32 y, Buffer *walkCodes, bool restoreEdges);
|
||||
void MoveRailNode(int32 nodeID, int32 x, int32 y, Buffer *walkCodes, bool restoreEdges);
|
||||
bool RemoveRailNode(int32 nodeID, Buffer *walkCodes, bool restoreEdges);
|
||||
bool RailNodeExists(int32 nodeID, int32 *nodeX, int32 *nodeY);
|
||||
int16 GetEdgeLength(int32 node1, int32 node2);
|
||||
bool GetShortestPath(int32 origID, int32 destID, railNode **shortPath);
|
||||
railNode *CreateCustomPath(int coord, ...);
|
||||
void DisposePath(railNode *pathStart);
|
||||
bool intr_LineCrossesRect(int32 line_x1, int32 line_y1, int32 line_x2, int32 line_y2,
|
||||
int32 rect_x1, int32 rect_y1, int32 rect_x2, int32 rect_y2);
|
||||
bool intr_LinesCross(int32 line1_x1, int32 line1_y1, int32 line1_x2, int32 line1_y2,
|
||||
int32 line2_x1, int32 line2_y1, int32 line2_x2, int32 line2_y2);
|
||||
bool intr_PathCrossesLine(int32 startX, int32 startY, railNode *pathStart,
|
||||
int32 line_x1, int32 line_y1, int32 line_x2, int32 line_y2);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
136
engines/m4/adv_r/adv_scale.cpp
Normal file
136
engines/m4/adv_r/adv_scale.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* 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 "m4/adv_r/adv_scale.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/graphics/gr_line.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define LABEL_OFFSET 8
|
||||
#define _GS(X) _G(scale)._##X
|
||||
|
||||
static void scale_editor_clear_rects() {
|
||||
_GS(old_front) = _GS(old_back) = -1;
|
||||
_GS(myback) = _GS(myfront) = _GS(mybs) = _GS(myfs) = -1;
|
||||
}
|
||||
|
||||
static void scale_editor_init() {
|
||||
scale_editor_clear_rects();
|
||||
}
|
||||
|
||||
static void scale_editor_undraw() {
|
||||
Buffer *scr_orig = _G(game_bgBuff)->get_buffer();
|
||||
Buffer *game_buff = _G(gameDrawBuff)->get_buffer();
|
||||
int32 status;
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
|
||||
if (_GS(old_back) != -1) {
|
||||
gr_buffer_rect_copy_2(scr_orig, game_buff, 0, _GS(old_back) - LABEL_OFFSET, 0,
|
||||
_GS(old_back) - LABEL_OFFSET, scr_orig->w, LABEL_OFFSET + 1);
|
||||
RestoreScreensInContext(0, _GS(old_back) - LABEL_OFFSET, scr_orig->w, _GS(old_back) + 1, game_buff_ptr);
|
||||
_GS(old_back) = -1;
|
||||
}
|
||||
if (_GS(old_front) != -1) {
|
||||
gr_buffer_rect_copy_2(scr_orig, game_buff, 0, _GS(old_front) - LABEL_OFFSET, 0,
|
||||
_GS(old_front) - LABEL_OFFSET, scr_orig->w, LABEL_OFFSET + 1);
|
||||
RestoreScreensInContext(0, _GS(old_front) - LABEL_OFFSET, scr_orig->w, _GS(old_front) + 1, game_buff_ptr);
|
||||
_GS(old_front) = -1;
|
||||
}
|
||||
|
||||
_G(game_bgBuff)->release();
|
||||
_G(gameDrawBuff)->release();
|
||||
scale_editor_clear_rects();
|
||||
}
|
||||
|
||||
void scale_editor_draw() {
|
||||
bool bail = true;
|
||||
|
||||
// Have we drawn before?
|
||||
if (_GS(myback) == -1 && _GS(myfront) == -1)
|
||||
bail = false;
|
||||
|
||||
// Has back or front y changed?
|
||||
if (bail && _GS(myback) != _G(currentSceneDef).back_y && _GS(myfront) != _G(currentSceneDef).front_y)
|
||||
bail = false;
|
||||
|
||||
// Has back or front scale changed?
|
||||
if (bail && _GS(mybs) != _G(currentSceneDef).back_scale && _GS(myfs) != _G(currentSceneDef).front_scale)
|
||||
bail = false;
|
||||
|
||||
// No changes, don't draw.
|
||||
if (bail)
|
||||
return;
|
||||
|
||||
scale_editor_undraw();
|
||||
|
||||
Buffer *game_buff = _G(gameDrawBuff)->get_buffer();
|
||||
int32 status;
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
|
||||
Buffer *scr_orig = _G(game_bgBuff)->get_buffer();
|
||||
|
||||
gr_color_set(__YELLOW);
|
||||
_GS(myback) = _GS(old_back) = _G(currentSceneDef).back_y;
|
||||
_GS(myfront) = _GS(old_front) = _G(currentSceneDef).front_y;
|
||||
_GS(mybs) = _G(currentSceneDef).back_scale;
|
||||
_GS(myfs) = _G(currentSceneDef).front_scale;
|
||||
gr_hline(game_buff, 0, scr_orig->w, _GS(old_back));
|
||||
gr_hline(game_buff, 0, scr_orig->w, _GS(old_front));
|
||||
|
||||
char string[20];
|
||||
gr_font_set_color(__WHITE);
|
||||
gr_font_set(_G(font_tiny));
|
||||
|
||||
Common::sprintf_s(string, "Front: %d, %d", _GS(old_front), _G(currentSceneDef).front_scale);
|
||||
int x;
|
||||
for (x = 10; x < scr_orig->w - 220; x += 400)
|
||||
gr_font_write(game_buff, string, x, _GS(old_front) - LABEL_OFFSET, 0, 0);
|
||||
|
||||
Common::sprintf_s(string, "Back: %d, %d", _GS(old_back), _G(currentSceneDef).back_scale);
|
||||
for (x = 110; x < scr_orig->w - 320; x += 400)
|
||||
gr_font_write(game_buff, string, x, _GS(old_back) - LABEL_OFFSET, 0, 0);
|
||||
|
||||
RestoreScreensInContext(0, _GS(old_back) - LABEL_OFFSET, scr_orig->w, _GS(old_back) + 1, game_buff_ptr);
|
||||
RestoreScreensInContext(0, _GS(old_front) - LABEL_OFFSET, scr_orig->w, _GS(old_front) + 1, game_buff_ptr);
|
||||
|
||||
_G(game_bgBuff)->release();
|
||||
_G(gameDrawBuff)->release();
|
||||
}
|
||||
|
||||
void scale_editor_cancel() {
|
||||
scale_editor_undraw();
|
||||
_G(editors_in_use) &= ~kScaleEditor;
|
||||
}
|
||||
|
||||
void scale_editor_toggle() {
|
||||
if (_G(editors_in_use) & kScaleEditor)
|
||||
scale_editor_cancel();
|
||||
else {
|
||||
_G(editors_in_use) |= kScaleEditor;
|
||||
scale_editor_init();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
47
engines/m4/adv_r/adv_scale.h
Normal file
47
engines/m4/adv_r/adv_scale.h
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_SCALE_H
|
||||
#define M4_ADV_R_ADV_SCALE_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
constexpr int kScaleEditor = 1;
|
||||
|
||||
struct ADVScale_Globals {
|
||||
int32 _old_front = -1;
|
||||
int32 _old_back = -1;
|
||||
int _myback = -1;
|
||||
int _myfront = -1;
|
||||
int _mybs = -1;
|
||||
int _myfs = -1;
|
||||
};
|
||||
|
||||
void scale_editor_draw();
|
||||
void scale_editor_cancel();
|
||||
void scale_editor_toggle();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
187
engines/m4/adv_r/adv_trigger.cpp
Normal file
187
engines/m4/adv_r/adv_trigger.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/* 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 "m4/adv_r/adv_trigger.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/vars.h"
|
||||
#include "m4/m4.h"
|
||||
#include "m4/platform/timer.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define _GT(X) _G(triggers)._##X
|
||||
|
||||
int32 kernel_trigger_create(int32 trigger_num) {
|
||||
if (trigger_num < 0)
|
||||
return (trigger_num);
|
||||
|
||||
if (trigger_num > 0xffff) { // If room changed, this is an invalid trigger
|
||||
error_show(FL, 'BADT', "bad trigger. %d > 0xffff", trigger_num);
|
||||
}
|
||||
|
||||
const int32 new_trigger = trigger_num + (_G(game).room_id << 16) + (_G(kernel).trigger_mode << 28);
|
||||
|
||||
return new_trigger;
|
||||
}
|
||||
|
||||
bool kernel_trigger_dispatch_now(int32 trigger_num) {
|
||||
if (g_engine->getGameType() == GType_Riddle)
|
||||
return kernel_trigger_dispatchx(trigger_num);
|
||||
|
||||
return kernel_trigger_dispatchx(kernel_trigger_create(trigger_num));
|
||||
}
|
||||
|
||||
void cisco_dispatch_triggers() {
|
||||
for (int i = 0; i < _GT(q_end); ++i) {
|
||||
kernel_trigger_dispatchx(_GT(sound_trigger_q)[i]);
|
||||
}
|
||||
|
||||
_GT(q_end) = 0;
|
||||
}
|
||||
|
||||
void cisco_clear_triggers() {
|
||||
_GT(q_end) = _GT(q_start) = 0;
|
||||
}
|
||||
|
||||
bool kernel_trigger_dispatchx(int32 trigger_num) {
|
||||
if (_G(between_rooms))
|
||||
return true;
|
||||
|
||||
const KernelTriggerType old_trigger_mode = _G(kernel).trigger_mode;
|
||||
const int32 old_trigger = _G(kernel).trigger;
|
||||
bool result = false;
|
||||
|
||||
if (trigger_num < 0)
|
||||
return false;
|
||||
|
||||
if (((trigger_num >> 16) & 0xfff) != _G(game).room_id) { // if room changed, this is an invalid trigger
|
||||
term_message("orphan scene trigger:mode: %d, scene: %d, trigger: %d",
|
||||
trigger_num >> 28, (trigger_num >> 16) & 0xffff, trigger_num & 0xffff);
|
||||
return false;
|
||||
}
|
||||
|
||||
_G(kernel).trigger = trigger_num & 0xffff; // If no command in Q, must be here because of code
|
||||
|
||||
switch (trigger_num >> 28) {
|
||||
case KT_PREPARSE:
|
||||
if (_G(kernel).trigger >= 32000)
|
||||
break;
|
||||
_G(kernel).trigger_mode = KT_PREPARSE;
|
||||
|
||||
g_engine->room_pre_parser();
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case KT_PARSE:
|
||||
if (_G(kernel).trigger >= 32000)
|
||||
break;
|
||||
_G(kernel).trigger_mode = KT_PARSE;
|
||||
_G(player).command_ready = true;
|
||||
g_engine->room_parser();
|
||||
|
||||
if (_G(player).command_ready) {
|
||||
g_engine->global_parser();
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case KT_DAEMON:
|
||||
g_engine->game_daemon_code();
|
||||
result = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
term_message("orphan mode trigger: mode: %d, scene: %d, trigger: %d",
|
||||
trigger_num >> 28, (trigger_num >> 16) & 0xffff, trigger_num & 0xffff);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
_G(kernel).trigger_mode = old_trigger_mode;
|
||||
_G(kernel).trigger = old_trigger;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void timer_callback(frac16 myMessage, struct machine *sender) {
|
||||
kernel_trigger_dispatchx(myMessage);
|
||||
}
|
||||
|
||||
void kernel_timing_trigger(int32 ticks, int16 trigger, const char *name) {
|
||||
if (ticks <= 0) {
|
||||
// Trigger immediately
|
||||
kernel_trigger_dispatchx(kernel_trigger_create(trigger));
|
||||
return;
|
||||
}
|
||||
|
||||
_G(globals)[GLB_TEMP_1] = ticks << 16;
|
||||
_G(globals)[GLB_TEMP_2] = kernel_trigger_create(trigger);
|
||||
|
||||
if (name) {
|
||||
const Common::String machName = Common::String::format("timer - %s", name);
|
||||
TriggerMachineByHash(2, nullptr, -1, -1, timer_callback, false, machName.c_str());
|
||||
|
||||
} else {
|
||||
TriggerMachineByHash(2, nullptr, -1, -1, timer_callback, false, "timer trigger");
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_timing_trigger(int32 ticks, int16 trigger,
|
||||
KernelTriggerType preMode, KernelTriggerType postMode) {
|
||||
_G(kernel).trigger_mode = preMode;
|
||||
kernel_timing_trigger(ticks, trigger, nullptr);
|
||||
_G(kernel).trigger_mode = postMode;
|
||||
}
|
||||
|
||||
void kernel_timing_trigger_daemon(int32 ticks, int16 trigger) {
|
||||
const KernelTriggerType oldMode = _G(kernel).trigger_mode;
|
||||
_G(kernel).trigger_mode = KT_DAEMON;
|
||||
kernel_timing_trigger(ticks, trigger, nullptr);
|
||||
_G(kernel).trigger_mode = oldMode;
|
||||
}
|
||||
|
||||
void kernel_service_timing_trigger_q() {
|
||||
// Dispatch pending timing triggers
|
||||
int32 iter = 0;
|
||||
const int32 now = timer_read_60();
|
||||
|
||||
while (iter < _GT(time_q_end) && _GT(time_q)[iter] <= now)
|
||||
{
|
||||
kernel_trigger_dispatchx(_GT(time_trigger_q)[iter]);
|
||||
++iter;
|
||||
}
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
// Remove dispatched triggers from the q
|
||||
const int32 total = iter;
|
||||
int32 dispatched = iter;
|
||||
iter = 0;
|
||||
while (dispatched < _GT(time_q_end)) {
|
||||
_GT(time_q)[iter] = _GT(time_q)[dispatched];
|
||||
_GT(time_trigger_q)[iter] = _GT(time_trigger_q)[dispatched];
|
||||
++iter;
|
||||
++dispatched;
|
||||
}
|
||||
|
||||
_GT(time_q_end) -= total;
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
76
engines/m4/adv_r/adv_trigger.h
Normal file
76
engines/m4/adv_r/adv_trigger.h
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_TRIGGER_H
|
||||
#define M4_ADV_R_ADV_TRIGGER_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/adv.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
constexpr int NO_TRIGGER = -1;
|
||||
constexpr int TENTH_SECOND = 6;
|
||||
constexpr int MAX_TIMERS = 32;
|
||||
|
||||
struct Triggers {
|
||||
int32 _time_q[MAX_TIMERS];
|
||||
int32 _time_trigger_q[MAX_TIMERS];
|
||||
int32 _time_q_end = 0;
|
||||
|
||||
int32 _sound_trigger_q[MAX_TIMERS];
|
||||
int32 _q_start = 0;
|
||||
int32 _q_end = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new trigger
|
||||
* Trigger usage:
|
||||
* [31-28][27-16][15-0]
|
||||
* | | |
|
||||
* | | +--- trigger_num (0 - 0xffff)
|
||||
* | +--- room_id (0 - 4096) (0 - 0xfff)
|
||||
* +--- trigger_mode (0-16)
|
||||
*/
|
||||
int32 kernel_trigger_create(int32 trigger_num);
|
||||
int32 kernel_trigger_create_mode(int32 trigger_num, int32 desired_mode);
|
||||
|
||||
/**
|
||||
* Dispatches a trigger.
|
||||
* @returns Returns true if the trigger was handled. If the trigger is for
|
||||
* a different room that current room_id, returns false. If no trigger_mode was
|
||||
* attached to the trigger, returns false
|
||||
*/
|
||||
bool kernel_trigger_dispatchx(int32 trigger_num);
|
||||
bool kernel_trigger_dispatch_now(int32 trigger_num);
|
||||
void kernel_timing_trigger(int32 ticks, int16 trigger, const char *name = nullptr);
|
||||
void kernel_timing_trigger_daemon(int32 ticks, int16 trigger);
|
||||
void kernel_timing_trigger(int32 ticks, int16 trigger,
|
||||
KernelTriggerType preMode, KernelTriggerType postMode);
|
||||
|
||||
void cisco_dispatch_triggers();
|
||||
void cisco_clear_triggers();
|
||||
void kernel_service_timing_trigger_q();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
509
engines/m4/adv_r/adv_walk.cpp
Normal file
509
engines/m4/adv_r/adv_walk.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
/* 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 "m4/adv_r/adv_walk.h"
|
||||
#include "m4/adv_r/adv_trigger.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/graphics/gr_series.h"
|
||||
#include "m4/wscript/wst_regs.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void set_walker_scaling(SceneDef *rdef) {
|
||||
_G(globals)[GLB_MIN_Y] = rdef->back_y << 16;
|
||||
_G(globals)[GLB_MAX_Y] = rdef->front_y << 16;
|
||||
_G(globals)[GLB_MIN_SCALE] = FixedDiv(rdef->back_scale << 16, 100 << 16);
|
||||
_G(globals)[GLB_MAX_SCALE] = FixedDiv(rdef->front_scale << 16, 100 << 16);
|
||||
if (_G(globals)[GLB_MIN_Y] == _G(globals)[GLB_MAX_Y])
|
||||
_G(globals)[GLB_SCALER] = 0;
|
||||
else
|
||||
_G(globals)[GLB_SCALER] = FixedDiv(_G(globals)[GLB_MAX_SCALE] - _G(globals)[GLB_MIN_SCALE], _G(globals)[GLB_MAX_Y] - _G(globals)[GLB_MIN_Y]);
|
||||
}
|
||||
|
||||
static void ws_walkto_node(machine *myWalker, railNode *destNode, bool firstTime) {
|
||||
// Parameter verification
|
||||
if (!myWalker) {
|
||||
error_show(FL, 'W:-(');
|
||||
return;
|
||||
}
|
||||
if (!destNode) {
|
||||
error_show(FL, 'WNDN');
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the destination values x, y, s
|
||||
const frac16 x = destNode->x << 16;
|
||||
const frac16 y = destNode->y << 16;
|
||||
const frac16 s = _G(globals)[GLB_MIN_SCALE] + FixedMul(y - _G(globals)[GLB_MIN_Y], _G(globals)[GLB_SCALER]);
|
||||
|
||||
// Plug in the destination x, y, and s
|
||||
_G(globals)[GLB_TEMP_1] = x;
|
||||
_G(globals)[GLB_TEMP_2] = y;
|
||||
_G(globals)[GLB_TEMP_3] = s;
|
||||
|
||||
// Final direction (GLB_TEMP_4) and trigger (GLB_TEMP_5) are set in ws_walk() below
|
||||
if (firstTime) {
|
||||
if (_G(completeWalk)) {
|
||||
_G(globals)[GLB_TEMP_6] = 0x10000; // so the feet will come together
|
||||
} else {
|
||||
_G(globals)[GLB_TEMP_6] = 0; // so the walker will freeze when he reaches the last node
|
||||
}
|
||||
sendWSMessage(STARTWALK << 16, 0, myWalker, 0, nullptr, 1);
|
||||
} else {
|
||||
sendWSMessage(WALKSEQ << 16, 0, myWalker, 0, nullptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool walker_has_walk_finished(machine *sender) {
|
||||
// Parameter verification
|
||||
if ((!sender) || (!sender->myAnim8)) {
|
||||
error_show(FL, 'W:-(');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the node we just arrived at from the sender's walkPath
|
||||
if (sender->walkPath) {
|
||||
railNode *tempNode = sender->walkPath;
|
||||
sender->walkPath = sender->walkPath->shortPath;
|
||||
mem_free((void *)tempNode);
|
||||
}
|
||||
|
||||
// If no more nodes to traverse (a canadian word), check if he's standing.
|
||||
// If not standing, let him finish standing, then when he finishes standing
|
||||
if (!sender->walkPath) {
|
||||
return true;
|
||||
} else {
|
||||
// Else there are more nodes, so keep walking
|
||||
ws_walkto_node(sender, sender->walkPath, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by player_walk
|
||||
*/
|
||||
void ws_walk(machine *myWalker, int32 x, int32 y, GrBuff **, int16 trigger, int32 finalFacing, bool complete_walk) {
|
||||
int8 directions[14] = { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9 };
|
||||
int32 currNodeID, destNodeID;
|
||||
|
||||
if (!myWalker || !myWalker->myAnim8)
|
||||
error_show(FL, 'W:-(');
|
||||
|
||||
// Get walker's current location
|
||||
const int32 currX = myWalker->myAnim8->myRegs[IDX_X] >> 16;
|
||||
const int32 currY = myWalker->myAnim8->myRegs[IDX_Y] >> 16;
|
||||
|
||||
// Add the walker's current location and the destination to the rail nodes...
|
||||
Buffer *walkerCodes = nullptr;
|
||||
if (_G(screenCodeBuff))
|
||||
walkerCodes = _G(screenCodeBuff)->get_buffer();
|
||||
if ((currNodeID = AddRailNode(currX, currY, walkerCodes, true)) < 0) {
|
||||
error_show(FL, 'WCAN', "Walker's curr posn: %d %d", currX, currY);
|
||||
}
|
||||
if ((destNodeID = AddRailNode(x, y, walkerCodes, true)) < 0) {
|
||||
error_show(FL, 'WCAN', "Trying to walk to: %d %d", x, y);
|
||||
}
|
||||
|
||||
// Dispose of the current path myWalker is following
|
||||
if (myWalker->walkPath) {
|
||||
DisposePath(myWalker->walkPath);
|
||||
}
|
||||
|
||||
// Find the shortest path between currNodeID, and destNodeID
|
||||
const bool result = GetShortestPath(currNodeID, destNodeID, &(myWalker->walkPath));
|
||||
|
||||
// Now that a path has been found, remove the two extra added nodes
|
||||
RemoveRailNode(currNodeID, walkerCodes, true);
|
||||
RemoveRailNode(destNodeID, walkerCodes, true);
|
||||
if (_G(screenCodeBuff))
|
||||
_G(screenCodeBuff)->release();
|
||||
|
||||
// Check the success of GetShortestPath
|
||||
if (!result) {
|
||||
term_message("Player: Can't walk there!!!");
|
||||
_G(player).waiting_for_walk = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the result was true, but no path was returned, we are already there
|
||||
if (!myWalker->walkPath) {
|
||||
_G(player).need_to_walk = false;
|
||||
|
||||
//we can only turn to face the final direction
|
||||
ws_turn_to_face(myWalker, finalFacing, trigger);
|
||||
} else {
|
||||
// Otherwise we have a path to follow, so get going...
|
||||
|
||||
// Verify that finalFacing is valid or set -1
|
||||
if (finalFacing > 0 && finalFacing < 13) {
|
||||
_G(globals)[GLB_TEMP_4] = directions[finalFacing] << 16;
|
||||
} else {
|
||||
_G(globals)[GLB_TEMP_4] = (frac16)-1 & ~0xffff;
|
||||
}
|
||||
|
||||
// Set the trigger to be returned when the walk is finished
|
||||
_G(globals)[GLB_TEMP_5] = kernel_trigger_create(trigger);
|
||||
|
||||
_G(completeWalk) = complete_walk;
|
||||
ws_walkto_node(myWalker, myWalker->walkPath, true);
|
||||
}
|
||||
|
||||
if (_G(hyperwalk))
|
||||
adv_hyperwalk_to_final_destination(nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool adv_walker_path_exists(machine *myWalker, int32 x, int32 y) {
|
||||
int32 currNodeID, destNodeID;
|
||||
|
||||
if (!myWalker || !myWalker->myAnim8) {
|
||||
error_show(FL, 'W:-(');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get walker's current location
|
||||
const int32 currX = myWalker->myAnim8->myRegs[IDX_X] >> 16;
|
||||
const int32 currY = myWalker->myAnim8->myRegs[IDX_Y] >> 16;
|
||||
|
||||
// Add the walker's current location and the destination to the rail nodes...
|
||||
Buffer *walkerCodes = nullptr;
|
||||
if (_G(screenCodeBuff)) {
|
||||
walkerCodes = _G(screenCodeBuff)->get_buffer();
|
||||
}
|
||||
if ((currNodeID = AddRailNode(currX, currY, walkerCodes, true)) < 0) {
|
||||
error_show(FL, 'WCAN', "Walker's curr posn: %d %d", currX, currY);
|
||||
}
|
||||
if ((destNodeID = AddRailNode(x, y, walkerCodes, true)) < 0) {
|
||||
error_show(FL, 'WCAN', "Trying to walk to: %d %d", x, y);
|
||||
}
|
||||
|
||||
// Dispose of the current path myWalker is following
|
||||
if (myWalker->walkPath) {
|
||||
DisposePath(myWalker->walkPath);
|
||||
}
|
||||
|
||||
// Find the shortest path between currNodeID, and destNodeID
|
||||
const bool result = GetShortestPath(currNodeID, destNodeID, &(myWalker->walkPath));
|
||||
|
||||
// Now that a path has been attempted, remove the two extra added nodes
|
||||
RemoveRailNode(currNodeID, walkerCodes, true);
|
||||
RemoveRailNode(destNodeID, walkerCodes, true);
|
||||
if (_G(screenCodeBuff))
|
||||
_G(screenCodeBuff)->release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ws_custom_walk(machine *myWalker, int32 finalFacing, int32 trigger, bool complete_walk) {
|
||||
const int8 directions[14] = { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
// Verify parameters
|
||||
if ((!myWalker) || (!myWalker->walkPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that finalFacing is valid or set -1
|
||||
if (finalFacing > 0 && finalFacing < 13) {
|
||||
_G(globals)[GLB_TEMP_4] = directions[finalFacing] << 16;
|
||||
} else {
|
||||
_G(globals)[GLB_TEMP_4] = (frac16)-1 & ~0xffff;
|
||||
}
|
||||
|
||||
// Set the trigger to be returned when the walk is finished
|
||||
_G(globals)[GLB_TEMP_5] = kernel_trigger_create(trigger);
|
||||
|
||||
// Begin the walk...
|
||||
_G(completeWalk) = complete_walk;
|
||||
ws_walkto_node(myWalker, myWalker->walkPath, true);
|
||||
}
|
||||
|
||||
|
||||
void ws_demand_facing(machine *myWalker, int32 facing) {
|
||||
const int8 directions[13] = { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
if ((!myWalker) || (!myWalker->myAnim8)) {
|
||||
term_message("demand facing, but no walker");
|
||||
return;
|
||||
}
|
||||
|
||||
if (facing > 0 && facing < 13) {
|
||||
_G(globals)[GLB_TEMP_4] = directions[facing] << 16;
|
||||
sendWSMessage(DEMAND_FACING << 16, 0, myWalker, 0, nullptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_demand_location(machine *myWalker, int32 x, int32 y, int facing) {
|
||||
if (!myWalker || !myWalker->myAnim8) {
|
||||
term_message("demand locn, no walker");
|
||||
return;
|
||||
}
|
||||
|
||||
frac16 s = _G(globals)[GLB_MIN_SCALE] + FixedMul((y << 16) - _G(globals)[GLB_MIN_Y], _G(globals)[GLB_SCALER]);
|
||||
|
||||
_G(globals)[GLB_TEMP_1] = x << 16;
|
||||
_G(globals)[GLB_TEMP_2] = y << 16;
|
||||
_G(globals)[GLB_TEMP_3] = s;
|
||||
|
||||
sendWSMessage(DEMAND_LOCATION << 16, 0, myWalker, 0, nullptr, 1);
|
||||
|
||||
if (facing != -1)
|
||||
ws_demand_facing(myWalker, facing);
|
||||
}
|
||||
|
||||
static void ws_demand_location_and_facing(machine *myWalker, int32 x, int32 y, int32 facing) {
|
||||
if ((!myWalker) || (!myWalker->myAnim8)) {
|
||||
term_message("demand f & l, no walker");
|
||||
return;
|
||||
}
|
||||
|
||||
frac16 s = _G(globals)[GLB_MIN_SCALE] + FixedMul((y << 16) - _G(globals)[GLB_MIN_Y], _G(globals)[GLB_SCALER]);
|
||||
|
||||
_G(globals)[GLB_TEMP_1] = x << 16;
|
||||
_G(globals)[GLB_TEMP_2] = y << 16;
|
||||
_G(globals)[GLB_TEMP_3] = s;
|
||||
|
||||
if (facing > 0 && facing < 13)
|
||||
// WORKAROUND: The original's hyperwalk didn't work. By doing
|
||||
// the facing set separately, this is fixed
|
||||
ws_demand_facing(facing);
|
||||
|
||||
sendWSMessage(DEMAND_LOCATION << 16, 0, myWalker, 0, nullptr, 1);
|
||||
_G(player).waiting_for_walk = false; // lets parse code get called when there is no facing set (from scenedit)
|
||||
}
|
||||
|
||||
void ws_turn_to_face(machine *myWalker, int32 facing, int32 trigger) {
|
||||
int8 directions[13] = { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
if (!myWalker || !myWalker->myAnim8) {
|
||||
error_show(FL, 'W:-(', "demand facing: %d", facing);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that facing is valid or set -1
|
||||
if (facing > 0 && facing < 13) {
|
||||
_G(globals)[GLB_TEMP_4] = directions[facing] << 16;
|
||||
} else {
|
||||
_G(globals)[GLB_TEMP_4] = (frac16)-1 & ~0xffff;
|
||||
}
|
||||
|
||||
// Set the trigger to be returned when the walk is finished
|
||||
_G(globals)[GLB_TEMP_5] = kernel_trigger_create(trigger);
|
||||
|
||||
// Make sure the _G(completeWalk) flag is set
|
||||
_G(globals)[GLB_TEMP_6] = 0x10000;
|
||||
|
||||
sendWSMessage(TURN_TO_FACE << 16, 0, myWalker, 0, nullptr, 1);
|
||||
}
|
||||
|
||||
void ws_demand_location(int32 x, int32 y, int facing) {
|
||||
ws_demand_location(_G(my_walker), x, y, facing);
|
||||
}
|
||||
|
||||
void ws_hide_walker(machine *myWalker) {
|
||||
if (!myWalker) {
|
||||
error_show(FL, 'W:-(');
|
||||
return;
|
||||
}
|
||||
|
||||
_G(player).walker_visible = false;
|
||||
sendWSMessage(PLAYER_HIDE << 16, 0, myWalker, 0, nullptr, 1);
|
||||
}
|
||||
|
||||
void ws_unhide_walker(machine *myWalker) {
|
||||
if (!myWalker) {
|
||||
error_show(FL, 'W:-(');
|
||||
return;
|
||||
}
|
||||
|
||||
_G(player).walker_visible = true;
|
||||
sendWSMessage(PLAYER_UNHIDE << 16, 0, myWalker, 0, nullptr, 1);
|
||||
}
|
||||
|
||||
void ws_demand_facing(int32 newFacing) {
|
||||
ws_demand_facing(_G(my_walker), newFacing);
|
||||
}
|
||||
|
||||
void ws_turn_to_face(int32 facing, int32 trigger) {
|
||||
ws_turn_to_face(_G(my_walker), facing, trigger);
|
||||
}
|
||||
|
||||
void ws_hide_walker() {
|
||||
ws_hide_walker(_G(my_walker));
|
||||
}
|
||||
|
||||
void ws_unhide_walker() {
|
||||
ws_unhide_walker(_G(my_walker));
|
||||
}
|
||||
|
||||
void ws_walk(int32 x, int32 y, GrBuff **buffer, int16 trigger, int32 finalFacing, bool complete_walk) {
|
||||
ws_walk(_G(my_walker), x, y, buffer, trigger, finalFacing, complete_walk);
|
||||
}
|
||||
|
||||
void ws_get_walker_info(machine *myWalker, int32 *x, int32 *y, int32 *s, int32 *layer, int32 *facing) {
|
||||
const int8 facings[10] = { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11 };
|
||||
|
||||
if (!myWalker || !myWalker->myAnim8) {
|
||||
error_show(FL, 'W:-(');
|
||||
return;
|
||||
}
|
||||
|
||||
Anim8 *myAnim8 = myWalker->myAnim8;
|
||||
|
||||
if (x) {
|
||||
*x = myAnim8->myRegs[IDX_X] >> 16;
|
||||
}
|
||||
if (y) {
|
||||
*y = myAnim8->myRegs[IDX_Y] >> 16;
|
||||
}
|
||||
if (s) {
|
||||
*s = MulSF16(100 << 16, myAnim8->myRegs[IDX_S]) >> 16;
|
||||
}
|
||||
if (layer) {
|
||||
*layer = myAnim8->myRegs[IDX_LAYER] >> 16;
|
||||
}
|
||||
if (facing) {
|
||||
int index = myAnim8->myRegs[IDX_CELS_HASH] >> 24;
|
||||
|
||||
// WORKAROUND: At the very least, Mei Chen in Riddle room 201
|
||||
// produces a negative index value. This ensures indexes are valid
|
||||
if (index < 0 || index > 9)
|
||||
index = 0;
|
||||
|
||||
if (myAnim8->myRegs[IDX_W] < 0)
|
||||
index = 9 - index;
|
||||
|
||||
*facing = facings[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ws_walk_init_system() {
|
||||
// Initialize walker
|
||||
_G(globals)[GLB_MIN_Y] = _G(currentSceneDef).back_y << 16;
|
||||
_G(globals)[GLB_MAX_Y] = _G(currentSceneDef).front_y << 16;
|
||||
_G(globals)[GLB_MIN_SCALE] = FixedDiv(_G(currentSceneDef).back_scale << 16, 100 << 16);
|
||||
_G(globals)[GLB_MAX_SCALE] = FixedDiv(_G(currentSceneDef).front_scale << 16, 100 << 16);
|
||||
if (_G(globals)[GLB_MIN_Y] == _G(globals)[GLB_MAX_Y]) {
|
||||
_G(globals)[GLB_SCALER] = 0;
|
||||
} else {
|
||||
_G(globals)[GLB_SCALER] = FixedDiv(_G(globals)[GLB_MAX_SCALE] - _G(globals)[GLB_MIN_SCALE], _G(globals)[GLB_MAX_Y] - _G(globals)[GLB_MIN_Y]);
|
||||
}
|
||||
|
||||
_G(my_walker) = _GW().walk_initialize_walker();
|
||||
|
||||
if (!_G(my_walker)) {
|
||||
error_show(FL, 'W:-(');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_walk_load_series(const int16 *dir_array, const char *name_array[], bool shadow_flag, bool load_palette) {
|
||||
int32 i = 0;
|
||||
|
||||
while (dir_array[i] >= 0) {
|
||||
const int32 result = AddWSAssetCELS(name_array[i], dir_array[i],
|
||||
(load_palette && !shadow_flag) ? _G(master_palette) : nullptr);
|
||||
if (result < 0)
|
||||
error_show(FL, 'W:-(');
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_walk_load_walker_series(const int16 *dir_array, const char *name_array[], bool load_palette) {
|
||||
return (ws_walk_load_series(dir_array, name_array, false, load_palette));
|
||||
}
|
||||
|
||||
bool ws_walk_load_shadow_series(const int16 *dir_array, const char *name_array[]) {
|
||||
return (ws_walk_load_series(dir_array, name_array, true, false));
|
||||
}
|
||||
|
||||
void ws_walk_dump_series(int16 num_directions, int16 start_hash) {
|
||||
for (int32 i = 0; i < num_directions; i++) {
|
||||
series_unload(start_hash++);
|
||||
}
|
||||
}
|
||||
|
||||
void adv_get_walker_destination(machine *my_walker, int32 *x, int32 *y, int32 *final_facing) {
|
||||
int8 directions[11] = { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11 };
|
||||
|
||||
// If there is no walker, or the walker is not on a walk path, return
|
||||
if (!my_walker || !my_walker->walkPath) {
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*final_facing = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the end of the path
|
||||
railNode *current_node = my_walker->walkPath;
|
||||
while (current_node->shortPath) {
|
||||
current_node = current_node->shortPath;
|
||||
}
|
||||
|
||||
// Set the destination coords
|
||||
*x = current_node->x;
|
||||
*y = current_node->y;
|
||||
|
||||
// Get final facing from l.v.6 = myRegs[6 + IDX_COUNT]
|
||||
int32 face = my_walker->myAnim8->myRegs[6 + IDX_COUNT] >> 16;
|
||||
|
||||
// FIXME: Riddle room 608 Twelvetrees cutscene has face -1. Not sure if happens in original
|
||||
if (face == -1)
|
||||
face = 0;
|
||||
|
||||
*final_facing = directions[face];
|
||||
}
|
||||
|
||||
|
||||
void adv_hyperwalk_to_final_destination(void *, void *) {
|
||||
int32 x, y;
|
||||
int32 facing;
|
||||
|
||||
_G(i_just_hyperwalked) = true;
|
||||
|
||||
// Make sure we have a walker, that it can walk in this scene, and that we can hyperwalk
|
||||
if ((!_G(my_walker)) || (!_G(player).walker_in_this_scene) || _G(player).disable_hyperwalk) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the walker is not currently walking anywhere, return
|
||||
if (!_G(my_walker)->walkPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
//get the final direction and facing
|
||||
adv_get_walker_destination(_G(my_walker), &x, &y, &facing);
|
||||
|
||||
// Nuke the rail node path
|
||||
DisposePath(_G(my_walker)->walkPath);
|
||||
_G(my_walker)->walkPath = nullptr;
|
||||
|
||||
// This will make player goto x,y,facing. when that happens, trigger will return
|
||||
ws_demand_location_and_facing(_G(my_walker), x, y, facing);
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
99
engines/m4/adv_r/adv_walk.h
Normal file
99
engines/m4/adv_r/adv_walk.h
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
/* 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 M4_ADV_R_ADV_WALK_H
|
||||
#define M4_ADV_R_ADV_WALK_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
class Walker {
|
||||
public:
|
||||
virtual ~Walker() {}
|
||||
|
||||
virtual bool walk_load_walker_and_shadow_series() = 0;
|
||||
virtual machine *walk_initialize_walker() = 0;
|
||||
};
|
||||
|
||||
void set_walker_scaling(SceneDef *rdef);
|
||||
|
||||
/**
|
||||
* Called every time s/he hits a node
|
||||
*/
|
||||
bool walker_has_walk_finished(machine *sender);
|
||||
void ws_demand_location(machine *myWalker, int32 x, int32 y, int facing = -1);
|
||||
void ws_demand_facing(machine *myWalker, int32 newFacing);
|
||||
void ws_turn_to_face(machine *myWalker, int32 facing, int32 trigger = -1);
|
||||
void ws_hide_walker(machine *myWalker);
|
||||
void ws_unhide_walker(machine *myWalker);
|
||||
void ws_walk(machine *myWalker, int32 x, int32 y, GrBuff **, int16 trigger, int32 finalFacing, bool complete_walk = true);
|
||||
|
||||
void ws_demand_location(int32 x, int32 y, int facing = -1);
|
||||
void ws_demand_facing(int32 newFacing);
|
||||
void ws_turn_to_face(int32 facing, int32 trigger = -1);
|
||||
void ws_hide_walker();
|
||||
void ws_unhide_walker();
|
||||
void ws_walk(int32 x, int32 y, GrBuff **buffer, int16 trigger, int32 finalFacing = -1, bool complete_walk = true);
|
||||
|
||||
void ws_get_walker_info(machine *myWalker, int32 *x, int32 *y, int32 *s, int32 *layer, int32 *facing);
|
||||
|
||||
bool ws_walk_init_system();
|
||||
|
||||
bool ws_walk_load_series(const int16 *dir_array, const char *name_array[], bool shadow_flag, bool load_palette);
|
||||
bool ws_walk_load_walker_series(const int16 *dir_array, const char *name_array[], bool load_palette = false);
|
||||
bool ws_walk_load_shadow_series(const int16 *dir_array, const char *name_array[]);
|
||||
|
||||
void ws_walk_dump_series(int16 num_directions, int16 start_hash);
|
||||
#define ws_walk_dump_walker_series(xx, yy) (ws_walk_dump_series (xx, yy))
|
||||
#define ws_walk_dump_shadow_series(xx, yy) (ws_walk_dump_series (xx, yy))
|
||||
|
||||
#define player_walk(xx, yy, ff, tt) (ws_walk(_G(my_walker), xx, yy, nullptr, tt, ff, true))
|
||||
#define player_walk_no_finish(xx, yy, ff, tt) (ws_walk(_G(my_walker), xx, yy, nullptr, tt, ff, FALSE))
|
||||
#define player_demand_facing(dd) (ws_demand_facing(_G(my_walker), dd))
|
||||
#define player_demand_location(xx, yy) (ws_demand_location(_G(my_walker), xx, yy))
|
||||
#define player_turn_to_face(dd, tt) (ws_turn_to_face(_G(my_walker), dd, tt))
|
||||
#define player_hide() (ws_hide_walker(_G(my_walker)))
|
||||
#define player_unhide() (ws_unhide_walker(_G(my_walker)))
|
||||
#define player_get_info() (player_update_info(_G(my_walker), &_G(player_info)))
|
||||
|
||||
|
||||
// New walking stuff
|
||||
void ws_custom_walk(machine *myWalker, int32 finalFacing, int32 trigger, bool complete_walk = true);
|
||||
#define adv_walker_custom_walk(ww, ff, tt) (ws_custom_walk(ww, ff, tt, true))
|
||||
#define adv_walker_custom_walk_no_finish(ww, ff, tt) (ws_custom_walk(ww, ff, tt, FALSE))
|
||||
#define adv_walker_walk(ww, xx, yy, ff, tt) (ws_walk(ww, xx, yy, nullptr, tt, ff, true))
|
||||
#define adv_walker_walk_no_finish(ww, xx, yy, ff, tt) (ws_walk(ww, xx, yy, nullptr, tt, ff, FALSE))
|
||||
#define adv_walker_face(ww, dd) (ws_demand_facing(ww, dd))
|
||||
#define adv_walker_turn_to_face(ww, dd, tt) (ws_turn_to_face(ww, dd, tt))
|
||||
#define adv_walker_move(ww, xx, yy) (ws_demand_location(ww, xx, yy))
|
||||
#define adv_walker_hide(ww) (ws_hide_walker(ww))
|
||||
#define adv_walker_unhide(ww) (ws_unhide_walker(ww))
|
||||
bool adv_walker_path_exists(machine *myWalker, int32 x, int32 y);
|
||||
|
||||
void adv_hyperwalk_to_final_destination(void *, void *);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
629
engines/m4/adv_r/chunk_ops.cpp
Normal file
629
engines/m4/adv_r/chunk_ops.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
/* 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/textconsole.h"
|
||||
#include "m4/adv_r/chunk_ops.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
int32 conv_ops_text_strlen(char *s) {
|
||||
int32 len = strlen(s) + 1; // Added +1 for null char.
|
||||
|
||||
if ((len % 4) == 0)
|
||||
return len;
|
||||
|
||||
len += 4 - (len % 4);
|
||||
return len;
|
||||
}
|
||||
|
||||
void conv_ops_unknown_chunk(int32 tag, const char *s) {
|
||||
char *tag_name = (char *)&tag;
|
||||
|
||||
error_show(FL, 'PARS', "'%s' What type is this chunk: %c%c%c%c ?", s, tag_name[3], tag_name[2], tag_name[1], tag_name[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an entry and auto-advance the pointer past it.
|
||||
*/
|
||||
char *conv_ops_get_entry(int32 i, int32 *next, int32 *tag, Conv *c) {
|
||||
int32 num_blocks;
|
||||
int32 j = 0, k = 0;
|
||||
lnode_chunk *L;
|
||||
node_chunk *N;
|
||||
text_chunk *T;
|
||||
w_reply_chunk *W;
|
||||
conv_chunk *CC;
|
||||
|
||||
if ((i + c->myCNode) > c->chunkSize) {
|
||||
error_show(FL, 'PARS', "Conv pointer skipped past chunk EOF. Please check script and make sure HAG is up to date");
|
||||
}
|
||||
|
||||
char *outChunk = &(c->conv[c->myCNode]);
|
||||
*tag = *(int32 *)&outChunk[i];
|
||||
|
||||
if (_GC(swap))
|
||||
*tag = convert_intel32(*tag);
|
||||
|
||||
switch (*tag) {
|
||||
case C_ASGN_CHUNK:
|
||||
k = sizeof(c_assign_chunk);
|
||||
break;
|
||||
|
||||
case ASGN_CHUNK:
|
||||
k = sizeof(assign_chunk);
|
||||
break;
|
||||
|
||||
case CONV_CHUNK:
|
||||
CC = (conv_chunk *)&outChunk[i];
|
||||
|
||||
j = CC->size;
|
||||
break;
|
||||
|
||||
case DECL_CHUNK:
|
||||
k = sizeof(decl_chunk);
|
||||
break;
|
||||
|
||||
case FALL_CHUNK:
|
||||
k = sizeof(fall_chunk);
|
||||
break;
|
||||
|
||||
case LNODE_CHUNK:
|
||||
L = (lnode_chunk *)&outChunk[i];
|
||||
|
||||
k = sizeof(lnode_chunk);
|
||||
|
||||
if (_GC(swap)) {
|
||||
j = convert_intel32(L->num_entries) * sizeof(int32);
|
||||
j = convert_intel32(j);
|
||||
} else {
|
||||
j = L->num_entries * sizeof(int32);
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_CHUNK:
|
||||
N = (node_chunk *)&outChunk[i];
|
||||
|
||||
k = sizeof(node_chunk);
|
||||
|
||||
if (_GC(swap)) {
|
||||
j = convert_intel32(N->num_entries) * sizeof(int32);
|
||||
j = convert_intel32(j);
|
||||
} else {
|
||||
j = N->num_entries * sizeof(int32); //was +=
|
||||
}
|
||||
break;
|
||||
|
||||
case ENTRY_CHUNK:
|
||||
k = sizeof(entry_chunk);
|
||||
break;
|
||||
|
||||
case TEXT_CHUNK:
|
||||
case MESSAGE_CHUNK:
|
||||
T = (text_chunk *)&outChunk[i];
|
||||
num_blocks = T->size;
|
||||
|
||||
k = sizeof(text_chunk);
|
||||
j = num_blocks;
|
||||
|
||||
break;
|
||||
|
||||
case REPLY_CHUNK:
|
||||
k = sizeof(reply_chunk);
|
||||
break;
|
||||
|
||||
case WEIGHT_REPLY_CHUNK:
|
||||
case WEIGHT_PREPLY_CHUNK:
|
||||
W = (w_reply_chunk *)&outChunk[i];
|
||||
k = sizeof(w_reply_chunk);
|
||||
|
||||
if (_GC(swap)) {
|
||||
j = convert_intel32(W->num_replies) * (2 * sizeof(int32)); //was +=
|
||||
j = convert_intel32(j);
|
||||
} else {
|
||||
j = W->num_replies * (2 * sizeof(int32)); //was +=
|
||||
}
|
||||
break;
|
||||
|
||||
case COND_REPLY_CHUNK:
|
||||
k = sizeof(c_reply_chunk);
|
||||
break;
|
||||
|
||||
case COND_EXIT_GOTO_CHUNK:
|
||||
case COND_GOTO_CHUNK:
|
||||
k = sizeof(c_goto_chunk);
|
||||
break;
|
||||
|
||||
case GOTO_CHUNK:
|
||||
case EXIT_GOTO_CHUNK:
|
||||
k = sizeof(goto_chunk);
|
||||
break;
|
||||
|
||||
case HIDE_CHUNK:
|
||||
case UHID_CHUNK:
|
||||
case DSTR_CHUNK:
|
||||
k = sizeof(misc_chunk);
|
||||
break;
|
||||
|
||||
case CHDE_CHUNK:
|
||||
case CUHD_CHUNK:
|
||||
case CDST_CHUNK:
|
||||
k = sizeof(c_misc_chunk);
|
||||
break;
|
||||
|
||||
default:
|
||||
error_show(FL, 'PARS', "Tag: %d (%x) Node: %d (%x hex)", *tag, *tag, c->myCNode, c->myCNode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_GC(swap))
|
||||
j = convert_intel32(j);
|
||||
j += k;
|
||||
|
||||
j += i;
|
||||
*next = j;
|
||||
|
||||
return &outChunk[i];
|
||||
}
|
||||
|
||||
static void swap_assign(assign_chunk *a) {
|
||||
a->tag = convert_intel32(a->tag);
|
||||
a->index = convert_intel32(a->index);
|
||||
a->op = convert_intel32(a->op);
|
||||
a->opnd1 = convert_intel32(a->opnd1);
|
||||
}
|
||||
|
||||
assign_chunk *get_asgn(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (assign_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_c_asgn(c_assign_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
|
||||
c->c_op_l = convert_intel32(c->c_op_l);
|
||||
c->c_op = convert_intel32(c->c_op);
|
||||
c->c_op_r = convert_intel32(c->c_op_r);
|
||||
|
||||
c->index = convert_intel32(c->index);
|
||||
c->op = convert_intel32(c->op);
|
||||
c->opnd1 = convert_intel32(c->opnd1);
|
||||
}
|
||||
|
||||
c_assign_chunk *get_c_asgn(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (c_assign_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_conv(conv_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
c->size = convert_intel32(c->size);
|
||||
}
|
||||
|
||||
conv_chunk *get_conv(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (conv_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_decl(decl_chunk *d) {
|
||||
d->tag = convert_intel32(d->tag);
|
||||
d->val = convert_intel32(d->val);
|
||||
d->flags = convert_intel32(d->flags);
|
||||
}
|
||||
|
||||
decl_chunk *get_decl(Conv *c, int32 cSize) {
|
||||
return (decl_chunk *)&c->conv[cSize];
|
||||
}
|
||||
|
||||
static void swap_fall(fall_chunk *l) {
|
||||
l->tag = convert_intel32(l->tag);
|
||||
l->val = convert_intel32(l->val);
|
||||
l->index = convert_intel32(l->index);
|
||||
}
|
||||
|
||||
fall_chunk *get_fall(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (fall_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_lnode(lnode_chunk *l) {
|
||||
l->tag = convert_intel32(l->tag);
|
||||
l->hash = convert_intel32(l->hash);
|
||||
l->size = convert_intel32(l->size);
|
||||
l->entry_num = convert_intel32(l->entry_num);
|
||||
l->num_entries = convert_intel32(l->num_entries);
|
||||
|
||||
int32 *L = (int32 *)l;
|
||||
L += 5;
|
||||
for (int i = 0; i < l->num_entries; i++) {
|
||||
L[i] = convert_intel32(L[i]);
|
||||
}
|
||||
}
|
||||
|
||||
lnode_chunk *get_lnode(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (lnode_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_node(node_chunk *n) {
|
||||
n->tag = convert_intel32(n->tag);
|
||||
n->hash = convert_intel32(n->hash);
|
||||
n->size = convert_intel32(n->size);
|
||||
n->num_entries = convert_intel32(n->num_entries);
|
||||
|
||||
int32 *L = (int32 *)(n + 1);
|
||||
|
||||
for (int i = 0; i < n->num_entries; i++) {
|
||||
L[i] = convert_intel32(L[i]);
|
||||
}
|
||||
}
|
||||
|
||||
node_chunk *get_node(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (node_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_entry(entry_chunk *e) {
|
||||
e->tag = convert_intel32(e->tag);
|
||||
e->size = convert_intel32(e->size);
|
||||
e->status = convert_intel32(e->status);
|
||||
}
|
||||
|
||||
entry_chunk *get_entry(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (entry_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
entry_chunk *get_hash_entry(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[0]);
|
||||
return (entry_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_text(text_chunk *t) {
|
||||
t->tag = convert_intel32(t->tag);
|
||||
t->size = convert_intel32(t->size);
|
||||
}
|
||||
|
||||
text_chunk *get_text(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (text_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_mesg(mesg_chunk *m) {
|
||||
m->tag = convert_intel32(m->tag);
|
||||
m->size = convert_intel32(m->size);
|
||||
}
|
||||
|
||||
mesg_chunk *get_mesg(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (mesg_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_reply(reply_chunk *r) {
|
||||
r->tag = convert_intel32(r->tag);
|
||||
r->index = convert_intel32(r->index);
|
||||
}
|
||||
|
||||
reply_chunk *get_reply(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (reply_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_c_reply(c_reply_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
c->op_l = convert_intel32(c->op_l);
|
||||
c->op = convert_intel32(c->op);
|
||||
c->op_r = convert_intel32(c->op_r);
|
||||
c->index = convert_intel32(c->index);
|
||||
}
|
||||
|
||||
c_reply_chunk *get_c_reply(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (c_reply_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_w_reply(w_reply_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
c->num_replies = convert_intel32(c->num_replies);
|
||||
}
|
||||
|
||||
w_reply_chunk *get_w_reply(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (w_reply_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_w_entry(w_entry_chunk *w) {
|
||||
w->weight = convert_intel32(w->weight);
|
||||
w->index = convert_intel32(w->index);
|
||||
}
|
||||
|
||||
w_entry_chunk *get_w_entry(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (w_entry_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_goto(goto_chunk *g) {
|
||||
g->tag = convert_intel32(g->tag);
|
||||
g->index = convert_intel32(g->index);
|
||||
}
|
||||
|
||||
goto_chunk *get_goto(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (goto_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_c_goto(c_goto_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
c->opnd1 = convert_intel32(c->opnd1);
|
||||
c->op = convert_intel32(c->op);
|
||||
c->opnd2 = convert_intel32(c->opnd2);
|
||||
c->index = convert_intel32(c->index);
|
||||
}
|
||||
|
||||
c_goto_chunk *get_c_goto(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (c_goto_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_misc(misc_chunk *m) {
|
||||
m->tag = convert_intel32(m->tag);
|
||||
m->index = convert_intel32(m->index);
|
||||
}
|
||||
|
||||
misc_chunk *get_misc(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (misc_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
static void swap_c_misc(c_misc_chunk *c) {
|
||||
c->tag = convert_intel32(c->tag);
|
||||
|
||||
c->c_op_l = convert_intel32(c->c_op_l);
|
||||
c->c_op = convert_intel32(c->c_op);
|
||||
c->c_op_r = convert_intel32(c->c_op_r);
|
||||
|
||||
c->index = convert_intel32(c->index);
|
||||
}
|
||||
|
||||
c_misc_chunk *get_c_misc(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
return (c_misc_chunk *)&s[cSize];
|
||||
}
|
||||
|
||||
int32 get_long(Conv *c, int32 cSize) {
|
||||
char *s = &(c->conv[c->myCNode]);
|
||||
int32 *l = (int32 *)&s[cSize];
|
||||
return *l;
|
||||
}
|
||||
|
||||
char *get_string(Conv *c, int32 cSize) {
|
||||
return &c->conv[cSize];
|
||||
}
|
||||
|
||||
int conv_ops_cond_successful(int32 l_op, int32 op, int32 r_op) {
|
||||
switch (op) {
|
||||
case PERCENT:
|
||||
return l_op % r_op;
|
||||
|
||||
case GE:
|
||||
return l_op >= r_op;
|
||||
|
||||
case LE:
|
||||
return l_op <= r_op;
|
||||
|
||||
case GT:
|
||||
return l_op > r_op;
|
||||
|
||||
case LT:
|
||||
return l_op < r_op;
|
||||
|
||||
case NE:
|
||||
case CNE:
|
||||
return !(l_op == r_op);
|
||||
|
||||
case IS_ASSIGNED:
|
||||
return l_op == r_op;
|
||||
|
||||
case ANDAND:
|
||||
return l_op && r_op;
|
||||
|
||||
case OROR:
|
||||
return l_op || r_op;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 conv_ops_process_asgn(int32 val, int32 oprtr, int32 opnd) {
|
||||
switch (oprtr) {
|
||||
case PPLUS:
|
||||
val += opnd;
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
val -= opnd;
|
||||
break;
|
||||
|
||||
case TIMES:
|
||||
val *= opnd;
|
||||
break;
|
||||
|
||||
case DIVIDE:
|
||||
val /= opnd;
|
||||
break;
|
||||
|
||||
case IS_ASSIGNED:
|
||||
val = opnd;
|
||||
break;
|
||||
|
||||
default:
|
||||
error_show(FL, 'PARS', "Operator must be a +,-,*,/,=, Please check tag type: %d in token header file", oprtr);
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void conv_swap_words(Conv *c) {
|
||||
int32 ent = 0, tag = 0, next;
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
c->myCNode = 0;
|
||||
const int32 ent_old = c->myCNode;
|
||||
c->myCNode = 0;
|
||||
|
||||
_GC(swap) = true;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
switch (tag) {
|
||||
case C_ASGN_CHUNK: {
|
||||
c_assign_chunk *c_asgn = get_c_asgn(c, ent);
|
||||
swap_c_asgn(c_asgn);
|
||||
}
|
||||
break;
|
||||
|
||||
case ASGN_CHUNK: {
|
||||
assign_chunk *asgn = get_asgn(c, ent);
|
||||
swap_assign(asgn);
|
||||
}
|
||||
break;
|
||||
|
||||
case HIDE_CHUNK:
|
||||
case DSTR_CHUNK:
|
||||
case UHID_CHUNK: {
|
||||
misc_chunk *misc = get_misc(c, ent);
|
||||
swap_misc(misc);
|
||||
}
|
||||
break;
|
||||
|
||||
case CHDE_CHUNK:
|
||||
case CUHD_CHUNK:
|
||||
case CDST_CHUNK: {
|
||||
c_misc_chunk *c_misc = get_c_misc(c, ent);
|
||||
swap_c_misc(c_misc);
|
||||
}
|
||||
break;
|
||||
|
||||
case CONV_CHUNK: {
|
||||
conv_chunk *conv = get_conv(c, ent);
|
||||
swap_conv(conv);
|
||||
}
|
||||
break;
|
||||
|
||||
case DECL_CHUNK: {
|
||||
decl_chunk *decl = get_decl(c, ent);
|
||||
swap_decl(decl);
|
||||
}
|
||||
break;
|
||||
|
||||
case FALL_CHUNK: {
|
||||
fall_chunk *fall = get_fall(c, ent);
|
||||
swap_fall(fall);
|
||||
}
|
||||
break;
|
||||
|
||||
case LNODE_CHUNK: {
|
||||
lnode_chunk *lnode = get_lnode(c, ent);
|
||||
swap_lnode(lnode);
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_CHUNK: {
|
||||
node_chunk *node = get_node(c, ent);
|
||||
swap_node(node);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENTRY_CHUNK: {
|
||||
entry_chunk *entry = get_entry(c, ent);
|
||||
swap_entry(entry);
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXT_CHUNK: {
|
||||
text_chunk *text = get_text(c, ent);
|
||||
swap_text(text);
|
||||
}
|
||||
break;
|
||||
|
||||
case REPLY_CHUNK: {
|
||||
reply_chunk *reply = get_reply(c, ent);
|
||||
swap_reply(reply);
|
||||
}
|
||||
break;
|
||||
|
||||
case WEIGHT_REPLY_CHUNK:
|
||||
case WEIGHT_PREPLY_CHUNK: {
|
||||
w_reply_chunk *w_reply = get_w_reply(c, ent);
|
||||
swap_w_reply(w_reply);
|
||||
|
||||
int32 tempEnt = ent + sizeof(w_reply_chunk);
|
||||
|
||||
for (int x = 0; x < w_reply->num_replies; x++) {
|
||||
w_entry_chunk *w_entry = get_w_entry(c, tempEnt);
|
||||
swap_w_entry(w_entry);
|
||||
tempEnt += sizeof(w_entry_chunk);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case COND_REPLY_CHUNK: {
|
||||
c_reply_chunk *c_reply = get_c_reply(c, ent);
|
||||
swap_c_reply(c_reply);
|
||||
}
|
||||
break;
|
||||
|
||||
case MESSAGE_CHUNK: {
|
||||
mesg_chunk *mesg = get_mesg(c, ent);
|
||||
swap_mesg(mesg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GOTO_CHUNK:
|
||||
case EXIT_GOTO_CHUNK: {
|
||||
goto_chunk *go = get_goto(c, ent);
|
||||
swap_goto(go);
|
||||
}
|
||||
break;
|
||||
|
||||
case COND_GOTO_CHUNK:
|
||||
case COND_EXIT_GOTO_CHUNK: {
|
||||
c_goto_chunk *c_goto = get_c_goto(c, ent);
|
||||
swap_c_goto(c_goto);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ent = next;
|
||||
}
|
||||
|
||||
_GC(swap) = false;
|
||||
c->myCNode = ent_old;
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
94
engines/m4/adv_r/chunk_ops.h
Normal file
94
engines/m4/adv_r/chunk_ops.h
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
/* 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 M4_ADV_R_CHUNK_OPS_H
|
||||
#define M4_ADV_R_CHUNK_OPS_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/conv.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define PPLUS 402
|
||||
#define MINUS 403
|
||||
#define TIMES 404
|
||||
#define PERCENT 405
|
||||
#define POWER 406
|
||||
#define IS_ASSIGNED 407
|
||||
#define PERIOD 410
|
||||
#define DOLLAR 411
|
||||
#define LT 412
|
||||
#define GT 413
|
||||
#define L_BRAK 416
|
||||
#define R_BRAK 417
|
||||
|
||||
#define DIVIDE 418
|
||||
#define NOT 419
|
||||
|
||||
#define LE 420
|
||||
#define GE 421
|
||||
#define NE 422
|
||||
#define PE 423
|
||||
#define ME 424
|
||||
#define TE 425
|
||||
#define DE 426
|
||||
#define AE 427
|
||||
#define OE 428
|
||||
#define EQ 429
|
||||
#define AND 430
|
||||
#define OR 431
|
||||
#define TILDA 432
|
||||
#define DBL_QUOTE 433
|
||||
#define ANDAND 444
|
||||
#define OROR 445
|
||||
#define DOT 446
|
||||
#define CNE 448
|
||||
|
||||
conv_chunk *get_conv(Conv *c, int32 cSize);
|
||||
entry_chunk *get_entry(Conv *c, int32 cSize);
|
||||
char *conv_ops_get_entry(int32 i, int32 *next, int32 *tag, Conv *c);
|
||||
void conv_ops_unknown_chunk(int32 tag, const char *s);
|
||||
decl_chunk *get_decl(Conv *c, int32 cSize);
|
||||
char *get_string(Conv *c, int32 cSize);
|
||||
text_chunk *get_text(Conv *c, int32 cSize);
|
||||
int32 conv_ops_text_strlen(char *s);
|
||||
c_assign_chunk *get_c_asgn(Conv *c, int32 cSize);
|
||||
int conv_ops_cond_successful(int32 l_op, int32 op, int32 r_op);
|
||||
int32 conv_ops_process_asgn(int32 val, int32 oprtr, int32 opnd);
|
||||
assign_chunk *get_asgn(Conv *c, int32 cSize);
|
||||
misc_chunk *get_misc(Conv *c, int32 cSize);
|
||||
entry_chunk *get_hash_entry(Conv *c, int32 cSize);
|
||||
c_misc_chunk *get_c_misc(Conv *c, int32 cSize);
|
||||
c_goto_chunk *get_c_goto(Conv *c, int32 cSize);
|
||||
goto_chunk *get_goto(Conv *c, int32 cSize);
|
||||
reply_chunk *get_reply(Conv *c, int32 cSize);
|
||||
lnode_chunk *get_lnode(Conv *c, int32 cSize);
|
||||
node_chunk *get_node(Conv *c, int32 cSize);
|
||||
fall_chunk *get_fall(Conv *c, int32 cSize);
|
||||
int32 get_long(Conv *c, int32 cSize);
|
||||
c_reply_chunk *get_c_reply(Conv *c, int32 cSize);
|
||||
w_reply_chunk *get_w_reply(Conv *c, int32 cSize);
|
||||
w_entry_chunk *get_w_entry(Conv *c, int32 cSize);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
956
engines/m4/adv_r/conv.cpp
Normal file
956
engines/m4/adv_r/conv.cpp
Normal file
@@ -0,0 +1,956 @@
|
||||
/* 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 "m4/adv_r/conv.h"
|
||||
#include "m4/adv_r/adv_control.h"
|
||||
#include "m4/adv_r/chunk_ops.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/gui/gui_univ.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/vars.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
// ---------------
|
||||
// Set entry stats,
|
||||
// Get next node pointer
|
||||
// Process declarations
|
||||
// Get message text
|
||||
static void conv_exec_entry(int32 offset, Conv *c) {
|
||||
int32 i = offset;
|
||||
int32 tag, next;
|
||||
|
||||
goto_chunk *go;
|
||||
c_goto_chunk *c_goto;
|
||||
decl_chunk *decl;
|
||||
assign_chunk *asgn;
|
||||
c_assign_chunk *c_asgn;
|
||||
misc_chunk *misc;
|
||||
c_misc_chunk *c_misc;
|
||||
|
||||
int32 l_op;
|
||||
int32 r_op;
|
||||
|
||||
entry_chunk *entry = get_entry(c, i);
|
||||
const int32 entry_count = entry->size;
|
||||
entry->status = conv_toggle_flags(entry);
|
||||
|
||||
i += sizeof(entry_chunk);
|
||||
|
||||
while (i < offset + entry_count) {
|
||||
conv_ops_get_entry(i, &next, &tag, c);
|
||||
|
||||
switch (tag) {
|
||||
case TEXT_CHUNK:
|
||||
case MESSAGE_CHUNK:
|
||||
case ENTRY_CHUNK:
|
||||
case FALL_CHUNK:
|
||||
break;
|
||||
|
||||
case C_ASGN_CHUNK:
|
||||
c_asgn = get_c_asgn(c, i);
|
||||
|
||||
decl = get_decl(c, c_asgn->c_op_l);
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_asgn->c_op, c_asgn->c_op_r)) {
|
||||
decl = get_decl(c, c_asgn->index);
|
||||
conv_set_decl_val(c, decl, conv_ops_process_asgn(conv_get_decl_val(c, decl), c_asgn->op, c_asgn->opnd1));
|
||||
}
|
||||
break;
|
||||
|
||||
case ASGN_CHUNK:
|
||||
asgn = get_asgn(c, i);
|
||||
decl = get_decl(c, asgn->index);
|
||||
conv_set_decl_val(c, decl, conv_ops_process_asgn(conv_get_decl_val(c, decl), asgn->op, asgn->opnd1));
|
||||
break;
|
||||
|
||||
case HIDE_CHUNK:
|
||||
misc = get_misc(c, i);
|
||||
entry = get_hash_entry(c, misc->index);
|
||||
|
||||
if (!(entry->status & DESTROYED))
|
||||
entry->status |= HIDDEN;
|
||||
break;
|
||||
|
||||
case CHDE_CHUNK:
|
||||
c_misc = get_c_misc(c, i);
|
||||
entry = get_hash_entry(c, c_misc->index);
|
||||
|
||||
decl = get_decl(c, c_misc->c_op_l);
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r)) {
|
||||
if (!(entry->status & DESTROYED))
|
||||
entry->status |= HIDDEN;
|
||||
}
|
||||
break;
|
||||
|
||||
case UHID_CHUNK:
|
||||
misc = get_misc(c, i);
|
||||
entry = get_hash_entry(c, misc->index);
|
||||
if (!(entry->status & DESTROYED)) {
|
||||
entry->status &= 0xfffffffb; // Mask HIDDEN bit
|
||||
entry->status |= 0x00000001;
|
||||
}
|
||||
break;
|
||||
|
||||
case CUHD_CHUNK:
|
||||
c_misc = get_c_misc(c, i);
|
||||
entry = get_hash_entry(c, c_misc->index);
|
||||
|
||||
decl = get_decl(c, c_misc->c_op_l);
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r)) {
|
||||
if (!(entry->status & DESTROYED)) {
|
||||
entry->status &= 0xfffffffb;
|
||||
entry->status |= 0x00000001;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DSTR_CHUNK:
|
||||
misc = get_misc(c, i);
|
||||
entry = get_hash_entry(c, misc->index);
|
||||
entry->status |= DESTROYED;
|
||||
break;
|
||||
|
||||
case CDST_CHUNK:
|
||||
c_misc = get_c_misc(c, i);
|
||||
entry = get_hash_entry(c, c_misc->index);
|
||||
|
||||
decl = get_decl(c, c_misc->c_op_l);
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r))
|
||||
entry->status |= DESTROYED;
|
||||
break;
|
||||
|
||||
case COND_GOTO_CHUNK:
|
||||
c_goto = get_c_goto(c, i);
|
||||
decl = get_decl(c, c_goto->opnd1);
|
||||
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
r_op = c_goto->opnd2; //val
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_goto->op, r_op)) {
|
||||
c->myCNode = c_goto->index;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case COND_EXIT_GOTO_CHUNK:
|
||||
c_goto = get_c_goto(c, i);
|
||||
decl = get_decl(c, c_goto->opnd1);
|
||||
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
r_op = c_goto->opnd2; //val
|
||||
|
||||
if (conv_ops_cond_successful(l_op, c_goto->op, r_op)) {
|
||||
if (c_goto->index != CONV_QUIT) { //was go->index
|
||||
c->myCNode = c_goto->index; //was go->index
|
||||
c->exit_now = CONV_BAIL;
|
||||
} else {
|
||||
c->exit_now = CONV_QUIT;
|
||||
c->myCNode = CONV_QUIT;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXIT_GOTO_CHUNK:
|
||||
go = get_goto(c, i);
|
||||
|
||||
if (go->index != CONV_QUIT) {
|
||||
c->myCNode = go->index;
|
||||
c->exit_now = CONV_BAIL;
|
||||
} else {
|
||||
c->exit_now = CONV_QUIT;
|
||||
c->myCNode = CONV_QUIT;
|
||||
}
|
||||
return;
|
||||
|
||||
case GOTO_CHUNK:
|
||||
go = get_goto(c, i);
|
||||
c->myCNode = go->index;
|
||||
return;
|
||||
|
||||
// Replies are non-player responses
|
||||
case REPLY_CHUNK:
|
||||
case COND_REPLY_CHUNK:
|
||||
case WEIGHT_REPLY_CHUNK:
|
||||
case WEIGHT_PREPLY_CHUNK:
|
||||
break;
|
||||
|
||||
default:
|
||||
conv_ops_unknown_chunk(tag, "conv_exec_entry");
|
||||
break;
|
||||
}
|
||||
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
static int conv_get_mesg(int32 offset, int32 is_valid, Conv *c) {
|
||||
int32 i = offset;
|
||||
int32 x, y, s_offset = 0, cSize;
|
||||
int32 tag, next;
|
||||
int32 text_len;
|
||||
int sum, result = 0;
|
||||
|
||||
decl_chunk *decl;
|
||||
reply_chunk *reply;
|
||||
c_reply_chunk *c_reply;
|
||||
w_reply_chunk *w_reply;
|
||||
w_entry_chunk *w_entry;
|
||||
|
||||
int32 l_op;
|
||||
int32 r_op;
|
||||
|
||||
entry_chunk *entry = get_entry(c, i);
|
||||
const int32 entry_count = entry->size;
|
||||
|
||||
i += sizeof(entry_chunk);
|
||||
|
||||
while (i < offset + entry_count) {
|
||||
conv_ops_get_entry(i, &next, &tag, c);
|
||||
|
||||
switch (tag) {
|
||||
case TEXT_CHUNK:
|
||||
case MESSAGE_CHUNK:
|
||||
case ENTRY_CHUNK:
|
||||
case FALL_CHUNK:
|
||||
case C_ASGN_CHUNK:
|
||||
case ASGN_CHUNK:
|
||||
case HIDE_CHUNK:
|
||||
case CHDE_CHUNK:
|
||||
case UHID_CHUNK:
|
||||
case CUHD_CHUNK:
|
||||
case DSTR_CHUNK:
|
||||
case CDST_CHUNK:
|
||||
case COND_GOTO_CHUNK:
|
||||
case COND_EXIT_GOTO_CHUNK:
|
||||
case EXIT_GOTO_CHUNK:
|
||||
case GOTO_CHUNK:
|
||||
break;
|
||||
|
||||
case REPLY_CHUNK:
|
||||
reply = get_reply(c, i);
|
||||
|
||||
if (is_valid) {
|
||||
result = 1;
|
||||
_G(cdd).player_non_player = 0;
|
||||
|
||||
if (!strcmp(_G(cdd).mesg, "")) {
|
||||
text_len = conv_ops_text_strlen(get_string(c, reply->index + sizeof(mesg_chunk)));
|
||||
|
||||
Common::strcpy_s(_G(cdd).mesg, get_string(c, reply->index + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, reply->index + sizeof(mesg_chunk));
|
||||
|
||||
} else {
|
||||
Common::strcat_s(_G(cdd).mesg, " ");
|
||||
text_len = conv_ops_text_strlen(get_string(c, reply->index + sizeof(mesg_chunk)));
|
||||
Common::strcat_s(_G(cdd).mesg, get_string(c, reply->index + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, reply->index + sizeof(mesg_chunk));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case COND_REPLY_CHUNK:
|
||||
c_reply = get_c_reply(c, i);
|
||||
decl = get_decl(c, c_reply->op_l);
|
||||
|
||||
l_op = conv_get_decl_val(c, decl);
|
||||
r_op = c_reply->op_r; //val
|
||||
|
||||
if (is_valid && conv_ops_cond_successful(l_op, c_reply->op, r_op)) {
|
||||
result = 1;
|
||||
_G(cdd).player_non_player = 0;
|
||||
|
||||
if (!strcmp(_G(cdd).mesg, "")) {
|
||||
text_len = conv_ops_text_strlen(get_string(c, c_reply->index + sizeof(mesg_chunk)));
|
||||
Common::strcpy_s(_G(cdd).mesg, get_string(c, c_reply->index + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, c_reply->index + sizeof(mesg_chunk));
|
||||
|
||||
} else {
|
||||
Common::strcat_s(_G(cdd).mesg, " ");
|
||||
text_len = conv_ops_text_strlen(get_string(c, c_reply->index + sizeof(mesg_chunk)));
|
||||
Common::strcat_s(_G(cdd).mesg, get_string(c, c_reply->index + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, c_reply->index + sizeof(mesg_chunk));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WEIGHT_REPLY_CHUNK:
|
||||
cSize = i;
|
||||
w_reply = get_w_reply(c, i);
|
||||
cSize += sizeof(w_reply_chunk);
|
||||
|
||||
sum = 0;
|
||||
for (x = 0; x < w_reply->num_replies; x++) {
|
||||
w_entry = get_w_entry(c, cSize);
|
||||
sum += w_entry->weight;
|
||||
cSize += sizeof(w_entry_chunk);
|
||||
}
|
||||
y = g_engine->getRandomNumber(sum - 1) + 1;
|
||||
|
||||
cSize = i;
|
||||
w_reply = get_w_reply(c, i);
|
||||
cSize += sizeof(w_reply_chunk);
|
||||
|
||||
sum = 0;
|
||||
for (x = 0; (x < w_reply->num_replies) && (sum < y); x++) {
|
||||
w_entry = get_w_entry(c, cSize);
|
||||
s_offset = w_entry->index;
|
||||
sum += w_entry->weight;
|
||||
cSize += sizeof(w_entry_chunk);
|
||||
}
|
||||
|
||||
if (is_valid) {
|
||||
result = 1;
|
||||
_G(cdd).player_non_player = 0;
|
||||
|
||||
if (!strcmp(_G(cdd).mesg, "")) {
|
||||
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
|
||||
Common::strcpy_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
|
||||
} else {
|
||||
Common::strcat_s(_G(cdd).mesg, " ");
|
||||
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
|
||||
Common::strcat_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WEIGHT_PREPLY_CHUNK:
|
||||
cSize = i;
|
||||
w_reply = get_w_reply(c, i);
|
||||
cSize += sizeof(w_reply_chunk);
|
||||
|
||||
sum = 0;
|
||||
for (x = 0; x < w_reply->num_replies; x++) {
|
||||
w_entry = get_w_entry(c, cSize);
|
||||
sum += w_entry->weight;
|
||||
cSize += sizeof(w_entry_chunk);
|
||||
}
|
||||
y = g_engine->getRandomNumber(sum - 1) + 1;
|
||||
|
||||
cSize = i;
|
||||
w_reply = get_w_reply(c, i);
|
||||
cSize += sizeof(w_reply_chunk);
|
||||
|
||||
sum = 0;
|
||||
for (x = 0; (x < w_reply->num_replies) && (sum < y); x++) {
|
||||
w_entry = get_w_entry(c, cSize);
|
||||
s_offset = w_entry->index;
|
||||
sum += w_entry->weight;
|
||||
cSize += sizeof(w_entry_chunk);
|
||||
}
|
||||
|
||||
if (is_valid) {
|
||||
result = 1;
|
||||
_G(cdd).player_non_player = 1;
|
||||
|
||||
if (!strcmp(_G(cdd).mesg, "")) {
|
||||
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
|
||||
Common::strcpy_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
|
||||
} else {
|
||||
Common::strcat_s(_G(cdd).mesg, " ");
|
||||
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
|
||||
Common::strcat_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
|
||||
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
conv_ops_unknown_chunk(tag, "conv_get_mesg");
|
||||
break;
|
||||
}
|
||||
i = next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void find_true_ent(int entry_num, Conv *c) {
|
||||
int32 ent = 0, n = 0;
|
||||
int32 next = 0, tag = 0, num_ents = 0;
|
||||
int i;
|
||||
|
||||
// Start by getting the current NODE or LNODE
|
||||
node_chunk *node;
|
||||
lnode_chunk *lnode;
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
switch (tag) {
|
||||
case LNODE_CHUNK:
|
||||
lnode = get_lnode(c, ent);
|
||||
ent += sizeof(lnode_chunk);
|
||||
num_ents = lnode->num_entries;
|
||||
entry_num = lnode->entry_num;
|
||||
c->node_hash = lnode->hash;
|
||||
break;
|
||||
|
||||
case NODE_CHUNK:
|
||||
node = get_node(c, ent);
|
||||
ent += sizeof(node_chunk);
|
||||
num_ents = node->num_entries;
|
||||
c->node_hash = node->hash;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// ent will now be pointing at an ENTRY or FALLTHROUGH
|
||||
const int32 sub_ent = next;
|
||||
conv_ops_get_entry(sub_ent, &next, &tag, c);
|
||||
if (tag == FALL_CHUNK) {
|
||||
// We either want to jump to a new node
|
||||
// or skip to the first offset.
|
||||
|
||||
fall_chunk *fall = get_fall(c, sub_ent);
|
||||
assert(fall);
|
||||
|
||||
//do this to skip the fall chunk and all will be fine.
|
||||
ent += sizeof(int32); //was get_long, sizeof( fall_chunk )
|
||||
}
|
||||
|
||||
_GC(ent) = 0;
|
||||
|
||||
// Not only i<entry_num, check to see entry->num_entries
|
||||
for (i = 0, n = 0; n < num_ents; n++) {
|
||||
const int32 offset = get_long(c, ent);
|
||||
entry_chunk *entry = get_entry(c, ent + offset);
|
||||
|
||||
if (i == entry_num)
|
||||
break;
|
||||
|
||||
if ((entry->status & 0x00000003) && ok_status(entry)) //was 1
|
||||
i++;
|
||||
|
||||
_GC(ent)++;
|
||||
|
||||
ent += sizeof(int32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Simplify me now that all changes have been made.
|
||||
static int conv_get_node_text(Conv *c) {
|
||||
lnode_chunk *lnode = nullptr;
|
||||
node_chunk *node;
|
||||
entry_chunk *entry = nullptr;
|
||||
fall_chunk *fall = nullptr;
|
||||
|
||||
int32 ent = 0, offset = 0, tag, next, num_ents = 0;
|
||||
int i = 0, num_vis = 0, result = 0;
|
||||
|
||||
_G(cdd).num_txt_ents = 0;
|
||||
_GC(width) = 0; _GC(height) = 0;
|
||||
|
||||
// conv _get_node_text will either get a NODE or LNODE
|
||||
conv_ops_get_entry(offset, &next, &tag, c);
|
||||
offset = 0; //not needed.?
|
||||
_GC(n_t_e) = 0;
|
||||
|
||||
switch (tag) {
|
||||
case LNODE_CHUNK:
|
||||
lnode = get_lnode(c, offset);
|
||||
offset += sizeof(lnode_chunk);
|
||||
num_ents = lnode->num_entries;
|
||||
c->node_hash = lnode->hash;
|
||||
break;
|
||||
|
||||
case NODE_CHUNK:
|
||||
node = get_node(c, offset);
|
||||
offset += sizeof(node_chunk);
|
||||
num_ents = node->num_entries;
|
||||
c->node_hash = node->hash;
|
||||
break;
|
||||
|
||||
default:
|
||||
// handle error.
|
||||
break;
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case LNODE_CHUNK:
|
||||
// was in bounds.
|
||||
// lnode->entry_num starts at 0. in the chunk.
|
||||
if (lnode->entry_num >= lnode->num_entries)
|
||||
lnode->entry_num = 0;
|
||||
|
||||
for (i = 0; (i <= lnode->entry_num) && (i < num_ents); i++) {
|
||||
ent = get_long(c, offset);
|
||||
entry = get_entry(c, offset + ent);
|
||||
|
||||
offset += sizeof(int32);
|
||||
}
|
||||
|
||||
offset -= sizeof(int32);
|
||||
|
||||
// Set sound file name instead.?
|
||||
if ((entry->status != 0) && (num_ents != 0) && ok_status(entry)) {
|
||||
//here here here.
|
||||
if (conv_get_text(offset + ent, entry->size, c)) {
|
||||
result = 1;
|
||||
|
||||
_G(cdd).num_txt_ents = 0;
|
||||
_G(cdd).mesg_snd_file = _G(cdd).snd_files[0];
|
||||
|
||||
_G(cdd).text[0] = nullptr;
|
||||
_G(cdd).snd_files[0] = nullptr;
|
||||
_G(cdd).player_non_player = 1;
|
||||
c->c_entry_num = lnode->entry_num;
|
||||
}
|
||||
num_vis++;
|
||||
}
|
||||
|
||||
lnode->entry_num++;
|
||||
|
||||
_GC(ent) = lnode->entry_num;
|
||||
break;
|
||||
|
||||
case NODE_CHUNK:
|
||||
for (i = 0; i < num_ents; i++) {
|
||||
|
||||
ent = get_long(c, offset);
|
||||
entry = get_entry(c, offset + ent);
|
||||
|
||||
if (entry->tag != FALL_CHUNK) {
|
||||
if ((entry->status != 0) && ok_status(entry)) {
|
||||
if (conv_get_text(offset + ent, entry->size, c)) {
|
||||
result = 1;
|
||||
|
||||
_G(cdd).player_non_player = 1;
|
||||
}
|
||||
num_vis++;
|
||||
_GC(n_t_e)++;
|
||||
}
|
||||
} else {
|
||||
fall = get_fall(c, offset + ent);
|
||||
}
|
||||
|
||||
offset += sizeof(int32);
|
||||
}
|
||||
|
||||
if (fall) {
|
||||
if (num_vis <= fall->val) {
|
||||
_GC(n_t_e) = 0;
|
||||
|
||||
c->myCNode = fall->index;
|
||||
c->mode = CONV_GET_TEXT_MODE;
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void conv_shutdown() {
|
||||
if (conv_get_handle())
|
||||
conv_unload(conv_get_handle());
|
||||
|
||||
if (_GC(myTextScrn))
|
||||
TextScrn_Destroy(_GC(myTextScrn));
|
||||
_GC(myTextScrn) = nullptr;
|
||||
}
|
||||
|
||||
static void conv_start(Conv *c) {
|
||||
int32 ok = 1, ent = 0, tag = 0, next;
|
||||
decl_chunk *decl;
|
||||
|
||||
switch (c->exit_now) {
|
||||
case CONV_OK:
|
||||
// Potential prob. when entering while loop.
|
||||
break;
|
||||
|
||||
// Goto_exit encountered.
|
||||
// a conversation state.
|
||||
case CONV_BAIL:
|
||||
return;
|
||||
|
||||
// Goodbye forever.
|
||||
case CONV_QUIT:
|
||||
return;
|
||||
|
||||
//new conv. no restore file on hard disk.
|
||||
case CONV_NEW:
|
||||
c->exit_now = CONV_OK;
|
||||
c->myCNode = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((ent < c->chunkSize) && ok) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c); //ok if c->myCNode = 0
|
||||
|
||||
switch (tag) {
|
||||
case LNODE_CHUNK:
|
||||
case NODE_CHUNK:
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
case DECL_CHUNK:
|
||||
decl = get_decl(c, ent);
|
||||
assert(decl);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
ent = next;
|
||||
}
|
||||
c->myCNode = ent;
|
||||
|
||||
// if we exit, the current node is set, the next node is null
|
||||
}
|
||||
|
||||
static int conv_next_node(Conv *c) {
|
||||
if (c->myCNode == -1)
|
||||
return 0;
|
||||
|
||||
switch (c->exit_now) {
|
||||
case CONV_OK:
|
||||
return 1;
|
||||
|
||||
case CONV_QUIT:
|
||||
case CONV_BAIL:
|
||||
return 0;
|
||||
|
||||
case CONV_NEW:
|
||||
conv_start(c); // Should go in conv_load.
|
||||
return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int conv_process_entry(int entry_num, Conv *c, int mode) {
|
||||
node_chunk *node;
|
||||
lnode_chunk *lnode;
|
||||
int32 offset = 0, ent = 0, is_valid = 0, n = 0;
|
||||
int32 next = 0, tag = 0, num_ents = 0;
|
||||
int i = 0;
|
||||
int result = 1;
|
||||
|
||||
// Start by getting the current NODE or LNODE
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
switch (tag) {
|
||||
case LNODE_CHUNK:
|
||||
lnode = get_lnode(c, ent);
|
||||
ent += sizeof(lnode_chunk);
|
||||
num_ents = lnode->num_entries;
|
||||
entry_num = lnode->entry_num;
|
||||
c->node_hash = lnode->hash;
|
||||
break;
|
||||
|
||||
case NODE_CHUNK:
|
||||
node = get_node(c, ent);
|
||||
ent += sizeof(node_chunk);
|
||||
num_ents = node->num_entries;
|
||||
c->node_hash = node->hash;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// ent will now be pointing at an ENTRY or FALLTHROUGH
|
||||
const int32 sub_ent = next;
|
||||
conv_ops_get_entry(sub_ent, &next, &tag, c);
|
||||
if (tag == FALL_CHUNK) {
|
||||
// We either want to jump to a new node
|
||||
// or skip to the first offset.
|
||||
|
||||
fall_chunk *fall = get_fall(c, sub_ent);
|
||||
assert(fall);
|
||||
|
||||
// Do this to skip the fall chunk and all will be fine.
|
||||
ent += sizeof(int32); //was get_long, sizeof( fall_chunk )
|
||||
n++; //don't increment i.
|
||||
}
|
||||
|
||||
|
||||
// Not only i<entry_num, check to see entry->num_entries
|
||||
while ((i < entry_num) && (n < num_ents)) {
|
||||
offset = get_long(c, ent);
|
||||
entry_chunk *entry = get_entry(c, ent + offset);
|
||||
|
||||
if ((entry->status != 0) && ok_status(entry)) {
|
||||
i++;
|
||||
is_valid = 1;
|
||||
}
|
||||
|
||||
ent += sizeof(int32);
|
||||
n++;
|
||||
}
|
||||
|
||||
ent -= sizeof(int32);
|
||||
|
||||
if (is_valid) {
|
||||
switch (mode) {
|
||||
case CONV_GET_MESG_MODE:
|
||||
result = conv_get_mesg(ent + offset, is_valid, c);
|
||||
break;
|
||||
|
||||
case CONV_UPDATE_MODE:
|
||||
conv_exec_entry(ent + offset, c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void textBoxInit();
|
||||
|
||||
static int conv_run(Conv *c) {
|
||||
if (!c)
|
||||
return 0;
|
||||
|
||||
int ok = 1;
|
||||
|
||||
if (conv_next_node(c)) {
|
||||
switch (c->exit_now) {
|
||||
case CONV_NEW:
|
||||
case CONV_QUIT:
|
||||
case CONV_BAIL:
|
||||
break;
|
||||
|
||||
case CONV_OK:
|
||||
while (ok && conv_next_node(c)) {
|
||||
switch (c->mode) {
|
||||
case CONV_GET_TEXT_MODE:
|
||||
cdd_init();
|
||||
|
||||
c->mode = CONV_GET_MESG_MODE;
|
||||
if (conv_get_node_text(c)) {
|
||||
ok = 0;
|
||||
if (_G(cdd).num_txt_ents) { //node
|
||||
mouse_unlock_sprite();
|
||||
mouse_lock_sprite(0);
|
||||
|
||||
textBoxInit();
|
||||
} else { //linear node.
|
||||
conv_set_event(-1);
|
||||
|
||||
Common::strcpy_s(_G(player).verb, _GC(conv_name)); // was verb.
|
||||
c->c_entry_num = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONV_GET_MESG_MODE:
|
||||
cdd_init();
|
||||
|
||||
if (conv_process_entry(c->c_entry_num, c, CONV_GET_MESG_MODE)) {
|
||||
mouse_unlock_sprite();
|
||||
mouse_lock_sprite(5);
|
||||
|
||||
conv_set_event(-1);
|
||||
Common::strcpy_s(_G(player).verb, _GC(conv_name));
|
||||
|
||||
ok = 0;
|
||||
}
|
||||
c->mode = CONV_UPDATE_MODE;
|
||||
break;
|
||||
|
||||
case CONV_UPDATE_MODE:
|
||||
conv_process_entry(c->c_entry_num, c, CONV_UPDATE_MODE);
|
||||
|
||||
c->mode = CONV_GET_TEXT_MODE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conv_next_node(c))
|
||||
conv_unload(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void convtestCallback(void *a, void *) {
|
||||
mouse_unlock_sprite();
|
||||
mouse_lock_sprite(5);
|
||||
|
||||
player_set_commands_allowed(false);
|
||||
TextItem *i = (TextItem *)a;
|
||||
|
||||
Conv *c = conv_get_handle();
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
c->c_entry_num = i->tag;
|
||||
c->mode = CONV_GET_MESG_MODE;
|
||||
|
||||
TextScrn_Destroy(_GC(myTextScrn));
|
||||
_GC(myTextScrn) = nullptr;
|
||||
|
||||
find_true_ent(c->c_entry_num, c);
|
||||
|
||||
_G(cdd).mesg_snd_file = _G(cdd).snd_files[c->c_entry_num - 1];
|
||||
_G(cdd).player_non_player = 1;
|
||||
|
||||
Common::strcpy_s(_G(player).verb, _GC(conv_name));
|
||||
_G(player).command_ready = true;
|
||||
conv_set_event(-1); // Must have or conv freezes.
|
||||
}
|
||||
|
||||
void set_dlg_rect() {
|
||||
int32 status;
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
if (!game_buff_ptr)
|
||||
error_show(FL, 'BUF!');
|
||||
|
||||
const int32 screen_x_center = VIDEO_W / 2;
|
||||
const int32 screen_y_center = (game_buff_ptr->y2 - game_buff_ptr->y1) / 2;
|
||||
const int32 screen_x_size = VIDEO_W;
|
||||
const int32 screen_y_size = (game_buff_ptr->y2 - game_buff_ptr->y1);
|
||||
|
||||
_GC(height) = gr_font_get_height() + _GC(conv_font_spacing_v); // Must have....
|
||||
_GC(width) += 2 * _GC(conv_font_spacing_h);
|
||||
|
||||
const int32 sizeX = _GC(width);
|
||||
const int32 sizeY = _G(cdd).num_txt_ents * (_GC(height)) + _GC(conv_font_spacing_v);
|
||||
|
||||
switch (_GC(glob_x)) {
|
||||
case DLG_CENTER_H:
|
||||
_GC(r_x1) = screen_x_center - (sizeX / 2);
|
||||
break;
|
||||
|
||||
case DLG_FLUSH_LEFT:
|
||||
_GC(r_x1) = 0;
|
||||
break;
|
||||
|
||||
case DLG_FLUSH_RIGHT:
|
||||
_GC(r_x1) = screen_x_size - sizeX;
|
||||
break;
|
||||
|
||||
default:
|
||||
_GC(r_x1) = _GC(glob_x);
|
||||
_GC(r_x1) += game_buff_ptr->x1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_GC(glob_y)) {
|
||||
case DLG_CENTER_V:
|
||||
_GC(r_y1) = screen_y_center - (sizeY / 2);
|
||||
break;
|
||||
|
||||
case DLG_FLUSH_TOP:
|
||||
_GC(r_y1) = 0;
|
||||
break;
|
||||
|
||||
case DLG_FLUSH_BOTTOM:
|
||||
_GC(r_y1) = screen_y_size - sizeY + game_buff_ptr->y1 - 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
_GC(r_y1) = _GC(glob_y);
|
||||
_GC(r_y1) += game_buff_ptr->y1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_GC(r_x1) < 0)
|
||||
_GC(r_x1) = 0;
|
||||
|
||||
if (_GC(r_y1) < 0)
|
||||
_GC(r_y1) = 0;
|
||||
|
||||
_GC(r_y2) = _GC(r_y1) + sizeY - 1;
|
||||
_GC(r_x2) = _GC(r_x1) + sizeX - 1;
|
||||
|
||||
_GC(r_x2) = imath_min(VIDEO_W, _GC(r_x2));
|
||||
_GC(r_y2) = imath_min(VIDEO_H, _GC(r_y2));
|
||||
}
|
||||
|
||||
static void textBoxInit() {
|
||||
player_set_commands_allowed(true);
|
||||
mouse_set_sprite(0);
|
||||
|
||||
gr_font_set(_G(font_conv));
|
||||
|
||||
conv_get_node_text(conv_get_handle());
|
||||
set_dlg_rect();
|
||||
|
||||
_GC(myTextScrn) = TextScrn_Create(_GC(r_x1), _GC(r_y1), _GC(r_x2), _GC(r_y2), _GC(conv_shading),
|
||||
6 | SF_GET_MOUSE | SF_IMMOVABLE | SF_BLOCK_MOUSE,
|
||||
_GC(conv_normal_colour), _GC(conv_hilite_colour), _GC(conv_normal_colour_alt1),
|
||||
_GC(conv_hilite_colour_alt1), _GC(conv_normal_colour_alt2),
|
||||
_GC(conv_hilite_colour_alt2));
|
||||
|
||||
for (int32 i = 0; i < _G(cdd).num_txt_ents; i++) {
|
||||
TextScrn_Add_TextItem(_GC(myTextScrn), _GC(conv_font_spacing_h),
|
||||
(i * _GC(height)) + _GC(conv_font_spacing_v), i + 1, TS_GIVEN,
|
||||
_G(cdd).text[i], convtestCallback);
|
||||
}
|
||||
|
||||
TextScrn_Activate(_GC(myTextScrn));
|
||||
}
|
||||
|
||||
void conv_get_dlg_coords(int32 *x1, int32 *y1, int32 *x2, int32 *y2) {
|
||||
*x1 = _GC(r_x1);
|
||||
*y1 = _GC(r_y1);
|
||||
*x2 = _GC(r_x2);
|
||||
*y2 = _GC(r_y2);
|
||||
}
|
||||
|
||||
void conv_set_dlg_coords(int32 x1, int32 y1, int32 x2, int32 y2) {
|
||||
_GC(r_x1) = x1;
|
||||
_GC(r_y1) = y1;
|
||||
_GC(r_x2) = x2;
|
||||
_GC(r_y2) = y2;
|
||||
}
|
||||
|
||||
void conv_go(Conv *c) {
|
||||
conv_run(c);
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
346
engines/m4/adv_r/conv.h
Normal file
346
engines/m4/adv_r/conv.h
Normal file
@@ -0,0 +1,346 @@
|
||||
|
||||
/* 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 M4_ADV_R_CONV_H
|
||||
#define M4_ADV_R_CONV_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define _GC(X) _G(conversations).X
|
||||
|
||||
#define CONV_WAIT_FOR_INPUT 1
|
||||
#define CONV_HALT_FOREVER 2
|
||||
#define CONV_HALT 3
|
||||
#define CONV_INPUT_OK 4
|
||||
#define CONV_DO_NOTHING 5
|
||||
|
||||
#define CONV_PLAYER_TALKING 1
|
||||
#define CONV_NON_PLAYER_TALKING 0
|
||||
|
||||
#define DLG_FLUSH_LEFT -1
|
||||
#define DLG_FLUSH_RIGHT -2
|
||||
#define DLG_FLUSH_TOP -3
|
||||
#define DLG_FLUSH_BOTTOM -4
|
||||
#define DLG_CENTER_H -5
|
||||
#define DLG_CENTER_V -6
|
||||
|
||||
|
||||
//from: prochunk.h
|
||||
#define C_ASGN_CHUNK ((int32) ('C' << 24) | ('A' << 16) | ('S' << 8) | 'N')
|
||||
|
||||
#define ASGN_CHUNK ((int32) ('A' << 24) | ('S' << 16) | ('G' << 8) | 'N')
|
||||
|
||||
#define HIDE_CHUNK ((int32) ('H' << 24) | ('I' << 16) | ('D' << 8) | 'E')
|
||||
#define UHID_CHUNK ((int32) ('U' << 24) | ('H' << 16) | ('I' << 8) | 'D')
|
||||
#define DSTR_CHUNK ((int32) ('D' << 24) | ('S' << 16) | ('T' << 8) | 'R')
|
||||
#define CHDE_CHUNK ((int32) ('C' << 24) | ('H' << 16) | ('D' << 8) | 'E')
|
||||
#define CUHD_CHUNK ((int32) ('C' << 24) | ('U' << 16) | ('H' << 8) | 'D')
|
||||
#define CDST_CHUNK ((int32) ('D' << 24) | ('D' << 16) | ('T' << 8) | 'S')
|
||||
|
||||
#define CONV_CHUNK ((int32) ('C' << 24) | ('O' << 16) | ('N' << 8) | 'V')
|
||||
#define DECL_CHUNK ((int32) ('D' << 24) | ('E' << 16) | ('C' << 8) | 'L')
|
||||
|
||||
#define FALL_CHUNK ((int32) ('F' << 24) | ('A' << 16) | ('L' << 8) | 'L')
|
||||
#define LNODE_CHUNK ((int32) ('L' << 24) | ('N' << 16) | ('O' << 8) | 'D')
|
||||
#define NODE_CHUNK ((int32) ('N' << 24) | ('O' << 16) | ('D' << 8) | 'E')
|
||||
#define ENTRY_CHUNK ((int32) ('E' << 24) | ('T' << 16) | ('R' << 8) | 'Y')
|
||||
#define TEXT_CHUNK ((int32) ('T' << 24) | ('E' << 16) | ('X' << 8) | 'T')
|
||||
|
||||
//reply
|
||||
#define REPLY_CHUNK ((int32) ('R' << 24) | ('P' << 16) | ('L' << 8) | 'Y')
|
||||
#define WEIGHT_REPLY_CHUNK ((int32) ('W' << 24) | ('R' << 16) | ('P' << 8) | 'L')
|
||||
#define WEIGHT_PREPLY_CHUNK ((int32) ('W' << 24) | ('P' << 16) | ('R' << 8) | 'L')
|
||||
#define COND_REPLY_CHUNK ((int32) ('C' << 24) | ('R' << 16) | ('P' << 8) | 'L')
|
||||
|
||||
#define MESSAGE_CHUNK ((int32) ('M' << 24) | ('E' << 16) | ('S' << 8) | 'G')
|
||||
|
||||
// goto
|
||||
#define GOTO_CHUNK ((int32) ('G' << 24) | ('O' << 16) | ('T' << 8) | 'O')
|
||||
#define EXIT_GOTO_CHUNK ((int32) ('E' << 24) | ('X' << 16) | ('I' << 8) | 'T')
|
||||
#define COND_GOTO_CHUNK ((int32) ('C' << 24) | ('C' << 16) | ('G' << 8) | 'O')
|
||||
|
||||
#define COND_EXIT_GOTO_CHUNK ((int32) ('C' << 24) | ('E' << 16) | ('G' << 8) | 'O')
|
||||
|
||||
|
||||
struct Conv {
|
||||
int32 chunkSize = 0;
|
||||
char *conv = nullptr;
|
||||
int32 myCNode = 0;
|
||||
int32 exit_now = 0;
|
||||
int32 node_hash = 0;
|
||||
|
||||
int32 mode = 0;
|
||||
int32 c_entry_num = 0;
|
||||
Common::Array<int32 *> _pointers;
|
||||
};
|
||||
|
||||
struct ConvDisplayData {
|
||||
char *text[16];
|
||||
char *snd_files[16];
|
||||
char mesg[1024];
|
||||
char *mesg_snd_file;
|
||||
int num_txt_ents;
|
||||
int player_non_player;
|
||||
int player_choice;
|
||||
};
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct conv_chunk {
|
||||
int32 tag;
|
||||
int32 size;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct decl_chunk {
|
||||
int32 tag;
|
||||
int32 val;
|
||||
int32 flags;
|
||||
int32 addrIndex; // Index into Conv::_pointers array
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct fall_chunk {
|
||||
int32 tag;
|
||||
int32 val;
|
||||
int32 index;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct node_chunk {
|
||||
int32 tag;
|
||||
int32 hash;
|
||||
int32 size;
|
||||
int32 num_entries;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct lnode_chunk {
|
||||
int32 tag;
|
||||
int32 hash;
|
||||
int32 size;
|
||||
int32 entry_num;
|
||||
int32 num_entries;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct entry_chunk {
|
||||
int32 tag;
|
||||
int32 size;
|
||||
int32 status;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct text_chunk {
|
||||
int32 tag;
|
||||
int32 size;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct mesg_chunk {
|
||||
int32 tag;
|
||||
int32 size;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct reply_chunk {
|
||||
int32 tag;
|
||||
int32 index; // Where the message is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct c_reply_chunk {
|
||||
int32 tag;
|
||||
int32 op_l;
|
||||
int32 op;
|
||||
int32 op_r;
|
||||
int32 index; // Where the message is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct w_reply_chunk {
|
||||
int32 tag;
|
||||
int32 num_replies;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct w_entry_chunk {
|
||||
int32 weight;
|
||||
int32 index; // Where the message is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct goto_chunk {
|
||||
int32 tag;
|
||||
int32 index; // Where the node is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct c_goto_chunk {
|
||||
int32 tag;
|
||||
int32 opnd1; // Where the decl is located.
|
||||
int32 op;
|
||||
int32 opnd2; // Integer value.
|
||||
int32 index; // Where the node is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct misc_chunk {
|
||||
int32 tag;
|
||||
int32 index; // Where the entry is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct c_misc_chunk {
|
||||
int32 tag;
|
||||
|
||||
int32 c_op_l; // Where the decl is located.
|
||||
int32 c_op;
|
||||
int32 c_op_r; // Integer value.
|
||||
|
||||
int32 index; // Where the entry is located.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct assign_chunk {
|
||||
int32 tag;
|
||||
int32 index; // Where the decl is located.
|
||||
int32 op;
|
||||
int32 opnd1; // Integer value.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct c_assign_chunk {
|
||||
int32 tag;
|
||||
|
||||
int32 c_op_l; // Where the decl is located.
|
||||
int32 c_op;
|
||||
int32 c_op_r; // Integer value.
|
||||
|
||||
int32 index; // Where the decl is located.
|
||||
int32 op;
|
||||
int32 opnd1; // Integer value.
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
/**
|
||||
"xxxxxxxx" means the size you have calculated a conversation box to be,
|
||||
x x given the sentences that are in it, and whatever border
|
||||
x x space you may have in it. The boxes in Figure A may be
|
||||
xxxxxxxx where the user wants to place them. Obviously, the user
|
||||
won't try to put them out in hyperspace, but may do this
|
||||
if he wants the box to be flush with a corner (to grow
|
||||
up, down, left, or right.) Figure B is the re-calculated
|
||||
coordinates of the boxes in order to get them onto the
|
||||
background. The new boxes should not be in the interface
|
||||
or in the letterboxed areas at the top and bottom.
|
||||
|
||||
|
||||
|
||||
|
||||
xxxxxxxxx
|
||||
x (d) x
|
||||
x x Figure A xxxxxxxxxxxx
|
||||
0,0 xxxxxxxxx x (b) x
|
||||
x x
|
||||
x x
|
||||
(letterbox at top) xxxxxxxxxxxx
|
||||
|
||||
|
||||
|
||||
|
||||
(background)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
xxxxxxxxxxxxx
|
||||
x (c) x
|
||||
x x
|
||||
x x
|
||||
x x
|
||||
x x
|
||||
xxxxxxxxxxxxxxxxxx x x
|
||||
x x xxxxxxxxxxxxx
|
||||
x x (interface)
|
||||
x x
|
||||
x x
|
||||
x x
|
||||
x x (letterbox at bottom)
|
||||
x x
|
||||
x x
|
||||
x (a) x 640,479
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Figure B
|
||||
0,0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
xxxxxxxx xxxxxxxxxxx
|
||||
x (d) x x (b) x
|
||||
x x x x
|
||||
xxxxxxxx x x
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
x x
|
||||
x x
|
||||
x x xxxxxxxxxxxxx
|
||||
x x x (c) x
|
||||
x x x x
|
||||
x x x x
|
||||
x x x x
|
||||
x (a) x x x
|
||||
xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxx
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
640,479
|
||||
|
||||
|
||||
|
||||
|
||||
If someone says to draw conversation box (a) at the location in Figure 1,
|
||||
then have it automatically re-position itself into where it is in Figure 2.
|
||||
The extra space around the newly re-positioned box should be about 10 pixels
|
||||
wide and/or tall. Make the spacing visually look identical. In other
|
||||
words, if the height of the border is 10 pixels, the width on the side of
|
||||
the new conversation box may need to be 15. You may have to experiment
|
||||
with this. In even other words, you should correct for the aspect ration.
|
||||
|
||||
The same thing should work for boxes (b), (c), and (d).
|
||||
*/
|
||||
void set_dlg_rect();
|
||||
|
||||
void conv_go(Conv *c);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
837
engines/m4/adv_r/conv_io.cpp
Normal file
837
engines/m4/adv_r/conv_io.cpp
Normal file
@@ -0,0 +1,837 @@
|
||||
/* 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 "m4/adv_r/conv_io.h"
|
||||
#include "m4/adv_r/adv_control.h"
|
||||
#include "m4/adv_r/conv.h"
|
||||
#include "m4/adv_r/chunk_ops.h"
|
||||
#include "m4/adv_r/db_env.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/vars.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define NAME_SIZE (g_engine->getGameType() == GType_Riddle ? 12 : 8)
|
||||
|
||||
#define HIDDEN 0x00000004
|
||||
#define DESTROYED 0x00000008
|
||||
|
||||
#define INITIAL 1
|
||||
#define PERSISTENT 2
|
||||
|
||||
#define CONV_OK 0
|
||||
#define CONV_QUIT -1
|
||||
#define CONV_NEW -2
|
||||
#define CONV_BAIL -3
|
||||
|
||||
#define CONV_UNKNOWN_MODE 0
|
||||
#define CONV_GET_TEXT_MODE 1
|
||||
#define CONV_SET_TEXT_MODE 2
|
||||
#define CONV_GET_MESG_MODE 3
|
||||
#define CONV_UPDATE_MODE 4
|
||||
|
||||
#define DECL_POINTER 1
|
||||
|
||||
void Converstation_Globals::syncGame(Common::Serializer &s) {
|
||||
if (s.isLoading())
|
||||
conv_reset_all();
|
||||
|
||||
// Handle size
|
||||
uint32 count = convSave.size();
|
||||
s.syncAsUint32LE(count);
|
||||
if (s.isLoading())
|
||||
convSave.resize(count);
|
||||
|
||||
// Sync buffer contents
|
||||
if (count)
|
||||
s.syncBytes(&convSave[0], count);
|
||||
}
|
||||
|
||||
void Converstation_Globals::conv_reset_all() {
|
||||
convSave.clear();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void cdd_init() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
_G(cdd).text[i] = nullptr;
|
||||
_G(cdd).snd_files[i] = nullptr;
|
||||
}
|
||||
|
||||
_G(cdd).num_txt_ents = 0;
|
||||
Common::strcpy_s(_G(cdd).mesg, "");
|
||||
_G(cdd).mesg_snd_file = nullptr;
|
||||
}
|
||||
|
||||
Conv *conv_get_handle(void) {
|
||||
return _GC(globConv);
|
||||
}
|
||||
|
||||
void conv_set_handle(Conv *c) {
|
||||
_GC(globConv) = c;
|
||||
}
|
||||
|
||||
void conv_resume(Conv *c) {
|
||||
conv_go(c);
|
||||
}
|
||||
|
||||
void conv_resume() {
|
||||
conv_resume(conv_get_handle());
|
||||
}
|
||||
|
||||
int conv_is_event_ready() {
|
||||
return _GC(event_ready);
|
||||
}
|
||||
|
||||
void conv_set_event(int e) {
|
||||
_GC(event) = e;
|
||||
_GC(event_ready) = 1;
|
||||
}
|
||||
|
||||
int conv_get_event() {
|
||||
_GC(event_ready) = 0;
|
||||
return _GC(event);
|
||||
}
|
||||
|
||||
void conv_play(Conv *c) {
|
||||
conv_go(c);
|
||||
}
|
||||
|
||||
void conv_play() {
|
||||
conv_play(conv_get_handle());
|
||||
}
|
||||
|
||||
int32 conv_current_node() {
|
||||
if (conv_get_handle())
|
||||
return conv_get_handle()->node_hash;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 conv_current_entry() {
|
||||
return _GC(ent) - 1;
|
||||
}
|
||||
|
||||
void conv_reset(const char *filename) {
|
||||
_GC(restore_conv) = 0;
|
||||
|
||||
Conv *c = conv_load(filename, 1, 1, -1, false);
|
||||
conv_unload(c);
|
||||
}
|
||||
|
||||
|
||||
void conv_reset_all() {
|
||||
_G(conversations).conv_reset_all();
|
||||
}
|
||||
|
||||
const char *conv_sound_to_play() {
|
||||
return _G(cdd).mesg_snd_file;
|
||||
}
|
||||
|
||||
int32 conv_whos_talking() {
|
||||
return _G(cdd).player_non_player;
|
||||
}
|
||||
|
||||
int ok_status(entry_chunk *entry) {
|
||||
if (entry->status & DESTROYED)
|
||||
return 0;
|
||||
|
||||
if (entry->status & HIDDEN)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int conv_toggle_flags(entry_chunk *entry) {
|
||||
if (ok_status(entry))
|
||||
return (entry->status & 0x0000000e); //mask off INITIAL bit.
|
||||
return entry->status;
|
||||
}
|
||||
|
||||
int32 conv_get_decl_val(Conv *c, decl_chunk *decl) {
|
||||
if (decl->flags == DECL_POINTER)
|
||||
return *c->_pointers[decl->addrIndex];
|
||||
|
||||
return decl->val;
|
||||
}
|
||||
|
||||
void conv_set_decl_val(Conv *c, decl_chunk *decl, int32 val) {
|
||||
if (decl->flags == DECL_POINTER) {
|
||||
decl->val = val;
|
||||
*c->_pointers[decl->addrIndex] = val;
|
||||
} else {
|
||||
decl->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
void conv_export_value(Conv *c, int32 val, int index) {
|
||||
int32 tag = 0, next;
|
||||
int i = 0;
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
const int32 ent_old = c->myCNode;
|
||||
int32 ent = 0;
|
||||
c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
if (tag == DECL_CHUNK) {
|
||||
if (i == index) {
|
||||
decl_chunk *decl = get_decl(c, ent);
|
||||
conv_set_decl_val(c, decl, val);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ent = next;
|
||||
}
|
||||
c->myCNode = ent_old;
|
||||
}
|
||||
|
||||
void conv_export_value_curr(int32 val, int index) {
|
||||
conv_export_value(conv_get_handle(), val, index);
|
||||
}
|
||||
|
||||
void conv_export_pointer(Conv *c, int32 *val, int index) {
|
||||
int32 tag = 0, next;
|
||||
int i = 0;
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
const int32 ent_old = c->myCNode;
|
||||
int32 ent = 0;
|
||||
c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
switch (tag) {
|
||||
case DECL_CHUNK:
|
||||
if (i == index) {
|
||||
decl_chunk *decl = get_decl(c, ent);
|
||||
|
||||
c->_pointers.push_back(val);
|
||||
decl->addrIndex = c->_pointers.size() - 1;
|
||||
decl->flags = DECL_POINTER;
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ent = next;
|
||||
}
|
||||
c->myCNode = ent_old;
|
||||
}
|
||||
|
||||
void conv_export_pointer_curr(int32 *val, int index) {
|
||||
conv_export_pointer(conv_get_handle(), val, index);
|
||||
}
|
||||
|
||||
void conv_init(Conv *c) {
|
||||
switch (c->exit_now) {
|
||||
case CONV_OK:
|
||||
case CONV_QUIT:
|
||||
break;
|
||||
|
||||
case CONV_BAIL:
|
||||
case CONV_NEW:
|
||||
if (c->myCNode != CONV_QUIT) {
|
||||
c->exit_now = CONV_NEW; //conv hasn't been run before. only done here once.
|
||||
c->myCNode = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 find_state(const char *s, char *c, int file_size) {
|
||||
char name[13];
|
||||
int32 size = 0, offset = 0;
|
||||
|
||||
while (offset < file_size) {
|
||||
Common::strcpy_s(name, &c[offset]);
|
||||
|
||||
if (!scumm_stricmp(name, s)) {
|
||||
offset += NAME_SIZE * sizeof(char);
|
||||
goto handled;
|
||||
}
|
||||
|
||||
offset += NAME_SIZE * sizeof(char);
|
||||
if (offset < file_size) {
|
||||
memcpy(&size, &c[offset], sizeof(int32));
|
||||
}
|
||||
|
||||
offset += size + sizeof(int32);
|
||||
}
|
||||
|
||||
offset = -1;
|
||||
|
||||
handled:
|
||||
return offset;
|
||||
}
|
||||
|
||||
void find_and_set_conv_name(Conv *c) {
|
||||
int32 ent = 0, tag = 0, next = 0;
|
||||
|
||||
c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
if (tag == CONV_CHUNK) {
|
||||
conv_chunk *conv = get_conv(c, ent);
|
||||
assert(conv);
|
||||
Common::strcpy_s(_GC(conv_name), get_string(c, c->myCNode + ent + sizeof(conv_chunk)));
|
||||
}
|
||||
ent = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void conv_save_state(Conv *c) {
|
||||
//-------------------------------------------------------------------------------
|
||||
// Calculate amt_to_write by counting up the size of DECL_CHUNKs.
|
||||
// the number of ENTRY_CHUNKs affects the amt_to_write
|
||||
// also extract fname from the CONV_CHUNK
|
||||
|
||||
int32 amt_to_write = 3 * sizeof(int32); // Header size
|
||||
int32 ent = 0;
|
||||
int32 next, tag; // receive conv_ops_get_entry results
|
||||
const int32 myCNode = c->myCNode;
|
||||
char fname[13];
|
||||
memset(fname, 0, 13);
|
||||
|
||||
int32 num_decls = 0;
|
||||
int32 num_entries = 0;
|
||||
|
||||
c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_chunk *conv;
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
switch (tag) {
|
||||
case CONV_CHUNK:
|
||||
conv = get_conv(c, ent);
|
||||
assert(conv);
|
||||
Common::strcpy_s(fname, get_string(c, c->myCNode + ent + sizeof(conv_chunk)));
|
||||
break;
|
||||
|
||||
case DECL_CHUNK:
|
||||
num_decls++;
|
||||
amt_to_write += sizeof(int32);
|
||||
break;
|
||||
|
||||
case ENTRY_CHUNK:
|
||||
num_entries++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ent = next;
|
||||
}
|
||||
|
||||
amt_to_write += (num_entries / 8) * sizeof(int32);
|
||||
if ((num_entries % 8) != 0)
|
||||
amt_to_write += sizeof(int32); // Pad the sucker
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// if consave data exists, read it in
|
||||
|
||||
int32 file_size = 0;
|
||||
int32 offset;
|
||||
char *conv_save_buff;
|
||||
bool overwrite_file = false;
|
||||
|
||||
if (!_GC(convSave).empty()) {
|
||||
file_size = _GC(convSave).size();
|
||||
|
||||
conv_save_buff = (char *)mem_alloc(file_size, "conv save buff");
|
||||
if (!conv_save_buff)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
Common::copy(&_GC(convSave)[0], &_GC(convSave)[0] + file_size, &conv_save_buff[0]);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// If this conversation already in conv data, overwrite it,
|
||||
// otherwise chuck out the buffer, and create a new buffer which is just
|
||||
// big enough to hold the new save data.
|
||||
|
||||
offset = find_state(fname, conv_save_buff, file_size);
|
||||
|
||||
if (offset != -1) {
|
||||
overwrite_file = true;
|
||||
/* int32 prev_size = */ READ_LE_UINT32(&conv_save_buff[offset]);
|
||||
/* prev_size += NAME_SIZE + sizeof(int32);*/
|
||||
offset += sizeof(int32); // Skip header. (name + size)
|
||||
} else {
|
||||
// Append
|
||||
offset = 0;
|
||||
|
||||
mem_free(conv_save_buff);
|
||||
conv_save_buff = (char *)mem_alloc(amt_to_write + NAME_SIZE + sizeof(int32), "conv save buff");
|
||||
if (!conv_save_buff)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
memcpy(&conv_save_buff[offset], fname, NAME_SIZE * sizeof(char));
|
||||
offset += NAME_SIZE * sizeof(char);
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], amt_to_write);
|
||||
offset += sizeof(int32);
|
||||
}
|
||||
} else {
|
||||
//----------------------------------------------------------------------------
|
||||
// Conv save dat didn't exist, so we set things up for a create here.
|
||||
|
||||
offset = 0;
|
||||
|
||||
conv_save_buff = (char *)mem_alloc(amt_to_write + NAME_SIZE + sizeof(int32), "conv save buff");
|
||||
if (!conv_save_buff)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
memcpy(&conv_save_buff[offset], fname, NAME_SIZE * sizeof(char));
|
||||
offset += NAME_SIZE * sizeof(char);
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], amt_to_write);
|
||||
offset += sizeof(int32);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// finish filling in conv_save_buff data with num of entries etc.
|
||||
|
||||
WRITE_LE_INT32(&conv_save_buff[offset], myCNode);
|
||||
offset += sizeof(int32);
|
||||
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], num_decls);
|
||||
offset += sizeof(int32);
|
||||
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], num_entries);
|
||||
offset += sizeof(int32);
|
||||
|
||||
int32 size = 3 * sizeof(int32);
|
||||
|
||||
// fill in all the entries themselves
|
||||
|
||||
int32 e_flags = 0;
|
||||
short flag_index = 0;
|
||||
|
||||
ent = 0;
|
||||
c->myCNode = 0;
|
||||
|
||||
int32 val;
|
||||
entry_chunk *entry;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
decl_chunk *decl;
|
||||
|
||||
switch (tag) {
|
||||
case DECL_CHUNK:
|
||||
decl = get_decl(c, ent);
|
||||
val = conv_get_decl_val(c, decl);
|
||||
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], val);
|
||||
offset += sizeof(int32);
|
||||
size += sizeof(int32);
|
||||
break;
|
||||
|
||||
case LNODE_CHUNK:
|
||||
case NODE_CHUNK:
|
||||
break;
|
||||
|
||||
case ENTRY_CHUNK:
|
||||
entry = get_entry(c, ent);
|
||||
|
||||
if (flag_index == 32) {
|
||||
flag_index = 0;
|
||||
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], e_flags);
|
||||
offset += sizeof(int32);
|
||||
size += sizeof(int32);
|
||||
|
||||
e_flags = 0;
|
||||
}
|
||||
|
||||
e_flags |= ((entry->status & 0x0000000f) << flag_index);
|
||||
|
||||
flag_index += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ent = next;
|
||||
}
|
||||
|
||||
// Copy the flags
|
||||
if (flag_index != 0) {
|
||||
WRITE_LE_UINT32(&conv_save_buff[offset], e_flags);
|
||||
// offset += sizeof(int32);
|
||||
size += sizeof(int32);
|
||||
}
|
||||
|
||||
if (amt_to_write != size)
|
||||
error_show(FL, 'CNVS', "save_state: error! size written != size (%d %d)", amt_to_write, size);
|
||||
|
||||
// Finally, write out the conversation data
|
||||
if (overwrite_file == true) {
|
||||
_GC(convSave).resize(file_size);
|
||||
Common::copy(conv_save_buff, conv_save_buff + file_size, &_GC(convSave)[0]);
|
||||
|
||||
} else {
|
||||
// Append conversation
|
||||
const size_t oldSize = _GC(convSave).size();
|
||||
file_size = amt_to_write + NAME_SIZE + sizeof(int32);
|
||||
|
||||
_GC(convSave).resize(_GC(convSave).size() + file_size);
|
||||
Common::copy(conv_save_buff, conv_save_buff + file_size, &_GC(convSave)[oldSize]);
|
||||
}
|
||||
|
||||
mem_free(conv_save_buff);
|
||||
}
|
||||
|
||||
static Conv *conv_restore_state(Conv *c) {
|
||||
int32 tag, next;
|
||||
|
||||
short flag_index = 0;
|
||||
int32 val;
|
||||
int32 e_flags = 0;
|
||||
int32 myCNode;
|
||||
|
||||
char fname[13];
|
||||
int file_size;
|
||||
|
||||
int32 ent;
|
||||
c->myCNode = 0;
|
||||
|
||||
find_and_set_conv_name(c);
|
||||
Common::strcpy_s(fname, _GC(conv_name));
|
||||
|
||||
if (_GC(convSave).empty())
|
||||
file_size = -1;
|
||||
else
|
||||
file_size = _GC(convSave).size();
|
||||
|
||||
if (file_size <= 0) {
|
||||
conv_init(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
char *conv_save_buff = (char *)mem_alloc(file_size, "conv save buff");
|
||||
if (!conv_save_buff)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
// ------------------
|
||||
|
||||
Common::copy(&_GC(convSave)[0], &_GC(convSave)[0] + file_size, &conv_save_buff[0]);
|
||||
int32 offset = find_state(fname, conv_save_buff, file_size);
|
||||
|
||||
if (offset == -1)
|
||||
goto i_am_so_done;
|
||||
|
||||
// Skip header.
|
||||
offset += sizeof(int32);
|
||||
|
||||
myCNode = READ_LE_INT32(&conv_save_buff[offset]);
|
||||
offset += sizeof(int32);
|
||||
|
||||
/*int num_decls = */READ_LE_UINT32(&conv_save_buff[offset]);
|
||||
offset += sizeof(int32);
|
||||
|
||||
/*int num_entries = */READ_LE_UINT32(&conv_save_buff[offset]);
|
||||
offset += sizeof(int32);
|
||||
|
||||
ent = 0; c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
if (tag == DECL_CHUNK) {
|
||||
val = READ_LE_UINT32(&conv_save_buff[offset]);
|
||||
offset += sizeof(int32);
|
||||
decl_chunk *decl = get_decl(c, ent);
|
||||
|
||||
conv_set_decl_val(c, decl, val);
|
||||
}
|
||||
|
||||
ent = next;
|
||||
}
|
||||
|
||||
ent = 0;
|
||||
c->myCNode = 0;
|
||||
|
||||
while (ent < c->chunkSize) {
|
||||
conv_ops_get_entry(ent, &next, &tag, c);
|
||||
|
||||
if (tag == ENTRY_CHUNK) {
|
||||
entry_chunk *entry = get_entry(c, ent);
|
||||
|
||||
if (flag_index == 32) {
|
||||
flag_index = 0;
|
||||
//flag_num++;
|
||||
}
|
||||
|
||||
if (flag_index == 0) {
|
||||
e_flags = READ_LE_UINT32(&conv_save_buff[offset]);
|
||||
offset += sizeof(int32);
|
||||
}
|
||||
|
||||
val = (e_flags >> flag_index) & 0x0000000f;
|
||||
entry->status = val;
|
||||
|
||||
flag_index += 4;
|
||||
}
|
||||
|
||||
ent = next;
|
||||
}
|
||||
|
||||
c->myCNode = myCNode;
|
||||
if (c->myCNode == CONV_QUIT) {
|
||||
c->exit_now = CONV_QUIT;
|
||||
|
||||
conv_unload(c);
|
||||
c = nullptr;
|
||||
} else
|
||||
c->exit_now = CONV_OK;
|
||||
|
||||
i_am_so_done:
|
||||
|
||||
mem_free(conv_save_buff);
|
||||
return c;
|
||||
}
|
||||
|
||||
void conv_set_font_spacing(int32 h, int32 v) {
|
||||
_GC(conv_font_spacing_h) = h;
|
||||
_GC(conv_font_spacing_v) = v;
|
||||
}
|
||||
|
||||
|
||||
void conv_set_text_colours(int32 norm_colour, int32 norm_colour_alt1, int32 norm_colour_alt2,
|
||||
int32 hi_colour, int32 hi_colour_alt1, int32 hi_colour_alt2) {
|
||||
_GC(conv_normal_colour) = norm_colour;
|
||||
_GC(conv_normal_colour_alt1) = norm_colour_alt1;
|
||||
_GC(conv_normal_colour_alt2) = norm_colour_alt2;
|
||||
_GC(conv_hilite_colour) = hi_colour;
|
||||
_GC(conv_hilite_colour_alt1) = hi_colour_alt1;
|
||||
_GC(conv_hilite_colour_alt2) = hi_colour_alt2;
|
||||
}
|
||||
|
||||
void conv_set_text_colour(int32 norm_colour, int32 hi_colour) {
|
||||
conv_set_text_colours(norm_colour, norm_colour, norm_colour, hi_colour, hi_colour, hi_colour);
|
||||
}
|
||||
|
||||
void conv_set_default_hv(int32 h, int32 v) {
|
||||
_GC(conv_default_h) = h;
|
||||
_GC(conv_default_v) = v;
|
||||
}
|
||||
|
||||
void conv_set_default_text_colour(int32 norm_colour, int32 hi_colour) {
|
||||
conv_set_text_colours(norm_colour, norm_colour, norm_colour, hi_colour, hi_colour, hi_colour);
|
||||
|
||||
_GC(conv_default_normal_colour) = norm_colour;
|
||||
_GC(conv_default_hilite_colour) = hi_colour;
|
||||
}
|
||||
|
||||
void conv_set_shading(int32 shade) {
|
||||
_GC(conv_shading) = shade;
|
||||
}
|
||||
|
||||
void conv_set_box_xy(int32 x, int32 y) {
|
||||
_GC(glob_x) = x;
|
||||
_GC(glob_y) = y;
|
||||
}
|
||||
|
||||
static void conv_set_disp_default(void) {
|
||||
_GC(conv_font_spacing_h) = _GC(conv_default_h);
|
||||
_GC(conv_font_spacing_v) = _GC(conv_default_v);
|
||||
_GC(conv_normal_colour) = _GC(conv_default_normal_colour);
|
||||
_GC(conv_hilite_colour) = _GC(conv_default_hilite_colour);
|
||||
_GC(conv_shading) = 75;
|
||||
}
|
||||
|
||||
Conv *conv_load(const char *filename, int x1, int y1, int32 myTrigger, bool want_box) {
|
||||
char fullPathname[MAX_FILENAME_SIZE];
|
||||
|
||||
term_message("conv_load");
|
||||
|
||||
// Remember if player commands are on before we start the conversation
|
||||
_GC(playerCommAllowed) = _G(player).comm_allowed;
|
||||
_GC(interface_was_visible) = INTERFACE_VISIBLE;
|
||||
|
||||
term_message("conv load: %s", filename);
|
||||
|
||||
if (want_box) {
|
||||
// If we want an interface box
|
||||
conv_set_disp_default();
|
||||
mouse_set_sprite(0); // Also if we want a text box, lock the mouse into arrow mode
|
||||
mouse_lock_sprite(0);
|
||||
player_set_commands_allowed(false); // with commands off
|
||||
|
||||
// Hide the interface if it's visible
|
||||
if (INTERFACE_VISIBLE)
|
||||
interface_hide();
|
||||
}
|
||||
|
||||
// if not in rooms.db, use actual filename
|
||||
char *str = env_find(filename);
|
||||
if (str)
|
||||
Common::strcpy_s(fullPathname, str);
|
||||
else
|
||||
Common::sprintf_s(fullPathname, "%s.chk", filename);
|
||||
|
||||
SysFile fp(fullPathname);
|
||||
if (!fp.exists()) {
|
||||
// Force the file open
|
||||
error_show(FL, 'CNVL', "couldn't conv_load %s", fullPathname);
|
||||
}
|
||||
|
||||
const int32 cSize = fp.size();
|
||||
|
||||
if (conv_get_handle() != nullptr) {
|
||||
conv_unload();
|
||||
}
|
||||
|
||||
Conv *convers = new Conv();
|
||||
convers->chunkSize = cSize;
|
||||
convers->conv = nullptr;
|
||||
convers->myCNode = 0;
|
||||
convers->exit_now = CONV_NEW;
|
||||
convers->node_hash = 0;
|
||||
convers->mode = CONV_GET_TEXT_MODE;
|
||||
convers->c_entry_num = 1;
|
||||
_GC(myFinalTrigger) = kernel_trigger_create(myTrigger);
|
||||
|
||||
convers->conv = (char *)mem_alloc(cSize * sizeof(char), "conv char data");
|
||||
|
||||
if (!fp.read((byte *)convers->conv, cSize)) {
|
||||
conv_set_handle(nullptr);
|
||||
delete convers;
|
||||
convers = nullptr;
|
||||
fp.close();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
conv_swap_words(convers);
|
||||
find_and_set_conv_name(convers);
|
||||
|
||||
_GC(glob_x) = x1;
|
||||
_GC(glob_y) = y1;
|
||||
|
||||
if (want_box)
|
||||
set_dlg_rect();
|
||||
|
||||
if (_GC(restore_conv))
|
||||
convers = conv_restore_state(convers);
|
||||
_GC(restore_conv) = 1;
|
||||
|
||||
conv_set_handle(convers);
|
||||
|
||||
fp.close();
|
||||
|
||||
return convers;
|
||||
}
|
||||
|
||||
void conv_load_and_prepare(const char *filename, int trigger, bool ignoreIt) {
|
||||
player_set_commands_allowed(false);
|
||||
|
||||
if (!ignoreIt) {
|
||||
conv_load(filename, 10, 375, trigger, true);
|
||||
conv_set_shading(100);
|
||||
conv_set_text_colours(3, 1, 2, 22, 10, 14);
|
||||
conv_set_font_spacing(10, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void conv_unload(Conv *c) {
|
||||
mouse_unlock_sprite();
|
||||
|
||||
if (_GC(interface_was_visible)) { // Turn interface back on if it was on
|
||||
interface_show();
|
||||
}
|
||||
|
||||
_GC(globConv) = nullptr;
|
||||
|
||||
if (c)
|
||||
conv_save_state(c);
|
||||
|
||||
player_set_commands_allowed(_GC(playerCommAllowed));
|
||||
|
||||
_G(player).command_ready = false;
|
||||
_G(player).ready_to_walk = false;
|
||||
_G(player).need_to_walk = false;
|
||||
|
||||
Common::strcpy_s(_G(player).verb, "");
|
||||
Common::strcpy_s(_G(player).noun, "");
|
||||
kernel_trigger_dispatchx(_GC(myFinalTrigger));
|
||||
|
||||
if (c) {
|
||||
if (c->conv)
|
||||
mem_free(c->conv);
|
||||
delete c;
|
||||
}
|
||||
|
||||
_GC(globConv) = c = nullptr;
|
||||
}
|
||||
|
||||
void conv_unload() {
|
||||
conv_unload(conv_get_handle());
|
||||
}
|
||||
|
||||
// only called if node is visible.
|
||||
// gets the TEXT chunks inside a node.
|
||||
int conv_get_text(int32 offset, int32 size, Conv *c) {
|
||||
int32 i = offset, tag, next;
|
||||
int result = 0;
|
||||
|
||||
size -= sizeof(entry_chunk);
|
||||
|
||||
while (i < offset + size) {
|
||||
conv_ops_get_entry(i, &next, &tag, c);
|
||||
|
||||
if (tag == TEXT_CHUNK) {
|
||||
result = 1;
|
||||
text_chunk *text = get_text(c, i);
|
||||
assert(text);
|
||||
const int32 text_len = conv_ops_text_strlen(get_string(c, c->myCNode + i + sizeof(text_chunk)));
|
||||
_G(cdd).snd_files[_G(cdd).num_txt_ents] = get_string(c, c->myCNode + i + sizeof(text_chunk));
|
||||
_G(cdd).text[_G(cdd).num_txt_ents] = get_string(c, c->myCNode + i + sizeof(text_chunk) + text_len);
|
||||
|
||||
const int32 text_width = gr_font_string_width(_G(cdd).text[_G(cdd).num_txt_ents], 1);
|
||||
if (text_width > _GC(width))
|
||||
_GC(width) = text_width;
|
||||
|
||||
_G(cdd).num_txt_ents++;
|
||||
}
|
||||
|
||||
i = next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
149
engines/m4/adv_r/conv_io.h
Normal file
149
engines/m4/adv_r/conv_io.h
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
/* 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 M4_ADV_R_CONV_IO_H
|
||||
#define M4_ADV_R_CONV_IO_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/conv.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/gui/gui_dialog.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define HIDDEN 0x00000004
|
||||
#define DESTROYED 0x00000008
|
||||
|
||||
#define INITIAL 1
|
||||
#define PERSISTENT 2
|
||||
|
||||
#define CONV_OK 0
|
||||
#define CONV_QUIT -1
|
||||
#define CONV_NEW -2
|
||||
#define CONV_BAIL -3
|
||||
|
||||
#define CONV_UNKNOWN_MODE 0
|
||||
#define CONV_GET_TEXT_MODE 1
|
||||
#define CONV_SET_TEXT_MODE 2
|
||||
#define CONV_GET_MESG_MODE 3
|
||||
#define CONV_UPDATE_MODE 4
|
||||
|
||||
#define DECL_POINTER 1
|
||||
|
||||
struct Converstation_Globals {
|
||||
Common::Array<byte> convSave; // Original used an actual file. We use a memory buffer
|
||||
int event = 0;
|
||||
int event_ready = 0;
|
||||
char conv_name[16];
|
||||
Conv *globConv = nullptr;
|
||||
bool playerCommAllowed = false;
|
||||
int32 myFinalTrigger = 0;
|
||||
bool interface_was_visible = false; // to remember to turn it back on
|
||||
int restore_conv = 1;
|
||||
int ent = 0;
|
||||
bool swap = false;
|
||||
|
||||
int32 conv_font_spacing_h = 0;
|
||||
int32 conv_font_spacing_v = 5;
|
||||
int32 conv_default_h = conv_font_spacing_h;
|
||||
int32 conv_default_v = conv_font_spacing_v;
|
||||
int32 conv_shading = 65;
|
||||
|
||||
int32 conv_normal_colour = __BLACK;
|
||||
int32 conv_normal_colour_alt1 = __GREEN;
|
||||
int32 conv_normal_colour_alt2 = __GREEN;
|
||||
int32 conv_hilite_colour = __YELLOW;
|
||||
int32 conv_default_hilite_colour = __YELLOW;
|
||||
int32 conv_hilite_colour_alt1 = __YELLOW;
|
||||
int32 conv_hilite_colour_alt2 = __YELLOW;
|
||||
int32 conv_default_normal_colour = __BLACK;
|
||||
|
||||
TextScrn *myTextScrn = nullptr;
|
||||
int32 width = 0, height = 0;
|
||||
int32 glob_x = 0, glob_y = 0;
|
||||
int32 r_x1 = 0, r_y1 = 0, r_x2 = 0, r_y2 = 0;
|
||||
int n_t_e = 0;
|
||||
|
||||
void syncGame(Common::Serializer &s);
|
||||
|
||||
void conv_reset_all();
|
||||
};
|
||||
|
||||
Conv *conv_load(const char *filename, int x1, int y1, int32 myTrigger, bool want_box = true);
|
||||
void conv_load_and_prepare(const char *filename, int trigger, bool ignoreIt = false);
|
||||
|
||||
void conv_unload(Conv *c);
|
||||
void conv_unload();
|
||||
void conv_shutdown();
|
||||
|
||||
Conv *conv_get_handle();
|
||||
void conv_set_handle(Conv *c);
|
||||
|
||||
void conv_resume(Conv *c);
|
||||
void conv_resume();
|
||||
void conv_reset(const char *filename);
|
||||
|
||||
void conv_reset_all();
|
||||
void conv_play(Conv *c);
|
||||
void conv_play();
|
||||
|
||||
const char *conv_sound_to_play();
|
||||
int32 conv_whos_talking();
|
||||
|
||||
int32 conv_get_decl_val(Conv *c, decl_chunk *decl);
|
||||
void conv_set_decl_val(Conv *c, decl_chunk *decl, int32 val);
|
||||
void conv_export_value(Conv *c, int32 val, int index);
|
||||
void conv_export_value_curr(int32 val, int index);
|
||||
void conv_export_pointer(Conv *c, int32 *val, int index);
|
||||
void conv_export_pointer_curr(int32 *val, int index);
|
||||
|
||||
void conv_set_font_spacing(int32 h, int32 v);
|
||||
void conv_set_text_colour(int32 norm_colour, int32 hi_colour);
|
||||
|
||||
void conv_set_text_colours(int32 norm_colour, int32 norm_colour_alt1, int32 norm_colour_alt2,
|
||||
int32 hi_colour, int32 hi_colour_alt1, int32 hi_colour_alt2);
|
||||
|
||||
void conv_set_shading(int32 shade);
|
||||
void conv_set_box_xy(int32 x, int32 y);
|
||||
void conv_get_dlg_coords(int32 *x1, int32 *y1, int32 *x2, int32 *y2);
|
||||
void conv_set_dlg_coords(int32 x1, int32 y1, int32 x2, int32 y2);
|
||||
void conv_set_default_text_colour(int32 norm_colour, int32 hi_colour);
|
||||
void conv_set_default_hv(int32 h, int32 v);
|
||||
|
||||
int conv_get_event();
|
||||
void conv_set_event(int e);
|
||||
int conv_is_event_ready();
|
||||
|
||||
void conv_swap_words(Conv *c);
|
||||
int32 conv_current_node();
|
||||
int32 conv_current_entry();
|
||||
|
||||
int conv_toggle_flags(entry_chunk *entry);
|
||||
int ok_status(entry_chunk *entry);
|
||||
int conv_get_text(int32 offset, int32 size, Conv *c);
|
||||
void cdd_init();
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
52
engines/m4/adv_r/db_env.cpp
Normal file
52
engines/m4/adv_r/db_env.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/str.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "m4/adv_db_r/db_catalog.h"
|
||||
#include "m4/adv_r/db_env.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
char *env_find(const Common::String &descName) {
|
||||
static char name[144];
|
||||
static char resultPath[144];
|
||||
int32 sceneCode;
|
||||
Common::strcpy_s(name, descName.c_str());
|
||||
|
||||
if (descName.hasPrefixIgnoreCase(".raw") || descName.hasPrefixIgnoreCase(".hmp")) {
|
||||
return name;
|
||||
|
||||
} else {
|
||||
db_rmlst_get_asset_room_path(name, resultPath, &sceneCode);
|
||||
if (strlen(resultPath) == 0)
|
||||
return nullptr;
|
||||
|
||||
env_get_path(name, sceneCode, resultPath);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
char *env_get_path(char *resultPath, int room_num, char *fileName) {
|
||||
error("env_get_path not implemented in ScummVM");
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
35
engines/m4/adv_r/db_env.h
Normal file
35
engines/m4/adv_r/db_env.h
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/* 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 M4_ADV_R_DB_ENV_H
|
||||
#define M4_ADV_R_DB_ENV_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
char *env_find(const Common::String &descName);
|
||||
char *env_get_path(char *resultPath, int room_num, char *fileName);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
77
engines/m4/adv_r/kernel.h
Normal file
77
engines/m4/adv_r/kernel.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 M4_ADV_R_KERNEL_H
|
||||
#define M4_ADV_R_KERNEL_H
|
||||
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define CACHE_NOT_OVERRIDE_BY_FLAG_PARSE 2
|
||||
#define KERNEL_RESTORING_GAME -2
|
||||
#define KERNEL_SCRATCH_SIZE 256 // Size of game scratch area
|
||||
|
||||
struct Kernel {
|
||||
uint32 scratch[KERNEL_SCRATCH_SIZE]; // Scratch variables for room
|
||||
bool hag_mode = true;
|
||||
|
||||
uint32 clock = 0; // Current game timing clock
|
||||
int32 trigger = 0; // Game trigger code, if any
|
||||
int32 letter_box_x = 0;
|
||||
int32 letter_box_y = 0;
|
||||
int32 restore_slot = -1;
|
||||
int16 first_non_walker_cel_hash = 0;
|
||||
int16 last_save = 0; // Most recent save slot #
|
||||
|
||||
char save_file_name[8] = { 0 };
|
||||
bool restore_game = false; // TRUE if we wanna restore
|
||||
bool teleported_in = false; // Flag if player teleported to room
|
||||
|
||||
int32 fade_up_time = 0;
|
||||
int16 first_fade = 0;
|
||||
bool fading_to_grey = false;
|
||||
bool suppress_fadeup = false;
|
||||
bool force_restart = false;
|
||||
|
||||
bool pause = false;
|
||||
|
||||
KernelTriggerType trigger_mode = KT_DAEMON; // trigger was/is invoked in this mode
|
||||
bool call_daemon_every_loop = false;
|
||||
bool continue_handling_trigger = true; // set to True in apps code when trigger is to
|
||||
// be handled by the next layer (scene/section/global daemon code)
|
||||
int suppress_cache = CACHE_NOT_OVERRIDE_BY_FLAG_PARSE;
|
||||
bool start_up_with_dbg_ws = false;
|
||||
bool use_debug_monitor = false;
|
||||
bool use_log_file = false;
|
||||
bool track_open_close = false;
|
||||
bool going = false;
|
||||
bool camera_pan_instant = false;
|
||||
bool unused = false;
|
||||
|
||||
size_t mem_avail() const { return 7999999; }
|
||||
bool cameraPans() const { return !camera_pan_instant; }
|
||||
};
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
||||
34
engines/m4/adv_r/other.cpp
Normal file
34
engines/m4/adv_r/other.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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 "m4/adv_r/other.h"
|
||||
#include "m4/adv_r/adv_file.h"
|
||||
#include "m4/core/errors.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void other_save_game_for_resurrection(void) {
|
||||
if (kernel_save_game(0, nullptr, 0, nullptr, 0)) {
|
||||
error_show(FL, 0, "couldn't other_save_game_for_res");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
34
engines/m4/adv_r/other.h
Normal file
34
engines/m4/adv_r/other.h
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
/* 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 M4_ADV_R_OTHER_H
|
||||
#define M4_ADV_R_OTHER_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void other_save_game_for_resurrection();
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user