Skip to content

Commit d9632a2

Browse files
committed
- D1 support; split region sources to shared, D1 and D2
1 parent 762913b commit d9632a2

File tree

8 files changed

+479
-63
lines changed

8 files changed

+479
-63
lines changed

DriverLevelTool/driver_routines/level.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include "driver_level.h"
2+
3+
#include "regions_d1.h"
24
#include "regions_d2.h"
5+
36
#include "core/VirtualStream.h"
47
#include "util/DkList.h"
58

@@ -124,8 +127,8 @@ void ProcessLumps(IVirtualStream* pFile)
124127
// failed to detect Driver 1 level file - try Driver 2 loader
125128
if (g_format >= LEV_FORMAT_DRIVER2_ALPHA16 || g_format == LEV_FORMAT_AUTODETECT)
126129
g_levMap = new CDriver2LevelMap();
127-
//else
128-
// g_levMap = new CDriver1LevelMap();
130+
else
131+
g_levMap = new CDriver1LevelMap();
129132
}
130133

131134
int lump_count = 255; // Driver 2 difference: you not need to read lump count

DriverLevelTool/driver_routines/regions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ int CBaseLevelRegion::UnpackCellPointers(ushort* dest_ptrs, char* src_data, int
136136

137137
void CBaseLevelRegion::LoadAreaData(IVirtualStream* pFile)
138138
{
139-
if (m_spoolInfo->super_region == 0xFF)
139+
if (!m_spoolInfo || m_spoolInfo && m_spoolInfo->super_region == 0xFF)
140140
return;
141141

142142
int areaDataNum = m_spoolInfo->super_region;
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
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("---------\nSpool %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 = &region;
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+
}

DriverLevelTool/driver_routines/region_d1.h renamed to DriverLevelTool/driver_routines/regions_d1.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
#define REGION_D1
33
#include "regions.h"
44

5-
65
//----------------------------------------------------------------------------------
76
// DRIVER 1
87
//----------------------------------------------------------------------------------
98

9+
struct CELL_ITERATOR_D1
10+
{
11+
CDriver1LevelRegion* region;
12+
CELL_DATA_D1* pcd;
13+
CELL_OBJECT* pco;
14+
};
15+
16+
1017
// Driver 1 region
1118
class CDriver1LevelRegion : public CBaseLevelRegion
1219
{
@@ -18,22 +25,15 @@ class CDriver1LevelRegion : public CBaseLevelRegion
1825
CELL_OBJECT* GetCellObject(int num) const;
1926

2027
protected:
21-
CELL_DATA* m_cells{ nullptr }; // cell data that holding information about cell pointers. 3D world seeks cells first here
28+
CELL_DATA_D1* m_cells{ nullptr }; // cell data that holding information about cell pointers. 3D world seeks cells first here
2229
CELL_OBJECT* m_cellObjects{ nullptr }; // cell objects that represents objects placed in the world
2330
};
2431

25-
struct CELL_ITERATOR_D1
26-
{
27-
CDriver1LevelRegion* region;
28-
CELL_DATA_D1* pcd;
29-
CELL_OBJECT* pco;
30-
XZPAIR nearCell;
31-
};
3232

3333
// Driver 1 level map
3434
class CDriver1LevelMap : public CBaseLevelMap
3535
{
36-
friend class CDriver2LevelRegion;
36+
friend class CDriver1LevelRegion;
3737
public:
3838
void FreeAll() override;
3939

@@ -50,8 +50,8 @@ class CDriver1LevelMap : public CBaseLevelMap
5050

5151
//----------------------------------------
5252
// cell iterator
53-
PACKED_CELL_OBJECT* GetFirstPackedCop(CELL_ITERATOR_D1* iterator, int cellx, int cellz) const;
54-
PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR_D1* iterator) const;
53+
CELL_OBJECT* GetFirstCop(CELL_ITERATOR_D1* iterator, int cellx, int cellz) const;
54+
CELL_OBJECT* GetNextCop(CELL_ITERATOR_D1* iterator) const;
5555

5656
protected:
5757

0 commit comments

Comments
 (0)