saf_comun.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /** This is a SAF interpreter of games written in programming language comun.
  2. Keep in mind that unless you make a precompiled version of the game, THIS IS
  3. A NON-STANDARD SAF PROGRAM because it reads from a file and writes errors to
  4. stderr (which is normally advised not to do with SAF). However once you make
  5. game, you can create a precompiled version that will again be a well-behaved
  6. SAF program.
  7. Usage: compile this like normal SAF program. Then when ran, the program
  8. looks for a file named "game.cmn" which is a comun source for the game to
  9. interpret. The file gets compiled and interpreted. In case of error in the
  10. program it is written to stderr.
  11. To make a precompiled version copy the precompiled data that's output by this
  12. program to some file (e.g. compiled_data.h) and include it as a library below.
  13. Then compiled this again.
  14. To learn the comun language, see its repository. SAF binding to comun is
  15. intuitive: the names of functions are the same as in saf.h, parameters are
  16. passed via stack so that they appear in the source code in the same order as
  17. in the function's prototype, e.g. what in C would be
  18. SAF_drawLine(1,2,3,4,SAF_COLOR_BLACK) in comun is
  19. 1 2 3 4 SAF_COLOR_BLACK SAF_drawLine. Strings are expected to be zero
  20. terminated but pushed in reverse order (as is standard in comun), image data
  21. are also expected to be pushed in reverse order, so that image width is on
  22. stack top, image height is one cell below etc.). Top level code is
  23. initialization (what in C is inside SAF_init), loop code goes to SAF_loop
  24. function (just as in C). */
  25. #define SAF_PROGRAM_NAME "comun game"
  26. #include "../saf.h"
  27. //#include "compiled_data.h" // include precompiled data here
  28. #if !PRECOMPILED
  29. #include <stdio.h>
  30. #endif
  31. #define CMN_STRING_PSEUDOHASH_SIZE 16
  32. #include "comun.h"
  33. #define GAME_FILE_NAME "game.cmn"
  34. #define WORKINGMEM_SIZE 2048
  35. #if !PRECOMPILED
  36. #define BYTECODEDMEM_SIZE 4096
  37. uint8_t bytecodeMem[BYTECODEDMEM_SIZE];
  38. #endif
  39. uint8_t workingMem[WORKINGMEM_SIZE];
  40. #define HELPER_STRING_SIZE 32
  41. char helperString[HELPER_STRING_SIZE];
  42. #define HELPER_IMAGE_SIZE (16 * 16)
  43. uint8_t helperImage[HELPER_IMAGE_SIZE];
  44. #define F_BUTTON_PRESSED 0x00
  45. #define F_BUTTON_JUST_PRESSED 0x01
  46. #define F_PLAY_SOUND 0x02
  47. #define F_SAVE 0x03
  48. #define F_LOAD 0x04
  49. #define F_FRAME 0x05
  50. #define F_TIME 0x06
  51. #define F_RANDOM 0x07
  52. #define F_RANDOM_SEED 0x08
  53. #define F_SIN 0x09
  54. #define F_COS 0x0a
  55. #define F_SQRT 0x0b
  56. #define F_COLOR_FROM_RGB 0x0c
  57. #define F_COLOR_TO_RGB 0x0d
  58. #define F_COLOR_TO_GRAYSCALE 0x0e
  59. #define F_COLOR_TO_1BIT 0x0f
  60. #define F_COLOR_INVERT 0x10
  61. #define F_DRAW_PIXEL 0x11
  62. #define F_DRAW_RECT 0x12
  63. #define F_DRAW_LINE 0x13
  64. #define F_DRAW_CIRCLE 0x14
  65. #define F_CLEAR_SCREEN 0x15
  66. #define F_DRAW_TEXT 0x16
  67. #define F_GET_FONT_CHARACTER 0x17
  68. #define F_DRAW_IMAGE 0x18
  69. #define F_DRAW_IMAGE_COMPRESSED 0x19
  70. #define F_DRAW_IMAGE_1BIT 0x1a
  71. #define F_INT_TO_STR 0x1b
  72. #define F_BUTTON_UP 0x1c
  73. #define F_BUTTON_DOWN 0x1d
  74. #define F_BUTTON_LEFT 0x1e
  75. #define F_BUTTON_RIGHT 0x1f
  76. #define F_BUTTON_A 0x20
  77. #define F_BUTTON_B 0x21
  78. #define F_BUTTON_C 0x22
  79. #define F_COLOR_BLACK 0x23
  80. #define F_COLOR_WHITE 0x24
  81. #define F_COLOR_GRAY 0x25
  82. #define F_COLOR_GRAY_DARK 0x26
  83. #define F_COLOR_RED 0x27
  84. #define F_COLOR_RED_DARK 0x28
  85. #define F_COLOR_GREEN 0x29
  86. #define F_COLOR_GREEN_DARK 0x2a
  87. #define F_COLOR_BLUE 0x2b
  88. #define F_COLOR_BLUE_DARK 0x2c
  89. #define F_COLOR_YELLOW 0x2d
  90. #define F_COLOR_ORANGE 0x2e
  91. #define F_COLOR_BROWN 0x2f
  92. #define F_SOUND_BEEP 0x30
  93. #define F_SOUND_CLICK 0x31
  94. #define F_SOUND_BOOM 0x32
  95. #define F_SOUND_BUMP 0x33
  96. #define F_TRANSFORM_NONE 0x34
  97. #define F_TRANSFORM_ROTATE_90 0x35
  98. #define F_TRANSFORM_ROTATE_180 0x36
  99. #define F_TRANSFORM_ROTATE_270 0x37
  100. #define F_TRANSFORM_FLIP 0x38
  101. #define F_TRANSFORM_SCALE_2 0x39
  102. #define F_TRANSFORM_SCALE_3 0x3a
  103. #define F_TRANSFORM_SCALE_4 0x3b
  104. #define F_TRANSFORM_INVERT 0x3c
  105. #define F_SCREEN_WIDTH 0x3d
  106. #define F_SCREEN_HEIGHT 0x3e
  107. #define F_FPS 0x3f
  108. #define FUNCTIONS_TOTAL 0x40
  109. #if !PRECOMPILED
  110. int8_t functions[FUNCTIONS_TOTAL];
  111. CMN_Compiler compiler;
  112. int32_t loopFunctionID;
  113. #endif
  114. CMN_Interpreter interpreter;
  115. uint8_t ok = 1;
  116. int16_t ioFunction(int16_t x)
  117. {
  118. if (x >= 0)
  119. putchar(x);
  120. return 0;
  121. }
  122. #define CV(n) CMN_interpreterGetValue(interp,n)
  123. #define CPOP(n) CMN_interpreterPop(interp,n)
  124. #define CPUSH(n) CMN_interpreterPush(interp,n)
  125. void loadImage(CMN_Interpreter *interp, uint8_t *image, uint16_t maxSize,
  126. uint8_t mode)
  127. {
  128. image[0] = CV(0);
  129. image[1] = CV(1);
  130. CPOP(2);
  131. uint16_t imageLen = ((uint16_t) image[0]) * ((uint16_t) image[1]);
  132. if (mode == 1)
  133. imageLen = 16 + imageLen / 2 + ((imageLen % 2) != 0);
  134. else if (mode == 2)
  135. imageLen = imageLen / 8 + ((imageLen % 8) != 0);
  136. if (imageLen > maxSize - 2)
  137. imageLen = maxSize - 2;
  138. for (uint16_t i = 0; i < imageLen; ++i)
  139. image[2 + i] = CV(i);
  140. CPOP(imageLen);
  141. }
  142. void functionCall(uint16_t id, CMN_Interpreter *interp)
  143. {
  144. uint8_t x, y, z, w;
  145. if (id >= FUNCTIONS_TOTAL || functions[id] < 0)
  146. {
  147. fputs("ERROR: call of unknown function\n",stderr);
  148. ok = 0;
  149. return;
  150. }
  151. switch (functions[id])
  152. {
  153. case F_BUTTON_PRESSED:
  154. x = CV(0); CPOP(1); CPUSH(SAF_buttonPressed(x)); break;
  155. case F_BUTTON_JUST_PRESSED:
  156. x = CV(0); CPOP(1); CPUSH(SAF_buttonJustPressed(x)); break;
  157. case F_SAVE: x = CV(0); y = CV(1); CPOP(2); SAF_save(y,x); break;
  158. case F_LOAD: x = CV(0); CPOP(1); CPUSH(SAF_load(x)); break;
  159. case F_PLAY_SOUND: SAF_playSound(CV(0)); CPOP(1); break;
  160. case F_FRAME: CPUSH(SAF_frame()); break;
  161. case F_TIME: CPUSH(SAF_time()); break;
  162. case F_RANDOM: CPUSH(SAF_random()); break;
  163. case F_RANDOM_SEED: x = CV(0); CPOP(1); SAF_randomSeed(x); break;
  164. case F_SIN: x = CV(0); CPOP(1); CPUSH(SAF_sin(x)); break;
  165. case F_COS: x = CV(0); CPOP(1); CPUSH(SAF_cos(x)); break;
  166. case F_SQRT: { uint32_t x32 = CV(0); CPOP(1); CPUSH(SAF_sqrt(x32)); break; }
  167. case F_CLEAR_SCREEN: SAF_clearScreen(CV(0)); CPOP(1); break;
  168. case F_DRAW_PIXEL:
  169. x = CV(0); y = CV(1); z = CV(2); CPOP(3); SAF_drawPixel(z,y,x); break;
  170. case F_DRAW_TEXT:
  171. {
  172. int8_t xs, ys;
  173. uint8_t l = 0;
  174. x = CV(0); y = CV(1);
  175. xs = CMN_unsignedToSignedNative(CV(2));
  176. ys = CMN_unsignedToSignedNative(CV(3));
  177. while (1)
  178. {
  179. if (l < HELPER_STRING_SIZE)
  180. helperString[l] = CV(l + 4);
  181. if (helperString[l] == 0)
  182. break;
  183. l++;
  184. }
  185. helperString[HELPER_STRING_SIZE - 1] = 0;
  186. CPOP(l + 5);
  187. SAF_drawText(helperString,ys,xs,y,x);
  188. break;
  189. }
  190. case F_COLOR_FROM_RGB:
  191. x = CV(0); y = CV(1); z = CV(2);
  192. CPOP(3); CPUSH(SAF_colorFromRGB(z,y,x));
  193. break;
  194. case F_COLOR_TO_RGB:
  195. x = CV(0); CPOP(1);
  196. SAF_colorToRGB(x,&y,&z,&w);
  197. CPUSH(w); CPUSH(z); CPUSH(y);
  198. break;
  199. case F_DRAW_RECT:
  200. {
  201. int8_t xs, ys, zs, ws;
  202. x = CV(0); y = CV(1);
  203. xs = CMN_unsignedToSignedNative(CV(2));
  204. ys = CMN_unsignedToSignedNative(CV(3));
  205. zs = CMN_unsignedToSignedNative(CV(4));
  206. ws = CMN_unsignedToSignedNative(CV(5));
  207. CPOP(6);
  208. SAF_drawRect(ws,zs,ys,xs,y,x);
  209. break;
  210. }
  211. case F_DRAW_LINE:
  212. case F_DRAW_CIRCLE:
  213. {
  214. int8_t xs, ys, zs, ws;
  215. x = CV(0);
  216. xs = CMN_unsignedToSignedNative(CV(1));
  217. ys = CMN_unsignedToSignedNative(CV(2));
  218. zs = CMN_unsignedToSignedNative(CV(3));
  219. ws = CMN_unsignedToSignedNative(CV(4));
  220. CPOP(5);
  221. if (functions[id] == F_DRAW_LINE)
  222. SAF_drawLine(ws,zs,ys,xs,x);
  223. else
  224. SAF_drawCircle(ws,zs,ys,xs,x);
  225. break;
  226. }
  227. case F_GET_FONT_CHARACTER:
  228. {
  229. uint8_t r[2];
  230. x = CV(0); CPOP(1);
  231. SAF_getFontCharacter(x,r);
  232. CPUSH(r[1]);
  233. CPUSH(r[0]);
  234. break;
  235. }
  236. case F_INT_TO_STR:
  237. {
  238. int v = CV(0); CPOP(1);
  239. const char *s = helperString;
  240. SAF_intToStr(v,helperString);
  241. while (*s != 0)
  242. s++;
  243. s--;
  244. CPUSH(0);
  245. while (s >= helperString)
  246. {
  247. CPUSH(*s);
  248. s--;
  249. }
  250. break;
  251. }
  252. case F_DRAW_IMAGE:
  253. case F_DRAW_IMAGE_COMPRESSED:
  254. {
  255. int8_t xs, ys;
  256. x = CV(0); y = CV(1);
  257. xs = CMN_unsignedToSignedNative(CV(2));
  258. ys = CMN_unsignedToSignedNative(CV(3));
  259. CPOP(4);
  260. loadImage(interp,helperImage,HELPER_STRING_SIZE,
  261. functions[id] == F_DRAW_IMAGE ? 0 : 1);
  262. if (functions[id] == F_DRAW_IMAGE)
  263. SAF_drawImage(helperImage,ys,xs,y,x);
  264. else
  265. SAF_drawImageCompressed(helperImage,ys,xs,y,x);
  266. break;
  267. }
  268. case F_DRAW_IMAGE_1BIT:
  269. {
  270. int8_t xs, ys;
  271. x = CV(0); y = CV(1); z = CV(2);
  272. CPOP(3);
  273. loadImage(interp,helperImage + HELPER_IMAGE_SIZE / 2,
  274. HELPER_IMAGE_SIZE / 2,2);
  275. xs = CMN_unsignedToSignedNative(CV(0));
  276. ys = CMN_unsignedToSignedNative(CV(1));
  277. CPOP(2);
  278. loadImage(interp,helperImage,HELPER_IMAGE_SIZE / 2,2);
  279. SAF_drawImage1Bit(helperImage,ys,xs,helperImage + HELPER_IMAGE_SIZE / 2,
  280. z,y,x);
  281. break;
  282. }
  283. case F_COLOR_TO_GRAYSCALE: x = CV(0); CPUSH(SAF_colorToGrayscale(x)); break;
  284. case F_COLOR_TO_1BIT: x = CV(0); CPUSH(SAF_colorTo1Bit(x)); break;
  285. case F_COLOR_INVERT: x = CV(0); CPUSH(SAF_colorInvert(x)); break;
  286. case F_COLOR_YELLOW: CPUSH(SAF_COLOR_YELLOW); break;
  287. case F_COLOR_BLACK: CPUSH(SAF_COLOR_BLACK); break;
  288. case F_COLOR_WHITE: CPUSH(SAF_COLOR_WHITE); break;
  289. case F_COLOR_GRAY: CPUSH(SAF_COLOR_GRAY); break;
  290. case F_COLOR_GRAY_DARK: CPUSH(SAF_COLOR_GRAY_DARK); break;
  291. case F_COLOR_RED: CPUSH(SAF_COLOR_RED); break;
  292. case F_COLOR_RED_DARK: CPUSH(SAF_COLOR_RED_DARK); break;
  293. case F_COLOR_GREEN: CPUSH(SAF_COLOR_GREEN); break;
  294. case F_COLOR_GREEN_DARK: CPUSH(SAF_COLOR_GREEN_DARK); break;
  295. case F_COLOR_BLUE: CPUSH(SAF_COLOR_BLUE); break;
  296. case F_COLOR_BLUE_DARK: CPUSH(SAF_COLOR_BLUE_DARK); break;
  297. case F_COLOR_ORANGE: CPUSH(SAF_COLOR_ORANGE); break;
  298. case F_COLOR_BROWN: CPUSH(SAF_COLOR_BROWN); break;
  299. case F_BUTTON_UP: CPUSH(SAF_BUTTON_UP); break;
  300. case F_BUTTON_DOWN: CPUSH(SAF_BUTTON_DOWN); break;
  301. case F_BUTTON_LEFT: CPUSH(SAF_BUTTON_LEFT); break;
  302. case F_BUTTON_RIGHT: CPUSH(SAF_BUTTON_RIGHT); break;
  303. case F_BUTTON_A: CPUSH(SAF_BUTTON_A); break;
  304. case F_BUTTON_B: CPUSH(SAF_BUTTON_B); break;
  305. case F_BUTTON_C: CPUSH(SAF_BUTTON_C); break;
  306. case F_SOUND_BEEP: CPUSH(SAF_SOUND_BEEP); break;
  307. case F_SOUND_CLICK: CPUSH(SAF_SOUND_CLICK); break;
  308. case F_SOUND_BOOM: CPUSH(SAF_SOUND_BOOM); break;
  309. case F_SOUND_BUMP: CPUSH(SAF_SOUND_BUMP); break;
  310. case F_TRANSFORM_NONE: CPUSH(SAF_TRANSFORM_NONE); break;
  311. case F_TRANSFORM_ROTATE_90: CPUSH(SAF_TRANSFORM_ROTATE_90); break;
  312. case F_TRANSFORM_ROTATE_180: CPUSH(SAF_TRANSFORM_ROTATE_180); break;
  313. case F_TRANSFORM_ROTATE_270: CPUSH(SAF_TRANSFORM_ROTATE_270); break;
  314. case F_TRANSFORM_FLIP: CPUSH(SAF_TRANSFORM_FLIP); break;
  315. case F_TRANSFORM_SCALE_2: CPUSH(SAF_TRANSFORM_SCALE_2); break;
  316. case F_TRANSFORM_SCALE_3: CPUSH(SAF_TRANSFORM_SCALE_3); break;
  317. case F_TRANSFORM_SCALE_4: CPUSH(SAF_TRANSFORM_SCALE_4); break;
  318. case F_TRANSFORM_INVERT: CPUSH(SAF_TRANSFORM_INVERT); break;
  319. case F_SCREEN_WIDTH: CPUSH(SAF_SCREEN_WIDTH); break;
  320. case F_SCREEN_HEIGHT: CPUSH(SAF_SCREEN_HEIGHT); break;
  321. case F_FPS: CPUSH(SAF_FPS); break;
  322. default: break;
  323. }
  324. }
  325. #undef CV
  326. #undef CPOP
  327. #undef CPUSH
  328. void SAF_init(void)
  329. {
  330. #if !PRECOMPILED
  331. CMN_compilerInit(&compiler,bytecodeMem,BYTECODEDMEM_SIZE,(char *) workingMem,
  332. WORKINGMEM_SIZE,0);
  333. FILE *f = fopen(GAME_FILE_NAME,"r");
  334. if (!f)
  335. {
  336. fputs("ERROR: couldn't open file \"" GAME_FILE_NAME "\"",stderr);
  337. ok = 0;
  338. }
  339. else
  340. {
  341. int line = 1;
  342. while (1)
  343. {
  344. int c = fgetc(f);
  345. if (c == '\n')
  346. line++;
  347. uint8_t cState = CMN_compilerFeedChar(&compiler,c == EOF ? 0 : c);
  348. if (cState != CMN_COMPILER_OK)
  349. {
  350. const char *errorStr = "unknown";
  351. switch (cState)
  352. {
  353. case CMN_COMPILER_ERROR_BAD_TOKEN: errorStr = "bad token"; break;
  354. case CMN_COMPILER_ERROR_UNEXPECTED_TOKEN: errorStr = "unexpected"; break;
  355. case CMN_COMPILER_ERROR_UNKNOWN_NAME: errorStr = "unknown name"; break;
  356. case CMN_COMPILER_ERROR_REDEFINED: errorStr = "symbol redefined"; break;
  357. case CMN_COMPILER_ERROR_UNEXPECTED_END: errorStr = "early end"; break;
  358. case CMN_COMPILER_ERROR_BYTECODE_TOO_BIG: errorStr = "program too big"; break;
  359. case CMN_COMPILER_ERROR_SYMBOL_TABLE: errorStr = "symbol table too small"; break;
  360. case CMN_COMPILER_ERROR_PARSE_STACK: errorStr = "parse stack overflow"; break;
  361. default: break;
  362. }
  363. fprintf(stderr,"ERROR: compilation failed, line %d: %s\n",line,errorStr);
  364. ok = 0;
  365. break;
  366. }
  367. if (c == EOF)
  368. break;
  369. }
  370. fclose(f);
  371. if (ok)
  372. {
  373. CMN_bytecodeOptimize(bytecodeMem,
  374. CMN_OPTIMIZE_REMOVE_NOPS | CMN_OPTIMIZE_INLINE |
  375. CMN_OPTIMIZE_REPLACE_OPS,&compiler);
  376. loopFunctionID = CMN_compilerFindFunction(&compiler,"SAF_loop",0);
  377. if (loopFunctionID < 0)
  378. {
  379. fputs("ERROR: no \"SAF_loop\" function\n",stderr);
  380. ok = 0;
  381. }
  382. else
  383. {
  384. for (uint8_t i = 0; i < FUNCTIONS_TOTAL; ++i)
  385. functions[i] = -1;
  386. int8_t id;
  387. #define FIND_FUNC(f,c)\
  388. id = CMN_compilerFindFunction(&compiler,f,1); \
  389. if (id >= 0 && id < FUNCTIONS_TOTAL) functions[id] = c;
  390. FIND_FUNC("SAF_buttonPressed",F_BUTTON_PRESSED)
  391. FIND_FUNC("SAF_buttonJustPressed",F_BUTTON_JUST_PRESSED)
  392. FIND_FUNC("SAF_playSound",F_PLAY_SOUND)
  393. FIND_FUNC("SAF_save",F_SAVE)
  394. FIND_FUNC("SAF_load",F_LOAD)
  395. FIND_FUNC("SAF_frame",F_FRAME)
  396. FIND_FUNC("SAF_time",F_TIME)
  397. FIND_FUNC("SAF_random",F_RANDOM)
  398. FIND_FUNC("SAF_randomSeed",F_RANDOM_SEED)
  399. FIND_FUNC("SAF_sin",F_SIN)
  400. FIND_FUNC("SAF_cos",F_COS)
  401. FIND_FUNC("SAF_sqrt",F_SQRT)
  402. FIND_FUNC("SAF_colorFromRGB",F_COLOR_FROM_RGB)
  403. FIND_FUNC("SAF_colorToRGB",F_COLOR_TO_RGB)
  404. FIND_FUNC("SAF_colorToGrayscale",F_COLOR_TO_GRAYSCALE)
  405. FIND_FUNC("SAF_colorTo1Bit",F_COLOR_TO_1BIT)
  406. FIND_FUNC("SAF_colorInvert",F_COLOR_INVERT)
  407. FIND_FUNC("SAF_drawPixel",F_DRAW_PIXEL)
  408. FIND_FUNC("SAF_drawRect",F_DRAW_RECT)
  409. FIND_FUNC("SAF_drawLine",F_DRAW_LINE)
  410. FIND_FUNC("SAF_drawCircle",F_DRAW_CIRCLE)
  411. FIND_FUNC("SAF_clearScreen",F_CLEAR_SCREEN)
  412. FIND_FUNC("SAF_drawText",F_DRAW_TEXT)
  413. FIND_FUNC("SAF_getFontCharacter",F_GET_FONT_CHARACTER)
  414. FIND_FUNC("SAF_drawImage",F_DRAW_IMAGE)
  415. FIND_FUNC("SAF_drawImageCompressed",F_DRAW_IMAGE_COMPRESSED)
  416. FIND_FUNC("SAF_drawImage1Bit",F_DRAW_IMAGE_1BIT)
  417. FIND_FUNC("SAF_intToStr",F_INT_TO_STR)
  418. FIND_FUNC("SAF_BUTTON_UP",F_BUTTON_UP)
  419. FIND_FUNC("SAF_BUTTON_RIGHT",F_BUTTON_RIGHT)
  420. FIND_FUNC("SAF_BUTTON_DOWN",F_BUTTON_DOWN)
  421. FIND_FUNC("SAF_BUTTON_LEFT",F_BUTTON_LEFT)
  422. FIND_FUNC("SAF_BUTTON_A",F_BUTTON_A)
  423. FIND_FUNC("SAF_BUTTON_B",F_BUTTON_B)
  424. FIND_FUNC("SAF_BUTTON_C",F_BUTTON_C)
  425. FIND_FUNC("SAF_COLOR_BLACK",F_COLOR_BLACK)
  426. FIND_FUNC("SAF_COLOR_WHITE",F_COLOR_WHITE)
  427. FIND_FUNC("SAF_COLOR_GRAY",F_COLOR_GRAY)
  428. FIND_FUNC("SAF_COLOR_GRAY_DARK",F_COLOR_GRAY_DARK)
  429. FIND_FUNC("SAF_COLOR_RED",F_COLOR_RED)
  430. FIND_FUNC("SAF_COLOR_RED_DARK",F_COLOR_RED_DARK)
  431. FIND_FUNC("SAF_COLOR_GREEN",F_COLOR_GREEN)
  432. FIND_FUNC("SAF_COLOR_GREEN_DARK",F_COLOR_GREEN_DARK)
  433. FIND_FUNC("SAF_COLOR_BLUE",F_COLOR_BLUE)
  434. FIND_FUNC("SAF_COLOR_BLUE_DARK",F_COLOR_BLUE_DARK)
  435. FIND_FUNC("SAF_COLOR_YELLOW",F_COLOR_YELLOW)
  436. FIND_FUNC("SAF_COLOR_ORANGE",F_COLOR_ORANGE)
  437. FIND_FUNC("SAF_COLOR_BROWN",F_COLOR_BROWN)
  438. FIND_FUNC("SAF_SOUND_BEEP",F_SOUND_BEEP)
  439. FIND_FUNC("SAF_SOUND_CLICK",F_SOUND_CLICK)
  440. FIND_FUNC("SAF_SOUND_BOOM",F_SOUND_BOOM)
  441. FIND_FUNC("SAF_SOUND_BUMP",F_SOUND_BUMP)
  442. FIND_FUNC("SAF_TRANSFORM_NONE",F_TRANSFORM_NONE)
  443. FIND_FUNC("SAF_TRANSFORM_ROTATE_90",F_TRANSFORM_ROTATE_90)
  444. FIND_FUNC("SAF_TRANSFORM_ROTATE_180",F_TRANSFORM_ROTATE_180)
  445. FIND_FUNC("SAF_TRANSFORM_ROTATE_270",F_TRANSFORM_ROTATE_270)
  446. FIND_FUNC("SAF_TRANSFORM_FLIP",F_TRANSFORM_FLIP)
  447. FIND_FUNC("SAF_TRANSFORM_SCALE_2",F_TRANSFORM_SCALE_2)
  448. FIND_FUNC("SAF_TRANSFORM_SCALE_3",F_TRANSFORM_SCALE_3)
  449. FIND_FUNC("SAF_TRANSFORM_SCALE_4",F_TRANSFORM_SCALE_4)
  450. FIND_FUNC("SAF_TRANSFORM_INVERT",F_TRANSFORM_INVERT)
  451. FIND_FUNC("SAF_SCREEN_WIDTH",F_SCREEN_WIDTH)
  452. FIND_FUNC("SAF_SCREEN_HEIGHT",F_SCREEN_HEIGHT)
  453. FIND_FUNC("SAF_FPS",F_FPS)
  454. #undef FIND_FUNC
  455. // now print the compiled bytecode (for precompiled version)
  456. puts("Compiled data follows (for making a precompiled version):");
  457. puts("#define PRECOMPILED 1");
  458. printf("int32_t loopFunctionID = %d;\n",loopFunctionID);
  459. unsigned int realSize = 0;
  460. for (uint32_t i = 0; i < BYTECODEDMEM_SIZE; i += 2)
  461. {
  462. realSize += 2;
  463. if (i > CMN_BYTECODE_HEADER_SIZE && bytecodeMem[i] == CMN_OPCODE_END)
  464. break;
  465. }
  466. printf("#define BYTECODEDMEM_SIZE %d\n",realSize);
  467. printf("uint8_t bytecodeMem[BYTECODEDMEM_SIZE] = {");
  468. for (uint32_t i = 0; i < realSize; ++i)
  469. {
  470. if (i != 0)
  471. putchar(',');
  472. if (i % 32 == 0)
  473. printf("\n ");
  474. printf("%d",bytecodeMem[i]);
  475. }
  476. printf("};\nint8_t functions[] = {");
  477. for (uint32_t i = 0; i < FUNCTIONS_TOTAL; ++i)
  478. {
  479. if (i != 0)
  480. putchar(',');
  481. if (i % 32 == 0)
  482. printf("\n ");
  483. printf("%d",functions[i]);
  484. }
  485. puts("};");
  486. #endif
  487. if (!CMN_interpreterInit(&interpreter,bytecodeMem,workingMem,
  488. WORKINGMEM_SIZE,64,ioFunction,functionCall,0,0))
  489. {
  490. fputs("ERROR: couldn't initialize interpreter\n",stderr);
  491. ok = 0;
  492. }
  493. else if (CMN_interpreterStep(&interpreter,0) != CMN_INTERPRETER_END)
  494. {
  495. fputs("ERROR: runtime error during initialization\n",stderr);
  496. ok = 0;
  497. }
  498. #if !PRECOMPILED
  499. }
  500. }
  501. }
  502. #endif
  503. }
  504. uint8_t SAF_loop()
  505. {
  506. if (ok)
  507. {
  508. CMN_interpreterCallFunction(&interpreter,loopFunctionID);
  509. uint8_t interpreterState = CMN_interpreterStep(&interpreter,0);
  510. if (interpreterState != CMN_INTERPRETER_END)
  511. {
  512. #if !PRECOMPILED
  513. fputs("ERROR: error at runtime: ",stderr);
  514. switch(interpreterState)
  515. {
  516. case CMN_INTERPRETER_ERROR_CALLSTACK:
  517. fputs("call stack overflow",stderr); break;
  518. case CMN_INTERPRETER_ERROR_STACK_OF:
  519. fputs("stack overflow",stderr); break;
  520. case CMN_INTERPRETER_ERROR_ZERODIV:
  521. fputs("division by zero",stderr); break;
  522. default: fputs("unknown",stderr); break;
  523. }
  524. fputc('\n',stderr);
  525. #endif
  526. ok = 0;
  527. }
  528. }
  529. else
  530. {
  531. SAF_clearScreen(SAF_COLOR_RED);
  532. SAF_drawText("ERROR",6,17,SAF_COLOR_BLACK,2);
  533. }
  534. return 1;
  535. }