diff --git a/sourcepawn/vm/sp_vm.c b/sourcepawn/vm/sp_vm.c
index 3e7ac7a3..d2896f5b 100644
--- a/sourcepawn/vm/sp_vm.c
+++ b/sourcepawn/vm/sp_vm.c
@@ -403,10 +403,6 @@ int SP_PushCellArray(sp_context_t *ctx, cell_t *local_addr, cell_t **phys_addr,
 	}
 
 	memcpy(ph_addr, array, numcells * sizeof(cell_t));
-	if (phys_addr)
-	{
-		*phys_addr = ph_addr;
-	}
 
 	if ((err = SP_PushCell(ctx, *local_addr)) != SP_ERR_NONE)
 	{
@@ -414,6 +410,11 @@ int SP_PushCellArray(sp_context_t *ctx, cell_t *local_addr, cell_t **phys_addr,
 		return err;
 	}
 
+	if (phys_addr)
+	{
+		*phys_addr = ph_addr;
+	}
+
 	return SP_ERR_NONE;
 }
 
@@ -467,16 +468,43 @@ int SP_PushString(sp_context_t *ctx, cell_t *local_addr, cell_t **phys_addr, con
 	}
 	ph_addr[numcells] = '\0';
 
-	if (phys_addr)
-	{
-		*phys_addr = ph_addr;
-	}
-
 	if ((err = SP_PushCell(ctx, *local_addr)) != SP_ERR_NONE)
 	{
 		SP_HeapRelease(ctx, *local_addr);
 		return err;
 	}
 
+	if (phys_addr)
+	{
+		*phys_addr = ph_addr;
+	}
+
+	return SP_ERR_NONE;
+}
+
+int SP_StringToLocal(sp_context_t *ctx, cell_t local_addr, size_t chars, const char *source)
+{
+	cell_t *dest;
+	size_t i, len;
+
+	if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->memory))
+	{
+		return SP_ERR_INVALID_ADDRESS;
+	}
+
+	len = strlen(source);
+	dest = (cell_t *)(ctx->data + local_addr);
+
+	if (len >= chars)
+	{
+		len = chars - 1;
+	}
+
+	for (i=0; i<len; i++)
+	{
+		dest[i] = (cell_t)source[i];
+	}
+	dest[len] = '\0';
+
 	return SP_ERR_NONE;
 }
diff --git a/sourcepawn/vm/sp_vm_debug.c b/sourcepawn/vm/sp_vm_debug.c
new file mode 100644
index 00000000..f3fc80e9
--- /dev/null
+++ b/sourcepawn/vm/sp_vm_debug.c
@@ -0,0 +1,88 @@
+#include "sp_vm.h"
+#include "sp_vm_debug.h"
+
+int SP_DbgLookupFile(sp_context_t *ctx, ucell_t addr, const char **filename)
+{
+	uint32_t mid, low, high;
+	int diff;
+
+	high = ctx->plugin->debug.files_num - 1;
+	low = 0;
+
+	while (low <= high)
+	{
+		mid = (low + high) / 2;
+		diff = ctx->files[mid].addr - addr;
+		if (diff == 0)
+		{
+			*filename = ctx->files[mid].name;
+			return SP_ERR_NONE;
+		} else if (diff < 0) {
+			low = mid + 1;
+		} else {
+			high = mid - 1;
+		}
+	}
+
+	return SP_ERR_NOT_FOUND;
+}
+
+int SP_DbgLookupFunction(sp_context_t *ctx, ucell_t addr, const char **name)
+{
+	uint32_t iter, max = ctx->plugin->debug.syms_num;
+
+	for (iter=0; iter<max; iter++)
+	{
+		if ((ctx->symbols[iter].sym->ident == SP_SYM_FUNCTION) 
+			&& (ctx->symbols[iter].codestart <= addr) 
+			&& (ctx->symbols[iter].codeend > addr))
+		{
+			break;
+		}
+	}
+
+	if (iter >= max)
+	{
+		return SP_ERR_NOT_FOUND;
+	}
+
+	*name = ctx->symbols[iter].name;
+
+	return SP_ERR_NONE;
+}
+
+int SP_DbgLookupLine(sp_context_t *ctx, ucell_t addr, uint32_t *line)
+{
+	uint32_t mid, low, high;
+	int diff;
+
+	high = ctx->plugin->debug.lines_num - 1;
+	low = 0;
+
+	while (low <= high)
+	{
+		mid = (low + high) / 2;
+		diff = ctx->lines[mid].addr - addr;
+		if (diff == 0)
+		{
+			*line = ctx->lines[mid].line;
+			return SP_ERR_NONE;
+		} else if (diff < 0) {
+			low = mid + 1;
+		} else {
+			high = mid - 1;
+		}
+	}
+
+	return SP_ERR_NOT_FOUND;
+}
+
+int SP_DbgInstallBreak(sp_context_t *ctx, SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn)
+{
+	if (ctx->dbreak)
+		*oldpfn = ctx->dbreak;
+
+	ctx->dbreak = newpfn;
+
+	return SP_ERR_NONE;
+}