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

372
engines/tony/mpal/expr.cpp Normal file
View File

@@ -0,0 +1,372 @@
/* 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#include "tony/mpal/mpal.h"
#include "tony/mpal/memory.h"
#include "tony/mpal/mpaldll.h"
#include "tony/tony.h"
namespace Tony {
namespace MPAL {
static const size_t EXPR_LENGTH_SIZE =
#ifndef NO_CXX11_ALIGNAS
alignof(max_align_t)
#else
sizeof(byte)
#endif
;
/**
* Duplicate a mathematical expression.
*
* @param h Handle to the original expression
* @retruns Pointer to the cloned expression
*/
static void *duplicateExpression(MpalHandle h) {
byte *orig, *clone;
orig = (byte *)globalLock(h);
int num = *orig;
LpExpression one = (LpExpression)(orig + EXPR_LENGTH_SIZE);
clone = (byte *)globalAlloc(GMEM_FIXED, sizeof(Expression) * num + EXPR_LENGTH_SIZE);
LpExpression two = (LpExpression)(clone + EXPR_LENGTH_SIZE);
memcpy(clone, orig, sizeof(Expression) * num + EXPR_LENGTH_SIZE);
for (int i = 0; i < num; i++) {
if (one->_type == ELT_PARENTH) {
two->_type = ELT_PARENTH2;
two->_val._pson = duplicateExpression(two->_val._son);
}
++one;
++two;
}
globalUnlock(h);
return clone;
}
static int32 Compute(int32 a, int32 b, byte symbol) {
switch (symbol) {
case OP_MUL:
return a * b;
case OP_DIV:
return a / b;
case OP_MODULE:
return a % b;
case OP_ADD:
return a + b;
case OP_SUB:
return a - b;
case OP_SHL:
return a << b;
case OP_SHR:
return a >> b;
case OP_MINOR:
return a < b;
case OP_MAJOR:
return a > b;
case OP_MINEQ:
return a <= b;
case OP_MAJEQ:
return a >= b;
case OP_EQUAL:
return a == b;
case OP_NOEQUAL:
return a != b;
case OP_BITAND:
return a & b;
case OP_BITXOR:
return a ^ b;
case OP_BITOR:
return a | b;
case OP_AND:
return a && b;
case OP_OR:
return a || b;
default:
GLOBALS._mpalError = 1;
break;
}
return 0;
}
static void solve(LpExpression one, int num) {
LpExpression two, three;
while (num > 1) {
two = one + 1;
if ((two->_symbol == 0) || (one->_symbol & 0xF0) <= (two->_symbol & 0xF0)) {
two->_val._num = Compute(one->_val._num, two->_val._num, one->_symbol);
memmove(one, two, (num - 1) * sizeof(Expression));
--num;
} else {
int j = 1;
three = two + 1;
while ((three->_symbol != 0) && (two->_symbol & 0xF0) > (three->_symbol & 0xF0)) {
++two;
++three;
++j;
}
three->_val._num = Compute(two->_val._num, three->_val._num, two->_symbol);
memmove(two, three, (num - j - 1) * sizeof(Expression));
--num;
}
}
}
/**
* Calculates the result of a mathematical expression, replacing the current
* value of any variable.
*
* @param expr Pointer to an expression duplicated by DuplicateExpression
* @returns Value
*/
static int32 evaluateAndFreeExpression(void *expr) {
int num = *(byte *)expr;
LpExpression one = (LpExpression)((byte *)expr + EXPR_LENGTH_SIZE);
// 1) Substitutions of variables
LpExpression cur = one;
for (int i = 0; i < num; i++, cur++) {
if (cur->_type == ELT_VAR) {
cur->_type = ELT_NUMBER;
cur->_val._num = varGetValue(cur->_val._name);
}
}
// 2) Replacement of brackets (using recursive calls)
cur = one;
for (int i = 0; i < num; i++, cur++) {
if (cur->_type == ELT_PARENTH2) {
cur->_type = ELT_NUMBER;
cur->_val._num = evaluateAndFreeExpression(cur->_val._pson);
}
}
// 3) algebraic resolution
solve(one, num);
int32 val = one->_val._num;
globalDestroy(expr);
return val;
}
/**
* Parses a mathematical expression from the MPC file
*
* @param buf Buffer containing the expression to evaluate
* @param h Pointer to a handle that, at the end of execution,
* will point to the area of memory containing the parsed expression
* @returns Pointer to the buffer immediately after the expression, or NULL if error.
*/
const byte *parseExpression(const byte *lpBuf, const Common::UnalignedPtr<MpalHandle> &h) {
byte *start;
byte num = *lpBuf;
lpBuf++;
if (num == 0)
return NULL;
h.store(globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, num * sizeof(Expression) + EXPR_LENGTH_SIZE));
if (h.load() == NULL)
return NULL;
start = (byte *)globalLock(h.load());
*start = num;
LpExpression cur = (LpExpression)(start + EXPR_LENGTH_SIZE);
for (uint32 i = 0;i < num; i++) {
cur->_type = *(lpBuf);
// *(lpBuf + 1) contains the unary operator, unused => skipped
lpBuf += 2;
switch (cur->_type) {
case ELT_NUMBER:
cur->_val._num = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
break;
case ELT_VAR:
// As name is a byte, there is no alignment rule
cur->_val._name = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, (*lpBuf) + 1);
if (cur->_val._name == NULL)
return NULL;
memcpy(cur->_val._name, lpBuf + 1, *lpBuf);
lpBuf += *lpBuf + 1;
break;
case ELT_PARENTH:
lpBuf = parseExpression(lpBuf, &cur->_val._son);
if (lpBuf == NULL)
return NULL;
break;
default:
return NULL;
}
cur->_symbol = *lpBuf;
lpBuf++;
cur++;
}
if (*lpBuf != 0)
return NULL;
lpBuf++;
return lpBuf;
}
/**
* Calculate the value of a mathematical expression
*
* @param h Handle to the expression
* @returns Numeric value
*/
int32 evaluateExpression(MpalHandle h) {
lockVar();
int32 ret = evaluateAndFreeExpression(duplicateExpression(h));
unlockVar();
return ret;
}
/**
* Compare two mathematical expressions together
*
* @param h1 Expression to be compared
* @param h2 Expression to be compared
*/
bool compareExpressions(MpalHandle h1, MpalHandle h2) {
byte *e1, *e2;
e1 = (byte *)globalLock(h1);
e2 = (byte *)globalLock(h2);
int num1 = *e1;
int num2 = *e2;
if (num1 != num2) {
globalUnlock(h1);
globalUnlock(h2);
return false;
}
LpExpression one = (LpExpression)(e1 + EXPR_LENGTH_SIZE);
LpExpression two = (LpExpression)(e2 + EXPR_LENGTH_SIZE);
for (int i = 0; i < num1; i++) {
if (one->_type != two->_type || (i != num1 - 1 && one->_symbol != two->_symbol)) {
globalUnlock(h1);
globalUnlock(h2);
return false;
}
switch (one->_type) {
case ELT_NUMBER:
if (one->_val._num != two->_val._num) {
globalUnlock(h1);
globalUnlock(h2);
return false;
}
break;
case ELT_VAR:
if (strcmp(one->_val._name, two->_val._name) != 0) {
globalUnlock(h1);
globalUnlock(h2);
return false;
}
break;
case ELT_PARENTH:
if (!compareExpressions(one->_val._son, two->_val._son)) {
globalUnlock(h1);
globalUnlock(h2);
return false;
}
break;
default:
break;
}
++one;
++two;
}
globalUnlock(h1);
globalUnlock(h2);
return true;
}
/**
* Frees an expression that was previously parsed
*
* @param h Handle for the expression
*/
void freeExpression(MpalHandle h) {
byte *data = (byte *)globalLock(h);
int num = *data;
LpExpression cur = (LpExpression)(data + EXPR_LENGTH_SIZE);
for (int i = 0; i < num; ++i, ++cur) {
switch (cur->_type) {
case ELT_VAR:
globalDestroy(cur->_val._name);
break;
case ELT_PARENTH:
freeExpression(cur->_val._son);
break;
default:
break;
}
}
globalUnlock(h);
globalFree(h);
}
} // end of namespace MPAL
} // end of namespace Tony

138
engines/tony/mpal/expr.h Normal file
View File

