ugl_bc.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. ugl_bc.c
  3. items can be at three places
  4. 1) map
  5. 2) inventory
  6. 3) hero
  7. map --> inventory take
  8. inventory --> map drop
  9. inventory --> hero equip
  10. hero --> inventory unequip
  11. hero --> map drop
  12. inputs:
  13. hDir() // direction into which the hero wants to walk, had waked or looks
  14. iDir() // direction into which the item/creatue/missel wants to go, went or looks
  15. hX() // hero X position
  16. hY() // hero Y position
  17. posByH // set current position to the position of the hero
  18. posByI // set current position to the position of the current item
  19. posAppyDir(dir) // change the possition going one step into the specified direction
  20. */
  21. #include "ugl_bc.h"
  22. #include <stdio.h>
  23. #include <assert.h>
  24. #ifndef UGL_TEST
  25. #include "item.h"
  26. #include "map.h"
  27. #endif
  28. void bc_push_on_arg_stack(bc_t *bc, uint16_t val)
  29. {
  30. bc->arg_stack[bc->arg_stack_pointer] = val;
  31. bc->arg_stack_pointer++;
  32. }
  33. uint16_t bc_pop_from_arg_stack(bc_t *bc)
  34. {
  35. assert( bc->arg_stack_pointer > 0 );
  36. bc->arg_stack_pointer--;
  37. return bc->arg_stack[bc->arg_stack_pointer] ;
  38. }
  39. void bc_duplicate_arg_stack_top_value(bc_t *bc)
  40. {
  41. bc->arg_stack[bc->arg_stack_pointer] = bc->arg_stack[bc->arg_stack_pointer-1];
  42. bc->arg_stack_pointer++;
  43. }
  44. void bc_push_on_return_stack(bc_t *bc, uint16_t val)
  45. {
  46. bc->return_stack[bc->return_stack_pointer] = val;
  47. bc->return_stack_pointer++;
  48. }
  49. uint16_t bc_pop_from_return_stack(bc_t *bc)
  50. {
  51. assert( bc->return_stack_pointer > 0 );
  52. bc->return_stack_pointer--;
  53. return bc->return_stack[bc->return_stack_pointer];
  54. }
  55. uint16_t bc_get_value(uint8_t *code)
  56. {
  57. uint16_t val;
  58. val = *code;
  59. code++;
  60. val <<= 8;
  61. val |= *code;
  62. code++;
  63. return val;
  64. }
  65. void bc_init(bc_t *bc)
  66. {
  67. bc->arg_stack_pointer = 0;
  68. bc->return_stack_pointer = 0;
  69. }
  70. #define BC_DBG_OUT_POS(pos) printf("%05d ", (int)(pos))
  71. #define BC_DBG_OUT_HEX(c) printf("0x%02x ", (int)(c))
  72. #define BC_DBG_OUT_STR(str) printf("%s ", (str))
  73. #define BC_DBG_OUT_NUM(n) printf("%d ", (int)(n))
  74. #define BC_DBG_OUT_NUM3(n) printf("%03d ", (int)(n))
  75. #define BC_DBG_OUT_CR() printf("\n")
  76. void bc_exec(bc_t *bc, uint8_t *code, uint16_t pos)
  77. {
  78. uint16_t val;
  79. uint8_t cmd;
  80. bc_init(bc);
  81. bc->code = code;
  82. bc->code_pos = pos;
  83. for(;;)
  84. {
  85. cmd = bc->code[bc->code_pos];
  86. BC_DBG_OUT_POS(bc->code_pos);
  87. BC_DBG_OUT_NUM3(bc->arg_stack_pointer);
  88. BC_DBG_OUT_HEX(cmd);
  89. bc->code_pos++;
  90. val = cmd;
  91. val &=0x0f0; /* put upper four bit as upper 4bit of the 12bit value into val */
  92. val <<= 4;
  93. switch(cmd&15)
  94. {
  95. case BC_CMD_LOAD_12BIT:
  96. BC_DBG_OUT_STR("LOAD12");
  97. val |= bc->code[bc->code_pos];
  98. BC_DBG_OUT_NUM(val);
  99. bc->code_pos++;
  100. bc_push_on_arg_stack(bc, val);
  101. BC_DBG_OUT_CR();
  102. break;
  103. case BC_CMD_CALL_BUILDIN:
  104. BC_DBG_OUT_STR("CALL BUILDIN");
  105. val |= bc->code[bc->code_pos];
  106. BC_DBG_OUT_NUM(val);
  107. bc->code_pos++;
  108. BC_DBG_OUT_CR();
  109. bc_buildin_list[val](bc);
  110. break;
  111. case BC_CMD_CALL_BUILDIN_POP_STACK:
  112. BC_DBG_OUT_STR("CALL BUILDIN POP ARG STACK");
  113. val |= bc->code[bc->code_pos];
  114. BC_DBG_OUT_NUM(val);
  115. bc->code_pos++;
  116. BC_DBG_OUT_CR();
  117. bc_buildin_list[val](bc);
  118. bc_pop_from_arg_stack(bc);
  119. break;
  120. case BC_CMD_BRANCH:
  121. BC_DBG_OUT_STR("BRANCH");
  122. val |= bc->code[bc->code_pos];
  123. bc->code_pos++;
  124. if ( val < 0x0800 )
  125. {
  126. bc->code_pos += val;
  127. }
  128. else
  129. {
  130. val = 0x1000 - val;
  131. bc->code_pos -= val;
  132. }
  133. BC_DBG_OUT_POS(bc->code_pos);
  134. BC_DBG_OUT_CR();
  135. case BC_CMD_POP_ARG_STACK:
  136. cmd >>= 4; /* in this case we need the lower 4 bit */
  137. BC_DBG_OUT_STR("POP ARG STACK");
  138. cmd++; /* cmd is reused as a counter for the number of stack pops */
  139. BC_DBG_OUT_NUM(cmd);
  140. do
  141. {
  142. bc_pop_from_arg_stack(bc);
  143. cmd--;
  144. } while( cmd > 0 );
  145. BC_DBG_OUT_CR();
  146. break;
  147. case BC_CMD_PUSH_ARG_STACK:
  148. cmd >>= 4; /* in this case we need the lower 4 bit */
  149. BC_DBG_OUT_STR("PUSH ARG STACK");
  150. cmd++; /* cmd is reused as a counter for the number of stack pops */
  151. BC_DBG_OUT_NUM(cmd);
  152. do
  153. {
  154. bc_push_on_arg_stack(bc, 0);
  155. cmd--;
  156. } while( cmd > 0 );
  157. BC_DBG_OUT_CR();
  158. break;
  159. case BC_CMD_CALL_PROCEDURE:
  160. BC_DBG_OUT_STR("CALL PROC");
  161. cmd >>= 4; /* in this case we need the lower 4 bit--> number of args */
  162. BC_DBG_OUT_NUM(cmd); /* output number of args */
  163. val = bc->code[bc->code_pos];
  164. bc->code_pos++;
  165. val <<= 8;
  166. val |= bc->code[bc->code_pos];
  167. bc->code_pos++;
  168. bc_push_on_return_stack(bc, bc->code_pos); /* return position */
  169. bc_push_on_return_stack(bc, bc->arg_stack_pointer - cmd -1); /* store the start pos of the return value and the args */
  170. bc->code_pos = val;
  171. BC_DBG_OUT_NUM(bc->code_pos);
  172. BC_DBG_OUT_CR();
  173. break;
  174. default: /* assume 0x0f, extended command */
  175. switch( cmd )
  176. {
  177. case BC_CMD_LOAD_0:
  178. BC_DBG_OUT_STR("LOAD#0");
  179. bc_push_on_arg_stack(bc, 0);
  180. BC_DBG_OUT_CR();
  181. break;
  182. case BC_CMD_LOAD_1:
  183. BC_DBG_OUT_STR("LOAD#1");
  184. bc_push_on_arg_stack(bc, 1);
  185. BC_DBG_OUT_CR();
  186. break;
  187. case BC_CMD_LOAD_16BIT:
  188. BC_DBG_OUT_STR("LOAD16");
  189. val = bc->code[bc->code_pos];
  190. bc->code_pos++;
  191. val <<= 8;
  192. val |= bc->code[bc->code_pos];
  193. bc->code_pos++;
  194. bc_push_on_arg_stack(bc, val);
  195. BC_DBG_OUT_NUM(val);
  196. BC_DBG_OUT_CR();
  197. break;
  198. case BC_CMD_RETURN_FROM_PROCEDURE:
  199. BC_DBG_OUT_STR("RETURN to");
  200. if ( bc->return_stack_pointer == 0 )
  201. {
  202. BC_DBG_OUT_STR("exit");
  203. BC_DBG_OUT_CR();
  204. BC_DBG_OUT_STR("arg stack: ");
  205. BC_DBG_OUT_NUM(bc->arg_stack_pointer);
  206. BC_DBG_OUT_CR();
  207. BC_DBG_OUT_STR("return stack: ");
  208. BC_DBG_OUT_NUM(bc->return_stack_pointer);
  209. BC_DBG_OUT_CR();
  210. return; /* stop execution */
  211. }
  212. //bc_push_on_arg_stack(bc, bc_pop_from_return_stack(bc)); /* copy return value on arg stack */
  213. bc->arg_stack_pointer = bc_pop_from_return_stack(bc) + 1; /* restore the arg stack pointer, leave return value on stack */
  214. bc->code_pos = bc_pop_from_return_stack(bc);
  215. BC_DBG_OUT_NUM(bc->code_pos);
  216. BC_DBG_OUT_CR();
  217. break;
  218. case BC_CMD_JUMP_NOT_ZERO:
  219. BC_DBG_OUT_STR("JUMP NZ");
  220. val = bc->code[bc->code_pos];
  221. bc->code_pos++;
  222. val <<= 8;
  223. val |= bc->code[bc->code_pos];
  224. bc->code_pos++;
  225. if ( bc_pop_from_arg_stack(bc) != 0 )
  226. bc->code_pos = val;
  227. break;
  228. BC_DBG_OUT_NUM(bc->code_pos);
  229. BC_DBG_OUT_CR();
  230. case BC_CMD_JUMP_ZERO:
  231. BC_DBG_OUT_STR("JUMP Z");
  232. val = bc->code[bc->code_pos];
  233. bc->code_pos++;
  234. val <<= 8;
  235. val |= bc->code[bc->code_pos];
  236. bc->code_pos++;
  237. if ( bc_pop_from_arg_stack(bc) == 0 )
  238. bc->code_pos = val;
  239. BC_DBG_OUT_NUM(bc->code_pos);
  240. BC_DBG_OUT_CR();
  241. break;
  242. case BC_CMD_CALL_PROCEDURE:
  243. BC_DBG_OUT_STR("CALL PROC");
  244. val = bc->code[bc->code_pos];
  245. bc->code_pos++;
  246. val <<= 8;
  247. val |= bc->code[bc->code_pos];
  248. bc->code_pos++;
  249. bc_push_on_return_stack(bc, bc->code_pos); /* return position */
  250. bc_push_on_return_stack(bc, 0); /* return value */
  251. bc->code_pos = val;
  252. BC_DBG_OUT_NUM(bc->code_pos);
  253. BC_DBG_OUT_CR();
  254. break;
  255. /*
  256. case BC_CMD_POP_ARG_STACK:
  257. BC_DBG_OUT_STR("POP ARG STACK");
  258. BC_DBG_OUT_CR();
  259. bc_pop_from_arg_stack(bc);
  260. break;
  261. */
  262. default:
  263. break;
  264. }
  265. break;
  266. } /* switch() */
  267. } /* for(;;) */
  268. }
  269. /*======================================================*/
  270. /* put top of stack into register a, reduce stack */
  271. //void bc_pop_a(bc_t *bc)
  272. //{
  273. // bc->stack_pointer--;
  274. // bc->a = bc->stack[bc->stack_pointer];
  275. //}
  276. /*======================================================*/
  277. /* return a pointer to a variable on the arg stack within the current stack frame */
  278. /* pos = 0 is the return value of a user function, pos = 1... are the args for that function */
  279. uint16_t *bc_get_stack_frame_address(bc_t *bc, uint8_t pos)
  280. {
  281. return bc->arg_stack + bc->return_stack[bc->return_stack_pointer-1] + pos ;
  282. }
  283. void bc_fn_nop(bc_t *bc)
  284. {
  285. bc_push_on_arg_stack(bc, 0);
  286. }
  287. /* description: "return" sets the return value of a procedure. If used inside an expresion, it returns its argument */
  288. /* assign return value for a user defined function */
  289. /* identical to arg(0) */
  290. void bc_fn_return(bc_t *bc)
  291. {
  292. bc_duplicate_arg_stack_top_value(bc); /* goal is to leave a value on the stack */
  293. *bc_get_stack_frame_address(bc, 0) = bc_pop_from_arg_stack(bc);
  294. /*
  295. v = bc_pop_from_arg_stack(bc);
  296. bc_push_on_arg_stack(bc, v);
  297. bc_pop_from_return_stack(bc);
  298. bc_push_on_return_stack(bc, v);
  299. */
  300. }
  301. void bc_fn_print(bc_t *bc)
  302. {
  303. bc_duplicate_arg_stack_top_value(bc); /* goal is to leave a value on the stack */
  304. printf("%u\n", bc_pop_from_arg_stack(bc));
  305. }
  306. /* return an argument of a user defined procedure */
  307. void bc_fn_arg1(bc_t *bc)
  308. {
  309. bc_push_on_arg_stack(bc, *bc_get_stack_frame_address(bc, bc_pop_from_arg_stack(bc)));
  310. }
  311. /* remove the top element from the stack and return the same */
  312. void bc_fn_arg2(bc_t *bc)
  313. {
  314. uint16_t v = bc_pop_from_arg_stack(bc); /* the value, which should be assigned */
  315. *bc_get_stack_frame_address(bc, bc_pop_from_arg_stack(bc)) = v;
  316. bc_push_on_arg_stack(bc, v); /* push the value back on the stack */
  317. }
  318. void bc_fn_add(bc_t *bc)
  319. {
  320. uint16_t v;
  321. v = bc_pop_from_arg_stack(bc);
  322. v += bc_pop_from_arg_stack(bc);
  323. bc_push_on_arg_stack(bc, v);
  324. }
  325. #ifndef UGL_TEST
  326. pos_t bc_pos;
  327. #endif
  328. void bc_fn_setPos(bc_t *bc)
  329. {
  330. uint8_t x, y;
  331. y = bc_pop_from_arg_stack(bc);
  332. x = bc_pop_from_arg_stack(bc);
  333. #ifndef UGL_TEST
  334. bc_pos.x = x;
  335. bc_pos.y = y;
  336. #endif
  337. bc_push_on_arg_stack(bc, 0);
  338. }
  339. void bc_fn_setItemPos(bc_t *bc)
  340. {
  341. uint8_t i;
  342. i = bc_pop_from_arg_stack(bc);
  343. #ifndef UGL_TEST
  344. pool_GetItem(i)->pos = bc_pos;
  345. printf("item %d new x=%d y=%d\n", i, bc_pos.x, bc_pos.y);
  346. #endif
  347. bc_push_on_arg_stack(bc, i);
  348. }
  349. /*======================================================*/
  350. bc_buildin_fn bc_buildin_list[] =
  351. {
  352. /* 0 */ bc_fn_nop,
  353. /* 1 */ bc_fn_return,
  354. /* 2 */ bc_fn_arg1, /* one argument */
  355. /* 3 */ bc_fn_arg2, /* two arguments */
  356. /* 4 */ bc_fn_add,
  357. /* 5 */ bc_fn_print,
  358. /* 6 */ bc_fn_setPos, /* two args: x & y*/
  359. /* 7 */ bc_fn_setItemPos, /* one args: item */
  360. };