| 77 | } |
| 78 | |
| 79 | bool CMap::Load(const char *pFullName, IStorage *pStorage, const char *pPath, int StorageType) |
| 80 | { |
| 81 | // Ensure current datafile is not left in an inconsistent state if loading fails, |
| 82 | // by loading the new datafile separately first. |
| 83 | CDataFileReader NewDataFile; |
| 84 | if(!NewDataFile.Open(pFullName, pStorage, pPath, StorageType)) |
| 85 | return false; |
| 86 | |
| 87 | // Check version |
| 88 | const CMapItemVersion *pItem = (CMapItemVersion *)NewDataFile.FindItem(MAPITEMTYPE_VERSION, 0); |
| 89 | if(pItem == nullptr || pItem->m_Version != 1) |
| 90 | { |
| 91 | log_error("map/load", "Error: map version not supported."); |
| 92 | NewDataFile.Close(); |
| 93 | return false; |
| 94 | } |
| 95 | |
| 96 | // Replace compressed tile layers with uncompressed ones |
| 97 | int GroupsStart, GroupsNum, LayersStart, LayersNum; |
| 98 | NewDataFile.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum); |
| 99 | NewDataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); |
| 100 | for(int g = 0; g < GroupsNum; g++) |
| 101 | { |
| 102 | const CMapItemGroup *pGroup = static_cast<CMapItemGroup *>(NewDataFile.GetItem(GroupsStart + g)); |
| 103 | for(int l = 0; l < pGroup->m_NumLayers; l++) |
| 104 | { |
| 105 | CMapItemLayer *pLayer = static_cast<CMapItemLayer *>(NewDataFile.GetItem(LayersStart + pGroup->m_StartLayer + l)); |
| 106 | if(pLayer->m_Type == LAYERTYPE_TILES) |
| 107 | { |
| 108 | CMapItemLayerTilemap *pTilemap = reinterpret_cast<CMapItemLayerTilemap *>(pLayer); |
| 109 | if(pTilemap->m_Version >= CMapItemLayerTilemap::VERSION_TEEWORLDS_TILESKIP) |
| 110 | { |
| 111 | const size_t TilemapCount = (size_t)pTilemap->m_Width * pTilemap->m_Height; |
| 112 | const size_t TilemapSize = TilemapCount * sizeof(CTile); |
| 113 | |
| 114 | if(((int)TilemapCount / pTilemap->m_Width != pTilemap->m_Height) || (TilemapSize / sizeof(CTile) != TilemapCount)) |
| 115 | { |
| 116 | log_error("map/load", "map layer too big (%d * %d * %d causes an integer overflow)", pTilemap->m_Width, pTilemap->m_Height, (int)sizeof(CTile)); |
| 117 | return false; |
| 118 | } |
| 119 | CTile *pTiles = static_cast<CTile *>(malloc(TilemapSize)); |
| 120 | if(!pTiles) |
| 121 | return false; |
| 122 | ExtractTiles(pTiles, (size_t)pTilemap->m_Width * pTilemap->m_Height, static_cast<CTile *>(NewDataFile.GetData(pTilemap->m_Data)), NewDataFile.GetDataSize(pTilemap->m_Data) / sizeof(CTile)); |
| 123 | NewDataFile.ReplaceData(pTilemap->m_Data, reinterpret_cast<char *>(pTiles), TilemapSize); |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Replace existing datafile with new datafile |
| 130 | m_DataFile.Close(); |
| 131 | m_DataFile = std::move(NewDataFile); |
| 132 | return true; |
| 133 | } |
| 134 | |
| 135 | bool CMap::Load(IStorage *pStorage, const char *pPath, int StorageType) |
| 136 | { |
no test coverage detected