bbruntime_dll.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #pragma warning( disable:4786 )
  2. #include "bbruntime_dll.h"
  3. #include "../debugger/debugger.h"
  4. #ifdef PRODEMO
  5. #include "../shareprot/shareprot.h"
  6. #endif
  7. using namespace std;
  8. #include <map>
  9. #include <eh.h>
  10. #include <float.h>
  11. #include "../bbruntime/bbruntime.h"
  12. class DummyDebugger : public Debugger{
  13. public:
  14. virtual void debugRun(){}
  15. virtual void debugStop(){}// bbruntime_panic(0); }
  16. virtual void debugStmt( int srcpos,const char *file ){}
  17. virtual void debugEnter( void *frame,void *env,const char *func ){}
  18. virtual void debugLeave(){}
  19. virtual void debugLog( const char *msg ){}
  20. virtual void debugMsg( const char *e,bool serious ){
  21. if( serious ) MessageBox( 0,e,"Error!",MB_OK|MB_TOPMOST|MB_SETFOREGROUND );
  22. }
  23. virtual void debugSys( void *msg ){}
  24. };
  25. static HINSTANCE hinst;
  26. static map<const char*,void*> syms;
  27. map<const char*,void*>::iterator sym_it;
  28. static gxRuntime *gx_runtime;
  29. static void rtSym( const char *sym,void *pc ){
  30. syms[sym]=pc;
  31. }
  32. #ifdef PRODEMO
  33. static void killer(){
  34. ExitProcess( -1 );
  35. }
  36. #endif
  37. static void _cdecl seTranslator( unsigned int u,EXCEPTION_POINTERS* pExp ){
  38. switch( u ){
  39. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  40. bbruntime_panic( "Integer divide by zero" );
  41. case EXCEPTION_ACCESS_VIOLATION:
  42. bbruntime_panic( "Memory access violation" );
  43. case EXCEPTION_ILLEGAL_INSTRUCTION:
  44. bbruntime_panic( "Illegal instruction" );
  45. case EXCEPTION_STACK_OVERFLOW:
  46. bbruntime_panic( "Stack overflow!" );
  47. }
  48. bbruntime_panic( "Unknown runtime exception" );
  49. }
  50. int Runtime::version(){
  51. return VERSION;
  52. }
  53. const char *Runtime::nextSym(){
  54. if( !syms.size() ){
  55. bbruntime_link( rtSym );
  56. sym_it=syms.begin();
  57. }
  58. if( sym_it==syms.end() ){
  59. syms.clear();return 0;
  60. }
  61. return (sym_it++)->first;
  62. }
  63. int Runtime::symValue( const char *sym ){
  64. map<const char*,void*>::iterator it=syms.find( sym );
  65. if( it!=syms.end() ) return (int)it->second;
  66. return -1;
  67. }
  68. void Runtime::startup( HINSTANCE h ){
  69. hinst=h;
  70. }
  71. void Runtime::shutdown(){
  72. trackmem( false );
  73. syms.clear();
  74. }
  75. void Runtime::execute( void (*pc)(),const char *args,Debugger *dbg ){
  76. bool debug=!!dbg;
  77. static DummyDebugger dummydebug;
  78. if( !dbg ) dbg=&dummydebug;
  79. trackmem( true );
  80. _se_translator_function old_trans=_set_se_translator( seTranslator );
  81. _control87( _RC_NEAR|_PC_24|_EM_INVALID|_EM_ZERODIVIDE|_EM_OVERFLOW|_EM_UNDERFLOW|_EM_INEXACT|_EM_DENORMAL,0xfffff );
  82. //strip spaces from ends of args...
  83. string params=args;
  84. while( params.size() && params[0]==' ' ) params=params.substr( 1 );
  85. while( params.size() && params[params.size()-1]==' ' ) params=params.substr( 0,params.size()-1 );
  86. if( gx_runtime=gxRuntime::openRuntime( hinst,params,dbg ) ){
  87. #ifdef PRODEMO
  88. shareProtCheck( killer );
  89. #endif
  90. bbruntime_run( gx_runtime,pc,debug );
  91. gxRuntime *t=gx_runtime;
  92. gx_runtime=0;
  93. gxRuntime::closeRuntime( t );
  94. }
  95. _control87( _CW_DEFAULT,0xfffff );
  96. _set_se_translator( old_trans );
  97. }
  98. void Runtime::asyncStop(){
  99. if( gx_runtime ) gx_runtime->asyncStop();
  100. }
  101. void Runtime::asyncRun(){
  102. if( gx_runtime ) gx_runtime->asyncRun();
  103. }
  104. void Runtime::asyncEnd(){
  105. if( gx_runtime ) gx_runtime->asyncEnd();
  106. }
  107. void Runtime::checkmem( streambuf *buf ){
  108. ostream out( buf );
  109. ::checkmem( out );
  110. }
  111. Runtime *_cdecl runtimeGetRuntime(){
  112. static Runtime runtime;
  113. return &runtime;
  114. }
  115. /********************** BUTT UGLY DLL->EXE HOOK! *************************/
  116. static void *module_pc;
  117. static map<string,int> module_syms;
  118. static map<string,int> runtime_syms;
  119. static Runtime *runtime;
  120. static void fail(){
  121. MessageBox( 0,"Unable to run Blitz Basic module",0,0 );
  122. ExitProcess(-1);
  123. }
  124. struct Sym{
  125. string name;
  126. int value;
  127. };
  128. static Sym getSym( void **p ){
  129. Sym sym;
  130. char *t=(char*)*p;
  131. while( char c=*t++ ) sym.name+=c;
  132. sym.value=*(int*)t+(int)module_pc;
  133. *p=t+4;return sym;
  134. }
  135. static int findSym( const string &t ){
  136. map<string,int>::iterator it;
  137. it=module_syms.find( t );
  138. if( it!=module_syms.end() ) return it->second;
  139. it=runtime_syms.find( t );
  140. if( it!=runtime_syms.end() ) return it->second;
  141. string err="Can't find symbol: "+t;
  142. MessageBox( 0,err.c_str(),0,0 );
  143. ExitProcess(0);
  144. return 0;
  145. }
  146. static void link(){
  147. while( const char *sc=runtime->nextSym() ){
  148. string t(sc);
  149. if( t[0]=='_' ){
  150. runtime_syms["_"+t]=runtime->symValue(sc);
  151. continue;
  152. }
  153. if( t[0]=='!' ) t=t.substr(1);
  154. if( !isalnum(t[0]) ) t=t.substr(1);
  155. for( int k=0;k<t.size();++k ){
  156. if( isalnum(t[k]) || t[k]=='_' ) continue;
  157. t=t.substr( 0,k );break;
  158. }
  159. runtime_syms["_f"+tolower(t)]=runtime->symValue(sc);
  160. }
  161. HRSRC hres=FindResource( 0,MAKEINTRESOURCE(1111),RT_RCDATA );if( !hres ) fail();
  162. HGLOBAL hglo=LoadResource( 0,hres );if( !hglo ) fail();
  163. void *p=LockResource( hglo );if( !p ) fail();
  164. int sz=*(int*)p;p=(int*)p+1;
  165. //replace malloc for service pack 2 Data Execution Prevention (DEP).
  166. module_pc=VirtualAlloc( 0,sz,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE );
  167. memcpy( module_pc,p,sz );
  168. p=(char*)p+sz;
  169. int k,cnt;
  170. cnt=*(int*)p;p=(int*)p+1;
  171. for( k=0;k<cnt;++k ){
  172. Sym sym=getSym( &p );
  173. if( sym.value<(int)module_pc || sym.value>=(int)module_pc+sz ) fail();
  174. module_syms[sym.name]=sym.value;
  175. }
  176. cnt=*(int*)p;p=(int*)p+1;
  177. for( k=0;k<cnt;++k ){
  178. Sym sym=getSym( &p );
  179. int *pp=(int*)sym.value;
  180. int dest=findSym( sym.name );
  181. *pp+=dest-(int)pp;
  182. }
  183. cnt=*(int*)p;p=(int*)p+1;
  184. for( k=0;k<cnt;++k ){
  185. Sym sym=getSym( &p );
  186. int *pp=(int*)sym.value;
  187. int dest=findSym( sym.name );
  188. *pp+=dest;
  189. }
  190. runtime_syms.clear();
  191. module_syms.clear();
  192. }
  193. extern "C" _declspec(dllexport) int _stdcall bbWinMain();
  194. extern "C" BOOL _stdcall _DllMainCRTStartup( HANDLE,DWORD,LPVOID );
  195. bool WINAPI DllMain( HANDLE module,DWORD reason,void *reserved ){
  196. return TRUE;
  197. }
  198. int __stdcall bbWinMain(){
  199. HINSTANCE inst=GetModuleHandle( 0 );
  200. _DllMainCRTStartup( inst,DLL_PROCESS_ATTACH,0 );
  201. #ifdef BETA
  202. int ver=VERSION & 0x7fff;
  203. string t="Created with Blitz3D Beta V"+itoa( ver/100 )+"."+itoa( ver%100 );
  204. MessageBox( GetDesktopWindow(),t.c_str(),"Blitz3D Message",MB_OK );
  205. #endif
  206. #ifdef SCHOOLS
  207. MessageBox( GetDesktopWindow(),"Created with the schools version of Blitz Basic","Blitz Basic Message",MB_OK );
  208. #endif
  209. runtime=runtimeGetRuntime();
  210. runtime->startup( inst );
  211. link();
  212. //get cmd_line and params
  213. string cmd=GetCommandLine(),params;
  214. while( cmd.size() && cmd[0]==' ' ) cmd=cmd.substr( 1 );
  215. if( cmd.find( '\"' )==0 ){
  216. int n=cmd.find( '\"',1 );
  217. if( n!=string::npos ){
  218. params=cmd.substr( n+1 );
  219. cmd=cmd.substr( 1,n-1 );
  220. }
  221. }else{
  222. int n=cmd.find( ' ' );
  223. if( n!=string::npos ){
  224. params=cmd.substr( n+1 );
  225. cmd=cmd.substr( 0,n );
  226. }
  227. }
  228. runtime->execute( (void(*)())module_pc,params.c_str(),0 );
  229. runtime->shutdown();
  230. _DllMainCRTStartup( inst,DLL_PROCESS_DETACH,0 );
  231. ExitProcess(0);
  232. return 0;
  233. }