4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
17 * Some "local" parameters, used to help write savefiles
20 static FILE *fff
; /* Current save "file" */
22 static byte xor_byte
; /* Simple encryption */
24 static u32b v_stamp
= 0L; /* A simple "checksum" on the actual values */
25 static u32b x_stamp
= 0L; /* A simple "checksum" on the encoded bytes */
30 * These functions place information into a savefile a byte at a time
33 static void sf_put(byte v
)
35 /* Encode the value, write a character */
37 (void)putc((int)xor_byte
, fff
);
39 /* Maintain the checksum info */
44 static void wr_byte(byte v
)
49 static void wr_u16b(u16b v
)
51 sf_put((byte
)(v
& 0xFF));
52 sf_put((byte
)((v
>> 8) & 0xFF));
55 static void wr_s16b(s16b v
)
60 static void wr_u32b(u32b v
)
62 sf_put((byte
)(v
& 0xFF));
63 sf_put((byte
)((v
>> 8) & 0xFF));
64 sf_put((byte
)((v
>> 16) & 0xFF));
65 sf_put((byte
)((v
>> 24) & 0xFF));
68 static void wr_s32b(s32b v
)
73 static void wr_string(cptr str
)
85 * These functions write info in larger logical records
90 * Write an "item" record
92 static void wr_item(const object_type
*o_ptr
)
94 wr_s16b(o_ptr
->k_idx
);
100 wr_byte(o_ptr
->tval
);
101 wr_byte(o_ptr
->sval
);
102 wr_s16b(o_ptr
->pval
);
104 wr_byte(o_ptr
->pseudo
);
106 wr_byte(o_ptr
->number
);
107 wr_s16b(o_ptr
->weight
);
109 wr_byte(o_ptr
->name1
);
110 wr_byte(o_ptr
->name2
);
112 wr_s16b(o_ptr
->timeout
);
114 wr_s16b(o_ptr
->to_h
);
115 wr_s16b(o_ptr
->to_d
);
116 wr_s16b(o_ptr
->to_a
);
121 wr_byte(o_ptr
->ident
);
123 wr_byte(o_ptr
->marked
);
130 /* Held by monster index */
131 wr_s16b(o_ptr
->held_m_idx
);
133 /* Extra information */
134 wr_byte(o_ptr
->xtra1
);
135 wr_byte(o_ptr
->xtra2
);
137 /* Save the inscription (if any) */
140 wr_string(quark_str(o_ptr
->note
));
150 * Write a "monster" record
152 static void wr_monster(const monster_type
*m_ptr
)
154 wr_s16b(m_ptr
->r_idx
);
158 wr_s16b(m_ptr
->maxhp
);
159 wr_s16b(m_ptr
->csleep
);
160 wr_byte(m_ptr
->mspeed
);
161 wr_byte(m_ptr
->energy
);
162 wr_byte(m_ptr
->stunned
);
163 wr_byte(m_ptr
->confused
);
164 wr_byte(m_ptr
->monfear
);
170 * Write a "lore" record
172 static void wr_lore(int r_idx
)
176 monster_race
*r_ptr
= &r_info
[r_idx
];
177 monster_lore
*l_ptr
= &l_list
[r_idx
];
179 /* Count sights/deaths/kills */
180 wr_s16b(l_ptr
->sights
);
181 wr_s16b(l_ptr
->deaths
);
182 wr_s16b(l_ptr
->pkills
);
183 wr_s16b(l_ptr
->tkills
);
185 /* Count wakes and ignores */
186 wr_byte(l_ptr
->wake
);
187 wr_byte(l_ptr
->ignore
);
190 wr_byte(l_ptr
->xtra1
);
191 wr_byte(l_ptr
->xtra2
);
194 wr_byte(l_ptr
->drop_gold
);
195 wr_byte(l_ptr
->drop_item
);
198 wr_byte(l_ptr
->cast_innate
);
199 wr_byte(l_ptr
->cast_spell
);
201 /* Count blows of each type */
202 for (i
= 0; i
< MONSTER_BLOW_MAX
; i
++)
203 wr_byte(l_ptr
->blows
[i
]);
206 wr_u32b(l_ptr
->flags1
);
207 wr_u32b(l_ptr
->flags2
);
208 wr_u32b(l_ptr
->flags3
);
209 wr_u32b(l_ptr
->flags4
);
210 wr_u32b(l_ptr
->flags5
);
211 wr_u32b(l_ptr
->flags6
);
214 /* Monster limit per level */
215 wr_byte(r_ptr
->max_num
);
225 * Write an "xtra" record
227 static void wr_xtra(int k_idx
)
231 object_kind
*k_ptr
= &k_info
[k_idx
];
233 if (k_ptr
->aware
) tmp8u
|= 0x01;
234 if (k_ptr
->tried
) tmp8u
|= 0x02;
235 if (k_ptr
->squelch
) tmp8u
|= 0x04;
236 if (k_ptr
->everseen
) tmp8u
|= 0x08;
243 * Write a "store" record
245 static void wr_store(const store_type
*st_ptr
)
249 /* XXX Old value (<= Angband 3.0.3) */
252 /* XXX Old value (<= Angband 3.0.3) */
255 /* Save the current owner */
256 wr_byte(st_ptr
->owner
);
258 /* Save the stock size */
259 wr_byte(st_ptr
->stock_num
);
261 /* XXX Old values (<= Angband 3.0.3) */
266 for (j
= 0; j
< st_ptr
->stock_num
; j
++)
268 /* Save each item in stock */
269 wr_item(&st_ptr
->stock
[j
]);
277 static errr
wr_randomizer(void)
288 for (i
= 0; i
< RAND_DEG
; i
++)
290 wr_u32b(Rand_state
[i
]);
299 * Write the "options"
301 static void wr_options(void)
307 u32b window_flag
[ANGBAND_TERM_MAX
];
308 u32b window_mask
[ANGBAND_TERM_MAX
];
314 for (i
= 0; i
< 4; i
++) wr_u32b(0L);
317 /*** Special Options ***/
319 /* Write "delay_factor" */
320 wr_byte(op_ptr
->delay_factor
);
322 /* Write "hitpoint_warn" */
323 wr_byte(op_ptr
->hitpoint_warn
);
325 wr_u16b(0); /* oops */
328 /*** Normal options ***/
331 for (i
= 0; i
< 8; i
++)
337 /* Analyze the options */
338 for (i
= 0; i
< OPT_MAX
; i
++)
343 /* Process real entries */
350 flag
[os
] |= (1L << ob
);
354 mask
[os
] |= (1L << ob
);
359 for (i
= 0; i
< 8; i
++) wr_u32b(flag
[i
]);
362 for (i
= 0; i
< 8; i
++) wr_u32b(mask
[i
]);
365 /*** Window options ***/
368 for (i
= 0; i
< ANGBAND_TERM_MAX
; i
++)
371 window_flag
[i
] = op_ptr
->window_flag
[i
];
377 for (k
= 0; k
< 32; k
++)
380 if (window_flag_desc
[k
])
382 window_mask
[i
] |= (1L << k
);
388 for (i
= 0; i
< ANGBAND_TERM_MAX
; i
++) wr_u32b(window_flag
[i
]);
391 for (i
= 0; i
< ANGBAND_TERM_MAX
; i
++) wr_u32b(window_mask
[i
]);
396 * Hack -- Write the "ghost" info
398 static void wr_ghost(void)
403 wr_string("Broken Ghost");
405 /* Hack -- stupid data */
406 for (i
= 0; i
< 60; i
++) wr_byte(0);
411 * Write autoinscribe & squelch item-quality submenu to the savefile
413 static void wr_squelch(void)
417 /* Write number of squelch bytes */
418 wr_byte(SQUELCH_BYTES
);
419 for (i
= 0; i
< SQUELCH_BYTES
; i
++)
420 wr_byte(squelch_level
[i
]);
422 /* Write ego-item squelch bits */
423 wr_u16b(z_info
->e_max
);
424 for (i
= 0; i
< z_info
->e_max
; i
++)
428 /* Figure out and write the everseen flag */
429 if (e_info
[i
].everseen
) flags
|= 0x02;
433 /* Write the current number of auto-inscriptions */
434 wr_u16b(inscriptions_count
);
436 /* Write the autoinscriptions array */
437 for (i
= 0; i
< inscriptions_count
; i
++)
439 wr_s16b(inscriptions
[i
].kind_idx
);
440 wr_string(quark_str(inscriptions
[i
].inscription_idx
));
448 * Write some "extra" info
450 static void wr_extra(void)
454 wr_string(op_ptr
->full_name
);
456 wr_string(p_ptr
->died_from
);
458 wr_string(p_ptr
->history
);
460 /* Race/Class/Gender/Spells */
461 wr_byte(p_ptr
->prace
);
462 wr_byte(p_ptr
->pclass
);
463 wr_byte(p_ptr
->psex
);
464 wr_byte(0); /* oops */
466 wr_byte(p_ptr
->hitdie
);
467 wr_byte(p_ptr
->expfact
);
473 /* Dump the stats (maximum and current) */
474 for (i
= 0; i
< A_MAX
; ++i
) wr_s16b(p_ptr
->stat_max
[i
]);
475 for (i
= 0; i
< A_MAX
; ++i
) wr_s16b(p_ptr
->stat_cur
[i
]);
477 /* Ignore the transient stats */
478 for (i
= 0; i
< 12; ++i
) wr_s16b(0);
482 wr_u32b(p_ptr
->max_exp
);
484 wr_u16b(p_ptr
->exp_frac
);
489 wr_u16b(p_ptr
->chp_frac
);
493 wr_u16b(p_ptr
->csp_frac
);
495 /* Max Player and Dungeon Levels */
496 wr_s16b(p_ptr
->max_lev
);
497 wr_s16b(p_ptr
->max_depth
);
500 wr_s16b(0); /* oops */
501 wr_s16b(0); /* oops */
502 wr_s16b(0); /* oops */
503 wr_s16b(0); /* oops */
505 wr_s16b(0); /* oops */
507 wr_s16b(p_ptr
->food
);
508 wr_s16b(p_ptr
->energy
);
509 wr_s16b(p_ptr
->word_recall
);
510 wr_s16b(p_ptr
->see_infra
);
511 wr_byte(p_ptr
->confusing
);
512 wr_byte(p_ptr
->searching
);
514 /* Find the number of timed effects */
517 /* Read all the effects, in a loop */
518 for (i
= 0; i
< TMD_MAX
; i
++)
519 wr_s16b(p_ptr
->timed
[i
]);
522 for (i
= 0; i
< 10; i
++) wr_u32b(0L);
526 /* Random artifact version */
527 wr_u32b(RANDART_VERSION
);
529 /* Random artifact seed */
530 wr_u32b(seed_randart
);
533 /* Ignore some flags */
534 wr_u32b(0L); /* oops */
535 wr_u32b(0L); /* oops */
536 wr_u32b(0L); /* oops */
539 /* Write the "object seeds" */
540 wr_u32b(seed_flavor
);
545 wr_u16b(p_ptr
->panic_save
);
546 wr_u16b(p_ptr
->total_winner
);
547 wr_u16b(p_ptr
->noscore
);
551 wr_byte(p_ptr
->is_dead
);
556 /* Turn of last "feeling" */
565 * Dump the random artifacts
567 static void wr_randarts(void)
571 wr_u16b(z_info
->a_max
);
573 for (i
= 0; i
< z_info
->a_max
; i
++)
575 artifact_type
*a_ptr
= &a_info
[i
];
577 wr_byte(a_ptr
->tval
);
578 wr_byte(a_ptr
->sval
);
579 wr_s16b(a_ptr
->pval
);
581 wr_s16b(a_ptr
->to_h
);
582 wr_s16b(a_ptr
->to_d
);
583 wr_s16b(a_ptr
->to_a
);
589 wr_s16b(a_ptr
->weight
);
591 wr_s32b(a_ptr
->cost
);
593 wr_u32b(a_ptr
->flags1
);
594 wr_u32b(a_ptr
->flags2
);
595 wr_u32b(a_ptr
->flags3
);
597 wr_byte(a_ptr
->level
);
598 wr_byte(a_ptr
->rarity
);
600 wr_byte(a_ptr
->activation
);
601 wr_u16b(a_ptr
->time
);
602 wr_u16b(a_ptr
->randtime
);
608 * The cave grid flags that get saved in the savefile
610 #define IMPORTANT_FLAGS (CAVE_MARK | CAVE_GLOW | CAVE_ICKY | CAVE_ROOM)
614 * Write the current dungeon
616 static void wr_dungeon(void)
628 /* Dungeon specific info follows */
629 wr_u16b(p_ptr
->depth
);
633 wr_u16b(DUNGEON_HGT
);
634 wr_u16b(DUNGEON_WID
);
639 /*** Simple "Run-Length-Encoding" of cave ***/
641 /* Note that this will induce two wasted bytes */
646 for (y
= 0; y
< DUNGEON_HGT
; y
++)
648 for (x
= 0; x
< DUNGEON_WID
; x
++)
650 /* Extract the important cave_info flags */
651 tmp8u
= (cave_info
[y
][x
] & (IMPORTANT_FLAGS
));
653 /* If the run is broken, or too full, flush it */
654 if ((tmp8u
!= prev_char
) || (count
== MAX_UCHAR
))
656 wr_byte((byte
)count
);
657 wr_byte((byte
)prev_char
);
662 /* Continue the run */
670 /* Flush the data (if any) */
673 wr_byte((byte
)count
);
674 wr_byte((byte
)prev_char
);
678 /*** Simple "Run-Length-Encoding" of cave ***/
680 /* Note that this will induce two wasted bytes */
685 for (y
= 0; y
< DUNGEON_HGT
; y
++)
687 for (x
= 0; x
< DUNGEON_WID
; x
++)
690 tmp8u
= cave_feat
[y
][x
];
692 /* If the run is broken, or too full, flush it */
693 if ((tmp8u
!= prev_char
) || (count
== MAX_UCHAR
))
695 wr_byte((byte
)count
);
696 wr_byte((byte
)prev_char
);
701 /* Continue the run */
709 /* Flush the data (if any) */
712 wr_byte((byte
)count
);
713 wr_byte((byte
)prev_char
);
719 /* Compact the objects */
722 /* Compact the monsters */
726 /*** Dump objects ***/
731 /* Dump the objects */
732 for (i
= 1; i
< o_max
; i
++)
734 object_type
*o_ptr
= &o_list
[i
];
741 /*** Dump the monsters ***/
746 /* Dump the monsters */
747 for (i
= 1; i
< mon_max
; i
++)
749 monster_type
*m_ptr
= &mon_list
[i
];
759 * Actually write a save-file
761 static bool wr_savefile_new(void)
770 /* Guess at the current time */
771 now
= time((time_t *)0);
774 /* Note the operating system */
777 /* Note when the file was saved */
780 /* Note the number of saves */
784 /*** Actually write the file ***/
786 /* Dump the file header */
788 wr_byte(VERSION_MAJOR
);
790 wr_byte(VERSION_MINOR
);
792 wr_byte(VERSION_PATCH
);
794 wr_byte(VERSION_EXTRA
);
797 /* Reset the checksum */
802 /* Operating system */
806 /* Time file last saved */
809 /* Number of past lives */
812 /* Number of times saved */
821 /* Write the RNG state */
825 /* Write the boolean "options" */
829 /* Dump the number of "messages" */
830 tmp16u
= message_num();
831 if (tmp16u
> 80) tmp16u
= 80;
834 /* Dump the messages (oldest first!) */
835 for (i
= tmp16u
- 1; i
>= 0; i
--)
837 wr_string(message_str((s16b
)i
));
838 wr_u16b(message_type((s16b
)i
));
842 /* Dump the monster lore */
843 tmp16u
= z_info
->r_max
;
845 for (i
= 0; i
< tmp16u
; i
++) wr_lore(i
);
848 /* Dump the object memory */
849 tmp16u
= z_info
->k_max
;
851 for (i
= 0; i
< tmp16u
; i
++) wr_xtra(i
);
854 /* Hack -- Dump the quests */
857 for (i
= 0; i
< tmp16u
; i
++)
859 wr_byte(q_list
[i
].level
);
865 /* Hack -- Dump the artifacts */
866 tmp16u
= z_info
->a_max
;
868 for (i
= 0; i
< tmp16u
; i
++)
870 artifact_type
*a_ptr
= &a_info
[i
];
871 wr_byte(a_ptr
->cur_num
);
878 /* Write the "extra" information */
882 /* Dump the "player hp" entries */
883 tmp16u
= PY_MAX_LEVEL
;
885 for (i
= 0; i
< tmp16u
; i
++)
887 wr_s16b(p_ptr
->player_hp
[i
]);
891 /* Write spell data */
892 wr_u16b(PY_MAX_SPELLS
);
894 for (i
= 0; i
< PY_MAX_SPELLS
; i
++)
896 wr_byte(p_ptr
->spell_flags
[i
]);
899 /* Dump the ordered spells */
900 for (i
= 0; i
< PY_MAX_SPELLS
; i
++)
902 wr_byte(p_ptr
->spell_order
[i
]);
906 /* Write randart information */
913 /* Write the inventory */
914 for (i
= 0; i
< INVEN_TOTAL
; i
++)
916 object_type
*o_ptr
= &inventory
[i
];
918 /* Skip non-objects */
919 if (!o_ptr
->k_idx
) continue;
932 /* Note the stores */
936 /* Dump the stores */
937 for (i
= 0; i
< tmp16u
; i
++) wr_store(&store
[i
]);
940 /* Player is not dead, write the dungeon */
943 /* Dump the dungeon */
951 /* Write the "value check-sum" */
954 /* Write the "encoded checksum" */
959 if (ferror(fff
) || (fflush(fff
) == EOF
)) return FALSE
;
961 /* Successful save */
967 * Medium level player saver
969 static bool save_player_aux(cptr name
)
982 /* File type is "SAVE" */
983 FILE_TYPE(FILE_TYPE_SAVE
);
986 /* Grab permissions */
989 /* Create the savefile */
990 fd
= fd_make(name
, mode
);
992 /* Drop permissions */
1001 /* Grab permissions */
1004 /* Open the savefile */
1005 fff
= my_fopen(name
, "wb");
1007 /* Drop permissions */
1010 /* Successful open */
1013 /* Write the savefile */
1014 if (wr_savefile_new()) ok
= TRUE
;
1016 /* Attempt to close it */
1017 if (my_fclose(fff
)) ok
= FALSE
;
1020 /* Grab permissions */
1023 /* Remove "broken" files */
1024 if (!ok
) fd_kill(name
);
1026 /* Drop permissions */
1032 if (!ok
) return (FALSE
);
1034 /* Successful save */
1035 character_saved
= TRUE
;
1044 * Attempt to save the player in a savefile
1046 bool save_player(void)
1054 my_strcpy(safe
, savefile
, sizeof(safe
));
1055 my_strcat(safe
, ".new", sizeof(safe
));
1057 /* Grab permissions */
1063 /* Drop permissions */
1066 /* Attempt to save the player */
1067 if (save_player_aux(safe
))
1072 my_strcpy(temp
, savefile
, sizeof(temp
));
1073 my_strcat(temp
, ".old", sizeof(temp
));
1075 /* Grab permissions */
1081 /* Preserve old savefile */
1082 fd_move(savefile
, temp
);
1084 /* Activate new savefile */
1085 fd_move(safe
, savefile
);
1087 /* Remove preserved savefile */
1090 /* Drop permissions */
1098 /* Return the result */