626 lines
34 KiB
C++
626 lines
34 KiB
C++
//
|
||
// AVI変換ダイアログクラス
|
||
//
|
||
//
|
||
#define WIN32_LEAN_AND_MEAN
|
||
#include <windows.h>
|
||
#include <shellapi.h>
|
||
#include <commdlg.h>
|
||
#include <string>
|
||
using namespace std;
|
||
|
||
#include "VirtuaNESres.h"
|
||
#include "DebugOut.h"
|
||
#include "App.h"
|
||
#include "Config.h"
|
||
#include "Pathlib.h"
|
||
|
||
#include "Wnd.h"
|
||
#include "AviConvDlg.h"
|
||
|
||
#include "nes.h"
|
||
#include "mmu.h"
|
||
#include "ppu.h"
|
||
#include "apu.h"
|
||
#include "rom.h"
|
||
|
||
#include "DirectDraw.h"
|
||
|
||
CHAR CAviConvDlg::g_szErrorMessage[256];
|
||
|
||
DLG_MESSAGE_BEGIN(CAviConvDlg)
|
||
DLG_ON_MESSAGE( WM_INITDIALOG, OnInitDialog )
|
||
DLG_ON_MESSAGE( WM_TIMER, OnTimer )
|
||
DLG_ON_MESSAGE( WM_APP+100, OnConvertDone )
|
||
DLG_ON_MESSAGE( WM_APP+101, OnConvertError )
|
||
|
||
DLG_COMMAND_BEGIN()
|
||
DLG_ON_COMMAND( IDCANCEL, OnCancel )
|
||
|
||
DLG_ON_COMMAND( IDC_MCV_ROMBROWSE, OnRomFileBrowse )
|
||
DLG_ON_COMMAND( IDC_MCV_MOVIEBROWSE, OnMovieFileBrowse )
|
||
DLG_ON_COMMAND( IDC_MCV_AVIBROWSE, OnAviFileBrowse )
|
||
|
||
DLG_ON_COMMAND( IDC_MCV_VIDEOSELECT, OnVideoCompressSelect )
|
||
DLG_ON_COMMAND( IDC_MCV_CONVERT, OnConvertStart )
|
||
DLG_COMMAND_END()
|
||
DLG_MESSAGE_END()
|
||
|
||
CAviConvDlg::CAviConvDlg() :
|
||
m_lpRender(NULL),
|
||
m_lpLinecolor(NULL),
|
||
m_lpScreen(NULL),
|
||
m_lpSound(NULL),
|
||
m_pNes(NULL),
|
||
m_hThread(NULL)
|
||
{
|
||
if( !(m_lpRender = (LPBYTE)::malloc( CDirectDraw::RENDER_WIDTH*CDirectDraw::RENDER_HEIGHT )) ) {
|
||
throw CApp::GetErrorString( IDS_ERROR_OUTOFMEMORY );
|
||
}
|
||
if( !(m_lpScreen = (LPBYTE)::malloc( CDirectDraw::SCREEN_WIDTH*CDirectDraw::SCREEN_HEIGHT*3+16 )) ) {
|
||
throw CApp::GetErrorString( IDS_ERROR_OUTOFMEMORY );
|
||
}
|
||
if( !(m_lpLinecolor = (LPBYTE)::malloc( CDirectDraw::RENDER_HEIGHT )) ) {
|
||
throw CApp::GetErrorString( IDS_ERROR_OUTOFMEMORY );
|
||
}
|
||
if( !(m_lpSound = (LPBYTE)::malloc( 8192 )) ) {
|
||
throw CApp::GetErrorString( IDS_ERROR_OUTOFMEMORY );
|
||
}
|
||
}
|
||
|
||
CAviConvDlg::~CAviConvDlg()
|
||
{
|
||
FREE( m_lpSound );
|
||
FREE( m_lpLinecolor );
|
||
FREE( m_lpScreen );
|
||
FREE( m_lpRender );
|
||
}
|
||
|
||
INT CAviConvDlg::DoModal( HWND hWndParent )
|
||
{
|
||
return ::DialogBoxParam( CApp::GetPlugin(), MAKEINTRESOURCE(IDD_MOVIECONV),
|
||
hWndParent, g_DlgProc, (LPARAM)this );
|
||
}
|
||
|
||
DLGMSG CAviConvDlg::OnInitDialog( DLGMSGPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnInitDialog\n" );
|
||
|
||
m_szRomFile[0] = '\0';
|
||
m_szMovieFile[0] = '\0';
|
||
m_szAviFile[0] = '\0';
|
||
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_RESETCONTENT, 0, 0 );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)0, (LPARAM)"Full FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)1, (LPARAM)"1/2 FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)2, (LPARAM)"1/3 FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)3, (LPARAM)"1/4 FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)4, (LPARAM)"1/5 FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_INSERTSTRING, (WPARAM)5, (LPARAM)"1/6 FPS" );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_SETCURSEL, 0, 0 );
|
||
|
||
INT i, select = 0;
|
||
CHAR szMode[64];
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_SAMPLERATE_COMBO, CB_RESETCONTENT, 0, 0 );
|
||
// for( i = 0; i < 8; i++ ) {
|
||
for( i = 0; CConfig::SamplingRateTable[i*2+0]; i++ ) {
|
||
::wsprintf( szMode, "%d.%03dKHz %2dbits",
|
||
CConfig::SamplingRateTable[i*2+0]/1000,
|
||
CConfig::SamplingRateTable[i*2+0]%1000,
|
||
CConfig::SamplingRateTable[i*2+1] );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_SAMPLERATE_COMBO, CB_INSERTSTRING, (WPARAM)i, (LPARAM)szMode );
|
||
|
||
if( Config.sound.nRate == CConfig::SamplingRateTable[i*2+0]
|
||
&& Config.sound.nBits == CConfig::SamplingRateTable[i*2+1] ) {
|
||
select = i;
|
||
}
|
||
}
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FILTERTYPE_COMBO, CB_RESETCONTENT, 0, 0 );
|
||
for( i = IDS_SND_FILTER_NONE; i <= IDS_SND_FILTER_TYPE4; i++ ) {
|
||
CApp::LoadString( i, szMode, sizeof(szMode) );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FILTERTYPE_COMBO, CB_INSERTSTRING, (WPARAM)i-IDS_SND_FILTER_NONE, (LPARAM)szMode );
|
||
}
|
||
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_SAMPLERATE_COMBO, CB_SETCURSEL, (WPARAM)select, 0 );
|
||
::SendDlgItemMessage( m_hWnd, IDC_MCV_FILTERTYPE_COMBO, CB_SETCURSEL, (WPARAM)Config.sound.nFilterType, 0 );
|
||
|
||
CTRLENABLE( IDC_MCV_CONVERT, FALSE );
|
||
|
||
ZEROMEMORY( &m_BitmapHdr, sizeof(m_BitmapHdr) );
|
||
|
||
m_BitmapHdr.biSize = sizeof(BITMAPINFOHEADER);
|
||
m_BitmapHdr.biWidth = 256;
|
||
m_BitmapHdr.biHeight = 240;
|
||
m_BitmapHdr.biPlanes = 1;
|
||
m_BitmapHdr.biBitCount = 24;
|
||
m_BitmapHdr.biCompression = BI_RGB;
|
||
m_BitmapHdr.biSizeImage = 256*240*3;
|
||
|
||
::GetWindowText( m_hWnd, m_szTitle, sizeof(m_szTitle)-1 );
|
||
|
||
m_AviWriter.SetVideoFormat( &m_BitmapHdr );
|
||
|
||
m_hThread = NULL;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnCancel( DLGCMDPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnCancel\n" );
|
||
|
||
::KillTimer( m_hWnd, 0x1234 );
|
||
|
||
if( m_hThread ) {
|
||
m_bThreadExit = TRUE;
|
||
::WaitForSingleObject( m_hThread, INFINITE );
|
||
CLOSEHANDLE( m_hThread );
|
||
m_bThreadExit = FALSE;
|
||
|
||
if( m_pNes ) {
|
||
m_pNes->MovieStop();
|
||
DELETEPTR( m_pNes );
|
||
}
|
||
m_AviWriter.Close();
|
||
|
||
::SetWindowText( m_hWnd, m_szTitle );
|
||
|
||
ControlEnable( TRUE );
|
||
} else {
|
||
::EndDialog( m_hWnd, IDCANCEL );
|
||
}
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnRomFileBrowse( DLGCMDPARAM )
|
||
{
|
||
string pathstr;
|
||
if( Config.path.bRomPath ) {
|
||
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRomPath );
|
||
} else {
|
||
pathstr = CApp::GetModulePath();
|
||
}
|
||
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_ROMFILE, m_szRomFile, sizeof(m_szRomFile)-1 );
|
||
|
||
CHAR szTitle[256];
|
||
CApp::LoadString( IDS_UI_OPENROM, szTitle, sizeof(szTitle) );
|
||
|
||
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
||
ofn.hwndOwner = m_hWnd;
|
||
ofn.lpstrFile = m_szRomFile;
|
||
ofn.nMaxFile = sizeof(m_szRomFile);
|
||
ofn.lpstrFilter = "All Support Types\0*.nes;*.fds;*.lzh;*.zip;*.rar;*.cab\0"
|
||
"NES ROM (*.nes)\0*.nes\0Disk Image (*.fds)\0*.fds\0"
|
||
"Archive File\0*.lzh;*.zip;*.rar;*.cab\0";
|
||
ofn.nFilterIndex = 1;
|
||
ofn.Flags = OFN_READONLY|OFN_HIDEREADONLY|OFN_EXPLORER|OFN_PATHMUSTEXIST;
|
||
ofn.lpstrInitialDir = pathstr.c_str();
|
||
ofn.lpstrTitle = szTitle;
|
||
|
||
if( ::GetOpenFileName( &ofn ) ) {
|
||
::SetDlgItemText( m_hWnd, IDC_MCV_ROMFILE, m_szRomFile );
|
||
}
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnMovieFileBrowse( DLGCMDPARAM )
|
||
{
|
||
string pathstr;
|
||
if( Config.path.bMoviePath ) {
|
||
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szMoviePath );
|
||
::CreateDirectory( pathstr.c_str(), NULL );
|
||
} else {
|
||
pathstr = CApp::GetModulePath();
|
||
}
|
||
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_MOVIEFILE, m_szMovieFile, sizeof(m_szMovieFile)-1 );
|
||
|
||
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
||
ofn.hwndOwner = m_hWnd;
|
||
ofn.lpstrFile = m_szMovieFile;
|
||
ofn.lpstrDefExt = "vmv";
|
||
ofn.nMaxFile = sizeof(m_szMovieFile);
|
||
ofn.lpstrFilter = "Movie Files(*.vmv)\0*.vmv\0All Files(*.*)\0*.*\0";
|
||
ofn.nFilterIndex = 1;
|
||
ofn.Flags = OFN_EXPLORER|OFN_PATHMUSTEXIST;
|
||
ofn.lpstrInitialDir = pathstr.c_str();
|
||
|
||
CHAR szTitle[256];
|
||
CApp::LoadString( IDS_UI_PLAYMOVIE, szTitle, sizeof(szTitle) );
|
||
ofn.lpstrTitle = szTitle;
|
||
|
||
if( ::GetOpenFileName( &ofn ) ) {
|
||
::SetDlgItemText( m_hWnd, IDC_MCV_MOVIEFILE, m_szMovieFile );
|
||
}
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnAviFileBrowse( DLGCMDPARAM )
|
||
{
|
||
string pathstr, tempstr;
|
||
if( Config.path.bMoviePath ) {
|
||
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szMoviePath );
|
||
::CreateDirectory( pathstr.c_str(), NULL );
|
||
} else {
|
||
pathstr = CApp::GetModulePath();
|
||
}
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_AVIFILE, m_szAviFile, sizeof(m_szAviFile)-1 );
|
||
|
||
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
||
ofn.hwndOwner = m_hWnd;
|
||
ofn.lpstrFile = m_szAviFile;
|
||
ofn.lpstrDefExt = "avi";
|
||
ofn.nMaxFile = sizeof(m_szAviFile);
|
||
ofn.lpstrFilter = "Movie Files(*.avi)\0*.avi\0All Files(*.*)\0*.*\0";
|
||
ofn.nFilterIndex = 1;
|
||
ofn.Flags = OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT;
|
||
ofn.lpstrInitialDir = pathstr.c_str();
|
||
|
||
// CHAR szTitle[256];
|
||
// CApp::LoadString( IDS_UI_AVICONV, szTitle, sizeof(szTitle) );
|
||
// ofn.lpstrTitle = szTitle;
|
||
|
||
if( ::GetSaveFileName( &ofn ) ) {
|
||
::SetDlgItemText( m_hWnd, IDC_MCV_AVIFILE, m_szAviFile );
|
||
}
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnVideoCompressSelect( DLGCMDPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnCompressSelect\n" );
|
||
|
||
if( !m_AviWriter.SelectVideoFormat( m_hWnd ) ) {
|
||
return;
|
||
}
|
||
|
||
CTRLENABLE( IDC_MCV_CONVERT, TRUE );
|
||
}
|
||
|
||
DLGMSG CAviConvDlg::OnConvertDone( DLGMSGPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnConvertDone\n" );
|
||
|
||
::KillTimer( m_hWnd, 0x1234 );
|
||
|
||
::WaitForSingleObject( m_hThread, INFINITE );
|
||
CLOSEHANDLE( m_hThread );
|
||
|
||
::SetWindowText( m_hWnd, m_szTitle );
|
||
|
||
m_AviWriter.Close();
|
||
DELETEPTR( m_pNes );
|
||
ControlEnable( TRUE );
|
||
|
||
CHAR szTemp[256];
|
||
DWORD totaltime = (m_FinishTime - m_StartTime) / 1000;
|
||
INT h, m, s;
|
||
h = totaltime / 3600;
|
||
totaltime %= 3600;
|
||
m = totaltime / 60;
|
||
s = totaltime % 60;
|
||
|
||
::wsprintf( szTemp, "Convert Finished. Time:%02d:%02d:%02d", h, m, s );
|
||
|
||
::MessageBox( m_hWnd, szTemp, "VirtuaNES", MB_OK );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
DLGMSG CAviConvDlg::OnConvertError( DLGMSGPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnConvertError\n" );
|
||
|
||
::KillTimer( m_hWnd, 0x1234 );
|
||
|
||
::WaitForSingleObject( m_hThread, INFINITE );
|
||
CLOSEHANDLE( m_hThread );
|
||
|
||
::SetWindowText( m_hWnd, m_szTitle );
|
||
|
||
m_AviWriter.Close();
|
||
DELETEPTR( m_pNes );
|
||
ControlEnable( TRUE );
|
||
|
||
::MessageBox( m_hWnd, (LPSTR)lParam, "VirtuaNES", MB_OK );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
DLGCMD CAviConvDlg::OnConvertStart( DLGCMDPARAM )
|
||
{
|
||
// DEBUGOUT( "CAviConvDlg::OnConvertStart\n" );
|
||
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_ROMFILE, m_szRomFile, sizeof(m_szRomFile)-1 );
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_MOVIEFILE, m_szMovieFile, sizeof(m_szMovieFile)-1 );
|
||
::GetDlgItemText( m_hWnd, IDC_MCV_AVIFILE, m_szAviFile, sizeof(m_szAviFile)-1 );
|
||
|
||
INT select;
|
||
|
||
select = ::SendDlgItemMessage( m_hWnd, IDC_MCV_FRAMERATE_COMBO, CB_GETCURSEL, 0, 0 );
|
||
|
||
#if 1
|
||
m_FrameDivider = select + 1;
|
||
#else
|
||
switch( select ) {
|
||
default:
|
||
case 0: m_FrameDivider = 1; break;
|
||
case 1: m_FrameDivider = 2; break;
|
||
case 2: m_FrameDivider = 3; break;
|
||
case 3: m_FrameDivider = 4; break;
|
||
case 4: m_FrameDivider = 5; break;
|
||
case 5: m_FrameDivider = 6; break;
|
||
}
|
||
#endif
|
||
|
||
select = ::SendDlgItemMessage( m_hWnd, IDC_MCV_SAMPLERATE_COMBO, CB_GETCURSEL, 0, 0 );
|
||
Config.sound.nRate = CConfig::SamplingRateTable[select*2+0];
|
||
Config.sound.nBits = CConfig::SamplingRateTable[select*2+1];
|
||
|
||
Config.sound.nFilterType = ::SendDlgItemMessage( m_hWnd, IDC_MCV_FILTERTYPE_COMBO, CB_GETCURSEL, 0, 0 );
|
||
|
||
m_AviWriter.SetAudioFormat( Config.sound.nRate, Config.sound.nBits, 1 );
|
||
|
||
m_hThread = NULL;
|
||
|
||
try {
|
||
m_pNes = new NES(m_szRomFile);
|
||
m_pNes->ppu->SetScreenPtr( m_lpRender, m_lpLinecolor );
|
||
m_pNes->Reset();
|
||
|
||
if( !m_pNes->MoviePlay( m_szMovieFile ) )
|
||
throw "MoviePlay error.";
|
||
|
||
WORD wRecVersion, wVersion;
|
||
DWORD dwRecordTimes;
|
||
m_pNes->GetMovieInfo( wRecVersion, wVersion, m_RecordFrames, dwRecordTimes );
|
||
|
||
m_AviWriter.SetFrameRate( 10000, m_pNes->nescfg->FrameRate * 10000 / m_FrameDivider );
|
||
|
||
if( !m_AviWriter.Open( m_szAviFile ) ) {
|
||
CHAR szTemp[256];
|
||
::wsprintf( szTemp, CApp::GetErrorString(IDS_ERROR_OPEN), m_szAviFile );
|
||
throw szTemp;
|
||
}
|
||
|
||
if( !(m_hThread = ::CreateThread( NULL, 0, ThreadProc, this, CREATE_SUSPENDED, &m_dwThreadID )) ) {
|
||
throw "CreateThread failed.";
|
||
}
|
||
|
||
ControlEnable( FALSE );
|
||
DirectDraw.GetPaletteData2( m_Palette );
|
||
|
||
m_FrameNo = -1;
|
||
|
||
// Time Remain
|
||
::SetTimer( m_hWnd, 0x1234, 500, NULL );
|
||
|
||
// start converter
|
||
m_bThreadExit = FALSE;
|
||
// m_StartTime = m_FinishTime = ::timeGetTime();
|
||
::ResumeThread( m_hThread );
|
||
|
||
} catch( CHAR* str ) {
|
||
if( m_hThread ) {
|
||
::TerminateThread( m_hThread, 0 );
|
||
CLOSEHANDLE( m_hThread );
|
||
}
|
||
|
||
::KillTimer( m_hWnd, 0x1234 );
|
||
|
||
m_AviWriter.Close();
|
||
DELETEPTR( m_pNes );
|
||
|
||
::MessageBox( m_hWnd, str, "VirtuaNES", MB_OK );
|
||
#ifndef _DEBUG
|
||
} catch(...) {
|
||
if( m_hThread ) {
|
||
::TerminateThread( m_hThread, 0 );
|
||
CLOSEHANDLE( m_hThread );
|
||
}
|
||
|
||
::KillTimer( m_hWnd, 0x1234 );
|
||
|
||
m_AviWriter.Close();
|
||
DELETEPTR( m_pNes );
|
||
|
||
::MessageBox( m_hWnd, CApp::GetErrorString( IDS_ERROR_UNKNOWN ), "VirtuaNES", MB_OK );
|
||
#endif
|
||
}
|
||
}
|
||
|
||
DLGMSG CAviConvDlg::OnTimer( DLGMSGPARAM )
|
||
{
|
||
CHAR szTemp[256];
|
||
|
||
INT nowframe = m_FrameNo;
|
||
DWORD elapsed = ::timeGetTime() - m_StartTime;
|
||
|
||
if( m_FrameNo >= 0 && elapsed > 5000 ) {
|
||
DWORD elapsedave = elapsed / nowframe;
|
||
DWORD estimation = elapsedave * (m_RecordFrames-nowframe) / 1000;
|
||
INT h, m, s;
|
||
h = estimation / 3600;
|
||
estimation %= 3600;
|
||
m = estimation / 60;
|
||
s = estimation % 60;
|
||
|
||
::wsprintf( szTemp, "%s [%d/%d] Time remain %02d:%02d:%02d", m_szTitle, m_FrameNo, m_RecordFrames, h, m, s );
|
||
} else {
|
||
::wsprintf( szTemp, "%s [%d/%d] Time remain --:--:--", m_szTitle, m_FrameNo, m_RecordFrames );
|
||
}
|
||
|
||
::SetWindowText( m_hWnd, szTemp );
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
DWORD WINAPI CAviConvDlg::ThreadProc( LPVOID lpVoid )
|
||
{
|
||
CAviConvDlg* pAviConvDlg = (CAviConvDlg*)lpVoid;
|
||
NES* pNes = pAviConvDlg->m_pNes;
|
||
CAVIWriter& AviWriter = pAviConvDlg->m_AviWriter;
|
||
|
||
LPBYTE pRender = pAviConvDlg->m_lpRender;
|
||
LPBYTE pScreen = pAviConvDlg->m_lpScreen;
|
||
LPBYTE pLinecolor = pAviConvDlg->m_lpLinecolor;
|
||
RGBQUAD* pPalette = pAviConvDlg->m_Palette;
|
||
LPBYTE pSound = pAviConvDlg->m_lpSound;
|
||
|
||
INT FrameDivider = pAviConvDlg->m_FrameDivider;
|
||
|
||
BOOL bFinish = FALSE;
|
||
|
||
double Samples = 0.0;
|
||
|
||
pAviConvDlg->m_FrameNo = 0;
|
||
pAviConvDlg->m_StartTime = pAviConvDlg->m_FinishTime = ::timeGetTime();
|
||
|
||
while( !pAviConvDlg->m_bThreadExit ) {
|
||
if( !pNes->IsMoviePlay() ) {
|
||
bFinish = TRUE;
|
||
break;
|
||
}
|
||
|
||
try {
|
||
pNes->Movie();
|
||
|
||
if( (pAviConvDlg->m_FrameNo % FrameDivider) == 0 ) {
|
||
pNes->EmulateFrame( TRUE );
|
||
|
||
for( INT i = 0; i < CDirectDraw::SCREEN_HEIGHT; i++ ) {
|
||
LPBYTE pSrc = &pRender[CDirectDraw::RENDER_WIDTH*i+8];
|
||
LPBYTE pDst = &pScreen[CDirectDraw::SCREEN_WIDTH*3*(CDirectDraw::SCREEN_HEIGHT-i-1)];
|
||
RGBQUAD* pPal = &pPalette[ (pLinecolor[i] & 7)*256+((pLinecolor[i] & 0x80)?0x40:0x00) ];
|
||
#if 0
|
||
for( INT j = 0; j < CDirectDraw::SCREEN_WIDTH; j++ ) {
|
||
BYTE pixel = *pSrc++;
|
||
pixel |= (pLinecolor[i] & 0x80)?0x40:0;
|
||
*pDst++ = pPal[ pixel ].rgbBlue;
|
||
*pDst++ = pPal[ pixel ].rgbGreen;
|
||
*pDst++ = pPal[ pixel ].rgbRed;
|
||
}
|
||
#else
|
||
DWORD width = CDirectDraw::SCREEN_WIDTH;
|
||
|
||
__asm {
|
||
mov eax, pSrc
|
||
mov esi, pPal
|
||
mov edi, pDst
|
||
_render_loop:
|
||
mov edx, [eax]
|
||
movzx ebx, dl
|
||
mov ebx, [esi+ebx*4]
|
||
shr edx, 8
|
||
mov [edi+ 0], ebx
|
||
movzx ebx, dl
|
||
mov ebx, [esi+ebx*4]
|
||
shr edx, 8
|
||
mov [edi+ 3], ebx
|
||
movzx ebx, dl
|
||
shr edx, 8
|
||
mov ebx, [esi+ebx*4]
|
||
mov edx, [esi+edx*4]
|
||
mov [edi+ 6], ebx
|
||
mov [edi+ 9], dx
|
||
shr edx, 16
|
||
mov [edi+11], dl
|
||
|
||
mov edx, [eax+4]
|
||
movzx ebx, dl
|
||
mov ebx, [esi+ebx*4]
|
||
shr edx, 8
|
||
mov [edi+12], ebx
|
||
movzx ebx, dl
|
||
mov ebx, [esi+ebx*4]
|
||
shr edx, 8
|
||
mov [edi+15], ebx
|
||
movzx ebx, dl
|
||
shr edx, 8
|
||
mov ebx, [esi+ebx*4]
|
||
mov edx, [esi+edx*4]
|
||
mov [edi+18], ebx
|
||
mov [edi+21], dx
|
||
shr edx, 16
|
||
mov [edi+23], dl
|
||
|
||
lea eax, [eax+ 8]
|
||
lea edi, [edi+24]
|
||
|
||
sub width, 8
|
||
jg _render_loop
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if( !AviWriter.WriteVideo( (const char*)pScreen ) ) {
|
||
throw "Write error.(video)";
|
||
}
|
||
} else {
|
||
pNes->EmulateFrame( FALSE );
|
||
}
|
||
|
||
INT size;
|
||
INT blockalign = Config.sound.nBits / 8;
|
||
|
||
Samples += ((double)Config.sound.nRate / (double)pNes->nescfg->FrameRate) * (double)blockalign;
|
||
size = (INT)Samples - ((INT)Samples % blockalign);
|
||
Samples -= size;
|
||
|
||
pNes->apu->Process( pSound, size );
|
||
if( !AviWriter.WriteAudio( (const char*)pSound, size ) ) {
|
||
throw "Write error.(audio)";
|
||
}
|
||
|
||
pAviConvDlg->m_FrameNo++;
|
||
|
||
} catch( CHAR* str ) {
|
||
pNes->MovieStop();
|
||
AviWriter.Close();
|
||
|
||
::strcpy( g_szErrorMessage, str );
|
||
::PostMessage( pAviConvDlg->m_hWnd, WM_APP+101, 0, (LPARAM)g_szErrorMessage );
|
||
|
||
pAviConvDlg->m_bThreadExit = TRUE;
|
||
#ifndef _DEBUG
|
||
} catch(...) {
|
||
pNes->MovieStop();
|
||
AviWriter.Close();
|
||
|
||
::PostMessage( pAviConvDlg->m_hWnd, WM_APP+101, 0, (LPARAM)CApp::GetErrorString( IDS_ERROR_UNKNOWN ) );
|
||
|
||
pAviConvDlg->m_bThreadExit = TRUE;
|
||
#endif
|
||
}
|
||
|
||
// For Windows9x
|
||
::Sleep( 0 );
|
||
}
|
||
|
||
pNes->MovieStop();
|
||
AviWriter.Close();
|
||
|
||
if( bFinish ) {
|
||
pAviConvDlg->m_FinishTime = ::timeGetTime();
|
||
// Convert Done
|
||
::PostMessage( pAviConvDlg->m_hWnd, WM_APP+100, 0, 0 );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void CAviConvDlg::ControlEnable( BOOL bEnable )
|
||
{
|
||
CTRLENABLE( IDC_MCV_ROMBROWSE, bEnable );
|
||
CTRLENABLE( IDC_MCV_MOVIEBROWSE, bEnable );
|
||
CTRLENABLE( IDC_MCV_AVIBROWSE, bEnable );
|
||
CTRLENABLE( IDC_MCV_ROMFILE, bEnable );
|
||
CTRLENABLE( IDC_MCV_MOVIEFILE, bEnable );
|
||
CTRLENABLE( IDC_MCV_AVIFILE, bEnable );
|
||
|
||
CTRLENABLE( IDC_MCV_FRAMERATE_COMBO, bEnable );
|
||
CTRLENABLE( IDC_MCV_SAMPLERATE_COMBO, bEnable );
|
||
CTRLENABLE( IDC_MCV_FILTERTYPE_COMBO, bEnable );
|
||
CTRLENABLE( IDC_MCV_VIDEOSELECT, bEnable );
|
||
|
||
CTRLENABLE( IDC_MCV_CONVERT, bEnable );
|
||
}
|
||
|