@@ -0,0 +1,138 @@
/* 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#ifndef MPAL_EXPR_H
#define MPAL_EXPR_H
#include "tony/mpal/memory.h"
namespace Tony {
namespace MPAL {
/**
* @defgroup Mathematical operations
*/
//@{
#define OP_MUL ((1 << 4) | 0)
#define OP_DIV ((1 << 4) | 1)
#define OP_MODULE ((1 << 4) | 2)
#define OP_ADD ((2 << 4) | 0)
#define OP_SUB ((2 << 4) | 1)
#define OP_SHL ((3 << 4) | 0)
#define OP_SHR ((3 << 4) | 1)
#define OP_MINOR ((4 << 4) | 0)
#define OP_MAJOR ((4 << 4) | 1)
#define OP_MINEQ ((4 << 4) | 2)
#define OP_MAJEQ ((4 << 4) | 3)
#define OP_EQUAL ((5 << 4) | 0)
#define OP_NOEQUAL ((5 << 4) | 1)
#define OP_BITAND ((6 << 4) | 0)
#define OP_BITXOR ((7 << 4) | 0)
#define OP_BITOR ((8 << 4) | 0)
#define OP_AND ((9 << 4) | 0)
#define OP_OR ((10 << 4) | 0)
//@}
/**
* @defgroup Structures
*/
//@{
/**
* Mathematical framework to manage operations
*/
typedef struct {
byte _type; // Object Type (see enum ExprListTypes)
union {
int32 _num; // Identifier (if type == ELT_NUMBER)
char *_name; // Variable name (if type == ELT_VAR)
MpalHandle _son; // Handle expressions (if type == ELT_PARENTH)
void *_pson; // Handle lockato (if type == ELT_PARENTH2)
} _val;
byte _symbol; // Mathematic symbols (see #define OP_*)
} Expression;
typedef Expression *LpExpression;
//@}
/**
* Object types that can be contained in an EXPRESSION structure
*/
enum ExprListTypes {
ELT_NUMBER = 1,
ELT_VAR = 2,
ELT_PARENTH = 3,
ELT_PARENTH2 = 4
};
/****************************************************************************\
* Function Prototypes
\****************************************************************************/
/**
* Parses a mathematical expression from the MPC file
*
* @param buf Buffer containing the expression to evaluate
* @param h Pointer to a handle that, at the end of execution,
* will point to the area of memory containing the parsed expression
* @returns Pointer to the buffer immediately after the expression, or NULL if error.
*/
const byte *parseExpression(const byte *lpBuf, const Common::UnalignedPtr<MpalHandle> &h);
/**
* Calculate the value of a mathematical expression
*
* @param h Handle to the expression
* @returns Numeric value
*/
int32 evaluateExpression(MpalHandle h);
/**
* Compare two mathematical expressions together
*
* @param h1 Expression to be compared
* @param h2 Expression to be compared
*/
bool compareExpressions(MpalHandle h1, MpalHandle h2);
/**
* Frees an expression that was previously parsed
*
* @param h Handle for the expression
*/
void freeExpression(MpalHandle h);
} // end of namespace MPAL
} // end of namespace Tony
#endif

View File

