Find fragments in file map by binary search

This makes a noticeable difference in Ultimate Doom, which has a lot
more fragments by sheer file size.
This commit is contained in:
Lephenixnoir 2021-08-03 18:43:45 +02:00
parent 1e98b33a93
commit b0c1f019e3
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
1 changed files with 25 additions and 30 deletions

View File

@ -416,9 +416,7 @@ void IndexSearchSector(SectorIndexInfo *index, const void *buf, int *lo_ptr, int
while(lo < hi) {
int m = (lo + hi) / 2;
int diff = index[m].start_bytes - needle;
if(diff < 0) lo = m + 1;
if(index[m].start_bytes < needle) lo = m + 1;
else hi = m;
}
@ -530,48 +528,45 @@ int CreateFileMapping(int fd, FileMapping *pMap)
return pMap->miTotalLength;
}
/* Find a fragment in the file map by binary search. */
int FindFragmentInMap(FileMapping *map, int sector_number)
{
int lo=0, hi=map->miItemCount;
while (lo < hi)
{
int m = (lo + hi) / 2;
if (map->mTable[m].file_address > sector_number) hi = m;
else lo = m + 1;
}
return hi - 1;
}
int FindInFlash(const void **buf, int size, int readpos)
{
if(gWADmethod == CGDOOM_WAD_BFILE)
return 0;
int iPageReq = readpos / FLASH_PAGE_SIZE;
int iPageIndx = 0;
int iFragOffset = 0, iFragEnd, iAvailableLen;
int iSubOffset;
ASSERT(readpos >= 0);
if (readpos + size > gpWADMap->miTotalLength)
return -1;
/* Find fragment containing the specified readpos. */
for(;;)
{
if(iPageIndx >= gpWADMap->miItemCount ||
gpWADMap->mTable[iPageIndx].file_address > iPageReq)
{
iPageIndx--;
break;
}
iPageIndx++;
}
int iFragIndx = FindFragmentInMap(gpWADMap, readpos / FLASH_PAGE_SIZE);
int iFragOffset = gpWADMap->mTable[iFragIndx].file_address * FLASH_PAGE_SIZE;
int iSubOffset = readpos - iFragOffset;
iFragOffset = gpWADMap->mTable[iPageIndx].file_address * FLASH_PAGE_SIZE;
iSubOffset = readpos - iFragOffset;
if (iPageIndx+1 < gpWADMap->miItemCount)
iFragEnd = gpWADMap->mTable[iPageIndx+1].file_address * FLASH_PAGE_SIZE;
int iFragEnd;
if (iFragIndx+1 < gpWADMap->miItemCount)
iFragEnd = gpWADMap->mTable[iFragIndx+1].file_address * FLASH_PAGE_SIZE;
else
iFragEnd = gpWADMap->miTotalLength;
iAvailableLen = iFragEnd - readpos;
ASSERT(iAvailableLen > 0);
*buf = FLASH_CACHED_START + (gpWADMap->mTable[iFragIndx].flash_address * FLASH_PAGE_SIZE) + iSubOffset;
/* Return how many bytes can be read off the fragment (up to size). */
if(iAvailableLen > size)
iAvailableLen = size;
*buf = FLASH_CACHED_START + (gpWADMap->mTable[iPageIndx].flash_address * FLASH_PAGE_SIZE) + iSubOffset;
int iAvailableLen = min(iFragEnd - readpos, size);
ASSERT(iAvailableLen > 0);
return iAvailableLen;
}