]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_hc.c
Merge remote-tracking branch 'upstream/master'
[16.git] / src / lib / 16_hc.c
1 /* Project 16 Source Code~
2  * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123
3  *
4  * This file is part of Project 16.
5  *
6  * Project 16 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Project 16 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,
19  * Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22 /*
23         heap test stuff
24 */
25
26 #include "src/lib/16_hc.h"
27
28 #ifdef __BORLANDC__
29 void * LargestFreeBlock(size_t* Size)
30 #endif
31 #ifdef __WATCOMC__
32 void __near* LargestFreeBlock(size_t* Size)
33 #endif
34 {
35         size_t s0, s1;
36 #ifdef __BORLANDC__
37         void * p;
38 #endif
39 #ifdef __WATCOMC__
40         void __near* p;
41 #endif
42
43         s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
44 #ifdef __BORLANDC__
45         while (s0 && (p = malloc(s0)) == NULL)
46 #endif
47 #ifdef __WATCOMC__
48         while (s0 && (p = _nmalloc(s0)) == NULL)
49 #endif
50                 s0 >>= 1;
51
52         if (p)
53 #ifdef __BORLANDC__
54                 free(p);
55 #endif
56 #ifdef __WATCOMC__
57                 _nfree(p);
58 #endif
59
60         s1 = s0 >> 1;
61         while (s1)
62         {
63 #ifdef __BORLANDC__
64                 if ((p = malloc(s0 + s1)) != NULL)
65 #endif
66 #ifdef __WATCOMC__
67                 if ((p = _nmalloc(s0 + s1)) != NULL)
68 #endif
69                 {
70                         s0 += s1;
71 #ifdef __BORLANDC__
72                         free(p);
73 #endif
74 #ifdef __WATCOMC__
75                         _nfree(p);
76 #endif
77                 }
78         s1 >>= 1;
79         }
80 #ifdef __BORLANDC__
81         while (s0 && (p = malloc(s0)) == NULL)
82 #endif
83 #ifdef __WATCOMC__
84         while (s0 && (p = _nmalloc(s0)) == NULL)
85 #endif
86                 s0 ^= s0 & -s0;
87
88         *Size = s0;
89         return p;
90 }
91
92 size_t _coreleft(void)
93 {
94         size_t total = 0;
95         void __near* pFirst = NULL;
96         void __near* pLast = NULL;
97         for(;;)
98         {
99                 size_t largest;
100                 void __near* p = (void __near *)LargestFreeBlock(&largest);
101                 if (largest < sizeof(void __near*))
102                 {
103                         if (p != NULL)
104 #ifdef __BORLANDC__
105                         free(p);
106 #endif
107 #ifdef __WATCOMC__
108                         _nfree(p);
109 #endif
110                         break;
111                 }
112                 *(void __near* __near*)p = NULL;
113                 total += largest;
114                 if (pFirst == NULL)
115                         pFirst = p;
116
117                 if (pLast != NULL)
118                         *(void __near* __near*)pLast = p;
119                 pLast = p;
120         }
121
122         while (pFirst != NULL)
123         {
124                 void __near* p = *(void __near* __near*)pFirst;
125 #ifdef __BORLANDC__
126                 free(pFirst);
127 #endif
128 #ifdef __WATCOMC__
129                 _nfree(pFirst);
130 #endif
131                 pFirst = p;
132         }
133         return total;
134 }
135
136 void far* LargestFarFreeBlock(size_t* Size)
137 {
138         size_t s0, s1;
139         void far* p;
140
141         s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
142         while (s0 && (p = _fmalloc(s0)) == NULL)
143                 s0 >>= 1;
144
145         if (p)
146                 _ffree(p);
147
148         s1 = s0 >> 1;
149         while (s1)
150         {
151                 if ((p = _fmalloc(s0 + s1)) != NULL)
152                 {
153                         s0 += s1;
154                         _ffree(p);
155                 }
156         s1 >>= 1;
157         }
158         while (s0 && (p = _fmalloc(s0)) == NULL)
159                 s0 ^= s0 & -s0;
160
161         *Size = s0;
162         return p;
163 }
164
165 size_t _farcoreleft(void)
166 {
167         size_t total = 0;
168         void far* pFirst = NULL;
169         void far* pLast = NULL;
170         for(;;)
171         {
172                 size_t largest;
173                 void far* p = LargestFarFreeBlock(&largest);
174                 if (largest < sizeof(void far*))
175                 {
176                         if (p != NULL)
177                         _ffree(p);
178                         break;
179                 }
180                 *(void far* far*)p = NULL;
181                 total += largest;
182                 if (pFirst == NULL)
183                         pFirst = p;
184
185                 if (pLast != NULL)
186                         *(void far* far*)pLast = p;
187                 pLast = p;
188         }
189
190         while (pFirst != NULL)
191         {
192                 void far* p = *(void far* far*)pFirst;
193                 _ffree(pFirst);
194                 pFirst = p;
195         }
196         return total;
197 }
198
199 #ifdef __WATCOMC__
200 void huge* LargestHugeFreeBlock(size_t* Size)
201 {
202         size_t s0, s1;
203         void huge* p;
204
205         s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
206         while (s0 && (p = halloc((dword)s0, 1)) == NULL)
207                 s0 >>= 1;
208
209         if (p)
210                 hfree(p);
211
212         s1 = s0 >> 1;
213         while (s1)
214         {
215                 if ((p = halloc((dword)(s0 + s1), 1)) != NULL)
216                 {
217                         s0 += s1;
218                         hfree(p);
219                 }
220         s1 >>= 1;
221         }
222         while (s0 && (p = halloc((dword)s0, 1)) == NULL)
223                 s0 ^= s0 & -s0;
224
225         *Size = s0;
226         return p;
227 }
228
229 size_t _hugecoreleft(void)
230 {
231         size_t total = 0;
232         void huge* pFirst = NULL;
233         void huge* pLast = NULL;
234         for(;;)
235         {
236                 size_t largest;
237                 void huge* p = LargestHugeFreeBlock(&largest);
238                 if (largest < sizeof(void huge*))
239                 {
240                         if (p != NULL)
241                         hfree(p);
242                         break;
243                 }
244                 *(void huge* huge*)p = NULL;
245                 total += largest;
246                 if (pFirst == NULL)
247                         pFirst = p;
248
249                 if (pLast != NULL)
250                         *(void huge* huge*)pLast = p;
251                 pLast = p;
252         }
253
254         while (pFirst != NULL)
255         {
256                 void huge* p = *(void huge* huge*)pFirst;
257                 hfree(pFirst);
258                 pFirst = p;
259         }
260         return total;
261 }
262
263 /*void __based(__self)* LargestBasedFreeBlock(size_t* Size)
264 {
265         __segment segu;
266         size_t s0, s1;
267         void __based(__self)* p;
268
269         s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
270         while (s0 && (p = _bmalloc(segu, s0)) == NULL)
271                 s0 >>= 1;
272
273         if (p)
274                 _ffree(p);
275
276         s1 = s0 >> 1;
277         while (s1)
278         {
279                 if ((p = _bmalloc(segu, s0 + s1)) != NULL)
280                 {
281                         s0 += s1;
282                         _ffree(p);
283                 }
284         s1 >>= 1;
285         }
286         while (s0 && (p = _bmalloc(segu, s0)) == NULL)
287                 s0 ^= s0 & -s0;
288
289         *Size = s0;
290         return p;
291 }
292
293 size_t _basedcoreleft(void)
294 {
295         __segment segu;
296         size_t total = 0;
297         void __based(segu)* pFirst = NULL;
298         void __based(segu)* pLast = NULL;
299         // allocate based heap
300         segu = _bheapseg( 1024 );
301         if( segu == _NULLSEG ) {
302                 printf( "Unable to allocate based heap\n" );
303                 return 0;
304                 //exit( 1 );
305         }
306         else
307
308         for(;;)
309         {
310                 size_t largest;
311                 void __based(segu)* p = LargestBasedFreeBlock(&largest);
312                 if (largest < sizeof(void far*))
313                 {
314                         if (p != NULL)
315                         _ffree(p);
316                         break;
317                 }
318                 *(void far* far*)p = NULL;
319                 total += largest;
320                 if (pFirst == NULL)
321                         pFirst = p;
322
323                 if (pLast != NULL)
324                         *(void far* far*)pLast = p;
325                 pLast = p;
326         }
327
328         while (pFirst != NULL)
329         {
330                 void far* p = *(void far* far*)pFirst;
331                 _ffree(pFirst);
332                 pFirst = p;
333         }
334         return total;
335 }*/
336
337 size_t GetFreeSize(void)
338 {
339         struct _heapinfo h_info;
340         int heap_status;
341         size_t h_free=0, h_total=0, h_used=0;
342
343         h_info._pentry = NULL;
344         for(;;) {
345                 heap_status = _heapwalk( &h_info );
346                 if( heap_status != _HEAPOK ) break;
347                 if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
348                 if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
349                 h_total += h_info._size;
350         }
351         heapstat0(heap_status);
352         return h_free;
353 }
354
355 size_t GetFarFreeSize(void)
356 {
357         struct _heapinfo fh_info;
358         int heap_status;
359         size_t fh_free=0, fh_total=0, fh_used=0;
360
361         fh_info._pentry = NULL;
362         for(;;) {
363                 heap_status = _fheapwalk( &fh_info );
364                 if( heap_status != _HEAPOK ) break;
365                 if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
366                 if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
367                 fh_total += fh_info._size;
368         }
369         heapstat0(heap_status);
370         return fh_free;
371 }
372
373 size_t GetNearFreeSize(void)
374 {
375         struct _heapinfo nh_info;
376         int heap_status;
377         size_t nh_free=0, nh_total=0, nh_used=0;
378
379         nh_info._pentry = NULL;
380         for(;;) {
381                 heap_status = _nheapwalk( &nh_info );
382                 if( heap_status != _HEAPOK ) break;
383                 if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
384                 if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
385                 nh_total += nh_info._size;
386         }
387         heapstat0(heap_status);
388         return nh_free;
389 }
390
391 void heapdump(global_game_variables_t *gvar)
392 {
393         struct _heapinfo fh_info, nh_info, h_info;
394         int heap_status;
395         size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used;
396         byte    scratch[1024],str[16];
397
398         HC_OpenDebug(gvar);
399
400         strcpy(scratch,"\n      == default ==\n\n");
401         write(gvar->handle.heaphandle,scratch,strlen(scratch));
402         h_info._pentry = NULL;
403         h_free=0; h_total=0; h_used=0;
404         for(;;) {
405                 heap_status = _heapwalk( &h_info );
406                 if( heap_status != _HEAPOK ) break;
407                 strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
408                 if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
409                 if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
410                 h_total += h_info._size;
411                 write(gvar->handle.heaphandle,scratch,strlen(scratch));
412         }
413         heapstat(gvar, heap_status, &scratch);
414
415         //near
416         strcpy(scratch,"\n      == near ==\n\n");
417         write(gvar->handle.heaphandle,scratch,strlen(scratch));
418         nh_info._pentry = NULL;
419         nh_free=0; nh_total=0; nh_used=0;
420         for(;;) {
421                 heap_status = _nheapwalk( &nh_info );
422                 if( heap_status != _HEAPOK ) break;
423                 strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)nh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(nh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
424 /*              printf( "  %s block at %Fp of size %4.4X\n",
425 (nh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
426 nh_info._pentry, nh_info._size );*/
427                 if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
428                 if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
429                 nh_total += nh_info._size;
430                 write(gvar->handle.heaphandle,scratch,strlen(scratch));
431         }
432         heapstat(gvar, heap_status, &scratch);
433
434         //far
435         strcpy(scratch,"\n      == far ==\n\n");
436         write(gvar->handle.heaphandle,scratch,strlen(scratch));
437         fh_info._pentry = NULL;
438         fh_free=0; fh_total=0; fh_used=0;
439         for(;;) {
440                 heap_status = _fheapwalk( &fh_info );
441                 if( heap_status != _HEAPOK ) break;
442                 strcpy(scratch,"  "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)fh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(fh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
443                 /*printf( "  %s block at %Fp of size %4.4X\n",
444 (fh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
445 fh_info._pentry, fh_info._size );*/
446                 if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
447                 if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
448                 fh_total += fh_info._size;
449                 write(gvar->handle.heaphandle,scratch,strlen(scratch));
450         }
451         heapstat(gvar, heap_status, &scratch);
452
453         strcpy(scratch,"\n");
454         strcat(scratch,kittengets(2,0,"Memory Type         Total      Used       Free\n"));
455         strcat(scratch,"----------------  --------   --------   --------\n");
456         printmeminfoline(&scratch, "Default", h_total, h_used, h_free);
457         printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free);
458         printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free);
459         strcat(scratch,"----------------  --------   --------   --------\n");
460         strcat(scratch,"coreleft = ");                  ultoa((dword)_coreleft(),str,10);               strcat(scratch,str);    strcat(scratch,"\n");
461         strcat(scratch,"farcoreleft = ");               ultoa((dword)_farcoreleft(),str,10);    strcat(scratch,str);    strcat(scratch,"\n");
462         strcat(scratch,"GetFreeSize = ");               ultoa((dword)GetFreeSize(),str,10);             strcat(scratch,str);    strcat(scratch,"\n");
463         strcat(scratch,"GetNearFreeSize = ");   ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str);    strcat(scratch,"\n");
464         strcat(scratch,"GetFarFreeSize = ");    ultoa((dword)GetFarFreeSize(),str,10);  strcat(scratch,str);    strcat(scratch,"\n");
465         strcat(scratch,"memavl = ");                    ultoa((dword)_memavl(),str,10);                 strcat(scratch,str);    strcat(scratch,"\n");
466         strcat(scratch,"stackavail = ");                ultoa((dword)stackavail(),str,10);              strcat(scratch,str);    strcat(scratch,"\n");
467         write(gvar->handle.heaphandle,scratch,strlen(scratch));
468         HC_CloseDebug(gvar);
469 }
470
471 void heapstat(global_game_variables_t *gvar, int heap_status, byte *str)
472 {
473         switch( heap_status ) {
474                 case _HEAPEND:
475                         strcpy((str),"OK - end of heap\n");
476                 break;
477                 case _HEAPEMPTY:
478                         strcpy((str),"OK - heap is empty\n");
479
480                 break;
481                 case _HEAPBADBEGIN:
482                         strcpy((str),"ERROR - heap is damaged\n");
483                 break;
484                 case _HEAPBADPTR:
485                         strcpy((str),"ERROR - bad pointer to heap\n");
486                 break;
487                 case _HEAPBADNODE:
488                         strcpy((str),"ERROR - bad node in heap\n");
489         }
490         write(gvar->handle.heaphandle,(str),strlen((str)));
491 }
492
493 void heapstat0(int heap_status)
494 {
495         switch( heap_status ) {
496                 case _HEAPEND:
497                         //printf("OK - end of heap\n");
498                 break;
499                 case _HEAPEMPTY:
500                         //printf("OK - heap is empty\n");
501                 break;
502                 case _HEAPBADBEGIN:
503                         printf("ERROR - heap is damaged\n");
504                 break;
505                 case _HEAPBADPTR:
506                         printf("ERROR - bad pointer to heap\n");
507                 break;
508                 case _HEAPBADNODE:
509                         printf("ERROR - bad node in heap\n");
510         }
511 }
512 #endif
513 /*
514 ============================
515 =
516 = HC_OpenDebug / HC_CloseDebug
517 =
518 = Opens a binary file with the handle "heaphandle"
519 =
520 ============================
521 */
522 void HC_OpenDebug(global_game_variables_t *gvar)
523 {
524 #ifdef __BORLANDC__
525         unlink("heap.16b");
526         gvar->handle.heaphandle = open("heap.16b", O_CREAT | O_WRONLY | O_TEXT);
527 #endif
528 #ifdef __WATCOMC__
529         unlink("heap.16w");
530         gvar->handle.heaphandle = open("heap.16w", O_CREAT | O_WRONLY | O_TEXT);
531 #endif
532 }
533
534 void HC_CloseDebug(global_game_variables_t *gvar)
535 {
536         close(gvar->handle.heaphandle);
537 }