From e8e3b13c7c9e074a1659f2a5f63137162b396feb Mon Sep 17 00:00:00 2001 From: ALONSO Laurent Date: Wed, 29 Sep 2021 15:17:51 +0200 Subject: [PATCH] porting.{hc}pp: add a namespace, fileio_party.cpp: try to simplify the code which read legacy save, boe.specials.cpp: correct a problem when unlocking rectangles... --- src/fileio/fileio.cpp | 6 +- src/fileio/fileio_party.cpp | 116 ++++++++++++++--------------------- src/fileio/fileio_scen.cpp | 21 +++---- src/game/boe.fileio.cpp | 3 - src/game/boe.specials.cpp | 1 + src/gfx/qdpict.mac.cpp | 9 ++- src/pcedit/pc.main.cpp | 3 +- src/porting.cpp | 57 +++++++++++------ src/porting.hpp | 8 +++ src/scenedit/scen.fileio.cpp | 2 - 10 files changed, 110 insertions(+), 116 deletions(-) diff --git a/src/fileio/fileio.cpp b/src/fileio/fileio.cpp index 989203b7..4af7be7d 100644 --- a/src/fileio/fileio.cpp +++ b/src/fileio/fileio.cpp @@ -14,13 +14,13 @@ #include #include +#include "porting.hpp" #include "res_image.hpp" #include "res_cursor.hpp" #include "res_font.hpp" #include "res_strings.hpp" #include "res_sound.hpp" -bool mac_is_intel; fs::path progDir, tempDir, scenDir; // This is here to avoid unnecessarily duplicating it in platform-specific files. @@ -112,9 +112,7 @@ fs::path get_posix_tempdir() { } void check_for_intel() { - union {uint16_t x; uint8_t c;} endian; - endian.x = 1; - mac_is_intel = endian.c; + porting::check_endian(); } std::string read_maybe_quoted_string(std::istream& from) { diff --git a/src/fileio/fileio_party.cpp b/src/fileio/fileio_party.cpp index 09c05ea8..cc5dd274 100644 --- a/src/fileio/fileio_party.cpp +++ b/src/fileio/fileio_party.cpp @@ -20,7 +20,6 @@ #include "porting.hpp" #include "tarball.hpp" -extern bool mac_is_intel; extern fs::path progDir, tempDir; extern cCustomGraphics spec_scen_g; @@ -39,19 +38,6 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ short n; struct {ushort a; ushort b; ushort c; ushort d;} 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.string().c_str(), "rb"); if(file_id == nullptr) { showError("Loading Blades of Exile save file failed."); @@ -66,54 +52,43 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ showError("This is not a Blades of Exile save file."); return false; } - - if(mac_is_intel && flags.a == 0x8B1F){ // Gzip header (new format) + if(porting::is_small_endian()) { // reset the flags in big endian + porting::flip_short((short*)&flags.a); + porting::flip_short((short*)&flags.b); + porting::flip_short((short*)&flags.c); + } + if(flags.a == 0x1F8B) // Gzip header (new format) format = new_oboe; - }else if(!mac_is_intel && flags.a == 0x1F8B){ // Gzip header (new format) - format = new_oboe; - }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 { + // expected flags when reading an old file in big endian + static const unsigned short old_flags[3][2] = { + {0x169e,0x053e}, // slot 0 ... 5790 - out, 1342 - town + {0x64,0xc8}, // slot 1 ... 100 - in scenario, 200 - not in + {0xd5e,0x15bf} // slot 2 ... 3422 - no maps, 5567 - maps + }; + // first test mac file then windows file + for (int step=0; step<2; ++step) { + if (step==1) { + porting::flip_short((short*)&flags.a); + porting::flip_short((short*)&flags.b); + porting::flip_short((short*)&flags.c); + } + format = unknown; + if(flags.a != old_flags[0][0] && flags.a != old_flags[0][1]) + continue; + + format = step==0 ? old_mac : old_win; + town_restore = maps_there = in_scen = false; + if(flags.a == old_flags[0][1]) town_restore = true; + else if(flags.a != old_flags[0][0]) format = unknown; + if(flags.b == old_flags[1][0]) in_scen = true; + else if(flags.b != old_flags[1][1]) format = unknown; + if(flags.c == old_flags[2][1]) maps_there = true; + else if(flags.c != old_flags[2][0]) format = unknown; + if (format!=unknown) + break; } - }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){ @@ -130,7 +105,6 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ return true; } -extern bool cur_scen_is_mac; bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restore, bool in_scen, bool maps_there, bool mac_file){ std::ifstream fin(file_to_load.string().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 @@ -150,13 +124,13 @@ bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restor long len,store_len,count; // ------- set scenario is mac to party_is_mac to make porting.cpp works - cur_scen_is_mac=mac_file; + porting::set_current_file_type(mac_file); // LOAD PARTY len = (long) sizeof(legacy::party_record_type); // should be 46398 store_len = len; fin.read((char*)&store_party, len); - port_party(&store_party); + porting::port_party(&store_party); party_ptr = (char*) &store_party; for(count = 0; count < store_len; count++) party_ptr[count] ^= 0x5C; @@ -170,7 +144,7 @@ bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restor for(int i = 0; i < 6; i++) { len = store_len; fin.read((char*)&store_pc[i], len); - port_pc(&store_pc[i]); + porting::port_pc(&store_pc[i]); pc_ptr = (char*) &store_pc[i]; for(count = 0; count < store_len; count++) pc_ptr[count] ^= 0x6B; @@ -186,22 +160,22 @@ bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restor if(town_restore) { len = (long) sizeof(legacy::current_town_type); fin.read((char*)&store_c_town, len); - port_c_town(&store_c_town); + porting::port_c_town(&store_c_town); len = (long) sizeof(legacy::big_tr_type); fin.read((char*)&t_d, len); - port_t_d(&t_d); + porting::port_t_d(&t_d); len = (long) sizeof(legacy::town_item_list); fin.read((char*)&t_i, len); - port_t_i(&t_i); + porting::port_t_i(&t_i); } // 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); - port_stored_items_list(&stored_items[i]); + porting::port_stored_items_list(&stored_items[i]); } // LOAD SAVED MAPS @@ -222,7 +196,7 @@ bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restor } // end if_scen fin.close(); - // ------- the data of the party are all port, so load_scenario can reset cur_scen_is_mac + // ------- the data of the party are all port, so load_scenario can reset the file type cUniverse univ; @@ -361,7 +335,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& real_univ){ for(auto& i : univ.party.setup) for(auto& j : i) for(auto& k : j) - flip_short(reinterpret_cast(&k)); + porting::flip_short(reinterpret_cast(&k)); } if(partyIn.hasFile("save/town.txt")) { @@ -373,7 +347,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& real_univ){ } univ.town.readFrom(fin); } else univ.party.town_num = 200; - + if (partyIn.hasFile("save/townmaps.dat")) { // Read town maps std::istream& fin2 = partyIn.getFile("save/townmaps.dat"); diff --git a/src/fileio/fileio_scen.cpp b/src/fileio/fileio_scen.cpp index 5abae87d..eec57636 100644 --- a/src/fileio/fileio_scen.cpp +++ b/src/fileio/fileio_scen.cpp @@ -31,7 +31,6 @@ // Also, for some reason, it's not found in the include paths, so use a relative path #include "../scenario/town_import.tpp" -bool cur_scen_is_mac = true; extern cCustomGraphics spec_scen_g; extern fs::path tempDir, scenDir, progDir; @@ -206,12 +205,12 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head if((scenario.format.flag1 == 10) && (scenario.format.flag2 == 20) && (scenario.format.flag3 == 30) && (scenario.format.flag4 == 40)) { - cur_scen_is_mac = true; + porting::set_current_file_type(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; + porting::set_current_file_type(false); file_ok = true; } else if(scenario.format.flag1 == 'O' && scenario.format.flag2 == 'B' && scenario.format.flag3 == 'O' && scenario.format.flag4 == 'E') { // This means we're looking at the scenario header file of an unpacked new-format scenario. @@ -229,14 +228,14 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head fclose(file_id); return false; } - port_scenario(temp_scenario); + porting::port_scenario(temp_scenario); len = sizeof(legacy::scen_item_data_type); // item data if(fread(item_data, len, 1, file_id) < 1) { showError(err_prefix + "Failed to read scenario items.", get_file_error()); fclose(file_id); return false; } - port_item_list(item_data); + porting::port_item_list(item_data); scenario.import_legacy(*temp_scenario); scenario.import_legacy(*item_data); @@ -2295,13 +2294,13 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: fclose(file_id); return false; } - port_town(&store_town); + porting::port_town(&store_town); switch(scenario.town_size[which_town]) { case 0: len = sizeof(legacy::big_tr_type); fread(&t_d, len, 1, file_id); - port_t_d(&t_d); + porting::port_t_d(&t_d); the_town.import_legacy(store_town); the_town.import_legacy(t_d, which_town); break; @@ -2309,7 +2308,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: case 1: len = sizeof(legacy::ave_tr_type); fread(&ave_t, len, 1, file_id); - port_ave_t(&ave_t); + porting::port_ave_t(&ave_t); the_town.import_legacy(store_town); the_town.import_legacy(ave_t, which_town); break; @@ -2317,7 +2316,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: case 2: len = sizeof(legacy::tiny_tr_type); fread(&tiny_t, len, 1, file_id); - port_tiny_t(&tiny_t); + porting::port_tiny_t(&tiny_t); the_town.import_legacy(store_town); the_town.import_legacy(tiny_t, which_town); break; @@ -2348,7 +2347,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: fclose(file_id); return false; } - port_talk_nodes(&store_talk); + porting::port_talk_nodes(&store_talk); the_town.talking.talk_nodes.resize(60); for(short i = 0; i < 170; i++) { @@ -2432,7 +2431,7 @@ bool load_outdoors_v1(fs::path scen_file, location which_out,cOutdoors& the_out, the_out.x = which_out.x; the_out.y = which_out.y; - port_out(&store_out); + porting::port_out(&store_out); the_out.import_legacy(store_out); the_out.spec_strs.resize(90); the_out.sign_locs.resize(8); diff --git a/src/game/boe.fileio.cpp b/src/game/boe.fileio.cpp index c5f582a7..9f408780 100644 --- a/src/game/boe.fileio.cpp +++ b/src/game/boe.fileio.cpp @@ -34,7 +34,6 @@ extern sf::RenderWindow mini_map; extern short which_combat_type; extern short cur_town_talk_loaded; extern cUniverse univ; -extern bool mac_is_intel; bool loaded_yet = false, got_nagged = false; std::string last_load_file = "Blades of Exile Save"; @@ -42,8 +41,6 @@ fs::path file_to_load; fs::path store_file_reply; short jl; -extern bool cur_scen_is_mac; - void print_write_position (); void save_outdoor_maps(); void add_outdoor_maps(); diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp index 785d7ad8..6d2845d1 100644 --- a/src/game/boe.specials.cpp +++ b/src/game/boe.specials.cpp @@ -4453,6 +4453,7 @@ void rect_spec(const runtime_state& ctx){ draw_map(true); break; } + break; case eSpecType::RECT_SET_EXPLORED: if(spec.sd1) make_explored(l.x, l.y); diff --git a/src/gfx/qdpict.mac.cpp b/src/gfx/qdpict.mac.cpp index 51a988ca..ce15f203 100644 --- a/src/gfx/qdpict.mac.cpp +++ b/src/gfx/qdpict.mac.cpp @@ -27,13 +27,15 @@ static int16_t extract_word(char* ptr) { int16_t s = *(int16_t*) ptr; - flip_short(&s); + if (porting::is_small_endian()) + porting::flip_short(&s); return s; } static int32_t extract_long(char* ptr) { int32_t s = *(int32_t*) ptr; - flip_long(&s); + if (porting::is_small_endian()) + porting::flip_long(&s); return s; } @@ -163,7 +165,8 @@ static legacy::Rect loadPixMapData(ptr_guard& picData, ptr_guard(prefsDlog["scaleui"]).setState(ui_scale == 1.0 ? led_off : (ui_scale == 2.0 ? led_red : led_green)); dynamic_cast(prefsDlog["nosound"]).setState(get_bool_pref("PlaySounds", true) ? led_off : led_red); - + prefsDlog.run(); if(get_float_pref("UIScale") != ui_scale) diff --git a/src/porting.cpp b/src/porting.cpp index 8a161d53..d3c4e1e4 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -8,15 +8,31 @@ #include "porting.hpp" -extern bool cur_scen_is_mac, mac_is_intel; - -// check endian with cur_scen_is_mac and mac_is_intel -// check cur_scen_is_mac to see if we need to convert RECT in Rect +namespace porting { +// check endian with cur_file_is_mac and is_computer_small_endian +// check cur_file_is_mac to see if we need to convert RECT in Rect static void port_rect(legacy::Rect* s); +bool is_computer_small_endian=true; +void check_endian() { + union {uint16_t x; uint8_t c;} endian; + endian.x = 1; + is_computer_small_endian = endian.c; +} +bool is_small_endian() +{ + return is_computer_small_endian; +} + +bool cur_file_is_mac=true; +void set_current_file_type(bool isMac) +{ + cur_file_is_mac = isMac; +} + void port_town(legacy::town_record_type* dummy_town_ptr){ port_rect(&dummy_town_ptr->in_town_rect); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_short(&dummy_town_ptr->town_chop_time); flip_short(&dummy_town_ptr->town_chop_key); @@ -44,7 +60,7 @@ void port_town(legacy::town_record_type* dummy_town_ptr){ } void port_talk_nodes(legacy::talking_record_type* dummy_talk_ptr) { - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 60; i++) { flip_short(&dummy_talk_ptr->talk_nodes[i].personality); @@ -60,7 +76,7 @@ void port_t_d(legacy::big_tr_type* old) { for(short i = 0; i < 16; i++) port_rect(&old->room_rect[i]); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 60; i++) { @@ -75,7 +91,7 @@ void port_t_d(legacy::big_tr_type* old) { void port_t_i(legacy::town_item_list* old) { - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 115; i++) port_item_record(&(old->items[i])); @@ -83,7 +99,7 @@ void port_t_i(legacy::town_item_list* old) void port_stored_items_list(legacy::stored_items_list_type *old) { - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 115; i++) port_item_record(&(old->items[i])); @@ -93,7 +109,7 @@ void port_ave_t(legacy::ave_tr_type* old) { for(short i = 0; i < 16; i++) port_rect(&old->room_rect[i]); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 40; i++) { @@ -110,7 +126,7 @@ void port_tiny_t(legacy::tiny_tr_type* old) { for(short i = 0; i < 16; i++) port_rect(&old->room_rect[i]); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 30; i++) { @@ -127,7 +143,7 @@ void port_scenario(legacy::scenario_data_type* temp_scenario) { for(short i = 0; i < 3; i++) port_rect(&temp_scenario->store_item_rects[i]); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_short(&temp_scenario->flag_a); flip_short(&temp_scenario->flag_b); @@ -203,7 +219,7 @@ void port_scenario(legacy::scenario_data_type* temp_scenario) { } void port_item_record(legacy::item_record_type *old) { - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_short(&(old->variety)); @@ -212,7 +228,7 @@ void port_item_record(legacy::item_record_type *old) { } void port_item_list(legacy::scen_item_data_type* old){ - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 400; i++) @@ -223,7 +239,7 @@ void port_out(legacy::outdoor_record_type *out) { for(short i = 0; i < 8; i++) port_rect(&(out->info_rect[i])); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; for(short i = 0; i < 4; i++) { @@ -245,7 +261,7 @@ void port_out(legacy::outdoor_record_type *out) { } void port_party(legacy::party_record_type* old){ - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_long(&old->age); @@ -330,7 +346,7 @@ void port_party(legacy::party_record_type* old){ } void port_pc(legacy::pc_record_type* old){ - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_short(&old->main_status); @@ -359,7 +375,7 @@ void port_pc(legacy::pc_record_type* old){ void port_c_town(legacy::current_town_type* old){ port_town(&old->town); - if(cur_scen_is_mac != mac_is_intel) + if(cur_file_is_mac != is_computer_small_endian) return; flip_short(&old->town_num); @@ -447,12 +463,13 @@ void flip_rect(legacy::Rect* s) { } void port_rect(legacy::Rect* s) { - if(cur_scen_is_mac == mac_is_intel) { + if(cur_file_is_mac == is_computer_small_endian) { flip_short((int16_t *) &(s->top)); flip_short((int16_t *) &(s->bottom)); flip_short((int16_t *) &(s->left)); flip_short((int16_t *) &(s->right)); } - if(!cur_scen_is_mac) alter_rect(s); + if(!cur_file_is_mac) alter_rect(s); } +} diff --git a/src/porting.hpp b/src/porting.hpp index 16615fd4..b4e151a2 100644 --- a/src/porting.hpp +++ b/src/porting.hpp @@ -10,11 +10,18 @@ #include "oldstructs.hpp" #include "location.hpp" +namespace porting { +void check_endian(); +bool is_small_endian(); +void set_current_file_type(bool isMac); + +// always flip data void flip_long(int32_t *s); void flip_spec_node(legacy::special_node_type *spec); void flip_short(int16_t *s); void flip_rect(legacy::Rect* s); +// check the file type and the endian to decide what to flip/swap void port_t_i(legacy::town_item_list* old); void port_t_d(legacy::big_tr_type* old); void port_ave_t(legacy::ave_tr_type* old); @@ -29,3 +36,4 @@ void port_town(legacy::town_record_type* dummy_town_ptr); void port_party(legacy::party_record_type* old); void port_pc(legacy::pc_record_type* old); void port_c_town(legacy::current_town_type* old); +} diff --git a/src/scenedit/scen.fileio.cpp b/src/scenedit/scen.fileio.cpp index 9e152057..1467a82d 100644 --- a/src/scenedit/scen.fileio.cpp +++ b/src/scenedit/scen.fileio.cpp @@ -30,12 +30,10 @@ extern location cur_out; extern cOutdoors* current_terrain; extern bool change_made; extern cCustomGraphics spec_scen_g; -extern bool mac_is_intel; fs::path temp_file_to_load; std::string last_load_file = "Blades of Exile Scenario"; extern fs::path progDir, tempDir; -extern bool cur_scen_is_mac; void print_write_position (); void load_spec_graphics();