2 * nestedvm.c: NestedVM front end for my puzzle collection.
18 extern int _call_java(int cmd, int arg1, int arg2, int arg3);
20 void fatal(const char *fmt, ...)
23 fprintf(stderr, "fatal error: ");
25 vfprintf(stderr, fmt, ap);
27 fprintf(stderr, "\n");
32 // TODO kill unneeded members!
35 struct timeval last_time;
37 int cfg_which, cfgret;
43 void get_random_seed(void **randseed, int *randseedsize)
45 struct timeval *tvp = snew(struct timeval);
46 gettimeofday(tvp, NULL);
47 *randseed = (void *)tvp;
48 *randseedsize = sizeof(struct timeval);
51 void frontend_default_colour(frontend *fe, float *output)
53 output[0] = output[1]= output[2] = 0.8f;
56 void nestedvm_status_bar(void *handle, const char *text)
58 _call_java(4,0,(int)text,0);
61 void nestedvm_start_draw(void *handle)
63 frontend *fe = (frontend *)handle;
64 _call_java(5, 0, fe->w, fe->h);
65 _call_java(4, 1, fe->ox, fe->oy);
68 void nestedvm_clip(void *handle, int x, int y, int w, int h)
70 frontend *fe = (frontend *)handle;
71 _call_java(5, w, h, 0);
72 _call_java(4, 3, x + fe->ox, y + fe->oy);
75 void nestedvm_unclip(void *handle)
77 frontend *fe = (frontend *)handle;
78 _call_java(4, 4, fe->ox, fe->oy);
81 void nestedvm_draw_text(void *handle, int x, int y, int fonttype, int fontsize,
82 int align, int colour, const char *text)
84 frontend *fe = (frontend *)handle;
85 _call_java(5, x + fe->ox, y + fe->oy,
86 (fonttype == FONT_FIXED ? 0x10 : 0x0) | align);
87 _call_java(7, fontsize, colour, (int)text);
90 void nestedvm_draw_rect(void *handle, int x, int y, int w, int h, int colour)
92 frontend *fe = (frontend *)handle;
93 _call_java(5, w, h, colour);
94 _call_java(4, 5, x + fe->ox, y + fe->oy);
97 void nestedvm_draw_line(void *handle, int x1, int y1, int x2, int y2,
100 frontend *fe = (frontend *)handle;
101 _call_java(5, x2 + fe->ox, y2 + fe->oy, colour);
102 _call_java(4, 6, x1 + fe->ox, y1 + fe->oy);
105 void nestedvm_draw_poly(void *handle, int *coords, int npoints,
106 int fillcolour, int outlinecolour)
108 frontend *fe = (frontend *)handle;
110 _call_java(4, 7, npoints, 0);
111 for (i = 0; i < npoints; i++) {
112 _call_java(6, i, coords[i*2] + fe->ox, coords[i*2+1] + fe->oy);
114 _call_java(4, 8, outlinecolour, fillcolour);
117 void nestedvm_draw_circle(void *handle, int cx, int cy, int radius,
118 int fillcolour, int outlinecolour)
120 frontend *fe = (frontend *)handle;
121 _call_java(5, cx+fe->ox, cy+fe->oy, radius);
122 _call_java(4, 9, outlinecolour, fillcolour);
126 int handle, w, h, x, y;
129 blitter *nestedvm_blitter_new(void *handle, int w, int h)
131 blitter *bl = snew(blitter);
138 void nestedvm_blitter_free(void *handle, blitter *bl)
140 if (bl->handle != -1)
141 _call_java(4, 11, bl->handle, 0);
145 void nestedvm_blitter_save(void *handle, blitter *bl, int x, int y)
147 frontend *fe = (frontend *)handle;
148 if (bl->handle == -1)
149 bl->handle = _call_java(4,10,bl->w, bl->h);
152 _call_java(8, bl->handle, x + fe->ox, y + fe->oy);
155 void nestedvm_blitter_load(void *handle, blitter *bl, int x, int y)
157 frontend *fe = (frontend *)handle;
158 assert(bl->handle != -1);
159 if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
163 _call_java(9, bl->handle, x + fe->ox, y + fe->oy);
166 void nestedvm_end_draw(void *handle)
171 char *nestedvm_text_fallback(void *handle, const char *const *strings,
175 * We assume Java can cope with any UTF-8 likely to be emitted
178 return dupstr(strings[0]);
181 const struct drawing_api nestedvm_drawing = {
186 nestedvm_draw_circle,
187 NULL, // draw_update,
193 nestedvm_blitter_new,
194 nestedvm_blitter_free,
195 nestedvm_blitter_save,
196 nestedvm_blitter_load,
197 NULL, NULL, NULL, NULL, NULL, NULL, /* {begin,end}_{doc,page,puzzle} */
198 NULL, NULL, /* line_width, line_dotted */
199 nestedvm_text_fallback,
202 int jcallback_key_event(int x, int y, int keyval)
204 frontend *fe = (frontend *)_fe;
208 !midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval))
213 int jcallback_resize(int width, int height)
215 frontend *fe = (frontend *)_fe;
219 midend_size(fe->me, &x, &y, TRUE);
220 fe->ox = (width - x) / 2;
221 fe->oy = (height - y) / 2;
224 midend_force_redraw(fe->me);
228 int jcallback_timer_func()
230 frontend *fe = (frontend *)_fe;
231 if (fe->timer_active) {
234 gettimeofday(&now, NULL);
235 elapsed = ((now.tv_usec - fe->last_time.tv_usec) * 0.000001F +
236 (now.tv_sec - fe->last_time.tv_sec));
237 midend_timer(fe->me, elapsed); /* may clear timer_active */
240 return fe->timer_active;
243 void deactivate_timer(frontend *fe)
245 if (fe->timer_active)
246 _call_java(4, 13, 0, 0);
247 fe->timer_active = FALSE;
250 void activate_timer(frontend *fe)
252 if (!fe->timer_active) {
253 _call_java(4, 12, 0, 0);
254 gettimeofday(&fe->last_time, NULL);
256 fe->timer_active = TRUE;
259 void jcallback_config_ok()
261 frontend *fe = (frontend *)_fe;
264 err = midend_set_config(fe->me, fe->cfg_which, fe->cfg);
267 _call_java(2, (int) "Error", (int)err, 1);
273 void jcallback_config_set_string(int item_ptr, int char_ptr) {
274 config_item *i = (config_item *)item_ptr;
275 char* newval = (char*) char_ptr;
276 assert(i->type == C_STRING);
277 sfree(i->u.string.sval);
278 i->u.string.sval = dupstr(newval);
282 void jcallback_config_set_boolean(int item_ptr, int selected) {
283 config_item *i = (config_item *)item_ptr;
284 assert(i->type == C_BOOLEAN);
285 i->u.boolean.bval = selected != 0 ? TRUE : FALSE;
288 void jcallback_config_set_choice(int item_ptr, int selected) {
289 config_item *i = (config_item *)item_ptr;
290 assert(i->type == C_CHOICES);
291 i->u.choices.selected = selected;
294 static int get_config(frontend *fe, int which)
298 fe->cfg = midend_get_config(fe->me, which, &title);
299 fe->cfg_which = which;
301 _call_java(10, (int)title, 0, 0);
302 for (i = fe->cfg; i->type != C_END; i++) {
303 _call_java(5, (int)i, i->type, (int)i->name);
306 _call_java(11, (int)i->u.string.sval, 0, 0);
309 _call_java(11, 0, i->u.boolean.bval, 0);
312 _call_java(11, (int)i->u.choices.choicenames,
313 i->u.choices.selected, 0);
317 _call_java(12,0,0,0);
322 int jcallback_newgame_event(void)
324 frontend *fe = (frontend *)_fe;
325 if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME))
330 int jcallback_undo_event(void)
332 frontend *fe = (frontend *)_fe;
333 if (!midend_process_key(fe->me, 0, 0, UI_UNDO))
338 int jcallback_redo_event(void)
340 frontend *fe = (frontend *)_fe;
341 if (!midend_process_key(fe->me, 0, 0, UI_REDO))
346 int jcallback_quit_event(void)
348 frontend *fe = (frontend *)_fe;
349 if (!midend_process_key(fe->me, 0, 0, UI_QUIT))
354 static void resize_fe(frontend *fe)
360 midend_size(fe->me, &x, &y, FALSE);
361 _call_java(3, x, y, 0);
364 int jcallback_preset_event(int ptr_game_params)
366 frontend *fe = (frontend *)_fe;
367 game_params *params =
368 (game_params *)ptr_game_params;
370 midend_set_params(fe->me, params);
371 midend_new_game(fe->me);
373 _call_java(13, midend_which_preset(fe->me), 0, 0);
377 int jcallback_solve_event()
379 frontend *fe = (frontend *)_fe;
382 msg = midend_solve(fe->me);
385 _call_java(2, (int) "Error", (int)msg, 1);
389 int jcallback_restart_event()
391 frontend *fe = (frontend *)_fe;
393 midend_restart_game(fe->me);
397 int jcallback_config_event(int which)
399 frontend *fe = (frontend *)_fe;
400 _call_java(13, midend_which_preset(fe->me), 0, 0);
401 if (!get_config(fe, which))
403 midend_new_game(fe->me);
405 _call_java(13, midend_which_preset(fe->me), 0, 0);
409 int jcallback_about_event()
414 sprintf(titlebuf, "About %.200s", thegame.name);
417 "from Simon Tatham's Portable Puzzle Collection\n\n"
418 "%.500s", thegame.name, ver);
419 _call_java(2, (int)&titlebuf, (int)&textbuf, 0);
423 void preset_menu_populate(struct preset_menu *menu, int menuid)
427 for (i = 0; i < menu->n_entries; i++) {
428 struct preset_menu_entry *entry = &menu->entries[i];
430 _call_java(5, (int)entry->params, 0, 0);
431 _call_java(1, (int)entry->title, menuid, entry->id);
433 _call_java(5, 0, 0, 0);
434 _call_java(1, (int)entry->title, menuid, entry->id);
435 preset_menu_populate(entry->submenu, entry->id);
440 int main(int argc, char **argv)
445 _fe = snew(frontend);
446 _fe->timer_active = FALSE;
447 _fe->me = midend_new(_fe, &thegame, &nestedvm_drawing, _fe);
449 midend_game_id(_fe->me, argv[1]); /* ignore failure */
450 midend_new_game(_fe->me);
453 struct preset_menu *menu;
455 menu = midend_get_presets(_fe->me, &nids);
456 topmenu = _call_java(1, 0, nids, 0);
457 preset_menu_populate(menu, topmenu);
460 colours = midend_colours(_fe->me, &n);
463 _call_java(0, (int)thegame.name,
464 (thegame.can_configure ? 1 : 0) |
465 (midend_wants_statusbar(_fe->me) ? 2 : 0) |
466 (thegame.can_solve ? 4 : 0), n);
467 for (i = 0; i < n; i++) {
469 (int)(colours[i*3] * 0xFF),
470 (int)(colours[i*3+1] * 0xFF),
471 (int)(colours[i*3+2] * 0xFF));
475 _call_java(13, midend_which_preset(_fe->me), 0, 0);
477 // Now pause the vm. The VM will be call()ed when
478 // an input event occurs.
481 // shut down when the VM is resumed.
482 deactivate_timer(_fe);
483 midend_free(_fe->me);