diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6dac6b0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.10) +project(pm3) + +# Specify C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Add library +add_library(pm3lib STATIC pm3.cc) + +# Include directories for the library +target_include_directories(pm3lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# Create executable +add_executable(pm3 main.cc) + +# Link the library with the executable +target_link_libraries(pm3 PRIVATE pm3lib) diff --git a/main.cc b/main.cc index 299d780..04ecb4e 100644 --- a/main.cc +++ b/main.cc @@ -8,561 +8,7 @@ #include #include -#define CLUB_IDX_MAX 244 - -#define HOME 0 -#define AWAY 1 -#define DEFAULT_MANAGER_NAME "J.Smith " - -struct gamea { - - union { - struct { - int16_t premier_league[22]; - int16_t division_one[24]; - int16_t division_two[24]; - int16_t division_three[22]; - int16_t conference_league[22]; - int16_t misc[4]; - } __attribute__ ((packed)); - int16_t all[118]; - } __attribute__ ((packed)) club_index; - - union { - struct { - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) premier_league[22]; - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_one[24]; - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_two[24]; - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_three[22]; - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) conference_league[22]; - } __attribute__ ((packed)); - - struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; - int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; - int16_t xx; - } __attribute__ ((packed)) all[114]; - } __attribute__ ((packed)) table; - - uint16_t data000; - uint16_t data001; - uint32_t data002; - - union { - struct { - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) premier_league[15]; - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_one[15]; - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_two[15]; - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_three[15]; - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) conference_league[15]; - } __attribute__ ((packed)); - struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) all[75]; - } __attribute__ ((packed)) top_scorers; //450 - - uint16_t sorted_numbers[64]; - - struct referee { - char name[14]; - uint8_t magic : 3; - uint8_t age : 5; - uint8_t var[7]; - } __attribute__ ((packed)) referee[64]; - - - union cuppy { - struct { - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_fa_cup[36]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_league_cup[28]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) data090[4]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_champions_cup[16]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) data091[16]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_cup_winners_cup[16]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_uefa_cup[32]; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_charity_shield; - } __attribute__ ((packed)); - struct cup_entry { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) all[149]; - } __attribute__ ((packed)) cuppy; - - uint8_t data095[2240]; - - struct { - struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; - } __attribute__ ((packed)) the_charity_shield_history; // history? - - struct { - int16_t club1_idx; - int16_t club1_goals; - int32_t club1_audience; - int16_t club2_idx; - int16_t club2_goals; - int32_t club2_audience; - } __attribute__ ((packed)) some_table[16]; // history? - - union { - struct { - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_fa_cup[0]; - }; - struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) all[57]; - } __attribute__ ((packed)) last_results; - - struct { - struct { - int16_t year; - int16_t club_idx; - uint8_t data[12]; - } __attribute__ ((packed)) history[20]; - } __attribute__ ((packed)) league[5]; - - struct { - struct { - int16_t year; - int16_t club_idx_winner; - int16_t club_idx_runner_up; - uint8_t type_winner; - uint8_t type_runner_up; - } __attribute__ ((packed)) history[20]; - } __attribute__ ((packed)) cup[6]; - - struct { - int16_t club_idx1; - int16_t club_idx2; - } __attribute__ ((packed)) fixture[20]; - - uint8_t data100[106]; - struct { - int16_t player_idx; - int16_t club_idx; - } __attribute__ ((packed)) transfer_market[45]; - - uint8_t data10z[208]; - - struct { - int16_t player_idx; - int16_t from_club_idx; - int16_t to_club_idx; - int32_t fee; - } __attribute__ ((packed)) transfer[6]; - - uint8_t data101[20]; - int16_t retired_manager_club_idx; - int16_t new_manager_club_idx; - char manager_name[16]; - uint8_t data10w[8]; - uint16_t turn; - uint16_t year; - - /* seems to be a collection of 16bit numbers. */ - uint16_t data10x[15]; - - /* The players of the game */ - struct manager { - char name[16]; - int16_t club_idx; - int16_t unk_number; - uint16_t contract_length; - - struct { - uint8_t league_match_seating; - uint8_t league_match_terrace; - uint8_t cup_match_seating; - uint8_t cup_match_terrace; - }__attribute__ ((packed)) price; - - uint32_t seating_history[23]; - uint32_t terrace_history[23]; - - struct bank_statement { - int32_t gate_receipts[2]; - int32_t club_wages[2]; - int32_t transfer_fees[2]; - int32_t club_fines[2]; - int32_t grants_for_club[2]; - int32_t club_bills[2]; - int32_t miscellaneous_sales[2]; - int32_t bank_loan_payments[2]; - int32_t ground_improvements[2]; - int32_t advertising_boards[2]; - int32_t other_items[2]; - int32_t account_interest[2]; - } __attribute__ ((packed)) bank_statement[2]; - - struct loan { - uint32_t amount; - uint8_t turn; //3 turns in a week, 42 weeks in a year? - uint8_t year; - } __attribute__ ((packed)) loan[4]; - - struct employee { - char name[14]; - uint8_t skill; - uint8_t type : 4; - uint8_t age : 4; - } __attribute__ ((packed)) employee[20]; - - struct assistant_manager { - uint8_t do_training_schedules; - uint8_t treat_injured_players; - uint8_t check_sponsors_boards; - uint8_t hire_and_fire_employees; - uint8_t negotiate_player_contracts; - } __attribute__ ((packed)) assistant_manager; - - uint8_t data120; - uint8_t youth_player_type; - uint8_t data121; - - int16_t youth_player; - - uint8_t data147[3]; - - struct scout { - int8_t size; - uint8_t skill; - uint8_t rating; - uint8_t division : 3; - uint8_t foot : 5; - uint8_t club; - struct { - int16_t ix1; - int16_t ix2; - } __attribute__ ((packed)) results[18]; - uint8_t other[5]; - } __attribute__ ((packed)) scout[4]; - - uint8_t smnthn; - uint32_t number1; - uint32_t number2; - uint32_t number3; - uint32_t money_from_directors; - uint8_t data149[20]; - - struct news { - int16_t type; - int32_t amount; - int16_t ix1; - int16_t ix2; - int16_t ix3; - } __attribute__ ((packed)) news[8]; - - int32_t minus_one; - int16_t unknown_player_idx[2]; - uint8_t data150[576]; - - struct stadium { - struct { - char name[20]; - } __attribute__ ((packed)) stand[4]; - - struct { - uint8_t level : 3; - uint8_t time : 5; - } __attribute__ ((packed)) seating_build[4]; - - struct { - uint8_t level : 3; /* terraces, wooden seating, plastic seating */ - uint8_t time : 5; - } __attribute__ ((packed)) conversion[4]; - - struct { - uint8_t level : 3; - uint8_t time : 5; - } __attribute__ ((packed)) area_covering[4]; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) ground_facilities; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) supporters_club; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) flood_lights; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) scoreboard; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) undersoil_heating; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) changing_rooms; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) gymnasium; - - struct { - uint32_t level : 3; - uint32_t time : 29; - } __attribute__ ((packed)) car_park; - - uint8_t safety_rating[4]; - - struct { - uint16_t seating: 15; - uint16_t terraces: 1; - } __attribute__ ((packed)) capacity[4]; - - } __attribute__ ((packed)) stadium; - - int16_t numb01; - int16_t numb02; - int16_t numb03; - int16_t numb04; - - uint8_t managerial_rating_start; - uint8_t managerial_rating_current; - uint8_t directors_confidence_start; - uint8_t directors_confidence_current; - uint8_t supporters_confidence_start; - uint8_t supporters_confidence_current; - - uint8_t head6[6]; - int16_t player3_idx; - uint8_t magic4[4]; - int16_t player4_idx; - uint8_t foot6[6]; - - struct match_summary { - struct club { - uint16_t club_idx; - uint16_t total_goals; - uint16_t first_half_goals; - uint8_t pattern6[6]; // 02 00 26 50 60 77 - uint8_t match_data[4]; - uint8_t corners; - uint8_t throw_ins; - uint8_t free_kicks; - uint8_t penalties; - - struct lineup { - int16_t player_idx; - uint8_t data5[5]; - uint8_t fitness; // matches with benched players, but not onfield. - uint8_t card; - uint8_t shots_attempted; - uint8_t shots_missed; - uint8_t something; - uint8_t tackles_attempted; - uint8_t tackles_won; - uint8_t passes_attempted; - uint8_t passes_bad; - uint8_t shots_saved; // these are for opposing club in the fax_match_summary - uint8_t x[3]; - } __attribute__ ((packed)) lineup[14]; - - struct goal { - int16_t player_idx; - int16_t time; - } __attribute__ ((packed)) goal[8]; - - uint16_t always_null; - uint8_t substitutions_remaining; - uint8_t other; - uint16_t home_away_data; // home: 0x5738, away: 0x91f8 - } __attribute__ ((packed)) club[2]; // home + away club - - uint16_t weather; - uint8_t referee_idx; - uint8_t data156[4]; - /* - * 1e fa_cup semi final - * 1f fa_cup 4th/5th, - * 20 fa_cup 3rd, - * 21 league cup 2nd round 1, 4th round, quarter final - * 22 league cup 2nd round 2, 3rd round - * 23 champions cup 1st leg 1, - * 24 cup_win_cup 2nd round 1/2/qfinal - * 27 charity_shield - * 28 premier - * 29 home-friendly - * 2b conference - */ - uint8_t match_type; - uint8_t data157[6]; - uint32_t audience; - uint8_t data158[92]; - } __attribute__ ((packed)) match_summary; - - struct league_history { - uint16_t year; - uint16_t div; - uint16_t club_idx; - uint16_t ps; - uint16_t p; - uint16_t w; - uint16_t d; - uint16_t l; - uint16_t gd; - uint16_t pts; - uint8_t unk21; - uint8_t unk22; - uint8_t unk23; - uint8_t unk24; - uint8_t unk25; - uint8_t unk26; - uint8_t unk27; - uint8_t unk28; - uint8_t unk29; - uint8_t unk30; - uint8_t unk31; - uint8_t unk32; - } __attribute__ ((packed)) league_history[20]; - - struct { - uint16_t won; - uint16_t yrs; - } __attribute__ ((packed)) titles[11]; - - struct { - uint16_t play; - uint16_t won; - uint16_t drew; - uint16_t lost; - uint16_t forx; - uint16_t agn; - } __attribute__ ((packed)) manager_history[11]; - - uint8_t data159[12]; - - struct { - int16_t year_from; - int16_t year_to; - uint8_t club_idx; - uint8_t mngr; - uint8_t drct; - uint8_t sprt; - } __attribute__ ((packed)) previous_clubs[4]; - - int16_t year_start_cur_club; - - uint16_t manager_of_the_month_awards; - uint16_t manager_of_the_year_awards; - - struct { //1936 - uint8_t club_idx; - uint8_t played; - uint8_t won; - uint8_t draw; - uint16_t goals_f; - uint16_t goals_a; - } __attribute__ ((packed)) match_history[242]; - - uint8_t data160[1794]; - - struct { - char name[20]; - } __attribute__ ((packed)) tactic[8]; - } __attribute__ ((packed)) manager[2]; - - uint8_t data200[10]; - uint16_t inc_number1; - uint16_t inc_number2; - uint16_t inc_number3; - -} __attribute__ ((packed)) gamea; - -struct gameb { - struct club { - char name[16]; - char manager[16]; - int32_t bank_account; - char stadium[24]; - int32_t seating_avg; - int32_t seating_max; - uint8_t padding[8]; - int16_t player_index[24]; - - uint8_t misc000[75]; - uint8_t league; - - struct timetable { - struct week { - struct day { - - uint8_t opponent_idx; - - union { - struct { - uint8_t home: 4; - uint8_t away: 4; - } __attribute__ ((packed)); - int8_t result; - }; - - union { - struct { - uint8_t type: 5; - uint8_t game: 3; - } __attribute__ ((packed)); - uint8_t b3; - }; - - } __attribute__ ((packed)) day[3]; - } __attribute__ ((packed)) week[41]; - uint8_t end; - } __attribute__ ((packed)) timetable; - - } __attribute__ ((packed)) club[CLUB_IDX_MAX]; - -} __attribute__ ((packed)) gameb; - -struct gamec { - struct player { - char name[12]; - - uint8_t u13; - uint8_t hn; - uint8_t u15; - uint8_t tk; - uint8_t u17; - uint8_t ps; - uint8_t u19; - uint8_t sh; - uint8_t u21; - uint8_t hd; - uint8_t u23; - uint8_t cr; - uint8_t u25; - uint8_t ft; - - uint8_t morl : 4; - uint8_t aggr : 4; - - uint8_t ins : 2; - uint8_t age : 6; - - uint8_t foot : 2; - uint8_t dpts : 6; - - uint8_t played; - uint8_t scored; - uint8_t unk2; - uint16_t wage; - uint16_t ins_cost; - uint8_t inj_away; - - uint8_t unk4: 5; - uint8_t contract : 3; - - uint8_t unk5; - - uint8_t train : 4; - uint8_t intense : 4; - - } __attribute__ ((packed))player[3932]; -} __attribute__ ((packed)) gamec; +#include "pm3.h" void dump_gamea(); void dump_gamea_manager(int player = 0); @@ -570,24 +16,21 @@ void dump_gamea_match_summary(); void fax_match_summary(); void dump_gameb(); -struct gameb::club& get_club(int idx); void dump_club(struct gameb::club &club); void print_club_name(int16_t idx, bool newline = true); void dump_gamec(); -struct gamec::player& get_player(int16_t idx); void dump_player(struct gamec::player &player); void print_player_name(int16_t idx, bool newline = true); void dump_player_row(struct gamec::player &player, struct gameb::club &club); -const char* determine_player_type(struct gamec::player &player); void dump_free_players(); void print_help(char *command) { - fprintf(stderr, "Usage: %s -[abc] -g 1-8 [-f] [-t 0-113] [-s] [-h] [ /path/to/saves/ ]\n", command); + fprintf(stderr, "Usage: %s -[abc] -g 1-8 [-f] [-t 0-113] [-s] [-h] [ /path/to/pm3/ ]\n", command); fprintf(stderr, "\n"); fprintf(stderr, " -[abc]\n"); fprintf(stderr, " Dump game[abc]\n"); @@ -610,13 +53,10 @@ void print_help(char *command) { fprintf(stderr, " -h\n"); fprintf(stderr, " Displays this help message\n"); fprintf(stderr, "\n"); - fprintf(stderr, " [ /path/to/saves/ ]\n"); - fprintf(stderr, " optionally provide a path to saves\n"); + fprintf(stderr, " [ /path/to/pm3/ ]\n"); + fprintf(stderr, " optionally provide a path to pm3\n"); } -void soup_up(int player = 0); -void change_club(int new_club_idx, int player = 0); - int main(int argc, char *argv[]) { int c, optindex = 0; @@ -626,7 +66,7 @@ int main(int argc, char *argv[]) opt_dump_gamec = 0, opt_dump_free_players = 0; - char *path = NULL; + const char *path = NULL; int game_nr = -1, opt_soup_up = 0; int opt_new_club_idx = -1; int opt_club_idx = -2; @@ -683,6 +123,8 @@ int main(int argc, char *argv[]) /* assume a path has been provided */ path = argv[optind]; fprintf(stderr, "path:%s: argv:%s\n", path, argv[optind]); + } else { + path = "."; } if (help || argc == 1) { @@ -698,35 +140,7 @@ int main(int argc, char *argv[]) assert(sizeof (struct gameb::club) == 0x023A); assert(sizeof (struct gamec::player) == 0x0028); - char *gamexa = NULL, *gamexb = NULL, *gamexc = NULL; - FILE *fga = NULL, *fgb = NULL, *fgc = NULL; - - size_t gamexa_len = asprintf(&gamexa, "%sGAME%.1dA", path != NULL ? path : "", game_nr); - fga = fopen(gamexa, "r"); - if (fga == NULL) { - printf("Could not open file: %s\n", gamexa); - exit(EXIT_FAILURE); - } - fread(&gamea, sizeof (struct gamea), 1, fga); - fclose(fga); - - size_t gamexb_len = asprintf(&gamexb, "%sGAME%.1dB", path != NULL ? path : "", game_nr); - fgb = fopen(gamexb, "r"); - if (fgb == NULL) { - printf("Could not open file: %s\n", gamexb); - exit(EXIT_FAILURE); - } - fread(&gameb, sizeof (struct gameb), 1, fgb); - fclose(fgb); - - size_t gamexc_len = asprintf(&gamexc, "%sGAME%.1dC", path != NULL ? path : "", game_nr); - fgc = fopen(gamexc, "r"); - if (fgb == NULL) { - printf("Could not open file: %s\n", gamexc); - exit(EXIT_FAILURE); - } - fread(&gamec, sizeof (struct gamec), 1, fgc); - fclose(fgc); + load_binaries(game_nr, path); if ( opt_dump_gamea ) { printf("GAME%dA\n", game_nr); @@ -757,85 +171,19 @@ int main(int argc, char *argv[]) } if ( opt_soup_up ) { + printf("Souping up!"); soup_up(); - - fga = fopen(gamexa, "w+"); - fwrite(&gamea, sizeof (struct gamea), 1, fga); - fclose(fga); - - fgb = fopen(gamexb, "w+"); - fwrite(&gameb, sizeof (struct gameb), 1, fgb); - fclose(fgb); - - fgc = fopen(gamexc, "w+"); - fwrite(&gamec, sizeof (struct gamec), 1, fgc); - fclose(fgc); + save_binaries(game_nr, path); } if ( opt_new_club_idx != -1 ) { change_club(opt_new_club_idx); - - fga = fopen(gamexa, "w+"); - fwrite(&gamea, sizeof (struct gamea), 1, fga); - fclose(fga); - - fgb = fopen(gamexb, "w+"); - fwrite(&gameb, sizeof (struct gameb), 1, fgb); - fclose(fgb); - - fgc = fopen(gamexc, "w+"); - fwrite(&gamec, sizeof (struct gamec), 1, fgc); - fclose(fgc); + save_binaries(game_nr, path); } - - free(gamexa); - free(gamexb); - free(gamexc); - return EXIT_SUCCESS; } -void check_consistency() -{ - int all[3932]; - for (int i = 0; i < 3932; ++i) - all[i] = -1; - - for (int c = 0; c < CLUB_IDX_MAX; ++c) { - fprintf(stderr, "Club[%3d]\n", c); - for (int p = 0; p < 24; ++p) { - if ( gameb.club[c].player_index[p] == -1 ) - continue; - - if (all[ gameb.club[c].player_index[p] ] == -1) { - - all[ gameb.club[c].player_index[p] ] = c; - printf("Added %d %12.12s to %16.16s\n", - gameb.club[c].player_index[p], - gamec.player[ gameb.club[c].player_index[p] ].name, - gameb.club[c].name); - - } else { - printf("Duplicate. %4d %12.12s plays for\n" - "%16.16s AND %16.16s\n", - gameb.club[c].player_index[p], - gamec.player[ gameb.club[c].player_index[p] ].name, - gameb.club[ all[ gameb.club[c].player_index[p] ] ].name, - gameb.club[c].name); - } - } - } - - for (int i = 0; i < sizeof(all); ++i) { - if ( all[i] != -1) - continue; - - fprintf(stderr, "%4d %12.12s is without a club.\n", - i, gamec.player[i].name); - } -} - void dump_gamea() { int correction = 0; @@ -1994,10 +1342,6 @@ void dump_gameb() { } } -struct gameb::club& get_club(int idx) { - return gameb.club[idx]; -} - void dump_club(struct gameb::club &club) { printf("Club : %16.16s\n", club.name); printf("Manager: %16.16s\n", club.manager); @@ -2106,9 +1450,6 @@ void dump_gamec() { dump_player(player); } } -struct gamec::player& get_player(int16_t idx) { - return gamec.player[idx]; -} void dump_player(struct gamec::player &p) { @@ -2162,18 +1503,6 @@ void dump_player_row(struct gamec::player &p, struct gameb::club &club) { printf("%16.16s %1.1s %12.12s %2d %2d %2d %2d %2d %2d %2d %1.1s %1d %1d %2d %5d\n", club.name, determine_player_type(p), p.name, p.hn, p.tk, p.ps, p.sh, p.hd, p.cr, p.ft, foot[p.foot], p.aggr, p.morl, p.age, p.wage); } -const char* determine_player_type(struct gamec::player &p) { - if (p.hn > p.tk && p.hn > p.ps && p.hn > p.sh) { - return "G"; - } else if (p.tk > p.hn && p.tk > p.ps && p.tk > p.sh) { - return "D"; - } else if (p.ps > p.hd && p.ps > p.tk && p.ps > p.sh) { - return "M"; - } - - return "A"; -} - void print_player_name(int16_t idx, bool newline) { assert( idx >= -1 && idx < 3932); @@ -2184,8 +1513,7 @@ void print_player_name(int16_t idx, bool newline) { idx, gamec.player[idx].name, newline ? "\n" : ""); } -void fax_match_summary() -{ +void fax_match_summary() { static const char *match_type[] = { "00", "01", @@ -2327,8 +1655,7 @@ void fax_match_summary() } -void dump_gamea_match_summary() -{ +void dump_gamea_match_summary() { printf("head6:"); for (int i = 0; i < sizeof (gamea.manager[0].head6); ++i) printf(" %02x", gamea.manager[0].head6[i] ); @@ -2535,233 +1862,6 @@ void dump_gamea_match_summary() printf("\n\n"); } -void soup_up(int player) { - printf("Souping up!"); - - struct gamea::manager &manager = gamea.manager[player]; - - print_club_name(manager.club_idx); - - for (int i = 0; i < 20; ++i) { - struct gamea::manager::employee &employee = manager.employee[i]; - printf("Employee: %14.14s\n", employee.name); - employee.skill = 99; - //employee.age = i % 16; - } - - struct gameb::club &club = gameb.club[ manager.club_idx ]; - - for (int p = 0; p < 24; ++p) { - if (club.player_index[p] == -1) - continue; - - print_player_name(club.player_index[p]); - struct gamec::player &player = gamec.player[ club.player_index[p] ]; - - player.hn = 97; - player.tk = 97; - player.ps = 97; - player.sh = 97; - - switch ( p ) { - case 0: - case 11: - case 15: - player.hn = 99; break; - - case 1: - case 2: - case 4: - case 5: - case 12: - case 16: - case 19: - case 22: - player.tk = 99; break; - - case 3: - case 10: - case 13: - case 17: - case 20: - player.ps = 99; break; - - case 6: - case 7: - case 8: - case 9: - case 14: - case 18: - case 21: - case 23: - player.sh = 99; break; - - default: break; - } - - player.hd = 99; - player.cr = 99; - player.ft = 99; - - player.morl = 8; - } -} - -void change_club(int new_club_idx, int player) { - struct gamea::manager &manager = gamea.manager[player]; - int old_club_idx = manager.club_idx; - manager.club_idx = new_club_idx; - - switch (manager.club_idx) { - case 0 ... 21: - manager.unk_number = 0; - manager.stadium.ground_facilities.level = 3; - manager.stadium.supporters_club.level = 3; - manager.stadium.flood_lights.level = 2; - manager.stadium.scoreboard.level = 3; - manager.stadium.undersoil_heating.level = 1; - manager.stadium.changing_rooms.level = 2; - manager.stadium.gymnasium.level = 3; - manager.stadium.car_park.level = 2; - - for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { - manager.stadium.safety_rating[i] = 4; - } - - for (int i = 0; i < 4; ++i) { - manager.stadium.capacity[i].seating = 10000; - manager.stadium.capacity[i].terraces = 0; - manager.stadium.conversion[i].level= 2; - manager.stadium.area_covering[i].level= 3; - } - - manager.price.league_match_seating = 15; - manager.price.league_match_terrace = 13; - manager.price.cup_match_seating = 18; - manager.price.cup_match_terrace = 15; - - break; - case 22 ... 45: - manager.unk_number = 1; - manager.stadium.ground_facilities.level = 2; - manager.stadium.supporters_club.level = 2; - manager.stadium.flood_lights.level = 2; - manager.stadium.scoreboard.level = 2; - manager.stadium.undersoil_heating.level = 1; - manager.stadium.changing_rooms.level = 2; - manager.stadium.gymnasium.level = 2; - manager.stadium.car_park.level = 2; - - for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { - manager.stadium.safety_rating[i] = 3; - } - - for (int i = 0; i < 4; ++i) { - manager.stadium.capacity[i].seating = 5000; - manager.stadium.capacity[i].terraces = 0; - manager.stadium.conversion[i].level = 2; - manager.stadium.area_covering[i].level = 2; - } - - manager.price.league_match_seating = 13; - manager.price.league_match_terrace = 11; - manager.price.cup_match_seating = 16; - manager.price.cup_match_terrace = 13; - - break; - case 46 ... 69: - manager.unk_number = 2; - manager.stadium.ground_facilities.level = 2; - manager.stadium.supporters_club.level = 2; - manager.stadium.flood_lights.level = 1; - manager.stadium.scoreboard.level = 2; - manager.stadium.undersoil_heating.level = 0; - manager.stadium.changing_rooms.level = 1; - manager.stadium.gymnasium.level = 2; - manager.stadium.car_park.level = 1; - - for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { - manager.stadium.safety_rating[i] = 2; - } - - for (int i = 0; i < 4; ++i) { - manager.stadium.capacity[i].seating = 2500; - manager.stadium.capacity[i].terraces = 0; - manager.stadium.conversion[i].level = 1; - manager.stadium.area_covering[i].level = 1; - } - - manager.price.league_match_seating = 11; - manager.price.league_match_terrace = 9; - manager.price.cup_match_seating = 14; - manager.price.cup_match_terrace = 11; - - break; - case 70 ... 91: - manager.unk_number = 3; - manager.stadium.ground_facilities.level = 1; - manager.stadium.supporters_club.level = 1; - manager.stadium.flood_lights.level = 1; - manager.stadium.scoreboard.level = 1; - manager.stadium.undersoil_heating.level = 0; - manager.stadium.changing_rooms.level = 1; - manager.stadium.gymnasium.level = 1; - manager.stadium.car_park.level = 1; - - for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { - manager.stadium.safety_rating[i] = 1; - } - - for (int i = 0; i < 4; ++i) { - manager.stadium.capacity[i].seating = 1000; - manager.stadium.capacity[i].terraces = 1; - manager.stadium.conversion[i].level = 0; - manager.stadium.area_covering[i].level = 0; - } - - manager.price.league_match_seating = 9; - manager.price.league_match_terrace = 7; - manager.price.cup_match_seating = 12; - manager.price.cup_match_terrace = 9; - - break; - case 92 ... 113: - manager.unk_number = 4; - manager.stadium.ground_facilities.level = 1; - manager.stadium.supporters_club.level = 1; - manager.stadium.flood_lights.level = 0; - manager.stadium.scoreboard.level = 1; - manager.stadium.undersoil_heating.level = 0; - manager.stadium.changing_rooms.level = 0; - manager.stadium.gymnasium.level = 1; - manager.stadium.car_park.level = 0; - - for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { - manager.stadium.safety_rating[i] = 0; - } - - for (int i = 0; i < 4; ++i) { - manager.stadium.capacity[i].seating = 500; - manager.stadium.capacity[i].terraces = 1; - manager.stadium.conversion[i].level = 0; - manager.stadium.area_covering[i].level = 0; - } - - manager.price.league_match_seating = 7; - manager.price.league_match_terrace = 5; - manager.price.cup_match_seating = 10; - manager.price.cup_match_terrace = 7; - - break; - default: - fprintf(stderr, "Invalid Club index (%i)\n", new_club_idx); - exit(EXIT_FAILURE); - } - - strncpy(gameb.club[new_club_idx].manager, gameb.club[old_club_idx].manager, 16); - strncpy(gameb.club[old_club_idx].manager, DEFAULT_MANAGER_NAME, 16); -} - void dump_free_players() { printf("CLUB NAME PLAYER NAME HN TK PS SH HD CR FT F M A AG WAGES\n"); for (int i = 0; i < 114; ++i) { diff --git a/pm3.cc b/pm3.cc new file mode 100644 index 0000000..9d92197 --- /dev/null +++ b/pm3.cc @@ -0,0 +1,573 @@ +#include +#include +#include +#include +#include +#include + +#include "pm3.h" + +#define DEFAULT_MANAGER_NAME "J.Smith " + +struct gamea gamea; +struct gameb gameb; +struct gamec gamec; + +struct saves saves; +struct prefs prefs; + +void check_consistency() { + int all[3932]; + for (int i = 0; i < 3932; ++i) + all[i] = -1; + + for (int c = 0; c < CLUB_IDX_MAX; ++c) { + fprintf(stderr, "Club[%3d]\n", c); + for (int p = 0; p < 24; ++p) { + if ( gameb.club[c].player_index[p] == -1 ) + continue; + + if (all[ gameb.club[c].player_index[p] ] == -1) { + + all[ gameb.club[c].player_index[p] ] = c; + printf("Added %d %12.12s to %16.16s\n", + gameb.club[c].player_index[p], + gamec.player[ gameb.club[c].player_index[p] ].name, + gameb.club[c].name); + + } else { + printf("Duplicate. %4d %12.12s plays for\n" + "%16.16s AND %16.16s\n", + gameb.club[c].player_index[p], + gamec.player[ gameb.club[c].player_index[p] ].name, + gameb.club[ all[ gameb.club[c].player_index[p] ] ].name, + gameb.club[c].name); + } + } + } + + for (int i = 0; i < sizeof(all); ++i) { + if ( all[i] != -1) + continue; + + fprintf(stderr, "%4d %12.12s is without a club.\n", + i, gamec.player[i].name); + } +} + +struct gameb::club& get_club(int idx) { + return gameb.club[idx]; +} + +struct gamec::player& get_player(int16_t idx) { + return gamec.player[idx]; +} + +const char* determine_player_type(struct gamec::player &p) { + if (p.hn > p.tk && p.hn > p.ps && p.hn > p.sh) { + return "G"; + } else if (p.tk > p.hn && p.tk > p.ps && p.tk > p.sh) { + return "D"; + } else if (p.ps > p.hd && p.ps > p.tk && p.ps > p.sh) { + return "M"; + } + + return "A"; +} + +void change_club(int new_club_idx, int player) { + struct gamea::manager &manager = gamea.manager[player]; + int old_club_idx = manager.club_idx; + manager.club_idx = new_club_idx; + + switch (manager.club_idx) { + case 0 ... 21: + manager.unk_number = 0; + manager.stadium.ground_facilities.level = 3; + manager.stadium.supporters_club.level = 3; + manager.stadium.flood_lights.level = 2; + manager.stadium.scoreboard.level = 3; + manager.stadium.undersoil_heating.level = 1; + manager.stadium.changing_rooms.level = 2; + manager.stadium.gymnasium.level = 3; + manager.stadium.car_park.level = 2; + + for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { + manager.stadium.safety_rating[i] = 4; + } + + for (int i = 0; i < 4; ++i) { + manager.stadium.capacity[i].seating = 10000; + manager.stadium.capacity[i].terraces = 0; + manager.stadium.conversion[i].level= 2; + manager.stadium.area_covering[i].level= 3; + } + + manager.price.league_match_seating = 15; + manager.price.league_match_terrace = 13; + manager.price.cup_match_seating = 18; + manager.price.cup_match_terrace = 15; + + break; + case 22 ... 45: + manager.unk_number = 1; + manager.stadium.ground_facilities.level = 2; + manager.stadium.supporters_club.level = 2; + manager.stadium.flood_lights.level = 2; + manager.stadium.scoreboard.level = 2; + manager.stadium.undersoil_heating.level = 1; + manager.stadium.changing_rooms.level = 2; + manager.stadium.gymnasium.level = 2; + manager.stadium.car_park.level = 2; + + for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { + manager.stadium.safety_rating[i] = 3; + } + + for (int i = 0; i < 4; ++i) { + manager.stadium.capacity[i].seating = 5000; + manager.stadium.capacity[i].terraces = 0; + manager.stadium.conversion[i].level = 2; + manager.stadium.area_covering[i].level = 2; + } + + manager.price.league_match_seating = 13; + manager.price.league_match_terrace = 11; + manager.price.cup_match_seating = 16; + manager.price.cup_match_terrace = 13; + + break; + case 46 ... 69: + manager.unk_number = 2; + manager.stadium.ground_facilities.level = 2; + manager.stadium.supporters_club.level = 2; + manager.stadium.flood_lights.level = 1; + manager.stadium.scoreboard.level = 2; + manager.stadium.undersoil_heating.level = 0; + manager.stadium.changing_rooms.level = 1; + manager.stadium.gymnasium.level = 2; + manager.stadium.car_park.level = 1; + + for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { + manager.stadium.safety_rating[i] = 2; + } + + for (int i = 0; i < 4; ++i) { + manager.stadium.capacity[i].seating = 2500; + manager.stadium.capacity[i].terraces = 0; + manager.stadium.conversion[i].level = 1; + manager.stadium.area_covering[i].level = 1; + } + + manager.price.league_match_seating = 11; + manager.price.league_match_terrace = 9; + manager.price.cup_match_seating = 14; + manager.price.cup_match_terrace = 11; + + break; + case 70 ... 91: + manager.unk_number = 3; + manager.stadium.ground_facilities.level = 1; + manager.stadium.supporters_club.level = 1; + manager.stadium.flood_lights.level = 1; + manager.stadium.scoreboard.level = 1; + manager.stadium.undersoil_heating.level = 0; + manager.stadium.changing_rooms.level = 1; + manager.stadium.gymnasium.level = 1; + manager.stadium.car_park.level = 1; + + for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { + manager.stadium.safety_rating[i] = 1; + } + + for (int i = 0; i < 4; ++i) { + manager.stadium.capacity[i].seating = 1000; + manager.stadium.capacity[i].terraces = 1; + manager.stadium.conversion[i].level = 0; + manager.stadium.area_covering[i].level = 0; + } + + manager.price.league_match_seating = 9; + manager.price.league_match_terrace = 7; + manager.price.cup_match_seating = 12; + manager.price.cup_match_terrace = 9; + + break; + case 92 ... 113: + manager.unk_number = 4; + manager.stadium.ground_facilities.level = 1; + manager.stadium.supporters_club.level = 1; + manager.stadium.flood_lights.level = 0; + manager.stadium.scoreboard.level = 1; + manager.stadium.undersoil_heating.level = 0; + manager.stadium.changing_rooms.level = 0; + manager.stadium.gymnasium.level = 1; + manager.stadium.car_park.level = 0; + + for (int i = 0; i < sizeof (manager.stadium.safety_rating); ++i) { + manager.stadium.safety_rating[i] = 0; + } + + for (int i = 0; i < 4; ++i) { + manager.stadium.capacity[i].seating = 500; + manager.stadium.capacity[i].terraces = 1; + manager.stadium.conversion[i].level = 0; + manager.stadium.area_covering[i].level = 0; + } + + manager.price.league_match_seating = 7; + manager.price.league_match_terrace = 5; + manager.price.cup_match_seating = 10; + manager.price.cup_match_terrace = 7; + + break; + default: + fprintf(stderr, "Invalid Club index (%i)\n", new_club_idx); + exit(EXIT_FAILURE); + } + + strncpy(gameb.club[new_club_idx].manager, gameb.club[old_club_idx].manager, 16); + strncpy(gameb.club[old_club_idx].manager, DEFAULT_MANAGER_NAME, 16); +} + +void soup_up(int player) { + + struct gamea::manager &manager = gamea.manager[player]; + + for (int i = 0; i < 20; ++i) { + struct gamea::manager::employee &employee = manager.employee[i]; + printf("Employee: %14.14s\n", employee.name); + employee.skill = 99; + //employee.age = i % 16; + } + + struct gameb::club &club = gameb.club[ manager.club_idx ]; + + for (int p = 0; p < 24; ++p) { + if (club.player_index[p] == -1) + continue; + + struct gamec::player &player = gamec.player[ club.player_index[p] ]; + + player.hn = 97; + player.tk = 97; + player.ps = 97; + player.sh = 97; + + switch ( p ) { + case 0: + case 11: + case 15: + player.hn = 99; break; + + case 1: + case 2: + case 4: + case 5: + case 12: + case 16: + case 19: + case 22: + player.tk = 99; break; + + case 3: + case 10: + case 13: + case 17: + case 20: + player.ps = 99; break; + + case 6: + case 7: + case 8: + case 9: + case 14: + case 18: + case 21: + case 23: + player.sh = 99; break; + + default: break; + } + + player.hd = 99; + player.cr = 99; + player.ft = 99; + + player.morl = 8; + } +} + +void load_binaries(int game_nr, const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + void *game_data[] = { &gamea, &gameb, &gamec }; + size_t game_data_size[] = { + sizeof (struct gamea), + sizeof (struct gameb), + sizeof (struct gamec) + }; + + for (int i = 0; i < 3; ++i) { + DIR *dirp = opendir(game_path); + if (dirp == NULL) { + fprintf(stderr, "Could not open \"%s\": %s\n", game_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct dirent *entry = NULL; + while ((entry = readdir(dirp)) != NULL) { + if (0 == strcasecmp(entry->d_name, "SAVES")) + break; + } + if (entry == NULL) { + fprintf(stderr, "Could not find SAVES directory in %s\n", game_path); + exit(EXIT_FAILURE); + } + + char *savegame_path = NULL; + size_t res = asprintf(&savegame_path, "%s%s%s/GAME%.1d%c", + game_path, has_trailing_slash ? "" : "/", entry->d_name, game_nr, 'A' + i); + + FILE *fp = fopen(savegame_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", savegame_path, strerror(errno)); + exit(EXIT_FAILURE); + } + fread(game_data[i], game_data_size[i], 1, fp); + + fclose(fp); + free(savegame_path); + closedir(dirp); + } +} + +void save_binaries(int game_nr, const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + void *game_data[] = { &gamea, &gameb, &gamec }; + size_t game_data_size[] = { + sizeof (struct gamea), + sizeof (struct gameb), + sizeof (struct gamec) + }; + + for (int i = 0; i < 3; ++i) { + DIR *dirp = opendir(game_path); + if (dirp == NULL) { + fprintf(stderr, "Could not open \"%s\": %s\n", game_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct dirent *entry = NULL; + while ((entry = readdir(dirp)) != NULL) { + if (0 == strcasecmp(entry->d_name, "SAVES")) + break; + } + if (entry == NULL) { + fprintf(stderr, "Could not find SAVES directory in %s\n", game_path); + exit(EXIT_FAILURE); + } + + char *savegame_path = NULL; + size_t res = asprintf(&savegame_path, "%s%s%s/GAME%.1d%c", + game_path, has_trailing_slash ? "" : "/", entry->d_name, game_nr, 'A' + i); + + FILE *fp = fopen(savegame_path, "w+"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", savegame_path, strerror(errno)); + exit(EXIT_FAILURE); + } + fwrite(game_data[i], game_data_size[i], 1, fp); + + fclose(fp); + free(savegame_path); + closedir(dirp); + } +} + +void load_metadata(const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + DIR *dirp = opendir(game_path); + if (dirp == NULL) { + fprintf(stderr, "Could not open \"%s\": %s\n", game_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct dirent *entry = NULL; + while ((entry = readdir(dirp)) != NULL) { + if (0 == strcasecmp(entry->d_name, "SAVES")) + break; + } + if (entry == NULL) { + fprintf(stderr, "Could not find SAVES directory in %s\n", game_path); + exit(EXIT_FAILURE); + } + + FILE *fp = NULL; + + char *saves_path = NULL; + len = asprintf(&saves_path, "%s%s%s/SAVES.DIR", + game_path, has_trailing_slash ? "" : "/", entry->d_name); + + fp = fopen(saves_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", saves_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct saves { char hest[10]; } saves; + fread(&saves, sizeof (struct saves), 1, fp); + + fclose(fp); + free(saves_path); + + char *prefs_path = NULL; + len = asprintf(&prefs_path, "%s%s%s/PREFS", + game_path, has_trailing_slash ? "" : "/", entry->d_name); + + fp = fopen(prefs_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", prefs_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct prefs { char hest[10]; } prefs; + fread(&prefs, sizeof (struct prefs), 1, fp); + + fclose(fp); + free(prefs_path); +} + +void update_metadata(int game_nr) { + saves.game[game_nr - 1].year = gamea.year; + saves.game[game_nr - 1].turn = gamea.turn; + strcpy(saves.game[game_nr - 1].manager[0].name, gamea.manager[0].name); + strcpy(saves.game[game_nr - 1].manager[1].name, gamea.manager[1].name); + saves.game[game_nr - 1].manager[0].club_idx = gamea.manager[0].club_idx; + saves.game[game_nr - 1].manager[1].club_idx = gamea.manager[1].club_idx; +} + +void save_metadata(const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + DIR *dirp = opendir(game_path); + if (dirp == NULL) { + fprintf(stderr, "Could not open \"%s\": %s\n", game_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct dirent *entry = NULL; + while ((entry = readdir(dirp)) != NULL) { + if (0 == strcasecmp(entry->d_name, "SAVES")) + break; + } + if (entry == NULL) { + fprintf(stderr, "Could not find SAVES directory in %s\n", game_path); + exit(EXIT_FAILURE); + } + + FILE *fp = NULL; + + char *saves_path = NULL; + len = asprintf(&saves_path, "%s%s%s/SAVES.DIR", + game_path, has_trailing_slash ? "" : "/", entry->d_name); + + fp = fopen(saves_path, "w+"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", saves_path, strerror(errno)); + exit(EXIT_FAILURE); + } + fwrite(&saves, sizeof (struct saves), 1, fp); + + fclose(fp); + free(saves_path); + + char *prefs_path = NULL; + len = asprintf(&prefs_path, "%s%s%s/PREFS", + game_path, has_trailing_slash ? "" : "/", entry->d_name); + + fp = fopen(prefs_path, "w+"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", prefs_path, strerror(errno)); + exit(EXIT_FAILURE); + } + fwrite(&prefs, sizeof (struct prefs), 1, fp); + + fclose(fp); + free(prefs_path); +} + +struct gamea *load_default_gamedata(const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + char *gamedata_path = NULL; + size_t res = asprintf(&gamedata_path, "%s%sgamedata.dat", + game_path, has_trailing_slash ? "" : "/"); + + FILE *fp = fopen(gamedata_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", gamedata_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct gamea *gamedata = (struct gamea *) malloc(sizeof (struct gamea)); + fread(gamedata, sizeof(struct gamea), 1, fp); + + fclose(fp); + free(gamedata_path); + + return gamedata; +} + +struct gameb *load_default_clubdata(const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + char *clubdata_path = NULL; + size_t res = asprintf(&clubdata_path, "%s%sclubdata.dat", + game_path, has_trailing_slash ? "" : "/"); + + FILE *fp = fopen(clubdata_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", clubdata_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct gameb *clubdata = (struct gameb *) malloc(sizeof (struct gameb)); + fread(clubdata, sizeof(struct gameb), 1, fp); + + fclose(fp); + free(clubdata_path); + + return clubdata; +} + +struct gamec *load_default_playdata(const char *game_path) { + size_t len = strlen(game_path); + bool has_trailing_slash = (len > 0 && game_path[len - 1] == '/'); + + char *playerdata_path = NULL; + size_t res = asprintf(&playerdata_path, "%s%splaydata.dat", + playerdata_path, has_trailing_slash ? "" : "/"); + + FILE *fp = fopen(playerdata_path, "r"); + if (fp == nullptr) { + fprintf(stderr, "Could not open \"%s\": %s\n", playerdata_path, strerror(errno)); + exit(EXIT_FAILURE); + } + + struct gamec *playerdata = (struct gamec *) malloc(sizeof (struct gamec)); + fread(playerdata, sizeof(struct gamec), 1, fp); + + fclose(fp); + free(playerdata_path); + + return playerdata; +} diff --git a/pm3.h b/pm3.h new file mode 100644 index 0000000..6bec073 --- /dev/null +++ b/pm3.h @@ -0,0 +1,656 @@ +#ifndef _PM3_H +#define _PM3_H + +#include + +#define CLUB_IDX_MAX 244 +#define HOME 0 +#define AWAY 1 + +struct gamea { + + union { + struct { + int16_t premier_league[22]; + int16_t division_one[24]; + int16_t division_two[24]; + int16_t division_three[22]; + int16_t conference_league[22]; + int16_t misc[4]; + } __attribute__ ((packed)); + int16_t all[118]; + } __attribute__ ((packed)) club_index; + + union { + struct { + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) premier_league[22]; + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_one[24]; + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_two[24]; + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) division_three[22]; + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; int16_t xx; } __attribute__ ((packed)) conference_league[22]; + } __attribute__ ((packed)); + + struct { int16_t club_idx; int16_t hx; int16_t hw; int16_t hd; int16_t hl; int16_t hf; int16_t ha; + int16_t ax; int16_t aw; int16_t ad; int16_t al; int16_t af; int16_t aa; + int16_t xx; + } __attribute__ ((packed)) all[114]; + } __attribute__ ((packed)) table; + + uint16_t data000; + uint16_t data001; + uint32_t data002; + + union { + struct { + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) premier_league[15]; + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_one[15]; + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_two[15]; + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) division_three[15]; + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) conference_league[15]; + } __attribute__ ((packed)); + struct { int16_t player_idx; int16_t club_idx; int8_t pl; int8_t sc; } __attribute__ ((packed)) all[75]; + } __attribute__ ((packed)) top_scorers; //450 + + uint16_t sorted_numbers[64]; + + struct referee { + char name[14]; + uint8_t magic : 3; + uint8_t age : 5; + uint8_t var[7]; + } __attribute__ ((packed)) referee[64]; + + + union cuppy { + struct { + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_fa_cup[36]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_league_cup[28]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) data090[4]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_champions_cup[16]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) data091[16]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_cup_winners_cup[16]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_uefa_cup[32]; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_charity_shield; + } __attribute__ ((packed)); + struct cup_entry { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) all[149]; + } __attribute__ ((packed)) cuppy; + + uint8_t data095[2240]; + + struct { + struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; + } __attribute__ ((packed)) the_charity_shield_history; // history? + + struct { + int16_t club1_idx; + int16_t club1_goals; + int32_t club1_audience; + int16_t club2_idx; + int16_t club2_goals; + int32_t club2_audience; + } __attribute__ ((packed)) some_table[16]; // history? + + union { + struct { + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) the_fa_cup[0]; + }; + struct { struct { int16_t idx; int16_t goals; int32_t audience; } __attribute__ ((packed)) club[2]; } __attribute__ ((packed)) all[57]; + } __attribute__ ((packed)) last_results; + + struct { + struct { + int16_t year; + int16_t club_idx; + uint8_t data[12]; + } __attribute__ ((packed)) history[20]; + } __attribute__ ((packed)) league[5]; + + struct { + struct { + int16_t year; + int16_t club_idx_winner; + int16_t club_idx_runner_up; + uint8_t type_winner; + uint8_t type_runner_up; + } __attribute__ ((packed)) history[20]; + } __attribute__ ((packed)) cup[6]; + + struct { + int16_t club_idx1; + int16_t club_idx2; + } __attribute__ ((packed)) fixture[20]; + + uint8_t data100[106]; + struct { + int16_t player_idx; + int16_t club_idx; + } __attribute__ ((packed)) transfer_market[45]; + + uint8_t data10z[208]; + + struct { + int16_t player_idx; + int16_t from_club_idx; + int16_t to_club_idx; + int32_t fee; + } __attribute__ ((packed)) transfer[6]; + + uint8_t data101[20]; + int16_t retired_manager_club_idx; + int16_t new_manager_club_idx; + char manager_name[16]; + uint8_t data10w[8]; + uint16_t turn; + uint16_t year; + + /* seems to be a collection of 16bit numbers. */ + uint16_t data10x[15]; + + /* The players of the game */ + struct manager { + char name[16]; + int16_t club_idx; + int16_t division; + uint16_t contract_length; + + struct { + uint8_t league_match_seating; + uint8_t league_match_terrace; + uint8_t cup_match_seating; + uint8_t cup_match_terrace; + }__attribute__ ((packed)) price; + + uint32_t seating_history[23]; + uint32_t terrace_history[23]; + + struct bank_statement { + int32_t gate_receipts[2]; + int32_t club_wages[2]; + int32_t transfer_fees[2]; + int32_t club_fines[2]; + int32_t grants_for_club[2]; + int32_t club_bills[2]; + int32_t miscellaneous_sales[2]; + int32_t bank_loan_payments[2]; + int32_t ground_improvements[2]; + int32_t advertising_boards[2]; + int32_t other_items[2]; + int32_t account_interest[2]; + } __attribute__ ((packed)) bank_statement[2]; + + struct loan { + uint32_t amount; + uint8_t turn; //3 turns in a week, 42 weeks in a year? + uint8_t year; + } __attribute__ ((packed)) loan[4]; + + struct employee { + char name[14]; + uint8_t skill; + uint8_t type : 4; + uint8_t age : 4; + } __attribute__ ((packed)) employee[20]; + + struct assistant_manager { + uint8_t do_training_schedules; + uint8_t treat_injured_players; + uint8_t check_sponsors_boards; + uint8_t hire_and_fire_employees; + uint8_t negotiate_player_contracts; + } __attribute__ ((packed)) assistant_manager; + + uint8_t data120; + uint8_t youth_player_type; + uint8_t data121; + + int16_t youth_player; + + uint8_t data147[3]; + + struct scout { + int8_t size; + uint8_t skill; + uint8_t rating; + uint8_t division : 3; + uint8_t foot : 5; + uint8_t club; + struct { + int16_t ix1; + int16_t ix2; + } __attribute__ ((packed)) results[18]; + uint8_t other[5]; + } __attribute__ ((packed)) scout[4]; + + uint8_t smnthn; + uint32_t number1; + uint32_t number2; + uint32_t number3; + uint32_t money_from_directors; + uint8_t data149[20]; + + struct news { + int16_t type; + int32_t amount; + int16_t ix1; + int16_t ix2; + int16_t ix3; + } __attribute__ ((packed)) news[8]; + + int32_t minus_one; + int16_t unknown_player_idx[2]; + uint8_t data150[576]; + + struct stadium { + struct { + char name[20]; + } __attribute__ ((packed)) stand[4]; + + struct { + uint8_t level : 3; + uint8_t time : 5; + } __attribute__ ((packed)) seating_build[4]; + + struct { + uint8_t level : 3; /* terraces, wooden seating, plastic seating */ + uint8_t time : 5; + } __attribute__ ((packed)) conversion[4]; + + struct { + uint8_t level : 3; + uint8_t time : 5; + } __attribute__ ((packed)) area_covering[4]; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) ground_facilities; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) supporters_club; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) flood_lights; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) scoreboard; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) undersoil_heating; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) changing_rooms; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) gymnasium; + + struct { + uint32_t level : 3; + uint32_t time : 29; + } __attribute__ ((packed)) car_park; + + uint8_t safety_rating[4]; + + struct { + uint16_t seating: 15; + uint16_t terraces: 1; + } __attribute__ ((packed)) capacity[4]; + + } __attribute__ ((packed)) stadium; + + int16_t numb01; + int16_t numb02; + int16_t numb03; + int16_t numb04; + + uint8_t managerial_rating_start; + uint8_t managerial_rating_current; + uint8_t directors_confidence_start; + uint8_t directors_confidence_current; + uint8_t supporters_confidence_start; + uint8_t supporters_confidence_current; + + uint8_t head6[6]; + int16_t player3_idx; + uint8_t magic4[4]; + int16_t player4_idx; + uint8_t foot6[6]; + + struct match_summary { + struct club { + uint16_t club_idx; + uint16_t total_goals; + uint16_t first_half_goals; + uint8_t pattern6[6]; // 02 00 26 50 60 77 + uint8_t match_data[4]; + uint8_t corners; + uint8_t throw_ins; + uint8_t free_kicks; + uint8_t penalties; + + struct lineup { + int16_t player_idx; + uint8_t data5[5]; + uint8_t fitness; // matches with benched players, but not onfield. + uint8_t card; + uint8_t shots_attempted; + uint8_t shots_missed; + uint8_t something; + uint8_t tackles_attempted; + uint8_t tackles_won; + uint8_t passes_attempted; + uint8_t passes_bad; + uint8_t shots_saved; // these are for opposing club in the fax_match_summary + uint8_t x[3]; + } __attribute__ ((packed)) lineup[14]; + + struct goal { + int16_t player_idx; + int16_t time; + } __attribute__ ((packed)) goal[8]; + + uint16_t always_null; + uint8_t substitutions_remaining; + uint8_t other; + uint16_t home_away_data; // home: 0x5738, away: 0x91f8 + } __attribute__ ((packed)) club[2]; // home + away club + + uint16_t weather; + uint8_t referee_idx; + uint8_t data156[4]; + /* + * 1e fa_cup semi final + * 1f fa_cup 4th/5th, + * 20 fa_cup 3rd, + * 21 league cup 2nd round 1, 4th round, quarter final + * 22 league cup 2nd round 2, 3rd round + * 23 champions cup 1st leg 1, + * 24 cup_win_cup 2nd round 1/2/qfinal + * 27 charity_shield + * 28 premier + * 29 home-friendly + * 2b conference + */ + uint8_t match_type; + uint8_t data157[6]; + uint32_t audience; + uint8_t data158[92]; + } __attribute__ ((packed)) match_summary; + + struct league_history { + uint16_t year; + uint16_t div; + uint16_t club_idx; + uint16_t ps; + uint16_t p; + uint16_t w; + uint16_t d; + uint16_t l; + uint16_t gd; + uint16_t pts; + uint8_t unk21; + uint8_t unk22; + uint8_t unk23; + uint8_t unk24; + uint8_t unk25; + uint8_t unk26; + uint8_t unk27; + uint8_t unk28; + uint8_t unk29; + uint8_t unk30; + uint8_t unk31; + uint8_t unk32; + } __attribute__ ((packed)) league_history[20]; + + struct { + uint16_t won; + uint16_t yrs; + } __attribute__ ((packed)) titles[11]; + + struct { + uint16_t play; + uint16_t won; + uint16_t drew; + uint16_t lost; + uint16_t forx; + uint16_t agn; + } __attribute__ ((packed)) manager_history[11]; + + uint8_t data159[12]; + + struct { + int16_t year_from; + int16_t year_to; + uint8_t club_idx; + uint8_t mngr; + uint8_t drct; + uint8_t sprt; + } __attribute__ ((packed)) previous_clubs[4]; + + int16_t year_start_cur_club; + + uint16_t manager_of_the_month_awards; + uint16_t manager_of_the_year_awards; + + struct { //1936 + uint8_t club_idx; + uint8_t played; + uint8_t won; + uint8_t draw; + uint16_t goals_f; + uint16_t goals_a; + } __attribute__ ((packed)) match_history[242]; + + uint8_t data160[1794]; + + struct { + char name[20]; + } __attribute__ ((packed)) tactic[8]; + } __attribute__ ((packed)) manager[2]; + + uint8_t data200[10]; + uint16_t inc_number1; + uint16_t inc_number2; + uint16_t inc_number3; + +} __attribute__ ((packed)); +extern struct gamea gamea; + +struct gameb { + struct club { + char name[16]; + char manager[16]; + int32_t bank_account; + char stadium[24]; + int32_t seating_avg; + int32_t seating_max; + uint8_t padding[8]; + int16_t player_index[24]; + + uint8_t misc000[4]; + struct kit { + uint8_t shirt_design; + uint8_t shirt_primary_color_r : 4; + uint8_t shirt_primary_color_g : 4; + uint8_t shirt_primary_color_b : 4; + + uint8_t shirt_secondary_color_r : 4; + uint8_t shirt_secondary_color_g : 4; + uint8_t shirt_secondary_color_b : 4; + + uint8_t shorts_color_r : 4; + uint8_t shorts_color_g : 4; + uint8_t shorts_color_b : 4; + + uint8_t socks_color_r : 4; + uint8_t socks_color_g : 4; + uint8_t socks_color_b : 4; + } __attribute__ ((packed)) kit[3]; // 0=Home, 1=Away1, 2=Away2 + + uint8_t player_image; + uint8_t weekly_league_position[46]; + uint8_t misc005[3]; + uint8_t league; + + struct timetable { + struct week { + struct day { + + uint8_t opponent_idx; + + union { + struct { + uint8_t home: 4; + uint8_t away: 4; + } __attribute__ ((packed)); + int8_t result; + }; + + union { + struct { + uint8_t type: 5; + uint8_t game: 3; + } __attribute__ ((packed)); + uint8_t b3; + }; + + } __attribute__ ((packed)) day[3]; + } __attribute__ ((packed)) week[41]; + uint8_t end; + } __attribute__ ((packed)) timetable; + + } __attribute__ ((packed)) club[CLUB_IDX_MAX]; + +} __attribute__ ((packed)); +extern struct gameb gameb; + +struct gamec { + struct player { + char name[12]; + + uint8_t u13; + uint8_t hn; + uint8_t u15; + uint8_t tk; + uint8_t u17; + uint8_t ps; + uint8_t u19; + uint8_t sh; + uint8_t u21; + uint8_t hd; + uint8_t u23; + uint8_t cr; + uint8_t u25; + uint8_t ft; + + uint8_t morl : 4; + uint8_t aggr : 4; + + uint8_t ins : 2; + uint8_t age : 6; + + uint8_t foot : 2; + uint8_t dpts : 6; + + uint8_t played; + uint8_t scored; + uint8_t unk2; + uint16_t wage; + uint16_t ins_cost; + uint8_t inj_away; + + uint8_t unk4: 5; + uint8_t contract : 3; + + uint8_t unk5; + + uint8_t train : 4; + uint8_t intense : 4; + + } __attribute__ ((packed))player[3932]; +} __attribute__ ((packed)); +extern struct gamec gamec; + +struct saves { + struct game { + uint16_t year; + uint16_t turn; + struct manager { + char name[16]; + uint8_t club_idx; + } __attribute__ ((packed)) manager[2]; + uint8_t misc000[162]; // Tactics files + } __attribute__ ((packed)) game[8]; +} __attribute__ ((packed)); +extern struct saves saves; + +struct prefs { + struct league_reports { + int16_t hide_premier_league; + int16_t hide_division_one; + int16_t hide_division_two; + int16_t hide_division_three; + int16_t hide_conference_league; + } __attribute__ ((packed)) league_reports; + struct cup_reports { + int16_t hide_fa_cup; + int16_t hide_league_cup; + int16_t hide_champions_cup; + int16_t hide_cup_winners_cup; + int16_t hide_uefa_cup; + int16_t hide_charity_shield; + } __attribute__ ((packed)) cup_reports; + int16_t hide_friendlies; + struct view_screens { + int16_t hide_results_monitor; + int16_t hide_next_matches; + int16_t hide_manager_of_the_month; + } __attribute__ ((packed)) view_screens; + struct interactive_matches { + int16_t match_graphics; // 0 = None, 1 = Strips, 2 = Numbers + int16_t unused1; + int16_t show_match_pictures; + int16_t speed; // Revered so 00 = 50, 31 = 1 + int16_t unk1; + int16_t unused3; + } __attribute__ ((packed)) interactive_matches; + struct audio { + int16_t mute_sound_effects; + int16_t mute_music; + } __attribute__ ((packed)) audio; +} __attribute__ ((packed)); +extern struct prefs prefs; + +void check_consistency(); + +struct gameb::club& get_club(int idx); +struct gamec::player& get_player(int16_t idx); + +const char* determine_player_type(struct gamec::player &player); +void change_club(int new_club_idx, int player = 0); + +void soup_up(int player = 0); + +void load_binaries(int game_nr, const char *game_path); +void save_binaries(int game_nr, const char *game_path); + +void load_metadata(const char *game_path); +void update_metadata(int game_nr); +void save_metadata(const char *game_path); + +struct gamea *load_default_gamedata(const char *game_path); +struct gameb *load_default_clubdata(const char *game_path); +struct gamec *load_default_playdata(const char *game_path); + +#endif