needs_more_snake_case

This commit is contained in:
Nikhil Narayana 2023-08-20 13:50:43 -07:00
commit 2757adcbc7
No known key found for this signature in database
GPG key ID: 1B34839FA8D6245E
11 changed files with 359 additions and 353 deletions

View file

@ -314,9 +314,9 @@ void CEXISlippi::configureCommands(u8* payload, u8 length)
for (int i = 1; i < length; i += 3)
{
// Go through the receive commands payload and set up other commands
u8 commandByte = payload[i];
u32 commandPayloadSize = payload[i + 1] << 8 | payload[i + 2];
payloadSizes[commandByte] = commandPayloadSize;
u8 command_byte = payload[i];
u32 command_payload_size = payload[i + 1] << 8 | payload[i + 2];
payloadSizes[command_byte] = command_payload_size;
}
}
@ -474,6 +474,7 @@ void CEXISlippi::writeToFileAsync(u8* payload, u32 length, std::string file_opti
void CEXISlippi::FileWriteThread(void)
{
Common::SetCurrentThreadName("Slippi File Write");
while (write_thread_running || !file_write_queue.empty())
{
// Process all messages
@ -703,14 +704,14 @@ void CEXISlippi::prepareGameInfo(u8* payload)
Slippi::GameSettings* settings = m_current_game->GetSettings();
// Unlikely but reset the overclocking in case we quit during a hard ffw in a previous play
SConfig::GetSlippiConfig().oc_enable = g_playback_status->origOCEnable;
SConfig::GetSlippiConfig().oc_factor = g_playback_status->origOCFactor;
SConfig::GetSlippiConfig().oc_enable = g_playback_status->orig_OC_enable;
SConfig::GetSlippiConfig().oc_factor = g_playback_status->orig_OC_factor;
// Start in Fast Forward if this is mirrored
auto replay_comm_settings = g_replay_comm->getSettings();
if (!g_playback_status->isHardFFW)
g_playback_status->isHardFFW = replay_comm_settings.mode == "mirror";
g_playback_status->lastFFWFrame = INT_MIN;
if (!g_playback_status->is_hard_FFW)
g_playback_status->is_hard_FFW = replay_comm_settings.mode == "mirror";
g_playback_status->last_FFW_frame = INT_MIN;
// Build a word containing the stage and the presence of the characters
u32 random_seed = settings->randomSeed;
@ -786,7 +787,7 @@ void CEXISlippi::prepareGameInfo(u8* payload)
m_read_queue.push_back(settings->isFrozenPS);
// Write should resync setting
m_read_queue.push_back(replay_comm_settings.shouldResync ? 1 : 0);
m_read_queue.push_back(replay_comm_settings.should_resync ? 1 : 0);
// Write display names
for (int i = 0; i < 4; i++)
@ -802,7 +803,7 @@ void CEXISlippi::prepareGameInfo(u8* payload)
// Initialize frame sequence index value for reading rollbacks
frame_seq_idx = 0;
if (replay_comm_settings.rollbackDisplayMethod != "off")
if (replay_comm_settings.rollback_display_method != "off")
{
// Prepare savestates
available_savestates.clear();
@ -825,10 +826,10 @@ void CEXISlippi::prepareGameInfo(u8* payload)
}
// Reset playback frame to begining
g_playback_status->currentPlaybackFrame = Slippi::GAME_FIRST_FRAME;
g_playback_status->current_playback_frame = Slippi::GAME_FIRST_FRAME;
// Initialize replay related threads if not viewing rollback versions of relays
if (replay_comm_settings.rollbackDisplayMethod == "off" &&
if (replay_comm_settings.rollback_display_method == "off" &&
(replay_comm_settings.mode == "normal" || replay_comm_settings.mode == "queue"))
{
// g_playback_status->startThreads();
@ -845,7 +846,7 @@ void CEXISlippi::prepareGeckoList()
// Some codes should only be denylisted when not displaying rollbacks, these are codes
// that are required for things to not break when using Slippi savestates. Perhaps this
// should be handled by actually applying these codes in the playback ASM instead? not sure
auto should_deny = replay_comm_settings.rollbackDisplayMethod == "off";
auto should_deny = replay_comm_settings.rollback_display_method == "off";
deny_list[0x8038add0] = should_deny; // Online/Core/PreventFileAlarms/PreventMusicAlarm.asm
deny_list[0x80023FFC] = should_deny; // Online/Core/PreventFileAlarms/MuteMusic.asm
@ -938,19 +939,19 @@ void CEXISlippi::prepareCharacterFrameData(Slippi::FrameData* frame, u8 port, u8
// Add all of the inputs in order
appendWordToBuffer(&m_read_queue, data.randomSeed);
appendWordToBuffer(&m_read_queue, *(u32*)&data.joystickX);
appendWordToBuffer(&m_read_queue, *(u32*)&data.joystickY);
appendWordToBuffer(&m_read_queue, *(u32*)&data.cstickX);
appendWordToBuffer(&m_read_queue, *(u32*)&data.cstickY);
appendWordToBuffer(&m_read_queue, *(u32*)&data.trigger);
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.joystickX));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.joystickY));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.cstickX));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.cstickY));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.trigger));
appendWordToBuffer(&m_read_queue, data.buttons);
appendWordToBuffer(&m_read_queue, *(u32*)&data.locationX);
appendWordToBuffer(&m_read_queue, *(u32*)&data.locationY);
appendWordToBuffer(&m_read_queue, *(u32*)&data.facingDirection);
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.locationX));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.locationY));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.facingDirection));
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.animation));
m_read_queue.push_back(data.joystickXRaw);
m_read_queue.push_back(data.joystickYRaw);
appendWordToBuffer(&m_read_queue, *(u32*)&data.percent);
appendWordToBuffer(&m_read_queue, static_cast<u32>(data.percent));
// NOTE TO DEV: If you add data here, make sure to increase the size above
}
@ -992,11 +993,11 @@ void CEXISlippi::prepareFrameData(u8* payload)
// Parse input
s32 frame_idx = payload[0] << 24 | payload[1] << 16 | payload[2] << 8 | payload[3];
// If loading from queue, move on to the next replay if we have past endFrame
// If loading from queue, move on to the next replay if we have past end_frame
auto watch_settings = g_replay_comm->current;
if (frame_idx > watch_settings.endFrame)
if (frame_idx > watch_settings.end_frame)
{
INFO_LOG_FMT(SLIPPI, "Killing game because we are past endFrame");
INFO_LOG_FMT(SLIPPI, "Killing game because we are past end_frame");
m_read_queue.push_back(FRAME_RESP_TERMINATE);
return;
}
@ -1018,18 +1019,18 @@ void CEXISlippi::prepareFrameData(u8* payload)
// data from this frame. Don't wait until next frame is processing is complete
// (this is the last frame, in that case)
auto is_frame_found = m_current_game->DoesFrameExist(frame_idx);
g_playback_status->lastFrame = m_current_game->GetLatestIndex();
g_playback_status->last_frame = m_current_game->GetLatestIndex();
auto is_frame_complete = checkFrameFullyFetched(frame_idx);
auto is_frame_ready = is_frame_found && (is_processing_complete || is_frame_complete);
// If there is a startFrame configured, manage the fast-forward flag
if (watch_settings.startFrame > Slippi::GAME_FIRST_FRAME)
// If there is a start_frame configured, manage the fast-forward flag
if (watch_settings.start_frame > Slippi::GAME_FIRST_FRAME)
{
if (frame_idx < watch_settings.startFrame)
if (frame_idx < watch_settings.start_frame)
{
g_playback_status->setHardFFW(true);
}
else if (frame_idx == watch_settings.startFrame)
else if (frame_idx == watch_settings.start_frame)
{
// TODO: This might disable fast forward on first frame when we dont want to?
g_playback_status->setHardFFW(false);
@ -1037,11 +1038,11 @@ void CEXISlippi::prepareFrameData(u8* payload)
}
auto comm_settings = g_replay_comm->getSettings();
if (comm_settings.rollbackDisplayMethod == "normal")
if (comm_settings.rollback_display_method == "normal")
{
auto next_frame = m_current_game->GetFrameAt(frame_seq_idx);
bool should_hard_FFW =
next_frame && next_frame->frame <= g_playback_status->currentPlaybackFrame;
next_frame && next_frame->frame <= g_playback_status->current_playback_frame;
g_playback_status->setHardFFW(should_hard_FFW);
if (next_frame)
@ -1053,26 +1054,26 @@ void CEXISlippi::prepareFrameData(u8* payload)
}
// If RealTimeMode is enabled, let's trigger fast forwarding under certain conditions
auto is_far_behind = g_playback_status->lastFrame - frame_idx > 2;
auto is_very_far_behind = g_playback_status->lastFrame - frame_idx > 25;
if (is_far_behind && comm_settings.mode == "mirror" && comm_settings.isRealTimeMode)
auto is_far_behind = g_playback_status->last_frame - frame_idx > 2;
auto is_very_far_behind = g_playback_status->last_frame - frame_idx > 25;
if (is_far_behind && comm_settings.mode == "mirror" && comm_settings.is_real_time_mode)
{
g_playback_status->isSoftFFW = true;
g_playback_status->is_soft_FFW = true;
// Once isHardFFW has been turned on, do not turn it off with this condition, should
// Once is_hard_FFW has been turned on, do not turn it off with this condition, should
// hard FFW to the latest point
if (!g_playback_status->isHardFFW)
g_playback_status->isHardFFW = is_very_far_behind;
if (!g_playback_status->is_hard_FFW)
g_playback_status->is_hard_FFW = is_very_far_behind;
}
if (g_playback_status->lastFrame == frame_idx)
if (g_playback_status->last_frame == frame_idx)
{
// The reason to disable fast forwarding here is in hopes
// of disabling it on the last frame that we have actually received.
// Doing this will allow the rendering logic to run to display the
// last frame instead of the frame previous to fast forwarding.
// Not sure if this fully works with partial frames
g_playback_status->isSoftFFW = false;
g_playback_status->is_soft_FFW = false;
g_playback_status->setHardFFW(false);
}
@ -1088,7 +1089,7 @@ void CEXISlippi::prepareFrameData(u8* payload)
// Disable fast forward here too... this shouldn't be necessary but better
// safe than sorry I guess
g_playback_status->isSoftFFW = false;
g_playback_status->is_soft_FFW = false;
g_playback_status->setHardFFW(false);
if (request_result_code == FRAME_RESP_TERMINATE)
@ -1103,11 +1104,11 @@ void CEXISlippi::prepareFrameData(u8* payload)
u8 rollback_code = 0; // 0 = not rollback, 1 = rollback, perhaps other options in the future?
// Increment frame index if greater
if (frame_idx > g_playback_status->currentPlaybackFrame)
if (frame_idx > g_playback_status->current_playback_frame)
{
g_playback_status->currentPlaybackFrame = frame_idx;
g_playback_status->current_playback_frame = frame_idx;
}
else if (comm_settings.rollbackDisplayMethod != "off")
else if (comm_settings.rollback_display_method != "off")
{
rollback_code = 1;
}
@ -1116,8 +1117,8 @@ void CEXISlippi::prepareFrameData(u8* payload)
if (should_FFW)
{
WARN_LOG_FMT(SLIPPI, "[Frame {}] FFW frame, behind by: {} frames.", frame_idx,
g_playback_status->lastFrame - frame_idx);
g_playback_status->lastFFWFrame = frame_idx;
g_playback_status->last_frame - frame_idx);
g_playback_status->last_FFW_frame = frame_idx;
}
// Return success code
@ -1125,11 +1126,12 @@ void CEXISlippi::prepareFrameData(u8* payload)
// Get frame
Slippi::FrameData* frame = m_current_game->GetFrame(frame_idx);
if (comm_settings.rollbackDisplayMethod != "off")
if (comm_settings.rollback_display_method != "off")
{
auto previous_frame = m_current_game->GetFrameAt(frame_seq_idx - 1);
frame = m_current_game->GetFrameAt(frame_seq_idx);
// SLIPPITODO: document what is going on here
*(s32*)(&playback_savestate_payload[0]) = Common::swap32(frame->frame);
if (previous_frame && frame->frame <= previous_frame->frame)
@ -1157,7 +1159,7 @@ void CEXISlippi::prepareFrameData(u8* payload)
// Add frame rng seed to be restored at priority 0
u8 rng_result = frame->randomSeedExists ? 1 : 0;
m_read_queue.push_back(rng_result);
appendWordToBuffer(&m_read_queue, *(u32*)&frame->randomSeed);
appendWordToBuffer(&m_read_queue, static_cast<u32>(frame->randomSeed));
// Add frame data for every character
for (u8 port = 0; port < 4; port++)
@ -2034,7 +2036,7 @@ void CEXISlippi::prepareOnlineMatchState()
if (mm_state == SlippiMatchmaking::ProcessState::CONNECTION_SUCCESS)
{
m_local_player_index = matchmaking->LocalPlayerIndex();
m_local_player_idx = matchmaking->LocalPlayerIndex();
if (!slippi_netplay)
{
@ -2083,14 +2085,14 @@ void CEXISlippi::prepareOnlineMatchState()
if (remote_player_count == 1)
{
auto is_decider = slippi_netplay->IsDecider();
m_local_player_index = is_decider ? 0 : 1;
m_remote_player_index = is_decider ? 1 : 0;
m_local_player_idx = is_decider ? 0 : 1;
m_remote_player_idx = is_decider ? 1 : 0;
}
#endif
auto is_decider = slippi_netplay->IsDecider();
m_local_player_index = is_decider ? 0 : 1;
m_remote_player_index = is_decider ? 1 : 0;
m_local_player_idx = is_decider ? 0 : 1;
m_remote_player_idx = is_decider ? 1 : 0;
}
else
{
@ -2132,10 +2134,10 @@ void CEXISlippi::prepareOnlineMatchState()
opp_name = p2_name = "Player 2";
#endif
m_read_queue.push_back(local_player_ready); // Local player ready
m_read_queue.push_back(remote_players_ready); // Remote players ready
m_read_queue.push_back(m_local_player_index); // Local player index
m_read_queue.push_back(m_remote_player_index); // Remote player index
m_read_queue.push_back(local_player_ready); // Local player ready
m_read_queue.push_back(remote_players_ready); // Remote players ready
m_read_queue.push_back(m_local_player_idx); // Local player index
m_read_queue.push_back(m_remote_player_idx); // Remote player index
// Set chat message if any
if (slippi_netplay)
@ -2159,13 +2161,12 @@ void CEXISlippi::prepareOnlineMatchState()
}
else
{
chat_message_player_idx = m_local_player_index;
chat_message_player_idx = m_local_player_idx;
}
if (is_single_mode || !matchmaking)
{
chat_message_player_idx =
sent_chat_message_id > 0 ? m_local_player_index : m_remote_player_index;
chat_message_player_idx = sent_chat_message_id > 0 ? m_local_player_idx : m_remote_player_idx;
}
// in CSS p1 is always current player and p2 is opponent
local_player_name = p1_ame = user_info.display_name;
@ -2437,14 +2438,14 @@ void CEXISlippi::prepareOnlineMatchState()
std::vector<std::string> opponent_names = {};
if (matchmaking->RemotePlayerCount() == 1)
{
opponent_names.push_back(matchmaking->GetPlayerName(m_remote_player_index));
opponent_names.push_back(matchmaking->GetPlayerName(m_remote_player_idx));
}
else
{
int team_idx = online_match_block[0x69 + m_local_player_index * 0x24];
int team_idx = online_match_block[0x69 + m_local_player_idx * 0x24];
for (int i = 0; i < 4; i++)
{
if (m_local_player_index == i || online_match_block[0x69 + i * 0x24] == team_idx)
if (m_local_player_idx == i || online_match_block[0x69 + i * 0x24] == team_idx)
continue;
opponent_names.push_back(matchmaking->GetPlayerName(i));
@ -2847,8 +2848,8 @@ void CEXISlippi::handleReportGame(const SlippiExiTypes::ReportGameQuery& query)
SlippiMatchmakingOnlinePlayMode online_mode =
static_cast<SlippiMatchmakingOnlinePlayMode>(query.mode);
u32 duration_frames = query.frame_length;
u32 game_idx = query.game_index;
u32 tiebreak_idx = query.tiebreak_index;
u32 game_idx = query.game_idx;
u32 tiebreak_idx = query.tiebreak_idx;
s8 winner_idx = query.winner_idx;
int stage_id = Common::FromBigEndian(*(u16*)&query.game_info_block[0xE]);
u8 game_end_method = query.game_end_method;
@ -2904,8 +2905,8 @@ void CEXISlippi::handleReportGame(const SlippiExiTypes::ReportGameQuery& query)
{
SlippiSyncedGameState s;
s.match_id = match_id;
s.game_index = game_idx;
s.tiebreak_index = tiebreak_idx;
s.game_idx = game_idx;
s.tiebreak_idx = tiebreak_idx;
s.seconds_remaining = query.synced_timer;
for (int i = 0; i < 4; i++)
{

View file

@ -283,8 +283,8 @@ private:
// We put these at the class level to preserve values in the case of a disconnect
// while loading. Without this, someone could load into a game playing the wrong char
u8 m_local_player_index = 0;
u8 m_remote_player_index = 1;
u8 m_local_player_idx = 0;
u8 m_remote_player_idx = 1;
// Frame skipping variables
int frames_to_skip = 0;

View file

@ -27,8 +27,8 @@ struct ReportGameQuery
u8 command;
u8 mode;
u32 frame_length;
u32 game_index;
u32 tiebreak_index;
u32 game_idx;
u32 tiebreak_idx;
s8 winner_idx;
u8 game_end_method;
s8 lras_initiator;
@ -119,8 +119,8 @@ inline ReportGameQuery Convert(u8* payload)
{
auto q = *reinterpret_cast<ReportGameQuery*>(payload);
q.frame_length = Common::FromBigEndian(q.frame_length);
q.game_index = Common::FromBigEndian(q.game_index);
q.tiebreak_index = Common::FromBigEndian(q.tiebreak_index);
q.game_idx = Common::FromBigEndian(q.game_idx);
q.tiebreak_idx = Common::FromBigEndian(q.tiebreak_idx);
q.synced_timer = Common::FromBigEndian(q.synced_timer);
for (int i = 0; i < REPORT_PLAYER_COUNT; i++)
{

View file

@ -504,8 +504,8 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet, ENetPeer* peer)
SlippiSyncedGameState results;
packet >> results.match_id;
packet >> results.game_index;
packet >> results.tiebreak_index;
packet >> results.game_idx;
packet >> results.tiebreak_idx;
packet >> results.seconds_remaining;
for (int i = 0; i < 4; i++)
{
@ -515,7 +515,7 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet, ENetPeer* peer)
// ERROR_LOG_FMT(SLIPPI_ONLINE, "Received synced state from opponent. {}, {}, {}, {}. F1: {}
// ({}%%), F2: {} ({}%%)",
// results.match_id, results.game_index, results.tiebreak_index,
// results.match_id, results.game_idx, results.tiebreak_idx,
// results.seconds_remaining, results.fighters[0].stocks_remaining,
// results.fighters[0].current_health, results.fighters[1].stocks_remaining,
// results.fighters[1].current_health);
@ -1193,8 +1193,8 @@ void SlippiNetplayClient::SendSyncedGameState(SlippiSyncedGameState& s)
*spac << static_cast<u8>(NetPlay::MessageID::SLIPPI_SYNCED_STATE);
*spac << this->m_player_idx;
*spac << s.match_id;
*spac << s.game_index;
*spac << s.tiebreak_index;
*spac << s.game_idx;
*spac << s.tiebreak_idx;
*spac << s.seconds_remaining;
for (int i = 0; i < 4; i++)
{
@ -1454,10 +1454,10 @@ bool SlippiNetplayClient::IsWaitingForDesyncRecovery()
for (int i = 0; i < m_remotePlayerCount; i++)
{
if (local_sync_state.game_index != remote_sync_states[i].game_index)
if (local_sync_state.game_idx != remote_sync_states[i].game_idx)
return true;
if (local_sync_state.tiebreak_index != remote_sync_states[i].tiebreak_index)
if (local_sync_state.tiebreak_idx != remote_sync_states[i].tiebreak_idx)
return true;
}

View file

@ -58,8 +58,8 @@ struct SlippiSyncedFighterState
struct SlippiSyncedGameState
{
std::string match_id = "";
u32 game_index = 0;
u32 tiebreak_index = 0;
u32 game_idx = 0;
u32 tiebreak_idx = 0;
u32 seconds_remaining = 480;
SlippiSyncedFighterState fighters[4];
};

View file

@ -23,14 +23,14 @@ std::unique_ptr<SlippiPlaybackStatus> g_playback_status;
extern std::unique_ptr<SlippiReplayComm> g_replay_comm;
static std::mutex mtx;
static std::mutex seekMtx;
static std::mutex ffwMtx;
static std::mutex diffMtx;
static std::unique_lock<std::mutex> processingLock(diffMtx);
static std::condition_variable condVar;
static std::condition_variable cv_waitingForTargetFrame;
static std::condition_variable cv_processingDiff;
static std::atomic<int> numDiffsProcessing(0);
static std::mutex seek_mtx;
static std::mutex ffw_mtx;
static std::mutex diff_mtx;
static std::unique_lock<std::mutex> processing_lock(diff_mtx);
static std::condition_variable cond_var;
static std::condition_variable cv_waiting_for_target_frame;
static std::condition_variable cv_processing_diff;
static std::atomic<int> num_diffs_processing(0);
s32 emod(s32 a, s32 b)
{
@ -39,33 +39,33 @@ s32 emod(s32 a, s32 b)
return r >= 0 ? r : r + std::abs(b);
}
std::string processDiff(std::vector<u8> iState, std::vector<u8> cState)
std::string processDiff(std::vector<u8> initial_state, std::vector<u8> curr_state)
{
INFO_LOG_FMT(SLIPPI, "Processing diff");
numDiffsProcessing += 1;
cv_processingDiff.notify_one();
num_diffs_processing += 1;
cv_processing_diff.notify_one();
std::string diff = std::string();
open_vcdiff::VCDiffEncoder encoder((char*)iState.data(), iState.size());
encoder.Encode((char*)cState.data(), cState.size(), &diff);
open_vcdiff::VCDiffEncoder encoder((char*)initial_state.data(), initial_state.size());
encoder.Encode((char*)curr_state.data(), curr_state.size(), &diff);
INFO_LOG_FMT(SLIPPI, "done processing");
numDiffsProcessing -= 1;
cv_processingDiff.notify_one();
num_diffs_processing -= 1;
cv_processing_diff.notify_one();
return diff;
}
SlippiPlaybackStatus::SlippiPlaybackStatus()
{
shouldJumpBack = false;
shouldJumpForward = false;
inSlippiPlayback = false;
shouldRunThreads = false;
isHardFFW = false;
isSoftFFW = false;
lastFFWFrame = INT_MIN;
currentPlaybackFrame = INT_MIN;
targetFrameNum = INT_MAX;
lastFrame = Slippi::PLAYBACK_FIRST_SAVE;
should_jump_back = false;
should_jump_forward = false;
in_slippi_playback = false;
should_run_threads = false;
is_hard_FFW = false;
is_soft_FFW = false;
last_FFW_frame = INT_MIN;
current_playback_frame = INT_MIN;
target_frame_num = INT_MAX;
last_frame = Slippi::PLAYBACK_FIRST_SAVE;
#ifdef IS_PLAYBACK
// Only generate these if this is a playback configuration. Should this class get initialized at
// all?
@ -76,61 +76,62 @@ SlippiPlaybackStatus::SlippiPlaybackStatus()
void SlippiPlaybackStatus::startThreads()
{
shouldRunThreads = true;
m_savestateThread = std::thread(&SlippiPlaybackStatus::SavestateThread, this);
should_run_threads = true;
m_savestate_thread = std::thread(&SlippiPlaybackStatus::SavestateThread, this);
}
void SlippiPlaybackStatus::prepareSlippiPlayback(s32& frameIndex)
void SlippiPlaybackStatus::prepareSlippiPlayback(s32& frame_idx)
{
// block if there's too many diffs being processed
while (shouldRunThreads && numDiffsProcessing > 2)
while (should_run_threads && num_diffs_processing > 2)
{
INFO_LOG_FMT(SLIPPI, "Processing too many diffs, blocking main process");
cv_processingDiff.wait(processingLock);
cv_processing_diff.wait(processing_lock);
}
// Unblock thread to save a state every interval
if (shouldRunThreads && ((currentPlaybackFrame + 122) % FRAME_INTERVAL == 0))
condVar.notify_one();
if (should_run_threads && ((current_playback_frame + 122) % FRAME_INTERVAL == 0))
cond_var.notify_one();
// TODO: figure out why sometimes playback frame increments past targetFrameNum
if (inSlippiPlayback && frameIndex >= targetFrameNum)
// TODO: figure out why sometimes playback frame increments past target_frame_num
if (in_slippi_playback && frame_idx >= target_frame_num)
{
INFO_LOG_FMT(SLIPPI, "Reached frame {}. Target was {}. Unblocking", frameIndex, targetFrameNum);
cv_waitingForTargetFrame.notify_one();
INFO_LOG_FMT(SLIPPI, "Reached frame {}. Target was {}. Unblocking", frame_idx,
target_frame_num);
cv_waiting_for_target_frame.notify_one();
}
}
void SlippiPlaybackStatus::resetPlayback()
{
if (shouldRunThreads)
if (should_run_threads)
{
shouldRunThreads = false;
should_run_threads = false;
if (m_savestateThread.joinable())
m_savestateThread.detach();
if (m_savestate_thread.joinable())
m_savestate_thread.detach();
condVar.notify_one(); // Will allow thread to kill itself
futureDiffs.clear();
futureDiffs.rehash(0);
cond_var.notify_one(); // Will allow thread to kill itself
future_diffs.clear();
future_diffs.rehash(0);
}
shouldJumpBack = false;
shouldJumpForward = false;
isHardFFW = false;
isSoftFFW = false;
targetFrameNum = INT_MAX;
inSlippiPlayback = false;
should_jump_back = false;
should_jump_forward = false;
is_hard_FFW = false;
is_soft_FFW = false;
target_frame_num = INT_MAX;
in_slippi_playback = false;
}
void SlippiPlaybackStatus::processInitialState()
{
INFO_LOG_FMT(SLIPPI, "saving iState");
State::SaveToBuffer(iState);
// The initial save to cState causes a stutter of about 5-10 frames
INFO_LOG_FMT(SLIPPI, "saving initial_state");
State::SaveToBuffer(initial_state);
// The initial save to curr_state causes a stutter of about 5-10 frames
// Doing it here to get it out of the way and prevent stutters later
// Subsequent calls to SaveToBuffer for cState take ~1 frame
State::SaveToBuffer(cState);
// Subsequent calls to SaveToBuffer for curr_state take ~1 frame
State::SaveToBuffer(curr_state);
if (Config::Get(Config::SLIPPI_ENABLE_SEEK))
{
Config::SetCurrent(Config::MAIN_SHOW_CURSOR, Config::ShowCursor::Constantly);
@ -140,39 +141,40 @@ void SlippiPlaybackStatus::processInitialState()
void SlippiPlaybackStatus::SavestateThread()
{
Common::SetCurrentThreadName("Savestate thread");
std::unique_lock<std::mutex> intervalLock(mtx);
std::unique_lock<std::mutex> interval_lock(mtx);
INFO_LOG_FMT(SLIPPI, "Entering savestate thread");
while (shouldRunThreads)
while (should_run_threads)
{
// Wait to hit one of the intervals
// Possible while rewinding that we hit this wait again.
while (shouldRunThreads &&
(currentPlaybackFrame - Slippi::PLAYBACK_FIRST_SAVE) % FRAME_INTERVAL != 0)
condVar.wait(intervalLock);
while (should_run_threads &&
(current_playback_frame - Slippi::PLAYBACK_FIRST_SAVE) % FRAME_INTERVAL != 0)
cond_var.wait(interval_lock);
if (!shouldRunThreads)
if (!should_run_threads)
break;
s32 fixedFrameNumber = currentPlaybackFrame;
if (fixedFrameNumber == INT_MAX)
s32 fixed_frame_num = current_playback_frame;
if (fixed_frame_num == INT_MAX)
continue;
bool isStartFrame = fixedFrameNumber == Slippi::PLAYBACK_FIRST_SAVE;
bool hasStateBeenProcessed = futureDiffs.count(fixedFrameNumber) > 0;
bool is_start_frame = fixed_frame_num == Slippi::PLAYBACK_FIRST_SAVE;
bool has_state_been_processed = future_diffs.count(fixed_frame_num) > 0;
if (!inSlippiPlayback && isStartFrame)
if (!in_slippi_playback && is_start_frame)
{
processInitialState();
inSlippiPlayback = true;
in_slippi_playback = true;
}
else if (Config::Get(Config::SLIPPI_ENABLE_SEEK) && !hasStateBeenProcessed && !isStartFrame)
else if (Config::Get(Config::SLIPPI_ENABLE_SEEK) && !has_state_been_processed &&
!is_start_frame)
{
INFO_LOG_FMT(SLIPPI, "saving diff at frame: {}", fixedFrameNumber);
State::SaveToBuffer(cState);
INFO_LOG_FMT(SLIPPI, "saving diff at frame: {}", fixed_frame_num);
State::SaveToBuffer(curr_state);
futureDiffs[fixedFrameNumber] = std::async(processDiff, iState, cState);
future_diffs[fixed_frame_num] = std::async(processDiff, initial_state, curr_state);
}
Common::SleepCurrentThread(SLEEP_TIME_MS);
}
@ -182,82 +184,82 @@ void SlippiPlaybackStatus::SavestateThread()
void SlippiPlaybackStatus::seekToFrame()
{
if (seekMtx.try_lock())
if (seek_mtx.try_lock())
{
if (targetFrameNum < Slippi::PLAYBACK_FIRST_SAVE)
targetFrameNum = Slippi::PLAYBACK_FIRST_SAVE;
if (target_frame_num < Slippi::PLAYBACK_FIRST_SAVE)
target_frame_num = Slippi::PLAYBACK_FIRST_SAVE;
if (targetFrameNum > lastFrame)
if (target_frame_num > last_frame)
{
targetFrameNum = lastFrame;
target_frame_num = last_frame;
}
std::unique_lock<std::mutex> ffwLock(ffwMtx);
auto replayCommSettings = g_replay_comm->getSettings();
if (replayCommSettings.mode == "queue")
std::unique_lock<std::mutex> ffw_lock(ffw_mtx);
auto replay_comm_settings = g_replay_comm->getSettings();
if (replay_comm_settings.mode == "queue")
updateWatchSettingsStartEnd();
auto prevState = Core::GetState();
if (prevState != Core::State::Paused)
auto prev_state = Core::GetState();
if (prev_state != Core::State::Paused)
Core::SetState(Core::State::Paused);
s32 closestStateFrame =
targetFrameNum - emod(targetFrameNum - Slippi::PLAYBACK_FIRST_SAVE, FRAME_INTERVAL);
bool isLoadingStateOptimal =
targetFrameNum < currentPlaybackFrame || closestStateFrame > currentPlaybackFrame;
s32 closest_state_frame =
target_frame_num - emod(target_frame_num - Slippi::PLAYBACK_FIRST_SAVE, FRAME_INTERVAL);
bool is_loading_state_optimal =
target_frame_num < current_playback_frame || closest_state_frame > current_playback_frame;
if (isLoadingStateOptimal)
if (is_loading_state_optimal)
{
if (closestStateFrame <= Slippi::PLAYBACK_FIRST_SAVE)
if (closest_state_frame <= Slippi::PLAYBACK_FIRST_SAVE)
{
State::LoadFromBuffer(iState);
State::LoadFromBuffer(initial_state);
}
else
{
// If this diff exists, load it
if (futureDiffs.count(closestStateFrame) > 0)
if (future_diffs.count(closest_state_frame) > 0)
{
loadState(closestStateFrame);
loadState(closest_state_frame);
}
else if (targetFrameNum < currentPlaybackFrame)
else if (target_frame_num < current_playback_frame)
{
s32 closestActualStateFrame = closestStateFrame - FRAME_INTERVAL;
while (closestActualStateFrame > Slippi::PLAYBACK_FIRST_SAVE &&
futureDiffs.count(closestActualStateFrame) == 0)
closestActualStateFrame -= FRAME_INTERVAL;
loadState(closestActualStateFrame);
s32 closest_actual_state_frame = closest_state_frame - FRAME_INTERVAL;
while (closest_actual_state_frame > Slippi::PLAYBACK_FIRST_SAVE &&
future_diffs.count(closest_actual_state_frame) == 0)
closest_actual_state_frame -= FRAME_INTERVAL;
loadState(closest_actual_state_frame);
}
else if (targetFrameNum > currentPlaybackFrame)
else if (target_frame_num > current_playback_frame)
{
s32 closestActualStateFrame = closestStateFrame - FRAME_INTERVAL;
while (closestActualStateFrame > currentPlaybackFrame &&
futureDiffs.count(closestActualStateFrame) == 0)
closestActualStateFrame -= FRAME_INTERVAL;
s32 closest_actual_state_frame = closest_state_frame - FRAME_INTERVAL;
while (closest_actual_state_frame > current_playback_frame &&
future_diffs.count(closest_actual_state_frame) == 0)
closest_actual_state_frame -= FRAME_INTERVAL;
// only load a savestate if we find one past our current frame since we are seeking
// forwards
if (closestActualStateFrame > currentPlaybackFrame)
loadState(closestActualStateFrame);
if (closest_actual_state_frame > current_playback_frame)
loadState(closest_actual_state_frame);
}
}
}
// Fastforward until we get to the frame we want
if (targetFrameNum != closestStateFrame && targetFrameNum != lastFrame)
if (target_frame_num != closest_state_frame && target_frame_num != last_frame)
{
setHardFFW(true);
Core::SetState(Core::State::Running);
cv_waitingForTargetFrame.wait(ffwLock);
cv_waiting_for_target_frame.wait(ffw_lock);
Core::SetState(Core::State::Paused);
setHardFFW(false);
}
// We've reached the frame we want. Reset targetFrameNum and release mutex so another seek can
// We've reached the frame we want. Reset target_frame_num and release mutex so another seek can
// be performed
g_playback_status->currentPlaybackFrame = targetFrameNum;
targetFrameNum = INT_MAX;
Core::SetState(prevState);
seekMtx.unlock();
g_playback_status->current_playback_frame = target_frame_num;
target_frame_num = INT_MAX;
Core::SetState(prev_state);
seek_mtx.unlock();
}
else
{
@ -265,7 +267,7 @@ void SlippiPlaybackStatus::seekToFrame()
}
}
// Set isHardFFW and update OC settings to speed up the FFW
// Set is_hard_FFW and update OC settings to speed up the FFW
void SlippiPlaybackStatus::setHardFFW(bool enable)
{
if (enable)
@ -275,36 +277,36 @@ void SlippiPlaybackStatus::setHardFFW(bool enable)
}
else
{
SConfig::GetSlippiConfig().oc_factor = origOCFactor;
SConfig::GetSlippiConfig().oc_enable = origOCEnable;
SConfig::GetSlippiConfig().oc_factor = orig_OC_factor;
SConfig::GetSlippiConfig().oc_enable = orig_OC_enable;
}
isHardFFW = enable;
is_hard_FFW = enable;
}
void SlippiPlaybackStatus::loadState(s32 closestStateFrame)
void SlippiPlaybackStatus::loadState(s32 closest_state_frame)
{
if (closestStateFrame == Slippi::PLAYBACK_FIRST_SAVE)
State::LoadFromBuffer(iState);
if (closest_state_frame == Slippi::PLAYBACK_FIRST_SAVE)
State::LoadFromBuffer(initial_state);
else
{
std::string stateString;
decoder.Decode((char*)iState.data(), iState.size(), futureDiffs[closestStateFrame].get(),
&stateString);
std::vector<u8> stateToLoad(stateString.begin(), stateString.end());
State::LoadFromBuffer(stateToLoad);
std::string state_string;
decoder.Decode((char*)initial_state.data(), initial_state.size(),
future_diffs[closest_state_frame].get(), &state_string);
std::vector<u8> state_to_load(state_string.begin(), state_string.end());
State::LoadFromBuffer(state_to_load);
}
}
bool SlippiPlaybackStatus::shouldFFWFrame(s32 frameIndex) const
bool SlippiPlaybackStatus::shouldFFWFrame(s32 frame_idx) const
{
if (!isSoftFFW && !isHardFFW)
if (!is_soft_FFW && !is_hard_FFW)
{
// If no FFW at all, don't FFW this frame
return false;
}
if (isHardFFW)
if (is_hard_FFW)
{
// For a hard FFW, always FFW until it's turned off
return true;
@ -312,30 +314,30 @@ bool SlippiPlaybackStatus::shouldFFWFrame(s32 frameIndex) const
// Here we have a soft FFW, we only want to turn on FFW for single frames once
// every X frames to FFW in a more smooth manner
return (frameIndex - lastFFWFrame) >= 15;
return (frame_idx - last_FFW_frame) >= 15;
}
void SlippiPlaybackStatus::updateWatchSettingsStartEnd()
{
int startFrame = g_replay_comm->current.startFrame;
int endFrame = g_replay_comm->current.endFrame;
if (startFrame != Slippi::GAME_FIRST_FRAME || endFrame != INT_MAX)
int start_frame = g_replay_comm->current.start_frame;
int end_frame = g_replay_comm->current.end_frame;
if (start_frame != Slippi::GAME_FIRST_FRAME || end_frame != INT_MAX)
{
if (g_playback_status->targetFrameNum < startFrame)
g_replay_comm->current.startFrame = g_playback_status->targetFrameNum;
if (g_playback_status->targetFrameNum > endFrame)
g_replay_comm->current.endFrame = INT_MAX;
if (g_playback_status->target_frame_num < start_frame)
g_replay_comm->current.start_frame = g_playback_status->target_frame_num;
if (g_playback_status->target_frame_num > end_frame)
g_replay_comm->current.end_frame = INT_MAX;
}
}
std::unordered_map<u32, bool> SlippiPlaybackStatus::getDenylist()
{
return denylist;
return deny_list;
}
std::vector<u8> SlippiPlaybackStatus::getLegacyCodelist()
{
return legacyCodelist;
return legacy_code_list;
}
inline std::string readString(json obj, std::string key)
@ -378,10 +380,10 @@ bool compareInjectionList(File::FSTEntry i1, File::FSTEntry i2)
void SlippiPlaybackStatus::generateDenylist()
{
// We start by populating the denylist with old injections that are not longer used but need
// We start by populating the deny_list with old injections that are not longer used but need
// to be included for backward compatibility reasons.
// It also includes some common codes that are not in our codebase
denylist = {
deny_list = {
// Backward compatibility
// Post 3.4.0: Recording/FlushFrameBuffer.asm
{0x802fef88, true},
@ -450,30 +452,30 @@ void SlippiPlaybackStatus::generateDenylist()
}
// Check if tags indicate that this code affects gameplay, if so, do not put it on the
// denylist
// deny_list
auto tags = readString(injection, "Tags");
bool shouldDeny = tags.find("[affects-gameplay]") == std::string::npos;
bool should_deny = tags.find("[affects-gameplay]") == std::string::npos;
// Add injection to denylist
// Add injection to deny_list
u32 address;
auto addressStr = readString(injection, "InjectionAddress");
if (Common::FromChars(addressStr, address, 16).ec != std::errc{})
auto address_str = readString(injection, "InjectionAddress");
if (Common::FromChars(address_str, address, 16).ec != std::errc{})
{
ERROR_LOG_FMT(SLIPPI, "Injection list file {}: Could not parse address: {}",
entry.physicalName, addressStr);
entry.physicalName, address_str);
continue;
}
denylist[address] = shouldDeny;
// INFO_LOG(SLIPPI, "New denylist entry: %08X", address);
deny_list[address] = should_deny;
// INFO_LOG(SLIPPI, "New deny_list entry: %08X", address);
}
}
NOTICE_LOG_FMT(SLIPPI, "Denylist populated with length: {}", denylist.size());
NOTICE_LOG_FMT(SLIPPI, "Denylist populated with length: {}", deny_list.size());
}
void SlippiPlaybackStatus::generateLegacyCodelist()
{
legacyCodelist = {
legacy_code_list = {
0xC2, 0x0C, 0x9A, 0x44, 0x00, 0x00, 0x00,
0x2F, // #External/UCF + Arduino Toggle UI/UCF/UCF 0.74
// Dashback - Check for Toggle.asm

View file

@ -18,26 +18,26 @@ public:
SlippiPlaybackStatus();
~SlippiPlaybackStatus();
bool shouldJumpBack = false;
bool shouldJumpForward = false;
bool inSlippiPlayback = false;
volatile bool shouldRunThreads = false;
bool isHardFFW = false;
bool isSoftFFW = false;
bool origOCEnable = SConfig::GetSlippiConfig().oc_enable;
float origOCFactor = SConfig::GetSlippiConfig().oc_factor;
bool should_jump_back = false;
bool should_jump_forward = false;
bool in_slippi_playback = false;
volatile bool should_run_threads = false;
bool is_hard_FFW = false;
bool is_soft_FFW = false;
bool orig_OC_enable = SConfig::GetSlippiConfig().oc_enable;
float orig_OC_factor = SConfig::GetSlippiConfig().oc_factor;
s32 lastFFWFrame = INT_MIN;
s32 currentPlaybackFrame = INT_MIN;
s32 targetFrameNum = INT_MAX;
s32 lastFrame = Slippi::PLAYBACK_FIRST_SAVE;
s32 last_FFW_frame = INT_MIN;
s32 current_playback_frame = INT_MIN;
s32 target_frame_num = INT_MAX;
s32 last_frame = Slippi::PLAYBACK_FIRST_SAVE;
std::thread m_savestateThread;
std::thread m_savestate_thread;
void startThreads(void);
void resetPlayback(void);
bool shouldFFWFrame(s32 frameIndex) const;
void prepareSlippiPlayback(s32& frameIndex);
bool shouldFFWFrame(s32 frame_idx) const;
void prepareSlippiPlayback(s32& frame_idx);
void setHardFFW(bool enable);
std::unordered_map<u32, bool> getDenylist();
std::vector<u8> getLegacyCodelist();
@ -45,19 +45,19 @@ public:
private:
void SavestateThread(void);
void loadState(s32 closestStateFrame);
void loadState(s32 closest_state_frame);
void processInitialState();
void updateWatchSettingsStartEnd();
void generateDenylist();
void generateLegacyCodelist();
std::unordered_map<int32_t, std::shared_future<std::string>>
futureDiffs; // State diffs keyed by frameIndex, processed async
std::vector<u8> iState; // The initial state
std::vector<u8> cState; // The current (latest) state
future_diffs; // State diffs keyed by frame_idx, processed async
std::vector<u8> initial_state; // The initial state
std::vector<u8> curr_state; // The current (latest) state
std::unordered_map<u32, bool> denylist;
std::vector<u8> legacyCodelist;
std::unordered_map<u32, bool> deny_list;
std::vector<u8> legacy_code_list;
open_vcdiff::VCDiffDecoder decoder;
open_vcdiff::VCDiffEncoder* encoder = NULL;

View file

@ -1,11 +1,17 @@
#include "SlippiReplayComm.h"
#include <cctype>
#include <memory>
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Common/Logging/LogManager.h"
#include "Core/ConfigManager.h"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
std::unique_ptr<SlippiReplayComm> g_replay_comm;
// https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
@ -33,7 +39,7 @@ SlippiReplayComm::SlippiReplayComm()
{
INFO_LOG_FMT(EXPANSIONINTERFACE, "SlippiReplayComm: Using playback config path: {}",
SConfig::GetSlippiConfig().slippi_input);
configFilePath = SConfig::GetSlippiConfig().slippi_input;
config_file_path = SConfig::GetSlippiConfig().slippi_input;
}
SlippiReplayComm::~SlippiReplayComm()
@ -42,16 +48,16 @@ SlippiReplayComm::~SlippiReplayComm()
SlippiReplayComm::CommSettings SlippiReplayComm::getSettings()
{
return commFileSettings;
return comm_file_settings;
}
std::string SlippiReplayComm::getReplayPath()
{
std::string replayFilePath = commFileSettings.replayPath;
if (commFileSettings.mode == "queue")
std::string replayFilePath = comm_file_settings.replay_path;
if (comm_file_settings.mode == "queue")
{
// If we are in queue mode, let's grab the replay from the queue instead
replayFilePath = commFileSettings.queue.empty() ? "" : commFileSettings.queue.front().path;
replayFilePath = comm_file_settings.queue.empty() ? "" : comm_file_settings.queue.front().path;
}
return replayFilePath;
@ -62,21 +68,21 @@ bool SlippiReplayComm::isNewReplay()
loadFile();
std::string replayFilePath = getReplayPath();
bool hasPathChanged = replayFilePath != previousReplayLoaded;
bool hasPathChanged = replayFilePath != previous_replay_loaded;
bool isReplay = !!replayFilePath.length();
// The previous check is mostly good enough but it does not
// work if someone tries to load the same replay twice in a row
// the commandId was added to deal with this
bool hasCommandChanged = commFileSettings.commandId != previousCommandId;
// the command_id was added to deal with this
bool hasCommandChanged = comm_file_settings.command_id != previous_command_id;
// This checks if the queue index has changed, this is to fix the
// issue where the same replay showing up twice in a row in a
// queue would never cause this function to return true
bool hasQueueIdxChanged = false;
if (commFileSettings.mode == "queue" && !commFileSettings.queue.empty())
if (comm_file_settings.mode == "queue" && !comm_file_settings.queue.empty())
{
hasQueueIdxChanged = commFileSettings.queue.front().index != previousIndex;
hasQueueIdxChanged = comm_file_settings.queue.front().index != previous_idx;
}
bool isNewReplay = hasPathChanged || hasCommandChanged || hasQueueIdxChanged;
@ -86,11 +92,11 @@ bool SlippiReplayComm::isNewReplay()
void SlippiReplayComm::nextReplay()
{
if (commFileSettings.queue.empty())
if (comm_file_settings.queue.empty())
return;
// Increment queue position
commFileSettings.queue.pop();
comm_file_settings.queue.pop();
}
std::unique_ptr<Slippi::SlippiGame> SlippiReplayComm::loadGame()
@ -105,27 +111,27 @@ std::unique_ptr<Slippi::SlippiGame> SlippiReplayComm::loadGame()
// file did not exist yet, result will be falsy, which will keep
// the replay considered new so that the file will attempt to be
// loaded again
previousReplayLoaded = replayFilePath;
previousCommandId = commFileSettings.commandId;
if (commFileSettings.mode == "queue" && !commFileSettings.queue.empty())
previous_replay_loaded = replayFilePath;
previous_command_id = comm_file_settings.command_id;
if (comm_file_settings.mode == "queue" && !comm_file_settings.queue.empty())
{
previousIndex = commFileSettings.queue.front().index;
previous_idx = comm_file_settings.queue.front().index;
}
WatchSettings ws;
ws.path = replayFilePath;
ws.startFrame = commFileSettings.startFrame;
ws.endFrame = commFileSettings.endFrame;
if (commFileSettings.mode == "queue")
ws.start_frame = comm_file_settings.start_frame;
ws.end_frame = comm_file_settings.end_frame;
if (comm_file_settings.mode == "queue")
{
ws = commFileSettings.queue.front();
ws = comm_file_settings.queue.front();
}
if (commFileSettings.outputOverlayFiles)
if (comm_file_settings.output_overlay_files)
{
std::string dirpath = File::GetExeDirectory();
File::WriteStringToFile(dirpath + DIR_SEP + "Slippi/out-station.txt", ws.gameStation);
File::WriteStringToFile(dirpath + DIR_SEP + "Slippi/out-time.txt", ws.gameStartAt);
File::WriteStringToFile(dirpath + DIR_SEP + "Slippi/out-station.txt", ws.game_station);
File::WriteStringToFile(dirpath + DIR_SEP + "Slippi/out-time.txt", ws.game_start_at);
}
current = ws;
@ -139,43 +145,44 @@ void SlippiReplayComm::loadFile()
// TODO: Consider even only checking file mod time every 250 ms or something? Not sure
// TODO: what the perf impact is atm
u64 modTime = File::GetFileModTime(configFilePath);
if (modTime != 0 && modTime == configLastLoadModTime)
u64 modTime = File::GetFileModTime(config_file_path);
if (modTime != 0 && modTime == config_last_load_mod_time)
{
// TODO: Maybe be smarter than just using mod time? Look for other things that would
// TODO: indicate that file has changed and needs to be reloaded?
return;
}
WARN_LOG_FMT(EXPANSIONINTERFACE, "File change detected in comm file: {}", configFilePath.c_str());
configLastLoadModTime = modTime;
WARN_LOG_FMT(EXPANSIONINTERFACE, "File change detected in comm file: {}",
config_file_path.c_str());
config_last_load_mod_time = modTime;
// TODO: Maybe load file in a more intelligent way to save
// TODO: file operations
std::string commFileContents;
File::ReadFileToString(configFilePath, commFileContents);
File::ReadFileToString(config_file_path, commFileContents);
auto res = json::parse(commFileContents, nullptr, false);
if (res.is_discarded() || !res.is_object())
{
// Happens if there is a parse error, I think?
commFileSettings.mode = "normal";
commFileSettings.replayPath = "";
commFileSettings.startFrame = Slippi::GAME_FIRST_FRAME;
commFileSettings.endFrame = INT_MAX;
commFileSettings.commandId = "";
commFileSettings.outputOverlayFiles = false;
commFileSettings.isRealTimeMode = false;
commFileSettings.shouldResync = true;
commFileSettings.rollbackDisplayMethod = "off";
comm_file_settings.mode = "normal";
comm_file_settings.replay_path = "";
comm_file_settings.start_frame = Slippi::GAME_FIRST_FRAME;
comm_file_settings.end_frame = INT_MAX;
comm_file_settings.command_id = "";
comm_file_settings.output_overlay_files = false;
comm_file_settings.is_real_time_mode = false;
comm_file_settings.should_resync = true;
comm_file_settings.rollback_display_method = "off";
if (res.is_string())
{
// If we have a string, let's use that as the replayPath
// If we have a string, let's use that as the replay_path
// This is really only here because when developing it might be easier
// to just throw in a string instead of an object
commFileSettings.replayPath = res.get<std::string>();
comm_file_settings.replay_path = res.get<std::string>();
}
else
{
@ -183,44 +190,44 @@ void SlippiReplayComm::loadFile()
// Reset in the case of read error. this fixes a race condition where file mod time changes
// but the file is not readable yet?
configLastLoadModTime = 0;
config_last_load_mod_time = 0;
}
return;
}
// TODO: Support file with only path string
commFileSettings.mode = res.value("mode", "normal");
commFileSettings.replayPath = res.value("replay", "");
commFileSettings.startFrame = res.value("startFrame", Slippi::GAME_FIRST_FRAME);
commFileSettings.endFrame = res.value("endFrame", INT_MAX);
commFileSettings.commandId = res.value("commandId", "");
commFileSettings.outputOverlayFiles = res.value("outputOverlayFiles", false);
commFileSettings.isRealTimeMode = res.value("isRealTimeMode", false);
commFileSettings.shouldResync = res.value("shouldResync", true);
commFileSettings.rollbackDisplayMethod = res.value("rollbackDisplayMethod", "off");
comm_file_settings.mode = res.value("mode", "normal");
comm_file_settings.replay_path = res.value("replay", "");
comm_file_settings.start_frame = res.value("startFrame", Slippi::GAME_FIRST_FRAME);
comm_file_settings.end_frame = res.value("endFrame", INT_MAX);
comm_file_settings.command_id = res.value("commandId", "");
comm_file_settings.output_overlay_files = res.value("outputOverlayFiles", false);
comm_file_settings.is_real_time_mode = res.value("isRealTimeMode", false);
comm_file_settings.should_resync = res.value("shouldResync", true);
comm_file_settings.rollback_display_method = res.value("rollbackDisplayMethod", "off");
if (commFileSettings.mode == "queue")
if (comm_file_settings.mode == "queue")
{
auto queue = res["queue"];
if (queue.is_array())
{
std::queue<WatchSettings>().swap(commFileSettings.queue);
std::queue<WatchSettings>().swap(comm_file_settings.queue);
int index = 0;
for (json::iterator it = queue.begin(); it != queue.end(); ++it)
{
json el = *it;
WatchSettings w = {};
w.path = el.value("path", "");
w.startFrame = el.value("startFrame", Slippi::GAME_FIRST_FRAME);
w.endFrame = el.value("endFrame", INT_MAX);
w.gameStartAt = el.value("gameStartAt", "");
w.gameStation = el.value("gameStation", "");
w.start_frame = el.value("startFrame", Slippi::GAME_FIRST_FRAME);
w.end_frame = el.value("endFrame", INT_MAX);
w.game_start_at = el.value("gameStartAt", "");
w.game_station = el.value("gameStation", "");
w.index = index++;
commFileSettings.queue.push(w);
comm_file_settings.queue.push(w);
};
queueWasEmpty = false;
queue_was_empty = false;
}
}
}

View file

@ -1,7 +1,6 @@
#pragma once
#include <limits.h>
#include <nlohmann/json.hpp>
#include <queue>
#include <string>
@ -9,18 +8,16 @@
#include "SlippiGame.h"
using json = nlohmann::json;
class SlippiReplayComm
{
public:
typedef struct WatchSettings
{
std::string path;
int startFrame = Slippi::GAME_FIRST_FRAME;
int endFrame = INT_MAX;
std::string gameStartAt = "";
std::string gameStation = "";
int start_frame = Slippi::GAME_FIRST_FRAME;
int end_frame = INT_MAX;
std::string game_start_at = "";
std::string game_station = "";
int index = 0;
} WatchSettings;
@ -28,14 +25,14 @@ public:
typedef struct CommSettings
{
std::string mode;
std::string replayPath;
int startFrame = Slippi::GAME_FIRST_FRAME;
int endFrame = INT_MAX;
bool outputOverlayFiles;
bool isRealTimeMode;
bool shouldResync; // If true, logic will attempt to resync games
std::string rollbackDisplayMethod; // off, normal, visible
std::string commandId;
std::string replay_path;
int start_frame = Slippi::GAME_FIRST_FRAME;
int end_frame = INT_MAX;
bool output_overlay_files;
bool is_real_time_mode;
bool should_resync; // If true, logic will attempt to resync games
std::string rollback_display_method; // off, normal, visible
std::string command_id;
std::queue<WatchSettings> queue;
} CommSettings;
@ -53,16 +50,15 @@ private:
void loadFile();
std::string getReplayPath();
std::string configFilePath;
json fileData;
std::string previousReplayLoaded;
std::string previousCommandId;
int previousIndex;
std::string config_file_path;
std::string previous_replay_loaded;
std::string previous_command_id;
int previous_idx;
u64 configLastLoadModTime;
u64 config_last_load_mod_time;
// Queue stuff
bool queueWasEmpty = true;
bool queue_was_empty = true;
CommSettings commFileSettings;
CommSettings comm_file_settings;
};

View file

@ -561,9 +561,9 @@ void HotkeyScheduler::Run()
if (IsHotkey(HK_SLIPPI_JUMP_BACK))
{
INFO_LOG_FMT(SLIPPI, "jump back");
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame - 1200;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame - 1200;
Host_PlaybackSeek();
}
}
@ -571,9 +571,9 @@ void HotkeyScheduler::Run()
if (IsHotkey(HK_SLIPPI_STEP_BACK))
{
INFO_LOG_FMT(SLIPPI, "step back");
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame - 300;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame - 300;
Host_PlaybackSeek();
}
}
@ -581,9 +581,9 @@ void HotkeyScheduler::Run()
if (IsHotkey(HK_SLIPPI_STEP_FORWARD))
{
INFO_LOG_FMT(SLIPPI, "step forward");
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame + 300;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame + 300;
Host_PlaybackSeek();
}
}
@ -591,9 +591,9 @@ void HotkeyScheduler::Run()
if (IsHotkey(HK_SLIPPI_JUMP_FORWARD))
{
INFO_LOG_FMT(SLIPPI, "jump forward");
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame + 1200;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame + 1200;
Host_PlaybackSeek();
}
}

View file

@ -350,7 +350,7 @@ bool SeekBarBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v_max,
if (!isHeld)
{
value_changed = true;
g_playback_status->targetFrameNum = *v;
g_playback_status->target_frame_num = *v;
}
}
else
@ -415,9 +415,9 @@ bool SeekBarBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v_max,
// Progress bar
if (!isHeld)
{
frame = (g_playback_status->targetFrameNum == INT_MAX) ?
g_playback_status->currentPlaybackFrame :
g_playback_status->targetFrameNum;
frame = (g_playback_status->target_frame_num == INT_MAX) ?
g_playback_status->current_playback_frame :
g_playback_status->target_frame_num;
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y - scaled_height * 0.002f),
ImVec2(curr_grab_pos, bb.Min.y - scaled_height * 0.002f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 1.0f, 0.0f, style.Alpha)),
@ -629,7 +629,7 @@ void DrawSlippiPlaybackControls()
ImGui::SetWindowFontScale(scaled_height / 2000.0f);
if (SeekBar("SlippiSeek", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), &frame, Slippi::PLAYBACK_FIRST_SAVE,
g_playback_status->lastFrame, 1.0, "%d"))
g_playback_status->last_frame, 1.0, "%d"))
{
Host_PlaybackSeek();
}
@ -645,9 +645,9 @@ void DrawSlippiPlaybackControls()
// ImGui::SameLine(0.0f, 5.0f);
if (ButtonCustom(ICON_MD_FAST_REWIND, ImVec2(BUTTON_WIDTH, BUTTON_WIDTH)))
{
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame - 1200;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame - 1200;
Host_PlaybackSeek();
}
}
@ -665,9 +665,9 @@ void DrawSlippiPlaybackControls()
ImGui::SetCursorPos(ImVec2(BUTTON_WIDTH, height - scaled_height * 0.0265f));
if (ButtonCustom(ICON_MD_FIRST_PAGE, ImVec2(BUTTON_WIDTH, BUTTON_WIDTH)))
{
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame - 300;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame - 300;
Host_PlaybackSeek();
}
}
@ -685,9 +685,9 @@ void DrawSlippiPlaybackControls()
ImGui::SetCursorPos(ImVec2(BUTTON_WIDTH * 2, height - scaled_height * 0.0265f));
if (ButtonCustom(ICON_MD_LAST_PAGE, ImVec2(BUTTON_WIDTH, BUTTON_WIDTH)))
{
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame + 300;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame + 300;
Host_PlaybackSeek();
}
}
@ -705,9 +705,9 @@ void DrawSlippiPlaybackControls()
ImGui::SetCursorPos(ImVec2(BUTTON_WIDTH * 3, height - scaled_height * 0.0265f));
if (ButtonCustom(ICON_MD_FAST_FORWARD, ImVec2(BUTTON_WIDTH, BUTTON_WIDTH)))
{
if (g_playback_status->targetFrameNum == INT_MAX)
if (g_playback_status->target_frame_num == INT_MAX)
{
g_playback_status->targetFrameNum = g_playback_status->currentPlaybackFrame + 1200;
g_playback_status->target_frame_num = g_playback_status->current_playback_frame + 1200;
Host_PlaybackSeek();
}
}
@ -887,8 +887,8 @@ void DrawSlippiPlaybackControls()
// Time text
ImGui::SetCursorPos(ImVec2(BUTTON_WIDTH * 8, height - scaled_height * 0.024f));
auto playbackTime = GetTimeForFrame(g_playback_status->currentPlaybackFrame);
auto endTime = GetTimeForFrame(g_playback_status->lastFrame);
auto playbackTime = GetTimeForFrame(g_playback_status->current_playback_frame);
auto endTime = GetTimeForFrame(g_playback_status->last_frame);
auto timeString = playbackTime + " / " + endTime;
ImGui::Text("%s", timeString.c_str());
}