4 years ago[gens-sdl] gens-sdl.cpp: Removed unused includes. feature/gens-sdl-split-into-EventLoop github/feature/gens-sdl-split-into-EventLoop
David Korth [Sun, 6 Sep 2015 16:39:47 +0000 (12:39 -0400)] 
[gens-sdl] gens-sdl.cpp: Removed unused includes.

Most of these are needed by the event loops, which have been split
out into separate files.

Removed the Win32-only freopen() calls. SDL2 dropped support for stdio
redirection, so we don't have to undo it anymore.

4 years ago[gens-sdl] Moved the frameskip code into EmuLoop::runFrame().
David Korth [Sun, 6 Sep 2015 16:31:37 +0000 (12:31 -0400)] 
[gens-sdl] Moved the frameskip code into EmuLoop::runFrame().

EmuLoop::runFrame() calls abstract virtual functions runFullFrame() and
runFastFrame() depending on the number of frames to skip. These are
implemented by the subclasses.

This eliminates the frameskip duplication between EmuLoop and CrazyEffectLoop.

4 years ago[gens-sdl] EmuLoop: Moved internal SDL event processing functions to the private...
David Korth [Sat, 5 Sep 2015 14:17:16 +0000 (10:17 -0400)] 
[gens-sdl] EmuLoop: Moved internal SDL event processing functions to the private class.

Marked getSaveSlot_mtime() as static, since it doens't depend on
any of the class variables.

4 years ago[libgens] CrazyEffect: Improved performance by using a faster RNG.
David Korth [Thu, 3 Sep 2015 04:54:57 +0000 (00:54 -0400)] 
[libgens] CrazyEffect: Improved performance by using a faster RNG.

Xorshift+ is significantly faster than both glibc's and MSVC 2010's
rand() function. On my ThinkPad T60p, the Linux rand() version usually
runs at around 45-50 fps if something else is running, but the new
Xorshift+ version runs at 56-60 fps.

This version also helps to reduce the CPU load a bit.

TODO: Cache the upper bits of Xorshift+'s result so we can get
at least two 15-bit values out of a single iteration.

4 years ago[gens-sdl] CrazyEffectLoop: Stop SDL video when exiting the event loop.
David Korth [Thu, 3 Sep 2015 04:45:52 +0000 (00:45 -0400)] 
[gens-sdl] CrazyEffectLoop: Stop SDL video when exiting the event loop.

FIXME: We're not using audio here, so maybe deleting sdlHandler won't crash?

4 years ago[gens-sdl] EventLoop: New function processSdlEventQueue().
David Korth [Thu, 3 Sep 2015 04:27:14 +0000 (00:27 -0400)] 
[gens-sdl] EventLoop: New function processSdlEventQueue().

This consolidates the pause, OSD processing, and video expose handling
from EmuLoop and CrazyEffectLoop into a single function.

- Wait for what would be the next frame when emulation is paused?
  (This is in EmuLoop and CrazyEffectLoop, not processSdlEventQueue().)
- paused_t: Add assign/copy constructors and operator==(), or are they
  even needed?

4 years ago[gens-sdl] EventLoop_p.hpp: New header for EventLoopPrivate.
David Korth [Thu, 3 Sep 2015 03:07:21 +0000 (23:07 -0400)] 
[gens-sdl] EventLoop_p.hpp: New header for EventLoopPrivate.

Moved EventLoop's protected and private variables into EventLoopPrivate.

Rebased EmuLoopPrivate and CrazyEffectLoopPrivate on EventLoopPrivate.

Added Qt-style d_func() functions to handle private class inheritance.

Moved the OS-specific includes and yield() macro to EventLoop_p.hpp.

EventLoop: Added a vBackend accessor so gens-sdl can print messages
to the Onscreen Display.

4 years ago[gens-sdl] Created an EventLoop base class and rebased EmuLoop and CrazyEffectLoop.
David Korth [Thu, 3 Sep 2015 02:36:13 +0000 (22:36 -0400)] 
[gens-sdl] Created an EventLoop base class and rebased EmuLoop and CrazyEffectLoop.

The LibGens::Timing object has been moved to EventLoop::m_clks.

- Move EventLoop objects into a private class in EventLoop_p.hpp.
- Make EmuLoop's and CrazyEventLoop's private classes inherit
  from EventLoopPrivate.
- More cleanup and refactoring.

4 years ago[gens-sdl] EmuLoop.cpp::doStretchMode(): Use vBackend directly.
David Korth [Thu, 3 Sep 2015 02:15:12 +0000 (22:15 -0400)] 
[gens-sdl] EmuLoop.cpp::doStretchMode(): Use vBackend directly.

We're caching sdlHandler's vBackend for this exact reason.

Incidentally, later in the function, we *do* use vBackend directly
in order to print the message on the screen.

4 years ago[gens-sdl] Split the emulation loop and "Crazy" Effect loop into separate files.
David Korth [Thu, 3 Sep 2015 01:22:17 +0000 (21:22 -0400)] 
[gens-sdl] Split the emulation loop and "Crazy" Effect loop into separate files.

All of the functions are currently in the GensSdl namespace without
any enclosing classes.

EmuLoop.cpp has its own processSdlEvent_emuLoop() function to handle keys
that aren't needed for the "Crazy" Effect, e.g. savestates. If an event
isn't handled by EmuLoop, gens-sdl.cpp's processSdlEvent_common() will
try processing it. If that doesn't handle it, the key will be sent
to the KeyManager.

TODO: Convert EmuLoop and CrazyEffectLoop to classes with a common
base class.

4 years ago[zlib] CMakeLists.txt: Fixed the 64-bit MSVC build.
David Korth [Thu, 3 Sep 2015 01:15:15 +0000 (21:15 -0400)] 
[zlib] CMakeLists.txt: Fixed the 64-bit MSVC build.

inffas8664.c is required in order to use the asm code. Otherwise,
it fails to link because inflate_fast() is undefined.

4 years ago[gens-sdl] gens-sdl.cpp: Yield after every frame when rendering the "Crazy" effect.
David Korth [Wed, 2 Sep 2015 06:28:57 +0000 (02:28 -0400)] 
[gens-sdl] gens-sdl.cpp: Yield after every frame when rendering the "Crazy" effect.

TODO: Use the frameskip code to limit frames?

