Initial commit

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

334
engines/m4/core/cstring.cpp Normal file
View File

@@ -0,0 +1,334 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/str.h"
#include "common/util.h"
#include "m4/core/cstring.h"
namespace M4 {
bool cstr_isdigit(char c) {
return (c >= '0' && c <= '9');
}
bool charIsIn(char ch, char *str) {
if (!str)
return false;
int16 bail = 0;
char *mark = str;
while (*mark) {
if (*mark == ch)
return true;
++mark;
++bail;
if (bail > 256)
return false;
}
return false;
}
int32 cstrlen(const char *s) {
if (!s)
return 0;
int32 size = -1;
const char *str = s;
do {
++size;
} while (*str++);
return size;
}
void cstrcpy(char *dest, const char *src) {
if (!src || !dest)
return;
do {
*dest++ = *src;
} while (*src++);
}
void cstrncpy(char *dest, const char *src, const int16 max_len) {
if (!src || !dest)
return;
Common::strlcpy(dest, src, max_len);
}
char *cstrupr(char *src) {
if (!src)
return nullptr;
char *mark = src;
do {
if (*mark >= 'a' && *mark <= 'z')
*mark = (char)(*mark - 'a' + 'A');
} while (*mark++);
return src;
}
char *cstr_lower(char *src) {
if (!src)
return nullptr;
char *mark = src;
do {
if (*mark >= 'A' && *mark <= 'Z')
*mark = (char)(*mark - 'A' + 'a');
} while (*mark++);
return src;
}
int xtoi(char *string) {
if (!string)
return 0;
int value = 0;
while (*string) {
int item = *string++;
if (cstr_isdigit(item))
value = (value << 4) + item - '0';
else
if (Common::isDigit(item))
value = (value << 4) + toupper(item) - 'A' + 0xa;
else
while (*string)
string++; // if not hexadecimal, eat string.
}
return (value);
}
/* Returns position within TARGET of string KEY (1-length) */
int strpos(char *key, char *target) {
if (!key || !target)
return 0;
char *tmp = strstr(target, key);
if (tmp)
return(tmp - target + 1);
return 0;
}
/* Deletes AMOUNT characters from string INP starting at position indx */
void strdel(char *inp, int indx, int count) {
if (!inp)
return;
if (indx >= (int)strlen(inp) || !count)
return;
Common::strlcpy(&inp[indx], &inp[indx + count], count);
}
// Given a string, index and count, returns a substring of length count
void strseg(char *work, char *work2, int indx, int count) {
if (!work || !work2)
return;
char *s = nullptr;
s = &work2[indx];
Common::strlcpy(work, s, count);
}
/*
Inserts string NEW into string WORK at character INDEX.
INDEX is 1->strlen, not 0->strlen-1
*/
void strins(char *work, char *newStr, int indx) {
if (!work || !newStr) {
newStr = nullptr;
return;
}
const int l1 = (strlen(work) - indx + 2);
const int l = strlen(newStr);
memmove(work + indx + l - 1, work + indx - 1, l1);
memcpy(work + indx - 1, newStr, l);
}
void str_purge_trailing_spaces(char *myline) {
if (!myline)
return;
int again = true;
do {
char *search = &myline[strlen(myline) - 1];
if ((*search == 0x20) || (*search == 0x09))
*search = 0;
else
again = false;
search--;
if (search < myline) again = false;
} while (again);
}
void str_purge_all_spaces(char *text) {
if (!text)
return;
str_purge_trailing_spaces(text);
char *mark = text;
while (*mark && ((*mark == ' ') || (*mark == 0x09)))
mark++;
char work[256];
Common::strcpy_s(work, 256, mark);
Common::strcpy_s(text, 256, work);
}
char *str_strip_final_lf(char *mystring) {
if (!mystring)
return nullptr;
char *temp = strrchr(mystring, 0x0a);
if (temp != nullptr) {
*temp = '\0';
}
return (temp);
}
void str_add_final_lf(char *mystring) {
if (!mystring)
return;
char *temp = mystring + strlen(mystring);
*(temp++) = 0x0a;
*temp = '\0';
}
int16 char_IsIn(char ch, char *str) {
if (!str)
return -1;
int16 index = 0;
char *mark = str;
while (*mark) {
if (*mark == ch)
return index;
++index;
++mark;
if (index > 256)
return -1;
}
return -1;
}
// stringIsIn returns the index of the match string, or -1 if there wasn't one.
int16 stringIsIn(char *str, char *strings[]) {
if (!str || !strings)
return -1;
int16 index = 0;
while (*strings != nullptr) {
if (!strcmp(str, *strings))
return index;
++index;
++strings;
}
return -1;
}
// dtoi
// Converts decimal string to integer
int dtoi(char *string) {
if (!string)
return 0;
int value = 0;
while (*string) {
const char item = *string++;
if (cstr_isdigit(item))
value = (value * 10) + item - '0';
else
while (*string)
string++; // if not a digit, eat string.
}
return (value);
}
// returns true if str is a positive integer, false otherwise
bool stringIsInt(char *str) {
if (!str)
return false;
int16 bail = 0;
while (*str) {
if (!cstr_isdigit(*str))
return false;
++str;
++bail;
if (bail > 256)
return false;
}
return true;
}
bool stringIsFloat(char *str) {
if (!str)
return false;
int16 bail = 0;
bool decimal_seen = false;
while (*str) {
if (*str == '.') {
if (!decimal_seen)
decimal_seen = true;
else return false;
} else {
if (!cstr_isdigit(*str))
return false;
}
++str;
++bail;
if (bail > 256)
return false;
}
return true;
}
} // namespace M4

