home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / gtkloop.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  8.8 KB  |  435 lines

  1. /*
  2.  *    System loop for a GTK interface to v9t9
  3.  *
  4.  *
  5.  */
  6. #include <conf.h>
  7. #if defined(UNDER_UNIX)
  8. #include "unixmain.h"
  9. #else
  10. #include "winv9t9.h"
  11. #endif
  12. #include "v9t9_common.h"
  13.  
  14.  
  15.  
  16. #include <signal.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #include <sys/time.h>
  20.  
  21. #include <gtk/gtk.h>
  22. #include <pthread.h>
  23. #include "gtkinterface.h"
  24.  
  25. #include "gtkcallbacks.h"
  26. #include "gtkloop.h"
  27. #include "system.h"
  28. #include "timer.h"
  29. #include "v9t9.h"
  30. #include "command.h"
  31.  
  32. #include "command_rl.h"
  33. #include "moduleconfig.h"
  34. #include "v9t9_module.h"
  35.  
  36. #define _L     LOG_INTERNAL | LOG_INFO
  37.  
  38. /*    globals */
  39.  
  40. /*    window containing v9t9 and command buttons */
  41. GtkWidget        *v9t9_window;
  42.  
  43. /*    Drawing area for v9t9 screen */
  44. GtkWidget        *v9t9_drawing_area;
  45.  
  46. /*    Command log text entry widget */
  47. GtkWidget        *v9t9_command_log;
  48.  
  49. /* Use this function to set the directory containing installed pixmaps. */
  50. extern void
  51. add_pixmap_directory                   (const gchar     *directory);
  52.  
  53.  
  54. #if defined(GTK_VIDEO) && defined(GTK_KEYBOARD)
  55.  
  56. static int v9t9_return;
  57.  
  58. static int v9t9_execute_tag, v9t9_execute_flag;
  59.  
  60. //    a mutex to prevent us from sending commands
  61. //    while emulator is going... scary stuff
  62. static pthread_mutex_t    emulator_lock;
  63.  
  64. GtkWidget *command_center;
  65.  
  66. /*
  67.  *    This is where we actually do the stuff in GTK_system_loop.
  68.  */
  69. static gint gtk_idle_handler(gpointer *data)
  70. {
  71.     int ret;
  72.  
  73. //    g_print("Timer = %d\n", TM_GetTicks());
  74.  
  75.     if (!pthread_mutex_lock(&emulator_lock)) {
  76.         while (TM_Ticked) {
  77.             TM_TickHandler(0);
  78. //            TM_Ticked--;
  79.             TM_Ticked = 0;
  80.         }
  81.  
  82.         ret = v9t9_return = v9t9_execute();
  83.         
  84.         if (ret == em_TooFast) {
  85. #if defined(UNDER_UNIX)        
  86.             unix_system_pause();    
  87. #else
  88.             win32_system_pause();
  89. #endif                        
  90.         }
  91.         else if (ret == em_Quitting || ret == em_Dying) {
  92.             gtk_main_quit();
  93.             return FALSE;
  94.         }
  95.         pthread_mutex_unlock(&emulator_lock);
  96.     }
  97.  
  98.     // continue to call me...  :)
  99.     return TRUE;
  100. }
  101.  
  102. #if defined(UNDER_UNIX)
  103. #include "Xv9t9.h"
  104. #include <gdk/gdkx.h>
  105. #include "xlibrsrc.h"
  106.  
  107. extern Display *x11_dpy;
  108. extern int x11_screen;
  109.  
  110. static int
  111. GTK_get_initial_size(void)
  112. {
  113.     int vwxoff, vwyoff, vwxsz, vwysz;
  114.  
  115.     int dpy_xsize, dpy_ysize;
  116.     XSizeHints *vwin_size_hints; 
  117.     XrmDatabase cmdlineDB = 0;
  118.     char       *str_type;
  119.     XrmValue    value;
  120.     int         gravity;
  121.     bool        user_geometry;
  122.     int            flags;
  123.     int            i;
  124.  
  125.     /*  Read command-line args */
  126.     XrmParseCommand(&cmdlineDB, xlib_opTable, SIZEOF_OPS, 
  127.                     OS_GetFileNamePtr(v9t9_argv[0]), 
  128.                     &v9t9_argc, v9t9_argv);
  129.  
  130.     /*  Get hints for -display parsing */
  131.     x11_dpy = GDK_DISPLAY();
  132.     x11_screen = DefaultScreen(x11_dpy);
  133.  
  134.     dpy_xsize = DisplayWidth(x11_dpy, x11_screen);
  135.     dpy_ysize = DisplayHeight(x11_dpy, x11_screen);
  136.  
  137.     if ((vwin_size_hints = XAllocSizeHints()) == NULL) {
  138.         logger(_L|LOG_ERROR | LOG_USER, "cannot allocate size hints\n");
  139.         return 0;
  140.     }
  141.  
  142.     vwin_size_hints->flags = PMinSize | PMaxSize | PResizeInc | PAspect | PBaseSize;
  143.     vwin_size_hints->base_width = 0;
  144.     vwin_size_hints->base_height = 0;
  145.     vwin_size_hints->min_width = 256;
  146.     vwin_size_hints->min_height = 192;
  147.     vwin_size_hints->max_width = dpy_xsize;
  148.     vwin_size_hints->max_height = dpy_ysize;
  149.     vwin_size_hints->width_inc = 256;
  150.     vwin_size_hints->height_inc = 192;
  151.     vwin_size_hints->min_aspect.x = vwin_size_hints->max_aspect.x = 4;
  152.     vwin_size_hints->min_aspect.y = vwin_size_hints->max_aspect.y = 3;
  153.  
  154.     /* Read sizes from resource */
  155.  
  156.     xlib_get_resources(OS_GetFileNamePtr(v9t9_argv[0]), cmdlineDB);
  157.  
  158.     if (!XrmGetResource(xlib_rDB, "v9t9.geometry", "V9t9.Geometry",
  159.                         &str_type, &value)) {
  160.         user_geometry = false;
  161.         value.addr = 0L;
  162.     } else {
  163.         user_geometry = true;
  164.     }
  165.  
  166.     /*    Parse geometry specification  */
  167.  
  168.     if ((flags = XWMGeometry(x11_dpy, x11_screen,
  169.                     (char *) value.addr,
  170.                     "1x1",
  171.                     1 /* border width */ , vwin_size_hints,
  172.                     &vwxoff, &vwyoff, &vwxsz, &vwysz, &gravity))) {
  173.  
  174.         if (vwxsz >= 256*256 && vwysz >= 192*192) {
  175.             // assume they misunderstood the geometry and scale down
  176.             vwxsz /= 256;
  177.             vwysz /= 192;
  178.         }
  179.     }
  180.  
  181.     GTK_x_mult = vwxsz / 256;
  182.     GTK_y_mult = vwysz / 192;
  183.     GTK_user_size_configured = 1;
  184.     
  185.     // on_v9t9_draw_area_size_request uses this info
  186.     return 1;
  187. }
  188.  
  189. #elif defined(UNDER_WIN32)
  190.  
  191. static void
  192. GTK_get_initial_size(void)
  193. {
  194.  
  195. }
  196.  
  197. #endif
  198.  
  199. int
  200. GTK_system_init(void)
  201. {
  202.     char path[OS_PATHSIZE];
  203.  
  204.     gtk_set_locale();
  205.     gtk_init(&v9t9_argc, &v9t9_argv);
  206.  
  207.     add_pixmap_directory("./pixmaps");
  208.  
  209.     OS_PathSpecToString2(&v9t9_progspec.path, path);
  210.     strcat(path, "v9t9.gtkrc");
  211.     gtk_rc_parse(path);
  212.  
  213.     pthread_mutex_init(&emulator_lock, NULL);
  214.  
  215.     command_center = create_command_dialog();
  216.     gtk_widget_show(command_center);
  217.  
  218.     GTK_get_initial_size();
  219.  
  220.     return 1;
  221. }
  222.  
  223. int
  224. GTK_system_loop(void)
  225. {
  226.     guint idle_id;
  227.     
  228.     idle_id = gtk_idle_add((GtkFunction) gtk_idle_handler, 0L);
  229.  
  230. /*    v9t9_execute_tag = TM_UniqueTag();
  231.     TM_SetEvent(v9t9_execute_tag, 
  232.                 TM_HZ * 100 / 60, 
  233.                 0, 
  234.                 TM_REPEAT, 
  235.                 &v9t9_execute_flag);*/
  236.  
  237.     gtk_main();
  238.  
  239. /*    TM_ResetEvent(v9t9_execute_tag);*/
  240.  
  241.     gtk_idle_remove(idle_id);
  242.     return v9t9_return == em_Dying;
  243. }
  244.  
  245. /*
  246. void
  247. GTK_system_getcommands(void)
  248. {
  249.     unix_system_getcommands();
  250. }
  251. */
  252.  
  253. void
  254. GTK_system_log(u32 srcflags, const gchar *text)
  255. {
  256.     if (LOG_IS_VISIBLE(srcflags)) {
  257.         GTK_append_log(text, NULL, NULL);
  258.     }
  259.     //system_log(srcflags, text);
  260. }
  261.  
  262. void
  263. GTK_system_report_status(status_item item, va_list va)
  264. {
  265.     char buffer[256];
  266.     GtkLabel *label;
  267.     
  268.     label = GTK_LABEL(gtk_object_get_data(GTK_OBJECT(command_center),
  269.                                         "progress_label"));
  270.     switch (item)
  271.     {
  272.     case STATUS_CYCLES_SECOND:
  273.     {
  274.         int cyc_avg = va_arg(va, int);
  275.         int inst_avg = va_arg(va, int);
  276.         sprintf(buffer, "Executing %d cycles per second, "
  277.                 "%d instructions per second",
  278.                 cyc_avg, inst_avg);
  279.         gtk_label_set_text(label, buffer);
  280.         break;
  281.     }
  282.  
  283.     case STATUS_FRAMES_SECOND:
  284.     {
  285.         int frames_avg = va_arg(va, int);
  286.         sprintf(buffer, "Displaying %d frames per second",
  287.                 frames_avg);
  288.         gtk_label_set_text(label, buffer);
  289.         break;
  290.     }
  291.  
  292.     case STATUS_DISK_ACCESS:
  293.     case STATUS_RS232_ACCESS:
  294.     {
  295.         GtkWidget *w;
  296.         int num = va_arg(va, int);
  297.         int onoff = va_arg(va, int);
  298.         
  299.         w = (item == STATUS_DISK_ACCESS) ?
  300.             gtk_object_get_data(GTK_OBJECT(v9t9_window), "disk_access_drawing_area") :
  301.             gtk_object_get_data(GTK_OBJECT(v9t9_window), "rs232_access_drawing_area") ;
  302.         if (w)
  303.         {
  304.             GdkColor yellow = { 0xe0, 0xe0, 0x40 };
  305.             GdkColor black = { 0x00, 0x00, 0x00 };
  306.             GtkStyle *style = gtk_widget_get_style(v9t9_window);
  307.             GdkGC *gc = gdk_gc_new(v9t9_window->window);
  308.             gdk_gc_set_foreground(gc, onoff ? &style->fg[4] : &style->bg[0]);
  309.             gdk_draw_rectangle(w->window, 
  310.                                gc,
  311.                                true /*filled*/,
  312.                                0, 0,
  313.                                w->allocation.width, w->allocation.height);
  314. //            gtk_style_unref(style);
  315. //            g_print("%d\n", onoff);
  316.             gdk_gc_unref(gc);
  317.         }
  318.         break;
  319.     }
  320.  
  321.     case STATUS_DEBUG_REFRESH:
  322.     case STATUS_CPU_PC:
  323.     case STATUS_CPU_STATUS:
  324.     case STATUS_CPU_WP:
  325.     case STATUS_CPU_REGISTER_VIEW:
  326.     case STATUS_CPU_REGISTER_READ:
  327.     case STATUS_CPU_REGISTER_WRITE:
  328.     case STATUS_CPU_INSTRUCTION:
  329.     case STATUS_CPU_INSTRUCTION_LAST:
  330.     case STATUS_MEMORY_VIEW:
  331.     case STATUS_MEMORY_READ:
  332.     case STATUS_MEMORY_WRITE:
  333.         debugger_report_status(item, va);
  334.         break;
  335.  
  336.     default:
  337.         logger(LOG_USER|LOG_ERROR, "Unhandled event %d!", item);
  338.         break;
  339.     }
  340. }
  341.  
  342. /***********************/
  343.  
  344. /*
  345.  *    Get log font
  346.  */
  347. GdkFont *
  348. GTK_get_log_font(void)
  349. {
  350.     GtkStyle *style;
  351.     if (GTK_OBJECT(v9t9_command_log)->flags & GTK_DESTROYED)
  352.         return 0L;
  353.     style = gtk_widget_get_style(v9t9_command_log);
  354.     return style->font;
  355. }
  356.  
  357. /*
  358.  *    Change font used to display log text, NULL means reset to default
  359.  */
  360. void
  361. GTK_change_log_font(gchar *fontname)
  362. {
  363. #if defined(UNDER_UNIX)
  364.     GtkRcStyle *rcstyle = gtk_rc_style_new();
  365. #else
  366.     GtkStyle *rcstyle = gtk_style_new(); 
  367. #endif    
  368.  
  369.     if (GTK_OBJECT(v9t9_command_log)->flags & GTK_DESTROYED) {
  370.         g_free(rcstyle);
  371.         return;
  372.     }
  373.  
  374.     if (fontname) {
  375. #if defined(UNDER_UNIX)
  376.         rcstyle->font_name = fontname;
  377.         gtk_widget_modify_style(v9t9_command_log, rcstyle);
  378. #else
  379.         rcstyle->font = gdk_font_load(fontname);
  380.         gtk_widget_set_style(v9t9_command_log, rcstyle);
  381. #endif        
  382.     } else {
  383.         // this is probably too harsh for a cancel
  384.         gtk_widget_restore_default_style(v9t9_command_log);
  385.     }
  386. //    g_free(rcstyle);
  387. }
  388.  
  389. /*
  390.  *    Delete all text in the log
  391.  */
  392. void
  393. GTK_flush_log(void)
  394. {
  395.     if (!(GTK_OBJECT(v9t9_command_log)->flags & GTK_DESTROYED))
  396.         gtk_editable_delete_text(GTK_EDITABLE(v9t9_command_log), 
  397.                                  0, -1);
  398. }
  399.  
  400. /*
  401.  *    Append text to command log
  402.  */
  403. void
  404. GTK_append_log(const gchar *text, GdkColor *color, GdkFont *font)
  405. {
  406.     if (!(GTK_OBJECT(v9t9_command_log)->flags & GTK_DESTROYED))
  407.         gtk_text_insert(GTK_TEXT(v9t9_command_log), 
  408.                         font, 
  409.                         color, 
  410.                         NULL, 
  411.                         text, 
  412.                         strlen(text));
  413. }
  414.  
  415. /*    
  416.  *    Send a command to V9t9
  417.  */
  418. void
  419. GTK_send_command(const gchar *text)
  420. {
  421.     GdkColor red = { 0, 0x8000, 0x0000, 0x0000 };
  422.  
  423.     GTK_append_log(text, &red, NULL);
  424.     GTK_append_log("\n", &red, NULL);
  425.  
  426.     if (!pthread_mutex_lock(&emulator_lock)) {
  427.         command_parse_text((char *)text);
  428.         pthread_mutex_unlock(&emulator_lock);
  429.     }
  430. }
  431.  
  432.  
  433. #endif    // defined(GTK_VIDEO) && defined(GTK_KEYBOARD)
  434.  
  435.