Skip to content

Commit

Permalink
UI: Add visual list of recently played games (click to resume)
Browse files Browse the repository at this point in the history
  • Loading branch information
SourMesen committed May 6, 2017
1 parent 56656aa commit a412b45
Show file tree
Hide file tree
Showing 38 changed files with 831 additions and 103 deletions.
22 changes: 16 additions & 6 deletions Core/BaseVideoFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ uint8_t* BaseVideoFilter::GetOutputBuffer()
return _outputBuffer;
}

void BaseVideoFilter::TakeScreenshot()
void BaseVideoFilter::TakeScreenshot(string filename, std::stringstream *stream)
{
string romFilename = FolderUtilities::GetFilename(Console::GetRomName(), false);

uint32_t* frameBuffer = nullptr;
{
auto lock = _frameLock.AcquireSafe();
Expand All @@ -75,10 +73,23 @@ void BaseVideoFilter::TakeScreenshot()
}

//ARGB -> ABGR
for(uint32_t i = 0; i < _bufferSize/GetFrameInfo().BitsPerPixel; i++) {
for(uint32_t i = 0; i < _bufferSize / GetFrameInfo().BitsPerPixel; i++) {
frameBuffer[i] = 0xFF000000 | (frameBuffer[i] & 0xFF00) | ((frameBuffer[i] & 0xFF0000) >> 16) | ((frameBuffer[i] & 0xFF) << 16);
}

if(!filename.empty()) {
PNGHelper::WritePNG(filename, (uint8_t*)frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
} else {
PNGHelper::WritePNG(*stream, (uint8_t*)frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
}

delete[] frameBuffer;
}

void BaseVideoFilter::TakeScreenshot()
{
string romFilename = FolderUtilities::GetFilename(Console::GetRomName(), false);

int counter = 0;
string baseFilename = FolderUtilities::CombinePath(FolderUtilities::GetScreenshotFolder(), romFilename);
string ssFilename;
Expand All @@ -97,8 +108,7 @@ void BaseVideoFilter::TakeScreenshot()
counter++;
}

PNGHelper::WritePNG(ssFilename, (uint8_t*)frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
delete[] frameBuffer;
TakeScreenshot(ssFilename);

MessageManager::DisplayMessage("ScreenshotSaved", FolderUtilities::GetFilename(ssFilename, true));
}
Expand Down
1 change: 1 addition & 0 deletions Core/BaseVideoFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class BaseVideoFilter
uint8_t* GetOutputBuffer();
void SendFrame(uint16_t *ppuOutputBuffer);
void TakeScreenshot();
void TakeScreenshot(string filename, std::stringstream *stream = nullptr);

virtual FrameInfo GetFrameInfo() = 0;
};
22 changes: 20 additions & 2 deletions Core/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ShortcutKeyHandler.h"
#include "MovieManager.h"
#include "RewindManager.h"
#include "SaveStateManager.h"

shared_ptr<Console> Console::Instance(new Console());

Expand Down Expand Up @@ -54,9 +55,12 @@ bool Console::Initialize(string romFilename, stringstream *filestream, string pa
{
SoundMixer::StopAudio();

if(_mapper) {
if(!_romFilepath.empty() && _mapper) {
//Ensure we save any battery file before loading a new game
_mapper->SaveBattery();

//Save current game state before loading another one
SaveStateManager::SaveRecentGame(_mapper->GetRomName(), _romFilepath, _patchFilename, _archiveFileIndex);
}

MessageManager::SendNotification(ConsoleNotificationType::GameStopped);
Expand Down Expand Up @@ -336,11 +340,13 @@ void Console::Run()
VideoDecoder::GetInstance()->StartThread();

PlatformUtilities::DisableScreensaver();


bool crashed = false;
while(true) {
try {
_cpu->Exec();
} catch(const std::runtime_error &ex) {
crashed = true;
MessageManager::DisplayMessage("Error", "GameCrash", ex.what());
break;
}
Expand Down Expand Up @@ -421,6 +427,13 @@ void Console::Run()
}
}
}

if(!crashed) {
SaveStateManager::SaveRecentGame(_mapper->GetRomName(), _romFilepath, _patchFilename, _archiveFileIndex);
}

MessageManager::SendNotification(ConsoleNotificationType::GameStopped);

_rewindManager.reset();
SoundMixer::StopAudio();
MovieManager::Stop();
Expand All @@ -433,6 +446,11 @@ void Console::Run()

_initialized = false;
_romFilepath = "";
_mapper.reset();
_ppu.reset();
_cpu.reset();
_memoryManager.reset();
_controlManager.reset();

_stopLock.Release();
_runLock.Release();
Expand Down
2 changes: 2 additions & 0 deletions Core/EmulationSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ enum EmulationFlags : uint64_t

DisplayMovieIcons = 0x10000000000,
HidePauseOverlay = 0x20000000000,

ConsoleMode = 0x8000000000000000,
};

enum class AudioChannel
Expand Down
1 change: 1 addition & 0 deletions Core/NsfLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class NsfLoader
{
NsfHeader &header = romData.NsfInfo;

romData.Format = RomFormat::Nsf;
romData.MapperID = MapperFactory::NsfMapperID;

if(header.LoadAddress < 0x6000 || header.TotalSongs == 0) {
Expand Down
2 changes: 2 additions & 0 deletions Core/NsfeLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class NsfeLoader : public NsfLoader

InitHeader(header);

romData.Format = RomFormat::Nsf;

uint8_t* data = romFile.data() + 4;
uint8_t* endOfData = romFile.data() + romFile.size();

Expand Down
1 change: 1 addition & 0 deletions Core/RomData.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ enum class RomFormat
iNes = 1,
Unif = 2,
Fds = 3,
Nsf = 4,
};

struct RomData
Expand Down
129 changes: 95 additions & 34 deletions Core/SaveStateManager.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include "stdafx.h"

#include "../Utilities/FolderUtilities.h"
#include "../Utilities/ZipWriter.h"
#include "../Utilities/ZipReader.h"
#include "SaveStateManager.h"
#include "MessageManager.h"
#include "Console.h"
#include "../Utilities/FolderUtilities.h"
#include "EmulationSettings.h"
#include "VideoDecoder.h"

const uint32_t SaveStateManager::FileFormatVersion;
atomic<uint32_t> SaveStateManager::_lastIndex(1);
Expand Down Expand Up @@ -50,29 +52,62 @@ bool SaveStateManager::LoadState()
return LoadState(_lastIndex);
}

void SaveStateManager::SaveState(ostream &stream)
{
Console::Pause();

uint32_t emuVersion = EmulationSettings::GetMesenVersion();
stream.write("MST", 3);
stream.write((char*)&emuVersion, sizeof(emuVersion));
stream.write((char*)&SaveStateManager::FileFormatVersion, sizeof(uint32_t));

Console::SaveState(stream);
Console::Resume();
}

void SaveStateManager::SaveState(int stateIndex, bool displayMessage)
{
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
ofstream file(filepath, ios::out | ios::binary);

if(file) {
_lastIndex = stateIndex;
SaveState(file);
file.close();

Console::Pause();
if(displayMessage) {
MessageManager::DisplayMessage("SaveStates", "SaveStateSaved", std::to_string(stateIndex));
}
}
}

uint32_t emuVersion = EmulationSettings::GetMesenVersion();
file.write("MST", 3);
file.write((char*)&emuVersion, sizeof(emuVersion));
file.write((char*)&SaveStateManager::FileFormatVersion, sizeof(uint32_t));
bool SaveStateManager::LoadState(istream &stream)
{
char header[3];
stream.read(header, 3);
if(memcmp(header, "MST", 3) == 0) {
uint32_t emuVersion, fileFormatVersion;

stream.read((char*)&emuVersion, sizeof(emuVersion));
if(emuVersion > EmulationSettings::GetMesenVersion()) {
MessageManager::DisplayMessage("SaveStates", "SaveStateNewerVersion");
return false;
}

Console::SaveState(file);
stream.read((char*)&fileFormatVersion, sizeof(fileFormatVersion));
if(fileFormatVersion != SaveStateManager::FileFormatVersion) {
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion"); // , std::to_string(stateIndex));
return false;
}

Console::Pause();
Console::LoadState(stream);
Console::Resume();
file.close();

if(displayMessage) {
MessageManager::DisplayMessage("SaveStates", "SaveStateSaved", std::to_string(stateIndex));
}
return true;
}

return false;
}

bool SaveStateManager::LoadState(int stateIndex)
Expand All @@ -82,29 +117,8 @@ bool SaveStateManager::LoadState(int stateIndex)
bool result = false;

if(file) {
char header[3];
file.read(header, 3);
if(memcmp(header, "MST", 3) == 0) {
uint32_t emuVersion, fileFormatVersion;

file.read((char*)&emuVersion, sizeof(emuVersion));
if(emuVersion > EmulationSettings::GetMesenVersion()) {
MessageManager::DisplayMessage("SaveStates", "SaveStateNewerVersion");
return false;
}

file.read((char*)&fileFormatVersion, sizeof(fileFormatVersion));
if(fileFormatVersion != SaveStateManager::FileFormatVersion) {
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion", std::to_string(stateIndex));
return false;
}

if(LoadState(file)) {
_lastIndex = stateIndex;

Console::Pause();
Console::LoadState(file);
Console::Resume();

MessageManager::DisplayMessage("SaveStates", "SaveStateLoaded", std::to_string(stateIndex));
result = true;
} else {
Expand All @@ -118,4 +132,51 @@ bool SaveStateManager::LoadState(int stateIndex)
}

return result;
}

void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath, int32_t archiveFileIndex)
{
if(!EmulationSettings::CheckFlag(EmulationFlags::ConsoleMode) && Console::GetRomFormat() != RomFormat::Nsf) {
string filename = FolderUtilities::GetFilename(Console::GetRomName(), false) + ".rgd";
ZipWriter writer(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));

std::stringstream pngStream;
VideoDecoder::GetInstance()->TakeScreenshot(pngStream);
writer.AddFile(pngStream, "Screenshot.png");

std::stringstream stateStream;
SaveStateManager::SaveState(stateStream);
writer.AddFile(stateStream, "Savestate.mst");

std::stringstream romInfoStream;
romInfoStream << romName << std::endl;
romInfoStream << romPath << std::endl;
romInfoStream << patchPath << std::endl;
romInfoStream << std::to_string(archiveFileIndex) << std::endl;
writer.AddFile(romInfoStream, "RomInfo.txt");
}
}

void SaveStateManager::LoadRecentGame(string filename)
{
ZipReader reader;
reader.LoadArchive(filename);

std::stringstream romInfoStream = reader.GetStream("RomInfo.txt");
std::stringstream stateStream = reader.GetStream("Savestate.mst");

string romName, romPath, patchPath, archiveIndex;
std::getline(romInfoStream, romName);
std::getline(romInfoStream, romPath);
std::getline(romInfoStream, patchPath);
std::getline(romInfoStream, archiveIndex);

Console::Pause();
try {
Console::LoadROM(romPath, nullptr, std::stoi(archiveIndex.c_str()), patchPath);
SaveStateManager::LoadState(stateStream);
} catch(std::exception ex) {
Console::GetInstance()->Stop();
}
Console::Resume();
}
5 changes: 5 additions & 0 deletions Core/SaveStateManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ class SaveStateManager
static void SaveState();
static bool LoadState();

static void SaveState(ostream &stream);
static void SaveState(int stateIndex, bool displayMessage = true);
static bool LoadState(istream &stream);
static bool LoadState(int stateIndex);

static void SaveRecentGame(string romName, string romPath, string patchPath, int32_t archiveFileIndex);
static void LoadRecentGame(string filename);

static void MoveToNextSlot();
static void MoveToPreviousSlot();
};
9 changes: 9 additions & 0 deletions Core/VideoDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ void VideoDecoder::StopThread()

