1 /*---------------------------------------------------------------------*
2 Project:  tc library
3 File:     TCMem.c
4 
5 Copyright 1998-2001 Nintendo.  All rights reserved.
6 
7 These coded instructions, statements and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law.  They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12 
13 Change History:
14 
15  $Log: TCMem.cpp,v $
16  Revision 1.1  2006/02/17 09:01:53  mitu
17  1st version
18 
19 
20     3    4/11/01 3:08p John
21     Updated header copyrights and pathname.
22 
23     2     3/17/00 1:19p Mikepc
24     change tc to use indices numbered from 0.
25 
26     1     12/03/99 3:45p Ryan
27 
28     7     10/13/99 12:35p Mikepc
29     removed unused local var. from mFreeMem.
30 
31     6     10/08/99 2:45p Mikepc
32     update for tplConv portability: altered data structures, replaced
33     references to 'read tga code' with ' *fileFn, removed redundant
34     functions.  Changed some file conversion paths.
35 
36     5     9/02/99 11:12a Mikepc
37     some code re-organization between files.
38     added code (verify.cpp) to invoke s3tc.exe from within tc program.
39     changed some routines to accommodate the new texture creation path.
40 
41     4     8/26/99 4:59p Mikepc
42     renamed file extensions from .c to .cpp.
43     .cpp extension allows addition of namespace protection to remove
44     potential name collisions with tool code.  Exceptions are CreateTplFile
45     and QuickConvert.  These are extern "C" linked.
46 
47     3     8/26/99 11:38a Mikepc
48 
49     2     8/26/99 11:03a Mikepc
50     tplCon rewrite for efficient memory usage, batch file processing
51     ability.
52 
53  $NoKeywords: $
54 
55 -----------------------------------------------------------------------*/
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 
60 #include <charPipeline/tc/TCCommon.h>
61 
62 #include "TCMem.h"
63 #include "TCImageList.h"
64 #include "TCPaletteList.h"
65 #include "TCSrcImageList.h"
66 #include "TCTextureList.h"
67 #include "TCFileInternal.h"
68 
69 /********************************/
70 typedef struct TCMemNode
71 {
72 	void*  mem;
73 	u32    size;
74 
75 	struct TCMemNode* prev;
76 	struct TCMemNode* next;
77 
78 }TCMemNode, *TCMemNodePtr;
79 
80 /********************************/
81 // debugging- compare app. allocated memory to freed memory
82 // including memory allocated to 'MemNodes'
83 u32 TotalAlloc = 0;
84 u32 TotalFreed = 0;
85 
86 // allocated memory linked list
87 TCMemNode* MemList = NULL;
88 
89 /*>*******************************(*)*******************************<*/
90 static TCMemNode* TCNewMemNode	( void );
91 static void       TCFreeMemNode	( TCMemNode** thisNode );
92 
93 /*>*******************************(*)*******************************<*/
TCNewMemNode(void)94 static TCMemNode* TCNewMemNode ( void )
95 {
96 	TCMemNode* newM, *thisM;
97 
98 
99 	// use stdlib calloc
100 	if( (newM = (TCMemNode*)calloc( 1,sizeof(TCMemNode))) == NULL )
101 	{
102 		TCErrorMsg( "TCNewMemNode: couldn't allocate new TCMemNode\n" );
103 		return NULL;
104 	}
105 
106 
107 	if( MemList == NULL )
108 	{
109 		MemList    = newM;
110 		newM->prev = NULL;
111 		newM->next = NULL;
112 		return newM;
113 	}
114 	else if( MemList->next == NULL )
115 	{
116 		MemList->next = newM;
117 		newM->prev    = MemList;
118 		newM->next    = NULL;
119 		return newM;
120 	}
121 	else
122 	{
123 		thisM = MemList;
124 		while( thisM->next )
125 		{
126 			thisM = thisM->next;
127 		}
128 
129 		thisM->next = newM;
130 		newM->prev  = thisM;
131 		newM->next  = NULL;
132 		return newM;
133 	}
134 
135 	return newM;
136 }
137 
138 /*>*******************************(*)*******************************<*/
139 // free a node from within the list
140 /*>*******************************(*)*******************************<*/
TCFreeMemNode(TCMemNode ** thisNode)141 static void TCFreeMemNode ( TCMemNode** thisNode )
142 {
143 	TCMemNode* checkNode = NULL;
144 	u32        found     =    0;
145 
146 
147 	if( *thisNode == NULL )
148 	{
149 		TCErrorMsg( "TCFreeMemNode: tried to free a NULL TCMemNode\n" );
150 		return;
151 	}
152 
153 
154 	// ensure that *thisNode is part of the main memory list
155 	// this also guards against an empty list
156 	checkNode = MemList;
157 	while( checkNode )
158 	{
159 		if( checkNode == *thisNode )
160 		{
161 			found = 1;
162 			break;
163 		}
164 
165 		checkNode = checkNode->next;
166 	}
167 
168 	// couldn't find *thisNode
169 	TCAssertMsg( (found), "TCFreeMemNode: *thisNode is not part of MemList\n" );
170 
171 
172 	// free node data first
173 
174 	// stdlib free
175 	if( (*thisNode)->mem != NULL )
176 	{
177 		free( (*thisNode)->mem );
178 		(*thisNode)->mem = NULL;
179 
180 		TotalFreed += (*thisNode)->size;
181 	}
182 	(*thisNode)->size = 0;
183 
184 
185 	//------------------------
186 
187 	// remove the node from the linked list
188 
189 	if( *thisNode == MemList )          // head
190 	{
191 		if( (*thisNode)->next == NULL ) // single node list
192 		{
193 			(*thisNode)->prev = NULL;
194 			(*thisNode)->next = NULL;
195 			MemList           = NULL;
196 		}
197 		else                            // multi-node list
198 		{
199             MemList = (*thisNode)->next;
200 
201             (*thisNode)->next->prev = NULL;
202 			(*thisNode)->prev       = NULL;
203 			(*thisNode)->next       = NULL;
204 		}
205 	}
206 	else
207 	{
208 		if( (*thisNode)->next == NULL ) // tail
209 		{
210 			(*thisNode)->prev->next = NULL;
211             (*thisNode)->next       = NULL;
212 		    (*thisNode)->prev       = NULL;
213 		}
214 		else                           // middle of list
215 		{
216 			(*thisNode)->prev->next = (*thisNode)->next;
217 			(*thisNode)->next->prev = (*thisNode)->prev;
218             (*thisNode)->next       = NULL;
219 		    (*thisNode)->prev       = NULL;
220 		}
221 
222 	}
223 
224 	//-----------------------
225 
226 	// free thisNode's memory
227 	free( *thisNode );
228     TotalFreed += sizeof(TCMemNode);
229 	*thisNode   = NULL;
230 
231 }
232 
233 /*>*******************************(*)*******************************<*/
TCMalloc(u32 size)234 void* TCMalloc ( u32 size )
235 {
236 	TCMemNode* newM;
237 
238 
239 	newM = TCNewMemNode();
240 
241     if( size == 15 )
242     {
243         printf("found mem" );
244     }
245 
246 	if( (newM->mem = (void*)malloc(size)) == NULL )
247 	{
248 		TCErrorMsg("TCMalloc: couldn't allocate block of size %d\n", size );
249 		return NULL;
250 	}
251 
252 	newM->size = size;
253 
254 	TotalAlloc += ( size + sizeof(TCMemNode) );
255 
256 	return newM->mem;
257 }
258 
259 /*>*******************************(*)*******************************<*/
TCCalloc(u32 num,u32 size)260 void* TCCalloc ( u32 num, u32 size )
261 {
262 	TCMemNode* newM;
263 	u32 total;
264 
265 
266 	newM  = TCNewMemNode();
267 
268 	total = num * size;
269 
270     if( total == 15 )
271     {
272         printf("found mem" );
273     }
274 
275 	// use stdlib calloc
276 	if( (newM->mem = (void*)calloc(num, size)) == 0 )
277 	{
278 		TCErrorMsg("TCCalloc: couldn't allocate block of size %d\n", total );
279 		return 0;
280 	}
281 
282 	newM->size = total;
283 
284 	TotalAlloc += ( total + sizeof(TCMemNode) );
285 
286 	return newM->mem;
287 }
288 
289 /*>*******************************(*)*******************************<*/
TCFree(void ** vPtr)290 void TCFree ( void** vPtr )
291 {
292 	TCMemNode* thisNode;
293 
294 
295 	if( *vPtr == NULL )
296 	{
297 		return;
298 	}
299 
300 	thisNode = MemList;
301 	while( thisNode != NULL )
302 	{
303 		if( thisNode->mem != NULL )
304 		{
305 			if( thisNode->mem == *vPtr )
306 			{
307 				TCFreeMemNode( &thisNode );
308 				*vPtr = NULL;
309 				return;
310 			}
311 		}
312 
313 		thisNode = thisNode->next;
314 	}
315 
316 	return;
317 }
318 
319 /*>*******************************(*)*******************************<*/
TCFreeMem(void)320 void TCFreeMem ( void )
321 {
322 	TCMemNode* thisNode, *nextNode;
323 
324 
325 	// free all remaining allocated memory blocks
326 	thisNode = MemList;
327 	while( thisNode != NULL )
328 	{
329 		nextNode = thisNode->next;
330 
331 		TCFreeMemNode( &thisNode );
332 
333 		thisNode = nextNode;
334 	}
335 	MemList = NULL;
336 
337 	// reset all global pointers to NULL
338 	SiHead = NULL;
339 	ImHead = NULL;
340 	PlHead = NULL;
341 	TxHead = NULL;
342 
343 	// file cache
344 	DFSize = 0;
345 	DF     = NULL;
346 
347 	// file table
348 	FileTable = NULL;
349 
350 	// set the path pointers for txtFile keys to NULL
351 	*PathName = '\0';
352 	 PathPtr  = NULL;
353 
354 
355 	 // debugging info.
356 	printf("\n");
357 	printf( "total alloc: %d\n", TotalAlloc );
358 	printf( "total freed: %d\n", TotalFreed );
359 }
360 
361 /*>*******************************(*)*******************************<*/
362