completely reworked AVI recording

compression will be re-added soon
This commit is contained in:
spacy51 2007-12-16 19:45:25 +00:00
parent 06abf42d45
commit 396170e506
11 changed files with 588 additions and 494 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="VisualBoyAdvance"
ProjectGUID="{6D4C5EC8-933F-4C05-A1BF-498E658576DF}"
RootNamespace="VBA"
@ -88,7 +88,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib Vfw32.Lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib HtmlHelp.lib"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib HtmlHelp.lib"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
LinkIncremental="2"
@ -129,6 +129,115 @@
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)_temp"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2"
BuildLogFile="$(IntDir)\$(ProjectName)_BuildLog.htm"
>
<Tool
Name="VCPreBuildEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="0"
AdditionalIncludeDirectories="..\dependencies\zlib;..\dependencies\libpng;&quot;..\dependencies\File_Extractor-0.4.2\fex&quot;;..\dependencies\cximage;..\dependencies\msvc"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;DEV_VERSION;BKPT_SUPPORT;CRT_SECURE_NO_WARNINGS;HAS_FILE_EXTRACTOR;C_CORE"
StringPooling="false"
MinimalRebuild="true"
BasicRuntimeChecks="3"
SmallerTypeCheck="false"
RuntimeLibrary="1"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)\$(ProjectName).pdb"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateManifest="true"
AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
IgnoreDefaultLibraryNames="nafxcwd.lib;LIBCMTD.lib"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="1"
EnableCOMDATFolding="1"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
@ -198,7 +307,7 @@
Name="VCLinkerTool"
RegisterOutput="false"
IgnoreImportLibrary="false"
AdditionalDependencies="nafxcw.lib LIBCMT.lib Vfw32.Lib OpenGL32.Lib dinput8.lib winmm.lib dxguid.lib ddraw.lib Dsound.lib htmlhelp.lib"
AdditionalDependencies="nafxcw.lib LIBCMT.lib OpenGL32.Lib dinput8.lib winmm.lib dxguid.lib ddraw.lib Dsound.lib htmlhelp.lib"
ShowProgress="0"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
@ -251,115 +360,6 @@
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)_temp"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2"
BuildLogFile="$(IntDir)\$(ProjectName)_BuildLog.htm"
>
<Tool
Name="VCPreBuildEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="0"
AdditionalIncludeDirectories="..\dependencies\zlib;..\dependencies\libpng;&quot;..\dependencies\File_Extractor-0.4.2\fex&quot;;..\dependencies\cximage;..\dependencies\msvc"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;DEV_VERSION;BKPT_SUPPORT;CRT_SECURE_NO_WARNINGS;HAS_FILE_EXTRACTOR;C_CORE"
StringPooling="false"
MinimalRebuild="true"
BasicRuntimeChecks="3"
SmallerTypeCheck="false"
RuntimeLibrary="1"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)\$(ProjectName).pdb"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib Vfw32.Lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateManifest="true"
AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
IgnoreDefaultLibraryNames="nafxcwd.lib;LIBCMTD.lib"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="1"
EnableCOMDATFolding="1"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
@ -430,7 +430,7 @@
Name="VCLinkerTool"
RegisterOutput="false"
IgnoreImportLibrary="false"
AdditionalDependencies="nafxcw.lib LIBCMT.lib Vfw32.Lib OpenGL32.Lib dinput8.lib winmm.lib dxguid.lib ddraw.lib Dsound.lib"
AdditionalDependencies="nafxcw.lib LIBCMT.lib OpenGL32.Lib dinput8.lib winmm.lib dxguid.lib ddraw.lib Dsound.lib"
ShowProgress="0"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
@ -528,16 +528,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -d__DJGPP__ -O1 -fwin32 -Xvc -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
@ -548,6 +538,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -d__DJGPP__ -O1 -fwin32 -Xvc -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -623,16 +623,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
@ -643,6 +633,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -667,16 +667,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
@ -687,6 +677,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -711,16 +711,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
@ -731,6 +721,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -755,16 +755,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
@ -775,6 +765,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -O1 -isrc/ -fwin32 -Xvc -w-orphan-labels -o&quot;$(IntDir)\$(InputName).obj&quot; -- &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -1347,7 +1347,7 @@
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
@ -1355,7 +1355,7 @@
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"