85
engines/m4/core/cstring.h Normal file
View File

@@ -0,0 +1,85 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_CSTRING_H
#define M4_CORE_CSTRING_H
#include "common/str-array.h"
#include "m4/m4_types.h"
namespace M4 {
class StringArray : public Common::StringArray {
public:
StringArray() : Common::StringArray() {}
int indexOf(const Common::String &str) const {
for (uint i = 0; i < size(); ++i) {
if ((*this)[i] == str)
return i;
}
return -1;
}
bool contains(const Common::String &str) const {
return indexOf(str) != -1;
}
void remove(const Common::String &str) {
int idx = indexOf(str);
if (idx != -1)
remove_at(idx);
}
};
#define STR_PARSE_BUFFER_SIZE 255
bool charIsIn(char ch, char *str);
int16 char_IsIn(char ch, char *str); //new
int dtoi(char *string);
bool stringIsInt(char *str);
bool stringIsFloat(char *str);
int16 stringIsIn(char *str, char *strings[]);
int32 cstrlen(const char *s);
void cstrcpy(char *dest, const char *src);
void cstrncpy(char *dest, const char *src, const int16 max_len);
char *cstrupr(char *src);
char *cstr_lower(char *src);
int xtoi(char *string);
int strpos(char *key, char *target);
void strdel(char *inp, int indx, int count);
void strseg(char *work, char *work2, int indx, int count);
void strins(char *work, char *newStr, int indx);
void str_purge_trailing_spaces(char *myline);
void str_purge_all_spaces(char *text);
char *str_strip_final_lf(char *mystring);
void str_add_final_lf(char *mystring);
void str_parse_init(char *instring, char delimiter);
char *str_parse(char *out);
bool cstr_isdigit(char c);
#define strrun(a,b,c) memset(a,b,c)
} // namespace M4
#endif

View File

@@ -0,0 +1,74 @@
/* 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/file.h"
#include "common/textconsole.h"
#include "m4/core/errors.h"
namespace M4 {
inline static bool quadchar_equals_string(uint32 code, const Common::String &str) {
return READ_BE_UINT32(str.c_str()) == code;
}
void error_show(const char *filename, uint32 line, quadchar errorCode, const char *fmt, ...) {
assert(fmt);
va_list va;
va_start(va, fmt);
Common::String msg = Common::String::vformat(fmt, va);
va_end(va);
error("%s", msg.c_str());
}
void error_show(const char *filename, uint32 line, quadchar errorCode) {
error_show(filename, line, errorCode, "No extra description");
}
void error_look_up(quadchar errorCode, char *result_string) {
Common::File f;
*result_string = '\0';
if (!f.open(ERROR_FILE))
return;
Common::String buffer;
while (!f.eos()) {
buffer = f.readString();
const char *mark = buffer.c_str() + 1;
if (quadchar_equals_string(errorCode, buffer) || quadchar_equals_string(errorCode, mark)) {
const char *src = (const char *)buffer.c_str() + 5;
int16 count = 0;
do {
*result_string++ = *src;
++count;
} while (*src++ && (count < MAX_STRING_LEN));
break;
}
}
}
} // namespace M4

39
engines/m4/core/errors.h Normal file
View File

@@ -0,0 +1,39 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_ERRORS_H
#define M4_CORE_ERRORS_H
#include "common/scummsys.h"
#include "m4/m4_types.h"
namespace M4 {
#define FL __FILE__,__LINE__
#define ERROR_FILE "error.m4"
void NORETURN_PRE error_show(const char *filename, uint32 line, quadchar errorCode, const char *fmt, ...) NORETURN_POST;
void NORETURN_PRE error_show(const char *filename, uint32 line, quadchar errorCode) NORETURN_POST;
void error_look_up(quadchar errorCode, char *result_string);
} // namespace M4
#endif

89
engines/m4/core/globals.h Normal file
View File

@@ -0,0 +1,89 @@
/* 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/>.
*
*/
/**
* I know this is confusing, but the original game had two different Globals arrays
*/
#ifndef M4_CORE_GLOBALS_H
#define M4_CORE_GLOBALS_H
#include "common/array.h"
#include "common/serializer.h"
#include "m4/fileio/sys_file.h"
#include "m4/m4_types.h"
namespace M4 {
/**
* Global entry constants
*/
enum {
GLB_TIME = 0,
GLB_WATCH_DOG = 1,
GLB_MIN_Y = 2,
GLB_MAX_Y = 3,
GLB_MIN_SCALE = 4,
GLB_MAX_SCALE = 5,
GLB_SCALER = 6,
GLB_TEMP_1 = 7,
GLB_TEMP_2 = 8,
GLB_TEMP_3 = 9,
GLB_TEMP_4 = 10,
GLB_TEMP_5 = 11,
GLB_TEMP_6 = 12,
GLB_TEMP_7 = 13,
GLB_TEMP_8 = 14,
GLB_TEMP_9 = 15,
GLB_TEMP_10 = 16,
GLB_TEMP_11 = 17,
GLB_TEMP_12 = 18,
GLB_TEMP_13 = 19,
GLB_TEMP_14 = 20,
GLB_TEMP_15 = 21,
GLB_TEMP_16 = 22,
GLB_TEMP_17 = 23,
GLB_TEMP_18 = 24,
GLB_TEMP_19 = 25,
GLB_TEMP_20 = 26,
GLB_TEMP_21 = 27,
GLB_TEMP_22 = 28,
GLB_TEMP_23 = 29,
GLB_TEMP_24 = 30,
GLB_TEMP_25 = 31,
GLB_TEMP_26 = 32,
GLB_TEMP_27 = 33,
GLB_TEMP_28 = 34,
GLB_TEMP_29 = 35,
GLB_TEMP_30 = 36,
GLB_TEMP_31 = 37,
GLB_TEMP_32 = 38,
GLB_SCRATCH_VARS = 7, // 19-16 globals reserved for the compiler
GLB_USER_VARS = 17 // 17+ globals for the applications programmer
};
constexpr int GLB_SHARED_VARS = 256;
} // namespace M4
#endif