4 years ago[libgens] CrazyEffect: Improve performance on systems where RAND_MAX >= 0x3FFFFFFF.
David Korth [Wed, 2 Sep 2015 06:26:13 +0000 (02:26 -0400)] 
[libgens] CrazyEffect: Improve performance on systems where RAND_MAX >= 0x3FFFFFFF.

glibc's RAND_MAX is 0x7FFFFFFF. We can cache the high bits as a second
random number in order to cut the number of rand() calls in half.

This increases performance on my system from around ~45-50 fps to
~56-60 fps in both the debug and release builds. There's no difference
between the two, so I suspect that rand() is the main bottleneck.

TODO: Use a faster rand() implementation, e.g. Mersenne Twister?

4 years ago[libgens] CrazyEffect: Simplified the template parameters.
David Korth [Wed, 2 Sep 2015 06:14:10 +0000 (02:14 -0400)] 
[libgens] CrazyEffect: Simplified the template parameters.

The template now takes RBits, GBits, and BBits, similar to the other
effects. All of the masks are calculated within the function, and gcc
should be able to calculate these at compile time.

4 years ago[gens-sdl] gens-sdl.cpp: Added a quick and dirty test mode for the "Crazy" Effect.
David Korth [Wed, 2 Sep 2015 05:48:52 +0000 (01:48 -0400)] 
[gens-sdl] gens-sdl.cpp: Added a quick and dirty test mode for the "Crazy" Effect.

TODO: Split it into a separate main loop so we can run it without
initializing audio or an emulation context.

4 years ago[mdZ80] CMakeLists.txt: Use SET_MSVC_DEBUG_PATH().
David Korth [Wed, 2 Sep 2015 05:03:57 +0000 (01:03 -0400)] 
[mdZ80] CMakeLists.txt: Use SET_MSVC_DEBUG_PATH().

4 years agoExplicitly set the source language for the mdZ80 and starscream asm files.
David Korth [Wed, 2 Sep 2015 05:00:47 +0000 (01:00 -0400)] 
Explicitly set the source language for the mdZ80 and starscream asm files.

CMake assumed these were nasm, but due to the issues with the
zlib assembler files, we might as well explicitly specify that
these are, in fact, nasm files.

Prefixed the mdZ80 SRCS variable name with "mdZ80_" instead of
just using "SRCS".

4 years ago[zlib] _MODIFIED_ZLIB.txt: Also check for __x86_64__ in addition to __amd64__.
David Korth [Wed, 2 Sep 2015 04:55:18 +0000 (00:55 -0400)] 
[zlib] _MODIFIED_ZLIB.txt: Also check for __x86_64__ in addition to __amd64__.

4 years ago[zlib] Enable ASM optimizations on i386 and amd64.
David Korth [Wed, 2 Sep 2015 04:52:21 +0000 (00:52 -0400)] 
[zlib] Enable ASM optimizations on i386 and amd64.

set_source_files_properties(): Set COMPILE_FLAGS to "". Leaving out the
flags parameter entirely caused a CMake error:

CMake Error at extlib/zlib/CMakeLists.txt:152 (set_source_files_properties):
  set_source_files_properties called with incorrect number of arguments.

MSVC assembler: Explicilty set the language of the asm files as ASM_MASM.
For some reason, CMake is assuming that all .asm files are ASM_NASM,
which prevented these files from being assembled correctly.

4 years ago[libcompat] CMakeLists.txt: Update the regular expressions.
David Korth [Wed, 2 Sep 2015 04:43:20 +0000 (00:43 -0400)] 
[libcompat] CMakeLists.txt: Update the regular expressions.

This matches the version used in cmake/platform/msvc.cmake.

Specify 'arch' instead of "${arch}", since the MATCHES operator can
take a variable name in addition to a plain string.

4 years ago[cmake] platform/msvc.cmake: Set CMAKE_SIZEOF_VOID_P if it isn't set.
David Korth [Wed, 2 Sep 2015 04:42:51 +0000 (00:42 -0400)] 
[cmake] platform/msvc.cmake: Set CMAKE_SIZEOF_VOID_P if it isn't set.

CMake seems to forget to set this variable in MSVC builds sometimes.

FIXME: This won't work if we're cross-compiling, e.g. using the
x86_amd64 or amd64_x86 toolchains.

4 years ago[zlib] Added checks for __x86_64__ in addition to __amd64__.
David Korth [Wed, 2 Sep 2015 04:12:24 +0000 (00:12 -0400)] 
[zlib] Added checks for __x86_64__ in addition to __amd64__.

Intel's compiler defines __x86_64__ but not __amd64__.

4 years agoCheck for __x86_64__ in addition to __amd64__.
David Korth [Wed, 2 Sep 2015 04:09:42 +0000 (00:09 -0400)] 
Check for __x86_64__ in addition to __amd64__.

Intel's compiler defines __x86_64__ but not __amd64__ because of reasons.

4 years ago[libgens/tests] AudioWriteTest.cpp: Check for __GNUC__ when checking for MMX/SSE2.
David Korth [Wed, 2 Sep 2015 04:08:31 +0000 (00:08 -0400)] 
[libgens/tests] AudioWriteTest.cpp: Check for __GNUC__ when checking for MMX/SSE2.

4 years ago[doc] TODO.txt: localtime_r() wrapper returns _Tm.
David Korth [Wed, 2 Sep 2015 03:12:37 +0000 (23:12 -0400)] 
[doc] TODO.txt: localtime_r() wrapper returns _Tm.

This was fixed in commit 001c2ac491c85e784b82f40a9a463c0d98e6259e.
([libcompat] reentrant.h: Adjusted the localtime_r() implementation a bit.)

4 years ago[doc] TODO.txt: Win32ImageVersionLinkerFlags.cmake was added.
David Korth [Wed, 2 Sep 2015 03:07:19 +0000 (23:07 -0400)] 
[doc] TODO.txt: Win32ImageVersionLinkerFlags.cmake was added.

Added in commit 9a9e00c8e75e99bc4b2f4b2b96db1cf7798636dc.
([cmake] Win32ImageVersionLinkerFlags.cmake: CMake macro for setting the Win32 image version.)

4 years agoc++11-compat.h: #error if compiling with gcc-4.7+ in C++ mode and C++ 2011 mode isn...
David Korth [Wed, 2 Sep 2015 02:53:46 +0000 (22:53 -0400)] 
c++11-compat.h: #error if compiling with gcc-4.7+ in C++ mode and C++ 2011 mode isn't enabled.

