1 /*
2 BStone: A Source port of
3 Blake Stone: Aliens of Gold and Blake Stone: Planet Strike
4
5 Copyright (c) 1992-2013 Apogee Entertainment, LLC
6 Copyright (c) 2013-2015 Boris I. Bendovsky (bibendovsky@hotmail.com)
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24
25 #include "id_pm.h"
26 #include "id_heads.h"
27
28
29 // File specific variables
30 std::string PageFileName = "VSWAP.";
31
32 int ChunksInFile = 0;
33 int PMSpriteStart = 0;
34 int PMSoundStart = 0;
35
36
37 namespace {
38
39
40 using RawData = std::vector<uint8_t>;
41
42 bstone::FileStream PageFile;
43 RawData raw_data;
44 uint32_t* chunks_offsets = nullptr;
45
46
47 } // namespace
48
49
open_page_file(const std::string & file_name)50 static void open_page_file(
51 const std::string& file_name)
52 {
53 PageFile.open(file_name);
54
55 if (!PageFile.is_open()) {
56 ::Quit("Failed to open page file \"{}\".", file_name);
57 }
58
59 const auto file_length = PageFile.get_size();
60
61 if (file_length > 4 * 1024 * 1024) {
62 ::Quit("Page file is too large.");
63 }
64
65 const auto file_length_32 = static_cast<int32_t>(file_length);
66
67 raw_data.resize(file_length_32 + PMPageSize);
68
69 if (PageFile.read(raw_data.data(), file_length_32) != file_length_32)
70 {
71 ::Quit("Page file read error.");
72 }
73
74 bstone::MemoryBinaryReader reader(raw_data.data(), file_length);
75
76 ChunksInFile = bstone::Endian::le(reader.read_u16());
77 PMSpriteStart = bstone::Endian::le(reader.read_u16());
78 PMSoundStart = bstone::Endian::le(reader.read_u16());
79
80 chunks_offsets = reinterpret_cast<uint32_t*>(&raw_data[6]);
81 bstone::Endian::lei(chunks_offsets, ChunksInFile + 1);
82 }
83
PM_Startup()84 void PM_Startup()
85 {
86 ::PM_Shutdown();
87 ::open_page_file(::data_dir + PageFileName);
88 }
89
PM_Shutdown()90 void PM_Shutdown()
91 {
92 PageFile.close();
93
94 ChunksInFile = 0;
95 PMSpriteStart = 0;
96 PMSoundStart = 0;
97
98 RawData{}.swap(raw_data);
99
100 chunks_offsets = nullptr;
101 }
102
PM_GetPage(int page_number)103 void* PM_GetPage(
104 int page_number)
105 {
106 if (page_number >= ChunksInFile) {
107 ::Quit("Invalid page request.");
108 }
109
110 uint32_t offset = chunks_offsets[page_number];
111
112 if (offset == 0) {
113 ::Quit("Tried to load a sparse page.");
114 }
115
116 return &raw_data[offset];
117 }
118
PM_GetSoundPage(int page_number)119 void* PM_GetSoundPage(
120 int page_number)
121 {
122 return PM_GetPage(PMSoundStart + page_number);
123 }
124
PM_GetSpritePage(int page_number)125 void* PM_GetSpritePage(
126 int page_number)
127 {
128 return PM_GetPage(PMSpriteStart + page_number);
129 }
130