1
0

vcpu.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069
  1. #include <precomp.h>
  2. #include <wasabicfg.h>
  3. #include <api/skin/widgets/mb/scriptbrowser.h>
  4. #include <api/script/scriptmgr.h>
  5. #include <api/script/script.h>
  6. #include "vcpu.h"
  7. #include "opcodes.h"
  8. #include <api/wndmgr/container.h>
  9. #include <api/wndmgr/msgbox.h>
  10. #include <api/script/objecttable.h>
  11. #include <api/syscb/callbacks/consolecb.h>
  12. #include "../nu/AutoWide.h"
  13. ScriptObjectManager *VCPU::scriptManager = NULL;
  14. void VCPU::shutdown()
  15. {
  16. foreach(globalDlfList)
  17. FREE(globalDlfList.getfor()->functionName);
  18. delete globalDlfList.getfor();
  19. endfor
  20. globalDlfList.removeAll();
  21. atoms.deleteAll();
  22. }
  23. // -------------------------------------------------------------
  24. void VCPU::push(VCPUscriptVar v) {
  25. CpuStack.push(v);
  26. VSP++;
  27. }
  28. // -------------------------------------------------------------
  29. void VCPU::push(scriptVar v) {
  30. VCPUscriptVar _v;
  31. _v.v = v;
  32. CpuStack.push(_v);
  33. VSP++;
  34. }
  35. void VCPU::RemoveOldScripts()
  36. {
  37. while (scriptsToRemove.getNumItems())
  38. {
  39. int id = scriptsToRemove.getFirst();
  40. VCPU::removeScript(id);
  41. scriptsToRemove.delByPos(0);
  42. }
  43. }
  44. // -------------------------------------------------------------
  45. VCPUscriptVar VCPU::pop() {
  46. if (VSP <= 0) {
  47. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_POPEMPTYSTACK);
  48. VCPUscriptVar v;
  49. MEMSET(&v, 0, sizeof(v));
  50. return v;
  51. // ASSERT(0);
  52. }
  53. VCPUscriptVar v;
  54. CpuStack.pop(&v);
  55. VSP--;
  56. if (VSP == 0)
  57. VCPU::RemoveOldScripts(); // benski> TODO: dunno if this is the best place for this
  58. return v;
  59. }
  60. // -------------------------------------------------------------
  61. VCPUscriptVar VCPU::peekAt(int n) {
  62. if (VSP <= n) {
  63. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_INVALIDPEEKSTACK);
  64. VCPUscriptVar v;
  65. MEMSET(&v, 0, sizeof(v));
  66. return v;
  67. // ASSERT(0);
  68. }
  69. VCPUscriptVar v={0,{0},0};
  70. CpuStack.peekAt(&v, n);
  71. return v;
  72. }
  73. // -------------------------------------------------------------
  74. int VCPU::assignNewScriptId() {
  75. return numScripts++;
  76. }
  77. // -------------------------------------------------------------
  78. int VCPU::oldClassToClassId(int id) {
  79. if (id < SCRIPT_OBJECT) return id;
  80. if (id >= 0x10000) return id;
  81. switch (id) {
  82. case 7 : return ObjectTable::getClassFromName(L"Object");
  83. case 8 : return ObjectTable::getClassFromName(L"SystemObject");
  84. case 9 : return ObjectTable::getClassFromName(L"Container");
  85. case 10: return ObjectTable::getClassFromName(L"Layout");
  86. case 11: return ObjectTable::getClassFromName(L"Button");
  87. case 12: return ObjectTable::getClassFromName(L"Slider");
  88. case 13: return ObjectTable::getClassFromName(L"Text");
  89. case 14: return ObjectTable::getClassFromName(L"Image");
  90. case 15: return ObjectTable::getClassFromName(L"Anim");
  91. case 16: return ObjectTable::getClassFromName(L"Vis");
  92. case 17: return ObjectTable::getClassFromName(L"Component");
  93. case 18: return ObjectTable::getClassFromName(L"ToggleButton");
  94. case 19: return ObjectTable::getClassFromName(L"Timer");
  95. case 20: return ObjectTable::getClassFromName(L"Layer");
  96. case 21: return ObjectTable::getClassFromName(L"GuiObject");
  97. case 22: return ObjectTable::getClassFromName(L"AnimatedLayer");
  98. case 23: return ObjectTable::getClassFromName(L"Browser");
  99. case 24: return ObjectTable::getClassFromName(L"Edit");
  100. case 25: return ObjectTable::getClassFromName(L"Map");
  101. case 26: return ObjectTable::getClassFromName(L"Popup");
  102. case 27: return ObjectTable::getClassFromName(L"Title");
  103. case 28: return ObjectTable::getClassFromName(L"ComponentBucket");
  104. case 29: return ObjectTable::getClassFromName(L"Status");
  105. case 30: return ObjectTable::getClassFromName(L"Region");
  106. case 31: return ObjectTable::getClassFromName(L"Wac");
  107. case 32: return ObjectTable::getClassFromName(L"List");
  108. case 33: return ObjectTable::getClassFromName(L"SBitList");
  109. case 34: return ObjectTable::getClassFromName(L"SEqVis");
  110. default: Script::guruMeditation(NULL, GURU_INVALIDOLDID, L"xlat error", id);
  111. break;
  112. }
  113. return SCRIPT_INT; // heh =)
  114. }
  115. // -------------------------------------------------------------
  116. int VCPU::addScript(void *mem, int memsize, int id) {
  117. int i,j;
  118. int translateobjects = 0;
  119. char *p = (char *)mem;
  120. int hdr=0;
  121. if (!MEMCMP(p, "FG\x03\x04\x14\00\00\00\00", 8))
  122. hdr=1;
  123. else if (!MEMCMP(p, "FG\x03\x04\x15\00\00\00\00", 8))
  124. hdr=2;
  125. else if (!MEMCMP(p, "FG\x03\x04\x16\00\00\00\00", 8))
  126. hdr=3;
  127. else if (!MEMCMP(p, "FG\x03\x04\x17\00\00\00\00", 8))
  128. hdr=4;
  129. else if (!MEMCMP(p, "FG\x03\x04", 4)) {
  130. if (*(p+4) > 0x17)
  131. hdr = -1;
  132. }
  133. switch (hdr) {
  134. case -1:
  135. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_FUTUREFORMAT, L"NEED LATEST VERSION");
  136. return -1;
  137. case 0:
  138. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_INVALIDHEADER);
  139. return -1;
  140. case 1:
  141. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_OLDFORMAT, L"DEPRECATED BINARY");
  142. return -1;
  143. case 2:
  144. translateobjects=1;
  145. break;
  146. case 3:
  147. case 4:
  148. break;
  149. }
  150. SOM::getSystemObjectByScriptId(id)->setIsOldFormat(translateobjects);
  151. p+=8;
  152. TList<int> *typetable = SOM::getSystemObjectByScriptId(id)->getTypesList();
  153. typetable->removeAll();
  154. if (!translateobjects) {
  155. int nGuids = *(int *)p;
  156. p+=sizeof(int);
  157. for (int z=0;z<nGuids;z++) {
  158. GUID g;
  159. MEMCPY(&g, p, sizeof(GUID));
  160. p+=sizeof(GUID);
  161. char zz[256] = {0};
  162. nsGUID::toChar(g, zz);
  163. int t = ObjectTable::getClassFromGuid(g);
  164. if (t == -1) {
  165. DebugStringW(L"maki class entry %d not found : %s\n", z, zz);
  166. // __asm int 3;
  167. }
  168. typetable->addItem(t);
  169. }
  170. }
  171. // -------------------------------------------------------------
  172. // Load DLF Table
  173. int DLFEntryBase = DLFentryTable.getNumItems();
  174. int nDLFentries = *(int *)p;
  175. p+=sizeof(int);
  176. for (i=0;i<nDLFentries;i++) {
  177. int basetype = *(int *)p;
  178. int pt = basetype;
  179. int type = basetype;
  180. p+=sizeof(int);
  181. if (translateobjects) {
  182. basetype = oldClassToClassId(basetype);
  183. } else
  184. if (basetype >= CLASS_ID_BASE && basetype < 0x10000)
  185. basetype = typetable->enumItem(basetype - CLASS_ID_BASE);
  186. if (basetype == -1) {
  187. //CUT!!!! so annoying Std::messageBox("Error while loading a script, a component is missing", "Oops", 0);
  188. DebugStringW(L"Tried to link DLF %d (class entry %d) but the class isn't here\n", i, pt - CLASS_ID_BASE);
  189. //return -1;
  190. }
  191. type = basetype;
  192. uint16_t stringLen = *(uint16_t *)p;
  193. p+=sizeof(uint16_t);
  194. char functionName[65536+1] = {0};
  195. MEMCPY(functionName, p, stringLen);
  196. functionName[stringLen]=0;
  197. p+=stringLen;
  198. // check if entry seems valid
  199. if (!*functionName) {
  200. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_INVALIDFUNCINDLF);
  201. // api->messageBox("Invalid function name in DLF table", "Script Error", MSGBOX_OK, NULL, NULL);
  202. return -1;
  203. }
  204. // ok, register this function
  205. VCPUdlfEntry *e = new VCPUdlfEntry;
  206. e->basetype = type;
  207. #ifdef _WIN32
  208. int size = MultiByteToWideChar(CP_UTF8, 0, functionName, -1, 0,0);
  209. if (size)
  210. {
  211. wchar_t *wide = (wchar_t *)MALLOC(size*sizeof(wchar_t));
  212. MultiByteToWideChar(CP_UTF8, 0, functionName, -1, wide,size);
  213. e->functionName = wide;
  214. }
  215. else
  216. e->functionName = 0;
  217. #else
  218. e->functionName = WCSDUP(AutoWide(functionName));
  219. #warning port me
  220. #endif
  221. e->scriptId = id;
  222. // insert safe values
  223. e->nparams = -1;
  224. e->DLFid = -1;
  225. e->ptr = NULL;
  226. DLFentryTable.addItem(e);
  227. setupDLF(e, DLFEntryBase);
  228. }
  229. // -------------------------------------------------------------
  230. // Load VAR Table
  231. int variableBase = variablesTable.getNumItems();
  232. int nVariables = *(int *)p;
  233. p+=sizeof(int);
  234. for (i=0;i<nVariables;i++) {
  235. scriptVar e;
  236. MEMCPY(&e, p, sizeof(scriptVar));
  237. p+=sizeof(scriptVar);
  238. VCPUscriptVar *v = new VCPUscriptVar;
  239. v->isaclass = 0;
  240. if (e.type >= 0x10000) {
  241. int type = e.type;
  242. int id;
  243. do {
  244. id = type - 0x10000;
  245. VCPUscriptVar *v = variablesTable.enumItem(id+variableBase);
  246. v->isaclass = 1;
  247. type = v->v.type;
  248. } while (type >= 0x10000);
  249. }
  250. if (translateobjects) {
  251. e.type = oldClassToClassId(e.type);
  252. } else
  253. if (e.type >= CLASS_ID_BASE && e.type < 0x10000)
  254. e.type = typetable->enumItem(e.type - CLASS_ID_BASE);
  255. v->scriptId = id;
  256. v->varId = i;
  257. v->transcient = (*p++ == 0);
  258. if (hdr >= 4)
  259. v->isstatic = *p++;
  260. else
  261. v->isstatic = 0;
  262. if (hdr < 4) {
  263. // Autoassign system variables
  264. if (e.type == ObjectTable::getClassFromName(L"SystemObject")) {
  265. SystemObject *so = SOM::getSystemObjectByScriptId(id);
  266. if (so) e.data.odata = so->getScriptObject(); else e.data.odata = NULL;
  267. }
  268. } else {
  269. if (v->isstatic && e.type == ObjectTable::getClassFromName(L"SystemObject")) {
  270. SystemObject *so = SOM::getSystemObjectByScriptId(id);
  271. if (so) e.data.odata = so->getScriptObject(); else e.data.odata = NULL;
  272. v->isstatic = 0; // disable deletion
  273. } else if (v->isstatic) {
  274. // Autoassign class variables
  275. e.data.odata = ObjectTable::instantiate(e.type);
  276. if (e.data.odata)
  277. e.data.odata->vcpu_setScriptId(VSD);
  278. }
  279. }
  280. if (e.type == SCRIPT_STRING)
  281. {
  282. wchar_t *emptyString = WMALLOC(1);
  283. emptyString[0]=0;
  284. e.data.sdata = emptyString;
  285. }
  286. if (e.type == SCRIPT_DOUBLE)
  287. e.data.ddata = e.data.fdata;
  288. v->v = e;
  289. variablesTable.addItem(v);
  290. }
  291. // -------------------------------------------------------------
  292. // Load Strings into string vars
  293. int nStrings = *(int *)p;
  294. p+=sizeof(int);
  295. j=0;
  296. //CUT: int count=0;
  297. char string_buf[65536+1] = {0};
  298. for (i=0;i<nStrings;i++)
  299. {
  300. int attach_id = *(int *)p;
  301. p+=4;
  302. uint16_t stringLen = *(uint16_t *)p;
  303. p+=2;
  304. //char *string;
  305. //string = (char *)MALLOC(stringLen+1);
  306. MEMCPY(string_buf, p, stringLen);
  307. string_buf[stringLen]=0;
  308. p+=stringLen;
  309. // find next variable in this script that needs a string attached, and attach it
  310. VCPUscriptVar *v = variablesTable.enumItem(attach_id+variableBase);
  311. if (!v)
  312. {
  313. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_EXCEPTION, L"Invalid String ID");
  314. return -1;
  315. }
  316. FREE((wchar_t *)(v->v.data.sdata));
  317. // strings are stored in UTF-8, but we're using UTF-16 here
  318. #ifdef _WIN32
  319. int size = MultiByteToWideChar(CP_UTF8, 0, string_buf, -1, 0,0);
  320. if (size)
  321. {
  322. wchar_t *wide = (wchar_t *)MALLOC(size*sizeof(wchar_t));
  323. MultiByteToWideChar(CP_UTF8, 0, string_buf, -1, wide,size);
  324. v->v.data.sdata = wide;
  325. }
  326. else
  327. v->v.data.sdata = 0;
  328. #else
  329. #warning port me
  330. // TODO: benski> change to do one malloc
  331. v->v.data.sdata = WCSDUP(AutoWide(string_buf));
  332. #endif
  333. //FREE(string);
  334. }
  335. // -------------------------------------------------------------
  336. // Load Events into table
  337. int nEvents = *(int *)p;
  338. p+=sizeof(int);
  339. for (i=0;i<nEvents;i++) {
  340. int varId = *(int *)p;
  341. p+=sizeof(int);
  342. int DLFentry = *(int *)p;
  343. p+=sizeof(int);
  344. int pointer = *(int *)p;
  345. p+=sizeof(int);
  346. // check if this event seems valid
  347. if (DLFentry >= nDLFentries || DLFentry < 0) {
  348. // api->messageBox("Invalid event DLF descriptor", "Script Error", MSGBOX_OK, NULL, NULL);
  349. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_INVALIDEVENTDLF);
  350. return -1;
  351. }
  352. if (pointer < 0) {
  353. // api->messageBox("Invalid event address", "Script Error", MSGBOX_OK, NULL, NULL);
  354. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_INVALIDEVENTADDR);
  355. return -1;
  356. }
  357. if (varId < 0 || varId >= nVariables) {
  358. // api->messageBox("Invalid event variable", "Script Error", MSGBOX_OK, NULL, NULL);
  359. Script::guruMeditation(SOM::getSystemObjectByScriptId(id), GURU_INVALIDEVENTVAR);
  360. return -1;
  361. }
  362. // insert event into table
  363. VCPUeventEntry *e = new VCPUeventEntry;
  364. //e->DLFentry = DLFentry + DLFEntryBase;
  365. e->DLFid = DLFentryTable.enumItem(DLFEntryBase+DLFentry)->DLFid;
  366. e->pointer = pointer;
  367. e->scriptId = id;
  368. e->varId = varId;
  369. eventsTable.addItem(e);
  370. }
  371. // -------------------------------------------------------------
  372. // Load Code block into code table
  373. int codeSize = *(int *)p;
  374. p+=sizeof(int);
  375. VCPUcodeBlock *c = new VCPUcodeBlock;
  376. c->codeBlock = p;
  377. c->dlfBase = DLFEntryBase;
  378. c->varBase = variableBase;
  379. c->scriptId = id;
  380. c->size = codeSize;
  381. codeTable.addItem(c);
  382. SystemObject *so = SOM::getSystemObjectByScriptId(id);
  383. if (so) {
  384. ScriptObject *sso = so->getScriptObject();
  385. if (sso)
  386. sso->vcpu_addAssignedVariable(0, id);
  387. }
  388. cacheCount++;
  389. c->debugsymbols = c->codeBlock+codeSize;
  390. c->debugsize = memsize - (c->debugsymbols-(char *)mem);
  391. //WASABI_API_MAKIDEBUG->debugger_createJITD(id); // fucko !!
  392. return id;
  393. }
  394. // -------------------------------------------------------------
  395. int VCPU::varBase(int scriptId) {
  396. static int lasti=-1;;
  397. static int lastb=0;
  398. static int lastid=0;
  399. if (lastid == scriptId && lasti>=0 && lasti < codeTable.getNumItems()) {
  400. if (lastid == codeTable.enumItem(lasti)->scriptId)
  401. return lastb;
  402. }
  403. for (int i=0;i<codeTable.getNumItems();i++ ){
  404. if (codeTable.enumItem(i)->scriptId == scriptId) {
  405. lasti = i;
  406. lastid = scriptId;
  407. lastb = codeTable.enumItem(i)->varBase;
  408. return lastb;
  409. }
  410. }
  411. Script::guruMeditation(SOM::getSystemObjectByScriptId(scriptId), GURU_INVALIDSCRIPTID);
  412. ASSERT(0);
  413. return 0;
  414. }
  415. // -------------------------------------------------------------
  416. int VCPU::nVars(int scriptId) {
  417. for (int i=0;i<codeTable.getNumItems();i++ ){
  418. if (codeTable.enumItem(i)->scriptId == scriptId) {
  419. if (codeTable.getNumItems() == i+1)
  420. return variablesTable.getNumItems() - codeTable.enumItem(i)->varBase;
  421. return codeTable.enumItem(i+1)->varBase - codeTable.enumItem(i)->varBase;
  422. }
  423. }
  424. Script::guruMeditation(SOM::getSystemObjectByScriptId(scriptId), GURU_INVALIDSCRIPTID);
  425. ASSERT(0);
  426. return 0;
  427. }
  428. // -------------------------------------------------------------
  429. int VCPU::dlfBase(int scriptId) {
  430. for (int i=0;i<codeTable.getNumItems();i++ ){
  431. if (codeTable.enumItem(i)->scriptId == scriptId)
  432. return codeTable.enumItem(i)->dlfBase;
  433. }
  434. Script::guruMeditation(SOM::getSystemObjectByScriptId(scriptId), GURU_INVALIDSCRIPTID);
  435. ASSERT(0);
  436. return 0;
  437. }
  438. // -------------------------------------------------------------
  439. void VCPU::removeScript(int id)
  440. {
  441. // ASSERTPR(VCPU::VSP==0, "Can't unload script while in script");
  442. if (VCPU::VSP != 0)
  443. {
  444. scriptsToRemove.addItem(id);
  445. return;
  446. }
  447. SystemObject *s = SOM::getSystemObjectByScriptId(id);
  448. if (s)
  449. {
  450. s->onUnload();
  451. delete s;
  452. }
  453. PtrList<ScriptObject> *l = SystemObject::getAllScriptObjects();
  454. int i;
  455. for (i=0;i<l->getNumItems();i++) {
  456. ScriptObject *o = l->enumItem(i);
  457. o->vcpu_delMembers(id);
  458. }
  459. int dlfdeleted=0;
  460. int vardeleted=0;
  461. for (i=0;i<DLFentryTable.getNumItems();i++) {
  462. if (DLFentryTable.enumItem(i)->scriptId == id) {
  463. delrefDLF(DLFentryTable.enumItem(i));
  464. if (DLFentryTable.enumItem(i)->functionName)
  465. FREE(DLFentryTable.enumItem(i)->functionName);
  466. delete DLFentryTable.enumItem(i);
  467. DLFentryTable.delByPos(i);
  468. dlfdeleted++;
  469. i--;
  470. }
  471. }
  472. for (i=0;i<eventsTable.getNumItems();i++) {
  473. if (eventsTable.enumItem(i)->scriptId == id) {
  474. delete eventsTable.enumItem(i);
  475. eventsTable.delByPos(i);
  476. i--;
  477. }
  478. }
  479. for (i=0;i<variablesTable.getNumItems();i++) {
  480. if (variablesTable.enumItem(i)->scriptId == id) {
  481. VCPUscriptVar *v = variablesTable.enumItem(i);
  482. if (v->isstatic && v->v.type) {
  483. ObjectTable::destroy(v->v.data.odata);
  484. }
  485. if (v->v.type == SCRIPT_STRING)
  486. if (v->v.data.sdata)
  487. FREE((wchar_t *)v->v.data.sdata);
  488. delete v;
  489. variablesTable.delByPos(i);
  490. vardeleted++;
  491. i--;
  492. }
  493. }
  494. for (i=0;i<codeTable.getNumItems();i++) {
  495. if (codeTable.enumItem(i)->scriptId == id) {
  496. VCPUcodeBlock *b = codeTable.enumItem(i);
  497. delete b;
  498. codeTable.removeByPos(i);
  499. for (;i<codeTable.getNumItems();i++) {
  500. codeTable.enumItem(i)->dlfBase-=dlfdeleted;
  501. codeTable.enumItem(i)->varBase-=vardeleted;
  502. }
  503. }
  504. }
  505. cacheCount++;
  506. }
  507. // -------------------------------------------------------------
  508. // Find next matching object, starting from start
  509. int VCPU::findObject(ScriptObject *o, int start, int dlfid, int vcpuid) {
  510. /* int stop;
  511. if (vcpuid != -1) {
  512. int b = varBase(vcpuid);
  513. if (start < b)
  514. start = b;
  515. stop = b + nVars(vcpuid);
  516. } else {
  517. stop = variablesTable.getNumItems();
  518. if (start < 0)
  519. start = 0;
  520. }*/
  521. /* while (start < stop) {
  522. VCPUscriptVar *v = variablesTable.enumItem(start);
  523. if (v->v.data.odata == o && !v->transcient && (vcpuid == -1 || v->scriptId == vcpuid))
  524. return start;
  525. start++;
  526. }*/
  527. return -1;
  528. }
  529. // -------------------------------------------------------------
  530. // Assign DLF functionId to class exported functions, starting from the last non initialized DLF
  531. void VCPU::setupDLF(VCPUdlfEntry *e, int dlfEntryBase) {
  532. if (ObjectTable::addrefDLF(e, highestDLFId)) {
  533. newDlf();
  534. }
  535. }
  536. int VCPU::newDlf() {
  537. return highestDLFId++;
  538. }
  539. void VCPU::resetDlf() {
  540. highestDLFId = 0;
  541. }
  542. void VCPU::registerGlobalDlf(VCPUdlfEntry *e, int dlf) {
  543. ASSERT(dlf == globalDlfList.getNumItems());
  544. VCPUdlfEntry *_e = new VCPUdlfEntry;
  545. MEMCPY(_e, e, sizeof(VCPUdlfEntry));
  546. _e->functionName = WCSDUP(e->functionName);
  547. globalDlfList.addItem(_e);
  548. }
  549. void VCPU::delrefDLF(VCPUdlfEntry *e) {
  550. ObjectTable::delrefDLF(e);
  551. }
  552. // -------------------------------------------------------------
  553. TList<VCPUscriptVar> VCPU::plist;
  554. // -------------------------------------------------------------
  555. int VCPU::runEvent(VCPUeventEntry *e, int np, int pbase) {
  556. #ifdef WASABI_COMPILE_MAKIDEBUG
  557. /*if (WASABI_API_MAKIDEBUG && WASABI_API_MAKIDEBUG->debugger_isActive()) {
  558. if (WASABI_API_MAKIDEBUG->debugger_filterEvent(e->scriptId, e->DLFid)) {
  559. DebugString("Skipping event\n");
  560. scriptVar v;
  561. v.type = SCRIPT_INT;
  562. v.data.idata = 0;
  563. VCPU::push(v);
  564. return 1;
  565. }
  566. }*/
  567. #endif
  568. for (int z=0;z<np;z++) {
  569. VCPU::push(plist[z+pbase]);
  570. }
  571. runCode(e->scriptId, e->pointer, np);
  572. #ifdef WASABI_COMPILE_MAKIDEBUG
  573. /* if (WASABI_API_MAKIDEBUG && WASABI_API_MAKIDEBUG->debugger_isActive())
  574. WASABI_API_MAKIDEBUG->debugger_eventComplete();*/
  575. #endif
  576. return 1;
  577. }
  578. // This is the function that actually executes the event. In the future, it will sequencially parse all loaded scripts in reversed load order and stop
  579. // either at the end of the chain OR as soon as one of the event used "complete;" in its code
  580. // -------------------------------------------------------------
  581. scriptVar VCPU::executeEvent(scriptVar v, int functionId, int np, int vcpuid) {
  582. VCPUscriptVar retvar={0,{0},0};
  583. int pbase = plist.getNumItems();
  584. int varId=0;
  585. complete = 0;
  586. for (int z=0;z<np;z++) {
  587. VCPUscriptVar vcpuv = VCPU::pop();
  588. plist.addItem(vcpuv);
  589. }
  590. // find all variables containing this object, and run their event if it's traped
  591. int next = 0;
  592. while (!complete) {
  593. VCPUscriptVar *vclass=NULL;
  594. int inheritedevent=0;
  595. // varId = VCPU::findObject(v.data.odata, varId, vcpuid);
  596. int event;
  597. ASSERT(v.data.odata != NULL);
  598. varId = ((ScriptObject *)v.data.odata)->vcpu_getAssignedVariable(next, vcpuid, functionId, &next, &event, &inheritedevent);
  599. if (varId < 0) break;
  600. VCPUscriptVar *vc = variablesTable.enumItem(varId);
  601. ScriptObject *thisobject = (ScriptObject *)v.data.odata;
  602. VCPUeventEntry *e = eventsTable.enumItem(event);
  603. int r_varId = varId;
  604. if (!vc->isaclass && !inheritedevent) {
  605. if (e && runEvent(e, np, pbase))
  606. retvar = pop();
  607. if (getComplete())
  608. break;
  609. }
  610. while (vc->isaclass) {
  611. ASSERT(r_varId < variablesTable.getNumItems());
  612. vclass = variablesTable.enumItem(r_varId);
  613. vclass->v.data.odata = thisobject;
  614. if (runEvent(e, np, pbase))
  615. retvar = pop();
  616. if (getComplete())
  617. break;
  618. vc = vclass;
  619. if (vc->varId < 0x10000) break;
  620. r_varId = varBase(vc->scriptId) + vc->v.type - 0x10000;
  621. }
  622. if (getComplete())
  623. break;
  624. varId++;
  625. }
  626. for (int i=0;i<np;i++)
  627. plist.delByPos(pbase);
  628. return retvar.v;
  629. }
  630. void VCPU::callDlfCommand(void *ptr, int nargs, maki_cmd *cmd) {
  631. try {
  632. scriptVar v={0,0};
  633. switch (nargs) {
  634. case 0:
  635. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *))ptr)(cmd, -1, NULL);
  636. break;
  637. case 1:
  638. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar))ptr)(cmd, -1, NULL, v);
  639. break;
  640. case 2:
  641. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v);
  642. break;
  643. case 3:
  644. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v);
  645. break;
  646. case 4:
  647. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v);
  648. break;
  649. case 5:
  650. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v);
  651. break;
  652. case 6:
  653. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v, v);
  654. break;
  655. case 7:
  656. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v, v, v);
  657. break;
  658. case 8:
  659. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v, v, v, v);
  660. break;
  661. case 9:
  662. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v, v, v, v, v);
  663. break;
  664. case 10:
  665. ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))ptr)(cmd, -1, NULL, v, v, v, v, v, v, v, v, v, v);
  666. break;
  667. }
  668. }
  669. catch(...)
  670. {
  671. Script::guruMeditation(SOM::getSystemObjectByScriptId(VCPU::VSD), GURU_EXCEPTION, L"Script Fatal Error", -1);
  672. #ifdef ON_FATAL_SKIN_ERROR
  673. ON_FATAL_SKIN_ERROR
  674. #endif
  675. }
  676. }
  677. int VCPU::getDLFFromPointer(void *ptr, int nargs) {
  678. maki_cmd cmd={MAKI_CMD_GETDLF, -1};
  679. callDlfCommand(ptr, nargs, &cmd);
  680. return cmd.id;
  681. }
  682. // This sends the DLFId to the function itself.
  683. void VCPU::setupDLFFunction(void *ptr, int nargs, int DLFid, VCPUdlfEntry *e) {
  684. registerGlobalDlf(e, DLFid);
  685. maki_cmd cmd={MAKI_CMD_SETDLF, DLFid};
  686. callDlfCommand(ptr, nargs, &cmd);
  687. }
  688. // This sends the DLFId to the function itself.
  689. void VCPU::DLF_reset(void *ptr, int nargs) {
  690. maki_cmd cmd={MAKI_CMD_RESETDLF, -1};
  691. callDlfCommand(ptr, nargs, &cmd);
  692. }
  693. void VCPU::DLF_addref(void *ptr, int nargs) {
  694. maki_cmd cmd={MAKI_CMD_ADDREF, -1};
  695. callDlfCommand(ptr, nargs, &cmd);
  696. }
  697. void VCPU::DLF_remref(void *ptr, int nargs) {
  698. maki_cmd cmd={MAKI_CMD_REMREF, -1};
  699. callDlfCommand(ptr, nargs, &cmd);
  700. }
  701. // -------------------------------------------------------------
  702. scriptVar VCPU::safeDiv(VCPUscriptVar *v1, VCPUscriptVar *v2) {
  703. double _r=0;
  704. double _v1=SOM::makeDouble(&v1->v);
  705. double _v2=SOM::makeDouble(&v2->v);
  706. if (_v2 != 0.0)
  707. _r = _v1 / _v2;
  708. else
  709. Script::guruMeditation(SOM::getSystemObjectByScriptId(v1->scriptId), GURU_DIVBYZERO, L"Division by zero");
  710. scriptVar r = SOM::makeVar(SCRIPT_DOUBLE);
  711. SOM::assign(&r, _r);
  712. return r;
  713. }
  714. /*
  715. Registers :
  716. VIP : Instruction Pointer
  717. VSP : Stack Pointer
  718. VSD : Script Descriptor (ID of script we're in)
  719. CALLM calls member function, pops a variable ID and a DLF entry, and pushs the result of
  720. the function. CallC calls an address, so pushs the return address on its stack
  721. (independant from the Push/Pop stack), and jumps to the code. Ret gets the last
  722. address pushed and returns there. JIZ jumps to an address if the first value on the stack
  723. is an int zero. JMP jumps unconditionnaly.
  724. The stack is a stack of 4 bytes integers containing scriptVar IDs.
  725. Var IDs from binaries are being added the base ID of the current script so we
  726. have only one variables segment for all scripts. Same for DLF entries. Events
  727. aren't references in the bytecode other than in the event table that links
  728. addresses in code to DLF entries, so we don't need that kind of tweaking.
  729. */
  730. // -------------------------------------------------------------
  731. char *VCPU::getCodeBlock(int id, int *size) {
  732. for (int i=0;i<codeTable.getNumItems();i++) {
  733. if (codeTable.enumItem(i)->scriptId == id) {
  734. if (size != NULL) *size = codeTable.enumItem(i)->size;
  735. return codeTable.enumItem(i)->codeBlock;
  736. }
  737. }
  738. return NULL;
  739. }
  740. // -------------------------------------------------------------
  741. VCPUcodeBlock *VCPU::getCodeBlockEntry(int id) {
  742. for (int i=0;i<codeTable.getNumItems();i++) {
  743. if (codeTable.enumItem(i)->scriptId == id) {
  744. return codeTable.enumItem(i);
  745. }
  746. }
  747. return NULL;
  748. }
  749. // -------------------------------------------------------------
  750. void VCPU::runCode(int scriptId, int pointer, int np) {
  751. int quit=0;
  752. VIP = pointer;
  753. VSD = scriptId;
  754. #ifdef WASABI_COMPILE_MAKIDEBUG
  755. int debugger_present = debugApi ? debugApi->debugger_isActive() : 0;
  756. #endif
  757. char *codeblock = (char *)getCodeBlock(VSD);
  758. char *p = codeblock + VIP;
  759. unsigned char opcode;
  760. int stackbase = VSP-np;
  761. int callcbase = CallStack.peek();
  762. VCC = callcbase;
  763. while (!quit) {
  764. #ifdef WASABI_COMPILE_MAKIDEBUG
  765. if (debugger_present) {
  766. VIPstack.push(VIP);
  767. VSDstack.push(VSD);
  768. // VSPstack.push(VSP);
  769. VCCstack.push(VCC);
  770. debugApi->debugger_trace();
  771. VIPstack.pop(&VIP);
  772. VSDstack.pop(&VSD);
  773. // VSPstack.pop(&VSP);
  774. VCCstack.pop(&VCC);
  775. }
  776. #endif
  777. opcode = *p;
  778. p+=sizeof(opcode);
  779. VIP+=sizeof(opcode);
  780. switch (opcode) {
  781. case OPCODE_PUSH: {
  782. int id; // var id
  783. id = *(int *)p;
  784. p+=sizeof(int); VIP+=sizeof(int);
  785. VCPUscriptVar *var = variablesTable.enumItem(id+varBase(VSD));
  786. push(*var);
  787. break;
  788. }
  789. case OPCODE_POPI: {
  790. pop(); // discard
  791. if (VSP == stackbase)
  792. statementStringList.freeAll();
  793. break;
  794. }
  795. case OPCODE_POP: {
  796. int id = *(int *)p; // var id
  797. p+=sizeof(int); VIP+=sizeof(int);
  798. VCPUscriptVar v = pop();
  799. VCPUassign(id, v.v, VSD);
  800. break;
  801. }
  802. case OPCODE_SET: {
  803. VCPUscriptVar v2 = pop();
  804. VCPUscriptVar v1 = pop();
  805. if (v1.varId == -1) {
  806. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_SETNONINTERNAL);
  807. ASSERT(0);
  808. }
  809. scriptVar r = VCPUassign(v1.varId, v2.v, VSD);
  810. push(r);
  811. break;
  812. }
  813. case OPCODE_RETF: {
  814. if (/*VSP == stackbase+1 && */CallStack.peek() == callcbase) {
  815. quit = 1;
  816. break;
  817. }
  818. CallStack.pop(&p);
  819. VIP = p-(char *)getCodeBlock(VSD);
  820. break;
  821. }
  822. case OPCODE_CALLC: {
  823. int shift; // jump length
  824. shift = *(int *)p;
  825. p+=sizeof(int); VIP+=sizeof(int);
  826. CallStack.push(p);
  827. VCC++;
  828. p+=shift;
  829. VIP+=shift;
  830. break;
  831. }
  832. case OPCODE_CALLM: {
  833. int id; // DLF id
  834. id = *(int *)p;
  835. p+=sizeof(int); VIP+=sizeof(int);
  836. VCPUdlfEntry *e = DLFentryTable.enumItem(id+dlfBase(VSD));
  837. int np = *(int *)p;
  838. // OLD stack protection - was relying on a shody test based on the fact that the compiler should not be able to generate two FF's at this offset, replaced by new opcode but remains for backward compatibility
  839. if ((np & 0xFFFF0000) == 0xFFFF0000) {
  840. p += sizeof(int);
  841. VIP += sizeof(int);
  842. np &= 0xFFFF;
  843. } else np = -1;
  844. scriptVar r = callDLF(e, np);
  845. VCPUscriptVar vr;
  846. vr.scriptId = VSD;
  847. vr.varId = -1;
  848. vr.v = r;
  849. push(vr);
  850. break;
  851. }
  852. case OPCODE_CALLM2: {
  853. int id; // DLF id
  854. id = *(int *)p;
  855. p+=sizeof(int); VIP+=sizeof(int);
  856. VCPUdlfEntry *e = DLFentryTable.enumItem(id+dlfBase(VSD));
  857. int np = *(unsigned char *)p; p++; VIP+=1;
  858. scriptVar r = callDLF(e, np);
  859. VCPUscriptVar vr;
  860. vr.scriptId = VSD;
  861. vr.varId = -1;
  862. vr.v = r;
  863. push(vr);
  864. break;
  865. }
  866. case OPCODE_UMV:
  867. {
  868. VCPUscriptVar name = pop();
  869. VCPUscriptVar obj = pop();
  870. ASSERT(obj.v.data.odata!=NULL);
  871. ASSERT(name.v.data.sdata!=NULL);
  872. int rettype = *(int *)p;
  873. p+=sizeof(int); VIP+=sizeof(int);
  874. if (rettype >= CLASS_ID_BASE) {
  875. SystemObject *so = SOM::getSystemObjectByScriptId(VSD);
  876. TList<int> *typeslist = so->getTypesList();
  877. rettype = typeslist->enumItem(rettype - CLASS_ID_BASE);
  878. }
  879. int oid = ((ScriptObject *)obj.v.data.odata)->vcpu_getMember(name.v.data.sdata, VSD, rettype);
  880. VCPUscriptVar *v = getOrphan(oid);
  881. ASSERT(v != NULL);
  882. push(*v);
  883. break;
  884. }
  885. case OPCODE_CMPEQ: {
  886. VCPUscriptVar v2 = pop();
  887. VCPUscriptVar v1 = pop();
  888. VCPUscriptVar r;
  889. r.v = SOM::makeVar(SCRIPT_INT);
  890. SOM::assign(&r.v, SOM::compEq(&v1.v, &v2.v));
  891. push(r);
  892. break;
  893. }
  894. case OPCODE_CMPNE: {
  895. VCPUscriptVar v2 = pop();
  896. VCPUscriptVar v1 = pop();
  897. VCPUscriptVar r;
  898. r.v = SOM::makeVar(SCRIPT_INT);
  899. SOM::assign(&r.v, SOM::compNeq(&v1.v, &v2.v));
  900. push(r);
  901. break;
  902. }
  903. case OPCODE_CMPA: {
  904. VCPUscriptVar v2 = pop();
  905. VCPUscriptVar v1 = pop();
  906. VCPUscriptVar r;
  907. r.v = SOM::makeVar(SCRIPT_INT);
  908. SOM::assign(&r.v, SOM::compA(&v1.v, &v2.v));
  909. push(r);
  910. break;
  911. }
  912. case OPCODE_CMPAE: {
  913. VCPUscriptVar v2 = pop();
  914. VCPUscriptVar v1 = pop();
  915. VCPUscriptVar r;
  916. r.v = SOM::makeVar(SCRIPT_INT);
  917. SOM::assign(&r.v, SOM::compAe(&v1.v, &v2.v));
  918. push(r);
  919. break;
  920. }
  921. case OPCODE_CMPB: {
  922. VCPUscriptVar v2 = pop();
  923. VCPUscriptVar v1 = pop();
  924. VCPUscriptVar r;
  925. r.v = SOM::makeVar(SCRIPT_INT);
  926. SOM::assign(&r.v, SOM::compB(&v1.v, &v2.v));
  927. push(r);
  928. break;
  929. }
  930. case OPCODE_CMPBE: {
  931. VCPUscriptVar v2 = pop();
  932. VCPUscriptVar v1 = pop();
  933. VCPUscriptVar r;
  934. r.v = SOM::makeVar(SCRIPT_INT);
  935. SOM::assign(&r.v, SOM::compBe(&v1.v, &v2.v));
  936. push(r);
  937. break;
  938. }
  939. case OPCODE_JIZ: {
  940. int shift; // jump length
  941. shift = *(int *)p;
  942. p+=sizeof(int); VIP+=sizeof(int);
  943. VCPUscriptVar v = pop();
  944. if (v.v.data.idata == 0) {
  945. p+=shift;
  946. VIP+=shift;
  947. }
  948. break;
  949. }
  950. case OPCODE_JNZ: {
  951. int shift; // jump length
  952. shift = *(int *)p;
  953. p+=sizeof(int); VIP+=sizeof(int);
  954. VCPUscriptVar v = pop();
  955. if (v.v.data.idata != 0) {
  956. p+=shift;
  957. VIP+=shift;
  958. }
  959. break;
  960. }
  961. case OPCODE_JMP: {
  962. int shift; // jump length
  963. shift = *(int *)p;
  964. p+=sizeof(int); VIP+=sizeof(int);
  965. p+=shift;
  966. VIP+=shift;
  967. break;
  968. }
  969. case OPCODE_NOT: {
  970. VCPUscriptVar v = pop();
  971. VCPUscriptVar r;
  972. r.v = SOM::makeVar(SCRIPT_BOOLEAN);
  973. switch (v.v.type) {
  974. case SCRIPT_BOOLEAN:
  975. case SCRIPT_INT:
  976. case SCRIPT_FLOAT:
  977. case SCRIPT_DOUBLE: {
  978. int i = SOM::makeBoolean(&v.v);
  979. r.v.data.idata = i == 0 ? 1 : 0;
  980. }
  981. break;
  982. case SCRIPT_STRING:
  983. r.v.data.idata = (!v.v.data.sdata || !*v.v.data.sdata) ? 1 : 0;
  984. break;
  985. default:
  986. r.v.data.idata = (v.v.data.odata == NULL) ? 1 : 0;
  987. break;
  988. }
  989. push(r);
  990. break;
  991. }
  992. case OPCODE_INCS: {
  993. VCPUscriptVar v = pop();
  994. push(v);
  995. switch (v.v.type) {
  996. case SCRIPT_BOOLEAN:
  997. v.v.data.idata = 1;
  998. break;
  999. case SCRIPT_INT:
  1000. v.v.data.idata++;
  1001. break;
  1002. case SCRIPT_FLOAT:
  1003. v.v.data.fdata = v.v.data.fdata+1;
  1004. break;
  1005. case SCRIPT_DOUBLE:
  1006. v.v.data.ddata = v.v.data.ddata+1;
  1007. break;
  1008. default:
  1009. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_INCSNONNUM);
  1010. ASSERT(0);
  1011. break;
  1012. }
  1013. if (v.varId != -1)
  1014. VCPUassign(v.varId, v.v, VSD);
  1015. break;
  1016. }
  1017. case OPCODE_DECS: {
  1018. VCPUscriptVar v = pop();
  1019. push(v);
  1020. switch (v.v.type) {
  1021. case SCRIPT_BOOLEAN:
  1022. v.v.data.idata = 0;
  1023. break;
  1024. case SCRIPT_INT:
  1025. v.v.data.idata--;
  1026. break;
  1027. case SCRIPT_FLOAT:
  1028. v.v.data.fdata = v.v.data.fdata-1;
  1029. break;
  1030. case SCRIPT_DOUBLE:
  1031. v.v.data.ddata = v.v.data.ddata-1;
  1032. break;
  1033. default:
  1034. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_DECSNONNUM);
  1035. ASSERT(0);
  1036. break;
  1037. }
  1038. if (v.varId != -1)
  1039. VCPUassign(v.varId, v.v, VSD);
  1040. break;
  1041. }
  1042. case OPCODE_INCP: {
  1043. VCPUscriptVar v = pop();
  1044. switch (v.v.type) {
  1045. case SCRIPT_BOOLEAN:
  1046. v.v.data.idata = 1;
  1047. break;
  1048. case SCRIPT_INT:
  1049. v.v.data.idata++;
  1050. break;
  1051. case SCRIPT_FLOAT:
  1052. v.v.data.fdata = v.v.data.fdata+1;
  1053. break;
  1054. case SCRIPT_DOUBLE:
  1055. v.v.data.ddata = v.v.data.ddata+1;
  1056. break;
  1057. default:
  1058. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_INCPNONNUM);
  1059. ASSERT(0);
  1060. break;
  1061. }
  1062. if (v.varId != -1)
  1063. VCPUassign(v.varId, v.v, VSD);
  1064. push(v);
  1065. break;
  1066. }
  1067. case OPCODE_DECP: {
  1068. VCPUscriptVar v = pop();
  1069. switch (v.v.type) {
  1070. case SCRIPT_BOOLEAN:
  1071. v.v.data.idata = 0;
  1072. break;
  1073. case SCRIPT_INT:
  1074. v.v.data.idata--;
  1075. break;
  1076. case SCRIPT_FLOAT:
  1077. v.v.data.fdata = v.v.data.fdata-1;
  1078. break;
  1079. case SCRIPT_DOUBLE:
  1080. v.v.data.ddata = v.v.data.ddata-1;
  1081. break;
  1082. default:
  1083. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_DECSNONNUM);
  1084. ASSERT(0);
  1085. break;
  1086. }
  1087. if (v.varId != -1)
  1088. VCPUassign(v.varId, v.v, VSD);
  1089. push(v);
  1090. break;
  1091. }
  1092. case OPCODE_ADD: {
  1093. VCPUscriptVar v2 = pop();
  1094. VCPUscriptVar v1 = pop();
  1095. ASSERT(v1.v.type == SCRIPT_STRING || SOM::isNumeric(&v1.v));
  1096. ASSERT(v2.v.type == SCRIPT_STRING || SOM::isNumeric(&v2.v));
  1097. if (v2.v.type == SCRIPT_STRING)
  1098. {
  1099. int n=0;
  1100. if (!v2.v.data.sdata) break;
  1101. if (v1.v.data.sdata) n+= wcslen(v1.v.data.sdata);
  1102. n+= wcslen(v2.v.data.sdata);
  1103. wchar_t *s = (wchar_t *)WMALLOC((n+1));
  1104. ASSERT(s != NULL);
  1105. if (v1.v.data.sdata)
  1106. {
  1107. wcsncpy(s, v1.v.data.sdata, n);
  1108. wcsncat(s, (v2.v.data.sdata ? v2.v.data.sdata : L""), n);
  1109. } else
  1110. wcsncpy(s, (v2.v.data.sdata ? v2.v.data.sdata : L""), n);
  1111. v1.v = SOM::makeVar(SCRIPT_STRING);
  1112. SOM::assign(&v1.v, s);
  1113. FREE(s);
  1114. push(v1);
  1115. } else {
  1116. scriptVar r = SOM::makeVar(SCRIPT_DOUBLE);
  1117. SOM::assign(&r, SOM::makeDouble(&v1.v) + SOM::makeDouble(&v2.v));
  1118. push(r);
  1119. }
  1120. break;
  1121. }
  1122. case OPCODE_SUB: {
  1123. VCPUscriptVar v2 = pop();
  1124. VCPUscriptVar v1 = pop();
  1125. ASSERT(SOM::isNumeric(&v1.v));
  1126. ASSERT(SOM::isNumeric(&v2.v));
  1127. scriptVar r = SOM::makeVar(SCRIPT_DOUBLE);
  1128. SOM::assign(&r, SOM::makeDouble(&v1.v) - SOM::makeDouble(&v2.v));
  1129. push(r);
  1130. break;
  1131. }
  1132. case OPCODE_MUL: {
  1133. VCPUscriptVar v2 = pop();
  1134. VCPUscriptVar v1 = pop();
  1135. ASSERT(SOM::isNumeric(&v1.v));
  1136. ASSERT(SOM::isNumeric(&v2.v));
  1137. scriptVar r = SOM::makeVar(SCRIPT_DOUBLE);
  1138. SOM::assign(&r, SOM::makeDouble(&v1.v) * SOM::makeDouble(&v2.v));
  1139. push(r);
  1140. break;
  1141. }
  1142. case OPCODE_DIV: {
  1143. VCPUscriptVar v2 = pop();
  1144. VCPUscriptVar v1 = pop();
  1145. scriptVar r = safeDiv(&v1, &v2);
  1146. push(r);
  1147. break;
  1148. }
  1149. case OPCODE_MOD: {
  1150. VCPUscriptVar v2 = pop();
  1151. VCPUscriptVar v1 = pop();
  1152. if (!SOM::isNumeric(&v2.v) || !SOM::isNumeric(&v1.v)) {
  1153. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_MODNONNUM);
  1154. ASSERT(0);
  1155. }
  1156. SOM::assign(&v1.v, SOM::makeInt(&v1.v) % SOM::makeInt(&v2.v));
  1157. push(v1);
  1158. break;
  1159. }
  1160. case OPCODE_NEG: {
  1161. VCPUscriptVar v = pop();
  1162. switch (v.v.type) {
  1163. case SCRIPT_BOOLEAN:
  1164. break;
  1165. case SCRIPT_INT:
  1166. v.v.data.idata = -v.v.data.idata;
  1167. break;
  1168. case SCRIPT_FLOAT:
  1169. v.v.data.fdata = -v.v.data.fdata;
  1170. break;
  1171. case SCRIPT_DOUBLE:
  1172. v.v.data.ddata = -v.v.data.ddata;
  1173. break;
  1174. default:
  1175. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_NEGNONNUM);
  1176. ASSERT(0);
  1177. break;
  1178. }
  1179. push(v);
  1180. break;
  1181. }
  1182. case OPCODE_BNOT: {
  1183. VCPUscriptVar v = pop();
  1184. if (!SOM::isNumeric(&v.v)) {
  1185. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_BNOTNONNUM);
  1186. ASSERT(0);
  1187. }
  1188. SOM::assign(&v.v, ~SOM::makeInt(&v.v));
  1189. push(v);
  1190. break;
  1191. }
  1192. case OPCODE_SHL: {
  1193. VCPUscriptVar v2 = pop();
  1194. VCPUscriptVar v1 = pop();
  1195. if (!SOM::isNumeric(&v1.v) || !SOM::isNumeric(&v2.v)) {
  1196. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_SHLNONNUM);
  1197. ASSERT(0);
  1198. }
  1199. SOM::assign(&v1.v, SOM::makeInt(&v1.v) << SOM::makeInt(&v2.v));
  1200. push(v1);
  1201. break;
  1202. }
  1203. case OPCODE_SHR: {
  1204. VCPUscriptVar v2 = pop();
  1205. VCPUscriptVar v1 = pop();
  1206. if (!SOM::isNumeric(&v1.v) || !SOM::isNumeric(&v2.v)) {
  1207. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_SHRNONNUM);
  1208. ASSERT(0);
  1209. }
  1210. SOM::assign(&v1.v, SOM::makeInt(&v1.v) >> SOM::makeInt(&v2.v));
  1211. push(v1);
  1212. break;
  1213. }
  1214. case OPCODE_XOR: {
  1215. VCPUscriptVar v2 = pop();
  1216. VCPUscriptVar v1 = pop();
  1217. if (!SOM::isNumeric(&v1.v) || !SOM::isNumeric(&v2.v)) {
  1218. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_XORNONNUM);
  1219. ASSERT(0);
  1220. }
  1221. SOM::assign(&v1.v, SOM::makeInt(&v1.v) ^ SOM::makeInt(&v2.v));
  1222. push(v1);
  1223. break;
  1224. }
  1225. case OPCODE_AND: {
  1226. VCPUscriptVar v2 = pop();
  1227. VCPUscriptVar v1 = pop();
  1228. if (!SOM::isNumeric(&v1.v) || !SOM::isNumeric(&v2.v)) {
  1229. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_ANDNONNUM);
  1230. ASSERT(0);
  1231. }
  1232. SOM::assign(&v1.v, SOM::makeInt(&v1.v) & SOM::makeInt(&v2.v));
  1233. push(v1);
  1234. break;
  1235. }
  1236. case OPCODE_OR: {
  1237. VCPUscriptVar v2 = pop();
  1238. VCPUscriptVar v1 = pop();
  1239. if (!SOM::isNumeric(&v1.v) || !SOM::isNumeric(&v2.v)) {
  1240. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_ANDNONNUM);
  1241. ASSERT(0);
  1242. }
  1243. SOM::assign(&v1.v, SOM::makeInt(&v1.v) | SOM::makeInt(&v2.v));
  1244. push(v1);
  1245. break;
  1246. }
  1247. case OPCODE_LAND: {
  1248. VCPUscriptVar v2 = pop();
  1249. VCPUscriptVar v1 = pop();
  1250. VCPUscriptVar r;
  1251. r.v = SOM::makeVar(SCRIPT_BOOLEAN);
  1252. int a2 = SOM::makeBoolean(&v2.v);
  1253. int a1 = SOM::makeBoolean(&v1.v);
  1254. r.v.data.idata = (a2 && a1) ? 1 : 0;
  1255. push(r);
  1256. break;
  1257. }
  1258. case OPCODE_LOR: {
  1259. VCPUscriptVar v2 = pop();
  1260. VCPUscriptVar v1 = pop();
  1261. VCPUscriptVar r;
  1262. r.v = SOM::makeVar(SCRIPT_BOOLEAN);
  1263. int a2 = SOM::makeBoolean(&v2.v);
  1264. int a1 = SOM::makeBoolean(&v1.v);
  1265. r.v.data.idata = (a2 || a1) ? 1 : 0;
  1266. push(r);
  1267. break;
  1268. }
  1269. case OPCODE_DELETE: {
  1270. VCPUscriptVar v1 = pop();
  1271. int id = 0;
  1272. int type = v1.v.type;
  1273. if (type >= 0x10000)
  1274. do {
  1275. id = type - 0x10000;
  1276. VCPUscriptVar *v = variablesTable.enumItem(id+varBase(VSD));
  1277. type = v->v.type;
  1278. } while (type >= 0x10000);
  1279. if (isInstantiable(type)) {
  1280. ScriptObject *s = (ScriptObject *)v1.v.data.odata;
  1281. scriptVar v = SOM::makeVar(v1.v.type);
  1282. VCPUassign(v1.varId, v, v1.scriptId);
  1283. SystemObject *so = SOM::getSystemObjectByScriptId(VSD);
  1284. so->removeInstantiatedObject(s);
  1285. ObjectTable::destroy(s);
  1286. }
  1287. VCPU::push(v1);
  1288. break;
  1289. }
  1290. case OPCODE_NEW: {
  1291. int id = *(int *)p; // class id
  1292. p+=sizeof(int); VIP+=sizeof(int);
  1293. SystemObject *so = SOM::getSystemObjectByScriptId(VSD);
  1294. TList<int> *typeslist = so->getTypesList();
  1295. int _id;
  1296. if (id >= 0x10000)
  1297. do {
  1298. _id = id - 0x10000;
  1299. VCPUscriptVar *v = variablesTable.enumItem(_id+varBase(VSD));
  1300. id = v->v.type;
  1301. } while (id >= 0x10000);
  1302. if (SOM::getSystemObjectByScriptId(VSD)->isOldFormat())
  1303. id = oldClassToClassId(id);
  1304. else
  1305. id = typeslist->enumItem(id);
  1306. if (isInstantiable(id)) {
  1307. ScriptObject *s = ObjectTable::instantiate(id);
  1308. if (s) s->vcpu_setScriptId(VSD);
  1309. so->addInstantiatedObject(s);
  1310. if (s == NULL) {
  1311. Script::guruMeditation(SOM::getSystemObjectByScriptId(VSD), GURU_NEWFAILED);
  1312. }
  1313. VCPUscriptVar v={{SCRIPT_OBJECT, {0}}, 0};
  1314. SOM::assign(&v.v, s);
  1315. push(v);
  1316. } else {
  1317. VCPUscriptVar n = {{SCRIPT_OBJECT,NULL}, 0};
  1318. push(n);
  1319. }
  1320. break;
  1321. }
  1322. case OPCODE_CMPLT : {
  1323. complete = 1;
  1324. break;
  1325. }
  1326. case OPCODE_NOP :
  1327. {
  1328. #if defined(_WIN32) || defined(_WIN64)
  1329. OutputDebugStringA("Opcode 0 - NOP encountered, please check!\n");
  1330. #else
  1331. #warning port me
  1332. #endif
  1333. break;
  1334. }
  1335. default: {
  1336. ASSERTALWAYS(StringPrintf("Opcode %X not implemented", opcode));
  1337. break;
  1338. }
  1339. }
  1340. }
  1341. ASSERT(VSP == stackbase + 1);
  1342. }
  1343. // -------------------------------------------------------------
  1344. scriptVar VCPU::VCPUassign(int id, scriptVar sv, int scriptId) {
  1345. VCPUscriptVar *v = NULL;
  1346. if (id & (1 << 31)) {
  1347. id = id & ~(1 << 31);
  1348. v = getOrphan(id);
  1349. } else
  1350. v = variablesTable.enumItem(id+varBase(scriptId));
  1351. if (v->v.type != SCRIPT_STRING) {
  1352. if (!SOM::isNumeric(&v->v)) {
  1353. // assigning an object
  1354. scriptVar _sv = sv;
  1355. if (_sv.data.odata != NULL && !SystemObject::isObjectValid(_sv.data.odata))
  1356. _sv.data.odata = NULL;
  1357. if (v->v.data.odata != _sv.data.odata) {
  1358. if (v->v.data.odata != NULL && !v->transcient && SystemObject::isObjectValid(v->v.data.odata))
  1359. ((ScriptObject *)v->v.data.odata)->vcpu_removeAssignedVariable(v->varId, v->scriptId);
  1360. if (_sv.data.odata == NULL) {
  1361. v->v.data.odata = NULL;
  1362. } else {
  1363. SOM::assign(&v->v, &sv);
  1364. if (SOM::typeCheck(v, 0)) {
  1365. if (!v->isaclass && !v->transcient)
  1366. ((ScriptObject *)sv.data.odata)->vcpu_addAssignedVariable(v->varId, v->scriptId);
  1367. } else {
  1368. int type = v->v.type;
  1369. if (type >= 0x10000)
  1370. do {
  1371. id = type - 0x10000;
  1372. VCPUscriptVar *v = variablesTable.enumItem(id+varBase(VSD));
  1373. type = v->v.type;
  1374. } while (type >= 0x10000);
  1375. class_entry *e = ObjectTable::getClassEntry(type);
  1376. ASSERT(e != NULL);
  1377. GUID g = e->classGuid;
  1378. ScriptObject *o = NULL;
  1379. v->v.data.odata->vcpu_getInterfaceObject(g, &o);
  1380. if (o != NULL) {
  1381. v->v.data.odata = o;
  1382. if (!v->isaclass && !v->transcient)
  1383. o->vcpu_addAssignedVariable(v->varId, v->scriptId);
  1384. } else {
  1385. v->v.data.odata = NULL;
  1386. }
  1387. }
  1388. }
  1389. }
  1390. } else {
  1391. // assigning a number
  1392. SOM::assign(&v->v, &sv);
  1393. }
  1394. } else {
  1395. ASSERT(sv.type == SCRIPT_STRING);
  1396. SOM::persistentstrassign(&v->v, sv.data.sdata);
  1397. }
  1398. return v->v;
  1399. }
  1400. // -------------------------------------------------------------
  1401. void VCPU::traceState(VCPUscriptVar object, VCPUdlfEntry *e) {
  1402. _DebugString("vcpu[%2X]: %04X [%04X].%s", VCPU::VSD, VCPU::VIP, object.varId, e->functionName);
  1403. // CallbackManager::issueCallback(SysCallback::CONSOLE, ConsoleCallback::DEBUGMESSAGE, 0, reinterpret_cast<int>(t));
  1404. }
  1405. // -------------------------------------------------------------
  1406. // Calls the DLF function
  1407. scriptVar VCPU::callDLF(VCPUdlfEntry *e, int np) {
  1408. static Stack<int> cpuidstack;
  1409. cpuidstack.push(VSD);
  1410. cpuidstack.push(VIP);
  1411. cpuidstack.push(VCC);
  1412. /* if (e->external) {
  1413. char t[256] = {0};
  1414. VCPUscriptVar v = VCPU::peekAt(e->nparams);
  1415. SPRINTF(t, "vcpu: %04X [%04X].%s", VCPU::VIP, v.varId, e->functionName);
  1416. Console::outputString(0, t);
  1417. DebugString("%s", t);
  1418. ((void(*)(int))e->ptr)(-1);
  1419. scriptVar rv = pop().v; // returned val
  1420. cpuidstack.pop(&VCC);
  1421. cpuidstack.pop(&VIP);
  1422. cpuidstack.pop(&VSD);
  1423. return rv;
  1424. }*/
  1425. /* char t[256] = {0};
  1426. SPRINTF(t, "e->nparams = %d\n", e->nparams);
  1427. DebugString("%s", t); */
  1428. //ASSERT(np == -1 || np == e->nparams); // fucko!!!!!!!!
  1429. if (np == -1) {
  1430. np = e->nparams;
  1431. }
  1432. for (int i=0;i<np;i++) {
  1433. paramList[i] = pop().v;
  1434. }
  1435. VCPUscriptVar object = pop();
  1436. scriptVar r = MAKE_SCRIPT_INT(0);
  1437. //traceState(object, e);
  1438. if (object.v.data.odata == NULL) {
  1439. Script::guruMeditation(SOM::getSystemObjectByScriptId(VCPU::VSD), GURU_NULLCALLED, L"Null object called", object.varId);
  1440. cpuidstack.pop(&VCC);
  1441. cpuidstack.pop(&VIP);
  1442. cpuidstack.pop(&VSD);
  1443. return MAKE_SCRIPT_INT(0);
  1444. //ASSERT(0);
  1445. }
  1446. #ifndef _DEBUG
  1447. try
  1448. #endif
  1449. {
  1450. if (object.v.data.odata) object.v.data.odata->vcpu_setScriptId(object.scriptId);
  1451. if (e->ptr != NULL) {
  1452. switch (np) {
  1453. case 0:
  1454. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *))e->ptr)(NULL, VCPU::VSD, object.v.data.odata);
  1455. break;
  1456. case 1:
  1457. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0]);
  1458. break;
  1459. case 2:
  1460. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1]);
  1461. break;
  1462. case 3:
  1463. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2]);
  1464. break;
  1465. case 4:
  1466. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3]);
  1467. break;
  1468. case 5:
  1469. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4]);
  1470. break;
  1471. case 6:
  1472. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4], paramList[5]);
  1473. break;
  1474. case 7:
  1475. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4], paramList[5], paramList[6]);
  1476. break;
  1477. case 8:
  1478. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4], paramList[5], paramList[6], paramList[7]);
  1479. break;
  1480. case 9:
  1481. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4], paramList[5], paramList[6], paramList[7], paramList[8]);
  1482. break;
  1483. case 10:
  1484. r = ((scriptVar (*)(maki_cmd *, int vsd, class ScriptObject *, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar, scriptVar))e->ptr)(NULL, VCPU::VSD, object.v.data.odata, paramList[0], paramList[1], paramList[2], paramList[3], paramList[4], paramList[5], paramList[6], paramList[7], paramList[8], paramList[9]);
  1485. break;
  1486. }
  1487. }
  1488. }
  1489. #ifndef _DEBUG
  1490. catch(...)
  1491. {
  1492. Script::guruMeditation(SOM::getSystemObjectByScriptId(VCPU::VSD), GURU_EXCEPTION, L"Script Fatal Error", object.varId);
  1493. cpuidstack.pop(&VCC);
  1494. cpuidstack.pop(&VIP);
  1495. cpuidstack.pop(&VSD);
  1496. #ifdef ON_FATAL_SKIN_ERROR
  1497. ON_FATAL_SKIN_ERROR
  1498. #endif
  1499. return MAKE_SCRIPT_INT(0);
  1500. }
  1501. #endif
  1502. cpuidstack.pop(&VCC);
  1503. cpuidstack.pop(&VIP);
  1504. cpuidstack.pop(&VSD);
  1505. return r;
  1506. }
  1507. // -------------------------------------------------------------
  1508. void VCPU::addStatementString(wchar_t *s)
  1509. {
  1510. statementStringList.addItem(s);
  1511. }
  1512. // -------------------------------------------------------------
  1513. int VCPU::getComplete() {
  1514. return complete;
  1515. }
  1516. // -------------------------------------------------------------
  1517. int VCPU::isInstantiable(int id) {
  1518. ASSERT(!SOM::isNumericType(id));
  1519. return ObjectTable::isClassInstantiable(id);
  1520. }
  1521. // -------------------------------------------------------------
  1522. int VCPU::getDlfGlobalIndex(int dlfid, int scriptid) {
  1523. static int lasti=-1;
  1524. static int lastid=0;
  1525. static int lastsid=0;
  1526. if (lasti>=0 && lasti < DLFentryTable.getNumItems()) {
  1527. if (lastsid == scriptid && lastid == dlfid) {
  1528. VCPUdlfEntry *e = DLFentryTable.enumItem(lasti);
  1529. if (e->DLFid == dlfid && e->scriptId == scriptid)
  1530. return lasti;
  1531. }
  1532. }
  1533. for (int i=0;i<DLFentryTable.getNumItems();i++ ){
  1534. VCPUdlfEntry *e = DLFentryTable.enumItem(i);
  1535. if (e->scriptId == scriptid && e->DLFid == dlfid) {
  1536. lasti = i;
  1537. lastsid = scriptid;
  1538. lastid = dlfid;
  1539. return lasti;
  1540. }
  1541. }
  1542. Script::guruMeditation(SOM::getSystemObjectByScriptId(scriptid), GURU_INVALIDEVENTDLF);
  1543. return -1;
  1544. }
  1545. // -------------------------------------------------------------
  1546. int VCPU::isValidScriptId(int id) {
  1547. for (int i=0;i<codeTable.getNumItems();i++)
  1548. if (codeTable[i]->scriptId == id) return 1;
  1549. return 0;
  1550. }
  1551. // -------------------------------------------------------------
  1552. int VCPU::getCacheCount() {
  1553. return cacheCount;
  1554. }
  1555. // -------------------------------------------------------------
  1556. int VCPU::getUserAncestor(int varid, int scriptid) {
  1557. VCPUscriptVar *vc = variablesTable.enumItem(varid+varBase(scriptid)) ;
  1558. if (vc->v.type < 0x10000) return -1;
  1559. int r_varId = vc->v.type - 0x10000;
  1560. ASSERT(r_varId < variablesTable.getNumItems());
  1561. return r_varId;
  1562. }
  1563. // -------------------------------------------------------------
  1564. void VCPU::pushObject(void *o) {
  1565. scriptVar v = SOM::makeVar(SCRIPT_OBJECT, (ScriptObject *)o);
  1566. VCPU::push(v);
  1567. }
  1568. // -------------------------------------------------------------
  1569. void VCPU::pushInt(int i) {
  1570. scriptVar v = SOM::makeVar(SCRIPT_INT);
  1571. SOM::assign(&v, i);
  1572. VCPU::push(v);
  1573. }
  1574. // -------------------------------------------------------------
  1575. void VCPU::pushBoolean(int b) {
  1576. scriptVar v = SOM::makeVar(SCRIPT_BOOLEAN);
  1577. SOM::assign(&v, b);
  1578. VCPU::push(v);
  1579. }
  1580. // -------------------------------------------------------------
  1581. void VCPU::pushFloat(float f) {
  1582. scriptVar v = SOM::makeVar(SCRIPT_FLOAT);
  1583. SOM::assign(&v, f);
  1584. VCPU::push(v);
  1585. }
  1586. // -------------------------------------------------------------
  1587. void VCPU::pushDouble(double d) {
  1588. scriptVar v = SOM::makeVar(SCRIPT_DOUBLE);
  1589. SOM::assign(&v, d);
  1590. VCPU::push(v);
  1591. }
  1592. // -------------------------------------------------------------
  1593. void VCPU::pushString(const wchar_t *s)
  1594. {
  1595. scriptVar v = SOM::makeVar(SCRIPT_STRING);
  1596. SOM::assign(&v, s);
  1597. VCPU::push(v);
  1598. }
  1599. // -------------------------------------------------------------
  1600. void VCPU::pushVoid() {
  1601. scriptVar v = SOM::makeVar(SCRIPT_VOID);
  1602. VCPU::push(v);
  1603. }
  1604. // -------------------------------------------------------------
  1605. void *VCPU::popObject() {
  1606. return (void *)VCPU::pop().v.data.odata;
  1607. }
  1608. // -------------------------------------------------------------
  1609. int VCPU::popInt() {
  1610. scriptVar v = VCPU::pop().v;
  1611. ASSERT(SOM::isNumeric(&v));
  1612. return SOM::makeInt(&v);
  1613. }
  1614. // -------------------------------------------------------------
  1615. bool VCPU::popBoolean() {
  1616. scriptVar v = VCPU::pop().v;
  1617. ASSERT(SOM::isNumeric(&v));
  1618. return SOM::makeBoolean(&v);
  1619. }
  1620. // -------------------------------------------------------------
  1621. float VCPU::popFloat() {
  1622. scriptVar v = VCPU::pop().v;
  1623. ASSERT(SOM::isNumeric(&v));
  1624. return SOM::makeFloat(&v);
  1625. }
  1626. // -------------------------------------------------------------
  1627. double VCPU::popDouble() {
  1628. scriptVar v = VCPU::pop().v;
  1629. ASSERT(SOM::isNumeric(&v));
  1630. return SOM::makeDouble(&v);
  1631. }
  1632. // -------------------------------------------------------------
  1633. const wchar_t *VCPU::popString()
  1634. {
  1635. scriptVar v = VCPU::pop().v;
  1636. ASSERT(v.type == SCRIPT_STRING);
  1637. return v.data.sdata;
  1638. }
  1639. // -------------------------------------------------------------
  1640. void VCPU::popDiscard() {
  1641. VCPU::pop();
  1642. }
  1643. // -------------------------------------------------------------
  1644. VCPUdlfEntry *VCPU::getGlobalDlfEntry(int dlfid) {
  1645. return globalDlfList.enumItem(dlfid);
  1646. }
  1647. // -------------------------------------------------------------
  1648. int VCPU::createOrphan(int type) {
  1649. orphans.addItem(new OrphanEntry(orphanid, type));
  1650. return orphanid++;
  1651. }
  1652. // -------------------------------------------------------------
  1653. void VCPU::killOrphan(int id) {
  1654. int pos;
  1655. OrphanEntry *p = orphans.findItem((const wchar_t *)&id, &pos);
  1656. ASSERT(p != NULL && pos >= 0);
  1657. if (p->v.v.type == SCRIPT_STRING)
  1658. FREE((void *)p->v.v.data.sdata);
  1659. delete p;
  1660. orphans.removeByPos(pos);
  1661. }
  1662. // -------------------------------------------------------------
  1663. VCPUscriptVar *VCPU::getOrphan(int id) {
  1664. OrphanEntry *p = orphans.findItem((const wchar_t *)&id);
  1665. ASSERT(p != NULL);
  1666. return &p->v;
  1667. }
  1668. // -------------------------------------------------------------
  1669. int OrphanQuickSort::compareItem(void *p1, void *p2) {
  1670. if ((static_cast<OrphanEntry *>(p1))->id < (static_cast<OrphanEntry *>(p2))->id) return -1;
  1671. if ((static_cast<OrphanEntry *>(p1))->id > (static_cast<OrphanEntry *>(p2))->id) return 1;
  1672. return 0;
  1673. }
  1674. // -------------------------------------------------------------
  1675. int OrphanQuickSort::compareAttrib(const wchar_t *attr, void *p2)
  1676. {
  1677. int id = *(reinterpret_cast<const int *>(attr));
  1678. int eid = (static_cast<OrphanEntry *>(p2))->id;
  1679. if (id < eid) return -1;
  1680. if (id > eid) return 1;
  1681. return 0;
  1682. }
  1683. // -------------------------------------------------------------
  1684. OrphanEntry::OrphanEntry(int _id, int type) {
  1685. id = _id;
  1686. MEMSET(&v, 0, sizeof(VCPUscriptVar));
  1687. v.v.type = type;
  1688. v.scriptId = -1;
  1689. v.varId = id | (1 << 31);
  1690. v.transcient = 1; // so no event is trapped, will change later when compiler supports it
  1691. }
  1692. // -------------------------------------------------------------
  1693. void VCPU::setAtom(const wchar_t *atomname, ScriptObject *o) {
  1694. int pos;
  1695. ScriptAtom *sa = atoms.findItem(atomname, &pos);
  1696. if (pos >= 0) {
  1697. delete sa;
  1698. atoms.removeByPos(pos);
  1699. }
  1700. if (o)
  1701. atoms.addItem(new ScriptAtom(atomname, o));
  1702. }
  1703. // -------------------------------------------------------------
  1704. ScriptObject *VCPU::getAtom(const wchar_t *atomname) {
  1705. ScriptAtom *sa = atoms.findItem(atomname);
  1706. if (sa) {
  1707. return sa->getAtomObject();
  1708. }
  1709. return NULL;
  1710. }
  1711. // -------------------------------------------------------------
  1712. const wchar_t *VCPU::getClassName(int vcpuid, int localclassid) {
  1713. SystemObject *so = SOM::getSystemObject(vcpuid);
  1714. if (so != NULL) {
  1715. TList<int> *l = so->getTypesList();
  1716. if (l != NULL) {
  1717. int global = l->enumItem(localclassid);
  1718. class_entry *e = ObjectTable::getClassEntry(global);
  1719. if (e != NULL)
  1720. return e->classname;
  1721. }
  1722. }
  1723. return NULL;
  1724. }
  1725. // -------------------------------------------------------------
  1726. int VCPU::cacheCount = 0;
  1727. // segments
  1728. PtrList<VCPUscriptVar> VCPU::variablesTable;
  1729. PtrList<VCPUeventEntry> VCPU::eventsTable;
  1730. PtrList<VCPUdlfEntry> VCPU::DLFentryTable;
  1731. PtrList<VCPUdlfEntry> VCPU::globalDlfList;
  1732. PtrList<VCPUcodeBlock> VCPU::codeTable;
  1733. PtrList<wchar_t> VCPU::statementStringList;
  1734. PtrListInsertSorted<OrphanEntry, OrphanQuickSort> VCPU::orphans;
  1735. PtrListQuickSorted<ScriptAtom, ScriptAtomSort> VCPU::atoms;
  1736. int VCPU::orphanid=0;
  1737. // stacks
  1738. Stack<VCPUscriptVar> VCPU::CpuStack;
  1739. Stack<char *> VCPU::CallStack;
  1740. // registers
  1741. int VCPU::VIP=0;
  1742. int VCPU::VSP=0;
  1743. int VCPU::VSD=0;
  1744. int VCPU::VCC=0;
  1745. Stack<int> VCPU::VIPstack;
  1746. Stack<int> VCPU::VSPstack;
  1747. Stack<int> VCPU::VSDstack;
  1748. Stack<int> VCPU::VCCstack;
  1749. // misc
  1750. int VCPU::numScripts=0;
  1751. int VCPU::highestDLFId=0;
  1752. scriptVar VCPU::paramList[SCRIPT_MAXARGS];
  1753. int VCPU::complete;
  1754. TList<int> VCPU::scriptsToRemove;
  1755. // NOTES
  1756. // There is no reason why people would cast System, Layout and Container
  1757. // back to the common base class... so...
  1758. // GUI objects should descend from a GUIObject rather than ScriptObject
  1759. // GUIObject would descend from ScriptObject for the compiler and should
  1760. // be exported as "Object" for the script, ScriptObject should then not
  1761. // be exported at all, thus preventing someone from doing "Object o = System;"
  1762. // which makes no sense since System is not a GUI object. Of course you
  1763. // could still do "Layout l = System.getContainer("mqlksd").getLayout("lqsdkj");"
  1764. // but you won't be able to cast that to an "Object". Furthermore, to get a
  1765. // GUI object, you'll use the layout's function "getObject", so this
  1766. // will add consistency to the overall thing.
  1767. /*
  1768. --------------------------------------------------------------------------------
  1769. VCPU: Virtual CPU, The virtual machine processor.
  1770. The VCPU actually takes care of some kinds of segments of variables,
  1771. events, and so on. The VCPU's task is to run any number of scripts
  1772. serially in reversed loading order. Last script loaded takes precedence
  1773. over previous ones. Events and functions fall back to the the previous
  1774. script if it also defines them, unless explicitly prevented via 'complete;'
  1775. The VCPU links DLFs in reverse hierarchy order, allowing overriding of
  1776. functions in objects.
  1777. DLF : Dynamically Linked Function. Function name is used to link it to
  1778. whatever layout of functions we have in any release of the VCPU, allowing
  1779. us to reorder our functions in objects.
  1780. TODO: Add versionning info so we can safely expand this format.
  1781. Binaries format :
  1782. <obsolete>
  1783. Size Desc What
  1784. -----------------------------------------------------------------------------
  1785. 8 Header FG\x03\x04\x14\00\00\00\00
  1786. -----------------------------------------------------------------------------
  1787. 4 # of DLF int
  1788. -----------------------------------------------------------------------------
  1789. 4 DLF base type int
  1790. 1 Size of func name char
  1791. N Function name char[n]
  1792. ...
  1793. -----------------------------------------------------------------------------
  1794. 4 # of variables int
  1795. -----------------------------------------------------------------------------
  1796. 8 variable scriptVar
  1797. ...
  1798. -----------------------------------------------------------------------------
  1799. 4 # of strings int
  1800. -----------------------------------------------------------------------------
  1801. 1 Size of string char 1st string assigned to 1st string var
  1802. N String char[n] 2nd string assigned to 2nd string var...
  1803. ...
  1804. -----------------------------------------------------------------------------
  1805. 4 # of events int
  1806. -----------------------------------------------------------------------------
  1807. 4 variable id int Matching variable table
  1808. 4 DLF entry int Matching DLF table
  1809. 4 Function pointer int Pointer in code from base of code
  1810. ...
  1811. -----------------------------------------------------------------------------
  1812. 4 Size of code int
  1813. -----------------------------------------------------------------------------
  1814. N Compiled code char[n]
  1815. -----------------------------------------------------------------------------
  1816. */