Support for saving PNG screenshots

This commit is contained in:
Souryo 2014-07-10 21:17:37 -04:00
parent 82006c057b
commit 259f474ec7
11 changed files with 99 additions and 7 deletions

1
.gitignore vendored
View File

@ -159,3 +159,4 @@ $RECYCLE.BIN/
*.svs
*.spritefont
*.trt
*.zip

Binary file not shown.

View File

@ -359,6 +359,8 @@ namespace NES
SetMenuEnabled(ID_NETPLAY_CONNECT, !serverStarted && !clientConnected && !Movie::Playing());
SetMenuEnabled(ID_NETPLAY_DISCONNECT, !serverStarted && clientConnected);
SetMenuEnabled(ID_TOOLS_TAKESCREENSHOT, running);
SetMenuCheck(ID_SAVESTATESLOT_1, _currentSaveSlot == 0);
SetMenuCheck(ID_SAVESTATESLOT_2, _currentSaveSlot == 1);
SetMenuCheck(ID_SAVESTATESLOT_3, _currentSaveSlot == 2);
@ -374,8 +376,8 @@ namespace NES
}
_currentROM = _console->GetROMPath();
wstring currentROMName = FolderUtilities::GetFilename(_console->GetROMPath(), false);
SetWindowText(_hWnd, (wstring(_windowName) + L": " + currentROMName).c_str());
_currentROMName = FolderUtilities::GetFilename(_console->GetROMPath(), false);
SetWindowText(_hWnd, (wstring(_windowName) + L": " + _currentROMName).c_str());
Console::ClearFlags(EmulationFlags::Paused);
@ -642,6 +644,10 @@ namespace NES
GameClient::Disconnect();
break;
case ID_TOOLS_TAKESCREENSHOT:
mainWindow->_renderer->TakeScreenshot(mainWindow->_currentROMName);
break;
case ID_TESTS_RUNTESTS:
mainWindow->RunTests();
break;

View File

@ -329,7 +329,9 @@ namespace NES
dd.DepthPitch = _screenBufferSize;
_pDeviceContext->Map(_pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &dd);
_frameLock.Acquire();
memcpy(dd.pData, _nextFrameBuffer, _screenBufferSize);
_frameLock.Release();
_pDeviceContext->Unmap(_pTexture, 0);
ID3D11ShaderResourceView *nesOutputBuffer = GetShaderResourceView(_pTexture);
@ -407,4 +409,48 @@ namespace NES
_pSwapChain->Present(0, 0);
}
}
void Renderer::UpdateFrame(uint8_t* frameBuffer)
{
_frameChanged = true;
_frameLock.Acquire();
memcpy(_nextFrameBuffer, frameBuffer, 256 * 240 * 4);
_frameLock.Release();
}
void Renderer::TakeScreenshot(wstring romFilename)
{
uint32_t* frameBuffer = new uint32_t[256 * 240];
_frameLock.Acquire();
memcpy(frameBuffer, _nextFrameBuffer, 256 * 240 * 4);
_frameLock.Release();
//ARGB -> ABGR
for(uint32_t i = 0; i < 256 * 240; i++) {
frameBuffer[i] = (frameBuffer[i] & 0xFF00FF00) | ((frameBuffer[i] & 0xFF0000) >> 16) | ((frameBuffer[i] & 0xFF) << 16);
}
int counter = 0;
wstring baseFilename = FolderUtilities::GetScreenshotFolder() + romFilename;
wstring ssFilename;
while(true) {
wstring counterStr = std::to_wstring(counter);
while(counterStr.length() < 3) {
counterStr = L"0" + counterStr;
}
ssFilename = baseFilename + L"_" + counterStr + L".png";
ifstream file(ssFilename, ios::in);
if(file) {
file.close();
} else {
break;
}
counter++;
}
PNGWriter::WritePNG(ssFilename, (uint8_t*)frameBuffer, 256, 240);
}
}

View File

@ -3,6 +3,9 @@
#include "DirectXTK\SpriteFont.h"
#include "../Core/IVideoDevice.h"
#include "../Core/IMessageManager.h"
#include "../Utilities/PNGWriter.h"
#include "../Utilities/FolderUtilities.h"
#include "../Utilities/SimpleLock.h"
using namespace DirectX;
@ -33,6 +36,8 @@ namespace NES {
bool _frameChanged = true;
uint8_t* _nextFrameBuffer = nullptr;
SimpleLock _frameLock;
unique_ptr<SpriteFont> _font;
ID3D11Texture2D* _overlayTexture = nullptr;
@ -91,10 +96,7 @@ namespace NES {
return (_flags & flag) == flag;
}
void UpdateFrame(uint8_t* frameBuffer)
{
_frameChanged = true;
memcpy(_nextFrameBuffer, frameBuffer, 256 * 240 * 4);
}
void UpdateFrame(uint8_t* frameBuffer);
void TakeScreenshot(wstring romFilename);
};
}

Binary file not shown.

View File

@ -39,6 +39,13 @@ wstring FolderUtilities::GetMovieFolder()
return folder;
}
wstring FolderUtilities::GetScreenshotFolder()
{
wstring folder = GetHomeFolder() + L"Screenshots\\";
CreateDirectory(folder.c_str(), nullptr);
return folder;
}
vector<wstring> FolderUtilities::GetFolders(wstring rootFolder)
{
HANDLE hFind;

View File

@ -9,6 +9,7 @@ class FolderUtilities
static wstring GetSaveFolder();
static wstring GetSaveStateFolder();
static wstring GetMovieFolder();
static wstring GetScreenshotFolder();
static vector<wstring> GetFolders(wstring rootFolder);
static vector<wstring> GetFilesInFolder(wstring rootFolder, wstring mask, bool recursive);

25
Utilities/PNGWriter.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "stdafx.h"
#include "miniz.h"
using std::ofstream;
class PNGWriter
{
public:
static bool WritePNG(wstring filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32)
{
size_t pngSize = 0;
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel/8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
if(!pngData) {
std::cout << "tdefl_write_image_to_png_file_in_memory_ex() failed!" << std::endl;
return false;
} else {
ofstream file(filename, ios::out | ios::binary);
file.write((char*)pngData, pngSize);
file.close();
mz_free(pngData);
return true;
}
}
};

View File

@ -75,6 +75,7 @@
<ClInclude Include="CRC32.h" />
<ClInclude Include="FolderUtilities.h" />
<ClInclude Include="miniz.h" />
<ClInclude Include="PNGWriter.h" />
<ClInclude Include="UPnPPortMapper.h" />
<ClInclude Include="SimpleLock.h" />
<ClInclude Include="Socket.h" />

View File

@ -56,6 +56,9 @@
<ClInclude Include="miniz.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PNGWriter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">