mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-10 01:59:02 +00:00
Merge branch 'dolphin-mpn' into master
This commit is contained in:
commit
f3669dbbd4
903 changed files with 4243 additions and 386 deletions
|
@ -99,7 +99,7 @@
|
|||
#define SHADERCACHE_LEGACY_DIR "ShaderCache"
|
||||
|
||||
// The theme directory used by default
|
||||
#define DEFAULT_THEME_DIR "Clean"
|
||||
#define DEFAULT_THEME_DIR "Mario Party Netplay"
|
||||
|
||||
// Filenames
|
||||
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
||||
|
|
318
Source/Core/Common/GLideN64.custom.ini
Normal file
318
Source/Core/Common/GLideN64.custom.ini
Normal file
|
@ -0,0 +1,318 @@
|
|||
; Custom game settings
|
||||
[General]
|
||||
version=13
|
||||
|
||||
[TWINE]
|
||||
Good_Name=007 - The World Is Not Enough (E)(U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[40%20WINKS]
|
||||
Good_Name=40 Winks (E) (M3) (Prototype)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
|
||||
[BIOFREAKS]
|
||||
Good_Name=Bio F.R.E.A.K.S. (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[BioHazard%20II]
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[52150A67]
|
||||
Good_Name=Bokujou Monogatari 2 (J)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[67000C2B]
|
||||
Good_Name=Eikou no Saint Andrews (J)
|
||||
frameBufferEmulation\forceDepthBufferClear=1
|
||||
|
||||
[CAL%20SPEED]
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
|
||||
[CASTLEVANIA2]
|
||||
Good_Name=Castlevania - Legacy Of Darkness (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[DMPJ]
|
||||
Good_Name=Mario Artist Paint Studio (J) (64DD)
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
frameBufferEmulation\nativeResFactor=1
|
||||
generalEmulation\rdramImageDitheringMode=0
|
||||
|
||||
[DMTJ]
|
||||
Good_Name=Mario Artist Talent Studio (J) (64DD)
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[DINO%20PLANET]
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[DONKEY%20KONG%2064]
|
||||
Good_Name=Donkey Kong 64 (E)(J)(U)
|
||||
frameBufferEmulation\copyDepthToRDRAM=1
|
||||
frameBufferEmulation\N64DepthCompare=0
|
||||
|
||||
[DR.MARIO%2064]
|
||||
Good_Name=Dr. Mario 64 (U)
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
|
||||
[EXTREME_G]
|
||||
Good_Name=Extreme-G (E)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[EXTREME-G]
|
||||
Good_Name=Extreme-G (J)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[EXTREMEG]
|
||||
Good_Name=Extreme-G (U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[EXTREME%20G%202]
|
||||
Good_Name=Extreme-G XG2 (E) (U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[208E05CD]
|
||||
Good_Name=Extreme-G XG2 (J)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[F1%20POLE%20POSITION%2064]
|
||||
Good_Name=F-1 Pole Position 64 (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[FLAPPYBIRD64]
|
||||
Good_Name=FlappyBird64
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
|
||||
[GOEMON2%20DERODERO]
|
||||
Good_Name=Ganbare Goemon - Dero Dero Douchuu Obake Tenkomori (J)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
|
||||
[GOEMONS%20GREAT%20ADV]
|
||||
Good_Name=Goemons Great Adventure (U)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
|
||||
[HARVESTMOON64]
|
||||
Good_Name=Harvest Moon 64 (U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[5CFA0A2E]
|
||||
Good_Name=Heiwa Pachinko World 64 (J)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[HEXEN]
|
||||
Good_Name=Hexen (E)(F)(G)(J)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[HUMAN%20GRAND%20PRIX]
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[I%20S%20S%2064]
|
||||
Good_Name=International Superstar Soccer 64 (E) (U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[JET%20FORCE%20GEMINI]
|
||||
Good_Name=Jet Force Gemini (E)(U)
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[J%20F%20G%20DISPLAY]
|
||||
; See Jet Force Gemini for notes
|
||||
Good_Name=Jet Force Gemini Kiosk Demo (U)
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[J%20WORLD%20SOCCER3]
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[301E07CC]
|
||||
Good_Name=Mahjong Master (J)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[DMGJ]
|
||||
Good_Name=Mario Artist Polygon Studio (J)
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[KEN%20GRIFFEY%20SLUGFEST]
|
||||
Good_Name=Ken Griffey Jr.'s Slugfest
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
|
||||
[KIRBY64]
|
||||
Good_Name=Kirby 64 - The Crystal Shards (E)(J)(U)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
|
||||
[MARIOGOLF64]
|
||||
Good_Name=Mario Golf (E)(J)(U)
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[MARIOKART64]
|
||||
Good_Name=Mario Kart 64 (E)(J)(U)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
graphics2D\enableTexCoordBounds=1
|
||||
|
||||
[MARIO%20STORY]
|
||||
Good_Name=Mario Story (J)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[MEGA%20MAN%2064]
|
||||
Good_Name=Mega Man 64 (U)
|
||||
graphics2D\correctTexrectCoords=2
|
||||
|
||||
[MEGAMAN%2064]
|
||||
Good_Name=Mega Man 64 (Proto)
|
||||
graphics2D\correctTexrectCoords=2
|
||||
|
||||
[MLB%20FEATURING%20K%20G%20JR]
|
||||
Good_Name=Major League Baseball Featuring Ken Griffey Jr.
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
|
||||
[MYSTICAL%20NINJA2%20SG]
|
||||
Good_Name=Mystical Ninja 2 Starring Goemon (E)
|
||||
graphics2D\enableNativeResTexrects=1
|
||||
|
||||
[NASCAR%202000]
|
||||
Good_Name=NASCAR 2000 (U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[NASCAR%2099]
|
||||
Good_Name=NASCAR 99 (U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[NUD-DMPJ-JPN_convert]
|
||||
Good_Name=Mario Paint Studio (cart hack)
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
|
||||
[NUD-DMTJ-JPN_convert]
|
||||
Good_Name=Mario Artist Talent Studio (cart hack)
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[OGREBATTLE64]
|
||||
Good_Name=Ogre Battle 64 - Person of Lordly Caliber (U)
|
||||
graphics2D\enableTexCoordBounds=1
|
||||
|
||||
[OLYMPIC%20HOCKEY]
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
|
||||
[PAPER%20MARIO]
|
||||
Good_Name=Paper Mario (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
graphics2D\enableTexCoordBounds=1
|
||||
|
||||
[PENNY%20RACERS]
|
||||
Good_Name=Penny Racers (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
|
||||
[PERFECT%20STRIKER]
|
||||
Good_Name=Jikkyou J.League Perfect Striker (J)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[POKEMON%20SNAP]
|
||||
Good_Name=Pokemon Snap (U)
|
||||
generalEmulation\rdramImageDitheringMode=1
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
|
||||
[POKEMON%20STADIUM]
|
||||
Good_Name=Pokemon Stadium (U)
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[POKEMON%20STADIUM%202]
|
||||
Good_Name=Pokemon Stadium 2 (E)(F)(G)(I)(J)(S)(U)
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[POKEMON%20STADIUM%20G%26S]
|
||||
Good_Name=Pokemon Stadium Kin Gin (J)
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[PUZZLE%20LEAGUE%20N64]
|
||||
Good_Name=Pokemon Puzzle League (E)(F)(G)(U)
|
||||
texture\enableHalosRemoval=1
|
||||
|
||||
[RAT%20ATTACK]
|
||||
Good_Name=Rat Attack
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
|
||||
[RESIDENT%20EVIL%20II]
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[ROCKMAN%20DASH]
|
||||
Good_Name=Rockman Dash - Hagane no Boukenshin (J)
|
||||
graphics2D\correctTexrectCoords=2
|
||||
|
||||
[RUSH%202]
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
graphics2D\correctTexrectCoords=2
|
||||
|
||||
[SAN%20FRANCISCO%20RUSH]
|
||||
Good_Name=San Francisco Rush Extreme Racing (U)
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
graphics2D\enableNativeResTexrects=2
|
||||
|
||||
[S.F.RUSH]
|
||||
Good_Name=San Francisco Rush Extreme Racing (E)
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
graphics2D\enableNativeResTexrects=2
|
||||
|
||||
[S.F.%20RUSH]
|
||||
Good_Name=San Francisco Rush Extreme Racing (U)
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
graphics2D\enableNativeResTexrects=2
|
||||
|
||||
[SHADOWMAN]
|
||||
Good_Name=Shadow Man (B)(E)(F)(G)(U)
|
||||
frameBufferEmulation\copyDepthToRDRAM=0
|
||||
|
||||
[SPACE%20INVADERS]
|
||||
Good_Name=Space Invaders (U)
|
||||
frameBufferEmulation\copyToRDRAM=0
|
||||
|
||||
[STAR%20TWINS]
|
||||
; See Jet Force Gemini for notes
|
||||
Good_Name=Star Twins (J)
|
||||
frameBufferEmulation\fbInfoDisabled=0
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
|
||||
[TEST]
|
||||
Good_Name=Mario Artist Paint Studio (J) (1999-02-11 Prototype) (64DD)
|
||||
frameBufferEmulation\copyAuxToRDRAM=1
|
||||
frameBufferEmulation\copyFromRDRAM=1
|
||||
generalEmulation\rdramImageDitheringMode=0
|
||||
|
||||
[TETRISPHERE]
|
||||
Good_Name=Tetrisphere (U)
|
||||
generalEmulation\correctTexrectCoords=2
|
||||
|
||||
[TIGGER%27S%20HONEY%20HUNT]
|
||||
Good_Name=Tiggers Honey Hunt (E)(U)
|
||||
frameBufferEmulation\N64DepthCompare=1
|
||||
|
||||
[TONIC%20TROUBLE]
|
||||
Good_Name=Tonic Trouble (E)(U)
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[TG%20RALLY%202]
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[TOP%20GEAR%20RALLY%202]
|
||||
frameBufferEmulation\copyToRDRAM=1
|
||||
|
||||
[TUROK_DINOSAUR_HUNTE]
|
||||
Good_Name=Turok - Dinosaur Hunter (E)(G)(U)(J)
|
||||
frameBufferEmulation\copyDepthToRDRAM=1
|
||||
|
||||
[W.G.%203DHOCKEY]
|
||||
frameBufferEmulation\bufferSwapMode=1
|
||||
|
||||
[MARIOPARTY3]
|
||||
frameBufferEmulation\N64DepthCompare=1
|
|
@ -19,16 +19,8 @@ namespace Common
|
|||
|
||||
const std::string& GetScmRevStr()
|
||||
{
|
||||
static const std::string scm_rev_str = "Dolphin "
|
||||
#if !SCM_IS_MASTER
|
||||
"[" SCM_BRANCH_STR "] "
|
||||
#endif
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
BUILD_TYPE_STR SCM_DESC_STR "-ICC";
|
||||
#else
|
||||
BUILD_TYPE_STR SCM_DESC_STR;
|
||||
#endif
|
||||
#define MPN_REV_STR "02/27/2022"
|
||||
static const std::string scm_rev_str = "Dolphin MPN";
|
||||
return scm_rev_str;
|
||||
}
|
||||
|
||||
|
@ -64,12 +56,13 @@ const std::string& GetScmUpdateTrackStr()
|
|||
|
||||
const std::string& GetNetplayDolphinVer()
|
||||
{
|
||||
#define LABEL "MPN"
|
||||
#ifdef _WIN32
|
||||
static const std::string netplay_dolphin_ver = SCM_DESC_STR " Win";
|
||||
static const std::string netplay_dolphin_ver = LABEL " Win";
|
||||
#elif __APPLE__
|
||||
static const std::string netplay_dolphin_ver = SCM_DESC_STR " Mac";
|
||||
static const std::string netplay_dolphin_ver = LABEL " Mac";
|
||||
#else
|
||||
static const std::string netplay_dolphin_ver = SCM_DESC_STR " Lin";
|
||||
static const std::string netplay_dolphin_ver = LABEL " Lin";
|
||||
#endif
|
||||
return netplay_dolphin_ver;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ var branch = GetFirstStdOutLine(gitexe + cmd_branch);
|
|||
var isStable = +("master" == branch || "stable" == branch);
|
||||
|
||||
// Get environment information.
|
||||
var distributor = wshShell.ExpandEnvironmentStrings("%DOLPHIN_DISTRIBUTOR%");
|
||||
var distributor = "Mario Party Netplay";
|
||||
if (distributor == "%DOLPHIN_DISTRIBUTOR%") distributor = "None";
|
||||
var default_update_track = wshShell.ExpandEnvironmentStrings("%DOLPHIN_DEFAULT_UPDATE_TRACK%");
|
||||
if (default_update_track == "%DOLPHIN_DEFAULT_UPDATE_TRACK%") default_update_track = "";
|
||||
|
|
|
@ -429,6 +429,10 @@ add_library(core
|
|||
IOS/WFS/WFSSRV.h
|
||||
LibusbUtils.cpp
|
||||
LibusbUtils.h
|
||||
MarioPartyNetplay/Discord.cpp
|
||||
MarioPartyNetplay/Discord.h
|
||||
MarioPartyNetplay/Gamestate.cpp
|
||||
MarioPartyNetplay/Gamestate.h
|
||||
MemTools.cpp
|
||||
MemTools.h
|
||||
Movie.cpp
|
||||
|
|
|
@ -44,7 +44,7 @@ const Info<bool> GFX_OVERLAY_SCISSOR_STATS{{System::GFX, "Settings", "OverlaySci
|
|||
const Info<bool> GFX_DUMP_TEXTURES{{System::GFX, "Settings", "DumpTextures"}, false};
|
||||
const Info<bool> GFX_DUMP_MIP_TEXTURES{{System::GFX, "Settings", "DumpMipTextures"}, true};
|
||||
const Info<bool> GFX_DUMP_BASE_TEXTURES{{System::GFX, "Settings", "DumpBaseTextures"}, true};
|
||||
const Info<bool> GFX_HIRES_TEXTURES{{System::GFX, "Settings", "HiresTextures"}, false};
|
||||
const Info<bool> GFX_HIRES_TEXTURES{{System::GFX, "Settings", "HiresTextures"}, true};
|
||||
const Info<bool> GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresTextures"}, false};
|
||||
const Info<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false};
|
||||
const Info<bool> GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false};
|
||||
|
|
|
@ -44,7 +44,7 @@ const Info<int> MAIN_TIMING_VARIANCE{{System::Main, "Core", "TimingVariance"}, 4
|
|||
const Info<bool> MAIN_CPU_THREAD{{System::Main, "Core", "CPUThread"}, true};
|
||||
const Info<bool> MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkipIdle"}, true};
|
||||
const Info<std::string> MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""};
|
||||
const Info<bool> MAIN_ENABLE_CHEATS{{System::Main, "Core", "EnableCheats"}, false};
|
||||
const Info<bool> MAIN_ENABLE_CHEATS{{System::Main, "Core", "EnableCheats"}, true};
|
||||
const Info<int> MAIN_GC_LANGUAGE{{System::Main, "Core", "SelectedLanguage"}, 0};
|
||||
const Info<bool> MAIN_OVERRIDE_REGION_SETTINGS{{System::Main, "Core", "OverrideRegionSettings"},
|
||||
false};
|
||||
|
|
|
@ -21,7 +21,7 @@ const Info<std::string> NETPLAY_TRAVERSAL_CHOICE{{System::Main, "NetPlay", "Trav
|
|||
const Info<std::string> NETPLAY_INDEX_URL{{System::Main, "NetPlay", "IndexServer"},
|
||||
"https://lobby.dolphin-emu.org"};
|
||||
|
||||
const Info<bool> NETPLAY_USE_INDEX{{System::Main, "NetPlay", "UseIndex"}, false};
|
||||
const Info<bool> NETPLAY_USE_INDEX{{System::Main, "NetPlay", "UseIndex"}, true};
|
||||
const Info<std::string> NETPLAY_INDEX_NAME{{System::Main, "NetPlay", "IndexName"}, ""};
|
||||
const Info<std::string> NETPLAY_INDEX_REGION{{System::Main, "NetPlay", "IndexRegion"}, ""};
|
||||
const Info<std::string> NETPLAY_INDEX_PASSWORD{{System::Main, "NetPlay", "IndexPassword"}, ""};
|
||||
|
@ -33,7 +33,7 @@ const Info<std::string> NETPLAY_ADDRESS{{System::Main, "NetPlay", "Address"}, "1
|
|||
const Info<u16> NETPLAY_CONNECT_PORT{{System::Main, "NetPlay", "ConnectPort"}, DEFAULT_LISTEN_PORT};
|
||||
const Info<u16> NETPLAY_LISTEN_PORT{{System::Main, "NetPlay", "ListenPort"}, DEFAULT_LISTEN_PORT};
|
||||
|
||||
const Info<std::string> NETPLAY_NICKNAME{{System::Main, "NetPlay", "Nickname"}, "Player"};
|
||||
const Info<std::string> NETPLAY_NICKNAME{{System::Main, "NetPlay", "Nickname"}, "MPN Player"};
|
||||
const Info<bool> NETPLAY_USE_UPNP{{System::Main, "NetPlay", "UseUPNP"}, false};
|
||||
|
||||
const Info<bool> NETPLAY_ENABLE_QOS{{System::Main, "NetPlay", "EnableQoS"}, true};
|
||||
|
@ -48,6 +48,7 @@ const Info<u32> NETPLAY_CLIENT_BUFFER_SIZE{{System::Main, "NetPlay", "BufferSize
|
|||
const Info<bool> NETPLAY_SAVEDATA_LOAD{{System::Main, "NetPlay", "SyncSaves"}, true};
|
||||
const Info<bool> NETPLAY_SAVEDATA_WRITE{{System::Main, "NetPlay", "WriteSaveData"}, true};
|
||||
const Info<bool> NETPLAY_SAVEDATA_SYNC_ALL_WII{{System::Main, "NetPlay", "SyncAllWiiSaves"}, false};
|
||||
|
||||
const Info<bool> NETPLAY_SYNC_CODES{{System::Main, "NetPlay", "SyncCodes"}, true};
|
||||
const Info<bool> NETPLAY_RECORD_INPUTS{{System::Main, "NetPlay", "RecordInputs"}, false};
|
||||
const Info<bool> NETPLAY_STRICT_SETTINGS_SYNC{{System::Main, "NetPlay", "StrictSettingsSync"},
|
||||
|
|
28
Source/Core/Core/MarioPartyNetplay/8Player.h
Normal file
28
Source/Core/Core/MarioPartyNetplay/8Player.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef MPN_8PLAYER_H
|
||||
#define MPN_8PLAYER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
|
||||
#define MPN_TEAM_ACTIVE (1 << 0)
|
||||
#define MPN_TEAM_L_READY (1 << 1)
|
||||
#define MPN_TEAM_R_READY (1 << 2)
|
||||
|
||||
typedef struct mpn_team_t
|
||||
{
|
||||
uint8_t Flags;
|
||||
GCPadStatus LeftPad;
|
||||
GCPadStatus RightPad;
|
||||
} mpn_team_t;
|
||||
|
||||
bool mpn_8p_active ();
|
||||
GCPadStatus mpn_8p_combined_input (uint8_t Port);
|
||||
void mpn_8p_free ();
|
||||
void mpn_8p_init ();
|
||||
bool mpn_8p_port_ready (uint8_t Port);
|
||||
void mpn_8p_push_back_input (GCPadStatus* Pad, uint8_t Port);
|
||||
void mpn_8p_set_port_active (uint8_t Port, bool Active);
|
||||
|
||||
extern mpn_team_t* Teams;
|
||||
|
||||
#endif
|
44
Source/Core/Core/MarioPartyNetplay/Discord.cpp
Normal file
44
Source/Core/Core/MarioPartyNetplay/Discord.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "Discord.h"
|
||||
#include "UICommon/DiscordPresence.h"
|
||||
#include "Core/Config/NetplaySettings.h"
|
||||
|
||||
bool mpn_update_discord()
|
||||
{
|
||||
if (!Memory::IsInitialized())
|
||||
return false;
|
||||
|
||||
DiscordRichPresence RichPresence = {};
|
||||
|
||||
RichPresence.largeImageKey = CurrentState.Image ? CurrentState.Image : "default";
|
||||
RichPresence.largeImageText = CurrentState.Title ? CurrentState.Title : "In-Game";
|
||||
|
||||
if (CurrentState.Scenes != NULL && CurrentState.Scene != NULL)
|
||||
RichPresence.state = CurrentState.Scene->Name.c_str();
|
||||
|
||||
if (CurrentState.Addresses != NULL)
|
||||
{
|
||||
char Details[128] = "";
|
||||
|
||||
if (CurrentState.Boards && CurrentState.Board)
|
||||
{
|
||||
snprintf(Details, sizeof(Details), "Players: 1/4 Turn: %d/%d",
|
||||
mpn_read_value(CurrentState.Addresses->CurrentTurn, 1),
|
||||
mpn_read_value(CurrentState.Addresses->TotalTurns, 1));
|
||||
|
||||
RichPresence.smallImageKey = CurrentState.Board->Icon.c_str();
|
||||
RichPresence.smallImageText = CurrentState.Board->Name.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(Details, sizeof(Details), "Players: 1/4");
|
||||
RichPresence.smallImageKey = "";
|
||||
RichPresence.smallImageText = "";
|
||||
}
|
||||
RichPresence.details = Details;
|
||||
}
|
||||
|
||||
RichPresence.startTimestamp = std::time(nullptr);
|
||||
Discord_UpdatePresence(&RichPresence);
|
||||
|
||||
return true;
|
||||
}
|
4
Source/Core/Core/MarioPartyNetplay/Discord.h
Normal file
4
Source/Core/Core/MarioPartyNetplay/Discord.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include <discord_rpc.h>
|
||||
#include "Gamestate.h"
|
||||
|
||||
bool mpn_update_discord();
|
194
Source/Core/Core/MarioPartyNetplay/Gamestate.cpp
Normal file
194
Source/Core/Core/MarioPartyNetplay/Gamestate.cpp
Normal file
|
@ -0,0 +1,194 @@
|
|||
#include "Gamestate.h"
|
||||
|
||||
mpn_state_t CurrentState;
|
||||
|
||||
bool mpn_init_state()
|
||||
{
|
||||
if (!Memory::IsInitialized())
|
||||
return false;
|
||||
|
||||
switch (mpn_read_value(0x00000000, 4))
|
||||
{
|
||||
case MPN_GAMEID_MP4:
|
||||
CurrentState.Addresses = &MP4_ADDRESSES;
|
||||
CurrentState.Boards = MP4_BOARDS;
|
||||
CurrentState.Image = "box-mp4";
|
||||
CurrentState.IsMarioParty = true;
|
||||
CurrentState.Scenes = MP4_GAMESTATES;
|
||||
CurrentState.Title = "Mario Party 4";
|
||||
break;
|
||||
case MPN_GAMEID_MP5:
|
||||
CurrentState.Addresses = &MP5_ADDRESSES;
|
||||
CurrentState.Boards = MP5_BOARDS;
|
||||
CurrentState.Image = "box-mp5";
|
||||
CurrentState.IsMarioParty = true;
|
||||
CurrentState.Scenes = MP5_GAMESTATES;
|
||||
CurrentState.Title = "Mario Party 5";
|
||||
break;
|
||||
case MPN_GAMEID_MP6:
|
||||
CurrentState.Addresses = &MP6_ADDRESSES;
|
||||
CurrentState.Boards = MP6_BOARDS;
|
||||
CurrentState.Image = "box-mp6";
|
||||
CurrentState.IsMarioParty = true;
|
||||
CurrentState.Scenes = MP6_GAMESTATES;
|
||||
CurrentState.Title = "Mario Party 6";
|
||||
break;
|
||||
case MPN_GAMEID_MP7:
|
||||
CurrentState.Addresses = &MP7_ADDRESSES;
|
||||
CurrentState.Boards = MP7_BOARDS;
|
||||
CurrentState.Image = "box-mp7";
|
||||
CurrentState.IsMarioParty = true;
|
||||
CurrentState.Scenes = MP7_GAMESTATES;
|
||||
CurrentState.Title = "Mario Party 7";
|
||||
break;
|
||||
case MPN_GAMEID_MP8:
|
||||
CurrentState.Addresses = &MP8_ADDRESSES;
|
||||
CurrentState.Boards = NULL;
|
||||
CurrentState.Image = "box-mp8";
|
||||
CurrentState.IsMarioParty = true;
|
||||
CurrentState.Scenes = MP8_GAMESTATES;
|
||||
CurrentState.Title = "Mario Party 8";
|
||||
break;
|
||||
case MPN_GAMEID_MP9: /* TODO */
|
||||
default:
|
||||
CurrentState.Addresses = NULL;
|
||||
CurrentState.Boards = NULL;
|
||||
CurrentState.Image = "box-mp9";
|
||||
CurrentState.IsMarioParty = false;
|
||||
CurrentState.Scenes = NULL;
|
||||
}
|
||||
|
||||
return CurrentState.Scenes != NULL;
|
||||
}
|
||||
|
||||
bool mpn_update_board()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (CurrentState.Boards == NULL)
|
||||
CurrentState.Board = NULL;
|
||||
else if (CurrentState.CurrentSceneId != CurrentState.PreviousSceneId)
|
||||
{
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
/* Unknown scene ID */
|
||||
if (CurrentState.Boards[i].SceneId == NONE)
|
||||
break;
|
||||
if (CurrentState.Boards[i].SceneId == CurrentState.CurrentSceneId)
|
||||
{
|
||||
CurrentState.Board = &CurrentState.Boards[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t mpn_get_needs(uint16_t StateId, bool IsSceneId)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
if (CurrentState.Scenes == NULL)
|
||||
return MPN_NEEDS_NOTHING;
|
||||
else if (CurrentState.CurrentSceneId != CurrentState.PreviousSceneId)
|
||||
{
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
/* Unknown scene ID */
|
||||
if (CurrentState.Scenes[i].SceneId == NONE)
|
||||
return MPN_NEEDS_NOTHING;
|
||||
|
||||
/* Scene ID found in array */
|
||||
if ((IsSceneId && StateId == CurrentState.Scenes[i].SceneId) ||
|
||||
(StateId == CurrentState.Scenes[i].MiniGameId))
|
||||
return CurrentState.Scenes[i].Needs;
|
||||
}
|
||||
}
|
||||
|
||||
return MPN_NEEDS_NOTHING;
|
||||
}
|
||||
|
||||
void mpn_push_osd_message(const std::string& Message)
|
||||
{
|
||||
#ifdef MPN_USE_OSD
|
||||
OSD::AddMessage(Message, OSD::Duration::SHORT, MPN_OSD_COLOR);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mpn_update_state()
|
||||
{
|
||||
if (CurrentState.Scenes == NULL && !mpn_init_state())
|
||||
return false;
|
||||
if (!Memory::IsInitialized())
|
||||
return false;
|
||||
|
||||
CurrentState.PreviousSceneId = CurrentState.CurrentSceneId;
|
||||
CurrentState.CurrentSceneId = mpn_read_value(CurrentState.Addresses->SceneIdAddress, 2);
|
||||
|
||||
for (uint16_t i = 0;; i++)
|
||||
{
|
||||
if (CurrentState.Scenes[i].SceneId == NONE)
|
||||
break;
|
||||
if (CurrentState.CurrentSceneId == CurrentState.Scenes[i].SceneId)
|
||||
{
|
||||
CurrentState.Scene = &CurrentState.Scenes[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define OSD_PUSH(a) mpn_push_osd_message("Adjusting #a for " + CurrentState.Scene->Name);
|
||||
void mpn_per_frame()
|
||||
{
|
||||
uint8_t Needs = 0;
|
||||
|
||||
if (!mpn_update_state() || CurrentState.PreviousSceneId == CurrentState.CurrentSceneId)
|
||||
return;
|
||||
|
||||
mpn_update_board();
|
||||
mpn_update_discord();
|
||||
|
||||
Needs = mpn_get_needs(mpn_read_value(CurrentState.Addresses->SceneIdAddress, 2), true);
|
||||
|
||||
if (Needs != MPN_NEEDS_NOTHING)
|
||||
{
|
||||
if (Needs & MPN_NEEDS_SAFE_TEX_CACHE)
|
||||
{
|
||||
OSD_PUSH(GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES)
|
||||
Config::SetCurrent(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES, 0);
|
||||
}
|
||||
else
|
||||
Config::SetCurrent(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES, 128);
|
||||
|
||||
if (Needs & MPN_NEEDS_NATIVE_RES)
|
||||
{
|
||||
OSD_PUSH(GFX_EFB_SCALE)
|
||||
Config::SetCurrent(Config::GFX_EFB_SCALE, 1);
|
||||
}
|
||||
else
|
||||
Config::SetCurrent(Config::GFX_EFB_SCALE, Config::GetBase(Config::GFX_EFB_SCALE));
|
||||
|
||||
if (Needs & MPN_NEEDS_EFB_TO_TEXTURE)
|
||||
{
|
||||
OSD_PUSH(GFX_HACK_SKIP_EFB_COPY_TO_RAM)
|
||||
Config::SetCurrent(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, false);
|
||||
}
|
||||
else
|
||||
Config::SetCurrent(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, true);
|
||||
|
||||
UpdateActiveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mpn_read_value(uint32_t Address, uint8_t Size)
|
||||
{
|
||||
uint32_t Value = 0;
|
||||
|
||||
for (int8_t i = 0; i < Size; i++)
|
||||
Value += Memory::m_pRAM[Address + i] * pow(256, Size - i - 1);
|
||||
|
||||
return Value;
|
||||
}
|
684
Source/Core/Core/MarioPartyNetplay/Gamestate.h
Normal file
684
Source/Core/Core/MarioPartyNetplay/Gamestate.h
Normal file
|
@ -0,0 +1,684 @@
|
|||
#ifndef MPN_GAMESTATE_H
|
||||
#define MPN_GAMESTATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
#define MPN_GAMEID_MP4 0x474D5045
|
||||
#define MPN_GAMEID_MP5 0x47503545
|
||||
#define MPN_GAMEID_MP6 0x47503645
|
||||
#define MPN_GAMEID_MP7 0x47503745
|
||||
#define MPN_GAMEID_MP8 0x524D3845
|
||||
#define MPN_GAMEID_MP9 0x53535145
|
||||
|
||||
#define MPN_NEEDS_SAFE_TEX_CACHE (1 << 0)
|
||||
#define MPN_NEEDS_NATIVE_RES (1 << 1)
|
||||
#define MPN_NEEDS_EFB_TO_TEXTURE (1 << 2)
|
||||
#define MPN_NEEDS_SIDEWAYS_WIIMOTE (1 << 3)
|
||||
#define MPN_NEEDS_NOTHING 0xFF
|
||||
#define NONE -1
|
||||
|
||||
#undef MPN_USE_LEADERBOARDS
|
||||
#define MPN_USE_OSD
|
||||
|
||||
#include "Discord.h"
|
||||
|
||||
#ifdef MPN_USE_LEADERBOARDS
|
||||
#include "Core/MarioPartyNetplay/Leaderboards.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPN_USE_OSD
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#define MPN_OSD_COLOR 0xFF4A4A94
|
||||
#endif
|
||||
|
||||
typedef struct mpn_scene_t
|
||||
{
|
||||
int16_t MiniGameId;
|
||||
int16_t SceneId;
|
||||
std::string Name;
|
||||
uint8_t Needs;
|
||||
} mpn_scene_t;
|
||||
|
||||
typedef struct mpn_addresses_t
|
||||
{
|
||||
/*
|
||||
uint32_t BlueSpaces;
|
||||
uint32_t RedSpaces;
|
||||
uint32_t HappeningSpaces;
|
||||
uint32_t ChanceSpaces;
|
||||
uint32_t BowserSpaces;
|
||||
uint32_t BattleSpaces;
|
||||
uint32_t ItemSpaces;
|
||||
uint32_t SpringSpaces;
|
||||
*/
|
||||
uint32_t CurrentTurn;
|
||||
uint32_t TotalTurns;
|
||||
uint32_t MinigameIdAddress;
|
||||
uint32_t SceneIdAddress;
|
||||
} mpn_addresses_t;
|
||||
|
||||
typedef struct mpn_player_t
|
||||
{
|
||||
uint8_t BlueSpaces;
|
||||
uint16_t Coins;
|
||||
uint16_t CoinStar;
|
||||
uint16_t GameStar;
|
||||
uint8_t Stars;
|
||||
} mpn_player_t;
|
||||
|
||||
typedef struct mpn_board_t
|
||||
{
|
||||
int8_t BoardId;
|
||||
int16_t SceneId;
|
||||
std::string Name;
|
||||
std::string Icon;
|
||||
} mpn_board_t;
|
||||
|
||||
typedef struct mpn_state_t
|
||||
{
|
||||
bool IsMarioParty;
|
||||
|
||||
int16_t CurrentSceneId;
|
||||
int16_t PreviousSceneId;
|
||||
|
||||
const char* Title;
|
||||
const char* Image;
|
||||
|
||||
const mpn_addresses_t* Addresses;
|
||||
const mpn_board_t* Board;
|
||||
const mpn_board_t* Boards;
|
||||
const mpn_scene_t* Scene;
|
||||
const mpn_scene_t* Scenes;
|
||||
} mpn_state_t;
|
||||
|
||||
extern mpn_state_t CurrentState;
|
||||
|
||||
/* Function prototypes */
|
||||
uint8_t mpn_get_needs(uint16_t StateId, bool IsSceneId = false);
|
||||
void mpn_per_frame();
|
||||
uint32_t mpn_read_value(uint32_t Address, uint8_t Size);
|
||||
bool mpn_update_state();
|
||||
|
||||
/* ============================================================================
|
||||
Mario Party 4 metadata
|
||||
============================================================================ */
|
||||
const mpn_addresses_t MP4_ADDRESSES = {0x0018FCFC, 0x0018FCFD, 0x0018FD2C, 0x001D3CE2};
|
||||
|
||||
const mpn_board_t MP4_BOARDS[] = {{1, 0x59, {"Toad's Midway Madness"}, {"mp4-toad"}},
|
||||
{2, 0x5A, {"Goomba's Greedy Gala"}, {"mp4-goomba"}},
|
||||
{3, 0x5B, {"Shy Guy's Jungle Jam"}, {"mp4-shyguy"}},
|
||||
{4, 0x5C, {"Boo's Haunted Bash"}, {"mp4-boo"}},
|
||||
{5, 0x5D, {"Koopa's Seaside Soiree"}, {"mp4-koopa"}},
|
||||
{6, 0x5E, {"Bowser's Gnarly Party"}, {"mp4-bowser"}},
|
||||
{7, 0x60, {"Mega Board Mayhem"}, {"mp4-mega"}},
|
||||
{8, 0x61, {"Mini Board Mad-Dash"}, {"mp4-mini"}},
|
||||
|
||||
{NONE, NONE, {""}, ""}};
|
||||
|
||||
const mpn_scene_t MP4_GAMESTATES[] = {{NONE, 0x01, {"Title Screen"}, 0},
|
||||
{0x00, 0x09, {"Manta Rings"}, 0},
|
||||
{0x01, 0x0A, {"Slime Time"}, 0},
|
||||
{0x02, 0x0B, {"Booksquirm"}, 0},
|
||||
{0x03, 0x0C, {"Trace Race"}, MPN_NEEDS_SAFE_TEX_CACHE},
|
||||
{0x04, 0x0D, {"Mario Medley"}, 0},
|
||||
{0x05, 0x0E, {"Avalanche!"}, 0},
|
||||
{0x06, 0x0F, {"Domination"}, 0},
|
||||
{0x07, 0x10, {"Paratrooper Plunge"}, 0},
|
||||
{0x08, 0x11, {"Toad's Quick Draw"}, 0},
|
||||
{0x09, 0x12, {"Three Throw"}, 0},
|
||||
{0x0A, 0x13, {"Photo Finish"}, 0},
|
||||
{0x0B, 0x14, {"Mr. Blizzard's Brigade"}, 0},
|
||||
{0x0C, 0x15, {"Bob-omb Breakers"}, 0},
|
||||
{0x0D, 0x16, {"Long Claw of the Law"}, 0},
|
||||
{0x0E, 0x17, {"Stamp Out!"}, 0},
|
||||
{0x0F, 0x18, {"Candlelight Fright"}, 0},
|
||||
{0x10, 0x19, {"Makin' Waves"}, 0},
|
||||
{0x11, 0x1A, {"Hide and Go BOOM!"}, 0},
|
||||
{0x12, 0x1B, {"Tree Stomp"}, 0},
|
||||
{0x13, 0x1C, {"Fish n' Drips"}, 0},
|
||||
{0x14, 0x1D, {"Hop or Pop"}, 0},
|
||||
{0x15, 0x1E, {"Money Belts"}, 0},
|
||||
{0x16, 0x1F, {"GOOOOOOOAL!!"}, 0},
|
||||
{0x17, 0x20, {"Blame it on the Crane"}, 0},
|
||||
{0x18, 0x21, {"The Great Deflate"}, 0},
|
||||
{0x19, 0x22, {"Revers-a-Bomb"}, 0},
|
||||
{0x1A, 0x23, {"Right Oar Left?"}, 0},
|
||||
{0x1B, 0x24, {"Cliffhangers"}, 0},
|
||||
{0x1C, 0x25, {"Team Treasure Trek"}, 0},
|
||||
{0x1D, 0x26, {"Pair-a-sailing"}, 0},
|
||||
{0x1E, 0x27, {"Order Up"}, 0},
|
||||
{0x1F, 0x28, {"Dungeon Duos"}, 0},
|
||||
{0x20, 0x29, {"Beach Volley Folley"}, 0},
|
||||
{0x21, 0x2A, {"Cheep Cheep Sweep"}, 0},
|
||||
{0x22, 0x2B, {"Darts of Doom"}, 0},
|
||||
{0x23, 0x2C, {"Fruits of Doom"}, 0},
|
||||
{0x24, 0x2D, {"Balloon of Doom"}, 0},
|
||||
{0x25, 0x2E, {"Chain Chomp Fever"}, 0},
|
||||
{0x26, 0x2F, {"Paths of Peril"}, MPN_NEEDS_EFB_TO_TEXTURE},
|
||||
{0x27, 0x30, {"Bowser's Bigger Blast"}, 0},
|
||||
{0x28, 0x31, {"Butterfly Blitz"}, 0},
|
||||
{0x29, 0x32, {"Barrel Baron"}, 0},
|
||||
{0x2A, 0x33, {"Mario Speedwagons"}, 0},
|
||||
/* 2B? */
|
||||
{0x2C, 0x35, {"Bowser Bop"}, 0},
|
||||
{0x2D, 0x36, {"Mystic Match 'Em"}, 0},
|
||||
{0x2E, 0x37, {"Archaeologuess"}, 0},
|
||||
{0x2F, 0x38, {"Goomba's Chip Flip"}, 0},
|
||||
{0x30, 0x39, {"Kareening Koopas"}, 0},
|
||||
{0x31, 0x3A, {"The Final Battle!"}, 0},
|
||||
{NONE, 0x3B, {"Jigsaw Jitters"}, 0},
|
||||
{NONE, 0x3C, {"Challenge Booksquirm"}, 0},
|
||||
{NONE, 0x3D, {"Rumble Fishing"}, 0},
|
||||
{NONE, 0x3E, {"Take a Breather"}, 0},
|
||||
{NONE, 0x3F, {"Bowser Wrestling"}, 0},
|
||||
{NONE, 0x41, {"Mushroom Medic"}, 0},
|
||||
{NONE, 0x42, {"Doors of Doom"}, 0},
|
||||
{NONE, 0x43, {"Bob-omb X-ing"}, 0},
|
||||
{NONE, 0x44, {"Goomba Stomp"}, 0},
|
||||
{NONE, 0x45, {"Panel Panic"}, 0},
|
||||
{NONE, 0x46, {"Party Mode Menu"}, 0},
|
||||
{NONE, 0x48, {"Mini-Game Mode Menu"}, 0},
|
||||
{NONE, 0x4A, {"Main Menu"}, 0},
|
||||
{NONE, 0x4B, {"Extra Room"}, 0},
|
||||
{NONE, 0x52, {"Option Room"}, 0},
|
||||
{NONE, 0x53, {"Present Room"}, 0},
|
||||
{NONE, 0x59, {"Toad's Midway Madness"}, 0},
|
||||
{NONE, 0x5A, {"Goomba's Greedy Gala"}, 0},
|
||||
{NONE, 0x5B, {"Shy Guy's Jungle Jam"}, 0},
|
||||
{NONE, 0x5C, {"Boo's Haunted Bash"}, 0},
|
||||
{NONE, 0x5D, {"Koopa's Seaside Soiree"}, 0},
|
||||
{NONE, 0x5E, {"Bowser's Gnarly Party"}, 0},
|
||||
{NONE, 0x5F, {"Board Map Rules"}, 0},
|
||||
{NONE, 0x60, {"Mega Board Mayhem"}, 0},
|
||||
{NONE, 0x61, {"Mini Board Mad-Dash"}, 0},
|
||||
{NONE, 0x62, {"Beach Volley Folley Menu"}, 0},
|
||||
|
||||
{NONE, NONE, {""}}};
|
||||
|
||||
/* ============================================================================
|
||||
Mario Party 5 metadata
|
||||
============================================================================ */
|
||||
|
||||
const mpn_addresses_t MP5_ADDRESSES = {
|
||||
0x0022A494, // Current Turns
|
||||
0x0022A495, // Total Turns
|
||||
0x0022A4C4, // Mini ID
|
||||
0x00288862 // Scene ID
|
||||
};
|
||||
|
||||
const mpn_board_t MP5_BOARDS[] = {{1, 0x76, {"Toy Dream"}, {"mp5-toy"}},
|
||||
{2, 0x78, {"Rainbow Dream"}, {"mp5-rainbow"}},
|
||||
{3, 0x7A, {"Pirate Dream"}, {"mp5-pirate"}},
|
||||
{4, 0x7C, {"Undersea Dream"}, {"mp5-undersea"}},
|
||||
{5, 0x7E, {"Future Dream"}, {"mp5-future"}},
|
||||
{6, 0x80, {"Sweet Dream"}, {"mp5-sweet"}},
|
||||
{7, 0x82, {"Bowser Nightmare"}, {"mp5-bowser"}},
|
||||
|
||||
|
||||
{NONE, NONE, {""}, ""}};
|
||||
|
||||
const mpn_scene_t MP5_GAMESTATES[] = {{NONE, 0x01, {"Title Screen"}, 0},
|
||||
{NONE, 0x02, {"Card Party"}, 0},
|
||||
{NONE, 0x06, {"Save-File Screen"}, 0},
|
||||
//{NONE, 0x07, {"Mini-game Explanation"}, 0},
|
||||
{0x4D, 0x0B, {"Beach Volleyball"}, 0},
|
||||
{0x00, 0x0F, {"Coney Island"}, 0},
|
||||
{0x01, 0x10, {"Ground Pound Down"}, 0},
|
||||
{0x02, 0x11, {"Chimp Chase"}, 0},
|
||||
{0x03, 0x12, {"Chomp Romp"}, 0},
|
||||
{0x04, 0x13, {"Pushy Penguins"}, MPN_NEEDS_EFB_TO_TEXTURE},
|
||||
{0x05, 0x14, {"Leaf Leap"}, 0},
|
||||
{0x06, 0x15, {"Night Light Fright"}, 0},
|
||||
{0x07, 0x16, {"Pop-Star Piranhas"}, 0},
|
||||
{0x08, 0x17, {"Mazed & Confused"}, 0},
|
||||
{0x09, 0x18, {"Dinger Derby"}, 0},
|
||||
{0x0A, 0x19, {"Hydrostars"}, 0},
|
||||
{0x0B, 0x1A, {"Later Skater"}, 0},
|
||||
{0x0C, 0x1B, {"Will Flower"}, 0},
|
||||
{0x0D, 0x1C, {"Triple Jump"}, 0},
|
||||
{0x0E, 0x1D, {"Hotel Goomba"}, 0},
|
||||
{0x0F, 0x1E, {"Coin Cache"}, 0},
|
||||
{0x10, 0x1F, {"Flatiator"}, 0},
|
||||
{0x11, 0x20, {"Squared Away"}, 0},
|
||||
{0x12, 0x21, {"Mario Mechs"}, 0},
|
||||
{0x13, 0x22, {"Revolving Fire"}, 0},
|
||||
{0x14, 0x23, {"Clock Stoppers"}, 0},
|
||||
{0x15, 0x24, {"Heat Stroke"}, 0},
|
||||
{0x16, 0x25, {"Beam Team"}, 0},
|
||||
{0x17, 0x26, {"Vicious Vending"}, 0},
|
||||
{0x18, 0x27, {"Big Top Drop"}, 0},
|
||||
{0x19, 0x28, {"Defuse or Lose"}, 0},
|
||||
{0x1A, 0x29, {"ID UFO"}, 0},
|
||||
{0x1B, 0x2A, {"Mario Can-Can"}, 0},
|
||||
{0x1C, 0x2B, {"Handy Hoppers"}, 0},
|
||||
{0x1D, 0x2C, {"Berry Basket"}, 0},
|
||||
{0x1E, 0x2D, {"Bus Buffer"}, 0},
|
||||
{0x1F, 0x2E, {"Rumble Ready"}, 0},
|
||||
{0x20, 0x2F, {"Submarathon"}, 0},
|
||||
{0x21, 0x30, {"Manic Mallets"}, 0},
|
||||
{0x22, 0x31, {"Astro-Logical"}, 0},
|
||||
{0x23, 0x32, {"Bill Blasters"}, 0},
|
||||
{0x24, 0x33, {"Tug-o-Dorrie"}, 0},
|
||||
{0x25, 0x34, {"Twist 'n' Out"}, 0},
|
||||
{0x26, 0x35, {"Lucky Lineup"}, 0},
|
||||
{0x27, 0x36, {"Random Ride"}, 0},
|
||||
{0x28, 0x37, {"Shock Absorbers"}, 0},
|
||||
{0x29, 0x38, {"Countdown Pound"}, 0},
|
||||
{0x2A, 0x39, {"Whomp Maze"}, 0},
|
||||
{0x2B, 0x3A, {"Shy Guy Showdown"}, 0},
|
||||
{0x2C, 0x3B, {"Button Mashers"}, 0},
|
||||
{0x2D, 0x3C, {"Get a Rope"}, 0},
|
||||
{0x2E, 0x3D, {"Pump 'n' Jump"}, 0},
|
||||
{0x2F, 0x3E, {"Head Waiter"}, 0},
|
||||
{0x30, 0x3F, {"Blown Away"}, 0},
|
||||
{0x31, 0x40, {"Merry Poppings"}, 0},
|
||||
{0x32, 0x41, {"Pound Peril"}, 0},
|
||||
{0x33, 0x42, {"Piece Out"}, 0},
|
||||
{0x34, 0x43, {"Bound of Music"}, 0},
|
||||
{0x35, 0x44, {"Wind Wavers"}, 0},
|
||||
{0x36, 0x45, {"Sky Survivor"}, 0},
|
||||
{0x3A, 0x46, {"Rain of Fire"}, 0},
|
||||
{0x3B, 0x47, {"Cage-in Cookin'"}, 0},
|
||||
{0x3C, 0x48, {"Scaldin' Cauldron"}, 0},
|
||||
{0x3D, 0x49, {"Frightmare"}, 0},
|
||||
{0x3E, 0x4A, {"Flower Shower"}, 0},
|
||||
{0x3F, 0x4B, {"Dodge Bomb"}, 0},
|
||||
{0x40, 0x4C, {"Fish Upon a Star"}, 0},
|
||||
{0x41, 0x4D, {"Rumble Fumble"}, 0},
|
||||
{0x42, 0x4E, {"Quilt for Speed"}, 0},
|
||||
{0x43, 0x4F, {"Tube It or Lose It"}, 0},
|
||||
{0x44, 0x50, {"Mathletes"}, 0},
|
||||
{0x45, 0x51, {"Fight Cards"}, 0},
|
||||
{0x46, 0x52, {"Banana Punch"}, 0},
|
||||
{0x47, 0x53, {"Da Vine Climb"}, 0},
|
||||
{0x48, 0x54, {"Mass A-peel"}, 0},
|
||||
{0x49, 0x55, {"Panic Pinball"}, 0},
|
||||
{0x4A, 0x56, {"Banking Coins"}, 0},
|
||||
{0x4B, 0x57, {"Frozen Frenzy"}, 0},
|
||||
{0x4C, 0x58, {"Curvy Curbs"}, 0},
|
||||
{0x4E, 0x59, {"Fish Sticks"}, 0},
|
||||
{0x4F, 0x5A, {"Ice Hockey"}, 0},
|
||||
{NONE, 0x5C, {"Card Party Menu"}, 0},
|
||||
{NONE, 0x5E, {"Bonus Mode Menu"}, 0},
|
||||
{NONE, 0x60, {"Party Mode Menu"}, 0},
|
||||
{NONE, 0x61, {"Main Menu"}, 0},
|
||||
{NONE, 0x62, {"Party Mode Menu"}, 0},
|
||||
{NONE, 0x64, {"Free Play"}, 0},
|
||||
{NONE, 0x6F, {"Super Duel Mode Menu"}, 0},
|
||||
{NONE, 0x76, {"Toy Dream"}, 0},
|
||||
{NONE, 0x78, {"Rainbow Dream"}, 0},
|
||||
{NONE, 0x7A, {"Pirate Dream"}, 0},
|
||||
{NONE, 0x7C, {"Undersea Dream"}, 0},
|
||||
{NONE, 0x7E, {"Future Dream"}, 0},
|
||||
{NONE, 0x80, {"Sweet Dream"}, 0},
|
||||
{NONE, 0x82, {"Bowser Nightmare"}, 0},
|
||||
|
||||
{NONE, NONE, {""}}};
|
||||
|
||||
/* ============================================================================
|
||||
Mario Party 6 metadata
|
||||
============================================================================ */
|
||||
|
||||
const mpn_addresses_t MP6_ADDRESSES = {
|
||||
0x00265B74, // Current Turns
|
||||
0x00265B75, // Total Turns
|
||||
0x00265BA8, // Mini ID
|
||||
0x002C0256 // Scene ID
|
||||
};
|
||||
|
||||
const mpn_board_t MP6_BOARDS[] = {{1, 0x7B, {"Towering Treetop"}, {"mp6-treetop"}},
|
||||
{2, 0x7C, {"E. Gadd's Garage"}, {"mp6-garage"}},
|
||||
{3, 0x7D, {"Faire Square"}, {"mp6-square"}},
|
||||
{4, 0x7E, {"Snowflake Lake"}, {"mp6-lake"}},
|
||||
{5, 0x7F, {"Castaway Bay"}, {"mp6-bay"}},
|
||||
{6, 0x80, {"Clockwork Castle"}, {"mp6-castle"}},
|
||||
{7, 0x72, {"Thirsty Gultch"}, {"mp6-gultch"}},
|
||||
{8, 0x73, {"Astro Avenue"}, {"mp6-avenue"}},
|
||||
{9, 0x74, {"Infernal Tower"}, {"mp6-tower"}},
|
||||
|
||||
{NONE, NONE, {""}, ""}};
|
||||
|
||||
const mpn_scene_t MP6_GAMESTATES[] = {{NONE, 0x01, {"Title Screen"}, 0},
|
||||
{NONE, 0x03, {"File-selection Screen"}, 0},
|
||||
//{NONE, 0x04, {"Mini-game Explanation"}, 0},
|
||||
{0x00, 0x06, {"Smashdance"}, 0},
|
||||
{0x01, 0x07, {"Odd Card Out"}, 0},
|
||||
{0x02, 0x08, {"Freeze Frame"}, 0},
|
||||
{0x03, 0x09, {"What Goes Up..."}, 0},
|
||||
{0x04, 0x0A, {"Granite Getaway"}, 0},
|
||||
{0x05, 0x0B, {"Circuit Maximus"}, 0},
|
||||
{0x06, 0x0C, {"Catch You Letter"}, 0},
|
||||
{0x07, 0x0D, {"Snow Whirled"}, 0},
|
||||
{0x08, 0x0E, {"Daft Rafts"}, 0},
|
||||
{0x09, 0x0F, {"Tricky Tires"}, 0},
|
||||
{0x0A, 0x10, {"Treasure Trawlers"}, 0},
|
||||
{0x0B, 0x11, {"Memory Lane"}, 0},
|
||||
{0x0C, 0x12, {"Mowtown"}, MPN_NEEDS_SAFE_TEX_CACHE},
|
||||
{0x0D, 0x13, {"Cannonball Fun"}, 0},
|
||||
{0x0E, 0x14, {"Note to Self"}, 0},
|
||||
{0x0F, 0x15, {"Same is Lame"}, 0},
|
||||
{0x10, 0x16, {"Light Up My Night"}, 0},
|
||||
{0x11, 0x17, {"Lift Leapers"}, 0},
|
||||
{0x12, 0x18, {"Blooper Scooper"}, 0},
|
||||
{0x13, 0x19, {"Trap Ease Artist"}, 0},
|
||||
{0x14, 0x1A, {"Pokey Punch-out"}, 0},
|
||||
{0x15, 0x1B, {"Money Belt"}, 0},
|
||||
{0x16, 0x1C, {"Cash Flow"}, 0},
|
||||
{0x17, 0x1D, {"Cog Jog"}, 0},
|
||||
{0x18, 0x1E, {"Sink or Swim"}, 0},
|
||||
{0x19, 0x1F, {"Snow Brawl"}, 0},
|
||||
{0x1A, 0x20, {"Ball Dozers"}, 0},
|
||||
{0x1B, 0x21, {"Surge and Destroy"}, 0},
|
||||
{0x1C, 0x22, {"Pop Star"}, 0},
|
||||
{0x1D, 0x23, {"Stage Fright"}, 0},
|
||||
{0x1E, 0x24, {"Conveyor Bolt"}, 0},
|
||||
{0x1F, 0x25, {"Crate and Peril"}, 0},
|
||||
{0x20, 0x26, {"Ray of Fright"}, 0},
|
||||
{0x21, 0x27, {"Dust 'til Dawn"}, 0},
|
||||
{0x22, 0x28, {"Garden Grab"}, 0},
|
||||
{0x23, 0x29, {"Pixel Perfect"}, 0},
|
||||
{0x24, 0x2A, {"Slot Trot"}, 0},
|
||||
{0x25, 0x2B, {"Gondola Glide"}, 0},
|
||||
{0x26, 0x2C, {"Light Breeze"}, 0},
|
||||
{0x27, 0x2D, {"Body Builder"}, 0},
|
||||
{0x28, 0x2E, {"Mole-it!"}, 0},
|
||||
{0x29, 0x2F, {"Cashapult"}, 0},
|
||||
{0x2A, 0x30, {"Jump the Gun"}, 0},
|
||||
{0x2B, 0x31, {"Rocky Road"}, 0},
|
||||
{0x2C, 0x32, {"Clean Team"}, 0},
|
||||
{0x2D, 0x33, {"Hyper Sniper"}, 0},
|
||||
{0x2E, 0x34, {"Insectiride"}, 0},
|
||||
{0x2F, 0x35, {"Sunday Drivers"}, 0},
|
||||
{0x30, 0x36, {"Stamp By Me"}, 0},
|
||||
{0x31, 0x37, {"Throw Me a Bone"}, 0},
|
||||
{0x32, 0x38, {"Black Hole Boogie"}, 0},
|
||||
{0x33, 0x39, {"Full Tilt"}, 0},
|
||||
{0x34, 0x3A, {"Sumo of Doom-o"}, 0},
|
||||
{0x35, 0x3B, {"O-Zone"}, 0},
|
||||
{0x36, 0x3C, {"Pitifall"}, 0},
|
||||
{0x37, 0x3D, {"Mass Meteor"}, 0},
|
||||
{0x38, 0x3E, {"Lunar-tics"}, 0},
|
||||
{0x39, 0x3F, {"T Minus Five"}, 0},
|
||||
{0x3A, 0x40, {"Asteroad Rage"}, 0},
|
||||
{0x3B, 0x41, {"Boo'd Off the Stage"}, 0},
|
||||
{0x3C, 0x42, {"Boonanza!"}, 0},
|
||||
{0x3D, 0x43, {"Trick or Tree"}, 0},
|
||||
{0x3E, 0x44, {"Something's Amist"}, 0},
|
||||
{0x3F, 0x45, {"Wrasslin' Rapids"}, 0},
|
||||
{0x43, 0x46, {"Burnstile"}, 0},
|
||||
{0x44, 0x47, {"Word Herd"}, 0},
|
||||
{0x45, 0x48, {"Fruit Talktail"}, 0},
|
||||
{0x46, 0x4C, {"Pit Boss"}, 0},
|
||||
{0x47, 0x4D, {"Dizzy Rotisserie"}, 0},
|
||||
{0x48, 0x4E, {"Dark 'n Crispy"}, 0},
|
||||
{0x49, 0x4F, {"Tally Me Banana"}, 0},
|
||||
{0x4A, 0x50, {"Banana Shake"}, 0},
|
||||
{0x4B, 0x51, {"Pier Factor"}, 0},
|
||||
{0x4C, 0x52, {"Seer Terror"}, 0},
|
||||
{0x4D, 0x53, {"Block Star"}, 0},
|
||||
{0x4E, 0x54, {"Lab Brats"}, 0},
|
||||
{0x4F, 0x55, {"Strawberry Shortfuse"}, 0},
|
||||
{0x50, 0x56, {"Control Shtick"}, 0},
|
||||
{0x51, 0x57, {"Dunk Bros."}, 0},
|
||||
{NONE, 0x58, {"Star Bank"}, 0},
|
||||
{NONE, 0x5A, {"Mini-game Mode"}, 0},
|
||||
{NONE, 0x5B, {"Party Mode Menu"}, 0},
|
||||
{NONE, 0x5C, {"Final Results"}, 0},
|
||||
{NONE, 0x5D, {"Main Menu"}, 0},
|
||||
{NONE, 0x5E, {"Solo Mode Menu"}, 0},
|
||||
{NONE, 0x60, {"Battle Bridge"}, 0},
|
||||
{NONE, 0x61, {"Treetop Bingo"}, 0},
|
||||
{NONE, 0x62, {"Mount Duel"}, 0},
|
||||
{NONE, 0x63, {"Mini-game Tour"}, MPN_NEEDS_EFB_TO_TEXTURE},
|
||||
{NONE, 0x63, {"Decathlon Park"}, 0},
|
||||
{NONE, 0x64, {"Endurance Alley"}, 0},
|
||||
{NONE, 0x6F, {"Option Mode"}, 0},
|
||||
{NONE, 0x71, {"Mini-game Results"}, 0},
|
||||
{NONE, 0x72, {"Thirsty Gultch"}, 0},
|
||||
{NONE, 0x73, {"Astro Avenue"}, 0},
|
||||
{NONE, 0x74, {"Infernal Tower"}, 0},
|
||||
{NONE, 0x7B, {"Towering Treetop"}, 0},
|
||||
{NONE, 0x7C, {"E. Gadd's Garage"}, 0},
|
||||
{NONE, 0x7D, {"Faire Square"}, 0},
|
||||
{NONE, 0x7E, {"Snowflake Lake"}, 0},
|
||||
{NONE, 0x7F, {"Castaway Bay"}, 0},
|
||||
{NONE, 0x80, {"Clockwork Castle"}, 0},
|
||||
|
||||
{NONE, NONE, {""}}};
|
||||
|
||||
/* ============================================================================
|
||||
Mario Party 7 metadata
|
||||
============================================================================ */
|
||||
|
||||
const mpn_addresses_t MP7_ADDRESSES = {0x0029151C, 0x0029151D, 0x00291558, 0x002F2F3E};
|
||||
|
||||
const mpn_board_t MP7_BOARDS[] = {{1, 0x7A, {"Grand Canal"}, {"mp7-canal"}},
|
||||
{2, 0x7B, {"Pagoda Peak"}, {"mp7-peak"}},
|
||||
{3, 0x7C, {"Pyramid Park"}, {"mp7-park"}},
|
||||
{4, 0x7D, {"Neon Heights"}, {"mp7-heights"}},
|
||||
{5, 0x7E, {"Windmillville"}, {"mp7-windmillville"}},
|
||||
{6, 0x7F, {"Bowser's Enchanted Inferno!"}, {"mp7-inferno"}},
|
||||
|
||||
{NONE, NONE, "", ""}};
|
||||
|
||||
const mpn_scene_t MP7_GAMESTATES[] = {{NONE, 0x03, {"Boot Logos"}, 0},
|
||||
{NONE, 0x05, {"File Select"}, 0},
|
||||
//{NONE, 0x06, {"Mini-Game Explanation"}, 0},
|
||||
{0x00, 0x07, {"Catchy Tunes"}, 0},
|
||||
{0x01, 0x08, {"Bubble Brawl"}, 0},
|
||||
{0x02, 0x09, {"Track & Yield"}, 0},
|
||||
{0x03, 0x0A, {"Fun Run"}, 0},
|
||||
{0x04, 0x0B, {"Cointagious"}, 0},
|
||||
{0x05, 0x0C, {"Snow Ride"}, 0},
|
||||
{0x07, 0x0E, {"Picture This"}, 0},
|
||||
{0x08, 0x0F, {"Ghost in the Hall"}, 0},
|
||||
{0x09, 0x10, {"Big Dripper"}, 0},
|
||||
{0x0A, 0x11, {"Target Tag"}, 0},
|
||||
{0x0B, 0x12, {"Pokey Pummel"}, 0},
|
||||
{0x0C, 0x13, {"Take Me Ohm"}, 0},
|
||||
{0x0D, 0x14, {"Kart Wheeled"}, 0},
|
||||
{0x0E, 0x15, {"Balloon Busters"}, 0},
|
||||
{0x0F, 0x16, {"Clock Watchers"}, 0},
|
||||
{0x10, 0x17, {"Dart Attack"}, 0},
|
||||
{0x12, 0x18, {"Oil Crisis"}, 0},
|
||||
{0x14, 0x1A, {"La Bomba"}, 0},
|
||||
{0x15, 0x1B, {"Spray Anything"}, 0},
|
||||
{0x16, 0x1C, {"Balloonatic"}, 0},
|
||||
{0x17, 0x1D, {"Spinner Cell"}, 0},
|
||||
{0x18, 0x1E, {"Think Tank"}, 0},
|
||||
{0x19, 0x1F, {"Flashfright"}, 0},
|
||||
{0x1A, 0x20, {"Coin-op Bop"}, 0},
|
||||
{0x1B, 0x21, {"Easy Pickings"}, 0},
|
||||
{0x1C, 0x22, {"Wheel of Woe"}, 0},
|
||||
{0x1D, 0x23, {"Boxing Day"}, 0},
|
||||
{0x1E, 0x24, {"Be My Chum!"}, 0},
|
||||
{0x1F, 0x25, {"StratosFEAR!"}, 0},
|
||||
{0x20, 0x26, {"Pogo-a-go-go"}, 0},
|
||||
{0x21, 0x27, {"Buzzstormer"}, 0},
|
||||
{0x22, 0x28, {"Tile and Error"}, 0},
|
||||
{0x23, 0x29, {"Battery Ram"}, 0},
|
||||
{0x24, 0x2A, {"Cardinal Rule"}, 0},
|
||||
{0x25, 0x2B, {"Ice Moves"}, 0},
|
||||
{0x26, 0x2C, {"Bumper Crop"}, 0},
|
||||
{0x27, 0x2D, {"Hop-O-Matic 4000"}, 0},
|
||||
{0x28, 0x2E, {"Wingin' It"}, 0},
|
||||
{0x29, 0x2F, {"Sphere Factor"}, 0},
|
||||
{0x2A, 0x30, {"Herbicidal Maniac"}, 0},
|
||||
{0x2B, 0x31, {"Pyramid Scheme"}, 0},
|
||||
{0x2C, 0x32, {"World Piece"}, 0},
|
||||
{0x2D, 0x33, {"Warp Pipe Dreams"}, 0},
|
||||
{0x2E, 0x34, {"Weight for It"}, 0},
|
||||
{0x2F, 0x35, {"Helipopper"}, 0},
|
||||
{0x30, 0x36, {"Monty's Revenge"}, 0},
|
||||
{0x31, 0x37, {"Deck Hands"}, 0},
|
||||
{0x32, 0x38, {"Mad Props"}, 0},
|
||||
{0x33, 0x39, {"Gimme a Sign"}, 0},
|
||||
{0x34, 0x3A, {"Bridge Work"}, 0},
|
||||
{0x35, 0x3B, {"Spin Doctor"}, 0},
|
||||
{0x36, 0x3C, {"Hip Hop Drop"}, 0},
|
||||
{0x37, 0x3D, {"Air Farce"}, 0},
|
||||
{0x38, 0x3E, {"The Final Countdown"}, 0},
|
||||
{0x39, 0x3F, {"Royal Rumpus"}, 0},
|
||||
{0x3A, 0x40, {"Light Speed"}, 0},
|
||||
{0x3B, 0x41, {"Apes of Wrath"}, 0},
|
||||
{0x3C, 0x42, {"Fish & Cheeps"}, 0},
|
||||
{0x3D, 0x43, {"Camp Ukiki"}, 0},
|
||||
{0x3E, 0x44, {"Funstacle Course!"}, 0},
|
||||
{0x3F, 0x45, {"Funderwall!"}, 0},
|
||||
{0x40, 0x46, {"Magmagical Journey!"}, 0},
|
||||
{0x41, 0x47, {"Tunnel of Lava!"}, 0},
|
||||
{0x42, 0x48, {"Treasure Dome!"}, 0},
|
||||
{0x43, 0x49, {"Slot-O-Whirl!"}, 0},
|
||||
{0x44, 0x4A, {"Peel Out"}, 0},
|
||||
{0x45, 0x4B, {"Bananas Faster"}, 0},
|
||||
{0x46, 0x4C, {"Stump Change"}, 0},
|
||||
{0x47, 0x4D, {"Jump, Man"}, 0},
|
||||
{0x48, 0x4E, {"Vine Country"}, 0},
|
||||
{0x49, 0x4F, {"A Bridge Too Short"}, 0},
|
||||
{0x4A, 0x50, {"Spider Stomp"}, 0},
|
||||
{0x4B, 0x51, {"Stick and Spin"}, 0},
|
||||
{0x55, 0x5B, {"Bowser's Lovely Lift!"}, 0},
|
||||
{0x57, 0x5D, {"Mathemortician"}, 0},
|
||||
{NONE, 0x61, {"Duty-Free Shop"}, 0},
|
||||
{NONE, 0x63, {"Deluxe Cruise"}, 0},
|
||||
{NONE, 0x64, {"Minigame Cruise"}, 0},
|
||||
{NONE, 0x65, {"Control Room"}, 0},
|
||||
{NONE, 0x67, {"Main Menu"}, 0},
|
||||
{NONE, 0x68, {"Solo Cruise"}, 0},
|
||||
{NONE, 0x6A, {"Decathlon Castle"}, 0},
|
||||
{NONE, 0x6B, {"Free-Play Sub"}, 0},
|
||||
{NONE, 0x6C, {"Waterfall Battle"}, 0},
|
||||
{NONE, 0x6E, {"Volcano Peril"}, 0},
|
||||
{NONE, 0x6F, {"Pearl Hunt"}, 0},
|
||||
{NONE, 0x70, {"King of the River"}, 0},
|
||||
{NONE, 0x66, {"Party Cruise"}, 0},
|
||||
{NONE, 0x7A, {"Grand Canal"}, 0},
|
||||
{NONE, 0x7B, {"Pagoda Peak"}, 0},
|
||||
{NONE, 0x7C, {"Pyramid Park"}, 0},
|
||||
{NONE, 0x7D, {"Neon Heights"}, 0},
|
||||
{NONE, 0x7E, {"Windmillville"}, 0},
|
||||
{NONE, 0x7F, {"Bowser's Enchanted Inferno!"}, 0},
|
||||
{NONE, 0x73, {"Mini-Game Results"}, 0},
|
||||
|
||||
{NONE, NONE, {""}, 0}};
|
||||
|
||||
/* ============================================================================
|
||||
Mario Party 8 metadata
|
||||
============================================================================ */
|
||||
|
||||
const mpn_addresses_t MP8_ADDRESSES = {0x00228764, 0x00228765, 0x002287CC, 0x002CD222};
|
||||
|
||||
const mpn_board_t MP8_BOARDS[] = {{1, 0x10, {"DK's Treetop Temple"}, {"mp8-dktt"}},
|
||||
{2, 0x11, {"Goomba's Booty Boardwalk"}, {"mp8-gbb"}},
|
||||
{3, 0x12, {"King Boo's Haunted Hideaway"}, {"mp8-kbhh"}},
|
||||
{4, 0x13, {"Shy Guy's Perplex Express"}, {"mp8-sgpe"}},
|
||||
{5, 0x14, {"Koopa's Tycoon Town"}, {"mp8-ktt"}},
|
||||
{6, 0x15, {"Bowser's Warped Orbit"}, {"mp8-bwo"}},
|
||||
|
||||
{NONE, NONE, {""}, ""}};
|
||||
|
||||
const mpn_scene_t MP8_GAMESTATES[] = {
|
||||
{NONE, 0x04, {"Main Menu"}, 0},
|
||||
{NONE, 0x08, {"Fun Bazaar"}, 0},
|
||||
{NONE, 0x0A, {"Free Play Arcade"}, 0},
|
||||
{NONE, 0x0B, {"Crown Showdown"}, 0},
|
||||
{NONE, 0x0C, {"Flip-Out Frenzy"}, 0},
|
||||
{NONE, 0x0D, {"Tic-Tac Drop"}, 0},
|
||||
{NONE, 0x0E, {"Test for the Best"}, 0},
|
||||
{NONE, 0x10, {"DK's Treetop Temple"}, 0},
|
||||
{NONE, 0x11, {"Goomba's Booty Boardwalk"}, 0},
|
||||
{NONE, 0x12, {"King Boo's Haunted Hideaway"}, 0},
|
||||
{NONE, 0x13, {"Shy Guy's Perplex Express"}, 0},
|
||||
{NONE, 0x14, {"Koopa's Tycoon Town"}, 0},
|
||||
{NONE, 0x15, {"Bowser's Warped Orbit"}, 0},
|
||||
//{NONE, 0x16, {"Mini-Game Explanation"}, 0},
|
||||
{0x00, 0x17, {"Speedy Graffiti"}, MPN_NEEDS_EFB_TO_TEXTURE},
|
||||
{0x01, 0x18, {"Swing Kings"}, 0},
|
||||
{0x02, 0x19, {"Water Ski Spree"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x03, 0x1A, {"Punch-a-Bunch"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x04, 0x1B, {"Crank to Rank"}, 0},
|
||||
{0x05, 0x1C, {"At the Chomp Wash"}, 0},
|
||||
{0x06, 0x1D, {"Mosh-Pit Playroom"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x07, 0x1E, {"Mario Matrix"}, 0},
|
||||
{0x08, 0x1F, {"??? - Hammer de Pokari"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x09, 0x20, {"Grabby Giridion"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x0A, 0x21, {"Lava or Leave 'Em"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x0B, 0x22, {"Kartastrophe"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x0C, 0x23, {"??? - Ribbon Game"}, 0},
|
||||
{0x0D, 0x24, {"Aim of the Game"}, 0},
|
||||
{0x0E, 0x25, {"Rudder Madness"}, 0},
|
||||
{0x0F, 0x26, {"Gun the Runner"}, MPN_NEEDS_SIDEWAYS_WIIMOTE}, // 1P is sideways
|
||||
{0x10, 0x27, {"Grabbin' Gold"}, 0},
|
||||
{0x11, 0x28, {"Power Trip"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x12, 0x29, {"Bob-ombs Away"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x13, 0x2A, {"Swervin' Skies"}, 0},
|
||||
{0x14, 0x2B, {"Picture Perfect"}, 0},
|
||||
{0x15, 0x2C, {"Snow Way Out"}, MPN_NEEDS_SIDEWAYS_WIIMOTE}, // 3P are sideways
|
||||
{0x16, 0x2D, {"Thrash 'n' Crash"}, 0},
|
||||
{0x17, 0x2E, {"Chump Rope"}, 0},
|
||||
{0x18, 0x2F, {"Sick and Twisted"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x19, 0x30, {"Bumper Balloons"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x1A, 0x31, {"Rowed to Victory"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x1B, 0x32, {"Winner or Dinner"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x1C, 0x33, {"Paint Misbehavin'"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x1D, 0x34, {"Sugar Rush"}, 0},
|
||||
{0x1E, 0x35, {"King of the Thrill"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x1F, 0x36, {"Shake It Up"}, 0},
|
||||
{0x20, 0x37, {"Lean, Mean Ravine"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x21, 0x38, {"Boo-ting Gallery"}, 0},
|
||||
{0x22, 0x39, {"Crops 'n' Robbers"}, 0},
|
||||
{0x23, 0x3A, {"In the Nick of Time"}, 0},
|
||||
{0x24, 0x3B, {"Cut from the Team"}, 0},
|
||||
{0x25, 0x3C, {"Snipe for the Picking"}, 0},
|
||||
{0x26, 0x3D, {"Saucer Swarm"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x27, 0x3E, {"Glacial Meltdown"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x28, 0x3F, {"Attention Grabber"}, 0},
|
||||
{0x29, 0x40, {"Blazing Lassos"}, 0},
|
||||
{0x2A, 0x41, {"Wing and a Scare"}, 0},
|
||||
{0x2B, 0x42, {"Lob to Rob"}, 0},
|
||||
{0x2C, 0x43, {"Pumper Cars"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x2D, 0x44, {"Cosmic Slalom"}, 0},
|
||||
{0x2E, 0x45, {"Lava Lobbers"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x2F, 0x46, {"Loco Motives"}, 0},
|
||||
{0x30, 0x47, {"Specter Inspector"}, 0},
|
||||
{0x31, 0x48, {"Frozen Assets"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x32, 0x49, {"Breakneck Building"}, MPN_NEEDS_NATIVE_RES},
|
||||
{0x33, 0x4A, {"Surf's Way Up"}, 0},
|
||||
{0x34, 0x4B, {"??? - Bull Riding"}, 0},
|
||||
{0x35, 0x4C, {"Balancing Act"}, 0},
|
||||
{0x36, 0x4D, {"Ion the Prize"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x37, 0x4E, {"You're the Bob-omb"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x38, 0x4F, {"Scooter Pursuit"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x39, 0x50, {"Cardiators"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x3A, 0x51, {"Rotation Station"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x3B, 0x52, {"Eyebrawl"}, 0},
|
||||
{0x3C, 0x53, {"Table Menace"}, 0},
|
||||
{0x3D, 0x54, {"Flagging Rights"}, 0},
|
||||
{0x3E, 0x55, {"Trial by Tile"}, 0},
|
||||
{0x3F, 0x56, {"Star Carnival Bowling"}, 0},
|
||||
{0x40, 0x57, {"Puzzle Pillars"}, 0},
|
||||
{0x41, 0x58, {"Canyon Cruisers"}, 0},
|
||||
{0x42, 0x59, {"??? - CRASH"}, 0},
|
||||
{0x43, 0x5A, {"Settle It in Court"}, 0},
|
||||
{0x44, 0x5B, {"Moped Mayhem"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
{0x45, 0x5C, {"Flip the Chimp"}, 0},
|
||||
{0x46, 0x5D, {"Pour to Score"}, 0},
|
||||
{0x47, 0x5E, {"Fruit Picker"}, 0},
|
||||
{0x48, 0x5F, {"Stampede"}, 0},
|
||||
{0x49, 0x60, {"Superstar Showdown"}, 0},
|
||||
{0x4A, 0x61, {"Alpine Assault"}, 0},
|
||||
{0x4B, 0x62, {"Treacherous Tightrope"}, MPN_NEEDS_SIDEWAYS_WIIMOTE},
|
||||
|
||||
{NONE, NONE, {""}, 0}};
|
||||
|
||||
#endif
|
|
@ -130,9 +130,12 @@ public:
|
|||
void SendChatMessage(const std::string& msg);
|
||||
void RequestStopGame();
|
||||
void SendPowerButtonEvent();
|
||||
void SendActiveGeckoCodes();
|
||||
void GetActiveGeckoCodes();
|
||||
void RequestGolfControl(PlayerId pid);
|
||||
void RequestGolfControl();
|
||||
std::string GetCurrentGolfer();
|
||||
std::vector<std::string> v_ActiveGeckoCodes;
|
||||
|
||||
// Send and receive pads values
|
||||
struct WiimoteDataBatchEntry
|
||||
|
|
|
@ -425,8 +425,8 @@ ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Pack
|
|||
{
|
||||
std::string netplay_version;
|
||||
received_packet >> netplay_version;
|
||||
if (netplay_version != Common::GetScmRevGitStr())
|
||||
return ConnectionError::VersionMismatch;
|
||||
|
||||
|
||||
|
||||
if (m_is_running || m_start_pending)
|
||||
return ConnectionError::GameRunning;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Core/Debugger/PPCDebugInterface.h"
|
||||
#include "Core/GeckoCode.h"
|
||||
#include "Core/GeckoCodeConfig.h"
|
||||
#include "Core/MarioPartyNetplay/Gamestate.h"
|
||||
#include "Core/PowerPC/MMU.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
@ -345,6 +346,8 @@ bool ApplyFramePatches()
|
|||
ApplyPatches(guard, s_on_frame);
|
||||
ApplyMemoryPatches(guard, s_on_frame_memory);
|
||||
|
||||
mpn_per_frame();
|
||||
|
||||
// Run the Gecko code handler
|
||||
Gecko::RunCodeHandler(guard);
|
||||
ActionReplay::RunAllActive(guard);
|
||||
|
|
|
@ -59,6 +59,14 @@
|
|||
<Import Project="$(ExternalsDir)xxhash\exports.props" />
|
||||
<Import Project="$(ExternalsDir)zlib-ng\exports.props" />
|
||||
<Import Project="$(ExternalsDir)zstd\exports.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Core\MarioPartyNetplay\Discord.cpp" />
|
||||
<ClCompile Include="Core\MarioPartyNetplay\Gamestate.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Core\MarioPartyNetplay\Discord.h" />
|
||||
<ClInclude Include="Core\MarioPartyNetplay\Gamestate.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -96,4 +96,5 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga
|
|||
layout->addWidget(close_box);
|
||||
|
||||
setLayout(layout);
|
||||
tab_widget->setCurrentIndex(3);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
<Import Project="$(VSPropsDir)QtCompile.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>Dolphin-MPN</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>Dolphin-MPN</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)Config\Graphics;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
|
@ -408,9 +414,6 @@
|
|||
<ProjectReference Include="$(CoreDir)DolphinLib.vcxproj">
|
||||
<Project>{D79392F7-06D6-4B4B-A39F-4D587C215D3A}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(CoreDir)Common\SCMRevGen.vcxproj">
|
||||
<Project>{41279555-f94f-4ebc-99de-af863c10c5c4}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(DolphinRootDir)Languages\Languages.vcxproj">
|
||||
<Project>{0e033be3-2e08-428e-9ae9-bc673efa12b5}</Project>
|
||||
</ProjectReference>
|
||||
|
@ -444,13 +447,15 @@
|
|||
<!--Copy Exe, Data directory and DLLs which should be located in the executable directory-->
|
||||
<ItemGroup>
|
||||
<DataSysFiles Include="$(DolphinRootDir)Data\**\Sys\**\*.*" />
|
||||
<DataUserFiles Include="$(DolphinRootDir)Data\**\User\**\*.*" />
|
||||
<DataTxtFiles Include="$(DolphinRootDir)Data\license.txt" />
|
||||
<BinaryFiles Include="$(TargetPath)" />
|
||||
<AllInputFiles Include="@(DataSysFiles);@(DataTxtFiles);@(BinaryFiles)" />
|
||||
<AllInputFiles Include="@(DataSysFiles);@(DataUserFiles);@(DataTxtFiles);@(BinaryFiles)" />
|
||||
</ItemGroup>
|
||||
<Target Name="AfterBuild" Inputs="@(AllInputFiles)" Outputs="@(AllInputFiles -> '$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(Extension)')">
|
||||
<Message Text="Copying Data directory..." Importance="High" />
|
||||
<Copy SourceFiles="@(DataSysFiles)" DestinationFolder="$(BinaryOutputDir)%(RecursiveDir)" Condition="!Exists('$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(DataSysFiles.Extension)') OR $([System.DateTime]::Parse('%(ModifiedTime)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(DataSysFiles.Extension)').Ticks)" />
|
||||
<Copy SourceFiles="@(DataUserFiles)" DestinationFolder="$(BinaryOutputDir)%(RecursiveDir)" Condition="!Exists('$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(DataSysFiles.Extension)') OR $([System.DateTime]::Parse('%(ModifiedTime)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(DataSysFiles.Extension)').Ticks)" />
|
||||
<Copy SourceFiles="@(DataTxtFiles)" DestinationFolder="$(BinaryOutputDir)" Condition="!Exists('$(BinaryOutputDir)%(Filename)%(DataTxtFiles.Extension)') OR $([System.DateTime]::Parse('%(ModifiedTime)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(DataTxtFiles.Extension)').Ticks)" />
|
||||
<Message Text="Copy: @(BinaryFiles) -> $(BinaryOutputDir)" Importance="High" />
|
||||
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
|
||||
|
|
|
@ -518,8 +518,6 @@ void MainWindow::ConnectMenuBar()
|
|||
connect(m_menu_bar, &MenuBar::ImportNANDBackup, this, &MainWindow::OnImportNANDBackup);
|
||||
connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate);
|
||||
connect(m_menu_bar, &MenuBar::BootWiiSystemMenu, this, &MainWindow::BootWiiSystemMenu);
|
||||
connect(m_menu_bar, &MenuBar::StartNetPlay, this, &MainWindow::ShowNetPlaySetupDialog);
|
||||
connect(m_menu_bar, &MenuBar::BrowseNetPlay, this, &MainWindow::ShowNetPlayBrowser);
|
||||
connect(m_menu_bar, &MenuBar::ShowFIFOPlayer, this, &MainWindow::ShowFIFOPlayer);
|
||||
connect(m_menu_bar, &MenuBar::ShowSkylanderPortal, this, &MainWindow::ShowSkylanderPortal);
|
||||
connect(m_menu_bar, &MenuBar::ConnectWiiRemote, this, &MainWindow::OnConnectWiiRemote);
|
||||
|
@ -640,6 +638,8 @@ void MainWindow::ConnectToolBar()
|
|||
connect(m_tool_bar, &ToolBar::ControllersPressed, this, &MainWindow::ShowControllersWindow);
|
||||
connect(m_tool_bar, &ToolBar::GraphicsPressed, this, &MainWindow::ShowGraphicsWindow);
|
||||
|
||||
connect(m_tool_bar, &ToolBar::StartNetPlayPressed, this, &MainWindow::ShowNetPlaySetupDialog);
|
||||
|
||||
connect(m_tool_bar, &ToolBar::StepPressed, m_code_widget, &CodeWidget::Step);
|
||||
connect(m_tool_bar, &ToolBar::StepOverPressed, m_code_widget, &CodeWidget::StepOver);
|
||||
connect(m_tool_bar, &ToolBar::StepOutPressed, m_code_widget, &CodeWidget::StepOut);
|
||||
|
@ -947,6 +947,110 @@ bool MainWindow::RequestStop()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::RequestStopNetplay()
|
||||
{
|
||||
if (!Core::IsRunning())
|
||||
{
|
||||
Core::QueueHostJob([this] { OnStopComplete(); }, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool rendered_widget_was_active =
|
||||
m_render_widget->isActiveWindow() && !m_render_widget->isFullScreen();
|
||||
QWidget* confirm_parent = (!m_rendering_to_main && rendered_widget_was_active) ?
|
||||
m_render_widget :
|
||||
static_cast<QWidget*>(this);
|
||||
const bool was_cursor_locked = m_render_widget->IsCursorLocked();
|
||||
|
||||
if (!m_render_widget->isFullScreen())
|
||||
m_render_widget_geometry = m_render_widget->saveGeometry();
|
||||
else
|
||||
FullScreen();
|
||||
|
||||
if (Config::Get(Config::MAIN_CONFIRM_ON_STOP))
|
||||
{
|
||||
if (std::exchange(m_stop_confirm_showing, true))
|
||||
return true;
|
||||
|
||||
Common::ScopeGuard confirm_lock([this] { m_stop_confirm_showing = false; });
|
||||
|
||||
const Core::State state = Core::GetState();
|
||||
|
||||
// Only pause the game, if NetPlay is not running
|
||||
bool pause = !Settings::Instance().GetNetPlayClient();
|
||||
|
||||
if (pause)
|
||||
Core::SetState(Core::State::Paused);
|
||||
|
||||
if (rendered_widget_was_active)
|
||||
{
|
||||
// We have to do this before creating the message box, otherwise we might receive the window
|
||||
// activation event before we know we need to lock the cursor again.
|
||||
m_render_widget->SetCursorLockedOnNextActivation(was_cursor_locked);
|
||||
}
|
||||
|
||||
// This is to avoid any "race conditions" between the "Window Activate" message and the
|
||||
// message box returning, which could break cursor locking depending on the order
|
||||
m_render_widget->SetWaitingForMessageBox(true);
|
||||
auto confirm = ModalMessageBox::question(
|
||||
confirm_parent, tr("Quitter!"),
|
||||
m_stop_requested ? tr("A user closed down their game from the netplay lobby. "
|
||||
"This could the Netplay session has ended due to someone ragequitting! "
|
||||
"Do you want to stop the current emulation?") :
|
||||
tr("A user closed down their game from the netplay lobby. "
|
||||
"This could the Netplay session has ended due to someone ragequitting"
|
||||
"Do you want to stop the current emulation?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton, Qt::ApplicationModal);
|
||||
|
||||
// If a user confirmed stopping the emulation, we do not capture the cursor again,
|
||||
// even if the render widget will stay alive for a while.
|
||||
// If a used rejected stopping the emulation, we instead capture the cursor again,
|
||||
// and let them continue playing as if nothing had happened
|
||||
// (assuming cursor locking is on).
|
||||
if (confirm != QMessageBox::Yes)
|
||||
{
|
||||
m_render_widget->SetWaitingForMessageBox(false);
|
||||
|
||||
if (pause)
|
||||
Core::SetState(state);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_render_widget->SetCursorLockedOnNextActivation(false);
|
||||
// This needs to be after SetCursorLockedOnNextActivation(false) as it depends on it
|
||||
m_render_widget->SetWaitingForMessageBox(false);
|
||||
}
|
||||
}
|
||||
|
||||
OnStopRecording();
|
||||
// TODO: Add Debugger shutdown
|
||||
|
||||
if (!m_stop_requested && UICommon::TriggerSTMPowerEvent())
|
||||
{
|
||||
m_stop_requested = true;
|
||||
|
||||
// Unpause because gracefully shutting down needs the game to actually request a shutdown.
|
||||
// TODO: Do not unpause in debug mode to allow debugging until the complete shutdown.
|
||||
if (Core::GetState() == Core::State::Paused)
|
||||
Core::SetState(Core::State::Running);
|
||||
|
||||
// Tell NetPlay about the power event
|
||||
if (NetPlay::IsNetPlayRunning())
|
||||
NetPlay::SendPowerButtonEvent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ForceStop();
|
||||
#ifdef Q_OS_WIN
|
||||
// Allow windows to idle or turn off display again
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::ForceStop()
|
||||
{
|
||||
Core::Stop();
|
||||
|
@ -1424,10 +1528,11 @@ void MainWindow::NetPlayInit()
|
|||
m_netplay_discord = new DiscordHandler(this);
|
||||
#endif
|
||||
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::ForceStop);
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::RequestStopNetplay);
|
||||
connect(m_netplay_dialog, &NetPlayDialog::rejected, this, &MainWindow::NetPlayQuit);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Join, this, &MainWindow::NetPlayJoin);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Host, this, &MainWindow::NetPlayHost);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::JoinBrowser, this, &MainWindow::NetPlayJoin);
|
||||
#ifdef USE_DISCORD_PRESENCE
|
||||
connect(m_netplay_discord, &DiscordHandler::Join, this, &MainWindow::NetPlayJoin);
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ private:
|
|||
|
||||
// May ask for confirmation. Returns whether or not it actually stopped.
|
||||
bool RequestStop();
|
||||
bool RequestStopNetplay();
|
||||
void ForceStop();
|
||||
void Reset();
|
||||
void FrameAdvance();
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
#include "UICommon/AutoUpdate.h"
|
||||
#include "UICommon/GameFile.h"
|
||||
#include <qprocess.h>
|
||||
|
||||
QPointer<MenuBar> MenuBar::s_menu_bar;
|
||||
|
||||
|
@ -224,11 +225,6 @@ void MenuBar::AddToolsMenu()
|
|||
|
||||
tools_menu->addSeparator();
|
||||
|
||||
tools_menu->addAction(tr("Start &NetPlay..."), this, &MenuBar::StartNetPlay);
|
||||
tools_menu->addAction(tr("Browse &NetPlay Sessions...."), this, &MenuBar::BrowseNetPlay);
|
||||
|
||||
tools_menu->addSeparator();
|
||||
|
||||
QMenu* gc_ipl = tools_menu->addMenu(tr("Load GameCube Main Menu"));
|
||||
|
||||
m_ntscj_ipl = gc_ipl->addAction(tr("NTSC-J"), this,
|
||||
|
@ -296,7 +292,7 @@ void MenuBar::AddToolsMenu()
|
|||
void MenuBar::AddEmulationMenu()
|
||||
{
|
||||
QMenu* emu_menu = addMenu(tr("&Emulation"));
|
||||
m_play_action = emu_menu->addAction(tr("&Play"), this, &MenuBar::Play);
|
||||
m_play_action = emu_menu->addAction(tr("&Local Play"), this, &MenuBar::Play);
|
||||
m_pause_action = emu_menu->addAction(tr("&Pause"), this, &MenuBar::Pause);
|
||||
m_stop_action = emu_menu->addAction(tr("&Stop"), this, &MenuBar::Stop);
|
||||
m_reset_action = emu_menu->addAction(tr("&Reset"), this, &MenuBar::Reset);
|
||||
|
@ -543,16 +539,6 @@ void MenuBar::AddOptionsMenu()
|
|||
m_change_font = options_menu->addAction(tr("&Font..."), this, &MenuBar::ChangeDebugFont);
|
||||
}
|
||||
|
||||
void MenuBar::InstallUpdateManually()
|
||||
{
|
||||
const std::string autoupdate_track = Config::Get(Config::MAIN_AUTOUPDATE_UPDATE_TRACK);
|
||||
const std::string manual_track = autoupdate_track.empty() ? "dev" : autoupdate_track;
|
||||
auto* const updater = new Updater(this->parentWidget(), manual_track,
|
||||
Config::Get(Config::MAIN_AUTOUPDATE_HASH_OVERRIDE));
|
||||
|
||||
updater->CheckForUpdate();
|
||||
}
|
||||
|
||||
void MenuBar::AddHelpMenu()
|
||||
{
|
||||
QMenu* help_menu = addMenu(tr("&Help"));
|
||||
|
@ -574,13 +560,6 @@ void MenuBar::AddHelpMenu()
|
|||
QUrl(QStringLiteral("https://bugs.dolphin-emu.org/projects/emulator")));
|
||||
});
|
||||
|
||||
if (AutoUpdateChecker::SystemSupportsAutoUpdates())
|
||||
{
|
||||
help_menu->addSeparator();
|
||||
|
||||
help_menu->addAction(tr("&Check for Updates..."), this, &MenuBar::InstallUpdateManually);
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
help_menu->addSeparator();
|
||||
#endif
|
||||
|
|
|
@ -63,61 +63,7 @@ void NetPlayBrowser::CreateWidgets()
|
|||
{
|
||||
auto* layout = new QVBoxLayout;
|
||||
|
||||
m_table_widget = new QTableWidget;
|
||||
m_table_widget->setTabKeyNavigation(false);
|
||||
|
||||
m_table_widget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_table_widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_table_widget->setWordWrap(false);
|
||||
|
||||
m_region_combo = new QComboBox;
|
||||
|
||||
m_region_combo->addItem(tr("Any Region"));
|
||||
|
||||
for (const auto& region : NetPlayIndex::GetRegions())
|
||||
{
|
||||
m_region_combo->addItem(
|
||||
tr("%1 (%2)").arg(tr(region.second.c_str())).arg(QString::fromStdString(region.first)),
|
||||
QString::fromStdString(region.first));
|
||||
}
|
||||
|
||||
m_region_combo->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
||||
|
||||
m_status_label = new QLabel;
|
||||
m_button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
m_button_refresh = new NonDefaultQPushButton(tr("Refresh"));
|
||||
m_edit_name = new QLineEdit;
|
||||
m_edit_game_id = new QLineEdit;
|
||||
m_check_hide_incompatible = new QCheckBox(tr("Hide Incompatible Sessions"));
|
||||
m_check_hide_ingame = new QCheckBox(tr("Hide In-Game Sessions"));
|
||||
|
||||
m_check_hide_incompatible->setChecked(true);
|
||||
|
||||
m_radio_all = new QRadioButton(tr("Private and Public"));
|
||||
m_radio_private = new QRadioButton(tr("Private"));
|
||||
m_radio_public = new QRadioButton(tr("Public"));
|
||||
|
||||
m_radio_all->setChecked(true);
|
||||
|
||||
auto* filter_box = new QGroupBox(tr("Filters"));
|
||||
auto* filter_layout = new QGridLayout;
|
||||
filter_box->setLayout(filter_layout);
|
||||
|
||||
filter_layout->addWidget(new QLabel(tr("Region:")), 0, 0);
|
||||
filter_layout->addWidget(m_region_combo, 0, 1, 1, -1);
|
||||
filter_layout->addWidget(new QLabel(tr("Name:")), 1, 0);
|
||||
filter_layout->addWidget(m_edit_name, 1, 1, 1, -1);
|
||||
filter_layout->addWidget(new QLabel(tr("Game ID:")), 2, 0);
|
||||
filter_layout->addWidget(m_edit_game_id, 2, 1, 1, -1);
|
||||
filter_layout->addWidget(m_radio_all, 3, 1);
|
||||
filter_layout->addWidget(m_radio_public, 3, 2);
|
||||
filter_layout->addWidget(m_radio_private, 3, 3);
|
||||
filter_layout->addItem(new QSpacerItem(4, 1, QSizePolicy::Expanding), 3, 4);
|
||||
filter_layout->addWidget(m_check_hide_incompatible, 4, 1, 1, -1);
|
||||
filter_layout->addWidget(m_check_hide_ingame, 5, 1, 1, -1);
|
||||
|
||||
layout->addWidget(m_table_widget);
|
||||
layout->addWidget(filter_box);
|
||||
layout->addWidget(m_status_label);
|
||||
layout->addWidget(m_button_box);
|
||||
|
||||
|
@ -220,7 +166,7 @@ void NetPlayBrowser::UpdateList()
|
|||
|
||||
m_table_widget->clear();
|
||||
m_table_widget->setColumnCount(7);
|
||||
m_table_widget->setHorizontalHeaderLabels({tr("Region"), tr("Name"), tr("Password?"),
|
||||
m_table_widget->setHorizontalHeaderLabels({tr("Name"), tr("Password?"),
|
||||
tr("In-Game?"), tr("Game"), tr("Players"),
|
||||
tr("Version")});
|
||||
|
||||
|
@ -239,26 +185,20 @@ void NetPlayBrowser::UpdateList()
|
|||
{
|
||||
const auto& entry = m_sessions[i];
|
||||
|
||||
auto* region = new QTableWidgetItem(QString::fromStdString(entry.region));
|
||||
auto* name = new QTableWidgetItem(QString::fromStdString(entry.name));
|
||||
auto* password = new QTableWidgetItem(entry.has_password ? tr("Yes") : tr("No"));
|
||||
auto* in_game = new QTableWidgetItem(entry.in_game ? tr("Yes") : tr("No"));
|
||||
auto* game_id = new QTableWidgetItem(QString::fromStdString(entry.game_id));
|
||||
auto* player_count = new QTableWidgetItem(QStringLiteral("%1").arg(entry.player_count));
|
||||
auto* version = new QTableWidgetItem(QString::fromStdString(entry.version));
|
||||
|
||||
const bool enabled = Common::GetScmDescStr() == entry.version;
|
||||
|
||||
for (const auto& item : {region, name, password, in_game, game_id, player_count, version})
|
||||
for (const auto& item : {name, in_game, game_id, player_count})
|
||||
item->setFlags(enabled ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags);
|
||||
|
||||
m_table_widget->setItem(i, 0, region);
|
||||
m_table_widget->setItem(i, 1, name);
|
||||
m_table_widget->setItem(i, 2, password);
|
||||
m_table_widget->setItem(i, 3, in_game);
|
||||
m_table_widget->setItem(i, 4, game_id);
|
||||
m_table_widget->setItem(i, 5, player_count);
|
||||
m_table_widget->setItem(i, 6, version);
|
||||
m_table_widget->setItem(i, 2, in_game);
|
||||
m_table_widget->setItem(i, 3, game_id);
|
||||
m_table_widget->setItem(i, 4, player_count);
|
||||
}
|
||||
|
||||
m_status_label->setText(
|
||||
|
@ -377,8 +317,11 @@ void NetPlayBrowser::RestoreSettings()
|
|||
else if (visibility == QStringLiteral("private"))
|
||||
m_radio_private->setChecked(true);
|
||||
|
||||
m_check_hide_incompatible->setChecked(
|
||||
m_check_hide_incompatible->setChecked(true);
|
||||
m_check_hide_ingame->setChecked(true);
|
||||
|
||||
/* m_check_hide_incompatible->setChecked(
|
||||
settings.value(QStringLiteral("netplaybrowser/hide_incompatible"), true).toBool());
|
||||
m_check_hide_ingame->setChecked(
|
||||
settings.value(QStringLiteral("netplaybrowser/hide_ingame")).toBool());
|
||||
settings.value(QStringLiteral("netplaybrowser/hide_ingame")).toBool());*/
|
||||
}
|
||||
|
|
|
@ -129,6 +129,12 @@ void NetPlayDialog::CreateMainLayout()
|
|||
m_game_button = new QPushButton;
|
||||
m_start_button = new QPushButton(tr("Start"));
|
||||
m_buffer_size_box = new QSpinBox;
|
||||
m_buffer_size_box->setToolTip(
|
||||
tr("Set the buffer based on the ping. The buffer should be ping ÷ 8 (rounded up).\nFor a "
|
||||
"simple method, "
|
||||
"use 8 for 64 ping and less, 12 for 100 ping and less, and 16 for 150 ping and "
|
||||
"less.\nGames above 150 ping will be very laggy and are not recommended for competitive "
|
||||
"play."));
|
||||
m_buffer_label = new QLabel(tr("Buffer:"));
|
||||
m_quit_button = new QPushButton(tr("Quit"));
|
||||
m_splitter = new QSplitter(Qt::Horizontal);
|
||||
|
@ -922,7 +928,7 @@ void NetPlayDialog::OnPadBufferChanged(u32 buffer)
|
|||
});
|
||||
DisplayMessage(m_host_input_authority ? tr("Max buffer size changed to %1").arg(buffer) :
|
||||
tr("Buffer size changed to %1").arg(buffer),
|
||||
"darkcyan");
|
||||
"orange");
|
||||
|
||||
m_buffer_size = static_cast<int>(buffer);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,19 @@
|
|||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QSignalBlocker>
|
||||
#include <QSpinBox>
|
||||
#include <QTabWidget>
|
||||
#include <QTableWidget>
|
||||
#include <QTableWidgetItem>
|
||||
|
||||
#include "Core/Config/NetplaySettings.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
|
@ -25,6 +31,8 @@
|
|||
#include "DolphinQt/QtUtils/UTF8CodePointCountValidator.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "Common/Version.h"
|
||||
#include "DolphinQt/NetPlay/NetPlayBrowser.h"
|
||||
#include "UICommon/GameFile.h"
|
||||
#include "UICommon/NetPlayIndex.h"
|
||||
|
||||
|
@ -37,16 +45,11 @@ NetPlaySetupDialog::NetPlaySetupDialog(const GameListModel& game_list_model, QWi
|
|||
CreateMainLayout();
|
||||
|
||||
bool use_index = Config::Get(Config::NETPLAY_USE_INDEX);
|
||||
std::string index_region = Config::Get(Config::NETPLAY_INDEX_REGION);
|
||||
std::string index_name = Config::Get(Config::NETPLAY_INDEX_NAME);
|
||||
std::string index_password = Config::Get(Config::NETPLAY_INDEX_PASSWORD);
|
||||
std::string nickname = Config::Get(Config::NETPLAY_NICKNAME);
|
||||
std::string traversal_choice = Config::Get(Config::NETPLAY_TRAVERSAL_CHOICE);
|
||||
int connect_port = Config::Get(Config::NETPLAY_CONNECT_PORT);
|
||||
int host_port = Config::Get(Config::NETPLAY_HOST_PORT);
|
||||
int host_listen_port = Config::Get(Config::NETPLAY_LISTEN_PORT);
|
||||
bool enable_chunked_upload_limit = Config::Get(Config::NETPLAY_ENABLE_CHUNKED_UPLOAD_LIMIT);
|
||||
u32 chunked_upload_limit = Config::Get(Config::NETPLAY_CHUNKED_UPLOAD_LIMIT);
|
||||
#ifdef USE_UPNP
|
||||
bool use_upnp = Config::Get(Config::NETPLAY_USE_UPNP);
|
||||
|
||||
|
@ -58,28 +61,41 @@ NetPlaySetupDialog::NetPlaySetupDialog(const GameListModel& game_list_model, QWi
|
|||
m_connect_port_box->setValue(connect_port);
|
||||
m_host_port_box->setValue(host_port);
|
||||
|
||||
m_host_force_port_box->setValue(host_listen_port);
|
||||
m_host_force_port_box->setEnabled(false);
|
||||
|
||||
m_host_server_browser->setChecked(use_index);
|
||||
|
||||
m_host_server_region->setEnabled(use_index);
|
||||
m_host_server_region->setCurrentIndex(
|
||||
m_host_server_region->findData(QString::fromStdString(index_region)));
|
||||
|
||||
m_host_server_name->setEnabled(use_index);
|
||||
m_host_server_name->setText(QString::fromStdString(index_name));
|
||||
|
||||
m_host_server_password->setEnabled(use_index);
|
||||
m_host_server_password->setText(QString::fromStdString(index_password));
|
||||
// Browser Stuff
|
||||
const auto& settings = Settings::Instance().GetQSettings();
|
||||
|
||||
m_host_chunked_upload_limit_check->setChecked(enable_chunked_upload_limit);
|
||||
m_host_chunked_upload_limit_box->setValue(chunked_upload_limit);
|
||||
m_host_chunked_upload_limit_box->setEnabled(enable_chunked_upload_limit);
|
||||
const QByteArray geometry =
|
||||
settings.value(QStringLiteral("netplaybrowser/geometry")).toByteArray();
|
||||
if (!geometry.isEmpty())
|
||||
restoreGeometry(geometry);
|
||||
|
||||
const QString region = settings.value(QStringLiteral("netplaybrowser/region")).toString();
|
||||
const bool valid_region = m_region_combo->findText(region) != -1;
|
||||
if (valid_region)
|
||||
m_region_combo->setCurrentText(region);
|
||||
|
||||
m_edit_name->setText(settings.value(QStringLiteral("netplaybrowser/name")).toString());
|
||||
|
||||
const QString visibility = settings.value(QStringLiteral("netplaybrowser/visibility")).toString();
|
||||
if (visibility == QStringLiteral("public"))
|
||||
m_radio_public->setChecked(true);
|
||||
else if (visibility == QStringLiteral("private"))
|
||||
m_radio_private->setChecked(true);
|
||||
|
||||
m_check_hide_ingame->setChecked(true);
|
||||
|
||||
OnConnectionTypeChanged(m_connection_type->currentIndex());
|
||||
|
||||
ConnectWidgets();
|
||||
|
||||
m_refresh_run.Set(true);
|
||||
m_refresh_thread = std::thread([this] { RefreshLoopBrowser(); });
|
||||
|
||||
UpdateListBrowser();
|
||||
RefreshBrowser();
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::CreateMainLayout()
|
||||
|
@ -88,7 +104,10 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
m_button_box = new QDialogButtonBox(QDialogButtonBox::Cancel);
|
||||
m_nickname_edit = new QLineEdit;
|
||||
m_connection_type = new QComboBox;
|
||||
|
||||
m_connection_type->setCurrentIndex(1);
|
||||
m_reset_traversal_button = new NonDefaultQPushButton(tr("Reset Traversal Settings"));
|
||||
|
||||
m_tab_widget = new QTabWidget;
|
||||
|
||||
m_nickname_edit->setValidator(
|
||||
|
@ -98,6 +117,50 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
auto* connection_widget = new QWidget;
|
||||
auto* connection_layout = new QGridLayout;
|
||||
|
||||
// NetPlay Browser
|
||||
auto* browser_widget = new QWidget;
|
||||
auto* layout = new QVBoxLayout;
|
||||
|
||||
m_table_widget = new QTableWidget;
|
||||
m_table_widget->setTabKeyNavigation(false);
|
||||
|
||||
m_table_widget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_table_widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_table_widget->setWordWrap(false);
|
||||
|
||||
m_region_combo = new QComboBox;
|
||||
|
||||
m_region_combo->addItem(tr("Any Region"));
|
||||
|
||||
for (const auto& region : NetPlayIndex::GetRegions())
|
||||
{
|
||||
m_region_combo->addItem(
|
||||
tr("%1 (%2)").arg(tr(region.second.c_str())).arg(QString::fromStdString(region.first)),
|
||||
QString::fromStdString(region.first));
|
||||
}
|
||||
|
||||
m_region_combo->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
||||
|
||||
m_status_label = new QLabel;
|
||||
m_b_button_box = new QDialogButtonBox;
|
||||
m_button_refresh = new QPushButton(tr("Refresh"));
|
||||
m_edit_name = new QLineEdit;
|
||||
m_check_hide_ingame = new QCheckBox(tr("Hide In-Game Sessions"));
|
||||
|
||||
m_radio_all = new QRadioButton(tr("Private and Public"));
|
||||
m_radio_private = new QRadioButton(tr("Private"));
|
||||
m_radio_public = new QRadioButton(tr("Public"));
|
||||
|
||||
m_radio_all->setChecked(true);
|
||||
|
||||
layout->addWidget(m_table_widget);
|
||||
layout->addWidget(m_status_label);
|
||||
layout->addWidget(m_b_button_box);
|
||||
|
||||
m_b_button_box->addButton(m_button_refresh, QDialogButtonBox::ResetRole);
|
||||
|
||||
browser_widget->setLayout(layout);
|
||||
|
||||
m_ip_label = new QLabel;
|
||||
m_ip_edit = new QLineEdit;
|
||||
m_connect_port_label = new QLabel(tr("Port:"));
|
||||
|
@ -113,7 +176,7 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
connection_layout->addWidget(
|
||||
new QLabel(
|
||||
tr("ALERT:\n\n"
|
||||
"All players must use the same Dolphin version.\n"
|
||||
"All players must use the same Dolphin version, unless Orange Dolphin is used to host\n"
|
||||
"If enabled, SD cards must be identical between players.\n"
|
||||
"If DSP LLE is used, DSP ROMs must be identical between players.\n"
|
||||
"If a game is hanging on boot, it may not support Dual Core Netplay."
|
||||
|
@ -130,16 +193,10 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
// Host widget
|
||||
auto* host_widget = new QWidget;
|
||||
auto* host_layout = new QGridLayout;
|
||||
m_host_port_label = new QLabel(tr("Port:"));
|
||||
m_host_port_box = new QSpinBox;
|
||||
m_host_force_port_check = new QCheckBox(tr("Force Listen Port:"));
|
||||
m_host_force_port_box = new QSpinBox;
|
||||
m_host_chunked_upload_limit_check = new QCheckBox(tr("Limit Chunked Upload Speed:"));
|
||||
m_host_chunked_upload_limit_box = new QSpinBox;
|
||||
m_host_server_browser = new QCheckBox(tr("Show in server browser"));
|
||||
m_host_server_name = new QLineEdit;
|
||||
m_host_server_password = new QLineEdit;
|
||||
m_host_server_region = new QComboBox;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
m_host_upnp = new QCheckBox(tr("Forward port (UPnP)"));
|
||||
|
@ -148,41 +205,17 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
m_host_button = new NonDefaultQPushButton(tr("Host"));
|
||||
|
||||
m_host_port_box->setMaximum(65535);
|
||||
m_host_force_port_box->setMaximum(65535);
|
||||
m_host_chunked_upload_limit_box->setRange(1, 1000000);
|
||||
m_host_chunked_upload_limit_box->setSingleStep(100);
|
||||
m_host_chunked_upload_limit_box->setSuffix(QStringLiteral(" kbps"));
|
||||
|
||||
m_host_chunked_upload_limit_check->setToolTip(tr(
|
||||
"This will limit the speed of chunked uploading per client, which is used for save sync."));
|
||||
|
||||
m_host_server_name->setToolTip(tr("Name of your session shown in the server browser"));
|
||||
m_host_server_name->setPlaceholderText(tr("Name"));
|
||||
m_host_server_password->setToolTip(tr("Password for joining your game (leave empty for none)"));
|
||||
m_host_server_password->setPlaceholderText(tr("Password"));
|
||||
|
||||
for (const auto& region : NetPlayIndex::GetRegions())
|
||||
{
|
||||
m_host_server_region->addItem(
|
||||
tr("%1 (%2)").arg(tr(region.second.c_str())).arg(QString::fromStdString(region.first)),
|
||||
QString::fromStdString(region.first));
|
||||
}
|
||||
|
||||
host_layout->addWidget(m_host_port_label, 0, 0);
|
||||
host_layout->addWidget(m_host_port_box, 0, 1);
|
||||
host_layout->addWidget(m_host_port_box, 0, 0, Qt::AlignLeft);
|
||||
#ifdef USE_UPNP
|
||||
host_layout->addWidget(m_host_upnp, 0, 2);
|
||||
host_layout->addWidget(m_host_upnp, 0, 5, Qt::AlignRight);
|
||||
#endif
|
||||
host_layout->addWidget(m_host_server_browser, 1, 0);
|
||||
host_layout->addWidget(m_host_server_region, 1, 1);
|
||||
host_layout->addWidget(m_host_server_name, 1, 2);
|
||||
host_layout->addWidget(m_host_server_password, 1, 3);
|
||||
host_layout->addWidget(m_host_games, 2, 0, 1, -1);
|
||||
host_layout->addWidget(m_host_force_port_check, 3, 0);
|
||||
host_layout->addWidget(m_host_force_port_box, 3, 1, Qt::AlignLeft);
|
||||
host_layout->addWidget(m_host_chunked_upload_limit_check, 4, 0);
|
||||
host_layout->addWidget(m_host_chunked_upload_limit_box, 4, 1, Qt::AlignLeft);
|
||||
host_layout->addWidget(m_host_button, 4, 3, 2, 1, Qt::AlignRight);
|
||||
host_layout->addWidget(m_host_button, 4, 5, Qt::AlignRight);
|
||||
|
||||
host_widget->setLayout(host_layout);
|
||||
|
||||
|
@ -200,10 +233,21 @@ void NetPlaySetupDialog::CreateMainLayout()
|
|||
// Tabs
|
||||
m_tab_widget->addTab(connection_widget, tr("Connect"));
|
||||
m_tab_widget->addTab(host_widget, tr("Host"));
|
||||
m_tab_widget->addTab(browser_widget, tr("Browser"));
|
||||
|
||||
setLayout(m_main_layout);
|
||||
}
|
||||
|
||||
NetPlaySetupDialog::~NetPlaySetupDialog()
|
||||
{
|
||||
m_refresh_run.Set(false);
|
||||
m_refresh_event.Set();
|
||||
if (m_refresh_thread.joinable())
|
||||
m_refresh_thread.join();
|
||||
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::ConnectWidgets()
|
||||
{
|
||||
connect(m_connection_type, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
|
@ -222,23 +266,12 @@ void NetPlaySetupDialog::ConnectWidgets()
|
|||
m_host_games->item(index)->text());
|
||||
});
|
||||
|
||||
// refresh browser on tab changed
|
||||
connect(m_tab_widget, &QTabWidget::currentChanged, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
|
||||
connect(m_host_games, &QListWidget::itemDoubleClicked, this, &NetPlaySetupDialog::accept);
|
||||
|
||||
connect(m_host_force_port_check, &QCheckBox::toggled,
|
||||
[this](bool value) { m_host_force_port_box->setEnabled(value); });
|
||||
connect(m_host_chunked_upload_limit_check, &QCheckBox::toggled, this, [this](bool value) {
|
||||
m_host_chunked_upload_limit_box->setEnabled(value);
|
||||
SaveSettings();
|
||||
});
|
||||
connect(m_host_chunked_upload_limit_box, qOverload<int>(&QSpinBox::valueChanged), this,
|
||||
&NetPlaySetupDialog::SaveSettings);
|
||||
|
||||
connect(m_host_server_browser, &QCheckBox::toggled, this, &NetPlaySetupDialog::SaveSettings);
|
||||
connect(m_host_server_name, &QLineEdit::textChanged, this, &NetPlaySetupDialog::SaveSettings);
|
||||
connect(m_host_server_password, &QLineEdit::textChanged, this, &NetPlaySetupDialog::SaveSettings);
|
||||
connect(m_host_server_region,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||
&NetPlaySetupDialog::SaveSettings);
|
||||
|
||||
#ifdef USE_UPNP
|
||||
connect(m_host_upnp, &QCheckBox::stateChanged, this, &NetPlaySetupDialog::SaveSettings);
|
||||
|
@ -249,11 +282,26 @@ void NetPlaySetupDialog::ConnectWidgets()
|
|||
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
connect(m_reset_traversal_button, &QPushButton::clicked, this,
|
||||
&NetPlaySetupDialog::ResetTraversalHost);
|
||||
connect(m_host_server_browser, &QCheckBox::toggled, this, [this](bool value) {
|
||||
m_host_server_region->setEnabled(value);
|
||||
m_host_server_name->setEnabled(value);
|
||||
m_host_server_password->setEnabled(value);
|
||||
});
|
||||
|
||||
// Browser Stuff
|
||||
connect(m_region_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&NetPlaySetupDialog::RefreshBrowser);
|
||||
|
||||
connect(m_button_refresh, &QPushButton::clicked, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
|
||||
connect(m_radio_all, &QRadioButton::toggled, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
connect(m_radio_private, &QRadioButton::toggled, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
connect(m_check_hide_ingame, &QRadioButton::toggled, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
|
||||
connect(m_edit_name, &QLineEdit::textChanged, this, &NetPlaySetupDialog::RefreshBrowser);
|
||||
|
||||
connect(m_table_widget, &QTableWidget::itemDoubleClicked, this,
|
||||
&NetPlaySetupDialog::acceptBrowser);
|
||||
|
||||
connect(this, &NetPlaySetupDialog::UpdateStatusRequestedBrowser, this,
|
||||
&NetPlaySetupDialog::OnUpdateStatusRequestedBrowser, Qt::QueuedConnection);
|
||||
connect(this, &NetPlaySetupDialog::UpdateListRequestedBrowser, this,
|
||||
&NetPlaySetupDialog::OnUpdateListRequestedBrowser, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::SaveSettings()
|
||||
|
@ -271,21 +319,27 @@ void NetPlaySetupDialog::SaveSettings()
|
|||
Config::SetBaseOrCurrent(Config::NETPLAY_USE_UPNP, m_host_upnp->isChecked());
|
||||
#endif
|
||||
|
||||
if (m_host_force_port_check->isChecked())
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_LISTEN_PORT,
|
||||
static_cast<u16>(m_host_force_port_box->value()));
|
||||
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_ENABLE_CHUNKED_UPLOAD_LIMIT,
|
||||
m_host_chunked_upload_limit_check->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_CHUNKED_UPLOAD_LIMIT,
|
||||
m_host_chunked_upload_limit_box->value());
|
||||
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_USE_INDEX, m_host_server_browser->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_INDEX_REGION,
|
||||
m_host_server_region->currentData().toString().toStdString());
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_INDEX_REGION, "NA");
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_INDEX_NAME, m_host_server_name->text().toStdString());
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_INDEX_PASSWORD,
|
||||
m_host_server_password->text().toStdString());
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_INDEX_PASSWORD, "");
|
||||
|
||||
|
||||
// Browser Stuff
|
||||
auto& settings = Settings::Instance().GetQSettings();
|
||||
|
||||
settings.setValue(QStringLiteral("netplaybrowser/geometry"), saveGeometry());
|
||||
settings.setValue(QStringLiteral("netplaybrowser/region"), m_region_combo->currentText());
|
||||
settings.setValue(QStringLiteral("netplaybrowser/name"), m_edit_name->text());
|
||||
|
||||
QString visibility(QStringLiteral("all"));
|
||||
if (m_radio_public->isChecked())
|
||||
visibility = QStringLiteral("public");
|
||||
else if (m_radio_private->isChecked())
|
||||
visibility = QStringLiteral("private");
|
||||
settings.setValue(QStringLiteral("netplaybrowser/visibility"), visibility);
|
||||
|
||||
settings.setValue(QStringLiteral("netplaybrowser/hide_incompatible"), true);
|
||||
settings.setValue(QStringLiteral("netplaybrowser/hide_ingame"), m_check_hide_ingame->isChecked());
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::OnConnectionTypeChanged(int index)
|
||||
|
@ -293,14 +347,10 @@ void NetPlaySetupDialog::OnConnectionTypeChanged(int index)
|
|||
m_connect_port_box->setHidden(index != 0);
|
||||
m_connect_port_label->setHidden(index != 0);
|
||||
|
||||
m_host_port_label->setHidden(index != 0);
|
||||
m_host_port_box->setHidden(index != 0);
|
||||
#ifdef USE_UPNP
|
||||
m_host_upnp->setHidden(index != 0);
|
||||
#endif
|
||||
m_host_force_port_check->setHidden(index == 0);
|
||||
m_host_force_port_box->setHidden(index == 0);
|
||||
|
||||
m_reset_traversal_button->setHidden(index == 0);
|
||||
|
||||
std::string address =
|
||||
|
@ -315,6 +365,16 @@ void NetPlaySetupDialog::OnConnectionTypeChanged(int index)
|
|||
|
||||
void NetPlaySetupDialog::show()
|
||||
{
|
||||
// Here i'm setting the lobby name if it's empty to make
|
||||
// NetPlay sessions start more easily for first time players
|
||||
if (m_host_server_name->text().isEmpty())
|
||||
{
|
||||
std::string nickname = Config::Get(Config::NETPLAY_NICKNAME);
|
||||
m_host_server_name->setText(QString::fromStdString(nickname));
|
||||
}
|
||||
m_connection_type->setCurrentIndex(1);
|
||||
m_tab_widget->setCurrentIndex(2); // start on browser
|
||||
|
||||
PopulateGameList();
|
||||
QDialog::show();
|
||||
}
|
||||
|
@ -335,20 +395,6 @@ void NetPlaySetupDialog::accept()
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_host_server_browser->isChecked() && m_host_server_name->text().isEmpty())
|
||||
{
|
||||
ModalMessageBox::critical(this, tr("Error"), tr("You must provide a name for your session!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_host_server_browser->isChecked() &&
|
||||
m_host_server_region->currentData().toString().isEmpty())
|
||||
{
|
||||
ModalMessageBox::critical(this, tr("Error"),
|
||||
tr("You must provide a region for your session!"));
|
||||
return;
|
||||
}
|
||||
|
||||
emit Host(*items[0]->data(Qt::UserRole).value<std::shared_ptr<const UICommon::GameFile>>());
|
||||
}
|
||||
}
|
||||
|
@ -391,3 +437,176 @@ void NetPlaySetupDialog::ResetTraversalHost()
|
|||
.arg(QString::fromStdString(Config::NETPLAY_TRAVERSAL_SERVER.GetDefaultValue()),
|
||||
QString::number(Config::NETPLAY_TRAVERSAL_PORT.GetDefaultValue())));
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::RefreshBrowser()
|
||||
{
|
||||
std::map<std::string, std::string> filters;
|
||||
|
||||
if (!m_edit_name->text().isEmpty())
|
||||
filters["name"] = m_edit_name->text().toStdString();
|
||||
|
||||
if (true)
|
||||
filters["version"] = Common::GetScmDescStr();
|
||||
|
||||
if (!m_radio_all->isChecked())
|
||||
filters["password"] = std::to_string(m_radio_private->isChecked());
|
||||
|
||||
if (m_region_combo->currentIndex() != 0)
|
||||
filters["region"] = m_region_combo->currentData().toString().toStdString();
|
||||
|
||||
if (m_check_hide_ingame->isChecked())
|
||||
filters["in_game"] = "0";
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_refresh_filters_mutex);
|
||||
m_refresh_filters = std::move(filters);
|
||||
m_refresh_event.Set();
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::RefreshLoopBrowser()
|
||||
{
|
||||
while (m_refresh_run.IsSet())
|
||||
{
|
||||
m_refresh_event.Wait();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_refresh_filters_mutex);
|
||||
if (m_refresh_filters)
|
||||
{
|
||||
auto filters = std::move(*m_refresh_filters);
|
||||
m_refresh_filters.reset();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
emit UpdateStatusRequestedBrowser(tr("Refreshing..."));
|
||||
|
||||
NetPlayIndex client;
|
||||
|
||||
auto entries = client.List(filters);
|
||||
|
||||
if (entries)
|
||||
{
|
||||
emit UpdateListRequestedBrowser(std::move(*entries));
|
||||
}
|
||||
else
|
||||
{
|
||||
emit UpdateStatusRequestedBrowser(tr("Error obtaining session list: %1")
|
||||
.arg(QString::fromStdString(client.GetLastError())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::UpdateListBrowser()
|
||||
{
|
||||
const int session_count = static_cast<int>(m_sessions.size());
|
||||
|
||||
m_table_widget->clear();
|
||||
m_table_widget->setColumnCount(4);
|
||||
m_table_widget->setHorizontalHeaderLabels({
|
||||
tr("Name"),
|
||||
tr("Game"),
|
||||
tr("Players"),
|
||||
tr("In-Game"),
|
||||
});
|
||||
|
||||
auto* hor_header = m_table_widget->horizontalHeader();
|
||||
hor_header->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
hor_header->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
hor_header->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
hor_header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
|
||||
hor_header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
|
||||
hor_header->setHighlightSections(false);
|
||||
|
||||
m_table_widget->setRowCount(session_count);
|
||||
|
||||
for (int i = 0; i < session_count; i++)
|
||||
{
|
||||
const auto& entry = m_sessions[i];
|
||||
|
||||
auto* name = new QTableWidgetItem(QString::fromStdString(entry.name));
|
||||
auto* in_game = new QTableWidgetItem(entry.in_game ? tr("Yes") : tr("No"));
|
||||
auto* game_id = new QTableWidgetItem(QString::fromStdString(entry.game_id));
|
||||
auto* player_count = new QTableWidgetItem(QStringLiteral("%1").arg(entry.player_count));
|
||||
|
||||
const bool enabled = Common::GetScmDescStr() == entry.version;
|
||||
|
||||
for (const auto& item : {name, game_id, player_count, in_game})
|
||||
item->setFlags(enabled ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags);
|
||||
|
||||
m_table_widget->setItem(i, 0, name);
|
||||
m_table_widget->setItem(i, 1, game_id);
|
||||
m_table_widget->setItem(i, 2, player_count);
|
||||
m_table_widget->setItem(i, 3, in_game);
|
||||
|
||||
}
|
||||
|
||||
m_status_label->setText(
|
||||
(session_count == 1 ? tr("%1 session found") : tr("%1 sessions found")).arg(session_count));
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::OnSelectionChangedBrowser()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::OnUpdateStatusRequestedBrowser(const QString& status)
|
||||
{
|
||||
m_status_label->setText(status);
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::OnUpdateListRequestedBrowser(std::vector<NetPlaySession> sessions)
|
||||
{
|
||||
m_sessions = std::move(sessions);
|
||||
UpdateListBrowser();
|
||||
}
|
||||
|
||||
void NetPlaySetupDialog::acceptBrowser()
|
||||
{
|
||||
if (m_table_widget->selectedItems().isEmpty())
|
||||
return;
|
||||
|
||||
const int index = m_table_widget->selectedItems()[0]->row();
|
||||
|
||||
NetPlaySession& session = m_sessions[index];
|
||||
|
||||
std::string server_id = session.server_id;
|
||||
|
||||
if (m_sessions[index].has_password)
|
||||
{
|
||||
auto* dialog = new QInputDialog(this);
|
||||
|
||||
dialog->setWindowFlags(dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
dialog->setWindowTitle(tr("Enter password"));
|
||||
dialog->setLabelText(tr("This session requires a password:"));
|
||||
dialog->setWindowModality(Qt::WindowModal);
|
||||
dialog->setTextEchoMode(QLineEdit::Password);
|
||||
|
||||
if (dialog->exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
const std::string password = dialog->textValue().toStdString();
|
||||
|
||||
auto decrypted_id = session.DecryptID(password);
|
||||
|
||||
if (!decrypted_id)
|
||||
{
|
||||
ModalMessageBox::warning(this, tr("Error"), tr("Invalid password provided."));
|
||||
return;
|
||||
}
|
||||
|
||||
server_id = decrypted_id.value();
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_TRAVERSAL_CHOICE, session.method);
|
||||
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_CONNECT_PORT, session.port);
|
||||
|
||||
if (session.method == "traversal")
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_HOST_CODE, server_id);
|
||||
else
|
||||
Config::SetBaseOrCurrent(Config::NETPLAY_ADDRESS, server_id);
|
||||
|
||||
emit JoinBrowser();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "DolphinQt/GameList/GameListModel.h"
|
||||
#include "UICommon/NetPlayIndex.h"
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
|
@ -17,6 +18,9 @@ class QGridLayout;
|
|||
class QPushButton;
|
||||
class QSpinBox;
|
||||
class QTabWidget;
|
||||
class QGroupBox;
|
||||
class QTableWidget;
|
||||
class QRadioButton;
|
||||
|
||||
namespace UICommon
|
||||
{
|
||||
|
@ -28,13 +32,17 @@ class NetPlaySetupDialog : public QDialog
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit NetPlaySetupDialog(const GameListModel& game_list_model, QWidget* parent);
|
||||
~NetPlaySetupDialog();
|
||||
|
||||
void accept() override;
|
||||
void show();
|
||||
|
||||
signals:
|
||||
bool Join();
|
||||
void JoinBrowser();
|
||||
bool Host(const UICommon::GameFile& game);
|
||||
void UpdateStatusRequestedBrowser(const QString& status);
|
||||
void UpdateListRequestedBrowser(std::vector<NetPlaySession> sessions);
|
||||
|
||||
private:
|
||||
void CreateMainLayout();
|
||||
|
@ -42,6 +50,15 @@ private:
|
|||
void PopulateGameList();
|
||||
void ResetTraversalHost();
|
||||
|
||||
// Browser Stuff
|
||||
void RefreshBrowser();
|
||||
void RefreshLoopBrowser();
|
||||
void UpdateListBrowser();
|
||||
void OnSelectionChangedBrowser();
|
||||
void OnUpdateStatusRequestedBrowser(const QString& status);
|
||||
void OnUpdateListRequestedBrowser(std::vector<NetPlaySession> sessions);
|
||||
void acceptBrowser();
|
||||
|
||||
void SaveSettings();
|
||||
|
||||
void OnConnectionTypeChanged(int index);
|
||||
|
@ -62,18 +79,32 @@ private:
|
|||
QPushButton* m_connect_button;
|
||||
|
||||
// Host Widget
|
||||
QLabel* m_host_port_label;
|
||||
QSpinBox* m_host_port_box;
|
||||
QListWidget* m_host_games;
|
||||
QPushButton* m_host_button;
|
||||
QCheckBox* m_host_force_port_check;
|
||||
QSpinBox* m_host_force_port_box;
|
||||
QCheckBox* m_host_chunked_upload_limit_check;
|
||||
QSpinBox* m_host_chunked_upload_limit_box;
|
||||
QCheckBox* m_host_server_browser;
|
||||
QLineEdit* m_host_server_name;
|
||||
QLineEdit* m_host_server_password;
|
||||
QComboBox* m_host_server_region;
|
||||
|
||||
QTableWidget* m_table_widget;
|
||||
QComboBox* m_region_combo;
|
||||
QLabel* m_status_label;
|
||||
QDialogButtonBox* m_b_button_box;
|
||||
QPushButton* m_button_refresh;
|
||||
QLineEdit* m_edit_name;
|
||||
QCheckBox* m_check_hide_ingame;
|
||||
QRadioButton* m_radio_all;
|
||||
QRadioButton* m_radio_private;
|
||||
QRadioButton* m_radio_public;
|
||||
|
||||
std::vector<NetPlaySession> m_sessions;
|
||||
|
||||
std::thread m_refresh_thread;
|
||||
std::optional<std::map<std::string, std::string>> m_refresh_filters;
|
||||
std::mutex m_refresh_filters_mutex;
|
||||
Common::Flag m_refresh_run;
|
||||
Common::Event m_refresh_event;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
QCheckBox* m_host_upnp;
|
||||
|
|
|
@ -65,9 +65,6 @@ void GeneralPane::CreateLayout()
|
|||
// Create layout here
|
||||
CreateBasic();
|
||||
|
||||
if (AutoUpdateChecker::SystemSupportsAutoUpdates())
|
||||
CreateAutoUpdate();
|
||||
|
||||
CreateFallbackRegion();
|
||||
|
||||
#if defined(USE_ANALYTICS) && USE_ANALYTICS
|
||||
|
@ -175,25 +172,6 @@ void GeneralPane::CreateBasic()
|
|||
speed_limit_layout->addRow(tr("&Speed Limit:"), m_combobox_speedlimit);
|
||||
}
|
||||
|
||||
void GeneralPane::CreateAutoUpdate()
|
||||
{
|
||||
auto* auto_update_group = new QGroupBox(tr("Auto Update Settings"));
|
||||
auto* auto_update_group_layout = new QFormLayout;
|
||||
auto_update_group->setLayout(auto_update_group_layout);
|
||||
m_main_layout->addWidget(auto_update_group);
|
||||
|
||||
auto_update_group_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
auto_update_group_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||
|
||||
m_combobox_update_track = new QComboBox(this);
|
||||
|
||||
auto_update_group_layout->addRow(tr("&Auto Update:"), m_combobox_update_track);
|
||||
|
||||
for (const QString& option :
|
||||
{tr("Don't Update"), tr("Beta (once a month)"), tr("Dev (multiple times a day)")})
|
||||
m_combobox_update_track->addItem(option);
|
||||
}
|
||||
|
||||
void GeneralPane::CreateFallbackRegion()
|
||||
{
|
||||
auto* fallback_region_group = new QGroupBox(tr("Fallback Region"));
|
||||
|
|
|
@ -28,7 +28,7 @@ private:
|
|||
void CreateLayout();
|
||||
void ConnectLayout();
|
||||
void CreateBasic();
|
||||
void CreateAutoUpdate();
|
||||
//void CreateAutoUpdate();
|
||||
void CreateFallbackRegion();
|
||||
|
||||
void LoadConfig();
|
||||
|
|
|
@ -128,7 +128,7 @@ void InterfacePane::CreateUI()
|
|||
|
||||
// User Style Combobox
|
||||
m_combobox_userstyle = new QComboBox;
|
||||
m_label_userstyle = new QLabel(tr("User Style:"));
|
||||
m_label_userstyle = new QLabel(tr("Window Theme:"));
|
||||
combobox_layout->addRow(m_label_userstyle, m_combobox_userstyle);
|
||||
|
||||
auto userstyle_search_results = Common::DoFileSearch({File::GetUserPath(D_STYLES_IDX)});
|
||||
|
@ -210,6 +210,7 @@ void InterfacePane::ConnectLayout()
|
|||
{
|
||||
connect(m_checkbox_use_builtin_title_database, &QCheckBox::toggled, this,
|
||||
&InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_use_userstyle, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_use_covers, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_disable_screensaver, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_show_debugging_ui, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
|
|
|
@ -118,9 +118,12 @@ void ToolBar::MakeActions()
|
|||
|
||||
addSeparator();
|
||||
|
||||
m_pause_play_action = addAction(tr("Play"), this, &ToolBar::PlayPressed);
|
||||
|
||||
m_pause_play_action = addAction(tr("Local Play"), this, &ToolBar::PlayPressed);
|
||||
m_start_netplay_action = addAction(tr("Online Play"), this, &ToolBar::StartNetPlayPressed);
|
||||
m_stop_action = addAction(tr("Stop"), this, &ToolBar::StopPressed);
|
||||
|
||||
addSeparator();
|
||||
|
||||
m_fullscreen_action = addAction(tr("FullScr"), this, &ToolBar::FullScreenPressed);
|
||||
m_screenshot_action = addAction(tr("ScrShot"), this, &ToolBar::ScreenShotPressed);
|
||||
|
||||
|
@ -162,7 +165,7 @@ void ToolBar::UpdatePausePlayButtonState(const bool playing_state)
|
|||
else
|
||||
{
|
||||
disconnect(m_pause_play_action, 0, 0, 0);
|
||||
m_pause_play_action->setText(tr("Play"));
|
||||
m_pause_play_action->setText(tr("Local Play"));
|
||||
m_pause_play_action->setIcon(Resources::GetScaledThemeIcon("play"));
|
||||
connect(m_pause_play_action, &QAction::triggered, this, &ToolBar::PlayPressed);
|
||||
}
|
||||
|
@ -193,4 +196,5 @@ void ToolBar::UpdateIcons()
|
|||
m_config_action->setIcon(Resources::GetScaledThemeIcon("config"));
|
||||
m_controllers_action->setIcon(Resources::GetScaledThemeIcon("classic"));
|
||||
m_graphics_action->setIcon(Resources::GetScaledThemeIcon("graphics"));
|
||||
m_start_netplay_action->setIcon(Resources::GetScaledThemeIcon("wifi"));
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ signals:
|
|||
void ControllersPressed();
|
||||
void GraphicsPressed();
|
||||
|
||||
void StartNetPlayPressed();
|
||||
|
||||
void StepPressed();
|
||||
void StepOverPressed();
|
||||
void StepOutPressed();
|
||||
|
@ -58,6 +60,8 @@ private:
|
|||
QAction* m_controllers_action;
|
||||
QAction* m_graphics_action;
|
||||
|
||||
QAction* m_start_netplay_action;
|
||||
|
||||
QAction* m_step_action;
|
||||
QAction* m_step_over_action;
|
||||
QAction* m_step_out_action;
|
||||
|
|
|
@ -195,65 +195,17 @@ void AutoUpdateChecker::CheckForUpdate(std::string_view update_track,
|
|||
version_hash, GetPlatformID());
|
||||
|
||||
const bool is_manual_check = check_type == CheckType::Manual;
|
||||
|
||||
Common::HttpRequest req{std::chrono::seconds{10}};
|
||||
auto resp = req.Get(url);
|
||||
if (!resp)
|
||||
{
|
||||
if (is_manual_check)
|
||||
CriticalAlertFmtT("Unable to contact update server.");
|
||||
return;
|
||||
}
|
||||
const std::string contents(reinterpret_cast<char*>(resp->data()), resp->size());
|
||||
INFO_LOG_FMT(COMMON, "Auto-update JSON response: {}", contents);
|
||||
|
||||
picojson::value json;
|
||||
const std::string err = picojson::parse(json, contents);
|
||||
if (!err.empty())
|
||||
{
|
||||
CriticalAlertFmtT("Invalid JSON received from auto-update service : {0}", err);
|
||||
return;
|
||||
}
|
||||
picojson::object obj = json.get<picojson::object>();
|
||||
|
||||
if (obj["status"].get<std::string>() != "outdated")
|
||||
{
|
||||
if (is_manual_check)
|
||||
SuccessAlertFmtT("You are running the latest version available on this update track.");
|
||||
INFO_LOG_FMT(COMMON, "Auto-update status: we are up to date.");
|
||||
return;
|
||||
}
|
||||
|
||||
NewVersionInformation nvi;
|
||||
nvi.this_manifest_url = obj["old"].get<picojson::object>()["manifest"].get<std::string>();
|
||||
nvi.next_manifest_url = obj["new"].get<picojson::object>()["manifest"].get<std::string>();
|
||||
nvi.content_store_url = obj["content-store"].get<std::string>();
|
||||
nvi.new_shortrev = obj["new"].get<picojson::object>()["name"].get<std::string>();
|
||||
nvi.new_hash = obj["new"].get<picojson::object>()["hash"].get<std::string>();
|
||||
|
||||
// TODO: generate the HTML changelog from the JSON information.
|
||||
nvi.changelog_html = GenerateChangelog(obj["changelog"].get<picojson::array>());
|
||||
|
||||
if (std::getenv("DOLPHIN_UPDATE_TEST_DONE"))
|
||||
{
|
||||
// We are at end of updater test flow, send a message to server, which will kill us.
|
||||
req.Get(fmt::format("{}/update-test-done/{}", GetUpdateServerUrl(), GetOwnProcessId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnUpdateAvailable(nvi);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInformation& info,
|
||||
const AutoUpdateChecker::RestartMode restart_mode)
|
||||
{
|
||||
// Check to make sure we don't already have an update triggered
|
||||
if (s_update_triggered)
|
||||
/* if (s_update_triggered)
|
||||
{
|
||||
WARN_LOG_FMT(COMMON, "Auto-update: received a redundant trigger request, ignoring");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
s_update_triggered = true;
|
||||
#ifdef OS_SUPPORTS_UPDATER
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "UICommon/DiscordPresence.h"
|
||||
|
||||
#include "Common/Hash.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/Config/NetplaySettings.h"
|
||||
#include "Core/Config/UISettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
@ -109,11 +112,6 @@ std::string ArtworkForGameId(const std::string& gameid)
|
|||
"GFT", // GFTE01: Mario Golf: Toadstool Tour
|
||||
"RMC", // RMCE01: Mario Kart Wii
|
||||
"GM4", // GM4E01: Mario Kart: Double Dash!!
|
||||
"GMP", // GMPE01: Mario Party 4
|
||||
"GP5", // GP5E01: Mario Party 5
|
||||
"GP6", // GP6E01: Mario Party 6
|
||||
"GP7", // GP7E01: Mario Party 7
|
||||
"RM8", // RM8E01: Mario Party 8
|
||||
"SSQ", // SSQE01: Mario Party 9
|
||||
"GOM", // GOME01: Mario Power Tennis
|
||||
"GYQ", // GYQE01: Mario Superstar Baseball
|
||||
|
@ -191,7 +189,8 @@ void Init()
|
|||
handlers.ready = HandleDiscordReady;
|
||||
handlers.joinRequest = HandleDiscordJoinRequest;
|
||||
handlers.joinGame = HandleDiscordJoin;
|
||||
Discord_Initialize(DEFAULT_CLIENT_ID.c_str(), &handlers, 1, nullptr);
|
||||
// The number is the client ID for Dolphin, it's used for images and the application name
|
||||
Discord_Initialize("888655408623943731", &handlers, 1, nullptr);
|
||||
UpdateDiscordPresence();
|
||||
#endif
|
||||
}
|
||||
|
@ -283,33 +282,26 @@ void UpdateDiscordPresence(int party_size, SecretType type, const std::string& s
|
|||
DiscordRichPresence discord_presence = {};
|
||||
if (game_artwork.empty())
|
||||
{
|
||||
discord_presence.largeImageKey = "dolphin_logo";
|
||||
discord_presence.largeImageText = "Dolphin is an emulator for the GameCube and the Wii.";
|
||||
discord_presence.largeImageKey = "dolphin";
|
||||
}
|
||||
else
|
||||
{
|
||||
discord_presence.largeImageKey = game_artwork.c_str();
|
||||
discord_presence.largeImageText = title.c_str();
|
||||
discord_presence.smallImageKey = "dolphin_logo";
|
||||
discord_presence.smallImageText = "Dolphin is an emulator for the GameCube and the Wii.";
|
||||
discord_presence.smallImageKey = "dolphin";
|
||||
}
|
||||
discord_presence.details = title.empty() ? "Not in-game" : title.c_str();
|
||||
discord_presence.startTimestamp = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
if (party_size > 0)
|
||||
{
|
||||
if (party_size < 4)
|
||||
{
|
||||
discord_presence.state = "In a party";
|
||||
discord_presence.partySize = party_size;
|
||||
discord_presence.partyMax = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// others can still join to spectate
|
||||
discord_presence.state = "In a full party";
|
||||
discord_presence.partySize = party_size;
|
||||
// Note: joining still works without partyMax
|
||||
}
|
||||
|
|
|
@ -339,60 +339,11 @@ void SetUserDirectory(std::string custom_path)
|
|||
|
||||
local = local != 0 || File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt");
|
||||
|
||||
// Attempt to check if the old User directory exists in Documents.
|
||||
wil::unique_cotaskmem_string documents;
|
||||
bool documents_found = SUCCEEDED(
|
||||
SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, documents.put()));
|
||||
// Get Documents path in case we need it.
|
||||
// TODO: Maybe use WIL when it's available?
|
||||
PWSTR my_documents = nullptr;
|
||||
|
||||
std::optional<std::string> old_user_folder;
|
||||
if (documents_found)
|
||||
{
|
||||
old_user_folder = TStrToUTF8(documents.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||
}
|
||||
|
||||
if (local) // Case 1-2
|
||||
{
|
||||
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
||||
}
|
||||
else if (configPath) // Case 3
|
||||
{
|
||||
user_path = TStrToUTF8(configPath.get());
|
||||
}
|
||||
else if (old_user_folder && File::Exists(old_user_folder.value())) // Case 4
|
||||
{
|
||||
user_path = old_user_folder.value();
|
||||
}
|
||||
else if (appdata_found) // Case 5
|
||||
{
|
||||
user_path = TStrToUTF8(appdata.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||
|
||||
// Set the UserConfigPath value in the registry for backwards compatibility with older Dolphin
|
||||
// builds, which will look for the default User directory in Documents. If we set this key,
|
||||
// they will use this as the User directory instead.
|
||||
// (If we're in this case, then this key doesn't exist, so it's OK to set it.)
|
||||
std::wstring wstr_path = UTF8ToWString(user_path);
|
||||
RegSetKeyValueW(HKEY_CURRENT_USER, TEXT("Software\\Dolphin Emulator"), TEXT("UserConfigPath"),
|
||||
REG_SZ, wstr_path.c_str(),
|
||||
static_cast<DWORD>((wstr_path.size() + 1) * sizeof(wchar_t)));
|
||||
}
|
||||
else // Case 6
|
||||
{
|
||||
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
||||
}
|
||||
#else // ifndef STEAM
|
||||
if (File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt")) // Case 1
|
||||
{
|
||||
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
||||
}
|
||||
else if (appdata_found) // Case 2
|
||||
{
|
||||
user_path = TStrToUTF8(appdata.get()) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
|
||||
}
|
||||
else // Case 3
|
||||
{
|
||||
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
|
||||
}
|
||||
#endif
|
||||
user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
|
||||
|
||||
#else
|
||||
if (File::IsDirectory(ROOT_DIR DIR_SEP EMBEDDED_USER_DIR))
|
||||
|
|
|
@ -197,7 +197,7 @@ void HiresTexture::Prefetch()
|
|||
|
||||
if (size_sum > max_mem)
|
||||
{
|
||||
Config::SetCurrent(Config::GFX_HIRES_TEXTURES, false);
|
||||
Config::SetCurrent(Config::GFX_HIRES_TEXTURES, true);
|
||||
|
||||
OSD::AddMessage(
|
||||
fmt::format(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue