From 40eaa2095ed282d7b9247ca0116e7cc06360b2b9 Mon Sep 17 00:00:00 2001
From: Ghabry <gabriel+github@mastergk.de>
Date: Tue, 9 May 2017 20:02:48 +0200
Subject: [PATCH 1/3] Add MRI 1.8 Support

---
 binding-mri/binding-mri.cpp        |  12 ++-
 binding-mri/binding-util.cpp       |  74 ++++++++++++++++++
 binding-mri/binding-util.h         | 116 ++++++++++++++++++++++++++++-
 binding-mri/filesystem-binding.cpp |  12 ++-
 4 files changed, 210 insertions(+), 4 deletions(-)

diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp
index 1c0057b..b9be9bc 100644
--- a/binding-mri/binding-mri.cpp
+++ b/binding-mri/binding-mri.cpp
@@ -32,7 +32,9 @@
 #include "boost-hash.h"
 
 #include <ruby.h>
+#if RUBY_API_VERSION_MAJOR > 1
 #include <ruby/encoding.h>
+#endif
 
 #include <assert.h>
 #include <string>
@@ -204,7 +206,7 @@ RB_METHOD(mriP)
 RB_METHOD(mkxpDataDirectory)
 {
 	RB_UNUSED_PARAM;
-	
+
 	const std::string &path = shState->config().customDataPath;
 	const char *s = path.empty() ? "." : path.c_str();
 
@@ -580,9 +582,15 @@ static void mriBindingExecute()
 	 * stdio streams on some platforms (eg. Windows) */
 	int argc = 0;
 	char **argv = 0;
-	ruby_sysinit(&argc, &argv);
 
+#if RUBY_API_VERSION_MAJOR == 1
+	ruby_init();
+	//ruby_options(argc, argv);
+#else
+	ruby_sysinit(&argc, &argv);
 	ruby_setup();
+#endif
+
 	rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding()));
 
 	Config &conf = shState->rtData().config;
diff --git a/binding-mri/binding-util.cpp b/binding-mri/binding-util.cpp
index e73d999..ffbb742 100644
--- a/binding-mri/binding-util.cpp
+++ b/binding-mri/binding-util.cpp
@@ -90,6 +90,9 @@ void raiseRbExc(const Exception &exc)
 void
 raiseDisposedAccess(VALUE self)
 {
+#if RUBY_API_VERSION_MAJOR == 1
+// FIXME: raiseDisposedAccess not implemented
+#else
 	const char *klassName = RTYPEDDATA_TYPE(self)->wrap_struct_name;
 	char buf[32];
 
@@ -97,6 +100,7 @@ raiseDisposedAccess(VALUE self)
 	buf[0] = tolower(buf[0]);
 
 	rb_raise(getRbData()->exc[RGSS], "disposed %s", buf);
+#endif
 }
 
 int
@@ -319,3 +323,73 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
 
 	return argI;
 }
+
+#if RUBY_API_VERSION_MAJOR == 1
+// Functions providing Ruby 1.8 compatibililty
+VALUE rb_sprintf(const char* fmt, ...) {
+	va_list args;
+	va_start(args, fmt);
+	char buf[4096];
+	int const result = vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+
+	return rb_str_new2(buf);
+}
+
+VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t * rbType) {
+	return  rb_data_object_alloc(klass, 0, rbType->function.dmark, rbType->function.dfree);
+}
+
+void *rb_check_typeddata(VALUE v, const rb_data_type_t *) {
+// FIXME: rb_check_typeddata not implemented
+	return RTYPEDDATA_DATA(v);
+}
+
+NORETURN(void rb_error_arity(int, int, int)) {
+	assert(false);
+}
+
+VALUE rb_enc_str_new(const char* ch, long len, rb_encoding*) {
+	return rb_str_new(ch, len);
+}
+
+rb_encoding *rb_utf8_encoding(void) {
+	return NULL;
+}
+
+void rb_enc_set_default_external(VALUE encoding) {
+	// no-op, assuming UTF-8
+}
+
+VALUE rb_enc_from_encoding(rb_encoding *enc) {
+	return Qnil;
+}
+
+VALUE rb_str_catf(VALUE, const char*, ...) {
+	return Qnil;
+}
+
+VALUE rb_errinfo(void) {
+	return ruby_errinfo;
+}
+
+int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *) {
+	return 1;
+}
+
+VALUE rb_file_open_str(VALUE filename, const char* mode) {
+	return rb_file_open(RB_OBJ_STRING(filename), mode);
+}
+
+VALUE rb_enc_associate_index(VALUE, int) {
+	return Qnil;
+}
+
+int rb_utf8_encindex(void) {
+	return 0;
+}
+
+VALUE rb_hash_lookup2(VALUE, VALUE, VALUE) {
+	return Qnil;
+}
+#endif
diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h
index 1b758be..e3f35d9 100644
--- a/binding-mri/binding-util.h
+++ b/binding-mri/binding-util.h
@@ -23,9 +23,124 @@
 #define BINDING_UTIL_H
 
 #include <ruby.h>