_decodeThread.reset();

_hdScreenTiles = nullptr;
UpdateVideoFilter();
if(_ppuOutputBuffer != nullptr) {
//Clear whole screen
for(uint32_t i = 0; i < PPU::PixelCount; i++) {
Expand All @@ -226,3 +228,10 @@ void VideoDecoder::TakeScreenshot()
_videoFilter->TakeScreenshot();
}
}

void VideoDecoder::TakeScreenshot(std::stringstream &stream)
{
if(_videoFilter) {
_videoFilter->TakeScreenshot("", &stream);
}
}
1 change: 1 addition & 0 deletions Core/VideoDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class VideoDecoder

void DecodeFrame();
void TakeScreenshot();
void TakeScreenshot(std::stringstream &stream);

uint32_t GetFrameCount();

Expand Down
12 changes: 12 additions & 0 deletions GUI.NET/Config/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ public static string MovieFolder
}
}

public static string RecentGamesFolder
{
get
{
string recentGamesPath = Path.Combine(ConfigManager.HomeFolder, "RecentGames");
if(!Directory.Exists(recentGamesPath)) {
Directory.CreateDirectory(recentGamesPath);
}
return recentGamesPath;
}
}

public static string WaveFolder
{
get
Expand Down
Loading

0 comments on commit a412b45

Please sign in to comment.