Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
/* 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 "glk/magnetic/detection.h"
#include "glk/magnetic/detection_tables.h"
#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
#include "engines/game.h"
namespace Glk {
namespace Magnetic {
void MagneticMetaEngine::getSupportedGames(PlainGameList &games) {
for (const PlainGameDescriptor *pd = MAGNETIC_GAME_LIST; pd->gameId; ++pd) {
games.push_back(*pd);
}
}
const GlkDetectionEntry* MagneticMetaEngine::getDetectionEntries() {
return MAGNETIC_GAMES;
}
GameDescriptor MagneticMetaEngine::findGame(const char *gameId) {
for (const PlainGameDescriptor *pd = MAGNETIC_GAME_LIST; pd->gameId; ++pd) {
if (!strcmp(gameId, pd->gameId))
return *pd;
}
return PlainGameDescriptor::empty();
}
bool MagneticMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
const char *const EXTENSIONS[] = { ".mag", ".rsc", nullptr };
// Loop through the files of the folder
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
// Check for a recognised filename
if (file->isDirectory())
continue;
Common::String filename = file->getName();
bool hasExt = false;
for (const char *const *ext = &EXTENSIONS[0]; *ext && !hasExt; ++ext)
hasExt = filename.hasSuffixIgnoreCase(*ext);
if (!hasExt)
continue;
// Open up the file and calculate the md5
Common::File gameFile;
if (!gameFile.open(*file))
continue;
if (gameFile.readUint32BE() != MKTAG('M', 'a', 'S', 'c')) {
gameFile.close();
continue;
}
gameFile.seek(0);
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
size_t filesize = gameFile.size();
gameFile.close();
// Check for known games
const GlkDetectionEntry *p = MAGNETIC_GAMES;
while (p->_gameId && (md5 != p->_md5 || filesize != p->_filesize))
++p;
if (!p->_gameId) {
const PlainGameDescriptor &desc = MAGNETIC_GAME_LIST[0];
gameList.push_back(GlkDetectedGame(desc.gameId, desc.description, filename, md5, filesize));
} else {
PlainGameDescriptor gameDesc = findGame(p->_gameId);
gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, p->_extra, filename, p->_language));
}
}
return !gameList.empty();
}
void MagneticMetaEngine::detectClashes(Common::StringMap &map) {
for (const PlainGameDescriptor *pd = MAGNETIC_GAME_LIST; pd->gameId; ++pd) {
if (map.contains(pd->gameId))
error("Duplicate game Id found - %s", pd->gameId);
map[pd->gameId] = "";
}
}
const gms_game_table_t *gms_gameid_lookup_game(uint32 undo_size, uint32 undo_pc) {
const gms_game_table_t *game;
for (game = GMS_GAME_TABLE; game->name; game++) {
if (game->undo_size == undo_size && game->undo_pc == undo_pc)
break;
}
return game->name ? game : nullptr;
}
} // End of namespace Magnetic
} // End of namespace Glk

View File

@@ -0,0 +1,85 @@
/* 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 GLK_MAGNETIC_DETECTION
#define GLK_MAGNETIC_DETECTION
#include "common/fs.h"
#include "common/hash-str.h"
#include "engines/game.h"
#include "glk/detection.h"
namespace Glk {
namespace Magnetic {
/**
* The following game database is built from Generic/games.txt, and is used
* to identify the game being run. Magnetic Scrolls games don't generally
* supply a status line, so this data can be used instead.
*/
struct gms_game_table_t {
const uint32 undo_size; ///< Header word at offset 0x22
const uint32 undo_pc; ///< Header word at offset 0x26
const char *const name; ///< Game title and platform
};
typedef const gms_game_table_t *gms_game_tableref_t;
/**
* Meta engine for Magnetic interpreter
*/
class MagneticMetaEngine {
public:
/**
* Get a list of supported games
*/
static void getSupportedGames(PlainGameList &games);
/**
* Get the detection entries
*/
static const GlkDetectionEntry* getDetectionEntries();
/**
* Returns a game description for the given game Id, if it's supported
*/
static GameDescriptor findGame(const char *gameId);
/**
* Detect supported games
*/
static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
/**
* Check for game Id clashes with other sub-engines
*/
static void detectClashes(Common::StringMap &map);
};
/**
* Look up and return the game table entry given a game's undo size and
* undo pc values. Returns the entry, or NULL if not found.
*/
extern const gms_game_table_t *gms_gameid_lookup_game(uint32 undo_size, uint32 undo_pc);
} // End of namespace Magnetic
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,102 @@
/* 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 "engines/game.h"
#include "common/language.h"
namespace Glk {
namespace Magnetic {
const PlainGameDescriptor MAGNETIC_GAME_LIST[] = {
{ "magnetic", "Magnetic Scrolls Game" },
{ "corruption", "Corruption" },
{ "fish", "Fish!" },
{ "guild", "The Guild of Thieves" },
{ "jinxter", "Jinxter" },
{ "myth", "Myth" },
{ "pawn", "The Pawn" },
{ "wonderland", "Wonderland" },
{ nullptr, nullptr }
};
const GlkDetectionEntry MAGNETIC_GAMES[] = {
DT_ENTRY0("corruption", "313880cbe0f15bfa259ebaf228b4d0e9", 167466),
DT_ENTRY1("corruption", "Collection", "6fe35b357fa0311450d3a9c809e60ba8", 177185),
DT_ENTRY0("fish", "2efb8118f4cb9a36bb54646ce41a950e", 162858),
DT_ENTRY1("fish", "Collection", "cfe333306597d36c8aa3fc64f6be94ba", 172517),
DT_ENTRY0("guild", "bab78740d39ee5e058faf4912fdbf33d", 130858),
DT_ENTRY1("guild", "Collection", "36af907a4ec9db909148f308287586f1", 141766),
DT_ENTRY0("jinxter", "998cf5c49a67409bd344e59307a5213e", 156458),
DT_ENTRY0("myth", "9c2a5272a9c0b1e173401ba4df32567a", 99370),
DT_ENTRY0("pawn", "4a7847980f9e942acd7aa51ea12a6586", 103466),
DT_ENTRY0("wonderland", "2cea8fccf42d570be8836416c2802613", 183916),
DT_END_MARKER
};
const gms_game_table_t GMS_GAME_TABLE[] = {
{0x2100, 0x427e, "Corruption v1.11 (Amstrad CPC)"},
{0x2100, 0x43a0, "Corruption v1.11 (Archimedes)"},
{0x2100, 0x43a0, "Corruption v1.11 (DOS)"},
{0x2100, 0x4336, "Corruption v1.11 (Commodore 64)"},
{0x2100, 0x4222, "Corruption v1.11 (Spectrum +3)"},
{0x2100, 0x4350, "Corruption v1.12 (Archimedes)"},
{0x2500, 0x6624, "Corruption v1.12 (DOS, Magnetic Windows)"},
{0x2300, 0x3fa0, "Fish v1.02 (DOS)"},
{0x2400, 0x4364, "Fish v1.03 (Spectrum +3)"},
{0x2300, 0x3f72, "Fish v1.07 (Commodore 64)"},
{0x2200, 0x3f9c, "Fish v1.08 (Archimedes)"},
{0x2a00, 0x583a, "Fish v1.10 (DOS, Magnetic Windows)"},
{0x5000, 0x6c30, "Guild v1.0 (Amstrad CPC)"},
{0x5000, 0x6cac, "Guild v1.0 (Commodore 64)"},
{0x5000, 0x6d5c, "Guild v1.1 (DOS)"},
{0x3300, 0x698a, "Guild v1.3 (Archimedes)"},
{0x3200, 0x6772, "Guild v1.3 (Spectrum +3)"},
{0x3400, 0x6528, "Guild v1.3 (DOS, Magnetic Windows)"},
{0x2b00, 0x488c, "Jinxter v1.05 (Commodore 64)"},
{0x2c00, 0x4a08, "Jinxter v1.05 (DOS)"},
{0x2c00, 0x487a, "Jinxter v1.05 (Spectrum +3)"},
{0x2c00, 0x4a56, "Jinxter v1.10 (DOS)"},
{0x2b00, 0x4924, "Jinxter v1.22 (Amstrad CPC)"},
{0x2c00, 0x4960, "Jinxter v1.30 (Archimedes)"},
{0x1600, 0x3940, "Myth v1.0 (Commodore 64)"},
{0x1500, 0x3a0a, "Myth v1.0 (DOS)"},
{0x3600, 0x42cc, "Pawn v2.3 (Amstrad CPC)"},
{0x3600, 0x4420, "Pawn v2.3 (Archimedes)"},
{0x3600, 0x3fb0, "Pawn v2.3 (Commodore 64)"},
{0x3600, 0x4420, "Pawn v2.3 (DOS)"},
{0x3900, 0x42e4, "Pawn v2.3 (Spectrum 128)"},
{0x3900, 0x42f4, "Pawn v2.4 (Spectrum +3)"},
{0x3900, 0x75f2, "Wonderland v1.21 (DOS, Magnetic Windows)"},
{0x3900, 0x75f8, "Wonderland v1.27 (Archimedes)"},
{0, 0, NULL}
};
} // End of namespace Magnetic
} // End of namespace Glk

3530
engines/glk/magnetic/emu.cpp Normal file

File diff suppressed because it is too large Load Diff

4004
engines/glk/magnetic/glk.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,203 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "glk/magnetic/magnetic.h"
#include "glk/magnetic/magnetic_defs.h"
#include "common/config-manager.h"
#include "common/translation.h"
namespace Glk {
namespace Magnetic {
Magnetic *g_vm;
Magnetic::Magnetic(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
gms_gamma_mode(GAMMA_NORMAL), gms_animation_enabled(true),
gms_prompt_enabled(true), gms_abbreviations_enabled(true), gms_commands_enabled(true),
gms_graphics_enabled(true), GMS_PORT_VERSION(0x00010601),
gms_main_window(nullptr), gms_status_window(nullptr), gms_graphics_window(nullptr),
gms_hint_menu_window(nullptr), gms_hint_text_window(nullptr),
gms_transcript_stream(nullptr), gms_readlog_stream(nullptr),
gms_inputlog_stream(nullptr), gms_graphics_possible(true),
GMS_INPUT_PROMPT(">"), gms_gameid_game_name(nullptr), gms_graphics_bitmap(nullptr),
gms_graphics_width(0), gms_graphics_height(0), gms_graphics_animated(false),
gms_graphics_picture(0), gms_graphics_new_picture(false),
gms_graphics_repaint(false), gms_graphics_active(false),
gms_graphics_interpreter(false), gms_graphics_off_screen(nullptr),
gms_graphics_on_screen(nullptr), gms_graphics_current_gamma(Magnetic::GMS_GAMMA_TABLE),
gms_graphics_color_count(GMS_PALETTE_SIZE), gms_status_length(0),
gms_help_requested(false), gms_help_hints_silenced(false), gms_output_buffer(nullptr),
gms_output_allocation(0),gms_output_length(0), gms_output_prompt(false),
gms_hints(nullptr), gms_current_hint_node(0), gms_hint_cursor(nullptr),
gms_input_length(0), gms_input_cursor(0), gms_undo_notification(false),
gms_game_message(nullptr), gms_startup_called(false), gms_main_called(false),
i_count(0), string_size(0), rseed(0), pc(0), arg1i(0), mem_size(0), properties(0),
fl_sub(0), fl_tab(0), fl_size(0), fp_tab(0), fp_size(0), zflag(0), nflag(0),
cflag(0), vflag(0), byte1(0), byte2(0), regnr(0), admode(0), opsize(0),
arg1(nullptr), arg2(nullptr), is_reversible(0), running(0), lastchar(0), version(0),
sd(0), decode_table(nullptr), restart(nullptr), code(nullptr), string(nullptr),
string2(nullptr), string3(nullptr), dict(nullptr), quick_flag(0), gfx_ver(0),
gfx_buf(nullptr), gfx_data(nullptr), gfx2_hdr(nullptr), gfx2_buf(nullptr),
gfx2_name(nullptr), gfx2_hsize(0), gfx_fp(nullptr), snd_buf(nullptr), snd_hdr(nullptr),
snd_hsize(0), snd_fp(nullptr), undo_pc(0), undo_size(0), gfxtable(0), table_dist(0),
v4_id(0), next_table(1)
#ifndef NO_ANIMATION
, pos_table_size(0), command_table(nullptr), command_index(-1),
pos_table_index(-1), pos_table_max(-1), anim_repeat(0)
#endif
, hints(nullptr), hint_contents(nullptr), xpos(0), bufpos(0), log_on(0),
ms_gfx_enabled(0), _log1(nullptr), _log2(nullptr), GMS_LUMINANCE_WEIGHTS(299, 587, 114),
linear_gamma(nullptr), pic_current_crc(0), hints_current_crc(0),
hints_crc_initialized(false), _saveData(nullptr), _saveSize(0) {
Common::fill(&gms_graphics_palette[0], &gms_graphics_palette[GMS_PALETTE_SIZE], 0);
Common::fill(&gms_status_buffer[0], &gms_status_buffer[GMS_STATBUFFER_LENGTH], '\0');
Common::fill(&gms_input_buffer[0], &gms_input_buffer[GMS_INPUTBUFFER_LENGTH], '\0');
Common::fill(&dreg[0], &dreg[8], 0);
Common::fill(&areg[0], &areg[8], 0);
Common::fill(&tmparg[0], &tmparg[4], 0);
Common::fill(&undo_regs[0][0], &undo_regs[1][18], 0);
undo[0] = undo[1] = nullptr;
undo_stat[0] = undo_stat[1] = 0;
Common::fill(&buffer[0], &buffer[80], 0);
Common::fill(&filename[0], &filename[256], 0);
Common::fill(&crc_table[0], &crc_table[BYTE_MAX_VAL + 1], 0);
#ifndef NO_ANIMATION
Common::fill(&pos_table_count[0], &pos_table_count[MAX_POSITIONS], 0);
#endif
luminance_weighting = GMS_LUMINANCE_WEIGHTS.red + GMS_LUMINANCE_WEIGHTS.green
+ GMS_LUMINANCE_WEIGHTS.blue;
g_vm = this;
}
void Magnetic::runGame() {
initialize();
gms_main();
}
void Magnetic::initialize() {
initializeSettings();
initializeCRC();
initializeLinearGamma();
// Close the already opened gamefile, since the Magnetic code will open it on it's own
_gameFile.close();
}
void Magnetic::initializeSettings() {
// Local handling for Glk special commands
if (ConfMan.hasKey("commands_enabled"))
gms_commands_enabled = ConfMan.getBool("commands_enabled");
// Abbreviation expansions
if (ConfMan.hasKey("abbreviations_enabled"))
gms_abbreviations_enabled = ConfMan.getBool("abbreviations_enabled");
// Pictures enabled
if (ConfMan.hasKey("graphics_enabled"))
gms_graphics_enabled = ConfMan.getBool("graphics_enabled");
// Automatic gamma correction on pictures
if (ConfMan.hasKey("gamma_mode") && !ConfMan.getBool("gamma_mode"))
gms_gamma_mode = GAMMA_OFF;
// Animations
if (ConfMan.hasKey("animation_enabled"))
gms_animation_enabled = ConfMan.getBool("animation_enabled");
// Prompt enabled
if (ConfMan.hasKey("prompt_enabled"))
gms_prompt_enabled = ConfMan.getBool("prompt_enabled");
}
void Magnetic::initializeCRC() {
/* CRC table initialization polynomial. */
const glui32 GMS_CRC_POLYNOMIAL = 0xedb88320;
uint32 crc;
for (uint index = 0; index < BYTE_MAX_VAL + 1; ++index) {
int bit;
crc = index;
for (bit = 0; bit < BITS_PER_BYTE; bit++)
crc = crc & 1 ? GMS_CRC_POLYNOMIAL ^ (crc >> 1) : crc >> 1;
crc_table[index] = crc;
}
/* CRC lookup table self-test, after is_initialized set -- recursion. */
assert(gms_get_buffer_crc("123456789", 9) == 0xcbf43926);
}
void Magnetic::initializeLinearGamma() {
/* Find and cache the uncorrected gamma table entry. */
gms_gammaref_t gamma;
for (gamma = GMS_GAMMA_TABLE; gamma->level; gamma++) {
if (!gamma->is_corrected) {
linear_gamma = gamma;
break;
}
}
}
type8 Magnetic::ms_load_file(const char *name, type8 *ptr, type16 size) {
_saveData = ptr;
_saveSize = size;
return loadGame().getCode() == Common::kNoError ? 0 : 1;
}
Common::Error Magnetic::readSaveData(Common::SeekableReadStream *rs) {
return rs->read(_saveData, _saveSize) == _saveSize ? Common::kNoError : Common::kReadingFailed;
}
type8 Magnetic::ms_save_file(const char *name, type8 *ptr, type16 size) {
_saveData = ptr;
_saveSize = size;
return saveGame().getCode() == Common::kNoError ? 0 : 1;
}
Common::Error Magnetic::writeGameData(Common::WriteStream *ws) {
return ws->write(_saveData, _saveSize) == _saveSize ? Common::kNoError : Common::kWritingFailed;
}
/**
* The Magnetic engine currently doesn't support loading savegames from the GMM
*/
bool Magnetic::canLoadGameStateCurrently(Common::U32String *msg) {
if (msg)
*msg = _("This game does not support loading from the menu. Use in-game interface");
return false;
}
/**
* The Magnetic engine currently doesn't support saving games from the GMM
*/
bool Magnetic::canSaveGameStateCurrently(Common::U32String *msg) {
if (msg)
*msg = _("This game does not support saving from the menu. Use in-game interface");
return false;
}
} // End of namespace Magnetic
} // End of namespace Glk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
/* 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 MAGNETIC_DEFS_H
#define MAGNETIC_DEFS_H
#include "common/scummsys.h"
namespace Glk {
namespace Magnetic {
/*****************************************************************************\
* Type definitions for Magnetic
*
* Note: When running into trouble please ensure that these types have the
* correct number of bits on your system !!!
\*****************************************************************************/
typedef byte type8;
typedef int8 type8s;
typedef uint16 type16;
typedef int16 type16s;
typedef uint32 type32;
typedef int32 type32s;
enum { BYTE_MAX_VAL = 255 };
enum { BITS_PER_BYTE = 8 };
enum { UINT16_MAX_VAL = 0xffff };
enum { INT32_MAX_VAL = 0x7fffffff };
#define MAX_HINTS 260
#define MAX_HCONTENTS 30000
#define MAX_POSITIONS 20
#define MAX_ANIMS 200
#define MAX_FRAMES 20
#define MAX_STRING_SIZE 0xFF00
#define MAX_PICTURE_SIZE 0xC800
#define MAX_MUSIC_SIZE 0x4E20
#define MAX_HITEMS 25
/****************************************************************************\
* Compile time switches
\****************************************************************************/
/* Switch: SAVEMEM
Purpose: Magnetic loads a complete graphics file into memory by default.
Setting this switch you tell Magnetic to load images on request
(saving memory, wasting load time)
#define SAVEMEM
*/
/* Switch: NO_ANIMATION
Purpose: By default Magnetic plays animated graphics.
Setting this switch to ignore animations, Magnetic shows the
static parts of the images anyway!
#define NO_ANIMATION
*/
/****************************************************************************\
* Miscellaneous enums/types
*
\****************************************************************************/
enum { GMS_PALETTE_SIZE = 16 };
enum { GMS_INPUTBUFFER_LENGTH = 256 };
enum { GMS_STATBUFFER_LENGTH = 1024 };
enum GammaMode {
GAMMA_OFF, GAMMA_NORMAL, GAMMA_HIGH
};
/* Hint type definitions. */
enum {
GMS_HINT_TYPE_FOLDER = 1,
GMS_HINT_TYPE_TEXT = 2
};
} // End of namespace Magnetic
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,156 @@
/* 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 GLK_MAGNETIC_TYPES
#define GLK_MAGNETIC_TYPES
#include "common/scummsys.h"
#include "glk/magnetic/magnetic_defs.h"
namespace Glk {
namespace Magnetic {
struct lookup {
int16 flag;
int16 count;
lookup() : flag(0), count(0) {}
};
struct picture {
byte *data;
uint32 data_size;
uint16 width;
uint16 height;
uint16 wbytes;
uint16 plane_step;
byte *mask;
picture() : data(nullptr), data_size(0), width(0), height(0), wbytes(0), plane_step(0),
mask(nullptr) {}
};
/**
* Magnetic animated pictures support
*
* Note: Some of the pictures for Wonderland and the Collection Volume 1 games
* are animations. To detect these, pass a pointer to a type8 as the is_anim
* argument to ms_extract().
*
* There are two types of animated images, however almost all images are type1.
* A type1 image consists of four main elements:
* 1) A static picture which is loaded straight at the beginning
* 2) A set of frames with a mask. These frames are just "small pictures", which
* are coded like the normal static pictures. The image mask determines
* how the frame is removed after it has been displayed. A mask is exactly
* 1/8 the size of the image and holds 1 bit per pixel, saying "remove pixel"
* or leave pixel set when frame gets removed. It might be a good idea to check
* your system documentation for masking operations as your system might be
* able to use this mask data directly.
* 3) Positioning tables. These hold animation sequences consisting of commands
* like "Draw frame 12 at (123,456)"
* 4) A playback script, which determines how to use the positioning tables.
* These scripts are handled inside Magnetic, so no need to worry about.
* However, details can be found in the ms_animate() function.
*
* A type2 image is like a type1 image, but it does not have a static
* picture, nor does it have frame masking. It just consists of frames.
*
* How to support animations?
* After getting is_anim == 1 you should call ms_animate() immediately, and at
* regular intervals until ms_animate() returns 0. An appropriate interval
* between calls is about 100 milliseconds.
* Each call to ms_animate() will fill in the arguments with the address
* and size of an array of ms_position structures (see below), each of
* which holds an animation frame number and x and y co-ordinates. To
* display the animation, decode all the animation frames (discussed below)
* from a single call to ms_animate() and display each one over the main picture.
* If your port does not support animations, define NO_ANIMATION.
*/
struct ms_position {
int16 x, y;
int16 number;
ms_position() : x(0), y(0), number(0) {}
};
/**
* Magnetic Windows hint support
*
* The windowed Magnetic Scolls games included online hints. To add support
* for the hints to your magnetic port, you should implement the ms_showhints
* function. It retrieves a pointer to an array of ms_hint structs
* The root element is always hints[0]. The elcount determines the number
* of items in this topic. You probably want to display those in some kind
* of list interface. The content pointer points to the actual description of
* the items, separated by '\0' terminators. The nodetype is 1 if the items are
* "folders" and 2 if the items are hints. Hints should be displayed one after
* another. For "folder" items, the links array holds the index of the hint in
* the array which is to be displayed on selection. One hint block has exactly
* one type. The parent element determines the "back" target.
*/
struct ms_hint {
uint16 elcount;
uint16 nodetype;
const char *content;
uint16 links[MAX_HITEMS];
uint16 parent;
ms_hint() : elcount(0), nodetype(0), content(nullptr), parent(0) {
Common::fill(&links[0], &links[MAX_HITEMS], 0);
}
};
struct gms_gamma_t {
const char *const level; ///< Gamma correction level
const unsigned char table[8]; ///< Color lookup table
const bool is_corrected; ///< Flag if non-linear
};
typedef const gms_gamma_t *gms_gammaref_t;
/* R,G,B color triple definition. */
struct gms_rgb_t {
int red, green, blue;
gms_rgb_t() : red(0), green(0), blue(0) {}
gms_rgb_t(int r, int g, int b) : red(r), green(b), blue(b) {}
};
typedef gms_rgb_t *gms_rgbref_t;
#ifndef GARGLK
struct gms_layering_t {
long complexity; /* Count of vertices for this color. */
long usage; /* Color usage count. */
int color; /* Color index into palette. */
};
#endif
/* Table of single-character command abbreviations. */
struct gms_abbreviation_t {
const char abbreviation; /* Abbreviation character. */
const char *const expansion; /* Expansion string. */
};
typedef gms_abbreviation_t *gms_abbreviationref_t;
} // End of namespace Magnetic
} // End of namespace Glk
#endif