171
engines/m4/core/imath.cpp Normal file
View File

@@ -0,0 +1,171 @@
/* 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/endian.h"
#include "m4/core/imath.h"
namespace M4 {
unsigned long sqrtul(unsigned long v) {
unsigned long r = 0, s;
#define STEP(k) s = r + (1L << (k * 2)); r >>= 1; \
if (s <= v) { v -= s; r |= (1L << (k * 2)); }
STEP(15);
STEP(14);
STEP(13);
STEP(12);
STEP(11);
STEP(10);
STEP(9);
STEP(8);
STEP(7);
STEP(6);
STEP(5);
STEP(4);
STEP(3);
STEP(2);
STEP(1);
STEP(0);
return r;
#undef STEP
}
int32 imath_min(int32 a, int32 b) {
return ((a < b) ? a : b);
}
int32 imath_max(int32 a, int32 b) {
return ((a > b) ? a : b);
}
int32 imath_abs(int32 a) {
return ((a >= 0) ? a : -a);
}
static int32 seed;
void imath_seed(int32 seedNum) {
seed = seedNum;
}
uint32 imath_random() {
return(seed = (25173 * seed + 13849) & 0xffff);
}
int32 imath_ranged_rand(int32 a, int32 b) {
const int32 result = (a + (((1 + imath_abs(b - a)) * imath_random()) >> 16));
return result;
}
frac16 imath_ranged_rand16(frac16 a, frac16 b) {
const frac16 result = ((a + MulSF16(1 + imath_abs(b - a), imath_random())));
return result;
}
bool imath_rand_bool(int max) {
return imath_ranged_rand(1, max) == 1;
}
frac16 dist2d(int32 x1, int32 y1, int32 x2, int32 y2) {
if ((x2 -= x1) < 0)
x2 = -x2;
if ((y2 -= y1) < 0)
y2 = -y2;
return (x2 + y2 - (((x2 > y2) ? y2 : x2) >> 1));
}
#define STEP(k) s = r + (1L << (k * 2)); r >>= 1; \
if (s <= v) { v -= s; r |= (1L << (k * 2)); }
frac16 SqrtF16(frac16 n) {
ulong r = 0, s;
ulong v = (ulong)n;
STEP(15);
STEP(14);
STEP(13);
STEP(12);
STEP(11);
STEP(10);
STEP(9);
STEP(8);
STEP(7);
STEP(6);
STEP(5);
STEP(4);
STEP(3);
STEP(2);
STEP(1);
STEP(0);
return (frac16)r;
}
#define DIV_128_PI 0x28be61
frac16 ArcTan(frac16 x, frac16 y) {
const double floatX = (float)(x >> 16) + (float)((float)(x & 0xffff) / (float)65536);
const double floatY = (float)(y >> 16) + (float)((float)(y & 0xffff) / (float)65536);
const double result = atan2(floatY, floatX);
frac16 fracResult = (((int32)(floor(result))) << 16) + (int32)(floor((result - floor(result)) * 65536));
fracResult = MulSF16(fracResult, DIV_128_PI);
if (fracResult < 0) fracResult += 0x1000000;
return fracResult;
}
uint16 HighWord(uint32 n) {
return (uint16)(n >> 16);
}
uint16 LowWord(uint32 n) {
return (uint16)(n & 0xffff);
}
uint32 convert_intel32(uint32 a) {
return FROM_LE_32(a);
}
uint16 convert_intel16(uint16 a) {
return FROM_LE_16(a);
}
frac16 FixedMul(frac16 a, frac16 b) {
const float ta = a;
const float tb = b;
return (frac16)((ta * tb) / 65536.0);
}
frac16 FixedDiv(frac16 a, frac16 b) {
const float ta = a;
const float tb = b;
return (frac16)((ta / tb) * 65536.0);
}
frac16 FixedMulDiv(frac16 a, frac16 b, frac16 c) {
const float ta = a;
const float tb = b;
const float tc = c;
return (frac16)((ta * tb) / tc);
}
} // namespace M4

86
engines/m4/core/imath.h Normal file
View File

@@ -0,0 +1,86 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_IMATH_H
#define M4_CORE_IMATH_H
#include "common/endian.h"
#include "m4/m4_types.h"
namespace M4 {
#define FRAC16(a,b) ((a<<16) + (b))
#define Atan2F16(x1, x2) ArcTan(x1, x2)
#define MulSF16(x1, x2) FixedMul(x1, x2)
#define DivSF16(x1, x2) FixedDiv(x1, x2)
#define RecipUF16(x) FixedDiv(1, x)
#define SquareSF16(x) FixedMul(x, x)
#define SWAP_INT16(x) ((((x)>>8)&0x00ff) + (((x)&0x00ff)<<8))
#define SWAP_INT32(x) ((((int32)(x)&0x000000ff)<<24) + (((int32)(x)&0x0000ff00)<<8) + \
(((int32)(x)&0x00ff0000)>>8) + (((int32)(x)>>24)&0x000000ff))
frac16 FixedMul(frac16 Multiplicand, frac16 Multiplier);
frac16 FixedDiv(frac16 Dividend, frac16 Divisor);
unsigned long sqrtul(unsigned long v);
int32 imath_max(int32 a, int32 b);
int32 imath_min(int32 a, int32 b);
int32 imath_abs(int32 a);
void imath_seed(int32 seedNum);
uint32 imath_random();
int32 imath_ranged_rand(int32 a, int32 b);
frac16 imath_ranged_rand16(frac16 a, frac16 b);
bool imath_rand_bool(int max);
frac16 dist2d(int32 x1, int32 y1, int32 x2, int32 y2);
frac16 SqrtF16(frac16 n);
frac16 ArcTan(frac16 x, frac16 y);
uint16 HighWord(uint32 n);
uint16 LowWord(uint32 n);
uint32 convert_intel32(uint32 a);
uint16 convert_intel16(uint16 a);
//
// I N L I N E S
//
inline short abs(short a) {
return (a >= 0) ? a : -a;
}
inline long abs(long a) {
return (a >= 0) ? a : -a;
}
inline int16 convert_intel16(void *src) {
return READ_LE_INT16(src);
}
} // namespace M4
#endif

79
engines/m4/core/mouse.cpp Normal file
View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/core/mouse.h"
#include "m4/vars.h"
namespace M4 {
static byte Pointer[] = {
15, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 01, 01, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 01, 01, 01, 15, 15, 15, 15, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 01, 15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 01, 15, 00, 15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 15, 00, 00, 15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
15, 00, 00, 00, 00, 15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 15, 01, 01, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 15, 15, 15, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
};
// returns FALSE if the mouse couldn't be initialized
int mouse_init() {
auto &ms = _G(MouseState);
ms.CursorColumn = 640 / 2;
ms.CursorRow = 480 / 2;
return true;
}
void mouse_uninstall() {
// No implementation
}
byte *GetMousePicture() {
return &Pointer[0];
}
} // namespace M4

46
engines/m4/core/mouse.h Normal file
View File

@@ -0,0 +1,46 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_MOUSE_H
#define M4_CORE_MOUSE_H
#include "m4/m4_types.h"
namespace M4 {
enum cursor_states {
kARROW, kLOOK, kTAKE, kUSE
};
struct MouseDriverInfo {
byte MajorVersion = 0;
byte MinorVersion = 0;
byte MouseType = 0;
byte MouseIRQ = 0;
};
int mouse_init();
void mouse_uninstall();
byte *GetMousePicture();
} // namespace M4
#endif

79
engines/m4/core/param.cpp Normal file
View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "m4/core/param.h"
#include "m4/vars.h"
#include "m4/m4.h"
namespace M4 {
void param_init() {
}
void param_shutdown() {
}
void parse_all_flags() {
if (ConfMan.hasKey("LOG"))
_G(kernel).use_log_file = ConfMan.getBool("LOG");
if (ConfMan.hasKey("USECACHE"))
_G(kernel).suppress_cache = true;
else if (ConfMan.hasKey("NOCACHE"))
_G(kernel).suppress_cache = false;
_G(kernel).track_open_close = ConfMan.hasKey("FILECOUNT");
_G(kernel).start_up_with_dbg_ws = ConfMan.hasKey("W");
_G(kernel).use_debug_monitor = ConfMan.hasKey("H");
if (ConfMan.hasKey("M"))
_G(mem_to_alloc) = ConfMan.getInt("M");
if (ConfMan.hasKey("R")) {
int val = ConfMan.getInt("R");
if (!val) {
_G(kernel).last_save = -1;
_G(kernel).restore_game = true;
} else {
_G(kernel).last_save = val;
_G(kernel).restore_game = true;
}
}
if (ConfMan.hasKey("V")) {
g_engine->showEngineInfo();
_G(system_shutting_down) = true;
return;
}
if (ConfMan.hasKey("T")) {
const int room = ConfMan.getInt("T");
if (room) {
_G(kernel).teleported_in = true;
_G(game).setRoom(room);
}
}
}
} // namespace M4

44
engines/m4/core/param.h Normal file
View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_INFO_H
#define M4_INFO_H
namespace M4 {
/**
* Initialize params handler
*/
void param_init();
/**
* Shutdown params handler
*/
void param_shutdown();
/**
* Parses any flags
*/
void parse_all_flags();
} // namespace M4
#endif

