00001 #include "flGlobal.h"
00002
00003 #if FL_MEMORY_VMEM != 0
00004 #include <string.h>
00005 #include <stdio.h>
00006 #include <pspkernel.h>
00007
00008 #if FL_INCLUDE_ALL_C == 0
00009 #include "flMemory.h"
00010
00011 #if FL_DEBUG != 0
00012 #include "flDebug.h"
00013 #endif
00014 #endif
00015
00016 u32 vmemStart = MEMORY_VMEM_BASE;
00017 u32 vmemSize = MEMORY_VMEM_SIZE;
00018 u32* vmemBlockTable = NULL;
00019 u32 vmemBlocks = 0;
00020 u32 vmemFreeBlocks = 0;
00021 bool vmemInitialized = false;
00022
00023 #if FL_MEMORY_VMEM_CACHE
00024 void* vmemCache = (void*)((MEMORY_VMEM_BASE + MEMORY_VMEM_SIZE) - FL_MEMORY_VMEM_CACHE);
00025 #endif
00026
00027 VmemStrideBlock* vmemStrideBlocks = NULL;
00028
00029 void vmemInit() {
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 if(vmemInitialized) {
00042 #if FL_DEBUG_WARNING != 0
00043 debugWarning("Trying to initialize vram, but it is already initialized.");
00044 #endif
00045 return;
00046 }
00047
00048 #if FL_MEMORY_VMEM_CACHE
00049 vmemCache = (void*)memUncachedPtr(vmemAbsolutePtr(vmemAllocBuffer(FL_MEMORY_VMEM_CACHE, 1, 8, 0)));
00050 sceKernelDcacheWritebackInvalidateRange(vmemCache, FL_MEMORY_VMEM_CACHE);
00051 #endif
00052
00053 while(vmemStart & (FL_MEMORY_VMEM_BLOCKSIZE - 1)) {
00054 vmemStart++;
00055 vmemSize--;
00056 }
00057
00058 vmemBlocks = (vmemSize / FL_MEMORY_VMEM_BLOCKSIZE);
00059 vmemBlockTable = memAlloc(vmemBlocks << 2);
00060 vmemFreeBlocks = vmemBlocks;
00061
00062 vmemBlockTable[0] = (vmemBlocks & 0x00FFFFFF);
00063
00064 vmemInitialized = true;
00065 }
00066
00067 void vmemTerm() {
00068 if(!vmemInitialized) {
00069 #if FL_DEBUG_WARNING != 0
00070 debugWarning("Trying to de-initialize vram, but it is not initialized.");
00071 #endif
00072 return;
00073 }
00074 vmemInitialized = false;
00075 memFree(vmemBlockTable);
00076 vmemBlocks = 0;
00077 vmemSize = MEMORY_VMEM_SIZE;
00078 vmemStart = MEMORY_VMEM_BASE;
00079 vmemStrideBlockDelRecursive(vmemStrideBlocks);
00080 }
00081
00082 void* vmemNormalPtr(void* inPtr) {
00083 inPtr = memCachedPtr(inPtr);
00084
00085
00086
00087
00088
00089
00090 if(((u32)inPtr < MEMORY_VMEM_BASE) || ((u32)inPtr >= (MEMORY_VMEM_BASE + (MEMORY_VMEM_SIZE << 2))))
00091 return NULL;
00092 while((u32)inPtr >= (MEMORY_VMEM_BASE + MEMORY_VMEM_SIZE))
00093 inPtr = (void*)((u32)inPtr - MEMORY_VMEM_SIZE);
00094 return inPtr;
00095 }
00096
00097 void* vmemAllocBuffer(u32 inWidth, u32 inHeight, u8 inBitDepth, u32 inStride) {
00098 void* tempOut;
00099 if(vmemInitialized) {
00100 #if FL_DEBUG_DEVWARNING != 0
00101 debugDevWarning("Allocating buffers after vmem is initialized is bad practice.");
00102 #endif
00103 tempOut = vmemAlloc((inWidth * inHeight * inBitDepth) >> 3);
00104 } else {
00105 if(vmemSize < ((inWidth * inHeight * inBitDepth) >> 3)) {
00106 #if DEBUG_ERROR != 0
00107 debugError("Error allocating vram buffer.\nProgram will probably now be unstable.");
00108 #endif
00109 return (void*)(MEMORY_VMEM_SIZE << 2);
00110 }
00111 vmemSize -= ((inWidth * inHeight * inBitDepth) >> 3);
00112 tempOut = (void*)vmemStart;
00113 vmemStart += ((inWidth * inHeight * inBitDepth) >> 3);
00114 }
00115 if(inStride) {
00116 u32 tempStride = (((inWidth - inStride) * inBitDepth) >> 3);
00117 void* tempStart = (void*)((u32)tempOut + tempStride);
00118 u32 tempBlockSize = ((inStride * inBitDepth) >> 3);
00119 u32 tempBlockCount = inHeight;
00120 vmemStrideBlockAdd(tempStart, tempStride, tempBlockSize, tempBlockCount);
00121 }
00122 return vmemRelativePtr(tempOut);
00123 }
00124
00125 #if FL_DEBUG_CALLEDFROM != 0
00126 void* vmemAllocFrom(u32 inSize, const char* inFile, const char* inFunc, int inLine) {
00127 #else
00128 void* vmemAlloc(u32 inSize) {
00129 #endif
00130 void* tempOut = vmemStrideAlloc(inSize);
00131 if(tempOut)
00132 return tempOut;
00133
00134 if(!vmemInitialized) {
00135 #if FL_DEBUG_WARNING != 0
00136 #if FL_DEBUG_CALLEDFROM != 0
00137 debugWarningFrom(inFile, inFunc, inLine, "Trying to allocate vram before vram is initialized.");
00138 #else
00139 debugWarning("Trying to allocate vram before vram is initialized.");
00140 #endif
00141 #endif
00142 return NULL;
00143 }
00144
00145 if(inSize > (vmemFreeBlocks * FL_MEMORY_VMEM_BLOCKSIZE)) {
00146 #if FL_DEBUG_WARNING != 0
00147 #if FL_DEBUG_CALLEDFROM != 0
00148 debugWarningFrom(inFile, inFunc, inLine, "Error allocating video memory, not enough vmem free to attempt allocation.");
00149 #else
00150 debugWarning("Error allocating video memory, not enough vmem free to attempt allocation.");
00151 #endif
00152 #endif
00153 return NULL;
00154 }
00155
00156 while(inSize & (FL_MEMORY_VMEM_BLOCKSIZE - 1))
00157 inSize++;
00158 unsigned int tempBlocksNeeded = (inSize / FL_MEMORY_VMEM_BLOCKSIZE);
00159 int tempBestBlock = -1;
00160 unsigned int tempBestBlockSize = 0;
00161 unsigned int i = 0;
00162
00163
00164 while(i < vmemBlocks) {
00165 if(((vmemBlockTable[i] & 0xC0000000) == 0) && ((vmemBlockTable[i] & 0x00FFFFFF) >= tempBlocksNeeded)) {
00166 if(((vmemBlockTable[i] & 0x00FFFFFF) < tempBestBlockSize) || (tempBestBlock < 0)){
00167 tempBestBlock = i;
00168 tempBestBlockSize = (vmemBlockTable[i] & 0x00FFFFFF);
00169 if(tempBestBlockSize == tempBlocksNeeded)
00170 break;
00171 }
00172 }
00173 if(vmemBlockTable[i] & 0x40000000) {
00174 #if FL_DEBUG_WARNING != 0
00175 #if FL_DEBUG_CALLEDFROM != 0
00176 debugWarningFrom(inFile, inFunc, inLine, "Error while walking vmem, block table corrupt.");
00177 #else
00178 debugWarning("Error while walking vmem, block table corrupt.");
00179 #endif
00180 #endif
00181 return NULL;
00182 } else
00183 i += (vmemBlockTable[i] & 0x00FFFFFF);
00184 }
00185
00186
00187 if(tempBestBlock < 0) {
00188 #if FL_DEBUG_WARNING != 0
00189 #if FL_DEBUG_CALLEDFROM != 0
00190 debugWarningFrom(inFile, inFunc, inLine, "Error allocating video memory, memory is fragmented.");
00191 #else
00192 debugWarning("Error allocating video memory, memory is fragmented.");
00193 #endif
00194 #endif
00195 return NULL;
00196 }
00197
00198
00199 vmemBlockTable[tempBestBlock] = ((tempBlocksNeeded & 0x00FFFFFF) | 0x80000000);
00200 if(tempBlocksNeeded > 1)
00201 vmemBlockTable[tempBestBlock + tempBlocksNeeded - 1] = ((tempBestBlock & 0x00FFFFFF) | 0xC0000000);
00202 if(tempBestBlockSize != tempBlocksNeeded) {
00203 vmemBlockTable[tempBestBlock + tempBlocksNeeded] = ((tempBestBlockSize - tempBlocksNeeded) & 0x00FFFFFF);
00204 if((tempBestBlockSize - tempBlocksNeeded) > 1)
00205 vmemBlockTable[tempBestBlock + tempBestBlockSize - 1] = (((tempBestBlock + tempBlocksNeeded) & 0x00FFFFFF) | 0x40000000);
00206 }
00207
00208
00209 tempOut = (void*)(vmemStart + (tempBestBlock * FL_MEMORY_VMEM_BLOCKSIZE));
00210 vmemFreeBlocks -= tempBlocksNeeded;
00211
00212 return tempOut;
00213 }
00214
00215 #if FL_DEBUG_CALLEDFROM != 0
00216 void* vmemCallocFrom(u32 inSize0, u32 inSize1, const char* inFile, const char* inFunc, int inLine) {
00217 #else
00218 void* vmemCalloc(u32 inSize0, u32 inSize1) {
00219 #endif
00220 void* tempOut = vmemStrideCalloc(inSize0, inSize1);
00221 if(tempOut)
00222 return tempOut;
00223
00224 #if FL_DEBUG_CALLEDFROM != 0
00225 tempOut = vmemAllocFrom(inSize0 * inSize1, inFile, inFunc, inLine);
00226 #else
00227 tempOut = vmemAlloc(inSize0 * inSize1);
00228 #endif
00229
00230 if(!tempOut)
00231 return NULL;
00232 memClear(tempOut, (inSize0 * inSize1));
00233 return tempOut;
00234 }
00235
00236 #if FL_DEBUG_CALLEDFROM != 0
00237 void* vmemReallocFrom(void* inData, u32 inSize, const char* inFile, const char* inFunc, int inLine) {
00238 #else
00239 void* vmemRealloc(void* inData, u32 inSize) {
00240 #endif
00241 #if FL_DEBUG_DEVWARNING != 0
00242 #if FL_DEBUG_CALLEDFROM != 0
00243 debugDevWarningFrom(inFile, inFunc, inLine, "VRam reallocation not yet quickly implemented, reverting to vmemAlloc->memCopy->vmemFree combo.");
00244 #else
00245 debugDevWarning("VRam reallocation not yet quickly implemented, reverting to vmemAlloc->memCopy->vmemFree combo.");
00246 #endif
00247 #endif
00248 void* tempOut = vmemAlloc(inSize);
00249 if(!tempOut) {
00250 #if FL_DEBUG_WARNING != 0
00251 #if FL_DEBUG_CALLEDFROM != 0
00252 debugWarningFrom(inFile, inFunc, inLine, "VRam reallocation failed, memory is full/fragmented.");
00253 #else
00254 debugWarning("VRam reallocation failed, memory is full/fragmented.");
00255 #endif
00256 #endif
00257 return NULL;
00258 }
00259
00260 unsigned int tempStartBlock = ((((u32)memCachedPtr(vmemRelativePtr(inData))) - vmemStart) / FL_MEMORY_VMEM_BLOCKSIZE);
00261 if((((u32)memCachedPtr(vmemRelativePtr(inData))) < vmemStart) || (tempStartBlock >= vmemBlocks)) {
00262 #if FL_DEBUG_ERROR != 0
00263 #if FL_DEBUG_CALLEDFROM != 0
00264 debugErrorFrom(inFile, inFunc, inLine, "Trying to realloc invalid vram pointer, out of range.");
00265 #else
00266 debugError("Trying to realloc invalid vram pointer, out of range.");
00267 #endif
00268 #endif
00269 return NULL;
00270 }
00271 if((vmemBlockTable[tempStartBlock] & 0xC0000000) != 0x80000000) {
00272 #if FL_DEBUG_ERROR != 0
00273 #if FL_DEBUG_CALLEDFROM != 0
00274 debugErrorFrom(inFile, inFunc, inLine, "Trying to realloc invalid vram pointer, middle of block.");
00275 #else
00276 debugError("Trying to realloc invalid vram pointer, middle of block.");
00277 #endif
00278 #endif
00279 return NULL;
00280 }
00281 int tempLength = (vmemBlockTable[tempStartBlock] & 0x00FFFFFF);
00282
00283 memCopy(tempOut, inData, (tempLength * FL_MEMORY_VMEM_BLOCKSIZE));
00284
00285 vmemFree(inData);
00286 return tempOut;
00287 }
00288
00289 #if FL_DEBUG_CALLEDFROM != 0
00290 void vmemFreeFrom(void* inData, const char* inFile, const char* inFunc, int inLine) {
00291 #else
00292 void vmemFree(void* inData) {
00293 #endif
00294 if(!vmemInitialized)
00295 return;
00296
00297 if(vmemStrideFree(inData))
00298 return;
00299
00300 inData = vmemNormalPtr(inData);
00301
00302 if(!inData || (((u32)inData - vmemStart) % FL_MEMORY_VMEM_BLOCKSIZE) || (((u32)inData - vmemStart) >= vmemSize) || ((u32)inData < vmemStart)) {
00303 #if FL_DEBUG_ERROR != 0
00304 #if FL_DEBUG_CALLEDFROM != 0
00305 debugErrorFrom(inFile, inFunc, inLine, "Trying to free invalid vram pointer, out of range.");
00306 #else
00307 debugError("Trying to free invalid vram pointer, out of range.");
00308 #endif
00309 #endif
00310 return;
00311 }
00312
00313 u32 tempStartBlock = (((u32)inData - vmemStart) / FL_MEMORY_VMEM_BLOCKSIZE);
00314 u32 tempLength = (vmemBlockTable[tempStartBlock] & 0x00FFFFFF);
00315 if((vmemBlockTable[tempStartBlock] & 0xC0000000) != 0x80000000) {
00316 #if FL_DEBUG_ERROR != 0
00317 #if FL_DEBUG_CALLEDFROM != 0
00318 debugErrorFrom(inFile, inFunc, inLine, "Trying to free invalid vram pointer, middle of block or not allocated.");
00319 #else
00320 debugError("Trying to free invalid vram pointer, middle of block or not allocated.");
00321 #endif
00322 #endif
00323 return;
00324 }
00325
00326 vmemFreeBlocks += tempLength;
00327
00328
00329 if((tempStartBlock + tempLength) < vmemBlocks) {
00330 if((vmemBlockTable[tempStartBlock + tempLength] & 0xC0000000) == 0x00000000) {
00331 tempLength += (vmemBlockTable[tempStartBlock + tempLength] & 0x00FFFFFF);
00332 }
00333 }
00334
00335
00336 if(tempStartBlock > 0) {
00337 if((vmemBlockTable[tempStartBlock - 1] & 0xC0000000) == 0x00000000) {
00338 tempStartBlock--;
00339 tempLength++;
00340 } else if((vmemBlockTable[tempStartBlock - 1] & 0xC0000000) == 0x40000000) {
00341 tempStartBlock = (vmemBlockTable[tempStartBlock - 1] & 0x00FFFFFF);
00342 tempLength += (vmemBlockTable[tempStartBlock] & 0x00FFFFFF);
00343 }
00344 }
00345
00346
00347 vmemBlockTable[tempStartBlock] = tempLength;
00348 vmemBlockTable[tempStartBlock + tempLength - 1] = (tempStartBlock | 0x40000000);
00349
00350 return;
00351 }
00352
00353 u32 vmemFreeSpace() {
00354 return ((vmemFreeBlocks * FL_MEMORY_VMEM_BLOCKSIZE) + vmemStrideFreeSpace());
00355 }
00356
00357 u32 vmemLargestFreeBlock() {
00358 unsigned int i = 0;
00359 unsigned int tempOut = 0;
00360 while(i < vmemBlocks) {
00361 if((vmemBlockTable[i] & 0xC0000000) == 0) {
00362 if((vmemBlockTable[i] & 0x00FFFFFF) > tempOut)
00363 tempOut = (vmemBlockTable[i] & 0x00FFFFFF);
00364 }
00365 if(vmemBlockTable[i] & 0x40000000) {
00366 #if FL_DEBUG_WARNING != 0
00367 debugWarning("Error while walking vmem, block table corruption.");
00368 #endif
00369 return 0;
00370 } else
00371 i += (vmemBlockTable[i] & 0x00FFFFFF);
00372 }
00373 return (tempOut * FL_MEMORY_VMEM_BLOCKSIZE);
00374 }
00375
00376 float vmemFragmentation() {
00377 if(!vmemInitialized)
00378 return -1.0f;
00379 unsigned int i = 0;
00380 unsigned int tempFragments = 0;
00381 while(i < vmemBlocks) {
00382 if((vmemBlockTable[i] & 0xC0000000) == 0)
00383 tempFragments++;
00384 if(vmemBlockTable[i] & 0x40000000) {
00385 #if FL_DEBUG_WARNING != 0
00386 debugWarning("Error while walking vmem, block table corruption.");
00387 #endif
00388 return -1.0f;
00389 } else
00390 i += (vmemBlockTable[i] & 0x00FFFFFF);
00391 }
00392 float tempOut = ((float)vmemFreeSpace() / (float)tempFragments);
00393 return (tempOut * FL_MEMORY_VMEM_BLOCKSIZE);
00394 }
00395
00396 void vmemStrideBlockAdd(void* inStart, u32 inStride, u32 inBlockSize, u32 inBlockCount) {
00397 if(!inStride || !inBlockSize || !inBlockCount) {
00398 #if FL_DEBUG_WARNING != 0
00399 debugWarning("Trying to create stride block with bad parameters.");
00400 #endif
00401 return;
00402 }
00403 inStart = vmemNormalPtr(inStart);
00404 if(!memBlockValid(inStart, (((inBlockSize + inStride) * inBlockCount) - inStride))) {
00405 #if FL_DEBUG_WARNING != 0
00406 debugWarning("Cannot create stride block from an invalid pointer or memory block.");
00407 #endif
00408 return;
00409 }
00410
00411 VmemStrideBlock* tempOut = (VmemStrideBlock*)memAlloc(sizeof(VmemStrideBlock) + inBlockCount);
00412 if(!tempOut) {
00413 #if FL_DEBUG_WARNING != 0
00414 debugWarning("Failed to allocate node to add vmem stride block.");
00415 #endif
00416 return;
00417 }
00418
00419 tempOut->vmsbStart = inStart;
00420 tempOut->vmsbStride = inStride;
00421 tempOut->vmsbBlockSize = inBlockSize;
00422 tempOut->vmsbBlockCount = inBlockCount;
00423 tempOut->vmsbBlockAlign = min(memAddressAlignment(inStart), memAddressAlignment((void*)(inStride + inBlockSize)));
00424
00425 tempOut->vmsbBlockTable = (u8*)((u32)tempOut + sizeof(VmemStrideBlock));
00426 memClear(tempOut->vmsbBlockTable, tempOut->vmsbBlockCount);
00427 tempOut->vmsbLast = NULL;
00428 tempOut->vmsbNext = vmemStrideBlocks;
00429 if(tempOut->vmsbNext)
00430 ((VmemStrideBlock*)(tempOut->vmsbNext))->vmsbLast = tempOut;
00431 vmemStrideBlocks = tempOut;
00432 }
00433
00434 void vmemStrideBlockDel(VmemStrideBlock* inBlock) {
00435 if(!inBlock)
00436 return;
00437 if(!inBlock->vmsbLast)
00438 vmemStrideBlocks = (VmemStrideBlock*)inBlock->vmsbNext;
00439 else
00440 inBlock->vmsbLast = inBlock->vmsbNext;
00441 memFree(inBlock);
00442 }
00443
00444 void vmemStrideBlockDelRecursive(VmemStrideBlock* inBlock) {
00445 if(!inBlock)
00446 return;
00447 if(inBlock->vmsbLast) {
00448 vmemStrideBlockDelRecursive((VmemStrideBlock*)inBlock->vmsbLast);
00449 return;
00450 }
00451 if(inBlock->vmsbNext)
00452 vmemStrideBlockDelRecursive((VmemStrideBlock*)inBlock->vmsbNext);
00453 memFree(inBlock);
00454 }
00455
00456 void* vmemStrideAlign(u32 inAlign, u32 inSize) {
00457 if(!vmemStrideBlocks || !inSize)
00458 return NULL;
00459 if(!inAlign)
00460 inAlign = FL_MEMORY_ALIGNMENT_DEFAULT;
00461
00462 VmemStrideBlock* tempBlock = vmemStrideBlocks;
00463
00464 VmemStrideBlock* tempBestBlock = NULL;
00465 u32 tempBestIndex = 0;
00466
00467 u32 i;
00468 while(flRunning) {
00469 if((tempBlock->vmsbBlockAlign >= inAlign) && (tempBlock->vmsbBlockSize >= inSize)) {
00470 if(!tempBestBlock || (tempBlock->vmsbBlockSize < tempBestBlock->vmsbBlockSize)) {
00471 for(i = 0; i < tempBlock->vmsbBlockCount; i++) {
00472 if(!tempBlock->vmsbBlockTable[i]) {
00473 tempBestBlock = tempBlock;
00474 tempBestIndex = i;
00475 break;
00476 }
00477 }
00478 }
00479 }
00480 if(!tempBlock->vmsbNext)
00481 break;
00482 tempBlock = ((VmemStrideBlock*)(tempBlock->vmsbNext));
00483 }
00484
00485 if(!tempBestBlock)
00486 return NULL;
00487
00488 tempBestBlock->vmsbBlockTable[tempBestIndex] = 1;
00489 return (void*)((u32)tempBestBlock->vmsbStart + (tempBestIndex * (tempBestBlock->vmsbBlockSize + tempBestBlock->vmsbStride)));
00490 }
00491
00492 void* vmemStrideAlloc(u32 inSize) {
00493 return vmemStrideAlign(FL_MEMORY_ALIGNMENT_DEFAULT, inSize);
00494 }
00495
00496 void* vmemStrideCalloc(u32 inSize0, u32 inSize1) {
00497 void* tempOut = vmemStrideAlloc(inSize0 * inSize1);
00498 memClear(tempOut, (inSize0 * inSize1));
00499 return tempOut;
00500 }
00501
00502 bool vmemStrideFree(void* inData) {
00503 if(!vmemStrideBlocks)
00504 return false;
00505
00506 inData = vmemNormalPtr(inData);
00507 if(!inData)
00508 return false;
00509
00510 VmemStrideBlock* tempBlock = vmemStrideBlocks;
00511 u32 i;
00512 while(flRunning) {
00513 if(((u32)inData >= (u32)tempBlock->vmsbStart) && ((u32)inData < ((u32)tempBlock->vmsbStart + (((tempBlock->vmsbBlockSize + tempBlock->vmsbStride) * tempBlock->vmsbBlockCount) - tempBlock->vmsbStride)))) {
00514 for(i = 0; i < tempBlock->vmsbBlockCount; i++) {
00515 if(((u32)tempBlock->vmsbStart + (i * (tempBlock->vmsbStride + tempBlock->vmsbBlockSize))) == (u32)inData) {
00516 if(!tempBlock->vmsbBlockTable[i])
00517 return false;
00518 tempBlock->vmsbBlockTable[i] = 0;
00519 return true;
00520 }
00521 }
00522 #if FL_DEBUG_WARNING != 0
00523 debugWarning("Trying to free an invalid stride block");
00524 #endif
00525 return true;
00526 }
00527 if(!tempBlock->vmsbNext)
00528 break;
00529 tempBlock = ((VmemStrideBlock*)(tempBlock->vmsbNext));
00530 }
00531 return false;
00532 }
00533
00534 float vmemStrideUsage() {
00535 if(!vmemStrideBlocks)
00536 return 0.0f;
00537
00538 VmemStrideBlock* tempBlock = vmemStrideBlocks;
00539
00540 u32 tempSize = 0;
00541 u32 tempUsed = 0;
00542 u32 i;
00543
00544 while(flRunning) {
00545 tempSize += (tempBlock->vmsbBlockSize * tempBlock->vmsbBlockCount);
00546
00547 for(i = 0; i < tempBlock->vmsbBlockCount; i++) {
00548 if(tempBlock->vmsbBlockTable[i])
00549 tempUsed += tempBlock->vmsbBlockSize;
00550 }
00551
00552 if(!tempBlock->vmsbNext)
00553 break;
00554
00555 tempBlock = ((VmemStrideBlock*)(tempBlock->vmsbNext));
00556 }
00557
00558 if(!tempSize)
00559 return 0.0f;
00560 return ((float)tempUsed / (float)tempSize);
00561 }
00562
00563 u32 vmemStrideFreeSpace() {
00564 if(!vmemStrideBlocks)
00565 return 0;
00566
00567 VmemStrideBlock* tempBlock = vmemStrideBlocks;
00568
00569 u32 tempSize = 0;
00570 u32 tempUsed = 0;
00571 u32 i;
00572
00573 while(flRunning) {
00574 tempSize += (tempBlock->vmsbBlockSize * tempBlock->vmsbBlockCount);
00575
00576 for(i = 0; i < tempBlock->vmsbBlockCount; i++) {
00577 if(tempBlock->vmsbBlockTable[i])
00578 tempUsed += tempBlock->vmsbBlockSize;
00579 }
00580
00581 if(!tempBlock->vmsbNext)
00582 break;
00583
00584 tempBlock = ((VmemStrideBlock*)(tempBlock->vmsbNext));
00585 }
00586
00587 return (tempSize - tempUsed);
00588 }
00589
00590 #endif