View File

@ -198,73 +198,6 @@ void utilPutWord(u8 *p, u16 value)
*p = (value >> 8) & 255;
}
void utilWriteBMP(char *buf, int w, int h, u8 *pix)
{
u8 *b = (u8 *)buf;
int sizeX = w;
int sizeY = h;
switch(systemColorDepth) {
case 16:
{
u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
for(int y = 0; y < sizeY; y++) {
for(int x = 0; x < sizeX; x++) {
u16 v = *p++;
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
p -= 2*(w+2);
}
}
break;
case 24:
{
u8 *pixU8 = (u8 *)pix+3*w*(h-1);
for(int y = 0; y < sizeY; y++) {
for(int x = 0; x < sizeX; x++) {
if(systemRedShift > systemBlueShift) {
*b++ = *pixU8++; // B
*b++ = *pixU8++; // G
*b++ = *pixU8++; // R
} else {
int red = *pixU8++;
int green = *pixU8++;
int blue = *pixU8++;
*b++ = blue;
*b++ = green;
*b++ = red;
}
}
pixU8 -= 2*3*w;
}
}
break;
case 32:
{
u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
for(int y = 0; y < sizeY; y++) {
for(int x = 0; x < sizeX; x++) {
u32 v = *pixU32++;
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
pixU32++;
pixU32 -= 2*(w+1);
}
}
break;
}
}
bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
{
u8 writeBuffer[512 * 3];

View File

@ -38,7 +38,6 @@ typedef struct {
extern bool utilWritePNGFile(const char *, int, int, u8 *);
extern bool utilWriteBMPFile(const char *, int, int, u8 *);
extern void utilApplyIPS(const char *ips, u8 **rom, int *size);
extern void utilWriteBMP(char *, int, int, u8 *);
extern bool utilIsGBAImage(const char *);
extern bool utilIsGBImage(const char *);
extern bool utilIsZipFile(const char *);

View File

@ -1,6 +1,5 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// Copyright (C) 2007 VBA-M development team
// 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
@ -16,172 +15,242 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
#include "AVIWrite.h"
#pragma comment( lib, "vfw32.lib" )
AVIWrite::AVIWrite()
{
m_failed = false;
m_file = NULL;
m_stream = NULL;
m_streamCompressed = NULL;
m_streamSound = NULL;
m_samplesSound = 0;
m_failed = false;
m_file = NULL;
m_videoStream = NULL;
m_audioStream = NULL;
m_frameRate = 0;
m_frameCounter = 0;
m_sampleCounter = 0;
m_videoFrameSize = 0;
m_audioFrameSize = 0;
AVIFileInit();
AVIFileInit();
}
AVIWrite::~AVIWrite()
{
if(m_streamSound)
AVIStreamClose(m_streamSound);
if( m_audioStream ) {
AVIStreamRelease( m_audioStream );
}
if(m_streamCompressed)
AVIStreamClose(m_streamCompressed);
if( m_videoStream ) {
AVIStreamRelease( m_videoStream );
}
if(m_stream)
AVIStreamClose(m_stream);
if( m_file ) {
AVIFileRelease( m_file );
}
if(m_file)
AVIFileClose(m_file);
AVIFileExit();
AVIFileExit();
}
void AVIWrite::SetVideoFormat(BITMAPINFOHEADER *bh)
bool AVIWrite::CreateAVIFile( LPCTSTR filename )
{
// force size to 0x28 to avoid extra fields
memcpy(&m_bitmap, bh, 0x28);
if( m_file || m_failed ) return false;
HRESULT err = 0;
// -- create the AVI file --
err = AVIFileOpen(
&m_file,
filename,
OF_CREATE | OF_WRITE | OF_SHARE_EXCLUSIVE,
NULL
);
if( FAILED( err ) ) {
m_failed = true;
return false;
}
return true;
}
void AVIWrite::SetSoundFormat(WAVEFORMATEX *format)
// colorBits: 16, 24 or 32
bool AVIWrite::CreateVideoStream( LONG imageWidth, LONG imageHeight, WORD colorBits, DWORD framesPerSecond )
{
memcpy(&m_soundFormat, format, sizeof(WAVEFORMATEX));
ZeroMemory(&m_soundHeader, sizeof(AVISTREAMINFO));
// setup the sound stream header
m_soundHeader.fccType = streamtypeAUDIO;
m_soundHeader.dwQuality = (DWORD)-1;
m_soundHeader.dwScale = format->nBlockAlign;
m_soundHeader.dwInitialFrames = 1;
m_soundHeader.dwRate = format->nAvgBytesPerSec;
m_soundHeader.dwSampleSize = format->nBlockAlign;
if( m_videoStream || m_failed ) return false;
// create the sound stream
if(FAILED(AVIFileCreateStream(m_file, &m_streamSound, &m_soundHeader))) {
m_failed = true;
return;
}
HRESULT err = 0;
AVISTREAMINFO videoInfo;
BITMAPINFOHEADER bitmapInfo;
ZeroMemory( &videoInfo, sizeof( videoInfo ) );
ZeroMemory( &bitmapInfo, sizeof( bitmapInfo ) );
// setup the sound stream format
if(FAILED(AVIStreamSetFormat(m_streamSound, 0 , (void *)&m_soundFormat,
sizeof(WAVEFORMATEX)))) {
m_failed = true;
return;
}
// -- initialize the video stream information --
videoInfo.fccType = streamtypeVIDEO;
videoInfo.dwScale = 1;
videoInfo.dwRate = framesPerSecond;
videoInfo.dwSuggestedBufferSize = imageWidth * imageHeight * ( colorBits >> 3 );
// -- create the video stream --
err = AVIFileCreateStream(
m_file,
&m_videoStream,
&videoInfo
);
if( FAILED( err ) ) {
m_failed = true;
return false;
}
// -- initialize the video stream format --
bitmapInfo.biSize = sizeof( bitmapInfo );
bitmapInfo.biWidth = imageWidth;
bitmapInfo.biHeight = imageHeight;
bitmapInfo.biBitCount = colorBits;
bitmapInfo.biPlanes = 1;
bitmapInfo.biCompression = BI_RGB;
bitmapInfo.biSizeImage = imageWidth * imageHeight * ( colorBits >> 3 );
// -- set the video stream format --
err = AVIStreamSetFormat(
m_videoStream,
0,
&bitmapInfo,
sizeof( bitmapInfo )
);
if( FAILED( err ) ) {
m_failed = true;
return false;
}
m_frameRate = framesPerSecond;
m_videoFrameSize = imageWidth * imageHeight * ( colorBits >> 3 );
return true;
}
bool AVIWrite::Open(const char *filename)
// call AddVideoStream() first
// channelCount: max. 2
// sampleBits: max. 16
bool AVIWrite::CreateAudioStream( WORD channelCount, DWORD sampleRate, WORD sampleBits )
{
// create the AVI file
if(FAILED(AVIFileOpen(&m_file,
filename,
OF_WRITE | OF_CREATE,
NULL))) {
m_failed = true;
return false;
}
// setup the video stream information
ZeroMemory(&m_header, sizeof(AVISTREAMINFO));
m_header.fccType = streamtypeVIDEO;
m_header.dwScale = 1;
m_header.dwRate = m_fps;
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
if( m_audioStream || m_failed ) return false;
// create the video stream
if(FAILED(AVIFileCreateStream(m_file,
&m_stream,
&m_header))) {
m_failed = true;
return false;
}
HRESULT err = 0;
AVISTREAMINFO audioInfo;
WAVEFORMATEX waveInfo;
ZeroMemory( &audioInfo, sizeof( audioInfo ) );
ZeroMemory( &waveInfo, sizeof( waveInfo ) );
ZeroMemory(&m_options, sizeof(AVICOMPRESSOPTIONS));
m_arrayOptions[0] = &m_options;
// -- initialize the audio stream information --
audioInfo.fccType = streamtypeAUDIO;
audioInfo.dwQuality = (DWORD)-1;
audioInfo.dwScale = channelCount * ( sampleBits >> 3 );
audioInfo.dwRate = channelCount * ( sampleBits >> 3 ) * sampleRate;
audioInfo.dwInitialFrames = 1;
audioInfo.dwSampleSize = channelCount * ( sampleBits >> 3 );
audioInfo.dwSuggestedBufferSize = 0;
// call the dialog to setup the compress options to be used
if(!AVISaveOptions(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), 0, 1, &m_stream, m_arrayOptions)) {
m_failed = true;
return false;
}
// -- create the audio stream --
err = AVIFileCreateStream(
m_file,
&m_audioStream,
&audioInfo
);
// create the compressed stream
if(FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
m_failed = true;
return false;
}
if( FAILED( err ) ) {
m_failed = true;
return false;
}
// setup the video stream format
if(FAILED( AVIStreamSetFormat(m_streamCompressed, 0,
&m_bitmap,
m_bitmap.biSize +
m_bitmap.biClrUsed * sizeof(RGBQUAD)))) {
m_failed = true;
return false;
}
return true;
// -- initialize the audio stream format --
waveInfo.wFormatTag = WAVE_FORMAT_PCM;
waveInfo.nChannels = channelCount;
waveInfo.nSamplesPerSec = sampleRate;
waveInfo.nAvgBytesPerSec = channelCount * ( sampleBits >> 3 ) * sampleRate;
waveInfo.nBlockAlign = channelCount * ( sampleBits >> 3 );
waveInfo.wBitsPerSample = sampleBits;
waveInfo.cbSize = 0;
// -- set the audio stream format --
err = AVIStreamSetFormat(
m_audioStream,
0,
&waveInfo,
sizeof( waveInfo )
);
if( FAILED( err ) ) {
m_failed = true;
return false;
}
m_audioBlockAlign = channelCount * ( sampleBits >> 3 );
m_audioFrameSize = channelCount * ( sampleBits >> 3 ) * ( sampleRate / m_frameRate );
return true;
}
bool AVIWrite::AddSound(const char *sound, int len)
bool AVIWrite::AddVideoFrame( LPVOID imageData )
{
// return if we failed somewhere already
if(m_failed)
return false;
if( !m_videoStream || m_failed ) return false;
int samples = len / m_soundFormat.nBlockAlign;
HRESULT err = 0;
if(FAILED(AVIStreamWrite(m_streamSound,
m_samplesSound,
samples,
(LPVOID)sound,
len,
0,
NULL,
NULL))) {
m_failed = true;
return false;
}
m_samplesSound += samples;
err = AVIStreamWrite(
m_videoStream,
m_frameCounter,
1,
imageData,
m_videoFrameSize,
AVIIF_KEYFRAME,
NULL,
NULL
);
return true;
if( FAILED( err ) ) {
m_failed = true;
return false;
}
m_frameCounter++;
return true;
}
bool AVIWrite::AddFrame(const int frame, const char *bmp)
bool AVIWrite::AddAudioFrame( LPVOID soundData )
{
if (m_failed)
return false;
if( !m_audioStream || m_failed ) return false;
// write the frame to the video stream
if(FAILED(AVIStreamWrite(m_streamCompressed,
frame,
1,
(LPVOID)bmp,
m_bitmap.biSizeImage,
AVIIF_KEYFRAME,
NULL,
NULL))) {
m_failed = true;
return false;
}
return true;
}
HRESULT err = 0;
bool AVIWrite::IsSoundAdded()
{
return m_streamSound != NULL;
}
err = AVIStreamWrite(
m_audioStream,
m_sampleCounter,
m_audioFrameSize / m_audioBlockAlign,
soundData,
m_audioFrameSize,
0,
NULL,
NULL
);
void AVIWrite::SetFPS(int f)
{
m_fps = f;
if( FAILED( err ) ) {
m_failed = true;
return false;
}
m_sampleCounter += m_audioFrameSize / m_audioBlockAlign;
return true;
}

View File

@ -1,7 +1,5 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// Copyright (C) 2007 VBA-M development team
// 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
@ -17,33 +15,33 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
#include <vfw.h>
class AVIWrite {
public:
AVIWrite();
virtual ~AVIWrite();
bool Open(const char *filename);
virtual bool AddFrame(const int number, const char * bmp);
void SetFPS(int fps);
void SetVideoFormat(BITMAPINFOHEADER *);
bool IsSoundAdded();
void SetSoundFormat(WAVEFORMATEX *);
bool AddSound(const char *sound, int len);
// info: recreate the whole AVIWrite object if any method fails
class AVIWrite
{
public:
AVIWrite();
virtual ~AVIWrite();
private:
int m_fps;
WAVEFORMATEX m_soundFormat;
BITMAPINFOHEADER m_bitmap;
AVISTREAMINFO m_header;
AVISTREAMINFO m_soundHeader;
PAVIFILE m_file;
PAVISTREAM m_stream;
PAVISTREAM m_streamCompressed;
PAVISTREAM m_streamSound;
AVICOMPRESSOPTIONS m_options;
AVICOMPRESSOPTIONS *m_arrayOptions[1];
int m_samplesSound;
bool m_failed;
bool CreateAVIFile( LPCTSTR filename );
bool CreateVideoStream( LONG imageWidth, LONG imageHeight, WORD colorBits, DWORD framesPerSecond );
bool CreateAudioStream( WORD channelCount, DWORD sampleRate, WORD sampleBits );
bool AddVideoFrame( LPVOID imageData );
bool AddAudioFrame( LPVOID soundData );
private:
bool m_failed;
PAVIFILE m_file;
PAVISTREAM m_videoStream;
PAVISTREAM m_audioStream;
DWORD m_frameRate;
LONG m_frameCounter;
LONG m_sampleCounter;
LONG m_videoFrameSize;
LONG m_audioFrameSize;
WORD m_audioBlockAlign;
};

View File

@ -45,6 +45,7 @@ class IDisplay {
virtual int selectFullScreenMode(GUID **) = 0;
};
inline void cpyImg32( unsigned char *dst, unsigned int dstPitch, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height )
{
// fast, iterative C version
@ -59,6 +60,32 @@ inline void cpyImg32( unsigned char *dst, unsigned int dstPitch, unsigned char *
}
}
inline void cpyImg32bmp( unsigned char *dst, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height )
{
// dst will be an upside down bitmap with 24bit colors
// pix must contain 32bit colors (XRGB)
unsigned short srcLineSize = width<<2;
dst += height * width * 3; // move to the last scanline
register unsigned char r, g, b;
while( height-- ) {
unsigned short x = width;
src += srcLineSize;
while( x-- ) {
--src; // ignore one of 4 bytes
b = *--src;
g = *--src;
r = *--src;
*--dst = b;
*--dst = g;
*--dst = r;
}
src += srcPitch;
}
}
inline void cpyImg16( unsigned char *dst, unsigned int dstPitch, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height )
{
register unsigned short lineSize = width<<1;
@ -69,3 +96,17 @@ inline void cpyImg16( unsigned char *dst, unsigned int dstPitch, unsigned char *
dst += dstPitch;
}
}
inline void cpyImg16bmp( unsigned char *dst, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height )
{
// dst will be an upside down bitmap with 16bit colors
register unsigned short lineSize = width<<1;
dst += ( height - 1 ) * lineSize; // move to the last scanline
while( height-- ) {
memcpy( dst, src, lineSize );
src += srcPitch;
dst -= lineSize;
}
}

View File

@ -42,6 +42,7 @@
#include "../GBA.h"
#include "../Globals.h"
#include "../Sound.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@ -341,61 +342,117 @@ void MainWnd::OnUpdateOptionsSoundStoprecording(CCmdUI* pCmdUI)
pCmdUI->Enable(theApp.soundRecording);
}
void MainWnd::OnToolsRecordStartavirecording()
{
theApp.winCheckFullscreen();
CString captureBuffer;
theApp.winCheckFullscreen();
CString captureBuffer;
CString capdir = regQueryStringValue( "aviRecordDir", NULL );
if( capdir.IsEmpty() ) {
capdir = getDirFromFile( theApp.filename );
}
CString filter = theApp.winLoadFilter( IDS_FILTER_AVI );
CString title = winResLoadString( IDS_SELECT_AVI_NAME );
LPCTSTR exts[] = { ".AVI" };
FileDlg dlg( this, "", filter, 1, "AVI", exts, capdir, title, true );
if( dlg.DoModal() == IDCANCEL ) {
return;
}
captureBuffer = theApp.soundRecordName = dlg.GetPathName();
theApp.aviRecordName = captureBuffer;
theApp.aviRecording = true;
if( dlg.m_ofn.nFileOffset > 0 ) {
captureBuffer = captureBuffer.Left( dlg.m_ofn.nFileOffset );
}
int len = captureBuffer.GetLength();
if( ( len > 3 ) && captureBuffer[ len - 1 ] == '\\' ) {
captureBuffer = captureBuffer.Left( len - 1 );
}
regSetStringValue( "aviRecordDir", captureBuffer );
CString capdir = regQueryStringValue("aviRecordDir", NULL);
if(capdir.IsEmpty())
capdir = getDirFromFile(theApp.filename);
// create AVI file
bool ret;
CString filter = theApp.winLoadFilter(IDS_FILTER_AVI);
CString title = winResLoadString(IDS_SELECT_AVI_NAME);
if( theApp.aviRecorder ) {
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
}
theApp.aviRecorder = new AVIWrite();
LPCTSTR exts[] = { ".AVI" };
// create AVI file
ret = theApp.aviRecorder->CreateAVIFile( theApp.aviRecordName );
if( !ret ) {
systemMessage( IDS_AVI_CANNOT_CREATE_AVI, "Cannot create AVI file." );
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviRecording = false;
return;
}
FileDlg dlg(this, "", filter, 1, "AVI", exts, capdir, title, true);
// add video stream
ret = theApp.aviRecorder->CreateVideoStream(
theApp.sizeX,
theApp.sizeY,
( systemColorDepth == 32 ) ? 24 : 16,
60
);
if( !ret ) {
systemMessage( IDS_AVI_CANNOT_CREATE_VIDEO, "Cannot create video stream in AVI file." );
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviRecording = false;
return;
}
if(dlg.DoModal() == IDCANCEL) {
return;
}
captureBuffer = theApp.soundRecordName = dlg.GetPathName();
theApp.aviRecordName = captureBuffer;
theApp.aviRecording = true;
if(dlg.m_ofn.nFileOffset > 0) {
captureBuffer = captureBuffer.Left(dlg.m_ofn.nFileOffset);
}
int len = captureBuffer.GetLength();
if(len > 3 && captureBuffer[len-1] == '\\')
captureBuffer = captureBuffer.Left(len-1);
regSetStringValue("aviRecordDir", captureBuffer);
// add audio stream
if( !soundOffFlag ) {
ret = theApp.aviRecorder->CreateAudioStream(
2,
44100 / soundQuality,
16
);
if( !ret ) {
systemMessage( IDS_AVI_CANNOT_CREATE_AUDIO, "Cannot create audio stream in AVI file." );
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviRecording = false;
return;
}
}
}
void MainWnd::OnUpdateToolsRecordStartavirecording(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!theApp.aviRecording);
pCmdUI->Enable( !theApp.aviRecording && emulating );
}
void MainWnd::OnToolsRecordStopavirecording()
{
if(theApp.aviRecorder != NULL) {
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviFrameNumber = 0;
}
theApp.aviRecording = false;
if( theApp.aviRecorder ) {
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
}
theApp.aviRecording = false;
}
void MainWnd::OnUpdateToolsRecordStopavirecording(CCmdUI* pCmdUI)
{
pCmdUI->Enable(theApp.aviRecording);
pCmdUI->Enable( theApp.aviRecording );
}
void MainWnd::OnToolsRecordStartmovierecording()

View File

@ -1,6 +1,7 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2005 Forgotten and the VBA development team
// Copyright (C) 2007 VBA-M development team
// 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
@ -316,8 +317,8 @@ VBA::VBA()
sound = NULL;
aviRecording = false;
aviRecorder = NULL;
aviFrameNumber = 0;
painting = false;
skipAudioFrames = 0;
movieRecording = false;
moviePlaying = false;
movieFrame = 0;
@ -1000,49 +1001,32 @@ void systemDrawScreen()
if (Sm60FPS_CanSkipFrame())
return;
if(theApp.aviRecording && !theApp.painting) {
int width = 240;
int height = 160;
switch(theApp.cartridgeType) {
case 0:
width = 240;
height = 160;
break;
case 1:
if(gbBorderOn) {
width = 256;
height = 224;
} else {
width = 160;
height = 144;
}
break;
}
if(theApp.aviRecorder == NULL) {
theApp.aviRecorder = new AVIWrite();
theApp.aviFrameNumber = 0;
theApp.aviRecorder->SetFPS(60);
BITMAPINFOHEADER bi;
memset(&bi, 0, sizeof(bi));
bi.biSize = 0x28;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biWidth = width;
bi.biHeight = height;
bi.biSizeImage = 3*width*height;
theApp.aviRecorder->SetVideoFormat(&bi);
theApp.aviRecorder->Open(theApp.aviRecordName);
}
char *bmp = new char[width*height*3];
utilWriteBMP(bmp, width, height, pix);
theApp.aviRecorder->AddFrame(theApp.aviFrameNumber, bmp);
delete bmp;
if( theApp.aviRecording ) {
if( theApp.painting ) {
theApp.skipAudioFrames++;
} else {
unsigned char *bmp;
unsigned short srcPitch = theApp.sizeX * ( systemColorDepth >> 3 ) + 4;
switch( systemColorDepth )
{
case 16:
bmp = new unsigned char[ theApp.sizeX * theApp.sizeY * 2 ];
cpyImg16bmp( bmp, pix + srcPitch, srcPitch, theApp.sizeX, theApp.sizeY );
break;
case 32:
// use 24 bit colors to reduce video size
bmp = new unsigned char[ theApp.sizeX * theApp.sizeY * 3 ];
cpyImg32bmp( bmp, pix + srcPitch, srcPitch, theApp.sizeX, theApp.sizeY );
break;
}
if( false == theApp.aviRecorder->AddVideoFrame( bmp ) ) {
systemMessage( IDS_AVI_CANNOT_WRITE_VIDEO, "Cannot write video frame to AVI file." );
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviRecording = false;
}
delete bmp;
}
}
if( theApp.ifbFunction ) {
@ -1115,14 +1099,15 @@ void systemShowSpeed(int speed)
}
}
void systemFrame()
{
if(theApp.aviRecording)
theApp.aviFrameNumber++;
if(theApp.movieRecording || theApp.moviePlaying)
theApp.movieFrame++;
if( theApp.movieRecording || theApp.moviePlaying ) {
theApp.movieFrame++;
}
}
void system10Frames(int rate)
{
u32 time = systemGetClock();
@ -1220,17 +1205,17 @@ void systemSoundShutdown()
if( theApp.aviRecorder ) {
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviFrameNumber = 0;
}
theApp.aviRecording = false;
if( theApp.soundRecording ) {
if( theApp.soundRecorder ) {
delete theApp.soundRecorder;
theApp.soundRecorder = NULL;
}
theApp.soundRecording = false;
if( theApp.soundRecorder ) {
delete theApp.soundRecorder;
theApp.soundRecorder = NULL;
}
theApp.soundRecording = false;
if( theApp.sound ) {
delete theApp.sound;
theApp.sound = NULL;
@ -1278,18 +1263,16 @@ void systemWriteDataToSoundBuffer()
}
if( theApp.aviRecording && theApp.aviRecorder ) {
if( !theApp.aviRecorder->IsSoundAdded() ) {
WAVEFORMATEX format;
format.cbSize = 0;
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.nSamplesPerSec = 44100 / soundQuality;
format.wBitsPerSample = 16;
format.nBlockAlign = format.nChannels * ( format.wBitsPerSample >> 3 );
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
theApp.aviRecorder->SetSoundFormat( &format );
if( theApp.skipAudioFrames ) {
theApp.skipAudioFrames--;
} else {
if( false == theApp.aviRecorder->AddAudioFrame( soundFinalWave ) ) {
systemMessage( IDS_AVI_CANNOT_WRITE_AUDIO, "Cannot write audio frame to AVI file." );
delete theApp.aviRecorder;
theApp.aviRecorder = NULL;
theApp.aviRecording = false;
}
}
theApp.aviRecorder->AddSound( (const char *)soundFinalWave, soundBufferLen );
}
if( theApp.sound ) {

View File

@ -193,8 +193,8 @@ class VBA : public CWinApp
bool aviRecording;
AVIWrite *aviRecorder;
CString aviRecordName;
int aviFrameNumber;
bool painting;
unsigned int skipAudioFrames;
bool movieRecording;
bool moviePlaying;
int movieFrame;

View File

@ -2203,8 +2203,17 @@ BEGIN
"Invalid rewind interval value. Please enter a number between 0 and 600 seconds."
IDS_REGISTRY "VisualBoyAdvance no longer uses the registry to store its settings. Your previous settings have been exported into the file: %s"
IDS_MOVIE_PLAY "Playing a movie will load a save state which may erase your previous battery saves. Please be sure to have a saved state if you don't want to loose any previous data."
END
STRINGTABLE
BEGIN
IDS_OAL_NODEVICE "There are no sound devices present on this system."
IDS_OAL_NODLL "OpenAL32.dll could not be found on your system. Please install the runtime from http://openal.org"
IDS_AVI_CANNOT_CREATE_AVI "Cannot create AVI file."
IDS_AVI_CANNOT_CREATE_VIDEO "Cannot create video stream in AVI file."
IDS_AVI_CANNOT_CREATE_AUDIO "Cannot create audio stream in AVI file."
IDS_AVI_CANNOT_WRITE_VIDEO "Cannot write video frame to AVI file."
IDS_AVI_CANNOT_WRITE_AUDIO "Cannot write audio frame to AVI file."
END
#endif // English (U.S.) resources

View File

@ -380,9 +380,7 @@
#define IDC_SAVE_OBJ 1138
#define IDC_MAP_VIEW_ZOOM 1138
#define IDS_MOVIE_PLAY 1138
#define IDS_OAL_NODEVICE 1139
#define IDC_VIEWER 1140
#define IDS_OAL_NODLL 1140
#define IDC_ADDRESSES 1141
#define IDC_GO 1143
#define IDC_8_BIT 1144
@ -514,6 +512,13 @@
#define IDC_DEVICE 1269
#define IDC_SLIDER_BUFFERCOUNT 1270
#define IDC_BUFFERINFO 1271
#define IDS_OAL_NODEVICE 2000
#define IDS_OAL_NODLL 2001
#define IDS_AVI_CANNOT_CREATE_AVI 2002
#define IDS_AVI_CANNOT_CREATE_VIDEO 2003
#define IDS_AVI_CANNOT_CREATE_AUDIO 2004
#define IDS_AVI_CANNOT_WRITE_VIDEO 2005
#define IDS_AVI_CANNOT_WRITE_AUDIO 2006
#define ID_HELP_ABOUT 40001
#define ID_FILE_EXIT 40002
#define ID_OPTIONS_VIDEO_FRAMESKIP_0 40003