1+ #include " regions_d1.h"
2+
3+ #include " driver_level.h"
4+ #include " level.h"
5+ #include " core/cmdlib.h"
6+ #include " core/IVirtualStream.h"
7+
8+ void CDriver1LevelRegion::FreeAll ()
9+ {
10+ if (!m_loaded)
11+ return ;
12+
13+ CBaseLevelRegion::FreeAll ();
14+
15+ if (m_cells)
16+ free (m_cells);
17+ m_cells = nullptr ;
18+
19+ if (m_cellObjects)
20+ free (m_cellObjects);
21+ m_cellObjects = nullptr ;
22+ }
23+
24+ void CDriver1LevelRegion::LoadRegionData (IVirtualStream* pFile, Spool* spool)
25+ {
26+ m_spoolInfo = spool;
27+
28+ Msg (" ---------\n Spool %d %d\n " , m_regionX, m_regionZ);
29+
30+ Msg (" - offset: %d\n " , spool->offset );
31+
32+ for (int i = 0 ; i < spool->num_connected_areas && i < 2 ; i++)
33+ Msg (" - connected area %d: %d\n " , i, spool->connected_areas [i]);
34+
35+ Msg (" - pvs_size: %d\n " , spool->pvs_size );
36+ Msg (" - cell_data_size: %d %d %d\n " , spool->cell_data_size [0 ], spool->cell_data_size [1 ], spool->cell_data_size [2 ]);
37+
38+ Msg (" - super_region: %d\n " , spool->super_region );
39+
40+ // LoadRegionData - calculate offsets
41+ Msg (" - cell pointers size: %d\n " , spool->cell_data_size [1 ]);
42+ Msg (" - cell data size: %d\n " , spool->cell_data_size [0 ]);
43+ Msg (" - cell objects size: %d\n " , spool->cell_data_size [2 ]);
44+ Msg (" - PVS data size: %d\n " , spool->pvs_size );
45+ Msg (" - roadmap data size: %dx%d\n " , spool->roadm_size , spool->roadh_size );
46+
47+ //
48+ // Driver 1 use CELL_OBJECTS directly - 16 bytes, wasteful in RAM
49+ //
50+
51+ int cellPointersOffset = spool->offset + spool->roadm_size + spool->roadh_size ; // SKIP road map
52+ int cellDataOffset = cellPointersOffset + spool->cell_data_size [1 ];
53+ int cellObjectsOffset = cellDataOffset + spool->cell_data_size [0 ];
54+ int pvsDataOffset = cellObjectsOffset + spool->cell_data_size [2 ]; // FIXME: is it even there in Driver 1?
55+
56+ char * packed_cell_pointers = new char [spool->cell_data_size [1 ] * SPOOL_CD_BLOCK_SIZE * 2 ];
57+ m_cellPointers = new ushort[m_owner->m_mapInfo .region_size * m_owner->m_mapInfo .region_size * 2 ];
58+
59+ memset (m_cellPointers, 0xFF , sizeof (ushort) * m_owner->m_mapInfo .region_size * m_owner->m_mapInfo .region_size * 2 );
60+
61+ // read packed cell pointers
62+ pFile->Seek (g_levInfo.spooldata_offset + cellPointersOffset * SPOOL_CD_BLOCK_SIZE, VS_SEEK_SET);
63+ pFile->Read (packed_cell_pointers, spool->cell_data_size [1 ] * SPOOL_CD_BLOCK_SIZE * 2 , sizeof (char ));
64+
65+ // unpack cell pointers so we can use them
66+ if (UnpackCellPointers (m_cellPointers, packed_cell_pointers, 0 , 0 ) != -1 )
67+ {
68+ // read cell data
69+ m_cells = (CELL_DATA_D1*)malloc (spool->cell_data_size [0 ] * SPOOL_CD_BLOCK_SIZE * 2 );
70+ pFile->Seek (g_levInfo.spooldata_offset + cellDataOffset * SPOOL_CD_BLOCK_SIZE, VS_SEEK_SET);
71+ pFile->Read (m_cells, spool->cell_data_size [0 ] * SPOOL_CD_BLOCK_SIZE, sizeof (char ));
72+
73+ // read cell objects
74+ m_cellObjects = (CELL_OBJECT*)malloc (spool->cell_data_size [2 ] * SPOOL_CD_BLOCK_SIZE * 2 );
75+ pFile->Seek (g_levInfo.spooldata_offset + cellObjectsOffset * SPOOL_CD_BLOCK_SIZE, VS_SEEK_SET);
76+ pFile->Read (m_cellObjects, spool->cell_data_size [2 ] * SPOOL_CD_BLOCK_SIZE, sizeof (char ));
77+ }
78+ else
79+ MsgError (" BAD PACKED CELL POINTER DATA, region = %d\n " , m_regionNumber);
80+
81+ delete [] packed_cell_pointers;
82+
83+ // even if error occured we still need it to be here
84+ m_loaded = true ;
85+
86+ m_owner->OnRegionLoaded (this );
87+
88+ // TODO: PVS and heightmap data
89+ }
90+
91+ CELL_OBJECT* CDriver1LevelRegion::GetCellObject (int num) const
92+ {
93+ CDriver1LevelMap* owner = (CDriver1LevelMap*)m_owner;
94+
95+ int numStraddlers = owner->m_numStraddlers ;
96+
97+ if (num >= numStraddlers)
98+ {
99+ num -= owner->m_cell_objects_add [m_regionBarrelNumber] + numStraddlers;
100+ return &m_cellObjects[num];
101+ }
102+
103+ return &owner->m_straddlers [num];
104+ }
105+
106+
107+ // -------------------------------------------------------------------------------------------
108+
109+ void CDriver1LevelMap::FreeAll ()
110+ {
111+ int total_regions = m_regions_across * m_regions_down;
112+
113+ if (m_regions)
114+ {
115+ for (int i = 0 ; i < total_regions; i++)
116+ m_regions[i].FreeAll ();
117+ }
118+
119+ delete[] m_regions;
120+ m_regions = nullptr ;
121+
122+ delete[] m_straddlers;
123+ m_straddlers = nullptr ;
124+
125+ CBaseLevelMap::FreeAll ();
126+ }
127+
128+ // -------------------------------------------------------------
129+ // Loads map lump, Driver 2 version
130+ // -------------------------------------------------------------
131+ void CDriver1LevelMap::LoadMapLump (IVirtualStream* pFile)
132+ {
133+ int l_ofs = pFile->Tell ();
134+
135+ CBaseLevelMap::LoadMapLump (pFile);
136+
137+ // read straddlers
138+ // Driver 1 CO
139+ m_straddlers = new CELL_OBJECT[m_numStraddlers];
140+ pFile->Read (m_straddlers, m_numStraddlers, sizeof (CELL_OBJECT));
141+
142+ pFile->Seek (l_ofs, VS_SEEK_SET);
143+ }
144+
145+ // -------------------------------------------------------------
146+ // Load spool info, Driver 2 version
147+ // -------------------------------------------------------------
148+ void CDriver1LevelMap::LoadSpoolInfoLump (IVirtualStream* pFile)
149+ {
150+ int l_ofs = pFile->Tell ();
151+
152+ CBaseLevelMap::LoadSpoolInfoLump (pFile);
153+
154+ // Init regions
155+ int total_regions = m_regions_across * m_regions_down;
156+
157+ m_regions = new CDriver1LevelRegion[total_regions];
158+
159+ for (int i = 0 ; i < total_regions; i++)
160+ {
161+ const int region_x = i % m_regions_across;
162+ const int region_z = (i - region_x) / m_regions_across;
163+
164+ m_regions[i].m_owner = this ;
165+ m_regions[i].m_regionX = region_x;
166+ m_regions[i].m_regionZ = region_z;
167+ m_regions[i].m_regionNumber = i;
168+ m_regions[i].m_regionBarrelNumber = (region_x & 1 ) + (region_z & 1 ) * 2 ;
169+ }
170+
171+ // seek back
172+ pFile->Seek (l_ofs, VS_SEEK_SET);
173+ }
174+
175+ CBaseLevelRegion* CDriver1LevelMap::GetRegion (const XZPAIR& cell) const
176+ {
177+ // lookup region
178+ const int region_x = cell.x / m_mapInfo.region_size ;
179+ const int region_z = cell.z / m_mapInfo.region_size ;
180+
181+ return &m_regions[region_x + region_z * m_regions_across];
182+ }
183+
184+ CBaseLevelRegion* CDriver1LevelMap::GetRegion (int regionIdx) const
185+ {
186+ return &m_regions[regionIdx];
187+ }
188+
189+ void CDriver1LevelMap::SpoolRegion (const XZPAIR& cell)
190+ {
191+ CDriver1LevelRegion* region = (CDriver1LevelRegion*)GetRegion (cell);
192+
193+ if (!region->m_loaded )
194+ {
195+ if (m_regionSpoolInfoOffsets[region->m_regionNumber ] != REGION_EMPTY)
196+ {
197+ Spool* spool = (Spool*)((ubyte*)m_regionSpoolInfo + m_regionSpoolInfoOffsets[region->m_regionNumber ]);
198+ region->LoadRegionData (g_levStream, spool);
199+ region->LoadAreaData (g_levStream);
200+ }
201+ else
202+ region->m_loaded = true ;
203+ }
204+ }
205+
206+ void CDriver1LevelMap::SpoolRegion (int regionIdx)
207+ {
208+ CDriver1LevelRegion* region = (CDriver1LevelRegion*)GetRegion (regionIdx);
209+
210+ if (!region->m_loaded )
211+ {
212+ if (m_regionSpoolInfoOffsets[region->m_regionNumber ] != REGION_EMPTY)
213+ {
214+ Spool* spool = (Spool*)((ubyte*)m_regionSpoolInfo + m_regionSpoolInfoOffsets[region->m_regionNumber ]);
215+ region->LoadRegionData (g_levStream, spool);
216+ region->LoadAreaData (g_levStream);
217+ }
218+ else
219+ region->m_loaded = true ;
220+ }
221+ }
222+
223+ // -------------------------------------------------------------
224+ // returns first cell object of cell
225+ // -------------------------------------------------------------
226+ CELL_OBJECT* CDriver1LevelMap::GetFirstCop (CELL_ITERATOR_D1* iterator, int cellx, int cellz) const
227+ {
228+ // lookup region
229+ const int region_x = cellx / m_mapInfo.region_size ;
230+ const int region_z = cellz / m_mapInfo.region_size ;
231+
232+ int regionIdx = region_x + region_z * m_regions_across;
233+
234+ CDriver1LevelRegion& region = m_regions[regionIdx];
235+
236+ iterator->region = ®ion;
237+
238+ // don't do anything on empty or non-spooled regions
239+ if (!region.m_cells )
240+ return nullptr ;
241+
242+ // get cell index on the region
243+ const int region_cell_x = cellx % m_mapInfo.region_size ;
244+ const int region_cell_z = cellz % m_mapInfo.region_size ;
245+
246+ // FIXME: might be incorrect
247+ int cell_index = region_cell_x + region_cell_z * m_mapInfo.region_size ;
248+
249+ ushort cell_ptr = region.m_cellPointers [cell_index];
250+
251+ if (cell_ptr == 0xFFFF )
252+ return nullptr ;
253+
254+ // get the packed cell data start and near cell
255+ CELL_DATA_D1& cell = region.m_cells [cell_ptr];
256+
257+ CELL_OBJECT* pco = region.GetCellObject (cell.num & 0x3fff );
258+
259+ iterator->pcd = &cell;
260+ iterator->pco = pco;
261+
262+ return pco;
263+ }
264+
265+ // -------------------------------------------------------------
266+ // iterates cell objects
267+ // -------------------------------------------------------------
268+ CELL_OBJECT* CDriver1LevelMap::GetNextCop (CELL_ITERATOR_D1* iterator) const
269+ {
270+ ushort cell_ptr = iterator->pcd ->next_ptr ;
271+
272+ if (cell_ptr != 0xFFFF )
273+ {
274+ CDriver1LevelRegion* region = iterator->region ;
275+ cell_ptr -= m_cell_slots_add[region->m_regionBarrelNumber ];
276+
277+ // get the packed cell data start and near cell
278+ CELL_DATA_D1& cell = region->m_cells [cell_ptr];
279+ iterator->pcd = &cell;
280+
281+ CELL_OBJECT* pco = region->GetCellObject (cell.num & 0x3fff );
282+ iterator->pco = pco;
283+
284+ return pco;
285+ }
286+
287+ return nullptr ;
288+ }
0 commit comments