We can't check earlier versions because g++ wasn't setting the value of
__cplusplus correctly. g++ versions earlier than 4.7 set __cplusplus to 1
instead of the relevant standard version, i.e. 199711L for C++ 1998/2003
and 201103L for C++ 2011.
set to the C++ standard version.

4 years agoMerge branch 'feature/gens-sdl-autoPause'
David Korth [Wed, 2 Sep 2015 02:53:35 +0000 (22:53 -0400)] 
Merge branch 'feature/gens-sdl-autoPause'

4 years ago[gens-sdl] gens-sdl.cpp: Implemented auto-pause. feature/gens-sdl-autoPause github/feature/gens-sdl-autoPause
David Korth [Wed, 2 Sep 2015 02:53:18 +0000 (22:53 -0400)] 
[gens-sdl] gens-sdl.cpp: Implemented auto-pause.

Similar to the gens-qt4 implementation, I changed the 'paused' variable
to a struct containing a union of a bitfield and a uint8_t. This allows
us to easily set or unset both the "manual" and "auto" (called "focus"
because "auto" is a C keyword) paused bits, and to check if any of them
are set.

TODO: Write a popt-based command line parser with a struct containing
all of the options.

4 years ago[gens-sdl] gens-sdl.cpp: #include <cerrno>
David Korth [Wed, 2 Sep 2015 02:48:44 +0000 (22:48 -0400)] 
[gens-sdl] gens-sdl.cpp: #include <cerrno>

We're using POSIX error values here, and it's only explicitly included
if we're using -std=c++11 or -std=gnu++11. This might change in the
future, so explicitly #include <cerrno>.

4 years ago[doc] TODO.txt: GLEW and the Fast Blur shader have been ported from gens-qt4 to gens...
David Korth [Wed, 2 Sep 2015 01:41:45 +0000 (21:41 -0400)] 
[doc] TODO.txt: GLEW and the Fast Blur shader have been ported from gens-qt4 to gens-sdl.

GLEW doesn't support checking for GL_APPLE_packed_pixels for some reason,
but if your video card is old enough to not support OpenGL 1.2, chances
are it can't run Gens/GS II, either. (Well, either that or you're using
Remote Desktop, which has OpenGL 1.1 with GL_EXT_bgra and a few other
Microsoft-specific extensions.)

4 years agoMerge branch 'feature/gens-sdl-GLEW'
David Korth [Wed, 2 Sep 2015 01:34:51 +0000 (21:34 -0400)] 
Merge branch 'feature/gens-sdl-GLEW'

gens-sdl now has proper GL feature detection and an ARB fragment program
version of the Fast Blur effect. This code was mostly ported from the
gens-qt4 frontend, but with various improvements.

4 years ago[gens-sdl] GLShaderFastBlur.cpp: Removed an unnecessary include; updated the copyrigh... feature/gens-sdl-GLEW github/feature/gens-sdl-GLEW
David Korth [Wed, 2 Sep 2015 01:33:33 +0000 (21:33 -0400)] 
[gens-sdl] GLShaderFastBlur.cpp: Removed an unnecessary include; updated the copyright date.

Previously, strlen() was used to determine the length of the
ARB fragment program. Since the program was changed from
const char *const to const char[], strlen() is no longer needed,
since sizeof() works.

4 years ago[gens-sdl] GLShader: Split the GL_ATI_text_fragment_shader code into completely separ...
David Korth [Wed, 2 Sep 2015 01:31:13 +0000 (21:31 -0400)] 
[gens-sdl] GLShader: Split the GL_ATI_text_fragment_shader code into completely separate cases.

This significantly improves the code's readability.

4 years ago[gens-sdl] GLShaderFastBlur: Ported the Fast Blur shader from gens-qt4.
David Korth [Wed, 2 Sep 2015 01:26:52 +0000 (21:26 -0400)] 
[gens-sdl] GLShaderFastBlur: Ported the Fast Blur shader from gens-qt4.

This includes the GLShader base class.

There's a few differences between the gens-sdl version and the
original gens-qt4 version:

- GLEW is no longer conditional. There's no point in supporting
  a build without GLEW, since GLEW makes GL feature detection
  much easier.

- GLBackend handles the shaders directly, instead of using
  a separate GLShaderManager class.

- init() and end() return error codes, as do enable() and disable().

- The two shader name variables have been combined into a single
  variable, m_shaderName. Only one type of each shader can be in
  use at any given time, so there's no point in reserving memory
  for both the ARB fp name and the ATi fragment shader name.

- GLShaderFastBlur: The actual fragment program text is now stored
  in a private class, using const char[] instead of const char *const.
  This reduces memory usage by one pointer.

- sizeof() is used to determine the program size. Note that the NULL
  terminator should not be included. NVIDIA's Windows driver refuses
  to compile the shader if it is included; Mesa's r300g driver doesn't
  care if it is or not.

4 years ago[gens-sdl] Initialize and use GLEW.
David Korth [Wed, 2 Sep 2015 01:10:28 +0000 (21:10 -0400)] 
[gens-sdl] Initialize and use GLEW.

This lets us get rid of some hacks to work around MSVC's ancient
OpenGL headers, plus it lets us check if the GL implementation
actually supports certain functionality, e.g. packed pixels.

GLTex: TODO: Move internal variables to GLTexPrivate?

4 years ago[cmake] CheckOpenGL.cmake: Renamed GLEW_COMPILE_DEFINITIONS to GLEW_DEFINITIONS.
David Korth [Wed, 2 Sep 2015 00:52:06 +0000 (20:52 -0400)] 

This matches the other libraries.


4 years ago[gens-sdl] GLBackend: Don't memset() d->tex; it's a C++ class now.
David Korth [Wed, 2 Sep 2015 00:50:16 +0000 (20:50 -0400)] 
[gens-sdl] GLBackend: Don't memset() d->tex; it's a C++ class now.

GLTex was converted into a standard class in commit 34663496a5210a70a279375407117aceeee19629,
but I forgot to remove this memset().

Commit 34663496a5210a70a279375407117aceeee19629:
[gens-sdl] GLTex.cpp: Converted GLTex into a class.

4 years ago[gens-sdl] GLBackend: Moved the OpenGL includes from the header to the implementation...
David Korth [Wed, 2 Sep 2015 00:49:25 +0000 (20:49 -0400)] 
[gens-sdl] GLBackend: Moved the OpenGL includes from the header to the implementation file.

