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

  1. /*
  2. #error in disk dialog, need to quote string c:\tidisk\disk
  3. #error move win32 code into winloop.c again
  4. #error figure out why the startup problems sometimes
  5. #error why do we need to reparent?
  6. #error upon parse error, force reset of parser (escapes and such appear to cause this)
  7. #error propagate closes (v9t9_window)
  8. #error be sure to use correct log
  9. */
  10. #include "winv9t9.h"
  11. #include "v9t9_common.h"
  12.  
  13. #include <gtk/gtk.h>
  14. #include "gtkloop.h"
  15. #include "gtkinterface.h"
  16.  
  17. #include "log.h"
  18. #include "9900.h"
  19. #include "memory.h"
  20. #include "vdp.h"
  21. #include "timer.h"
  22. #include "v9t9.h"
  23. #include "video.h"
  24. #include "system.h"
  25. #include "command.h"
  26. #include "resource.h"
  27. #include "moduleconfig.h"
  28.  
  29. #include "video_win32.h"
  30.  
  31. #define _L     LOG_INFO | LOG_HOSTOS
  32.  
  33. static int  _argc_;
  34. static char **_argv_;
  35.  
  36. extern vmModule win32DirectDrawVideo, win32DrawDibVideo;
  37. extern vmModule win32KbdModule;
  38.  
  39. // used by directsound
  40. HWND        hWndApp;
  41. HWND        hWndWindow, hWndStatus;    // our windows
  42. HWND        hWndScreen;                // DD window
  43. //HACCEL        hAccelerators;            // key accelerators
  44.  
  45. HINSTANCE    myHInst, myHPreInst;    // startup params for video modules
  46. int            mynCmdShow;            
  47.  
  48. static void
  49. system_initlog(void);
  50.  
  51. static void
  52. system_termlog(void);
  53.  
  54. int        (*frontend_loop)(void) = 0L;
  55. void    (*frontend_getcommands)(void);
  56. void    (*frontend_log)(u32 srcflags, const char *text) = 0L;
  57. //void    (*frontend_statusline)(int line, const char *text) = 0L;
  58. void    (*frontend_report_status)(status_item item, va_list va) = 0L;
  59. void    (*frontend_debugger_enabled)(bool enabled) = 0L;
  60. void    (*frontend_execution_paused)(bool paused) = 0L;
  61.  
  62.  
  63. static void 
  64. MakeARGV(char *cmd)
  65. {
  66.     int         quoting = 0;
  67.     char       *ptr = cmd;
  68.     char       *arg = NULL;
  69.  
  70.     while (*ptr && isspace(*ptr))
  71.         ptr++;
  72.  
  73.     _argc_ = 0;
  74.     _argv_ = 0;
  75.  
  76.     _argv_ = (char **) xmalloc(2 * sizeof(char *));
  77.  
  78.     _argv_[_argc_++] = "v9t9";
  79.  
  80.     while (*ptr) {
  81.         if (arg == NULL) {
  82.             _argv_ =
  83.  
  84.                 (char **) xrealloc(_argv_, (_argc_ + 2) * sizeof(char *));
  85.             arg = _argv_[_argc_] = ptr;
  86.             _argc_++;
  87.         }
  88.  
  89.         if (quoting && *ptr == '\"') {
  90.             ptr++;
  91.             quoting = 0;
  92.         } else if (quoting)
  93.             *arg++ = *ptr++;
  94.         else if (*ptr == '\"') {
  95.             ptr++;
  96.             quoting = 1;
  97.         } else if (*ptr == ' ') {
  98.             *arg = 0;
  99.             arg = NULL;
  100.             ptr++;
  101.         } else
  102.             *arg++ = *ptr++;
  103.     }
  104.     if (arg)
  105.         *arg = 0;
  106.     _argv_[_argc_] = 0;
  107. }
  108.  
  109.  
  110. int win_frontend;
  111.  
  112. int WINAPI
  113. WinMain(HINSTANCE hInst,        /*Win32 entry-point routine */
  114.         HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow)
  115. {
  116.     int ret;
  117.  
  118.     win_frontend = FE_UNKNOWN;
  119.         
  120.     system_initlog();
  121.     initlog();
  122.  
  123.     if (!win_createBitmap())
  124.         return vmInternalError;
  125.  
  126.     MakeARGV(lpszCmdLine);
  127.  
  128. #define argc v9t9_argc
  129. #define argv v9t9_argv
  130.  
  131.     v9t9_config(_argc_, _argv_);
  132.  
  133.     /* Look for explicit choice of win_frontend */
  134.     if (argc > 2 && strcmp(argv[1], "-fe") == 0) {
  135. #if HAS_DDRAW
  136.         if (strcasecmp(argv[2], "ddraw") == 0) {
  137.             win_frontend = FE_DDRAW;
  138.             argv += 2;
  139.             argc -= 2;
  140.         } else 
  141. #endif
  142. #if HAS_DRAWDIB
  143.         if (strcasecmp(argv[2], "drawdib") == 0 ||
  144.             strcasecmp(argv[2], "win32") == 0) {
  145.             win_frontend = FE_DRAWDIB;
  146.             argv += 2;
  147.             argc -= 2;
  148.         } else 
  149. #endif
  150. #if HAS_GTK
  151.         if (strcasecmp(argv[2], "gtk") == 0) {
  152.             win_frontend = FE_GTK;
  153.             argv += 2;
  154.             argc -= 2;
  155.         } else
  156. #endif
  157.         {
  158.             logger(_L|LOG_USER|LOG_ERROR, "Unknown option '%s %s';\n"
  159.                     "expected one of "
  160. #if HAS_DDRAW
  161.                    "ddraw|"
  162. #endif
  163. #if HAS_DRAWDIB
  164.                    "win32|"
  165. #endif
  166. #if HAS_GTK
  167.                    "gtk"
  168. #endif
  169.                    "\n",
  170.                     argv[1], argv[2]);
  171.             return 1;
  172.         }
  173.     }
  174.  
  175. #if HAS_GTK && HAS_DRAWDIB
  176.     if ((win_frontend == FE_UNKNOWN || win_frontend == FE_GTK) && 
  177.         GTK_system_init()) {
  178.         char *var;
  179.         
  180.         win_frontend = FE_GTK;
  181.         frontend_log = GTK_system_log;
  182.         frontend_getcommands = win32_system_getcommands;
  183.         frontend_report_status = GTK_system_report_status;
  184.         frontend_debugger_enabled = GTK_system_debugger_enabled;
  185.         frontend_execution_paused = GTK_system_execution_paused;
  186.         frontend_loop = win32_gtk_system_loop;
  187.  
  188. #if HAS_DDRAW
  189.         win32DirectDrawVideo.runtimeflags |= vmRTUnselected;
  190. #endif
  191. #if HAS_DRAWDIB
  192. //        win32DrawDibVideo.runtimeflags |= vmRTUnselected;
  193. #endif
  194.  
  195.         // why why why does the GTK win32 interface suck so bad?
  196.         // I got over the video speed problems but finally
  197.         // hit a dead end when finding that the keyboard events
  198.         // are always on/off right in succession, even with the
  199.         // key held down... sigh...
  200.         gtkVideo.runtimeflags |= vmRTUnselected;
  201.         gtkKeyboard.runtimeflags |= vmRTUnselected;
  202.         
  203.         // don't ask me why, but the presence of this
  204.         // variable causes a MASSIVE startup delay
  205.         var = getenv("HOME");
  206.         if (var) *var = 0;
  207.         SetEnvironmentVariable("HOME", NULL);
  208.         
  209.         logger(_L|LOG_USER, "Using GTK\n");
  210.  
  211. #if 1
  212.         v9t9_window = create_v9t9_window();
  213.         v9t9_drawing_area = gtk_object_get_data(GTK_OBJECT(v9t9_window),
  214.                                                 "v9t9_drawing_area");
  215. // don't show this since it's empty!  (drawdib puts up separate window)
  216. //        gtk_widget_show(v9t9_window);
  217. #endif        
  218.     } else 
  219. #endif
  220. #if HAS_DRAWDIB
  221.     if ((win_frontend == FE_UNKNOWN || win_frontend == FE_DRAWDIB) && 
  222.                win32_system_init()) {
  223.         win_frontend = FE_DRAWDIB;
  224.         frontend_log = win32_system_log;
  225.         frontend_getcommands = win32_system_getcommands;
  226.         frontend_report_status = win32_system_report_status;
  227.         frontend_debugger_enabled = win32_system_debugger_enabled;
  228.         frontend_execution_paused = win32_system_execution_paused;
  229.         frontend_loop = win32_system_loop;
  230.  
  231. #if HAS_DDRAW
  232.         win32DirectDrawVideo.runtimeflags |= vmRTUnselected;
  233.         //win32Keyboard.runtimeflags |= vmRTUnselected;
  234. #endif
  235. #if HAS_GTK
  236.         gtkVideo.runtimeflags |= vmRTUnselected;
  237.         gtkKeyboard.runtimeflags |= vmRTUnselected;
  238. #endif
  239.         logger(_L|LOG_USER, "Using DrawDib\n");
  240.     } else 
  241. #endif
  242. #if HAS_DDRAW
  243.     if ((win_frontend == FE_UNKNOWN || win_frontend == FE_DDRAW) && 
  244.                win32_system_init()) {
  245.         win_frontend = FE_DDRAW;
  246.         frontend_log = win32_system_log;
  247.         frontend_getcommands = win32_system_getcommands;
  248.         frontend_report_status = win32_system_report_status;
  249.         frontend_debugger_enabled = win32_system_debugger_enabled;
  250.         frontend_execution_paused = win32_system_execution_paused;
  251.         frontend_loop = win32_system_loop;
  252.  
  253. #if HAS_DRAWDIB
  254.         win32DrawDibVideo.runtimeflags |= vmRTUnselected;
  255.         //win32Keyboard.runtimeflags |= vmRTUnselected;
  256. #endif
  257. #if HAS_GTK
  258.         gtkVideo.runtimeflags |= vmRTUnselected;
  259.         gtkKeyboard.runtimeflags |= vmRTUnselected;
  260. #endif
  261.  
  262.         logger(_L|LOG_USER, "Using DirectDraw\n");
  263.     } else 
  264. #endif
  265.     {
  266.         logger(_L|LOG_FATAL, "Could not find a frontend\n");
  267.         return 2;
  268.     }
  269.  
  270. #if HAS_GTK
  271.     if (win_frontend == FE_GTK)
  272.     {
  273.         gtk_text_freeze(GTK_TEXT(v9t9_command_log));
  274.     }
  275. #endif
  276.  
  277.     if (!v9t9_init())
  278.         return 3;
  279.  
  280. #if HAS_GTK
  281.     if (win_frontend == FE_GTK)
  282.     {
  283.         gtk_text_thaw(GTK_TEXT(v9t9_command_log));
  284.     }
  285. #endif
  286.  
  287.     if (!v9t9_restart())
  288.         return 4;
  289.  
  290.  
  291. #undef argc
  292. #undef argv
  293.  
  294.     ret = frontend_loop();
  295.  
  296.     v9t9_restop();
  297.  
  298.     v9t9_term(ret);
  299.  
  300.     termlog();
  301.     system_termlog();
  302.  
  303.     PostQuitMessage(0);
  304.     exit(ret);
  305.     return TRUE;
  306. }
  307.  
  308. ////////////////
  309. int 
  310. win32_system_init(void)
  311. {
  312.     return 1;
  313. }
  314.  
  315. static int  TM_Ticked;            /* we can't do jack inside a callback */
  316.  
  317. int v9t9_return;
  318.  
  319. int
  320. win32_system_loop(void)
  321. {
  322.     int ret;
  323.     MSG         lpMsg;
  324.  
  325.     while (1) {
  326.     #if defined(USE_MM_TIMER) || defined(USE_WAITABLE_TIMER)
  327.         while (TM_Ticked) {
  328.             TM_TickHandler(0);
  329. //            TM_Ticked--;
  330.             TM_Ticked = 0;
  331.         }
  332.     #endif
  333.     
  334.         lpMsg.message = WM_NULL;
  335.         while (PeekMessage(&lpMsg, NULL, 0, 0, PM_REMOVE)) {
  336.             if (lpMsg.message == WM_DESTROY || lpMsg.message == WM_CLOSE) 
  337.                 return 1;
  338.                 
  339.             TranslateMessage(&lpMsg);
  340.             DispatchMessage(&lpMsg);
  341.         }
  342.             
  343.         ret = v9t9_execute();
  344.         if (ret == em_TooFast)
  345.             win32_system_pause();
  346.         else if (ret == em_Quitting || ret == em_Dying)
  347.             break;
  348.     }
  349.     return ret == em_Dying;
  350. }
  351.  
  352. extern gint gtk_idle_handler(gpointer *data);
  353.  
  354.  
  355. static int 
  356. win32_system_idle(gpointer *data)
  357. {
  358.     MSG         lpMsg;
  359.     int ret;
  360.  
  361. #if defined(USE_MM_TIMER) || defined(USE_WAITABLE_TIMER)
  362.     while (TM_Ticked /*1||(++TM_Ticked & 63)==0*/) {
  363.     //    logger(LOG_USER, ".");
  364.         TM_TickHandler(0);
  365.         TM_Ticked--;
  366.     }
  367. #endif
  368.  
  369.         /* window paints, keyboard messages */
  370.     while (PeekMessage(&lpMsg, NULL, 0, 0, PM_REMOVE)) {
  371.     //    logger(LOG_USER, "-");
  372.         TranslateMessage(&lpMsg);
  373.         DispatchMessage(&lpMsg);
  374.     }
  375.         
  376.     ret = v9t9_return = v9t9_execute();
  377.     if (ret == em_TooFast)
  378.         win32_system_pause();
  379.     else if (ret == em_Quitting || ret == em_Dying) {
  380.         gtk_main_quit();
  381.         return FALSE;
  382.     }
  383.     
  384.     return TRUE;
  385. }
  386.  
  387. int
  388. win32_gtk_system_loop(void)
  389. {
  390.     guint idle_id;
  391.  
  392.     idle_id = gtk_idle_add((GtkFunction) win32_system_idle, 0L);
  393.     
  394.     gtk_main();
  395.  
  396.     gtk_idle_remove(idle_id);
  397.  
  398.     gtk_widget_destroy(v9t9_window);    
  399.     return v9t9_return == em_Dying;
  400. }
  401.  
  402.  
  403. /////////
  404.  
  405. char        statuslines[8][160];
  406. void
  407. win_StatusLine(int which, char *text)
  408. {
  409. #if 0
  410.     strcpy(statuslines[which], text);
  411.     REDRAWSTATUS;
  412. #endif
  413. }
  414.  
  415. ////////////////
  416.  
  417. // in Timer.c
  418. extern HANDLE hTimerTickEvent;
  419.  
  420. /*    The value '1' is almost perfect.  
  421.     Don't try zero -- that makes v9t9 hog the processor and the OS
  422.     responds slowly and sluggishly. */
  423. void
  424. win32_system_pause(void)
  425. {
  426.     WaitForSingleObject(hTimerTickEvent, 1);
  427.     //TM_Ticked = 1;
  428. }
  429.  
  430. /************************************************/
  431.  
  432. #if defined(USE_MESSAGE_TIMER)
  433.  
  434. #define TIMERCODE 0x1
  435.  
  436. static UINT timer;
  437. static DWORD tm;
  438.  
  439. static void CALLBACK
  440. myHandleTimer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  441. {
  442.     if (idEvent == TIMERCODE) {
  443.         static DWORD lastcalled, lasttm;
  444.  
  445.         if (!lastcalled)
  446.             lastcalled = dwTime;
  447.  
  448.         /*  this loop is necessary since the timer event is
  449.            not at all prioritizable, and we can miss tons of
  450.            messages (on an unburdened Win98 box, it never goes
  451.            faster than 10Hz!)
  452.          */
  453.         while (lastcalled + 10 < dwTime) {
  454.             tm++;
  455.             lastcalled += 10;
  456.             TM_TickHandler(0);
  457.         }
  458.     }
  459. }
  460.  
  461. /*
  462. static void
  463. TakeABreak(void)
  464. {
  465.     stateflag |= ST_STOP;
  466. }
  467. */
  468. void
  469. system_timer_init(void)
  470. {
  471.     //TM_SetEvent(TM_UniqueTag(), TM_HZ*100/10, 0, TM_FUNC|TM_REPEAT, TakeABreak);
  472. }
  473.  
  474. void
  475. system_timer_install(void)
  476. {
  477.     timer = SetTimer(win_GetWindow(), TIMERCODE, 1000 / TM_HZ, myHandleTimer);    /* 100 Hz */
  478. }
  479.  
  480.  
  481. void
  482. system_timer_uninstall(void)
  483. {
  484.     KillTimer(win_GetWindow(), timer);
  485. }
  486.  
  487. #elif defined(USE_MM_TIMER)
  488.  
  489. #define TARGET_RESOLUTION (1000/TM_HZ)    /* 100 Hz */
  490. #define TIMERCODE 0x1
  491.  
  492. static UINT timer;
  493. static UINT timerRes;
  494. static DWORD tm;
  495.  
  496. HANDLE      hTimerTickEvent;
  497.  
  498. static void CALLBACK
  499. myHandleTimer(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
  500. {
  501.     if (uID == timer) {
  502.         TM_Ticked++;
  503.         if (TM_Ticked > 10) TM_Ticked = 10;
  504.  
  505.         if (!(stateflag & ST_PAUSE)) stateflag |= ST_STOP;
  506.         tm++;
  507.  
  508.         SetEvent(hTimerTickEvent);
  509.     }
  510. }
  511.  
  512. void
  513. system_timer_init(void)
  514. {
  515.     TIMECAPS    tc;
  516.  
  517.     logger(_L|L_2, "timer init\n");
  518.     if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
  519.         logger(_L | LOG_FATAL, "Could not get timer caps\n");
  520.         ExitThread(-1);
  521.     }
  522.  
  523.     timerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
  524.     logger(_L|L_2,"timerRes = %d\n", timerRes);
  525. }
  526.  
  527. void
  528. system_timer_install(void)
  529. {
  530.     timeBeginPeriod(timerRes);
  531.  
  532.     logger(_L|L_2, "timer install\n");
  533.     timer = timeSetEvent(timerRes, 1, myHandleTimer, 0, TIME_PERIODIC);
  534.     if (timer == 0) {
  535.         logger(_L | LOG_ERROR, "Could not set timer to %d ms\n\n", timerRes);
  536.         ExitThread(-1);
  537.     }
  538.     hTimerTickEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  539.     if (hTimerTickEvent == 0) {
  540.         logger(_L | LOG_ERROR, "Could not create timer event\n");
  541.         ExitThread(-1);
  542.     }
  543.  
  544. }
  545.  
  546.  
  547. void
  548. system_timer_uninstall(void)
  549. {
  550.     logger(_L|L_2, "timer uninstall\n");
  551.     timeKillEvent(timer);
  552.     timeEndPeriod(timerRes);
  553. }
  554.  
  555. #elif defined(USE_WAITABLE_TIMER)
  556.  
  557. #define TIMERCODE 0x1
  558.  
  559. static HANDLE hTimer;
  560. static DWORD tm;
  561.  
  562. static VOID APIENTRY
  563. myHandleTimer(LPVOID lpArgToCompletionRoutine,
  564.               DWORD dwTimerLowValue, DWORD dwTimerHighValue)
  565. {
  566. //  log("ticked\n");
  567.     TM_Ticked++;
  568.     if (TM_Ticked > 10) TM_Ticked = 10;
  569.     if (!(stateflag & ST_PAUSE)) stateflag |= ST_STOP;
  570.     tm++;
  571. }
  572.  
  573. void
  574. system_timer_init(void)
  575. {
  576.     hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
  577.     if (hTimer == 0) {
  578.         fatal("Could not create timer\n");
  579.     }
  580. }
  581.  
  582. void
  583. system_timer_install(void)
  584. {
  585.     LARGE_INTEGER pDue;
  586.  
  587.     pDue.QuadPart = -100;
  588.     if (!SetWaitableTimer
  589.         (hTimer, (LARGE_INTEGER *) & pDue, 10, myHandleTimer, 0, 0))
  590.         fatal("Could not set timer to 10 ms");
  591. }
  592.  
  593.  
  594. void
  595. system_timer_uninstall(void)
  596. {
  597.     CancelWaitableTimer(hTimer);
  598. }
  599.  
  600. #endif
  601.  
  602. void
  603. system_getcommands(void)
  604. {
  605.     if (frontend_getcommands)
  606.         frontend_getcommands();
  607.     else
  608.         win32_system_getcommands();
  609. }
  610.  
  611. void
  612. win32_system_getcommands(void)
  613. {
  614. //  SetForegroundWindow(hWndStatus);
  615.  
  616.     FILE       *cmds = fopen("CONIN$", "r");
  617.  
  618.     logger(_L | L_0, "Entering interactive mode\n\n");
  619.     if (cmds == NULL || feof(cmds)) {
  620.         logger(_L | LOG_USER | LOG_ERROR, "FAILED: could not open stdin\n\n");
  621.         return;
  622.     }
  623.  
  624.     v9t9_restop();
  625.  
  626.     while ((stateflag & ST_INTERACTIVE) && !feof(cmds)) {
  627.         char        buf[256];
  628.  
  629.         logger(_L | LOG_USER, "\nEnter a command> ");
  630.         if (fgets(buf, sizeof(buf), cmds) && *buf)
  631.             command_parse_text(buf);
  632.         else
  633.             logger(_L | LOG_USER, "<EOF>\n\n");
  634.     }
  635.  
  636.     v9t9_restart();
  637. }
  638.  
  639.  
  640. static FILE *logfile;
  641. static HANDLE conout;
  642.  
  643. static void
  644. system_initlog(void)
  645. {
  646.     if (logfile == NULL) {
  647.         COORD       buf;
  648.         SMALL_RECT  rect;
  649.  
  650.         logfile = fopen("log.win.txt", "w");
  651.         if (logfile == NULL)
  652.             FAIL("could not open log.win.txt\n");
  653.         if (!AllocConsole())
  654.             FAIL("Could not create console\n");
  655.         if ((conout = GetStdHandle(STD_OUTPUT_HANDLE)) ==
  656.             INVALID_HANDLE_VALUE) FAIL("Could not get stdout for console\n");
  657.         SetConsoleTitle("V9t9 Log");
  658.         SetConsoleMode(conout, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
  659.                        ENABLE_PROCESSED_INPUT | ENABLE_PROCESSED_OUTPUT |
  660.                        ENABLE_WRAP_AT_EOL_OUTPUT);
  661.         rect.Left = 0;
  662.         rect.Right = 80;
  663.         rect.Top = 0;
  664.         rect.Bottom = 25;
  665.         SetConsoleWindowInfo(conout, true, &rect);
  666.         buf.X = 80;
  667.         buf.Y = 25;
  668.         SetConsoleScreenBufferSize(conout, buf);
  669.     }
  670.  
  671. }
  672.  
  673. static void
  674. system_termlog(void)
  675. {
  676.     if (logfile) {
  677.         fclose(logfile);
  678.         FreeConsole();
  679.     }
  680. }
  681.  
  682. //  emit text to log (do not add newline)
  683. void
  684. win32_system_log(u32 srcflags, const char *text)
  685. {
  686.     int         len = strlen(text);
  687.     DWORD       writ;
  688.  
  689.     if (LOG_IS_VISIBLE(srcflags)) {
  690.         WriteFile(conout, text, len, &writ, NULL);
  691.     }
  692. }
  693.  
  694. void
  695. system_log(u32 srcflags, const char *text)
  696. {
  697.     if (logfile) {
  698.         fwrite(text, 1, strlen(text), logfile);
  699.         fflush(logfile);
  700.     }
  701.  
  702.     if (frontend_log)
  703.         frontend_log(srcflags, text);
  704. }
  705.  
  706. /*
  707. //  show debugger line
  708. static void
  709. system_statusline(int line, const char *text)
  710. {
  711.     if (logfile) {
  712.         if (!line)
  713.             fputs("\n", logfile);
  714.         fputs(text, logfile);
  715.         fputs("\n", logfile);
  716.     }
  717.  
  718.     if (frontend_statusline)
  719.         frontend_statusline(line, text);
  720. }
  721.  
  722. void
  723. win32_system_statusline(int line, const char *text)
  724. {
  725.     DWORD writ;
  726.     if (!line)
  727.         WriteFile(conout, "\r\n", 2, &writ, NULL);
  728.     WriteFile(conout, text, strlen(text), &writ, NULL);
  729.     WriteFile(conout, "\r\n", 2, &writ, NULL);
  730. }
  731. */
  732.  
  733. #define ITEM_ON_CODE_LINE(item) \
  734.         ((item) >= STATUS_CPU_PC && \
  735.         (item) <= STATUS_CPU_INSTRUCTION_LAST && \
  736.          (item) != STATUS_CPU_REGISTER_VIEW)
  737.  
  738. void
  739. system_report_status(status_item item, va_list va)
  740. {
  741.     char buffer[1024], *bptr = buffer+1;
  742.     static bool last_item_on_code_line;
  743.     bool item_on_code_line;
  744.  
  745.     report_status_text(item, va, bptr, sizeof(buffer)-1);
  746.  
  747.     if (*bptr)
  748.     {
  749.         item_on_code_line = ITEM_ON_CODE_LINE(item);
  750.         if (last_item_on_code_line != item_on_code_line) {
  751.             buffer[0] = '\n';
  752.             bptr--;
  753.         }
  754.  
  755.         system_log(LOG_USER, bptr);
  756.  
  757.         last_item_on_code_line = item_on_code_line;
  758.     }
  759.  
  760.     if (frontend_report_status)
  761.         frontend_report_status(item, va);
  762. }
  763.  
  764. void
  765. win32_system_report_status(status_item item, va_list va)
  766. {
  767. }
  768.  
  769. void
  770. system_execution_paused(bool paused)
  771. {
  772.     if (frontend_execution_paused)
  773.         frontend_execution_paused(paused);
  774. }
  775.  
  776. void
  777. win32_system_execution_paused(bool paused)
  778. {
  779.     logger(LOG_USER, "Execution is %s\n", 
  780.            paused  ? "paused" : "resumed");
  781. }
  782.  
  783. void
  784. system_debugger_enabled(bool enabled)
  785. {
  786.     if (frontend_debugger_enabled)
  787.         frontend_debugger_enabled(enabled);
  788. }
  789.  
  790. void
  791. win32_system_debugger_enabled(bool enabled)
  792. {
  793. }
  794.  
  795. int
  796. win_command(HWND hWnd, WORD cmd)
  797. {
  798.     logger(_L | L_1, "win_command: %d\n\n", cmd);
  799.     switch (cmd) {
  800.     case ID_FILE_EXIT:
  801.         v9t9_term(0);
  802.         break;
  803.  
  804.     case ID_MODULES_LOADMODULE:
  805.         return 0;
  806.  
  807.     case ID_VIDEO_FULLSCREEN:
  808.         win_video_switchmodes();
  809.         return 0;
  810.  
  811.     case ID_EMULATOR_RESETCOMPUTER:
  812.         command_parse_text("Reset\n");
  813.         return 0;
  814.  
  815.     case ID_COMMANDS_ENTERINTERACTIVEMODE:
  816.         command_parse_text("Interactive=On\n");
  817.         return 0;
  818.  
  819.     case ID_COMMANDS_RELOADV9T9CNF:
  820.         command_parse_text("#include \"v9t9.cnf\"\n");
  821.         return 0;
  822.         
  823.     case ID_OPEN_CONFIG:
  824.         command_parse_text("#include \"savesession.cnf\"\n");
  825.         return 0;
  826.         
  827.     case ID_SAVE_CONFIG:
  828.         command_parse_text("SaveConfig \"savesession.cnf\"\n");
  829.         return 0;
  830.                 
  831.     }
  832.     return 1;
  833. }
  834.