@@ -0,0 +1,786 @@
/* 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#include "mpal.h"
#include "mpaldll.h"
#include "memory.h"
#include "tony/tony.h"
namespace Tony {
namespace MPAL {
/****************************************************************************\
* Static functions
\****************************************************************************/
static bool compareCommands(struct Command *cmd1, struct Command *cmd2) {
if (cmd1->_type == 2 && cmd2->_type == 2) {
if (strcmp(cmd1->_lpszVarName, cmd2->_lpszVarName) == 0 &&
compareExpressions(cmd1->_expr, cmd2->_expr))
return true;
else
return false;
} else
return (memcmp(cmd1, cmd2, sizeof(struct Command)) == 0);
}
/**
* Parses a script from the MPC file, and inserts its data into a structure
*
* @param lpBuf Buffer containing the compiled script.
* @param lpmsScript Pointer to a structure that will be filled with the
* data of the script.
* @returns Pointer to the buffer after the item, or NULL on failure.
*/
static const byte *ParseScript(const byte *lpBuf, LpMpalScript lpmsScript) {
lpmsScript->_nObj = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmsScript->_nMoments = READ_LE_UINT16(lpBuf);
lpBuf += 2;
int curCmd = 0;
for (uint i = 0; i < lpmsScript->_nMoments; i++) {
lpmsScript->_moment[i]._dwTime = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmsScript->_moment[i]._nCmds = *lpBuf;
lpBuf++;
for (int j = 0; j < lpmsScript->_moment[i]._nCmds; j++) {
lpmsScript->_command[curCmd]._type = *lpBuf;
lpBuf++;
switch (lpmsScript->_command[curCmd]._type) {
case 1:
lpmsScript->_command[curCmd]._nCf = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmsScript->_command[curCmd]._arg1 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmsScript->_command[curCmd]._arg2 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmsScript->_command[curCmd]._arg3 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmsScript->_command[curCmd]._arg4 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
break;
case 2: { // Variable assign
int len = *lpBuf;
lpBuf++;
lpmsScript->_command[curCmd]._lpszVarName = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len + 1);
if (lpmsScript->_command[curCmd]._lpszVarName == NULL)
return NULL;
memcpy(lpmsScript->_command[curCmd]._lpszVarName, lpBuf, len);
lpBuf += len;
lpBuf = parseExpression(lpBuf, &lpmsScript->_command[curCmd]._expr);
if (lpBuf == NULL)
return NULL;
break;
}
default:
return NULL;
}
lpmsScript->_moment[i]._cmdNum[j] = curCmd;
curCmd++;
}
}
return lpBuf;
}
/**
* Frees a script allocated via a previous call to ParseScript
*
* @param lpmsScript Pointer to a script structure
*/
static void FreeScript(LpMpalScript lpmsScript) {
for (int i = 0; i < MAX_COMMANDS_PER_SCRIPT && (lpmsScript->_command[i]._type); ++i, ++lpmsScript) {
if (lpmsScript->_command[i]._type == 2) {
// Variable Assign
globalDestroy(lpmsScript->_command[i]._lpszVarName);
freeExpression(lpmsScript->_command[i]._expr);
}
}
}
/**
* Parses a dialog from the MPC file, and inserts its data into a structure
*
* @param lpBuf Buffer containing the compiled dialog.
* @param lpmdDialog Pointer to a structure that will be filled with the
* data of the dialog.
* @returns Pointer to the buffer after the item, or NULL on failure.
*/
static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) {
lpmdDialog->_nObj = READ_LE_UINT32(lpBuf);
lpBuf += 4;
// Periods
uint32 num = READ_LE_UINT16(lpBuf);
lpBuf += 2;
if (num >= MAX_PERIODS_PER_DIALOG - 1)
error("Too much periods in dialog #%d", lpmdDialog->_nObj);
uint32 i;
for (i = 0; i < num; i++) {
lpmdDialog->_periodNums[i] = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmdDialog->_periods[i] = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, *lpBuf + 1);
byte *lpLock = (byte *)globalLock(lpmdDialog->_periods[i]);
Common::copy(lpBuf + 1, lpBuf + 1 + *lpBuf, lpLock);
globalUnlock(lpmdDialog->_periods[i]);
lpBuf += (*lpBuf) + 1;
}
lpmdDialog->_periodNums[i] = 0;
lpmdDialog->_periods[i] = NULL;
// Groups
num = READ_LE_UINT16(lpBuf);
lpBuf += 2;
uint32 curCmd = 0;
if (num >= MAX_GROUPS_PER_DIALOG)
error("Too much groups in dialog #%d", lpmdDialog->_nObj);
for (i = 0; i < num; i++) {
lpmdDialog->_group[i]._num = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmdDialog->_group[i]._nCmds = *lpBuf; lpBuf++;
if (lpmdDialog->_group[i]._nCmds >= MAX_COMMANDS_PER_GROUP)
error("Too much commands in group #%d in dialog #%d", lpmdDialog->_group[i]._num, lpmdDialog->_nObj);
for (uint32 j = 0; j < lpmdDialog->_group[i]._nCmds; j++) {
lpmdDialog->_command[curCmd]._type = *lpBuf;
lpBuf++;
switch (lpmdDialog->_command[curCmd]._type) {
// Call custom function
case 1:
lpmdDialog->_command[curCmd]._nCf = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmdDialog->_command[curCmd]._arg1 = READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmdDialog->_command[curCmd]._arg2 = READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmdDialog->_command[curCmd]._arg3 = READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmdDialog->_command[curCmd]._arg4 = READ_LE_UINT32(lpBuf);
lpBuf += 4;
break;
// Variable assign
case 2: {
uint32 len = *lpBuf;
lpBuf++;
lpmdDialog->_command[curCmd]._lpszVarName = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len + 1);
if (lpmdDialog->_command[curCmd]._lpszVarName == NULL)
return NULL;
Common::copy(lpBuf, lpBuf + len, lpmdDialog->_command[curCmd]._lpszVarName);
lpBuf += len;
lpBuf = parseExpression(lpBuf, &lpmdDialog->_command[curCmd]._expr);
if (lpBuf == NULL)
return NULL;
break;
}
// Do Choice
case 3:
lpmdDialog->_command[curCmd]._nChoice = READ_LE_UINT16(lpBuf);
lpBuf += 2;
break;
default:
return NULL;
}
uint32 kk;
for (kk = 0;kk < curCmd; kk++) {
if (compareCommands(&lpmdDialog->_command[kk], &lpmdDialog->_command[curCmd])) {
lpmdDialog->_group[i]._cmdNum[j] = kk;
// Free any data allocated for the duplictaed command
if (lpmdDialog->_command[curCmd]._type == 2) {
globalDestroy(lpmdDialog->_command[curCmd]._lpszVarName);
freeExpression(lpmdDialog->_command[curCmd]._expr);
lpmdDialog->_command[curCmd]._lpszVarName = NULL;
lpmdDialog->_command[curCmd]._expr = 0;
lpmdDialog->_command[curCmd]._type = 0;
}
break;
}
}
if (kk == curCmd) {
lpmdDialog->_group[i]._cmdNum[j] = curCmd;
curCmd++;
}
}
}
if (curCmd >= MAX_COMMANDS_PER_DIALOG)
error("Too much commands in dialog #%d", lpmdDialog->_nObj);
// Choices
num = READ_LE_UINT16(lpBuf);
lpBuf += 2;
if (num >= MAX_CHOICES_PER_DIALOG)
error("Too much choices in dialog #%d", lpmdDialog->_nObj);
for (i = 0; i < num; i++) {
lpmdDialog->_choice[i]._nChoice = READ_LE_UINT16(lpBuf);
lpBuf += 2;
uint32 num2 = *lpBuf++;
if (num2 >= MAX_SELECTS_PER_CHOICE)
error("Too much selects in choice #%d in dialog #%d", lpmdDialog->_choice[i]._nChoice, lpmdDialog->_nObj);
for (uint32 j = 0; j < num2; j++) {
// When
switch (*lpBuf++) {
case 0:
lpmdDialog->_choice[i]._select[j]._when = NULL;
break;
case 1:
lpBuf = parseExpression(lpBuf, &lpmdDialog->_choice[i]._select[j]._when);
if (lpBuf == NULL)
return NULL;
break;
case 2:
return NULL;
default:
break;
}
// Attrib
lpmdDialog->_choice[i]._select[j]._attr = *lpBuf++;
// Data
lpmdDialog->_choice[i]._select[j]._dwData = READ_LE_UINT32(lpBuf);
lpBuf += 4;
// PlayGroup
uint32 num3 = *lpBuf++;
if (num3 >= MAX_PLAYGROUPS_PER_SELECT)
error("Too much playgroups in select #%d in choice #%d in dialog #%d", j, lpmdDialog->_choice[i]._nChoice, lpmdDialog->_nObj);
for (uint32 z = 0; z < num3; z++) {
lpmdDialog->_choice[i]._select[j]._wPlayGroup[z] = READ_LE_UINT16(lpBuf);
lpBuf += 2;
}
lpmdDialog->_choice[i]._select[j]._wPlayGroup[num3] = 0;
}
// Mark the last selection
lpmdDialog->_choice[i]._select[num2]._dwData = 0;
}
lpmdDialog->_choice[num]._nChoice = 0;
return lpBuf;
}
/**
* Parses an item from the MPC file, and inserts its data into a structure
*
* @param lpBuf Buffer containing the compiled dialog.
* @param lpmiItem Pointer to a structure that will be filled with the
* data of the item.
* @returns Pointer to the buffer after the item, or NULL on failure.
* @remarks It's necessary that the structure that is passed has been
* completely initialized to 0 beforehand.
*/
static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) {
lpmiItem->_nObj = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
byte len = *lpBuf;
lpBuf++;
memcpy(lpmiItem->_lpszDescribe, lpBuf, MIN((byte)MAX_DESCRIBE_SIZE, len));
lpBuf += len;
if (len >= MAX_DESCRIBE_SIZE)
error("Describe too long in item #%d", lpmiItem->_nObj);
lpmiItem->_nActions=*lpBuf;
lpBuf++;
// Allocation action
if (lpmiItem->_nActions > 0)
lpmiItem->_action = (ItemAction *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(struct ItemAction) * (int)lpmiItem->_nActions);
uint32 curCmd = 0;
for (uint32 i = 0; i < lpmiItem->_nActions; i++) {
lpmiItem->_action[i]._num = *lpBuf;
lpBuf++;
lpmiItem->_action[i]._wParm = READ_LE_UINT16(lpBuf);
lpBuf += 2;
if (lpmiItem->_action[i]._num == 0xFF) {
lpmiItem->_action[i]._wTime = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmiItem->_action[i]._perc = *lpBuf;
lpBuf++;
}
if (*lpBuf == 0) {
lpBuf++;
lpmiItem->_action[i]._when = NULL;
} else {
lpBuf++;
lpBuf = parseExpression(lpBuf,&lpmiItem->_action[i]._when);
if (lpBuf == NULL)
return NULL;
}
lpmiItem->_action[i]._nCmds=*lpBuf;
lpBuf++;
if (lpmiItem->_action[i]._nCmds >= MAX_COMMANDS_PER_ACTION)
error("Too much commands in action #%d in item #%d", lpmiItem->_action[i]._num, lpmiItem->_nObj);
for (uint32 j = 0; j < lpmiItem->_action[i]._nCmds; j++) {
lpmiItem->_command[curCmd]._type = *lpBuf;
lpBuf++;
switch (lpmiItem->_command[curCmd]._type) {
case 1: // Call custom function
lpmiItem->_command[curCmd]._nCf = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmiItem->_command[curCmd]._arg1 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmiItem->_command[curCmd]._arg2 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmiItem->_command[curCmd]._arg3 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmiItem->_command[curCmd]._arg4 = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
break;
case 2: // Variable assign
len = *lpBuf;
lpBuf++;
lpmiItem->_command[curCmd]._lpszVarName = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len + 1);
if (lpmiItem->_command[curCmd]._lpszVarName == NULL)
return NULL;
memcpy(lpmiItem->_command[curCmd]._lpszVarName, lpBuf, len);
lpBuf += len;
lpBuf = parseExpression(lpBuf, &lpmiItem->_command[curCmd]._expr);
if (lpBuf == NULL)
return NULL;
break;
default:
return NULL;
}
uint32 kk;
for (kk = 0; kk < curCmd; kk++) {
if (compareCommands(&lpmiItem->_command[kk], &lpmiItem->_command[curCmd])) {
lpmiItem->_action[i]._cmdNum[j] = kk;
// Free any data allocated for the duplictaed command
if (lpmiItem->_command[curCmd]._type == 2) {
globalDestroy(lpmiItem->_command[curCmd]._lpszVarName);
freeExpression(lpmiItem->_command[curCmd]._expr);
lpmiItem->_command[curCmd]._lpszVarName = NULL;
lpmiItem->_command[curCmd]._expr = 0;
lpmiItem->_command[curCmd]._type = 0;
}
break;
}
}
if (kk == curCmd) {
lpmiItem->_action[i]._cmdNum[j] = curCmd;
curCmd++;
if (curCmd >= MAX_COMMANDS_PER_ITEM) {
error("Too much commands in item #%d", lpmiItem->_nObj);
//curCmd=0;
}
}
}
}
lpmiItem->_dwRes = READ_LE_UINT32(lpBuf);
lpBuf += 4;
return lpBuf;
}
/**
* Frees an item parsed from a prior call to ParseItem
*
* @param lpmiItem Pointer to an item structure
*/
static void freeItem(LpMpalItem lpmiItem) {
// Free the actions
if (lpmiItem->_action) {
for (int i = 0; i < lpmiItem->_nActions; ++i) {
if (lpmiItem->_action[i]._when != 0)
freeExpression(lpmiItem->_action[i]._when);
}
globalDestroy(lpmiItem->_action);
}
// Free the commands
for (int i = 0; i < MAX_COMMANDS_PER_ITEM && (lpmiItem->_command[i]._type); ++i) {
if (lpmiItem->_command[i]._type == 2) {
// Variable Assign
globalDestroy(lpmiItem->_command[i]._lpszVarName);
freeExpression(lpmiItem->_command[i]._expr);
}
}
}
/**
* Parses a location from the MPC file, and inserts its data into a structure
*
* @param lpBuf Buffer containing the compiled location.
* @param lpmiLocation Pointer to a structure that will be filled with the
* data of the location.
* @returns Pointer to the buffer after the location, or NULL on failure.
*/
static const byte *ParseLocation(const byte *lpBuf, LpMpalLocation lpmlLocation) {
lpmlLocation->_nObj = (int32)READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpmlLocation->_dwXlen = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmlLocation->_dwYlen = READ_LE_UINT16(lpBuf);
lpBuf += 2;
lpmlLocation->_dwPicRes = READ_LE_UINT32(lpBuf);
lpBuf += 4;
return lpBuf;
}
/****************************************************************************\
* Exported functions
\****************************************************************************/
/**
* @defgroup Exported functions
*/
//@{
/**
* Reads and interprets the MPC file, and create structures for various directives
* in the global variables
*
* @param lpBuf Buffer containing the MPC file data, excluding the header.
* @returns True if succeeded OK, false if failure.
*/
bool parseMpc(const byte *lpBuf) {
byte *lpTemp;
// 1. Variables
if (lpBuf[0] != 'V' || lpBuf[1] != 'A' || lpBuf[2] != 'R' || lpBuf[3] != 'S')
return false;
lpBuf += 4;
GLOBALS._nVars = READ_LE_UINT16(lpBuf);
lpBuf += 2;
GLOBALS._hVars = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(MpalVar) * (uint32)GLOBALS._nVars);
if (GLOBALS._hVars == NULL)
return false;
GLOBALS._lpmvVars = (LpMpalVar)globalLock(GLOBALS._hVars);
for (uint16 i = 0; i < GLOBALS._nVars; i++) {
uint16 wLen = *(const byte *)lpBuf;
lpBuf++;
memcpy(GLOBALS._lpmvVars->_lpszVarName, lpBuf, MIN(wLen, (uint16)32));
lpBuf += wLen;
GLOBALS._lpmvVars->_dwVal = READ_LE_UINT32(lpBuf);
lpBuf += 4;
lpBuf++; // Skip 'ext'
GLOBALS._lpmvVars++;
}
globalUnlock(GLOBALS._hVars);
// 2. Messages
if (lpBuf[0] != 'M' || lpBuf[1] != 'S' || lpBuf[2] != 'G' || lpBuf[3] != 'S')
return false;
lpBuf += 4;
GLOBALS._nMsgs = READ_LE_UINT16(lpBuf);
lpBuf += 2;
#ifdef NEED_LOCK_MSGS
GLOBALS._hMsgs = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(MpalMsg) * (uint32)GLOBALS._nMsgs);
if (GLOBALS._hMsgs == NULL)
return false;
GLOBALS._lpmmMsgs = (LpMpalMsg)globalLock(GLOBALS._hMsgs);
#else
GLOBALS._lpmmMsgs=(LPMPALMSG)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALMSG) * (uint32)GLOBALS._nMsgs);
if (GLOBALS._lpmmMsgs==NULL)
return false;
#endif
for (uint16 i = 0; i < GLOBALS._nMsgs; i++) {
GLOBALS._lpmmMsgs->_wNum = READ_LE_UINT16(lpBuf);
lpBuf += 2;
uint16 j;
for (j = 0; lpBuf[j] != 0;)
j += lpBuf[j] + 1;
GLOBALS._lpmmMsgs->_hText = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, j + 1);
lpTemp = (byte *)globalLock(GLOBALS._lpmmMsgs->_hText);
for (j = 0; lpBuf[j] != 0;) {
memcpy(lpTemp, &lpBuf[j + 1], lpBuf[j]);
lpTemp += lpBuf[j];
*lpTemp ++= '\0';
j += lpBuf[j] + 1;
}
lpBuf += j + 1;
*lpTemp = '\0';
globalUnlock(GLOBALS._lpmmMsgs->_hText);
GLOBALS._lpmmMsgs++;
}
#ifdef NEED_LOCK_MSGS
globalUnlock(GLOBALS._hMsgs);
#endif
// 3. Objects
if (lpBuf[0] != 'O' || lpBuf[1] != 'B' || lpBuf[2] != 'J' || lpBuf[3] != 'S')
return false;
lpBuf += 4;
GLOBALS._nObjs = READ_LE_UINT16(lpBuf);
lpBuf += 2;
// Check out the dialogs
GLOBALS._nDialogs = 0;
GLOBALS._hDialogs = GLOBALS._lpmdDialogs = NULL;
if (*((const byte *)lpBuf + 2) == 6 && strncmp((const char *)lpBuf + 3, "Dialog", 6) == 0) {
GLOBALS._nDialogs = READ_LE_UINT16(lpBuf);
lpBuf += 2;
GLOBALS._hDialogs = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, (uint32)GLOBALS._nDialogs * sizeof(MpalDialog));
if (GLOBALS._hDialogs == NULL)
return false;
GLOBALS._lpmdDialogs = (LpMpalDialog)globalLock(GLOBALS._hDialogs);
for (uint16 i = 0; i < GLOBALS._nDialogs; i++) {
if ((lpBuf = parseDialog(lpBuf + 7, &GLOBALS._lpmdDialogs[i])) == NULL)
return false;
}
globalUnlock(GLOBALS._hDialogs);
}
// Check the items
GLOBALS._nItems = 0;
GLOBALS._hItems = GLOBALS._lpmiItems = NULL;
if (*(lpBuf + 2) == 4 && strncmp((const char *)lpBuf + 3, "Item", 4) == 0) {
GLOBALS._nItems = READ_LE_UINT16(lpBuf);
lpBuf += 2;
// Allocate memory and read them in
GLOBALS._hItems = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, (uint32)GLOBALS._nItems * sizeof(MpalItem));
if (GLOBALS._hItems == NULL)
return false;
GLOBALS._lpmiItems = (LpMpalItem)globalLock(GLOBALS._hItems);
for (uint16 i = 0; i < GLOBALS._nItems; i++) {
if ((lpBuf = parseItem(lpBuf + 5, &GLOBALS._lpmiItems[i])) == NULL)
return false;
}
globalUnlock(GLOBALS._hItems);
}
// Check the locations
GLOBALS._nLocations = 0;
GLOBALS._hLocations = GLOBALS._lpmlLocations = NULL;
if (*(lpBuf + 2) == 8 && strncmp((const char *)lpBuf + 3, "Location", 8) == 0) {
GLOBALS._nLocations = READ_LE_UINT16(lpBuf);
lpBuf += 2;
// Allocate memory and read them in
GLOBALS._hLocations = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, (uint32)GLOBALS._nLocations * sizeof(MpalLocation));
if (GLOBALS._hLocations == NULL)
return false;
GLOBALS._lpmlLocations = (LpMpalLocation)globalLock(GLOBALS._hLocations);
for (uint16 i = 0; i < GLOBALS._nLocations; i++) {
if ((lpBuf = ParseLocation(lpBuf + 9, &GLOBALS._lpmlLocations[i])) == NULL)
return false;
}
globalUnlock(GLOBALS._hLocations);
}
// Check the scripts
GLOBALS._nScripts = 0;
GLOBALS._hScripts = GLOBALS._lpmsScripts = NULL;
if (*(lpBuf + 2) == 6 && strncmp((const char *)lpBuf + 3, "Script", 6) == 0) {
GLOBALS._nScripts = READ_LE_UINT16(lpBuf);
lpBuf += 2;
// Allocate memory
GLOBALS._hScripts = globalAllocate(GMEM_MOVEABLE | GMEM_ZEROINIT, (uint32)GLOBALS._nScripts * sizeof(MpalScript));
if (GLOBALS._hScripts == NULL)
return false;
GLOBALS._lpmsScripts = (LpMpalScript)globalLock(GLOBALS._hScripts);
for (uint16 i = 0; i < GLOBALS._nScripts; i++) {
if ((lpBuf = ParseScript(lpBuf + 7, &GLOBALS._lpmsScripts[i])) == NULL)
return false;
// Sort the various moments of the script
//qsort(
//GLOBALS.lpmsScripts[i].Moment,
//GLOBALS.lpmsScripts[i].nMoments,
//sizeof(GLOBALS.lpmsScripts[i].Moment[0]),
//(int (*)(const void *, const void *))CompareMoments
//);
}
globalUnlock(GLOBALS._hScripts);
}
if (lpBuf[0] != 'E' || lpBuf[1] != 'N' || lpBuf[2] != 'D' || lpBuf[3] != '0')
return false;
return true;
}
/**
* Free the given dialog
*/
static void freeDialog(LpMpalDialog lpmdDialog) {
// Free the periods
for (int i = 0; i < MAX_PERIODS_PER_DIALOG && (lpmdDialog->_periods[i]); ++i)
globalFree(lpmdDialog->_periods[i]);
for (int i = 0; i < MAX_COMMANDS_PER_DIALOG && (lpmdDialog->_command[i]._type); i++) {
if (lpmdDialog->_command[i]._type == 2) {
// Variable assign
globalDestroy(lpmdDialog->_command[i]._lpszVarName);
freeExpression(lpmdDialog->_command[i]._expr);
}
}
// Free the choices
for (int i = 0; i < MAX_CHOICES_PER_DIALOG; ++i) {
for (int j = 0; j < MAX_SELECTS_PER_CHOICE; j++) {
if (lpmdDialog->_choice[i]._select[j]._when)
freeExpression(lpmdDialog->_choice[i]._select[j]._when);
}
}
}
/**
* Frees any data allocated from the parsing of the MPC file
*/
void freeMpc() {
// Free variables
globalFree(GLOBALS._hVars);
// Free messages
LpMpalMsg lpmmMsgs = (LpMpalMsg)globalLock(GLOBALS._hMsgs);
for (int i = 0; i < GLOBALS._nMsgs; i++, ++lpmmMsgs)
globalFree(lpmmMsgs->_hText);
globalUnlock(GLOBALS._hMsgs);
globalFree(GLOBALS._hMsgs);
// Free objects
if (GLOBALS._hDialogs) {
LpMpalDialog lpmdDialogs = (LpMpalDialog)globalLock(GLOBALS._hDialogs);
for (int i = 0; i < GLOBALS._nDialogs; i++, ++lpmdDialogs)
freeDialog(lpmdDialogs);
globalFree(GLOBALS._hDialogs);
}
// Free items
if (GLOBALS._hItems) {
LpMpalItem lpmiItems = (LpMpalItem)globalLock(GLOBALS._hItems);
for (int i = 0; i < GLOBALS._nItems; ++i, ++lpmiItems)
freeItem(lpmiItems);
globalUnlock(GLOBALS._hItems);
globalFree(GLOBALS._hItems);
}
// Free the locations
if (GLOBALS._hLocations) {
globalFree(GLOBALS._hLocations);
}
// Free the scripts
if (GLOBALS._hScripts) {
LpMpalScript lpmsScripts = (LpMpalScript)globalLock(GLOBALS._hScripts);
for (int i = 0; i < GLOBALS._nScripts; ++i, ++lpmsScripts) {
FreeScript(lpmsScripts);
}
globalUnlock(GLOBALS._hScripts);
}
}
//@}
} // end of namespace MPAL
} // end of namespace Tony