No need to expose the GL headers here, since all of the GL variables
are in a private class in GLBackend.cpp.

4 years ago[libgens] VdpDebug.cpp: The test register is uint16_t, not uint8_t.
David Korth [Wed, 2 Sep 2015 00:42:23 +0000 (20:42 -0400)] 
[libgens] VdpDebug.cpp: The test register is uint16_t, not uint8_t.

Not that it's being used for anything right now, but we should
use the correct data type anyway.

This fixes the following compiler warning on MSVC 2010:

src\libgens\Vdp\VdpDebug.cpp(144) : warning C4244: '=' : conversion from 'uint16_t' to 'uint8_t', possible loss of data

4 years ago[libgens/tests] AudioWriteTest_data.c: Ignore MSVC warning C4146.
David Korth [Wed, 2 Sep 2015 00:40:31 +0000 (20:40 -0400)] 
[libgens/tests] AudioWriteTest_data.c: Ignore MSVC warning C4146.

MSVC complains that some values have a negative sign but end up
overflowing the data type, e.g. -0x80000000. This is expected,
so disable the warning.

This fixes the following compiler warnings on MSVC 2010:

src\libgens\tests\sound\AudioWriteTest_data.c(33) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
src\libgens\tests\sound\AudioWriteTest_data.c(236) : warning C4146: unary minus operator applied to unsigned type, result still unsigned

4 years ago[libgens/tests] EEPRomI2CTest: Cast the result of time() to unsigned int.
David Korth [Wed, 2 Sep 2015 00:36:18 +0000 (20:36 -0400)] 
[libgens/tests] EEPRomI2CTest: Cast the result of time() to unsigned int.

time() returns time_t, which is 64-bit on most 64-bit OSes and some
compilers on 32-bit OSes, including Mac OS X, MinGW-w64, and MSVC 2010.

This fixes a compiler warning on MSVC 2010:

src\libgens\tests\EEPRomI2CTest\EEPRomI2CTest.cpp(252) : warning C4244: 'initializing' : conversion from 'time_t' to 'unsigned int', possible loss of data

Interestingly, neither 64-bit Linux gcc nor MinGW-w64 complained about this.

Prefix the random number seed fprintf() with "0x" to make it more obvious
that it's a hexadecimal number, just in case the number happens to only
have digits between 0 and 9.

4 years ago[libgens] SRam.hpp: Switch back to bool for the internal SRAM flags.
David Korth [Wed, 2 Sep 2015 00:30:38 +0000 (20:30 -0400)] 
[libgens] SRam.hpp: Switch back to bool for the internal SRAM flags.

Updated the various inline functions to handle this such that MSVC
no longer complains about "performance" due to implicit bool to int

4 years ago[libgens] FastBlur.x86.inc.cpp: Improve pxCount handling in DoFastBlur_16_MMX().
David Korth [Wed, 2 Sep 2015 00:29:24 +0000 (20:29 -0400)] 
[libgens] FastBlur.x86.inc.cpp: Improve pxCount handling in DoFastBlur_16_MMX().

This matches the other functions.

TODO: Try using 'pavgb' in the SSE2 version and see if that improves
performance enough to make it worth using SSE2.

4 years ago[libgens] FastBlur.generic.inc.cpp: Split the generic Fast Blur into a separate file.
David Korth [Wed, 2 Sep 2015 00:28:02 +0000 (20:28 -0400)] 
[libgens] FastBlur.generic.inc.cpp: Split the generic Fast Blur into a separate file.

The functions are no longer templated; instead, there's separate
functions for 15/16-bit color and 32-bit color, and 1-FB/2-FB is
handled by using the DO_1FB and DO_2FB macros.

Changed the mask constants from macros to FastBlurPrivate static constants.

TODO: Optimize the generic versions by unrolling the loop and/or
doing multiple pixels at a time using e.g. 2 WORDs in a DWORD,
4 WORDs in a QWORD, and/or 2 DWORDs in a QWORD.

4 years ago[libgens] M68K_Write_Word_VDP(): Removed the odd address check for PSG.
David Korth [Wed, 2 Sep 2015 00:21:36 +0000 (20:21 -0400)] 
[libgens] M68K_Write_Word_VDP(): Removed the odd address check for PSG.

This is a word write, so the address's LSB can never be set.

Mask data with 0xFF. Even though the parameter is uint8_t, being expliit
is always a good thing.

TODO: Compare (uint8_t)data to (data & 0xFF) and see how various
compilers handle them.

4 years ago[libcompat/W32U] W32U_argv.c: Initialize some variables.
David Korth [Wed, 2 Sep 2015 00:17:17 +0000 (20:17 -0400)] 
[libcompat/W32U] W32U_argv.c: Initialize some variables.

MSVC complained about W32U_GetArgvU()'s argcW potentially being
uninitialized when compiling with /W4:

src\libcompat\w32u\w32u_argv.c(560) : warning C4701: potentially uninitialized local variable 'argcU' used

getArgvAtoW(): Initialize the argc, argv, and envp variables. MSVC didn't
complain about this because MSVC 2010 doesn't support targetting anything
older than Windows 2000, so ANSI support is disabled.

4 years ago[gens-sdl] SdlHandler: Fixed two mismatched memory deallocation calls.
David Korth [Wed, 2 Sep 2015 00:15:39 +0000 (20:15 -0400)] 
[gens-sdl] SdlHandler: Fixed two mismatched memory deallocation calls.

m_audioBuffer is a C++ object, so it needs to be deallocated using
delete, not free().

m_segBuffer was allocated using aligned_malloc(), so it needs to be
freed using aligned_free(). MSVC's debug CRT complained about this.

4 years agoUse DO_SPLIT_DEBUG() for gens-qt4, gens-sdl, and mcd_pcm.
David Korth [Wed, 2 Sep 2015 00:13:55 +0000 (20:13 -0400)] 
Use DO_SPLIT_DEBUG() for gens-qt4, gens-sdl, and mcd_pcm.

4 years ago[cmake] Win32ImageVersionLinkerFlags.cmake: CMake macro for setting the Win32 image...
David Korth [Wed, 2 Sep 2015 00:07:02 +0000 (20:07 -0400)] 
[cmake] Win32ImageVersionLinkerFlags.cmake: CMake macro for setting the Win32 image version.

