/* * Read an object * * This function attempts to "repair" old savefiles, and to extract * the most up to date values for various object fields. * * Note that Angband 2.7.9 introduced a new method for object "flags" * in which the "flags" on an object are actually extracted when they * are needed from the object kind, artifact index, ego-item index, * and two special "xtra" fields which are used to encode any "extra" * power of certain ego-items. This had the side effect that items * imported from pre-2.7.9 savefiles will lose any "extra" powers they * may have had, and also, all "uncursed" items will become "cursed" * again, including Calris, even if it is being worn at the time. As * a complete hack, items which are inscribed with "uncursed" will be * "uncursed" when imported from pre-2.7.9 savefiles. */ static void rd_item(object_type *o_ptr) { char buf[128]; /* Kind */ rd_s16b(&o_ptr->k_idx); /* Location */ rd_byte(&o_ptr->iy); rd_byte(&o_ptr->ix); /* Type/Subtype */ rd_byte(&o_ptr->tval); rd_byte(&o_ptr->sval); rd_s32b(&o_ptr->pval); rd_byte(&o_ptr->discount); rd_byte(&o_ptr->number); rd_s16b(&o_ptr->weight); rd_byte(&o_ptr->name1); rd_byte(&o_ptr->name2); rd_s32b(&o_ptr->timeout); rd_s16b(&o_ptr->to_h); rd_s16b(&o_ptr->to_d); rd_s16b(&o_ptr->to_a); rd_s16b(&o_ptr->ac); rd_byte(&o_ptr->dd); rd_byte(&o_ptr->ds); rd_byte(&o_ptr->ident); rd_byte(&o_ptr->marked); /* Old flags */ rd_u32b(&o_ptr->art_flags1); rd_u32b(&o_ptr->art_flags2); rd_u32b(&o_ptr->art_flags3); /* Monster holding object */ rd_s16b(&o_ptr->held_m_idx); /* Special powers */ rd_byte(&o_ptr->xtra1); rd_byte(&o_ptr->xtra2); rd_s16b(&o_ptr->xtra3); /* Feeling - from 2.3.1, "savefile version 1" */ rd_byte(&o_ptr->feeling); /* Inscription */ rd_string(buf, sizeof(buf)); /* If this savefile is old, maybe we need to translate the feeling */ if (sf_version < 1) { byte i; for (i = 0; i <= FEEL_MAX; i++) { if (game_inscriptions[i] == NULL) { continue; } if (streq(buf, game_inscriptions[i])) { o_ptr->feeling = i; buf[0] = 0; break; } } } /* Save the inscription */ if (buf[0]) o_ptr->inscription = quark_add(buf); /* Random artifact */ rd_string(buf, sizeof(buf)); if (buf[0]) o_ptr->art_name = quark_add(buf); /* Named ego */ rd_string(buf, sizeof(buf)); if (buf[0]) o_ptr->ego_name = quark_add(buf); /* The Python object - old */ { s32b tmp32s; rd_s32b(&tmp32s); strip_bytes(tmp32s); } #if 0 /* Mega-Hack -- handle "dungeon objects" later */ if ((o_ptr->k_idx >= 445) && (o_ptr->k_idx <= 479)) return; #endif /* Paranoia */ if (o_ptr->name1) { artifact_type *a_ptr; /* Obtain the artifact info */ a_ptr = &a_info[o_ptr->name1]; /* Verify that artifact */ if (!a_ptr->name) o_ptr->name1 = 0; } /* Paranoia */ if (o_ptr->name2) { ego_item_type *e_ptr; /* Obtain the ego-item info */ e_ptr = &e_info[o_ptr->name2]; /* Verify that ego-item */ if (!e_ptr->name) o_ptr->name2 = 0; } }
/* * Read the "extra" information */ static void rd_extra(void) { int i; byte tmp8u; s16b tmp16s; rd_string(player_name, sizeof(player_name)); rd_string(died_from, sizeof(died_from)); load_quick_start(); for (i = 0; i < 4; i++) { rd_string(history[i], sizeof(history[i])); } /* Class/Race/Gender/Spells */ rd_byte(&p_ptr->prace); rd_byte(&p_ptr->pclass); rd_byte(&p_ptr->psex); rd_byte(&p_ptr->realm1); rd_byte(&p_ptr->realm2); rd_byte(&tmp8u); /* oops */ /* Special Race/Class info */ rd_byte(&p_ptr->hitdie); rd_u16b(&p_ptr->expfact); /* Age/Height/Weight */ rd_s16b(&p_ptr->age); rd_s16b(&p_ptr->ht); rd_s16b(&p_ptr->wt); /* Read the stat info */ for (i = 0; i < 6; i++) rd_s16b(&p_ptr->stat_max[i]); for (i = 0; i < 6; i++) rd_s16b(&p_ptr->stat_cur[i]); strip_bytes(24); /* oops */ rd_s32b(&p_ptr->au); rd_s32b(&p_ptr->max_exp); rd_s32b(&p_ptr->exp); rd_u16b(&p_ptr->exp_frac); rd_s16b(&p_ptr->lev); rd_s16b(&p_ptr->town_num); /* Read arena and rewards information */ rd_s16b(&p_ptr->arena_number); rd_s16b(&p_ptr->inside_arena); rd_s16b(&p_ptr->inside_quest); rd_byte(&p_ptr->exit_bldg); rd_byte(&tmp8u); rd_s16b(&p_ptr->oldpx); rd_s16b(&p_ptr->oldpy); rd_s16b(&tmp16s); if (tmp16s > MAX_BACT) { #ifdef JP note(format("の中", tmp16s)); #else note(format("Too many (%d) building rewards!", tmp16s)); #endif } for (i = 0; i < tmp16s; i++) rd_s16b(&p_ptr->rewards[i]) ; rd_s16b(&p_ptr->mhp); rd_s16b(&p_ptr->chp); rd_u16b(&p_ptr->chp_frac); rd_s16b(&p_ptr->msp); rd_s16b(&p_ptr->csp); rd_u16b(&p_ptr->csp_frac); rd_s16b(&p_ptr->max_plv); rd_s16b(&p_ptr->max_dlv); /* Repair maximum player level XXX XXX XXX */ if (p_ptr->max_plv < p_ptr->lev) p_ptr->max_plv = p_ptr->lev; /* Repair maximum dungeon level */ if (p_ptr->max_dlv < 0) p_ptr->max_dlv = 1; /* More info */ strip_bytes(8); rd_s16b(&p_ptr->sc); strip_bytes(2); /* Read the flags */ strip_bytes(2); /* Old "rest" */ rd_s16b(&p_ptr->blind); rd_s16b(&p_ptr->paralyzed); rd_s16b(&p_ptr->confused); rd_s16b(&p_ptr->food); strip_bytes(4); /* Old "food_digested" / "protection" */ rd_s16b(&p_ptr->energy_need); rd_s16b(&p_ptr->fast); rd_s16b(&p_ptr->slow); rd_s16b(&p_ptr->afraid); rd_s16b(&p_ptr->cut); rd_s16b(&p_ptr->stun); rd_s16b(&p_ptr->poisoned); rd_s16b(&p_ptr->image); rd_s16b(&p_ptr->protevil); rd_s16b(&p_ptr->invuln); rd_s16b(&p_ptr->hero); rd_s16b(&p_ptr->shero); rd_s16b(&p_ptr->shield); rd_s16b(&p_ptr->magicdef); rd_s16b(&p_ptr->musou); rd_s16b(&p_ptr->blessed); rd_s16b(&p_ptr->tim_invis); rd_s16b(&p_ptr->word_recall); rd_s16b(&p_ptr->see_infra); rd_s16b(&p_ptr->tim_infra); rd_s16b(&p_ptr->tim_regen); rd_s16b(&p_ptr->tim_sh_fire); rd_s16b(&p_ptr->tim_sh_elec); rd_s16b(&p_ptr->tim_sh_cold); rd_s16b(&p_ptr->oppose_fire); rd_s16b(&p_ptr->oppose_cold); rd_s16b(&p_ptr->oppose_acid); rd_s16b(&p_ptr->oppose_elec); rd_s16b(&p_ptr->oppose_pois); rd_s16b(&p_ptr->tim_esp); rd_s16b(&p_ptr->tim_wraith); rd_s16b(&p_ptr->resist_magic); rd_s16b(&p_ptr->tim_radar); rd_s16b(&p_ptr->tim_might); rd_s16b(&p_ptr->tim_xtra2); rd_s16b(&p_ptr->tim_xtra3); rd_s16b(&p_ptr->tim_brand); rd_u32b(&p_ptr->xtra_brand); rd_s16b(&p_ptr->valar_patron); rd_u32b(&p_ptr->muta); /* Calc the regeneration modifier for mutations */ mutant_regenerate_mod = calc_mutant_regenerate_mod(); rd_byte(&p_ptr->confusing); rd_byte(&tmp8u); /* oops */ rd_byte(&tmp8u); p_ptr->autopick_autoregister = tmp8u ? TRUE : FALSE; rd_byte(&tmp8u); /* oops */ rd_byte(&p_ptr->searching); rd_byte(&tmp8u); /* maximize_mode was deleted */ rd_byte(&preserve_mode); rd_byte(&tmp8u); /* Future use */ for (i = 0; i < 48; i++) rd_byte(&tmp8u); /* Skip the flags */ strip_bytes(12); /* Hack -- the two "special seeds" */ rd_u32b(&seed_flavor); rd_u32b(&seed_town); /* Special stuff */ rd_u16b(&panic_save); rd_u16b(&total_winner); rd_u16b(&noscore); /* Read "death" */ rd_byte(&tmp8u); death = tmp8u; /* Read "feeling" */ rd_byte(&p_ptr->feeling); /* Turn when level began */ rd_s32b(&old_turn); /* Turn of last "feeling" */ rd_s32b(&p_ptr->feeling_turn); /* Current turn */ rd_s32b(&turn); /* Current total playtime */ rd_u32b(&playtime); }
/* * Actually read the savefile */ static errr rd_savefile_new_aux(void) { int i, j; int town_count; s32b wild_x_size; s32b wild_y_size; byte tmp8u; u16b tmp16u; u32b tmp32u; u16b tmp_k_idx; #ifdef VERIFY_CHECKSUMS u32b n_x_check, n_v_check; u32b o_x_check, o_v_check; #endif /* Mention the savefile version */ #ifdef JP note(format("バージョン %d.%d.%d のセーブ・ファイルをロード中...", #else note(format("Loading a %d.%d.%d savefile...", #endif sf_major, sf_minor, sf_patch)); /* Strip the version bytes */ strip_bytes(4); /* Hack -- decrypt */ xor_byte = sf_extra; /* Clear the checksums */ v_check = 0L; x_check = 0L; #if SAVEFILE_VERSION /* Read the version number of the savefile */ rd_u32b(&sf_version); #endif /* SAVEFILE_VERSION */ /* Operating system info */ rd_u32b(&sf_xtra); /* Time of savefile creation */ rd_u32b(&sf_when); /* Number of resurrections */ rd_u16b(&sf_lives); /* Number of times played */ rd_u16b(&sf_saves); /* Later use (always zero) */ rd_u32b(&tmp32u); /* Later use (always zero) */ rd_u16b(&tmp16u); /* Later use (always zero) */ rd_byte(&tmp8u); /* Kanji code */ rd_byte(&kanji_code); /* Read RNG state */ rd_randomizer(); #ifdef JP if (arg_fiddle) note("乱数情報をロードしました"); #else if (arg_fiddle) note("Loaded Randomizer Info"); #endif /* Then the options */ rd_options(); #ifdef JP if (arg_fiddle) note("オプションをロードしました"); #else if (arg_fiddle) note("Loaded Option Flags"); #endif /* * Munchkin players are marked * * XXX - should be replaced with a better method, * after the new scorefile-handling is implemented. */ if (munchkin_death) { /* Mark savefile */ noscore |= 0x0001; } /* Then the "messages" */ rd_messages(); #ifdef JP if (arg_fiddle) note("メッセージをロードしました"); #else if (arg_fiddle) note("Loaded Messages"); #endif /* Monster Memory */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > max_r_idx) { #ifdef JP note(format("モンスターの種族が多すぎる(%u)!", tmp16u)); #else note(format("Too many (%u) monster races!", tmp16u)); #endif return (21); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { /* Read the lore */ rd_lore(i); } #ifdef JP if (arg_fiddle) note("モンスターの思い出をロードしました"); #else if (arg_fiddle) note("Loaded Monster Memory"); #endif /* Object Memory */ rd_u16b(&tmp_k_idx); /* Incompatible save files */ if (tmp_k_idx > max_k_idx) { #ifdef JP note(format("アイテムの種類が多すぎる(%u)!", tmp16u)); #else note(format("Too many (%u) object kinds!", tmp16u)); #endif return (22); } /* Make array for object memory */ C_MAKE(obj_mem, tmp_k_idx, byte); /* Read the object memory */ for (i = 0; i < tmp_k_idx; i++) { #if 0 byte tmp8u; object_kind *k_ptr = &k_info[i]; rd_byte(&tmp8u); k_ptr->aware = (tmp8u & 0x01) ? TRUE: FALSE; k_ptr->tried = (tmp8u & 0x02) ? TRUE: FALSE; #else rd_byte(&obj_mem[i]); #endif } #ifdef JP if (arg_fiddle) note("アイテムの記録をロードしました"); #else if (arg_fiddle) note("Loaded Object Memory"); #endif #if 0 /* * Initialize arena and rewards information */ p_ptr->arena_number = 0; p_ptr->inside_arena = 0; p_ptr->inside_quest = 0; p_ptr->exit_bldg = TRUE; /* Start in town 1 */ p_ptr->town_num = 1; p_ptr->wilderness_x = 4; p_ptr->wilderness_y = 4; #endif /* Init the wilderness seeds */ for (i = 0; i < max_wild_x; i++) { for (j = 0; j < max_wild_y; j++) { wilderness[j][i].seed = randint0(0x10000000); } } /* 2.1.3 or newer version */ { u16b max_towns_load; u16b max_quests_load; byte max_rquests_load; /* Number of towns */ rd_u16b(&max_towns_load); /* Incompatible save files */ if (max_towns_load > max_towns) { #ifdef JP note(format("町が多すぎる(%u)!", max_towns_load)); #else note(format("Too many (%u) towns!", max_towns_load)); #endif return (23); } /* Number of quests */ rd_u16b(&max_quests_load); rd_byte(&max_rquests_load); /* Incompatible save files */ if (max_quests_load > max_quests) { #ifdef JP note(format("クエストが多すぎる(%u)!", max_quests_load)); #else note(format("Too many (%u) quests!", max_quests_load)); #endif return (23); } for (i = 0; i < max_quests_load; i++) { if (i < max_quests) { rd_s16b(&quest[i].status); rd_s16b(&quest[i].level); rd_byte(&quest[i].complev); /* Load quest status if quest is running */ if ((quest[i].status == QUEST_STATUS_TAKEN) || (quest[i].status == QUEST_STATUS_COMPLETED) || ((i >= MIN_RANDOM_QUEST) && (i <= (MIN_RANDOM_QUEST + max_rquests_load)))) { rd_s16b(&quest[i].cur_num); rd_s16b(&quest[i].max_num); rd_s16b(&quest[i].type); /* Load quest monster index */ rd_s16b(&quest[i].r_idx); if ((quest[i].type == QUEST_TYPE_RANDOM) && (!quest[i].r_idx)) { int r_idx; while (1) { monster_race *r_ptr; /* * Random monster 5 - 10 levels out of depth * (depending on level) */ r_idx = get_mon_num(quest[i].level + 10); r_ptr = &r_info[r_idx]; if(!(r_ptr->flags1 & RF1_UNIQUE)) continue; if (r_ptr->flags1 & RF1_QUESTOR) continue; if (r_ptr->level >= quest[i].level + 5) continue; if (r_ptr->level >= quest[i].level) break; } quest[i].r_idx = r_idx; } /* Load quest item index */ rd_s16b(&quest[i].k_idx); if (quest[i].k_idx) a_info[quest[i].k_idx].gen_flags |= TRG_QUESTITEM; /* Load quest flags */ rd_byte(&quest[i].flags); } } /* Ignore the empty quests from old versions */ else { /* Ignore quest status */ strip_bytes(2); /* Ignore quest level */ strip_bytes(2); /* * We don't have to care about the other info, * since status should be 0 for these quests anyway */ } } /* Position in the wilderness */ rd_s32b(&p_ptr->wilderness_x); rd_s32b(&p_ptr->wilderness_y); /* Size of the wilderness */ rd_s32b(&wild_x_size); rd_s32b(&wild_y_size); /* Incompatible save files */ if ((wild_x_size > max_wild_x) || (wild_y_size > max_wild_y)) { #ifdef JP note(format("荒野が大きすぎる(%u/%u)!", wild_x_size, wild_y_size)); #else note(format("Wilderness is too big (%u/%u)!", wild_x_size, wild_y_size)); #endif return (23); } /* Load the wilderness seeds */ for (i = 0; i < wild_x_size; i++) { for (j = 0; j < wild_y_size; j++) { rd_u32b(&wilderness[j][i].seed); } } } #ifdef JP if (arg_fiddle) note("クエスト情報をロードしました"); #else if (arg_fiddle) note("Loaded Quests"); #endif /* Load the Artifacts */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > max_a_idx) { #ifdef JP note(format("伝説のアイテムが多すぎる(%u)!", tmp16u)); #else note(format("Too many (%u) artifacts!", tmp16u)); #endif return (24); } /* Read the artifact flags */ for (i = 0; i < tmp16u; i++) { rd_byte(&tmp8u); a_info[i].cur_num = tmp8u; rd_byte(&tmp8u); rd_byte(&tmp8u); rd_byte(&tmp8u); } #ifdef JP if (arg_fiddle) note("伝説のアイテムをロードしました"); #else if (arg_fiddle) note("Loaded Artifacts"); #endif /* Read the extra stuff */ rd_extra(); #ifdef JP if (arg_fiddle) note("特別情報をロードしました"); #else if (arg_fiddle) note("Loaded extra information"); #endif /* Read the player_hp array */ rd_u16b(&tmp16u); /* Remark questor flag on random quester */ if (!death) { for (i = MIN_RANDOM_QUEST; i <= MAX_RANDOM_QUEST; i++) { r_info[quest[i].r_idx].flags1 |= RF1_QUESTOR; } } /* Incompatible save files */ if (tmp16u > PY_MAX_LEVEL) { #ifdef JP note(format("ヒットポイント配列が大きすぎる(%u)!", tmp16u)); #else note(format("Too many (%u) hitpoint entries!", tmp16u)); #endif return (25); } /* Read the player_hp array */ for (i = 0; i < tmp16u; i++) { rd_s16b(&player_hp[i]); } /* Important -- Initialize the sex */ sp_ptr = &sex_info[p_ptr->psex]; /* Important -- Initialize the race/class */ rp_ptr = &race_info[p_ptr->prace]; cp_ptr = &class_info[p_ptr->pclass]; /* Important -- Initialize the magic */ mp_ptr = &m_info[p_ptr->pclass]; /* Read spell info */ rd_u32b(&spell_learned1); rd_u32b(&spell_learned2); rd_u32b(&spell_worked1); rd_u32b(&spell_worked2); rd_u32b(&spell_forgotten1); rd_u32b(&spell_forgotten2); for (i = 0; i < 64; i++) { rd_byte(&spell_order[i]); } /* Read the inventory */ if (rd_inventory()) { #ifdef JP note("持ち物情報を読み込むことができません"); #else note("Unable to read inventory"); #endif return (21); } /* Read number of towns */ rd_u16b(&tmp16u); town_count = tmp16u; /* Read the stores */ rd_u16b(&tmp16u); for (i = 1; i < town_count; i++) { for (j = 0; j < tmp16u; j++) { if (rd_store(i, j)) return (22); } } for (i = 0; i < tmp_k_idx; i++) { byte tmp8u = obj_mem[i]; object_kind *k_ptr = &k_info[i]; k_ptr->aware = (tmp8u & 0x01) ? TRUE: FALSE; k_ptr->tried = (tmp8u & 0x02) ? TRUE: FALSE; } /* Free array for object memories */ C_KILL(obj_mem, tmp_k_idx, byte); /* Read the pet command settings */ if (sf_version > 2) { rd_s16b(&p_ptr->pet_follow_distance); rd_byte(&p_ptr->pet_open_doors); rd_byte(&p_ptr->pet_pickup_items); } else { rd_byte(&tmp8u); p_ptr->pet_follow_distance = tmp8u; rd_byte(&p_ptr->pet_open_doors); rd_byte(&p_ptr->pet_pickup_items); } /* I'm not dead yet... */ if (!death) { /* Dead players have no dungeon */ #ifdef JP note("ダンジョン復元中..."); #else note("Restoring Dungeon..."); #endif if (rd_dungeon()) { #ifdef JP note("ダンジョンデータ読み込み失敗"); #else note("Error reading dungeon data"); #endif return (34); } /* Read the ghost info */ rd_ghost(); { s32b tmp32s; rd_s32b(&tmp32s); strip_bytes(tmp32s); } } #ifdef VERIFY_CHECKSUMS /* Save the checksum */ n_v_check = v_check; /* Read the old checksum */ rd_u32b(&o_v_check); /* Verify */ if (o_v_check != n_v_check) { #ifdef JP note("チェックサムがおかしい"); #else note("Invalid checksum"); #endif return (11); } /* Save the encoded checksum */ n_x_check = x_check; /* Read the checksum */ rd_u32b(&o_x_check); /* Verify */ if (o_x_check != n_x_check) { #ifdef JP note("エンコードされたチェックサムがおかしい"); #else note("Invalid encoded checksum"); #endif return (11); } #endif /* Success */ return (0); }
/* * Actually read the savefile */ static errr rd_savefile_new_aux(void) { int i; byte tmp8u; u16b tmp16u; u32b tmp32u; u32b n_x_check, n_v_check; u32b o_x_check, o_v_check; /* Mention the savefile version */ note(format("Loading a %d.%d.%d savefile...", sf_major, sf_minor, sf_patch)); /* Strip the version bytes, and the game_mode byte */ strip_bytes(5); /* Hack -- decrypt */ xor_byte = sf_extra; /* Clear the checksums */ v_check = 0L; x_check = 0L; /* Operating system info */ rd_u32b(&sf_xtra); /* Time of savefile creation */ rd_u32b(&sf_when); /* Number of resurrections */ rd_u16b(&sf_lives); /* Number of times played */ rd_u16b(&sf_saves); /* Later use (always zero) */ rd_u32b(&tmp32u); /* Later use (always zero) */ rd_u32b(&tmp32u); /* Read RNG state */ rd_randomizer(); if (arg_fiddle) note("Loaded Randomizer Info"); /* Then the options */ rd_options(); if (arg_fiddle) note("Loaded Option Flags"); /* Then the "messages" */ rd_messages(); if (arg_fiddle) note("Loaded Messages"); /* Monster Memory */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->r_max) { note(format("Too many (%u) monster races!", tmp16u)); return (-1); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { /* Read the lore */ rd_monster_lore(i); } if (arg_fiddle) note("Loaded Monster Memory"); /* Object Memory */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->k_max) { note(format("Too many (%u) object kinds!", tmp16u)); return (-1); } /* Read the object memory */ for (i = 0; i < tmp16u; i++) { byte tmp8u; object_kind *k_ptr = &k_info[i]; rd_byte(&tmp8u); k_ptr->aware = (tmp8u & 0x01) ? TRUE: FALSE; k_ptr->tried = (tmp8u & 0x02) ? TRUE: FALSE; k_ptr->everseen = (tmp8u & 0x08) ? TRUE: FALSE; rd_byte(&k_ptr->squelch); /* Hack - Repair the savefile */ if (!k_ptr->everseen) k_ptr->squelch = SQUELCH_NEVER; } if (arg_fiddle) note("Loaded Object Memory"); /* Load the Quests */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->q_max) { note(format("Too many (%u) quests!", tmp16u)); return (23); } /* Load the Quests */ for (i = 0; i < tmp16u; i++) { quest_type *q_ptr = &q_info[i]; rd_byte(&q_ptr->q_type); /* Only limited info for permanent quests. The rest is detailed in quest.txt */ if (q_ptr->q_type == QUEST_PERMANENT) { rd_byte(&q_ptr->q_flags); rd_s16b(&q_ptr->q_num_killed); continue; } rd_u16b(&q_ptr->q_reward); rd_u16b(&q_ptr->q_fame_inc); rd_byte(&q_ptr->base_level); rd_byte(&q_ptr->q_theme); rd_s16b(&q_ptr->mon_idx); rd_s32b(&q_ptr->turn_counter); rd_s16b(&q_ptr->q_num_killed); rd_s16b(&q_ptr->q_max_num); rd_byte(&q_ptr->q_flags); } if (arg_fiddle) note("Loaded Quests"); /* Load the Artifacts */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->art_max) { note(format("Too many (%u) artifacts!", tmp16u)); return (-1); } /* Read the artifact flags */ for (i = 0; i < tmp16u; i++) { rd_byte(&tmp8u); a_info[i].a_cur_num = tmp8u; rd_byte(&tmp8u); rd_byte(&tmp8u); rd_byte(&tmp8u); } if (arg_fiddle) note("Loaded Artifacts"); /* Read the extra stuff */ if (rd_extra()) return (-1); if (arg_fiddle) note("Loaded extra information"); if (rd_randarts()) return (-1); if (arg_fiddle) note("Loaded Random Artifacts"); if (rd_notes()) return (-1); if (arg_fiddle) note("Loaded Notes"); if (rd_extensions()) return (-1); if (arg_fiddle) note("Loaded Extensions"); /* Important -- Initialize the sex */ sp_ptr = &sex_info[p_ptr->psex]; /* Important -- Initialize the race/class */ rp_ptr = &p_info[p_ptr->prace]; cp_ptr = &c_info[p_ptr->pclass]; /* Important -- Initialize the magic */ mp_ptr = &cp_ptr->spells; /* Hack - In NPP 050, we moved a spell out of ironman book.*/ if (cp_ptr->spell_book == TV_MAGIC_BOOK) p_ptr->spell_flags[SPELL_FLIGHT] &= ~(PY_SPELL_IRONMAN); /* Read the inventory */ if (rd_inventory()) { note("Unable to read inventory"); return (-1); } /* Read the stores */ rd_u16b(&tmp16u); for (i = 0; i < tmp16u; i++) { if (rd_store(i)) return (-1); } /* Read the stored number of terrain features */ rd_u16b(&tmp16u); /* Check bounds */ if (tmp16u > z_info->f_max) { note(format("Too many (%u) terrain features!", tmp16u)); return (-1); } /* Read terrain lore */ for (i = 0; i < tmp16u; i++) { if (rd_feature_lore(i)) return (-1); } /* Artifact lore */ /* Read the stored number of artifacts (normal + special) */ rd_u16b(&tmp16u); /* Check bounds */ if (tmp16u > z_info->art_norm_max) { note(format("Too many (%u) artifacts!", tmp16u)); return (-1); } /* Read artifact lore */ for (i = 0; i < tmp16u; i++) { if (rd_artifact_lore(i)) return (-1); } /* I'm not dead yet... */ if (!p_ptr->is_dead) { /* Dead players have no dungeon */ note("Restoring Dungeon..."); if (rd_dungeon()) { note("Error reading dungeon data"); return (-1); } } /* Save the checksum */ n_v_check = v_check; /* Read the old checksum */ rd_u32b(&o_v_check); /* Verify */ if (o_v_check != n_v_check) { note("Invalid checksum"); return (-1); } /* Save the encoded checksum */ n_x_check = x_check; /* Read the checksum */ rd_u32b(&o_x_check); /* Verify */ if (o_x_check != n_x_check) { note("Invalid encoded checksum"); return (-1); } /* Success */ return (0); }
/* * Read the random artifacts */ static errr rd_randarts(void) { int i; byte tmp8u; s16b tmp16s; u16b tmp16u; u16b artifact_count, begin; s32b tmp32s; u32b tmp32u; /* Read the number of artifacts */ rd_u16b(&begin); rd_u16b(&artifact_count); rd_u16b(&art_norm_count); /* Alive or cheating death */ if (!p_ptr->is_dead || arg_wizard) { /* Incompatible save files */ if ((artifact_count > z_info->art_max) || (art_norm_count > z_info->art_norm_max)) { note(format("Too many (%u) artifacts!", artifact_count)); return (-1); } /*Mark any new added artifacts*/ if (art_norm_count < z_info->art_norm_max) { new_artifacts = z_info->art_norm_max - art_norm_count; } else new_artifacts = 0; /* Mark the old artifacts as "empty" */ for (i = begin; i < z_info->art_max; i++) { artifact_type *a_ptr = &a_info[i]; /*hack - if a new "normal artifact has been added in mid-game, don't erase it*/ if ((i >= art_norm_count) && (i < z_info->art_norm_max)) continue; a_ptr->tval = 0; a_ptr->sval = 0; a_ptr->name[0] = '\0'; } /* Read the artifacts */ for (i = begin; i < artifact_count; i++) { artifact_type *a_ptr = &a_info[i]; /*hack - if a new "normal artifact has been added in mid-game, don't erase it*/ if ((i >= art_norm_count) && (i < z_info->art_norm_max)) continue; rd_string (a_ptr->name, MAX_LEN_ART_NAME); rd_byte(&a_ptr->tval); rd_byte(&a_ptr->sval); rd_s16b(&a_ptr->pval); rd_s16b(&a_ptr->to_h); rd_s16b(&a_ptr->to_d); rd_s16b(&a_ptr->to_a); rd_s16b(&a_ptr->ac); rd_byte(&a_ptr->dd); rd_byte(&a_ptr->ds); rd_s16b(&a_ptr->weight); rd_s32b(&a_ptr->cost); rd_u32b(&a_ptr->a_flags1); rd_u32b(&a_ptr->a_flags2); rd_u32b(&a_ptr->a_flags3); rd_u32b(&a_ptr->a_native); rd_byte(&a_ptr->a_level); rd_byte(&a_ptr->a_rarity); rd_byte(&a_ptr->activation); rd_u16b(&a_ptr->time); rd_u16b(&a_ptr->randtime); } } else { /* Strip the the artifacts for a dead/new character*/ for (i = begin; i < artifact_count; i++) { char tmpstr[MAX_LEN_ART_NAME]; rd_string (tmpstr, sizeof (tmpstr)); /*a_ptr->name*/ rd_byte(&tmp8u); /* a_ptr->tval */ rd_byte(&tmp8u); /* a_ptr->sval */ rd_s16b(&tmp16s); /* a_ptr->pval */ rd_s16b(&tmp16s); /* a_ptr->to_h */ rd_s16b(&tmp16s); /* a_ptr->to_d */ rd_s16b(&tmp16s); /* a_ptr->to_a */ rd_s16b(&tmp16s); /* a_ptr->ac */ rd_byte(&tmp8u); /* a_ptr->dd */ rd_byte(&tmp8u); /* a_ptr->ds */ rd_s16b(&tmp16s); /* a_ptr->weight */ rd_s32b(&tmp32s); /* a_ptr->cost */ rd_u32b(&tmp32u); /* a_ptr->flags1 */ rd_u32b(&tmp32u); /* a_ptr->flags2 */ rd_u32b(&tmp32u); /* a_ptr->flags3 */ rd_u32b(&tmp32u); /* a_ptr->a_native */ rd_byte(&tmp8u); /* a_ptr->level */ rd_byte(&tmp8u); /* a_ptr->rarity */ rd_byte(&tmp8u); /* a_ptr->activation */ rd_u16b(&tmp16u); /* a_ptr->time */ rd_u16b(&tmp16u); /* a_ptr->randtime */ } } return (0); }
/* * Read the "extra" information */ static errr rd_extra(void) { int i; byte tmp8u; u16b tmp16u; u16b file_e_max; byte num; rd_string(op_ptr->full_name, sizeof(op_ptr->full_name)); rd_string(p_ptr->died_from, 80); rd_string(p_ptr->history, 250); /* Player race */ rd_byte(&p_ptr->prace); /* Verify player race */ if (p_ptr->prace >= z_info->p_max) { note(format("Invalid player race (%d).", p_ptr->prace)); return (-1); } /* Player class */ rd_byte(&p_ptr->pclass); /* Verify player class */ if (p_ptr->pclass >= z_info->c_max) { note(format("Invalid player class (%d).", p_ptr->pclass)); return (-1); } /* Player gender */ rd_byte(&p_ptr->psex); strip_bytes(1); /* Special Race/Class info */ rd_byte(&p_ptr->hitdie); rd_byte(&p_ptr->expfact); /* Age/Height/Weight */ rd_s16b(&p_ptr->age); rd_s16b(&p_ptr->ht); rd_s16b(&p_ptr->wt); /* Read the stat info */ for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_max[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_cur[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_birth[i]); for (i = 0; i < A_MAX; ++i) rd_s16b(&p_ptr->stat_quest_add[i]); rd_s16b(&p_ptr->ht_birth); rd_s16b(&p_ptr->wt_birth); rd_s16b(&p_ptr->sc_birth); rd_s32b(&p_ptr->au_birth); strip_bytes(24); /* oops */ rd_u16b(&p_ptr->q_fame); rd_u16b(&p_ptr->deferred_rewards); rd_s32b(&p_ptr->au); rd_s32b(&p_ptr->max_exp); rd_s32b(&p_ptr->exp); rd_u16b(&p_ptr->exp_frac); rd_s16b(&p_ptr->lev); /* Verify player level */ if ((p_ptr->lev < 1) || (p_ptr->lev > z_info->max_level)) { note(format("Invalid player level (%d).", p_ptr->lev)); return (-1); } rd_s16b(&p_ptr->mhp); rd_s16b(&p_ptr->chp); rd_u16b(&p_ptr->chp_frac); rd_s16b(&p_ptr->msp); rd_s16b(&p_ptr->csp); rd_u16b(&p_ptr->csp_frac); rd_s16b(&p_ptr->max_lev); rd_s16b(&p_ptr->max_depth); rd_s16b(&p_ptr->recall_depth); /* Hack -- Repair maximum player level */ if (p_ptr->max_lev < p_ptr->lev) p_ptr->max_lev = p_ptr->lev; /* Hack -- Repair maximum dungeon level */ if (p_ptr->max_depth < 0) p_ptr->max_depth = 1; /* Hack -- Repair recall dungeon level */ if (p_ptr->recall_depth < 0) p_ptr->recall_depth = 1; rd_s16b(&p_ptr->quest_depth); /* Hack -- Repair max quest level */ if ((p_ptr->max_depth > 1) && (p_ptr->max_depth > p_ptr->quest_depth)) { p_ptr->quest_depth = p_ptr->max_depth; } /* More info */ strip_bytes(6); rd_s16b(&p_ptr->sc); strip_bytes(2); /* Read the flags */ strip_bytes(2); /* Old "rest" */ rd_s16b(&p_ptr->food); strip_bytes(4); /* Old "food_digested" / "protection" */ rd_s16b(&p_ptr->p_energy); rd_s16b(&p_ptr->word_recall); rd_s16b(&p_ptr->state.see_infra); rd_byte(&p_ptr->confusing); rd_byte(&tmp8u); rd_byte(&p_ptr->searching); rd_byte(&tmp8u); /* oops */ rd_byte(&tmp8u); /* oops */ rd_byte(&tmp8u); /* oops */ /* Find the number of timed effects */ rd_byte(&num); if (num == TMD_MAX) { /* Read all the effects */ for (i = 0; i < num; i++) rd_s16b(&p_ptr->timed[i]); } else { s16b dummy2; /* Probably in trouble anyway */ for (i = 0; i < TMD_MAX; i++) rd_s16b(&dummy2); /* Discard unused entries */ note("Discarding unsupported timed effects"); } rd_s16b(&p_ptr->base_wakeup_chance); rd_s16b(&total_wakeup_chance); /* Read item-quality squelch sub-menu */ for (i = 0; i < SQUELCH_BYTES; i++) rd_byte(&squelch_level[i]); /* Load the name of the current greater vault */ rd_string(g_vault_name, sizeof(g_vault_name)); /* Read the number of saved ego-item types */ rd_u16b(&file_e_max); /* Read ego-item squelch settings */ for (i = 0; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; tmp8u = 0; if (i < file_e_max) rd_byte(&tmp8u); e_ptr->squelch |= (tmp8u & 0x01); e_ptr->everseen |= (tmp8u & 0x02); /* Hack - Repair the savefile */ if (!e_ptr->everseen) e_ptr->squelch = FALSE; } /* Read possible extra elements */ while (i < file_e_max) { rd_byte(&tmp8u); i++; } /*Read the current number of auto-inscriptions*/ rd_u16b(&inscriptionsCount); /*Read the autoinscriptions array*/ for(i = 0; i < inscriptionsCount; i++) { char tmp[80]; rd_s16b(&inscriptions[i].kindIdx); rd_string(tmp, 80); inscriptions[i].inscriptionIdx = quark_add(tmp); } /* * The number of the bone file (if any) that player ghosts should use to * derive the ghost name, sex, class, race, and level. */ rd_s16b(&player_ghost_num); /* Find out how many thefts have recently occurred. */ strip_bytes(1); /* Read number of monster traps on level. */ rd_byte(&num_trap_on_level); /* Future use */ strip_bytes(13); /* Read the summon spells that have already failed on the level */ rd_u32b(&dungeon_summon_mask_f7); /* Read the randart seed */ rd_u32b(&seed_randart); /* Skip the flags */ strip_bytes(12); /* Hack -- the three "special seeds" */ rd_u32b(&seed_flavor); rd_u32b(&seed_town); rd_u32b(&seed_ghost); /* Special stuff */ rd_u16b(&p_ptr->panic_save); rd_u16b(&p_ptr->total_winner); rd_u16b(&p_ptr->noscore); /* Read "death" */ rd_byte(&tmp8u); p_ptr->is_dead = tmp8u; /* Read "feeling" */ rd_byte(&tmp8u); feeling = tmp8u; /*read the level feeling*/ rd_byte(&tmp8u); do_feeling = tmp8u; /* Current turn */ rd_s32b(&turn); /*Current Player Turn*/ rd_s32b(&p_ptr->p_turn); /* Turn count for quest indicator */ rd_u16b(&quest_indicator_timer); /* Check if the quest indicator must flash the victory sign */ if (quest_indicator_timer & (QUEST_INDICATOR_COMPLETE_BIT)) { /* We won the quest */ quest_indicator_complete = TRUE; /* Clear the mark from the timer */ quest_indicator_timer &= ~(QUEST_INDICATOR_COMPLETE_BIT); } /* Panel change offsets */ rd_u16b(&panel_change_offset_y); rd_u16b(&panel_change_offset_x); /* Check bounds */ if (panel_change_offset_y < MIN_PANEL_CHANGE_OFFSET_Y) { panel_change_offset_y = MIN_PANEL_CHANGE_OFFSET_Y; } if (panel_change_offset_x < MIN_PANEL_CHANGE_OFFSET_X) { panel_change_offset_x = MIN_PANEL_CHANGE_OFFSET_X; } /* Read the player_hp array */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->max_level) { note(format("Too many (%u) hitpoint entries!", tmp16u)); return (-1); } /* Read the player_hp array */ for (i = 0; i < tmp16u; i++) { rd_s16b(&p_ptr->player_hp[i]); } /* Read the player spells */ if (rd_player_spells()) return (-1); return (0); }
/* * Read the "extra" information */ static errr rd_extra(void) { int i, j; byte tmp8u; u16b file_e_max; rd_string(op_ptr->full_name, sizeof(op_ptr->full_name)); rd_string(p_ptr->died_from, 80); rd_string(p_ptr->history, 250); /* Player race */ rd_byte(&p_ptr->prace); /* Verify player race */ if (p_ptr->prace >= z_info->p_max) { note(format("Invalid player race (%d).", p_ptr->prace)); return (-1); } /* Player house */ rd_byte(&p_ptr->phouse); /* Verify player house */ if (p_ptr->phouse >= z_info->c_max) { note(format("Invalid player house (%d).", p_ptr->phouse)); return (-1); } /* Player sex */ rd_byte(&p_ptr->psex); /* Tutorial? */ rd_s16b(&p_ptr->game_type); /* Age/Height/Weight */ rd_s16b(&p_ptr->age); rd_s16b(&p_ptr->ht); rd_s16b(&p_ptr->wt); /* Read the stat info */ for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_base[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_drain[i]); /* Read the skill info */ for (i = 0; i < S_MAX; i++) rd_s16b(&p_ptr->skill_base[i]); /* Read the abilities info */ for (i = 0; i < S_MAX; i++) { for (j = 0; j < ABILITIES_MAX; j++) { rd_byte(&p_ptr->innate_ability[i][j]); rd_byte(&p_ptr->active_ability[i][j]); } } rd_s16b(&p_ptr->last_attack_m_idx); rd_s16b(&p_ptr->consecutive_attacks); rd_s16b(&p_ptr->bane_type); for (i = 0; i < ACTION_MAX; ++i) { rd_byte(&(p_ptr->previous_action[i])); } rd_byte(&p_ptr->focused); rd_s32b(&p_ptr->new_exp); rd_s32b(&p_ptr->exp); rd_s32b(&p_ptr->encounter_exp); rd_s32b(&p_ptr->kill_exp); rd_s32b(&p_ptr->descent_exp); rd_s32b(&p_ptr->ident_exp); rd_s16b(&p_ptr->mhp); rd_s16b(&p_ptr->chp); rd_u16b(&p_ptr->chp_frac); rd_s16b(&p_ptr->msp); rd_s16b(&p_ptr->csp); rd_u16b(&p_ptr->csp_frac); rd_s16b(&p_ptr->max_depth); /* Hack -- Repair maximum dungeon level */ if (p_ptr->max_depth < 0) p_ptr->max_depth = 1; rd_u16b(&p_ptr->staircasiness); /* More info */ rd_s16b(&p_ptr->sc); /* Read the flags */ rd_byte(&p_ptr->song1); rd_byte(&p_ptr->song2); rd_s16b(&p_ptr->song_duration); rd_s16b(&p_ptr->wrath); rd_s16b(&p_ptr->blind); rd_s16b(&p_ptr->entranced); rd_s16b(&p_ptr->confused); rd_s16b(&p_ptr->food); rd_u16b(&p_ptr->stairs_taken); rd_u16b(&p_ptr->forge_drought); rd_u16b(&p_ptr->forge_count); rd_s16b(&p_ptr->energy); rd_s16b(&p_ptr->fast); rd_s16b(&p_ptr->slow); rd_s16b(&p_ptr->afraid); rd_s16b(&p_ptr->cut); rd_s16b(&p_ptr->stun); rd_s16b(&p_ptr->poisoned); rd_s16b(&p_ptr->image); rd_s16b(&p_ptr->rage); rd_s16b(&p_ptr->tmp_str); rd_s16b(&p_ptr->tmp_dex); rd_s16b(&p_ptr->tmp_con); rd_s16b(&p_ptr->tmp_gra); rd_s16b(&p_ptr->tim_invis); rd_s16b(&p_ptr->word_recall); rd_s16b(&p_ptr->darkened); rd_s16b(&p_ptr->oppose_fire); rd_s16b(&p_ptr->oppose_cold); rd_s16b(&p_ptr->oppose_pois); rd_byte(&p_ptr->stealth_mode); rd_byte(&p_ptr->self_made_arts); // 20 spare bytes strip_bytes(20); /* Read item-quality squelch sub-menu */ for (i = 0; i < SQUELCH_BYTES; i++) rd_byte(&squelch_level[i]); /* Load the name of the current greater vault */ rd_string(g_vault_name, sizeof(g_vault_name)); /* Read the number of saved special item types */ rd_u16b(&file_e_max); /* Read special item squelch settings */ for (i = 0; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; tmp8u = 0; if (i < file_e_max) rd_byte(&tmp8u); e_ptr->squelch |= (tmp8u & 0x01); e_ptr->everseen |= (tmp8u & 0x02); e_ptr->aware |= (tmp8u & 0x04); /* Hack - Repair the savefile */ if (!e_ptr->everseen) e_ptr->squelch = FALSE; } /* Read possible extra elements */ while (i < file_e_max) { rd_byte(&tmp8u); i++; } /*Write the current number of auto-inscriptions*/ rd_u16b(&inscriptionsCount); /*Write the autoinscriptions array*/ for(i = 0; i < inscriptionsCount; i++) { char tmp[80]; rd_s16b(&inscriptions[i].kindIdx); rd_string(tmp, 80); inscriptions[i].inscriptionIdx = quark_add(tmp); } for (i = 0; i < MAX_GREATER_VAULTS; i++) { s16b n; rd_s16b(&n); p_ptr->greater_vaults[i] = n; } /* Read the randart version */ rd_u32b(&randart_version); /* Read the randart seed */ rd_u32b(&seed_randart); /* Hack -- the two "special seeds" */ rd_u32b(&seed_flavor); /* Special stuff */ rd_u16b(&p_ptr->panic_save); rd_byte(&p_ptr->truce); rd_byte(&p_ptr->morgoth_hits); rd_byte(&p_ptr->crown_hint); rd_byte(&p_ptr->crown_shatter); rd_byte(&p_ptr->cursed); rd_byte(&p_ptr->on_the_run); rd_byte(&p_ptr->morgoth_slain); rd_u16b(&p_ptr->escaped); rd_u16b(&p_ptr->noscore); rd_s16b(&p_ptr->smithing_leftover); rd_byte(&tmp8u); p_ptr->unique_forge_made = tmp8u; rd_byte(&tmp8u); p_ptr->unique_forge_seen = tmp8u; /* Read "death" */ rd_byte(&tmp8u); p_ptr->is_dead = tmp8u; /* Read "feeling" */ rd_byte(&tmp8u); feeling = tmp8u; /*read the level feeling*/ rd_byte(&tmp8u); do_feeling = tmp8u; /* Current turn */ rd_s32b(&turn); /* Current player turn */ rd_s32b(&playerturn); return (0); }