View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#ifndef __LOADMPC_H
#define __LOADMPC_H
namespace Tony {
namespace MPAL {
/****************************************************************************\
* Function prototypes
\****************************************************************************/
/**
* Reads and interprets the MPC file, and create structures for various directives
* in the global variables
*
* @param lpBuf Buffer containing the MPC file data, excluding the header.
* @returns True if succeeded OK, false if failure.
*/
bool parseMpc(const byte *lpBuf);
/**
* Frees any data allocated from the parsing of the MPC file
*/
void freeMpc();
} // end of namespace MPAL
} // end of namespace Tony
#endif

220
engines/tony/mpal/lzo.cpp Normal file
View File

@@ -0,0 +1,220 @@
/* 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/>.
*
*/
/* minilzo.c -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library 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 the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
#include "lzo.h"
#include "common/textconsole.h"
namespace Tony {
namespace MPAL {
#define pd(a, b) ((uint32) ((a) - (b)))
#define TEST_IP (ip < ip_end)
#define M2_MAX_OFFSET 0x0800
/**
* Decompresses an LZO compressed resource
*/
int lzo1x_decompress(const byte *in, uint32 in_len, byte *out, uint32 *out_len) {
byte *op;
const byte *ip;
uint32 t = 0;
const byte *m_pos;
const byte * const ip_end = in + in_len;
*out_len = 0;
op = out;
ip = in;
if (*ip > 17) {
t = *ip++ - 17;
if (t < 4)
goto match_next;
assert(t > 0);
do {
*op++ = *ip++;
} while (--t > 0);
goto first_literal_run;
}
while (TEST_IP) {
t = *ip++;
if (t >= 16)
goto match;
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 15 + *ip++;
}
assert(t > 0);
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
do {
*op++ = *ip++;
} while (--t > 0);
first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
do {
match:
if (t >= 64) {
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
assert(t > 0);
goto copy_match;
} else if (t >= 32) {
t &= 31;
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
} else if (t >= 16) {
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0) {
while (*ip == 0) {
t += 255;
ip++;
}
t += 7 + *ip++;
}
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
} else {
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}
assert(t > 0);
{
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do {
*op++ = *m_pos++;
} while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
assert(t > 0);
assert(t < 4);
*op++ = *ip++;
if (t > 1) {
*op++ = *ip++;
if (t > 2)
*op++ = *ip++;
}
t = *ip++;
} while (TEST_IP);
}
eof_found:
assert(t == 1);
*out_len = pd(op, out);
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
}
} // end of namespace MPAL
} // end of namespace Tony

