diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index f10f95cd..b32a53cb 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -3960,6 +3960,7 @@ + diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index 3e368704..6d367b0c 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -15009,6 +15009,9 @@ Source Files\src\pc\network\packets + + Source Files\src\pc\network\packets + diff --git a/src/game/game_init.c b/src/game/game_init.c index f683782a..55618052 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -570,7 +570,7 @@ void thread5_game_loop(UNUSED void *arg) { init_rumble_pak_scheduler_queue(); init_controllers(); create_thread_6(); - save_file_load_all(); + save_file_load_all(FALSE); set_vblank_handler(2, &gGameVblankHandler, &gGameVblankQueue, (OSMesg) 1); diff --git a/src/game/save_file.c b/src/game/save_file.c index 9652c97b..65fa8866 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -12,6 +12,7 @@ #include "thread6.h" #include "macros.h" #include "pc/ini.h" +#include "pc/network/network.h" #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 @@ -345,16 +346,17 @@ void save_file_do_save(s32 fileIndex) { if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES) return; - if (gSaveFileModified) #ifdef TEXTSAVES - { + if (gSaveFileModified && networkType != NT_CLIENT) { // Write to text file write_text_save(fileIndex); gSaveFileModified = FALSE; gMainMenuDataModified = FALSE; + return; } -#else - { +#endif + + if (gSaveFileModified) { // Compute checksum add_save_block_signature(&gSaveBuffer.files[fileIndex][0], sizeof(gSaveBuffer.files[fileIndex][0]), SAVE_FILE_MAGIC); @@ -369,7 +371,6 @@ void save_file_do_save(s32 fileIndex) { gSaveFileModified = FALSE; } save_main_menu_data(); -#endif } void save_file_erase(s32 fileIndex) { @@ -396,7 +397,18 @@ BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) { save_file_do_save(destFileIndex); } -void save_file_load_all(void) { +#ifdef TEXTSAVES +static void save_file_load_textsaves(void) { + for (file = 0; file < NUM_SAVE_FILES; file++) { + read_text_save(file); + } + gSaveFileModified = TRUE; + gMainMenuDataModified = TRUE; + stub_save_file_1(); +} +#endif + +void save_file_load_all(u8 reload) { s32 file; gMainMenuDataModified = FALSE; @@ -405,19 +417,19 @@ void save_file_load_all(void) { bzero(&gSaveBuffer, sizeof(gSaveBuffer)); #ifdef TEXTSAVES - for (file = 0; file < NUM_SAVE_FILES; file++) { - read_text_save(file); + if (!reload) { + save_file_load_textsaves(); + return; } - gSaveFileModified = TRUE; - gMainMenuDataModified = TRUE; -#else - s32 validSlots; +#endif + read_eeprom_data(&gSaveBuffer, sizeof(gSaveBuffer)); if (save_file_need_bswap(&gSaveBuffer)) save_file_bswap(&gSaveBuffer); // Verify the main menu data and create a backup copy if only one of the slots is valid. + s32 validSlots; validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC); validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1; switch (validSlots) { @@ -448,7 +460,6 @@ void save_file_load_all(void) { break; } } -#endif // TEXTSAVES stub_save_file_1(); } diff --git a/src/game/save_file.h b/src/game/save_file.h index c292a156..11a92b8d 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -124,7 +124,7 @@ extern s8 gSaveFileModified; void save_file_do_save(s32 fileIndex); void save_file_erase(s32 fileIndex); BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex); -void save_file_load_all(void); +void save_file_load_all(u8 reload); void save_file_reload(void); void save_file_collect_star_or_key(s16 coinScore, s16 starIndex); s32 save_file_exists(s32 fileIndex); diff --git a/src/menu/file_select.c b/src/menu/file_select.c index 4ca0454e..3fc4e87a 100644 --- a/src/menu/file_select.c +++ b/src/menu/file_select.c @@ -382,6 +382,7 @@ void exit_join_to_network_menu(void) { && sCursorClickingTimer == 2) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; + network_shutdown(); keyboard_stop_text_input(); } // End exit @@ -399,7 +400,8 @@ void keyboard_exit_join_to_network_menu(void) { } void join_server_as_client(void) { - sCursorClickingTimer = 2; + if (networkType != NT_NONE) { return; } + char delims[] = { ' ' }; // trim whitespace @@ -420,8 +422,13 @@ void join_server_as_client(void) { return; } + keyboard_stop_text_input(); network_init(NT_CLIENT, textInput, port); - sSelectedFileNum = 1; +} + +void joined_server_as_client(s16 fileIndex) { + if (networkType != NT_CLIENT) { return; } + sSelectedFileNum = fileIndex; } void render_network_mode_menu_buttons(struct Object* soundModeButton) { @@ -3054,7 +3061,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) { sClickPos[0] = -10000; sClickPos[1] = -10000; sCursorClickingTimer = 0; - sSelectedFileNum = 0; + if (networkType != NT_CLIENT) { sSelectedFileNum = 0; } sSelectedFileIndex = MENU_BUTTON_NONE; sFadeOutText = FALSE; sStatusMessageID = 0; @@ -3080,7 +3087,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) { sCursorPos[1] = -24.0f; // immediately jump in - if (networkType != NT_NONE) { + if (networkType == NT_SERVER) { sSelectedFileNum = 1; } diff --git a/src/menu/file_select.h b/src/menu/file_select.h index 91fbb81d..7629ebbd 100644 --- a/src/menu/file_select.h +++ b/src/menu/file_select.h @@ -143,5 +143,6 @@ void bhv_menu_button_manager_loop(void); Gfx *geo_file_select_strings_and_menu_cursor(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx); s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused); s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused); +void joined_server_as_client(s16 fileIndex); #endif // FILE_SELECT_H diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 2c86e40c..8a77ce84 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -34,6 +34,10 @@ void network_init(enum NetworkType inNetworkType, char* ip, char* port) { txAddr.sin_port = htons(atoi(port)); txAddr.sin_addr.s_addr = inet_addr(ip); } + + if (networkType == NT_CLIENT) { + network_send_save_file_request(); + } } void network_on_init_level(void) { @@ -108,6 +112,8 @@ void network_update(void) { case PACKET_COLLECT_ITEM: network_receive_collect_item(&p); break; case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(&p); break; case PACKET_RESERVATION: network_receive_reservation(&p); break; + case PACKET_SAVE_FILE_REQUEST: network_receive_save_file_request(&p); break; + case PACKET_SAVE_FILE: network_receive_save_file(&p); break; case PACKET_CUSTOM: network_receive_custom(&p); break; default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]); } @@ -123,4 +129,5 @@ void network_update(void) { void network_shutdown(void) { if (networkType == NT_NONE) { return; } socket_close(gSocket); + networkType = NT_NONE; } diff --git a/src/pc/network/network.h b/src/pc/network/network.h index f27d9dba..dc3e8b64 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -29,6 +29,8 @@ enum PacketType { PACKET_COLLECT_ITEM, PACKET_RESERVATION_REQUEST, PACKET_RESERVATION, + PACKET_SAVE_FILE_REQUEST, + PACKET_SAVE_FILE, PACKET_CUSTOM = 255, }; @@ -127,10 +129,15 @@ void network_send_collect_item(struct Object* o); void network_receive_collect_item(struct Packet* p); void network_send_reservation_request(void); -void network_receive_reservation_request(struct Packet* p); +void network_receive_reservation_request(UNUSED struct Packet* p); void network_send_reservation(void); void network_receive_reservation(struct Packet* p); +void network_send_save_file_request(void); +void network_receive_save_file_request(UNUSED struct Packet* p); +void network_send_save_file(void); +void network_receive_save_file(struct Packet* p); + u8 network_register_custom_packet(void (*send_callback)(struct Packet* p, void* params), void (*receive_callback)(struct Packet* p)); void network_send_custom(u8 customId, bool reliable, void* params); void network_receive_custom(struct Packet* p); diff --git a/src/pc/network/packets/packet_custom.c b/src/pc/network/packets/packet_custom.c index 702e8751..4a076335 100644 --- a/src/pc/network/packets/packet_custom.c +++ b/src/pc/network/packets/packet_custom.c @@ -1,7 +1,7 @@ #include #include "../network.h" -#define MAX_CUSTOM_PACKETS 32 +#define MAX_CUSTOM_PACKETS 128 struct NetworkCustomPacket { void (*send_callback)(struct Packet* p, void* params); diff --git a/src/pc/network/packets/packet_save_file.c b/src/pc/network/packets/packet_save_file.c new file mode 100644 index 00000000..3b2dd129 --- /dev/null +++ b/src/pc/network/packets/packet_save_file.c @@ -0,0 +1,59 @@ +#include +#include "../network.h" +#include "object_fields.h" +#include "object_constants.h" +#include "behavior_table.h" +#include "course_table.h" +#include "src/game/interaction.h" +#include "src/engine/math_util.h" +#include "src/game/save_file.h" +#include "src/menu/file_select.h" +#include "src/pc/fs/fs.h" +#include "PR/os_eeprom.h" + +extern u8* gOverrideEeprom; +static u8 eeprom[512] = { 0 }; + +void network_send_save_file_request(void) { + assert(networkType == NT_CLIENT); + + gOverrideEeprom = eeprom; + + struct Packet p; + packet_init(&p, PACKET_SAVE_FILE_REQUEST, true); + network_send(&p); +} + +void network_receive_save_file_request(UNUSED struct Packet* p) { + assert(networkType == NT_SERVER); + network_send_save_file(); +} + +void network_send_save_file(void) { + assert(networkType == NT_SERVER); + + fs_file_t* fp = fs_open(SAVE_FILENAME); + if (fp != NULL) { + fs_read(fp, eeprom, 512); + fs_close(fp); + } + + struct Packet p; + packet_init(&p, PACKET_SAVE_FILE, true); + packet_write(&p, &gCurrSaveFileNum, sizeof(s16)); + packet_write(&p, eeprom, sizeof(u8) * 512); + network_send(&p); +} + +void network_receive_save_file(struct Packet* p) { + assert(networkType == NT_CLIENT); + + gOverrideEeprom = eeprom; + + // find all reserved objects + packet_read(p, &gCurrSaveFileNum, sizeof(s16)); + packet_read(p, eeprom, sizeof(u8) * 512); + + save_file_load_all(TRUE); + joined_server_as_client(gCurrSaveFileNum); +} diff --git a/src/pc/ultra_reimplementation.c b/src/pc/ultra_reimplementation.c index 0389776b..c3776b16 100644 --- a/src/pc/ultra_reimplementation.c +++ b/src/pc/ultra_reimplementation.c @@ -9,6 +9,8 @@ #include #endif +u8* gOverrideEeprom = NULL; + extern OSMgrArgs piMgrArgs; u64 osClockRate = 62500000; @@ -124,6 +126,11 @@ s32 osEepromProbe(UNUSED OSMesgQueue *mq) { } s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) { + if (gOverrideEeprom != NULL) { + memcpy(buffer, gOverrideEeprom + address * 8, nbytes); + return 0; + } + u8 content[512]; s32 ret = -1; @@ -162,6 +169,11 @@ s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) } s32 osEepromLongWrite(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) { + if (gOverrideEeprom != NULL) { + memcpy(gOverrideEeprom + address * 8, buffer, nbytes); + return 0; + } + u8 content[512] = {0}; if (address != 0 || nbytes != 512) { osEepromLongRead(mq, 0, content, 512);