void wall_write(wall *w, short version, PHYSFS_file *fp) { if (version >= 17) { PHYSFS_writeSLE32(fp, w->segnum); PHYSFS_writeSLE32(fp, w->sidenum); } if (version >= 20) { PHYSFSX_writeFix(fp, w->hps); PHYSFS_writeSLE32(fp, w->linked_wall); } PHYSFSX_writeU8(fp, w->type); PHYSFSX_writeU8(fp, w->flags); if (version < 20) PHYSFSX_writeFix(fp, w->hps); else PHYSFSX_writeU8(fp, w->state); PHYSFSX_writeU8(fp, w->trigger); PHYSFSX_writeU8(fp, w->clip_num); PHYSFSX_writeU8(fp, w->keys); if (version >= 20) { PHYSFSX_writeU8(fp, w->controlling_trigger); PHYSFSX_writeU8(fp, w->cloak_value); } else if (version >= 17) PHYSFS_writeSLE32(fp, w->linked_wall); }
static void writeSurfaces( const char *filename, std::vector< RenderSurface > &surfaces ) { uint64_t hashedName = HashedString( 0, filename ); char outfile[256]; PHYSFS_mkdir( "static_models/" ); sprintf( outfile, "static_models/%08x_%08x.sm", (uint32_t)(hashedName>>32), (uint32_t)(hashedName&0xffffffff) ); PHYSFS_File *model = PHYSFS_openWrite( outfile ); if ( model ) { PHYSFS_writeULE32( model, 0x090 ); PHYSFS_writeULE32( model, surfaces.size() ); for ( uint32_t i=0; i<surfaces.size(); i++ ) { RenderSurface const &surf = surfaces[i]; PHYSFS_writeCStr( model, surf.name.c_str() ); PHYSFS_writeCStr( model, surf.mat->Name() ); const ModelGeometry *geom = surf.geom; PHYSFS_writeSLE32( model, geom->m_numIndices ); PHYSFS_writeSLE32( model, geom->m_numVerts ); PHYSFS_write( model, geom->m_indices, sizeof(uint16_t)*geom->m_numIndices, 1 ); PHYSFS_write( model, geom->m_verts, sizeof(geom->m_verts[0])*geom->m_numVerts, 1 ); } PHYSFS_close( model ); } }
void FileStream::add32(int32 v) { if(!m_caching) { if(PHYSFS_writeSLE32(m_fileHandle, v) == 0) throwError("write failed", true); } else { m_data.grow(m_pos + 4); stdext::writeSLE32(&m_data[m_pos], v); m_pos += 4; } }
//write out player's saved games. returns errno (0 == no error) int write_player_file() { char filename[PATH_MAX]; PHYSFS_file *file; int errno_ret, i; if ( Newdemo_state == ND_STATE_PLAYBACK ) return -1; errno_ret = WriteConfigFile(); memset(filename, '\0', PATH_MAX); snprintf(filename, PATH_MAX, GameArg.SysUsePlayersDir? "Players/%.8s.plx" : "%.8s.plx", Players[Player_num].callsign); write_player_d1x(filename); snprintf(filename, PATH_MAX, GameArg.SysUsePlayersDir? "Players/%.8s.plr" : "%.8s.plr", Players[Player_num].callsign); file = PHYSFSX_openWriteBuffered(filename); if (!file) return errno; PHYSFS_writeULE32(file, SAVE_FILE_ID); PHYSFS_writeULE16(file, SAVED_GAME_VERSION); PHYSFS_writeULE16(file, PLAYER_STRUCT_VERSION); PHYSFS_writeSLE32(file, PlayerCfg.NHighestLevels); PHYSFS_writeSLE32(file, PlayerCfg.DefaultDifficulty); PHYSFS_writeSLE32(file, PlayerCfg.AutoLeveling); errno_ret = EZERO; //write higest level info if ((PHYSFS_write( file, PlayerCfg.HighestLevels, sizeof(hli), PlayerCfg.NHighestLevels) != PlayerCfg.NHighestLevels)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } if (PHYSFS_write( file, saved_games,sizeof(saved_games),1) != 1) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } #ifdef NETWORK if ((PHYSFS_write( file, PlayerCfg.NetworkMessageMacro, MAX_MESSAGE_LEN, 4) != 4)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } #else { //PHYSFS_seek( file, PHYSFS_tell(file)+MAX_MESSAGE_LEN * 4 ); // Seeking is bad for Mac OS 9 char dummy[MAX_MESSAGE_LEN][4]; if ((PHYSFS_write( file, dummy, MAX_MESSAGE_LEN, 4) != 4)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } } #endif //write kconfig info { if (PHYSFS_write(file, PlayerCfg.KeySettings[0], sizeof(PlayerCfg.KeySettings[0]), 1) != 1) errno_ret=errno; if (PHYSFS_write(file, PlayerCfg.KeySettings[1], sizeof(PlayerCfg.KeySettings[1]), 1) != 1) errno_ret=errno; for (i = 0; i < MAX_CONTROLS*3; i++) if (PHYSFS_write(file, "0", sizeof(ubyte), 1) != 1) // Skip obsolete Flightstick/Thrustmaster/Gravis map fields errno_ret=errno; if (PHYSFS_write(file, PlayerCfg.KeySettings[2], sizeof(PlayerCfg.KeySettings[2]), 1) != 1) errno_ret=errno; for (i = 0; i < MAX_CONTROLS; i++) if (PHYSFS_write(file, "0", sizeof(ubyte), 1) != 1) // Skip obsolete Cyberman map field errno_ret=errno; if(errno_ret == EZERO) { ubyte old_avg_joy_sensitivity = 8; if (PHYSFS_write( file, &PlayerCfg.ControlType, sizeof(ubyte), 1 )!=1) errno_ret=errno; else if (PHYSFS_write( file, &old_avg_joy_sensitivity, sizeof(ubyte), 1 )!=1) errno_ret=errno; } } if (!PHYSFS_close(file)) errno_ret = errno; if (errno_ret != EZERO) { PHYSFS_delete(filename); //delete bogus file nm_messagebox(TXT_ERROR, 1, TXT_OK, "%s\n\n%s",TXT_ERROR_WRITING_PLR, strerror(errno_ret)); } return errno_ret; }
//writes one object to the given file void write_object(object *obj, PHYSFS_file *f) { PHYSFSX_writeU8(f, obj->type); PHYSFSX_writeU8(f, obj->id); PHYSFSX_writeU8(f, obj->control_type); PHYSFSX_writeU8(f, obj->movement_type); PHYSFSX_writeU8(f, obj->render_type); PHYSFSX_writeU8(f, obj->flags); PHYSFS_writeSLE16(f, obj->segnum); PHYSFSX_writeVector(f, &obj->pos); PHYSFSX_writeMatrix(f, &obj->orient); PHYSFSX_writeFix(f, obj->size); PHYSFSX_writeFix(f, obj->shields); PHYSFSX_writeVector(f, &obj->last_pos); 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: PHYSFSX_writeVector(f, &obj->mtype.phys_info.velocity); PHYSFSX_writeVector(f, &obj->mtype.phys_info.thrust); PHYSFSX_writeFix(f, obj->mtype.phys_info.mass); PHYSFSX_writeFix(f, obj->mtype.phys_info.drag); PHYSFSX_writeFix(f, obj->mtype.phys_info.brakes); PHYSFSX_writeVector(f, &obj->mtype.phys_info.rotvel); PHYSFSX_writeVector(f, &obj->mtype.phys_info.rotthrust); PHYSFSX_writeFixAng(f, obj->mtype.phys_info.turnroll); PHYSFS_writeSLE16(f, obj->mtype.phys_info.flags); break; case MT_SPINNING: PHYSFSX_writeVector(f, &obj->mtype.spin_rate); break; case MT_NONE: break; default: Int3(); } switch (obj->control_type) { case CT_AI: { int i; PHYSFSX_writeU8(f, obj->ctype.ai_info.behavior); for (i = 0; i < MAX_AI_FLAGS; i++) PHYSFSX_writeU8(f, obj->ctype.ai_info.flags[i]); 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); PHYSFS_writeSLE16(f, obj->ctype.ai_info.follow_path_start_seg); PHYSFS_writeSLE16(f, obj->ctype.ai_info.follow_path_end_seg); break; } case CT_EXPLOSION: 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; case CT_WEAPON: //do I really need to write these objects? 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: PHYSFSX_writeFix(f, obj->ctype.light_info.intensity); break; case CT_POWERUP: PHYSFS_writeSLE32(f, obj->ctype.powerup_info.count); break; case CT_NONE: case CT_FLYING: case CT_DEBRIS: break; case CT_SLEW: //the player is generally saved as slew break; case CT_CNTRLCEN: break; //control center object. case CT_MORPH: case CT_REPAIRCEN: case CT_FLYTHROUGH: default: Int3(); } switch (obj->render_type) { case RT_NONE: break; case RT_MORPH: case RT_POLYOBJ: { int i; PHYSFS_writeSLE32(f, obj->rtype.pobj_info.model_num); for (i = 0; i < MAX_SUBMODELS; i++) PHYSFSX_writeAngleVec(f, &obj->rtype.pobj_info.anim_angles[i]); PHYSFS_writeSLE32(f, obj->rtype.pobj_info.subobj_flags); PHYSFS_writeSLE32(f, obj->rtype.pobj_info.tmap_override); break; } case RT_WEAPON_VCLIP: case RT_HOSTAGE: case RT_POWERUP: case RT_FIREBALL: 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; case RT_LASER: break; default: Int3(); } }
// ----------------------------------------------------------------------------- // Save game int save_level_sub(char * filename, int compiled_version) { PHYSFS_file * SaveFile; char temp_filename[PATH_MAX]; int minedata_offset=0,gamedata_offset=0,hostagetext_offset=0; // if ( !compiled_version ) { write_game_text_file(filename); if (Errors_in_mine) { if (is_real_level(filename)) { char ErrorMessage[200]; sprintf( ErrorMessage, "Warning: %i errors in this mine!\n", Errors_in_mine ); gr_palette_load(gr_palette); if (nm_messagebox( NULL, 2, "Cancel Save", "Save", ErrorMessage )!=1) { return 1; } } } // change_filename_extension(temp_filename,filename,".LVL"); } // else { change_filename_extension(temp_filename, filename, ".RDL"); } SaveFile = PHYSFSX_openWriteBuffered(temp_filename); if (!SaveFile) { char ErrorMessage[256]; snprintf( ErrorMessage, sizeof(ErrorMessage), "ERROR: Cannot write to '%s'.", temp_filename); gr_palette_load(gr_palette); nm_messagebox( NULL, 1, "Ok", ErrorMessage ); return 1; } if (Current_level_name[0] == 0) strcpy(Current_level_name,"Untitled"); clear_transient_objects(1); //1 means clear proximity bombs compress_objects(); //after this, Highest_object_index == num objects //make sure player is in a segment if (update_object_seg(&Objects[Players[0].objnum]) == 0) { if (ConsoleObject->segnum > Highest_segment_index) ConsoleObject->segnum = 0; compute_segment_center(&ConsoleObject->pos,&(Segments[ConsoleObject->segnum])); } fix_object_segs(); //Write the header PHYSFS_writeSLE32(SaveFile, MAKE_SIG('P','L','V','L')); PHYSFS_writeSLE32(SaveFile, Gamesave_current_version); //save placeholders PHYSFS_writeSLE32(SaveFile, minedata_offset); PHYSFS_writeSLE32(SaveFile, gamedata_offset); PHYSFS_writeSLE32(SaveFile, hostagetext_offset); //Now write the damn data 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 = PHYSFS_tell(SaveFile); save_game_data(SaveFile); hostagetext_offset = PHYSFS_tell(SaveFile); PHYSFS_seek(SaveFile, sizeof(int) + sizeof(Gamesave_current_version)); PHYSFS_writeSLE32(SaveFile, minedata_offset); PHYSFS_writeSLE32(SaveFile, gamedata_offset); PHYSFS_writeSLE32(SaveFile, hostagetext_offset); //==================== CLOSE THE FILE ============================= PHYSFS_close(SaveFile); // if ( !compiled_version ) { if (EditorWindow) editor_status_fmt("Saved mine %s, \"%s\"",filename,Current_level_name); } return 0; }
// ----------------------------------------------------------------------------- // Save game int save_game_data(PHYSFS_file *SaveFile) { short game_top_fileinfo_version = Gamesave_current_version >= 5 ? 31 : GAME_VERSION; int player_offset=0, object_offset=0, walls_offset=0, doors_offset=0, triggers_offset=0, control_offset=0, matcen_offset=0; //, links_offset; int offset_offset=0, end_offset=0; int i; //===================== SAVE FILE INFO ======================== 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); // Write the mine name PHYSFSX_printf(SaveFile, "%s\n", Current_level_name); PHYSFS_writeSLE16(SaveFile, N_polygon_models); PHYSFS_write(SaveFile, Pof_names, sizeof(*Pof_names), N_polygon_models); //==================== SAVE PLAYER INFO =========================== 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 = PHYSFS_tell(SaveFile); //fwrite( &Objects, sizeof(object), game_fileinfo.object_howmany, SaveFile ); for (i = 0; i <= Highest_object_index; i++) write_object(&Objects[i], SaveFile); //==================== SAVE WALL INFO ============================= walls_offset = PHYSFS_tell(SaveFile); for (i = 0; i < Num_walls; i++) wall_write(&Walls[i], game_top_fileinfo_version, SaveFile); //==================== SAVE DOOR INFO ============================= #if 0 // FIXME: okay to leave this out? doors_offset = PHYSFS_tell(SaveFile); for (i = 0; i < Num_open_doors; i++) door_write(&ActiveDoors[i], game_top_fileinfo_version, SaveFile); #endif //==================== SAVE TRIGGER INFO ============================= triggers_offset = PHYSFS_tell(SaveFile); for (i = 0; i < Num_triggers; i++) trigger_write(&Triggers[i], game_top_fileinfo_version, SaveFile); //================ SAVE CONTROL CENTER TRIGGER INFO =============== control_offset = PHYSFS_tell(SaveFile); control_center_triggers_write(&ControlCenterTriggers, SaveFile); //================ SAVE MATERIALIZATION CENTER TRIGGER INFO =============== matcen_offset = PHYSFS_tell(SaveFile); for (i = 0; i < Num_robot_centers; i++) matcen_info_write(&RobotCenters[i], game_top_fileinfo_version, SaveFile); //============= REWRITE FILE INFO, TO SAVE OFFSETS =============== end_offset = PHYSFS_tell(SaveFile); // Update the offset fields #define WRITE_OFFSET(o, n) do { PHYSFS_seek(SaveFile, offset_offset); PHYSFS_writeSLE32(SaveFile, o ## _offset); offset_offset += sizeof(int)*n; } while (0) 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); // Go back to end of data PHYSFS_seek(SaveFile, end_offset); return 0; }
void WriteFile::writeSLE32(Sint32 val) { if(!PHYSFS_writeSLE32(file, val)) throw Exception("couldn't write: %s", PHYSFS_getLastError()); }