diff --git a/Online/Core/CustomizeMessageLRAS.asm b/Online/Core/CustomizeMessageLRAS.asm index 8a9b9508..9ea5c6eb 100644 --- a/Online/Core/CustomizeMessageLRAS.asm +++ b/Online/Core/CustomizeMessageLRAS.asm @@ -50,6 +50,9 @@ PLAY_SOUND: branchl r12, SFX_Menu_CommonSound SKIP_PLAY_SOUND: +# 0: Time, 1: Sudden Death, 2: Success, 3: Ready, 4: GO!, 5: Game!, 6: Failure, 7: Complete, 8: Nothing, 9: Crash +# branch r12, 0x802f70c0 # Time +# branch r12, 0x802f70e8 # Complete # branch r12, 0x802f70fc # Failure # branch r12, 0x802f7110 # Game! branch r12, 0x802f7120 # Exit function, shows nothing and plays no sound diff --git a/Online/Core/LGLExceededGameEnd.asm b/Online/Core/LGLExceededGameEnd.asm new file mode 100644 index 00000000..dbbcc8a0 --- /dev/null +++ b/Online/Core/LGLExceededGameEnd.asm @@ -0,0 +1,139 @@ +################################################################################ +# Address: 0x802f70c4 # HUD_DisplayEndingExclaimationGraphic +################################################################################ + +.include "Common/Common.s" +.include "Online/Online.s" + +.set REG_P1_LEDGE_GRABS, 28 +.set REG_P2_LEDGE_GRABS, 27 +.set REG_LGL_LOSER, 26 +.set REG_DISPLAY_MESSAGE_ID, 25 +.set REG_DO, 24 +.set REG_FILL_COLOR, 23 +.set REG_FIRST_STRING, 22 + +# This function's main goal is to overwrite the message displayed on an LGL timeout. Here are the options: +# 0: Time, 1: Sudden Death, 2: Success, 3: Ready, 4: GO!, 5: Game!, 6: Failure, 7: Complete, 8: Nothing, 9: Crash + +b CODE_START + +DATA_BLRL: +blrl +.set DO_SCALE, 0 +.float 0.7 +.set DO_POS_X, DO_SCALE + 4 +.float 0 +.set DO_POS_Y_WIN, DO_POS_X + 4 +.float 70 +.set DO_POS_Y_LOSS, DO_POS_Y_WIN + 4 +.float 60 +.set DO_STROKE_OFFSET, DO_POS_Y_LOSS + 4 +.float 1 +.set DO_COLOR_OUTLINE, DO_STROKE_OFFSET + 4 +.byte 0,0,0,255 +.set DO_COLOR_FILL_LOSS, DO_COLOR_OUTLINE + 4 +.byte 215,165,255,255 +.set DO_COLOR_FILL_WIN, DO_COLOR_FILL_LOSS + 4 +.byte 250,250,120,255 +.set DO_STRING_YOU, DO_COLOR_FILL_WIN + 4 +.string "You" +.set DO_STRING_OPP, DO_STRING_YOU + 4 +.string "Opponent" +.set DO_STRING, DO_STRING_OPP + 9 +.string "%s Exceeded Ledge Grab Limit of %d" +.align 2 + + +CODE_START: +backup + +# Store values of r4-r6 so we can restore on exit. They are args to the function that will be called. +# The other args, r3, r7, and r8 are about to be set so we don't need to worry about those +mr r31, r4 +mr r30, r5 +mr r29, r6 +li REG_DISPLAY_MESSAGE_ID, 0 + +# Grab data address +bl DATA_BLRL +mflr REG_DO + +# Ensure that this is an online match +getMinorMajor r3 +cmpwi r3, SCENE_ONLINE_IN_GAME +bne EXIT + +# Don't run this code for teams +lbz r3, OFST_R13_ONLINE_MODE(r13) +cmpwi r3, ONLINE_MODE_TEAMS +beq EXIT + +# Check to see if this is an LGL victory + +# Fetch ledge grab amounts +li r3, 0 +branchl r12, 0x80040af0 # PlayerBlock_GetCliffhangerStat +mr REG_P1_LEDGE_GRABS, r3 +li r3, 1 +branchl r12, 0x80040af0 # PlayerBlock_GetCliffhangerStat +mr REG_P2_LEDGE_GRABS, r3 + +# First handle condition where both players are over LGL +cmpwi REG_P1_LEDGE_GRABS, LGL_LIMIT +ble CHECK_LGL_LOSS +cmpwi REG_P2_LEDGE_GRABS, LGL_LIMIT +bgt EXIT # If we branch here both players have more than 45 so ignore LGL + +CHECK_LGL_LOSS: +cmpwi REG_P1_LEDGE_GRABS, LGL_LIMIT +li REG_LGL_LOSER, 0 +bgt SET_MODIFIED_MESSAGE # If P1 has more than 45 ledge grabs, P2 wins +cmpwi REG_P2_LEDGE_GRABS, LGL_LIMIT +li REG_LGL_LOSER, 1 +bgt SET_MODIFIED_MESSAGE # If P2 has more than 45 ledge grabs, P1 wins +b EXIT # If neither player has more than 45 ledge grabs, exit + +SET_MODIFIED_MESSAGE: +# Check if we won or lost via LGL +lwz r3, OFST_R13_ODB_ADDR(r13) # data buffer address +lbz r3, ODB_LOCAL_PLAYER_INDEX(r3) +cmpw r3, REG_LGL_LOSER # Compare local player index of winner +li REG_DISPLAY_MESSAGE_ID, 2 # Set message to "Success" if we won +addi REG_FILL_COLOR, REG_DO, DO_COLOR_FILL_WIN +addi REG_FIRST_STRING, REG_DO, DO_STRING_OPP +lfs f3, DO_POS_Y_WIN(REG_DO) +bne DISPLAY_LGL_MESSAGE +li REG_DISPLAY_MESSAGE_ID, 6 # Set message to "Failure" if we lost +addi REG_FILL_COLOR, REG_DO, DO_COLOR_FILL_LOSS +addi REG_FIRST_STRING, REG_DO, DO_STRING_YOU +lfs f3, DO_POS_Y_LOSS(REG_DO) + +DISPLAY_LGL_MESSAGE: +# Make game exit transition longer +load r3, 0x8046b6a0 # Some static match state struct +li r4, 0xFD # Default value for this is 0x6e +stb r4, 0x24D5(r3) # Overwrite the GAME! think max time to make it longer + +# Print text on screen indicating what happened +lwz r3, OFST_R13_ODB_ADDR(r13) # data buffer address +lwz r3, ODB_HUD_TEXT_STRUCT(r3) +mr r4, REG_FILL_COLOR +li r5, 1 +addi r6, REG_DO, DO_COLOR_OUTLINE # Outline Color +addi r7, REG_DO, DO_STRING # String +mr r8, REG_FIRST_STRING +li r9, LGL_LIMIT # LGL Limit +lfs f1, DO_SCALE(REG_DO) +lfs f2, DO_POS_X(REG_DO) +lfs f6, DO_STROKE_OFFSET(REG_DO) +branchl r12, FG_CreateSubtext + +EXIT: +# Restore r4-r6 +mr r4, r31 +mr r5, r30 +mr r6, r29 +mr r3, REG_DISPLAY_MESSAGE_ID # Use the message ID we set earlier. 0 if no LGL which is replaced codeline +restore +addi r7, r31, 0 # Line 802f70c0 may have been clobbered, set it again \ No newline at end of file diff --git a/Online/Online.s b/Online/Online.s index 185ab50a..adab30cf 100644 --- a/Online/Online.s +++ b/Online/Online.s @@ -41,6 +41,7 @@ .set MIN_DELAY_FRAMES, 1 .set MAX_DELAY_FRAMES, 15 .set ROLLBACK_MAX_FRAME_COUNT, 7 +.set LGL_LIMIT, 45 # Ledge grabs that exceed this number will result in a loss on timeout # I don't know exactly how long the local input buffer has to be but in very rare cases with a length # of ROLLBACK_MAX_FRAME_COUNT we could overflow into the negative indices: diff --git a/Online/Slippi Online Scene/main.asm b/Online/Slippi Online Scene/main.asm index a7e613be..0199dd72 100644 --- a/Online/Slippi Online Scene/main.asm +++ b/Online/Slippi Online Scene/main.asm @@ -607,13 +607,26 @@ bne VSSceneDecide_SkipRankedHandler # If connection is not active, just go back to CSS lbz r3, MSRB_CONNECTION_STATE(REG_MSRB_ADDR) cmpwi r3, MM_STATE_IDLE -bne VSSceneDecide_ConnectionActive +beq VSSceneDecide_Disconnected + +# I think I can access ODB values here since we are still in the VS scene +# If last match ended in a disconnect, return to CSS +lwz r4, OFST_R13_ODB_ADDR(r13) # ODB address +lbz r3, ODB_IS_DISCONNECT_STATE_DISPLAYED(r4) +cmpwi r3, 1 +beq VSSceneDecide_Disconnected + +b VSSceneDecide_ConnectionActive + +VSSceneDecide_Disconnected: # Report disconnect li r3, 1 bl FN_ReportSetCompletion -b VSSceneDecide_SkipRankedHandler -VSSceneDecide_ConnectionActive: +# We still trigger disconnection calls here because the previous game can end with disconnected message +# while the connection is still technically active +b VSSceneDecide_DisconnectAndReturnToCSS +VSSceneDecide_ConnectionActive: bl GamePrepData_BLRL mflr REG_GPD @@ -683,6 +696,7 @@ VSSceneDecide_RankedSetOver: li r3, 0 bl FN_ReportSetCompletion +VSSceneDecide_DisconnectAndReturnToCSS: # Disconnect from opponent # Prepare buffer for EXI transfer li r3, 1 @@ -1226,6 +1240,23 @@ beq SinglesDetermineWinner_HANDLE_COMPLETION b SinglesDetermineWinner_TIE SinglesDetermineWinner_HANDLE_TIMEOUT: +# Handle ledge grab limit +li r3, 0 +branchl r12, 0x80040af0 # PlayerBlock_GetCliffhangerStat +mr REG_TEMP_VAR, r3 +li r3, 1 +branchl r12, 0x80040af0 # PlayerBlock_GetCliffhangerStat +cmpwi REG_TEMP_VAR, LGL_LIMIT +ble SinglesDetermineWinner_CHECK_LGL_LOSS +cmpwi r3, LGL_LIMIT +bgt SinglesDetermineWinner_LGL_EXIT # If we branch here both players have more than 45 so ignore LGL +SinglesDetermineWinner_CHECK_LGL_LOSS: +cmpwi REG_TEMP_VAR, LGL_LIMIT +bgt SinglesDetermineWinner_P2_WIN # If P1 has more than 45 ledge grabs, P2 wins +cmpwi r3, LGL_LIMIT +bgt SinglesDetermineWinner_P1_WIN # If P2 has more than 45 ledge grabs, P1 wins +SinglesDetermineWinner_LGL_EXIT: + li r3, 0 branchl r12, 0x80033bd8 # PlayerBlock_LoadStocksLeft mr REG_TEMP_VAR, r3 @@ -1407,9 +1438,11 @@ beq GamePrepSceneDecide_ExecNormal # Here we have disconnected from opponent, go back to CSS -# I commented the below because the game setup scene itself already sends the communication -# li r3, 1 -# bl FN_ReportSetCompletion +# In theory this should have already been sent by the game setup scene but there's +# no harm in sending a duplicate and this covers our bases in the case of a poorly timed +# disconnect, such as maybe right before the game tries to load +li r3, 1 +bl FN_ReportSetCompletion # Go back to CSS load r4, 0x80479d30 diff --git a/Online/Static/SubtextFunctions.asm b/Online/Static/SubtextFunctions.asm index 0764c737..7d46212f 100644 --- a/Online/Static/SubtextFunctions.asm +++ b/Online/Static/SubtextFunctions.asm @@ -11,11 +11,10 @@ # r6 = outline color pointer # r7... = string pointers -# f1 = scale size x -# f2 = scale size y -# f3 = x pos -# f4 = y pos -# f5 = inner text y-scale +# f1 = scale size +# f2 = x pos +# f3 = y pos +# f5 = inner text y-scale (unused?) # f6 = outline offset/size ################################################################################ # Output: @@ -42,7 +41,7 @@ .set REG_X, REG_SCALE-1 .set REG_Y, REG_X-1 .set REG_Z, REG_Y-1 -.set REG_OUTLINE_SIZE, REG_Z-1 +.set REG_OUTLINE_SIZE, REG_Z-1 # looks unused? .set REG_OUTLINE_OFFSET, REG_OUTLINE_SIZE-1 # outlines offsets to create size .set REG_LOOP_INDEX, 15 diff --git a/Output/InjectionLists/list_netplay.json b/Output/InjectionLists/list_netplay.json index 71b9f580..a914113e 100644 --- a/Output/InjectionLists/list_netplay.json +++ b/Output/InjectionLists/list_netplay.json @@ -637,6 +637,13 @@ "Annotation": "Online/Core/InitPause.asm", "Tags": "" }, + { + "InjectionAddress": "802F70C4", + "Name": "Required: Slippi Online", + "Codetype": "Auto", + "Annotation": "Online/Core/LGLExceededGameEnd.asm", + "Tags": "" + }, { "InjectionAddress": "801A5014", "Name": "Required: Slippi Online", diff --git a/Playback/Core/RestoreGameFrame.asm b/Playback/Core/RestoreGameFrame.asm index 07544da7..268a4679 100644 --- a/Playback/Core/RestoreGameFrame.asm +++ b/Playback/Core/RestoreGameFrame.asm @@ -162,6 +162,10 @@ SKIP_RESYNC: stb r3, 0x2(r20) #store raw x analog lbz r3, AnalogRawInputY(PlayerBackup) stb r3, 0x3(r20) #store raw y analog + lbz r3, CStickRawInputX(PlayerBackup) + stb r3, 0x4(r20) #store raw x cstick + lbz r3, CStickRawInputY(PlayerBackup) + stb r3, 0x5(r20) #store raw y cstick # If we do not have resync logic enabled, don't try to restore percentage lbz r3, PDB_SHOULD_RESYNC(REG_PDB_ADDR) diff --git a/Playback/Playback.s b/Playback/Playback.s index f404e9fa..b2daaf58 100644 --- a/Playback/Playback.s +++ b/Playback/Playback.s @@ -86,7 +86,7 @@ # gameframe .set GameFrame_Start, InitialRNG_Start + InitialRNG_Length # per player offsets - .set PlayerDataLength,0x32 + .set PlayerDataLength,0x34 .set RNGSeed,0x00 .set AnalogX,0x04 .set AnalogY,0x08 @@ -101,6 +101,8 @@ .set AnalogRawInputX,0x2C .set AnalogRawInputY,0x2D .set Percentage,0x2E + .set CStickRawInputX,0x32 + .set CStickRawInputY,0x33 .set GameFrame_Length, PlayerDataLength * 8 diff --git a/Recording/Recording.s b/Recording/Recording.s index d8bbac87..30e80e19 100644 --- a/Recording/Recording.s +++ b/Recording/Recording.s @@ -31,7 +31,7 @@ .set MESSAGE_DESCRIPTIONS_PAYLOAD_LENGTH, 3 * (COMMAND_COUNT - 1) + 1 # byte count .set GAME_INFO_PAYLOAD_LENGTH, 760 # byte count .set GAME_FRAME_START_PAYLOAD_LENGTH, 12 #byte count -.set GAME_PRE_FRAME_PAYLOAD_LENGTH, 64 # byte count +.set GAME_PRE_FRAME_PAYLOAD_LENGTH, 66 # byte count .set GAME_POST_FRAME_PAYLOAD_LENGTH, 84 # byte count .set GAME_ITEM_INFO_PAYLOAD_LENGTH, 44 # byte count .set GAME_FRAME_BOOKEND_PAYLOAD_LENGTH, 8 # byte count @@ -67,8 +67,8 @@ # build version number. Each byte is one digit # any change in command data should result in a minor version change -# current version: 3.16.0 -.set CURRENT_VERSION,0x031000FF +# current version: 3.17.0 +.set CURRENT_VERSION,0x031100FF ################################################################################ # Static Function Locations diff --git a/Recording/SendGamePreFrame.asm b/Recording/SendGamePreFrame.asm index 12585f73..282d1fd0 100644 --- a/Recording/SendGamePreFrame.asm +++ b/Recording/SendGamePreFrame.asm @@ -111,6 +111,10 @@ CONTINUE_RAW_X: stb r3, 0x3B(REG_Buffer) lbz r3, 0x3(r4) #load raw y analog stb r3, 0x40(REG_Buffer) + lbz r3, 0x4(r4) #load raw x c-stick + stb r3, 0x41(REG_Buffer) + lbz r3, 0x5(r4) #load raw y c-stick + stb r3, 0x42(REG_Buffer) # Send player's percent lwz r3,0x1830(r31)