Pol  Revision:cb584c9
RawMap.cpp
Go to the documentation of this file.
1 #include "RawMap.h"
2 
3 #include "../clib/passert.h"
4 #include "../clib/logfacility.h"
5 
6 #include "uopreader/uop.h"
7 #include "uopreader/uophash.h"
8 
9 #include <cstdio>
10 #include <cstring>
11 #include <map>
12 
13 using namespace Pol::Core;
14 
15 namespace Pol
16 {
17 namespace Plib
18 {
19 USTRUCT_MAPINFO RawMap::get_cell( unsigned int blockidx, unsigned int x_offset,
20  unsigned int y_offset )
21 {
22  return m_mapinfo_vec.at( blockidx ).cell[y_offset][x_offset];
23 }
24 
25 signed char RawMap::rawinfo( unsigned short x, unsigned short y, USTRUCT_MAPINFO* gi )
26 {
27  passert_r( is_init, "Tried to read map information before loading the map files" );
28  passert( m_mapwidth > 0 && m_mapheight > 0 && x < m_mapwidth && y < m_mapheight );
29 
30  unsigned int x_block = x / 8;
31  unsigned int y_block = y / 8;
32  unsigned int block = ( x_block * ( m_mapheight / 8 ) + y_block );
33 
34  unsigned int x_offset = x & 0x7;
35  unsigned int y_offset = y & 0x7;
36 
37  *gi = get_cell( block, x_offset, y_offset );
38  return gi->z;
39 }
40 
41 void RawMap::add_block( const USTRUCT_MAPINFO_BLOCK& block )
42 {
43  m_mapinfo_vec.push_back( block );
44 }
45 
46 void RawMap::set_bounds( unsigned short width, unsigned short height )
47 {
48  m_mapwidth = width;
49  m_mapheight = height;
50 }
51 
52 unsigned int RawMap::load_map_difflist( FILE* mapdifl_file )
53 {
54  unsigned index = 0;
55  if ( mapdifl_file != NULL )
56  {
57  u32 blockid;
58  while ( fread( &blockid, sizeof blockid, 1, mapdifl_file ) == 1 )
59  {
60  mapdifl[blockid] = index;
61  ++index;
62  }
63  }
64  return index;
65 }
66 
67 unsigned int RawMap::load_full_map( FILE* mapfile, FILE* mapdif_file )
68 {
69  passert_r( !is_init, "tried to initialize RawMap twice" );
70 
71  if ( mapfile == nullptr )
72  throw std::runtime_error( "load_full_map: mapfile is not open" );
73 
74  if ( mapdifl.size() > 0 && mapdif_file == nullptr )
75  throw std::runtime_error( "load_full_map: mapdifl is loaded but mapdif is not" );
76 
77  unsigned int block = 0;
79 
80  while ( fread( &buffer, sizeof buffer, 1, mapfile ) == 1 )
81  {
82  auto citr = mapdifl.find( block );
83  if ( citr == mapdifl.end() )
84  {
85  add_block( buffer );
86  }
87  else
88  {
89  // it's in the dif file.. get it from there.
90  unsigned dif_index = ( *citr ).second;
91  unsigned int file_offset = dif_index * sizeof( USTRUCT_MAPINFO_BLOCK );
92  if ( fseek( mapdif_file, file_offset, SEEK_SET ) != 0 )
93  throw std::runtime_error( "rawmapinfo: fseek(mapdif_file) failure" );
94 
95  if ( fread( &buffer, sizeof buffer, 1, mapdif_file ) != 1 )
96  throw std::runtime_error( "rawmapinfo: fread(mapdif_file) failure" );
97  add_block( buffer );
98  }
99  ++block;
100  }
101 
102  is_init = true;
103  return block;
104 }
105 
106 // TODO: cleanup the code
107 unsigned int RawMap::load_full_map( int uo_mapid, std::istream& ifs )
108 {
109  auto maphash = []( int mapid, size_t chunkidx ) {
110  char mapstring[1024];
111  snprintf( mapstring, sizeof mapstring, "build/map%dlegacymul/%08i.dat", mapid, (int)chunkidx );
112  return HashLittle2( mapstring );
113  };
114 
115  passert_r( !is_init, "tried to initialize RawMap twice" );
116 
117  if ( !ifs )
118  {
119  ERROR_PRINT << "Error when opening UOP file.\n";
120  return 0;
121  }
122 
123  kaitai::kstream ks( &ifs );
124  uop_t uopfile( &ks );
125 
126  size_t totalSize = 0;
127  std::map<uint64_t, uop_t::file_t*> filemap;
128 
129  // First pass over the data to build up filehash -> file mapping and calculate total map size.
130  // NOTE: This only reads the first block of the UOP file, which is all that is used for the
131  // current version (~2018). If that ever changes, you need to access the next blocks in
132  // sequence:
133  // currentblock = currentblock->block_body()->next_addr()
134  // until next_addr() == nullptr.
135  //
136  uop_t::block_addr_t* currentblock = uopfile.header()->firstblock();
137 
138  for ( auto file : *currentblock->block_body()->files() )
139  {
140  if ( file == nullptr )
141  continue;
142  if ( file->decompressed_size() == 0 )
143  continue;
144 
145  passert_r( file->compression_type() == uop_t::COMPRESSION_TYPE_NO_COMPRESSION,
146  "This map is zlib compressed and we can't handle that yet." );
147 
148  filemap[file->filehash()] = file;
149  totalSize += file->decompressed_size();
150  }
151  if ( uopfile.header()->nfiles() != filemap.size() )
152  INFO_PRINT << "Warning: not all chunks read (" << filemap.size() << "/"
153  << uopfile.header()->nfiles() << ")\n";
154 
155  // Sanity checking and pre-allocate mapinfo vector
156  passert_r(
157  size_t( totalSize / sizeof( USTRUCT_MAPINFO_BLOCK ) ) * sizeof( USTRUCT_MAPINFO_BLOCK ) ==
158  totalSize,
159  "Not an integer number of blocks! Check if the sizes are correct." );
160  m_mapinfo_vec.clear();
161  m_mapinfo_vec.resize( totalSize / sizeof( USTRUCT_MAPINFO_BLOCK ) );
162 
163  // Reads the mapinfo by concatenating all tiles, in the correct order, directly into the mapinfo
164  // vector.
165  size_t vecidx = 0;
166  for ( size_t i = 0, remaining = totalSize; i < filemap.size(); i++ )
167  {
168  auto fileitr = filemap.find( maphash( uo_mapid, i ) );
169  if ( fileitr == filemap.end() )
170  {
171  ERROR_PRINT << "Couldn't find file hash: " << std::to_string( maphash( uo_mapid, i ) )
172  << "\n";
173  throw std::runtime_error( "UOP map is missing a file chunk." );
174  }
175 
176  auto file = fileitr->second;
177 
178  passert( remaining >= file->data()->filebytes().size() );
179  memcpy( &m_mapinfo_vec[vecidx], file->data()->filebytes().data(),
180  file->data()->filebytes().size() );
181 
182  remaining -= file->data()->filebytes().size();
183  vecidx += file->data()->filebytes().size() / sizeof( USTRUCT_MAPINFO_BLOCK );
184  }
185 
186  if ( !m_mapinfo_vec.empty() )
187  is_init = true;
188 
189  return (unsigned int)m_mapinfo_vec.size();
190 }
191 
192 RawMap::RawMap() : m_mapwidth( 0 ), m_mapheight( 0 ) {}
193 
194 
195 RawMap::~RawMap() = default;
196 
197 } // namespace Plib
198 } // namespace Pol
Definition: uop.h:15
FILE * mapdif_file
Definition: uofile00.cpp:30
#define passert_r(exp, reason)
Definition: passert.h:66
int uo_mapid
Definition: uofile00.cpp:85
unsigned char buffer[10000]
Definition: UoToolMain.cpp:109
unsigned int u32
Definition: rawtypes.h:27
std::vector< file_t * > * files() const
Definition: uop.h:96
FILE * mapdifl_file
Definition: uofile00.cpp:29
#define passert(exp)
Definition: passert.h:62
FILE * mapfile
Definition: uofile00.cpp:21
uint64_t HashLittle2(std::string s)
Definition: uophash.h:9
block_body_t * block_body()
Definition: uop.cpp:40
block_addr_t * firstblock() const
Definition: uop.h:152
#define ERROR_PRINT
Definition: logfacility.h:230
#define INFO_PRINT
Definition: logfacility.h:223
uint32_t nfiles() const
Definition: uop.h:154
Definition: berror.cpp:12
header_t * header() const
Definition: uop.h:217