Added support for dumping avi files (thanks baby.lueshi). Use Microsoft Video 1 codec for starters. Make sure to check the dump rendered frames box in the video plugin settings, or it won't work.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2781 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Marcus Wanners 2009-03-28 21:07:16 +00:00
parent da07d04da9
commit 711f08c29b
20 changed files with 418 additions and 29 deletions

View File

@ -21,7 +21,7 @@ System Requirements:
[Windows Version]
DolphinWx.exe: The main program
Dolphin.exe: The main program
Arguments:
-d Run Dolphin with the debugger tools
-l Run Dolphin with the logmanager enabled

View File

@ -69,6 +69,7 @@
#define SCREENSHOTS_DIR "ScreenShots"
#define DUMP_DIR "Dump"
#define DUMP_TEXTURES_DIR "Textures"
#define DUMP_FRAMES_DIR "Frames"
#define LOGS_DIR "Logs"
#define MAIL_LOGS_DIR "Mail"
@ -122,7 +123,8 @@
#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP
#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP
#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
#define FULL_FRAMES_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP DUMP_FRAMES_DIR
#define FULL_DUMP_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP
#define FULL_DUMP_TEXTURES_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP DUMP_TEXTURES_DIR
#define FULL_LOGS_DIR FULL_USERDATA_DIR LOGS_DIR DIR_SEP

View File

@ -142,6 +142,22 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
_uReturnValue = AlphaReg;
return;
case 0x010:
_uReturnValue = 0x80;
return;
case 0x012:
_uReturnValue = 0xA0;
return;
case 0x014:
_uReturnValue = 0x80;
return;
case 0x016:
_uReturnValue = 0xA0;
return;
default:
WARN_LOG(PIXELENGINE, "(r16): unknown @ %08x", _iAddress);
break;

View File

@ -0,0 +1,157 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AVIDump.h"
#include "tchar.h"
#include <cstdio>
#include <cstring>
#include <vfw.h>
#include <winerror.h>
#include "CommonPaths.h"
#include "Log.h"
static HWND m_emuWnd;
static int m_width;
static int m_height;
static LONG m_byteBuffer;
static LONG m_frameCount;
static LONG m_totalBytes;
static PAVIFILE m_file;
static int m_fileCount;
static PAVISTREAM m_stream;
static PAVISTREAM m_streamCompressed;
static AVISTREAMINFO m_header;
static AVICOMPRESSOPTIONS m_options;
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
static BITMAPINFOHEADER m_bitmap;
bool AVIDump::Start(HWND hWnd, int w, int h)
{
m_emuWnd = hWnd;
m_fileCount = 0;
m_width = w;
m_height = h;
return CreateFile();
}
bool AVIDump::CreateFile() {
m_totalBytes = 0;
m_frameCount = 0;
char movie_file_name[255];
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
AVIFileInit();
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
if (FAILED(AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL))) {
Stop();
return false;
}
SetBitmapFormat();
NOTICE_LOG(VIDEO, "Setting video format...");
if (!SetVideoFormat()) {
Stop();
return false;
}
if (!m_fileCount) {
if (!SetCompressionOptions()) {
Stop();
return false;
}
}
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
Stop();
return false;
}
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
Stop();
return false;
}
return true;
}
void AVIDump::CloseFile()
{
if (m_streamCompressed) {
AVIStreamClose(m_streamCompressed);
m_streamCompressed = NULL;
}
if (m_stream) {
AVIStreamClose(m_stream);
m_stream = NULL;
}
if (m_file) {
AVIFileRelease(m_file);
m_file = NULL;
}
AVIFileExit();
}
void AVIDump::Stop()
{
CloseFile();
m_fileCount = 0;
}
void AVIDump::AddFrame(char *data)
{
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
m_totalBytes += m_byteBuffer;
// Fun fact: VfW can't property save files over 2gb in size, but can keep
// writing to them up to 4gb.
if (m_totalBytes >= 2000000000) {
CloseFile();
m_fileCount++;
CreateFile();
}
}
void AVIDump::SetBitmapFormat()
{
memset(&m_bitmap, 0, sizeof(m_bitmap));
m_bitmap.biSize = 0x28;
m_bitmap.biPlanes = 1;
m_bitmap.biBitCount = 24;
m_bitmap.biWidth = m_width;
m_bitmap.biHeight = m_height;
m_bitmap.biSizeImage = 3 * m_width * m_height;
}
bool AVIDump::SetCompressionOptions()
{
memset(&m_options, 0, sizeof(m_options));
m_arrayOptions[0] = &m_options;
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
}
bool AVIDump::SetVideoFormat()
{
memset(&m_header, 0, sizeof(m_header));
m_header.fccType = streamtypeVIDEO;
m_header.dwScale = 1;
// TODO: Decect FPS using NTSC/PAL
m_header.dwRate = 60;
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
}

