(PC Editor and Scenario Editor are unaffected by this commit.) Things removed: - All references to Carbon and QuickDraw are gone. - No more Resource Manager; the game no longer relies on old resource files at all - The old dialog framework (from dlogtool.c, functions usually prefixed with cd_) is no longer used. - Files that weren't being compiled - Boost libraries that are now in the C++ library (function, shared_ptr) - Obsolete build settings Replacement dependencies: - Boost Filesystem replaces references to things like FSSpec - SFML replaces all the QuickDraw code and most window management - Cocoa replaces AppleEvent management, menu management, and some window management - I wrote a resource manager interface to mimick the important aspects of the behaviour of the Mac Resource Manager - I had to rewrite some functions that QuickDraw provided natively, such as clipping regions; not all of these are tested Things added: - Every referenced dialog has been converted from a DITL resource into the new XML-based dialog format. - All referenced STR# resources have been extracted into simple text files - Now compiles against Mac OSX 10.7 SDK and libc++ - The first item in the Help menu opens the docs on Sylae's website - It seems all the constants for soundtool vanished somewhere, so I added them back from the original Mac source Other changes: - Updated to XCode 4(?) project format - Added the xcschemes created by XCode 4; I'm not sure how important these are, but they seem like they might be important - Added document on converting dialogs to the XML format. - Make string formatting mismatches into errors instead of warnings - Disable error limit - Graphics sheets that previously used masking now have alpha transparency - Converted all graphics sheets to 8-bit PNG - Trimmed white border from intro image - Converted dialogs in the resource file have their resource name set to the name of the XML file of the converted version - Referenced string resources in the resource file have their resource name set to the name of the text file of the extracted version - Add the black-and-white patterns from the PAT resources to the pixpats.png; at least one of them is used somewhere in the game - Recreated the menu.xib as a Cocoa xib file instead of a Carbon xib file - Disable GNU C++ extensions; maybe this'll make it easier to compile with cl.exe later - Add marks to the enormous handle_action function to make it easier to navigate\ - A build step to validate the XML dialogs using xmllint (doesn't quite work properly yet but does at least catch dialogs that are not well-formed)- Fix a lot of warnings about assigning string constants to non-const char pointers - Fixed the file and application icons (which had somehow become corrupted at some point) - Lots of additional functions in the custom location and rectangle classes, including implicit conversion to and from SFML rects and vectors; also they now store coordinates as int instead of char - A new enum for encounter note types - Much tweaking of the encounter note recording mechanisms - To ease porting, I added a simple function that converts from classic Mac ticks (about 1/60 of a second) to the SFML time type - Python script to convert STR# resources to txt files, replacing newlines with vertical bars - Extracted the Mac font (Dungeon Bold) from the resource file and also added the Windows font (MaidenWord) XML Dialog Framework changes: - Remove the static initialization object in favour of manually calling cDialog::init() - {set,get}Format() no longer used for colour; there's a dedicated {set,get}Colour() instead - draw() methods unprotected in the control classes so that controls can be drawn in the main window - There's no longer a friend relationship between the dialogs and the controls - Fixed buttons duplicating the "depressed" boolean - Buttons now properly offset the label for tiny and push buttons, and for LEDs - Buttons no longer assume that either none or both of "width" and "height" are given in the XML - Add {get,set}BtnType() to cButton - cLedGroup now overrides handleClick(), which has also been made virtual; this was necessary for LEDs within a group to properly hilite while being clicked - Add addChoice() to cLedGroup to insert additional LED choices - Moved the key enums and cKey to a separate file - Add a method to get a control's attached key - Add methods to get and set a control's rect and position - Controls can now directly take a window as a parent rather than a dialog - Add addLabelFor() method to cDialog which adds a static text control as a label for another control - Remove hack for storing a dialog result of arbitrary type in favour of boost::any - Add method to get default text colour for a dialog - Add method to get a dialog's rect - Add method to add the same event handler to multiple controls in a dialog - Add concept of default button to dialogs - Add enum for text field type (currently either number or text) - Implement the text field without use of native controls, including somewhat decent text input and a flashing insertion point - cPict no longer stores references to every sheet; it fetches them as needed from the resource manager - The many draw functions in cPict are no longer static, since they need to access the window containing the pict (before they could only be static due to QuickDraw's global state) - Add setPict() without a type argument to change the graphic without changing the type, which is a common operation - Add a scrollbar control; the specifics aren't implemented yet - Change signature of the record callback for cStrDlog; it will no longer be passed the strings - Publicize the no-button constructor of cChoiceDlog; it'll assume "okay" is the only button - Add operator-> to cPictChoice for accessing the underlying dialog - Add constructor to cPictChoice that takes a starting and ending pic num - Remove err parameter from giveError - Many more keys handled, plus support for catching copy, paste, cut, and select all keyboard shortcuts - Text input fields take priority, overriding any other keyboard shortcuts in the dialog, but they never catch help (F1), escape, or enter - Some changes to the format itself: -> keys go in the "def-key" attribute, but modifiers go in "key-mod" -> "clickable" is no longer a recognized attribute -> "title" is now a recognized text size (18pt, even larger than "large" at 12pt) -> "defbtn" attribute on the root element
1734 lines
48 KiB
C++
1734 lines
48 KiB
C++
/*
|
|
* fileio.cpp
|
|
* BoE
|
|
*
|
|
* Created by Celtic Minstrel on 22/04/09.
|
|
*
|
|
*/
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <sstream>
|
|
|
|
#include <zlib.h>
|
|
//#include "scen.global.h"
|
|
#include <fstream>
|
|
#include "classes.h"
|
|
//#include "scen.fileio.h"
|
|
//#include "scen.keydlgs.h"
|
|
#include "graphtool.h"
|
|
//#include "scen.core.h"
|
|
//#include "soundtool.h"
|
|
#include "mathutil.h"
|
|
#include "fileio.h"
|
|
#include "porting.h"
|
|
#include "dlogutil.h"
|
|
#include "restypes.hpp"
|
|
|
|
extern bool cur_scen_is_mac, mac_is_intel;
|
|
extern cScenario scenario;
|
|
extern sf::Texture spec_scen_g,items_gworld,tiny_obj_gworld,fields_gworld,roads_gworld,boom_gworld,missiles_gworld;
|
|
extern sf::Texture dlogpics_gworld,monst_gworld[],terrain_gworld[],anim_gworld,talkfaces_gworld,pc_gworld;
|
|
extern sf::Texture status_gworld, vehicle_gworld, small_ter_gworld;
|
|
extern cUniverse univ;
|
|
//extern unsigned char borders[4][50];
|
|
//extern cOutdoors current_terrain;
|
|
//extern cTown* town;
|
|
extern fs::path progDir;
|
|
//extern short overall_mode;
|
|
|
|
struct header_posix_ustar {
|
|
char name[100];
|
|
char mode[8];
|
|
char uid[8];
|
|
char gid[8];
|
|
char size[12];
|
|
char mtime[12];
|
|
char checksum[8];
|
|
char typeflag[1];
|
|
char linkname[100];
|
|
char magic[6];
|
|
char version[2];
|
|
char uname[32];
|
|
char gname[32];
|
|
char devmajor[8];
|
|
char devminor[8];
|
|
char prefix[155];
|
|
char pad[12];
|
|
};
|
|
|
|
#include <stdexcept>
|
|
|
|
header_posix_ustar generateTarHeader(const std::string& fileName, unsigned long long fileSize,bool directory=false){
|
|
if(fileSize>077777777777LL)
|
|
throw std::length_error("Specified file size >= 8 GB");
|
|
if(fileName.length()>=100)
|
|
throw std::length_error("Specified file name longer than 99 characters.");
|
|
header_posix_ustar header;
|
|
char* init = (char*) &header;
|
|
for(unsigned int i = 0; i < sizeof(header); i++) init[i] = 0;
|
|
|
|
sprintf(header.name,"%s",fileName.c_str());
|
|
sprintf(header.mode,"%07o",0600);
|
|
//leave uid filled with NULs
|
|
//leave gid filled with NULs
|
|
sprintf(header.size,"%011llo",fileSize);
|
|
sprintf(header.mtime,"%011lo",time(NULL));
|
|
memset(header.checksum,' ',8);
|
|
header.typeflag[0]=directory?'5':'0';
|
|
//leave linkname filled with NULs
|
|
sprintf(header.magic,"ustar "); //overwrites header with " \0"
|
|
//leave uname filled with NULs
|
|
//leave gname filled with NULs
|
|
//leave devmajor filled with NULs
|
|
//leave devminor filled with NULs
|
|
//leave prefix filled with NULs
|
|
//leave pad filled with NULs
|
|
|
|
unsigned int sum=0;
|
|
unsigned char* ptr=reinterpret_cast<unsigned char*>(&header);
|
|
for(unsigned int i=0; i<sizeof(header); i++){
|
|
sum+=ptr[i];
|
|
}
|
|
if(sum>0777777)
|
|
throw std::runtime_error("Checksum overflow");
|
|
sprintf(header.checksum,"%o",sum);
|
|
return(header);
|
|
}
|
|
|
|
bool load_scenario(fs::path file_to_load){
|
|
short i,n;
|
|
bool file_ok = false;
|
|
long len;
|
|
legacy::scenario_data_type *temp_scenario = new legacy::scenario_data_type;
|
|
legacy::scen_item_data_type *item_data = new legacy::scen_item_data_type;
|
|
// TODO: Convert this (and all the others in this file) to use C++ streams
|
|
FILE* file_id = fopen(file_to_load.c_str(),"rb");
|
|
if(file_id == NULL) {
|
|
// TODO: The third parameter to oopsError is supposed to specify whether we're in the scenario editor or the game, but I don't think this code knows that.
|
|
// TODO: Alternatively, nuke oopsError and just use giveError. It's more informative, anyway.
|
|
oopsError(10, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = (long) sizeof(scenario_header_flags);
|
|
|
|
if (fread(&scenario.format, len, 1, file_id) < 1){
|
|
fclose(file_id);
|
|
oopsError(11, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
if ((scenario.format.flag1 == 10) && (scenario.format.flag2 == 20) &&
|
|
(scenario.format.flag3 == 30) && (scenario.format.flag4 == 40)) {
|
|
cur_scen_is_mac = true;
|
|
file_ok = true;
|
|
}
|
|
else if ((scenario.format.flag1 == 20) && (scenario.format.flag2 == 40) &&
|
|
(scenario.format.flag3 == 60) && (scenario.format.flag4 == 80)) {
|
|
cur_scen_is_mac = false;
|
|
file_ok = true;
|
|
}
|
|
if (file_ok == false) {
|
|
fclose(file_id);
|
|
giveError("This is not a legitimate Blades of Exile scenario.");
|
|
return false;
|
|
}
|
|
|
|
len = (long) sizeof(legacy::scenario_data_type);
|
|
n = fread(temp_scenario, len, 1, file_id);
|
|
if(n < 1){
|
|
fclose(file_id);
|
|
oopsError(12, 0, 0);
|
|
return false;
|
|
}
|
|
port_scenario(temp_scenario);
|
|
len = sizeof(legacy::scen_item_data_type); // item data
|
|
n = fread(item_data, len, 1, file_id);
|
|
if(n < 1){
|
|
fclose(file_id);
|
|
oopsError(13, 0, 0);
|
|
return false;
|
|
}
|
|
port_item_list(item_data);
|
|
scenario = *temp_scenario;
|
|
scenario.append(*item_data);
|
|
for (i = 0; i < 270; i++) {
|
|
len = (long) (scenario.scen_str_len[i]);
|
|
n = fread(&(scenario.scen_strs(i)), len, 1, file_id);
|
|
scenario.scen_strs(i)[len] = 0;
|
|
}
|
|
|
|
fclose(file_id);
|
|
|
|
// code for master
|
|
/*
|
|
for (i = 0; i < 30000; i++) {
|
|
if (check_p(i) == true) {
|
|
user_given_password = i;
|
|
i = 30000;
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
/* Now check password
|
|
|
|
if (check_p(0) == false) {
|
|
user_given_password = enter_password();
|
|
if (check_p(user_given_password) == false) {
|
|
fancy_choice_dialog(868,0);
|
|
if (overall_mode != 61) {
|
|
user_given_password = enter_password();
|
|
if (check_p(user_given_password) == false)
|
|
ExitToShell();
|
|
}
|
|
else return;
|
|
}
|
|
}
|
|
else user_given_password = 0; /**/
|
|
|
|
|
|
//given_password = user_given_password;
|
|
|
|
scenario.ter_types[23].fly_over = false;
|
|
delete temp_scenario;
|
|
delete item_data;
|
|
|
|
//store_file_reply = file_to_load;
|
|
// overall_mode = 60;
|
|
// change_made = false;
|
|
// if(!load_town(scenario.last_town_edited)) return false;
|
|
// //load_town(0);
|
|
// if(!load_outdoors(scenario.last_out_edited,0)) return false;
|
|
// augment_terrain(scenario.last_out_edited);
|
|
scenario.scen_file = file_to_load;
|
|
load_spec_graphics();
|
|
return true;
|
|
}
|
|
|
|
long get_town_offset(short which_town){
|
|
int i,j;
|
|
long len_to_jump,store;
|
|
|
|
len_to_jump = sizeof(scenario_header_flags);
|
|
len_to_jump += sizeof(legacy::scenario_data_type);
|
|
len_to_jump += sizeof(legacy::scen_item_data_type);
|
|
for (i = 0; i < 300; i++)
|
|
len_to_jump += (long) scenario.scen_str_len[i];
|
|
store = 0;
|
|
for (i = 0; i < 100; i++)
|
|
for (j = 0; j < 2; j++)
|
|
store += (long) (scenario.out_data_size[i][j]);
|
|
for (i = 0; i < which_town; i++)
|
|
for (j = 0; j < 5; j++)
|
|
store += (long) (scenario.town_data_size[i][j]);
|
|
len_to_jump += store;
|
|
|
|
return len_to_jump;
|
|
}
|
|
|
|
bool load_town(short which_town, cTown*& the_town){
|
|
short i,n;
|
|
long len,len_to_jump = 0;
|
|
legacy::town_record_type store_town;
|
|
legacy::talking_record_type store_talk;
|
|
legacy::big_tr_type t_d;
|
|
legacy::ave_tr_type ave_t;
|
|
legacy::tiny_tr_type tiny_t;
|
|
|
|
// if (overall_mode == 61)
|
|
// return;
|
|
|
|
if (which_town != minmax(0,scenario.num_towns - 1,which_town)) {
|
|
// This should never be reached from the scenario editor,
|
|
// because it does its own range checking before calling load_town.
|
|
giveError("The scenario tried to place you into a non-existant town.");
|
|
return false;
|
|
}
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(14, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_town_offset(which_town);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(15, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::town_record_type);
|
|
n = fread(&store_town, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(16, 0, 0);
|
|
return false;
|
|
}
|
|
port_town(&store_town);
|
|
|
|
if(the_town != NULL) delete the_town;
|
|
switch (scenario.town_size[which_town]) {
|
|
case 0:
|
|
len = sizeof(legacy::big_tr_type);
|
|
n = fread(&t_d, len, 1, file_id);
|
|
port_t_d(&t_d);
|
|
the_town = new cBigTown;
|
|
*the_town = store_town;
|
|
the_town->append(t_d);
|
|
break;
|
|
|
|
case 1:
|
|
len = sizeof(legacy::ave_tr_type);
|
|
n = fread(&ave_t, len, 1, file_id);
|
|
port_ave_t(&ave_t);
|
|
the_town = new cMedTown;
|
|
*the_town = store_town;
|
|
the_town->append(ave_t);
|
|
break;
|
|
|
|
case 2:
|
|
len = sizeof(legacy::tiny_tr_type);
|
|
n = fread(&tiny_t, len, 1, file_id);
|
|
port_tiny_t(&tiny_t);
|
|
the_town = new cTinyTown;
|
|
*the_town = store_town;
|
|
the_town->append(tiny_t);
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < 140; i++) {
|
|
len = (long) (the_town->strlens[i]);
|
|
n = fread(&(the_town->town_strs(i)), len, 1, file_id);
|
|
the_town->town_strs(i)[len] = 0;
|
|
}
|
|
|
|
len = sizeof(legacy::talking_record_type);
|
|
n = fread(&store_talk, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(17, 0, 0);
|
|
return false;
|
|
}
|
|
port_talk_nodes(&store_talk);
|
|
the_town->talking = store_talk;
|
|
|
|
for (i = 0; i < 170; i++) {
|
|
len = (long) (the_town->talking.strlens[i]);
|
|
n = fread(&(the_town->talking.talk_strs[i]), len, 1, file_id);
|
|
the_town->talking.talk_strs[i][len] = 0;
|
|
}
|
|
|
|
// town_type = scenario.town_size[which_town];
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(18, 0, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool load_town(short which_town, cSpeech& the_talk){
|
|
short i,n;
|
|
long len,len_to_jump = 0;
|
|
legacy::town_record_type store_town;
|
|
legacy::talking_record_type store_talk;
|
|
|
|
// if (overall_mode == 61)
|
|
// return;
|
|
|
|
if (which_town != minmax(0,scenario.num_towns - 1,which_town)) {
|
|
// This should never be reached from the scenario editor,
|
|
// because it does its own range checking before calling load_town.
|
|
giveError("The scenario tried to place you into a non-existant town.");
|
|
return false;
|
|
}
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(19, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_town_offset(which_town);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(20, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::town_record_type);
|
|
n = fread(&store_town, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(21, 0, 0);
|
|
return false;
|
|
}
|
|
port_town(&store_town);
|
|
|
|
switch (scenario.town_size[which_town]) {
|
|
case 0:
|
|
len = sizeof(legacy::big_tr_type);
|
|
break;
|
|
case 1:
|
|
len = sizeof(legacy::ave_tr_type);
|
|
break;
|
|
case 2:
|
|
len = sizeof(legacy::tiny_tr_type);
|
|
break;
|
|
}
|
|
|
|
n = fseek(file_id, len, SEEK_CUR);
|
|
for (i = 0; i < 140; i++) {
|
|
len = (long) (store_town.strlens[i]);
|
|
fseek(file_id, len, SEEK_CUR);
|
|
}
|
|
|
|
len = sizeof(legacy::talking_record_type);
|
|
n = fread(&store_talk, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(22, 0, 0);
|
|
return false;
|
|
}
|
|
port_talk_nodes(&store_talk);
|
|
the_talk = store_talk;
|
|
|
|
for (i = 0; i < 170; i++) {
|
|
len = (long) (the_talk.strlens[i]);
|
|
n = fread(&(the_talk.talk_strs[i]), len, 1, file_id);
|
|
the_talk.talk_strs[i][len] = 0;
|
|
}
|
|
|
|
// town_type = scenario.town_size[which_town];
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(23, 0, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool load_town_str(short which_town, short which_str, char* str){
|
|
short i,n;
|
|
long len,len_to_jump = 0;
|
|
legacy::town_record_type store_town;
|
|
|
|
// if (overall_mode == 61)
|
|
// return;
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(24, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_town_offset(which_town);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(25, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::town_record_type);
|
|
|
|
n = fread(&store_town, len, 1, file_id);
|
|
if(len < 1) {
|
|
fclose(file_id);
|
|
oopsError(26, 0, 0);
|
|
return false;
|
|
}
|
|
port_town(&store_town);
|
|
|
|
switch (scenario.town_size[which_town]) {
|
|
case 0:
|
|
len = sizeof(legacy::big_tr_type);
|
|
break;
|
|
case 1:
|
|
len = sizeof(legacy::ave_tr_type);
|
|
break;
|
|
case 2:
|
|
len = sizeof(legacy::tiny_tr_type);
|
|
break;
|
|
}
|
|
|
|
n = fseek(file_id, len, SEEK_CUR);
|
|
for (i = 0; i < 140; i++) {
|
|
len = (long) (univ.town->strlens[i]);
|
|
if(i == which_str){
|
|
n = fread(str, len, 1, file_id);
|
|
str[len] = 0;
|
|
}
|
|
else fseek(file_id, len, SEEK_CUR);
|
|
}
|
|
|
|
// town_type = scenario.town_size[which_town];
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(27, 0, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool load_town_str(short which_town, cTown*& t){
|
|
short i,n;
|
|
long len,len_to_jump = 0;
|
|
legacy::town_record_type store_town;
|
|
|
|
// if (overall_mode == 61)
|
|
// return;
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(28, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_town_offset(which_town);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(29, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::town_record_type);
|
|
n = fread(&store_town, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(30, 0, 0);
|
|
return false;
|
|
}
|
|
port_town(&store_town);
|
|
|
|
switch (scenario.town_size[which_town]) {
|
|
case 0:
|
|
len = sizeof(legacy::big_tr_type);
|
|
break;
|
|
case 1:
|
|
len = sizeof(legacy::ave_tr_type);
|
|
break;
|
|
case 2:
|
|
len = sizeof(legacy::tiny_tr_type);
|
|
break;
|
|
}
|
|
|
|
n = fseek(file_id, len, SEEK_CUR);
|
|
for (i = 0; i < 140; i++) {
|
|
len = (long) (t->strlens[i]);
|
|
n = fread(&(t->town_strs(i)), len, 1, file_id);
|
|
t->town_strs(i)[len] = 0;
|
|
}
|
|
|
|
// town_type = scenario.town_size[which_town];
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(31, 0, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
long get_outdoors_offset(location& which_out){
|
|
int i,j,out_sec_num;
|
|
long len_to_jump,store;
|
|
out_sec_num = scenario.out_width * which_out.y + which_out.x;
|
|
|
|
len_to_jump = sizeof(scenario_header_flags);
|
|
len_to_jump += sizeof(legacy::scenario_data_type);
|
|
len_to_jump += sizeof(legacy::scen_item_data_type);
|
|
for (i = 0; i < 300; i++)
|
|
len_to_jump += (long) scenario.scen_str_len[i];
|
|
store = 0;
|
|
for (i = 0; i < out_sec_num; i++)
|
|
for (j = 0; j < 2; j++)
|
|
store += (long) (scenario.out_data_size[i][j]);
|
|
len_to_jump += store;
|
|
|
|
return len_to_jump;
|
|
}
|
|
|
|
//mode -> 0 - primary load 1 - add to top 2 - right 3 - bottom 4 - left
|
|
bool load_outdoors(location which_out,cOutdoors& the_out){
|
|
short i,n;
|
|
long len,len_to_jump;
|
|
legacy::outdoor_record_type store_out;
|
|
|
|
// if (overall_mode == 61)
|
|
// return;
|
|
|
|
if ((which_out.x != minmax(0,scenario.out_width - 1,which_out.x)) ||
|
|
(which_out.y != minmax(0,scenario.out_height - 1,which_out.y))) {
|
|
the_out = cOutdoors();
|
|
return true;
|
|
}
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(32, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_outdoors_offset(which_out);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(33, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::outdoor_record_type);
|
|
n = fread(&store_out, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(34, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
port_out(&store_out);
|
|
the_out = store_out;
|
|
for (i = 0; i < 108; i++) {
|
|
len = (long) (the_out.strlens[i]);
|
|
n = fread(&(the_out.out_strs(i)), len, 1, file_id);
|
|
the_out.out_strs(i)[len] = 0;
|
|
}
|
|
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(35, 0, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool load_outdoors(location which_out, short mode, ter_num_t borders[4][50]){
|
|
short j,n;
|
|
long len,len_to_jump;
|
|
legacy::outdoor_record_type store_out;
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(36, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_outdoors_offset(which_out);
|
|
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(37, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len = sizeof(legacy::outdoor_record_type);
|
|
n = fread(&store_out, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
oopsError(38, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
switch(mode) {
|
|
case 1:
|
|
for (j = 0; j < 48; j++) {
|
|
borders[0][j] = store_out.terrain[j][47];
|
|
}
|
|
break;
|
|
case 2:
|
|
for (j = 0; j < 48; j++) {
|
|
borders[1][j] = store_out.terrain[0][j];
|
|
}
|
|
break;
|
|
case 3:
|
|
for (j = 0; j < 48; j++) {
|
|
borders[2][j] = store_out.terrain[j][0];
|
|
}
|
|
break;
|
|
case 4:
|
|
for (j = 0; j < 48; j++) {
|
|
borders[3][j] = store_out.terrain[47][j];
|
|
}
|
|
break;
|
|
}
|
|
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(39, 0, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool load_outdoor_str(location which_out, short which_str, char* str){
|
|
short i,n;
|
|
long len,len_to_jump;
|
|
legacy::outdoor_record_type store_out;
|
|
|
|
FILE* file_id = fopen(scenario.scen_file.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
oopsError(40, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
len_to_jump = get_outdoors_offset(which_out);
|
|
n = fseek(file_id, len_to_jump, SEEK_SET);
|
|
if(n != 0) {
|
|
fclose(file_id);
|
|
oopsError(41, 0, 0);
|
|
return false;
|
|
}
|
|
|
|
n = fread(&store_out, len, 1, file_id);
|
|
for (i = 0; i < 120; i++) {
|
|
len = (long) (store_out.strlens[i]);
|
|
if (i == which_str) {
|
|
n = fread(str, len, 1, file_id);
|
|
str[len] = 0;
|
|
}
|
|
else fseek(file_id, len, SEEK_CUR);
|
|
}
|
|
|
|
n = fclose(file_id);
|
|
if(n != 0) {
|
|
oopsError(42, 0, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void load_spec_graphics()
|
|
{
|
|
short i;
|
|
fs::path path(scenario.scen_file);
|
|
printf("Loading scenario graphics... (%s)\n",path.c_str());
|
|
path.replace_extension("exr");
|
|
// TODO: Load new-style sheets
|
|
//if(err != noErr)
|
|
{
|
|
// for (i = 0; i < 63; i++)
|
|
// file_name[i] = whatever[i];
|
|
path.replace_extension("meg");
|
|
// TODO: There's no way around it; I'll have to read resource files for this section.
|
|
#if 0
|
|
err = FSPathMakeRef(path, &file, NULL);
|
|
err = FSOpenResourceFile(&file, 0, NULL, fsRdPerm /*fsRdWrPerm*/, &custRef);
|
|
//file_num = HOpen(file_to_load.vRefNum,file_to_load.parID,file_name,1);
|
|
//if (file_num < 0){
|
|
if(err != noErr){
|
|
//whatever = (char *) file_to_load.name;
|
|
printf("First attempt failed... (%s)\n",(char*)path);
|
|
for (i = 0; i < 250; i++) {
|
|
if (path[i] == '.') {
|
|
path[i + 1] = 'b';
|
|
path[i + 2] = 'm';
|
|
path[i + 3] = 'p';
|
|
//path[i + 4] = 0;
|
|
break;
|
|
}
|
|
}
|
|
err = FSPathMakeRef(path, &file, NULL);
|
|
FSSpec spec;
|
|
FSGetCatalogInfo(&file, kFSCatInfoNone, NULL, NULL, &spec, NULL);
|
|
err = FSpOpenDF(&spec, fsRdPerm, &custRef);
|
|
//spec_scen_g = load_bmp_from_file(file_name);
|
|
spec_scen_g = importPictureFileToGWorld(&spec);
|
|
if(spec_scen_g == NULL)printf("Scenario graphics not found (%s).\n",file_name);
|
|
}else{
|
|
spec_scen_g = load_pict(1);
|
|
CloseResFile(custRef);
|
|
}
|
|
#endif
|
|
}//else{}
|
|
|
|
// Now load regular graphics
|
|
items_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("objects"));
|
|
tiny_obj_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("tinyobj"));
|
|
fields_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("fields"));
|
|
roads_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("trim"));
|
|
boom_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("booms"));
|
|
missiles_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("missiles"));
|
|
dlogpics_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("dlogpics"));
|
|
status_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("staticons"));
|
|
|
|
for (i = 0; i < NUM_MONST_SHEETS; i++){
|
|
std::ostringstream sout;
|
|
sout << "monst" << i + 1;
|
|
monst_gworld[i].loadFromImage(*ResMgr::get<ImageRsrc>(sout.str()));
|
|
}
|
|
for (i = 0; i < NUM_TER_SHEETS; i++){
|
|
std::ostringstream sout;
|
|
sout << "ter" << i + 1;
|
|
terrain_gworld[i].loadFromImage(*ResMgr::get<ImageRsrc>(sout.str()));
|
|
}
|
|
anim_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("teranim"));
|
|
talkfaces_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("talkportraits"));
|
|
pc_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("pcs"));
|
|
vehicle_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("vehicle"));
|
|
small_ter_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("mapOLD")); // TODO: Should use the new map graphics instead
|
|
// TODO: Scenario icons ...
|
|
}
|
|
|
|
|
|
bool load_party_v1(fs::path file_to_load, bool town_restore, bool in_scen, bool maps_there, bool must_port);
|
|
bool load_party_v2(fs::path file_to_load, bool town_restore, bool in_scen, bool maps_there);
|
|
bool load_party(fs::path file_to_load){
|
|
bool town_restore = false;
|
|
bool maps_there = false;
|
|
bool in_scen = false;
|
|
enum {old_mac, old_win, new_oboe, unknown} format;
|
|
|
|
//char flag_data[8];
|
|
long len;
|
|
// flag_type flag;
|
|
// flag_type *flag_ptr;
|
|
short vers,n;
|
|
struct __attribute__((packed)) {ushort a; ushort b; ushort c; ushort d; ushort e;} flags;
|
|
|
|
// TODO: Putting these flags in hex would make some things a bit clearer
|
|
static const unsigned short mac_flags[3][2] = {
|
|
{5790,1342}, // slot 0 ... 5790 - out, 1342 - town
|
|
{100,200}, // slot 1 ... 100 - in scenario, 200 - not in
|
|
{3422,5567} // slot 2 ... 3422 - no maps, 5567 - maps
|
|
};
|
|
static const unsigned short win_flags[3][2] = {
|
|
{40470,15877}, // slot 0 ... 40470 - out, 15877 - town
|
|
{25600,51200}, // slot 1 ... 25600 - in scenario, 51200 - not in
|
|
{24077,48917} // slot 2 ... 24077 - no maps, 48917 - maps
|
|
};
|
|
// but if the first flag is 0x0B0E, we have a new-format save
|
|
// the three flags still follow that.
|
|
FILE* file_id = fopen(file_to_load.c_str(), "rb");
|
|
if(file_id == NULL) {
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}
|
|
|
|
|
|
//file_size = sizeof(legacy::party_record_type); // 45368
|
|
|
|
len = sizeof(flags); // 10
|
|
|
|
// sprintf((char *) debug, " Len %d ", (short) len);
|
|
// add_string_to_buf((char *) debug);
|
|
|
|
n = fread(&flags, len, 1, file_id);
|
|
if(n < 1) {
|
|
fclose(file_id);
|
|
cChoiceDlog("not-save-game.xml").show();
|
|
return false;
|
|
}
|
|
|
|
if(mac_is_intel && flags.a == 0x0B0E){ // new format
|
|
format = new_oboe;
|
|
if(flags.b == mac_flags[0][1]) town_restore = true;
|
|
else if(flags.b != mac_flags[0][0]) format = unknown;
|
|
if(flags.c == mac_flags[1][0]) in_scen = true;
|
|
else if(flags.c != mac_flags[1][1]) format = unknown;
|
|
if(flags.d == mac_flags[2][1]) maps_there = true;
|
|
else if(flags.d != mac_flags[2][0]) format = unknown;
|
|
vers = flags.e;
|
|
}else if(!mac_is_intel && flags.a == 0x0E0B){ // new format
|
|
format = new_oboe;
|
|
flip_short((short*)&flags.b);
|
|
flip_short((short*)&flags.c);
|
|
flip_short((short*)&flags.d);
|
|
flip_short((short*)&flags.e);
|
|
if(flags.b == mac_flags[0][1]) town_restore = true;
|
|
else if(flags.b != mac_flags[0][0]) format = unknown;
|
|
if(flags.c == mac_flags[1][0]) in_scen = true;
|
|
else if(flags.c != mac_flags[1][1]) format = unknown;
|
|
if(flags.d == mac_flags[2][1]) maps_there = true;
|
|
else if(flags.d != mac_flags[2][0]) format = unknown;
|
|
vers = flags.e;
|
|
}else if(flags.a == mac_flags[0][0] || flags.a == mac_flags[0][1]){ // old format
|
|
if(mac_is_intel){ // it's actually a windows save
|
|
flip_short((short*)&flags.a);
|
|
flip_short((short*)&flags.b);
|
|
flip_short((short*)&flags.c);
|
|
format = old_win;
|
|
if(flags.a == win_flags[0][1]) town_restore = true;
|
|
else if(flags.a != win_flags[0][0]) format = unknown;
|
|
if(flags.b == win_flags[1][0]) in_scen = true;
|
|
else if(flags.b != win_flags[1][1]) format = unknown;
|
|
if(flags.c == win_flags[2][1]) maps_there = true;
|
|
else if(flags.c != win_flags[2][0]) format = unknown;
|
|
}else{ // mac save
|
|
format = old_mac;
|
|
if(flags.a == mac_flags[0][1]) town_restore = true;
|
|
else if(flags.a != mac_flags[0][0]) format = unknown;
|
|
if(flags.b == mac_flags[1][0]) in_scen = true;
|
|
else if(flags.b != mac_flags[1][1]) format = unknown;
|
|
if(flags.c == mac_flags[2][1]) maps_there = true;
|
|
else if(flags.c != mac_flags[2][0]) format = unknown;
|
|
}
|
|
}else if(flags.a == win_flags[0][0] || flags.a == win_flags[0][1]){ // old format
|
|
if(mac_is_intel){ // it's actually a macintosh save
|
|
flip_short((short*)&flags.a);
|
|
flip_short((short*)&flags.b);
|
|
flip_short((short*)&flags.c);
|
|
format = old_mac;
|
|
if(flags.a == mac_flags[0][1]) town_restore = true;
|
|
else if(flags.a != mac_flags[0][0]) format = unknown;
|
|
if(flags.b == mac_flags[1][0]) in_scen = true;
|
|
else if(flags.b != mac_flags[1][1]) format = unknown;
|
|
if(flags.c == mac_flags[2][1]) maps_there = true;
|
|
else if(flags.c != mac_flags[2][0]) format = unknown;
|
|
}else{ // win save
|
|
format = old_win;
|
|
if(flags.a == win_flags[0][1]) town_restore = true;
|
|
else if(flags.a != win_flags[0][0]) format = unknown;
|
|
if(flags.b == win_flags[1][0]) in_scen = true;
|
|
else if(flags.b != win_flags[1][1]) format = unknown;
|
|
if(flags.c == win_flags[2][1]) maps_there = true;
|
|
else if(flags.c != win_flags[2][0]) format = unknown;
|
|
}
|
|
}else format = unknown;
|
|
|
|
fclose(file_id);
|
|
switch(format){
|
|
case old_mac:
|
|
return load_party_v1(file_to_load, town_restore, in_scen, maps_there, mac_is_intel);
|
|
case old_win:
|
|
return load_party_v1(file_to_load, town_restore, in_scen, maps_there, !mac_is_intel);
|
|
case new_oboe:
|
|
return load_party_v2(file_to_load, town_restore, in_scen, maps_there);
|
|
case unknown:
|
|
cChoiceDlog("not-save-game.xml").show();
|
|
return false;
|
|
}
|
|
|
|
// for (i = 0; i < 3; i++) {
|
|
// error = FSRead(file_id, &len, (char *) &flag);
|
|
// if (error != 0) {
|
|
// FSClose(file_id);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
//// flag_ptr = (flag_type *) flag_data;
|
|
//// flag = *flag_ptr;
|
|
// if (flag == 0x0B0E) { // new format save
|
|
// new_format = true;
|
|
// i--;
|
|
// continue;
|
|
// }
|
|
// if(mac_is_intel && !new_format) flip_short(&flag); // because the old format save was made for non-intel macs
|
|
// if ((flag != flags[i][0]) && (flag != flags[i][1])) { // OK Exile II save file?
|
|
// FSClose(file_id);
|
|
// FCD(1063,0);
|
|
// return false;
|
|
// }
|
|
//
|
|
// if ((i == 0) && (flag == flags[i][1]))
|
|
// town_restore = true;
|
|
// if ((i == 1) && (flag == flags[i][0])) {
|
|
// in_scen = true;
|
|
// }
|
|
// if ((i == 2) && (flag == flags[i][1]))
|
|
// maps_there = true;
|
|
// }
|
|
return true;
|
|
}
|
|
|
|
bool load_party_v1(fs::path file_to_load, bool town_restore, bool in_scen, bool maps_there, bool must_port){
|
|
std::ifstream fin(file_to_load.c_str(), std::ios_base::binary);
|
|
fin.seekg(3*sizeof(short),std::ios_base::beg); // skip the header, which is 6 bytes in the old format
|
|
//short flags[3];
|
|
//fin.read((char*)flags,3*sizeof(short));
|
|
// OSErr error = FSpOpenDF(&file_to_load,1,&file_id);
|
|
// if (error != 0) {
|
|
// FCD(1064,0);
|
|
// SysBeep(2);
|
|
// return false;
|
|
// }
|
|
|
|
legacy::party_record_type store_party;
|
|
legacy::setup_save_type store_setup;
|
|
legacy::pc_record_type store_pc[6];
|
|
legacy::out_info_type store_out_info;
|
|
legacy::current_town_type store_c_town;
|
|
legacy::big_tr_type t_d;
|
|
legacy::town_item_list t_i;
|
|
legacy::stored_items_list_type stored_items[3];
|
|
legacy::stored_town_maps_type town_maps;
|
|
legacy::stored_outdoor_maps_type o_maps;
|
|
unsigned char misc_i[64][64], sfx[64][64];
|
|
char *party_ptr;
|
|
char *pc_ptr;
|
|
long len,store_len,count;
|
|
|
|
// LOAD PARTY
|
|
len = (long) sizeof(legacy::party_record_type); // 45368
|
|
store_len = len;
|
|
fin.read((char*)&store_party, len);
|
|
// error = FSRead(file_id, &len, (char *) &store_party)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
if(must_port) port_party(&store_party);
|
|
party_ptr = (char*) &store_party;
|
|
for (count = 0; count < store_len; count++)
|
|
party_ptr[count] ^= 0x5C;
|
|
|
|
// LOAD SETUP
|
|
len = (long) sizeof(legacy::setup_save_type);
|
|
fin.read((char*)&store_setup, len);
|
|
// error = FSRead(file_id, &len, (char *) &store_setup)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
|
|
// LOAD PCS
|
|
store_len = (long) sizeof(legacy::pc_record_type);
|
|
for (int i = 0; i < 6; i++) {
|
|
len = store_len;
|
|
fin.read((char*)&store_pc[i], len);
|
|
// error = FSRead(file_id, &len, (char *) &store_pc[i]);
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
if(must_port) port_pc(&store_pc[i]);
|
|
pc_ptr = (char*) &store_pc[i];
|
|
for (count = 0; count < store_len; count++)
|
|
pc_ptr[count] ^= 0x6B;
|
|
}
|
|
|
|
if (in_scen) {
|
|
|
|
// LOAD OUTDOOR MAP
|
|
len = (long) sizeof(legacy::out_info_type);
|
|
fin.read((char*)&store_out_info, len);
|
|
// error = FSRead(file_id, &len, (char *) &store_out_info)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
|
|
if(univ.town.loaded()) univ.town.unload();
|
|
|
|
// LOAD TOWN
|
|
if (town_restore) {
|
|
len = (long) sizeof(legacy::current_town_type);
|
|
fin.read((char*)&store_c_town, len);
|
|
// error = FSRead(file_id, &len, (char *) &store_c_town)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
if(must_port) port_c_town(&store_c_town);
|
|
|
|
len = (long) sizeof(legacy::big_tr_type);
|
|
fin.read((char*)&t_d, len);
|
|
// error = FSRead(file_id, &len, (char *) &t_d)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
if(must_port) port_t_d(&t_d);
|
|
|
|
len = (long) sizeof(legacy::town_item_list);
|
|
fin.read((char*)&t_i, len);
|
|
// error = FSRead(file_id, &len, (char *) &t_i)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
|
|
}else univ.town.num = 200;
|
|
|
|
// LOAD STORED ITEMS
|
|
for (int i = 0; i < 3; i++) {
|
|
len = (long) sizeof(legacy::stored_items_list_type);
|
|
fin.read((char*)&stored_items[i], len);
|
|
// error = FSRead(file_id, &len, (char *) &stored_items[i])
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
}
|
|
|
|
// LOAD SAVED MAPS
|
|
if (maps_there) {
|
|
len = (long) sizeof(legacy::stored_town_maps_type);
|
|
fin.read((char*)&town_maps, len);
|
|
// error = FSRead(file_id, &len, (char *) &(town_maps))
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
|
|
len = (long) sizeof(legacy::stored_outdoor_maps_type);
|
|
fin.read((char*)&o_maps, len);
|
|
// error = FSRead(file_id, &len, (char *) &o_maps)
|
|
// if (error != 0) {
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
}
|
|
|
|
// LOAD SFX & MISC_I
|
|
len = (long) (64 * 64);
|
|
fin.read((char*)sfx, len);
|
|
// error = FSRead(file_id, &len, (char *) sfx)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
fin.read((char*)misc_i, len);
|
|
// error = FSRead(file_id, &len, (char *) misc_i)
|
|
// if (error != 0){
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// FCD(1064,0);
|
|
// return false;
|
|
// }
|
|
|
|
} // end if_scen
|
|
|
|
fin.close();
|
|
// error = FSClose(file_id)
|
|
// if (error != 0){
|
|
// give_error("Load: Can't close file.","",0);
|
|
// SysBeep(2);
|
|
// return false;
|
|
// }
|
|
|
|
univ.party = store_party;
|
|
univ.party.append(store_setup);
|
|
univ.party.void_pcs();
|
|
for(int i = 0; i < 6; i++)
|
|
univ.party.add_pc(store_pc[i]);
|
|
if(in_scen){
|
|
univ.out.append(store_out_info);
|
|
if(town_restore){
|
|
univ.town.append(store_c_town,scenario.town_size[univ.town.num]);
|
|
univ.town.append(t_d);
|
|
univ.town.append(t_i);
|
|
}
|
|
for(int i = 0; i < 3; i++)
|
|
univ.party.append(stored_items[i],i);
|
|
univ.append(town_maps);
|
|
univ.append(o_maps);
|
|
univ.town.append(sfx, misc_i);
|
|
}
|
|
if(in_scen){
|
|
fs::path path;
|
|
path = progDir/"Blades of Exile Scenarios"/univ.party.scen_name;
|
|
//std::cout<<path<<'\n';
|
|
if(!load_scenario(path))
|
|
return false;
|
|
univ.file = path;
|
|
}else{
|
|
univ.party.scen_name = "";
|
|
}
|
|
|
|
// Compatibility flags
|
|
if(in_scen && scenario.format.prog_make_ver[0] < 2){
|
|
univ.party.stuff_done[305][8] = 1;
|
|
} else {
|
|
univ.party.stuff_done[305][8] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool load_party_v2(fs::path file_to_load, bool town_restore, bool in_scen, bool maps_there){
|
|
char* buf;
|
|
FILE* f = fopen(file_to_load.c_str(),"rb");
|
|
|
|
// TODO: Write the parsers and stuff
|
|
/* Skip header */
|
|
fseek(f, sizeof(short) * 5, SEEK_SET);
|
|
gzFile party_file = gzdopen(fileno(f), "rb");
|
|
|
|
/* Initialize various variables */
|
|
header_posix_ustar header;
|
|
// TODO: Don't call this sin; that's a trig function
|
|
std::istringstream sin;
|
|
std::string tar_name;
|
|
std::string tar_entry;
|
|
size_t tar_size;
|
|
std::map<std::string,std::string> party_archive;
|
|
|
|
/* Split the tar archive into its component files */
|
|
while(!gzeof(party_file)){
|
|
gzread(party_file, &header, sizeof(header));
|
|
sscanf(header.size, "%lo", &tar_size);
|
|
tar_name = header.name;
|
|
buf = new char[tar_size];
|
|
gzread(party_file, buf, tar_size);
|
|
tar_entry = buf;
|
|
delete buf;
|
|
party_archive[tar_name] = tar_entry;
|
|
gzseek(party_file, sizeof(header) * 2, SEEK_CUR);
|
|
}
|
|
|
|
/* Read the data from each file */
|
|
if(party_archive.find("save/party.txt") == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive["save/party.txt"]);
|
|
univ.party.readFrom(sin);
|
|
}
|
|
for(int i = 0; i < 6; i++){
|
|
buf = new char[20];
|
|
sprintf(buf,"save/pc%i.txt",i);
|
|
std::string f_name = buf;
|
|
delete buf;
|
|
if(party_archive.find(f_name) == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive[f_name]);
|
|
univ.party[i].readFrom(sin);
|
|
}
|
|
}
|
|
if(in_scen){
|
|
if(town_restore){
|
|
if(party_archive.find("save/town.txt") == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive["save/town.txt"]);
|
|
univ.town.readFrom(sin);
|
|
}
|
|
if(party_archive.find("save/townmaps.dat") == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive["save/townmaps.dat"]);
|
|
for(int i = 0; i < 200; i++)
|
|
for(int j = 0; j < 8; j++)
|
|
for(int k = 0; k < 64; k++)
|
|
univ.town_maps[i][j][k] = sin.get();
|
|
}
|
|
}
|
|
if(party_archive.find("save/out.txt") == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive["save/out.txt"]);
|
|
univ.out.readFrom(sin);
|
|
}
|
|
if(party_archive.find("save/outmaps.dat") == party_archive.end()){
|
|
cChoiceDlog("load-game-fail.xml").show();
|
|
return false;
|
|
}else{
|
|
sin.str(party_archive["save/outmaps.dat"]);
|
|
for(int i = 0; i < 100; i++)
|
|
for(int j = 0; j < 6; j++)
|
|
for(int k = 0; k < 48; k++)
|
|
univ.out_maps[i][j][k] = sin.get();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool save_party(fs::path dest_file)
|
|
//mode; // 0 - normal 1 - save as
|
|
{
|
|
//printf("Saving is currently disabled.\n");
|
|
bool in_scen = univ.party.scen_name != "";
|
|
bool in_town = univ.town.num < 200;
|
|
bool save_maps = !univ.party.stuff_done[306][0];
|
|
|
|
// TODO: Strip off the header and save the remainder to a temporary file, then use gzip on that; this should fix the issue of the header being interpreted as compressed.
|
|
/* Open the GZip file and write the (uncompressed) header */
|
|
std::ofstream fout(dest_file.c_str(), std::ios_base::binary);
|
|
short flags[] = {
|
|
0x0B0E, // to indicate new format
|
|
static_cast<short>(in_town ? 1342 : 5790), // is the party in town?
|
|
static_cast<short>(in_scen ? 100 : 200), // is the party in a scenario?
|
|
static_cast<short>(save_maps ? 5567 : 3422), // is the save maps feature enabled?
|
|
0x0100, // current version number, major and minor revisions only
|
|
// Version 1 indicates a beta format that won't be supported in the final release
|
|
};
|
|
if(!mac_is_intel) // must flip all the flags to little-endian
|
|
for(int i = 0; i < 5; i++)
|
|
flip_short(&flags[i]);
|
|
//fwrite(flags, sizeof(short), 5, f);
|
|
//gzFile party_file = gzdopen(fileno(f),"wb0"); // 0 indicates no compression; this is temporary
|
|
//gzwrite(party_file, flags, sizeof(short)*5);
|
|
//int q = gzflush(party_file, Z_FULL_FLUSH); // required in order to avoid the header getting compressed
|
|
//gzsetparams(party_file, Z_DEFAULT_COMPRESSION, Z_DEFAULT_STRATEGY);
|
|
fout.write((char*) flags, 5*sizeof(short));
|
|
|
|
/* Initialize buffer and other variables */
|
|
header_posix_ustar header;
|
|
static char footer[2*sizeof(header_posix_ustar)] = {0};
|
|
std::ostringstream sout("");
|
|
std::ostringstream bout("",std::ios_base::binary);
|
|
std::string tar_entry;
|
|
size_t tar_size, y;
|
|
int x;
|
|
sout << x;
|
|
/* Write main party data to a buffer, and then to the file */
|
|
univ.party.writeTo(sout);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
header = generateTarHeader("save/party.txt",tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
sout.str(""); // clear the stream (I think)
|
|
|
|
/* Write player character data to a buffer, and then to the file */
|
|
for(int i = 0; i < 6; i++){
|
|
char f_name[20];
|
|
univ.party[i].writeTo(sout);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
sprintf(f_name,"save/pc%i.txt",i+1);
|
|
header = generateTarHeader(f_name,tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
sout.str(""); // clear the stream (I think)
|
|
}
|
|
|
|
if(in_scen){
|
|
if(in_town){
|
|
/* Write current town data to a buffer, and then to the file */
|
|
univ.town.writeTo(sout);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
header = generateTarHeader("save/town.txt",tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
sout.str(""); // clear the stream (I think)
|
|
|
|
if(save_maps){
|
|
/* Write town maps data to a buffer, and then to the file */
|
|
for(int i = 0; i < 200; i++)
|
|
for(int j = 0; j < 8; j++)
|
|
for(int k = 0; k < 64; k++)
|
|
sout.put(univ.town_maps[i][j][k]);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
header = generateTarHeader("save/townmaps.dat",tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
sout.str(""); // clear the stream (I think)
|
|
}
|
|
}
|
|
|
|
/* Write current outdoors data to a buffer, and then to the file */
|
|
univ.out.writeTo(sout);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
header = generateTarHeader("save/out.txt",tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
sout.str(""); // clear the stream (I think)
|
|
|
|
if(save_maps){
|
|
/* Write outdoor maps data to a buffer, and then to the file */
|
|
for(int i = 0; i < 100; i++)
|
|
for(int j = 0; j < 6; j++)
|
|
for(int k = 0; k < 48; k++)
|
|
sout.put(univ.out_maps[i][j][k]);
|
|
//write the footer to end the file
|
|
// for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++)
|
|
// sout.put('\0');
|
|
tar_entry = sout.str();
|
|
y = tar_size = tar_entry.length();
|
|
while(y % 512){
|
|
y++;
|
|
tar_entry += '\0';
|
|
}
|
|
header = generateTarHeader("save/outmaps.dat",tar_size);
|
|
bout.write((char*) &header, sizeof(header));
|
|
bout.write(tar_entry.c_str(), y);
|
|
// x = gzwrite(party_file, (char*) &header, sizeof(header));
|
|
// x = gzwrite(party_file, tar_entry.c_str(), y);
|
|
// //x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
// if(x == 0) { // error
|
|
// gzerror(party_file, &x);
|
|
// oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1);
|
|
// gzclose(party_file);
|
|
// return false;
|
|
// }
|
|
// sout.str(""); // clear the stream (I think)
|
|
}
|
|
}
|
|
//x = gzwrite(party_file, footer, 2*sizeof(header_posix_ustar));
|
|
//gzclose(party_file);
|
|
bout.write(footer, 2*sizeof(header_posix_ustar));
|
|
tar_entry = bout.str();
|
|
tar_size = tar_entry.length();
|
|
unsigned char* buf = new unsigned char[tar_size];
|
|
compress(buf, &tar_size, (unsigned char*) tar_entry.data(), tar_size);
|
|
fout.write((char*)buf, tar_size);
|
|
delete buf;
|
|
fout.close();
|
|
// NavReplyRecord reply;
|
|
// OSErr error;
|
|
// short file_id;
|
|
// bool town_save = false;
|
|
// Str63 store_name;
|
|
// FSSpec to_load;
|
|
//
|
|
// short i;
|
|
//
|
|
// long len,store_len,count;
|
|
// flag_type flag;
|
|
// flag_type *store;
|
|
// party_record_type *party_ptr;
|
|
// setup_save_type *setup_ptr;
|
|
// pc_record_type *pc_ptr;
|
|
// // out_info_type store_explored;
|
|
// current_town_type *town_ptr;
|
|
// big_tr_type *town_data_ptr;
|
|
// town_item_list *item_ptr;
|
|
// stored_items_list_type *items_ptr;
|
|
// stored_town_maps_type *maps_ptr;
|
|
// stored_outdoor_maps_type *o_maps_ptr;
|
|
//
|
|
// char *party_encryptor;
|
|
//
|
|
// if ((in_startup_mode == false) && (is_town()))
|
|
// town_save = true;
|
|
//
|
|
// strcpy ((char *) store_name, (char *) last_load_file);
|
|
//
|
|
//
|
|
// if ((mode == 1) || (loaded_yet == false)) {
|
|
// NavPutFile(NULL,&reply,NULL,NULL,'beSV','blx!',NULL);
|
|
// if (reply.validRecord == false)
|
|
// return;
|
|
//
|
|
// AEKeyword keyword;
|
|
// DescType descType;
|
|
// Size actualSize;
|
|
//
|
|
// AEGetNthPtr(&reply.selection,1,typeFSS,&keyword,&descType,&to_load,sizeof(FSSpec),&actualSize);
|
|
// loaded_yet = true;
|
|
// }
|
|
// else to_load = store_file_reply;
|
|
//
|
|
// error = FSpCreate(&to_load,'blx!','beSV',reply.keyScript);
|
|
// if ((error != 0) && (error != dupFNErr)) {
|
|
// add_string_to_buf("Save: Couldn't create file. ");
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// if ((error = FSpOpenDF(&to_load,3,&file_id)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't open file. ");
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// strcpy ((char *) last_load_file, (char *) to_load.name);
|
|
// store_file_reply = to_load;
|
|
//
|
|
//
|
|
// store = &flag;
|
|
//
|
|
// len = sizeof(flag_type);
|
|
//
|
|
// flag.i = (town_save == true) ? 1342 : 5790;
|
|
// if ((error = FSWrite(file_id, &len, (char *) store)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// }
|
|
// flag.i = (in_startup_mode == false) ? 100 : 200;
|
|
// if ((error = FSWrite(file_id, &len, (char *) store)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// flag.i = (save_maps == true) ? 5567 : 3422;
|
|
// if ((error = FSWrite(file_id, &len, (char *) store)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
//
|
|
// // SAVE PARTY
|
|
// party_ptr = &party;
|
|
// len = sizeof(party_record_type);
|
|
//
|
|
// store_len = len;
|
|
// party_encryptor = (char *) party_ptr;
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x5C;
|
|
// if ((error = FSWrite(file_id, &len, (char *) party_ptr)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x5C;
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x5C;
|
|
//
|
|
// // SAVE SETUP
|
|
// setup_ptr = &setup_save;
|
|
// len = sizeof(setup_save_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) setup_ptr)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
//
|
|
// // SAVE PCS
|
|
// store_len = sizeof(pc_record_type);
|
|
// for (i = 0; i < 6; i++) {
|
|
// pc_ptr = &adven[i];
|
|
//
|
|
// len = store_len;
|
|
// party_encryptor = (char *) pc_ptr;
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x6B;
|
|
// if ((error = FSWrite(file_id, &len, (char *) pc_ptr)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x6B;
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// for (count = 0; count < store_len; count++)
|
|
// party_encryptor[count] ^= 0x6B;
|
|
// }
|
|
//
|
|
// if (in_startup_mode == false) {
|
|
//
|
|
// // SAVE OUT DATA
|
|
// len = sizeof(out_info_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) out_e)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
//
|
|
// if (town_save == true) {
|
|
// town_ptr = &c_town;
|
|
// len = sizeof(current_town_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) town_ptr)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// town_data_ptr = &t_d;
|
|
// len = sizeof(big_tr_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) town_data_ptr)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// item_ptr = &t_i;
|
|
// len = sizeof(town_item_list);
|
|
// if ((error = FSWrite(file_id, &len, (char *) item_ptr)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// }
|
|
//
|
|
// // Save stored items
|
|
// for (i = 0; i < 3; i++) {
|
|
// items_ptr = &stored_items[i];
|
|
// len = (long) sizeof(stored_items_list_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) items_ptr)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// }
|
|
//
|
|
// // If saving maps, save maps
|
|
// if (save_maps == true) {
|
|
// maps_ptr = &(town_maps);
|
|
// len = (long) sizeof(stored_town_maps_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) maps_ptr)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
//
|
|
// o_maps_ptr = &o_maps;
|
|
// len = (long) sizeof(stored_outdoor_maps_type);
|
|
// if ((error = FSWrite(file_id, &len, (char *) o_maps_ptr)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// }
|
|
//
|
|
// // SAVE SFX and MISC_I
|
|
// len = (long) (64 * 64);
|
|
// if ((error = FSWrite(file_id, &len, (char *) sfx)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// if ((error = FSWrite(file_id, &len, (char *) misc_i)) != 0){
|
|
// add_string_to_buf("Save: Couldn't write to file. ");
|
|
// FSClose(file_id);
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
//
|
|
//
|
|
//
|
|
// }
|
|
//
|
|
// if ((error = FSClose(file_id)) != 0) {
|
|
// add_string_to_buf("Save: Couldn't close file. ");
|
|
// SysBeep(2);
|
|
// return;
|
|
// }
|
|
// if (in_startup_mode == false)
|
|
// add_string_to_buf("Save: Game saved. ");
|
|
return true;
|
|
}
|
|
|
|
std::vector<std::string> load_strings(std::string which){
|
|
// TODO: Fix the bundle-ness
|
|
// TODO: Is this even used anywhere?
|
|
#if 0
|
|
UniChar* strListName = new UniChar[which.length()];
|
|
for(int i = 0; i < which.length(); i++) strListName[i] = which[i];
|
|
char stringsPath[512];
|
|
std::string path;
|
|
CFBundleRef mainBundle=CFBundleGetMainBundle();
|
|
CFURLRef stringsURL = CFBundleCopyResourceURL(
|
|
mainBundle,
|
|
CFStringCreateWithCharacters(NULL, strListName, which.length()),
|
|
CFSTR(""), CFSTR("strings")
|
|
);
|
|
delete strListName;
|
|
if(stringsURL == NULL) return std::vector<std::string>(); // if not found, return an empty list
|
|
CFStringGetCString(CFURLCopyFileSystemPath(stringsURL, kCFURLPOSIXPathStyle), stringsPath, 512, kCFStringEncodingUTF8);
|
|
#endif
|
|
fs::path path = progDir/which;
|
|
printf("Loading strings from: %s\n",path.c_str());
|
|
std::ifstream fin(path.c_str());
|
|
std::string s;
|
|
std::vector<std::string> v;
|
|
while(getline(fin,s))
|
|
v.push_back(s);
|
|
return v;
|
|
}
|