CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

ALLOC.CPP (20263B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /***************************************************************************
     17  **   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **
     18  ***************************************************************************
     19  *                                                                         *
     20  *                 Project Name : Westwood Library                         *
     21  *                                                                         *
     22  *                    File Name : ALLOC.CPP                                *
     23  *                                                                         *
     24  *                   Programmer : Joe L. Bostic                            *
     25  *                                                                         *
     26  *                   Start Date : February 1, 1992                         *
     27  *                                                                         *
     28  *                  Last Update : March 9, 1995 [JLB]                      *
     29  *                                                                         *
     30  *-------------------------------------------------------------------------*
     31  * Functions:                                                              *
     32  *   Alloc -- Allocates system RAM.                                        *
     33  *   Ram_Free -- Determines the largest free chunk of RAM.                 *
     34  *   Free -- Free an Alloc'ed block of RAM.                                *
     35  *   Resize_Alloc -- Change the size of an allocated block.                *
     36  *   Heap_Size -- Size of the heap we have.                                *
     37  *   Total_Ram_Free -- Total amount of free RAM.                           *
     38  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     39 
     40 #include <malloc.h>
     41 #include <string.h>
     42 #include <stdlib.h>
     43 //#include <dos.h>
     44 //#include <bios.h>
     45 
     46 
     47 #ifndef WWMEM_H
     48 #include "wwmem.h"
     49 #endif
     50 
     51 
     52 extern "C" unsigned long Largest_Mem_Block ( void ) ;
     53 
     54 /*
     55 ** Define the equates necessary to call a DPMI interrupt.
     56 */
     57 #define	DPMI_INT									0x0031
     58 #define	DPMI_LOCK_MEM							0x0600
     59 #define	DPMI_UNLOCK_MEM						0x0601
     60 
     61 /*=========================================================================*/
     62 /* The following PRIVATE functions are in this file:                       */
     63 /*=========================================================================*/
     64 
     65 
     66 /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
     67 
     68 unsigned long MinRam=0L;		// Record of least memory at worst case.
     69 unsigned long MaxRam=0L;		// Record of total allocated at worst case.
     70 static unsigned long TotalRam = 0L;
     71 static unsigned long Memory_Calls = 0L;
     72 
     73 void (*Memory_Error)(void) = NULL;
     74 extern void (*Memory_Error_Exit)(char *string)=NULL;
     75 
     76 
     77 //#define MEM_CHECK
     78 
     79 #ifdef MEM_CHECK
     80 extern "C"{
     81 	extern void __cdecl Int3(void);
     82 }
     83 #endif	//MEM_CHECK
     84 
     85 /***************************************************************************
     86  * DPMI_LOCK -- handles locking a block of DPMI memory                     *
     87  *                                                                         *
     88  * INPUT:                                                                  *
     89  *                                                                         *
     90  * OUTPUT:                                                                 *
     91  *                                                                         *
     92  * WARNINGS:                                                               *
     93  *                                                                         *
     94  * HISTORY:                                                                *
     95  *   06/23/1995 PWG : Created.                                             *
     96  *=========================================================================*/
     97 #include"mono.h"
     98 void DPMI_Lock(VOID const *, long const )
     99 {
    100 }
    101 
    102 /***************************************************************************
    103  * DPMI_UNLOCK -- Handles unlocking a locked block of DPMI                 *
    104  *                                                                         *
    105  * INPUT:                                                                  *
    106  *                                                                         *
    107  * OUTPUT:                                                                 *
    108  *                                                                         *
    109  * WARNINGS:                                                               *
    110  *                                                                         *
    111  * HISTORY:                                                                *
    112  *   06/23/1995 PWG : Created.                                             *
    113  *=========================================================================*/
    114 void DPMI_Unlock(void const *, long const )
    115 {
    116 }
    117 
    118 /***************************************************************************
    119  * Alloc -- Allocates system RAM.                                          *
    120  *                                                                         *
    121  *    This is the basic RAM allocation function.  It is used for all       *
    122  *    memory allocations needed by the system or the main program.         *
    123  *                                                                         *
    124  * INPUT:   bytes_to_alloc -- LONG value of the number of bytes to alloc.  *
    125  *                                                                         *
    126  *          flags          -- Memory allocation control flags.             *
    127  *             MEM_NORMAL: No special flags.                               *
    128  *             MEM_CLEAR:  Zero out memory block.                        	*
    129  *             MEM_NEW:		Called by a new.                                *
    130  *                                                                         *
    131  * OUTPUT:  Returns with pointer to allocated block.  If NULL was returned *
    132  *          it indicates a failure to allocate.  Note: NULL will never be  *
    133  *          returned if the standard library allocation error routine is   *
    134  *          used.                                                          *
    135  *                                                                         *
    136  * WARNINGS:   If you replace the standard memory allocation error routine *
    137  *             and make it so that Alloc CAN return with a NULL, be sure   *
    138  *             and check for this in your code.                            *
    139  *                                                                         *
    140  * HISTORY:                                                                *
    141  *   09/03/1991 JLB : Documented.                                          *
    142  *   08/09/1993 JLB : Updated with EMS memory support.                     *
    143  *   04/28/1994 JAW : Updated to 32bit Protected mode.                     *
    144  *   03/09/1995 JLB : Fixed                                                *
    145  *   09/28/1995 ST  : Simplified for win95                                                                      *
    146  *=========================================================================*/
    147 void *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)
    148 {
    149 
    150 #ifdef WIN32
    151 
    152 	void	*mem_ptr;
    153 
    154 #ifdef MEM_CHECK
    155 	bytes_to_alloc += 32;
    156 #endif	//MEM_CHECK
    157 
    158 	mem_ptr = malloc ( bytes_to_alloc );
    159 
    160 	if ( !mem_ptr && Memory_Error ){
    161 		Memory_Error();
    162 	}
    163 
    164 	if ( mem_ptr && ( flags & MEM_CLEAR ) ){
    165 		memset ( mem_ptr , 0 , bytes_to_alloc );
    166 	}
    167 
    168 #ifdef MEM_CHECK
    169 	mem_ptr = (void*)((char*)mem_ptr + 16);
    170 	unsigned long *magic_ptr =(unsigned long*) ( ((char *)mem_ptr) - 16 );
    171 	*magic_ptr++ = (unsigned long)mem_ptr;
    172 	*magic_ptr++ = (unsigned long)mem_ptr;
    173 	*magic_ptr++ = (unsigned long)mem_ptr;
    174 	*magic_ptr 	 = bytes_to_alloc - 32;
    175 	magic_ptr = (unsigned long*) ( ((char*)mem_ptr) + bytes_to_alloc - 32 );
    176 	*magic_ptr++ = (unsigned long)mem_ptr;
    177 	*magic_ptr++ = (unsigned long)mem_ptr;
    178 	*magic_ptr++ = (unsigned long)mem_ptr;
    179 	*magic_ptr 	 = (unsigned long)mem_ptr;
    180 #endif	//MEM_CHECK
    181 
    182 	Memory_Calls++;
    183 	return ( mem_ptr );
    184 
    185 #else
    186 
    187 
    188 
    189 	union REGS		regs ;
    190 	struct SREGS 	sregs ;
    191 	unsigned char *retval=NULL;	// Pointer to allocated block.
    192 	unsigned long	original_size;	// Original allocation size.
    193 	unsigned long	bytesfree;		// Number of free bytes.
    194 	long 				*longptr=NULL;	// Pointer used to store selector
    195 
    196 	/*
    197 	** Save the original allocated space size so that we can clear the
    198 	** exact amount of RAM if they specified MEM_CLEAR.
    199 	*/
    200 	original_size = bytes_to_alloc;
    201 
    202 	/*
    203 	** Reserve one byte for the header of the memory we allocated.
    204 	** We will store the flags variable there for later use.
    205 	*/
    206 	bytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;
    207 
    208 	/*
    209 	**	Initialize the total ram available value.
    210 	*/
    211 	if (!TotalRam) {
    212 		TotalRam = Total_Ram_Free(MEM_NORMAL);
    213 	}
    214 
    215 
    216 	// Try to allocate the memory out of the protected mode memory
    217 	// chain if we did not require a real mode allocation.  If this
    218 	// fails we will have to try to allocate it out of real mode memory.
    219 	// Real mode memory is a last resort because some types of applications
    220 	// require real mode memory.
    221 	if (!(flags & MEM_REAL)) {
    222 		retval = (unsigned char*)malloc(bytes_to_alloc);
    223 	}
    224 
    225 	// Try to allocate the memory out of the real mode memory using DPMI
    226 	// service 0x100.  Note that retval will be null if we are requesting
    227 	// real mode memory so that we do not have to explicitly check for the
    228 	// real mode flag.  Remember we need to reserve room for the dos
    229 	// selector value at the beginning of our allocated block so rather than
    230 	// adding fifteen and rounding, we need to add 19 and round.
    231 	if (!retval) {
    232 		flags = (MemoryFlagType)(flags | MEM_REAL);
    233 		regs.x.eax = 0x100;
    234 		regs.x.ebx = (bytes_to_alloc + 19) >> 4;
    235 		if (regs.x.ebx & 0xFFFF0000) {
    236 			retval = NULL;
    237 		} else {
    238 			segread ( & sregs ) ;
    239 			int386x ( 0x31 , & regs, & regs , & sregs	) ;
    240 			if (regs.x.cflag)
    241 				retval = NULL;
    242 			else {
    243 				longptr		= (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);
    244 				*longptr++	= regs.x.edx & 0xFFFF;
    245 				retval		= (unsigned char *)longptr;
    246 			}
    247 		}
    248 	}
    249 
    250 	// If the alloc failed then we need to signify a memory error.
    251 	if (retval == NULL) {
    252 		if(Memory_Error != NULL)
    253 			Memory_Error();
    254 		return NULL;
    255 	}
    256 
    257 	// If the memory needs to be DPMI locked then we should store the
    258 	// original size in the header before we store the flags.
    259 	if (flags & MEM_LOCK) {
    260 		longptr		= (long *)retval;
    261 		*longptr++	= original_size;
    262 		retval		= (unsigned char *)longptr;
    263 	}
    264 
    265 
    266 	// Now that we know the alloc was sucessful (and for an extra byte
    267 	// more than the user wanted) we need to stick in the memory flags.
    268 	*retval++ 		= flags;
    269 
    270 	// If the memory needed to be DPMI locked then set it up so it
    271 	// is locked.
    272 	if (flags & MEM_LOCK) {
    273 		DPMI_Lock(retval, original_size);
    274 
    275 	}
    276 
    277 
    278 	/* Clear the space if they wanted it clear */
    279 
    280 	if (flags & MEM_CLEAR) {
    281 		unsigned char	*ptr;		// Working memory block pointer.
    282 
    283 		ptr = retval;
    284 		memset(ptr, '\0', original_size);
    285 	}
    286 
    287 	bytesfree = Total_Ram_Free(MEM_NORMAL);
    288 	if (bytesfree < MinRam) {
    289 		MinRam = bytesfree;
    290 	}
    291 	if (TotalRam-bytesfree > MaxRam) {
    292 		MaxRam = TotalRam-bytesfree;
    293 	}
    294 
    295 	Memory_Calls++;
    296 
    297 	return(retval);
    298 
    299 #endif
    300 }
    301 
    302 
    303 /***************************************************************************
    304  * Free -- Free an Alloc'ed block of RAM.                                  *
    305  *                                                                         *
    306  * FUNCTION:                                                               *
    307  *                                                                         *
    308  * INPUT:       A pointer to a block of RAM from Alloc.                    *
    309  *                                                                         *
    310  * OUTPUT:      None.                                                      *
    311  *                                                                         *
    312  * WARNINGS:    Don't use this for an Alloc_Block'ed RAM block.            *
    313  *                                                                         *
    314  * HISTORY:                                                                *
    315  *   05/25/1990     : Created.                                             *
    316  ***************************************************************************/
    317 #ifdef WIN32
    318 
    319 void Free(void const *pointer)
    320 {
    321 
    322 	if ( pointer ){
    323 
    324 #ifdef MEM_CHECK
    325 
    326 		unsigned long	*magic_ptr = (unsigned long*) ( ((char*)pointer) - 16 );
    327 
    328 		if (*magic_ptr++ != (unsigned long)pointer ||
    329 		 	*magic_ptr++ != (unsigned long)pointer ||
    330 		 	*magic_ptr++ != (unsigned long)pointer ){
    331 		 	Int3();
    332 		}
    333 
    334 		magic_ptr = (unsigned long*) ( ((char*)pointer) + *magic_ptr );
    335 
    336 		if (*magic_ptr++ != (unsigned long)pointer ||
    337 		 	*magic_ptr++ != (unsigned long)pointer ||
    338 		 	*magic_ptr++ != (unsigned long)pointer ||
    339 		 	*magic_ptr++ != (unsigned long)pointer ){
    340 		 	Int3();
    341 		}
    342 
    343 		pointer = (void*) (((char*)pointer)-16);
    344 #endif	//MEM_CHECK
    345 
    346 		free ( (void*)pointer );
    347 		Memory_Calls--;
    348 	}
    349 
    350 #else
    351 
    352 void Free(void const *pointer)
    353 {
    354 
    355 	union REGS		regs ;
    356 	struct SREGS 	sregs ;
    357 
    358 
    359 	if (pointer) {
    360 		/*
    361 		** Get a pointer to the flags that we stored off.
    362 		*/
    363 		char *byteptr	= ((char *)pointer) - 1;
    364 
    365 		/*
    366 		** Check to see if this was locked me and if it was unlock it.
    367 		*/
    368 		if (*byteptr & MEM_LOCK) {
    369 			long *longptr = ((long *)byteptr) - 1;
    370 			DPMI_Unlock(pointer, *longptr);
    371 			pointer = (void *)longptr;
    372 		} else
    373 			pointer = (void *)byteptr;
    374 
    375 
    376 		// If the pointer is a real mode pointer than it will point to the
    377 		// first megabyte of system memory.  If it does than we need to
    378 		// use DPMI to free it.
    379 		if (*byteptr & MEM_REAL) {
    380 			regs.x.eax	= 0x101;
    381 			regs.x.edx	= *(((long *)pointer) - 1);
    382 			segread ( & sregs ) ;
    383 			int386x(0x31, &regs, &regs, &sregs);
    384 		} else {
    385 			free((void *)pointer);
    386 		}
    387 		Memory_Calls--;
    388 	}
    389 
    390 #endif
    391 }
    392 
    393 
    394 
    395 /***************************************************************************
    396  * Resize_Alloc -- Change the size of an allocated block.                  *
    397  *                                                                         *
    398  *    This routine will take a previously allocated block and change its   *
    399  *    size without unnecessarily altering its contents.                    *
    400  *                                                                         *
    401  * INPUT:   pointer  -- Pointer to the original memory allocation.         *
    402  *                                                                         *
    403  *          new_size -- Size in bytes that it will be converted to.        *
    404  *                                                                         *
    405  * OUTPUT:  Returns with a pointer to the new allocation.                  *
    406  *                                                                         *
    407  * WARNINGS:   ???                                                         *
    408  *                                                                         *
    409  * HISTORY:                                                                *
    410  *   02/01/1992 JLB : Commented.                                           *
    411  *=========================================================================*/
    412 void *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)
    413 {
    414 
    415 	unsigned long *temp;
    416 
    417 	temp = (unsigned long*)original_ptr;
    418 
    419 	/* ReAlloc the space */
    420 	temp = (unsigned long *)realloc(temp, new_size_in_bytes);
    421 	if (temp == NULL) {
    422 		if(Memory_Error != NULL)
    423 			Memory_Error();
    424 		return NULL;
    425 	}
    426 
    427 	return(temp);
    428 }
    429 
    430 
    431 /***************************************************************************
    432  * Ram_Free -- Determines the largest free chunk of RAM.                   *
    433  *                                                                         *
    434  *    Use this routine to determine the largest free chunk of available    *
    435  *    RAM for allocation.  It also performs a check of the memory chain.   *
    436  *                                                                         *
    437  * INPUT:   none                                                           *
    438  *                                                                         *
    439  * OUTPUT:  Returns with the size of the largest free chunk of RAM.        *
    440  *                                                                         *
    441  * WARNINGS:   This does not return the TOTAL memory free, only the        *
    442  *             largest free chunk.                                         *
    443  *                                                                         *
    444  * HISTORY:                                                                *
    445  *   09/03/1991 JLB : Commented.                                           *
    446  *=========================================================================*/
    447 long Ram_Free(MemoryFlagType)
    448 {
    449 //	return(_memmax());
    450 #if(0)
    451 	MEMORYSTATUS	mem_info;
    452 	mem_info.dwLength=sizeof(mem_info);
    453 	GlobalMemoryStatus(&mem_info);
    454 	return ( mem_info.dwAvailPhys );
    455 #endif
    456 	return ( 64*1024*1024 );
    457 }
    458 
    459 
    460 /***************************************************************************
    461  * Heap_Size -- Size of the heap we have.                                  *
    462  *                                                                         *
    463  *                                                                         *
    464  *                                                                         *
    465  * INPUT:                                                                  *
    466  *                                                                         *
    467  * OUTPUT:                                                                 *
    468  *                                                                         *
    469  * WARNINGS:                                                               *
    470  *                                                                         *
    471  * HISTORY:                                                                *
    472  *   06/21/1994 SKB : Created.                                             *
    473  *=========================================================================*/
    474 long Heap_Size(MemoryFlagType )
    475 {
    476 	if (!TotalRam) {
    477 		TotalRam = Total_Ram_Free(MEM_NORMAL);
    478 	}
    479 	return(TotalRam);
    480 }
    481 
    482 
    483 /***************************************************************************
    484  * Total_Ram_Free -- Total amount of free RAM.                             *
    485  *                                                                         *
    486  *                                                                         *
    487  *                                                                         *
    488  * INPUT:                                                                  *
    489  *                                                                         *
    490  * OUTPUT:                                                                 *
    491  *                                                                         *
    492  * WARNINGS:                                                               *
    493  *                                                                         *
    494  * HISTORY:                                                                *
    495  *   06/21/1994 SKB : Created.                                             *
    496  *   03/09/1995 JLB : Uses prerecorded heap size maximum.                  *
    497  *=========================================================================*/
    498 long Total_Ram_Free(MemoryFlagType )
    499 {
    500 #if(0)
    501 	MEMORYSTATUS	mem_info;
    502 	mem_info.dwLength=sizeof(mem_info);
    503 	GlobalMemoryStatus(&mem_info);
    504 	return ( mem_info.dwAvailPhys );
    505 #endif
    506 
    507 	return ( 64*1024*1024 );
    508 }
    509