Report actual data sizes in CDataFileReader::GetDataSize

Previously it reported the internal file data size (compressed). This
made the `map_resave` tool do the wrong job.

Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
Robert Müller 2022-08-14 18:00:52 +02:00
parent 32f2fe936a
commit 785f03e73a
3 changed files with 39 additions and 12 deletions

View file

@ -87,6 +87,7 @@ struct CDatafile
CDatafileHeader m_Header;
int m_DataStartOffset;
char **m_ppDataPtrs;
int *m_pDataSizes;
char *m_pData;
};
@ -163,18 +164,27 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int
unsigned AllocSize = Size;
AllocSize += sizeof(CDatafile); // add space for info structure
AllocSize += Header.m_NumRawData * sizeof(void *); // add space for data pointers
AllocSize += Header.m_NumRawData * sizeof(int); // add space for data sizes
if(Size > (((int64_t)1) << 31) || Header.m_NumItemTypes < 0 || Header.m_NumItems < 0 || Header.m_NumRawData < 0 || Header.m_ItemSize < 0)
{
io_close(File);
dbg_msg("datafile", "unable to load file, invalid file information");
return false;
}
CDatafile *pTmpDataFile = (CDatafile *)malloc(AllocSize);
pTmpDataFile->m_Header = Header;
pTmpDataFile->m_DataStartOffset = sizeof(CDatafileHeader) + Size;
pTmpDataFile->m_ppDataPtrs = (char **)(pTmpDataFile + 1);
pTmpDataFile->m_pData = (char *)(pTmpDataFile + 1) + Header.m_NumRawData * sizeof(char *);
pTmpDataFile->m_pDataSizes = (int *)(pTmpDataFile->m_ppDataPtrs + Header.m_NumRawData);
pTmpDataFile->m_pData = (char *)(pTmpDataFile->m_pDataSizes + Header.m_NumRawData);
pTmpDataFile->m_File = File;
pTmpDataFile->m_Sha256 = Sha256;
pTmpDataFile->m_Crc = Crc;
// clear the data pointers
// clear the data pointers and sizes
mem_zero(pTmpDataFile->m_ppDataPtrs, Header.m_NumRawData * sizeof(void *));
mem_zero(pTmpDataFile->m_pDataSizes, Header.m_NumRawData * sizeof(int));
// read types, offsets, sizes and item data
unsigned ReadSize = io_read(File, pTmpDataFile->m_pData, Size);
@ -224,7 +234,11 @@ bool CDataFileReader::Close()
// free the data that is loaded
for(int i = 0; i < m_pDataFile->m_Header.m_NumRawData; i++)
{
free(m_pDataFile->m_ppDataPtrs[i]);
m_pDataFile->m_ppDataPtrs[i] = nullptr;
m_pDataFile->m_pDataSizes[i] = 0;
}
io_close(m_pDataFile->m_File);
free(m_pDataFile);
@ -258,21 +272,30 @@ int CDataFileReader::GetFileDataSize(int Index) const
if(Index == m_pDataFile->m_Header.m_NumRawData - 1)
return m_pDataFile->m_Header.m_DataSize - m_pDataFile->m_Info.m_pDataOffsets[Index];
return m_pDataFile->m_Info.m_pDataOffsets[Index + 1] - m_pDataFile->m_Info.m_pDataOffsets[Index];
}
// returns the size of the resulting data
int CDataFileReader::GetDataSize(int Index) const
{
if(!m_pDataFile)
if(!m_pDataFile || Index < 0 || Index >= m_pDataFile->m_Header.m_NumRawData)
{
return 0;
}
if(m_pDataFile->m_Header.m_Version == 4)
return m_pDataFile->m_Info.m_pDataSizes[Index];
else
return GetFileDataSize(Index);
if(!m_pDataFile->m_ppDataPtrs[Index])
{
if(m_pDataFile->m_Header.m_Version >= 4)
{
return m_pDataFile->m_Info.m_pDataSizes[Index];
}
else
{
return GetFileDataSize(Index);
}
}
return m_pDataFile->m_pDataSizes[Index];
}
void *CDataFileReader::GetDataImpl(int Index, int Swap)
@ -303,6 +326,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap)
log_trace("datafile", "loading data index=%d size=%d uncompressed=%lu", Index, DataSize, UncompressedSize);
m_pDataFile->m_ppDataPtrs[Index] = (char *)malloc(UncompressedSize);
m_pDataFile->m_pDataSizes[Index] = UncompressedSize;
// read the compressed data
io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset + m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START);
@ -323,6 +347,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap)
// load the data
log_trace("datafile", "loading data index=%d size=%d", Index, DataSize);
m_pDataFile->m_ppDataPtrs[Index] = (char *)malloc(DataSize);
m_pDataFile->m_pDataSizes[Index] = DataSize;
io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset + m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START);
io_read(m_pDataFile->m_File, m_pDataFile->m_ppDataPtrs[Index], DataSize);
}
@ -346,13 +371,14 @@ void *CDataFileReader::GetDataSwapped(int Index)
return GetDataImpl(Index, 1);
}
void CDataFileReader::ReplaceData(int Index, char *pData)
void CDataFileReader::ReplaceData(int Index, char *pData, size_t Size)
{
// make sure the data has been loaded
GetDataImpl(Index, 0);
UnloadData(Index);
m_pDataFile->m_ppDataPtrs[Index] = pData;
m_pDataFile->m_pDataSizes[Index] = Size;
}
void CDataFileReader::UnloadData(int Index)
@ -360,9 +386,9 @@ void CDataFileReader::UnloadData(int Index)
if(Index < 0 || Index >= m_pDataFile->m_Header.m_NumRawData)
return;
//
free(m_pDataFile->m_ppDataPtrs[Index]);
m_pDataFile->m_ppDataPtrs[Index] = nullptr;
m_pDataFile->m_pDataSizes[Index] = 0;
}
int CDataFileReader::GetItemSize(int Index) const

View file

@ -38,7 +38,7 @@ public:
void *GetData(int Index);
void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved
int GetDataSize(int Index) const;
void ReplaceData(int Index, char *pData);
void ReplaceData(int Index, char *pData, size_t Size);
void UnloadData(int Index);
int NumData() const;

View file

@ -85,9 +85,10 @@ bool CMap::Load(const char *pMapName)
CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer);
if(pTilemap->m_Version >= CMapItemLayerTilemap::TILE_SKIP_MIN_VERSION)
{
CTile *pTiles = static_cast<CTile *>(malloc((size_t)pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile)));
const size_t TilemapSize = (size_t)pTilemap->m_Width * pTilemap->m_Height * sizeof(CTile);
CTile *pTiles = static_cast<CTile *>(malloc(TilemapSize));
ExtractTiles(pTiles, (size_t)pTilemap->m_Width * pTilemap->m_Height, static_cast<CTile *>(m_DataFile.GetData(pTilemap->m_Data)), m_DataFile.GetDataSize(pTilemap->m_Data) / sizeof(CTile));
m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles));
m_DataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles), TilemapSize);
}
}
}