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(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
, 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
, 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
;
277 i
->sval
= dupstr(newval
);
281 void jcallback_config_set_boolean(int item_ptr
, int selected
) {
282 config_item
*i
= (config_item
*)item_ptr
;
283 i
->ival
= selected
!= 0 ? TRUE
: FALSE
;
286 void jcallback_config_set_choice(int item_ptr
, int selected
) {
287 config_item
*i
= (config_item
*)item_ptr
;
291 static int get_config(frontend
*fe
, int which
)
295 fe
->cfg
= midend_get_config(fe
->me
, which
, &title
);
296 fe
->cfg_which
= which
;
298 _call_java(10, (int)title
, 0, 0);
299 for (i
= fe
->cfg
; i
->type
!= C_END
; i
++) {
300 _call_java(5, (int)i
, i
->type
, (int)i
->name
);
301 _call_java(11, (int)i
->sval
, i
->ival
, 0);
303 _call_java(12,0,0,0);
308 int jcallback_menu_key_event(int key
)
310 frontend
*fe
= (frontend
*)_fe
;
311 if (!midend_process_key(fe
->me
, 0, 0, key
))
316 static void resize_fe(frontend
*fe
)
322 midend_size(fe
->me
, &x
, &y
, FALSE
);
323 _call_java(3, x
, y
, 0);
326 int jcallback_preset_event(int ptr_game_params
)
328 frontend
*fe
= (frontend
*)_fe
;
329 game_params
*params
=
330 (game_params
*)ptr_game_params
;
332 midend_set_params(fe
->me
, params
);
333 midend_new_game(fe
->me
);
335 _call_java(13, midend_which_preset(fe
->me
), 0, 0);
339 int jcallback_solve_event()
341 frontend
*fe
= (frontend
*)_fe
;
344 msg
= midend_solve(fe
->me
);
347 _call_java(2, (int) "Error", (int)msg
, 1);
351 int jcallback_restart_event()
353 frontend
*fe
= (frontend
*)_fe
;
355 midend_restart_game(fe
->me
);
359 int jcallback_config_event(int which
)
361 frontend
*fe
= (frontend
*)_fe
;
362 _call_java(13, midend_which_preset(fe
->me
), 0, 0);
363 if (!get_config(fe
, which
))
365 midend_new_game(fe
->me
);
367 _call_java(13, midend_which_preset(fe
->me
), 0, 0);
371 int jcallback_about_event()
376 sprintf(titlebuf
, "About %.200s", thegame
.name
);
379 "from Simon Tatham's Portable Puzzle Collection\n\n"
380 "%.500s", thegame
.name
, ver
);
381 _call_java(2, (int)&titlebuf
, (int)&textbuf
, 0);
385 int main(int argc
, char **argv
)
390 _fe
= snew(frontend
);
391 _fe
->timer_active
= FALSE
;
392 _fe
->me
= midend_new(_fe
, &thegame
, &nestedvm_drawing
, _fe
);
394 midend_game_id(_fe
->me
, argv
[1]); /* ignore failure */
395 midend_new_game(_fe
->me
);
397 if ((n
= midend_num_presets(_fe
->me
)) > 0) {
399 for (i
= 0; i
< n
; i
++) {
402 midend_fetch_preset(_fe
->me
, i
, &name
, ¶ms
);
403 _call_java(1, (int)name
, (int)params
, 0);
407 colours
= midend_colours(_fe
->me
, &n
);
410 _call_java(0, (int)thegame
.name
,
411 (thegame
.can_configure
? 1 : 0) |
412 (midend_wants_statusbar(_fe
->me
) ? 2 : 0) |
413 (thegame
.can_solve
? 4 : 0), n
);
414 for (i
= 0; i
< n
; i
++) {
416 (int)(colours
[i
*3] * 0xFF),
417 (int)(colours
[i
*3+1] * 0xFF),
418 (int)(colours
[i
*3+2] * 0xFF));
422 _call_java(13, midend_which_preset(_fe
->me
), 0, 0);
424 // Now pause the vm. The VM will be call()ed when
425 // an input event occurs.
428 // shut down when the VM is resumed.
429 deactivate_timer(_fe
);
430 midend_free(_fe
->me
);