home *** CD-ROM | disk | FTP | other *** search
/ Doom Extras / DExtras.iso / accessor / dos / deu521 / source / swapmem.c < prev    next >
C/C++ Source or Header  |  1994-05-17  |  9KB  |  307 lines

  1. /*
  2.    Memory swapping by Raphaël Quinet <quinet@montefiore.ulg.ac.be>
  3.           and Christian Johannes Schladetsch <s924706@yallara.cs.rmit.OZ.AU>
  4.  
  5.    You are allowed to use any parts of this code in another program, as
  6.    long as you give credits to the authors in the documentation and in
  7.    the program itself.  Read the file README.1ST for more information.
  8.  
  9.    This program comes with absolutely no warranty.
  10.  
  11.    SWAPMEM.C - When the memory is low....
  12.  
  13.    Note from RQ:
  14.       Yuck!  I don't like this horrible thing.  The program should be
  15.       able to swap almost anything to XMS or to disk, not only the
  16.       five objects used here (Things, LineDefs, SideDefs, Vertexes and
  17.       Sectors).  That was a quick and dirty hack...  I didn't have the
  18.       time to write a cleaner code...
  19.  
  20.    Note2 from RQ:
  21.       After having tested these routines, I see that they are not very
  22.       useful...  I'm still getting "out of memory" errors while editing
  23.       E2M7 and other huge levels.  I should rewrite all this for GCC,
  24.       use a flat memory model and a DOS extender, then just delete all
  25.       this code...  I will have to do that anyway if I want to port it
  26.       to other systems (Unix, Linux), so why not?
  27.       Moral of the story: never waste long hours writing high-level
  28.       memory swapping routines on a deficient OS.  Use a real OS with
  29.       a better memory management instead.
  30.  
  31.    Note for CJS:
  32.       It should be easy to include your XMS code in this file.  Just
  33.       add the necessary lines in InitSwap(), SwapIn() and SwapOut().
  34.       You won't need to edit any other file.  Put all your routines
  35.       in XMS.C, with the necessary includes in XMS.H.  Please keep it
  36.       short and simple... :-)
  37.       ... And delete this note once you're done.
  38. */
  39.  
  40. /* the includes and typedefs */
  41. #include "deu.h"
  42. #include "levels.h"
  43. #ifdef SWAP_TO_XMS
  44. #include "xms.h"
  45. typedef XMSHandle SwapHandle;    /* XMS handle */
  46. #define INVALID_HANDLE        -1
  47. #else
  48. typedef char SwapHandle[ 128];    /* name of the temporary disk file */
  49. #define INVALID_HANDLE        "..."
  50. #endif /* SWAP_TO_XMS */
  51.  
  52. /* global variables */
  53. Bool NeedThings = FALSE;
  54. Bool NeedLineDefs = FALSE;
  55. Bool NeedSideDefs = FALSE;
  56. Bool NeedVertexes = FALSE;
  57. Bool NeedSectors = FALSE;
  58. SwapHandle ThingsH;
  59. SwapHandle LineDefsH;
  60. SwapHandle SideDefsH;
  61. SwapHandle VertexesH;
  62. SwapHandle SectorsH;
  63.  
  64.  
  65. /*
  66.    do the necessary initialisation for the secondary storage
  67. */
  68.  
  69. void InitSwap()
  70. {
  71. #ifdef SWAP_TO_XMS
  72.    /* Init XMS */
  73.    ...
  74. #else
  75.    strcpy(ThingsH, INVALID_HANDLE);
  76.    strcpy(LineDefsH, INVALID_HANDLE);
  77.    strcpy(SideDefsH, INVALID_HANDLE);
  78.    strcpy(VertexesH, INVALID_HANDLE);
  79.    strcpy(SectorsH, INVALID_HANDLE);
  80. #endif /* SWAP_TO_XMS */
  81. }
  82.  
  83.  
  84.  
  85. /*
  86.    moves an object from secondary storage to lower RAM
  87. */
  88.  
  89. void huge *SwapIn( SwapHandle handle, unsigned long size)
  90. {
  91.    void huge *ptr;
  92. #ifdef SWAP_TO_XMS
  93.    /* allocate a new memory block (in lower RAM) */
  94.    ptr = GetFarMemory( size);
  95.    /* read the data from XMS */
  96.    ...
  97.    /* free the XMS memory block */
  98.    ...
  99.    /* delete the handle */
  100.    ...
  101. #else
  102.    FILE      *file;
  103.    char huge *data;
  104.    SwapHandle oldhandle;
  105.  
  106.    /* Note from RQ:
  107.      the following test is there to prevent an infinite loop when
  108.      SwapIn calls GetFarMemory, which calls FreeSomeMemory, which
  109.      in turn calls SwapOut, then SwapIn...
  110.     */
  111.    if (! strcmp( handle, INVALID_HANDLE))
  112.       return NULL;
  113. #ifdef DEBUG
  114.    LogMessage( "swapping in %lu bytes from %s\n", size, handle);
  115. #endif /* DEBUG */
  116.    strcpy( oldhandle, handle);
  117.    /* invalidate the handle (must be before "GetFarMemory") */
  118.    strcpy( handle, INVALID_HANDLE);
  119.    /* allocate a new memory block (in lower RAM) */
  120.    ptr = GetFarMemory( size);
  121.    /* read the data from the temporary file */
  122.    file = fopen( oldhandle, "rb");
  123.    data = ptr;
  124.    if (file == NULL)
  125.    {
  126. #ifdef DEBUG
  127.       LogMessage( "\nFree memory before crash: %lu bytes.", farcoreleft());
  128. #endif /* DEBUG */
  129.       ProgError( "error opening temporary file \"%s\"", oldhandle);
  130.    }
  131.    while (size > 0x8000)
  132.    {
  133.       if (fread( data, 1, 0x8000, file) != 0x8000)
  134.      ProgError( "error reading from temporary file \"%s\"", oldhandle);
  135.       data = data + 0x8000;
  136.       size -= 0x8000;
  137.    }
  138.    if (fread( data, 1, size, file) != size)
  139.       ProgError( "error reading from temporary file \"%s\"", oldhandle);
  140.    fclose( file);
  141.    /* delete the file */
  142.    unlink( oldhandle);
  143. #endif /* !SWAP_TO_XMS */
  144.    return ptr;
  145. }
  146.  
  147.  
  148.  
  149. /*
  150.    moves an object from lower RAM to secondary storage
  151. */
  152.  
  153. void SwapOut( void huge *ptr, SwapHandle handle, unsigned long size)
  154. {
  155. #ifdef SWAP_TO_XMS
  156.    /* get a new XMS handle */
  157.    ...
  158.    /* write the data to XMS */
  159.    ...
  160. #else
  161.    FILE      *file;
  162.    char huge *data;
  163.    char      *tmp;
  164.  
  165.    /* get a new (unique) file name */
  166.    tmp = tempnam( NULL, "{DEU}");
  167.    if (tmp == NULL)
  168.    {
  169. #ifdef DEBUG
  170.       LogMessage( "\nFree memory before crash: %lu bytes.", farcoreleft());
  171. #endif /* DEBUG */
  172.       ProgError( "cannot create a temporary file name (out of memory)");
  173.    }
  174.    strcpy( handle, tmp);
  175.    free( tmp);
  176. #ifdef DEBUG
  177.    LogMessage( "swapping out %lu bytes to %s\n", size, handle);
  178. #endif /* DEBUG */
  179.    /* write the data to the temporary file */
  180.    data = ptr;
  181.    file = fopen( handle, "wb");
  182.    if (file == NULL)
  183.    {
  184. #ifdef DEBUG
  185.       LogMessage( "\nFree memory before crash: %lu bytes.", farcoreleft());
  186. #endif /* DEBUG */
  187.       ProgError( "error creating temporary file \"%s\"", handle);
  188.    }
  189.    while (size > 0x8000)
  190.    {
  191.       if (fwrite( data, 1, 0x8000, file) != 0x8000)
  192.      ProgError( "error writing to temporary file \"%s\"", handle);
  193.       data = data + 0x8000;
  194.       size -= 0x8000;
  195.    }
  196.    if (fwrite( data, 1, size, file) != size)
  197.       ProgError( "error writing to temporary file \"%s\"", handle);
  198.    fclose( file);
  199. #endif /* !SWAP_TO_XMS */
  200.    /* free the data block (in lower RAM) */
  201.    FreeFarMemory( ptr);
  202. }
  203.  
  204.  
  205.  
  206. /*
  207.    get the objects needed (if they aren't already in memory)
  208. */
  209.  
  210. void SwapInObjects( void)
  211. {
  212.    if (NeedThings && NumThings > 0 && Things == NULL)
  213.       Things = SwapIn( ThingsH, (unsigned long) NumThings * sizeof (struct Thing));
  214.    if (NeedLineDefs && NumLineDefs > 0 && LineDefs == NULL)
  215.       LineDefs = SwapIn( LineDefsH, (unsigned long) NumLineDefs * sizeof (struct LineDef));
  216.    if (NeedSideDefs && NumSideDefs > 0 && SideDefs == NULL)
  217.       SideDefs = SwapIn( SideDefsH, (unsigned long) NumSideDefs * sizeof (struct SideDef));
  218.    if (NeedVertexes && NumVertexes > 0 && Vertexes == NULL)
  219.       Vertexes = SwapIn( VertexesH, (unsigned long) NumVertexes * sizeof (struct Vertex));
  220.    if (NeedSectors && NumSectors > 0 && Sectors == NULL)
  221.       Sectors = SwapIn( SectorsH, (unsigned long) NumSectors * sizeof (struct Sector));
  222. }
  223.  
  224.  
  225. /*
  226.    mark the objects that should be in lower RAM
  227. */
  228.  
  229. void ObjectsNeeded( int objtype, ...)
  230. {
  231.    va_list args;
  232.  
  233.    /* get the list of objects */
  234.    NeedThings = FALSE;
  235.    NeedLineDefs = FALSE;
  236.    NeedSideDefs = FALSE;
  237.    NeedVertexes = FALSE;
  238.    NeedSectors = FALSE;
  239.    va_start( args, objtype);
  240.    while (objtype > 0)
  241.    {
  242.       switch (objtype)
  243.       {
  244.       case OBJ_THINGS:
  245.      NeedThings = TRUE;
  246.      break;
  247.       case OBJ_LINEDEFS:
  248.      NeedLineDefs = TRUE;
  249.      break;
  250.       case OBJ_SIDEDEFS:
  251.      NeedSideDefs = TRUE;
  252.      break;
  253.       case OBJ_VERTEXES:
  254.      NeedVertexes = TRUE;
  255.      break;
  256.       case OBJ_SECTORS:
  257.      NeedSectors = TRUE;
  258.      break;
  259.       }
  260.       objtype = va_arg( args, int);
  261.    }
  262.    va_end( args);
  263.    /* get the objects if they aren't already in memory */
  264.    SwapInObjects();
  265. }
  266.  
  267.  
  268.  
  269. /*
  270.    free as much memory as possible by moving some objects out of lower RAM
  271. */
  272.  
  273. void FreeSomeMemory( void)
  274. {
  275.    /* move everything to secondary storage */
  276.    if (NumSectors > 0 && Sectors != NULL)
  277.    {
  278.       SwapOut( Sectors, SectorsH, (unsigned long) NumSectors * sizeof (struct Sector));
  279.       Sectors = NULL;
  280.    }
  281.    if (NumVertexes > 0 && Vertexes != NULL)
  282.    {
  283.       SwapOut( Vertexes, VertexesH, (unsigned long) NumVertexes * sizeof (struct Vertex));
  284.       Vertexes = NULL;
  285.    }
  286.    if (NumSideDefs > 0 && SideDefs != NULL)
  287.    {
  288.       SwapOut( SideDefs, SideDefsH, (unsigned long) NumSideDefs * sizeof (struct SideDef));
  289.       SideDefs = NULL;
  290.    }
  291.    if (NumLineDefs > 0 && LineDefs != NULL)
  292.    {
  293.       SwapOut( LineDefs, LineDefsH, (unsigned long) NumLineDefs * sizeof (struct LineDef));
  294.       LineDefs = NULL;
  295.    }
  296.    if (NumThings > 0 && Things != NULL)
  297.    {
  298.       SwapOut( Things, ThingsH, (unsigned long) NumThings * sizeof (struct Thing));
  299.       Things = NULL;
  300.    }
  301.    /* re-load the objects that are needed */
  302.    SwapInObjects();
  303. }
  304.  
  305.  
  306. /* end of file */
  307.