88
engines/tony/mpal/lzo.h Normal file
View 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/>.
*
*/
/* minilzo.c -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library 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 the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
#ifndef TONY_MPAL_LZO_H
#define TONY_MPAL_LZO_H
#include "common/scummsys.h"
namespace Tony {
namespace MPAL {
/* Error codes for the compression/decompression functions. Negative
* values are errors, positive values will be used for special but
* normal events.
*/
#define LZO_E_OK 0
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
/**
* Decompresses an LZO compressed resource
*/
int lzo1x_decompress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len);
} // end of namespace MPAL
} // end of namespace Tony
#endif /* already included */

View File

@@ -0,0 +1,124 @@
/* 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/algorithm.h"
#include "common/textconsole.h"
#include "tony/mpal/memory.h"
namespace Tony {
namespace MPAL {
/****************************************************************************\
* MemoryManager methods
\****************************************************************************/
/**
* Allocates a new memory block
* @return Returns a MemoryItem instance for the new block
*/
MpalHandle MemoryManager::allocate(uint32 size, uint flags) {
MemoryItem *newItem = (MemoryItem *)malloc(sizeof(MemoryItem) - sizeof(byte[1]) + size);
newItem->_id = BLOCK_ID;
newItem->_size = size;
newItem->_lockCount = 0;
// If requested, clear the allocated data block
if ((flags & GMEM_ZEROINIT) != 0) {
byte *dataP = newItem->_data;
Common::fill(dataP, dataP + size, 0);
}
return (MpalHandle)newItem;
}
/**
* Allocates a new memory block and returns its data pointer
* @return Data pointer to allocated block
*/
void *MemoryManager::alloc(uint32 size, uint flags) {
MemoryItem *item = (MemoryItem *)allocate(size, flags);
++item->_lockCount;
return &item->_data[0];
}
#define OFFSETOF(type, field) ((size_t) &(((type *) 0)->field))
/**
* Returns a reference to the MemoryItem for a gien byte pointer
* @param block Byte pointer
*/
MemoryItem *MemoryManager::getItem(MpalHandle handle) {
MemoryItem *rec = (MemoryItem *)((byte *)handle - OFFSETOF(MemoryItem, _data));
assert(rec->_id == BLOCK_ID);
return rec;
}
/**
* Returns a size of a memory block given its pointer
*/
uint32 MemoryManager::getSize(MpalHandle handle) {
MemoryItem *item = (MemoryItem *)handle;
assert(item->_id == BLOCK_ID);
return item->_size;
}
/**
* Erases a given item
*/
void MemoryManager::freeBlock(MpalHandle handle) {
MemoryItem *item = (MemoryItem *)handle;
assert(item->_id == BLOCK_ID);
free(item);
}
/**
* Erases a given item
*/
void MemoryManager::destroyItem(MpalHandle handle) {
MemoryItem *item = getItem(handle);
assert(item->_id == BLOCK_ID);
free(item);
}
/**
* Locks an item for access
*/
void *MemoryManager::lockItem(MpalHandle handle) {
MemoryItem *item = (MemoryItem *)handle;
assert(item->_id == BLOCK_ID);
++item->_lockCount;
return &item->_data[0];
}
/**
* Unlocks a locked item
*/
void MemoryManager::unlockItem(MpalHandle handle) {
MemoryItem *item = (MemoryItem *)handle;
assert(item->_id == BLOCK_ID);
assert(item->_lockCount > 0);
--item->_lockCount;
}
} // end of namespace MPAL
} // end of namespace Tony