View File

@ -484,6 +484,14 @@
<Filter
Name="Util"
>
<File
RelativePath=".\Src\AVIDump.cpp"
>
</File>
<File
RelativePath=".\Src\AVIDump.h"
>
</File>
<File
RelativePath=".\Src\ImageWrite.cpp"
>

View File

@ -92,7 +92,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="&quot;..\..\core\common\win32\release\common.lib&quot;"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoDX9.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -200,7 +200,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX9.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -299,7 +299,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="&quot;..\..\core\common\win32\debug\common.lib&quot;"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_VideoDX9D.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -397,7 +397,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX9D.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -505,7 +505,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib"
AdditionalDependencies="dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib cg.lib cgD3D9.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoDX9DF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -614,7 +614,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib"
AdditionalDependencies="cg.lib cgD3D9.lib dsound.lib odbc32.lib odbccp32.lib comctl32.lib d3d9.lib d3dx9.lib winmm.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX9DF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"

View File

@ -41,6 +41,7 @@ void Config::Load()
iniFile.Get("Settings", "OverlayProjection", &bOverlayProjStats, false);
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
iniFile.Get("Settings", "DumpFrames", &bDumpFrames, 0);
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
@ -68,6 +69,7 @@ void Config::Save()
iniFile.Set("Settings", "OverlayProjection", bOverlayProjStats);
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
iniFile.Set("Settings", "DumpFrames", bDumpFrames);
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
iniFile.Set("Settings", "Multisample", iMultisampleMode);
iniFile.Set("Settings", "TexDumpPath", texDumpPath);

View File

@ -39,6 +39,7 @@ struct Config
bool bOverlayStats;
bool bOverlayProjStats;
bool bDumpTextures;
bool bDumpFrames;
bool bOldCard;
bool bShowShaderErrors;
//enhancements

View File

@ -123,6 +123,7 @@ struct TabAdvanced : public W32Util::Tab
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYPROJSTATS), g_Config.bOverlayProjStats);
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
Button_SetCheck(GetDlgItem(hDlg,IDC_DUMPFRAMES), g_Config.bDumpFrames);
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
@ -160,6 +161,7 @@ struct TabAdvanced : public W32Util::Tab
g_Config.bOverlayProjStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYPROJSTATS)) ? true : false;
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
g_Config.bDumpFrames = Button_GetCheck(GetDlgItem(hDlg,IDC_DUMPFRAMES)) ? true : false;
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
char temp[MAX_PATH];
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);

View File

