stppc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /**
  2. This is a simple SAF frontend for Simon Tatham's Portable Puzzle Collection.
  3. Not all games work, the frontend is KISS and not 100% compliant, some games
  4. can't bear the low resolution.
  5. At start input is in normal mode, C button toggles mouse emulation. If mouse
  6. emulation is active, going completely to the righ brings up menu with
  7. options to start new game, undo, solve, write digits etc.
  8. how to:
  9. 1. clone the STPPC
  10. 2. copy this file and saf.h to that directory
  11. 3. compile specific games e.g. as:
  12. gcc -O3 -DSAF_PLATFORM_SDL2 -DGAME_NAME=\"game.c\" \
  13. -lm -lSDL2 -o game stppc.c
  14. game stats:
  15. - workikng (fully or with very tiny glitches):
  16. cube, untangle, fifteen, pegs, unequal, samegame, unruly, lightup,
  17. netslide, mosaic, singles, palisade
  18. - kinda working (minor glitches but playable):
  19. twiddle, dominosa, sixteen, pearl, towers, rect, range, tents, galaxies,
  20. inertia, undead
  21. - not working (unplayable):
  22. blackbox, bridges, map, mines, filling, flip (icons too small to see),
  23. net (too tiny), solo, slant (too tiny), tracks (divide by zero,
  24. possible bug due to small screen?), keen, loopy (too tiny),
  25. guess (not sure), magnets (almost works), signpost, pattern (tiny AF)
  26. This file is by drummyfish, released under CC0 (the puzzle collection itself
  27. is not included here and is available under different license).
  28. */
  29. #define memswap _memswp // prevent name collision
  30. #include "sort.c"
  31. #undef memswap
  32. #include "loopgen.h" // include everything!
  33. #include "loopgen.c"
  34. #include "penrose.h"
  35. #include "penrose.c"
  36. #include "grid.h"
  37. #include "grid.c"
  38. #include "tdq.c"
  39. #include "combi.c"
  40. #include "laydomino.c"
  41. #include "findloop.c"
  42. #include "tree234.c"
  43. #include "latin.c"
  44. #include "version.c"
  45. #include "malloc.c"
  46. #include "misc.c"
  47. #include "drawing.c"
  48. #include "printing.c"
  49. #include "midend.c"
  50. #include "random.c"
  51. #include "matching.h"
  52. #include "matching.c"
  53. #include "dsf.c"
  54. #include "divvy.c"
  55. #include "puzzles.h"
  56. #define encode_params _encp1 // prevent name collision
  57. #define grid_type _gridt // name collision in bridges.c
  58. #include GAME_NAME
  59. #define SAF_PROGRAM_NAME "STPPC " GAME_NAME
  60. #define SAF_SETTING_ENABLE_SOUND 0
  61. #define SAF_SETTING_ENABLE_SAVES 0
  62. #include "saf.h"
  63. #define MAX_COLORS 32
  64. #define BAR_WIDTH 5
  65. #define BAR_MAX_LENGTH 64
  66. #define DEFAULT_COLOR SAF_COLOR_GRAY
  67. #define GAME_MENU_ITEMS (10 + 3)
  68. midend *middleEnd;
  69. char barText[BAR_MAX_LENGTH + 1];
  70. uint8_t colors[MAX_COLORS];
  71. int colorCount;
  72. uint8_t inputEmulation = 0;
  73. uint8_t gameMenuItem = 0;
  74. uint8_t cursorPos[2];
  75. uint8_t cursorButtons[2];
  76. int16_t clipRect[4];
  77. int sw = SAF_SCREEN_WIDTH;
  78. int sh = SAF_SCREEN_HEIGHT;
  79. struct blitter
  80. {
  81. uint8_t dummy;
  82. };
  83. struct blitter safBlitter;
  84. char getGameMenuItem(int index)
  85. {
  86. index %= GAME_MENU_ITEMS;
  87. switch (index)
  88. {
  89. case 0: return 'N'; break;
  90. case 1: return 'U'; break;
  91. case 2: return 'S'; break;
  92. default:
  93. return '0' + index - 4;
  94. break;
  95. }
  96. }
  97. void drawCursor(void)
  98. {
  99. SAF_drawPixel(cursorPos[0],cursorPos[1],255);
  100. for (int i = 1; i <= 2; ++i)
  101. {
  102. SAF_drawPixel(cursorPos[0] - i,cursorPos[1],0);
  103. SAF_drawPixel(cursorPos[0] + i,cursorPos[1],0);
  104. SAF_drawPixel(cursorPos[0],cursorPos[1] - i,0);
  105. SAF_drawPixel(cursorPos[0],cursorPos[1] + i,0);
  106. }
  107. if (cursorPos[0] > SAF_SCREEN_WIDTH - BAR_WIDTH)
  108. {
  109. SAF_drawRect(SAF_SCREEN_WIDTH - BAR_WIDTH,0,BAR_WIDTH,
  110. SAF_SCREEN_HEIGHT,SAF_COLOR_WHITE,1);
  111. char mt[2];
  112. mt[1] = 0;
  113. for (int i = 0; i < SAF_SCREEN_HEIGHT / 5; ++i)
  114. {
  115. mt[0] = getGameMenuItem(gameMenuItem + i);
  116. SAF_drawText(mt,SAF_SCREEN_WIDTH - BAR_WIDTH + 1,1 + i * 5,
  117. (mt[0] >= 'A' && mt[0] <= 'Z') ? SAF_COLOR_BLUE : SAF_COLOR_BLACK,1);
  118. }
  119. SAF_drawRect(SAF_SCREEN_WIDTH - BAR_WIDTH,0,BAR_WIDTH,6,
  120. SAF_COLOR_GREEN_DARK,0);
  121. }
  122. }
  123. int pointNotClipped(int x, int y)
  124. {
  125. return (x >= clipRect[0] && x < clipRect[2] &&
  126. y >= clipRect[1] && y < clipRect[3]);
  127. }
  128. void deactivate_timer(frontend *fe)
  129. {
  130. }
  131. void activate_timer(frontend *fe)
  132. {
  133. }
  134. void fatal(const char *fmt, ...)
  135. {
  136. }
  137. void frontend_default_colour(frontend *fe, float *output)
  138. {
  139. uint8_t r, g, b;
  140. SAF_colorToRGB(DEFAULT_COLOR,&r,&g,&b);
  141. output[0] = ((float) r) / 255.0;
  142. output[1] = ((float) g) / 255.0;
  143. output[2] = ((float) b) / 255.0;
  144. }
  145. void get_random_seed(void **randseed, int *randseedsize)
  146. {
  147. *randseed = malloc(4);
  148. **((uint32_t **) randseed) = SAF_time();
  149. *randseedsize = 4;
  150. }
  151. static void saf_status_bar(void *handle, const char *text)
  152. {
  153. int i = 0;
  154. while (*text != 0 && i < BAR_MAX_LENGTH)
  155. {
  156. barText[i] = *text;
  157. text++;
  158. i++;
  159. }
  160. barText[i] = 0;
  161. }
  162. static blitter *saf_blitter_new(void *handle, int w, int h)
  163. {
  164. return &safBlitter;
  165. }
  166. static void saf_blitter_free(void *handle, blitter *bl)
  167. {
  168. }
  169. static void saf_blitter_save(void *handle, blitter *bl, int x, int y)
  170. {
  171. }
  172. static void saf_blitter_load(void *handle, blitter *bl, int x, int y)
  173. {
  174. }
  175. static void saf_set_brush(frontend *fe, int colour)
  176. {
  177. }
  178. static void saf_reset_brush(frontend *fe)
  179. {
  180. }
  181. static void saf_set_pen(frontend *fe, int colour, int thin)
  182. {
  183. }
  184. static void saf_reset_pen(frontend *fe)
  185. {
  186. }
  187. static void saf_clip(void *handle, int x, int y, int w, int h)
  188. {
  189. clipRect[0] = x;
  190. clipRect[1] = y;
  191. clipRect[2] = x + w;
  192. clipRect[3] = y + h;
  193. }
  194. static void saf_unclip(void *handle)
  195. {
  196. clipRect[0] = -1000;
  197. clipRect[1] = -1000;
  198. clipRect[2] = 1000;
  199. clipRect[3] = 1000;
  200. }
  201. static void saf_draw_text(void *handle, int x, int y, int fonttype,
  202. int fontsize, int align, int colour, const char *text)
  203. {
  204. int l = 0;
  205. const char *t = text;
  206. while (*t != 0)
  207. {
  208. l++;
  209. t++;
  210. }
  211. if (align & ALIGN_HCENTRE)
  212. x -= (l * 5) / 2;
  213. if (align & ALIGN_VCENTRE)
  214. y -= 2;
  215. #define TOLERANCE 2
  216. if (pointNotClipped(x + TOLERANCE,y + TOLERANCE) &&
  217. pointNotClipped(x + l * 5 - TOLERANCE,y + 4 - TOLERANCE))
  218. SAF_drawText(text,x,y,colors[colour],1);
  219. }
  220. static void saf_draw_rect(void *handle, int x, int y, int w, int h, int colour)
  221. {
  222. w += x;
  223. h += y;
  224. if (x < clipRect[0])
  225. x = clipRect[0];
  226. else if (x > clipRect[2])
  227. x = clipRect[2];
  228. if (y < clipRect[1])
  229. y = clipRect[1];
  230. else if (y > clipRect[3])
  231. y = clipRect[3];
  232. if (w < clipRect[0])
  233. w = clipRect[0];
  234. else if (w > clipRect[2])
  235. w = clipRect[2];
  236. if (h < clipRect[1])
  237. h = clipRect[1];
  238. else if (h > clipRect[3])
  239. h = clipRect[3];
  240. w -= x;
  241. h -= y;
  242. SAF_drawRect(x,y,w,h,colors[colour],1);
  243. }
  244. static void saf_draw_line(void *handle, int x1, int y1, int x2, int y2,
  245. int colour)
  246. {
  247. // TODO: points could actually be clipped and drawn
  248. if (pointNotClipped(x1,y1) && pointNotClipped(x2,y2))
  249. SAF_drawLine(x1,y1,x2,y2,colors[colour]);
  250. }
  251. void saf_draw_thick_line(void *handle, float thickness, float x1, float y1,
  252. float x2, float y2, int colour)
  253. {
  254. if (pointNotClipped(x1,y1) && pointNotClipped(x2,y2))
  255. SAF_drawLine(x1,y1,x2,y2,colors[colour]);
  256. }
  257. static void saf_draw_circle(void *handle, int cx, int cy, int radius,
  258. int fillcolour, int outlinecolour)
  259. {
  260. if (pointNotClipped(cx,cy))
  261. {
  262. if (fillcolour >= 0)
  263. SAF_drawCircle(cx,cy,radius,colors[fillcolour],1);
  264. SAF_drawCircle(cx,cy,radius,colors[outlinecolour],0);
  265. }
  266. }
  267. int pointIsInTriangle(int px, int py, int tp[6])
  268. {
  269. // winding of the whole triangle:
  270. int w = (tp[3] - tp[1]) * (tp[4] - tp[2]) - (tp[2] - tp[0]) * (tp[5] - tp[3]);
  271. int sign = w > 0 ? 1 : (w < 0 ? -1 : 0);
  272. for (int i = 0; i < 3; ++i) // test winding of point with each side
  273. {
  274. int i1 = 2 * i;
  275. int i2 = i1 != 4 ? i1 + 2 : 0;
  276. int w2 = (tp[i1 + 1] - py) * (tp[i2] - tp[i1]) - (tp[i1] - px) * (tp[i2 + 1] - tp[i1 + 1]);
  277. int sign2 = w2 > 0 ? 1 : (w2 < 0 ? -1 : 0);
  278. if (sign * sign2 == -1) // includes edges
  279. //if (sign != sign2) // excludes edges
  280. return 0;
  281. }
  282. return 1;
  283. }
  284. static void saf_draw_polygon(void *handle, const int *coords, int npoints,
  285. int fillcolour, int outlinecolour)
  286. {
  287. if (fillcolour >= 0)
  288. {
  289. /* filling a polygon is hard, this method is imperfect, it just draws
  290. triangles in hopes it will mostly work :) */
  291. int cx = 0, cy = 0;
  292. int minX = clipRect[2],
  293. minY = clipRect[3],
  294. maxX = clipRect[0],
  295. maxY = clipRect[1];
  296. for (int i = 0; i < npoints; ++i)
  297. {
  298. cx += coords[2 * i];
  299. cy += coords[2 * i + 1];
  300. if (coords[2 * i] > maxX)
  301. maxX = coords[2 * i];
  302. if (coords[2 * i] < minX)
  303. minX = coords[2 * i];
  304. if (coords[2 * i + 1] > maxY)
  305. maxY = coords[2 * i + 1];
  306. if (coords[2 * i + 1] < minY)
  307. minY = coords[2 * i + 1];
  308. }
  309. cx /= npoints;
  310. cy /= npoints;
  311. for (int i = 0; i < npoints; ++i)
  312. {
  313. int tp[6];
  314. tp[0] = cx; tp[1] = cy;
  315. tp[2] = coords[2 * i]; tp[3] = coords[2 * i + 1];
  316. tp[4] = coords[2 * ((i + 1) % npoints)],
  317. tp[5] = coords[2 * ((i + 1) % npoints) + 1];
  318. if (pointNotClipped(tp[2],tp[3]) &&
  319. pointNotClipped(tp[4],tp[5]))
  320. for (int y = minY; y < maxY; ++y)
  321. for (int x = minX; x < maxX; ++x)
  322. if (pointIsInTriangle(x,y,tp))
  323. SAF_drawPixel(x,y,colors[fillcolour]);
  324. }
  325. }
  326. for (int i = 0; i < npoints; ++i)
  327. {
  328. int i1 = 2 * i, i2 = 2 * ((i + 1) % npoints);
  329. if (pointNotClipped(coords[i],coords[i + 1]) &&
  330. pointNotClipped(coords[i2],coords[i2 + 1]))
  331. SAF_drawLine(
  332. coords[i1],coords[i1 + 1],
  333. coords[i2],coords[i2 + 1],
  334. colors[outlinecolour]
  335. );
  336. }
  337. }
  338. static void saf_start_draw(void *handle)
  339. {
  340. SAF_drawRect(sw,0,SAF_SCREEN_WIDTH - sw,SAF_SCREEN_HEIGHT,DEFAULT_COLOR,1);
  341. SAF_drawRect(0,sh,SAF_SCREEN_WIDTH,SAF_SCREEN_HEIGHT - sh,DEFAULT_COLOR,1);
  342. }
  343. static void saf_draw_update(void *handle, int x, int y, int w, int h)
  344. {
  345. }
  346. static void saf_end_draw(void *handle)
  347. {
  348. }
  349. static void saf_line_width(void *handle, float width)
  350. {
  351. }
  352. static void saf_line_dotted(void *handle, bool dotted)
  353. {
  354. }
  355. static void saf_begin_doc(void *handle, int pages)
  356. {
  357. }
  358. static void saf_begin_page(void *handle, int number)
  359. {
  360. }
  361. static void saf_begin_puzzle(void *handle, float xm, float xc,
  362. float ym, float yc, int pw, int ph, float wmm)
  363. {
  364. }
  365. static void saf_end_puzzle(void *handle)
  366. {
  367. }
  368. static void saf_end_page(void *handle, int number)
  369. {
  370. }
  371. static void saf_end_doc(void *handle)
  372. {
  373. }
  374. char *saf_text_fallback(void *handle, const char *const *strings, int nstrings)
  375. {
  376. return NULL;
  377. }
  378. const struct drawing_api drawAPI =
  379. {
  380. saf_draw_text,
  381. saf_draw_rect,
  382. saf_draw_line,
  383. saf_draw_polygon,
  384. saf_draw_circle,
  385. saf_draw_update,
  386. saf_clip,
  387. saf_unclip,
  388. saf_start_draw,
  389. saf_end_draw,
  390. saf_status_bar,
  391. saf_blitter_new,
  392. saf_blitter_free,
  393. saf_blitter_save,
  394. saf_blitter_load,
  395. saf_begin_doc,
  396. saf_begin_page,
  397. saf_begin_puzzle,
  398. saf_end_puzzle,
  399. saf_end_page,
  400. saf_end_doc,
  401. saf_line_width,
  402. saf_line_dotted,
  403. saf_text_fallback,
  404. saf_draw_thick_line
  405. };
  406. void clearBar(void)
  407. {
  408. for (int i = 0; i < BAR_MAX_LENGTH; ++i)
  409. barText[i] = ' ';
  410. barText[BAR_MAX_LENGTH] = 0;
  411. }
  412. void SAF_init(void)
  413. {
  414. float *tmpColors;
  415. SAF_clearScreen(DEFAULT_COLOR);
  416. saf_unclip(NULL);
  417. clearBar();
  418. middleEnd = midend_new(NULL,&thegame,&drawAPI,NULL);
  419. tmpColors = midend_colours(middleEnd,&colorCount);
  420. colorCount %= MAX_COLORS;
  421. for (int i = 0; i < colorCount; ++i)
  422. {
  423. colors[i] = SAF_colorFromRGB(
  424. tmpColors[3 * i] * 255,
  425. tmpColors[3 * i + 1] * 255,
  426. tmpColors[3 * i + 2] * 255);
  427. }
  428. midend_new_game(middleEnd);
  429. sw = SAF_SCREEN_WIDTH;
  430. sh = SAF_SCREEN_HEIGHT - BAR_WIDTH;
  431. midend_reset_tilesize(middleEnd);
  432. midend_size(middleEnd,&sw,&sh,1);
  433. cursorPos[0] = SAF_SCREEN_WIDTH / 2;
  434. cursorPos[1] = SAF_SCREEN_HEIGHT / 2;
  435. cursorButtons[0] = 0;
  436. cursorButtons[1] = 0;
  437. midend_which_preset(middleEnd);
  438. midend_redraw(middleEnd);
  439. }
  440. int buttonOn(uint8_t button)
  441. {
  442. return SAF_buttonPressed(button) == 1 || SAF_buttonPressed(button) > 10;
  443. }
  444. uint8_t SAF_loop(void)
  445. {
  446. midend_timer(middleEnd,1.0 / ((float) SAF_MS_PER_FRAME));
  447. if (inputEmulation)
  448. {
  449. if (cursorPos[0] <= SAF_SCREEN_WIDTH - BAR_WIDTH)
  450. {
  451. uint8_t redraw = 1;
  452. if (buttonOn(SAF_BUTTON_LEFT) && cursorPos[0] > 0)
  453. {
  454. cursorPos[0]--;
  455. if (cursorButtons[0])
  456. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],LEFT_DRAG);
  457. }
  458. else if (buttonOn(SAF_BUTTON_RIGHT) && cursorPos[0] < SAF_SCREEN_WIDTH - 1)
  459. {
  460. cursorPos[0]++;
  461. if (cursorButtons[0])
  462. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],LEFT_DRAG);
  463. }
  464. else if (buttonOn(SAF_BUTTON_UP) && cursorPos[1] > 0)
  465. {
  466. cursorPos[1]--;
  467. if (cursorButtons[0])
  468. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],LEFT_DRAG);
  469. }
  470. else if (buttonOn(SAF_BUTTON_DOWN) && cursorPos[1] < SAF_SCREEN_HEIGHT - 1)
  471. {
  472. cursorPos[1]++;
  473. if (cursorButtons[0])
  474. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],LEFT_DRAG);
  475. }
  476. else if ((SAF_buttonPressed(SAF_BUTTON_A) != 0) != cursorButtons[0])
  477. {
  478. cursorButtons[0] = SAF_buttonPressed(SAF_BUTTON_A) != 0;
  479. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],
  480. cursorButtons[0] ? LEFT_BUTTON : LEFT_RELEASE);
  481. }
  482. else if ((SAF_buttonPressed(SAF_BUTTON_B) != 0) != cursorButtons[1])
  483. {
  484. cursorButtons[1] = SAF_buttonPressed(SAF_BUTTON_B) != 0;
  485. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],
  486. cursorButtons[1] ? RIGHT_BUTTON : RIGHT_RELEASE);
  487. }
  488. else
  489. redraw = 0;
  490. if (redraw)
  491. midend_force_redraw(middleEnd);
  492. }
  493. else
  494. {
  495. if (buttonOn(SAF_BUTTON_LEFT))
  496. cursorPos[0]--;
  497. else if (buttonOn(SAF_BUTTON_UP))
  498. gameMenuItem =
  499. gameMenuItem > 0 ? gameMenuItem - 1 : GAME_MENU_ITEMS - 1;
  500. else if (buttonOn(SAF_BUTTON_DOWN))
  501. gameMenuItem =
  502. gameMenuItem < GAME_MENU_ITEMS - 1 ? gameMenuItem + 1 : 0;
  503. else if (buttonOn(SAF_BUTTON_A))
  504. {
  505. char item = getGameMenuItem(gameMenuItem);
  506. switch (item)
  507. {
  508. case 'S':
  509. midend_solve(middleEnd);
  510. midend_force_redraw(middleEnd);
  511. break;
  512. case 'N':
  513. midend_new_game(middleEnd);
  514. midend_force_redraw(middleEnd);
  515. break;
  516. case 'U':
  517. midend_undo(middleEnd);
  518. midend_force_redraw(middleEnd);
  519. break;
  520. default:
  521. midend_process_key(middleEnd,cursorPos[0],cursorPos[1],item);
  522. break;
  523. }
  524. }
  525. }
  526. }
  527. else
  528. {
  529. if (SAF_buttonJustPressed(SAF_BUTTON_LEFT))
  530. midend_process_key(middleEnd,0,0,CURSOR_LEFT);
  531. if (SAF_buttonJustPressed(SAF_BUTTON_RIGHT))
  532. midend_process_key(middleEnd,0,0,CURSOR_RIGHT);
  533. if (SAF_buttonJustPressed(SAF_BUTTON_UP))
  534. midend_process_key(middleEnd,0,0,CURSOR_UP);
  535. if (SAF_buttonJustPressed(SAF_BUTTON_DOWN))
  536. midend_process_key(middleEnd,0,0,CURSOR_DOWN);
  537. if (SAF_buttonJustPressed(SAF_BUTTON_A))
  538. midend_process_key(middleEnd,0,0,CURSOR_SELECT);
  539. if (SAF_buttonJustPressed(SAF_BUTTON_B))
  540. midend_process_key(middleEnd,0,0,CURSOR_SELECT2);
  541. }
  542. if (SAF_buttonJustPressed(SAF_BUTTON_C))
  543. {
  544. inputEmulation = !inputEmulation;
  545. midend_force_redraw(middleEnd);
  546. }
  547. SAF_drawRect(0,SAF_SCREEN_HEIGHT - BAR_WIDTH,SAF_SCREEN_WIDTH,BAR_WIDTH,
  548. SAF_COLOR_WHITE,1);
  549. SAF_drawText(barText,1,SAF_SCREEN_HEIGHT - BAR_WIDTH + 1,SAF_COLOR_BLACK,1);
  550. int status = midend_status(middleEnd);
  551. if (status == 1)
  552. SAF_drawText("WIN",1,1,SAF_COLOR_GREEN,1);
  553. else if (status == -1)
  554. SAF_drawText("LOST",1,1,SAF_COLOR_RED,1);
  555. if (inputEmulation)
  556. drawCursor();
  557. return 1;
  558. }