View File

@@ -0,0 +1,79 @@
/* 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 TONY_MPAL_MEMORY
#define TONY_MPAL_MEMORY
#include "common/scummsys.h"
#include "common/list.h"
namespace Tony {
namespace MPAL {
typedef void *MpalHandle;
struct MemoryItem {
uint32 _id;
uint32 _size;
int _lockCount;
#ifndef NO_CXX11_ALIGNAS
alignas(max_align_t)
#endif
byte _data[1];
// Casting for access to data
operator void *() { return &_data[0]; }
};
class MemoryManager {
private:
static MemoryItem *getItem(MpalHandle handle);
public:
static MpalHandle allocate(uint32 size, uint flags);
static void *alloc(uint32 size, uint flags);
static void freeBlock(MpalHandle handle);
static void destroyItem(MpalHandle handle);
static uint32 getSize(MpalHandle handle);
static void *lockItem(MpalHandle handle);
static void unlockItem(MpalHandle handle);
};
// defines
#define globalAlloc(flags, size) MemoryManager::alloc(size, flags)
#define globalAllocate(flags, size) MemoryManager::allocate(size, flags)
#define globalFree(handle) MemoryManager::freeBlock(handle)
#define globalDestroy(handle) MemoryManager::destroyItem(handle)
#define globalLock(handle) MemoryManager::lockItem(handle)
#define globalUnlock(handle) MemoryManager::unlockItem(handle)
#define globalSize(handle) MemoryManager::getSize(handle)
#define GMEM_FIXED 1
#define GMEM_MOVEABLE 2
#define GMEM_ZEROINIT 4
const uint32 BLOCK_ID = 0x12345678;
} // end of namespace MPAL
} // end of namespace Tony
#endif

2096
engines/tony/mpal/mpal.cpp Normal file

File diff suppressed because it is too large Load Diff

501
engines/tony/mpal/mpal.h Normal file
View File

@@ -0,0 +1,501 @@
/* 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
/****************************************************************************\
* General Introduction
\****************************************************************************/
/*
* MPAL (MultiPurpose Adventure Language) is a high level language
* for the definition of adventure. Through the use of MPAL you can describe
* storyboard the adventure, and then use it with any user interface.
* In fact, unlike many other similar products, MPAL is not programmed through
* the whole adventure, but are defined only the locations, objects, as they may
* interact with each other, etc.. thus making MPAL useful for any type of adventure.
*/
/****************************************************************************\
* Structure
\****************************************************************************/
/*
* MPAL consists of two main files: MPAL.DLL and MPAL.H
* The first is the DLL that contains the code to interface with MPAL
* adventures, the second is the header that defines the prototypes
* functions. MPAL is compiled for Win32, and it can therefore be used with
* any compiler that supports Win32 DLL (Watcom C++, Visual C++,
* Delphi, etc.), and therefore compatible with both Windows 95 and Windows NT.
*
* To use the DLL, and 'obviously need to create a library for symbols to export.
*
*/
/****************************************************************************\
* Custom Functions
\****************************************************************************/
/*
* A custom function and a function specified by the program that uses the
* library, to perform the particular code. The custom functions are
* retrieved from the library as specified in the source MPAL, and in particular
* in defining the behavior of an item with some action.
*
* To use the custom functions, you need to prepare an array of
* pointers to functions (such as using the type casting LPCUSTOMFUNCTION,
* (defined below), and pass it as second parameter to mpalInit (). Note you
* must specify the size of the array, as elements of pointers and which do not
* contain the same: the library will call it only those functions specified in
* the source MPAL. It can be useful, for debugging reasons, do not bet
* the shares of arrays used to debugging function, to avoid unpleasant crash,
* if it has been made an error in source and / or some oversight in the code.
*
*/
#ifndef TONY_MPAL_H
#define TONY_MPAL_H
#include "common/scummsys.h"
#include "common/coroutines.h"
#include "common/rect.h"
#include "common/str.h"
#include "tony/mpal/memory.h"
namespace Tony {
namespace MPAL {
/****************************************************************************\
* Macro definitions and structures
\****************************************************************************/
// OK value for the error codes
#define OK 0
#define MAXFRAMES 400 // frame animation of an object
#define MAXPATTERN 40 // pattern of animation of an object
#define MAXPOLLINGLOCATIONS 64
#define GETARG(type) va_arg(v, type)
/**
* Macro for use with queries that may refer to X and Y co-ordinates
*/
enum QueryCoordinates {
MPQ_X,
MPQ_Y
};
/**
* Query can be used with mpalQuery methods. In practice corresponds all claims
* that can do at the library
*/
enum QueryTypes {
// General Query
MPQ_VERSION = 10,
MPQ_GLOBAL_VAR = 50,
MPQ_RESOURCE,
MPQ_MESSAGE,
// Query on leases
MPQ_LOCATION_IMAGE = 100,
MPQ_LOCATION_SIZE,
// Queries about items
MPQ_ITEM_LIST = 200,
MPQ_ITEM_DATA,
MPQ_ITEM_PATTERN,
MPQ_ITEM_NAME,
MPQ_ITEM_IS_ACTIVE,
// Query dialog
MPQ_DIALOG_PERIOD = 300,
MPQ_DIALOG_WAITFORCHOICE,
MPQ_DIALOG_SELECTLIST,
MPQ_DIALOG_SELECTION,
// Query execution
MPQ_DO_ACTION = 400,
MPQ_DO_DIALOG
};
/**
* Framework to manage the animation of an item
*/
typedef struct {
char *_frames[MAXFRAMES];
Common::Rect _frameslocations[MAXFRAMES];
Common::Rect _bbox[MAXFRAMES];
short _pattern[MAXPATTERN][MAXFRAMES];
short _speed;
char _numframe;
char _numpattern;
char _curframe;
char _curpattern;
short _destX, _destY;
signed char _destZ;
short _objectID;
} Item;
typedef Item *LpItem;
/**
* Define a custom function, to use the language MPAL to perform various controls as a result of an action
*/
typedef void (*LPCUSTOMFUNCTION)(CORO_PARAM, uint32, uint32, uint32, uint32);
typedef LPCUSTOMFUNCTION *LPLPCUSTOMFUNCTION;
/**
*
* Define an IRQ of an item that is called when the pattern changes or the status of an item
*/
typedef void (*LPITEMIRQFUNCTION)(uint32, int, int);
typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION;
/**
* @defgroup Macrofunctions query
*
* The following are defines used for simplifying calling the mpalQuery variants
*/
//@{
/**
* Gets the current version of MPAL
*
* @returns Version number (0x1232 = 1.2.3b)
*/
#define mpalQueryVersion() \
(uint16)mpalQueryDWORD(MPQ_VERSION)
/**
* Gets the numerical value of a global variable
*
* @param lpszVarName Variable name (ASCIIZ)
* @returns Global variable value
* @remarks This query was implemented for debugging. The program,
* if well designed, should not need to access variables from
* within the library.
*/
#define mpalQueryGlobalVar(lpszVarName) \
mpalQueryDWORD(MPQ_GLOBAL_VAR, (const char *)(lpszVarName))
/**
* Provides access to a resource inside the .MPC file
*
* @param dwResId Resource Id
* @returns Handle to a memory area containing the resource, ready for use.
*/
#define mpalQueryResource(dwResId) \
mpalQueryHANDLE(MPQ_RESOURCE, (uint32)(dwResId))
/**
* Returns a message.
*
* @param nMsg Message number
* @returns ASCIIZ message
* @remarks The returned pointer must be freed via the memory manager
* after use. The message will be in ASCIIZ format.
*/
#define mpalQueryMessage(nMsg) \
(char *)mpalQueryHANDLE(MPQ_MESSAGE, (uint32)(nMsg))
/**
* Provides a location image
* @return Returns a picture handle
*/
#define mpalQueryLocationImage(nLoc) \
mpalQueryHANDLE(MPQ_LOCATION_IMAGE, (uint32)(nLoc))
/**
* Request the x or y size of a location in pixels
*
* @param nLoc Location number
* @param dwCoord MPQ_X or MPQ_Y coordinate to retrieve
* @returns Size
*/
#define mpalQueryLocationSize(nLoc, dwCoord) \
mpalQueryDWORD(MPQ_LOCATION_SIZE, (uint32)(nLoc), (uint32)(dwCoord))
/**
* Provides the list of objects in a location.
*
* @param nLoc Location number
* @returns List of objects (accessible by Item [0], Item [1], etc.)
*/
// TODO: Determine if this is endian safe
#define mpalQueryItemList(nLoc) \
(uint32 *)mpalQueryHANDLE(MPQ_ITEM_LIST, (uint32)(nLoc))
/**
* Provides information on an item
*
* @param nItem Item number
* @returns Structure filled with requested information
*/
#define mpalQueryItemData(nItem) \
(LpItem)mpalQueryHANDLE(MPQ_ITEM_DATA, (uint32)(nItem))
/**
* Provides the current pattern of an item
*
* @param nItem Item number
* @returns Number of animation patterns to be executed.
* @remarks By default, the pattern of 0 indicates that we should do nothing.
*/
#define mpalQueryItemPattern(nItem) \
mpalQueryDWORD(MPQ_ITEM_PATTERN, (uint32)(nItem))
/**
* Returns true if an item is active
*
* @param nItem Item number
* @returns TRUE if the item is active, FALSE otherwise
*/
#define mpalQueryItemIsActive(nItem) \
(bool)mpalQueryDWORD(MPQ_ITEM_IS_ACTIVE, (uint32)(nItem))
/**
* Returns the name of an item
*
* @param nItem Item number
* @param lpszName Pointer to a buffer of at least 33 bytes
* that will be filled with the name
* @remarks If the item is not active (ie. if its status or number
* is less than or equal to 0), the string will be empty.
*/
#define mpalQueryItemName(nItem, lpszName) \
mpalQueryHANDLE(MPQ_ITEM_NAME, (uint32)(nItem), (char *)(lpszName))
/**
* Returns a sentence of dialog.
*
* @param nDialog Dialog number
* @param nPeriod Number of words
* @returns A pointer to the string of words, or NULL on failure.
* @remarks The string must be freed after use using the memory manager.
* Unlike normal messages, the sentences of dialogue are formed by a single
* string terminated with 0.
*/
#define mpalQueryDialogPeriod(nPeriod) \
(char *)mpalQueryHANDLE(MPQ_DIALOG_PERIOD, (uint32)(nPeriod))
/**
* Wait until the moment in which the need is signaled to make a choice by the user.
* @returns Number of choice to be made, or -1 if the dialogue is finished.
*/
#define mpalQueryDialogWaitForChoice(dwRet) \
CORO_INVOKE_2(mpalQueryCORO, MPQ_DIALOG_WAITFORCHOICE, dwRet)
/**
* Requires a list of various options for some choice within the current dialog.
*
* @param nChoice Choice number
* @returns A pointer to an array containing the data matched to each option.
* @remarks The figure 'a uint32 specified in the source to which MPAL
* You can assign meaning that the more' suits.
* The pointer msut be freed after use using the memory memory.
*/
#define mpalQueryDialogSelectList(nChoice) \
(uint32 *)mpalQueryHANDLE(MPQ_DIALOG_SELECTLIST, (uint32)(nChoice))
/**
* Warns the library that the user has selected, in a certain choice of the current dialog,
* corresponding option at a certain given.
*
* @param nChoice Choice number of the choice that was in progress
* @param dwData Option that was selected by the user.
* @returns TRUE if all OK, FALSE on failure.
* @remarks After execution of this query, MPAL continue
* Groups according to the execution of the dialogue. And necessary so the game
* remains on hold again for another chosen by mpalQueryDialogWaitForChoice ().
*/
#define mpalQueryDialogSelection(nChoice, dwData) \
(bool)mpalQueryDWORD(MPQ_DIALOG_SELECTION, (uint32)(nChoice), (uint32)(dwData))
#define mpalQueryDialogSelectionDWORD(nChoice, dwData) \
mpalQueryDWORD(MPQ_DIALOG_SELECTION, (uint32)(nChoice), (uint32)(dwData))
/**
* Warns the library an action was performed on a Object.
* The library will call custom functions, if necessary.
*
* @param nAction Action number
* @param nItem Item number
* @param dwParam Action parameter
* @returns Handle to the thread that is performing the action, or CORO_INVALID_PID_VALUE
* if the action is not defined for the item, or the item is inactive.
* @remarks The parameter is used primarily to implement actions
* as "U.S." involving two objects together. The action will be executed only
* if the item is active, ie if its status is a positive number greater than 0.
*/
#define mpalQueryDoAction(nAction, nItem, dwParam) \
mpalQueryDWORD(MPQ_DO_ACTION, (uint32)(nAction), (uint32)(nItem), (uint32)(dwParam))
/**
* Warns the library a dialogue was required.
*
* @param nDialog Dialog number
* @param nGroup Group number to use
* @returns Handle to the thread that is running the box, or
* CORO_INVALID_PID_VALUE if the dialogue does not exist.
*/
#define mpalQueryDoDialog(nDialog, nGroup) \
mpalQueryDWORD(MPQ_DO_DIALOG, (uint32)(nDialog), (uint32)(nGroup))
/**
* @defgroup Functions exported to the main game
*/
//@{
/**
* Initializes the MPAL library, and opens an .MPC file, which will be 'used for all queries
* @param lpszMpcFileName Name of the .MPC file, including extension
* @param lpszMprFileName Name of the .MPR file, including extension
* @param lplpcfArray Array of pointers to custom functions
* @returns TRUE if all OK, FALSE on failure
*/
bool mpalInit(const char *lpszFileName, const char *lpszMprFileName,
LPLPCUSTOMFUNCTION lplpcfArray, Common::String *lpcfStrings);
/**
* Frees resources allocated by the MPAL subsystem
*/
void mpalFree();
/**
* This is a general function to communicate with the library, to request information
* about what is in the .MPC file
*
* @param wQueryType Type of query. The list is in the QueryTypes enum.
* @returns 4 bytes depending on the type of query
* @remarks This is the specialized version of the original single mpalQuery
* method that returns numeric results.
*/
uint32 mpalQueryDWORD(uint wQueryType, ...);
/**
* This is a general function to communicate with the library, to request information
* about what is in the .MPC file
*
* @param wQueryType Type of query. The list is in the QueryTypes enum.
* @returns 4 bytes depending on the type of query
* @remarks This is the specialized version of the original single mpalQuery
* method that returns a pointer or handle.
*/
MpalHandle mpalQueryHANDLE(uint wQueryType, ...);
/**
* This is a general function to communicate with the library, to request information
* about what is in the .MPC file
*
* @param wQueryType Type of query. The list is in the QueryTypes enum.
* @returns 4 bytes depending on the type of query
* @remarks This is the specialized version of the original single mpalQuery
* method that needs to run within a co-routine context.
*/
void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet);
/**
* Execute a script. The script runs on multitasking by a thread.
*
* @param nScript Script number to run
* @returns TRUE if the script 'was launched, FALSE on failure
*/
bool mpalExecuteScript(int nScript);
/**
* Returns the current MPAL error code
*
* @returns Error code
*/
uint32 mpalGetError();
/**
* Install a custom routine That will be called by MPAL every time the pattern
* of an item has been changed.
*
* @param lpiifCustom Custom function to install
*/
void mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCustom);
/**
* Process the idle actions of the items on one location.
*
* @param nLoc Number of the location whose items must be processed
* for idle actions.
* @returns TRUE if all OK, and FALSE if it exceeded the maximum limit.
* @remarks The maximum number of locations that can be polled
* simultaneously is defined defined by MAXPOLLINGFUNCIONS
*/
bool mpalStartIdlePoll(int nLoc);
/**
* Stop processing the idle actions of the items on one location.
*
* @param nLo Number of the location
* @returns TRUE if all OK, FALSE if the specified location was not
* in the process of polling
*/
void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result);
/**
* Load a save state from a buffer.
*
* @param buf Buffer where to store the state
* @returns Length of the state buffer in bytes
*/
int mpalLoadState(byte *buf);
/**
* Store the save state into a buffer. The buffer must be
* length at least the size specified with mpalGetSaveStateSize
*
* @param buf Buffer where to store the state
*/
void mpalSaveState(byte *buf);
/**
* Retrieve the length of a save state
*
* @returns Length in bytes
*/
int mpalGetSaveStateSize();
/**
* Locks the variables for access
*/
void lockVar();
/**
* Unlocks variables after use
*/
void unlockVar();
} // end of namespace MPAL
} // end of namespace Tony
#endif