+#include <ruby/version.h>
 
 #include "exception.h"
 
+// Ruby 1.8 and Ruby 2.x use different version macros
+#ifndef RUBY_API_VERSION_MAJOR
+#define RUBY_API_VERSION_MAJOR RUBY_VERSION_MAJOR
+#endif
+
+#if RUBY_API_VERSION_MAJOR == 1
+// Functions and macros providing Ruby 1.8 compatibililty
+#define FLONUM_P(x) 0
+
+#define RB_FLOAT_TYPE_P(obj) (FLONUM_P(obj) || (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == T_FLOAT))
+
+#define RB_TYPE_P(obj, type) ( \
+	((type) == T_FIXNUM) ? FIXNUM_P(obj) : \
+	((type) == T_TRUE) ? ((obj) == Qtrue) : \
+	((type) == T_FALSE) ? ((obj) == Qfalse) : \
+	((type) == T_NIL) ? ((obj) == Qnil) : \
+	((type) == T_UNDEF) ? ((obj) == Qundef) : \
+	((type) == T_SYMBOL) ? SYMBOL_P(obj) : \
+	((type) == T_FLOAT) ? RB_FLOAT_TYPE_P(obj) : \
+	(!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == (type)))
+
+#define RUBY_T_ARRAY T_ARRAY
+#define RUBY_T_STRING T_STRING
+#define RUBY_T_FLOAT T_FLOAT
+#define RUBY_T_FIXNUM T_FIXNUM
+#define RUBY_T_TRUE T_TRUE
+#define RUBY_T_FALSE T_FALSE
+#define RUBY_T_NIL T_NIL
+
+#define OBJ_INIT_COPY(obj, orig) \
+    ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
+
+#define rb_str_new_cstr rb_str_new2
+
+#define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1)
+#define RUBY_NEVER_FREE   ((RUBY_DATA_FUNC)0)
+#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
+#define RUBY_TYPED_NEVER_FREE   RUBY_NEVER_FREE
+
+#define PRIsVALUE "s"
+#define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+#define RB_OBJ_STRING(obj) StringValueCStr(obj)
+
+#define RTYPEDDATA_DATA DATA_PTR
+
+#define RFLOAT_VALUE(d) RFLOAT(d)->value
+
+#define ENCODING_INLINE_MAX 127
+#define ENCODING_SHIFT (FL_USHIFT+10)
+#define ENCODING_MASK (((VALUE)ENCODING_INLINE_MAX)<<ENCODING_SHIFT) /* FL_USER10|FL_USER11|FL_USER12|FL_USER13|FL_USER14|FL_USER15|FL_USER16 */
+
+#define ENCODING_SET_INLINED(obj,i) do {\
+    RBASIC(obj)->flags &= ~ENCODING_MASK;\
+    RBASIC(obj)->flags |= (VALUE)(i) << ENCODING_SHIFT;\
+} while (0)
+#define ENCODING_SET(obj,i) rb_enc_set_index((obj), (i))
+
+#define ENCODING_GET_INLINED(obj) (int)((RBASIC(obj)->flags & ENCODING_MASK)>>ENCODING_SHIFT)
+#define ENCODING_GET(obj) \
+    (ENCODING_GET_INLINED(obj) != ENCODING_INLINE_MAX ? \
+     ENCODING_GET_INLINED(obj) : \
+     rb_enc_get_index(obj))
+
+#define ENCODING_IS_ASCII8BIT(obj) (ENCODING_GET_INLINED(obj) == 0)
+
+typedef struct {
+	const char *wrap_struct_name;
+	struct {
+		void (*dmark)(void*);
+		void (*dfree)(void*);
+		size_t (*dsize)(const void *);
+		void *reserved[2];
+	} function;
+	const char *parent;
+	void *data;
+	VALUE flags;
+} rb_data_type_t;
+
+VALUE rb_sprintf(const char* fmt, ...);
+
+VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *);
+
+void *rb_check_typeddata(VALUE, const rb_data_type_t *);
+
+#define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t))
+
+NORETURN(void rb_error_arity(int, int, int));
+
+typedef void rb_encoding;
+
+VALUE rb_enc_str_new(const char*, long, rb_encoding*);
+
+rb_encoding *rb_utf8_encoding(void);
+
+void rb_enc_set_default_external(VALUE encoding);
+
+VALUE rb_enc_from_encoding(rb_encoding *enc);
+
+VALUE rb_str_catf(VALUE, const char*, ...);
+
+VALUE rb_errinfo(void);
+
+int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *);
+
+VALUE rb_file_open_str(VALUE, const char*);
+
+VALUE rb_enc_associate_index(VALUE, int);
+
+int rb_utf8_encindex(void);
+
+VALUE rb_hash_lookup2(VALUE, VALUE, VALUE);
+
+#endif
+
 enum RbException
 {
 	RGSS = 0,
@@ -66,7 +181,6 @@ raiseRbExc(const Exception &exc);
 	extern rb_data_type_t Klass##Type
 
 /* 2.1 has added a new field (flags) to rb_data_type_t */
-#include <ruby/version.h>
 #if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 1
 /* TODO: can mkxp use RUBY_TYPED_FREE_IMMEDIATELY here? */
 #define DEF_TYPE_FLAGS 0
diff --git a/binding-mri/filesystem-binding.cpp b/binding-mri/filesystem-binding.cpp
index 4bc5e03..c12e268 100644
--- a/binding-mri/filesystem-binding.cpp
+++ b/binding-mri/filesystem-binding.cpp
@@ -25,7 +25,9 @@
 #include "filesystem.h"
 #include "util.h"
 
+#if RUBY_API_VERSION_MAJOR > 1
 #include "ruby/encoding.h"
+#endif
 #include "ruby/intern.h"
 
 static void
@@ -130,7 +132,6 @@ kernelLoadDataInt(const char *filename, bool rubyExc)
 	VALUE port = fileIntForPath(filename, rubyExc);
 
 	VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
-
 	// FIXME need to catch exceptions here with begin rescue
 	VALUE result = rb_funcall2(marsh, rb_intern("load"), 1, &port);
 
@@ -195,14 +196,21 @@ RB_METHOD(_marshalLoad)
 	rb_get_args(argc, argv, "o|o", &port, &proc RB_ARG_END);
 
 	VALUE utf8Proc;
+	// FIXME: Not implemented for Ruby 1.8
+#if RUBY_API_VERSION_MAJOR > 1
 	if (NIL_P(proc))
 		utf8Proc = rb_proc_new(RUBY_METHOD_FUNC(stringForceUTF8), Qnil);
 	else
 		utf8Proc = rb_proc_new(RUBY_METHOD_FUNC(customProc), proc);
+#endif
 
 	VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
 
+#if RUBY_API_VERSION_MAJOR > 1
 	VALUE v[] = { port, utf8Proc };
+#else
+	VALUE v[] = { port, proc };
+#endif
 	return rb_funcall2(marsh, rb_intern("_mkxp_load_alias"), ARRAY_SIZE(v), v);
 }
 
