2 * @brief セーブファイル読み込み処理 / Purpose: support for loading savefiles -BEN-
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
7 * This software may be copied and distributed for educational, research,
8 * and not for profit purposes provided that this copyright and statement
9 * are included in all such copies. Other copyrights may also apply.
12 #include "load/load.h"
13 #include "dungeon/quest.h"
14 #include "game-option/birth-options.h"
15 #include "game-option/runtime-arguments.h"
16 #include "io/files-util.h"
17 #include "io/report.h"
18 #include "io/uid-checker.h"
19 #include "load/angband-version-comparer.h"
20 #include "load/dummy-loader.h"
21 #include "load/dungeon-loader.h"
22 #include "load/extra-loader.h"
23 #include "load/info-loader.h"
24 #include "load/inventory-loader.h"
25 #include "load/item-loader.h"
26 #include "load/load-util.h"
27 #include "load/load-v1-5-0.h"
28 #include "load/load-v1-7-0.h"
29 #include "load/load-zangband.h"
30 #include "load/lore-loader.h"
31 #include "load/option-loader.h"
32 #include "load/player-info-loader.h"
33 #include "load/quest-loader.h"
34 #include "load/store-loader.h"
35 #include "load/world-loader.h"
36 #include "player-info/class-info.h"
37 #include "player-info/race-info.h"
38 #include "player/player-personality.h"
39 #include "player/player-sex.h"
40 #include "player/race-info-table.h"
41 #include "system/angband-version.h"
42 #include "system/player-type-definition.h"
43 #include "system/system-variables.h"
44 #include "util/angband-files.h"
45 #include "util/enum-converter.h"
46 #include "view/display-messages.h"
47 #include "world/world.h"
50 * @brief 変愚蛮怒 v2.1.3で追加された街とクエストについて読み込む
51 * @param creature_ptr プレーヤーへの参照ポインタ
54 static errr load_town_quest(player_type *creature_ptr)
56 if (h_older_than(2, 1, 3))
59 errr load_town_result = load_town();
60 if (load_town_result != 0)
61 return load_town_result;
63 uint16_t max_quests_load;
64 byte max_rquests_load;
65 errr load_quest_result = load_quest_info(&max_quests_load, &max_rquests_load);
66 if (load_quest_result != 0)
67 return load_quest_result;
69 analyze_quests(creature_ptr, max_quests_load, max_rquests_load);
71 /* Quest 18 was removed */
72 if (h_older_than(1, 7, 0, 6)) {
73 (void)WIPE(&quest[OLD_QUEST_WATER_CAVE], quest_type);
74 quest[OLD_QUEST_WATER_CAVE].status = QUEST_STATUS_UNTAKEN;
77 load_wilderness_info(creature_ptr);
78 return analyze_wilderness();
82 * @brief 合計のプレイ時間をロードする
84 static void rd_total_play_time()
86 if (loading_savefile_version_is_older_than(4))
89 rd_u32b(¤t_world_ptr->sf_play_time);
93 * @brief 勝利した職業フラグをロードする
95 static void rd_winner_class()
97 if (loading_savefile_version_is_older_than(4))
100 rd_FlagGroup(current_world_ptr->sf_winner, rd_byte);
101 rd_FlagGroup(current_world_ptr->sf_retired, rd_byte);
104 static void load_player_world(player_type *creature_ptr)
106 rd_total_play_time();
108 rd_base_info(creature_ptr);
109 rd_player_info(creature_ptr);
110 rd_byte((byte *)&preserve_mode);
111 rd_byte((byte *)&creature_ptr->wait_report_score);
113 rd_global_configurations(creature_ptr);
114 rd_extra(creature_ptr);
116 if (creature_ptr->energy_need < -999)
117 creature_ptr->timewalk = true;
120 load_note(_("特別情報をロードしました", "Loaded extra information"));
123 static errr load_hp(player_type *creature_ptr)
127 if (tmp16u > PY_MAX_LEVEL) {
128 load_note(format(_("ヒットポイント配列が大きすぎる(%u)!", "Too many (%u) hitpoint entries!"), tmp16u));
132 for (int i = 0; i < tmp16u; i++) {
135 creature_ptr->player_hp[i] = (HIT_POINT)tmp16s;
141 static void load_spells(player_type *creature_ptr)
143 rd_u32b(&creature_ptr->spell_learned1);
144 rd_u32b(&creature_ptr->spell_learned2);
145 rd_u32b(&creature_ptr->spell_worked1);
146 rd_u32b(&creature_ptr->spell_worked2);
147 rd_u32b(&creature_ptr->spell_forgotten1);
148 rd_u32b(&creature_ptr->spell_forgotten2);
150 if (h_older_than(0, 0, 5))
151 set_zangband_learnt_spells(creature_ptr);
153 rd_s16b(&creature_ptr->learned_spells);
155 if (h_older_than(0, 0, 6))
156 creature_ptr->add_spells = 0;
158 rd_s16b(&creature_ptr->add_spells);
161 static errr verify_checksum()
163 uint32_t n_v_check = v_check;
166 if (o_v_check == n_v_check)
169 load_note(_("チェックサムがおかしい", "Invalid checksum"));
173 static errr verify_encoded_checksum()
175 uint32_t n_x_check = x_check;
178 if (o_x_check == n_x_check)
181 load_note(_("エンコードされたチェックサムがおかしい", "Invalid encoded checksum"));
186 * @brief セーブファイル読み込み処理の実体 / Actually read the savefile
189 static errr exe_reading_savefile(player_type *creature_ptr)
195 errr load_lore_result = load_lore();
196 if (load_lore_result != 0)
197 return load_lore_result;
199 errr load_item_result = load_item();
200 if (load_item_result != 0)
201 return load_item_result;
203 errr load_town_quest_result = load_town_quest(creature_ptr);
204 if (load_town_quest_result != 0)
205 return load_town_quest_result;
208 load_note(_("クエスト情報をロードしました", "Loaded Quests"));
210 errr load_artifact_result = load_artifact();
211 if (load_artifact_result != 0)
212 return load_artifact_result;
214 load_player_world(creature_ptr);
215 errr load_hp_result = load_hp(creature_ptr);
216 if (load_hp_result != 0)
217 return load_hp_result;
219 sp_ptr = &sex_info[creature_ptr->psex];
220 rp_ptr = &race_info[enum2i(creature_ptr->prace)];
221 cp_ptr = &class_info[creature_ptr->pclass];
222 ap_ptr = &personality_info[creature_ptr->pseikaku];
224 set_zangband_class(creature_ptr);
225 mp_ptr = &m_info[creature_ptr->pclass];
227 load_spells(creature_ptr);
228 if (creature_ptr->pclass == CLASS_MINDCRAFTER)
229 creature_ptr->add_spells = 0;
231 errr load_inventory_result = load_inventory(creature_ptr);
232 if (load_inventory_result != 0)
233 return load_inventory_result;
235 errr load_store_result = load_store(creature_ptr);
236 if (load_store_result != 0)
237 return load_store_result;
239 rd_s16b(&creature_ptr->pet_follow_distance);
240 if (h_older_than(0, 4, 10))
241 set_zangband_pet(creature_ptr);
243 rd_u16b(&creature_ptr->pet_extra_flags);
245 if (!h_older_than(1, 0, 9)) {
247 C_MAKE(buf, SCREEN_BUF_MAX_SIZE, char);
248 rd_string(buf, SCREEN_BUF_MAX_SIZE);
250 screen_dump = string_make(buf);
251 C_KILL(buf, SCREEN_BUF_MAX_SIZE, char);
254 errr restore_dungeon_result = restore_dungeon(creature_ptr);
255 if (restore_dungeon_result != 0)
256 return restore_dungeon_result;
258 if (h_older_than(1, 7, 0, 6))
259 remove_water_cave(creature_ptr);
261 errr checksum_result = verify_checksum();
262 if (checksum_result != 0)
263 return checksum_result;
265 return verify_encoded_checksum();
269 * @brief セーブファイル読み込み処理 (UIDチェック等含む) / Reading the savefile (including UID check)
270 * @param player_ptr プレーヤーへの参照ポインタ
273 static errr rd_savefile(player_type *player_ptr)
275 safe_setuid_grab(player_ptr);
276 loading_savefile = angband_fopen(savefile, "rb");
278 if (!loading_savefile)
281 errr err = exe_reading_savefile(player_ptr);
282 if (ferror(loading_savefile))
285 angband_fclose(loading_savefile);
290 * @brief セーブデータ読み込みのメインルーチン /
291 * Attempt to Load a "savefile"
292 * @param creature_ptr プレーヤーへの参照ポインタ
293 * @param new_game セーブデータの新規作成が必要か否か
294 * @return セーブデータが読み込めればtrue
296 bool load_savedata(player_type *player_ptr, bool *new_game)
298 concptr what = "generic";
299 current_world_ptr->game_turn = 0;
300 player_ptr->is_dead = false;
305 if (access(savefile, 0) < 0) {
306 msg_print(_("セーブファイルがありません。", "Savefile does not exist."));
317 fd = fd_open(savefile, O_RDONLY);
322 what = _("セーブファイルを開けません", "Cannot open savefile");
326 if (fd_read(fd, (char *)(fake_ver), 4))
330 what = _("セーブファイルを読めません", "Cannot read savefile");
336 if (fake_ver[0] < FAKE_VER_PLUS) {
337 what = _("セーブデータが古すぎます", "Savefile version is too old");
343 msg_format("%s: %s", what, savefile);
348 current_world_ptr->sf_extra = fake_ver[3];
352 if (rd_savefile(player_ptr))
355 what = _("セーブファイルを解析出来ません。", "Cannot parse savefile");
359 if (!current_world_ptr->game_turn)
363 what = _("セーブファイルが壊れています", "Broken savefile");
367 msg_format(_("エラー(%s)がバージョン%d.%d.%d.%d 用セーブファイル読み込み中に発生。", "Error (%s) reading %d.%d.%d.% savefile."), what,
368 current_world_ptr->h_ver_major, current_world_ptr->h_ver_minor, current_world_ptr->h_ver_patch, current_world_ptr->h_ver_extra);
374 if (player_ptr->is_dead) {
377 current_world_ptr->character_loaded = true;
381 player_ptr->is_dead = false;
382 current_world_ptr->sf_lives++;
386 current_world_ptr->character_loaded = true;
387 uint32_t tmp = counts_read(player_ptr, 2);
388 if (tmp > player_ptr->count)
389 player_ptr->count = tmp;
391 if (counts_read(player_ptr, 0) > current_world_ptr->play_time || counts_read(player_ptr, 1) == current_world_ptr->play_time)
392 counts_write(player_ptr, 2, ++player_ptr->count);
394 counts_write(player_ptr, 1, current_world_ptr->play_time);