246
engines/tony/mpal/mpaldll.h Normal file
View 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/>.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#ifndef __MPALDLL_H
#define __MPALDLL_H
#include "common/file.h"
#include "tony/mpal/memory.h"
#include "tony/mpal/loadmpc.h"
#include "tony/mpal/expr.h"
namespace Tony {
namespace MPAL {
/****************************************************************************\
* Defines
\****************************************************************************/
#define HEX_VERSION 0x0170
#define MAX_ACTIONS_PER_ITEM 40
#define MAX_COMMANDS_PER_ITEM 128
#define MAX_COMMANDS_PER_ACTION 128
#define MAX_DESCRIBE_SIZE 64
#define MAX_MOMENTS_PER_SCRIPT 256
#define MAX_COMMANDS_PER_SCRIPT 256
#define MAX_COMMANDS_PER_MOMENT 32
#define MAX_GROUPS_PER_DIALOG 128
#define MAX_COMMANDS_PER_DIALOG 480
#define MAX_COMMANDS_PER_GROUP 64
#define MAX_CHOICES_PER_DIALOG 64
#define MAX_SELECTS_PER_CHOICE 64
#define MAX_PLAYGROUPS_PER_SELECT 9
#define MAX_PERIODS_PER_DIALOG 400
#define NEED_LOCK_MSGS
/****************************************************************************\
* Structures
\****************************************************************************/
#include "common/pack-start.h"
/**
* MPAL global variables
*/
struct MpalVar {
uint32 _dwVal; // Variable value
char _lpszVarName[33]; // Variable name
} PACKED_STRUCT;
typedef MpalVar *LpMpalVar;
/**
* MPAL Messages
*/
struct MpalMsg {
MpalHandle _hText; // Handle to the message text
uint16 _wNum; // Message number
} PACKED_STRUCT;
typedef MpalMsg *LpMpalMsg;
/**
* MPAL Locations
*/
struct MpalLocation {
uint32 _nObj; // Location number
uint32 _dwXlen, _dwYlen; // Dimensions
uint32 _dwPicRes; // Resource that contains the image
} PACKED_STRUCT;
typedef MpalLocation *LpMpalLocation;
/**
* All the data for a command, ie. tags used by OnAction in the item, the time
* in the script, and in the group dialog.
*/
struct Command {
/*
* Types of commands that are recognized
*
* #1 -> Custom function call (ITEM, SCRIPT, DIALOG)
* #2 -> Variable assignment (ITEM, SCRIPT, DIALOG)
* #3 -> Making a choice (DIALOG)
*
*/
byte _type; // Type of control
union {
int32 _nCf; // Custom function call [#1]
char *_lpszVarName; // Variable name [#2]
int32 _nChoice; // Number of choice you make [#3]
};
union {
int32 _arg1; // Argument for custom function [#1]
MpalHandle _expr; // Expression to assign to a variable [#2]
};
int32 _arg2, _arg3, _arg4; // Arguments for custom function [#1]
} PACKED_STRUCT;
/**
* MPAL dialog
*/
struct MpalDialog {
uint32 _nObj; // Dialog number
struct Command _command[MAX_COMMANDS_PER_DIALOG];
struct {
uint16 _num;
byte _nCmds;
uint16 _cmdNum[MAX_COMMANDS_PER_GROUP];
} _group[MAX_GROUPS_PER_DIALOG];
struct {
// The last choice has nChoice == 0
uint16 _nChoice;
// The select number (we're pretty stingy with RAM). The last select has dwData == 0
struct {
MpalHandle _when;
uint32 _dwData;
uint16 _wPlayGroup[MAX_PLAYGROUPS_PER_SELECT];
// Bit 0=endchoice Bit 1=enddialog
byte _attr;
// Modified at run-time: 0 if the select is currently disabled,
// and 1 if currently active
byte _curActive;
} _select[MAX_SELECTS_PER_CHOICE];
} _choice[MAX_CHOICES_PER_DIALOG];
uint16 _periodNums[MAX_PERIODS_PER_DIALOG];
MpalHandle _periods[MAX_PERIODS_PER_DIALOG];
} PACKED_STRUCT;
typedef MpalDialog *LpMpalDialog;
/**
* MPAL Item
*/
struct ItemAction {
byte _num; // Action number
uint16 _wTime; // If idle, the time which must pass
byte _perc; // Percentage of the idle run
MpalHandle _when; // Expression to compute. If != 0, then action can be done
uint16 _wParm; // Parameter for action
byte _nCmds; // Number of commands to be executed
uint32 _cmdNum[MAX_COMMANDS_PER_ACTION]; // Commands to execute
} PACKED_STRUCT;
struct MpalItem {
uint32 _nObj; // Item number
byte _lpszDescribe[MAX_DESCRIBE_SIZE]; // Name
byte _nActions; // Number of managed actions
uint32 _dwRes; // Resource that contains frames and patterns
struct Command _command[MAX_COMMANDS_PER_ITEM];
// Pointer to array of structures containing various managed activities. In practice, of
// every action we know what commands to run, including those defined in structures above
struct ItemAction *_action;
} PACKED_STRUCT;
typedef MpalItem *LpMpalItem;
/**
* MPAL Script
*/
struct MpalScript {
uint32 _nObj;
uint32 _nMoments;
struct Command _command[MAX_COMMANDS_PER_SCRIPT];
struct {
int32 _dwTime;
byte _nCmds;
uint32 _cmdNum[MAX_COMMANDS_PER_MOMENT];
} _moment[MAX_MOMENTS_PER_SCRIPT];
} PACKED_STRUCT;
typedef MpalScript *LpMpalScript;
#include "common/pack-end.h"
/****************************************************************************\
* Function prototypes
\****************************************************************************/
/**
* Returns the current value of a global variable
*
* @param lpszVarName Name of the variable
* @returns Current value
* @remarks Before using this method, you must call LockVar() to
* lock the global variablves for use. Then afterwards, you will
* need to remember to call UnlockVar()
*/
extern int32 varGetValue(const char *lpszVarName);
/**
* Sets the value of a MPAL global variable
* @param lpszVarName Name of the variable
* @param val Value to set
*/
extern void varSetValue(const char *lpszVarName, int32 val);
} // end of namespace MPAL
} // end of namespace Tony
#endif

