aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2019-04-16 21:21:58 -0700
committerPaul Gilbert2019-04-17 20:46:07 -0700
commit936b9731536d914c35b9632e919b510f3ae46506 (patch)
tree02dbbcb04a44cc17f66e04950fe15d20f0145b88
parentee8362cc073a02c91038add400f67dc2e6dba683 (diff)
downloadscummvm-rg350-936b9731536d914c35b9632e919b510f3ae46506.tar.gz
scummvm-rg350-936b9731536d914c35b9632e919b510f3ae46506.tar.bz2
scummvm-rg350-936b9731536d914c35b9632e919b510f3ae46506.zip
GLK: GLULXE: Add miscellaneous missing methods
-rw-r--r--engines/glk/glulxe/accel.cpp2
-rw-r--r--engines/glk/glulxe/exec.cpp2
-rw-r--r--engines/glk/glulxe/float.cpp102
-rw-r--r--engines/glk/glulxe/funcs.cpp2
-rw-r--r--engines/glk/glulxe/gestalt.cpp2
-rw-r--r--engines/glk/glulxe/glkop.cpp2
-rw-r--r--engines/glk/glulxe/glulxe.cpp23
-rw-r--r--engines/glk/glulxe/glulxe.h63
-rw-r--r--engines/glk/glulxe/heap.cpp2
-rw-r--r--engines/glk/glulxe/operand.cpp2
-rw-r--r--engines/glk/glulxe/search.cpp2
-rw-r--r--engines/glk/glulxe/serial.cpp4
-rw-r--r--engines/glk/glulxe/string.cpp2
-rw-r--r--engines/glk/glulxe/vm.cpp64
-rw-r--r--engines/glk/tads/tads2/data.cpp6
-rw-r--r--engines/glk/tads/tads2/regex.cpp8
-rw-r--r--engines/glk/tads/tads2/regex.h2
17 files changed, 220 insertions, 70 deletions
diff --git a/engines/glk/glulxe/accel.cpp b/engines/glk/glulxe/accel.cpp
index e4d60cf13b..929c6ab461 100644
--- a/engines/glk/glulxe/accel.cpp
+++ b/engines/glk/glulxe/accel.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/exec.cpp b/engines/glk/glulxe/exec.cpp
index 4fefe05e54..f314ca43e2 100644
--- a/engines/glk/glulxe/exec.cpp
+++ b/engines/glk/glulxe/exec.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/float.cpp b/engines/glk/glulxe/float.cpp
index c1ffc77be9..36ef2f479b 100644
--- a/engines/glk/glulxe/float.cpp
+++ b/engines/glk/glulxe/float.cpp
@@ -20,11 +20,111 @@
*
*/
-#include "glk/glulxe/float.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
+uint Glulxe::encode_float(gfloat32 val) {
+ gfloat32 absval;
+ uint sign;
+ int expo;
+ gfloat32 mant;
+ uint fbits;
+
+ if (signbit(val)) {
+ sign = 0x80000000;
+ absval = -val;
+ }
+ else {
+ sign = 0x0;
+ absval = val;
+ }
+
+ if (isinf(val)) {
+ return sign | 0x7f800000; /* infinity */
+ }
+
+ if (isnan(val)) {
+ return sign | 0x7fc00000;
+ }
+
+ mant = frexpf(absval, &expo);
+
+ /* Normalize mantissa to be in the range [1.0, 2.0) */
+ if (0.5 <= mant && mant < 1.0) {
+ mant *= 2.0;
+ expo--;
+ }
+ else if (mant == 0.0) {
+ expo = 0;
+ }
+ else {
+ return sign | 0x7f800000; /* infinity */
+ }
+
+ if (expo >= 128) {
+ return sign | 0x7f800000; /* infinity */
+ }
+ else if (expo < -126) {
+ /* Denormalized (very small) number */
+ mant = ldexpf(mant, 126 + expo);
+ expo = 0;
+ }
+ else if (!(expo == 0 && mant == 0.0)) {
+ expo += 127;
+ mant -= 1.0; /* Get rid of leading 1 */
+ }
+
+ mant *= 8388608.0; /* 2^23 */
+ fbits = (uint)(mant + 0.5); /* round mant to nearest int */
+ if (fbits >> 23) {
+ /* The carry propagated out of a string of 23 1 bits. */
+ fbits = 0;
+ expo++;
+ if (expo >= 255) {
+ return sign | 0x7f800000; /* infinity */
+ }
+ }
+
+ return (sign) | ((uint)(expo << 23)) | (fbits);
+}
+
+gfloat32 Glulxe::decode_float(uint val) {
+ int sign;
+ int expo;
+ uint mant;
+ gfloat32 res;
+
+ /* First byte */
+ sign = ((val & 0x80000000) != 0);
+ expo = (val >> 23) & 0xFF;
+ mant = val & 0x7FFFFF;
+
+ if (expo == 255) {
+ if (mant == 0) {
+ /* Infinity */
+ return (sign ? (-INFINITY) : (INFINITY));
+ }
+ else {
+ /* Not a number */
+ return (sign ? (-NAN) : (NAN));
+ }
+ }
+
+ res = (gfloat32)mant / 8388608.0;
+
+ if (expo == 0) {
+ expo = -126;
+ }
+ else {
+ res += 1.0;
+ expo -= 127;
+ }
+ res = ldexpf(res, expo);
+
+ return (sign ? (-res) : (res));
+}
} // End of namespace Glulxe
} // End of namespace Glk
diff --git a/engines/glk/glulxe/funcs.cpp b/engines/glk/glulxe/funcs.cpp
index cb427e24fe..b85844a8c1 100644
--- a/engines/glk/glulxe/funcs.cpp
+++ b/engines/glk/glulxe/funcs.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/gestalt.cpp b/engines/glk/glulxe/gestalt.cpp
index 2839c52676..21f8974513 100644
--- a/engines/glk/glulxe/gestalt.cpp
+++ b/engines/glk/glulxe/gestalt.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/glkop.cpp b/engines/glk/glulxe/glkop.cpp
index ee7f78bf42..12d4fef0d3 100644
--- a/engines/glk/glulxe/glkop.cpp
+++ b/engines/glk/glulxe/glkop.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/glulxe.cpp b/engines/glk/glulxe/glulxe.cpp
index 576b961872..1b82f58c05 100644
--- a/engines/glk/glulxe/glulxe.cpp
+++ b/engines/glk/glulxe/glulxe.cpp
@@ -29,12 +29,14 @@ namespace Glulxe {
Glulxe *g_vm;
-Glulxe::Glulxe(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
+Glulxe::Glulxe(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc), _random("glulxe"),
vm_exited_cleanly(false), gamefile(nullptr), gamefile_start(0), gamefile_len(0),
memmap(nullptr), stack(nullptr), ramstart(0), endgamefile(0), origendmem(0), stacksize(0),
startfuncaddr(0), checksum(0), stackptr(0), frameptr(0), pc(0), prevpc(0), origstringtable(0),
stringtable(0), valstackbase(0), localsbase(0), endmem(0), protectstart(0), protectend(0),
stream_char_handler(nullptr), stream_unichar_handler(nullptr),
+ // main
+ library_autorestore_hook(nullptr),
// accel
classes_table(0), indiv_prop_start(0), class_metaclass(0), object_metaclass(0),
routine_metaclass(0), string_metaclass(0), self(0), num_attr_bytes(0), cpv__start(0),
@@ -52,7 +54,20 @@ void Glulxe::runGame() {
if (!is_gamefile_valid())
return;
- // TODO
+ setup_vm();
+ if (library_autorestore_hook)
+ library_autorestore_hook();
+
+ execute_loop();
+ finalize_vm();
+
+ gamefile = NULL;
+ gamefile_start = 0;
+ gamefile_len = 0;
+ init_err = NULL;
+ vm_exited_cleanly = true;
+
+ profile_quit();
}
Common::Error Glulxe::loadGameData(strid_t file) {
@@ -128,5 +143,9 @@ void Glulxe::nonfatal_warning_handler(const char *str, const char *arg, bool use
warning("%s", msg.c_str());
}
+void Glulxe::glulx_sort(void *addr, int count, int size, int(*comparefunc)(const void *p1, const void *p2)) {
+ qsort(addr, count, size, comparefunc);
+}
+
} // End of namespace Glulxe
} // End of namespace Glk
diff --git a/engines/glk/glulxe/glulxe.h b/engines/glk/glulxe/glulxe.h
index f7684f1830..0690560d14 100644
--- a/engines/glk/glulxe/glulxe.h
+++ b/engines/glk/glulxe/glulxe.h
@@ -24,6 +24,7 @@
#define GLK_GLULXE
#include "common/scummsys.h"
+#include "common/random.h"
#include "glk/glk_api.h"
#include "glk/glulxe/glulxe_types.h"
@@ -74,6 +75,20 @@ private:
/**@}*/
/**
+ * \defgroup main fields
+ * @{
+ */
+
+ /**
+ * The library_autorestore_hook is called right after the VM's initial setup. This is an appropriate time
+ * to autorestore an initial game state, if the library has that capability. (Currently, only iosglk does.)
+ */
+ void(*library_autorestore_hook)(void);
+ Common::RandomSource _random;
+
+ /**@}*/
+
+ /**
* \defgroup accel fields
* @{
*/
@@ -327,7 +342,7 @@ protected:
uint read_heapstate(dest_t *dest, uint chunklen, int portable, uint *sumlen, uint **summary);
uint read_stackstate(dest_t *dest, uint chunklen, int portable);
uint write_heapstate_sub(uint sumlen, uint *sumarray, dest_t *dest, int portable);
- static int sort_heap_summary(void *p1, void *p2);
+ static int sort_heap_summary(const void *p1, const void *p2);
int read_byte(dest_t *dest, byte *val);
int read_short(dest_t *dest, uint16 *val);
@@ -675,13 +690,23 @@ public:
* @{
*/
- void *glulx_malloc(uint len);
- void *glulx_realloc(void *ptr, uint len);
- void glulx_free(void *ptr);
- void glulx_setrandom(uint seed);
- uint glulx_random();
- void glulx_sort(void *addr, int count, int size,
- int(*comparefunc)(void *p1, void *p2));
+ inline void *glulx_malloc(uint len) {
+ return malloc(len);
+ }
+ inline void *glulx_realloc(void *ptr, uint len) {
+ return realloc(ptr, len);
+ }
+ inline void glulx_free(void *ptr) {
+ free(ptr);
+ }
+ inline void glulx_setrandom(uint32 seed) {
+ _random.setSeed(seed);
+ }
+ inline uint glulx_random() {
+ return _random.getRandomNumber(0xffffffff);
+ }
+
+ void glulx_sort(void *addr, int count, int size, int(*comparefunc)(const void *p1, const void *p2));
/**@}*/
@@ -846,17 +871,28 @@ public:
(but safer) encoding and decoding functions. */
/* #define FLOAT_NOT_NATIVE (1) */
- /* float.c */
- int init_float();
- uint encode_float(gfloat32 val);
- gfloat32 decode_float(uint val);
+ int init_float() { return true; }
+
+ /**
+ * Encode floats by a lot of annoying bit manipulation.
+ * The function is adapted from code in Python (Objects/floatobject.c)
+ */
+ static uint encode_float(gfloat32 val);
+
+ /**
+ * Decode floats by a lot of annoying bit manipulation.
+ * The function is adapted from code in Python (Objects/floatobject.c)
+ */
+ static gfloat32 decode_float(uint val);
/* Uncomment this definition if your powf() function does not support
all the corner cases specified by C99. If you uncomment this,
osdepend.c will provide a safer implementation of glulx_powf(). */
/* #define FLOAT_COMPILE_SAFER_POWF (1) */
- gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2);
+ inline gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2) const {
+ return powf(val1, val2);
+ }
#endif /* FLOAT_SUPPORT */
/**@}*/
@@ -906,7 +942,6 @@ public:
/**@}*/
-
/**
* \defgroup Strings access methods
* @{
diff --git a/engines/glk/glulxe/heap.cpp b/engines/glk/glulxe/heap.cpp
index 29d9405aca..00b8dcb74c 100644
--- a/engines/glk/glulxe/heap.cpp
+++ b/engines/glk/glulxe/heap.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/operand.cpp b/engines/glk/glulxe/operand.cpp
index a48d68e0b9..cee8420d41 100644
--- a/engines/glk/glulxe/operand.cpp
+++ b/engines/glk/glulxe/operand.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/search.cpp b/engines/glk/glulxe/search.cpp
index d2f1c85d68..440da553f0 100644
--- a/engines/glk/glulxe/search.cpp
+++ b/engines/glk/glulxe/search.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/serial.cpp b/engines/glk/glulxe/serial.cpp
index 6d662166c4..1aa316327c 100644
--- a/engines/glk/glulxe/serial.cpp
+++ b/engines/glk/glulxe/serial.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
@@ -751,7 +751,7 @@ uint Glulxe::write_heapstate_sub(uint sumlen, uint *sumarray, dest_t *dest, int
return 0;
}
-int Glulxe::sort_heap_summary(void *p1, void *p2) {
+int Glulxe::sort_heap_summary(const void *p1, const void *p2) {
uint v1 = *(uint *)p1;
uint v2 = *(uint *)p2;
diff --git a/engines/glk/glulxe/string.cpp b/engines/glk/glulxe/string.cpp
index 2c95c3e851..59420fa1b5 100644
--- a/engines/glk/glulxe/string.cpp
+++ b/engines/glk/glulxe/string.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
diff --git a/engines/glk/glulxe/vm.cpp b/engines/glk/glulxe/vm.cpp
index f332c92248..eb4b1121b4 100644
--- a/engines/glk/glulxe/vm.cpp
+++ b/engines/glk/glulxe/vm.cpp
@@ -20,43 +20,38 @@
*
*/
-#include "engines/glk/glulxe/glulxe.h"
+#include "glk/glulxe/glulxe.h"
namespace Glk {
namespace Glulxe {
void Glulxe::setup_vm() {
- unsigned char buf[4 * 7];
- int res;
+ byte buf[4 * 7];
- pc = 0; /* Clear this, so that error messages are cleaner. */
+ pc = 0; // Clear this, so that error messages are cleaner.
prevpc = 0;
- /* Read in all the size constants from the game file header. */
-
- stream_char_handler = NULL;
- stream_unichar_handler = NULL;
+ // Read in all the size constants from the game file header
+ stream_char_handler = nullptr;
+ stream_unichar_handler = nullptr;
- glk_stream_set_position(gamefile, gamefile_start+8, seekmode_Start);
- res = glk_get_buffer_stream(gamefile, (char *)buf, 4 * 7);
- if (res != 4 * 7) {
+ _gameFile.seek(0);
+ if (_gameFile.read(buf, 4 * 7) != (4 * 7))
fatal_error("The game file header is too short.");
- }
- ramstart = Read4(buf+0);
- endgamefile = Read4(buf+4);
- origendmem = Read4(buf+8);
- stacksize = Read4(buf+12);
- startfuncaddr = Read4(buf+16);
- origstringtable = Read4(buf+20);
- checksum = Read4(buf+24);
-
- /* Set the protection range to (0, 0), meaning "off". */
+ ramstart = Read4(buf + 0);
+ endgamefile = Read4(buf + 4);
+ origendmem = Read4(buf + 8);
+ stacksize = Read4(buf + 12);
+ startfuncaddr = Read4(buf + 16);
+ origstringtable = Read4(buf + 20);
+ checksum = Read4(buf + 24);
+
+ // Set the protection range to (0, 0), meaning "off".
protectstart = 0;
protectend = 0;
- /* Do a few sanity checks. */
-
+ // Do a few sanity checks.
if ((ramstart & 0xFF)
|| (endgamefile & 0xFF)
|| (origendmem & 0xFF)
@@ -81,28 +76,29 @@ void Glulxe::setup_vm() {
/* Allocate main memory and the stack. This is where memory allocation
errors are most likely to occur. */
endmem = origendmem;
- memmap = (unsigned char *)glulx_malloc(origendmem);
+ memmap = (byte *)glulx_malloc(origendmem);
if (!memmap) {
fatal_error("Unable to allocate Glulx memory space.");
}
- stack = (unsigned char *)glulx_malloc(stacksize);
+ stack = (byte *)glulx_malloc(stacksize);
if (!stack) {
glulx_free(memmap);
- memmap = NULL;
+ memmap = nullptr;
fatal_error("Unable to allocate Glulx stack space.");
}
stringtable = 0;
- /* Initialize various other things in the terp. */
+ // Initialize various other things in the terp.
init_operands();
init_serial();
- /* Set up the initial machine state. */
+ // Set up the initial machine state.
vm_restart();
/* If the debugger is compiled in, check that the debug data matches
the game. (This only prints warnings for mismatch.) */
debugger_check_story_file();
+
/* Also, set up any start-time debugger state. This may do a block-
and-debug, if the user has requested that. */
debugger_setup_start_state();
@@ -113,11 +109,11 @@ void Glulxe::finalize_vm() {
if (memmap) {
glulx_free(memmap);
- memmap = NULL;
+ memmap = nullptr;
}
if (stack) {
glulx_free(stack);
- stack = NULL;
+ stack = nullptr;
}
final_serial();
@@ -173,7 +169,7 @@ void Glulxe::vm_restart() {
/* Note that we do not reset the protection range. */
/* Push the first function call. (No arguments.) */
- enter_function(startfuncaddr, 0, NULL);
+ enter_function(startfuncaddr, 0, nullptr);
/* We're now ready to execute. */
}
@@ -219,17 +215,17 @@ uint Glulxe::change_memsize(uint newlen, bool internal) {
}
uint *Glulxe::pop_arguments(uint count, uint addr) {
- int ix;
+ uint ix;
uint argptr;
uint *array;
#define MAXARGS (32)
static uint statarray[MAXARGS];
- static uint *dynarray = NULL;
+ static uint *dynarray = nullptr;
static uint dynarray_size = 0;
if (count == 0)
- return NULL;
+ return nullptr;
if (count <= MAXARGS) {
/* Store in the static array. */
diff --git a/engines/glk/tads/tads2/data.cpp b/engines/glk/tads/tads2/data.cpp
index a2bbf741fe..c60fcb2c5f 100644
--- a/engines/glk/tads/tads2/data.cpp
+++ b/engines/glk/tads/tads2/data.cpp
@@ -20,9 +20,9 @@
*
*/
-#include "engines/glk/tads/tads2/data.h"
-#include "engines/glk/tads/tads2/types.h"
-#include "engines/glk/tads/tads2/vocabulary.h"
+#include "glk/tads/tads2/data.h"
+#include "glk/tads/tads2/types.h"
+#include "glk/tads/tads2/vocabulary.h"
#include "common/algorithm.h"
namespace Glk {
diff --git a/engines/glk/tads/tads2/regex.cpp b/engines/glk/tads/tads2/regex.cpp
index c0404202bf..a7f7d99369 100644
--- a/engines/glk/tads/tads2/regex.cpp
+++ b/engines/glk/tads/tads2/regex.cpp
@@ -67,10 +67,10 @@ Notes
numbers.
*/
-#include "engines/glk/tads/tads2/regex.h"
-#include "engines/glk/tads/tads2/ler.h"
-#include "engines/glk/tads/tads2/os.h"
-//#include "engines/glk/tads/tads2/std.h"
+#include "glk/tads/tads2/regex.h"
+#include "glk/tads/tads2/ler.h"
+#include "glk/tads/tads2/os.h"
+//#include "glk/tads/tads2/std.h"
#//include "engines/glk/tads/tads2/ler.h"
namespace Glk {
diff --git a/engines/glk/tads/tads2/regex.h b/engines/glk/tads/tads2/regex.h
index 4c48a8985d..cd975e066b 100644
--- a/engines/glk/tads/tads2/regex.h
+++ b/engines/glk/tads/tads2/regex.h
@@ -24,7 +24,7 @@
#define GLK_TADS_TADS2_REGEX
#include "common/array.h"
-#include "engines/glk/tads/tads2/ler.h"
+#include "glk/tads/tads2/ler.h"
namespace Glk {
namespace TADS {