Initial commit
This commit is contained in:
372
engines/tony/mpal/expr.cpp
Normal file
372
engines/tony/mpal/expr.cpp
Normal 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
138
engines/tony/mpal/expr.h
Normal 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
|
||||
786
engines/tony/mpal/loadmpc.cpp
Normal file
786
engines/tony/mpal/loadmpc.cpp
Normal 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
|
||||
57
engines/tony/mpal/loadmpc.h
Normal file
57
engines/tony/mpal/loadmpc.h
Normal 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
220
engines/tony/mpal/lzo.cpp
Normal 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
88
engines/tony/mpal/lzo.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* 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 */
|
||||
124
engines/tony/mpal/memory.cpp
Normal file
124
engines/tony/mpal/memory.cpp
Normal 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
|
||||
79
engines/tony/mpal/memory.h
Normal file
79
engines/tony/mpal/memory.h
Normal 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
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
501
engines/tony/mpal/mpal.h
Normal 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
246
engines/tony/mpal/mpaldll.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* 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
|
||||
|
||||
115
engines/tony/mpal/mpalutils.cpp
Normal file
115
engines/tony/mpal/mpalutils.cpp
Normal 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
|
||||
72
engines/tony/mpal/mpalutils.h
Normal file
72
engines/tony/mpal/mpalutils.h
Normal 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
|
||||
Reference in New Issue
Block a user