@ -37,6 +37,7 @@
#include "TextureCache.h"
#include "Utils.h"
#include "EmuWindow.h"
#include "AVIDump.h"
#include <Cg/cg.h>
#include <Cg/cgD3D9.h>
@ -52,6 +53,9 @@ float Renderer::m_height;
float Renderer::xScale;
float Renderer::yScale;
int Renderer::m_recordWidth;
int Renderer::m_recordHeight;
std::vector<LPDIRECT3DBASETEXTURE9> Renderer::m_Textures;
DWORD Renderer::m_RenderStates[MaxRenderStates+46];
@ -59,6 +63,9 @@ DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
DWORD Renderer::m_FVF;
bool Renderer::m_LastFrameDumped;
bool Renderer::m_AVIDumping;
#define NUMWNDRES 6
extern int g_Res[NUMWNDRES][2];
@ -106,6 +113,9 @@ void Renderer::Init(SVideoInitialize &_VideoInitialize)
xScale = width / (float)EFB_WIDTH;
yScale = height / (float)EFB_HEIGHT;
m_LastFrameDumped = false;
m_AVIDumping = false;
// We're not using much fixed function. Let's just set the matrices to identity.
D3DXMATRIX mtx;
D3DXMatrixIdentity(&mtx);
@ -126,6 +136,10 @@ void Renderer::Shutdown()
D3D::font.Shutdown();
D3D::EndFrame();
D3D::Close();
if(m_AVIDumping) {
AVIDump::Stop();
}
}
void Renderer::Initialize()
@ -194,6 +208,19 @@ void dumpMatrix(D3DXMATRIX &mtx)
}
}
void formatBufferDump(char *in, char *out, int w, int h, int p)
{
for(int i = 0; i < h; i++) {
char *line = in + (h - i - 1) * p;
for (int j = 0; j < w; j++) {
memcpy(out, line, 3);
out += 3;
line += 4;
}
}
}
void Renderer::SwapBuffers()
{
// Center window again.
@ -208,6 +235,53 @@ void Renderer::SwapBuffers()
::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE);
}
// Frame dumping routine
if (g_Config.bDumpFrames) {
D3DDISPLAYMODE DisplayMode;
if (SUCCEEDED(D3D::dev->GetDisplayMode(0, &DisplayMode))) {
LPDIRECT3DSURFACE9 surf;
if (SUCCEEDED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surf, NULL))) {
if (!m_LastFrameDumped) {
RECT windowRect;
GetWindowRect(EmuWindow::GetWnd(), &windowRect);
m_recordWidth = windowRect.right - windowRect.left;
m_recordHeight = windowRect.bottom - windowRect.top;
m_AVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), m_recordWidth, m_recordHeight);
if (!m_AVIDumping) {
PanicAlert("Error dumping frames to AVI.");
} else {
char msg [255];
sprintf(msg, "Dumping Frames to \"%s/framedump0.avi\" (%dx%d RGB24)", FULL_FRAMES_DIR, m_recordWidth, m_recordHeight);
AddMessage(msg, 2000);
}
}
if (m_AVIDumping) {
if (SUCCEEDED(D3D::dev->GetFrontBufferData(0, surf))) {
RECT windowRect;
GetWindowRect(EmuWindow::GetWnd(), &windowRect);
D3DLOCKED_RECT rect;
if (SUCCEEDED(surf->LockRect(&rect, &windowRect, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) {
char *data = (char *) malloc(3 * m_recordWidth * m_recordHeight);
formatBufferDump((char *) rect.pBits, data, m_recordWidth, m_recordHeight, rect.Pitch);
AVIDump::AddFrame(data);
free(data);
surf->UnlockRect();
}
}
}
m_LastFrameDumped = true;
surf->Release();
}
}
} else {
if(m_LastFrameDumped && m_AVIDumping) {
AVIDump::Stop();
m_AVIDumping = false;
}
m_LastFrameDumped = false;
}
//Finish up the current frame, print some stats
Postprocess::FinalizeFrame();
if (g_Config.bOverlayStats)

View File

@ -38,6 +38,10 @@ class Renderer
static float m_height;
static float xScale;
static float yScale;
static bool m_LastFrameDumped;
static bool m_AVIDumping;
static int m_recordWidth;
static int m_recordHeight;
const static int MaxTextureStages = 9;
const static int MaxRenderStates = 210;
const static DWORD MaxTextureTypes = 33;

View File

@ -57,6 +57,7 @@
#define IDC_TEXFMT_CENTER 1034
#define IDC_TEXFMT_OVERLAY 1035
#define IDC_OVERLAYPROJSTATS 1036
#define IDC_DUMPFRAMES 1037
// Next default values for new objects
//

View File