Setting the TARGET_VERSION field causes GNU ld to append the version
number to the filename, e.g. "quack.exe-0.0" (or something like that).
This macro, which I originally wrote for sadx-mod-loader, fixes that.


4 years agoCMakeLists.txt: Re-enable the OpenGL check.
David Korth [Sun, 30 Aug 2015 23:31:43 +0000 (19:31 -0400)] 
CMakeLists.txt: Re-enable the OpenGL check.

This was temporarily disabled while testing the RVL build for
some unit tests.

This is a regression from commit 0fa75f211155e86264f8ba912f1449a44587169f.
([starscream] Use a proper cross-compile setup.)

4 years ago[doc] TODO.txt: Paused Effect and Fast Blur are implemented.
David Korth [Sun, 30 Aug 2015 23:30:53 +0000 (19:30 -0400)] 
[doc] TODO.txt: Paused Effect and Fast Blur are implemented.

TODO: Fast Blur shader.

4 years ago[libgens/tests] #include "libcompat/tests/gtest_main.inc.cpp" in most tests.
David Korth [Sun, 30 Aug 2015 22:55:18 +0000 (18:55 -0400)] 
[libgens/tests] #include "libcompat/tests/gtest_main.inc.cpp" in most tests.

The non-Google Test tests haven't been updated, nor has Z80Tests, since
it's completely broken right now and has been changed in the
switch-to-libz80 branch.

VdpSpriteMaskingTest, AudioWriteTest, and PsgRegisterTest all pass on Wii.

- VdpFIFOTesting won't compile due to undefined references. It won't
  run on Wii anyway, since it requires the 68000 core, and that's
  currently i386 only.
- The Effects tests won't run due to missing PNG files. This can be
  resolved by putting the PNG files on an SD card, but I'm not sure
  what the current directory is when using 'wiiload'.

4 years ago[libgens/tests] CMakeLists.txt: test_VdpPalette_DAC_generate runs on the build system...
David Korth [Sun, 30 Aug 2015 22:50:10 +0000 (18:50 -0400)] 
[libgens/tests] CMakeLists.txt: test_VdpPalette_DAC_generate runs on the build system, not the host system.

TODO: Port test_VdpPalette_DAC_generate and test_VdpPalette_DAC
to Google Test.

4 years ago[starscream] Add quotes to ${STAR_M68K_EXE} and ${STAR_S68K_EXE}.
David Korth [Sun, 30 Aug 2015 22:42:01 +0000 (18:42 -0400)] 
[starscream] Add quotes to ${STAR_M68K_EXE} and ${STAR_S68K_EXE}.

4 years ago[starscream] Set split debug information for star_m68k, star_s68k, and starscream.
David Korth [Sun, 30 Aug 2015 22:34:27 +0000 (18:34 -0400)] 
[starscream] Set split debug information for star_m68k, star_s68k, and starscream.

4 years ago[starscream] Use a proper cross-compile setup.
David Korth [Sun, 30 Aug 2015 22:28:44 +0000 (18:28 -0400)] 
[starscream] Use a proper cross-compile setup.

Reference: http://www.cmake.org/Wiki/CMake_Cross_Compiling

This requires a native build on the same machine.

CMakeLists.txt: Check for IMPORT_EXECUTABLES if cross-compiling.
Note that unlike the example, I'm using per-subdirectory import
files to make things easier to manage, though IMPORT_EXECUTABLES
is only checked in the root CMakeLists.txt file.

David Korth [Sun, 30 Aug 2015 22:08:23 +0000 (18:08 -0400)] 

4 years ago[cmake] CheckPopt.cmake: s/CMAKE_CURRENT_SOURCE_DIR/CMAKE_SOURCE_DIR/
David Korth [Sun, 30 Aug 2015 22:05:15 +0000 (18:05 -0400)] 

4 years ago[cmake] CheckOpenGL.cmake: Fixed a merge error.
David Korth [Sun, 30 Aug 2015 22:00:38 +0000 (18:00 -0400)] 
[cmake] CheckOpenGL.cmake: Fixed a merge error.

In the libgens-do-MMX-SSE2-audio-video branch, some stuff was moved around.
As a result, git decided to include two copies of this line:


CMake doesn't like it if you start an IF() and don't end it with an
ENDIF(), so this broke the build.

This is a regression from commit 4a6ac4e974db752715e5ed1508cc9c80a4eaa9df.
(Merge branch 'libgens-do-MMX-SSE2-audio-video')

4 years agoMerge branch 'libgens-do-MMX-SSE2-audio-video'
David Korth [Sun, 30 Aug 2015 21:58:54 +0000 (17:58 -0400)] 
Merge branch 'libgens-do-MMX-SSE2-audio-video'

In this branch, I optimized several components using MMX and/or SSE2:
- SoundMgr write functions (moved from the UI frontends)
- Array byteswap (C code was also improved.)
- Paused Effect
- Fast Blur effect

I also added unit tests for SoundMgr write functions, Paused Effect,
and Fast Blur effect.

cpuflags.c and byteswap.c were both moved from libgens to libcompat
in order to allow other components, e.g. libzomg, to use them.

Preliminary Wii support was added for some unit tests.
- cmake/toolchain/devkitPPC.RVL.toolchain: Toolchain file.
  TODO: Needs testing on Windows build platforms.
- gtest: Disable POSIX regular expressions and stream redirection.
  Work around broken color output and millisecond timing in libogc.
- cpuflags_ppc.c: Currently hard-coded to retrieve specific values
  on Wii, vWii (Wii U), and GameCube platforms.
- libcompat/gtest_main.inc.cpp: Google Test main() function.
  When compiling with libogc, this includes gtest_main.ogc.inc.cpp,
  which initializes libogc's console and waits for the user to press
  the HOME button to exit.
  - TODO: Add support for HW_DOL, maybe.

Other changes:
- libcompat/cpuflags.h now saves the vendor ID (e.g. "GenuineIntel") and
  the CPU brand string (P4 and later).
- Marked all extlib components as EXCLUDE_FROM_ALL and EXCLUDE_FROM_DEFAULT_BUILD.
- Only compile Timing_unix.cpp on Unix or Linux.
- Split debug symbols for all test suites.
- SPLIT_DEBUG_INFORMATION(): Use `strip` instead of `objcopy --strip-debug`.
  - `objcopy --strip-debug` leaves .symtab and .strtab.
- Screenshot: Made the 'rom' parameter optional.
  - Useful for debugging effects.
  - toFile(): Moved the 'filename' parameter to the beginning of the list.

