1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ags/shared/ac/character_info.h"
24 #include "ags/shared/ac/game_setup_struct_base.h"
25 #include "ags/shared/ac/game_version.h"
26 #include "ags/shared/ac/words_dictionary.h"
27 #include "ags/shared/script/cc_script.h"
28 #include "ags/shared/util/stream.h"
29
30 namespace AGS3 {
31
32 using AGS::Shared::Stream;
33
GameSetupStructBase()34 GameSetupStructBase::GameSetupStructBase()
35 : numviews(0)
36 , numcharacters(0)
37 , playercharacter(-1)
38 , totalscore(0)
39 , numinvitems(0)
40 , numdialog(0)
41 , numdlgmessage(0)
42 , numfonts(0)
43 , color_depth(0)
44 , target_win(0)
45 , dialog_bullet(0)
46 , hotdot(0)
47 , hotdotouter(0)
48 , uniqueid(0)
49 , numgui(0)
50 , numcursors(0)
51 , default_lipsync_frame(0)
52 , invhotdotsprite(0)
53 , dict(nullptr)
54 , globalscript(nullptr)
55 , chars(nullptr)
56 , compiled_script(nullptr)
57 , load_messages(nullptr)
58 , load_dictionary(false)
59 , load_compiled_script(false)
60 , _resolutionType(kGameResolution_Undefined)
61 , _dataUpscaleMult(1)
62 , _screenUpscaleMult(1) {
63 memset(gamename, 0, sizeof(gamename));
64 memset(options, 0, sizeof(options));
65 memset(paluses, 0, sizeof(paluses));
66 memset(defpal, 0, sizeof(defpal));
67 memset(reserved, 0, sizeof(reserved));
68 memset(messages, 0, sizeof(messages));
69 }
70
~GameSetupStructBase()71 GameSetupStructBase::~GameSetupStructBase() {
72 Free();
73 }
74
Free()75 void GameSetupStructBase::Free() {
76 for (int i = 0; i < MAXGLOBALMES; ++i) {
77 delete[] messages[i];
78 messages[i] = nullptr;
79 }
80 delete[] load_messages;
81 load_messages = nullptr;
82 delete dict;
83 dict = nullptr;
84 delete globalscript;
85 globalscript = nullptr;
86 delete compiled_script;
87 compiled_script = nullptr;
88 delete[] chars;
89 chars = nullptr;
90 }
91
SetDefaultResolution(GameResolutionType type)92 void GameSetupStructBase::SetDefaultResolution(GameResolutionType type) {
93 SetDefaultResolution(type, Size());
94 }
95
SetDefaultResolution(Size size)96 void GameSetupStructBase::SetDefaultResolution(Size size) {
97 SetDefaultResolution(kGameResolution_Custom, size);
98 }
99
SetDefaultResolution(GameResolutionType type,Size size)100 void GameSetupStructBase::SetDefaultResolution(GameResolutionType type, Size size) {
101 // Calculate native res first then remember it
102 SetNativeResolution(type, size);
103 _defGameResolution = _gameResolution;
104 // Setup data resolution according to legacy settings (if set)
105 _dataResolution = _defGameResolution;
106 if (IsLegacyHiRes() && options[OPT_NATIVECOORDINATES] == 0) {
107 _dataResolution = _defGameResolution / HIRES_COORD_MULTIPLIER;
108 }
109 OnResolutionSet();
110 }
111
SetNativeResolution(GameResolutionType type,Size game_res)112 void GameSetupStructBase::SetNativeResolution(GameResolutionType type, Size game_res) {
113 if (type == kGameResolution_Custom) {
114 _resolutionType = kGameResolution_Custom;
115 _gameResolution = game_res;
116 _letterboxSize = _gameResolution;
117 } else {
118 _resolutionType = type;
119 _gameResolution = ResolutionTypeToSize(_resolutionType, IsLegacyLetterbox());
120 _letterboxSize = ResolutionTypeToSize(_resolutionType, false);
121 }
122 }
123
SetGameResolution(GameResolutionType type)124 void GameSetupStructBase::SetGameResolution(GameResolutionType type) {
125 SetNativeResolution(type, Size());
126 OnResolutionSet();
127 }
128
SetGameResolution(Size game_res)129 void GameSetupStructBase::SetGameResolution(Size game_res) {
130 SetNativeResolution(kGameResolution_Custom, game_res);
131 OnResolutionSet();
132 }
133
OnResolutionSet()134 void GameSetupStructBase::OnResolutionSet() {
135 // The final data-to-game multiplier is always set after actual game resolution (not default one)
136 if (!_dataResolution.IsNull())
137 _dataUpscaleMult = _gameResolution.Width / _dataResolution.Width;
138 else
139 _dataUpscaleMult = 1;
140 if (!_defGameResolution.IsNull())
141 _screenUpscaleMult = _gameResolution.Width / _defGameResolution.Width;
142 else
143 _screenUpscaleMult = 1;
144 _relativeUIMult = IsLegacyHiRes() ? HIRES_COORD_MULTIPLIER : 1;
145 }
146
ReadFromFile(Stream * in)147 void GameSetupStructBase::ReadFromFile(Stream *in) {
148 in->Read(&gamename[0], GAME_NAME_LENGTH);
149 in->ReadArrayOfInt32(options, MAX_OPTIONS);
150 if (_G(loaded_game_file_version) < kGameVersion_340_4) { // TODO: this should probably be possible to deduce script API level
151 // using game data version and other options like OPT_STRICTSCRIPTING
152 options[OPT_BASESCRIPTAPI] = kScriptAPI_Undefined;
153 options[OPT_SCRIPTCOMPATLEV] = kScriptAPI_Undefined;
154 }
155 in->Read(&paluses[0], 256);
156 // colors are an array of chars
157 in->Read(&defpal[0], sizeof(RGB) * 256);
158 numviews = in->ReadInt32();
159 numcharacters = in->ReadInt32();
160 playercharacter = in->ReadInt32();
161 totalscore = in->ReadInt32();
162 numinvitems = in->ReadInt16();
163 numdialog = in->ReadInt32();
164 numdlgmessage = in->ReadInt32();
165 numfonts = in->ReadInt32();
166 color_depth = in->ReadInt32();
167 target_win = in->ReadInt32();
168 dialog_bullet = in->ReadInt32();
169 hotdot = in->ReadInt16();
170 hotdotouter = in->ReadInt16();
171 uniqueid = in->ReadInt32();
172 numgui = in->ReadInt32();
173 numcursors = in->ReadInt32();
174 GameResolutionType resolution_type = (GameResolutionType)in->ReadInt32();
175 Size game_size;
176 if (resolution_type == kGameResolution_Custom && _G(loaded_game_file_version) >= kGameVersion_330) {
177 game_size.Width = in->ReadInt32();
178 game_size.Height = in->ReadInt32();
179 }
180 SetDefaultResolution(resolution_type, game_size);
181
182 default_lipsync_frame = in->ReadInt32();
183 invhotdotsprite = in->ReadInt32();
184 in->ReadArrayOfInt32(reserved, NUM_INTS_RESERVED);
185 load_messages = new int32_t[MAXGLOBALMES];
186 in->ReadArrayOfInt32(load_messages, MAXGLOBALMES);
187
188 // - GameSetupStruct::read_words_dictionary() checks load_dictionary
189 // - load_game_file() checks load_compiled_script
190 load_dictionary = in->ReadInt32() != 0;
191 in->ReadInt32(); // globalscript
192 in->ReadInt32(); // chars
193 load_compiled_script = in->ReadInt32() != 0;
194 }
195
WriteToFile(Stream * out)196 void GameSetupStructBase::WriteToFile(Stream *out) {
197 out->Write(&gamename[0], 50);
198 out->WriteArrayOfInt32(options, 100);
199 out->Write(&paluses[0], 256);
200 // colors are an array of chars
201 out->Write(&defpal[0], sizeof(RGB) * 256);
202 out->WriteInt32(numviews);
203 out->WriteInt32(numcharacters);
204 out->WriteInt32(playercharacter);
205 out->WriteInt32(totalscore);
206 out->WriteInt16(numinvitems);
207 out->WriteInt32(numdialog);
208 out->WriteInt32(numdlgmessage);
209 out->WriteInt32(numfonts);
210 out->WriteInt32(color_depth);
211 out->WriteInt32(target_win);
212 out->WriteInt32(dialog_bullet);
213 out->WriteInt16(hotdot);
214 out->WriteInt16(hotdotouter);
215 out->WriteInt32(uniqueid);
216 out->WriteInt32(numgui);
217 out->WriteInt32(numcursors);
218 out->WriteInt32(_resolutionType);
219 if (_resolutionType == kGameResolution_Custom) {
220 out->WriteInt32(_defGameResolution.Width);
221 out->WriteInt32(_defGameResolution.Height);
222 }
223 out->WriteInt32(default_lipsync_frame);
224 out->WriteInt32(invhotdotsprite);
225 out->WriteArrayOfInt32(reserved, 17);
226 for (int i = 0; i < MAXGLOBALMES; ++i) {
227 out->WriteInt32(messages[i] ? 1 : 0);
228 }
229 out->WriteInt32(dict ? 1 : 0);
230 out->WriteInt32(0); // globalscript
231 out->WriteInt32(0); // chars
232 out->WriteInt32(compiled_script ? 1 : 0);
233 }
234
ResolutionTypeToSize(GameResolutionType resolution,bool letterbox)235 Size ResolutionTypeToSize(GameResolutionType resolution, bool letterbox) {
236 switch (resolution) {
237 case kGameResolution_Default:
238 case kGameResolution_320x200:
239 return letterbox ? Size(320, 240) : Size(320, 200);
240 case kGameResolution_320x240:
241 return Size(320, 240);
242 case kGameResolution_640x400:
243 return letterbox ? Size(640, 480) : Size(640, 400);
244 case kGameResolution_640x480:
245 return Size(640, 480);
246 case kGameResolution_800x600:
247 return Size(800, 600);
248 case kGameResolution_1024x768:
249 return Size(1024, 768);
250 case kGameResolution_1280x720:
251 return Size(1280, 720);
252 default:
253 break;
254 }
255 return Size();
256 }
257
GetScriptAPIName(ScriptAPIVersion v)258 const char *GetScriptAPIName(ScriptAPIVersion v) {
259 switch (v) {
260 case kScriptAPI_v321: return "v3.2.1";
261 case kScriptAPI_v330: return "v3.3.0";
262 case kScriptAPI_v334: return "v3.3.4";
263 case kScriptAPI_v335: return "v3.3.5";
264 case kScriptAPI_v340: return "v3.4.0";
265 case kScriptAPI_v341: return "v3.4.1";
266 case kScriptAPI_v350: return "v3.5.0-alpha";
267 case kScriptAPI_v3507: return "v3.5.0-final";
268 case kScriptAPI_v351: return "v3.5.1";
269 case kScriptAPI_v360: return "v3.6.0";
270 case kScriptAPI_Undefined: return "undefined";
271 }
272 return "unknown";
273 }
274
275 } // namespace AGS3
276