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

  1. /*
  2.  *    Main program for Un*x-hosted v9t9.
  3.  *
  4.  */
  5. #include <signal.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include <sys/time.h>
  9. #include <X11/Xlib.h>
  10. #include <stdarg.h>
  11.  
  12. #include "v9t9_common.h"
  13. #include "system.h"
  14. #include "timer.h"
  15. #include "v9t9.h"
  16.  
  17. #include "command_rl.h"
  18. #include "debugger.h"
  19. #include "moduleconfig.h"
  20. #include "v9t9_module.h"
  21.  
  22. #include <gtk/gtk.h>
  23. #include "gtkloop.h"
  24. #include "gtkinterface.h"
  25. #include "unixmain.h"
  26.  
  27. #define _L     LOG_INTERNAL | LOG_INFO
  28.  
  29. static int    unix_v9t9_initialized;
  30. int         console_fd;
  31. int         gdb_debugging = 0;
  32.  
  33. static void
  34. system_initlog(void);
  35.  
  36. static void
  37. system_termlog(void);
  38.  
  39. int        (*frontend_loop)(void) = 0L;
  40. void    (*frontend_getcommands)(void);
  41. void    (*frontend_log)(u32 srcflags, const char *text) = 0L;
  42. void    (*frontend_report_status)(status_item item, va_list va) = 0L;
  43. void    (*frontend_debugger_enabled)(bool enabled) = 0L;
  44. void    (*frontend_execution_paused)(bool paused) = 0L;
  45.  
  46. static void
  47. sigsegv(int x)
  48. {
  49.     //v9t9_restop();
  50.     if (linuxKeyboard.runtimeflags & vmRTInUse)
  51.         linuxKeyboard.restop();
  52.     if (!gdb_debugging) {
  53.         signal(SIGSEGV, SIG_DFL);
  54.         logger(_L | LOG_FATAL, "SIGSEGV caught.\n");
  55.         exit(23);
  56.     } else {
  57.         signal(SIGSEGV, SIG_DFL);
  58.         *(char *) 0 = 0;
  59.     }
  60. }
  61.  
  62. #if defined(LINUX_SVGA_KEYBOARD) && defined(LINUX_SVGA_VIDEO)
  63. #define HAS_SVGA    1
  64. #endif
  65.  
  66. #if defined(X_WIN_KEYBOARD) && defined(X_WIN_VIDEO)
  67. #define HAS_XLIB    1
  68. #endif
  69.  
  70. #if defined(GTK_KEYBOARD) && defined(GTK_VIDEO)
  71. #define    HAS_GTK        1
  72. #endif
  73.  
  74. int
  75. main(int argc, char **argv)
  76. {
  77.     enum {
  78.         FE_UNKNOWN,
  79. #if HAS_SVGA
  80.         FE_SVGA,
  81. #endif
  82. #if HAS_XLIB
  83.         FE_XLIB,
  84. #endif
  85. #if HAS_GTK
  86.         FE_GTK,
  87. #endif
  88.     }    frontend = FE_UNKNOWN;
  89.     Display *display;
  90.  
  91.     int ret;
  92.     int status;
  93.  
  94.     v9t9_config(argc, argv);
  95.  
  96.     unix_v9t9_initialized = 0;
  97.  
  98.     system_initlog();
  99.     initlog();
  100.  
  101.     console_fd = open("/dev/console", O_RDWR);
  102. //  sound_fd = open("/dev/dsp", O_RDWR);
  103.  
  104.     if (argc > 1 && strcmp(argv[1], "--debug") == 0) {
  105.         gdb_debugging = 1;
  106.         argc--;
  107.         argv++;
  108.     }
  109.  
  110.     if (!gdb_debugging)
  111.       signal(SIGSEGV, sigsegv);
  112.     else
  113.       signal(SIGSEGV, SIG_DFL);
  114.  
  115. #ifdef LINUX_SVGA_VIDEO
  116.     if (argc > 1 && strcmp(argv[1], "--no-video") == 0) {
  117.         svgaVideo.runtimeflags |= vmRTUnselected;
  118.         argc--;
  119.         argv++;
  120.     }
  121. #endif
  122.  
  123. #ifdef LINUX_SVGA_KEYBOARD
  124.     if (argc > 1 && strcmp(argv[1], "--no-kbd") == 0) {
  125.         linuxKeyboard.runtimeflags |= vmRTUnselected;
  126.         argc--;
  127.         argv++;
  128.     }
  129. #endif
  130.  
  131.     /* Look for explicit choice of frontend */
  132.     if (argc > 2 && strcmp(argv[1], "-fe") == 0) {
  133. #if HAS_SVGA
  134.         if (strcasecmp(argv[2], "svga") == 0) {
  135.             frontend = FE_SVGA;
  136.             argv += 2;
  137.             argc -= 2;
  138.         } else 
  139. #endif
  140. #if HAS_XLIB
  141.         if (strcasecmp(argv[2], "xlib") == 0) {
  142.             frontend = FE_XLIB;
  143.             argv += 2;
  144.             argc -= 2;
  145.         } else 
  146. #endif
  147. #if HAS_GTK
  148.         if (strcasecmp(argv[2], "gtk") == 0) {
  149.             frontend = FE_GTK;
  150.             svgaVideo.runtimeflags |= vmRTUnselected;
  151.             linuxKeyboard.runtimeflags |= vmRTUnselected;
  152.             argv += 2;
  153.             argc -= 2;
  154.         } else
  155. #endif
  156.         {
  157.             logger(_L|LOG_USER|LOG_ERROR, "Unknown option '%s %s';\n"
  158.                     "expected one of "
  159. #if HAS_SVGA
  160.                    "svga|"
  161. #endif
  162. #if HAS_XLIB
  163.                    "xlib|"
  164. #endif
  165. #if HAS_GTK
  166.                    "gtk"
  167. #endif
  168.                    "\n",
  169.                     argv[1], argv[2]);
  170.             return 1;
  171.         }
  172.     }
  173.  
  174.     argv[0] = v9t9_argv[0];
  175.     v9t9_argv = argv;
  176.     v9t9_argc = argc;
  177.  
  178. #if HAS_GTK || HAS_XLIB
  179.     /* Check for X connection before assuming GTK
  180.        will work; it ABORTS if it can't open a connection. */
  181.  
  182.     if ((display = XOpenDisplay(NULL)) == NULL) {
  183.         if (frontend == FE_UNKNOWN 
  184. #if HAS_GTK
  185.             || frontend == FE_GTK
  186. #endif
  187.             )
  188.             frontend = FE_SVGA;
  189.     } else {
  190.         XrmInitialize();
  191.         XCloseDisplay(display);
  192.     }
  193. #endif
  194.  
  195. #if HAS_GTK
  196.     if ((frontend == FE_UNKNOWN || frontend == FE_GTK) && 
  197.         GTK_system_init()) {
  198.         frontend = FE_GTK;
  199.         frontend_log = GTK_system_log;
  200.         frontend_getcommands = unix_system_getcommands;
  201.         frontend_report_status = GTK_system_report_status;
  202.         frontend_debugger_enabled = GTK_system_debugger_enabled;
  203.         frontend_execution_paused = GTK_system_execution_paused;
  204.         frontend_loop = GTK_system_loop;
  205.  
  206. #if HAS_SVGA
  207.         svgaVideo.runtimeflags |= vmRTUnselected;
  208.         linuxKeyboard.runtimeflags |= vmRTUnselected;
  209. #endif
  210. #if HAS_XLIB
  211.         X_Video.runtimeflags |= vmRTUnselected;
  212.         X_Keyboard.runtimeflags |= vmRTUnselected;
  213. #endif
  214.         logger(_L|LOG_USER, "Using GTK\n");
  215.         v9t9_window = create_v9t9_window();
  216.         v9t9_drawing_area = gtk_object_get_data(GTK_OBJECT(v9t9_window),
  217.                                                 "v9t9_drawing_area");
  218.         gtk_widget_show(v9t9_window);
  219.     } else 
  220. #endif
  221. #if HAS_XLIB
  222.     if ((frontend == FE_UNKNOWN || frontend == FE_XLIB) && 
  223.                xlib_system_init()) {
  224.         frontend = FE_XLIB;
  225.         frontend_log = unix_system_log;
  226.         frontend_getcommands = unix_system_getcommands;
  227.         frontend_report_status = unix_system_report_status;
  228.         frontend_loop = xlib_system_loop;
  229.         frontend_debugger_enabled = unix_system_debugger_enabled;
  230.         frontend_execution_paused = unix_system_execution_paused;
  231.  
  232. #if HAS_SVGA
  233.         svgaVideo.runtimeflags |= vmRTUnselected;
  234.         linuxKeyboard.runtimeflags |= vmRTUnselected;
  235. #endif
  236. #if HAS_GTK
  237.         gtkVideo.runtimeflags |= vmRTUnselected;
  238.         gtkKeyboard.runtimeflags |= vmRTUnselected;
  239. #endif
  240.         logger(_L|LOG_USER, "Using Xlib\n");
  241.     } else 
  242. #endif
  243. #if HAS_SVGA
  244.     if ((frontend == FE_UNKNOWN || frontend == FE_SVGA) && 
  245.                svga_system_init()) {
  246.         frontend = FE_SVGA;
  247.         frontend_log = unix_system_log;
  248.         frontend_getcommands = unix_system_getcommands;
  249.         frontend_report_status = unix_system_report_status;
  250.         frontend_loop = svga_system_loop;
  251.         frontend_debugger_enabled = unix_system_debugger_enabled;
  252.         frontend_execution_paused = unix_system_execution_paused;
  253.  
  254. #if HAS_XLIB
  255.         X_Video.runtimeflags |= vmRTUnselected;
  256.         X_Keyboard.runtimeflags |= vmRTUnselected;
  257. #endif
  258. #if HAS_GTK
  259.         gtkVideo.runtimeflags |= vmRTUnselected;
  260.         gtkKeyboard.runtimeflags |= vmRTUnselected;
  261. #endif
  262.  
  263.         logger(_L|LOG_USER, "Using SVGAlib\n");
  264.     } else 
  265. #endif
  266.     {
  267.         logger(_L|LOG_FATAL, "Could not find a frontend\n");
  268.         return 2;
  269.     }
  270.  
  271.     if (!v9t9_init())
  272.         return 3;
  273.  
  274.     if (!v9t9_restart())
  275.         return 4;
  276.  
  277.     signal(SIGINT, v9t9_sigint);
  278.     signal(SIGTERM, v9t9_sigterm);
  279.  
  280.     unix_v9t9_initialized = 1;
  281.     ret = frontend_loop();
  282.  
  283.     v9t9_restop();
  284.  
  285.     v9t9_term(ret);
  286.  
  287.     termlog();
  288.     system_termlog();
  289.  
  290.     wait(&status);
  291.     exit(ret);
  292. }
  293.  
  294.  
  295. void
  296. unix_system_pause(void)
  297. {
  298.     /* Recommended way from glibc info pages
  299.        for waiting until a certain signal arrives. */
  300.     sigset_t    mask, oldmask;
  301.  
  302.     sigemptyset(&mask);
  303.     sigaddset(&mask, SIGINT);
  304.     sigprocmask(SIG_BLOCK, &mask, &oldmask);
  305.     sigsuspend(&oldmask);
  306.     sigprocmask(SIG_UNBLOCK, &mask, NULL);
  307. }
  308.  
  309. void
  310. system_getcommands(void)
  311. {
  312.     if (frontend_getcommands)
  313.         frontend_getcommands();
  314.     else
  315.         unix_system_getcommands();
  316. }
  317.  
  318. void
  319. unix_system_getcommands(void)
  320. {
  321.     FILE       *cmdsin = fopen("/dev/tty", "r");
  322.     FILE       *cmdsout = fopen("/dev/tty", "w");
  323.  
  324.     logger(_L|LOG_INFO, "Entering interactive mode\n");
  325.     if (cmdsin == NULL || cmdsout == NULL || feof(cmdsin)) {
  326.         logger(_L|LOG_ERROR, "FAILED: could not open terminal\n");
  327.         return;
  328.     }
  329.  
  330. // this leaves sound and timer going!
  331. //    if (X_Video.runtimeflags & vmRTInUse) 
  332. //      MODULE_ITERATE(vmKeyboard, vmRestopModule);
  333. //    else
  334.     v9t9_restop();
  335.  
  336. //    system_task();                // eat up X events
  337.     readline_getcommands(cmdsin, cmdsout);
  338.  
  339. // this leaves sound and timer going!
  340. //    if (X_Video.runtimeflags & vmRTInUse) 
  341. //      MODULE_ITERATE(vmKeyboard, vmRestartModule);
  342. //    else
  343.     v9t9_restart();
  344.  
  345. }
  346.  
  347. static struct itimerval my_timer;
  348. unsigned int TM_Ticked;
  349.  
  350. static void unix_system_timer_handler(int unused)
  351. {
  352.     TM_Ticked++;
  353.     if (TM_Ticked > 10) TM_Ticked = 10;
  354.     if (!(stateflag & ST_PAUSE)) stateflag |= ST_STOP;
  355. }
  356.  
  357. void
  358. system_timer_init(void)
  359. {
  360.     TM_Ticked = 0;
  361. }
  362.  
  363. void
  364. system_timer_install(void)
  365. {
  366.     struct sigaction s;
  367.  
  368. //    s.sa_handler = TM_TickHandler;
  369.     s.sa_handler = unix_system_timer_handler;
  370.     sigemptyset(&s.sa_mask);
  371.     s.sa_flags = SA_RESTART;
  372.     s.sa_restorer = NULL;
  373.  
  374.     sigaction(SIGALRM, &s, NULL);
  375.  
  376.     my_timer.it_value.tv_sec = 0;
  377.     my_timer.it_value.tv_usec = 1000000 / TM_HZ;    /* Hz */
  378.     my_timer.it_interval.tv_sec = 0;
  379.     my_timer.it_interval.tv_usec = 1000000 / TM_HZ;
  380.  
  381.     setitimer(ITIMER_REAL, &my_timer, NULL);
  382. }
  383.  
  384. void
  385. system_timer_uninstall(void)
  386. {
  387.     struct itimerval t;
  388.  
  389.     /* turn off and save current timer */
  390.     memset((void *) &t, 0, sizeof(t));
  391.  
  392.     setitimer(ITIMER_REAL, &t, &my_timer);
  393. }
  394.  
  395. //  We emit text to both stdout and a logfile.
  396.  
  397. static FILE *logfile;            // to disk
  398. static FILE *loguser;            // to tty
  399.  
  400. static void
  401. system_initlog(void)
  402. {
  403.     if ((logfile = fopen("log.unix.txt", "w")) == NULL) {
  404.         fprintf(stderr, "Could not create log file\n");
  405.         exit(1);
  406.     }
  407.     if ((loguser = fopen("/dev/tty", "w")) == NULL) {
  408.         fprintf(stderr, "Could not create user log file\n");
  409.         exit(1);
  410.     }
  411.     setbuf(logfile, NULL);
  412.     setbuf(loguser, NULL);
  413.     atexit(system_termlog);
  414. }
  415.  
  416. static void
  417. system_termlog(void)
  418. {
  419.     fclose(logfile);
  420.     fclose(loguser);
  421. }
  422.  
  423. void
  424. system_log(u32 srcflags, const char *text)
  425. {
  426.     fwrite(text, 1, strlen(text), logfile);
  427.     fflush(logfile);
  428.  
  429.     if (!unix_v9t9_initialized && (srcflags & LOG_TYPE_MASK) == LOG_ERROR) {
  430.         fwrite(text, 1, strlen(text), stdout);
  431.         fflush(stdout);
  432.     }
  433.  
  434.     if (frontend_log)
  435.         frontend_log(srcflags, text);
  436. }
  437.  
  438. void
  439. unix_system_log(u32 srcflags, const char *text)
  440. {
  441.     if (LOG_IS_VISIBLE(srcflags)) {
  442.         const char *cptr = strchr(text, ':');
  443.  
  444.         if (!cptr || (srcflags & LOG_SRC_MASK) == 0)
  445.             cptr = text;
  446.         else
  447.             cptr += 2;
  448.         if (*text == '\n' && cptr != text)
  449.             fwrite("\n", 1, 1, loguser);
  450.         fwrite(cptr, 1, strlen(cptr), loguser);
  451.         fflush(loguser);
  452.     }
  453. }
  454.  
  455.  
  456. #define ITEM_ON_CODE_LINE(item) \
  457.         ((item) >= STATUS_CPU_PC && \
  458.         (item) <= STATUS_CPU_INSTRUCTION_LAST && \
  459.          (item) != STATUS_CPU_REGISTER_VIEW)
  460.  
  461. void
  462. system_report_status(status_item item, va_list va)
  463. {
  464.     char buffer[1024], *bptr = buffer+1;
  465.     static bool last_item_on_code_line;
  466.     bool item_on_code_line;
  467.  
  468.     report_status_text(item, va, bptr, sizeof(buffer)-1);
  469.  
  470.     if (*bptr)
  471.     {
  472.         item_on_code_line = ITEM_ON_CODE_LINE(item);
  473.         if (last_item_on_code_line != item_on_code_line) {
  474.             buffer[0] = '\n';
  475.             bptr--;
  476.         }
  477.  
  478.         system_log(LOG_USER, bptr);
  479.  
  480.         last_item_on_code_line = item_on_code_line;
  481.     }
  482.  
  483.     if (frontend_report_status)
  484.         frontend_report_status(item, va);
  485. }
  486.  
  487. void
  488. unix_system_report_status(status_item item, va_list va)
  489. {
  490. }
  491.  
  492. void
  493. system_debugger_enabled(bool enabled)
  494. {
  495.     if (frontend_debugger_enabled)
  496.         frontend_debugger_enabled(enabled);
  497. }
  498.  
  499. void
  500. unix_system_debugger_enabled(bool enabled)
  501. {
  502. }
  503.  
  504. void
  505. system_execution_paused(bool paused)
  506. {
  507.     if (frontend_execution_paused)
  508.         frontend_execution_paused(paused);
  509. }
  510.  
  511. void
  512. unix_system_execution_paused(bool paused)
  513. {
  514.     logger(LOG_USER, "Execution is %s\n", 
  515.            paused  ? "paused" : "resumed");
  516. }
  517.