1 #include "xr_ai_version.h"
2 #include "xr_level_graph.h"
3 #include "xr_file_system.h"
4 
5 using namespace xray_re;
6 
xr_level_graph()7 xr_level_graph::xr_level_graph(): m_version(AI_VERSION_8),
8 	m_levels(0), m_vertices(0), m_edges(0), m_death_points(0)
9 {
10 	m_guid.reset();
11 }
12 
~xr_level_graph()13 xr_level_graph::~xr_level_graph()
14 {
15 	delete[] m_levels;
16 	delete[] m_vertices;
17 	delete[] m_edges;
18 	delete[] m_death_points;
19 }
20 
load(xr_reader & r)21 void xr_level_graph::load(xr_reader& r)
22 {
23 	m_version = r.r_u8();
24 	m_num_vertices = r.r_u16();
25 	if (m_num_vertices == 0) {
26 		// looks like an older 2215-style v8 format, so
27 		// make sure the highest byte is zero.
28 		unsigned high = r.r_u8();
29 		xr_assert(m_version == AI_VERSION_8 && high == 0);
30 		m_version = AI_VERSION_2215;
31 
32 		m_num_levels = r.r_u32();
33 		m_num_vertices = r.r_u32();
34 		m_num_edges = r.r_u32();
35 		m_num_death_points = r.r_u32();
36 		m_guid.load(r);
37 
38 		m_levels = new gg_level[m_num_levels];
39 		r.r_cseq(m_num_levels, m_levels, gg_level2215_io());
40 		unsigned edge_base = m_num_vertices * sizeof(gg_vertex_2215);
41 		unsigned death_point_base = edge_base + m_num_edges * sizeof(gg_edge_2215);
42 		m_vertices = new gg_vertex[m_num_vertices];
43 		r.r_cseq(m_num_vertices, m_vertices, gg_vertex2215_io(edge_base, death_point_base));
44 		m_edges = new gg_edge[m_num_edges];
45 		r.r_cseq(m_num_edges, m_edges, gg_edge2215_io());
46 	} else {
47 		// either modern 2947-style v8 or CS.
48 		xr_assert(m_version >= AI_VERSION_8 && m_version <= AI_VERSION_10);
49 		m_num_edges = r.r_u32();
50 		m_num_death_points = r.r_u32();
51 		m_guid.load(r);
52 		m_num_levels = r.r_u8();
53 
54 		m_levels = new gg_level[m_num_levels];
55 		r.r_cseq(m_num_levels, m_levels, gg_level_io());
56 		unsigned edge_base = m_num_vertices*sizeof(gg_vertex_2947);
57 		unsigned death_point_base = edge_base + m_num_edges*sizeof(gg_edge_2947);
58 		m_vertices = new gg_vertex[m_num_vertices];
59 		r.r_cseq(m_num_vertices, m_vertices, gg_vertex_io(edge_base, death_point_base));
60 		m_edges = new gg_edge[m_num_edges];
61 		r.r_cseq(m_num_edges, m_edges, gg_edge_io());
62 	}
63 	if (m_num_death_points) {
64 		m_death_points = new gg_level_point[m_num_death_points];
65 		r.r_cseq(m_num_death_points, m_death_points, gg_level_point_io());
66 	}
67 }
68 
save(xr_writer & w) const69 void xr_level_graph::save(xr_writer& w) const
70 {
71 	if (m_version == AI_VERSION_2215) {
72 		w.w_u32(AI_VERSION_8);
73 		w.w_u32(m_num_levels);
74 		w.w_u32(m_num_vertices);
75 		w.w_u32(m_num_edges);
76 		w.w_u32(m_num_death_points);
77 		m_guid.save(w);
78 
79 		w.w_cseq(m_num_levels, m_levels, gg_level2215_io());
80 		unsigned edge_base = m_num_vertices*sizeof(gg_vertex_2215);
81 		unsigned death_point_base = m_num_edges*sizeof(gg_edge_2215) + edge_base;
82 		w.w_cseq(m_num_vertices, m_vertices, gg_vertex2215_io(edge_base, death_point_base));
83 		w.w_cseq(m_num_edges, m_edges, gg_edge2215_io());
84 	} else {
85 		w.w_u8(m_version);
86 		w.w_size_u16(m_num_vertices);
87 		w.w_u32(m_num_edges);
88 		w.w_u32(m_num_death_points);
89 		m_guid.save(w);
90 		w.w_size_u8(m_num_levels);
91 
92 		w.w_cseq(m_num_levels, m_levels, gg_level_io());
93 		unsigned edge_base = m_num_vertices*sizeof(gg_vertex_2947);
94 		unsigned death_point_base = m_num_edges*sizeof(gg_edge_2947) + edge_base;
95 		w.w_cseq(m_num_vertices, m_vertices, gg_vertex_io(edge_base, death_point_base));
96 		w.w_cseq(m_num_edges, m_edges, gg_edge_io());
97 	}
98 	if (m_num_death_points)
99 		w.w_cseq(m_num_death_points, m_death_points, gg_level_point_io());
100 }
101 
load(const char * path,const char * name)102 bool xr_level_graph::load(const char* path, const char* name)
103 {
104 	xr_file_system& fs = xr_file_system::instance();
105 	xr_reader* r = fs.r_open(path, name);
106 	if (r == 0)
107 		return false;
108 	load(*r);
109 	fs.r_close(r);
110 	return true;
111 }
112 
save(const char * path,const char * name) const113 bool xr_level_graph::save(const char* path, const char* name) const
114 {
115 	xr_file_system& fs = xr_file_system::instance();
116 	xr_writer* w = fs.w_open(path, name);
117 	if (w == 0)
118 		return false;
119 	save(*w);
120 	fs.w_close(w);
121 	return true;
122 }
123