]> 4ch.mooo.com Git - 16.git/blob - src/lib/xms.c
inputest manipulates d and q like scroll.exe
[16.git] / src / lib / xms.c
1 /* This file implements rudimentary XMS memory handling.
2  * Documentation on the XMS API was found on http://www.qzx.com/pc-gpe/xms30.txt
3  */
4
5 #include "src\lib\xms.h"
6
7 /* Set up the XMS driver, returns 0 on success and non-zero on failure */
8 static int initxms(void)
9 {
10         char XMSStatus = 0;
11
12         if ( XMSControl == 0 )
13         {
14                 __asm {
15                 ; Is an XMS driver installed?
16                         mov ax,4300h
17                         int 2Fh
18                         mov [XMSStatus], al
19                 }
20
21                 if ( XMSStatus == 0x80 )
22                 {
23                         __asm {
24                         ; Get the address of the driver control function
25                                 mov ax,4310h
26                                 int 2Fh
27                                 mov word ptr [XMSControl]  ,bx
28                                 mov word ptr [XMSControl+2],es
29                         }
30                 }
31         }
32
33         return ( XMSControl == 0 );
34 }
35
36 /* Allocate a slab of memory from XMS */
37 void huge * xmsmalloc(long unsigned int size)
38 {
39         unsigned int kB;
40         unsigned int XMSStatus = 0;
41         unsigned int XMSHandle = 0;
42         void huge * XMSPointer = NULL;
43         int n;
44
45         /* If we can not initialize XMS, the allocation fails */
46         if ( initxms() )
47                 return NULL;
48
49         /* It is not possible to allocate more kilobytes than a 16-bit register can hold :-) */
50         if ( size / 1024 > UINT_MAX )
51                 return NULL;
52
53         /* Get the next free entry in the handle <-> pointer mapping */
54         for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )
55         {
56                 if ( allocMapXMS[n].XMSPointer == NULL )
57                         break;
58         }
59
60         if ( n == MAX_XMS_ALLOCATIONS )
61                 return NULL;
62
63         kB = size / 1024 + (size % 1024 > 0);
64
65         __asm {
66         ; Allocate [kB] kilobytes of XMS memory
67                 mov ah, 09h
68                 mov dx, [kB]
69                 call [XMSControl]
70                 mov [XMSStatus], ax
71                 mov [XMSHandle], dx
72         }
73
74         /* Check if XMS allocation failed */
75         if ( XMSStatus == 0)
76                 return NULL;
77
78         __asm {
79         ; Convert XMS handle to normal pointer
80                 mov ah, 0Ch
81                 mov dx, [XMSHandle]
82                 call [XMSControl]
83                 mov [XMSStatus], ax
84
85                 mov word ptr [XMSPointer],  bx
86                 mov word ptr [XMSPointer+2],dx
87         }
88
89         if ( XMSStatus == 0 )
90         {
91                 /* Lock failed, deallocate the handle */
92                 __asm {
93                 ; Free XMS handle
94                         mov ah, 0Ah
95                         mov dx, [XMSHandle]
96                         call [XMSControl]
97
98                 ; Return value is not really interesting 
99                 ;   mov [XMSStatus], ax
100                 }
101                 return NULL;
102         }
103
104         /* Create an entry in the handle <-> pointer mapping */
105         allocMapXMS[n].XMSHandle = XMSHandle;
106         allocMapXMS[n].XMSPointer = XMSPointer;
107
108         return XMSPointer;
109 }
110
111 /* Free a pointer allocated with xmsalloc */
112 void xmsfree(void huge * XMSPointer)
113 {
114         int n;
115
116         if ( XMSPointer == NULL )
117                 return;
118
119         if ( initxms() )
120                 return;
121
122         for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ )
123         {
124                 if ( allocMapXMS[n].XMSPointer == XMSPointer )
125                 {
126                         int XMSHandle = allocMapXMS[n].XMSHandle;
127
128                         __asm {
129                         ; Unlock handle so we can free the memory block
130                                 mov ah, 0Dh
131                                 mov dx, [XMSHandle]
132                                 call [XMSControl]
133
134                         ; Free XMS memory
135                                 mov ah, 0Ah
136                                 mov dx, [XMSHandle]
137                                 call [XMSControl]
138
139                         ; Return value ignored
140                         }
141
142                         /* Clear handle <-> pointer map entry so it can be reused */
143                         allocMapXMS[n].XMSHandle = 0;
144                         allocMapXMS[n].XMSPointer = NULL;
145
146                         return;
147                 }
148         }
149 }
150
151 /* Write a memory report for debugging purposes */
152 void xmsreport(void/*FILE * stream*/)
153 {
154         int XMSVersionNumber = 0;
155         unsigned int XMSLargestBlock = 0;
156         unsigned int XMSTotal = 0;
157
158         if ( initxms() )
159         {
160                 puts("Could not initialize XMS Driver!");
161                 return;
162         }
163
164         __asm {
165         ; Get the driver version number
166                 mov ah,00h
167                 call [XMSControl] ; Get XMS Version Number
168                 mov [XMSVersionNumber], ax
169
170         ; Get the amount of free XMS memory
171                 mov ah, 08h
172                 call [XMSControl]
173                 mov [XMSLargestBlock], ax
174                 mov [XMSTotal], dx
175         }
176
177         //fprintf(stream, "XMS Version number: %d\n", XMSVersionNumber);
178         //fprintf(stream, "Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);
179         printf("XMS Version number: %d\n", XMSVersionNumber);
180         printf("Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal);
181 }
182
183 /*int main()
184 {
185         xmsreport(fopen("xms.log", "w"));
186         return 0;
187 }*/