- libzomg now uses libcompat's byteswap instead of its own.
- PngReader: Added a 'flags' parameter. Currently used to specify if
  the alpha channel should be inverted or not. (Should not be inverted
  for OpenGL display; should be inverted for unit tests that compare
  images to the internal framebuffer.)
- Metadata:
  - Save the CPU name from libcompat/cpuflags.h.
  - If CRC32 == 0, assume it isn't set.

4 years ago[libcompat/tests] gtest_main.ogc.inc.cpp: Currently HW_RVL only. libgens-do-MMX-SSE2-audio-video github/libgens-do-MMX-SSE2-audio-video
David Korth [Sun, 30 Aug 2015 21:50:28 +0000 (17:50 -0400)] 
[libcompat/tests] gtest_main.ogc.inc.cpp: Currently HW_RVL only.

4 years ago[libzomg] Metadata::InitProgramMetadata(): Clear strings if the variable is nullptr.
David Korth [Sun, 30 Aug 2015 21:37:24 +0000 (17:37 -0400)] 
[libzomg] Metadata::InitProgramMetadata(): Clear strings if the variable is nullptr.

This was done previously, but I changed it as an optimization. However,
this optimization breaks if the function is called multiple times with
different parameters as nullptr, since the strings won't be cleared.

This partially reverts commit 59433c7106a450a8c811df0992e98d58a32b60b1.
([libgens] config.libgens.h.in: Provide the CMake version information.)

4 years ago[libgens] FastBlur.x86.inc.cpp: FIXME: 2FB version is slower on Core 2 T7200 than...
David Korth [Sun, 30 Aug 2015 21:28:31 +0000 (17:28 -0400)] 
[libgens] FastBlur.x86.inc.cpp: FIXME: 2FB version is slower on Core 2 T7200 than the C implementation.

4 years ago[libgens] FastBlur: Disabled the SSE2 code for now.
David Korth [Sun, 30 Aug 2015 21:25:28 +0000 (17:25 -0400)] 
[libgens] FastBlur: Disabled the SSE2 code for now.

It's generally slower than MMX due to unaligned access restrictions.

[libgens/tests] FastBlurTest: Disabled SSE2 tests, since the SSE2
Fast Blur implementation was disabled.

4 years ago[libgens] FastBlur: Added an SSE2-optimized 32-bit Fast Blur.
David Korth [Sun, 30 Aug 2015 21:17:08 +0000 (17:17 -0400)] 
[libgens] FastBlur: Added an SSE2-optimized 32-bit Fast Blur.

1-FB seems slightly faster than MMX, but 2-FB seems slightly slower:

                 | SSE2 1-FB | SSE2 2-FB |
| gcc-5.2.0, -Og |    265 ms |    434 ms |
| gcc-5.2.0, -O2 |    255 ms |    398 ms |

TODO: Use movdqa+shift instead of movdqu?

4 years ago[libgens] PausedEffect.x86.inc.cpp: Check framebuffer alignment before loading the...
David Korth [Sun, 30 Aug 2015 21:09:21 +0000 (17:09 -0400)] 
[libgens] PausedEffect.x86.inc.cpp: Check framebuffer alignment before loading the constants into xmm registers.

4 years ago[libgens] FastBlur.x86.inc.cpp: Minor formatting changes.
David Korth [Sun, 30 Aug 2015 20:52:33 +0000 (16:52 -0400)] 
[libgens] FastBlur.x86.inc.cpp: Minor formatting changes.

TODO: Figure out how to blur 8px at a time in the 15/16-bit color
version. I tried the same method I used for 32-bit, and it resulted
in a gigantic mess (and the tests failed).

4 years ago[libgens] FastBlur.x86.inc.cpp: 15/16-bit should use psrlw, not psrld.
David Korth [Sun, 30 Aug 2015 20:47:26 +0000 (16:47 -0400)] 
[libgens] FastBlur.x86.inc.cpp: 15/16-bit should use psrlw, not psrld.

No effective difference due to the mask, but psrlw makes more sense,
since we're working in units of 16-bit pixels.

4 years ago[libgens] FastBlur.x86.inc.cpp: 32-bit color: Blur 4px per iteration.
David Korth [Sun, 30 Aug 2015 20:40:40 +0000 (16:40 -0400)] 
[libgens] FastBlur.x86.inc.cpp: 32-bit color: Blur 4px per iteration.

Benchmark results: (32-bit, MMX)

                 | 2px 1-FB | 2px 2-FB | 4px 1-FB | 4px 2-FB |
| gcc-5.2.0, -Og |   320 ms |   254 ms |   294 ms |   212 ms |
| gcc-5.2.0, -O2 |   321 ms |   221 ms |   294 ms |   199 ms |

4 years ago[libgens] FastBlur.x86.inc.cpp: Added commented-out clobber lists.
David Korth [Sun, 30 Aug 2015 20:32:46 +0000 (16:32 -0400)] 
[libgens] FastBlur.x86.inc.cpp: Added commented-out clobber lists.

4 years ago[libgens/tests] FastBlurTest_benchmark.cpp: Added benchmarks.
David Korth [Sun, 30 Aug 2015 20:25:44 +0000 (16:25 -0400)] 
[libgens/tests] FastBlurTest_benchmark.cpp: Added benchmarks.

Benchmark results:

C version:

                 | 15-bit 1FB | 15-bit 2FB | 16-bit 1FB | 16-bit 2FB | 32-bit 1FB | 32-bit 2FB |
| gcc-5.2.0, -Og |     301 ms |     266 ms |     303 ms |     268 ms |     353 ms |     269 ms |
| gcc-5.2.0, -O2 |     309 ms |     222 ms |     308 ms |     219 ms |     351 ms |     228 ms |

MMX version:

                 | 15-bit 1FB | 15-bit 2FB | 16-bit 1FB | 16-bit 2FB | 32-bit 1FB | 32-bit 2FB |
| gcc-5.2.0, -Og |     163 ms |     130 ms |     163 ms |     129 ms |     320 ms |     254 ms |
| gcc-5.2.0, -O2 |     162 ms |     112 ms |     162 ms |     111 ms |     321 ms |     221 ms |

4 years ago[libgens/tests] FastBlurTest: s/Fast Blur/Fast Blur effect/g
David Korth [Sun, 30 Aug 2015 20:24:31 +0000 (16:24 -0400)] 
[libgens/tests] FastBlurTest: s/Fast Blur/Fast Blur effect/g