View File

@@ -0,0 +1,115 @@
/* 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 "tony/mpal/mpalutils.h"
#include "tony/tony.h"
#include "common/memstream.h"
namespace Tony {
namespace MPAL {
/****************************************************************************\
* RMRes methods
\****************************************************************************/
/**
* Constructor
* @param resId MPAL resource to open
*/
RMRes::RMRes(uint32 resID) {
_buf = NULL;
_h = g_vm->_resUpdate.queryResource(resID);
if (_h == NULL)
_h = mpalQueryResource(resID);
if (_h != NULL)
_buf = (byte *)globalLock(_h);
}
/**
* Destructor
*/
RMRes::~RMRes() {
if (_h != NULL) {
globalUnlock(_h);
globalFree(_h);
}
}
/**
* Returns a pointer to the resource
*/
const byte *RMRes::dataPointer() {
return _buf;
}
/**
* Returns a pointer to the resource
*/
RMRes::operator const byte *() {
return dataPointer();
}
/**
* Returns the size of the resource
*/
unsigned int RMRes::size() {
return globalSize(_h);
}
Common::SeekableReadStream *RMRes::getReadStream() {
return new Common::MemoryReadStream(_buf, size());
}
bool RMRes::isValid() {
return _h != NULL;
}
/****************************************************************************\
* RMResRaw methods
\****************************************************************************/
RMResRaw::RMResRaw(uint32 resID) : RMRes(resID) {
}
RMResRaw::~RMResRaw() {
}
const byte *RMResRaw::dataPointer() {
return _buf + 8;
}
RMResRaw::operator const byte *() {
return dataPointer();
}
int RMResRaw::width() {
return READ_LE_UINT16(_buf + 4);
}
int RMResRaw::height() {
return READ_LE_UINT16(_buf + 6);
}
} // end of namespace MPAL
} // end of namespace Tony

View File

@@ -0,0 +1,72 @@
/* 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 TONY_MPAL_MPALUTILS
#define TONY_MPAL_MPALUTILS
#include "common/scummsys.h"
#include "tony/mpal/memory.h"
namespace Common {
class SeekableReadStream;
}
namespace Tony {
namespace MPAL {
class RMRes {
protected:
MpalHandle _h;
byte *_buf;
public:
RMRes(uint32 resID);
virtual ~RMRes();
// Attributes
unsigned int size();
const byte *dataPointer();
bool isValid();
// Casting for access to data
operator const byte*();
Common::SeekableReadStream *getReadStream();
};
class RMResRaw : public RMRes {
public:
RMResRaw(uint32 resID);
~RMResRaw() override;
const byte *dataPointer();
operator const byte*();
int width();
int height();
};
} // end of namespace MPAL
} // end of namespace Tony
#endif