492
engines/m4/core/rooms.cpp Normal file
View File

@@ -0,0 +1,492 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/core/rooms.h"
#include "m4/core/errors.h"
#include "m4/core/imath.h"
#include "m4/adv_r/adv_been.h"
#include "m4/adv_r/adv_control.h"
#include "m4/adv_r/adv_file.h"
#include "m4/adv_r/adv_interface.h"
#include "m4/adv_r/adv_scale.h"
#include "m4/adv_r/adv_walk.h"
#include "m4/adv_r/db_env.h"
#include "m4/adv_r/other.h"
#include "m4/fileio/extensions.h"
#include "m4/graphics/krn_pal.h"
#include "m4/gui/gui_buffer.h"
#include "m4/gui/gui_sys.h"
#include "m4/gui/gui_vmng.h"
#include "m4/wscript/wst_regs.h"
#include "m4/vars.h"
#include "m4/m4.h"
#include "m4/platform/timer.h"
namespace M4 {
void Room::preload() {
_G(player).walker_in_this_scene = true;
}
void Room::parser() {
_G(kernel).trigger = KT_DAEMON;
}
void Sections::global_section_constructor() {
const uint sectionNum = _G(game).new_section;
assert(sectionNum >= 1 && sectionNum <= 9);
_activeSection = _sections[sectionNum - 1];
assert(_activeSection);
}
void Sections::section_room_constructor() {
_activeRoom = (*_activeSection)[_G(game).new_room];
assert(_activeRoom);
}
void Sections::game_daemon_code() {
_G(kernel).trigger_mode = KT_DAEMON;
_G(kernel).continue_handling_trigger = false;
room_daemon();
if (_G(kernel).continue_handling_trigger) {
_G(kernel).continue_handling_trigger = false;
daemon();
}
if (_G(kernel).continue_handling_trigger)
global_daemon();
if (_G(kernel).trigger == TRIG_RESTORE_GAME) {
_G(game).room_id = -1;
_G(game).section_id = -1;
_G(game).previous_room = KERNEL_RESTORING_GAME;
}
}
void Sections::m4SceneLoad() {
_G(between_rooms) = true;
_cameraShiftAmount = 0;
_cameraShift_vert_Amount = 0;
_G(art_base_override) = nullptr;
_G(use_alternate_attribute_file) = true;
_G(shut_down_digi_tracks_between_rooms) = true;
camera_pan_step = 10;
_G(camera_reacts_to_player) = true;
_G(kernel).force_restart = false;
player_set_defaults();
player_set_commands_allowed(false); // Also sets "Wait" cursor
// -------------------- SECTION CONSTRUCTOR and ROOM PRELOAD ------------------
section_room_constructor();
_G(kernel).suppress_fadeup = false;
room_preload();
// -------------------- ROOM LOAD ------------------
_GI().cancel_sentence();
gr_pal_clear_range(_G(master_palette), _G(kernel).first_fade, 255);
term_message("Calling kernel_load_room");
_G(kernel).going = kernel_load_room(MIN_PAL_ENTRY, MAX_PAL_ENTRY,
&_G(currentSceneDef), &_G(screenCodeBuff), &_G(game_bgBuff));
if (!_G(kernel).going)
error_show(FL, 'IMP!'); // this should never ever happen
get_ipl();
// Must reset event handler because loading a room re-initalizes gameBuff
gui_buffer_set_event_handler(_G(gameDrawBuff), intr_EventHandler);
if (_G(player).walker_in_this_scene)
get_walker();
_G(kernel).trigger_mode = KT_DAEMON;
_G(kernel).call_daemon_every_loop = false;
_G(kernel).fade_up_time = 30;
//-------------------- GLOBAL ROOM INIT and ROOM INIT ------------------
player_set_commands_allowed(false);
_G(set_commands_allowed_since_last_checked) = false;
_G(between_rooms) = false;
global_room_init();
_G(player).walker_trigger = -1;
if (_G(game).previous_room == KERNEL_RESTORING_GAME) {
if (_G(player).walker_in_this_scene) {
// If restoring game, restore player position and facing
player_demand_location(_G(player_info).x, _G(player_info).y);
player_demand_facing(_G(player_info).facing);
}
// Restore camera position
MoveScreenAbs(_G(game_buff_ptr), _G(player_info).camera_x, _G(player_info).camera_y);
}
_G(player).been_here_before = player_been_here(_G(game).room_id);
term_message("calling room_init_code");
room_init();
if (_G(game).previous_room == KERNEL_RESTORING_GAME) {
_G(game).previous_room = -1;
}
// Init for fade up screen
if (!_G(kernel).suppress_fadeup) {
pal_fade_set_start(&_G(master_palette)[0], 0); // Set fade to black instantly (0 ticks)
pal_fade_init(&_G(master_palette)[0], _G(kernel).first_fade, 255, 100,
_G(kernel).fade_up_time, 32765); // 30 ticks
}
if (!_G(set_commands_allowed_since_last_checked))
player_set_commands_allowed(true);
//-------------------- PRE-PLAY ROOM ------------------
term_message("Off to the races -- %d", timer_read_60());
}
void Sections::m4RunScene() {
if (!player_been_here(_G(game).room_id))
player_enters_scene(_G(game).room_id);
game_control_cycle();
}
void Sections::m4EndScene() {
_G(between_rooms) = true;
hotspot_unhide_and_dump();
if (!_G(kernel).going && _GI()._visible && player_commands_allowed())
other_save_game_for_resurrection();
if (_G(kernel).teleported_in) {
_G(kernel).teleported_in = false;
pal_fade_set_start(&_G(master_palette)[0], 0); // Set fade to black instantly (0 ticks)
}
//-------------------- cancel all editors ------------------
scale_editor_cancel();
//-------------------- ROOM SHUTDOWN CODE ------------------
term_message("Shuttin' down the scene");
room_shutdown();
kernel_unload_room(&_G(currentSceneDef), &_G(screenCodeBuff), &_G(game_bgBuff));
pal_cycle_stop();
if (_G(shut_down_digi_tracks_between_rooms)) {
_G(digi).stop(1);
_G(digi).stop(2);
_G(digi).stop(3);
_G(digi).flush_mem();
}
conv_unload(conv_get_handle());
ws_KillDeadMachines();
//-------------------- DUMP ASSETS AND MINI-ENGINES ------------------
// Note machines should always be cleared before anything else
ClearWSAssets(_WS_ASSET_MACH, 0, 255);
ClearWSAssets(_WS_ASSET_SEQU, 0, 255);
ClearWSAssets(_WS_ASSET_DATA, 0, 255);
ClearWSAssets(_WS_ASSET_CELS, 0, 255);
// Dump a list of any resources remaining in memory
_G(resources).dumpResources();
// Reload the walker and show scripts.
if (!LoadWSAssets("walker script", &_G(master_palette)[0]))
error_show(FL, 'FNF!', "walker script");
if (!LoadWSAssets("show script", &_G(master_palette)[0]))
error_show(FL, 'FNF!', "show script");
if (!LoadWSAssets("stream script", &_G(master_palette)[0]))
error_show(FL, 'FNF', "stream script");
g_vars->global_menu_system_init();
}
void Sections::get_ipl() {
if (_G(inverse_pal))
delete _G(inverse_pal);
_G(inverse_pal) = nullptr;
Common::String filename;
char *name = env_find(_G(currentSceneDef).art_base);
if (name) {
// Means found in database
filename = f_extension_new(name, "ipl");
} else {
// Concat hag mode
filename = Common::String::format("%s.IPL", _G(currentSceneDef).art_base);
}
_G(inverse_pal) = new InvPal(filename.c_str());
}
void Sections::get_walker() {
term_message("Loading walker sprites");
if (!_GW().walk_load_walker_and_shadow_series())
error_show(FL, 'WLOD');
ws_walk_init_system();
}
void Sections::game_control_cycle() {
while (_G(game).new_room == _G(game).room_id && _G(kernel).going && !_G(kernel).force_restart) {
krn_pal_game_task();
int32 status;
ScreenContext *screen = vmng_screen_find(_G(gameDrawBuff), &status);
if (!screen)
error_show(FL, 'BUF!');
if (_G(player).ready_to_walk) {
if (_G(player).need_to_walk) {
if (_G(player).noun[0] == '@' || !_G(player).walker_in_this_scene) {
term_message("parsing0");
parse_player_command_now();
term_message("parsed0");
} else {
term_message("player: walk to (%d, %d), facing: %d",
_G(player).walk_x, _G(player).walk_y, _G(player).walk_facing);
if (_G(player).walk_x < 0 || _G(player).walk_y < 0) {
term_message("walk x or y < 0 - player: %s %s %s",
_G(player).verb, _G(player).noun, _G(player).prep);
}
_G(player).waiting_for_walk = true;
ws_walk(_G(my_walker), _G(player).walk_x, _G(player).walk_y,
nullptr, _G(player).walker_trigger, _G(player).walk_facing);
term_message("walked");
_G(player).need_to_walk = false;
}
} else if (!_G(player).waiting_for_walk) {
term_message("parsing1");
parse_player_command_now();
term_message("parsed0");
_G(player).ready_to_walk = false;
}
}
if (_G(player).walker_in_this_scene && _G(camera_reacts_to_player) &&
_G(gameDrawBuff)->w > 640 && _G(my_walker)) {
const int xp = (_G(my_walker)->myAnim8->myRegs[IDX_X] >> 16) + screen->x1;
if (xp > 560 && _cameraShiftAmount >= 0) {
_cameraShiftAmount += screen->x1 - 427;
const int xv = _cameraShiftAmount + _G(gameDrawBuff)->w - 1;
if (xv < 639)
_cameraShiftAmount = -(_G(gameDrawBuff)->w - 640);
_cameraShiftAmount -= screen->x1;
} else if (xp < 80 && _cameraShiftAmount <= 0) {
_cameraShiftAmount += screen->x1 + 427;
if (_cameraShiftAmount > 0)
_cameraShiftAmount = 0;
_cameraShiftAmount -= screen->x1;
}
}
// Ensure the screen is updated
g_system->updateScreen();
g_system->delayMillis(10);
g_engine->updateSubtitleOverlay();
if (g_engine->shouldQuit())
_G(kernel).going = false;
}
_GI().cancel_sentence();
}
void Sections::parse_player_command_now() {
if (_G(player).command_ready) {
term_message("player: %s %s %s", _G(player).verb, _G(player).noun, _G(player).prep);
_G(cursor_state) = kARROW;
_G(kernel).trigger_mode = KT_PARSE;
room_parser();
if (_G(player).command_ready) {
section_parser();
if (_G(player).command_ready) {
global_parser();
if (_G(player).command_ready) {
room_error();
if (_G(player).command_ready)
global_error_code();
}
}
}
term_message("...parsed");
}
}
void Sections::pal_game_task() {
int32 status;
int delta;
Common::String line;
if (!player_commands_allowed())
mouse_set_sprite(5);
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
if (!_G(kernel).pause) {
if (_G(toggle_cursor) != CURSCHANGE_NONE) {
const CursorChange change = _G(toggle_cursor);
_G(toggle_cursor) = CURSCHANGE_NONE;
g_vars->getHotkeys()->toggle_through_cursors(change);
}
const bool updateVideo = !_cameraShiftAmount && !_cameraShift_vert_Amount;
cycleEngines(_G(game_bgBuff)->get_buffer(), &(_G(currentSceneDef).depth_table[0]),
_G(screenCodeBuff)->get_buffer(), (uint8 *)&_G(master_palette)[0], _G(inverse_pal)->get_ptr(), updateVideo);
_G(inverse_pal)->release();
_G(game_bgBuff)->release();
if (!game_buff_ptr)
error_show(FL, 'BUF!');
if _G(please_hyperwalk) {
_G(please_hyperwalk) = false;
adv_hyperwalk_to_final_destination(nullptr, nullptr);
}
if (_cameraShiftAmount) {
if (_G(kernel).camera_pan_instant) {
delta = _cameraShiftAmount;
_cameraShiftAmount = 0;
} else {
if (_cameraShiftAmount > 0) {
delta = imath_min(_cameraShiftAmount, camera_pan_step);
} else {
delta = imath_max(_cameraShiftAmount, -camera_pan_step);
}
_cameraShiftAmount -= delta;
}
MoveScreenDelta(game_buff_ptr, delta, 0);
}
if (_cameraShift_vert_Amount) {
if (_G(kernel).camera_pan_instant) {
delta = _cameraShift_vert_Amount;
_cameraShift_vert_Amount = 0;
} else {
if (_cameraShift_vert_Amount > 0) {
delta = imath_min(_cameraShift_vert_Amount, camera_pan_step);
} else {
delta = imath_max(_cameraShift_vert_Amount, camera_pan_step);
}
_cameraShift_vert_Amount -= delta;
}
}
}
pal_fx_update();
_G(digi).read_another_chunk();
_G(midi).loop();
gui_system_event_handler();
if (conv_is_event_ready()) {
_G(player).command_ready = true;
term_message("conv parse row");
parse_player_command_now();
term_message("conv parse finish");
(void)conv_get_event();
}
f_stream_Process(2);
if (_G(kernel).call_daemon_every_loop)
tick();
if (_G(editors_in_use) && (_G(editors_in_use) & 1))
scale_editor_draw();
if (_G(showMousePos))
update_mouse_pos_dialog();
}
void Sections::camera_shift_xy(int32 x, int32 y) {
int32 status;
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), &status);
assert(sc);
_cameraShiftAmount = -sc->x1 - x + _G(kernel).letter_box_x;
_cameraShift_vert_Amount = -sc->y1 - y + _G(kernel).letter_box_y;
}
void Sections::set_camera_delta_pan(int32 deltaX, int32 deltaY) {
_cameraShiftAmount = -deltaX;
_cameraShift_vert_Amount = -deltaY;
}
void Sections::adv_camera_pan_step(int32 step) {
camera_pan_step = step;
}
Room *Sections::getRoom(int room) const {
return (*_sections[(room / 100) - 1])[room];
}
/*------------------------------------------------------------------------*/
Room *Section::operator[](uint roomNum) {
Room *room = _rooms[roomNum];
if (!room)
error("Unknown room number - %d", roomNum);
return room;
}
} // namespace M4