4 years ago[libgens/tests] FastBlurTest: s/Paused Effect/Fast Blur/g
David Korth [Sun, 30 Aug 2015 20:17:20 +0000 (16:17 -0400)] 
[libgens/tests] FastBlurTest: s/Paused Effect/Fast Blur/g

4 years ago[libgens/tests] FastBlurTest: New test for the Fast Blur effect.
David Korth [Sun, 30 Aug 2015 20:04:20 +0000 (16:04 -0400)] 
[libgens/tests] FastBlurTest: New test for the Fast Blur effect.

TODO: Add benchmarks.

4 years ago[libgens/tests] EffectTest: Added an abstract function renderType().
David Korth [Sun, 30 Aug 2015 19:44:09 +0000 (15:44 -0400)] 
[libgens/tests] EffectTest: Added an abstract function renderType().

This is used by subclasses to determine if we should read e.g. "SW" or
"SW-int" files. In the case of PausedEffect, "SW" is the old software
renderer that used floating-point, and "SW-int" is the new one that
uses integers for higher performance with slightly less accuracy.

4 years ago[libgens/tests] PausedEffectTest.cpp: Removed some unused includes.
David Korth [Sun, 30 Aug 2015 19:39:02 +0000 (15:39 -0400)] 
[libgens/tests] PausedEffectTest.cpp: Removed some unused includes.

4 years ago[libgens/tests] EffectTest: Split the initialization code out of PausedEffectTest.
David Korth [Sun, 30 Aug 2015 19:37:09 +0000 (15:37 -0400)] 
[libgens/tests] EffectTest: Split the initialization code out of PausedEffectTest.

FastBlurTest will derive from EffectTest, so I won't have to create
a separate copy of the image loading code.

4 years ago[libgens/tests] Renamed PausedEffect.Normal.*.png to Effects.Normal.*.png .
David Korth [Sun, 30 Aug 2015 19:26:57 +0000 (15:26 -0400)] 
[libgens/tests] Renamed PausedEffect.Normal.*.png to Effects.Normal.*.png .

These images will be used as reference images for the Fast Blur test.

4 years ago[libgens] FastBlur: Added RESTRICT to the MMX functions.
David Korth [Sun, 30 Aug 2015 19:23:53 +0000 (15:23 -0400)] 
[libgens] FastBlur: Added RESTRICT to the MMX functions.

4 years ago[libgens] FastBlur.cpp: Split the MMX code into a separate file.
David Korth [Sun, 30 Aug 2015 19:21:30 +0000 (15:21 -0400)] 
[libgens] FastBlur.cpp: Split the MMX code into a separate file.

Consolidated the 1-FB and 2-FB functions into a single function using
DO_1FB and DO_2FB, similar to PausedEffect.

Use variable names for inline asm instead of indexes.

Moved the definition of MASK_DIV2_32_MMX into the 32-bit MMX function.

4 years ago[libgens/tests] Effects/CMakeLists.txt: Copy the reference images to the test directory.
David Korth [Sun, 30 Aug 2015 19:09:38 +0000 (15:09 -0400)] 
[libgens/tests] Effects/CMakeLists.txt: Copy the reference images to the test directory.

4 years ago[libgens] PausedEffect: Added an SSE2 version.
David Korth [Sun, 30 Aug 2015 19:01:42 +0000 (15:01 -0400)] 
[libgens] PausedEffect: Added an SSE2 version.

SSE2 adds the pshuf* opcodes (well, pshufw was added in SSE1),
which makes it easier to improve performance.

Benchmarks: (32-bit color)

                 | MMX 1-FB | MMX 2-FB | SSE2 1-FB | SSE2 2-FB |
| gcc-5.2.0, -Og |   602 ms |   515 ms |    443 ms |    370 ms |
| gcc-5.2.0, -O2 |   663 ms |   521 ms |    437 ms |    364 ms |

4 years ago[libgens] PausedEffect.x86.inc.cpp: s/px1/px2/
David Korth [Sun, 30 Aug 2015 18:43:19 +0000 (14:43 -0400)] 
[libgens] PausedEffect.x86.inc.cpp: s/px1/px2/

4 years ago[libgens] PausedEffect.x86.inc.cpp: Minor comment updates.
David Korth [Sun, 30 Aug 2015 18:42:29 +0000 (14:42 -0400)] 
[libgens] PausedEffect.x86.inc.cpp: Minor comment updates.

- Blue tint is applied.
- We're doing 2px at a time, not 1.

4 years ago[libgens] PausedEffect.x86.inc.cpp: Removed the braces from GRAY_32_MMX.
David Korth [Sun, 30 Aug 2015 18:37:24 +0000 (14:37 -0400)] 
[libgens] PausedEffect.x86.inc.cpp: Removed the braces from GRAY_32_MMX.

Not sure how this even compiled, since the variable isn't an array.

4 years ago[libgens] PausedEffect.cpp: Split the MMX code into an include file.
David Korth [Sun, 30 Aug 2015 18:35:37 +0000 (14:35 -0400)] 
[libgens] PausedEffect.cpp: Split the MMX code into an include file.

PausedEffect.x86.inc.cpp is compiled differently depending on whether
DO_1FB is defined or DO_2FB is defined. This allows us to easily build
both 1FB and 2FB versions without writing the functions twice.

TODO: Do that for the C++ version?

Benchmark results for 32-bit color, MMX-optimized:

                 |   1FB   |   2FB   |
| gcc-5.2.0, -Og |  604 ms |  516 ms |
| gcc-5.2.0, -O2 |  603 ms |  522 ms |

4 years ago[libgens] Moved the RESTRICT macro from PausedEffect.hpp to macros/common.h.
David Korth [Sun, 30 Aug 2015 18:23:58 +0000 (14:23 -0400)] 
[libgens] Moved the RESTRICT macro from PausedEffect.hpp to macros/common.h.

Added RESTRICT to DoPausedEffect_32_MMX().

4 years ago[libgens] PausedEffect.cpp: Use paddusb instead of paddusw.
David Korth [Sun, 30 Aug 2015 18:21:41 +0000 (14:21 -0400)] 
[libgens] PausedEffect.cpp: Use paddusb instead of paddusw.

The extra precision from paddusw can result in the blue value being
slightly omre than double the grayscale value (usually +1), which
results in test failures.

