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

  1. /* This is file PAGING.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 paging.c, valloc.c and dalloc.c
  18.  */
  19. /* History:112,12 */
  20.  
  21. #include "build.h"
  22.  
  23. static unsigned dalloc(void);
  24. static void __pascal dfree(unsigned);
  25. static void __pascal dwrite(word8 * buf, unsigned block);
  26. static void __pascal dread(word8 * buf, unsigned block);
  27. static unsigned __pascal valloc(int where);
  28. static void __pascal vfree(unsigned);
  29. static int page_out(void);
  30.  
  31. #if DEBUGGER
  32. #define MAX_PAGING_NUM 1
  33. #else
  34. #define MAX_PAGING_NUM 4
  35. #endif
  36.  
  37. extern word32 __pascal ptr2linear(void far * ptr);
  38.  
  39. static CLIENT client;            /*  VCPI Change Mode Structure  */
  40. word32 abs_client;                /*  _DS * 16L + &client         */
  41. far32 vcpi_entry;
  42. static SYS_TBL int_descriptor;
  43. static SYS_TBL gbl_descriptor;
  44.  
  45. extern word16 vcpi_installed;    /*  VCPI Installed Flag  */
  46. extern near protect_entry();
  47.  
  48. extern TSS *utils_tss;
  49. extern int debug_mode;
  50. static word16 mem_avail;
  51. extern long header_offset;
  52.  
  53. typedef struct AREAS {
  54.     word32 first_addr;
  55.     word32 last_addr;
  56.     word32 foffset;                /* corresponding to first_addr; -1 = zero fill only */
  57. } AREAS;
  58.  
  59. #define MAX_AREA    8
  60. static AREAS areas[MAX_AREA];
  61. #if TOPLINEINFO
  62. static char achar[MAX_AREA] = "tdbmsg?e";
  63. #endif
  64. typedef enum {
  65.     A_text,
  66.     A_data,
  67.     A_bss,
  68.     A_arena,
  69.     A_stack,
  70.     A_vga,
  71.     A_syms,
  72.     A_emu
  73. } AREA_TYPES;
  74.  
  75. static aout_f;
  76. static emu_f;
  77.  
  78. static word32 far *pd = 0;
  79. word32 far *graphics_pt;
  80. extern word32 graphics_pt_lin;
  81. static word8 paging_buffer[4096 * MAX_PAGING_NUM];
  82.  
  83. /*  VCPI Get Interface  */
  84. static void __pascal link_vcpi(word32 far * dir, word32 far * table)
  85. {
  86.  
  87.     vcpi_entry.selector = g_vcpicode * 8;
  88.     vcpi_entry.offset32 = get_interface(table, &gdt[g_vcpicode]);
  89.     if (vcpi_entry.offset32 == ULONG_MAX) {
  90.         printf("CAUTION !!!!  This EMS driver used address 1B0000H.\n"
  91.                "This memory area is broken by handle_screen_swap().\n");
  92.         exit(1);
  93.     }
  94.     int_descriptor.limit_16 = sizeof(idt);
  95.     int_descriptor.base_32 = ptr2linear(idt);
  96.     gbl_descriptor.limit_16 = sizeof(gdt);
  97.     gbl_descriptor.base_32 = ptr2linear(gdt);
  98.  
  99.     client.page_table = (word32) dir >> 12;
  100.     client.gdt_address = ptr2linear(&gbl_descriptor);
  101.     client.idt_address = ptr2linear(&int_descriptor);
  102.     client.ldt_selector = 0;
  103.     client.tss_selector = g_ctss * 8;
  104.     client.entry_eip = (word16) protect_entry;
  105.     client.entry_cs = g_rcode * 8;
  106.  
  107.     abs_client = ptr2linear(&client);
  108. }
  109.  
  110. static void __pascal handle_screen_swap(word32 far * pt)
  111. {
  112.     struct REGPACK r;
  113.     int have_mono, have_color, have_graphics, save, new, i;
  114.     have_mono = have_color = have_graphics = 0;
  115.  
  116.     r.r_ax = 0x1200;
  117.     r.r_bx = 0xff10;
  118.     r.r_cx = 0xffff;
  119.     intr(0x10, &r);
  120.     if (r.r_cx == 0xffff)
  121.         pokeb(0x40, 0x84, 24);    /* the only size for CGA/MDA */
  122.  
  123.     save = peekb(screen_seg, 0);
  124.     pokeb(screen_seg, 0, ~save);
  125.     new = peekb(screen_seg, 0);
  126.     pokeb(screen_seg, 0, save);
  127.     if (new == ~save)
  128.         have_color = 1;
  129.  
  130.     save = peekb(0xb000, 0);
  131.     pokeb(0xb000, 0, ~save);
  132.     new = peekb(0xb000, 0);
  133.     pokeb(0xb000, 0, save);
  134.     if (new == ~save)
  135.         have_mono = 1;
  136.  
  137.     r.r_ax = 0x0f00;
  138.     intr(0x10, &r);
  139.     if ((r.r_ax & 0xff) > 0x07)
  140.         have_graphics = 1;
  141.  
  142.     if (have_graphics && have_mono)
  143.         have_color = 1;
  144.     else if (have_graphics && have_color)
  145.         have_mono = 1;
  146.  
  147.     for (i = 0; i < 16; i++)
  148.         pt[0x1b0 + i] = pt[0xb0 + i];
  149.  
  150.     if (have_color && !have_mono) {
  151.         for (i = 0; i < 8; i++)
  152.             pt[0x1b0 + i] = pt[0xb8 + i];
  153.         return;
  154.     }
  155.     if (have_mono && !have_color) {
  156.         for (i = 0; i < 8; i++)
  157.             pt[0x1b8 + i] = pt[0xb0 + i];
  158.         return;
  159.     }
  160.     if ((biosequip() & 0x0030) == 0x0030) {        /* mono mode, swap! */
  161.         for (i = 0; i < 8; i++) {
  162.             pt[0x1b0 + i] ^= pt[0x1b8 + i];
  163.             pt[0x1b8 + i] ^= pt[0x1b0 + i];
  164.             pt[0x1b0 + i] ^= pt[0x1b8 + i];
  165.         }
  166.         return;
  167.     }
  168. }
  169.  
  170. void __pascal paging_set_file(char *fname)
  171. {
  172.     word32 far *pt;
  173.     FILEHDR filehdr;
  174.     AOUTHDR aouthdr;
  175.     SCNHDR scnhdr[3];
  176.     GNU_AOUT gnu_aout;
  177.     int i;
  178.     aout_f = open(fname, O_RDONLY | O_BINARY);
  179.     if (aout_f == -1) {
  180.         printf("Can't open file <%s>\n", fname);
  181.         exit(1);
  182.     }
  183. #if TOPLINEINFO
  184.     for (i = 0; fname[i]; i++)
  185.         poke(screen_seg, i * 2 + 10, fname[i] | 0x0700);
  186. #endif
  187.  
  188.     lseek(aout_f, header_offset, 0);
  189.  
  190.     read(aout_f, &filehdr, sizeof(filehdr));
  191.     if (filehdr.f_magic != 0x14c) {
  192.         lseek(aout_f, header_offset, 0);
  193.         read(aout_f, &gnu_aout, sizeof(gnu_aout));
  194.         a_tss.tss_eip = gnu_aout.entry;
  195.         aouthdr.tsize = gnu_aout.tsize;
  196.         aouthdr.dsize = gnu_aout.dsize;
  197.         aouthdr.bsize = gnu_aout.bsize;
  198.     } else {
  199.         read(aout_f, &aouthdr, sizeof(aouthdr));
  200.         a_tss.tss_eip = aouthdr.entry;
  201.         read(aout_f, scnhdr, sizeof(scnhdr));
  202.     }
  203.     a_tss.tss_cs = g_acode * 8;
  204.     a_tss.tss_ds = a_tss.tss_es = a_tss.tss_fs = a_tss.tss_gs = a_tss.tss_ss = g_adata * 8;
  205.     a_tss.tss_esp = 0x7ffffffcL;
  206.  
  207.     if (filehdr.f_magic == 0x14c) {
  208.         areas[0].first_addr = aouthdr.text_start + ARENA;
  209.         areas[0].foffset = scnhdr[0].s_scnptr + header_offset;
  210.         areas[0].last_addr = areas[0].first_addr + aouthdr.tsize;
  211.     } else if (filehdr.f_magic == 0x10b) {
  212.         areas[0].first_addr = ARENA;
  213.         if (a_tss.tss_eip >= 0x1000)    /* leave space for null reference */
  214.             areas[0].first_addr += 0x1000;    /* to cause seg fault */
  215.         areas[0].foffset = header_offset;
  216.         areas[0].last_addr = areas[0].first_addr + aouthdr.tsize + 0x20;
  217.     }
  218. #if DEBUGGER
  219.     else if (filehdr.f_magic == 0x107) {
  220.         struct stat sbuf;
  221.         fstat(aout_f, &sbuf);
  222.         areas[0].first_addr = ARENA;
  223.         areas[0].foffset = 0x20 + header_offset;
  224.         areas[0].last_addr = sbuf.st_size + ARENA - 0x20;
  225.     } else {
  226.         struct stat sbuf;
  227.         fstat(aout_f, &sbuf);
  228.         areas[0].first_addr = ARENA;
  229.         areas[0].foffset = header_offset;
  230.         areas[0].last_addr = sbuf.st_size + ARENA;
  231.     }
  232. #else
  233.     else {
  234.         printf("Unknown file type %#x (%#o)\n", filehdr.f_magic, filehdr.f_magic);
  235.         exit(-1);
  236.     }
  237. #endif
  238. #if DEBUGGER
  239.     if (debug_mode)
  240.         printf("%ld+%ld+%ld = %ld\n",
  241.                aouthdr.tsize, aouthdr.dsize, aouthdr.bsize,
  242.                aouthdr.tsize + aouthdr.dsize + aouthdr.bsize);
  243. #endif
  244.  
  245.     if (filehdr.f_magic == 0x14c) {
  246.         areas[1].first_addr = aouthdr.data_start + ARENA;
  247.         areas[1].foffset = scnhdr[1].s_scnptr + header_offset;
  248.     } else {
  249.         areas[1].first_addr = (areas[0].last_addr + 0x3fffffL) & ~0x3fffffL;
  250.         areas[1].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
  251.     }
  252.     areas[1].last_addr = areas[1].first_addr + aouthdr.dsize - 1;
  253.     areas[2].first_addr = areas[1].last_addr + 1;
  254.     areas[2].last_addr = areas[2].first_addr + aouthdr.bsize - 1;
  255.     areas[3].first_addr = areas[2].last_addr;
  256.     areas[3].last_addr = areas[3].first_addr;
  257.     areas[4].first_addr = 0x50000000L;
  258.     areas[4].last_addr = 0x8fffffffL;
  259.     areas[5].first_addr = 0xe0000000L;
  260.     areas[5].last_addr = 0xe03fffffL;
  261.     areas[A_syms].first_addr = 0xa0000000L;
  262.     areas[A_syms].last_addr = 0xafffffffL;
  263.  
  264.     areas[2].foffset = areas[3].foffset = areas[4].foffset = areas[5].foffset = areas[A_syms].foffset = ULONG_MAX;
  265.  
  266.     pd = MK_FP(valloc(VA_640) << 8, 0);
  267.     pt = MK_FP(valloc(VA_640) << 8, 0);
  268.     for (i = 0; i < 1024; i++)
  269.         pd[i] = 0;
  270.  
  271.     if (vcpi_installed) {
  272.         link_vcpi(pd, pt);        /*  Get VCPI Page Table  */
  273.         for (i = 0; i < 1024; i++)
  274.             if (pt[i] & PT_P)
  275.                 pt[i] |= PT_I;
  276.     } else {
  277.         for (i = 0; i < 256; i++)
  278.             pt[i] = ((unsigned long)i << 12) | PT_P | PT_W | PT_I;
  279.         for (; i < 1024; i++)
  280.             pt[i] = 0;
  281.     }
  282.  
  283.     pd[0] = pd[0x3c0] = ((word32) pt >> 12) | PT_P | PT_W | PT_I;
  284.     /* map 0-1M 1:1 */
  285.     /* map also to 0xF0000000 */
  286.     handle_screen_swap(pt);
  287.  
  288.     graphics_pt = MK_FP(valloc(VA_640) << 8, 0);
  289.     graphics_pt_lin = ptr2linear(graphics_pt);
  290.     for (i = 0; i < 1024; i++)
  291.         graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
  292.     pd[0x380] = ((word32) graphics_pt >> 12) | PT_P | PT_W | PT_U;
  293.  
  294.     c_tss.tss_cr3 = a_tss.tss_cr3 = o_tss.tss_cr3 = i_tss.tss_cr3 = p_tss.tss_cr3 = f_tss.tss_cr3 = (word32) pd >> 12;
  295. }
  296.  
  297. #if TOPLINEINFO
  298. static __pascal update_status(int c, int col)
  299. {
  300.     int r = peek(screen_seg, 2 * 79);
  301.     poke(screen_seg, 2 * col, c);
  302.     return r;
  303. }
  304. #endif
  305.  
  306. word32 __pascal paging_brk(word32 b)
  307. {
  308.     word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
  309.     areas[3].last_addr = b + ARENA;
  310.     return r;
  311. }
  312.  
  313. word32 paging_sbrk(int32 b)
  314. {
  315.     word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
  316.     areas[3].last_addr = r + b + ARENA;
  317.     return r;
  318. }
  319.  
  320. int __pascal page_is_valid(word32 vaddr)
  321. {
  322.     int a;
  323.     for (a = 0; a < MAX_AREA; a++)
  324.         if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  325.             return 1;
  326.     if (vaddr >= 0xf000000L)
  327.         return 1;
  328.     return 0;
  329. }
  330.  
  331. int page_in(void)
  332. {
  333.     TSS *old_util_tss;
  334.     word32 far *pt;
  335.     word32 vaddr, cnt32;
  336.     word32 eaddr, vtran, vcnt, zaddr;
  337.     int pdi, pti, pn, a, count;
  338.     unsigned dblock;
  339. #if TOPLINEINFO
  340.     int old_status;
  341. #endif
  342.  
  343.     old_util_tss = utils_tss;
  344.     utils_tss = &f_tss;
  345.     vaddr = tss_ptr->tss_cr2;
  346.  
  347.     for (a = 0; a < MAX_AREA; a++)
  348.         if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  349.             goto got_area;
  350.  
  351.     printf("Segmentation Violation referencing address %#lx\n", tss_ptr->tss_cr2 - ARENA);
  352.     return 1;
  353.  
  354.   got_area:
  355.     vaddr &= 0xFFFFF000L;        /* points to beginning of page */
  356.  
  357.     if ((a == 2) & (vaddr < areas[a].first_addr)) {        /* bss, but data too */
  358.         a = 1;                    /* set to page in data */
  359.     }
  360. #if TOPLINEINFO
  361.     old_status = update_status(achar[a] | 0x0a00, 78);
  362. #endif
  363.     pdi = (word16) (vaddr >> 22);
  364.     if (!(pd[pdi] & PT_P)) {    /* put in an empty page table if required */
  365.         pn = valloc(VA_640);
  366.         pt = MK_FP(pn << 8, 0);
  367.         pd[pdi] = ((word32) pn << 12) | PT_P | PT_W | PT_I | PT_S;
  368.         for (pti = 0; pti < 1024; pti++)
  369.             pt[pti] = PT_W | PT_S;
  370.     } else
  371.         pt = (word32 far *) ((pd[pdi] & ~0xFFF) << 12);
  372.     pti = (word16) (vaddr >> 12) & 0x3ff;
  373.     if (pt[pti] & PT_P) {
  374.         utils_tss = old_util_tss;
  375. #if TOPLINEINFO
  376.         update_status(old_status, 78);
  377. #endif
  378.         return 0;
  379.     }
  380.     count = MAX_PAGING_NUM;
  381.     if (count > mem_avail / 4)
  382.         count = mem_avail / 4;
  383.     if (pti + count > 1024)
  384.         count = 1024 - pti;
  385.     if (vaddr + count * 4096L > areas[a].last_addr + 4096L)
  386.         count = (int)((areas[a].last_addr - vaddr + 4095) / 4096);
  387.     if (count < 1)
  388.         count = 1;
  389.     zaddr = eaddr = ULONG_MAX;
  390.     vtran = vaddr;
  391.     vcnt = 0;
  392.     for (; count; count--, pti++, vaddr += 4096) {
  393.         if (pt[pti] & PT_P)
  394.             break;
  395.         dblock = (unsigned)(pt[pti] >> 12);
  396.         pn = valloc(VA_1M);
  397.         pt[pti] &= 0xfffL & ~(word32) (PT_A | PT_D | PT_C);
  398.         pt[pti] |= ((word32) pn << 12) | PT_P;
  399.  
  400.         if (pt[pti] & PT_I) {
  401.             dread(paging_buffer, dblock);
  402.             dfree(dblock);
  403.             memput(vaddr, paging_buffer, 4096);
  404.         } else {
  405.             if (areas[a].foffset != ULONG_MAX) {
  406.                 if (eaddr == ULONG_MAX) {
  407.                     eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
  408.                     vtran = vaddr;
  409.                 }
  410.                 cnt32 = areas[a].last_addr - vaddr + 1;
  411.                 if (cnt32 > 4096)
  412.                     cnt32 = 4096;
  413.                 else
  414.                     zaddr = vaddr;
  415.                 vcnt += cnt32;
  416.             } else
  417.                 zero32(vaddr);
  418.             pt[pti] |= PT_I;
  419.         }
  420.     }
  421.     if (eaddr != ULONG_MAX) {
  422.         int cur_f, rsize;
  423.         if (a == A_emu)
  424.             cur_f = emu_f;
  425.         else
  426.             cur_f = aout_f;
  427.         lseek(cur_f, eaddr, 0);
  428.         rsize = read(cur_f, paging_buffer, (size_t) vcnt);
  429.         if (rsize < vcnt)
  430.             memset(paging_buffer + rsize, 0, (size_t) (vcnt - rsize));
  431.         if (zaddr != ULONG_MAX)
  432.             zero32(zaddr);
  433.         memput(vtran, paging_buffer, (size_t) vcnt);
  434.     }
  435.     utils_tss = old_util_tss;
  436. #if TOPLINEINFO
  437.     update_status(old_status, 78);
  438. #endif
  439.     return 0;
  440. }
  441.  
  442. static last_po_pdi = 0;
  443. static last_po_pti = 0;
  444.  
  445. static int page_out(void)
  446. {                                /* return 1 if paged out, 0 if not */
  447.     unsigned start_pdi, start_pti, dblock, pn;
  448.     word32 far *pt, v;
  449. #if TOPLINEINFO
  450.     int old_status;
  451.     old_status = update_status('>' | 0x0a00, 79);
  452. #endif
  453.     start_pdi = last_po_pdi;
  454.     start_pti = last_po_pti;
  455.     pt = (word32 far *) ((pd[last_po_pdi] & ~0xFFF) << 12);
  456.     do {
  457.         if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S)) {
  458.             if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S)) {
  459.                 pn = (unsigned)(pt[last_po_pti] >> 12);
  460.                 dblock = dalloc();
  461.                 v = ((word32) last_po_pdi << 22) | ((word32) last_po_pti << 12);
  462.                 memget(v, paging_buffer, 4096);
  463.                 dwrite(paging_buffer, dblock);
  464.                 pt[last_po_pti] &= 0xfff & ~PT_P;    /* no longer present */
  465.                 pt[last_po_pti] |= (long)dblock << 12;
  466.                 vfree(pn);
  467. #if TOPLINEINFO
  468.                 update_status(old_status, 79);
  469. #endif
  470.                 return 1;
  471.             }
  472.         } else                    /* imagine we just checked the last entry */
  473.             last_po_pti = 1023;
  474.         if (++last_po_pti == 1024) {
  475.             last_po_pti = 0;
  476.             if (++last_po_pdi == 1024)
  477.                 last_po_pdi = 0;
  478.             pt = (word32 far *) ((pd[last_po_pdi] & ~0xFFF) << 12);
  479.         }
  480.     } while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
  481. #if TOPLINEINFO
  482.     update_status(old_status, 79);
  483. #endif
  484.     return 0;
  485. }
  486.  
  487. static unsigned pd_dblock;
  488. static int valloc_initted = 0;
  489.  
  490. void page_out_everything(void)
  491. {
  492.     int pdi;
  493.     unsigned ptb;
  494.     void far *fp;
  495.     while (page_out());
  496.     for (pdi = 0; pdi < 1024; pdi++)
  497.         if (pd[pdi]) {
  498.             ptb = dalloc();
  499.             fp = (void far *)((pd[pdi] & ~0xFFF) << 12);
  500.             movedata(FP_SEG(fp), FP_OFF(fp), _DS, FP_OFF(paging_buffer), 4096);
  501.             dwrite(paging_buffer, ptb);
  502.             vfree((unsigned)(pd[pdi] >> 12));
  503.             pd[pdi] = (pd[pdi] & (0xFFF & ~PT_P)) | ((word32) ptb << 12);
  504.         }
  505.     movedata(FP_SEG(pd), 0, _DS, FP_OFF(paging_buffer), 4096);
  506.     pd_dblock = dalloc();
  507.     dwrite(paging_buffer, pd_dblock);
  508.     vfree(FP_SEG(pd) >> 8);
  509.     xms_free();
  510. }
  511.  
  512. void page_in_everything(void)
  513. {
  514.     int pdi;
  515.     unsigned pta, ptb;
  516.     valloc_initted = 0;
  517.     pd = MK_FP(valloc(VA_640) << 8, 0);
  518.     dread(paging_buffer, pd_dblock);
  519.     dfree(pd_dblock);
  520.     movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pd), 0, 4096);
  521.     for (pdi = 0; pdi < 1024; pdi++)
  522.         if (pd[pdi]) {
  523.             pta = valloc(VA_640);
  524.             ptb = (unsigned)(pd[pdi] >> 12);
  525.             dread(paging_buffer, ptb);
  526.             dfree(ptb);
  527.             movedata(_DS, FP_OFF(paging_buffer), pta << 8, 0, 4096);
  528.             pd[pdi] = (pd[pdi] & 0xFFF) | ((word32) pta << 12) | PT_P;
  529.         }
  530.     graphics_pt = (word32 far *) ((pd[0x380] & ~0xfff) << 12);
  531.     graphics_pt_lin = ptr2linear(graphics_pt);
  532. }
  533.  
  534. int __fastcall emu_install(char *filename)
  535. {
  536.     GNU_AOUT eh;
  537.     areas[A_emu].first_addr = EMU_TEXT + ARENA;
  538.     areas[A_emu].last_addr = areas[A_emu].first_addr - 1;
  539.     areas[A_emu].foffset = 0;
  540.  
  541.     if (!filename)
  542.         return 0;
  543.     emu_f = open(filename, O_RDONLY | O_BINARY);
  544.     if (emu_f == -1) {
  545.         printf("Can't open 80387 emulator file <%s>\n", filename);
  546.         return 0;
  547.     }
  548.     read(emu_f, &eh, sizeof(eh));
  549.     areas[A_emu].last_addr += eh.tsize + eh.dsize + eh.bsize + 0x20;
  550.     return 1;
  551. }
  552. /* This is file VALLOC.C */
  553.  
  554. #define VA_FREE    0
  555. #define VA_USED    1
  556.  
  557. #define    DOS_PAGE 256            /*  1MB / 4KB = 256 Pages  */
  558.  
  559. static word8 map[4096];
  560. static word16 mem_used;
  561. static word16 left_lo, left_hi;
  562.  
  563. static unsigned pn_lo_first, pn_lo_last, pn_hi_first, pn_hi_last;
  564. static unsigned vcpi_flush_ok = 0;
  565.  
  566. #if TOPLINEINFO
  567. static void valloc_update_status(void)
  568. {
  569.     char buf[20];
  570.     int i;
  571.     if (!valloc_initted)
  572.         return;
  573.     sprintf(buf, "%5dk", mem_avail);
  574.     for (i = 0; i < 6; i++)
  575.         poke(screen_seg, (i + 70) * 2, buf[i] | 0x0a00);
  576.     sprintf(buf, "%5dk", mem_used);
  577.     for (i = 0; i < 6; i++)
  578.         poke(screen_seg, (i + 62) * 2, buf[i] | 0x0a00);
  579. }
  580. #endif
  581.  
  582. static void __pascal vset(unsigned i, int b)
  583. {
  584.     register unsigned o, m;
  585.     m = 1 << (i & 7);
  586.     o = i >> 3;
  587.     if (b && !(map[o] & m)) {
  588. #if TOPLINEINFO
  589.         mem_avail -= 4;
  590.         mem_used += 4;
  591.         valloc_update_status();
  592. #endif
  593.         map[o] |= m;
  594.     } else if (map[o] & m) {
  595. #if TOPLINEINFO
  596.         mem_avail += 4;
  597.         mem_used -= 4;
  598.         valloc_update_status();
  599. #endif
  600.         map[o] &= ~m;
  601.     }
  602. }
  603.  
  604. static int __pascal vtest(unsigned i)
  605. {
  606.     register unsigned m;
  607.     m = 1 << (i & 7);
  608.     return map[i >> 3] & m;
  609. }
  610.  
  611. static emb_handle_t emb_handle = -1;
  612.  
  613. void xms_free(void)
  614. {
  615.     if (use_xms && emb_handle != -1) {
  616.         xms_unlock_emb(emb_handle);
  617.         xms_emb_free(emb_handle);
  618. #if DEBUGGER
  619.         printf("XMS memory freed\n");
  620. #endif
  621.     }
  622. }
  623.  
  624. static void xms_alloc_init(void)
  625. {
  626.     xms_extended_info *x = xms_query_extended_memory();
  627.     emb_off_t linear_base;
  628.     emb_size_K_t emb_size;
  629. #if DEBUGGER
  630.     printf("XMS driver detected\n");
  631. #endif
  632.     emb_size = x->max_free_block;
  633.     emb_handle = xms_emb_allocate(emb_size);
  634.     linear_base = xms_lock_emb(emb_handle);
  635.     pn_hi_first = (unsigned)((linear_base + 4095) / 4096);
  636.     pn_hi_last = pn_hi_first + emb_size / 4 - 1;
  637. }
  638.  
  639. static void valloc_init(void)
  640. {
  641.     unsigned char far *vdisk;
  642.     int has_vdisk = 1;
  643.     unsigned long vdisk_top;
  644.     unsigned i, lol;
  645.     struct REGPACK r;
  646.  
  647.     if (vcpi_installed) {
  648.         pn_hi_first = 32767;
  649.         pn_hi_last = DOS_PAGE;
  650.     } else if (use_xms)
  651.         xms_alloc_init();        /*  Try XMS allocation  */
  652.     else {
  653.         /*
  654.            ** int 15/vdisk memory allocation
  655.          */
  656.         r.r_ax = 0x8800;        /* get extended memory size */
  657.         intr(0x15, &r);
  658.         pn_hi_last = r.r_ax / 4 + 255;
  659.  
  660.         /* get ivec 19h, seg only */
  661.         vdisk = (unsigned char far *)(*(long far *)0x64L & 0xFFFF0000L);
  662.         for (i = 0; i < 5; i++)
  663.             if (vdisk[i + 18] != "VDISK"[i])
  664.                 has_vdisk = 0;
  665.         if (has_vdisk) {
  666.             vdisk_top = vdisk[46] * 65536L + vdisk[45] * 256 + vdisk[44];
  667.             pn_hi_first = (unsigned)((vdisk_top + 4095) / 4096);
  668.         } else
  669.             pn_hi_first = 256;
  670.     }
  671.  
  672.     r.r_ax = 0x4800;            /* get real memory size */
  673.     r.r_bx = 0xffff;
  674.     intr(0x21, &r);                /* lol == size of largest free memory block */
  675.     lol = r.r_bx;
  676.     r.r_ax = 0x4800;
  677.     intr(0x21, &r);                /* get the block */
  678.     pn_lo_first = (r.r_ax + 0xFF) >> 8;        /* lowest real mem 4K block */
  679.     pn_lo_last = (r.r_ax + lol - 1) >> 8;    /* highest real mem 4K block */
  680.  
  681.     r.r_es = r.r_ax;            /* free the block just allocated */
  682.     r.r_ax = 0x4900;            /* because Turbo Debugger won't if we don't */
  683.     intr(0x21, &r);
  684.  
  685.     mem_avail = 0;
  686.     for (i = 0; i < DOS_PAGE / 8; i++)
  687.         map[i] = 0xff;            /* DOS Area  */
  688.     for (; i < 4096; i++)
  689.         map[i] = (vcpi_installed) ? 0x00 : 0xff;    /* Extened Memory Area  */
  690.  
  691.     for (i = pn_lo_first; i <= pn_lo_last; i++)
  692.         vset(i, VA_FREE);
  693.     for (i = pn_hi_first; i <= pn_hi_last; i++)
  694.         vset(i, VA_FREE);
  695.     vcpi_flush_ok = 1;
  696.  
  697.     mem_used = 0;
  698.     left_lo = (pn_lo_last - pn_lo_first + 1) * 4;
  699.     left_hi = (vcpi_installed) ? vcpi_capacity() * 4 : (pn_hi_last - pn_hi_first + 1) * 4;
  700.     if (vcpi_installed)
  701.         mem_avail = left_lo + left_hi;
  702.  
  703. /*  mem_avail = (pn_lo_last-pn_lo_first+1)*4 + (pn_hi_last-pn_hi_first+1)*4; */
  704. #if DEBUGGER
  705.     if (debug_mode)
  706.         printf("%d Kb conventional, %d Kb extended - %d Kb total RAM available\n", left_lo, left_hi, mem_avail);
  707. #endif
  708.  
  709. #if TOPLINEINFO
  710.     valloc_update_status();
  711. #endif
  712.     valloc_initted = 1;
  713. }
  714.  
  715. static unsigned __pascal valloc(where)
  716. {
  717.     unsigned pn;
  718.     if (!valloc_initted)
  719.         valloc_init();
  720.     switch (where) {
  721.     case VA_640:
  722.       more_640:
  723.         for (pn = pn_lo_first; pn <= pn_lo_last; pn++)
  724.             if (vtest(pn) == VA_FREE) {
  725.                 left_lo -= 4;
  726.                 vset(pn, VA_USED);
  727.                 return pn;
  728.             }
  729.         page_out();
  730.         goto more_640;
  731.     case VA_1M:
  732.       more_1m:
  733.         if (vcpi_installed) {
  734.             pn = vcpi_alloc();
  735.             if (pn) {
  736.                 left_hi -= 4;
  737.                 if (pn < pn_hi_first)
  738.                     pn_hi_first = pn;
  739.                 if (pn > pn_hi_last)
  740.                     pn_hi_last = pn;
  741.                 vset(pn, VA_USED);
  742.                 return pn;
  743.             }
  744.         } else
  745.             for (pn = pn_hi_first; pn <= pn_hi_last; pn++)
  746.                 if (vtest(pn) == VA_FREE) {
  747.                     left_hi -= 4;
  748.                     vset(pn, VA_USED);
  749.                     return pn;
  750.                 }
  751.         for (pn = pn_lo_first; pn <= pn_lo_last; pn++)
  752.             if (vtest(pn) == VA_FREE) {
  753.                 left_lo -= 4;
  754.                 vset(pn, VA_USED);
  755.                 return pn;
  756.             }
  757.         page_out();
  758.         goto more_1m;
  759.     }
  760.     return 0;
  761. }
  762.  
  763. static void __pascal vfree(unsigned pn)
  764. {
  765.     if ((vcpi_installed) && (pn >= DOS_PAGE))
  766.         vcpi_free(pn);
  767.     vset(pn, VA_FREE);
  768. }
  769.  
  770. void vcpi_flush(void)
  771. {
  772.     word16 pn;
  773.  
  774.     if (!vcpi_flush_ok)
  775.         return;                    /*  Not Initaialized Map[]  */
  776.     for (pn = pn_hi_first; pn <= pn_hi_last; pn++)
  777.         if (vtest(pn))
  778.             vcpi_free(pn);
  779.  
  780. #if DEBUGGER
  781.     printf("VCPI memory freed\n");
  782. #endif
  783. }
  784.  
  785. /* This is file DALLOC.C */
  786. #define DA_FREE    0
  787. #define DA_USED    1
  788.  
  789. #define MAX_DBLOCK 32760        /* 4095 * 8 -> 128 Mb */
  790.  
  791. static int dalloc_initted = 0;
  792. static word8 dmap[4096];
  793. static first_avail, last_avail;
  794. static int dfile = -1;
  795. #if TOPLINEINFO
  796. static disk_used = 0;
  797. #endif
  798.  
  799. static void __pascal dset(unsigned i, int b)
  800. {
  801.     register unsigned o, m;
  802.     m = 1 << (i & 7);
  803.     o = i >> 3;
  804.     if (b)
  805.         dmap[o] |= m;
  806.     else
  807.         dmap[o] &= ~m;
  808. }
  809.  
  810. static int dtest(unsigned i)
  811. {
  812.     register unsigned m;
  813.     m = 1 << (i & 7);
  814.     return dmap[i >> 3] & m;
  815. }
  816.  
  817. static char dfilename[80];
  818.  
  819. void dalloc_init(void)
  820. {
  821.     int i;
  822.     char *tmp;
  823.     tmp = getenv("GO32TMP");
  824.     if (!tmp)
  825.         tmp = getenv("GCCTMP");
  826.     if (!tmp)
  827.         tmp = getenv("TMP");
  828.     if (!tmp)
  829.         tmp = getenv("TEMP");
  830.     if (!tmp)
  831.         tmp = "/";
  832.     i = strlen(tmp) - 1;
  833.     if ((tmp[i] == '/') || (tmp[i] == '\\'))
  834.         tmp[i] = '\0';
  835.     sprintf(dfilename, "%s/page%04x.386", tmp, _CS);
  836.     dfile = open(dfilename, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IWRITE | S_IREAD);
  837.     if (dfile == -1) {
  838.         printf("Fatal! cannot open swap file %s\n", dfilename);
  839.         exit(1);
  840.     }
  841.     memset(dmap, 0, 4096);
  842.     first_avail = last_avail = 0;
  843.     dalloc_initted = 1;
  844. }
  845.  
  846. void dalloc_uninit(void)
  847. {
  848.     if (dfile == -1)
  849.         return;
  850.     close(dfile);
  851.     unlink(dfilename);
  852. }
  853.  
  854. static unsigned dalloc(void)
  855. {
  856. #if TOPLINEINFO
  857.     char buf[8];
  858.     int i;
  859. #endif
  860.     unsigned pn;
  861.     if (!dalloc_initted)
  862.         dalloc_init();
  863.     for (pn = first_avail; pn <= MAX_DBLOCK; pn++)
  864.         if (dtest(pn) == DA_FREE) {
  865.             dset(pn, DA_USED);
  866.             first_avail = pn + 1;
  867. #if TOPLINEINFO
  868.             if (pn >= last_avail)
  869.                 last_avail = pn + 1;
  870.             disk_used++;
  871.             sprintf(buf, "%5dk", disk_used * 4);
  872.             for (i = 0; i < 6; i++)
  873.                 poke(screen_seg, (54 + i) * 2, buf[i] | 0x0c00);
  874. #endif
  875.             return pn;
  876.         }
  877.     printf("Fatal: out of swap space!\n");
  878.     return 0;
  879. }
  880.  
  881. static void __pascal dfree(unsigned pn)
  882. {
  883. #if TOPLINEINFO
  884.     char buf[8];
  885.     int i;
  886. #endif
  887.     dset(pn, DA_FREE);
  888.     if (pn < first_avail)
  889.         first_avail = pn;
  890. #if TOPLINEINFO
  891.     disk_used--;
  892.     sprintf(buf, "%5dk", disk_used * 4);
  893.     for (i = 0; i < 6; i++)
  894.         poke(screen_seg, (54 + i) * 2, buf[i] | 0x0c00);
  895. #endif
  896. }
  897.  
  898. static void __pascal dwrite(word8 * buf, unsigned block)
  899. {
  900.     lseek(dfile, (long)block * 4096L, 0);
  901.     if (write(dfile, buf, 4096) < 4096) {
  902.         printf("Fatal! disk full writing to swap file\n");
  903.         exit(1);
  904.     }
  905. }
  906.  
  907. static void __pascal dread(word8 * buf, unsigned block)
  908. {
  909.     lseek(dfile, (long)block * 4096L, 0);
  910.     read(dfile, buf, 4096);
  911. }
  912.