Skip to content

Commit

Permalink
add indicator for pause/fast forward
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamiras committed Sep 14, 2024
1 parent 8fc231d commit 3218cea
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 10 deletions.
34 changes: 33 additions & 1 deletion src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,7 @@ void Application::unloadCore()
_memory.destroy();
_core.destroy();
_video.reset();
updateSpeedIndicator();
}

void Application::resetGame()
Expand Down Expand Up @@ -2344,6 +2345,8 @@ void Application::handle(const SDL_SysWMEvent* syswm)

case IDM_EMULATOR_CONFIG:
_config.showEmulatorSettingsDialog();
updateSpeedIndicator();
_video.draw(true);
break;

case IDM_SAVING_CONFIG:
Expand Down Expand Up @@ -2560,6 +2563,7 @@ void Application::handle(const KeyBinds::Action action, unsigned extra)
// Emulation speed
case KeyBinds::Action::kStep:
_fsm.step();
updateSpeedIndicator();
break;

case KeyBinds::Action::kPauseToggle: /* overlay toggle */
Expand All @@ -2574,7 +2578,7 @@ void Application::handle(const KeyBinds::Action action, unsigned extra)
_fsm.pauseGame();
RA_SetPaused(true);
}

updateSpeedIndicator();
break;

case KeyBinds::Action::kPauseToggleNoOvl: /* non-overlay pause toggle */
Expand All @@ -2593,6 +2597,7 @@ void Application::handle(const KeyBinds::Action action, unsigned extra)
// not paused, pause without overlay (will fail silently in hardcore)
_fsm.pauseGameNoOvl();
}
updateSpeedIndicator();

break;

Expand Down Expand Up @@ -2646,6 +2651,33 @@ void Application::toggleFastForwarding(unsigned extra)
SetMenuItemInfo(_menu, IDM_TURBO_GAME, false, &info);
break;
}

updateSpeedIndicator();
}

void Application::updateSpeedIndicator()
{
if (!_config.getShowSpeedIndicator())
{
_video.showSpeedIndicator(Video::Speed::None);
return;
}

switch (_fsm.currentState())
{
case Fsm::State::GamePaused:
case Fsm::State::GamePausedNoOvl:
case Fsm::State::FrameStep:
_video.showSpeedIndicator(Video::Speed::Paused);
_video.draw(true);
break;

default:
if (_config.getFastForwarding())
_video.showSpeedIndicator(Video::Speed::FastForwarding);
else
_video.showSpeedIndicator(Video::Speed::None);
}
}

void Application::toggleBackgroundInput()
Expand Down
1 change: 1 addition & 0 deletions src/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class Application
void loadConfiguration(int* window_x, int* window_y, int* window_width, int* window_height);
void saveConfiguration();
std::string serializeRecentList();
void updateSpeedIndicator();
void toggleFastForwarding(unsigned extra);
void toggleBackgroundInput();
void setBackgroundInput(bool enabled);
Expand Down
19 changes: 17 additions & 2 deletions src/components/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ bool Config::init(libretro::LoggerComponent* logger)
// these settings are global and should not be modified by reset()
_audioWhileFastForwarding = true;
_fastForwardRatio = 5;
_backgroundInput = false;
_showSpeedIndicator = true;

reset();
return true;
Expand Down Expand Up @@ -550,7 +552,7 @@ void Config::initializeControllerVariable(Variable& variable, const char* name,
}
}