178
engines/m4/core/rooms.h Normal file
View File

@@ -0,0 +1,178 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_ROOMS_H
#define M4_CORE_ROOMS_H
#include "common/hashmap.h"
#include "common/serializer.h"
#include "m4/adv_r/adv.h"
#include "m4/adv_r/adv_control.h"
#include "m4/adv_r/adv_hotspot.h"
namespace M4 {
class Room {
public:
Room() {}
virtual ~Room() {}
virtual void preload();
virtual void init() {}
virtual void daemon() {}
virtual void pre_parser() {}
virtual void parser();
virtual void roomError() {}
virtual void shutdown() {}
virtual void syncGame(Common::Serializer &s) {}
/**
* Used to return custom hotspots at a given position
*/
virtual HotSpotRec *custom_hotspot_which(int32 x, int32 y) {
return nullptr;
}
};
class Section {
private:
Common::HashMap<int, Room *> _rooms;
protected:
// Add a room to the section
void add(int roomNum, Room *room) {
_rooms[roomNum] = room;
}
public:
Section() {}
virtual ~Section() {}
virtual void preLoad() {}
/**
* Section initialization
*/
virtual void init() {}
/**
* Iterates through the rooms array to find a given room
*/
Room *operator[](uint roomNum);
virtual void global_room_init() {}
virtual void daemon() = 0;
virtual void tick() {}
virtual void pre_parser() {}
virtual void parser() {}
};
class Sections {
private:
int32 _cameraShiftAmount = 0;
int32 _cameraShift_vert_Amount = 0;
int32 camera_pan_step = 10;
void get_ipl();
void get_walker();
void game_control_cycle();
protected:
Common::Array<Section *> _sections;
public:
Section *_activeSection = nullptr;
Room *_activeRoom = nullptr;
public:
Sections() {}
virtual ~Sections() {}
void global_section_constructor();
void section_room_constructor();
void game_daemon_code();
void parse_player_command_now();
void section_init() {
_activeSection->init();
}
void daemon() {
_activeSection->daemon();
}
void global_room_init() {
_activeSection->global_room_init();
}
void tick() {
_activeSection->tick();
}
void section_parser() {
_activeSection->parser();
}
void room_preload() {
_activeRoom->preload();
}
void room_init() {
_activeRoom->init();
}
void room_daemon() {
_activeRoom->daemon();
}
void room_pre_parser() {
_activeRoom->pre_parser();
}
void room_parser() {
_activeRoom->parser();
}
void room_error() {
_activeRoom->roomError();
}
void room_shutdown() {
_activeRoom->shutdown();
}
HotSpotRec *custom_hotspot_which(int x, int y) {
return _activeRoom->custom_hotspot_which(x, y);
}
Room *getRoom(int room) const;
void m4SceneLoad();
void m4RunScene();
void m4EndScene();
void pal_game_task();
void camera_shift_xy(int32 x, int32 y);
void set_camera_delta_pan(int32 deltaX, int32 deltaY);
void adv_camera_pan_step(int32 step);
bool game_camera_panning() const {
return _cameraShiftAmount != 0 || _cameraShift_vert_Amount != 0;
}
virtual void global_daemon() = 0;
virtual void global_pre_parser() {}
virtual void global_parser() = 0;
void global_error_code() {
// No implementation
}
};
} // namespace M4
#endif