The 32-bit 2-FB MMX test now passes.

4 years ago[libgens] PausedEffect: Tint the image blue.
David Korth [Sun, 30 Aug 2015 18:07:57 +0000 (14:07 -0400)] 
[libgens] PausedEffect: Tint the image blue.

This doesn't change the benchmarks much for 32-bit MMX:

                 | No tint | With tint |
| gcc-5.2.0, -Og |  520 ms |    514 ms |
| gcc-5.2.0, -O2 |  527 ms |    538 ms |

FIXME: PausedEffectTest is still reporting errors when comparing the
32-bit MMX output to the reference image.

4 years ago[libgens] PausedEffect: Write 2 pixels per MMX loop.
David Korth [Sun, 30 Aug 2015 17:57:35 +0000 (13:57 -0400)] 
[libgens] PausedEffect: Write 2 pixels per MMX loop.

It actually seems to be slightly worse than the 1px loop, but I'm keeping
it anyway:

                 | 32-bit MMX (1x) | 32-bit MMX (2x) |
| gcc-5.2.0, -Og |          509 ms |          520 ms |
| gcc-5.2.0, -O2 |          503 ms |          527 ms |

- Optimize writing to outScreen.
- Tint it blue.

4 years ago[libgens] PausedEffect.cpp: Use integers instead of floats.
David Korth [Sun, 30 Aug 2015 17:38:31 +0000 (13:38 -0400)] 
[libgens] PausedEffect.cpp: Use integers instead of floats.

Similar to the MMX code, we're now using integer arithmetic in the
C code. This improves performance significantly at the cost of a
slight loss of precision.

PausedEffect.SW-int.*.png: New reference images for the integer version.

[libgens/tests] PausedEffectTest.cpp: Use the integer reference images.

Benchmark results when using 'float': (2,000 iterations)
[Retested due to the column repeat issue frrom earlier.]

                 | 15-bit 1FB | 15-bit 2FB | 16-bit 1FB | 16-bit 2FB | 32-bit 1FB | 32-bit 2FB |
| gcc-5.2.0, -Og |   3,109 ms |   3,056 ms |   3,149 ms |   3,114 ms |   3,132 ms |   3,020 ms |
| gcc-5.2.0, -O2 |   2,352 ms |   2,308 ms |   2,222 ms |   2,187 ms |   2,026 ms |   1,916 ms |

Benchmark results when using integers: (2,000 iterations)

                 | 15-bit 1FB | 15-bit 2FB | 16-bit 1FB | 16-bit 2FB | 32-bit 1FB | 32-bit 2FB |
| gcc-5.2.0, -Og |   1,529 ms |   1,512 ms |   1,789 ms |   1,576 ms |   1,355 ms |   1,215 ms |
| gcc-5.2.0, -O2 |   1,470 ms |   1,435 ms |   1,388 ms |   1,378 ms |   1,118 ms |   1,043 ms |

4 years ago[WTF] [libgens/tests] PausedEffectTest.cpp: Fixed a rather major error in copyToFb15...
David Korth [Sun, 30 Aug 2015 17:08:26 +0000 (13:08 -0400)] 
[WTF] [libgens/tests] PausedEffectTest.cpp: Fixed a rather major error in copyToFb15() and copyToFb16().

pData isn't incremented during the loop, so we ended up with framebuffers
that contained the first column repeated throughout the image.

pSrc *is* incremented, so use that for the data source instead of pData.

No changes to the test results for non-MMX.

4 years ago[libgens] Util/Screenshot.cpp: Made the 'rom' parameter optional.
David Korth [Sun, 30 Aug 2015 17:06:49 +0000 (13:06 -0400)] 
[libgens] Util/Screenshot.cpp: Made the 'rom' parameter optional.

LibGens::Screenshot is useful for debugging some things with Effects when
a ROM isn't loaded.

NOTE: While the parameter can be nullptr now, I'm not including a
'default' parameter, so it has to be specified explicitly.

Moved the filename parameter of toFile() to the beginning of the list.

4 years ago[libgens/tests] Effects/CMakeLists.txt: Forgot to add this file...
David Korth [Sun, 30 Aug 2015 17:05:53 +0000 (13:05 -0400)] 
[libgens/tests] Effects/CMakeLists.txt: Forgot to add this file...

4 years ago[libgens] PausedEffect: Initial 2-FB 32-bit MMX paused effect.
David Korth [Sun, 30 Aug 2015 16:38:07 +0000 (12:38 -0400)] 
[libgens] PausedEffect: Initial 2-FB 32-bit MMX paused effect.

Currently only does grayscale, and 1px per iteration, but the results
are quite good:

                 | 32-bit C | 32-bit MMX |
| gcc-5.2.0, -Og | 3,032 ms |     509 ms |
| gcc-5.2.0, -O2 | 1,900 ms |     503 ms |

Note that some of this could be attributed to the C version using floating-point,
whereas the MMX version uses integers. Using integers results in slightly less
precision, but that doesn't really matter for a simple effect.

4 years ago[libgens] PausedEffect.cpp: Removed a few more "MUST BE 336x240!" warnings.
David Korth [Sun, 30 Aug 2015 16:06:46 +0000 (12:06 -0400)] 
[libgens] PausedEffect.cpp: Removed a few more "MUST BE 336x240!" warnings.

4 years ago[libgens] PausedEffect.cpp: Removed the MD_Screen[] notice.
David Korth [Sun, 30 Aug 2015 16:03:28 +0000 (12:03 -0400)] 
[libgens] PausedEffect.cpp: Removed the MD_Screen[] notice.

The Paused Effect is applied to whatever framebuffer(s) are specified.

4 years ago[libgens] PausedEffect.cpp: Added a parameter 'pxCount' to the internal functions.
David Korth [Sun, 30 Aug 2015 16:02:17 +0000 (12:02 -0400)] 
[libgens] PausedEffect.cpp: Added a parameter 'pxCount' to the internal functions.

Previously, PausedEffect assumed a total framebuffer size of 336*240.
Now, it uses the actual framebuffer size. (It's still 336x240 right now,
but that might change later.)

4 years ago[libgens] PausedEffect: Moved the 1-FB function above the 2-FB function.
David Korth [Sun, 30 Aug 2015 15:58:01 +0000 (11:58 -0400)] 
[libgens] PausedEffect: Moved the 1-FB function above the 2-FB function.