@@ -214,6 +222,8 @@ fileIntBindingInit()
 
 	_rb_define_method(klass, "read", fileIntRead);
 	_rb_define_method(klass, "getbyte", fileIntGetByte);
+	// Used by Ruby 1.8 Marshaller
+	_rb_define_method(klass, "getc", fileIntGetByte);
 	_rb_define_method(klass, "binmode", fileIntBinmode);
 	_rb_define_method(klass, "close", fileIntClose);
 

From 5064e19421e29060b75bf7394a2e5e1be6c649bd Mon Sep 17 00:00:00 2001
From: Ghabry <gabriel+github@mastergk.de>
Date: Fri, 12 May 2017 12:32:38 +0200
Subject: [PATCH 2/3] Add MRI 1.9 Support.

Unfortunately crashes on startup with "[BUG] object allocation during garbage collection phase"
---
 binding-mri/binding-mri.cpp        |  2 +-
 binding-mri/binding-util.cpp       | 13 ++++-----
 binding-mri/binding-util.h         | 42 +++++++++++++++++-------------
 binding-mri/filesystem-binding.cpp |  6 ++---
 4 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp
index b9be9bc..a6d9685 100644
--- a/binding-mri/binding-mri.cpp
+++ b/binding-mri/binding-mri.cpp
@@ -32,7 +32,7 @@
 #include "boost-hash.h"
 
 #include <ruby.h>
-#if RUBY_API_VERSION_MAJOR > 1
+#ifndef RUBY_LEGACY_VERSION
 #include <ruby/encoding.h>
 #endif
 
diff --git a/binding-mri/binding-util.cpp b/binding-mri/binding-util.cpp
index ffbb742..6203ec8 100644
--- a/binding-mri/binding-util.cpp
+++ b/binding-mri/binding-util.cpp
@@ -90,7 +90,7 @@ void raiseRbExc(const Exception &exc)
 void
 raiseDisposedAccess(VALUE self)
 {
-#if RUBY_API_VERSION_MAJOR == 1
+#ifdef RUBY_LEGACY_VERSION
 // FIXME: raiseDisposedAccess not implemented
 #else
 	const char *klassName = RTYPEDDATA_TYPE(self)->wrap_struct_name;
@@ -325,6 +325,10 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
 }
 
 #if RUBY_API_VERSION_MAJOR == 1
+NORETURN(void rb_error_arity(int, int, int)) {
+	assert(false);
+}
+#if RUBY_API_VERSION_MINOR == 8
 // Functions providing Ruby 1.8 compatibililty
 VALUE rb_sprintf(const char* fmt, ...) {
 	va_list args;
@@ -345,10 +349,6 @@ void *rb_check_typeddata(VALUE v, const rb_data_type_t *) {
 	return RTYPEDDATA_DATA(v);
 }
 
-NORETURN(void rb_error_arity(int, int, int)) {
-	assert(false);
-}
-
 VALUE rb_enc_str_new(const char* ch, long len, rb_encoding*) {
 	return rb_str_new(ch, len);
 }
@@ -392,4 +392,5 @@ int rb_utf8_encindex(void) {
 VALUE rb_hash_lookup2(VALUE, VALUE, VALUE) {
 	return Qnil;
 }
-#endif
+#endif // RUBY_API_VERSION_MINOR == 8
+#endif // RUBY_API_VERSION_MAJOR == 1
\ No newline at end of file
diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h
index e3f35d9..b6bf9f1 100644
--- a/binding-mri/binding-util.h
+++ b/binding-mri/binding-util.h
@@ -27,12 +27,27 @@
 
 #include "exception.h"
 
-// Ruby 1.8 and Ruby 2.x use different version macros
+// Ruby 1.8 and Ruby 1.9+ use different version macros
 #ifndef RUBY_API_VERSION_MAJOR
 #define RUBY_API_VERSION_MAJOR RUBY_VERSION_MAJOR
 #endif
 
+#ifndef RUBY_API_VERSION_MINOR
+#define RUBY_API_VERSION_MINOR RUBY_VERSION_MINOR
+#endif
+
 #if RUBY_API_VERSION_MAJOR == 1
+#define PRIsVALUE "s"
+#define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+#define RB_OBJ_STRING(obj) StringValueCStr(obj)
+
+NORETURN(void rb_error_arity(int, int, int));
+
+#define OBJ_INIT_COPY(obj, orig) \
+	((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
+#if RUBY_API_VERSION_MINOR == 8
+// Makes version checks easier
+#define RUBY_LEGACY_VERSION
 // Functions and macros providing Ruby 1.8 compatibililty
 #define FLONUM_P(x) 0
 
@@ -56,9 +71,6 @@
 #define RUBY_T_FALSE T_FALSE
 #define RUBY_T_NIL T_NIL
 
-#define OBJ_INIT_COPY(obj, orig) \
-    ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
-
 #define rb_str_new_cstr rb_str_new2
 
 #define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1)
@@ -66,10 +78,6 @@
 #define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
 #define RUBY_TYPED_NEVER_FREE   RUBY_NEVER_FREE
 
-#define PRIsVALUE "s"
-#define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-#define RB_OBJ_STRING(obj) StringValueCStr(obj)
-
 #define RTYPEDDATA_DATA DATA_PTR
 
 #define RFLOAT_VALUE(d) RFLOAT(d)->value
@@ -79,16 +87,16 @@
 #define ENCODING_MASK (((VALUE)ENCODING_INLINE_MAX)<<ENCODING_SHIFT) /* FL_USER10|FL_USER11|FL_USER12|FL_USER13|FL_USER14|FL_USER15|FL_USER16 */
 
 #define ENCODING_SET_INLINED(obj,i) do {\
-    RBASIC(obj)->flags &= ~ENCODING_MASK;\
-    RBASIC(obj)->flags |= (VALUE)(i) << ENCODING_SHIFT;\
+	RBASIC(obj)->flags &= ~ENCODING_MASK;\
+	RBASIC(obj)->flags |= (VALUE)(i) << ENCODING_SHIFT;\
 } while (0)
 #define ENCODING_SET(obj,i) rb_enc_set_index((obj), (i))
 
 #define ENCODING_GET_INLINED(obj) (int)((RBASIC(obj)->flags & ENCODING_MASK)>>ENCODING_SHIFT)
 #define ENCODING_GET(obj) \
-    (ENCODING_GET_INLINED(obj) != ENCODING_INLINE_MAX ? \
-     ENCODING_GET_INLINED(obj) : \
-     rb_enc_get_index(obj))
+	(ENCODING_GET_INLINED(obj) != ENCODING_INLINE_MAX ? \
+	ENCODING_GET_INLINED(obj) : \
+	rb_enc_get_index(obj))
 
 #define ENCODING_IS_ASCII8BIT(obj) (ENCODING_GET_INLINED(obj) == 0)
 
@@ -113,8 +121,6 @@ void *rb_check_typeddata(VALUE, const rb_data_type_t *);
 
 #define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t))
 
-NORETURN(void rb_error_arity(int, int, int));
-
 typedef void rb_encoding;
 
 VALUE rb_enc_str_new(const char*, long, rb_encoding*);
@@ -139,7 +145,8 @@ int rb_utf8_encindex(void);
 
 VALUE rb_hash_lookup2(VALUE, VALUE, VALUE);
 
-#endif
+#endif // RUBY_API_VERSION_MINOR == 8
+#endif // RUBY_API_VERSION_MAJOR == 1
 
 enum RbException
 {
@@ -181,7 +188,7 @@ raiseRbExc(const Exception &exc);
 	extern rb_data_type_t Klass##Type
 
 /* 2.1 has added a new field (flags) to rb_data_type_t */
-#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 1
+#if RUBY_API_VERSION_MAJOR > 1 && RUBY_API_VERSION_MINOR > 0
 /* TODO: can mkxp use RUBY_TYPED_FREE_IMMEDIATELY here? */
 #define DEF_TYPE_FLAGS 0
 #else
@@ -497,5 +504,4 @@ rb_check_argc(int actual, int expected)
 	_rb_define_method(klass, prop_name_s "=", Klass##Set##PropName); \
 }
 
-
 #endif // BINDING_UTIL_H
diff --git a/binding-mri/filesystem-binding.cpp b/binding-mri/filesystem-binding.cpp
index c12e268..9a92c52 100644
--- a/binding-mri/filesystem-binding.cpp
+++ b/binding-mri/filesystem-binding.cpp
@@ -25,7 +25,7 @@
 #include "filesystem.h"
 #include "util.h"
 
-#if RUBY_API_VERSION_MAJOR > 1
+#ifndef RUBY_LEGACY_VERSION
 #include "ruby/encoding.h"
 #endif
 #include "ruby/intern.h"
@@ -197,7 +197,7 @@ RB_METHOD(_marshalLoad)
 
 	VALUE utf8Proc;
 	// FIXME: Not implemented for Ruby 1.8
-#if RUBY_API_VERSION_MAJOR > 1
+#ifndef RUBY_LEGACY_VERSION
 	if (NIL_P(proc))
 		utf8Proc = rb_proc_new(RUBY_METHOD_FUNC(stringForceUTF8), Qnil);
 	else
@@ -206,7 +206,7 @@ RB_METHOD(_marshalLoad)
 
 	VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
 
-#if RUBY_API_VERSION_MAJOR > 1
+#ifndef RUBY_LEGACY_VERSION
 	VALUE v[] = { port, utf8Proc };
 #else
 	VALUE v[] = { port, proc };

From 7ef1213b37ac92e25a4c87fecefb1394bf1a7dc1 Mon Sep 17 00:00:00 2001
From: Ghabry <gabriel+github@mastergk.de>
Date: Mon, 22 May 2017 19:22:14 +0200
Subject: [PATCH 3/3] Ruby 1.8: Style improvements. Implement rb_str_catf &
 rb_hash_lookup2.

---
 binding-mri/binding-mri.cpp        |   1 -
 binding-mri/binding-util.cpp       | 106 +++++++++++++++++++++--------
 binding-mri/filesystem-binding.cpp |   1 +
 3 files changed, 78 insertions(+), 30 deletions(-)

diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp
index a6d9685..a4f0960 100644
--- a/binding-mri/binding-mri.cpp
+++ b/binding-mri/binding-mri.cpp
@@ -585,7 +585,6 @@ static void mriBindingExecute()
 
 #if RUBY_API_VERSION_MAJOR == 1
 	ruby_init();
-	//ruby_options(argc, argv);
 #else
 	ruby_sysinit(&argc, &argv);
 	ruby_setup();
diff --git a/binding-mri/binding-util.cpp b/binding-mri/binding-util.cpp
index 6203ec8..1bc2b49 100644
--- a/binding-mri/binding-util.cpp
+++ b/binding-mri/binding-util.cpp
@@ -91,16 +91,16 @@ void
 raiseDisposedAccess(VALUE self)
 {
 #ifdef RUBY_LEGACY_VERSION
-// FIXME: raiseDisposedAccess not implemented
+	const char *klassName = rb_class2name(self);
 #else
 	const char *klassName = RTYPEDDATA_TYPE(self)->wrap_struct_name;
+#endif
 	char buf[32];
 
 	strncpy(buf, klassName, sizeof(buf));
 	buf[0] = tolower(buf[0]);
 
 	rb_raise(getRbData()->exc[RGSS], "disposed %s", buf);
-#endif
 }
 
 int
@@ -325,72 +325,120 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
 }
 
 #if RUBY_API_VERSION_MAJOR == 1
-NORETURN(void rb_error_arity(int, int, int)) {
+NORETURN(void rb_error_arity(int, int, int))
+{
 	assert(false);
 }
+
 #if RUBY_API_VERSION_MINOR == 8
-// Functions providing Ruby 1.8 compatibililty
-VALUE rb_sprintf(const char* fmt, ...) {
-	va_list args;
-	va_start(args, fmt);
+/*
+Functions providing Ruby 1.8 compatibililty.
+All encoding related functions return dummy values because mkxp only uses them
+to retrieve the UTF-8 encoding.
+*/
+VALUE rb_sprintf_vararg(const char* fmt, va_list args) {
 	char buf[4096];
-	int const result = vsnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
+	int result = vsnprintf(buf, sizeof(buf), fmt, args);
+
+	if (result < 0) {
+		buf[0] = '\0';
+	}
 
 	return rb_str_new2(buf);
 }
 
-VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t * rbType) {
-	return  rb_data_object_alloc(klass, 0, rbType->function.dmark, rbType->function.dfree);
+VALUE rb_sprintf(const char* fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	VALUE val = rb_sprintf_vararg(fmt, args);
+	va_end(args);
+
+	return val;
 }
 
-void *rb_check_typeddata(VALUE v, const rb_data_type_t *) {
-// FIXME: rb_check_typeddata not implemented
-	return RTYPEDDATA_DATA(v);
+VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *rbType)
+{
+	return rb_data_object_alloc(klass, 0, rbType->function.dmark, rbType->function.dfree);
 }
 
-VALUE rb_enc_str_new(const char* ch, long len, rb_encoding*) {
+void *rb_check_typeddata(VALUE value, const rb_data_type_t* typed)
+{
+// FIXME: Won't work because rb_typeddata_is_kind_of is not implemented
+	if (!rb_typeddata_is_kind_of(value, typed)) {
+		rb_raise(getRbData()->exc[RGSS],
+			"wrong data type %s (expected %s)", rb_class2name(value), typed->wrap_struct_name
+		);
+	}
+
+	return RTYPEDDATA_DATA(value);
+}
+
+VALUE rb_enc_str_new(const char* ch, long len, rb_encoding*)
+{
+	// Encoding is ignored
 	return rb_str_new(ch, len);
 }
 
-rb_encoding *rb_utf8_encoding(void) {
+rb_encoding *rb_utf8_encoding(void)
+{
+	// not relevant
 	return NULL;
 }
 
-void rb_enc_set_default_external(VALUE encoding) {
-	// no-op, assuming UTF-8
+void rb_enc_set_default_external(VALUE)
+{
+	// not relevant
 }
 
-VALUE rb_enc_from_encoding(rb_encoding *enc) {
+VALUE rb_enc_from_encoding(rb_encoding*)
+{
+	// not relevant
 	return Qnil;
 }
 
-VALUE rb_str_catf(VALUE, const char*, ...) {
-	return Qnil;
+VALUE rb_str_catf(VALUE value, const char* fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	VALUE second = rb_sprintf_vararg(fmt, args);
+	va_end(args);
+
+	return rb_str_concat(value, second);
 }
 
-VALUE rb_errinfo(void) {
+VALUE rb_errinfo(void)
+{
 	return ruby_errinfo;
 }
 
-int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *) {
+int rb_typeddata_is_kind_of(VALUE value, const rb_data_type_t* typed)
+{
+// FIXME: rb_typeddata_is_kind_of not implemented
 	return 1;
 }
 
-VALUE rb_file_open_str(VALUE filename, const char* mode) {
+VALUE rb_file_open_str(VALUE filename, const char* mode)
+{
 	return rb_file_open(RB_OBJ_STRING(filename), mode);
 }
 
-VALUE rb_enc_associate_index(VALUE, int) {
+VALUE rb_enc_associate_index(VALUE, int)
+{
+	// not relevant
 	return Qnil;
 }
 
-int rb_utf8_encindex(void) {
+int rb_utf8_encindex(void)
+{
+	// not relevant
 	return 0;
 }
 
-VALUE rb_hash_lookup2(VALUE, VALUE, VALUE) {
-	return Qnil;
+VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
+{
+	VALUE v = rb_hash_lookup(hash, key);
+	return (v == Qnil) ? def : v;
 }
 #endif // RUBY_API_VERSION_MINOR == 8
-#endif // RUBY_API_VERSION_MAJOR == 1
\ No newline at end of file
+#endif // RUBY_API_VERSION_MAJOR == 1
diff --git a/binding-mri/filesystem-binding.cpp b/binding-mri/filesystem-binding.cpp
index 9a92c52..512ce4f 100644
--- a/binding-mri/filesystem-binding.cpp
+++ b/binding-mri/filesystem-binding.cpp
@@ -132,6 +132,7 @@ kernelLoadDataInt(const char *filename, bool rubyExc)
 	VALUE port = fileIntForPath(filename, rubyExc);
 
 	VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
+
 	// FIXME need to catch exceptions here with begin rescue
 	VALUE result = rb_funcall2(marsh, rb_intern("load"), 1, &port);