OSDN Git Service

[Refactor] #40532 Moved save.c/h from savedata/ to save/
[hengbandforosx/hengbandosx.git] / src / savedata / floor-loader.c
1 #include "savedata/floor-loader.h"
2 #include "floor/floor-generate.h"
3 #include "game-option/birth-options.h"
4 #include "grid/feature.h"
5 #include "grid/grid.h"
6 #include "io/files-util.h"
7 #include "io/uid-checker.h"
8 #include "monster-race/monster-race.h"
9 #include "monster/monster-info.h"
10 #include "monster/monster-list.h"
11 #include "object-hook/hook-checker.h"
12 #include "savedata/angband-version-comparer.h"
13 #include "savedata/item-loader.h"
14 #include "savedata/monster-loader.h"
15 #include "savedata/load-util.h"
16 #include "savedata/load-v1-5-0.h"
17 #include "savedata/old-feature-types.h"
18 #include "save/save.h"
19 #include "system/angband-version.h"
20 #include "system/floor-type-definition.h"
21 #include "system/object-type-definition.h"
22 #include "util/angband-files.h"
23 #include "world/world-object.h"
24 #include "world/world.h"
25
26 /*!
27  * @brief 保存されたフロアを読み込む / Read the saved floor
28  * @param player_ptr プレーヤーへの参照ポインタ
29  * @param sf_ptr 最後に保存されたフロアへの参照ポインタ
30  * @return info読み込みエラーコード
31  * @details
32  * この関数は、セーブデータの互換性を保つために多くのデータ改変処理を備えている。
33  * 現在確認している処理は以下の通り、
34  * <ul>
35  * <li>1.7.0.2で8bitだったgrid_typeのfeat,mimicのID値を16bitに拡張する処理。</li>
36  * <li>1.7.0.8までに廃止、IDなどを差し替えたクエスト番号を置換する処理。</li>
37  * </ul>
38  * The monsters/objects must be loaded in the same order
39  * that they were stored, since the actual indexes matter.
40  */
41 errr rd_saved_floor(player_type *player_ptr, saved_floor_type *sf_ptr)
42 {
43     grid_template_type *templates;
44     floor_type *floor_ptr = player_ptr->current_floor_ptr;
45     clear_cave(player_ptr);
46     player_ptr->x = player_ptr->y = 0;
47
48     if (!sf_ptr) {
49         s16b tmp16s;
50         rd_s16b(&tmp16s);
51         floor_ptr->dun_level = (DEPTH)tmp16s;
52         floor_ptr->base_level = floor_ptr->dun_level;
53     } else {
54         s16b tmp16s;
55         rd_s16b(&tmp16s);
56         if (tmp16s != sf_ptr->floor_id)
57             return 171;
58
59         byte tmp8u;
60         rd_byte(&tmp8u);
61         if (tmp8u != sf_ptr->savefile_id)
62             return 171;
63
64         rd_s16b(&tmp16s);
65         if (tmp16s != sf_ptr->dun_level)
66             return 171;
67         floor_ptr->dun_level = sf_ptr->dun_level;
68
69         s32b tmp32s;
70         rd_s32b(&tmp32s);
71         if (tmp32s != sf_ptr->last_visit)
72             return 171;
73
74         u32b tmp32u;
75         rd_u32b(&tmp32u);
76         if (tmp32u != sf_ptr->visit_mark)
77             return 171;
78
79         rd_s16b(&tmp16s);
80         if (tmp16s != sf_ptr->upper_floor_id)
81             return 171;
82
83         rd_s16b(&tmp16s);
84         if (tmp16s != sf_ptr->lower_floor_id)
85             return 171;
86     }
87
88     s16b tmp16s;
89     rd_s16b(&tmp16s);
90     floor_ptr->base_level = (DEPTH)tmp16s;
91     rd_s16b(&tmp16s);
92     floor_ptr->num_repro = (MONSTER_NUMBER)tmp16s;
93
94     u16b tmp16u;
95     rd_u16b(&tmp16u);
96     player_ptr->y = (POSITION)tmp16u;
97
98     rd_u16b(&tmp16u);
99     player_ptr->x = (POSITION)tmp16u;
100
101     rd_s16b(&tmp16s);
102     floor_ptr->height = (POSITION)tmp16s;
103     rd_s16b(&tmp16s);
104     floor_ptr->width = (POSITION)tmp16s;
105
106     rd_byte(&player_ptr->feeling);
107
108     u16b limit;
109     rd_u16b(&limit);
110     C_MAKE(templates, limit, grid_template_type);
111
112     for (int i = 0; i < limit; i++) {
113         grid_template_type *ct_ptr = &templates[i];
114         rd_u16b(&tmp16u);
115         ct_ptr->info = (BIT_FLAGS)tmp16u;
116         if (h_older_than(1, 7, 0, 2)) {
117             byte tmp8u;
118             rd_byte(&tmp8u);
119             ct_ptr->feat = (s16b)tmp8u;
120             rd_byte(&tmp8u);
121             ct_ptr->mimic = (s16b)tmp8u;
122         } else {
123             rd_s16b(&ct_ptr->feat);
124             rd_s16b(&ct_ptr->mimic);
125         }
126
127         rd_s16b(&ct_ptr->special);
128     }
129
130     POSITION ymax = floor_ptr->height;
131     POSITION xmax = floor_ptr->width;
132     for (POSITION x = 0, y = 0; y < ymax;) {
133         byte count;
134         rd_byte(&count);
135
136         u16b id = 0;
137         byte tmp8u;
138         do {
139             rd_byte(&tmp8u);
140             id += tmp8u;
141         } while (tmp8u == MAX_UCHAR);
142
143         for (int i = count; i > 0; i--) {
144             grid_type *g_ptr = &floor_ptr->grid_array[y][x];
145             g_ptr->info = templates[id].info;
146             g_ptr->feat = templates[id].feat;
147             g_ptr->mimic = templates[id].mimic;
148             g_ptr->special = templates[id].special;
149
150             if (++x >= xmax) {
151                 x = 0;
152                 if (++y >= ymax)
153                     break;
154             }
155         }
156     }
157
158     /* Quest 18 was removed */
159     if (h_older_than(1, 7, 0, 6) && !vanilla_town) {
160         for (POSITION y = 0; y < ymax; y++) {
161             for (POSITION x = 0; x < xmax; x++) {
162                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
163
164                 if ((g_ptr->special == OLD_QUEST_WATER_CAVE) && !floor_ptr->dun_level) {
165                     if (g_ptr->feat == OLD_FEAT_QUEST_ENTER) {
166                         g_ptr->feat = feat_tree;
167                         g_ptr->special = 0;
168                     } else if (g_ptr->feat == OLD_FEAT_BLDG_1) {
169                         g_ptr->special = lite_town ? QUEST_OLD_CASTLE : QUEST_ROYAL_CRYPT;
170                     }
171                 } else if ((g_ptr->feat == OLD_FEAT_QUEST_EXIT) && (floor_ptr->inside_quest == OLD_QUEST_WATER_CAVE)) {
172                     g_ptr->feat = feat_up_stair;
173                     g_ptr->special = 0;
174                 }
175             }
176         }
177     }
178
179     C_KILL(templates, limit, grid_template_type);
180     rd_u16b(&limit);
181     if (limit > current_world_ptr->max_o_idx)
182         return 151;
183     for (int i = 1; i < limit; i++) {
184         OBJECT_IDX o_idx;
185         object_type *o_ptr;
186         o_idx = o_pop(floor_ptr);
187         if (i != o_idx)
188             return 152;
189
190         o_ptr = &floor_ptr->o_list[o_idx];
191         rd_item(player_ptr, o_ptr);
192
193         if (object_is_held_monster(o_ptr)) {
194             monster_type *m_ptr;
195             m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
196             o_ptr->next_o_idx = m_ptr->hold_o_idx;
197             m_ptr->hold_o_idx = o_idx;
198         } else {
199             grid_type *g_ptr = &floor_ptr->grid_array[o_ptr->iy][o_ptr->ix];
200             o_ptr->next_o_idx = g_ptr->o_idx;
201             g_ptr->o_idx = o_idx;
202         }
203     }
204
205     rd_u16b(&limit);
206     if (limit > current_world_ptr->max_m_idx)
207         return 161;
208
209     for (int i = 1; i < limit; i++) {
210         grid_type *g_ptr;
211         MONSTER_IDX m_idx;
212         monster_type *m_ptr;
213         m_idx = m_pop(floor_ptr);
214         if (i != m_idx)
215             return 162;
216
217         m_ptr = &floor_ptr->m_list[m_idx];
218         rd_monster(player_ptr, m_ptr);
219         g_ptr = &floor_ptr->grid_array[m_ptr->fy][m_ptr->fx];
220         g_ptr->m_idx = m_idx;
221         real_r_ptr(m_ptr)->cur_num++;
222     }
223
224     return 0;
225 }
226
227 /*!
228  * @brief 保存フロア読み込みのサブ関数 / Actually load and verify a floor save data
229  * @param player_ptr プレーヤーへの参照ポインタ
230  * @param sf_ptr 保存フロア読み込み先
231  * @return 成功したらtrue
232  */
233 static bool load_floor_aux(player_type *player_ptr, saved_floor_type *sf_ptr)
234 {
235     u32b n_x_check, n_v_check;
236     u32b o_x_check, o_v_check;
237
238     load_xor_byte = 0;
239     byte tmp8u;
240     rd_byte(&tmp8u);
241
242     v_check = 0L;
243     x_check = 0L;
244
245     current_world_ptr->h_ver_extra = H_VER_EXTRA;
246     current_world_ptr->h_ver_patch = H_VER_PATCH;
247     current_world_ptr->h_ver_minor = H_VER_MINOR;
248     current_world_ptr->h_ver_major = H_VER_MAJOR;
249
250     u32b tmp32u;
251     rd_u32b(&tmp32u);
252     if (saved_floor_file_sign != tmp32u)
253         return FALSE;
254
255     if (rd_saved_floor(player_ptr, sf_ptr))
256         return FALSE;
257
258     n_v_check = v_check;
259     rd_u32b(&o_v_check);
260
261     if (o_v_check != n_v_check)
262         return FALSE;
263
264     n_x_check = x_check;
265     rd_u32b(&o_x_check);
266
267     if (o_x_check != n_x_check)
268         return FALSE;
269     return TRUE;
270 }
271
272 /*!
273  * @brief 一時保存フロア情報を読み込む / Attempt to load the temporarily saved-floor data
274  * @param player_ptr プレーヤーへの参照ポインタ
275  * @param sf_ptr 保存フロア読み込み先
276  * @param mode オプション
277  * @return 成功したらtrue
278  */
279 bool load_floor(player_type *player_ptr, saved_floor_type *sf_ptr, BIT_FLAGS mode)
280 {
281     /*
282      * Temporary files are always written in system depended kanji
283      * code.
284      */
285 #ifdef JP
286 #ifdef EUC
287     kanji_code = 2;
288 #endif
289 #ifdef SJIS
290     kanji_code = 3;
291 #endif
292 #else
293     kanji_code = 1;
294 #endif
295
296     FILE *old_fff = NULL;
297     byte old_xor_byte = 0;
298     u32b old_v_check = 0;
299     u32b old_x_check = 0;
300     byte old_h_ver_major = 0;
301     byte old_h_ver_minor = 0;
302     byte old_h_ver_patch = 0;
303     byte old_h_ver_extra = 0;
304     if (mode & SLF_SECOND) {
305         old_fff = loading_savefile;
306         old_xor_byte = load_xor_byte;
307         old_v_check = v_check;
308         old_x_check = x_check;
309         old_h_ver_major = current_world_ptr->h_ver_major;
310         old_h_ver_minor = current_world_ptr->h_ver_minor;
311         old_h_ver_patch = current_world_ptr->h_ver_patch;
312         old_h_ver_extra = current_world_ptr->h_ver_extra;
313     }
314
315     char floor_savefile[1024];
316     sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
317
318     safe_setuid_grab(player_ptr);
319     loading_savefile = angband_fopen(floor_savefile, "rb");
320     safe_setuid_drop();
321
322     bool is_save_successful = TRUE;
323     if (!loading_savefile)
324         is_save_successful = FALSE;
325
326     if (is_save_successful) {
327         is_save_successful = load_floor_aux(player_ptr, sf_ptr);
328         if (ferror(loading_savefile))
329             is_save_successful = FALSE;
330
331         angband_fclose(loading_savefile);
332         safe_setuid_grab(player_ptr);
333         if (!(mode & SLF_NO_KILL))
334             (void)fd_kill(floor_savefile);
335
336         safe_setuid_drop();
337     }
338
339     if (mode & SLF_SECOND) {
340         loading_savefile = old_fff;
341         load_xor_byte = old_xor_byte;
342         v_check = old_v_check;
343         x_check = old_x_check;
344         current_world_ptr->h_ver_major = old_h_ver_major;
345         current_world_ptr->h_ver_minor = old_h_ver_minor;
346         current_world_ptr->h_ver_patch = old_h_ver_patch;
347         current_world_ptr->h_ver_extra = old_h_ver_extra;
348     }
349
350     byte old_kanji_code = kanji_code;
351     kanji_code = old_kanji_code;
352     return is_save_successful;
353 }