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