mirror of https://github.com/snes9xgit/snes9x.git
Win32: Rework AVI image generation (gocha)
New option in emulation settings allows forcing the recording size to 512x448, otherwise always resize output to 256x239. Also improves avi sound sync (gocha)
This commit is contained in:
parent
c7c2ff4f6f
commit
c3bf1d7b59
|
@ -79,6 +79,7 @@
|
|||
#define IDC_VIDEO_MODE 1066
|
||||
#define IDC_CUSTOMROMOPEN 1066
|
||||
#define IDC_HEADER 1067
|
||||
#define IDC_HIRESAVI 1067
|
||||
#define IDC_ROMLIST 1068
|
||||
#define IDC_MEM_TYPE 1069
|
||||
#define IDC_HOSTNAME 1086
|
||||
|
|
|
@ -99,7 +99,7 @@ BEGIN
|
|||
EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 148
|
||||
IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 154
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "APP - Emulator Settings"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
|
@ -113,8 +113,8 @@ BEGIN
|
|||
EDITTEXT IDC_TURBO_SKIP,91,85,49,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "Spin4",IDC_SPIN_TURBO_SKIP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,296,94,11,13
|
||||
CONTROL "Toggled Turbo Mode",IDC_TOGGLE_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,103,123,12
|
||||
DEFPUSHBUTTON "&OK",IDOK,215,127,46,14
|
||||
PUSHBUTTON "&Cancel",IDCANCEL,266,127,46,14
|
||||
DEFPUSHBUTTON "&OK",IDOK,215,136,46,14
|
||||
PUSHBUTTON "&Cancel",IDCANCEL,266,135,46,14
|
||||
RTEXT "Directory",IDC_LABEL_FREEZE,53,28,32,14,SS_CENTERIMAGE
|
||||
RTEXT "Auto-Save S-RAM",IDC_LABEL_ASRAM,21,47,64,14,SS_CENTERIMAGE
|
||||
RTEXT "Skip at most",IDC_LABEL_SMAX,40,66,45,14,SS_CENTERIMAGE
|
||||
|
@ -122,12 +122,13 @@ BEGIN
|
|||
LTEXT "seconds after last change (0 disables auto-save)",IDC_LABEL_ASRAM_TEXT,146,47,161,14,SS_CENTERIMAGE
|
||||
LTEXT "frames in auto-frame rate mode",IDC_LABEL_SMAX_TEXT,146,66,138,14,SS_CENTERIMAGE
|
||||
LTEXT "frames in Turbo mode",IDC_LABEL_STURBO_TEXT,146,85,92,14,SS_CENTERIMAGE
|
||||
CONTROL "Pause When Inactive",IDC_INACTIVE_PAUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,116,100,12
|
||||
CONTROL "Pause When Inactive",IDC_INACTIVE_PAUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,114,100,12
|
||||
LTEXT "Config file",IDC_STATIC,54,11,34,11
|
||||
EDITTEXT IDC_CONFIG_NAME_BOX,91,9,49,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
|
||||
LTEXT "all of Snes9x's settings are stored in this file",IDC_STATIC,147,11,160,11
|
||||
COMBOBOX IDC_DIRCOMBO,7,29,44,30,CBS_DROPDOWNLIST | WS_TABSTOP
|
||||
CONTROL "Custom ROM Open Dialog",IDC_CUSTOMROMOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,130,117,12
|
||||
CONTROL "Custom ROM Open Dialog",IDC_CUSTOMROMOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,125,117,12
|
||||
CONTROL "Hi-Res AVI Recording",IDC_HIRESAVI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,136,117,12
|
||||
END
|
||||
|
||||
IDD_OPEN_ROM DIALOGEX 0, 0, 430, 223
|
||||
|
@ -588,7 +589,7 @@ BEGIN
|
|||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 312
|
||||
BOTTOMMARGIN, 141
|
||||
BOTTOMMARGIN, 147
|
||||
END
|
||||
|
||||
IDD_OPEN_ROM, DIALOG
|
||||
|
|
|
@ -905,6 +905,7 @@ void WinRegisterConfigItems()
|
|||
#define CATEGORY "Settings\\Win"
|
||||
AddBoolC("PauseWhenInactive", GUI.InactivePause, TRUE, "true to pause Snes9x when it is not the active window");
|
||||
AddBoolC("CustomRomOpenDialog", GUI.CustomRomOpen, false, "false to use standard Windows open dialog for the ROM open dialog");
|
||||
AddBoolC("AVIHiRes", GUI.AVIHiRes, false, "true to record AVI in Hi-Res scale");
|
||||
AddBoolC("ToggledTurbo", GUI.TurboModeToggle, FALSE, "true to allow fast-forward to stay on without holding the turbo button");
|
||||
// AddUIntC("Language", GUI.Language, 0, "0=English, 1=Nederlands"); // NYI
|
||||
AddBoolC("FrameAdvanceSkipsNonInput", GUI.FASkipsNonInput, false, "causes frame advance to fast-forward past frames where the game is definitely not checking input, such as during lag or loading time. EXPERIMENTAL");
|
||||
|
|
294
win32/win32.cpp
294
win32/win32.cpp
|
@ -191,6 +191,7 @@
|
|||
|
||||
#include "wsnes9x.h"
|
||||
#include "win32_sound.h"
|
||||
#include "win32_display.h"
|
||||
|
||||
#include "render.h"
|
||||
#include "AVIOutput.h"
|
||||
|
@ -199,14 +200,8 @@
|
|||
#include <direct.h>
|
||||
|
||||
#include <io.h>
|
||||
//#define DEBUGGER
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
BYTE *ScreenBuf1 = NULL;
|
||||
BYTE *ScreenBuffer = NULL;
|
||||
|
@ -219,14 +214,15 @@ bool8 do_frame_adjust=false;
|
|||
static uint8* avi_buffer = NULL;
|
||||
static uint8* avi_sound_buffer = NULL;
|
||||
static int avi_sound_bytes_per_sample = 0;
|
||||
static int avi_sound_samples_per_update = 0;
|
||||
static double avi_sound_samples_per_update = 0;
|
||||
static double avi_sound_samples_error = 0;
|
||||
static int avi_width = 0;
|
||||
static int avi_height = 0;
|
||||
static int avi_pitch = 0;
|
||||
static int avi_image_size = 0;
|
||||
static uint32 avi_skip_frames = 0;
|
||||
static bool pre_avi_soundsync = true;
|
||||
static uint32 pre_avi_soundinputrate = 32000;
|
||||
//void Convert8To24 (SSurface *src, SSurface *dst, RECT *srect);
|
||||
void Convert16To24 (SSurface *src, SSurface *dst, RECT *srect);
|
||||
void DoAVIOpen(const char* filename);
|
||||
void DoAVIClose(int reason);
|
||||
|
||||
|
@ -989,14 +985,12 @@ void InitSnes9X( void)
|
|||
GFX.RealPPL = EXT_PITCH;
|
||||
GFX.Screen = (uint16*)(ScreenBuf1 + EXT_OFFSET);
|
||||
|
||||
S9xSetWinPixelFormat ();
|
||||
S9xGraphicsInit();
|
||||
|
||||
InitializeCriticalSection(&GUI.SoundCritSect);
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
S9xInitAPU();
|
||||
|
||||
|
||||
WinDisplayReset();
|
||||
ReInitSound();
|
||||
|
||||
S9xMovieInit ();
|
||||
|
@ -1121,6 +1115,186 @@ bool JustifierOffscreen()
|
|||
// }
|
||||
//}
|
||||
|
||||
#define Interp(c1, c2) \
|
||||
(c1 == c2) ? c1 : \
|
||||
(((((c1 & 0x07E0) + (c2 & 0x07E0)) >> 1) & 0x07E0) + \
|
||||
((((c1 & 0xF81F) + (c2 & 0xF81F)) >> 1) & 0xF81F))
|
||||
|
||||
// Src: GFX.Screen (variable size) 16bpp top-down
|
||||
// Dst: avi_buffer 256xH (1x1) 24bpp bottom-up
|
||||
void BuildAVIVideoFrame1X (void)
|
||||
{
|
||||
const int srcWidth = IPPU.RenderedScreenWidth;
|
||||
const int srcHeight = IPPU.RenderedScreenHeight;
|
||||
|
||||
const bool hires = srcWidth > SNES_WIDTH;
|
||||
const bool interlaced = srcHeight > SNES_HEIGHT_EXTENDED;
|
||||
|
||||
const int srcPitch = GFX.Pitch >> 1;
|
||||
const int srcStep = (interlaced ? srcPitch << 1 : srcPitch) - (hires ? avi_width << 1 : avi_width);
|
||||
const int dstStep = avi_pitch + avi_width * 3;
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
|
||||
#else
|
||||
const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
|
||||
#endif
|
||||
|
||||
const int image_offset = (avi_height - (interlaced?srcHeight>>1:srcHeight)) * avi_pitch;
|
||||
uint16 *s = GFX.Screen;
|
||||
uint8 *d = avi_buffer + (avi_height - 1) * avi_pitch;
|
||||
|
||||
for(int y = 0; y < avi_height; y++)
|
||||
{
|
||||
for(int x = 0; x < avi_width; x++)
|
||||
{
|
||||
uint32 pixel;
|
||||
if(hires && interlaced) {
|
||||
uint16 *s2 = s + srcPitch;
|
||||
pixel = Interp(Interp(*s,*(s+1)),Interp(*s2,*(s2+1)));
|
||||
s+=2;
|
||||
} else if(interlaced) {
|
||||
uint16 *s2 = s + srcPitch;
|
||||
pixel = Interp(*s,*s2);
|
||||
s++;
|
||||
} else if(hires) {
|
||||
pixel = Interp(*s,*(s+1));
|
||||
s+=2;
|
||||
} else {
|
||||
pixel = *s;
|
||||
s++;
|
||||
}
|
||||
|
||||
if(order_is_rgb)
|
||||
{
|
||||
// Order is RGB
|
||||
*(d + 0) = (pixel >> (11 - 3)) & 0xf8;
|
||||
*(d + 1) = (pixel >> (6 - 3)) & 0xf8;
|
||||
*(d + 2) = (pixel & 0x1f) << 3;
|
||||
d += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Order is BGR
|
||||
*(d + 0) = (pixel & 0x1f) << 3;
|
||||
*(d + 1) = (pixel >> (6 - 3)) & 0xf8;
|
||||
*(d + 2) = (pixel >> (11 - 3)) & 0xf8;
|
||||
d += 3;
|
||||
}
|
||||
}
|
||||
s += srcStep;
|
||||
d -= dstStep;
|
||||
}
|
||||
|
||||
// black out what we might have missed
|
||||
if(image_offset > 0)
|
||||
memset(avi_buffer, 0, image_offset);
|
||||
}
|
||||
|
||||
// Src: GFX.Screen (variable size) 16bpp top-down
|
||||
// Dst: avi_buffer 512x2H (2x2) 24bpp bottom-up
|
||||
void BuildAVIVideoFrame2X (void)
|
||||
{
|
||||
const int srcWidth = IPPU.RenderedScreenWidth;
|
||||
const int srcHeight = IPPU.RenderedScreenHeight;
|
||||
|
||||
const bool hires = srcWidth > SNES_WIDTH;
|
||||
const bool interlaced = srcHeight > SNES_HEIGHT_EXTENDED;
|
||||
|
||||
const int srcPitch = GFX.Pitch >> 1;
|
||||
const int srcStep = (interlaced ? srcPitch << 1 : srcPitch) - (hires ? avi_width : avi_width >> 1);
|
||||
const int dstStep = (avi_pitch << 1) + avi_width * 3;
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
|
||||
#else
|
||||
const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
|
||||
#endif
|
||||
|
||||
const int image_offset = (avi_height - (interlaced?srcHeight:srcHeight<<1)) * avi_pitch;
|
||||
uint16 *s = GFX.Screen;
|
||||
uint8 *d = avi_buffer + (avi_height - 1) * avi_pitch;
|
||||
uint8 *d2 = d - avi_pitch;
|
||||
|
||||
for(int y = 0; y < avi_height >> 1; y++)
|
||||
{
|
||||
for(int x = 0; x < avi_width >> 1; x++)
|
||||
{
|
||||
uint32 pixel, pixel2, pixel3, pixel4;
|
||||
if(hires && interlaced) {
|
||||
uint16 *s2 = s + srcPitch;
|
||||
pixel = *s;
|
||||
pixel2 = *(s+1);
|
||||
pixel3 = *s2;
|
||||
pixel4 = *(s2+1);
|
||||
s+=2;
|
||||
} else if(interlaced) {
|
||||
uint16 *s2 = s + srcPitch;
|
||||
pixel = pixel2 = *s;
|
||||
pixel3 = pixel4 = *s2;
|
||||
s++;
|
||||
} else if(hires) {
|
||||
pixel = pixel3 = *s;
|
||||
pixel2 = pixel4 = *(s+1);
|
||||
s+=2;
|
||||
} else {
|
||||
pixel = pixel2 = pixel3 = pixel4 = *s;
|
||||
s++;
|
||||
}
|
||||
|
||||
if(order_is_rgb)
|
||||
{
|
||||
// Order is RGB
|
||||
*(d + 0) = (pixel >> (11 - 3)) & 0xf8;
|
||||
*(d + 1) = (pixel >> (6 - 3)) & 0xf8;
|
||||
*(d + 2) = (pixel & 0x1f) << 3;
|
||||
|
||||
*(d + 0) = (pixel2 >> (11 - 3)) & 0xf8;
|
||||
*(d + 1) = (pixel2 >> (6 - 3)) & 0xf8;
|
||||
*(d + 2) = (pixel2 & 0x1f) << 3;
|
||||
d += 6;
|
||||
|
||||
*(d2 + 0) = (pixel3 >> (11 - 3)) & 0xf8;
|
||||
*(d2 + 1) = (pixel3 >> (6 - 3)) & 0xf8;
|
||||
*(d2 + 2) = (pixel3 & 0x1f) << 3;
|
||||
|
||||
*(d2 + 0) = (pixel4 >> (11 - 3)) & 0xf8;
|
||||
*(d2 + 1) = (pixel4 >> (6 - 3)) & 0xf8;
|
||||
*(d2 + 2) = (pixel4 & 0x1f) << 3;
|
||||
d2 += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Order is BGR
|
||||
*(d + 0) = (pixel & 0x1f) << 3;
|
||||
*(d + 1) = (pixel >> (6 - 3)) & 0xf8;
|
||||
*(d + 2) = (pixel >> (11 - 3)) & 0xf8;
|
||||
|
||||
*(d + 3) = (pixel2 & 0x1f) << 3;
|
||||
*(d + 4) = (pixel2 >> (6 - 3)) & 0xf8;
|
||||
*(d + 5) = (pixel2 >> (11 - 3)) & 0xf8;
|
||||
d += 6;
|
||||
|
||||
*(d2 + 0) = (pixel3 & 0x1f) << 3;
|
||||
*(d2 + 1) = (pixel3 >> (6 - 3)) & 0xf8;
|
||||
*(d2 + 2) = (pixel3 >> (11 - 3)) & 0xf8;
|
||||
|
||||
*(d2 + 3) = (pixel4 & 0x1f) << 3;
|
||||
*(d2 + 4) = (pixel4 >> (6 - 3)) & 0xf8;
|
||||
*(d2 + 5) = (pixel4 >> (11 - 3)) & 0xf8;
|
||||
d2 += 6;
|
||||
}
|
||||
}
|
||||
s += srcStep;
|
||||
d -= dstStep;
|
||||
d2 -= dstStep;
|
||||
}
|
||||
|
||||
// black out what we might have missed
|
||||
if(image_offset > 0)
|
||||
memset(avi_buffer, 0, image_offset);
|
||||
}
|
||||
|
||||
void DoAVIOpen(const TCHAR* filename)
|
||||
{
|
||||
// close current instance
|
||||
|
@ -1149,16 +1323,21 @@ void DoAVIOpen(const TCHAR* filename)
|
|||
|
||||
AVISetFramerate(framerate, frameskip, GUI.AVIOut);
|
||||
|
||||
avi_width = IPPU.RenderedScreenWidth;
|
||||
avi_height = IPPU.RenderedScreenHeight;
|
||||
avi_width = SNES_WIDTH;
|
||||
avi_height = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
|
||||
avi_skip_frames = Settings.SkipFrames;
|
||||
|
||||
if(GUI.HeightExtend && avi_height < SNES_HEIGHT_EXTENDED)
|
||||
avi_height = SNES_HEIGHT_EXTENDED;
|
||||
if(GUI.AVIHiRes) {
|
||||
avi_width *= 2;
|
||||
avi_height *= 2;
|
||||
}
|
||||
|
||||
if(avi_height % 2 != 0) // most codecs can't handle odd-height images
|
||||
avi_height++;
|
||||
|
||||
avi_pitch = ((avi_width * 3) + 3) & ~3; //((avi_width * 24 + 31) / 8) & ~3;
|
||||
avi_image_size = avi_pitch * avi_height;
|
||||
|
||||
BITMAPINFOHEADER bi;
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.biSize = 0x28;
|
||||
|
@ -1166,7 +1345,7 @@ void DoAVIOpen(const TCHAR* filename)
|
|||
bi.biBitCount = 24;
|
||||
bi.biWidth = avi_width;
|
||||
bi.biHeight = avi_height;
|
||||
bi.biSizeImage = 3*bi.biWidth*bi.biHeight;
|
||||
bi.biSizeImage = avi_image_size;
|
||||
|
||||
AVISetVideoFormat(&bi, GUI.AVIOut);
|
||||
|
||||
|
@ -1192,12 +1371,13 @@ void DoAVIOpen(const TCHAR* filename)
|
|||
return;
|
||||
}
|
||||
|
||||
avi_sound_samples_per_update = (wfx.nSamplesPerSec * frameskip) / framerate;
|
||||
avi_sound_samples_per_update = (double) (wfx.nSamplesPerSec * frameskip) / framerate;
|
||||
avi_sound_bytes_per_sample = wfx.nBlockAlign;
|
||||
avi_sound_samples_error = 0;
|
||||
|
||||
// init buffers
|
||||
avi_buffer = new uint8[3*avi_width*avi_height];
|
||||
avi_sound_buffer = new uint8[avi_sound_samples_per_update * avi_sound_bytes_per_sample];
|
||||
avi_buffer = new uint8[avi_image_size];
|
||||
avi_sound_buffer = new uint8[(int) ceil(avi_sound_samples_per_update) * avi_sound_bytes_per_sample];
|
||||
}
|
||||
|
||||
void DoAVIClose(int reason)
|
||||
|
@ -1236,7 +1416,7 @@ void DoAVIClose(int reason)
|
|||
}
|
||||
}
|
||||
|
||||
void DoAVIVideoFrame(SSurface* source_surface)
|
||||
void DoAVIVideoFrame()
|
||||
{
|
||||
static uint32 lastFrameCount=0;
|
||||
if(!GUI.AVIOut || !avi_buffer || (IPPU.FrameCount==lastFrameCount))
|
||||
|
@ -1255,65 +1435,17 @@ void DoAVIVideoFrame(SSurface* source_surface)
|
|||
wfx.wBitsPerSample = Settings.SixteenBitSound ? 16 : 8;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
if(//avi_width != Width ||
|
||||
//avi_height != Height ||
|
||||
avi_skip_frames != Settings.SkipFrames ||
|
||||
if(avi_skip_frames != Settings.SkipFrames ||
|
||||
(AVIGetSoundFormat(GUI.AVIOut, &pwfex) && memcmp(pwfex, &wfx, sizeof(WAVEFORMATEX))))
|
||||
{
|
||||
DoAVIClose(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert to bitdepth 24
|
||||
SSurface avi_dest_surface;
|
||||
RECT full_rect;
|
||||
avi_dest_surface.Surface = avi_buffer;
|
||||
avi_dest_surface.Pitch = avi_width * 3;
|
||||
avi_dest_surface.Width = avi_width;
|
||||
avi_dest_surface.Height = avi_height;
|
||||
full_rect.top = 0;
|
||||
full_rect.left = 0;
|
||||
full_rect.bottom = avi_height;
|
||||
full_rect.right = avi_width;
|
||||
//if(sixteen_bit)
|
||||
//{
|
||||
Convert16To24(source_surface, &avi_dest_surface, &full_rect);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Convert8To24(source_surface, &avi_dest_surface, &full_rect);
|
||||
//}
|
||||
|
||||
// flip the image vertically
|
||||
const int pitch = 3*avi_width;
|
||||
int y;
|
||||
for(y=0; y<avi_height>>1; ++y)
|
||||
{
|
||||
uint8* lo_8 = avi_buffer+y*pitch;
|
||||
uint8* hi_8 = avi_buffer+(avi_height-1-y)*pitch;
|
||||
uint32* lo_32=(uint32*)lo_8;
|
||||
uint32* hi_32=(uint32*)hi_8;
|
||||
|
||||
int q;
|
||||
{
|
||||
register uint32 a, b;
|
||||
for(q=pitch>>4; q>0; --q)
|
||||
{
|
||||
a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32;
|
||||
a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32;
|
||||
a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32;
|
||||
a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
register uint8 c, d;
|
||||
for(q=(pitch&0x0f); q>0; --q)
|
||||
{
|
||||
c=*lo_8; d=*hi_8; *lo_8=d; *hi_8=c;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(GUI.AVIHiRes)
|
||||
BuildAVIVideoFrame2X();
|
||||
else
|
||||
BuildAVIVideoFrame1X();
|
||||
|
||||
// write to AVI
|
||||
AVIAddVideoFrame(avi_buffer, GUI.AVIOut);
|
||||
|
@ -1322,9 +1454,13 @@ void DoAVIVideoFrame(SSurface* source_surface)
|
|||
if(pwfex)
|
||||
{
|
||||
const int stereo_multiplier = (Settings.Stereo) ? 2 : 1;
|
||||
|
||||
S9xMixSamples(avi_sound_buffer, avi_sound_samples_per_update*stereo_multiplier);
|
||||
|
||||
AVIAddSoundSamples(avi_sound_buffer, avi_sound_samples_per_update, GUI.AVIOut);
|
||||
avi_sound_samples_error += avi_sound_samples_per_update;
|
||||
int samples = (int) avi_sound_samples_error;
|
||||
avi_sound_samples_error -= samples;
|
||||
|
||||
S9xMixSamples(avi_sound_buffer, samples*stereo_multiplier);
|
||||
|
||||
AVIAddSoundSamples(avi_sound_buffer, samples, GUI.AVIOut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ IS9xDisplayOutput *S9xDisplayOutput=&Direct3D;
|
|||
#endif
|
||||
|
||||
bool8 S9xDeinitUpdate (int, int);
|
||||
void DoAVIVideoFrame(SSurface* source_surface);
|
||||
void DoAVIVideoFrame();
|
||||
|
||||
/* WinRefreshDisplay
|
||||
repeats the last rendered frame
|
||||
|
@ -348,7 +348,7 @@ bool8 S9xContinueUpdate(int Width, int Height)
|
|||
Src.Surface = (BYTE*)GFX.Screen;
|
||||
|
||||
// avi writing
|
||||
DoAVIVideoFrame(&Src);
|
||||
DoAVIVideoFrame();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -371,13 +371,13 @@ bool8 S9xDeinitUpdate (int Width, int Height)
|
|||
const int OrigHeight = Height;
|
||||
Height = Src.Height;
|
||||
|
||||
// avi writing
|
||||
DoAVIVideoFrame();
|
||||
|
||||
if(GUI.BlendHiRes) {
|
||||
RenderMergeHires(Src.Surface,Src.Pitch,Src.Width,Src.Height);
|
||||
}
|
||||
|
||||
// avi writing
|
||||
DoAVIVideoFrame(&Src);
|
||||
|
||||
// Clear some of the old SNES rendered image
|
||||
// when the resolution becomes lower in x or y,
|
||||
// otherwise the image processors (filters) might access
|
||||
|
|
|
@ -218,11 +218,14 @@ returns true if successful, false otherwise
|
|||
*/
|
||||
bool ReInitSound()
|
||||
{
|
||||
if (GUI.AVIOut)
|
||||
return false;
|
||||
Settings.SoundInputRate = CLAMP(Settings.SoundInputRate,8000, 48000);
|
||||
Settings.SoundPlaybackRate = CLAMP(Settings.SoundPlaybackRate,8000, 48000);
|
||||
S9xSetSoundMute(GUI.Mute);
|
||||
if(S9xSoundOutput)
|
||||
S9xSoundOutput->DeInitSoundOutput();
|
||||
|
||||
return S9xInitSound(GUI.SoundBufferSize,0);
|
||||
}
|
||||
|
||||
|
|
|
@ -3225,16 +3225,14 @@ int WINAPI WinMain(
|
|||
|
||||
RestoreMainWinPos();
|
||||
|
||||
WinDisplayReset();
|
||||
void InitSnes9X (void);
|
||||
InitSnes9X ();
|
||||
|
||||
if(GUI.FullScreen) {
|
||||
GUI.FullScreen = false;
|
||||
ToggleFullScreen();
|
||||
}
|
||||
|
||||
void InitSnes9X (void);
|
||||
InitSnes9X ();
|
||||
|
||||
TIMECAPS tc;
|
||||
if (timeGetDevCaps(&tc, sizeof(TIMECAPS))== TIMERR_NOERROR)
|
||||
{
|
||||
|
@ -4918,6 +4916,7 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar
|
|||
CheckDlgButton(hDlg,IDC_TOGGLE_TURBO,GUI.TurboModeToggle ? BST_CHECKED : BST_UNCHECKED);
|
||||
CheckDlgButton(hDlg,IDC_INACTIVE_PAUSE,GUI.InactivePause ? BST_CHECKED : BST_UNCHECKED);
|
||||
CheckDlgButton(hDlg,IDC_CUSTOMROMOPEN,GUI.CustomRomOpen ? BST_CHECKED : BST_UNCHECKED);
|
||||
CheckDlgButton(hDlg,IDC_HIRESAVI,GUI.AVIHiRes ? BST_CHECKED : BST_UNCHECKED);
|
||||
|
||||
int inum = 0;
|
||||
lstrcpy(paths[inum++],GUI.RomDir);
|
||||
|
@ -5001,6 +5000,7 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar
|
|||
GUI.TurboModeToggle = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_TOGGLE_TURBO));
|
||||
GUI.InactivePause = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_INACTIVE_PAUSE));
|
||||
GUI.CustomRomOpen = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_CUSTOMROMOPEN));
|
||||
GUI.AVIHiRes = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_HIRESAVI));
|
||||
|
||||
Settings.TurboSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_GETPOS, 0,0);
|
||||
Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_GETPOS, 0,0);
|
||||
|
|
|
@ -301,6 +301,7 @@ struct sGUI {
|
|||
RenderFilter Scale;
|
||||
RenderFilter ScaleHiRes;
|
||||
bool BlendHiRes;
|
||||
bool AVIHiRes;
|
||||
bool DoubleBuffered;
|
||||
bool FullScreen;
|
||||
bool Stretch;
|
||||
|
|
Loading…
Reference in New Issue