@ -50,7 +50,7 @@ BEGIN
CONTROL "",IDC_REGISTERSELECT,"SysTabControl32",TCS_BUTTONS,80,52,145,13
END
IDD_ADVANCED DIALOGEX 0, 0, 206, 175
IDD_ADVANCED DIALOGEX 0, 0, 206, 195
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
@ -60,13 +60,14 @@ BEGIN
CONTROL "Overlay &Projection Statistics",IDC_OVERLAYPROJSTATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,42,118,9
CONTROL "Show s&hader compilation errors",IDC_SHOWSHADERERRORS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,53,127,9
GROUPBOX "&Data dumping",IDC_STATIC,7,91,192,44
GROUPBOX "&Data dumping",IDC_STATIC,7,91,192,58
CONTROL "Dump &textures to:",IDC_TEXDUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,104,70,9
EDITTEXT IDC_TEXDUMPPATH,25,116,148,12,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_BROWSETEXDUMPPATH,176,116,14,13
GROUPBOX "Texture Format Overlay",IDC_STATIC,7,138,192,30
CONTROL "Enable Overlay",IDC_TEXFMT_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,150,74,10
CONTROL "Centered",IDC_TEXFMT_CENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,150,82,10
CONTROL "Dump Frames to User/Dump/Frames",IDC_DUMPFRAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,132,138,9
GROUPBOX "Texture Format Overlay",IDC_STATIC,7,156,192,30
CONTROL "Enable Overlay",IDC_TEXFMT_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,168,74,10
CONTROL "Centered",IDC_TEXFMT_CENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,168,82,10
END
IDD_ENHANCEMENTS DIALOGEX 0, 0, 207, 175

View File

@ -90,7 +90,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoOGL.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -199,7 +199,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib rpcrt4.lib glew64s.lib"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib rpcrt4.lib glew64s.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoOGL.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -298,7 +298,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_VideoOGLD.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -396,7 +396,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib glew64s.lib rpcrt4.lib"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib glew64s.lib rpcrt4.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoOGLD.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -504,7 +504,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib glew32s.lib libjpeg.lib glu32.lib rpcrt4.lib vfw32.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoOGLDF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -614,7 +614,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib glew64s.lib rpcrt4.lib"
AdditionalDependencies="comctl32.lib winmm.lib cg.lib cgGL.lib opengl32.lib libjpeg64.lib glu32.lib glew64s.lib rpcrt4.lib vfw32.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoOGLDF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"

View File

@ -61,6 +61,7 @@ void Config::Load()
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
iniFile.Get("Settings", "DumpEFBTarget", &bDumpEFBTarget, 0);
iniFile.Get("Settings", "DumpFrames", &bDumpFrames, 0);
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
iniFile.Get("Settings", "MSAA", &iMultisampleMode, 0);
iniFile.Get("Settings", "DstAlphaPass", &bDstAlphaPass, false);
@ -143,6 +144,7 @@ void Config::Save()
iniFile.Set("Settings", "Show", iCompileDLsLevel);
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
iniFile.Set("Settings", "DumpEFBTarget", bDumpEFBTarget);
iniFile.Set("Settings", "DumpFrames", bDumpFrames);
iniFile.Set("Settings", "ShowEFBCopyRegions", bShowEFBCopyRegions);
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
iniFile.Set("Settings", "MSAA", iMultisampleMode);

View File

@ -84,6 +84,7 @@ struct Config
// Utility
bool bDumpTextures;
bool bDumpEFBTarget;
bool bDumpFrames;
// Hacks
bool bEFBCopyDisable;

View File

