mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Movie: GBA Support
This commit is contained in:
@ -419,7 +419,11 @@ void Init()
|
|||||||
{
|
{
|
||||||
s_desired_device_types[i] = SIDEVICE_NONE;
|
s_desired_device_types[i] = SIDEVICE_NONE;
|
||||||
|
|
||||||
if (Movie::IsUsingPad(i))
|
if (Movie::IsUsingGBA(i))
|
||||||
|
{
|
||||||
|
s_desired_device_types[i] = SIDEVICE_GC_GBA_EMULATED;
|
||||||
|
}
|
||||||
|
else if (Movie::IsUsingPad(i))
|
||||||
{
|
{
|
||||||
SIDevices current = SConfig::GetInstance().m_SIDevice[i];
|
SIDevices current = SConfig::GetInstance().m_SIDevice[i];
|
||||||
// GC pad-compatible devices can be used for both playing and recording
|
// GC pad-compatible devices can be used for both playing and recording
|
||||||
|
@ -82,7 +82,8 @@ static bool s_bReadOnly = true;
|
|||||||
static u32 s_rerecords = 0;
|
static u32 s_rerecords = 0;
|
||||||
static PlayMode s_playMode = MODE_NONE;
|
static PlayMode s_playMode = MODE_NONE;
|
||||||
|
|
||||||
static u8 s_controllers = 0;
|
static std::array<ControllerType, 4> s_controllers{};
|
||||||
|
static std::array<bool, 4> s_wiimotes{};
|
||||||
static ControllerState s_padState;
|
static ControllerState s_padState;
|
||||||
static DTMHeader tmpHeader;
|
static DTMHeader tmpHeader;
|
||||||
static std::vector<u8> s_temp_input;
|
static std::vector<u8> s_temp_input;
|
||||||
@ -157,24 +158,33 @@ std::string GetInputDisplay()
|
|||||||
{
|
{
|
||||||
if (!IsMovieActive())
|
if (!IsMovieActive())
|
||||||
{
|
{
|
||||||
s_controllers = 0;
|
s_controllers = {};
|
||||||
|
s_wiimotes = {};
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
if (SerialInterface::GetDeviceType(i) != SerialInterface::SIDEVICE_NONE)
|
if (SerialInterface::GetDeviceType(i) == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
|
||||||
s_controllers |= (1 << i);
|
s_controllers[i] = ControllerType::GBA;
|
||||||
if (WiimoteCommon::GetSource(i) != WiimoteSource::None)
|
else if (SerialInterface::GetDeviceType(i) != SerialInterface::SIDEVICE_NONE)
|
||||||
s_controllers |= (1 << (i + 4));
|
s_controllers[i] = ControllerType::GC;
|
||||||
|
else
|
||||||
|
s_controllers[i] = ControllerType::None;
|
||||||
|
s_wiimotes[i] = WiimoteCommon::GetSource(i) != WiimoteSource::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string input_display;
|
std::string input_display;
|
||||||
{
|
{
|
||||||
std::lock_guard guard(s_input_display_lock);
|
std::lock_guard guard(s_input_display_lock);
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
if ((s_controllers & (1 << i)) != 0)
|
if (IsUsingPad(i))
|
||||||
input_display += s_InputDisplay[i] + '\n';
|
input_display += s_InputDisplay[i] + '\n';
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (IsUsingWiimote(i))
|
||||||
|
input_display += s_InputDisplay[i + 4] + '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return input_display;
|
return input_display;
|
||||||
}
|
}
|
||||||
@ -386,7 +396,7 @@ void SetReset(bool reset)
|
|||||||
|
|
||||||
bool IsUsingPad(int controller)
|
bool IsUsingPad(int controller)
|
||||||
{
|
{
|
||||||
return ((s_controllers & (1 << controller)) != 0);
|
return s_controllers[controller] != ControllerType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsUsingBongo(int controller)
|
bool IsUsingBongo(int controller)
|
||||||
@ -394,9 +404,14 @@ bool IsUsingBongo(int controller)
|
|||||||
return ((s_bongos & (1 << controller)) != 0);
|
return ((s_bongos & (1 << controller)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUsingGBA(int controller)
|
||||||
|
{
|
||||||
|
return s_controllers[controller] == ControllerType::GBA;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsUsingWiimote(int wiimote)
|
bool IsUsingWiimote(int wiimote)
|
||||||
{
|
{
|
||||||
return ((s_controllers & (1 << (wiimote + 4))) != 0);
|
return s_wiimotes[wiimote];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsConfigSaved()
|
bool IsConfigSaved()
|
||||||
@ -425,21 +440,29 @@ void ChangePads()
|
|||||||
if (!Core::IsRunning())
|
if (!Core::IsRunning())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int controllers = 0;
|
ControllerTypeArray controllers{};
|
||||||
|
|
||||||
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
|
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
if (SConfig::GetInstance().m_SIDevice[i] == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
|
||||||
controllers |= (1 << i);
|
controllers[i] = ControllerType::GBA;
|
||||||
|
else if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
||||||
|
controllers[i] = ControllerType::GC;
|
||||||
|
else
|
||||||
|
controllers[i] = ControllerType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((s_controllers & 0x0F) == controllers)
|
if (s_controllers == controllers)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
|
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
SerialInterface::SIDevices device = SerialInterface::SIDEVICE_NONE;
|
SerialInterface::SIDevices device = SerialInterface::SIDEVICE_NONE;
|
||||||
if (IsUsingPad(i))
|
if (IsUsingGBA(i))
|
||||||
|
{
|
||||||
|
device = SerialInterface::SIDEVICE_GC_GBA_EMULATED;
|
||||||
|
}
|
||||||
|
else if (IsUsingPad(i))
|
||||||
{
|
{
|
||||||
if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
||||||
{
|
{
|
||||||
@ -459,14 +482,15 @@ void ChangePads()
|
|||||||
// NOTE: Host / Emu Threads
|
// NOTE: Host / Emu Threads
|
||||||
void ChangeWiiPads(bool instantly)
|
void ChangeWiiPads(bool instantly)
|
||||||
{
|
{
|
||||||
int controllers = 0;
|
WiimoteEnabledArray wiimotes{};
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||||
if (WiimoteCommon::GetSource(i) != WiimoteSource::None)
|
{
|
||||||
controllers |= (1 << i);
|
wiimotes[i] = WiimoteCommon::GetSource(i) != WiimoteSource::None;
|
||||||
|
}
|
||||||
|
|
||||||
// This is important for Wiimotes, because they can desync easily if they get re-activated
|
// This is important for Wiimotes, because they can desync easily if they get re-activated
|
||||||
if (instantly && (s_controllers >> 4) == controllers)
|
if (instantly && s_wiimotes == wiimotes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto bt = WiiUtils::GetBluetoothEmuDevice();
|
const auto bt = WiiUtils::GetBluetoothEmuDevice();
|
||||||
@ -481,13 +505,16 @@ void ChangeWiiPads(bool instantly)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Host Thread
|
// NOTE: Host Thread
|
||||||
bool BeginRecordingInput(int controllers)
|
bool BeginRecordingInput(const ControllerTypeArray& controllers,
|
||||||
|
const WiimoteEnabledArray& wiimotes)
|
||||||
{
|
{
|
||||||
if (s_playMode != MODE_NONE || controllers == 0)
|
if (s_playMode != MODE_NONE ||
|
||||||
|
(controllers == ControllerTypeArray{} && wiimotes == WiimoteEnabledArray{}))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Core::RunAsCPUThread([controllers] {
|
Core::RunAsCPUThread([controllers, wiimotes] {
|
||||||
s_controllers = controllers;
|
s_controllers = controllers;
|
||||||
|
s_wiimotes = wiimotes;
|
||||||
s_currentFrame = s_totalFrames = 0;
|
s_currentFrame = s_totalFrames = 0;
|
||||||
s_currentLagCount = s_totalLagCount = 0;
|
s_currentLagCount = s_totalLagCount = 0;
|
||||||
s_currentInputCount = s_totalInputCount = 0;
|
s_currentInputCount = s_totalInputCount = 0;
|
||||||
@ -842,7 +869,16 @@ void RecordWiimote(int wiimote, const u8* data, u8 size)
|
|||||||
// NOTE: EmuThread / Host Thread
|
// NOTE: EmuThread / Host Thread
|
||||||
void ReadHeader()
|
void ReadHeader()
|
||||||
{
|
{
|
||||||
s_controllers = tmpHeader.controllers;
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (tmpHeader.GBAControllers & (1 << i))
|
||||||
|
s_controllers[i] = ControllerType::GBA;
|
||||||
|
else if (tmpHeader.controllers & (1 << i))
|
||||||
|
s_controllers[i] = ControllerType::GC;
|
||||||
|
else
|
||||||
|
s_controllers[i] = ControllerType::None;
|
||||||
|
s_wiimotes[i] = (tmpHeader.controllers & (1 << (i + 4))) != 0;
|
||||||
|
}
|
||||||
s_recordingStartTime = tmpHeader.recordingStartTime;
|
s_recordingStartTime = tmpHeader.recordingStartTime;
|
||||||
if (s_rerecords < tmpHeader.numRerecords)
|
if (s_rerecords < tmpHeader.numRerecords)
|
||||||
s_rerecords = tmpHeader.numRerecords;
|
s_rerecords = tmpHeader.numRerecords;
|
||||||
@ -1219,7 +1255,8 @@ bool PlayWiimote(int wiimote, WiimoteCommon::DataReportBuilder& rpt, int ext,
|
|||||||
PanicAlertFmtT(
|
PanicAlertFmtT(
|
||||||
"Fatal desync. Aborting playback. (Error in PlayWiimote: {0} != {1}, byte {2}.){3}",
|
"Fatal desync. Aborting playback. (Error in PlayWiimote: {0} != {1}, byte {2}.){3}",
|
||||||
sizeInMovie, size, s_currentByte,
|
sizeInMovie, size, s_currentByte,
|
||||||
(s_controllers & 0xF) ? " Try re-creating the recording with all GameCube controllers "
|
(s_controllers == ControllerTypeArray{}) ?
|
||||||
|
" Try re-creating the recording with all GameCube controllers "
|
||||||
"disabled (in Configure > GameCube > Device Settings)." :
|
"disabled (in Configure > GameCube > Device Settings)." :
|
||||||
"");
|
"");
|
||||||
EndPlayInput(!s_bReadOnly);
|
EndPlayInput(!s_bReadOnly);
|
||||||
@ -1296,7 +1333,17 @@ void SaveRecording(const std::string& filename)
|
|||||||
strncpy(header.gameID.data(), SConfig::GetInstance().GetGameID().c_str(), 6);
|
strncpy(header.gameID.data(), SConfig::GetInstance().GetGameID().c_str(), 6);
|
||||||
header.bWii = SConfig::GetInstance().bWii;
|
header.bWii = SConfig::GetInstance().bWii;
|
||||||
header.bFollowBranch = SConfig::GetInstance().bJITFollowBranch;
|
header.bFollowBranch = SConfig::GetInstance().bJITFollowBranch;
|
||||||
header.controllers = s_controllers & (SConfig::GetInstance().bWii ? 0xFF : 0x0F);
|
header.controllers = 0;
|
||||||
|
header.GBAControllers = 0;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (IsUsingGBA(i))
|
||||||
|
header.GBAControllers |= 1 << i;
|
||||||
|
if (IsUsingPad(i))
|
||||||
|
header.controllers |= 1 << i;
|
||||||
|
if (IsUsingWiimote(i) && SConfig::GetInstance().bWii)
|
||||||
|
header.controllers |= 1 << (i + 4);
|
||||||
|
}
|
||||||
|
|
||||||
header.bFromSaveState = s_bRecordingFromSaveState;
|
header.bFromSaveState = s_bRecordingFromSaveState;
|
||||||
header.frameCount = s_totalFrames;
|
header.frameCount = s_totalFrames;
|
||||||
|
@ -39,6 +39,15 @@ enum PlayMode
|
|||||||
MODE_PLAYING
|
MODE_PLAYING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ControllerType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
GC,
|
||||||
|
GBA,
|
||||||
|
};
|
||||||
|
using ControllerTypeArray = std::array<ControllerType, 4>;
|
||||||
|
using WiimoteEnabledArray = std::array<bool, 4>;
|
||||||
|
|
||||||
// GameCube Controller State
|
// GameCube Controller State
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct ControllerState
|
struct ControllerState
|
||||||
@ -116,7 +125,8 @@ struct DTMHeader
|
|||||||
u8 reserved3;
|
u8 reserved3;
|
||||||
bool bFollowBranch;
|
bool bFollowBranch;
|
||||||
bool bUseFMA;
|
bool bUseFMA;
|
||||||
std::array<u8, 8> reserved; // Padding for any new config options
|
u8 GBAControllers; // GBA Controllers plugged in (the bits are ports 1-4)
|
||||||
|
std::array<u8, 7> reserved; // Padding for any new config options
|
||||||
std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games.
|
std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games.
|
||||||
std::array<u8, 20> revision; // Git hash
|
std::array<u8, 20> revision; // Git hash
|
||||||
u32 DSPiromHash;
|
u32 DSPiromHash;
|
||||||
@ -163,12 +173,14 @@ bool IsNetPlayRecording();
|
|||||||
bool IsUsingPad(int controller);
|
bool IsUsingPad(int controller);
|
||||||
bool IsUsingWiimote(int wiimote);
|
bool IsUsingWiimote(int wiimote);
|
||||||
bool IsUsingBongo(int controller);
|
bool IsUsingBongo(int controller);
|
||||||
|
bool IsUsingGBA(int controller);
|
||||||
void ChangePads();
|
void ChangePads();
|
||||||
void ChangeWiiPads(bool instantly = false);
|
void ChangeWiiPads(bool instantly = false);
|
||||||
|
|
||||||
void SetReadOnly(bool bEnabled);
|
void SetReadOnly(bool bEnabled);
|
||||||
|
|
||||||
bool BeginRecordingInput(int controllers);
|
bool BeginRecordingInput(const ControllerTypeArray& controllers,
|
||||||
|
const WiimoteEnabledArray& wiimotes);
|
||||||
void RecordInput(const GCPadStatus* PadStatus, int controllerID);
|
void RecordInput(const GCPadStatus* PadStatus, int controllerID);
|
||||||
void RecordWiimote(int wiimote, const u8* data, u8 size);
|
void RecordWiimote(int wiimote, const u8* data, u8 size);
|
||||||
|
|
||||||
|
@ -1606,15 +1606,19 @@ bool NetPlayClient::StartGame(const std::string& path)
|
|||||||
if (Movie::IsReadOnly())
|
if (Movie::IsReadOnly())
|
||||||
Movie::SetReadOnly(false);
|
Movie::SetReadOnly(false);
|
||||||
|
|
||||||
u8 controllers_mask = 0;
|
Movie::ControllerTypeArray controllers{};
|
||||||
|
Movie::WiimoteEnabledArray wiimotes{};
|
||||||
for (unsigned int i = 0; i < 4; ++i)
|
for (unsigned int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
if (m_pad_map[i] > 0)
|
if (m_pad_map[i] > 0 && m_gba_config[i].enabled)
|
||||||
controllers_mask |= (1 << i);
|
controllers[i] = Movie::ControllerType::GBA;
|
||||||
if (m_wiimote_map[i] > 0)
|
else if (m_pad_map[i] > 0)
|
||||||
controllers_mask |= (1 << (i + 4));
|
controllers[i] = Movie::ControllerType::GC;
|
||||||
|
else
|
||||||
|
controllers[i] = Movie::ControllerType::None;
|
||||||
|
wiimotes[i] = m_wiimote_map[i] > 0;
|
||||||
}
|
}
|
||||||
Movie::BeginRecordingInput(controllers_mask);
|
Movie::BeginRecordingInput(controllers, wiimotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 4; ++i)
|
for (unsigned int i = 0; i < 4; ++i)
|
||||||
|
@ -1691,18 +1691,21 @@ void MainWindow::OnStartRecording()
|
|||||||
emit ReadOnlyModeChanged(true);
|
emit ReadOnlyModeChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int controllers = 0;
|
Movie::ControllerTypeArray controllers{};
|
||||||
|
Movie::WiimoteEnabledArray wiimotes{};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
if (SConfig::GetInstance().m_SIDevice[i] == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
|
||||||
controllers |= (1 << i);
|
controllers[i] = Movie::ControllerType::GBA;
|
||||||
|
else if (SerialInterface::SIDevice_IsGCController(SConfig::GetInstance().m_SIDevice[i]))
|
||||||
if (WiimoteCommon::GetSource(i) != WiimoteSource::None)
|
controllers[i] = Movie::ControllerType::GC;
|
||||||
controllers |= (1 << (i + 4));
|
else
|
||||||
|
controllers[i] = Movie::ControllerType::None;
|
||||||
|
wiimotes[i] = WiimoteCommon::GetSource(i) != WiimoteSource::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Movie::BeginRecordingInput(controllers))
|
if (Movie::BeginRecordingInput(controllers, wiimotes))
|
||||||
{
|
{
|
||||||
emit RecordingStatusChanged(true);
|
emit RecordingStatusChanged(true);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user