]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_mm.c
broke fuck
[16.git] / src / lib / 16_mm.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 // NEWMM.C\r
24 \r
25 /*\r
26 =============================================================================\r
27 \r
28                         ID software memory manager\r
29                         --------------------------\r
30 \r
31 Primary coder: John Carmack\r
32 \r
33 RELIES ON\r
34 ---------\r
35 Quit (global_game_variables_t *gvar, char *error) function\r
36 \r
37 \r
38 WORK TO DO\r
39 ----------\r
40 MM_SizePtr to change the size of a given pointer\r
41 \r
42 Multiple purge levels utilized\r
43 \r
44 EMS / XMS unmanaged routines\r
45 \r
46 =============================================================================\r
47 */\r
48 /*\r
49 \r
50 Open Watcom port by sparky4\r
51 \r
52 */\r
53 #include "src/lib/16_mm.h"\r
54 #include "src/lib/16_ca.h"\r
55 #include <malloc.h>\r
56 #pragma hdrstop\r
57 \r
58 #pragma warn -pro\r
59 #pragma warn -use\r
60 \r
61 \r
62 /*\r
63 =============================================================================\r
64 \r
65                                                         LOCAL INFO\r
66 \r
67 =============================================================================\r
68 */\r
69 \r
70 //#define LOCKBIT               0x80    // if set in attributes, block cannot be moved\r
71 //#define PURGEBITS     3               // 0-3 level, 0= unpurgable, 3= purge first\r
72 //#define PURGEMASK     0xfffc\r
73 //#define BASEATTRIBUTES        0       // unlocked, non purgable\r
74 \r
75 //#define MAXUMBS               10\r
76 \r
77 /*typedef struct mmblockstruct\r
78 {\r
79         unsigned        start,length;\r
80         unsigned        attributes;\r
81         memptr          *useptr;        // pointer to the segment start\r
82         struct mmblockstruct far *next;\r
83 } mmblocktype;*/\r
84 \r
85 \r
86 //#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;}\r
87 //\r
88 \r
89 //#define GETNEWBLOCK {if(!gvar->mm.mmfree)MML_ClearBlock(gvar);gvar->mm.mmnew=gvar->mm.mmfree;gvar->mm.mmfree=gvar->mm.mmfree->next;}\r
90 \r
91 //#define FREEBLOCK(x) {*x->useptr=NULL;x->next=gvar->mm.mmfree;gvar->mm.mmfree=x;}\r
92 \r
93 /*\r
94 =============================================================================\r
95 \r
96                                                  GLOBAL VARIABLES\r
97 \r
98 =============================================================================\r
99 */\r
100 \r
101 /*mminfotype    mminfo;\r
102 memptr          bufferseg;\r
103 boolean         mmerror;*/\r
104 \r
105 void            (* beforesort) (void);\r
106 void            (* aftersort) (void);\r
107 \r
108 /*\r
109 =============================================================================\r
110 \r
111                                                  LOCAL VARIABLES\r
112 \r
113 =============================================================================\r
114 */\r
115 \r
116 /*boolean               mmstarted;\r
117 \r
118 void far        *farheap;\r
119 void            *nearheap;\r
120 \r
121 mmblocktype     far mmblocks[MAXBLOCKS]\r
122                         ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
123 \r
124 boolean         bombonerror;*/\r
125 \r
126 //unsigned      totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
127 \r
128 void            (* XMSaddr) (void);             // far pointer to XMS driver\r
129 \r
130 /*unsigned      numUMBs,UMBbase[MAXUMBS];*/\r
131 \r
132 //==========================================================================\r
133 \r
134 //\r
135 // local prototypes\r
136 //\r
137 \r
138 boolean         MML_CheckForEMS (void);\r
139 void            MML_ShutdownEMS (void);\r
140 void            MM_MapEMS (void);\r
141 boolean         MML_CheckForXMS (void);\r
142 void            MML_ShutdownXMS (void);\r
143 //void          MML_UseSpace (unsigned segstart, unsigned seglength);\r
144 //void          MML_ClearBlock (void);\r
145 \r
146 //==========================================================================\r
147 #ifndef __16_PM__\r
148 #if 0\r
149 static  char *ParmStringsexmm[] = {"noems","noxms",""};\r
150 #endif\r
151 #endif\r
152 /*\r
153 ======================\r
154 =\r
155 = MML_CheckForEMS\r
156 =\r
157 = Routine from p36 of Extending DOS\r
158 =\r
159 =======================\r
160 */\r
161 \r
162 boolean MML_CheckForEMS(void)\r
163 {\r
164         boolean emmcfems = false;\r
165         word            EMSPageFrame = 0;\r
166         byte    err=0, str[64];\r
167         static char     emmname[] = "EMMXXXX0"; //fix by andrius4669\r
168         __asm {\r
169                 mov     dx,OFFSET emmname       //fix by andrius4669\r
170                 mov     ax,0x3d00\r
171                 int     EMM_INT         // try to open EMMXXXX0 device\r
172                 jc      error\r
173 \r
174                 mov     bx,ax\r
175                 mov     ax,0x4400\r
176 \r
177                 int     EMM_INT         // get device info\r
178                 jc      error\r
179 \r
180                 and     dx,0x80\r
181                 jz      error\r
182 \r
183                 mov     ax,0x4407\r
184 \r
185                 int     EMM_INT         // get status\r
186                 jc      error\r
187                 or      al,al\r
188                 jz      error\r
189 \r
190                 mov     ah,0x3e\r
191                 int     EMM_INT         // close handle\r
192                 jc      error\r
193 \r
194                 //\r
195                 // pageframe check\r
196                 //\r
197                 mov     ah,EMS_GETFRAME\r
198                 int     EMS_INT                 // find the page frame address\r
199                 or      ah,ah\r
200                 jnz     error\r
201                 mov     [EMSPageFrame],bx\r
202 \r
203                 //\r
204                 // EMS is good\r
205                 //\r
206                 mov     emmcfems,1\r
207                 jmp     End\r
208 #ifdef __BORLANDC__\r
209         }\r
210 #endif\r
211                 error:\r
212 #ifdef __BORLANDC__\r
213         __asm {\r
214 #endif\r
215                 //\r
216                 // EMS is bad\r
217                 //\r
218                 mov     err,ah\r
219                 mov     emmcfems,0\r
220 #ifdef __BORLANDC__\r
221         }\r
222 #endif\r
223                 End:\r
224 #ifdef __WATCOMC__\r
225         }\r
226 #endif\r
227 \r
228         //\r
229         // Pageframe switch to determine if there is one!\r
230         //\r
231         if(!EMSPageFrame)\r
232         {\r
233                 emmcfems = false;\r
234 #if defined(__DEBUG_PM__) || defined(__DEBUG_MM__)\r
235                 printf("MML_CheckForEMS: EMS error No Pageframe!\nAddress detected to be %04x\n", EMSPageFrame);\r
236 #endif\r
237         }else   if(!emmcfems)// if there is an error and page frame is not 0000\r
238         {\r
239                 strcpy(str,"MML_CheckForEMS: EMS error ");\r
240                 MM_EMSerr(str, err);\r
241                 printf("%s\n",str);\r
242         }\r
243 \r
244         return(emmcfems);\r
245 }\r
246 \r
247 #ifndef __16_PM__\r
248 #if 0\r
249 /*\r
250 ======================\r
251 =\r
252 = MML_SetupEMS\r
253 =\r
254 =======================\r
255 */\r
256 \r
257 byte MML_SetupEMS(global_game_variables_t *gvar)\r
258 {\r
259         byte    str[160];\r
260         byte    err;\r
261         boolean errorflag=false;\r
262 \r
263         unsigned int EMSVer = 0;\r
264         //byte  EMS_status;\r
265         unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle;\r
266         totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0;\r
267 \r
268         __asm {\r
269                 mov     ah,EMS_STATUS\r
270                 int     EMS_INT                                         // make sure EMS hardware is present\r
271                 or      ah,ah\r
272                 //mov   [EMS_status],ah\r
273                 jnz     error\r
274 \r
275                 mov     ah,EMS_VERSION\r
276                 int     EMS_INT\r
277                 or      ah,ah\r
278                 jnz     error\r
279                 mov     [EMSVer],ax                             //      set EMSVer\r
280                 cmp     al,0x32                                         // only work on ems 3.2 or greater\r
281                 jb      error\r
282 \r
283                 mov     ah,EMS_GETFRAME\r
284                 int     EMS_INT                                         // find the page frame address\r
285                 or      ah,ah\r
286                 jnz     error\r
287                 mov     [EMSPageFrame],bx\r
288 \r
289                 mov     ah,EMS_GETPAGES\r
290                 int     EMS_INT                                         // find out how much EMS is there\r
291                 or      ah,ah\r
292                 jnz     error\r
293                 mov     [totalEMSpages],dx\r
294                 mov     [freeEMSpages],bx\r
295                 or      bx,bx\r
296                 jz      noEMS                                           // no EMS at all to allocate\r
297                                                                                         //EXPAND DONG!!!!\r
298                 cmp     [EMSVer],0x40\r
299                 jb      low\r
300                 cmp     bx,[freeEMSpages]\r
301                 jle     getpages\r
302                 mov     bx,[freeEMSpages]\r
303                 jmp     getpages\r
304 #ifdef __BORLANDC__\r
305         }\r
306 #endif\r
307         low:\r
308 #ifdef __BORLANDC__\r
309         __asm {\r
310 #endif\r
311                 cmp     bx,4\r
312                 jle     getpages                                        // there is only 1,2,3,or 4 pages\r
313                 mov     bx,4                                            // we can't use more than 4 pages\r
314 #ifdef __BORLANDC__\r
315         }\r
316 #endif\r
317         getpages:\r
318 #ifdef __BORLANDC__\r
319         __asm {\r
320 #endif\r
321                 mov     [EMSpagesmapped],bx\r
322                 mov     ah,EMS_ALLOCPAGES                       // allocate up to 64k of EMS\r
323                 int     EMS_INT\r
324                 or      ah,ah\r
325                 jnz     error\r
326                 mov     [EMSHandle],dx\r
327                 jmp End\r
328 #ifdef __BORLANDC__\r
329         }\r
330 #endif\r
331         error:\r
332 #ifdef __BORLANDC__\r
333         __asm {\r
334 #endif\r
335                 mov     err,ah\r
336                 mov     errorflag,1\r
337                 jmp End\r
338 #ifdef __BORLANDC__\r
339         }\r
340 #endif\r
341 noEMS:\r
342 End:\r
343 #ifdef __WATCOMC__\r
344         }\r
345 #endif\r
346         if(errorflag==true)\r
347         {\r
348                 strcpy(str,"MM_SetupEMS: EMS error ");\r
349                 MM_EMSerr(str, err);\r
350                 printf("%s\n",str);\r
351                 return err;\r
352         }\r
353         gvar->mm.totalEMSpages=totalEMSpages;\r
354         gvar->mm.freeEMSpages=freeEMSpages;\r
355         gvar->mm.EMSPageFrame=EMSPageFrame;\r
356         gvar->mm.EMSpagesmapped=EMSpagesmapped;\r
357         gvar->mm.EMSHandle=EMSHandle;\r
358         gvar->mm.EMSVer=EMSVer;\r
359         return 0;\r
360 }\r
361 \r
362 \r
363 /*\r
364 ======================\r
365 =\r
366 = MML_ShutdownEMS\r
367 =\r
368 =======================\r
369 */\r
370 \r
371 void MML_ShutdownEMS(global_game_variables_t *gvar)\r
372 {\r
373         boolean errorflag=false;\r
374         unsigned EMSHandle=gvar->mm.EMSHandle;\r
375 \r
376         if(!EMSHandle)\r
377                 return;\r
378         __asm {\r
379                 mov     ah,EMS_FREEPAGES\r
380                 mov     dx,[EMSHandle]\r
381                 int     EMS_INT\r
382                 or      ah,ah\r
383                 jz      ok\r
384                 mov     errorflag,1\r
385 #ifdef __BORLANDC__\r
386         }\r
387 #endif\r
388                 ok:\r
389 #ifdef __WATCOMC__\r
390         }\r
391 #endif\r
392         if(errorflag==true)\r
393                 Quit (gvar, "MML_ShutdownEMS: Error freeing EMS!\n");   //++++ add something\r
394 }\r
395 \r
396 /*\r
397 ====================\r
398 =\r
399 = MM_MapEMS\r
400 =\r
401 = Maps the 64k of EMS used by memory manager into the page frame\r
402 = for general use.  This only needs to be called if you are keeping\r
403 = other things in EMS.\r
404 =\r
405 ====================\r
406 */\r
407 \r
408 byte MM_MapEMS(global_game_variables_t *gvar)\r
409 {\r
410         byte    str[160];\r
411         unsigned        EMSHandle;\r
412         byte err;\r
413         boolean errorflag=false;\r
414         int     i;\r
415         EMSHandle=gvar->mm.EMSHandle;\r
416 \r
417         for (i=0;i<4/*MAPPAGES*/;i++)\r
418         {\r
419                 __asm {\r
420                         mov     ah,EMS_MAPPAGE\r
421                         mov     bx,[i]                  // logical page\r
422                         mov     al,bl                   // physical page\r
423                         mov     dx,[EMSHandle]  // handle\r
424                         int     EMS_INT\r
425                         or      ah,ah\r
426                         jnz     error\r
427                         jmp End\r
428 #ifdef __BORLANDC__\r
429                 }\r
430 #endif\r
431                         error:\r
432 #ifdef __BORLANDC__\r
433                 __asm {\r
434 #endif\r
435                         mov     err,ah\r
436                         mov     errorflag,1\r
437 #ifdef __BORLANDC__\r
438                 }\r
439 #endif\r
440                         End:\r
441 #ifdef __WATCOMC__\r
442                 }\r
443 #endif\r
444                 if(errorflag==true)\r
445                 {\r
446                         strcpy(str,"MM_MapEMS: EMS error ");\r
447                         MM_EMSerr(str, err);\r
448                         printf("%s\n",str);\r
449                         return err;\r
450                 }\r
451         }\r
452         gvar->mmi.EMSmem = (i)*0x4000lu;\r
453         return 0;\r
454 }\r
455 \r
456 byte MM_MapXEMS(global_game_variables_t *gvar)\r
457 {\r
458 //SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
459 \r
460         //Maps up to 4 logical EMS pages to physical pages in the page frame, where:\r
461         //PhysicalStart = Physical page first logical page is mapped to\r
462         //LogicalStart  = First logical page to map\r
463         //NumPages      = Number of pages to map (1 to 4)\r
464         //Handle        = EMS handle logical pages are allocated to\r
465 \r
466   /*//Create a buffer containing the page information\r
467 //  FOR x = 0 TO NumPages - 1\r
468 //    MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)\r
469 //  NEXT*/\r
470 \r
471 //  Regs.ax = 0x5000                           //Map the pages in the buffer\r
472 //  Regs.cx = NumPages                         //to the pageframe\r
473 //  Regs.dx = Handle\r
474 //  Regs.ds = VARSEG(MapInfo$)\r
475 //  Regs.si = SADD(MapInfo$)\r
476 //  InterruptX 0x67, Regs, Regs\r
477 //      EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100  //Store the status code\r
478 \r
479 //END SUB\r
480         byte    str[160];\r
481         byte err;\r
482         word    EMSHandle;\r
483         boolean errorflag=false;\r
484         int     i;\r
485         EMSHandle=gvar->mm.EMSHandle;\r
486 \r
487         if(gvar->mm.EMSVer<0x40)\r
488                 return 5;\r
489 \r
490         for (i=0;i<MAPPAGES;i++)\r
491         {\r
492                 __asm {\r
493                         mov     ah,EMS_MAPXPAGE\r
494                         mov     cx,[i]                  // logical page\r
495                         mov     al,bl                   // physical page\r
496                         mov     dx,[EMSHandle]  // handle\r
497                         int     EMS_INT\r
498                         or      ah,ah\r
499                         jnz     error\r
500                         jmp End\r
501 #ifdef __BORLANDC__\r
502                 }\r
503 #endif\r
504                         error:\r
505 #ifdef __BORLANDC__\r
506                 __asm {\r
507 #endif\r
508                         mov     err,ah\r
509                         mov     errorflag,1\r
510 #ifdef __BORLANDC__\r
511                 }\r
512 #endif\r
513                         End:\r
514 #ifdef __WATCOMC__\r
515                 }\r
516 #endif\r
517                 if(errorflag==true)\r
518                 {\r
519                         //strcpy(str,"MM_MapXEMS: EMS error 0x");\r
520                         strcpy(str,"MM_MapXEMS: EMS error ");\r
521                         //itoa(err,str2,16);\r
522                         MM_EMSerr(str, err);\r
523                         printf("%s\n",str);\r
524                         //printf("%s%x\n",str, err);\r
525                         //printf("FACK! %x\n", err);\r
526                         return err;\r
527                 }\r
528         }\r
529         gvar->mmi.EMSmem = (i)*0x4000lu;\r
530         return 0;\r
531 }\r
532 #endif\r
533 #endif\r
534 //==========================================================================\r
535 \r
536 /*\r
537 ======================\r
538 =\r
539 = MML_CheckForXMS\r
540 =\r
541 = Check for XMM driver\r
542 =\r
543 =======================\r
544 */\r
545 \r
546 boolean MML_CheckForXMS(void)\r
547 {\r
548         //numUMBs = 0;\r
549         boolean errorflag=false;\r
550 \r
551         __asm {\r
552                 mov     ax,0x4300\r
553                 int     0x2f                            // query status of installed diver\r
554                 cmp     al,0x80\r
555                 je      good\r
556                 mov     errorflag,1\r
557 #ifdef __BORLANDC__\r
558         }\r
559 #endif\r
560                 good:\r
561 #ifdef __WATCOMC__\r
562         }\r
563 #endif\r
564         if(errorflag==true) return false;\r
565         else return true;\r
566 }\r
567 \r
568 #ifndef __16_PM__\r
569 #if 0\r
570 /*\r
571 ======================\r
572 =\r
573 = MML_SetupXMS\r
574 =\r
575 = Try to allocate all upper memory block\r
576 =\r
577 =======================\r
578 */\r
579 \r
580 void MML_SetupXMS(global_game_variables_t *gvar)\r
581 {\r
582         word    base,size;\r
583 \r
584 \r
585         __asm {\r
586                 mov     ax,0x4310\r
587                 int     0x2f\r
588                 mov     [WORD PTR XMSaddr],bx\r
589                 mov     [WORD PTR XMSaddr+2],es         // function pointer to XMS driver\r
590         }\r
591 getmemory:\r
592         __asm {\r
593                 mov     ah,XMS_ALLOCUMB\r
594                 mov     dx,0xffff                                       // try for largest block possible\r
595                 //mov     ax,dx                                         // Set available Kbytes.\r
596                 call    [DWORD PTR XMSaddr]\r
597                 or      ax,ax\r
598                 jnz     gotone\r
599 \r
600                 cmp     bl,0xb0                                         // error: smaller UMB is available\r
601                 jne     done;\r
602 \r
603                 mov     ah,XMS_ALLOCUMB\r
604                 call    [DWORD PTR XMSaddr]             // DX holds largest available UMB\r
605                 or      ax,ax\r
606                 jz      done                                            // another error...\r
607 #ifdef __BORLANDC__\r
608         }\r
609 #endif\r
610                 gotone:\r
611 #ifdef __BORLANDC__\r
612         __asm {\r
613 #endif\r
614                 mov     [base],bx\r
615                 mov     [size],dx\r
616 #ifdef __BORLANDC__\r
617         }\r
618 #endif\r
619                 done:\r
620 #ifdef __WATCOMC__\r
621         }\r
622 #endif\r
623 //      printf("base=%u ", base); printf("size=%u\n", size);\r
624         MML_UseSpace (base,size, gvar);\r
625         gvar->mmi.XMSmem += size*16;\r
626         gvar->mm.UMBbase[gvar->mm.numUMBs] = base;\r
627         gvar->mm.numUMBs++;\r
628         if(gvar->mm.numUMBs < MAXUMBS)\r
629                 goto getmemory;\r
630 }\r
631 \r
632 \r
633 /*\r
634 ======================\r
635 =\r
636 = MML_ShutdownXMS\r
637 =\r
638 ======================\r
639 */\r
640 \r
641 void MML_ShutdownXMS(global_game_variables_t *gvar)\r
642 {\r
643         int     i;\r
644         unsigned        base;\r
645 \r
646         for (i=0;i<gvar->mm.numUMBs;i++)\r
647         {\r
648                 base = gvar->mm.UMBbase[i];\r
649                 __asm {\r
650                         mov     ah,XMS_FREEUMB\r
651                         mov     dx,[base]\r
652                         call    [DWORD PTR XMSaddr]\r
653                 }\r
654         }\r
655 }\r
656 #endif\r
657 #endif\r
658 //==========================================================================\r
659 \r
660 /*\r
661 ======================\r
662 =\r
663 = MML_UseSpace\r
664 =\r
665 = Marks a range of paragraphs as usable by the memory manager\r
666 = This is used to mark space for the near heap, far heap, ems page frame,\r
667 = and upper memory blocks\r
668 =\r
669 ======================\r
670 */\r
671 \r
672 /*\r
673         extra = oldend - (segstart+seglength);\r
674 \r
675         segmlen=extra;\r
676 \r
677         //++++emsver stuff!\r
678         if(segm>1)/// || extra>=0x10000lu)\r
679         //if(extra>0xfffflu)\r
680         {\r
681                 scan->blob=segm;\r
682 \r
683                 //MML_UseSpace (segstart, seglength, gvar);\r
684 \r
685                 printf("MML_UseSpace: Segment spans two blocks!\n");\r
686         //}\r
687         printf("segm=%u         ", segm);\r
688         printf("ex=%lu  ", extra);\r
689         printf("old=%u  ", oldend);\r
690         printf("start+seglen=%lu\n", segstart+seglength);\r
691         printf("segsta=%x       ", segstart);\r
692         printf("len=%lu ", scan->length);\r
693         printf("seglen=%lu      ", seglength);\r
694         printf("segmlen=%lu\n", segmlen);\r
695         }\r
696 //++++todo: linked list of segment!\r
697 */\r
698 void MML_UseSpace (word segstart, word seglength, global_game_variables_t *gvar)\r
699 {\r
700         mmblocktype far *scan,far *last;\r
701         word    oldend;\r
702         sdword          extra;\r
703         //word segm=1;\r
704 \r
705         scan = last = gvar->mm.mmhead;\r
706         gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
707 \r
708 //\r
709 // search for the block that contains the range of segments\r
710 //\r
711         while (scan->start+scan->length < segstart)\r
712         {\r
713                 last = scan;\r
714                 scan = scan->next;\r
715         }\r
716 \r
717 //\r
718 // find out how many blocks it spans!\r
719 //\r
720         /*for(;seglength>=0x10000;seglength-=0xFFFF)\r
721         {\r
722                 //printf("      seglen=%lu\n", segmlen);\r
723                 segm++;\r
724         }*/\r
725 \r
726 //\r
727 // take the given range out of the block\r
728 //\r
729         oldend = scan->start + scan->length;\r
730         extra = oldend - (segstart+seglength);\r
731         if (extra < 0)\r
732 #ifdef __DEBUG_MM__\r
733         {\r
734                 printf("========================================\n");\r
735                 printf("start=%x        ", scan->start);\r
736                 printf("old=%u  ", oldend);\r
737                 printf("start+seglen=%lu\n", segstart+seglength);\r
738                 printf("segsta=%x       ", segstart);\r
739                 printf("len=%lu ", scan->length);\r
740                 printf("seglen=%lu      ", seglength);\r
741                 printf("\n");\r
742                 printf("MML_UseSpace: Segment spans two blocks! %d\n", extra);\r
743                 printf("========================================\n");\r
744                 //return;\r
745         }\r
746 #else\r
747                 Quit ("MML_UseSpace: Segment spans two blocks!");\r
748 #endif\r
749 \r
750         if (segstart == scan->start)\r
751         {\r
752                 last->next = scan->next;                        // unlink block\r
753                 FREEBLOCK(scan);\r
754                 scan = last;\r
755         }\r
756         else\r
757                 scan->length = segstart-scan->start;    // shorten block\r
758 \r
759         if (extra > 0)\r
760         {\r
761                 GETNEWBLOCK;\r
762                 gvar->mm.mmnew->useptr = NULL;\r
763 \r
764                 gvar->mm.mmnew->next = scan->next;\r
765                 scan->next = gvar->mm.mmnew;\r
766                 gvar->mm.mmnew->start = segstart+seglength;\r
767                 gvar->mm.mmnew->length = extra;\r
768                 gvar->mm.mmnew->attributes = LOCKBIT;\r
769         }//else if(segm>0) goto segu;\r
770 \r
771 }\r
772 \r
773 //==========================================================================\r
774 \r
775 /*\r
776 ====================\r
777 =\r
778 = MML_ClearBlock\r
779 =\r
780 = We are out of blocks, so free a purgable block\r
781 =\r
782 ====================\r
783 */\r
784 \r
785 void MML_ClearBlock (global_game_variables_t *gvar)\r
786 {\r
787         mmblocktype far *scan;//,far *last;\r
788 \r
789         scan = gvar->mm.mmhead->next;\r
790 \r
791         while(scan)\r
792         {\r
793                 if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))\r
794                 {\r
795                         MM_FreePtr(scan->useptr, gvar);\r
796                         return;\r
797                 }\r
798                 scan = scan->next;\r
799         }\r
800 \r
801         Quit (gvar, "MM_ClearBlock: No purgable blocks!\n");\r
802 }\r
803 \r
804 \r
805 //==========================================================================\r
806 \r
807 /*\r
808 ===================\r
809 =\r
810 = MM_Startup\r
811 =\r
812 = Grabs all space from turbo with malloc/farmalloc\r
813 = Allocates bufferseg misc buffer\r
814 =\r
815 ===================\r
816 */\r
817 \r
818 void MM_Startup (global_game_variables_t *gvar)\r
819 {\r
820         int i;\r
821         dword length;\r
822         void far        *start;\r
823         word    segstart,seglength;//,endfree;\r
824 \r
825         if(gvar->mm.mmstarted)\r
826                 MM_Shutdown (gvar);\r
827 \r
828         gvar->mm.mmstarted = true;\r
829         gvar->mm.bombonerror = true;\r
830 \r
831 //\r
832 // set up the linked list (everything in the free list;\r
833 //\r
834         gvar->mm.mmhead = NULL;\r
835         gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
836         for (i=0;i<MAXBLOCKS-1;i++)\r
837                 gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\r
838         gvar->mm.mmblocks[i].next = NULL;\r
839 \r
840 //\r
841 // locked block of all memory until we punch out free space\r
842 //\r
843         GETNEWBLOCK;\r
844         gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node\r
845         gvar->mm.mmnew->start = 0;\r
846         gvar->mm.mmnew->length = 0xffff;\r
847         gvar->mm.mmnew->attributes = LOCKBIT;\r
848         gvar->mm.mmnew->next = NULL;\r
849         gvar->mm.mmrover = gvar->mm.mmhead;\r
850 \r
851 \r
852 //\r
853 // get all available near conventional memory segments\r
854 //\r
855 #ifdef __WATCOMC__\r
856         _nheapgrow();\r
857 #endif\r
858         length=(word)_memavl();//(word)coreleft();\r
859         //start = gvar->mm.nearheap = _fmalloc(length);\r
860 #ifdef __WATCOMC__\r
861         start = (void __far *)(gvar->mm.nearheap = _nmalloc(length));\r
862 #endif\r
863 #ifdef __BORLANDC__\r
864         start = (void far *)(gvar->mm.nearheap = malloc(length));\r
865 #endif\r
866 \r
867         length -= 16-(FP_OFF(start)&15);\r
868         length -= SAVENEARHEAP;\r
869         seglength = length / 16;                        // now in paragraphs\r
870         segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
871         MML_UseSpace (segstart,seglength, gvar);\r
872         gvar->mmi.nearheap = length;\r
873         //0000printf("near:     start=%Fp       segstart=%x     seglen=%lu      len=%lu\n", start, segstart, (dword)seglength, length);\r
874 \r
875 //\r
876 // get all available far conventional memory segments\r
877 //\r
878 #ifdef __WATCOMC__\r
879         _fheapgrow();\r
880 #endif\r
881 #ifdef __BORLANDC__\r
882 //      printf("farcoreleft()                           %lu\n", farcoreleft());\r
883 //      printf("(farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));\r
884 #endif\r
885         length=_FCORELEFT;\r
886         start = gvar->mm.farheap = _fmalloc(length);//start = gvar->mm.farheap = halloc(length, 1);\r
887 \r
888         length -= 16-(FP_OFF(start)&15);\r
889         length -= SAVEFARHEAP;\r
890         seglength = length / 16;                        // now in paragraphs\r
891         segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
892         MML_UseSpace (segstart,seglength, gvar);\r
893         gvar->mmi.farheap = length;\r
894         //0000printf("far:      start=%Fp       segstart=%x     seglen=%lu      len=%lu\n", start, segstart, (dword)seglength, length);\r
895 \r
896         gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;\r
897 \r
898 #if !defined(__16_PM__)// && defined(__WATCOMC__)\r
899 #if 0\r
900         if(!dbg_debugpm) {\r
901 //\r
902 // detect EMS and allocate up to 64K at page frame\r
903 //\r
904         gvar->mmi.EMSmem = 0;\r
905 //goto emsskip; //0000\r
906         for(i = 1;i < _argc;i++)\r
907         {\r
908                 if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)\r
909                         goto emsskip;                           // param NOEMS\r
910         }\r
911         if(MML_CheckForEMS())\r
912         {\r
913                 MML_SetupEMS(gvar);                                     // allocate space\r
914                 //16_PM: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!\r
915                 MML_UseSpace (gvar->mm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);\r
916                 //if(gvar->pm.emm.EMSVer<0x40)\r
917                         MM_MapEMS(gvar);                                        // map in used pages\r
918                 //else\r
919                         //MM_MapXEMS(gvar);                                     // map in used pages\r
920         }\r
921 \r
922 //\r
923 // detect XMS and get upper memory blocks\r
924 //\r
925 emsskip:\r
926         gvar->mmi.XMSmem = 0;\r
927 goto xmsskip;//0000\r
928         for(i = 1;i < _argc;i++)\r
929         {\r
930                 if(US_CheckParm( _argv[i],ParmStringsexmm) == 0)\r
931                         goto xmsskip;                           // param NOXMS\r
932         }\r
933         if(MML_CheckForXMS())\r
934         {\r
935                 MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible\r
936         }\r
937 \r
938         }\r
939 xmsskip:\r
940 #endif\r
941 #endif\r
942 //\r
943 // allocate the misc buffer\r
944 //\r
945         gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block\r
946 \r
947         MM_GetPtr (&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
948 }\r
949 \r
950 //==========================================================================\r
951 \r
952 /*\r
953 ====================\r
954 =\r
955 = MM_Shutdown\r
956 =\r
957 = Frees all conventional, EMS, and XMS allocated\r
958 =\r
959 ====================\r
960 */\r
961 \r
962 void MM_Shutdown (global_game_variables_t *gvar)\r
963 {\r
964         if(!(gvar->mm.mmstarted))\r
965                 return;\r
966 \r
967         _ffree(gvar->mm.farheap);//     printf("                far freed\n");\r
968 #ifdef __WATCOMC__\r
969         _nfree(gvar->mm.nearheap);//    printf("                near freed\n");\r
970 #endif\r
971 #ifdef __BORLANDC__\r
972         free(gvar->mm.nearheap);//      printf("                near freed\n");\r
973 #endif\r
974 #ifndef __16_PM__\r
975 #if 0\r
976 #ifdef __DEBUG__\r
977         if(!dbg_debugpm) {\r
978 #endif\r
979         if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }\r
980         if(MML_CheckForXMS()){ MML_ShutdownXMS(gvar); }//printf("               XMS freed\n"); }\r
981 #ifdef __DEBUG__\r
982         }\r
983 #endif\r
984 #endif\r
985 #endif\r
986 }\r
987 \r
988 //==========================================================================\r
989 \r
990 /*\r
991 ====================\r
992 =\r
993 = MM_GetPtr\r
994 =\r
995 = Allocates an unlocked, unpurgable block\r
996 =\r
997 ====================\r
998 */\r
999 \r
1000 void MM_GetPtr (memptr *baseptr,dword size, global_game_variables_t *gvar)\r
1001 {\r
1002         mmblocktype far *scan,far *lastscan,far *endscan\r
1003                                 ,far *purge,far *next;\r
1004         int                     search;\r
1005         unsigned        needed,startseg;\r
1006 \r
1007         needed = (size+15)/16;          // convert size from bytes to paragraphs\r
1008 \r
1009         GETNEWBLOCK;                            // fill in start and next after a spot is found\r
1010         gvar->mm.mmnew->length = needed;\r
1011         gvar->mm.mmnew->useptr = baseptr;\r
1012         gvar->mm.mmnew->attributes = BASEATTRIBUTES;\r
1013         //if(gvar->mm.mmnew->useptr==NULL){\r
1014 #ifdef __DEBUG_MM__\r
1015         printf("MM_GetPtr\n");\r
1016         if(dbg_debugmm>0){\r
1017                 //%04x\r
1018                 printf("        baseptr=%Fp     ", baseptr); printf("useptr=%Fp\n", gvar->mm.mmnew->useptr);\r
1019                 printf("        *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));\r
1020                 printf("        &baseptr=%Fp    ", &baseptr); printf("&useptr=%Fp\n", &(gvar->mm.mmnew->useptr));\r
1021         }\r
1022         printf("        size is %lu\n", size);\r
1023 #endif\r
1024         //Quit(gvar, "gvar->mm.mmnew->useptr==NULL"); }\r
1025 \r
1026 //tryagain:\r
1027         for (search = 0; search<3; search++)\r
1028         {\r
1029         //\r
1030         // first search:        try to allocate right after the rover, then on up\r
1031         // second search:       search from the head pointer up to the rover\r
1032         // third search:        compress memory, then scan from start\r
1033                 if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead)\r
1034                         search++;\r
1035 \r
1036                 switch (search)\r
1037                 {\r
1038                 case 0:\r
1039                         lastscan = gvar->mm.mmrover;\r
1040                         scan = gvar->mm.mmrover->next;\r
1041                         endscan = NULL;\r
1042                         break;\r
1043                 case 1:\r
1044                         lastscan = gvar->mm.mmhead;\r
1045                         scan = gvar->mm.mmhead->next;\r
1046                         endscan = gvar->mm.mmrover;\r
1047                         break;\r
1048                 case 2:\r
1049                         MM_SortMem (gvar);\r
1050                         lastscan = gvar->mm.mmhead;\r
1051                         scan = gvar->mm.mmhead->next;\r
1052                         endscan = NULL;\r
1053                         break;\r
1054                 }\r
1055 \r
1056                 startseg = lastscan->start + lastscan->length;\r
1057 \r
1058                 while (scan != endscan)\r
1059                 {\r
1060                         if (scan->start - startseg >= needed)\r
1061                         {\r
1062                         //\r
1063                         // got enough space between the end of lastscan and\r
1064                         // the start of scan, so throw out anything in the middle\r
1065                         // and allocate the new block\r
1066                         //\r
1067                                 purge = lastscan->next;\r
1068                                 lastscan->next = gvar->mm.mmnew;\r
1069                                 gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;\r
1070                                 gvar->mm.mmnew->next = scan;\r
1071                                 while ( purge != scan)\r
1072                                 {       // free the purgable block\r
1073                                         next = purge->next;\r
1074                                         FREEBLOCK(purge);\r
1075                                         purge = next;           // purge another if not at scan\r
1076                                 }\r
1077                                 gvar->mm.mmrover = gvar->mm.mmnew;\r
1078                                 return; // good allocation!\r
1079                         }\r
1080 \r
1081                         //\r
1082                         // if this block is purge level zero or locked, skip past it\r
1083                         //\r
1084                         if ( (scan->attributes & LOCKBIT)\r
1085                                 || !(scan->attributes & PURGEBITS) )\r
1086                         {\r
1087                                 lastscan = scan;\r
1088                                 startseg = lastscan->start + lastscan->length;\r
1089                         }\r
1090 \r
1091 \r
1092                         scan=scan->next;                // look at next line\r
1093                 }\r
1094         }\r
1095 \r
1096         if (gvar->mm.bombonerror)\r
1097         {\r
1098 #ifdef __WATCOMC__\r
1099                 //heapdump();\r
1100 #endif\r
1101                 printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));\r
1102                 Quit(gvar, "for stability reasons the program will shut down! wwww\n");\r
1103         }\r
1104         else\r
1105                 gvar->mm.mmerror = true;\r
1106 }\r
1107 \r
1108 //==========================================================================\r
1109 \r
1110 /*\r
1111 ====================\r
1112 =\r
1113 = MM_FreePtr\r
1114 =\r
1115 = Deallocates an unlocked, purgable block\r
1116 =\r
1117 ====================\r
1118 */\r
1119 \r
1120 void MM_FreePtr (memptr *baseptr, global_game_variables_t *gvar)\r
1121 {\r
1122         mmblocktype far *scan,far *last;\r
1123 \r
1124         last = gvar->mm.mmhead;\r
1125         scan = last->next;\r
1126 \r
1127         if (baseptr == gvar->mm.mmrover->useptr)        // removed the last allocated block\r
1128                 gvar->mm.mmrover = gvar->mm.mmhead;\r
1129 \r
1130         while(scan->useptr != baseptr && scan)\r
1131         {\r
1132                 last = scan;\r
1133                 scan = scan->next;\r
1134         }\r
1135 \r
1136         if(!scan)\r
1137                 Quit (gvar, "MM_FreePtr: Block not found!");\r
1138 \r
1139         last->next = scan->next;\r
1140 \r
1141         FREEBLOCK(scan);\r
1142 }\r
1143 //==========================================================================\r
1144 \r
1145 /*\r
1146 =====================\r
1147 =\r
1148 = MM_SetPurge\r
1149 =\r
1150 = Sets the purge level for a block (locked blocks cannot be made purgable)\r
1151 =\r
1152 =====================\r
1153 */\r
1154 \r
1155 void MM_SetPurge (memptr *baseptr, int purge, global_game_variables_t *gvar)\r
1156 {\r
1157         mmblocktype far *start;\r
1158 \r
1159         start = gvar->mm.mmrover;\r
1160 \r
1161         do\r
1162         {\r
1163                 if (gvar->mm.mmrover->useptr == baseptr)\r
1164                         break;\r
1165 \r
1166                 gvar->mm.mmrover = gvar->mm.mmrover->next;\r
1167 \r
1168                 if (!gvar->mm.mmrover)\r
1169                         gvar->mm.mmrover = gvar->mm.mmhead;\r
1170                 else if (gvar->mm.mmrover == start)\r
1171                         Quit (gvar, "MM_SetPurge: Block not found!");\r
1172 \r
1173         } while(1);\r
1174 \r
1175         gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
1176         gvar->mm.mmrover->attributes |= purge;\r
1177 }\r
1178 \r
1179 //==========================================================================\r
1180 \r
1181 /*\r
1182 =====================\r
1183 =\r
1184 = MM_SetLock\r
1185 =\r
1186 = Locks / unlocks the block\r
1187 =\r
1188 =====================\r
1189 */\r
1190 \r
1191 void MM_SetLock (memptr *baseptr, boolean locked, global_game_variables_t *gvar)\r
1192 {\r
1193         mmblocktype far *start;\r
1194 \r
1195         start = gvar->mm.mmrover;\r
1196 \r
1197         do\r
1198         {\r
1199                 if (gvar->mm.mmrover->useptr == baseptr)\r
1200                         break;\r
1201 \r
1202                 gvar->mm.mmrover = gvar->mm.mmrover->next;\r
1203 \r
1204                 if (!gvar->mm.mmrover)\r
1205                         gvar->mm.mmrover = gvar->mm.mmhead;\r
1206                 else if (gvar->mm.mmrover == start)\r
1207                         Quit (gvar, "MM_SetLock: Block not found!");\r
1208 \r
1209         } while(1);\r
1210 \r
1211         gvar->mm.mmrover->attributes &= ~LOCKBIT;\r
1212         gvar->mm.mmrover->attributes |= locked*LOCKBIT;\r
1213 }\r
1214 \r
1215 //==========================================================================\r
1216 \r
1217 /*\r
1218 =====================\r
1219 =\r
1220 = MM_SortMem\r
1221 =\r
1222 = Throws out all purgable stuff and compresses movable blocks\r
1223 =\r
1224 =====================\r
1225 */\r
1226 \r
1227 void MM_SortMem (global_game_variables_t *gvar)\r
1228 {\r
1229         mmblocktype far *scan,far *last,far *next;\r
1230         unsigned        start,length,source,dest,oldborder;\r
1231         //++++int                       playing;\r
1232 \r
1233         //\r
1234         // lock down a currently playing sound\r
1235         //\r
1236 /*++++  playing = SD_SoundPlaying ();\r
1237         if(playing)\r
1238         {\r
1239                 switch (SoundMode)\r
1240                 {\r
1241                 case sdm_PC:\r
1242                         playing += STARTPCSOUNDS;\r
1243                         break;\r
1244                 case sdm_AdLib:\r
1245                         playing += STARTADLIBSOUNDS;\r
1246                         break;\r
1247                 }\r
1248                 MM_SetLock((memptr *)&audiosegs[playing],true);\r
1249         }\r
1250 \r
1251 \r
1252         SD_StopSound();*/\r
1253         oldborder = gvar->video.bordercolor;\r
1254         gvar->video.bordercolor = modexPalOverscan(15);\r
1255 \r
1256         if(beforesort)\r
1257                 beforesort();\r
1258 \r
1259         scan = gvar->mm.mmhead;\r
1260 \r
1261         last = NULL;            // shut up compiler warning\r
1262 \r
1263         while(scan)\r
1264         {\r
1265                 if(scan->attributes & LOCKBIT)\r
1266                 {\r
1267                 //\r
1268                 // block is locked, so try to pile later blocks right after it\r
1269                 //\r
1270                         start = scan->start + scan->length;\r
1271                 }\r
1272                 else\r
1273                 {\r
1274                         if(scan->attributes & PURGEBITS)\r
1275                         {\r
1276                         //\r
1277                         // throw out the purgable block\r
1278                         //\r
1279                                 next = scan->next;\r
1280                                 FREEBLOCK(scan); //MM_FreeBlock(scan, gvar);\r
1281                                 last->next = next;\r
1282                                 scan = next;\r
1283                                 continue;\r
1284                         }\r
1285                         else\r
1286                         {\r
1287                         //\r
1288                         // push the non purgable block on top of the last moved block\r
1289                         //\r
1290                                 if(scan->start != start)\r
1291                                 {\r
1292                                         length = scan->length;\r
1293                                         source = scan->start;\r
1294                                         dest = start;\r
1295                                         while(length > 0xf00)\r
1296                                         {\r
1297                                                 movedata(source,0,dest,0,0xf00*16);\r
1298                                                 length -= 0xf00;\r
1299                                                 source += 0xf00;\r
1300                                                 dest += 0xf00;\r
1301                                         }\r
1302                                         movedata(source,0,dest,0,length*16);\r
1303 \r
1304                                         scan->start = start;\r
1305                                         *(unsigned *)scan->useptr = start;\r
1306                                 }\r
1307                                 start = scan->start + scan->length;\r
1308                         }\r
1309                 }\r
1310 \r
1311                 last = scan;\r
1312                 scan = scan->next;              // go to next block\r
1313         }\r
1314 \r
1315         gvar->mm.mmrover = gvar->mm.mmhead;\r
1316 \r
1317         if(aftersort)\r
1318                 aftersort();\r
1319 \r
1320         VL_ColorBorder (oldborder, &gvar->video);\r
1321 \r
1322 /*++++  if(playing)\r
1323                 MM_SetLock((memptr *)&audiosegs[playing],false);*/\r
1324 }\r
1325 \r
1326 //==========================================================================\r
1327 \r
1328 /*\r
1329 =====================\r
1330 =\r
1331 = MM_ShowMemory\r
1332 =\r
1333 =====================\r
1334 */\r
1335 \r
1336 #ifdef __WATCOMC__\r
1337 //#define MMSMPANVID\r
1338 #define MMSMSCANINFO\r
1339 #endif\r
1340 \r
1341 void MM_ShowMemory (global_game_variables_t *gvar)\r
1342 {\r
1343         mmblocktype far *scan;\r
1344         unsigned color,temp,x,y         ,w,q,width;\r
1345         sdword  end,owner;\r
1346         byte            scratch[160],scratch0[4096],str[16];\r
1347         mmshowmemoryinfo_t scaninfo[MAXBLOCKS];\r
1348 \r
1349         if(!gvar->video.page[0].width) gvar->video.page[0].sw = gvar->video.page[0].width = 320;        //to prevent division by 0\r
1350 //--    VL_SetLineWidth(40, gvar);\r
1351         //temp = gvar->video.ofs.bufferofs;\r
1352         //gvar->video.ofs.bufferofs = gvar->video.ofs.displayofs;\r
1353         temp = BDOFSCONV gvar->video.BOFS;\r
1354         gvar->video.BOFS = gvar->video.DOFS;\r
1355         scan = gvar->mm.mmhead;\r
1356 \r
1357         end = -1; w = 0;\r
1358 \r
1359         width = gvar->video.page[0].width; q = 0;\r
1360 \r
1361         CA_OpenDebug (gvar);\r
1362         while (scan)\r
1363         {\r
1364                 scaninfo[q].scan = scan;\r
1365                 strcpy(scratch, AARESET);\r
1366                 if(scan->attributes & PURGEBITS)\r
1367                 {\r
1368                         color = 6;              // dark purple = purgable\r
1369                         strcpy(scratch0, AAMAGENTA);            // dark purple = purgable\r
1370                 }else{\r
1371                         color = 2;              // medium blue = non purgable\r
1372                         strcpy(scratch0, AABLUE);               // medium blue = non purgable\r
1373                 }\r
1374                 if(scan->attributes & LOCKBIT)\r
1375                 {\r
1376                         color = 1;              // red = locked\r
1377                         strcpy(scratch0, AARED);                // red = locked\r
1378                 }\r
1379                 if (scan->start<=end)\r
1380                 {\r
1381                         printf("\nend==%d\n\n", end);\r
1382                         strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n");\r
1383                         strcat(scratch, "End's Size: ");\r
1384                         ultoa (end,str,10);\r
1385                         strcat (scratch,str);\r
1386                         strcat(scratch, "\nscan->start's Size: ");\r
1387                         ultoa (scan->start,str,10);\r
1388                         strcat (scratch,str);\r
1389                         write(gvar->handle.debughandle,scratch,strlen(scratch));\r
1390                         Quit (gvar, "MM_ShowMemory: Memory block order currupted!");\r
1391                 }\r
1392                 end = scan->length-1;\r
1393                 y = scan->start/width;\r
1394                 x = scan->start%width;\r
1395                 scaninfo[q].x = x;\r
1396                 scaninfo[q].y = y;\r
1397                 VW_Hlin(x,x+end,y,color,gvar);\r
1398                 VL_Plot(x,y,5,gvar);\r
1399 //++==++==optional                      strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");\r
1400                 for(w=(scan->start)/80;w<=end/80;w++)\r
1401                 {\r
1402 //printf("+     %u      %lu\n", w, scan->length);\r
1403                         strcat(scratch0, "+");\r
1404                 }\r
1405 \r
1406                 if (scan->next && scan->next->start > end+1)\r
1407                 {\r
1408                         VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,3,gvar);    // black = free//now green\r
1409                         strcat(scratch0, AARESET);\r
1410 //++==++==optional                      strcat(scratch0, "\n");\r
1411                         strcat(scratch0,AAGREEN);\r
1412                         for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++)\r
1413                         {\r
1414 //printf("0     %x      %u      %lu\n", scan->next->start, w, scan->length);\r
1415                                 strcat(scratch0,"0");\r
1416                         }\r
1417                         //printf("==================\n");\r
1418                         //printf("w=%u  start=%04x      next=%04x       end=%lu\n", w/80, scan->start, (scan->next->start), end+1);\r
1419                         //printf("==================\n");\r
1420                         strcat(scratch0, "\n");\r
1421                 }\r
1422 #if 0\r
1423                 else {//if(scan->next->start <= scan->start){\r
1424                         scan->next->start=scan->start+0x1000;\r
1425                         strcat(scratch0, AARESET);\r
1426                         strcat(scratch0, "\n");\r
1427                         strcat(scratch0,AAGREEN);\r
1428                         for(w=(end+1);w<=(0x1000/80);w++)\r
1429                         {\r
1430                                 //printf("0     %x      %x      %u\n", scan->start, w);\r
1431                                 strcat(scratch0,"0");\r
1432                         }\r
1433                         printf("================\n");\r
1434                         printf("w=%x    start=%x        next=%x end=%u\n", w, scan->start, (scan->next->start), end+1);\r
1435                         printf("================\n");\r
1436                         getch();\r
1437                 }\r
1438 #endif\r
1439                 strcat(scratch0, AARESET);\r
1440                 //strcat(scratch0,"\n");\r
1441                 strcat(scratch,"Seg:");\r
1442                 ultoa (scan->start,str,16);\r
1443                 strcat (scratch,str);\r
1444 //              strcat(scratch, AABLACK); strcat(scratch,"\t"); strcat(scratch, AARESET);\r
1445                 strcat (scratch,"\tSize:");\r
1446                 ultoa ((unsigned)scan->length,str,10);\r
1447                 strcat (scratch,str);\r
1448 //              strcat(scratch, AABLACK); strcat(scratch,"\t"); strcat(scratch, AARESET);\r
1449                 strcat (scratch,"\tOwner:0x");\r
1450                 owner = (unsigned)scan->useptr;\r
1451                 ultoa (owner,str,16);\r
1452                 strcat (scratch,str);\r
1453                 strcat (scratch,"\n");\r
1454                 write(gvar->handle.debughandle,scratch,strlen(scratch));\r
1455                 write(gvar->handle.debughandle,scratch0,strlen(scratch0));\r
1456 //fprintf(stdout, "%s", scratch);\r
1457 \r
1458                 scan = scan->next;\r
1459                 q++;\r
1460 //if(color!=6) IN_Ack(gvar);\r
1461         }\r
1462 \r
1463         CA_CloseDebug (gvar);\r
1464 \r
1465 #ifdef MMSMPANVID\r
1466         {\r
1467                 int dx,dy,odx,ody;\r
1468                 odx = gvar->video.page[0].dx;\r
1469                 ody = gvar->video.page[0].dy;\r
1470                 dx = dy = 0;\r
1471                 while(!gvar->in.inst->Keyboard[sc_Escape])\r
1472                 {\r
1473                         if(gvar->in.inst->Keyboard[sc_UpArrow])\r
1474                         {\r
1475                                 if(dy>0)\r
1476                                         dy--;\r
1477                         }\r
1478                         else if(gvar->in.inst->Keyboard[sc_DownArrow])\r
1479                         {\r
1480                                 if(dy<gvar->video.page[0].height-gvar->video.page[0].sh)\r
1481                                         dy++;\r
1482                         }\r
1483                         if(gvar->in.inst->Keyboard[sc_LeftArrow])\r
1484                         {\r
1485                                 if(dx>0)\r
1486                                         dx--;\r
1487                         }\r
1488                         else if(gvar->in.inst->Keyboard[sc_RightArrow])\r
1489                         {\r
1490                                 if(dx<gvar->video.page[0].width-gvar->video.page[0].sw)\r
1491                                         dx++;\r
1492                         }\r
1493 \r
1494                         modexPanPage(&gvar->video.page[0], dx, dy);\r
1495                         VL_ShowPage(&gvar->video.page[0], 1, 1);\r
1496                 }\r
1497 \r
1498                 gvar->video.page[0].dx = odx;\r
1499                 gvar->video.page[0].dy = ody;\r
1500         }\r
1501 #endif\r
1502 #ifdef MMSMSCANINFO\r
1503         {\r
1504                 byte scratch1[4];\r
1505                 unsigned                maxq = q;\r
1506                 boolean                 done;\r
1507                 ScanCode                scancode;\r
1508                 int xpos,ypos;\r
1509                 word qq, ccolor = 3;\r
1510                 IN_Ack(gvar);\r
1511 //              VL_ClearVideo (8);\r
1512                 for (qq = 0,done = false;!done;)\r
1513                 {\r
1514                         if(scaninfo[qq].scan->attributes & PURGEBITS)\r
1515                         {\r
1516                                 ccolor = 6;             // dark purple = purgable\r
1517                                 strcpy(scratch1, AAMAGENTA);            // dark purple = purgable\r
1518                                 //printf("%s", AAMAGENTA);\r
1519                         }else{\r
1520                                 ccolor = 2;             // medium blue = non purgable\r
1521                                 strcpy(scratch1, AABLUE);               // medium blue = non purgable\r
1522                                 //printf("%s", AABLUE);\r
1523                         }\r
1524                         if(scaninfo[qq].scan->attributes & LOCKBIT)\r
1525                         {\r
1526                                 ccolor = 1;             // red = locked\r
1527                                 strcpy(scratch1, AARED);                // red = locked\r
1528                                 //printf("%s", AARED);\r
1529                         }\r
1530                         end = scaninfo[qq].scan->length-1;\r
1531 /*typedef struct mmblockstruct{\r
1532         word    start,length;\r
1533         unsigned        attributes;\r
1534         memptr          *useptr;        // pointer to the segment start\r
1535         struct mmblockstruct far *next;\r
1536 } mmblocktype;*/\r
1537                         //modexprint(page, x, y, t, tlsw, color, bgcolor, vidsw, const byte *str);\r
1538 #define MMSMPRINTMEMINFO modexprint(&(gvar->video.page[0]), xpos, ypos, 1, 0, ccolor, 8, gvar->video.VL_Started, global_temp_status_text); ypos+=8;\r
1539                         if(!gvar->video.VL_Started) clrscr(); else\r
1540                         {\r
1541                                 VL_ShowPage(&gvar->video.page[0], 1, 0);\r
1542                                 modexClearRegion(&gvar->video.page[0], 0, 0, gvar->video.page[0].width, gvar->video.page[0].height, 8);\r
1543                         }\r
1544                         sprintf(global_temp_status_text, "block #%04u", qq); MMSMPRINTMEMINFO\r
1545 //                      sprintf(global_temp_status_text, "%Fp", scaninfo[qq].scan->useptr); MMSMPRINTMEMINFO\r
1546                         sprintf(global_temp_status_text, "%04x", (unsigned)scaninfo[qq].scan->useptr); MMSMPRINTMEMINFO\r
1547                         sprintf(global_temp_status_text, "size: %05u", (unsigned)scaninfo[qq].scan->length); MMSMPRINTMEMINFO\r
1548                         if (scaninfo[qq].scan->next && scaninfo[qq].scan->next->start > end+1)\r
1549                         {\r
1550                                 sprintf(global_temp_status_text, "free: %05u", (unsigned)(scaninfo[qq].scan->next->start-scaninfo[qq].scan->start)); MMSMPRINTMEMINFO\r
1551                         }\r
1552                         if(gvar->video.VL_Started)\r
1553                         {\r
1554                                 y = ypos;//scaninfo[qq].scan->start/width;\r
1555                                 x = xpos;//scaninfo[qq].scan->start%width;\r
1556                                 VW_Hlin(x,x+end,y,ccolor,gvar);\r
1557                                 VL_Plot(x,y,5,gvar);\r
1558                         }\r
1559                         else\r
1560                         {\r
1561                                 printf("%s", scratch1);\r
1562                                 printf("%s", AAGREY); printf("_");\r
1563                                 for(w=(scaninfo[qq].scan->start)/80;w<=end/80;w++)\r
1564                                 {\r
1565                                         //strcat(scratch1, "+");\r
1566                                         printf("+");\r
1567                                 }\r
1568                         }\r
1569 \r
1570 \r
1571                                 if (scaninfo[qq].scan->next && scaninfo[qq].scan->next->start > end+1) if(!gvar->video.VL_Started)\r
1572                                 {\r
1573                                         //strcat(scratch1, AARESET);\r
1574                                         printf("%s", AARESET);\r
1575                                         //strcat(scratch1,AAGREEN);\r
1576                                         printf("%s", AAGREEN);\r
1577                                         for(w=(end+1)/80;w<=((scaninfo[qq].scan->next->start-scaninfo[qq].scan->start)/80);w++)\r
1578                                         {\r
1579                                                 //strcat(scratch1,"0");\r
1580                                                 printf("0");\r
1581                                         }\r
1582                                 }else VW_Hlin(x+end+1,x+(scaninfo[qq].scan->next->start-scaninfo[qq].scan->start),y,3,gvar);    // black = free//now green\r
1583 \r
1584 \r
1585                         if(gvar->video.VL_Started)\r
1586                         {\r
1587                                 //if (scan->next && scan->next->start > end+1) free\r
1588                                 xpos = 16;\r
1589                                 ypos = 16;//(gvar->video.page[0].sh-(32));//8*4\r
1590                         }\r
1591                         else\r
1592                         {\r
1593                                 //printf("%s\n", scratch1);\r
1594                                 printf("%s", AARESET);\r
1595                                 printf("\n");\r
1596                         }\r
1597                         while (!(scancode = gvar->in.inst->LastScan)){}\r
1598 \r
1599                         IN_ClearKey(scancode);\r
1600                         switch (scancode)\r
1601                         {\r
1602                                 case sc_LeftArrow:\r
1603                                         if(qq>0) qq--;\r
1604                                         else    qq = maxq;\r
1605                                 break;\r
1606                                 case sc_RightArrow:\r
1607                                         if(qq<maxq) qq++;\r
1608                                         else qq = 0;\r
1609                                 break;\r
1610                                 case sc_Escape:\r
1611                                         done = true;\r
1612                                 break;\r
1613                         }\r
1614                 }\r
1615         }\r
1616 #endif\r
1617 \r
1618         if(gvar->video.VL_Started) IN_Ack(gvar);\r
1619 \r
1620         gvar->video.BOFS = (byte __far *)temp;\r
1621 }\r
1622 \r
1623 //==========================================================================\r
1624 \r
1625 /*\r
1626 =====================\r
1627 =\r
1628 = MM_DumpData\r
1629 =\r
1630 =====================\r
1631 */\r
1632 \r
1633 void MM_DumpData (global_game_variables_t *gvar)\r
1634 {\r
1635         mmblocktype far *scan,far *best;\r
1636         long    lowest,oldlowest;\r
1637         unsigned        owner;\r
1638         char    lock,purge;\r
1639         FILE    *dumpfile;\r
1640 \r
1641 #ifdef __WATCOMC__\r
1642         _nfree(gvar->mm.nearheap);\r
1643 #endif\r
1644 #ifdef __BORLANDC__\r
1645         free(gvar->mm.nearheap);\r
1646 #endif\r
1647 #ifdef __BORLANDC__\r
1648                 dumpfile = fopen ("mmdump.16b","w");\r
1649 #endif\r
1650 #ifdef __WATCOMC__\r
1651                 dumpfile = fopen ("mmdump.16w","w");\r
1652 #endif\r
1653         if (!dumpfile){\r
1654                 printf("MM_DumpData: Couldn't open MMDUMP.16!\n");\r
1655                 return;\r
1656         }\r
1657 \r
1658         lowest = -1;\r
1659         do\r
1660         {\r
1661                 oldlowest = lowest;\r
1662                 lowest = 0xffff;\r
1663 \r
1664                 scan = gvar->mm.mmhead;\r
1665                 while (scan)\r
1666                 {\r
1667                         owner = (unsigned)scan->useptr;\r
1668 \r
1669                         if (owner && owner<lowest && owner > oldlowest)\r
1670                         {\r
1671                                 best = scan;\r
1672                                 lowest = owner;\r
1673                         }\r
1674 \r
1675                         scan = scan->next;\r
1676                 }\r
1677 \r
1678                 if (lowest != 0xffff)\r
1679                 {\r
1680                         if (best->attributes & PURGEBITS)\r
1681                                 purge = 'P';\r
1682                         else\r
1683                                 purge = '-';\r
1684                         if (best->attributes & LOCKBIT)\r
1685                                 lock = 'L';\r
1686                         else\r
1687                                 lock = '-';\r
1688                         fprintf (dumpfile,"0x%p (%c%c) = %u\n"\r
1689                         ,(unsigned)lowest,lock,purge,best->length);\r
1690                 }\r
1691 \r
1692         } while (lowest != 0xffff);\r
1693 \r
1694         fclose(dumpfile);\r
1695         printf("MMDUMP.16 created.\n");\r
1696 }\r
1697 \r
1698 //==========================================================================\r
1699 \r
1700 \r
1701 /*\r
1702 ======================\r
1703 =\r
1704 = MM_UnusedMemory\r
1705 =\r
1706 = Returns the total free space without purging\r
1707 =\r
1708 ======================\r
1709 */\r
1710 \r
1711 dword MM_UnusedMemory (global_game_variables_t *gvar)\r
1712 {\r
1713         unsigned free;\r
1714         mmblocktype far *scan;\r
1715 \r
1716         free = 0;\r
1717         scan = gvar->mm.mmhead;\r
1718 \r
1719         while(scan->next)\r
1720         {\r
1721                 free += scan->next->start - (scan->start + scan->length);\r
1722                 scan = scan->next;\r
1723         }\r
1724 \r
1725         return free*16lu;\r
1726 }\r
1727 \r
1728 //==========================================================================\r
1729 \r
1730 \r
1731 /*\r
1732 ======================\r
1733 =\r
1734 = MM_TotalFree\r
1735 =\r
1736 = Returns the total free space with purging\r
1737 =\r
1738 ======================\r
1739 */\r
1740 \r
1741 dword MM_TotalFree (global_game_variables_t *gvar)\r
1742 {\r
1743         unsigned free;\r
1744         mmblocktype far *scan;\r
1745 \r
1746         free = 0;\r
1747         scan = gvar->mm.mmhead;\r
1748 \r
1749         while(scan->next)\r
1750         {\r
1751                 if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
1752                         free += scan->length;\r
1753                 free += scan->next->start - (scan->start + scan->length);\r
1754                 scan = scan->next;\r
1755         }\r
1756 \r
1757         return free*16lu;\r
1758 }\r
1759 \r
1760 //==========================================================================\r
1761 \r
1762 /*\r
1763 =====================\r
1764 =\r
1765 = MM_Report\r
1766 =\r
1767 =====================\r
1768 */\r
1769 \r
1770 void MM_Report_ (global_game_variables_t *gvar)\r
1771 {\r
1772         printf("========================================\n");\r
1773         printf("                MM_Report_\n");\r
1774         printf("========================================\n");\r
1775         if(MML_CheckForEMS())\r
1776         {\r
1777                 printf("        %cLIMEMS        %u\n", 0xC9, gvar->pm.emm.EMSPresent);\r
1778                 printf("        %c%cEMM v%x.%x available\n", 0xC7, 0xC4, gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);\r
1779                 printf("        %c%ctotalEMSpages:      %u      ", 0xC7, 0xC4, gvar->pm.emm.totalEMSpages); printf("freeEMSpages:       %u\n", gvar->pm.emm.freeEMSpages);\r
1780                 printf("        %c%cEMSPageFrame:       %04x\n", 0xC7, 0xC4, gvar->pm.emm.EMSPageFrame);\r
1781                 printf("        %c%cEMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.EMSmem);\r
1782         }\r
1783         if(MML_CheckForXMS())\r
1784         {\r
1785                 printf("        %cXMS   %u\n", 0xC9, gvar->pm.xmm.XMSPresent);\r
1786                 printf("        %c%cXMS v%x.%x available\n", 0xC7, 0xC4, XMSVer>>8,XMSVer&0x0F);\r
1787                 printf("        %c%cXMSDriver:  %Fp\n", 0xC7, 0xC4, XMSDriver);\r
1788                 printf("        %c%cXMSHandle:  %04x\n", 0xC7, 0xC4, gvar->pm.xmm.XMSHandle);\r
1789                 printf("        %c%cXMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.XMSmem);\r
1790         }\r
1791         printf("        %cConv. %u\n", 0xC9, gvar->pm.mm.MainPresent); DebugMemory_(gvar, 0);\r
1792         //printf("mainmem:      %lu\n", gvar->mmi.mainmem);\r
1793         //printf("Total convmem:        %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem); printf("TotalUsed:   %lu\n", gvar->mmi.mainmem);\r
1794         //printf("                      UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));\r
1795         printf("nearheap:       %lu             ", gvar->mmi.nearheap); printf("farheap:        %lu\n", gvar->mmi.farheap);\r
1796 }\r
1797 \r
1798 //==========================================================================\r
1799 \r
1800 /*\r
1801 =====================\r
1802 =\r
1803 = MM_EMSerr\r
1804 =\r
1805 =====================\r
1806 */\r
1807 \r
1808 void MM_EMSerr(byte *stri, byte err)\r
1809 {\r
1810         //Returns a text string describing the error code in EMS.Error.\r
1811         switch(err)\r
1812         {\r
1813                 case 0x0:\r
1814                         strcat(stri, "successful");\r
1815                 break;\r
1816                 case 0x80:\r
1817                         strcat(stri, "internal error");\r
1818                 break;\r
1819                 case 0x81:\r
1820                         strcat(stri, "hardware malfunction");\r
1821                 break;\r
1822                 case 0x82:\r
1823                         strcat(stri, "busy .. retry later");\r
1824                 break;\r
1825                 case 0x83:\r
1826                         strcat(stri, "invalid handle");\r
1827                 break;\r
1828                 case 0x84:\r
1829                         strcat(stri, "undefined function requested by application");\r
1830                 break;\r
1831                 case 0x85:\r
1832                         strcat(stri, "no more handles available");\r
1833                 break;\r
1834                 case 0x86:\r
1835                         strcat(stri, "error in save or restore of mapping context");\r
1836                 break;\r
1837                 case 0x87:\r
1838                         strcat(stri, "insufficient memory pages in system");\r
1839                 break;\r
1840                 case 0x88:\r
1841                         strcat(stri, "insufficient memory pages available");\r
1842                 break;\r
1843                 case 0x89:\r
1844                         strcat(stri, "zero pages requested");\r
1845                 break;\r
1846                 case 0x8A:\r
1847                         strcat(stri, "invalid logical page number encountered");\r
1848                 break;\r
1849                 case 0x8B:\r
1850                         strcat(stri, "invalid physical page number encountered");\r
1851                 break;\r
1852                 case 0x8C:\r
1853                         strcat(stri, "page-mapping hardware state save area is full");\r
1854                 break;\r
1855                 case 0x8D:\r
1856                         strcat(stri, "save of mapping context failed");\r
1857                 break;\r
1858                 case 0x8E:\r
1859                         strcat(stri, "restore of mapping context failed");\r
1860                 break;\r
1861                 case 0x8F:\r
1862                         strcat(stri, "undefined subfunction");\r
1863                 break;\r
1864                 case 0x90:\r
1865                         strcat(stri, "undefined attribute type");\r
1866                 break;\r
1867                 case 0x91:\r
1868                         strcat(stri, "feature not supported");\r
1869                 break;\r
1870                 case 0x92:\r
1871                         strcat(stri, "successful, but a portion of the source region has been overwritten");\r
1872                 break;\r
1873                 case 0x93:\r
1874                         strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle");\r
1875                 break;\r
1876                 case 0x94:\r
1877                         strcat(stri, "conventional and expanded memory regions overlap");\r
1878                 break;\r
1879                 case 0x95:\r
1880                         strcat(stri, "offset within logical page exceeds size of logical page");\r
1881                 break;\r
1882                 case 0x96:\r
1883                         strcat(stri, "region length exceeds 1 MB");\r
1884                 break;\r
1885                 case 0x97:\r
1886                         strcat(stri, "source and destination EMS regions have same handle and overlap");\r
1887                 break;\r
1888                 case 0x98:\r
1889                         strcat(stri, "memory source or destination type undefined");\r
1890                 break;\r
1891                 case 0x9A:\r
1892                         strcat(stri, "specified alternate map register or DMA register set not supported");\r
1893                 break;\r
1894                 case 0x9B:\r
1895                         strcat(stri, "all alternate map register or DMA register sets currently allocated");\r
1896                 break;\r
1897                 case 0x9C:\r
1898                         strcat(stri, "alternate map register or DMA register sets not supported");\r
1899                 break;\r
1900                 case 0x9D:\r
1901                         strcat(stri, "undefined or unallocated alternate map register or DMA register set");\r
1902                 break;\r
1903                 case 0x9E:\r
1904                         strcat(stri, "dedicated DMA channels not supported");\r
1905                 break;\r
1906                 case 0x9F:\r
1907                         strcat(stri, "specified dedicated DMA channel not supported");\r
1908                 break;\r
1909                 case 0xA0:\r
1910                         strcat(stri, "no such handle name");\r
1911                 break;\r
1912                 case 0xA1:\r
1913                         strcat(stri, "a handle found had no name, or duplicate handle name");\r
1914                 break;\r
1915                 case 0xA2:\r
1916                         strcat(stri, "attempted to wrap around 1M conventional address space");\r
1917                 break;\r
1918                 case 0xA3:\r
1919                         strcat(stri, "source array corrupted");\r
1920                 break;\r
1921                 case 0xA4:\r
1922                         strcat(stri, "operating system denied access");\r
1923                 break;\r
1924                 default:\r
1925                         strcat(stri, "undefined error");\r
1926         }\r
1927 }\r
1928 \r
1929 //==========================================================================\r
1930 \r
1931 /*\r
1932 =====================\r
1933 =\r
1934 = MM_BombOnError\r
1935 =\r
1936 =====================\r
1937 */\r
1938 \r
1939 void MM_BombOnError (boolean bomb, global_game_variables_t *gvar)\r
1940 {\r
1941         gvar->mm.bombonerror = bomb;\r
1942 }\r
1943 \r
1944 #if 0\r
1945 void MM_GetNewBlock(global_game_variables_t *gvar)\r
1946 {\r
1947         if(!gvar->mm.mmfree)\r
1948                 MML_ClearBlock(gvar);\r
1949         gvar->mm.mmnew=gvar->mm.mmfree;\r
1950         gvar->mm.mmfree=gvar->mm.mmfree->next;\r
1951         if(!(gvar->mm.mmnew=gvar->mm.mmfree))\r
1952         {\r
1953                 printf("MM_GETNEWBLOCK: No free blocks!\n");\r
1954                 return;\r
1955         }\r
1956         gvar->mm.mmfree=gvar->mm.mmfree->next;\r
1957 }\r
1958 \r
1959 void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)\r
1960 {\r
1961         x->useptr=NULL;\r
1962         x->next=gvar->mm.mmfree;\r
1963         gvar->mm.mmfree=x;\r
1964 }\r
1965 #endif\r
1966 \r
1967 void xms_call(byte v, global_game_variables_t *gvar)\r
1968 {\r
1969         dword XMSDriver = gvar->pm.xmm.XMSDriver;\r
1970         __asm {\r
1971                 mov     ah,[v]\r
1972                 call [DWORD PTR XMSDriver]\r
1973         }\r
1974 }\r
1975 \r
1976 /*void MM_seguin(void)\r
1977 {\r
1978         __asm {\r
1979                 push    ds\r
1980                 mov     ax,ds\r
1981                 inc             ax\r
1982                 mov     ds,ax\r
1983         }\r
1984 }\r
1985 \r
1986 void MM_segude(void)\r
1987 {\r
1988         __asm {\r
1989                 pop ds\r
1990         }\r
1991 }*/\r
1992 \r
1993 /*\r
1994 pull data from far and put it into ds var\r
1995 mov ax,es:si\r
1996 mov x,ax\r
1997 */\r
1998 /*\r
1999 ss stack segment\r
2000 sp top of stack\r
2001 bp bottem of stack\r
2002 */\r