+static const char * const display_filename_default_ =
+#ifdef HAVE_LIBPNG
+ "dcpu16-display.png"
+#else /* HAVE_LIBPNG */
+ "dcpu16-display.pnm"
+#endif /* HAVE_LIBPNG */
+;
+COMMAND_IMPL(display) {
+ struct dcpu16_hw *hw;
+ const char *renderer = arg_vector[1];
+ const char *renderer_arg = NULL;
+ void *renderer_data;
+
+ if (arg_count == 3)
+ renderer_arg = arg_vector[2];
+
+ hw = lem1802_new(vm);
+ if (hw == NULL) {
+ fprintf(stderr, "failed to initialize new display\n");
+ return 0;
+ }
+
+ /* handle per-renderer setup of data.. */
+ /* FIXME: these are awkward */
+ if (strcmp(renderer, "pnm") == 0) {
+ if (renderer_arg == NULL)
+ renderer_arg = display_filename_default_;
+ renderer_data = (void *)renderer_arg;
+ }
+
+#ifdef HAVE_LIBPNG
+ if (strcmp(renderer, "png") == 0) {
+ if (renderer_arg == NULL)
+ renderer_arg = display_filename_default_;
+ renderer_data = (void *)renderer_arg;
+ }
+#endif /* HAVE_LIBPNG */
+
+#ifdef HAVE_LIBVNCSERVER
+ if (strcmp(renderer, "vnc") == 0) {
+ int argc = 1;
+ char *argv[] = { "vm-dcpu16", NULL };
+ struct rfb_instance_ *s;
+
+ s = rfbScreen_next_available_display_(&rfbScreens_, argc, argv);
+ if (s == NULL) {
+ fprintf(stderr, "failed to initialize vnc\n");
+ lem1802_del(&hw);
+ return 0;
+ }
+
+ lem1802_vnc_associate(hw, s->screen);
+ s->attached_display = hw;
+ rfbScreen_start(s->screen);
+ renderer_data = s->screen;
+ }
+#endif /* HAVE_LIBVNCSERVER */
+
+ if (lem1802_renderer_set(hw, renderer, renderer_data)) {
+ fprintf(stderr, "failed to set back-end renderer for display\n");
+ lem1802_del(&hw);
+ return 0;
+ }
+
+ if (dcpu16_hw_add(vm, hw)) {
+ fprintf(stderr, "failed to attach new display\n");
+ lem1802_del(&hw);
+ return 0;
+ }
+
+ return 0;
+}
+COMMAND_HELP(display) {
+ char *name, *args;
+ void *iter;
+
+ fprintf(f, "\tdisplay renderer [renderer data]\n");
+ if (summary) return;
+
+ fprintf(f, "Attaches new display unit, using 'renderer' as back-end output.\n"
+ );
+
+ fprintf(f, "Supported renderers:\n");
+ iter = NULL;
+ while ( (lem1802_renderers_iter(&iter, &name, &args)) ) {
+ fprintf(f, "\t%s %s\n", name, args);
+ }
+}
+
+COMMAND_IMPL(keyboard) {
+ struct dcpu16_hw *hw;
+
+ (void)arg_count, (void)arg_vector;
+
+ hw = keyboard_new(vm);
+ if (hw == NULL) {
+ fprintf(stderr, "failed to initialize new keyboard\n");
+ return 0;
+ }
+
+#ifdef HAVE_LIBVNCSERVER
+ struct rfb_instance_ *s;
+ int argc = 1;
+ char *argv[] = { "vm-dcpu16", NULL };
+
+ s = rfbScreen_next_available_keyboard_(&rfbScreens_, argc, argv);
+ if (s == NULL) {
+ fprintf(stderr, "failed to initialize vnc\n");
+ keyboard_del(&hw);
+ return 0;
+ }
+ keyboard_vnc_associate(hw, s->screen);
+ s->attached_keyboard = hw;
+
+ if (dcpu16_hw_add(vm, hw)) {
+ fprintf(stderr, "failed to attach new keyboard\n");
+ keyboard_del(&hw);
+ return 0;
+ }
+#endif /* HAVE_LIBVNCSERVER */
+
+ return 0;
+}
+COMMAND_HELP(keyboard) {
+ fprintf(f, "\tkeyboard\n");
+ if (summary) return;
+
+ fprintf(f, "Attaches new keyboard unit.\n");
+}
+