Files
BlitzNext/Runtime/bbruntime_dll.cpp
T

337 lines
6.8 KiB
C++
Raw Normal View History

2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
#pragma warning(disable : 4786)
2014-01-31 08:23:00 +13:00
2019-01-18 15:55:06 +01:00
#include "bbruntime_dll.hpp"
#include "../debugger/debugger.hpp"
2014-01-31 08:23:00 +13:00
using namespace std;
#include <eh.h>
#include <float.h>
2019-01-18 17:04:17 +01:00
#include <map>
2014-01-31 08:23:00 +13:00
2019-01-18 15:55:06 +01:00
#include "bbruntime.hpp"
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
class DummyDebugger : public Debugger {
public:
virtual void debugRun() {}
virtual void debugStop() {} // bbruntime_panic(0); }
virtual void debugStmt(int srcpos, const char* file) {}
virtual void debugEnter(void* frame, void* env, const char* func) {}
virtual void debugLeave() {}
virtual void debugLog(const char* msg) {}
virtual void debugMsg(const char* e, bool serious)
{
if (serious)
MessageBox(0, e, "Error!", MB_OK | MB_TOPMOST | MB_SETFOREGROUND);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
virtual void debugSys(void* msg) {}
2014-01-31 08:23:00 +13:00
};
2019-01-18 17:04:17 +01:00
static HINSTANCE hinst;
static map<const char*, void*> syms;
map<const char*, void*>::iterator sym_it;
static gxRuntime* gx_runtime;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
static void rtSym(const char* sym, void* pc)
{
syms[sym] = pc;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
static void _cdecl seTranslator(unsigned int u, EXCEPTION_POINTERS* pExp)
{
switch (u) {
2014-01-31 08:23:00 +13:00
case EXCEPTION_INT_DIVIDE_BY_ZERO:
2019-01-18 17:04:17 +01:00
bbruntime_panic("Integer divide by zero");
2014-01-31 08:23:00 +13:00
case EXCEPTION_ACCESS_VIOLATION:
2019-01-18 17:04:17 +01:00
bbruntime_panic("Memory access violation");
2014-01-31 08:23:00 +13:00
case EXCEPTION_ILLEGAL_INSTRUCTION:
2019-01-18 17:04:17 +01:00
bbruntime_panic("Illegal instruction");
2014-01-31 08:23:00 +13:00
case EXCEPTION_STACK_OVERFLOW:
2019-01-18 17:04:17 +01:00
bbruntime_panic("Stack overflow!");
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
bbruntime_panic("Unknown runtime exception");
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
int Runtime::version()
{
2014-01-31 08:23:00 +13:00
return VERSION;
}
2019-01-18 17:04:17 +01:00
const char* Runtime::nextSym()
{
if (!syms.size()) {
bbruntime_link(rtSym);
sym_it = syms.begin();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
if (sym_it == syms.end()) {
syms.clear();
return 0;
2014-01-31 08:23:00 +13:00
}
return (sym_it++)->first;
}
2019-01-18 17:04:17 +01:00
int Runtime::symValue(const char* sym)
{
map<const char*, void*>::iterator it = syms.find(sym);
if (it != syms.end())
return (int)it->second;
2014-01-31 08:23:00 +13:00
return -1;
}
2019-01-18 17:04:17 +01:00
void Runtime::startup(HINSTANCE h)
{
hinst = h;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Runtime::shutdown()
{
trackmem(false);
2014-01-31 08:23:00 +13:00
syms.clear();
}
2019-01-18 17:04:17 +01:00
void Runtime::execute(void (*pc)(), const char* args, Debugger* dbg)
{
bool debug = !!dbg;
2014-01-31 08:23:00 +13:00
static DummyDebugger dummydebug;
2019-01-18 17:04:17 +01:00
if (!dbg)
dbg = &dummydebug;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
trackmem(true);
2014-01-31 08:23:00 +13:00
2016-07-20 02:01:40 +02:00
_se_translator_function old_trans = _set_se_translator(seTranslator);
2019-01-18 17:04:17 +01:00
_control87(_RC_NEAR | _PC_24 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT
| _EM_DENORMAL,
0xfffff);
2014-01-31 08:23:00 +13:00
//strip spaces from ends of args...
2019-01-18 17:04:17 +01:00
string params = args;
while (params.size() && params[0] == ' ')
params = params.substr(1);
while (params.size() && params[params.size() - 1] == ' ')
params = params.substr(0, params.size() - 1);
if (gx_runtime = gxRuntime::openRuntime(hinst, params, dbg)) {
bbruntime_run(gx_runtime, pc, debug);
gxRuntime* t = gx_runtime;
gx_runtime = 0;
gxRuntime::closeRuntime(t);
2014-01-31 08:23:00 +13:00
}
2016-07-20 02:01:40 +02:00
_control87(_CW_DEFAULT, 0xfffff);
_set_se_translator(old_trans);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Runtime::asyncStop()
{
if (gx_runtime)
gx_runtime->asyncStop();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Runtime::asyncRun()
{
if (gx_runtime)
gx_runtime->asyncRun();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Runtime::asyncEnd()
{
if (gx_runtime)
gx_runtime->asyncEnd();
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
void Runtime::checkmem(streambuf* buf)
{
ostream out(buf);
::checkmem(out);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
Runtime* _cdecl runtimeGetRuntime()
{
2014-01-31 08:23:00 +13:00
static Runtime runtime;
return &runtime;
}
/********************** BUTT UGLY DLL->EXE HOOK! *************************/
2019-01-18 17:04:17 +01:00
static void* module_pc;
static map<string, int> module_syms;
static map<string, int> runtime_syms;
static Runtime* runtime;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
static void fail()
{
MessageBox(0, "Unable to run Blitz Basic module", 0, 0);
2014-01-31 08:23:00 +13:00
ExitProcess(-1);
}
2019-01-18 17:04:17 +01:00
struct Sym {
2014-01-31 08:23:00 +13:00
string name;
2019-01-18 17:04:17 +01:00
int value;
2014-01-31 08:23:00 +13:00
};
2019-01-18 17:04:17 +01:00
static Sym getSym(void** p)
{
Sym sym;
char* t = (char*)*p;
while (char c = *t++)
sym.name += c;
sym.value = *(int*)t + (int)module_pc;
*p = t + 4;
return sym;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
static int findSym(const string& t)
{
map<string, int>::iterator it;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
it = module_syms.find(t);
if (it != module_syms.end())
return it->second;
it = runtime_syms.find(t);
if (it != runtime_syms.end())
return it->second;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
string err = "Can't find symbol: " + t;
MessageBox(0, err.c_str(), 0, 0);
2014-01-31 08:23:00 +13:00
ExitProcess(0);
return 0;
}
2019-01-18 17:04:17 +01:00
static void link()
{
while (const char* sc = runtime->nextSym()) {
2014-01-31 08:23:00 +13:00
string t(sc);
2019-01-18 17:04:17 +01:00
if (t[0] == '_') {
runtime_syms["_" + t] = runtime->symValue(sc);
2014-01-31 08:23:00 +13:00
continue;
}
2019-01-18 17:04:17 +01:00
if (t[0] == '!')
t = t.substr(1);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
if (!isalnum(t[0]))
t = t.substr(1);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
for (int k = 0; k < t.size(); ++k) {
if (isalnum(t[k]) || t[k] == '_')
continue;
t = t.substr(0, k);
break;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
runtime_syms["_f" + tolower(t)] = runtime->symValue(sc);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
HRSRC hres = FindResource(0, MAKEINTRESOURCE(1111), RT_RCDATA);
if (!hres)
fail();
HGLOBAL hglo = LoadResource(0, hres);
if (!hglo)
fail();
void* p = LockResource(hglo);
if (!p)
fail();
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
int sz = *(int*)p;
p = (int*)p + 1;
2014-01-31 08:23:00 +13:00
//replace malloc for service pack 2 Data Execution Prevention (DEP).
2019-01-18 17:04:17 +01:00
module_pc = VirtualAlloc(0, sz, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
memcpy(module_pc, p, sz);
p = (char*)p + sz;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
int k, cnt;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
cnt = *(int*)p;
p = (int*)p + 1;
for (k = 0; k < cnt; ++k) {
Sym sym = getSym(&p);
if (sym.value < (int)module_pc || sym.value >= (int)module_pc + sz)
fail();
module_syms[sym.name] = sym.value;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
cnt = *(int*)p;
p = (int*)p + 1;
for (k = 0; k < cnt; ++k) {
Sym sym = getSym(&p);
int* pp = (int*)sym.value;
int dest = findSym(sym.name);
*pp += dest - (int)pp;
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
cnt = *(int*)p;
p = (int*)p + 1;
for (k = 0; k < cnt; ++k) {
Sym sym = getSym(&p);
int* pp = (int*)sym.value;
int dest = findSym(sym.name);
*pp += dest;
2014-01-31 08:23:00 +13:00
}
runtime_syms.clear();
module_syms.clear();
}
extern "C" _declspec(dllexport) int _stdcall bbWinMain();
2019-01-18 17:04:17 +01:00
extern "C" BOOL _stdcall _DllMainCRTStartup(HANDLE, DWORD, LPVOID);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
bool WINAPI DllMain(HANDLE module, DWORD reason, void* reserved)
{
2014-01-31 08:23:00 +13:00
return TRUE;
}
2019-01-18 17:04:17 +01:00
int __stdcall bbWinMain()
{
HINSTANCE inst = GetModuleHandle(0);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:17 +01:00
_DllMainCRTStartup(inst, DLL_PROCESS_ATTACH, 0);
2014-01-31 08:23:00 +13:00
#ifdef BETA
2019-01-18 17:04:17 +01:00
int ver = VERSION & 0x7fff;
string t = "Created with Blitz3D Beta V" + itoa(ver / 100) + "." + itoa(ver % 100);
MessageBox(GetDesktopWindow(), t.c_str(), "Blitz3D Message", MB_OK);
2014-01-31 08:23:00 +13:00
#endif
#ifdef SCHOOLS
2019-01-18 17:04:17 +01:00
MessageBox(GetDesktopWindow(), "Created with the schools version of Blitz Basic", "Blitz Basic Message", MB_OK);
2014-01-31 08:23:00 +13:00
#endif
2019-01-18 17:04:17 +01:00
runtime = runtimeGetRuntime();
runtime->startup(inst);
2014-01-31 08:23:00 +13:00
link();
//get cmd_line and params
2019-01-18 17:04:17 +01:00
string cmd = GetCommandLine(), params;
while (cmd.size() && cmd[0] == ' ')
cmd = cmd.substr(1);
if (cmd.find('\"') == 0) {
int n = cmd.find('\"', 1);
if (n != string::npos) {
params = cmd.substr(n + 1);
cmd = cmd.substr(1, n - 1);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:17 +01:00
} else {
int n = cmd.find(' ');
if (n != string::npos) {
params = cmd.substr(n + 1);
cmd = cmd.substr(0, n);
2014-01-31 08:23:00 +13:00
}
}
2019-01-18 17:04:17 +01:00
runtime->execute((void (*)())module_pc, params.c_str(), 0);
2014-01-31 08:23:00 +13:00
runtime->shutdown();
2019-01-18 17:04:17 +01:00
_DllMainCRTStartup(inst, DLL_PROCESS_DETACH, 0);
2014-01-31 08:23:00 +13:00
ExitProcess(0);
return 0;
}