86
engines/m4/core/term.cpp Normal file
View File

@@ -0,0 +1,86 @@
/* 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/debug.h"
#include "common/savefile.h"
#include "common/system.h"
#include "m4/core/term.h"
#include "m4/vars.h"
namespace M4 {
void Term::init(bool use_me, bool use_log) {
_using_mono_screen = use_me;
_use_log_file = use_log;
set_mode(MESSAGE_MODE);
if (use_log) {
_file = g_system->getSavefileManager()->openForSaving("term.log");
if (!_file)
error("Fail to create term.log file");
}
}
void Term::set_mode(TermMode mode) {
if (_using_mono_screen && mode != _mode) {
_mode = mode;
switch (mode) {
case MESSAGE_MODE:
message("********Message Mode");
break;
case MEMORY_MODE:
message("********Memory Mode");
break;
default:
break;
}
}
}
void Term::message(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
vmessage(fmt, va);
va_end(va);
}
void Term::vmessage(const char *fmt, va_list va) {
if (_mode != MEMORY_MODE) {
Common::String msg = Common::String::vformat(fmt, va);
debug(1, "%s", msg.c_str());
if (_file) {
_file->writeString(msg);
_file->writeByte('\n');
_file->writeByte(0);
}
}
}
void term_message(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
_G(term).vmessage(fmt, va);
va_end(va);
}
} // namespace M4

68
engines/m4/core/term.h Normal file
View File

@@ -0,0 +1,68 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_CORE_TERM_H
#define M4_CORE_TERM_H
#include "common/stream.h"
namespace M4 {
enum TermMode {
NO_MODE = 0,
MESSAGE_MODE,
MEMORY_MODE
};
class Term {
private:
Common::WriteStream *_file = nullptr;
bool _using_mono_screen = false;
bool _use_log_file = false;
TermMode _mode = NO_MODE;
public:
/**
* Initialization
*/
void init(bool use_me, bool use_log);
~Term() {
delete _file;
}
/**
* Set the terminal mode
*/
void set_mode(TermMode mode);
/**
* Show a message
*/
void message(const char *fmt, ...);
void vmessage(const char *fmt, va_list va);
};
void term_message(const char *fmt, ...);
} // namespace M4
#endif