std::string Config::serializeEmulatorSettings()
std::string Config::serializeEmulatorSettings() const
{
std::string json("{");

Expand All @@ -564,6 +566,10 @@ std::string Config::serializeEmulatorSettings()

json.append("\"backgroundInput\":");
json.append(_backgroundInput ? "true" : "false");
json.append(",");

json.append("\"showSpeedIndicator\":");
json.append(_showSpeedIndicator ? "true" : "false");

json.append("}");
return json;
Expand Down Expand Up @@ -598,6 +604,10 @@ bool Config::deserializeEmulatorSettings(const char* json)
{
ud->self->_backgroundInput = num != 0;
}
else if (ud->key == "showSpeedIndicator")
{
ud->self->_showSpeedIndicator = num != 0;
}
}
else if (event == JSONSAX_NUMBER)
{
Expand Down Expand Up @@ -908,7 +918,7 @@ static const char* s_getFastForwardRatioOptions(int index, void* udata)

void Config::showEmulatorSettingsDialog()
{
const WORD WIDTH = 140;
const WORD WIDTH = 170;
const WORD LINE = 15;

Dialog db;
Expand All @@ -925,13 +935,18 @@ void Config::showEmulatorSettingsDialog()
db.addCheckbox("Play Audio while Fast Forwarding", 51002, 0, y, WIDTH - 10, 8, &playAudio);
y += LINE;

bool showSpeedIndicator = _showSpeedIndicator;
db.addCheckbox("Show Indicator when Paused or Fast Forwarding", 51004, 0, y, WIDTH - 10, 8, &showSpeedIndicator);
y += LINE;

db.addButton("OK", IDOK, WIDTH - 55 - 50, y, 50, 14, true);
db.addButton("Cancel", IDCANCEL, WIDTH - 50, y, 50, 14, false);

if (db.show())
{
_audioWhileFastForwarding = playAudio;
_fastForwardRatio = fastForwardRatio + 2;
_showSpeedIndicator = showSpeedIndicator;
}
}
#endif
Expand Down
6 changes: 5 additions & 1 deletion src/components/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class Config: public libretro::ConfigComponent
virtual bool getAudioWhileFastForwarding() override { return _audioWhileFastForwarding; }
virtual int getFastForwardRatio() override { return _fastForwardRatio; }

virtual bool getShowSpeedIndicator() override { return _showSpeedIndicator; }
virtual void setShowSpeedIndicator(bool value) override { _showSpeedIndicator = value; }

void setSaveDirectory(const std::string& path) { _saveFolder = path; }

const char* getRootFolder()
Expand All @@ -74,7 +77,7 @@ class Config: public libretro::ConfigComponent

bool validateSettingsForHardcore(const char* library_name, int console_id, bool prompt);

std::string serializeEmulatorSettings();
std::string serializeEmulatorSettings() const;
bool deserializeEmulatorSettings(const char* json);

#ifdef _WINDOWS
Expand Down Expand Up @@ -148,6 +151,7 @@ class Config: public libretro::ConfigComponent
bool _hadDisallowedSetting;
bool _audioWhileFastForwarding;
bool _backgroundInput;
bool _showSpeedIndicator;

int _fastForwardRatio;

Expand Down
113 changes: 107 additions & 6 deletions src/components/Video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ along with RALibretro. If not, see <http://www.gnu.org/licenses/>.
#define OSD_CHAR_WIDTH 8
#define OSD_CHAR_HEIGHT 16
#define OSD_PADDING 4
#define OSD_SPEED_INDICATOR_WIDTH 32
#define OSD_SPEED_INDICATOR_HEIGHT 32
#define OSD_SPEED_INDICATOR_PADDING 6

struct VertexData
{
Expand All @@ -51,7 +54,7 @@ Video::Video()
_viewWidth = _viewHeight = 0;

_vertexArray = _vertexBuffer = 0;
_texture = 0;
_texture = _speedIndicatorTexture = 0;
_rotation = Rotation::None;
_rotationHandler = NULL;

Expand Down Expand Up @@ -119,6 +122,12 @@ void Video::destroy()
}
_numMessages = 0;

if (_speedIndicatorTexture != 0)
{
Gl::deleteTextures(1, &_speedIndicatorTexture);
_texture = 0;
}

if (_vertexArray != 0)
{
Gl::deleteVertexArrays(1, &_vertexArray);
Expand Down Expand Up @@ -199,19 +208,28 @@ void Video::draw(bool force)

Gl::drawArrays(GL_TRIANGLE_STRIP, 0, 4);

if (_numMessages != 0)
if (_numMessages != 0 || _speedIndicatorTexture != 0)
{
const GLint messageHeight = (OSD_PADDING + OSD_CHAR_HEIGHT + OSD_PADDING);
const GLint x = 8;
GLint y = 8;

Gl::bindBuffer(GL_ARRAY_BUFFER, _indentityVertexBuffer);
Gl::enableVertexAttribArray(_posAttribute);
Gl::vertexAttribPointer(_posAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, x));
Gl::enableVertexAttribArray(_uvAttribute);
Gl::vertexAttribPointer(_uvAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, u));
Gl::bindBuffer(GL_ARRAY_BUFFER, 0);

if (_speedIndicatorTexture != 0)
{
Gl::viewport(_windowWidth - 8 - OSD_SPEED_INDICATOR_WIDTH, _windowHeight - 8 - OSD_SPEED_INDICATOR_HEIGHT,
OSD_SPEED_INDICATOR_WIDTH, OSD_SPEED_INDICATOR_WIDTH);
Gl::bindTexture(GL_TEXTURE_2D, _speedIndicatorTexture);
Gl::uniform1i(_texUniform, 0);
Gl::drawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

const GLint messageHeight = (OSD_PADDING + OSD_CHAR_HEIGHT + OSD_PADDING);
const GLint x = 8;
GLint y = 8;

for (int i = _numMessages - 1; i >= 0; --i)
{
Gl::viewport(x, y, _messageWidth[i], messageHeight);
Expand Down Expand Up @@ -455,6 +473,89 @@ void Video::showMessage(const char* msg, unsigned frames)
free(data);
}

void Video::showSpeedIndicator(Speed indicator)
{
if (indicator == Speed::None)
{
if (_speedIndicatorTexture != 0)
{
Gl::deleteTextures(1, &_speedIndicatorTexture);
_speedIndicatorTexture = 0;
}

return;
}

const size_t numBytes = OSD_SPEED_INDICATOR_WIDTH * OSD_SPEED_INDICATOR_HEIGHT * 2;

uint16_t* data = (uint16_t*)malloc(numBytes);
if (!data)
{
showSpeedIndicator(Speed::None);
return;
}

if (_speedIndicatorTexture == 0)
{
_speedIndicatorTexture = GlUtil::createTexture(OSD_SPEED_INDICATOR_WIDTH, OSD_SPEED_INDICATOR_HEIGHT, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_NEAREST);
if (_speedIndicatorTexture == 0)
{
free(data);
return;
}
}

memset(data, 0, numBytes);
uint16_t* out = &data[OSD_SPEED_INDICATOR_PADDING * OSD_SPEED_INDICATOR_WIDTH + OSD_SPEED_INDICATOR_PADDING];
const size_t width = OSD_SPEED_INDICATOR_WIDTH - OSD_SPEED_INDICATOR_PADDING * 2;
const size_t height = OSD_SPEED_INDICATOR_HEIGHT - OSD_SPEED_INDICATOR_PADDING * 2;

switch (indicator)
{
case Speed::Paused:
for (size_t i = 0; i < (width + 2) / 3; ++i)
{
out[i] = 0xFFFF;
out[width - i - 1] = 0xFFFF;
}
for (int i = 1; i < height; ++i)
memcpy(&out[i * OSD_SPEED_INDICATOR_WIDTH], out, width * 2);
break;

case Speed::FastForwarding:
for (size_t i = 0; i < height / 2; ++i)
{
for (size_t j = 0; j <= i; ++j)
{
out[j] = 0xFFFF;
out[j + width / 2 + 1] = 0xFFFF;
}
out += OSD_SPEED_INDICATOR_WIDTH;
}
for (size_t i = 0; i < height / 2; ++i)
{
for (size_t j = 0; j < height / 2 - i; ++j)
{
out[j] = 0xFFFF;
out[j + width / 2 + 1] = 0xFFFF;
}
out += OSD_SPEED_INDICATOR_WIDTH;
}
break;

default:
break;
}

Gl::bindTexture(GL_TEXTURE_2D, _speedIndicatorTexture);
Gl::pixelStorei(GL_UNPACK_ROW_LENGTH, OSD_SPEED_INDICATOR_WIDTH);
Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, OSD_SPEED_INDICATOR_WIDTH, OSD_SPEED_INDICATOR_HEIGHT, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
Gl::pixelStorei(GL_UNPACK_ROW_LENGTH, 0);
Gl::bindTexture(GL_TEXTURE_2D, 0);

free(data);
}

void Video::windowResized(unsigned width, unsigned height)
{
_ctx->enableCoreContext(false);
Expand Down
3 changes: 3 additions & 0 deletions src/components/Video.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Video: public libretro::VideoComponent
virtual void showMessage(const char* msg, unsigned frames) override;
bool hasMessage() const { return _numMessages != 0; }

virtual void showSpeedIndicator(Speed visibleIndicator) override;

void windowResized(unsigned width, unsigned height);
void getFramebufferSize(unsigned* width, unsigned* height, enum retro_pixel_format* format);
const void* getFramebuffer(unsigned* width, unsigned* height, unsigned* pitch, enum retro_pixel_format* format);
Expand Down Expand Up @@ -100,6 +102,7 @@ class Video: public libretro::VideoComponent
unsigned _messageWidth[4];
unsigned _messageFrames[4];
unsigned _numMessages;
GLuint _speedIndicatorTexture;

unsigned _windowWidth;
unsigned _windowHeight;
Expand Down
11 changes: 11 additions & 0 deletions src/libretro/Components.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ namespace libretro

virtual bool getAudioWhileFastForwarding() = 0;
virtual int getFastForwardRatio() = 0;

virtual bool getShowSpeedIndicator() = 0;
virtual void setShowSpeedIndicator(bool value) = 0;
};

/**
Expand Down Expand Up @@ -187,6 +190,14 @@ namespace libretro

virtual void showMessage(const char* msg, unsigned frames) = 0;

enum class Speed
{
None,
Paused,
FastForwarding,
};
virtual void showSpeedIndicator(Speed visibleIndicator) = 0;

/* NOTE: these are counter-clockwise rotations per libretro.h */
enum class Rotation
{
Expand Down
Loading

0 comments on commit 3218cea

Please sign in to comment.