/* Sarien - A Sierra AGI resource interpreter engine * Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka * * $Id: savegame.c,v 1.46 2001/11/02 14:28:41 cmatsuoka Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; see docs/COPYING for further details. */ /* * Savegame support by Vasyl Tsvirkunov */ #ifndef PALMOS #include #include #ifndef __MPW__ #ifndef __DICE__ #include #endif #include #endif #ifdef WIN32 #include #endif #include "sarien.h" #include "agi.h" #include "graphics.h" #include "sprite.h" #include "text.h" #include "savegame.h" #if defined(__DICE__) || defined(WIN32) # define MKDIR(a,b) mkdir(a) #else # define MKDIR(a,b) mkdir(a,b) #endif /* Image stack support */ struct image_stack_element { UINT8 type; UINT8 pad; SINT16 parm1; SINT16 parm2; SINT16 parm3; SINT16 parm4; SINT16 parm5; SINT16 parm6; SINT16 parm7; struct image_stack_element* next; }; struct image_stack_element* image_stack = NULL; void clear_image_stack(void) { struct image_stack_element* ptr = image_stack; struct image_stack_element* doomed; while(ptr) { doomed = ptr; ptr = ptr->next; free(doomed); } image_stack = NULL; } void record_image_stack_call(UINT8 type, SINT16 p1, SINT16 p2, SINT16 p3, SINT16 p4, SINT16 p5, SINT16 p6, SINT16 p7) { struct image_stack_element* pnew; struct image_stack_element* ptr; pnew = (struct image_stack_element*)malloc(sizeof(struct image_stack_element)); pnew->type = type; pnew->parm1 = p1; pnew->parm2 = p2; pnew->parm3 = p3; pnew->parm4 = p4; pnew->parm5 = p5; pnew->parm6 = p6; pnew->parm7 = p7; pnew->next = NULL; if(image_stack) { ptr = image_stack; while(ptr->next) ptr = ptr->next; ptr->next = pnew; } else image_stack = pnew; } void replay_image_stack_call(UINT8 type, SINT16 p1, SINT16 p2, SINT16 p3, SINT16 p4, SINT16 p5, SINT16 p6, SINT16 p7) { switch(type) { case ADD_PIC: agi_load_resource(rPICTURE, p1); decode_picture(p1, p2); break; case ADD_VIEW: agi_load_resource(rVIEW, p1); add_to_pic(p1, p2, p3, p4, p5, p6, p7); break; } } /* */ static char* strSig = "Sarien:"; void write_uint8(FILE* f, SINT8 val) { fwrite(&val, 1, 1, f); } void write_sint16(FILE* f, SINT16 val) { static UINT8 buf[2]; buf[0] = (UINT8)((val>>8)&255); buf[1] = (UINT8)(val&255); fwrite(buf, 1, 2, f); } void write_uint16(FILE* f, UINT16 val) { static UINT8 buf[2]; buf[0] = (UINT8)((val>>8)&255); buf[1] = (UINT8)(val&255); fwrite(buf, 1, 2, f); } UINT8 read_uint8(FILE* f) { static UINT8 buf[1]; fread(buf, 1, 1, f); return buf[0]; } UINT16 read_uint16(FILE* f) { static UINT8 buf[2]; fread(buf, 1, 2, f); return (buf[0]<<8)|buf[1]; } SINT16 read_sint16(FILE* f) { static UINT8 buf[2]; fread(buf, 1, 2, f); return (SINT16)((buf[0]<<8)|buf[1]); } void write_string(FILE* f, char* s) { write_sint16(f, (SINT16)strlen(s)); fwrite(s, 1, strlen(s), f); } void read_string(FILE* f, char* s) { SINT16 size = read_sint16(f); fread(s, 1, size, f); s[size] = (char)0; } void write_bytes(FILE* f, char* s, SINT16 size) { fwrite(s, 1, size, f); } void read_bytes(FILE* f, char* s, SINT16 size) { fread(s, 1, size, f); } int save_game(char* s, char* d) { SINT16 i; struct image_stack_element* ptr = image_stack; FILE* f=fopen(s, "wb"); if(!f) return err_BadFileOpen; write_bytes(f, strSig, 8); write_string(f, d); write_sint16(f, (SINT16)game.state); /* game.name */ write_string(f, game.id); /* game.crc */ for(i=0; istep_time); write_uint8(f, v->step_time_count); write_uint8(f, v->entry); write_sint16(f, v->x_pos); write_sint16(f, v->y_pos); write_uint8(f, v->current_view); /* v->view_data */ write_uint8(f, v->current_loop); write_uint8(f, v->num_loops); /* v->loop_data */ write_uint8(f, v->current_cel); write_uint8(f, v->num_cels); /* v->cel_data */ /* v->cel_data_2 */ write_sint16(f, v->x_pos2); write_sint16(f, v->y_pos2); /* v->s */ write_sint16(f, v->x_size); write_sint16(f, v->y_size); write_uint8(f, v->step_size); write_uint8(f, v->cycle_time); write_uint8(f, v->cycle_time_count); write_uint8(f, v->direction); write_uint8(f, v->motion); write_uint8(f, v->cycle); write_uint8(f, v->priority); write_uint16(f, v->flags); write_uint8(f, v->parm1); write_uint8(f, v->parm2); write_uint8(f, v->parm3); write_uint8(f, v->parm4); } /* Save image stack */ while(ptr) { write_uint8(f, ptr->type); write_sint16(f, ptr->parm1); write_sint16(f, ptr->parm2); write_sint16(f, ptr->parm3); write_sint16(f, ptr->parm4); write_sint16(f, ptr->parm5); write_sint16(f, ptr->parm6); write_sint16(f, ptr->parm7); ptr = ptr->next; } write_uint8(f, 0); fclose(f); return err_OK; } int load_game(char* s) { int i; UINT8 t; SINT16 parm[7]; char sig[8]; char id[8]; char description[256]; FILE* f=fopen(s, "rb"); if(!f) return err_BadFileOpen; read_bytes(f, sig, 8); if(strncmp(sig, strSig, 8)) { fclose(f); return err_BadFileOpen; } read_string(f, description); game.state = read_sint16(f); /* game.name - not saved */ read_string(f, id); if(strcmp(id, game.id)) { fclose(f); return err_BadFileOpen; } /* game.crc - not saved */ for(i=0; istep_time = read_uint8(f); v->step_time_count = read_uint8(f); v->entry = read_uint8(f); v->x_pos = read_sint16(f); v->y_pos = read_sint16(f); v->current_view = read_uint8(f); /* v->view_data - fixed below */ v->current_loop = read_uint8(f); v->num_loops = read_uint8(f); /* v->loop_data - fixed below */ v->current_cel = read_uint8(f); v->num_cels = read_uint8(f); /* v->cel_data - fixed below */ /* v->cel_data_2 - fixed below */ v->x_pos2 = read_sint16(f); v->y_pos2 = read_sint16(f); /* v->s - fixed below */ v->x_size = read_sint16(f); v->y_size = read_sint16(f); v->step_size = read_uint8(f); v->cycle_time = read_uint8(f); v->cycle_time_count = read_uint8(f); v->direction = read_uint8(f); v->motion = read_uint8(f); v->cycle = read_uint8(f); v->priority = read_uint8(f); v->flags = read_uint16(f); v->parm1 = read_uint8(f); v->parm2 = read_uint8(f); v->parm3 = read_uint8(f); v->parm4 = read_uint8(f); } /* Fix some pointers in viewtable */ for(i=0; icurrent_view].offset == _EMPTY) continue; if(!(game.dir_view[v->current_view].flags & RES_LOADED)) agi_load_resource(rVIEW, v->current_view); set_view(v, v->current_view); /* Fix v->view_data */ set_loop(v, v->current_loop); /* Fix v->loop_data */ set_cel(v, v->current_cel); /* Fix v->cel_data */ v->cel_data_2 = v->cel_data; v->s = NULL; /* not sure if it is used... */ } erase_both(); /* Clear input line */ clear_screen(0); write_status(); /* Recreate background from saved image stack */ clear_image_stack(); while((t = read_uint8(f)) != 0) { for(i=0; i<7; i++) parm[i] = read_sint16(f); replay_image_stack_call(t, parm[0], parm[1], parm[2], parm[3], parm[4], parm[5], parm[6]); } if(ferror(f) || feof(f)) { fclose(f); return err_BadFileOpen; } fclose(f); setflag(F_restore_just_ran, TRUE); game.has_prompt = 0; /* force input line repaint if necessary*/ clean_input(); erase_both(); blit_both(); commit_both(); show_pic(); do_update(); return err_OK; } int savegame_dialog () { char home[MAX_PATH], path[MAX_PATH]; char *desc; int slot = 0; if (get_app_dir (home, MAX_PATH) < 0) { message_box ("Couldn't save game."); return err_BadFileOpen; } message_box ("Multi-slot savegames are under development and" "will be available in future versions of Sarien."); desc = "Save game test"; /* DATADIR conflicts with ObjIdl.h in win32 SDK, renamed to DATA_DIR */ sprintf (path, "%s/" DATA_DIR "/", home); MKDIR (path, 0755); sprintf (path, "%s/" DATA_DIR "/%s/", home, game.id); MKDIR (path, 0711); sprintf (path, "%s/" DATA_DIR "/%s/%08d.sav", home, game.id, slot); _D (_D_WARN "file is [%s]", path); save_game(path, desc); message_box ("Game saved."); return err_OK; } int loadgame_dialog () { char home[MAX_PATH], path[MAX_PATH]; int slot = 0; int rc; if (get_app_dir (home, MAX_PATH) < 0) { message_box ("Error loading game."); return err_BadFileOpen; } sprintf (path, "%s/" DATA_DIR "/", home); MKDIR (path, 0755); sprintf (path, "%s/" DATA_DIR "/%s/", home, game.id); MKDIR (path, 0711); sprintf (path, "%s/" DATA_DIR "/%s/%08d.sav", home, game.id, slot); stop_sound(); if((rc = load_game (path)) == err_OK) message_box ("Game loaded."); else message_box ("Error loading game."); return rc; } #endif /* PALMOS */ /* end: savegame.c */