home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 October / VPR9710A.ISO / BENCH / DJ1SRC_K / 105 / CONTROL.C < prev    next >
C/C++ Source or Header  |  1997-05-02  |  28KB  |  1,145 lines

  1. /* This is file CONTROL.C */
  2. /*
  3.    ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4.    **
  5.    ** This file is distributed under the terms listed in the document
  6.    ** "copying.dj", available from DJ Delorie at the address above.
  7.    ** A copy of "copying.dj" should accompany this file; if not, a copy
  8.    ** should be available from where this file was obtained.  This file
  9.    ** may not be distributed without a verbatim copy of "copying.dj".
  10.    **
  11.    ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12.    ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  */
  14. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  15. /* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp) 
  16.    for reduce binary size and for dead code elimination.
  17.    and merged control.c and exphdlr.c
  18.  */
  19. /* History:87,1 */
  20.  
  21. #include "build.h"
  22.  
  23. TSS *tss_ptr;
  24. int debug_mode = 0;
  25. static int self_contained;
  26. long header_offset = 0;
  27. int use_ansi = 0;
  28. int use_mono = 0;
  29. static int redir_1_mono = 0;
  30. static int redir_2_mono = 0;
  31. static int redir_2_1 = 0;
  32. static int redir_1_2 = 0;
  33.  
  34. static int old_video_mode;
  35.  
  36. static int16 ems_handle = 0;    /*  Get EMS Handle  */
  37. word16 vcpi_installed = 0;        /*  VCPI Installed Flag  */
  38.  
  39. #if DEBUGGER
  40. extern void debugger(void);
  41. #else
  42. extern void go_til_stop(void);
  43. #endif
  44.  
  45. extern int cputype(void);
  46. extern int detect_80387(void);
  47. extern go_real_mode();
  48. extern void vcpi_flush(void);    /*  VCPI Memory All Cleared  */
  49. extern ivec0(), ivec1(), ivec7(), ivec75();
  50. extern interrupt_common(), page_fault();
  51. extern word32 far *pd;
  52.  
  53. static void init_controllers(void);
  54. static void uninit_controllers(void);
  55. static void __pascal set_command_line(char **argv, char **envv);
  56.  
  57. static void __pascal fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  58. {
  59.     GDT_S *g;
  60.     g = gdt + sel;
  61.     if (G & 2)
  62.         limit = limit >> 12;
  63.     g->lim0 = (word16) limit;
  64.     g->lim1 = (word8) (limit >> 16) & 0x0f;
  65.     g->base0 = (word16) base;
  66.     g->base1 = (word8) (base >> 16);
  67.     g->base2 = (word8) (base >> 24);
  68.     g->stype = type;
  69.     g->lim1 |= G * 0x40;
  70. }
  71.  
  72. word32 __pascal ptr2linear(void far * ptr)
  73. {
  74.     word32 linear = (word32) FP_SEG(ptr) * 16L + (word32) FP_OFF(ptr);
  75.     return linear;
  76. }
  77.  
  78. static void __pascal setup_tss(TSS * t, int (*eip) ())
  79. {
  80.     memset(t, 0, sizeof(TSS));
  81.     t->tss_eip = (long)FP_OFF(eip);
  82.     t->tss_esp = (long)FP_OFF(t->tss_stack);
  83.     t->tss_cs = g_rcode * 8;
  84.     t->tss_ss = t->tss_ds = t->tss_es = t->tss_fs = t->tss_gs = g_rdata * 8;
  85.     t->tss_eflags = 0x0200;
  86.     t->tss_iomap = 0xffff;        /* no map */
  87. }
  88.  
  89. static void exit_func(void)
  90. {
  91. #if TOPLINEINFO
  92.     int i;
  93. #endif
  94.     dalloc_uninit();
  95.     uninit_controllers();
  96.     xms_free();
  97.     if ((ems_handle) && (ems_handle != -1))
  98.         ems_free(ems_handle);    /*  Deallocated EMS Page    */
  99.     if (vcpi_installed)
  100.         vcpi_flush();            /*  Deallocated VCPI Pages  */
  101.  
  102. #if TOPLINEINFO
  103.     for (i = 0; i < 80; i++)
  104.         poke(screen_seg, i * 2, 0x0720);
  105. #endif
  106. }
  107.  
  108. static int ctrl_c_flag = 0;
  109.  
  110. static int ctrlbrk_func(void)
  111. {
  112. #if DEBUGGER
  113.     ctrl_c_flag = 1;
  114. #else
  115.     exit(3);
  116. #endif
  117.     return 0;
  118. }
  119.  
  120. static void usage(char *s)
  121. {
  122.     printf("Usage: %s [program [options . . . ]]\n", s);
  123.     _exit(1);
  124. }
  125.  
  126. int have_80387;
  127. int use_xms = 0;
  128. static word32 __pascal push32(void *ptr, int len);
  129.  
  130. int main(int argc, char **argv, char **envp)
  131. {
  132.     int i, n, set_brk, emu_installed;
  133.     struct stat stbuf;
  134.     char *cp, *path, *argv0, *emu_fn = 0;
  135.     unsigned short header[3];
  136.     set_brk = emu_installed = 0;
  137.  
  138.     if (xms_installed())
  139.         use_xms = 1;
  140.     old_video_mode = peekb(0x40, 0x49);
  141.  
  142.     if (!strcmp(argv[1], "!proxy")) {
  143.         int oseg, optr, i;
  144.         int far *oargv;
  145.         char far *oargve;
  146.         sscanf(argv[2], "%x", &argc);
  147.         sscanf(argv[3], "%x", &oseg);
  148.         sscanf(argv[4], "%x", &optr);
  149.         oargv = MK_FP(oseg, optr);
  150.         argv = (char **)malloc(sizeof(char *) * (argc + 1));
  151.         for (i = 0; i < argc + 1; i++) {
  152.             if (!oargv[i]) {
  153.                 argv[i] = 0;
  154.                 break;
  155.             }
  156.             oargve = MK_FP(oseg, oargv[i]);
  157.             for (optr = 0; oargve[optr]; optr++);
  158.             argv[i] = (char *)malloc(optr + 1);
  159.             for (optr = 0; oargve[optr]; optr++)
  160.                 argv[i][optr] = oargve[optr];
  161.             argv[i][optr] = 0;
  162.         }
  163.     }
  164.     ems_handle = emm_present();
  165.     switch (cputype()) {
  166.     case 1:
  167.         if ((ems_handle) && (ems_handle != -1))
  168.             ems_free(ems_handle);
  169.         fprintf(stderr, "CPU must be a 386 to run this program.\n");
  170.         exit(1);
  171.     case 2:
  172.         if (ems_handle) {
  173.             vcpi_installed = vcpi_present();
  174.             if (vcpi_installed)
  175.                 break;
  176.             else if (ems_handle != -1)
  177.                 ems_free(ems_handle);
  178.         }
  179.         fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
  180.         exit(1);
  181.     }
  182.  
  183.     if (peekb(0x40, 0x49) == 7)
  184.         screen_seg = 0xb000;
  185.  
  186.     _fmode = O_BINARY;
  187.  
  188.     cp = getenv("GO32");
  189.     path = 0;
  190.     if (cp)
  191.         while (1) {
  192.             char sw[100];
  193.             char val[100];
  194.             if (sscanf(cp, "%s%n", sw, &i) < 1)
  195.                 break;
  196.             cp += i;
  197.             if (!strcmp(sw, "ansi"))
  198.                 use_ansi = 1;
  199.             else if (!strcmp(sw, "mono"))
  200.                 use_mono = 1;
  201.             else if (!strcmp(sw, "2r1"))
  202.                 redir_2_1 = 1;
  203.             else if (!strcmp(sw, "1r2"))
  204.                 redir_1_2 = 1;
  205.             else if (!strcmp(sw, "2rm"))
  206.                 redir_2_mono = 1;
  207.             else if (!strcmp(sw, "1rm"))
  208.                 redir_1_mono = 1;
  209.             else {
  210.                 val[0] = 0;
  211.                 sscanf(cp, "%s%n", val, &i);
  212.                 cp += i;
  213.                 if (!val[0])
  214.                     break;
  215.             }
  216.             if (!strcmp(sw, "driver")) {
  217.                 if (path)
  218.                     free(path);
  219.                 path = strdup(val);
  220.             } else if (!strcmp(sw, "tw"))
  221.                 gr_def_tw = atoi(val);
  222.             else if (!strcmp(sw, "th"))
  223.                 gr_def_th = atoi(val);
  224.             else if (!strcmp(sw, "gw"))
  225.                 gr_def_gw = atoi(val);
  226.             else if (!strcmp(sw, "gh"))
  227.                 gr_def_gh = atoi(val);
  228.             else if (!strcmp(sw, "emu")) {
  229.                 if (emu_fn)
  230.                     free(emu_fn);
  231.                 emu_fn = strdup(val);
  232.             }
  233.         }
  234. #if ! DEBUGGER
  235.     use_mono = 0;
  236. #endif
  237.     setup_graphics_driver(path);
  238.     if (path)
  239.         free(path);
  240. #if DEBUGGER
  241.     if (use_mono) {
  242.         use_ansi = 0;
  243.         screen_seg = 0xb000;
  244.     }
  245. #endif
  246.     setbuf(stdin, 0);
  247.     atexit((atexit_t) exit_func);
  248.     ctrlbrk(ctrlbrk_func);
  249.     n = (int)ivec1 - (int)ivec0;
  250.     for (i = 0; i < 256; i++) {
  251.         idt[i].selector = g_rcode * 8;
  252.         idt[i].stype = 0x8e00;
  253.         idt[i].offset0 = FP_OFF((int)ivec0 + n * i);
  254.         idt[i].offset1 = 0;
  255.     }
  256.     idt[14].selector = g_ptss * 8;
  257.     idt[14].stype = 0x8500;
  258.     idt[14].offset0 = idt[14].offset1 = 0;
  259.  
  260.     cp = getenv("387");
  261.     if (cp)
  262.         if (tolower(cp[0]) == 'n')
  263.             have_80387 = 0;
  264.         else if (tolower(cp[0]) == 'y')
  265.             have_80387 = 1;
  266.         else
  267.             have_80387 = detect_80387();
  268.     else
  269.         have_80387 = detect_80387();
  270.     if (have_80387) {
  271.         idt[7].offset0 = (int)ivec7;
  272.         idt[0x75].offset0 = (int)ivec75;
  273.         idt[7].offset1 = idt[0x75].offset1 = 0;
  274.     }
  275.     if (cp && (tolower(cp[0]) == 'q'))
  276.         if (have_80387)
  277.             printf("An 80387 has been detected.\n");
  278.         else
  279.             printf("No 80387 has been detected.\n");
  280.  
  281.     fillgdt(g_zero, 0, 0, 0, 0);
  282.     fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  283.     fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  284.     fillgdt(g_rcode, 0xffff, (word32) _CS * 16L, 0x9a, 0);
  285.     fillgdt(g_rdata, 0xffff, (word32) _DS * 16L, 0x92, 0);
  286.     fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  287.     fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  288.     fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  289.     fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 1);
  290.     fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 1);
  291.     fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 1);
  292.     fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 1);
  293.     fillgdt(g_rc32, 0xffff, (word32) _CS * 16L, 0x9a, 3);
  294.     fillgdt(g_grdr, 0xffff, (word32) gr_paging_segment * 16L, 0x9a, 0);
  295.  
  296.     setup_tss(&c_tss, go_real_mode);
  297.     setup_tss(&a_tss, go_real_mode);
  298.     setup_tss(&o_tss, go_real_mode);
  299.     setup_tss(&f_tss, go_real_mode);
  300.     setup_tss(&i_tss, interrupt_common);
  301.     setup_tss(&p_tss, page_fault);
  302.     tss_ptr = &a_tss;
  303.  
  304.     argv0 = argv[0];
  305.     for (i = 0; argv0[i]; i++) {
  306.         if (argv0[i] == '\\')
  307.             argv0[i] = '/';
  308.         argv0[i] = tolower(argv0[i]);
  309.     }
  310.     if (!strcmp(argv[1], "-nobrk")) {
  311.         set_brk = 1;
  312.         argv++;
  313.         argc--;
  314.     }
  315. #if TOPLINEINFO
  316.     for (i = 0; i < 80; i++)
  317.         poke(screen_seg, i * 2, 0x0720);
  318. #endif
  319.  
  320.     self_contained = 0;
  321.     n = open(argv0, O_RDONLY | O_BINARY);
  322.     header[0] = 0;
  323.     read(n, header, sizeof(header));
  324.     if (header[0] == 0x5a4d) {
  325.         header_offset = (long)header[1] + ((long)header[2] - 1) * 512L;
  326.         lseek(n, header_offset, 0);
  327.         header[0] = 0;
  328.         read(n, header, sizeof(header));
  329.         if (header[0] == 0x010b)
  330.             self_contained = 1;
  331.     }
  332.     if (self_contained) {
  333. #if DEBUGGER
  334.         debug_mode = 1;
  335. #else
  336.         debug_mode = 0;
  337. #endif
  338.         paging_set_file(argv0);
  339.         emu_installed = emu_install(emu_fn);
  340.         set_command_line(argv, envp);
  341. #if DEBUGGER
  342.         syms_init(argv0);
  343. #endif
  344.     } else {
  345.         header_offset = 0;
  346.         for (cp = argv0; *cp; cp++)
  347.             if (*cp == '.')
  348.                 path = cp;
  349.         *path = 0;
  350.         if (stat(argv0, &stbuf)) {    /* not found */
  351.             fprintf(stderr, "%s.exe Copyright (C) 1991 DJ Delorie\n", argv0);
  352.             debug_mode = 1;
  353.             if (!argv[1])
  354.                 usage(argv0);
  355.             paging_set_file(argv[1]);
  356.             emu_installed = emu_install(emu_fn);
  357.             set_command_line(argv + 1, envp);
  358. #if DEBUGGER
  359.             syms_init(argv[1]);
  360. #endif
  361.         } else {                /* found */
  362.             debug_mode = 0;
  363.             paging_set_file(argv0);
  364.             emu_installed = emu_install(emu_fn);
  365.             set_command_line(argv, envp);
  366. #if DEBUGGER
  367.             syms_init(argv0);
  368. #endif
  369.         }
  370.     }
  371.  
  372.     if (set_brk)
  373.         paging_brk(0x8fffffffL);
  374.  
  375.     dalloc_init();
  376.     init_controllers();
  377.     if (emu_installed) {
  378.         push32(&(a_tss.tss_eip), 4);
  379.         a_tss.tss_eip = 0xb0000020L;
  380.     }
  381. #if DEBUGGER
  382.     debugger();
  383.     if (peekb(0x40, 0x49) != old_video_mode) {
  384.         _AX = old_video_mode;
  385.         geninterrupt(0x10);
  386.     }
  387.     return 0;
  388. #else
  389.     go_til_stop();
  390.     if (tss_ptr->tss_irqn == 0x79)
  391.         fprintf(stderr, "Ctrl-C Hit!  Stopped at address %lx\n", tss_ptr->tss_eip);
  392.     else
  393.         fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
  394.     return 1;
  395. #endif
  396. }
  397.  
  398. static word32 __pascal push32(void *ptr, int len)
  399. {
  400.     if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp - len) & ~0xFFF)) {
  401.         a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  402.         page_in();
  403.     }
  404.     a_tss.tss_esp -= len;
  405.     a_tss.tss_esp = a_tss.tss_esp & (~3);
  406.     memput(a_tss.tss_esp + ARENA, ptr, len);
  407.     return a_tss.tss_esp;
  408. }
  409.  
  410. static void __pascal foreach_arg(char **argv, void __fastcall(*func) (char *))
  411. {
  412.     int i;
  413.     FILE *f;
  414.     char buf[80];
  415.     for (i = 0; argv[i]; i++) {
  416.         if (argv[i][0] == '@') {
  417.             f = fopen(argv[i] + 1, "rt");
  418.             while (fscanf(f, "%s", buf) == 1) {
  419.                 if (strcmp(buf, "\032"))
  420.                     func(buf);
  421.             }
  422.             fclose(f);
  423.         } else
  424.             func(argv[i]);
  425.     }
  426. }
  427.  
  428. static int num_actual_args;
  429.  
  430. static void __fastcall just_incr(char *d)
  431. {
  432.     num_actual_args++;
  433. }
  434.  
  435. static word32 *a;
  436.  
  437. static void __fastcall pusharg(char *ar)
  438. {
  439.     a[num_actual_args] = push32(ar, strlen(ar) + 1);
  440.     num_actual_args++;
  441. }
  442.  
  443. static void __pascal set_command_line(char **argv, char **envv)
  444. {
  445.     unsigned envc;
  446.     word32 *e, v, argp, envp;
  447.  
  448.     a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  449.     page_in();
  450.  
  451.     num_actual_args = 0;
  452.     foreach_arg(argv, just_incr);
  453.  
  454.     for (envc = 0; envv[envc]; envc++);
  455.     e = (word32 *) malloc((envc + 1) * sizeof(word32));
  456.     if (!e) {
  457.         printf("Fatal! no memory to copy environment\n");
  458.         exit(1);
  459.     }
  460.     for (envc = 0; envv[envc]; envc++) {
  461.         v = push32(envv[envc], strlen(envv[envc]) + 1);
  462.         e[envc] = v;
  463.     }
  464.     e[envc] = 0;
  465.  
  466.     a = (word32 *) malloc((num_actual_args + 1) * sizeof(word32));
  467.     if (!a) {
  468.         printf("Fatal! no memory to copy arguments\n");
  469.         exit(1);
  470.     }
  471.     num_actual_args = 0;
  472.     foreach_arg(argv, pusharg);
  473.     a[num_actual_args] = 0;
  474.  
  475.     envp = push32(e, (envc + 1) * sizeof(word32));
  476.     argp = push32(a, (num_actual_args + 1) * sizeof(word32));
  477.  
  478.     push32(&envp, sizeof(word32));
  479.     push32(&argp, sizeof(word32));
  480.     v = num_actual_args;
  481.     push32(&v, sizeof(word32));
  482. }
  483.  
  484. /* This is file EXPHDLR.C */
  485. #define SEGFAULT(p) { \
  486.   printf("Segmentation violation in pointer %#08lx\n", (p)); \
  487.   return 1; \
  488.   }
  489.  
  490. extern word32 far *graphics_pt;
  491.  
  492. static word16 master_pic = 0x08;    /* Default IRQ0 Vector */
  493. static char transfer_buffer[4096];    /* must be near ptr for small model */
  494.  
  495. static word32 user_dta;
  496. static struct REGPACK r;
  497. static int in_graphics_mode = 0;
  498.  
  499. static int generic_handler(void);
  500. static int i_10(void);
  501. static int i_21(void);
  502. static int i_33(void);
  503. static int turbo_assist(void);
  504. static int i_21_44(void);
  505. static void __fastcall tss2reg(struct REGPACK *r);
  506. static void __fastcall reg2tss(struct REGPACK *r);
  507.  
  508. #define flmerge(rf,tf)    (((tf) & ~0xcffL) | ((rf) & 0xcff))
  509.  
  510. static void __pascal set_controller(int v)
  511. {
  512. /*  disable();  */
  513.     outportb(0x20, 0x11);
  514.     outportb(0x21, v);
  515.     outportb(0x21, 4);
  516.     outportb(0x21, 1);
  517. /*  enable();  */
  518. }
  519.  
  520. static void init_controllers(void)
  521. {
  522.     disable();
  523.     movedata(0, 0x08 * 4, 0, 0x78 * 4, 0x08 * 4);
  524.     if (vcpi_installed) {
  525.         master_pic = vcpi_get_pic();
  526.         vcpi_set_pic(0x78);
  527.     }
  528.     set_controller(0x78);
  529.     enable();
  530. }
  531.  
  532. static void uninit_controllers(void)
  533. {
  534.     disable();
  535.     if (vcpi_installed)
  536.         vcpi_set_pic(master_pic);
  537.     set_controller(master_pic);
  538.     enable();
  539. }
  540.  
  541. int exception_handler(void)
  542. {
  543.     int i;
  544. #if TOPLINEINFO
  545.     char buf[20];
  546.     sprintf(buf, "%#08lx", tss_ptr->tss_eip);
  547.     for (i = 0; buf[i]; i++)
  548.         poke(screen_seg, i * 2 + 80, buf[i] | 0x0600);
  549. #endif
  550.     i = tss_ptr->tss_irqn;
  551. /*  printf("i=%#02x, a0=%02x\n", i, inportb(0xa0)); */
  552.     if ((i >= 0x70) && (i < 0x7f) && (i != 0x75)) {
  553.         if (i < 0x78)
  554.             intr(i, &r);
  555.         else
  556.             intr(i - 0x70, &r);
  557.         if (i == 0x79) {
  558.             r.r_ax = 0x0100;
  559.             intr(0x16, &r);
  560.             if (!(r.r_flags & 0x40) && (r.r_ax == 0x2e03)) {
  561.                 _AH = 0;
  562.                 geninterrupt(0x16);
  563.                 ctrl_c_flag = 1;
  564.             }
  565.         }
  566.         if (ctrl_c_flag) {
  567.             ctrl_c_flag = 0;
  568.             return 1;
  569.         }
  570.         return 0;
  571.     }
  572.     switch (i) {
  573.     case 8:
  574.         printf("double fault!\n");
  575.         exit(1);
  576.     case 0:
  577.     case 1:
  578.     case 2:
  579.     case 3:
  580.     case 4:
  581.     case 5:
  582.     case 6:
  583.     case 9:
  584.     case 10:
  585.     case 11:
  586.     case 12:
  587.     case 13:
  588.     case 15:
  589.         return 1;
  590.     case 0x75:
  591.         return 1;
  592.     case 7:
  593.         printf("Fatal!  Application attempted to use not-present 80387!\n"
  594.                "Floating point opcode at virtual address %#08lx\n", tss_ptr->tss_eip);
  595.         return 1;
  596.     case 14:
  597.         return page_in();
  598.  
  599.     case 0x10:
  600.         return i_10();
  601.     case 0x11:
  602.     case 0x12:
  603.     case 0x14:
  604.     case 0x16:
  605.     case 0x17:
  606.     case 0x1a:
  607.         return generic_handler();
  608.     case 0x21:
  609.         return i_21();
  610.     case 0x33:
  611.         return i_33();
  612.     default:
  613.         return 1;
  614.     }
  615. }
  616.  
  617. #if DEBUGGER
  618. static char flset[] = "VMRF  NT    OFDNIETFMIZR  AC  PE  CY";
  619. static char floff[] = "              UPID  PLNZ      PO  NC";
  620. static char fluse[] =
  621. {1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1};
  622.  
  623. void __pascal tssprint(TSS * t)
  624. {
  625.     int i;
  626.     printf("eax=%08lx  ebx=%08lx  ecx=%08lx  edx=%08lx\n"
  627.            "esi=%08lx  edi=%08lx  ebp=%08lx ",
  628.            t->tss_eax, t->tss_ebx, t->tss_ecx, t->tss_edx, t->tss_esi, t->tss_edi, t->tss_ebp);
  629.     for (i = 0; i < 18; i++)
  630.         if (fluse[i])
  631.             if (t->tss_eflags & (1L << (17 - i)))
  632.                 printf(" %2.2s", flset + i * 2);
  633.             else
  634.                 printf(" %2.2s", floff + i * 2);
  635.     printf("\nds=%04x es=%04x fs=%04x gs=%04x ss:esp=%04x:%08lx cs=%04x\n",
  636.            t->tss_ds, t->tss_es, t->tss_fs, t->tss_gs, t->tss_ss, t->tss_esp, t->tss_cs);
  637. }
  638. #endif /* DEBUGGER */
  639.  
  640. static int __pascal retrieve_string(word32 v, char *transfer_buffer, char tchar)
  641. {
  642.     int i;
  643.     char c;
  644.     for (i = 0; i < 4096; i++) {
  645.         c = peek8(v);
  646.         v++;
  647.         transfer_buffer[i] = c;
  648.         if (c == tchar)
  649.             break;
  650.     }
  651.     return i + 1;                /* number of characters placed in buffer */
  652. }
  653.  
  654. static int generic_handler(void)
  655. {
  656.     tss2reg(&r);
  657.     intr(tss_ptr->tss_irqn, &r);
  658.     reg2tss(&r);
  659.     return 0;
  660. }
  661.  
  662. static int i_10(void)
  663. {
  664.     if ((tss_ptr->tss_eax & 0xFF00) == 0xFF00) {
  665.         graphics_mode((unsigned)tss_ptr->tss_eax & 0xff);
  666.         in_graphics_mode = (peekb(0x40, 0x49) > 7);
  667.         return 0;
  668.     }
  669.     tss2reg(&r);
  670.     intr(0x10, &r);
  671.     reg2tss(&r);
  672.     tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
  673.     return 0;
  674. }
  675.  
  676. static int i_33(void)
  677. {
  678.     if (!*((unsigned far *)0x000000CEL))
  679.         return 0;
  680.     r.r_ax = (word16) tss_ptr->tss_eax;
  681.     r.r_bx = (word16) tss_ptr->tss_ebx;
  682.     r.r_cx = (word16) tss_ptr->tss_ecx;
  683.     r.r_dx = (word16) tss_ptr->tss_edx;
  684.     intr(0x33, &r);
  685.     tss_ptr->tss_eax = r.r_ax;
  686.     tss_ptr->tss_ebx = r.r_bx;
  687.     tss_ptr->tss_ecx = r.r_cx;
  688.     tss_ptr->tss_edx = r.r_dx;
  689.     return 0;
  690. }
  691.  
  692. static TSS last_tss;
  693.  
  694. static int i_21(void)
  695. {
  696.     word32 v, trans_total, countleft;
  697.     int i, c, ah, tchar, trans_count;
  698.     char *cp;
  699.     memcpy(&last_tss, tss_ptr, sizeof(TSS));
  700.     tss2reg(&r);
  701.     ah = (int)(tss_ptr->tss_eax >> 8) & 0xff;
  702.     switch (ah) {
  703.     case 1:
  704.     case 2:
  705.     case 3:
  706.     case 4:
  707.     case 5:
  708.     case 6:
  709.     case 7:
  710.     case 8:
  711.     case 0x0b:
  712.     case 0x0e:
  713.     case 0x19:
  714.     case 0x2a:
  715.     case 0x2b:
  716.     case 0x2c:
  717.     case 0x2d:
  718.     case 0x33:
  719.     case 0x42:
  720.     case 0x45:
  721.     case 0x46:
  722.     case 0x57:
  723.     case 0x68:
  724.     case 0x6a:
  725.         intr(0x21, &r);
  726.         reg2tss(&r);
  727.         return 0;
  728.     case 0x3e:
  729. #if DEBUGGER
  730.         if (r.r_bx <= 2)
  731.             return 0;
  732. #endif
  733.         if (r.r_bx == 1)
  734.             redir_1_mono = redir_1_2 = 0;
  735.         if (r.r_bx == 2)
  736.             redir_2_mono = redir_2_1 = 0;
  737.         intr(0x21, &r);
  738.         reg2tss(&r);
  739.         return 0;
  740.     case 9:
  741.     case 0x39:
  742.     case 0x3a:
  743.     case 0x3b:
  744.     case 0x41:
  745.     case 0x43:
  746.         tchar = (ah == 9) ? '$' : 0;
  747.         v = tss_ptr->tss_edx + ARENA;
  748.         if (!page_is_valid(v)) {
  749.             printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
  750.             return 1;
  751.         }
  752.         retrieve_string(v, transfer_buffer, tchar);
  753.         r.r_dx = FP_OFF(transfer_buffer);
  754.         r.r_ds = _DS;
  755.         intr(0x21, &r);
  756.         reg2tss(&r);
  757.         return 0;
  758.     case 0x3c:
  759.         v = tss_ptr->tss_edx + ARENA;
  760.         if (!page_is_valid(v)) {
  761.             printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
  762.             return 1;
  763.         }
  764.         retrieve_string(v, transfer_buffer, 0);
  765.         i = _rtl_creat(transfer_buffer, (int)(tss_ptr->tss_ecx));
  766.         if (i == -1) {
  767.             tss_ptr->tss_eax = errno;
  768.             tss_ptr->tss_eflags |= 1;
  769.         } else {
  770.             tss_ptr->tss_eax = i;
  771.             tss_ptr->tss_eflags &= ~1;
  772.         }
  773.         return 0;
  774.     case 0x3d:
  775.         v = tss_ptr->tss_edx + ARENA;
  776.         if (!page_is_valid(v)) {
  777.             printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
  778.             return 1;
  779.         }
  780.         retrieve_string(v, transfer_buffer, 0);
  781.         i = (int)tss_ptr->tss_eax & 0xf0;
  782.         if (tss_ptr->tss_eax & O_WRONLY)
  783.             i &= 1;
  784.         if (tss_ptr->tss_eax & O_RDWR)
  785.             i &= 2;
  786.         i = _rtl_open(transfer_buffer, i);
  787.         if (i == -1) {
  788.             tss_ptr->tss_eax = errno;
  789.             tss_ptr->tss_eflags |= 1;
  790.         } else {
  791.             tss_ptr->tss_eax = i;
  792.             tss_ptr->tss_eflags &= ~1;
  793.         }
  794.         return 0;
  795.     case 0x1a:
  796.         user_dta = tss_ptr->tss_edx;
  797.         setdta((char far *)transfer_buffer);
  798.         return 0;
  799.     case 0x2f:
  800.         tss_ptr->tss_ebx = user_dta;
  801.         return 0;
  802.     case 0x30:
  803.         intr(0x21, &r);
  804.         reg2tss(&r);
  805.         return 0;
  806.     case 0x56:
  807.         v = tss_ptr->tss_edx + ARENA;
  808.         if (!page_is_valid(v)) {
  809.             printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
  810.             return 1;
  811.         }
  812.         i = retrieve_string(v, transfer_buffer, 0);
  813.         r.r_dx = FP_OFF(transfer_buffer);
  814.         r.r_ds = _DS;
  815.         v = tss_ptr->tss_edi + ARENA;
  816.         retrieve_string(v, transfer_buffer + i, 0);
  817.         r.r_di = FP_OFF(transfer_buffer) + i;
  818.         r.r_es = _DS;
  819.         intr(0x21, &r);
  820.         tss_ptr->tss_eax = r.r_ax;
  821.         tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  822.         return 0;
  823.     case 0x3f:
  824.         trans_total = 0;
  825.         countleft = tss_ptr->tss_ecx;
  826.         v = tss_ptr->tss_edx;
  827.         if (!page_is_valid(v + ARENA)) {
  828.             printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
  829.             return 1;
  830.         }
  831.         while (countleft > 0) {
  832.             trans_count = (countleft <= 4096) ? (int)countleft : 4096;
  833.             i = read(r.r_bx, transfer_buffer, trans_count);
  834.             if (i < 0) {
  835.                 tss_ptr->tss_eflags |= 1;    /* carry */
  836.                 tss_ptr->tss_eax = _doserrno;
  837.                 return 0;
  838.             }
  839.             memput(v + ARENA, transfer_buffer, i);
  840.             trans_total += i;
  841.             v += i;
  842.             countleft -= i;
  843.             if (isatty(r.r_bx) && (i < trans_count))
  844.                 break;            /* they're line buffered */
  845.             if (!i)
  846.                 break;
  847.         }
  848.         tss_ptr->tss_eax = trans_total;
  849.         tss_ptr->tss_eflags &= ~1;
  850.         return 0;
  851.     case 0x40:
  852.         trans_total = 0;
  853.         countleft = tss_ptr->tss_ecx;
  854.         if (!countleft) {
  855.             r.r_ax = 0x4000;
  856.             r.r_cx = 0;
  857.             intr(0x21, &r);
  858.             tss_ptr->tss_eax = 0;
  859.             tss_ptr->tss_eflags &= ~1;
  860.             return 0;
  861.         }
  862.         v = tss_ptr->tss_edx;
  863.         if (!page_is_valid(v + ARENA))
  864.             SEGFAULT(v);
  865.         r.r_dx = (int)transfer_buffer;
  866.         while (countleft > 0) {
  867.             trans_count = (countleft <= 4096) ? (int)countleft : 4096;
  868.             memget(v + ARENA, transfer_buffer, trans_count);
  869.             if ((r.r_bx == 1) && redir_1_mono)
  870.                 i = mono_write(transfer_buffer, trans_count);
  871.             else if ((r.r_bx == 2) && redir_2_mono)
  872.                 i = mono_write(transfer_buffer, trans_count);
  873.             else {
  874.                 int fd = r.r_bx;
  875.                 if ((r.r_bx == 2) && redir_2_1)
  876.                     fd = 1;
  877.                 else if ((r.r_bx == 1) && redir_1_2)
  878.                     fd = 2;
  879.                 i = write(fd, transfer_buffer, trans_count);
  880.                 if (in_graphics_mode && (fd < 3)) {
  881.                     word32 far *p = graphics_pt;
  882.                     for (c = 0; c < 256; c++)
  883.                         *p++ &= ~PT_P;
  884.                 }
  885.             }
  886.             if (i < 0) {        /* carry */
  887.                 tss_ptr->tss_eflags |= 1;    /* carry */
  888.                 tss_ptr->tss_eax = _doserrno;
  889.                 return 0;
  890.             }
  891.             trans_total += i;
  892.             v += i;
  893.             countleft -= i;
  894.             if (i < trans_count)
  895.                 break;
  896.         }
  897.         tss_ptr->tss_eax = trans_total;
  898.         tss_ptr->tss_eflags &= ~1;
  899.         return 0;
  900.     case 0x44:
  901.         return i_21_44();
  902.     case 0x4e:
  903.         if (!page_is_valid(user_dta + ARENA))
  904.             SEGFAULT(user_dta);
  905.         v = tss_ptr->tss_edx + ARENA;
  906.         if (!page_is_valid(v))
  907.             SEGFAULT(v);
  908.         retrieve_string(v, transfer_buffer + 43, 0);
  909.         r.r_dx = FP_OFF(transfer_buffer + 43);
  910.         r.r_ds = _DS;
  911.         intr(0x21, &r);
  912.         reg2tss(&r);
  913.         for (i = 20; i >= 0; i--)
  914.             transfer_buffer[i + 28] = transfer_buffer[i + 26];
  915.         transfer_buffer[32 + 13] = 0;    /* asciiz termination */
  916.         memput(user_dta + ARENA, transfer_buffer, 48);
  917.         return 0;
  918.     case 0x4f:
  919.         if (!page_is_valid(user_dta + ARENA))
  920.             SEGFAULT(user_dta);
  921.         memget(user_dta + ARENA, transfer_buffer, 48);
  922.         for (i = 0; i <= 20; i++)
  923.             transfer_buffer[i + 26] = transfer_buffer[i + 28];
  924.         intr(0x21, &r);
  925.         reg2tss(&r);
  926.         for (i = 20; i >= 0; i--)
  927.             transfer_buffer[i + 28] = transfer_buffer[i + 26];
  928.         transfer_buffer[32 + 13] = 0;    /* asciiz termination */
  929.         memput(user_dta + ARENA, transfer_buffer, 48);
  930.         return 0;
  931.     case 0x47:
  932.         getcurdir((int)(tss_ptr->tss_edx & 0xff), transfer_buffer);
  933.         for (cp = transfer_buffer; *cp; cp++) {
  934.             if (*cp == '\\')
  935.                 *cp = '/';
  936.             *cp = tolower(*cp);
  937.         }
  938.         memput(tss_ptr->tss_esi + ARENA, transfer_buffer, strlen(transfer_buffer));
  939.         tss_ptr->tss_eax = (unsigned)r.r_ax;
  940.         tss_ptr->tss_eflags &= ~1;
  941.         return 0;
  942.     case 0x4a:
  943.         tss_ptr->tss_eax = (tss_ptr->tss_eax & 0xff) ? paging_sbrk(tss_ptr->tss_ebx) : paging_brk(tss_ptr->tss_ebx);
  944.         return 0;
  945.     case 0x4c:
  946. #if DEBUGGER
  947.         printf("Program exited normally, return code %d (%#x)\n",
  948.                (int)(tss_ptr->tss_eax & 0xff), (int)(tss_ptr->tss_eax & 0xff));
  949.         return 1;
  950. #else
  951.         exit((int)tss_ptr->tss_eax & 0xff);
  952. #endif
  953.     case 0xff:
  954.         return turbo_assist();
  955.     default:
  956.         return 1;
  957.     }
  958. }
  959.  
  960. struct time32 {
  961.     word32 secs;
  962.     word32 usecs;
  963. };
  964.  
  965. struct tz32 {
  966.     word32 offset;
  967.     word32 dst;
  968. };
  969.  
  970. struct stat32 {
  971.     short st_dev;
  972.     short st_ino;
  973.     short st_mode;
  974.     short st_nlink;
  975.     short st_uid;
  976.     short st_gid;
  977.     short st_rdev;
  978.     short st_align_for_word32;
  979.     long st_size;
  980.     long st_atime;
  981.     long st_mtime;
  982.     long st_ctime;
  983.     long st_blksize;
  984. };
  985.  
  986. static int dev_count = 1;
  987.  
  988. static int turbo_assist(void)
  989. {
  990.     word32 p1, p2, r;
  991.     struct time32 time32;
  992.     struct tz32 tz32;
  993.     struct stat32 statbuf32;
  994.     struct stat statbuf;
  995.     int i;
  996.  
  997.     char buf[128];
  998.     p1 = tss_ptr->tss_ebx;
  999.     p2 = tss_ptr->tss_ecx;
  1000.     switch (tss_ptr->tss_eax & 0xff) {
  1001.     case 1:
  1002.         retrieve_string(p1 + ARENA, buf, 0);
  1003.         r = creat(buf, S_IREAD | S_IWRITE);
  1004.         break;
  1005.     case 2:
  1006.         retrieve_string(p1 + ARENA, buf, 0);
  1007.         r = open(buf, (int)p2, S_IREAD | S_IWRITE);
  1008.         break;
  1009.     case 3:
  1010.         memset(&statbuf, 0, sizeof(statbuf));
  1011.         r = fstat((int)p1, &statbuf);
  1012.         statbuf32.st_dev = dev_count++;
  1013.         statbuf32.st_ino = statbuf.st_ino;
  1014.         statbuf32.st_mode = statbuf.st_mode;
  1015.         statbuf32.st_nlink = statbuf.st_nlink;
  1016.         statbuf32.st_uid = statbuf.st_uid;
  1017.         statbuf32.st_gid = statbuf.st_gid;
  1018.         statbuf32.st_rdev = statbuf.st_rdev;
  1019.         statbuf32.st_size = statbuf.st_size;
  1020.         statbuf32.st_atime = statbuf.st_atime;
  1021.         statbuf32.st_mtime = statbuf.st_mtime;
  1022.         statbuf32.st_ctime = statbuf.st_ctime;
  1023.         statbuf32.st_blksize = 512;
  1024.         memput(p2 + ARENA, &statbuf32, sizeof(statbuf32));
  1025.         break;
  1026.     case 4:
  1027.         if (p2) {
  1028.             if (!page_is_valid(p2 + ARENA))
  1029.                 SEGFAULT(p2);
  1030.             tz32.offset = timezone;
  1031.             tz32.dst = daylight;
  1032.             memput(p2 + ARENA, &tz32, sizeof(tz32));
  1033.         }
  1034.         if (p1) {
  1035.             if (!page_is_valid(p1 + ARENA))
  1036.                 SEGFAULT(p1);
  1037.             time((time_t *) & time32.secs);
  1038.             _AH = 0x2c;
  1039.             geninterrupt(0x21);
  1040.             time32.usecs = _DL * 10000L;
  1041.             memput(p1 + ARENA, &time32, sizeof(time32));
  1042.         }
  1043.         r = 0;
  1044.         break;
  1045.     case 5:
  1046.         if (p2) {
  1047.             if (!page_is_valid(p2 + ARENA))
  1048.                 SEGFAULT(p2);
  1049.             memget(p2 + ARENA, &tz32, sizeof(tz32));
  1050.             timezone = tz32.offset;
  1051.             daylight = (int)tz32.dst;
  1052.         }
  1053.         if (p1) {
  1054.             if (!page_is_valid(p1 + ARENA))
  1055.                 SEGFAULT(p1);
  1056.             memget(p1 + ARENA, &time32, sizeof(time32));
  1057.             stime((time_t *) & time32.secs);
  1058.         }
  1059.         r = 0;
  1060.         break;
  1061.     case 6:
  1062.         memset(&statbuf, 0, sizeof(statbuf));
  1063.         retrieve_string(p1 + ARENA, transfer_buffer, 0);
  1064.         r = stat(transfer_buffer, &statbuf);
  1065.         statbuf32.st_dev = dev_count++;
  1066.         statbuf32.st_ino = statbuf.st_ino;
  1067.         statbuf32.st_mode = statbuf.st_mode;
  1068.         statbuf32.st_nlink = statbuf.st_nlink;
  1069.         statbuf32.st_uid = statbuf.st_uid;
  1070.         statbuf32.st_gid = statbuf.st_gid;
  1071.         statbuf32.st_rdev = statbuf.st_rdev;
  1072.         statbuf32.st_size = statbuf.st_size;
  1073.         statbuf32.st_atime = statbuf.st_atime;
  1074.         statbuf32.st_mtime = statbuf.st_mtime;
  1075.         statbuf32.st_ctime = statbuf.st_ctime;
  1076.         statbuf32.st_blksize = 512;
  1077.         memput(p2 + ARENA, &statbuf32, sizeof(statbuf32));
  1078.         break;
  1079.     case 7:
  1080.         retrieve_string(p1 + ARENA, transfer_buffer, 0);
  1081.         page_out_everything();
  1082.         uninit_controllers();
  1083.         sscanf(transfer_buffer, "%s%n", buf, &i);
  1084.         r = (strpbrk(transfer_buffer, "<>|") == NULL) ? spawnlp(P_WAIT, buf, buf, transfer_buffer + i, 0) : ULONG_MAX;
  1085.         if (r & 0x80000000L)
  1086.             r = system(transfer_buffer);
  1087.         init_controllers();
  1088.         page_in_everything();
  1089.         break;
  1090.     case 8:
  1091.         r = setmode((int)p1, (int)p2);
  1092.         break;
  1093.     default:
  1094.         return 1;
  1095.     }
  1096.     tss_ptr->tss_eflags &= ~1;
  1097.     if (r == ULONG_MAX) {
  1098.         tss_ptr->tss_eflags |= 1;
  1099.         tss_ptr->tss_eax = errno;
  1100.         return 0;
  1101.     }
  1102.     tss_ptr->tss_eax = r;
  1103.     return 0;
  1104. }
  1105.  
  1106. static int i_21_44(void)
  1107. {
  1108.     switch (tss_ptr->tss_eax & 0xff) {
  1109.     case 0x00:
  1110.     case 0x01:
  1111.     case 0x06:
  1112.     case 0x07:
  1113.         intr(0x21, &r);
  1114.         tss_ptr->tss_edx = r.r_dx;
  1115.         tss_ptr->tss_eax = r.r_ax;
  1116.         tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  1117.         return 0;
  1118.     default:
  1119.         return 1;
  1120.     }
  1121. }
  1122.  
  1123. static void __fastcall tss2reg(struct REGPACK *r)
  1124. {
  1125.     r->r_ax = (word16) tss_ptr->tss_eax;
  1126.     r->r_bx = (word16) tss_ptr->tss_ebx;
  1127.     r->r_cx = (word16) tss_ptr->tss_ecx;
  1128.     r->r_dx = (word16) tss_ptr->tss_edx;
  1129.     r->r_si = (word16) tss_ptr->tss_esi;
  1130.     r->r_di = (word16) tss_ptr->tss_edi;
  1131.     r->r_flags = (word16) tss_ptr->tss_eflags;
  1132.     r->r_ds = r->r_es = _DS;
  1133. }
  1134.  
  1135. static void __fastcall reg2tss(struct REGPACK *r)
  1136. {
  1137.     tss_ptr->tss_eax = r->r_ax;
  1138.     tss_ptr->tss_ebx = r->r_bx;
  1139.     tss_ptr->tss_ecx = r->r_cx;
  1140.     tss_ptr->tss_edx = r->r_dx;
  1141.     tss_ptr->tss_esi = r->r_si;
  1142.     tss_ptr->tss_edi = r->r_di;
  1143.     tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
  1144. }
  1145.