]> 4ch.mooo.com Git - 16.git/blob - src/lib/exmm/xmem.c
added a EMS & XMS library
[16.git] / src / lib / exmm / xmem.c
1
2 /*
3
4    Copyright 1994 Alec Russell, ALL rights reserved
5         Permission granted to use as you wish.
6
7    Slightly higher level xms calls than xmem.asm
8
9 */
10
11 #include <stdio.h>
12 #include <io.h>
13 #include <string.h>
14 #include <malloc.h>
15
16 #include <xmem.h>
17
18 xms_head_t xms_head={0};  // set handle to zero
19
20
21 /* ---------------------- alloc_xms() ----------------- February 19,1994 */
22 short alloc_xms(unsigned short far *size)  // size in 16k blocks
23 {
24    return(XMS_alloc(0, size));
25 }
26
27 /* ---------------------- xms_to_mem() ---------------- February 19,1994 */
28 short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n)
29 {
30    unsigned short block, boff;
31
32    block=off >> XMSBLOCKSHIFT;
33    boff=off - (block << XMSBLOCKSHIFT);
34
35    return(XMStoMem(handle, block, boff, n, p));
36 }
37
38 /* ---------------------- mem_to_xms() ---------------- February 19,1994 */
39 short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n)
40 {
41    unsigned short block, boff;
42
43    block=off >> XMSBLOCKSHIFT;
44    boff=off - (block << XMSBLOCKSHIFT);
45
46    return(MemToXMS(handle, block, boff, n, p));
47 }
48
49 /* ---------------------- qalloc_xms() -------------------- March 8,1994 */
50 xms_node_t *qalloc_xms(unsigned long size)
51 {
52    xms_node_t *node=NULL;
53    xms_node_t *t1;
54
55    if ( size <= xms_head.avail )
56       {
57       // look for existing node
58       t1=xms_head.next;
59       while ( t1 )
60          {
61          if ( t1->used == 0 && t1->size >= size )
62             {
63             t1->off=0;
64             t1->used=1;
65             node=t1;
66             break;
67             }
68          else
69             t1=t1->next;
70          }
71
72       if ( node == NULL ) // didn't find existing node
73          {
74          node=malloc(sizeof(xms_node_t));
75          if ( node )
76             {
77             node->off=0;
78             node->used=1;
79             node->size=size;
80             node->next=NULL;
81             node->start=xms_head.next_off;
82             xms_head.avail-=size;
83             xms_head.next_off+=size;
84             if ( xms_head.next == NULL )
85                {
86                xms_head.next=node;
87                }
88             else
89                {
90                t1=xms_head.next;
91                while ( t1->next )
92                   t1=t1->next;
93                t1->next=node;
94                }
95             }
96          else
97             pr2("out of near mem in qalloc_xms");
98          }
99       }
100    else
101       pr2("out of xms mem in qalloc size %lu avail %lu", size, xms_head.avail);
102
103    return(node);
104 }
105
106 /* ---------------------- qfree_xms() --------------------- March 8,1994 */
107 void qfree_xms(xms_node_t *node)
108 {
109    xms_node_t *t1;
110
111    if ( xms_head.next )
112       {
113       t1=xms_head.next;
114       while ( t1 != node && t1 )
115          t1=t1->next;
116
117       if ( t1 )
118          {
119          t1->used=0;
120          }
121       else
122          pr2("ERROR didn't find node qfree");
123       }
124    else
125       {
126       pr2("ATTEMPTED to qfree empty list");
127       }
128 }
129
130 /* ---------------------- xms_open() ---------------------- March 8,1994 */
131 xms_node_t *xms_open(char *file)
132 {
133    int i;
134    xms_node_t *node=NULL;
135    FILE *fp;
136    char *buffer;
137    unsigned long off;
138
139    fp=fopen(file, "rb");
140    if ( fp )
141       {
142       node=qalloc_xms(filelength(fileno(fp)));
143       if ( node )
144          {
145          buffer=malloc(4096);
146          if ( buffer )
147             {
148             off=0l;
149             while ( (i=fread(buffer, 1, 4096, fp)) )
150                {
151                mem_to_xms(xms_head.handle, (char far *)buffer, off+node->start, i);
152                off+=i;
153                }
154
155             free(buffer);
156             }
157          else
158             pr2("out of mem in xms_open 1");
159          }
160
161       fclose(fp);
162       }
163    else
164       pr2("ERROR opening %s in xms_open", file);
165
166    return(node);
167 }
168
169 /* ---------------------- xms_read() ---------------------- March 8,1994 */
170 short xms_read(void far *buffer, unsigned short n, xms_node_t *node)
171 {
172
173    if ( node->off >= node->size )
174       return 0;
175
176    if ( n+node->off > node->size )
177       n=node->size - node->off;
178
179    xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);
180    node->off+=n;
181
182    return(n);
183 }
184
185 /* ---------------------- xms_write() ---------------------- March 8,1994 */
186 short xms_write(void far *buffer, unsigned short n, xms_node_t *node)
187 {
188
189    if ( node->off >= node->size )
190       return 0;
191
192    if ( n+node->off > node->size )
193       n=node->size - node->off;
194
195    mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);
196    node->off+=n;
197
198    return(n);
199 }
200
201
202 /* ---------------------- xms_tell() ---------------------- March 8,1994 */
203 long xms_tell(xms_node_t *node)
204 {
205    return node->off;
206 }
207
208 /* ---------------------- xms_seek() ---------------------- March 8,1994 */
209 short xms_seek(xms_node_t *node, long off, short whence)
210 {
211    short err=0;
212
213    switch ( whence )
214       {
215       case SEEK_SET:
216          if ( off < 0l || off > node->size )
217             err=1;
218          else
219             node->off=off;
220          break;
221
222       case SEEK_END:
223          if ( off > 0l || (node->size + off) < 0l )
224             err=1;
225          else
226             node->off=node->size + off;
227          break;
228
229       case SEEK_CUR:
230          if ( node->off + off < 0l || node->off + off > node->size )
231             err=1;
232          else
233             node->off+=off;
234          break;
235       }
236
237    return(err);
238 }
239
240 /* ---------------------- xms_close() --------------------- March 8,1994 */
241 void xms_close(xms_node_t *node)
242 {
243    qfree_xms(node);
244 }
245
246 /* ---------------------- init_xms() ---------------------- March 8,1994 */
247 short init_xms(unsigned short min_blocks)
248 {
249    unsigned short blocks;
250
251    blocks=XMSblk_available();
252    if ( blocks >= min_blocks )
253       {
254       memset(&xms_head, 0, sizeof(xms_head_t));
255       if ( (xms_head.handle=alloc_xms(&blocks)) )
256          {
257          pr2("blocks minus by = %u", blocks);
258          min_blocks-=blocks;
259          xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;
260          blocks=min_blocks;
261          }
262       else
263          blocks=0;
264       }
265    else
266       blocks=0;
267
268    return(blocks);
269 }
270
271 /* ---------------------- deinit_xms() -------------------- March 8,1994 */
272 void deinit_xms(void)
273 {
274    xms_node_t *t1, *t2;
275
276    if ( xms_head.handle )
277       {
278       XMS_dealloc(xms_head.handle);
279       if ( xms_head.next )
280          {
281          t1=xms_head.next;
282          t2=t1->next;
283          while ( t1 )
284             {
285             free(t1);
286             t1=t2;
287             t2=t1->next;
288             }
289          }
290
291       memset(&xms_head, 0, sizeof(xms_head_t));
292       }
293 }
294 /* --------------------------- end of file ------------------------- */
295
296 /*
297
298 Not sure how to use this?
299
300 call init_xms(x) to allocate a big chunk of xms.
301 x is in 'blocks' of 16Kb. Pick X big enough to buffer all the files
302 you want to place in xms.
303
304 call xms_open("filename); for each file to be buffered. This copies the file
305 int xms.
306
307 then use xms_read(), xms_write(), and xms_seek() to read the file from
308 xms instead of disk.
309
310 call deinit_xms() just before exit to clean up.
311
312 You can also use the lower level calls directly.
313
314 */