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