@ -54,6 +54,7 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DUMPEFBTARGET, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DUMPFRAMES, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_EFBCOPYDISABLEHOTKEY, ConfigDialog::AdvancedSettingsChanged)
@ -334,6 +335,18 @@ void ConfigDialog::CreateGUIControls()
m_DumpTextures->SetValue(g_Config.bDumpTextures);
m_DumpEFBTarget = new wxCheckBox(m_PageAdvanced, ID_DUMPEFBTARGET, wxT("Dump EFB Target"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_DumpEFBTarget->SetValue(g_Config.bDumpEFBTarget);
m_DumpFrames = new wxCheckBox(m_PageAdvanced, ID_DUMPFRAMES, wxT("Dump Rendered Frames"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
#ifdef _WIN32
m_DumpFrames->SetToolTip(wxT(
"When dumping begins, you will be prompted to choose a video codec to"
" encode the video in."));
#else
m_DumpFrames->SetToolTip(wxT(
"!!WARNING!! This option dumps raw bitmaps of each frame, and will fill up"
" your hard drive very quickly. Only turn this on if you have a named pipe"
" set up for the dump or several gigabytes of space available."));
#endif
m_DumpFrames->SetValue(g_Config.bDumpFrames);
// Hacks controls
m_SafeTextureCache = new wxCheckBox(m_PageAdvanced, ID_SAFETEXTURECACHE, wxT("Use Safe texture cache"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@ -394,6 +407,7 @@ void ConfigDialog::CreateGUIControls()
sUtilities = new wxBoxSizer(wxHORIZONTAL);
sUtilities->Add(m_DumpTextures, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sUtilities->Add(m_DumpEFBTarget, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sUtilities->Add(m_DumpFrames, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
sbUtilities->Add(sUtilities, 1, wxEXPAND);
// Sizers
@ -525,6 +539,9 @@ void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event)
case ID_DUMPEFBTARGET:
g_Config.bDumpEFBTarget = m_DumpEFBTarget->IsChecked();
break;
case ID_DUMPFRAMES:
g_Config.bDumpFrames = m_DumpFrames->IsChecked();
break;
case ID_TEXTUREPATH:
break;
case ID_CHECKBOX_DISABLECOPYEFB:

View File

@ -106,6 +106,7 @@ class ConfigDialog : public wxDialog
wxCheckBox *m_DstAlphaPass;
wxCheckBox *m_DumpTextures;
wxCheckBox *m_DumpEFBTarget;
wxCheckBox *m_DumpFrames;
wxStaticBox * m_StaticBox_EFB;
wxCheckBox *m_CheckBox_DisableCopyEFB;
wxRadioButton *m_Radio_CopyEFBToRAM, *m_Radio_CopyEFBToGL;
@ -161,6 +162,7 @@ class ConfigDialog : public wxDialog
ID_DUMPTEXTURES,
ID_DUMPEFBTARGET,
ID_DUMPFRAMES,
ID_TEXTUREPATH,
ID_CHECKBOX_DISABLECOPYEFB,

View File

@ -19,6 +19,7 @@
#include <vector>
#include <cmath>
#include <cstdio>
#include "GLUtil.h"
@ -29,6 +30,7 @@
#include <mmsystem.h>
#endif
#include "CommonPaths.h"
#include "Config.h"
#include "Profiler.h"
#include "Statistics.h"
@ -52,6 +54,7 @@
#include "main.h" // Local
#ifdef _WIN32
#include "OS/Win32.h"
#include "AVIDump.h"
#endif
#if defined(HAVE_WX) && HAVE_WX
@ -71,6 +74,13 @@ RasterFont* s_pfont = NULL;
static bool s_bFullscreen = false;
static bool s_bLastFrameDumped = false;
#ifdef _WIN32
static bool s_bAVIDumping = false;
#else
static FILE* f_pFrameDump;
#endif
static int nZBufferRender = 0; // if > 0, then use zbuffer render, and count down.
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
@ -484,6 +494,15 @@ void Renderer::Shutdown(void)
glDeleteFramebuffersEXT(1, &s_uFramebuffer);
s_uFramebuffer = 0;
}
#ifdef _WIN32
if(s_bAVIDumping) {
AVIDump::Stop();
}
#else
if(f_pFrameDump != NULL) {
fclose(f_pFrameDump);
}
#endif
}
bool Renderer::InitializeGL()
@ -1092,6 +1111,81 @@ void Renderer::Swap(const TRectangle& rc)
s_criticalScreenshot.Leave();
}
// Frame dumps are handled a little differently in Windows
#ifdef _WIN32
if (g_Config.bDumpFrames) {
s_criticalScreenshot.Enter();
int w = OpenGL_GetBackbufferWidth();
int h = OpenGL_GetBackbufferHeight();
u8 *data = (u8 *) malloc(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);
if (glGetError() == GL_NO_ERROR) {
if (!s_bLastFrameDumped) {
s_bAVIDumping = AVIDump::Start(EmuWindow::GetChildParentWnd(), w, h);
if (!s_bAVIDumping) {
PanicAlert("Error dumping frames to AVI.");
} else {
char msg [255];
sprintf(msg, "Dumping Frames to \"%s/framedump0.avi\" (%dx%d RGB24)", FULL_FRAMES_DIR, w, h);
OSD::AddMessage(msg, 2000);
}
}
if (s_bAVIDumping) {
AVIDump::AddFrame((char *) data);
}
s_bLastFrameDumped = true;
}
free(data);
s_criticalScreenshot.Leave();
} else {
if(s_bLastFrameDumped && s_bAVIDumping) {
AVIDump::Stop();
s_bAVIDumping = false;
}
s_bLastFrameDumped = false;
}
#else
if (g_Config.bDumpFrames) {
s_criticalScreenshot.Enter();
char movie_file_name[255];
int w = OpenGL_GetBackbufferWidth();
int h = OpenGL_GetBackbufferHeight();
u8 *data = (u8 *) malloc(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data);
if (glGetError() == GL_NO_ERROR) {
if (!s_bLastFrameDumped) {
sprintf(movie_file_name, "%s/framedump.raw", FULL_FRAMES_DIR);
f_pFrameDump = fopen(movie_file_name, "wb");
if (f_pFrameDump == NULL) {
PanicAlert("Error opening framedump.raw for writing.");
} else {
char msg [255];
sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name, w, h);
OSD::AddMessage(msg, 2000);
}
}
if (f_pFrameDump != NULL) {
FlipImageData(data, w, h);
fwrite(data, w * 3, h, f_pFrameDump);
fflush(f_pFrameDump);
}
s_bLastFrameDumped = true;
}
free(data);
s_criticalScreenshot.Leave();
} else {
if(s_bLastFrameDumped && f_pFrameDump != NULL) {
fclose(f_pFrameDump);
f_pFrameDump = NULL;
}
s_bLastFrameDumped = false;
}
#endif
// Place messages on the picture, then copy it to the screen
SwapBuffers();
s_bNativeResolution = g_Config.bNativeResolution;
@ -1336,6 +1430,20 @@ bool Renderer::SaveRenderTarget(const char *filename, int w, int h)
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data);
if (glGetError() != GL_NO_ERROR)
return false;
FlipImageData(data, w, h);
#if defined(HAVE_WX) && HAVE_WX
wxImage a(w, h, data);
a.SaveFile(wxString::FromAscii(filename), wxBITMAP_TYPE_BMP);
bool result = true;
#else
bool result = SaveTGA(filename, w, h, data);
free(data);
#endif
return result;
}
void Renderer::FlipImageData(u8 *data, int w, int h)
{
// Flip image upside down. Damn OpenGL.
for (int y = 0; y < h / 2; y++)
{
@ -1346,16 +1454,6 @@ bool Renderer::SaveRenderTarget(const char *filename, int w, int h)
std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]);
}
}
#if defined(HAVE_WX) && HAVE_WX
wxImage a(w, h, data);
a.SaveFile(wxString::FromAscii(filename), wxBITMAP_TYPE_BMP);
bool result = true;
#else
bool result = SaveTGA(filename, w, h, data);
free(data);
#endif
return result;
}
//////////////////////////////////////////////////////////////////////////////////////

View File

@ -100,6 +100,7 @@ public:
static void RenderText(const char* pstr, int left, int top, u32 color);
static void DrawDebugText();
static void SetScreenshot(const char *filename);
static void FlipImageData(u8 *data, int w, int h);
static bool SaveRenderTarget(const char *filename, int w, int h);
// Finish up the current frame, print some stats