-+-+-+-+-+-+-+-+ START OF PART 56 -+-+-+-+-+-+-+-+ X#include X#endif X#else X#include "string.h" X#endif X#else X#include X#endif X#endif X X/* This must be included after fcntl.h, which has a prototype for `60open' X on some systems. Otherwise, the `60open' prototype conflicts with the X `60topen' declaration. */ X#include "externs.h" X X#ifdef ATARIST_TC X#include X#endif X XDEBUG(static FILE *logfile); X X#if defined(LINT_ARGS) Xstatic int sv_write(void); Xstatic void wr_byte(int8u); Xstatic void wr_short(int16u); Xstatic void wr_long(int32u); Xstatic void wr_bytes(int8u *, int); Xstatic void wr_string(char *); Xstatic void wr_shorts(int16u *, int); Xstatic void wr_item(inven_type *); Xstatic void wr_monster(monster_type *); Xstatic void rd_byte(int8u *); Xstatic void rd_short(int16u *); Xstatic void rd_long(int32u *); Xstatic void rd_bytes(int8u *, int); Xstatic void rd_string(char *); Xstatic void rd_shorts(int16u *, int); Xstatic void rd_item(inven_type *); Xstatic void rd_monster(monster_type *); X#else Xstatic int sv_write(); Xstatic void wr_byte(); Xstatic void wr_short(); Xstatic void wr_long(); Xstatic void wr_bytes(); Xstatic void wr_string(); Xstatic void wr_shorts(); Xstatic void wr_item(); Xstatic void wr_monster(); Xstatic void rd_byte(); Xstatic void rd_short(); Xstatic void rd_long(); Xstatic void rd_bytes(); Xstatic void rd_string(); Xstatic void rd_shorts(); Xstatic void rd_item(); Xstatic void rd_monster(); X#endif X X#if !defined(ATARIST_MWC) X#ifdef MAC X#include X#else Xlong time(); X#endif X#else Xchar *malloc(); X#endif X X/* these are used for the save file, to avoid having to pass them to every X procedure */ Xstatic FILE *fileptr; Xstatic int8u xor_byte; Xstatic int from_savefile;`09/* can overwrite old savefile when save */ Xstatic int32u start_time;`09/* time that play started */ X X/* This save package was brought to by`09`09`09-JWT- X and`09`09`09`09`09`09`09-RAK- X and has been completely rewritten for UNIX by`09-JEW- */ X/* and has been completely rewritten again by`09 -CJS-`09*/ X/* and completely rewritten again! for portability by -JEW- */ X Xstatic int sv_write() X`7B X int32u l; X register int i, j; X int count; X int8u char_tmp, prev_char; X register cave_type *c_ptr; X register recall_type *r_ptr; X struct stats *s_ptr; X register struct flags *f_ptr; X store_type *st_ptr; X struct misc *m_ptr; X#if defined(MSDOS) `7C`7C defined(ATARI_ST) X inven_type *t_ptr; X#endif X X /* clear the death flag when creating a HANGUP save file, so that player X can see tombstone when restart */ X if (eof_flag) X death = FALSE; X X l = 0; X if (find_cut) X l `7C= 0x1; X if (find_examine) X l `7C= 0x2; X if (find_prself) X l `7C= 0x4; X if (find_bound) X l `7C= 0x8; X if (prompt_carry_flag) X l `7C= 0x10; X if (rogue_like_commands) X l `7C= 0x20; X if (show_weight_flag) X l `7C= 0x40; X if (highlight_seams) X l `7C= 0x80; X if (find_ignore_doors) X l `7C= 0x100; X if (sound_beep_flag) X l `7C= 0x200; X if (display_counts) X l `7C= 0x400; X if (death) X l `7C= 0x80000000L;`09/* Sign bit */ X if (total_winner) X l `7C= 0x40000000L; X X for (i = 0; i < MAX_CREATURES; i++) X `7B X r_ptr = &c_recall`5Bi`5D; X if (r_ptr->r_cmove `7C`7C r_ptr->r_cdefense `7C`7C r_ptr->r_kills `7C` V7C X`09 r_ptr->r_spells `7C`7C r_ptr->r_deaths `7C`7C r_ptr->r_attacks`5B0`5D ` V7C`7C X`09 r_ptr->r_attacks`5B1`5D `7C`7C r_ptr->r_attacks`5B2`5D `7C`7C r_ptr->r_ Vattacks`5B3`5D) X`09`7B X`09 wr_short((int16u)i); X`09 wr_long(r_ptr->r_cmove); X`09 wr_long(r_ptr->r_spells); X`09 wr_short(r_ptr->r_kills); X`09 wr_short(r_ptr->r_deaths); X`09 wr_short(r_ptr->r_cdefense); X`09 wr_byte(r_ptr->r_wake); X`09 wr_byte(r_ptr->r_ignore); X`09 wr_bytes(r_ptr->r_attacks, MAX_MON_NATTACK); X`09`7D X `7D X wr_short((int16u)0xFFFF); /* sentinel to indicate no more monster info */ X X wr_long(l); X X m_ptr = &py.misc; X wr_string(m_ptr->name); X wr_byte(m_ptr->male); X wr_long((int32u)m_ptr->au); X wr_long((int32u)m_ptr->max_exp); X wr_long((int32u)m_ptr->exp); X wr_short(m_ptr->exp_frac); X wr_short(m_ptr->age); X wr_short(m_ptr->ht); X wr_short(m_ptr->wt); X wr_short(m_ptr->lev); X wr_short(m_ptr->max_dlv); X wr_short((int16u)m_ptr->srh); X wr_short((int16u)m_ptr->fos); X wr_short((int16u)m_ptr->bth); X wr_short((int16u)m_ptr->bthb); X wr_short((int16u)m_ptr->mana); X wr_short((int16u)m_ptr->mhp); X wr_short((int16u)m_ptr->ptohit); X wr_short((int16u)m_ptr->ptodam); X wr_short((int16u)m_ptr->pac); X wr_short((int16u)m_ptr->ptoac); X wr_short((int16u)m_ptr->dis_th); X wr_short((int16u)m_ptr->dis_td); X wr_short((int16u)m_ptr->dis_ac); X wr_short((int16u)m_ptr->dis_tac); X wr_short((int16u)m_ptr->disarm); X wr_short((int16u)m_ptr->save); X wr_short((int16u)m_ptr->sc); X wr_short((int16u)m_ptr->stl); X wr_byte(m_ptr->pclass); X wr_byte(m_ptr->prace); X wr_byte(m_ptr->hitdie); X wr_byte(m_ptr->expfact); X wr_short((int16u)m_ptr->cmana); X wr_short(m_ptr->cmana_frac); X wr_short((int16u)m_ptr->chp); X wr_short(m_ptr->chp_frac); X for (i = 0; i < 4; i++) X wr_string (m_ptr->history`5Bi`5D); X X s_ptr = &py.stats; X wr_bytes(s_ptr->max_stat, 6); X wr_bytes(s_ptr->cur_stat, 6); X wr_shorts((int16u *)s_ptr->mod_stat, 6); X wr_bytes(s_ptr->use_stat, 6); X X f_ptr = &py.flags; X wr_long(f_ptr->status); X wr_short((int16u)f_ptr->rest); X wr_short((int16u)f_ptr->blind); X wr_short((int16u)f_ptr->paralysis); X wr_short((int16u)f_ptr->confused); X wr_short((int16u)f_ptr->food); X wr_short((int16u)f_ptr->food_digested); X wr_short((int16u)f_ptr->protection); X wr_short((int16u)f_ptr->speed); X wr_short((int16u)f_ptr->fast); X wr_short((int16u)f_ptr->slow); X wr_short((int16u)f_ptr->afraid); X wr_short((int16u)f_ptr->poisoned); X wr_short((int16u)f_ptr->image); X wr_short((int16u)f_ptr->protevil); X wr_short((int16u)f_ptr->invuln); X wr_short((int16u)f_ptr->hero); X wr_short((int16u)f_ptr->shero); X wr_short((int16u)f_ptr->blessed); X wr_short((int16u)f_ptr->resist_heat); X wr_short((int16u)f_ptr->resist_cold); X wr_short((int16u)f_ptr->detect_inv); X wr_short((int16u)f_ptr->word_recall); X wr_short((int16u)f_ptr->see_infra); X wr_short((int16u)f_ptr->tim_infra); X wr_byte(f_ptr->see_inv); X wr_byte(f_ptr->teleport); X wr_byte(f_ptr->free_act); X wr_byte(f_ptr->slow_digest); X wr_byte(f_ptr->aggravate); X wr_byte(f_ptr->fire_resist); X wr_byte(f_ptr->cold_resist); X wr_byte(f_ptr->acid_resist); X wr_byte(f_ptr->regenerate); X wr_byte(f_ptr->lght_resist); X wr_byte(f_ptr->ffall); X wr_byte(f_ptr->sustain_str); X wr_byte(f_ptr->sustain_int); X wr_byte(f_ptr->sustain_wis); X wr_byte(f_ptr->sustain_con); X wr_byte(f_ptr->sustain_dex); X wr_byte(f_ptr->sustain_chr); X wr_byte(f_ptr->confuse_monster); X wr_byte(f_ptr->new_spells); X X wr_short((int16u)missile_ctr); X wr_long((int32u)turn); X wr_short((int16u)inven_ctr); X for (i = 0; i < inven_ctr; i++) X wr_item(&inventory`5Bi`5D); X for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) X wr_item(&inventory`5Bi`5D); X wr_short((int16u)inven_weight); X wr_short((int16u)equip_ctr); X wr_long(spell_learned); X wr_long(spell_worked); X wr_long(spell_forgotten); X wr_bytes(spell_order, 32); X wr_bytes(object_ident, OBJECT_IDENT_SIZE); X wr_long(randes_seed); X wr_long(town_seed); X wr_short((int16u)last_msg); X for (i = 0; i < MAX_SAVE_MSG; i++) X wr_string(old_msg`5Bi`5D); X X /* this indicates 'cheating' if it is a one */ X wr_short((int16u)panic_save); X wr_short((int16u)total_winner); X wr_short((int16u)noscore); X wr_shorts(player_hp, MAX_PLAYER_LEVEL); X X for (i = 0; i < MAX_STORES; i++) X `7B X st_ptr = &store`5Bi`5D; X wr_long((int32u)st_ptr->store_open); X wr_short((int16u)st_ptr->insult_cur); X wr_byte(st_ptr->owner); X wr_byte(st_ptr->store_ctr); X wr_short(st_ptr->good_buy); X wr_short(st_ptr->bad_buy); X for (j = 0; j < st_ptr->store_ctr; j++) X`09`7B X`09 wr_long((int32u)st_ptr->store_inven`5Bj`5D.scost); X`09 wr_item(&st_ptr->store_inven`5Bj`5D.sitem); X`09`7D X `7D X X /* save the current time in the savefile */ X#ifdef MAC X l = time((time_t *)0); X#else X l = time((long *)0); X#endif X if (l < start_time) X `7B X /* someone is messing with the clock!, assume that we have been X`09 playing for 1 day */ X l = start_time + 86400L; X `7D X wr_long(l); X X /* starting with 5.2, put died_from string in savefile */ X wr_string(died_from); X X /* starting with 5.2.2, put the max_score in the savefile */ X l = total_points (); X wr_long (l); X X /* starting with 5.2.2, put the birth_date in the savefile */ X wr_long ((int32u) birth_date); X X /* only level specific info follows, this allows characters to be X resurrected, the dungeon level info is not needed for a resurrection */ X if (death) X `7B X if (ferror(fileptr) `7C`7C fflush(fileptr) == EOF) X`09return FALSE; X return TRUE; X `7D X X wr_short((int16u)dun_level); X wr_short((int16u)char_row); X wr_short((int16u)char_col); X wr_short((int16u)mon_tot_mult); X wr_short((int16u)cur_height); X wr_short((int16u)cur_width); X wr_short((int16u)max_panel_rows); X wr_short((int16u)max_panel_cols); X X for (i = 0; i < MAX_HEIGHT; i++) X for (j = 0; j < MAX_WIDTH; j++) X `7B X`09c_ptr = &cave`5Bi`5D`5Bj`5D; X`09if (c_ptr->cptr != 0) X`09 `7B X`09 wr_byte((int8u)i); X`09 wr_byte((int8u)j); X`09 wr_byte(c_ptr->cptr); X`09 `7D X `7D X wr_byte((int8u)0xFF); /* marks end of cptr info */ X for (i = 0; i < MAX_HEIGHT; i++) X for (j = 0; j < MAX_WIDTH; j++) X `7B X`09c_ptr = &cave`5Bi`5D`5Bj`5D; X`09if (c_ptr->tptr != 0) X`09 `7B X`09 wr_byte((int8u)i); X`09 wr_byte((int8u)j); X`09 wr_byte(c_ptr->tptr); X`09 `7D X `7D X wr_byte((int8u)0xFF); /* marks end of tptr info */ X /* must set counter to zero, note that code may write out two bytes X unnecessarily */ X count = 0; X prev_char = 0; X for (i = 0; i < MAX_HEIGHT; i++) X for (j = 0; j < MAX_WIDTH; j++) X `7B X`09c_ptr = &cave`5Bi`5D`5Bj`5D; X`09char_tmp = c_ptr->fval `7C (c_ptr->lr << 4) `7C (c_ptr->fm << 5) `7C X`09 (c_ptr->pl << 6) `7C (c_ptr->tl << 7); X`09if (char_tmp != prev_char `7C`7C count == MAX_UCHAR) X`09 `7B X`09 wr_byte((int8u)count); X`09 wr_byte(prev_char); X`09 prev_char = char_tmp; X`09 count = 1; X`09 `7D X`09else X`09 count++; X `7D X /* save last entry */ X wr_byte((int8u)count); X wr_byte(prev_char); X X#if defined(MSDOS) `7C`7C defined(ATARI_ST) X /* must change graphics symbols for walls and floors back to default chars V, X this is necessary so that if the user changes the graphics line, the X program will be able change all existing walls and floors to the new X symbol */ X /* Or if the user moves the savefile from one machine to another, we X must have a consistent representation here. */ X t_ptr = &t_list`5Btcptr - 1`5D; X for (i = tcptr - 1; i >= MIN_TRIX; i--) X `7B X#ifdef MSDOS X if (t_ptr->tchar == wallsym) X`09t_ptr->tchar = '#'; X#endif X#ifdef ATARI_ST X if (t_ptr->tchar == (unsigned char)240) X`09t_ptr->tchar = '#'; X#endif X t_ptr--; X `7D X#endif X wr_short((int16u)tcptr); X for (i = MIN_TRIX; i < tcptr; i++) X wr_item(&t_list`5Bi`5D); X wr_short((int16u)mfptr); X for (i = MIN_MONIX; i < mfptr; i++) X wr_monster(&m_list`5Bi`5D); X X if (ferror(fileptr) `7C`7C (fflush(fileptr) == EOF)) X return FALSE; X return TRUE; X`7D X X#ifdef MAC X X/* Set up prior to actual save, do the save, then clean up */ X/* Notice that Mac version of this function takes a parameter */ X/* To do a "save as" set always_ask */ X/* To do a "save" clear always_ask */ X Xint save_char(always_ask) Xint always_ask; X`7B X int rc, already_set, proceed; X int16 vrefnum; X X /* cannot rely on _save_char to do this because we may put up a dialog */ X if (character_saved) return(TRUE); X X enablefilemenu(FALSE); X X already_set = getsavedefaults(savefile, &vrefnum); X X if (!already_set `7C`7C always_ask) X `7B X /* Here if always_ask or user has not yet specified a save file */ X /* User specifies a save file when he restarts a previous one */ X sfposition(vrefnum); X proceed = doputfile(death ? "Save memories as:" : "Save game as:", X`09`09`09 savefile, &vrefnum); X `7D X else X proceed = TRUE; X X if (proceed) X `7B X changedirectory(vrefnum); X rc = _save_char(savefile); X restoredirectory(); X `7D X else X rc = FALSE; X X if (rc) X (void) setfileinfo(savefile, vrefnum, SAVE_FTYPE); X X enablefilemenu(TRUE); X X return(rc); X`7D X X#else X X/* The Mac has different logic here -- See above */ X Xint save_char() X`7B X int i; X vtype temp; X X#ifdef SECURE X bePlayer(); X#endif X X while (!_save_char(savefile)) X `7B X (void) sprintf(temp, "Savefile '%s' fails.", savefile); X msg_print(temp); X i = 0; X if (access(savefile, 0) < 0 X`09 `7C`7C get_check("File exists. Delete old savefile?") == 0 X`09 `7C`7C (i = unlink(savefile)) < 0) X`09`7B X`09 if (i < 0) X`09 `7B X`09 (void) sprintf(temp, "Can't delete '%s'", savefile); X`09 msg_print(temp); X`09 `7D X`09 prt("New Savefile `5BESC to give up`5D:", 0, 0); X`09 if (!get_string(temp, 0, 31, 45)) X`09 return FALSE; X`09 if (temp`5B0`5D) X`09 (void) strcpy(savefile, temp); X`09`7D X (void) sprintf(temp, "Saving with %s...", savefile); X prt(temp, 0, 0); X `7D X#ifdef SECURE X beGames(); X#endif X return TRUE; X`7D X#endif X Xint _save_char(fnam) Xchar *fnam; X`7B X vtype temp; X register int ok, fd; X int8u char_tmp; X X if (character_saved) X return TRUE;`09/* Nothing to save. */ X X nosignals(); X put_qio(); X disturb (1, 0);`09`09/* Turn off resting and searching. */ X change_speed(-pack_heavy);`09/* Fix the speed */ X pack_heavy = 0; X ok = FALSE; +-+-+-+-+-+-+-+- END OF PART 56 +-+-+-+-+-+-+-+-