Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From c7691265db228e760b2076f6c55e351394d25ac9 Mon Sep 17 00:00:00 2001
- From: gocha <gochaism@gmail.com>
- Date: Sun, 30 Jan 2011 12:43:09 +0900
- Subject: [PATCH] windows: fixed AVI image size, now it should resize Hi-Res image properly.
- added GUI.AVIHiRes option, which allows us recording Hi-Res image without down-sampling. (it cannot be changed from GUI at the moment, needs a little more addition in menu/dialog)
- modified ReInitSound, to do nothing during AVI recording (fix "Reset during AVI recording" situation)
- Note: my AVI recording code doesn't use Convert16To24. I guess it can be simplified like Convert16To32 from now.
- ---
- win32/wconfig.cpp | 1 +
- win32/win32.cpp | 294 +++++++++++++++++++++++++++++++++++++++++--------
- win32/win32_sound.cpp | 5 +-
- win32/wsnes9x.h | 1 +
- 4 files changed, 252 insertions(+), 49 deletions(-)
- diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp
- index 03f97e8..28242ee 100644
- --- a/win32/wconfig.cpp
- +++ b/win32/wconfig.cpp
- @@ -864,6 +864,7 @@ void WinRegisterConfigItems()
- AddUIntC("FilterType", GUI.Scale, 0, filterString);
- AddUIntC("FilterHiRes", GUI.ScaleHiRes, 0, filterString2);
- AddBoolC("BlendHiRes", GUI.BlendHiRes, true, "true to horizontally blend Hi-Res images (better transparency effect on filters that do not account for this)");
- + AddBoolC("AVIHiRes", GUI.AVIHiRes, false, "true to record AVI in Hi-Res scale");
- AddBoolC("ShaderEnabled", GUI.shaderEnabled, false, "true to use pixel shader (if supported by output method)");
- AddStringC("Direct3D:HLSLFileName", GUI.HLSLshaderFileName, MAX_PATH, "", "shader filename for Direct3D mode");
- AddStringC("OpenGL:GLSLFileName", GUI.GLSLshaderFileName, MAX_PATH, "", "shader filename for OpenGL mode (bsnes-style XML shader)");
- diff --git a/win32/win32.cpp b/win32/win32.cpp
- index cebc8f6..8672d5a 100644
- --- a/win32/win32.cpp
- +++ b/win32/win32.cpp
- @@ -222,11 +222,11 @@ static int avi_sound_bytes_per_sample = 0;
- static int avi_sound_samples_per_update = 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);
- @@ -1121,6 +1121,221 @@ bool JustifierOffscreen()
- // }
- //}
- +// Dst: GFX.Screen 256xH (1x1) 16bpp top-down
- +// Src: avi_buffer 256xH (1x1) 24bpp bottom-up
- +void BuildAVIVideoFrame1X (void)
- +{
- + const int snesWidth = IPPU.RenderedScreenWidth;
- + const int snesHeight = IPPU.RenderedScreenHeight;
- + const int width = min(snesWidth, avi_width);
- + const int height = min(snesHeight, avi_height);
- + const int pitch = GFX.Pitch;
- +#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 src_step = pitch - width * 2;
- + const int dst_step = -(avi_pitch + width * 3);
- + const int image_offset = (avi_height - height) * avi_pitch;
- + uint16 *s = GFX.Screen;
- + uint8 *d = &avi_buffer[(avi_height - 1) * avi_pitch];
- +
- + for(int y = 0; y < height; y++)
- + {
- + for(int x = 0; x < width; x++)
- + {
- + if(order_is_rgb)
- + {
- + // Order is RGB
- + uint32 pixel = *s++;
- + *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel & 0x1f) << 3;
- + d += 3;
- + }
- + else
- + {
- + // Order is BGR
- + uint32 pixel = *s++;
- + *(d + 0) = (pixel & 0x1f) << 3;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
- + d += 3;
- + }
- + }
- + s = (uint16*)((uint8*)s + src_step);
- + d += dst_step;
- + }
- +
- + // black out what we might have missed
- + if(image_offset > 0)
- + memset(avi_buffer, 0, image_offset);
- +}
- +
- +// Dst: GFX.Screen 256xH (1x1) 16bpp top-down
- +// Src: avi_buffer 512x2H (2x2) 24bpp bottom-up
- +void BuildAVIVideoFrame2X (void)
- +{
- + const int snesWidth = IPPU.RenderedScreenWidth;
- + const int snesHeight = IPPU.RenderedScreenHeight;
- + const int width = min(snesWidth, avi_width / 2);
- + const int height = min(snesHeight, avi_height / 2);
- + const int pitch = GFX.Pitch;
- +#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 src_step[2] = { -width * 2, pitch - width * 2 };
- + const int dst_step = -(avi_pitch + width * 3 * 2);
- + const int image_offset = (avi_height - height * 2) * avi_pitch;
- + uint16 *s = GFX.Screen;
- + uint8 *d = &avi_buffer[(avi_height - 1) * avi_pitch];
- +
- + for(int y = 0; y < height * 2; y++)
- + {
- + for(int x = 0; x < width; x++)
- + {
- + if(order_is_rgb)
- + {
- + // Order is RGB
- + uint32 pixel = *s++;
- + *(d + 0) = *(d + 3) = (pixel >> (11 - 3)) & 0xf8;
- + *(d + 1) = *(d + 4) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = *(d + 5) = (pixel & 0x1f) << 3;
- + d += 6;
- + }
- + else
- + {
- + // Order is BGR
- + uint32 pixel = *s++;
- + *(d + 0) = *(d + 3) = (pixel & 0x1f) << 3;
- + *(d + 1) = *(d + 4) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = *(d + 5) = (pixel >> (11 - 3)) & 0xf8;
- + d += 6;
- + }
- + }
- + s = (uint16*)((uint8*)s + src_step[y % 2]);
- + d += dst_step;
- + }
- +
- + // black out what we might have missed
- + if(image_offset > 0)
- + memset(avi_buffer, 0, image_offset);
- +}
- +
- +// Dst: GFX.Screen 512xH (2x1) 16bpp top-down
- +// Src: avi_buffer 256xH (1x1) 24bpp bottom-up
- +void BuildAVIVideoFrame1XHiRes (void)
- +{
- + const int snesWidth = IPPU.RenderedScreenWidth;
- + const int snesHeight = IPPU.RenderedScreenHeight;
- + const int width = min(snesWidth / 2, avi_width);
- + const int height = min(snesHeight, avi_height);
- + const int pitch = GFX.Pitch;
- +#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 src_step = pitch - width * 2 * 2;
- + const int dst_step = -(avi_pitch + width * 3);
- + const int image_offset = (avi_height - height) * avi_pitch;
- + uint16 *s = GFX.Screen;
- + uint8 *d = &avi_buffer[(avi_height - 1) * avi_pitch];
- +
- + #define Interp(c1, c2) \
- + (c1 == c2) ? c1 : \
- + (((((c1 & 0x07E0) + (c2 & 0x07E0)) >> 1) & 0x07E0) + \
- + ((((c1 & 0xF81F) + (c2 & 0xF81F)) >> 1) & 0xF81F))
- +
- + for(int y = 0; y < height; y++)
- + {
- + for(int x = 0; x < width; x++)
- + {
- + if(order_is_rgb)
- + {
- + // Order is RGB
- + uint32 pixel = Interp(s[0],s[1]);
- + s += 2;
- + *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel & 0x1f) << 3;
- + d += 3;
- + }
- + else
- + {
- + // Order is BGR
- + uint32 pixel = Interp(s[0],s[1]);
- + s += 2;
- + *(d + 0) = (pixel & 0x1f) << 3;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
- + d += 3;
- + }
- + }
- + s = (uint16*)((uint8*)s + src_step);
- + d += dst_step;
- + }
- +
- + // black out what we might have missed
- + if(image_offset > 0)
- + memset(avi_buffer, 0, image_offset);
- +}
- +
- +// Dst: GFX.Screen 512xH (1x1) 16bpp top-down
- +// Src: avi_buffer 512x2H (1x2) 24bpp bottom-up
- +void BuildAVIVideoFrame2XHiRes (void)
- +{
- + const int snesWidth = IPPU.RenderedScreenWidth;
- + const int snesHeight = IPPU.RenderedScreenHeight;
- + const int width = min(snesWidth, avi_width);
- + const int height = min(snesHeight, avi_height / 2);
- + const int pitch = GFX.Pitch;
- +#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 src_step[2] = { -width * 2, pitch - width * 2 };
- + const int dst_step = -(avi_pitch + width * 3);
- + const int image_offset = (avi_height - height * 2) * avi_pitch;
- + uint16 *s = GFX.Screen;
- + uint8 *d = &avi_buffer[(avi_height - 1) * avi_pitch];
- +
- + for(int y = 0; y < height * 2; y++)
- + {
- + for(int x = 0; x < width; x++)
- + {
- + if(order_is_rgb)
- + {
- + // Order is RGB
- + uint32 pixel = *s++;
- + *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel & 0x1f) << 3;
- + d += 3;
- + }
- + else
- + {
- + // Order is BGR
- + uint32 pixel = *s++;
- + *(d + 0) = (pixel & 0x1f) << 3;
- + *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
- + *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
- + d += 3;
- + }
- + }
- + s = (uint16*)((uint8*)s + src_step[y % 2]);
- + d += dst_step;
- + }
- +
- + // 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
- @@ -1153,12 +1368,20 @@ void DoAVIOpen(const TCHAR* filename)
- avi_height = IPPU.RenderedScreenHeight;
- avi_skip_frames = Settings.SkipFrames;
- + if(GUI.AVIHiRes && avi_width <= SNES_WIDTH)
- + avi_width = SNES_WIDTH*2;
- + else if(!GUI.AVIHiRes && avi_width > SNES_WIDTH)
- + avi_width = SNES_WIDTH;
- if(GUI.HeightExtend && avi_height < SNES_HEIGHT_EXTENDED)
- avi_height = SNES_HEIGHT_EXTENDED;
- -
- + if(GUI.AVIHiRes)
- + avi_height *= 2;
- if(avi_height % 2 != 0) // most codecs can't handle odd-height images
- avi_height++;
- + avi_pitch = ((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 +1389,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);
- @@ -1196,7 +1419,7 @@ void DoAVIOpen(const TCHAR* filename)
- avi_sound_bytes_per_sample = wfx.nBlockAlign;
- // init buffers
- - avi_buffer = new uint8[3*avi_width*avi_height];
- + avi_buffer = new uint8[avi_image_size];
- avi_sound_buffer = new uint8[avi_sound_samples_per_update * avi_sound_bytes_per_sample];
- }
- @@ -1265,53 +1488,28 @@ void DoAVIVideoFrame(SSurface* source_surface)
- }
- // 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)
- + const int snesWidth = IPPU.RenderedScreenWidth;
- + const int snesHeight = IPPU.RenderedScreenHeight;
- + if(snesWidth < SNES_WIDTH*2) // normal
- {
- - 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;
- + if(avi_width < snesWidth*2) // 1x
- {
- - 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;
- - }
- + BuildAVIVideoFrame1X();
- }
- -
- + else // 2x
- {
- - register uint8 c, d;
- - for(q=(pitch&0x0f); q>0; --q)
- - {
- - c=*lo_8; d=*hi_8; *lo_8=d; *hi_8=c;
- - }
- + BuildAVIVideoFrame2X();
- + }
- + }
- + else // high-res
- + {
- + if(avi_width < snesWidth) // 1x
- + {
- + BuildAVIVideoFrame1XHiRes();
- + }
- + else // 2x
- + {
- + BuildAVIVideoFrame2XHiRes();
- }
- }
- diff --git a/win32/win32_sound.cpp b/win32/win32_sound.cpp
- index 55cae45..ae469b1 100644
- --- a/win32/win32_sound.cpp
- +++ b/win32/win32_sound.cpp
- @@ -218,12 +218,15 @@ 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);
- + bool result = S9xInitSound(GUI.SoundBufferSize,0);
- + return result;
- }
- void CloseSoundDevice() {
- diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h
- index 3273cea..409deed 100644
- --- a/win32/wsnes9x.h
- +++ b/win32/wsnes9x.h
- @@ -301,6 +301,7 @@ struct sGUI {
- RenderFilter Scale;
- RenderFilter ScaleHiRes;
- bool BlendHiRes;
- + bool AVIHiRes;
- bool DoubleBuffered;
- bool FullScreen;
- bool Stretch;
- --
- 1.7.3.1.msysgit.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement