From e1c583fb43562e342287e2c57a4501da63f91ed5 Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Wed, 22 Jun 2005 09:42:30 +0000 Subject: [PATCH] use PhysicsFS for saving levels --- ChangeLog | 4 + main/editor/mine.c | 233 +++++++++++----------- main/gamesave.c | 467 +++++++++++++++++++++------------------------ 3 files changed, 329 insertions(+), 375 deletions(-) diff --git a/ChangeLog b/ChangeLog index 92ca1418..62dfb432 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ add function for converting descent 2 texture numbers back to descent 1 texture numbers + * main/editor/mine.c, main/gamesave.c: use PhysicsFS for saving + levels. Entirely endian friendly and allows saving of .rdl and .rl2 + files. + 2005-06-14 Chris Taylor * main/mission.c: make sure there is a path to free for D2 Demo/OEM diff --git a/main/editor/mine.c b/main/editor/mine.c index 70e3f11e..fe2f9540 100644 --- a/main/editor/mine.c +++ b/main/editor/mine.c @@ -1,4 +1,4 @@ -/* $Id: mine.c,v 1.8 2005-06-22 09:21:52 chris Exp $ */ +/* $Id: mine.c,v 1.9 2005-06-22 09:42:04 chris Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO @@ -19,7 +19,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifdef RCS -static char rcsid[] = "$Id: mine.c,v 1.8 2005-06-22 09:21:52 chris Exp $"; +static char rcsid[] = "$Id: mine.c,v 1.9 2005-06-22 09:42:04 chris Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -31,6 +31,7 @@ static char rcsid[] = "$Id: mine.c,v 1.8 2005-06-22 09:21:52 chris Exp $"; #include #include +#include "physfsx.h" #include "nocfile.h" #include "mono.h" #include "key.h" @@ -46,6 +47,7 @@ static char rcsid[] = "$Id: mine.c,v 1.8 2005-06-22 09:21:52 chris Exp $"; #include "object.h" #include "gamemine.h" +#include "gamesave.h" #include "gameseg.h" #include "ui.h" // Because texpage.h need UI_WINDOW type @@ -60,7 +62,6 @@ static char rcsid[] = "$Id: mine.c,v 1.8 2005-06-22 09:21:52 chris Exp $"; int CreateDefaultNewSegment(); int save_mine_data(CFILE * SaveFile); -int save_mine_data_compiled_new(FILE * SaveFile); static char current_tmap_list[MAX_TEXTURES][13]; @@ -493,7 +494,7 @@ int save_mine_data(CFILE * SaveFile) #define COMPILED_MINE_VERSION 0 -void dump_fix_as_short( fix value, int nbits, CFILE * SaveFile ) +void dump_fix_as_short( fix value, int nbits, PHYSFS_file *SaveFile ) { int int_value=0; short short_value; @@ -510,11 +511,11 @@ void dump_fix_as_short( fix value, int nbits, CFILE * SaveFile ) else short_value = (short)int_value; - cfwrite( &short_value, sizeof(short_value), 1, SaveFile ); + PHYSFS_writeSLE16(SaveFile, short_value); } //version of dump for unsigned values -void dump_fix_as_ushort( fix value, int nbits, CFILE * SaveFile ) +void dump_fix_as_ushort( fix value, int nbits, PHYSFS_file *SaveFile ) { uint int_value=0; ushort short_value; @@ -534,97 +535,42 @@ void dump_fix_as_ushort( fix value, int nbits, CFILE * SaveFile ) else short_value = int_value; - cfwrite( &short_value, sizeof(short_value), 1, SaveFile ); + PHYSFS_writeULE16(SaveFile, short_value); } -// ----------------------------------------------------------------------------- -// saves compiled mine data to an already-open file... -int save_mine_data_compiled(FILE * SaveFile) +void write_children(segment *seg, ubyte bit_mask, PHYSFS_file *SaveFile) { - short i,segnum,sidenum; - ubyte version = COMPILED_MINE_VERSION; - -#ifndef SHAREWARE - if (New_file_format_save) - return save_mine_data_compiled_new(SaveFile); -#endif - - med_compress_mine(); - warn_if_concave_segments(); + int bit; - if (Highest_segment_index >= MAX_SEGMENTS) { - char message[128]; - sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_SEGMENTS); - MessageBox( -2, -2, 1, message, "Ok" ); - } - - if (Highest_vertex_index >= MAX_VERTICES) { - char message[128]; - sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_VERTICES); - MessageBox( -2, -2, 1, message, "Ok" ); + for (bit = 0; bit < MAX_SIDES_PER_SEGMENT; bit++) + { + if (bit_mask & (1 << bit)) + PHYSFS_writeSLE16(SaveFile, seg->children[bit]); } +} - //=============================== Writing part ============================== - cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version - cfwrite( &Num_vertices, sizeof(int), 1, SaveFile ); // 4 bytes = Num_vertices - cfwrite( &Num_segments, sizeof(int), 1, SaveFile ); // 4 bytes = Num_segments - cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile ); - - for (segnum=0; segnum>5, write as short, l>>1 write as short) - for (i=0; i<4; i++ ) { - dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile ); - dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile ); - dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile ); - //cfwrite( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, SaveFile ); - } - } - } + for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++) + PHYSFS_writeSLE16(SaveFile, seg->verts[i]); +} +void write_special(segment2 *seg2, ubyte bit_mask, PHYSFS_file *SaveFile) +{ + if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) + { + PHYSFSX_writeU8(SaveFile, seg2->special); + PHYSFSX_writeU8(SaveFile, seg2->matcen_num); + PHYSFS_writeSLE16(SaveFile, seg2->value); } - - return 0; } - // ----------------------------------------------------------------------------- // saves compiled mine data to an already-open file... -int save_mine_data_compiled_new(FILE * SaveFile) +int save_mine_data_compiled(PHYSFS_file *SaveFile) { - short i, segnum, sidenum, temp_short; + short i, segnum, sidenum; ubyte version = COMPILED_MINE_VERSION; ubyte bit_mask = 0; @@ -644,80 +590,119 @@ int save_mine_data_compiled_new(FILE * SaveFile) } //=============================== Writing part ============================== - cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version - temp_short = Num_vertices; - cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_vertices - temp_short = Num_segments; - cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_segments - cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile ); + PHYSFSX_writeU8(SaveFile, version); // 1 byte = compiled version + if (New_file_format_save) + { + PHYSFS_writeSLE16(SaveFile, Num_vertices); // 2 bytes = Num_vertices + PHYSFS_writeSLE16(SaveFile, Num_segments); // 2 bytes = Num_segments + } + else + { + PHYSFS_writeSLE32(SaveFile, Num_vertices); // 4 bytes = Num_vertices + PHYSFS_writeSLE32(SaveFile, Num_segments); // 4 bytes = Num_segments + } - for (segnum=0; segnumchildren[sidenum] != -1) bit_mask |= (1 << sidenum); } - if ((Segment2s[segnum].special != 0) || (Segment2s[segnum].matcen_num != 0) || (Segment2s[segnum].value != 0)) + if ((seg2->special != 0) || (seg2->matcen_num != 0) || (seg2->value != 0)) bit_mask |= (1 << MAX_SIDES_PER_SEGMENT); - cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile ); + if (New_file_format_save) + PHYSFSX_writeU8(SaveFile, bit_mask); + else + bit_mask = 0x7F; - for (sidenum=0; sidenumstatic_light, 4, SaveFile); // Write the walls as a 6 byte array bit_mask = 0; - for (sidenum=0; sidenum= 0) { + + if (seg->sides[sidenum].wall_num >= 0) + { bit_mask |= (1 << sidenum); - wallnum = Segments[segnum].sides[sidenum].wall_num; + wallnum = seg->sides[sidenum].wall_num; Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!! } } - cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile ); + if (New_file_format_save) + PHYSFSX_writeU8(SaveFile, bit_mask); + else + bit_mask = 0x3F; - for (sidenum=0; sidenumsides[sidenum].wall_num); } - for (sidenum=0; sidenumchildren[sidenum] == -1) || (seg->sides[sidenum].wall_num != -1)) + { ushort tmap_num, tmap_num2; - tmap_num = Segments[segnum].sides[sidenum].tmap_num; - tmap_num2 = Segments[segnum].sides[sidenum].tmap_num2; - if (tmap_num2 != 0) + tmap_num = seg->sides[sidenum].tmap_num; + tmap_num2 = seg->sides[sidenum].tmap_num2; + + if (Gamesave_current_version <= 3) // convert texture numbers back to d1 + { + tmap_num = convert_to_d1_tmap_num(tmap_num); + if (tmap_num2) + tmap_num2 = convert_to_d1_tmap_num(tmap_num2); + } + + if (tmap_num2 != 0 && New_file_format_save) tmap_num |= 0x8000; - cfwrite( &tmap_num, sizeof(ushort), 1, SaveFile ); - if (tmap_num2 != 0) - cfwrite( &tmap_num2, sizeof(ushort), 1, SaveFile ); + PHYSFS_writeSLE16(SaveFile, tmap_num); + if (tmap_num2 != 0 || !New_file_format_save) + PHYSFS_writeSLE16(SaveFile, tmap_num2); - for (i=0; i<4; i++ ) { - dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile ); - dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile ); - dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile ); + for (i = 0; i < 4; i++) + { + dump_fix_as_short(seg->sides[sidenum].uvls[i].u, 5, SaveFile); + dump_fix_as_short(seg->sides[sidenum].uvls[i].v, 5, SaveFile); + dump_fix_as_ushort(seg->sides[sidenum].uvls[i].l, 1, SaveFile); } } } } + if (Gamesave_current_version > 5) + for (i = 0; i < Num_segments; i++) + segment2_write(&Segment2s[i], SaveFile); + return 0; } diff --git a/main/gamesave.c b/main/gamesave.c index 52f286f1..f9fdadd0 100644 --- a/main/gamesave.c +++ b/main/gamesave.c @@ -1,4 +1,4 @@ -/* $Id: gamesave.c,v 1.31 2005-03-12 07:50:53 chris Exp $ */ +/* $Id: gamesave.c,v 1.32 2005-06-22 09:42:04 chris Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO @@ -23,7 +23,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #endif #ifdef RCS -char gamesave_rcsid[] = "$Id: gamesave.c,v 1.31 2005-03-12 07:50:53 chris Exp $"; +char gamesave_rcsid[] = "$Id: gamesave.c,v 1.32 2005-06-22 09:42:04 chris Exp $"; #endif #include @@ -136,7 +136,7 @@ struct { // LINT: adding function prototypes void read_object(object *obj, CFILE *f, int version); #ifdef EDITOR -void write_object(object *obj, FILE *f); +void write_object(object *obj, short version, PHYSFS_file *f); void do_load_save_levels(int save); #endif #ifndef NDEBUG @@ -148,7 +148,7 @@ extern char PowerupsInMine[MAX_POWERUP_TYPES]; #ifdef EDITOR extern char mine_filename[]; -extern int save_mine_data_compiled(FILE * SaveFile); +extern int save_mine_data_compiled(PHYSFS_file *SaveFile); //--unused-- #else //--unused-- char mine_filename[128]; #endif @@ -365,65 +365,6 @@ void verify_object( object * obj ) { // cfseek(file,len,SEEK_CUR); //} -#ifdef EDITOR -static void gs_write_int(int i,FILE *file) -{ - if (fwrite( &i, sizeof(i), 1, file) != 1) - Error( "Error reading int in gamesave.c" ); - -} - -static void gs_write_fix(fix f,FILE *file) -{ - if (fwrite( &f, sizeof(f), 1, file) != 1) - Error( "Error reading fix in gamesave.c" ); - -} - -static void gs_write_short(short s,FILE *file) -{ - if (fwrite( &s, sizeof(s), 1, file) != 1) - Error( "Error reading short in gamesave.c" ); - -} - -static void gs_write_fixang(fixang f,FILE *file) -{ - if (fwrite( &f, sizeof(f), 1, file) != 1) - Error( "Error reading fixang in gamesave.c" ); - -} - -static void gs_write_byte(sbyte b,FILE *file) -{ - if (fwrite( &b, sizeof(b), 1, file) != 1) - Error( "Error reading byte in gamesave.c" ); - -} - -static void gr_write_vector(vms_vector *v,FILE *file) -{ - gs_write_fix(v->x,file); - gs_write_fix(v->y,file); - gs_write_fix(v->z,file); -} - -static void gs_write_matrix(vms_matrix *m,FILE *file) -{ - gr_write_vector(&m->rvec,file); - gr_write_vector(&m->uvec,file); - gr_write_vector(&m->fvec,file); -} - -static void gs_write_angvec(vms_angvec *v,FILE *file) -{ - gs_write_fixang(v->p,file); - gs_write_fixang(v->b,file); - gs_write_fixang(v->h,file); -} - -#endif - extern int multi_powerup_is_4pack(int); //reads one object of the given version from the given file @@ -632,52 +573,52 @@ void read_object(object *obj,CFILE *f,int version) #ifdef EDITOR //writes one object to the given file -void write_object(object *obj,FILE *f) +void write_object(object *obj, short version, PHYSFS_file *f) { - gs_write_byte(obj->type,f); - gs_write_byte(obj->id,f); + PHYSFSX_writeU8(f, obj->type); + PHYSFSX_writeU8(f, obj->id); - gs_write_byte(obj->control_type,f); - gs_write_byte(obj->movement_type,f); - gs_write_byte(obj->render_type,f); - gs_write_byte(obj->flags,f); + PHYSFSX_writeU8(f, obj->control_type); + PHYSFSX_writeU8(f, obj->movement_type); + PHYSFSX_writeU8(f, obj->render_type); + PHYSFSX_writeU8(f, obj->flags); - gs_write_short(obj->segnum,f); + PHYSFS_writeSLE16(f, obj->segnum); - gr_write_vector(&obj->pos,f); - gs_write_matrix(&obj->orient,f); + PHYSFSX_writeVector(f, &obj->pos); + PHYSFSX_writeMatrix(f, &obj->orient); - gs_write_fix(obj->size,f); - gs_write_fix(obj->shields,f); + PHYSFSX_writeFix(f, obj->size); + PHYSFSX_writeFix(f, obj->shields); - gr_write_vector(&obj->last_pos,f); + PHYSFSX_writeVector(f, &obj->last_pos); - gs_write_byte(obj->contains_type,f); - gs_write_byte(obj->contains_id,f); - gs_write_byte(obj->contains_count,f); + PHYSFSX_writeU8(f, obj->contains_type); + PHYSFSX_writeU8(f, obj->contains_id); + PHYSFSX_writeU8(f, obj->contains_count); switch (obj->movement_type) { case MT_PHYSICS: - gr_write_vector(&obj->mtype.phys_info.velocity,f); - gr_write_vector(&obj->mtype.phys_info.thrust,f); + PHYSFSX_writeVector(f, &obj->mtype.phys_info.velocity); + PHYSFSX_writeVector(f, &obj->mtype.phys_info.thrust); - gs_write_fix(obj->mtype.phys_info.mass,f); - gs_write_fix(obj->mtype.phys_info.drag,f); - gs_write_fix(obj->mtype.phys_info.brakes,f); + PHYSFSX_writeFix(f, obj->mtype.phys_info.mass); + PHYSFSX_writeFix(f, obj->mtype.phys_info.drag); + PHYSFSX_writeFix(f, obj->mtype.phys_info.brakes); - gr_write_vector(&obj->mtype.phys_info.rotvel,f); - gr_write_vector(&obj->mtype.phys_info.rotthrust,f); + PHYSFSX_writeVector(f, &obj->mtype.phys_info.rotvel); + PHYSFSX_writeVector(f, &obj->mtype.phys_info.rotthrust); - gs_write_fixang(obj->mtype.phys_info.turnroll,f); - gs_write_short(obj->mtype.phys_info.flags,f); + PHYSFSX_writeFixAng(f, obj->mtype.phys_info.turnroll); + PHYSFS_writeSLE16(f, obj->mtype.phys_info.flags); break; case MT_SPINNING: - gr_write_vector(&obj->mtype.spin_rate,f); + PHYSFSX_writeVector(f, &obj->mtype.spin_rate); break; case MT_NONE: @@ -692,27 +633,30 @@ void write_object(object *obj,FILE *f) case CT_AI: { int i; - gs_write_byte(obj->ctype.ai_info.behavior,f); + PHYSFSX_writeU8(f, obj->ctype.ai_info.behavior); - for (i=0;ictype.ai_info.flags[i],f); + for (i = 0; i < MAX_AI_FLAGS; i++) + PHYSFSX_writeU8(f, obj->ctype.ai_info.flags[i]); - gs_write_short(obj->ctype.ai_info.hide_segment,f); - gs_write_short(obj->ctype.ai_info.hide_index,f); - gs_write_short(obj->ctype.ai_info.path_length,f); - gs_write_short(obj->ctype.ai_info.cur_path_index,f); + PHYSFS_writeSLE16(f, obj->ctype.ai_info.hide_segment); + PHYSFS_writeSLE16(f, obj->ctype.ai_info.hide_index); + PHYSFS_writeSLE16(f, obj->ctype.ai_info.path_length); + PHYSFS_writeSLE16(f, obj->ctype.ai_info.cur_path_index); - // -- unused! mk, 08/13/95 -- gs_write_short(obj->ctype.ai_info.follow_path_start_seg,f); - // -- unused! mk, 08/13/95 -- gs_write_short(obj->ctype.ai_info.follow_path_end_seg,f); + if (version <= 25) + { + PHYSFS_writeSLE16(f, -1); //obj->ctype.ai_info.follow_path_start_seg + PHYSFS_writeSLE16(f, -1); //obj->ctype.ai_info.follow_path_end_seg + } break; } case CT_EXPLOSION: - gs_write_fix(obj->ctype.expl_info.spawn_time,f); - gs_write_fix(obj->ctype.expl_info.delete_time,f); - gs_write_short(obj->ctype.expl_info.delete_objnum,f); + PHYSFSX_writeFix(f, obj->ctype.expl_info.spawn_time); + PHYSFSX_writeFix(f, obj->ctype.expl_info.delete_time); + PHYSFS_writeSLE16(f, obj->ctype.expl_info.delete_objnum); break; @@ -720,20 +664,21 @@ void write_object(object *obj,FILE *f) //do I really need to write these objects? - gs_write_short(obj->ctype.laser_info.parent_type,f); - gs_write_short(obj->ctype.laser_info.parent_num,f); - gs_write_int(obj->ctype.laser_info.parent_signature,f); + PHYSFS_writeSLE16(f, obj->ctype.laser_info.parent_type); + PHYSFS_writeSLE16(f, obj->ctype.laser_info.parent_num); + PHYSFS_writeSLE32(f, obj->ctype.laser_info.parent_signature); break; case CT_LIGHT: - gs_write_fix(obj->ctype.light_info.intensity,f); + PHYSFSX_writeFix(f, obj->ctype.light_info.intensity); break; case CT_POWERUP: - gs_write_int(obj->ctype.powerup_info.count,f); + if (version >= 25) + PHYSFS_writeSLE32(f, obj->ctype.powerup_info.count); break; case CT_NONE: @@ -764,14 +709,14 @@ void write_object(object *obj,FILE *f) case RT_POLYOBJ: { int i; - gs_write_int(obj->rtype.pobj_info.model_num,f); + PHYSFS_writeSLE32(f, obj->rtype.pobj_info.model_num); - for (i=0;irtype.pobj_info.anim_angles[i],f); + for (i = 0; i < MAX_SUBMODELS; i++) + PHYSFSX_writeAngleVec(f, &obj->rtype.pobj_info.anim_angles[i]); - gs_write_int(obj->rtype.pobj_info.subobj_flags,f); + PHYSFS_writeSLE32(f, obj->rtype.pobj_info.subobj_flags); - gs_write_int(obj->rtype.pobj_info.tmap_override,f); + PHYSFS_writeSLE32(f, obj->rtype.pobj_info.tmap_override); break; } @@ -781,9 +726,9 @@ void write_object(object *obj,FILE *f) case RT_POWERUP: case RT_FIREBALL: - gs_write_int(obj->rtype.vclip_info.vclip_num,f); - gs_write_fix(obj->rtype.vclip_info.frametime,f); - gs_write_byte(obj->rtype.vclip_info.framenum,f); + PHYSFS_writeSLE32(f, obj->rtype.vclip_info.vclip_num); + PHYSFSX_writeFix(f, obj->rtype.vclip_info.frametime); + PHYSFSX_writeU8(f, obj->rtype.vclip_info.framenum); break; @@ -1272,6 +1217,7 @@ extern void ncache_flush(); #endif extern int Slide_segs_computed; +extern int d1_pig_present; int no_old_level_file_error=0; @@ -1467,20 +1413,16 @@ int load_level(char * filename_passed) #endif #ifdef EDITOR - //If an old version, ask the use if he wants to save as new version - if (!no_old_level_file_error && (Function_mode == FMODE_EDITOR) && (((LEVEL_FILE_VERSION > 3) && Gamesave_current_version < LEVEL_FILE_VERSION) || mine_err == 1 || game_err == 1)) { - char ErrorMessage[200]; - - sprintf( ErrorMessage, - "You just loaded a old version\n" - "level. Would you like to save\n" - "it as a current version level?"); + //If a Descent 1 level and the Descent 1 pig isn't present, pretend it's a Descent 2 level. + if ((Function_mode == FMODE_EDITOR) && (Gamesave_current_version <= 3) && !d1_pig_present) + { + if (!no_old_level_file_error) + Warning("A Descent 1 level was loaded,\n" + "and there is no Descent 1 texture\n" + "set available. Saving it will\n" + "convert it to a Descent 2 level."); - stop_time(); - gr_palette_load(gr_palette); - if (nm_messagebox( NULL, 2, "Don't Save", "Save", ErrorMessage )==1) - save_level(filename); - start_time(); + Gamesave_current_version = LEVEL_FILE_VERSION; } #endif @@ -1563,133 +1505,140 @@ int compute_num_delta_light_records(void) // ----------------------------------------------------------------------------- // Save game -int save_game_data(FILE * SaveFile) +int save_game_data(PHYSFS_file *SaveFile) { + short game_top_fileinfo_version = Gamesave_current_version >= 5 ? 31 : 25; int player_offset, object_offset, walls_offset, doors_offset, triggers_offset, control_offset, matcen_offset; //, links_offset; int dl_indices_offset, delta_light_offset; - int start_offset,end_offset; - - start_offset = ftell(SaveFile); + int offset_offset, end_offset; + int num_delta_lights; + int i; //===================== SAVE FILE INFO ======================== - game_fileinfo.fileinfo_signature = 0x6705; - game_fileinfo.fileinfo_version = GAME_VERSION; - game_fileinfo.level = Current_level_num; - game_fileinfo.fileinfo_sizeof = sizeof(game_fileinfo); - game_fileinfo.player_offset = -1; - game_fileinfo.player_sizeof = sizeof(player); - game_fileinfo.object_offset = -1; - game_fileinfo.object_howmany = Highest_object_index+1; - game_fileinfo.object_sizeof = sizeof(object); - game_fileinfo.walls_offset = -1; - game_fileinfo.walls_howmany = Num_walls; - game_fileinfo.walls_sizeof = sizeof(wall); - game_fileinfo.doors_offset = -1; - game_fileinfo.doors_howmany = Num_open_doors; - game_fileinfo.doors_sizeof = sizeof(active_door); - game_fileinfo.triggers_offset = -1; - game_fileinfo.triggers_howmany = Num_triggers; - game_fileinfo.triggers_sizeof = sizeof(trigger); - game_fileinfo.control_offset = -1; - game_fileinfo.control_howmany = 1; - game_fileinfo.control_sizeof = sizeof(control_center_triggers); - game_fileinfo.matcen_offset = -1; - game_fileinfo.matcen_howmany = Num_robot_centers; - game_fileinfo.matcen_sizeof = sizeof(matcen_info); - - game_fileinfo.dl_indices_offset = -1; - game_fileinfo.dl_indices_howmany = Num_static_lights; - game_fileinfo.dl_indices_sizeof = sizeof(dl_index); - - game_fileinfo.delta_light_offset = -1; - game_fileinfo.delta_light_howmany = compute_num_delta_light_records(); - game_fileinfo.delta_light_sizeof = sizeof(delta_light); - - // Write the fileinfo - fwrite( &game_fileinfo, sizeof(game_fileinfo), 1, SaveFile ); + PHYSFS_writeSLE16(SaveFile, 0x6705); // signature + PHYSFS_writeSLE16(SaveFile, game_top_fileinfo_version); + PHYSFS_writeSLE32(SaveFile, sizeof(game_fileinfo)); + PHYSFS_write(SaveFile, Current_level_name, 15, 1); + PHYSFS_writeSLE32(SaveFile, Current_level_num); + offset_offset = PHYSFS_tell(SaveFile); // write the offsets later + PHYSFS_writeSLE32(SaveFile, -1); + PHYSFS_writeSLE32(SaveFile, sizeof(player)); + +#define WRITE_HEADER_ENTRY(t, n) do { PHYSFS_writeSLE32(SaveFile, -1); PHYSFS_writeSLE32(SaveFile, n); PHYSFS_writeSLE32(SaveFile, sizeof(t)); } while(0) + + WRITE_HEADER_ENTRY(object, Highest_object_index + 1); + WRITE_HEADER_ENTRY(wall, Num_walls); + WRITE_HEADER_ENTRY(active_door, Num_open_doors); + WRITE_HEADER_ENTRY(trigger, Num_triggers); + WRITE_HEADER_ENTRY(0, 0); // links (removed by Parallax) + WRITE_HEADER_ENTRY(control_center_triggers, 1); + WRITE_HEADER_ENTRY(matcen_info, Num_robot_centers); + + if (game_top_fileinfo_version >= 29) + { + WRITE_HEADER_ENTRY(dl_index, Num_static_lights); + WRITE_HEADER_ENTRY(delta_light, num_delta_lights = compute_num_delta_light_records()); + } // Write the mine name - fprintf(SaveFile,"%s\n",Current_level_name); + if (game_top_fileinfo_version >= 31) + PHYSFSX_printf(SaveFile, "%s\n", Current_level_name); + else if (game_top_fileinfo_version >= 14) + PHYSFSX_writeString(SaveFile, Current_level_name); - fwrite(&N_polygon_models,2,1,SaveFile); - fwrite(Pof_names,N_polygon_models,sizeof(*Pof_names),SaveFile); + if (game_top_fileinfo_version >= 19) + { + PHYSFS_writeSLE16(SaveFile, N_polygon_models); + PHYSFS_write(SaveFile, Pof_names, sizeof(*Pof_names), N_polygon_models); + } //==================== SAVE PLAYER INFO =========================== - player_offset = ftell(SaveFile); - fwrite( &Players[Player_num], sizeof(player), 1, SaveFile ); + player_offset = PHYSFS_tell(SaveFile); + PHYSFS_write(SaveFile, &Players[Player_num], sizeof(player), 1); // not endian friendly, but not used either //==================== SAVE OBJECT INFO =========================== - object_offset = ftell(SaveFile); + object_offset = PHYSFS_tell(SaveFile); //fwrite( &Objects, sizeof(object), game_fileinfo.object_howmany, SaveFile ); { - int i; - for (i=0;i= 29) + { + dl_indices_offset = PHYSFS_tell(SaveFile); + for (i = 0; i < Num_static_lights; i++) + dl_index_write(&Dl_indices[i], SaveFile); - delta_light_offset = ftell(SaveFile); - fwrite( Delta_lights, sizeof(delta_light), game_fileinfo.delta_light_howmany, SaveFile ); + delta_light_offset = PHYSFS_tell(SaveFile); + for (i = 0; i < num_delta_lights; i++) + delta_light_write(&Delta_lights[i], SaveFile); + } - //============= REWRITE FILE INFO, TO SAVE OFFSETS =============== + //============= SAVE OFFSETS =============== - // Update the offset fields - game_fileinfo.player_offset = player_offset; - game_fileinfo.object_offset = object_offset; - game_fileinfo.walls_offset = walls_offset; - game_fileinfo.doors_offset = doors_offset; - game_fileinfo.triggers_offset = triggers_offset; - game_fileinfo.control_offset = control_offset; - game_fileinfo.matcen_offset = matcen_offset; - game_fileinfo.dl_indices_offset = dl_indices_offset; - game_fileinfo.delta_light_offset = delta_light_offset; + end_offset = PHYSFS_tell(SaveFile); + // Update the offset fields - end_offset = ftell(SaveFile); +#define WRITE_OFFSET(o, n) do { PHYSFS_seek(SaveFile, offset_offset); PHYSFS_writeSLE32(SaveFile, o ## _offset); offset_offset += sizeof(int)*n; } while (0) - // Write the fileinfo - fseek( SaveFile, start_offset, SEEK_SET ); // Move to TOF - fwrite( &game_fileinfo, sizeof(game_fileinfo), 1, SaveFile ); + WRITE_OFFSET(player, 2); + WRITE_OFFSET(object, 3); + WRITE_OFFSET(walls, 3); + WRITE_OFFSET(doors, 3); + WRITE_OFFSET(triggers, 6); + WRITE_OFFSET(control, 3); + WRITE_OFFSET(matcen, 3); + if (game_top_fileinfo_version >= 29) + { + WRITE_OFFSET(dl_indices, 3); + WRITE_OFFSET(delta_light, 0); + } // Go back to end of data - fseek(SaveFile,end_offset,SEEK_SET); + PHYSFS_seek(SaveFile, end_offset); return 0; } @@ -1700,12 +1649,12 @@ int save_mine_data(FILE * SaveFile); // Save game int save_level_sub(char * filename, int compiled_version) { - FILE * SaveFile; + PHYSFS_file * SaveFile; char temp_filename[PATH_MAX]; - int sig = MAKE_SIG('P','L','V','L'),version=LEVEL_FILE_VERSION; int minedata_offset=0,gamedata_offset=0; - if ( !compiled_version ) { +// if ( !compiled_version ) + { write_game_text_file(filename); if (Errors_in_mine) { @@ -1724,19 +1673,17 @@ int save_level_sub(char * filename, int compiled_version) } else mprintf((1, "Error: %i errors in this mine. See the 'txm' file.\n", Errors_in_mine)); } - change_filename_extension(temp_filename,filename,".LVL"); +// change_filename_extension(temp_filename,filename,".LVL"); } - else +// else { - // macs are using the regular hog/rl2 files for shareware - #if defined(SHAREWARE) && !defined(MACINTOSH) - change_filename_extension(temp_filename,filename,".SL2"); - #else - change_filename_extension(temp_filename,filename,".RL2"); - #endif + if (Gamesave_current_version <= 3) + change_filename_extension(temp_filename, filename, ".RDL"); + else + change_filename_extension(temp_filename, filename, ".RL2"); } - SaveFile = fopen( temp_filename, "wb" ); + SaveFile = PHYSFSX_openWriteBuffered(temp_filename); if (!SaveFile) { char ErrorMessage[256]; @@ -1772,56 +1719,74 @@ int save_level_sub(char * filename, int compiled_version) //Write the header - gs_write_int(sig,SaveFile); - gs_write_int(version,SaveFile); + PHYSFS_writeSLE32(SaveFile, MAKE_SIG('P','L','V','L')); + PHYSFS_writeSLE32(SaveFile, Gamesave_current_version); //save placeholders - gs_write_int(minedata_offset,SaveFile); - gs_write_int(gamedata_offset,SaveFile); + PHYSFS_writeSLE32(SaveFile, minedata_offset); + PHYSFS_writeSLE32(SaveFile, gamedata_offset); //Now write the damn data - //write the version 8 data (to make file unreadable by 1.0 & 1.1) - gs_write_int(GameTime,SaveFile); - gs_write_short(FrameCount,SaveFile); - gs_write_byte(FrameTime,SaveFile); + if (Gamesave_current_version >= 8) + { + //write the version 8 data (to make file unreadable by 1.0 & 1.1) + PHYSFS_writeSLE32(SaveFile, GameTime); + PHYSFS_writeSLE16(SaveFile, FrameCount); + PHYSFSX_writeU8(SaveFile, FrameTime); + } + + if (Gamesave_current_version < 5) + PHYSFS_writeSLE32(SaveFile, -1); //was hostagetext_offset // Write the palette file name - fprintf(SaveFile,"%s\n",Current_level_palette); + if (Gamesave_current_version > 1) + PHYSFSX_printf(SaveFile, "%s\n", Current_level_palette); - gs_write_int(Base_control_center_explosion_time,SaveFile); - gs_write_int(Reactor_strength,SaveFile); + if (Gamesave_current_version >= 3) + PHYSFS_writeSLE32(SaveFile, Base_control_center_explosion_time); + if (Gamesave_current_version >= 4) + PHYSFS_writeSLE32(SaveFile, Reactor_strength); - gs_write_int(Num_flickering_lights,SaveFile); - fwrite(Flickering_lights,sizeof(*Flickering_lights),Num_flickering_lights,SaveFile); - - gs_write_int(Secret_return_segment, SaveFile); - gs_write_int(Secret_return_orient.rvec.x, SaveFile); - gs_write_int(Secret_return_orient.rvec.y, SaveFile); - gs_write_int(Secret_return_orient.rvec.z, SaveFile); - gs_write_int(Secret_return_orient.fvec.x, SaveFile); - gs_write_int(Secret_return_orient.fvec.y, SaveFile); - gs_write_int(Secret_return_orient.fvec.z, SaveFile); - gs_write_int(Secret_return_orient.uvec.x, SaveFile); - gs_write_int(Secret_return_orient.uvec.y, SaveFile); - gs_write_int(Secret_return_orient.uvec.z, SaveFile); - - minedata_offset = ftell(SaveFile); + if (Gamesave_current_version >= 7) + { + int i; + + PHYSFS_writeSLE32(SaveFile, Num_flickering_lights); + for (i = 0; i < Num_flickering_lights; i++) + flickering_light_write(&Flickering_lights[i], SaveFile); + } + + if (Gamesave_current_version >= 6) + { + PHYSFS_writeSLE32(SaveFile, Secret_return_segment); + PHYSFSX_writeVector(SaveFile, &Secret_return_orient.rvec); + PHYSFSX_writeVector(SaveFile, &Secret_return_orient.fvec); + PHYSFSX_writeVector(SaveFile, &Secret_return_orient.uvec); + } + + minedata_offset = PHYSFS_tell(SaveFile); +#if 0 // only save compiled mine data if ( !compiled_version ) save_mine_data(SaveFile); else +#endif save_mine_data_compiled(SaveFile); - gamedata_offset = ftell(SaveFile); + gamedata_offset = PHYSFS_tell(SaveFile); save_game_data(SaveFile); - fseek(SaveFile,sizeof(sig)+sizeof(version),SEEK_SET); - gs_write_int(minedata_offset,SaveFile); - gs_write_int(gamedata_offset,SaveFile); + PHYSFS_seek(SaveFile, sizeof(int) + sizeof(Gamesave_current_version)); + PHYSFS_writeSLE32(SaveFile, minedata_offset); + PHYSFS_writeSLE32(SaveFile, gamedata_offset); + + if (Gamesave_current_version < 5) + PHYSFS_writeSLE32(SaveFile, PHYSFS_fileLength(SaveFile)); //==================== CLOSE THE FILE ============================= - fclose(SaveFile); + PHYSFS_close(SaveFile); - if ( !compiled_version ) { +// if ( !compiled_version ) + { if (Function_mode == FMODE_EDITOR) editor_status("Saved mine %s, \"%s\"",filename,Current_level_name); } @@ -1839,10 +1804,10 @@ int save_level(char * filename) int r1; // Save normal version... - r1 = save_level_sub(filename, 0); + //save_level_sub(filename, 0); // just save compiled one // Save compiled version... - save_level_sub(filename, 1); + r1 = save_level_sub(filename, 1); return r1; } -- 2.39.2