diff --git a/.travis.yml b/.travis.yml
index 427f7f6..234cdfb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,46 @@
+sudo: required
+dist: xenial
 language: cpp
 compiler:
   - gcc
   - clang
+addons:
+  apt:
+    packages:
+    - git
 before_install:
-  - sudo apt-get update -qq
-  - sudo apt-get install -y git
   - git clone --depth=1 --branch=master git://github.com/mupen64plus/mupen64plus-core.git deps/mupen64plus-core
 env:
  - DUMP=0
  - DUMP=1
 script:
  - make -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 clean && LDFLAGS="-Wl,--no-add-needed -Wl,--no-undefined" OPTFLAGS="-O2" make CC="${CC}" CXX="${CXX}" -j$(nproc) -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 all
+
+# extra mxe build entries
+matrix:
+  include:
+    - env:
+      - MXE_CPU=i686
+      - PATH="/usr/lib/mxe/usr/bin/:$PATH"
+      before_install:
+      - curl -sSL "https://mirror.mxe.cc/repos/apt/client-conf/mxeapt.gpg" | sudo -E apt-key add -
+      - echo "deb https://mirror.mxe.cc/repos/apt xenial main" | sudo tee -a /etc/apt/sources.list
+      - sudo apt-get update -qq
+      - sudo apt-get -y --allow-unauthenticated install mxe-i686-w64-mingw32.shared-gcc
+      - git clone --depth=1 --branch=master git://github.com/mupen64plus/mupen64plus-core.git deps/mupen64plus-core
+      script:
+      - make UNAME=MINGW CROSS_COMPILE="${MXE_CPU}-w64-mingw32.shared-" CC="${MXE_CPU}-w64-mingw32.shared-gcc" CXX="${MXE_CPU}-w64-mingw32.shared-g++" HOST_CPU="${MXE_CPU}" -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/"  V=1  clean && 
+        make UNAME=MINGW CROSS_COMPILE="${MXE_CPU}-w64-mingw32.shared-" CC="${MXE_CPU}-w64-mingw32.shared-gcc" CXX="${MXE_CPU}-w64-mingw32.shared-g++" HOST_CPU="${MXE_CPU}" -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/"  V=1 -j$(nproc) all
+
+    - env:
+      - MXE_CPU=x86_64
+      - PATH="/usr/lib/mxe/usr/bin/:$PATH"
+      before_install:
+      - curl -sSL "https://mirror.mxe.cc/repos/apt/client-conf/mxeapt.gpg" | sudo -E apt-key add -
+      - echo "deb https://mirror.mxe.cc/repos/apt xenial main" | sudo tee -a /etc/apt/sources.list
+      - sudo apt-get update -qq
+      - sudo apt-get -y --allow-unauthenticated install mxe-x86-64-w64-mingw32.shared-gcc
+      - git clone --depth=1 --branch=master git://github.com/mupen64plus/mupen64plus-core.git deps/mupen64plus-core
+      script:
+      - make UNAME=MINGW CROSS_COMPILE="${MXE_CPU}-w64-mingw32.shared-" CC="${MXE_CPU}-w64-mingw32.shared-gcc" CXX="${MXE_CPU}-w64-mingw32.shared-g++" HOST_CPU="${MXE_CPU}" -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/"  V=1  clean && 
+        make UNAME=MINGW CROSS_COMPILE="${MXE_CPU}-w64-mingw32.shared-" CC="${MXE_CPU}-w64-mingw32.shared-gcc" CXX="${MXE_CPU}-w64-mingw32.shared-g++" HOST_CPU="${MXE_CPU}" -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/"  V=1 -j$(nproc) all
diff --git a/LICENSES b/LICENSES
index daea7fc..4319820 100644
--- a/LICENSES
+++ b/LICENSES
@@ -30,7 +30,7 @@ Mupen64Plus is based on GPL-licensed source code from Mupen64 v0.5, originally w
 		       Version 2, June 1991  
   
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
-                          675 Mass Ave, Cambridge, MA 02139, USA  
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies  
  of this license document, but changing it is not allowed.  
   
diff --git a/RELEASE b/RELEASE
index 0b19ad2..4ce99fa 100644
--- a/RELEASE
+++ b/RELEASE
@@ -1,6 +1,10 @@
 RSP High-Level Emulation plugin for Mupen64Plus
 -----------------------------------------------
 
+Mupen64Plus-rsp-hle v2.5.9 - February 10, 2019
+----------------------------------------------
+ - *** BETA RELEASE *** For Testing Only ***
+
 Mupen64Plus-rsp-hle v2.5 - April 26, 2015
 -------------------------------------------------
  - Game-specific fixes: Bottom of the 9th, IndianaJones, BattleForNaboo, Conkers Bad Fur Day
diff --git a/debian/changelog b/debian/changelog
index 77eb761..e825ba8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,6 @@
-mupen64plus-rsp-hle (2.5-6) UNRELEASED; urgency=medium
+mupen64plus-rsp-hle (2.5.9-1) UNRELEASED; urgency=medium
 
+  [ Sven Eckelmann ]
   * debian/control:
     - Upgraded to policy 4.5.0, no changes required
     - Allow build without (fake)root
@@ -12,7 +13,10 @@ mupen64plus-rsp-hle (2.5-6) UNRELEASED; urgency=medium
   * debian/rules:
     - Drop default flag --as-needed from linker flags
 
- -- Sven Eckelmann <sven@narfation.org>  Fri, 04 Oct 2019 13:23:00 +0200
+  [ Debian Janitor ]
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 03 Sep 2020 09:40:52 +0000
 
 mupen64plus-rsp-hle (2.5-5) unstable; urgency=medium
 
diff --git a/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj b/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj
index 426775c..3b6349f 100644
--- a/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj
+++ b/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj
@@ -1,122 +1,194 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}</ProjectGuid>
-    <RootNamespace>mupen64plusrsphle</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
-    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
-    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Windows</SubSystem>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Windows</SubSystem>
-      <OptimizeReferences>true</OptimizeReferences>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\src\alist.c" />
-    <ClCompile Include="..\..\src\alist_audio.c" />
-    <ClCompile Include="..\..\src\alist_naudio.c" />
-    <ClCompile Include="..\..\src\alist_nead.c" />
-    <ClCompile Include="..\..\src\audio.c" />
-    <ClCompile Include="..\..\src\cicx105.c" />
-    <ClCompile Include="..\..\src\hle.c" />
-    <ClCompile Include="..\..\src\jpeg.c" />
-    <ClCompile Include="..\..\src\memory.c" />
-    <ClCompile Include="..\..\src\mp3.c" />
-    <ClCompile Include="..\..\src\musyx.c" />
-    <ClCompile Include="..\..\src\plugin.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\..\src\alist.h" />
-    <ClInclude Include="..\..\src\arithmetics.h" />
-    <ClInclude Include="..\..\src\audio.h" />
-    <ClInclude Include="..\..\src\common.h" />
-    <ClInclude Include="..\..\src\hle.h" />
-    <ClInclude Include="..\..\src\hle_external.h" />
-    <ClInclude Include="..\..\src\hle_internal.h" />
-    <ClInclude Include="..\..\src\memory.h" />
-    <ClInclude Include="..\..\src\ucodes.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}</ProjectGuid>
+    <RootNamespace>mupen64plusrsphle</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120_xp</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\alist.c" />
+    <ClCompile Include="..\..\src\alist_audio.c" />
+    <ClCompile Include="..\..\src\alist_naudio.c" />
+    <ClCompile Include="..\..\src\alist_nead.c" />
+    <ClCompile Include="..\..\src\audio.c" />
+    <ClCompile Include="..\..\src\cicx105.c" />
+    <ClCompile Include="..\..\src\hle.c" />
+    <ClCompile Include="..\..\src\jpeg.c" />
+    <ClCompile Include="..\..\src\memory.c" />
+    <ClCompile Include="..\..\src\mp3.c" />
+    <ClCompile Include="..\..\src\musyx.c" />
+    <ClCompile Include="..\..\src\osal_dynamiclib_win32.c" />
+    <ClCompile Include="..\..\src\plugin.c" />
+    <ClCompile Include="..\..\src\re2.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\alist.h" />
+    <ClInclude Include="..\..\src\arithmetics.h" />
+    <ClInclude Include="..\..\src\audio.h" />
+    <ClInclude Include="..\..\src\common.h" />
+    <ClInclude Include="..\..\src\hle.h" />
+    <ClInclude Include="..\..\src\hle_external.h" />
+    <ClInclude Include="..\..\src\hle_internal.h" />
+    <ClInclude Include="..\..\src\memory.h" />
+    <ClInclude Include="..\..\src\osal_dynamiclib.h" />
+    <ClInclude Include="..\..\src\ucodes.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/projects/unix/Makefile b/projects/unix/Makefile
index a0d9b4e..57e0580 100755
--- a/projects/unix/Makefile
+++ b/projects/unix/Makefile
@@ -1,6 +1,6 @@
 #/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 # *   mupen64plus-rsp-hle - Makefile                                        *
-# *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+# *   Mupen64Plus homepage: https://mupen64plus.org/                        *
 # *   Copyright (C) 2008-2009 Richard Goedeken                              *
 # *   Copyright (C) 2007-2008 DarkJeztr Tillin9                             *
 # *                                                                         *
@@ -53,7 +53,6 @@ ifeq ("$(UNAME)","OpenBSD")
   OS = FREEBSD
   SO_EXTENSION = so
   SHARED = -shared
-  $(warning OS type "$(UNAME)" not officially supported.')
 endif
 ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","")
   OS = LINUX
@@ -67,7 +66,7 @@ ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW")
   PIC = 0
 endif
 ifeq ("$(OS)","NONE")
-  $(error OS type "$(UNAME)" not supported.  Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
+  $(error OS type "$(UNAME)" not supported.  Please file bug report at 'https://github.com/mupen64plus/mupen64plus-core/issues')
 endif
 
 # detect system architecture
@@ -117,8 +116,15 @@ ifneq ("$(filter mips,$(HOST_CPU))","")
   PIC ?= 1
   $(warning Architecture "$(HOST_CPU)" not officially supported.')
 endif
+ifneq ("$(filter aarch64,$(HOST_CPU))","")
+    CPU := AARCH
+    ARCH_DETECTED := 64BITS
+    PIC ?= 1
+    NEW_DYNAREC := 1
+    NO_ASM := 1
+endif
 ifeq ("$(CPU)","NONE")
-  $(error CPU type "$(HOST_CPU)" not supported.  Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
+  $(error CPU type "$(HOST_CPU)" not supported.  Please file bug report at 'https://github.com/mupen64plus/mupen64plus-core/issues')
 endif
 
 # base CFLAGS, LDLIBS, and LDFLAGS
@@ -152,11 +158,10 @@ endif
 ifeq ($(OS), LINUX)
   # only export api symbols
   LDFLAGS += -Wl,-version-script,$(SRCDIR)/rsp_api_export.ver
+  LDLIBS += -ldl
 endif
 ifeq ($(OS), OSX)
-  #xcode-select has been around since XCode 3.0, i.e. OS X 10.5
-  OSX_SDK_ROOT = $(shell xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs
-  OSX_SDK_PATH = $(OSX_SDK_ROOT)/$(shell ls $(OSX_SDK_ROOT) | tail -1)
+  OSX_SDK_PATH = $(shell xcrun --sdk macosx --show-sdk-path)
 
   ifeq ($(CPU), X86)
     ifeq ($(ARCH_DETECTED), 64BITS)
@@ -211,6 +216,7 @@ ifeq ($(DEBUG),1)
   CFLAGS += -g
   INSTALL_STRIP_FLAG ?= 
 else
+  CFLAGS += -DNDEBUG
   ifneq ($(OS),OSX)
     INSTALL_STRIP_FLAG ?= -s
   endif
@@ -249,8 +255,17 @@ SOURCE = \
 	$(SRCDIR)/memory.c \
 	$(SRCDIR)/mp3.c \
 	$(SRCDIR)/musyx.c \
+	$(SRCDIR)/re2.c \
 	$(SRCDIR)/plugin.c
 
+ifeq ($(OS), MINGW)
+SOURCE += \
+	$(SRCDIR)/osal_dynamiclib_win32.c
+else
+SOURCE += \
+	$(SRCDIR)/osal_dynamiclib_unix.c
+endif
+
 # generate a list of object files build, make a temporary directory for them
 OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(filter %.c, $(SOURCE)))
 OBJDIRS = $(dir $(OBJECTS))
diff --git a/src/alist.c b/src/alist.c
index f6c87f0..ef3adc2 100644
--- a/src/alist.c
+++ b/src/alist.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - alist.c                                         *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -50,17 +50,17 @@ static void swap(int16_t **a, int16_t **b)
 
 static int16_t* sample(struct hle_t* hle, unsigned pos)
 {
-    return (int16_t*)hle->alist_buffer + (pos ^ S);
+    return (int16_t*)hle->alist_buffer + ((pos ^ S) & 0xfff);
 }
 
 static uint8_t* alist_u8(struct hle_t* hle, uint16_t dmem)
 {
-    return u8(hle->alist_buffer, dmem);
+    return (uint8_t*)(hle->alist_buffer + ((dmem ^ S8) & 0xfff));
 }
 
 static int16_t* alist_s16(struct hle_t* hle, uint16_t dmem)
 {
-    return (int16_t*)u16(hle->alist_buffer, dmem);
+    return (int16_t*)(hle->alist_buffer + ((dmem ^ S16) & 0xfff));
 }
 
 
@@ -282,6 +282,7 @@ void alist_envmix_exp(
     int x, y;
     short save_buffer[40];
 
+    memcpy((uint8_t *)save_buffer, (hle->dram + address), sizeof(save_buffer));
     if (init) {
         ramps[0].value  = (vol[0] << 16);
         ramps[1].value  = (vol[1] << 16);
@@ -292,7 +293,6 @@ void alist_envmix_exp(
         exp_seq[0]      = (vol[0] * rate[0]);
         exp_seq[1]      = (vol[1] * rate[1]);
     } else {
-        memcpy((uint8_t *)save_buffer, (hle->dram + address), 80);
         wet             = *(int16_t *)(save_buffer +  0); /* 0-1 */
         dry             = *(int16_t *)(save_buffer +  2); /* 2-3 */
         ramps[0].target = *(int32_t *)(save_buffer +  4); /* 4-5 */
@@ -354,7 +354,7 @@ void alist_envmix_exp(
     *(int32_t *)(save_buffer + 14) = exp_seq[1];        /* 14-15 */
     *(int32_t *)(save_buffer + 16) = (int32_t)ramps[0].value;    /* 12-13 */
     *(int32_t *)(save_buffer + 18) = (int32_t)ramps[1].value;    /* 14-15 */
-    memcpy(hle->dram + address, (uint8_t *)save_buffer, 80);
+    memcpy(hle->dram + address, (uint8_t *)save_buffer, sizeof(save_buffer));
 }
 
 void alist_envmix_ge(
@@ -382,6 +382,7 @@ void alist_envmix_ge(
     struct ramp_t ramps[2];
     short save_buffer[40];
 
+    memcpy((uint8_t *)save_buffer, (hle->dram + address), 80);
     if (init) {
         ramps[0].value  = (vol[0] << 16);
         ramps[1].value  = (vol[1] << 16);
@@ -390,7 +391,6 @@ void alist_envmix_ge(
         ramps[0].step   = rate[0] / 8;
         ramps[1].step   = rate[1] / 8;
     } else {
-        memcpy((uint8_t *)save_buffer, (hle->dram + address), 80);
         wet             = *(int16_t *)(save_buffer +  0);   /* 0-1 */
         dry             = *(int16_t *)(save_buffer +  2);   /* 2-3 */
         ramps[0].target = *(int32_t *)(save_buffer +  4);   /* 4-5 */
@@ -458,6 +458,7 @@ void alist_envmix_lin(
     int16_t* const wl = (int16_t*)(hle->alist_buffer + dmem_wl);
     int16_t* const wr = (int16_t*)(hle->alist_buffer + dmem_wr);
 
+    memcpy((uint8_t *)save_buffer, hle->dram + address, 80);
     if (init) {
         ramps[0].step   = rate[0] / 8;
         ramps[0].value  = (vol[0] << 16);
@@ -467,7 +468,6 @@ void alist_envmix_lin(
         ramps[1].target = (target[1] << 16);
     }
     else {
-        memcpy((uint8_t *)save_buffer, hle->dram + address, 80);
         wet             = *(int16_t *)(save_buffer +  0); /* 0-1 */
         dry             = *(int16_t *)(save_buffer +  2); /* 2-3 */
         ramps[0].target = *(int16_t *)(save_buffer +  4) << 16; /* 4-5 */
@@ -666,11 +666,11 @@ void alist_resample(
     while (count != 0) {
         const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8);
 
-        *sample(hle, opos++) = clamp_s16(
-                ((*sample(hle, ipos    ) * lut[0]) >> 15) +
-                ((*sample(hle, ipos + 1) * lut[1]) >> 15) +
-                ((*sample(hle, ipos + 2) * lut[2]) >> 15) +
-                ((*sample(hle, ipos + 3) * lut[3]) >> 15));
+        *sample(hle, opos++) = clamp_s16( (
+            (*sample(hle, ipos    ) * lut[0]) +
+            (*sample(hle, ipos + 1) * lut[1]) +
+            (*sample(hle, ipos + 2) * lut[2]) +
+            (*sample(hle, ipos + 3) * lut[3]) ) >> 15);
 
         pitch_accu += pitch;
         ipos += (pitch_accu >> 16);
@@ -961,7 +961,7 @@ void alist_polef(
         count -= 16;
     } while (count != 0);
 
-    dram_store_u16(hle, (uint16_t*)(dst - 4), address, 4);
+    dram_store_u32(hle, (uint32_t*)(dst - 4), address, 2);
 }
 
 void alist_iirf(
diff --git a/src/alist.h b/src/alist.h
index 6e61043..398cdb8 100644
--- a/src/alist.h
+++ b/src/alist.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - alist.h                                         *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/alist_audio.c b/src/alist_audio.c
index ac54714..0d2dcea 100644
--- a/src/alist_audio.c
+++ b/src/alist_audio.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - alist_audio.c                                   *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -57,7 +57,7 @@ static void SPNOOP(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUS
 static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
 {
     uint16_t dmem  = w1 + DMEM_BASE;
-    uint16_t count = w2;
+    uint16_t count = w2 & 0xfff;
 
     if (count == 0)
         return;
@@ -111,7 +111,7 @@ static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
 
     alist_resample(
             hle,
-            flags & 0x1,
+            flags & A_INIT,
             flags & 0x2,
             hle->alist_audio.out,
             hle->alist_audio.in,
@@ -152,8 +152,8 @@ static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
 
     alist_adpcm(
             hle,
-            flags & 0x1,
-            flags & 0x2,
+            flags & A_INIT,
+            flags & A_LOOP,
             false,          /* unsupported in this ucode */
             hle->alist_audio.out,
             hle->alist_audio.in,
@@ -278,6 +278,7 @@ void alist_process_audio(struct hle_t* hle)
 
     clear_segments(hle);
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_audio_ge(struct hle_t* hle)
@@ -291,6 +292,7 @@ void alist_process_audio_ge(struct hle_t* hle)
 
     clear_segments(hle);
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_audio_bc(struct hle_t* hle)
@@ -304,4 +306,5 @@ void alist_process_audio_bc(struct hle_t* hle)
 
     clear_segments(hle);
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
diff --git a/src/alist_naudio.c b/src/alist_naudio.c
index 4cff9f7..bb53dd7 100644
--- a/src/alist_naudio.c
+++ b/src/alist_naudio.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - alist_naudio.c                                  *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -108,18 +108,18 @@ static void SETVOL(struct hle_t* hle, uint32_t w1, uint32_t w2)
 {
     uint8_t flags = (w1 >> 16);
 
-    if (flags & 0x4) {
-        if (flags & 0x2) {
+    if (flags & A_VOL) {
+        if (flags & A_LEFT) {
             hle->alist_naudio.vol[0] = w1;
             hle->alist_naudio.dry    = (w2 >> 16);
             hle->alist_naudio.wet    = w2;
         }
-        else {
+        else { /* A_RIGHT */
             hle->alist_naudio.target[1] = w1;
             hle->alist_naudio.rate[1]   = w2;
         }
     }
-    else {
+    else { /* A_RATE */
         hle->alist_naudio.target[0] = w1;
         hle->alist_naudio.rate[0]   = w2;
     }
@@ -134,7 +134,7 @@ static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
 
     alist_envmix_lin(
             hle,
-            flags & 0x1,
+            flags & A_INIT,
             NAUDIO_DRY_LEFT,
             NAUDIO_DRY_RIGHT,
             NAUDIO_WET_LEFT,
@@ -152,7 +152,7 @@ static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
 static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
 {
     uint16_t dmem  = w1 + NAUDIO_MAIN;
-    uint16_t count = w2;
+    uint16_t count = w2 & 0xfff;
 
     alist_clear(hle, dmem, count);
 }
@@ -216,8 +216,8 @@ static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
 
     alist_adpcm(
             hle,
-            flags & 0x1,
-            flags & 0x2,
+            flags & A_INIT,
+            flags & A_LOOP,
             false,          /* unsuported by this ucode */
             dmemo,
             dmemi,
@@ -237,7 +237,7 @@ static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
 
     alist_resample(
             hle,
-            flags & 0x1,
+            flags & A_INIT,
             false,          /* TODO: check which ABI supports it */
             dmemo,
             dmemi,
@@ -274,6 +274,7 @@ void alist_process_naudio(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_naudio_bk(struct hle_t* hle)
@@ -287,6 +288,7 @@ void alist_process_naudio_bk(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_naudio_dk(struct hle_t* hle)
@@ -300,6 +302,7 @@ void alist_process_naudio_dk(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_naudio_mp3(struct hle_t* hle)
@@ -312,6 +315,7 @@ void alist_process_naudio_mp3(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_naudio_cbfd(struct hle_t* hle)
@@ -325,4 +329,5 @@ void alist_process_naudio_cbfd(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x10);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
diff --git a/src/alist_nead.c b/src/alist_nead.c
index b8ce3c9..11dcb80 100644
--- a/src/alist_nead.c
+++ b/src/alist_nead.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - alist_nead.c                                    *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -92,7 +92,7 @@ static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
 static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
 {
     uint16_t dmem  = w1;
-    uint16_t count = w2;
+    uint16_t count = w2 & 0xfff;
 
     if (count == 0)
         return;
@@ -300,7 +300,7 @@ static void ADDMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
 static void HILOGAIN(struct hle_t* hle, uint32_t w1, uint32_t w2)
 {
     int8_t   gain  = (w1 >> 16); /* Q4.4 signed */
-    uint16_t count = w1;
+    uint16_t count = w1 & 0xfff;
     uint16_t dmem  = (w2 >> 16);
 
     alist_multQ44(hle, dmem, count, gain);
@@ -372,6 +372,7 @@ void alist_process_nead_mk(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x20);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_sf(struct hle_t* hle)
@@ -388,6 +389,7 @@ void alist_process_nead_sf(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x20);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_sfj(struct hle_t* hle)
@@ -404,6 +406,7 @@ void alist_process_nead_sfj(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x20);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_fz(struct hle_t* hle)
@@ -420,6 +423,7 @@ void alist_process_nead_fz(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x20);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_wrjb(struct hle_t* hle)
@@ -436,6 +440,7 @@ void alist_process_nead_wrjb(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x20);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_ys(struct hle_t* hle)
@@ -450,6 +455,7 @@ void alist_process_nead_ys(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_1080(struct hle_t* hle)
@@ -464,6 +470,7 @@ void alist_process_nead_1080(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_oot(struct hle_t* hle)
@@ -478,6 +485,7 @@ void alist_process_nead_oot(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_mm(struct hle_t* hle)
@@ -492,6 +500,7 @@ void alist_process_nead_mm(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_mmb(struct hle_t* hle)
@@ -506,6 +515,7 @@ void alist_process_nead_mmb(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 void alist_process_nead_ac(struct hle_t* hle)
@@ -520,4 +530,27 @@ void alist_process_nead_ac(struct hle_t* hle)
     };
 
     alist_process(hle, ABI, 0x18);
+    rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_mats(struct hle_t* hle)
+{
+    /* FIXME: implement proper ucode
+     * Forward the task if possible,
+     * otherwise better to have no sound than garbage sound
+     */
+    if (HleForwardTask(hle->user_defined) != 0) {
+        rsp_break(hle, SP_STATUS_TASKDONE);
+    }
+}
+
+void alist_process_nead_efz(struct hle_t* hle)
+{
+    /* FIXME: implement proper ucode
+     * Forward the task if possible,
+     * otherwise use FZero ucode which should be very similar
+     */
+    if (HleForwardTask(hle->user_defined) != 0) {
+        alist_process_nead_fz(hle);
+    }
 }
diff --git a/src/arithmetics.h b/src/arithmetics.h
index 529293d..2250b24 100644
--- a/src/arithmetics.h
+++ b/src/arithmetics.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - arithmetics.h                                   *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/audio.c b/src/audio.c
index 9a14ad5..fac2a10 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - audio.c                                         *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/audio.h b/src/audio.h
index 8942a78..21c7a09 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - audio.h                                         *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/cicx105.c b/src/cicx105.c
index 7ed8ae2..bda5eca 100644
--- a/src/cicx105.c
+++ b/src/cicx105.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - cicx105.c                                       *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2012 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -50,5 +50,7 @@ void cicx105_ucode(struct hle_t* hle)
         src += 0x8;
 
     }
+
+    rsp_break(hle, 0);
 }
 
diff --git a/src/common.h b/src/common.h
index 48a9229..cd5dfa6 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - common.h                                        *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/hle.c b/src/hle.c
index ea0e1b7..ddc0404 100644
--- a/src/hle.c
+++ b/src/hle.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - hle.c                                           *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2012 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -35,28 +35,20 @@
 
 #define min(a,b) (((a) < (b)) ? (a) : (b))
 
-/* some rsp status flags */
-#define SP_STATUS_HALT             0x1
-#define SP_STATUS_BROKE            0x2
-#define SP_STATUS_INTR_ON_BREAK    0x40
-#define SP_STATUS_TASKDONE         0x200
-
 /* some rdp status flags */
 #define DP_STATUS_FREEZE            0x2
 
-/* some mips interface interrupt flags */
-#define MI_INTR_SP                  0x1
 
 
 /* helper functions prototypes */
 static unsigned int sum_bytes(const unsigned char *bytes, unsigned int size);
 static bool is_task(struct hle_t* hle);
-static void rsp_break(struct hle_t* hle, unsigned int setbits);
-static void forward_gfx_task(struct hle_t* hle);
+static void send_dlist_to_gfx_plugin(struct hle_t* hle);
 static bool try_fast_audio_dispatching(struct hle_t* hle);
 static bool try_fast_task_dispatching(struct hle_t* hle);
 static void normal_task_dispatching(struct hle_t* hle);
 static void non_task_dispatching(struct hle_t* hle);
+static bool try_re2_task_dispatching(struct hle_t* hle);
 
 #ifdef ENABLE_TASK_DUMP
 static void dump_binary(struct hle_t* hle, const char *const filename,
@@ -66,9 +58,6 @@ static void dump_unknown_task(struct hle_t* hle, unsigned int sum);
 static void dump_unknown_non_task(struct hle_t* hle, unsigned int sum);
 #endif
 
-/* local variables */
-static const bool FORWARD_AUDIO = false, FORWARD_GFX = true;
-
 /* Global functions */
 void hle_init(struct hle_t* hle,
     unsigned char* dram,
@@ -123,10 +112,8 @@ void hle_execute(struct hle_t* hle)
     if (is_task(hle)) {
         if (!try_fast_task_dispatching(hle))
             normal_task_dispatching(hle);
-        rsp_break(hle, SP_STATUS_TASKDONE);
     } else {
         non_task_dispatching(hle);
-        rsp_break(hle, 0);
     }
 }
 
@@ -157,7 +144,7 @@ static bool is_task(struct hle_t* hle)
     return (*dmem_u32(hle, TASK_UCODE_BOOT_SIZE) <= 0x1000);
 }
 
-static void rsp_break(struct hle_t* hle, unsigned int setbits)
+void rsp_break(struct hle_t* hle, unsigned int setbits)
 {
     *hle->sp_status |= setbits | SP_STATUS_BROKE | SP_STATUS_HALT;
 
@@ -167,9 +154,27 @@ static void rsp_break(struct hle_t* hle, unsigned int setbits)
     }
 }
 
-static void forward_gfx_task(struct hle_t* hle)
+static void send_alist_to_audio_plugin(struct hle_t* hle)
+{
+    HleProcessAlistList(hle->user_defined);
+    rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+static void send_dlist_to_gfx_plugin(struct hle_t* hle)
 {
+    /* Since GFX_INFO version 2, these bits are set before calling the ProcessDlistList function.
+     * And the GFX plugin is responsible to unset them if needed.
+     * For GFX_INFO version < 2, the GFX plugin didn't have access to sp_status so
+     * it doesn't matter if we set these bits before calling ProcessDlistList function.
+     */
+    *hle->sp_status |= SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT;
+
     HleProcessDlistList(hle->user_defined);
+
+    if ((*hle->sp_status & SP_STATUS_INTR_ON_BREAK) && (*hle->sp_status & (SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT))) {
+        *hle->mi_intr |= MI_INTR_SP;
+        HleCheckInterrupts(hle->user_defined);
+    }
 }
 
 static bool try_fast_audio_dispatching(struct hle_t* hle)
@@ -220,7 +225,10 @@ static bool try_fast_audio_dispatching(struct hle_t* hle)
                 alist_process_nead_ac(hle); return true;
             case 0x00010010: /* MusyX v2 (IndianaJones, BattleForNaboo) */
                 musyx_v2_task(hle); return true;
-
+            case 0x1f701238: /* Mario Artist Talent Studio */
+                alist_process_nead_mats(hle); return true;
+            case 0x1f4c1230: /* FZeroX Expansion */
+                alist_process_nead_efz(hle); return true;
             default:
                 HleWarnMessage(hle->user_defined, "ABI2 identification regression: v=%08x", v);
             }
@@ -258,15 +266,20 @@ static bool try_fast_task_dispatching(struct hle_t* hle)
     /* identify task ucode by its type */
     switch (*dmem_u32(hle, TASK_TYPE)) {
     case 1:
-        if (FORWARD_GFX) {
-            forward_gfx_task(hle);
+        /* Resident evil 2 */
+        if (*dmem_u32(hle, TASK_DATA_PTR) == 0) {
+            return try_re2_task_dispatching(hle);
+        }
+
+        if (hle->hle_gfx) {
+            send_dlist_to_gfx_plugin(hle);
             return true;
         }
         break;
 
     case 2:
-        if (FORWARD_AUDIO) {
-            HleProcessAlistList(hle->user_defined);
+        if (hle->hle_aud) {
+            send_alist_to_audio_plugin(hle);
             return true;
         } else if (try_fast_audio_dispatching(hle))
             return true;
@@ -274,7 +287,7 @@ static bool try_fast_task_dispatching(struct hle_t* hle)
 
     case 7:
         HleShowCFB(hle->user_defined);
-        return true;
+        break;
     }
 
     return false;
@@ -289,12 +302,13 @@ static void normal_task_dispatching(struct hle_t* hle)
     /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */
     case 0x278:
         /* Nothing to emulate */
+        rsp_break(hle, SP_STATUS_TASKDONE);
         return;
 
     /* GFX: Twintris [misleading task->type == 0] */
     case 0x212ee:
-        if (FORWARD_GFX) {
-            forward_gfx_task(hle);
+        if (hle->hle_gfx) {
+            send_dlist_to_gfx_plugin(hle);
             return;
         }
         break;
@@ -316,10 +330,18 @@ static void normal_task_dispatching(struct hle_t* hle)
         return;
     }
 
-    HleWarnMessage(hle->user_defined, "unknown OSTask: sum: %x PC:%x", sum, *hle->sp_pc);
+    /* Forward task to RSP Fallback.
+     * If task is not forwarded, use the regular "unknown task" path */
+    if (HleForwardTask(hle->user_defined) != 0) {
+
+        /* Send task_done signal for unknown ucodes to allow further processings */
+        rsp_break(hle, SP_STATUS_TASKDONE);
+
+        HleWarnMessage(hle->user_defined, "unknown OSTask: sum: %x PC:%x", sum, *hle->sp_pc);
 #ifdef ENABLE_TASK_DUMP
-    dump_unknown_task(hle, sum);
+        dump_unknown_task(hle, sum);
 #endif
+    }
 }
 
 static void non_task_dispatching(struct hle_t* hle)
@@ -333,12 +355,40 @@ static void non_task_dispatching(struct hle_t* hle)
         return;
     }
 
-    HleWarnMessage(hle->user_defined, "unknown RSP code: sum: %x PC:%x", sum, *hle->sp_pc);
+    /* Forward task to RSP Fallback.
+     * If task is not forwarded, use the regular "unknown ucode" path */
+    if (HleForwardTask(hle->user_defined) != 0) {
+
+        HleWarnMessage(hle->user_defined, "unknown RSP code: sum: %x PC:%x", sum, *hle->sp_pc);
 #ifdef ENABLE_TASK_DUMP
-    dump_unknown_non_task(hle, sum);
+        dump_unknown_non_task(hle, sum);
 #endif
+    }
 }
 
+/* Resident evil 2 */
+static bool try_re2_task_dispatching(struct hle_t* hle)
+{
+    const unsigned int sum =
+        sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), 256);
+
+    switch (sum) {
+
+    case 0x450f:
+        resize_bilinear_task(hle);
+        return true;
+
+    case 0x3b44:
+        decode_video_frame_task(hle);
+        return true;
+
+    case 0x3d84:
+        fill_video_double_buffer_task(hle);
+        return true;
+    }
+
+    return false;
+}
 
 #ifdef ENABLE_TASK_DUMP
 static void dump_unknown_task(struct hle_t* hle, unsigned int sum)
diff --git a/src/hle.h b/src/hle.h
index 3c705a9..a420b75 100644
--- a/src/hle.h
+++ b/src/hle.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - hle.h                                           *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/hle_external.h b/src/hle_external.h
index 2f35a3c..5dcbf2e 100644
--- a/src/hle_external.h
+++ b/src/hle_external.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - hle_external.h                                  *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -25,6 +25,7 @@
 /* users of the hle core are expected to define these functions */
 
 void HleVerboseMessage(void* user_defined, const char *message, ...);
+void HleInfoMessage(void* user_defined, const char *message, ...);
 void HleErrorMessage(void* user_defined, const char *message, ...);
 void HleWarnMessage(void* user_defined, const char *message, ...);
 
@@ -33,6 +34,7 @@ void HleProcessDlistList(void* user_defined);
 void HleProcessAlistList(void* user_defined);
 void HleProcessRdpList(void* user_defined);
 void HleShowCFB(void* user_defined);
+int HleForwardTask(void* user_defined);
 
 #endif
 
diff --git a/src/hle_internal.h b/src/hle_internal.h
index 352d956..ad1708b 100644
--- a/src/hle_internal.h
+++ b/src/hle_internal.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - hle_internal.h                                  *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -57,6 +57,8 @@ struct hle_t
     /* for user convenience, this will be passed to "external" functions */
     void* user_defined;
 
+    int hle_gfx;
+    int hle_aud;
 
     /* alist.c */
     uint8_t alist_buffer[0x1000];
@@ -74,5 +76,16 @@ struct hle_t
     uint8_t  mp3_buffer[0x1000];
 };
 
+/* some mips interface interrupt flags */
+#define MI_INTR_SP                  0x1
+
+/* some rsp status flags */
+#define SP_STATUS_HALT             0x1
+#define SP_STATUS_BROKE            0x2
+#define SP_STATUS_INTR_ON_BREAK    0x40
+#define SP_STATUS_TASKDONE         0x200
+
+void rsp_break(struct hle_t* hle, unsigned int setbits);
+
 #endif
 
diff --git a/src/jpeg.c b/src/jpeg.c
index 4365c05..ff424c4 100644
--- a/src/jpeg.c
+++ b/src/jpeg.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - jpeg.c                                          *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2012 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -141,6 +141,7 @@ static const float IDCT_K[10] = {
 void jpeg_decode_PS0(struct hle_t* hle)
 {
     jpeg_decode_std(hle, "PS0", RescaleYSubBlock, RescaleUVSubBlock, EmitYUVTileLine);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 /***************************************************************************
@@ -150,6 +151,7 @@ void jpeg_decode_PS0(struct hle_t* hle)
 void jpeg_decode_PS(struct hle_t* hle)
 {
     jpeg_decode_std(hle, "PS", NULL, NULL, EmitRGBATileLine);
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 /***************************************************************************
@@ -190,6 +192,7 @@ void jpeg_decode_OB(struct hle_t* hle)
 
         address += (2 * 6 * SUBBLOCK_SIZE);
     }
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 
@@ -472,7 +475,7 @@ static void ReorderSubBlock(int16_t *dst, const int16_t *src, const unsigned int
     unsigned int i;
 
     /* source and destination sublocks cannot overlap */
-    assert(abs(dst - src) > SUBBLOCK_SIZE);
+    assert(labs(dst - src) > SUBBLOCK_SIZE);
 
     for (i = 0; i < SUBBLOCK_SIZE; ++i)
         dst[i] = src[table[i]];
diff --git a/src/memory.c b/src/memory.c
index ca06d6c..7d5066b 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - memory.c                                        *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/memory.h b/src/memory.h
index 8acc8c3..9c85104 100644
--- a/src/memory.h
+++ b/src/memory.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - memory.h                                        *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
diff --git a/src/mp3.c b/src/mp3.c
index 06c77a0..4e8ea14 100644
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - mp3.c                                           *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
diff --git a/src/musyx.c b/src/musyx.c
index 5a44917..d5a630a 100644
--- a/src/musyx.c
+++ b/src/musyx.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - musyx.c                                         *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2013 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -256,6 +256,8 @@ void musyx_v1_task(struct hle_t* hle)
     dram_store_u16(hle, (uint16_t *)musyx.cc0, state_ptr + STATE_CC0, SUBFRAME_SIZE);
     dram_store_u16(hle, (uint16_t *)musyx.subframe_740_last4, state_ptr + STATE_740_LAST4_V1,
               4);
+
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 /**************************************************************************
@@ -333,6 +335,8 @@ void musyx_v2_task(struct hle_t* hle)
 
         sfd_ptr += SFD2_VOICES + MAX_VOICES * VOICE_SIZE;
     }
+
+    rsp_break(hle, SP_STATUS_TASKDONE);
 }
 
 
diff --git a/src/osal_dynamiclib.h b/src/osal_dynamiclib.h
new file mode 100644
index 0000000..dc5e5ba
--- /dev/null
+++ b/src/osal_dynamiclib.h
@@ -0,0 +1,34 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-ui-console - osal_dynamiclib.h                            *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#if !defined(OSAL_DYNAMICLIB_H)
+#define OSAL_DYNAMICLIB_H
+
+#include "m64p_types.h"
+
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath);
+
+void *     osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName);
+
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle);
+
+#endif /* #define OSAL_DYNAMICLIB_H */
+
diff --git a/src/osal_dynamiclib_unix.c b/src/osal_dynamiclib_unix.c
new file mode 100644
index 0000000..9d937ed
--- /dev/null
+++ b/src/osal_dynamiclib_unix.c
@@ -0,0 +1,71 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-ui-console - osal_dynamiclib_unix.c                       *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "m64p_types.h"
+#include "hle_external.h"
+#include "osal_dynamiclib.h"
+
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
+{
+    if (pLibHandle == NULL || pccLibraryPath == NULL)
+        return M64ERR_INPUT_ASSERT;
+
+    *pLibHandle = dlopen(pccLibraryPath, RTLD_NOW);
+
+    if (*pLibHandle == NULL)
+    {
+        /* only print an error message if there is a directory separator (/) in the pathname */
+        /* this prevents us from throwing an error for the use case where Mupen64Plus is not installed */
+        if (strchr(pccLibraryPath, '/') != NULL)
+            HleErrorMessage(NULL, "dlopen('%s') failed: %s", pccLibraryPath, dlerror());
+        return M64ERR_INPUT_NOT_FOUND;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
+{
+    if (pccProcedureName == NULL)
+        return NULL;
+
+    return dlsym(LibHandle, pccProcedureName);
+}
+
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
+{
+    int rval = dlclose(LibHandle);
+
+    if (rval != 0)
+    {
+        HleErrorMessage(NULL, "dlclose() failed: %s", dlerror());
+        return M64ERR_INTERNAL;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+
diff --git a/src/osal_dynamiclib_win32.c b/src/osal_dynamiclib_win32.c
new file mode 100644
index 0000000..fe77cf3
--- /dev/null
+++ b/src/osal_dynamiclib_win32.c
@@ -0,0 +1,75 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-ui-console - osal_dynamiclib_win32.c                      *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+
+#include "m64p_types.h"
+#include "hle_external.h"
+#include "osal_dynamiclib.h"
+
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
+{
+    if (pLibHandle == NULL || pccLibraryPath == NULL)
+        return M64ERR_INPUT_ASSERT;
+
+    *pLibHandle = LoadLibrary(pccLibraryPath);
+
+    if (*pLibHandle == NULL)
+    {
+        char *pchErrMsg;
+        DWORD dwErr = GetLastError();
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
+        HleErrorMessage(NULL, "LoadLibrary('%s') error: %s", pccLibraryPath, pchErrMsg);
+        LocalFree(pchErrMsg);
+        return M64ERR_INPUT_NOT_FOUND;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
+{
+    if (pccProcedureName == NULL)
+        return NULL;
+
+    return GetProcAddress(LibHandle, pccProcedureName);
+}
+
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
+{
+    int rval = FreeLibrary(LibHandle);
+
+    if (rval == 0)
+    {
+        char *pchErrMsg;
+        DWORD dwErr = GetLastError();
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
+        HleErrorMessage(NULL, "FreeLibrary() error: %s", pchErrMsg);
+        LocalFree(pchErrMsg);
+        return M64ERR_INTERNAL;
+    }
+
+    return M64ERR_SUCCESS;
+}
diff --git a/src/plugin.c b/src/plugin.c
index 64f8164..f14fd26 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - plugin.c                                        *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *   Copyright (C) 2002 Hacktarux                                          *
@@ -23,19 +23,42 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "common.h"
 #include "hle.h"
 #include "hle_internal.h"
+#include "hle_external.h"
 
 #define M64P_PLUGIN_PROTOTYPES 1
 #include "m64p_common.h"
+#include "m64p_config.h"
+#include "m64p_frontend.h"
 #include "m64p_plugin.h"
 #include "m64p_types.h"
 
-#define RSP_HLE_VERSION        0x020500
+#include "osal_dynamiclib.h"
+
+#define CONFIG_API_VERSION       0x020100
+#define CONFIG_PARAM_VERSION     1.00
+
+#define RSP_API_VERSION   0x20000
+#define RSP_HLE_VERSION        0x020509
 #define RSP_PLUGIN_API_VERSION 0x020000
 
+#define RSP_HLE_CONFIG_SECTION "Rsp-HLE"
+#define RSP_HLE_CONFIG_VERSION "Version"
+#define RSP_HLE_CONFIG_FALLBACK "RspFallback"
+#define RSP_HLE_CONFIG_HLE_GFX  "DisplayListToGraphicsPlugin"
+#define RSP_HLE_CONFIG_HLE_AUD  "AudioListToAudioPlugin"
+
+
+#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
+
+/* Handy macro to avoid code bloat when loading symbols */
+#define GET_FUNC(type, field, name) \
+    ((field = (type)osal_dynlib_getproc(handle, name)) != NULL)
+
 /* local variables */
 static struct hle_t g_hle;
 static void (*l_CheckInterrupts)(void) = NULL;
@@ -45,9 +68,125 @@ static void (*l_ProcessRdpList)(void) = NULL;
 static void (*l_ShowCFB)(void) = NULL;
 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
 static void *l_DebugCallContext = NULL;
+static m64p_dynlib_handle l_CoreHandle = NULL;
 static int l_PluginInit = 0;
 
+static m64p_handle l_ConfigRspHle;
+static m64p_dynlib_handle l_RspFallback;
+static ptr_InitiateRSP l_InitiateRSP = NULL;
+static ptr_DoRspCycles l_DoRspCycles = NULL;
+static ptr_RomClosed l_RomClosed = NULL;
+static ptr_PluginShutdown l_PluginShutdown = NULL;
+
+/* definitions of pointers to Core functions */
+static ptr_ConfigOpenSection      ConfigOpenSection = NULL;
+static ptr_ConfigDeleteSection    ConfigDeleteSection = NULL;
+static ptr_ConfigSetParameter     ConfigSetParameter = NULL;
+static ptr_ConfigGetParameter     ConfigGetParameter = NULL;
+static ptr_ConfigSetDefaultInt    ConfigSetDefaultInt = NULL;
+static ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat = NULL;
+static ptr_ConfigSetDefaultBool   ConfigSetDefaultBool = NULL;
+static ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
+static ptr_ConfigGetParamInt      ConfigGetParamInt = NULL;
+static ptr_ConfigGetParamFloat    ConfigGetParamFloat = NULL;
+static ptr_ConfigGetParamBool     ConfigGetParamBool = NULL;
+static ptr_ConfigGetParamString   ConfigGetParamString = NULL;
+static ptr_CoreDoCommand          CoreDoCommand = NULL;
+
 /* local function */
+static void teardown_rsp_fallback()
+{
+    if (l_RspFallback != NULL) {
+        (*l_PluginShutdown)();
+        osal_dynlib_close(l_RspFallback);
+    }
+
+    l_RspFallback = NULL;
+    l_DoRspCycles = NULL;
+    l_InitiateRSP = NULL;
+    l_RomClosed = NULL;
+    l_PluginShutdown = NULL;
+}
+
+static void setup_rsp_fallback(const char* rsp_fallback_path)
+{
+    m64p_dynlib_handle handle = NULL;
+
+    /* reset rsp fallback */
+    teardown_rsp_fallback();
+
+    if (rsp_fallback_path == NULL || strlen(rsp_fallback_path) == 0) {
+        HleInfoMessage(NULL, "RSP Fallback disabled !");
+        return;
+    }
+
+    /* load plugin */
+    if (osal_dynlib_open(&handle, rsp_fallback_path) != M64ERR_SUCCESS) {
+        HleErrorMessage(NULL, "Can't load library: %s", rsp_fallback_path);
+        return;
+    }
+
+    /* call the GetVersion function for the plugin and check compatibility */
+    ptr_PluginGetVersion PluginGetVersion = (ptr_PluginGetVersion) osal_dynlib_getproc(handle, "PluginGetVersion");
+    if (PluginGetVersion == NULL)
+    {
+        HleErrorMessage(NULL, "library '%s' is not a Mupen64Plus library.", rsp_fallback_path);
+        goto close_handle;
+    }
+
+    m64p_plugin_type plugin_type = (m64p_plugin_type)0;
+    int plugin_version = 0;
+    const char *plugin_name = NULL;
+    int api_version = 0;
+
+    (*PluginGetVersion)(&plugin_type, &plugin_version, &api_version, &plugin_name, NULL);
+
+    if (plugin_type != M64PLUGIN_RSP) {
+        HleErrorMessage(NULL, "plugin %s is not an RSP plugin (%u)", plugin_name, plugin_type);
+        goto close_handle;
+    }
+
+    if ((api_version & 0xffff0000) != (RSP_API_VERSION & 0xffff0000)) {
+        HleErrorMessage(NULL, "plugin %s. Version mismatch: %u.%u. Expected >= %u.0",
+            plugin_name,
+            (uint16_t)(api_version >> 16),
+            (uint16_t)(api_version),
+            (uint16_t)(RSP_API_VERSION >> 16));
+        goto close_handle;
+    }
+
+    /* load functions */
+    ptr_PluginStartup PluginStartup;
+
+    if (!GET_FUNC(ptr_PluginStartup, PluginStartup, "PluginStartup") ||
+        !GET_FUNC(ptr_PluginShutdown, l_PluginShutdown, "PluginShutdown") ||
+        !GET_FUNC(ptr_DoRspCycles, l_DoRspCycles, "DoRspCycles") ||
+        !GET_FUNC(ptr_InitiateRSP, l_InitiateRSP, "InitiateRSP") ||
+        !GET_FUNC(ptr_RomClosed, l_RomClosed, "RomClosed"))
+    {
+        HleErrorMessage(NULL, "broken RSP plugin; function(s) not found.");
+        l_PluginShutdown = NULL;
+        l_DoRspCycles = NULL;
+        l_InitiateRSP = NULL;
+        l_RomClosed = NULL;
+        goto close_handle;
+    }
+
+    /* call the plugin's initialization function and make sure it starts okay */
+    if ((*PluginStartup)(l_CoreHandle, l_DebugCallContext, l_DebugCallback) != M64ERR_SUCCESS) {
+        HleErrorMessage(NULL, "Error: %s plugin library '%s' failed to start.", plugin_name, rsp_fallback_path);
+        goto close_handle;
+    }
+
+    /* OK we're done ! */
+    l_RspFallback = handle;
+    HleInfoMessage(NULL, "RSP Fallback '%s' loaded successfully !", rsp_fallback_path);
+    return;
+
+close_handle:
+    osal_dynlib_close(handle);
+}
+
 static void DebugMessage(int level, const char *message, va_list args)
 {
     char msgbuf[1024];
@@ -69,6 +208,14 @@ void HleVerboseMessage(void* UNUSED(user_defined), const char *message, ...)
     va_end(args);
 }
 
+void HleInfoMessage(void* UNUSED(user_defined), const char *message, ...)
+{
+    va_list args;
+    va_start(args, message);
+    DebugMessage(M64MSG_INFO, message, args);
+    va_end(args);
+}
+
 void HleErrorMessage(void* UNUSED(user_defined), const char *message, ...)
 {
     va_list args;
@@ -126,10 +273,24 @@ void HleShowCFB(void* UNUSED(user_defined))
 }
 
 
+int HleForwardTask(void* user_defined)
+{
+    if (l_DoRspCycles == NULL)
+        return -1;
+
+    (*l_DoRspCycles)(-1);
+    return 0;
+}
+
+
 /* DLL-exported functions */
-EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle UNUSED(CoreLibHandle), void *Context,
+EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
                                      void (*DebugCallback)(void *, int, const char *))
 {
+    ptr_CoreGetAPIVersions CoreAPIVersionFunc;
+    int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
+    float fConfigParamsVersion = 0.0f;
+
     if (l_PluginInit)
         return M64ERR_ALREADY_INIT;
 
@@ -137,7 +298,87 @@ EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle UNUSED(CoreLibHandle), v
     l_DebugCallback = DebugCallback;
     l_DebugCallContext = Context;
 
-    /* this plugin doesn't use any Core library functions (ex for Configuration), so no need to keep the CoreLibHandle */
+    /* attach and call the CoreGetAPIVersions function, check Config API version for compatibility */
+    CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
+    if (CoreAPIVersionFunc == NULL)
+    {
+        HleErrorMessage(NULL, "Core emulator broken; no CoreAPIVersionFunc() function found.");
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
+    if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
+    {
+        HleErrorMessage(NULL, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
+                VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    /* Get the core config function pointers from the library handle */
+    ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
+    ConfigDeleteSection = (ptr_ConfigDeleteSection) osal_dynlib_getproc(CoreLibHandle, "ConfigDeleteSection");
+    ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
+    ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
+    ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
+    ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
+    ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
+    ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
+    ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
+    ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
+    ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
+    ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
+
+    if (!ConfigOpenSection || !ConfigDeleteSection || !ConfigSetParameter || !ConfigGetParameter ||
+        !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
+        !ConfigGetParamInt   || !ConfigGetParamFloat   || !ConfigGetParamBool   || !ConfigGetParamString)
+        return M64ERR_INCOMPATIBLE;
+
+    /* Get core DoCommand function */
+    CoreDoCommand = (ptr_CoreDoCommand) osal_dynlib_getproc(CoreLibHandle, "CoreDoCommand");
+    if (!CoreDoCommand) {
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    /* get a configuration section handle */
+    if (ConfigOpenSection(RSP_HLE_CONFIG_SECTION, &l_ConfigRspHle) != M64ERR_SUCCESS)
+    {
+        HleErrorMessage(NULL, "Couldn't open config section '" RSP_HLE_CONFIG_SECTION "'");
+        return M64ERR_INPUT_NOT_FOUND;
+    }
+
+    /* check the section version number */
+    if (ConfigGetParameter(l_ConfigRspHle, RSP_HLE_CONFIG_VERSION, M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS)
+    {
+        HleWarnMessage(NULL, "No version number in '" RSP_HLE_CONFIG_SECTION "' config section. Setting defaults.");
+        ConfigDeleteSection(RSP_HLE_CONFIG_SECTION);
+        ConfigOpenSection(RSP_HLE_CONFIG_SECTION, &l_ConfigRspHle);
+    }
+    else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION))
+    {
+        HleWarnMessage(NULL, "Incompatible version %.2f in '" RSP_HLE_CONFIG_SECTION "' config section: current is %.2f. Setting defaults.", fConfigParamsVersion, (float) CONFIG_PARAM_VERSION);
+        ConfigDeleteSection(RSP_HLE_CONFIG_SECTION);
+        ConfigOpenSection(RSP_HLE_CONFIG_SECTION, &l_ConfigRspHle);
+    }
+    else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f)
+    {
+        /* handle upgrades */
+        float fVersion = CONFIG_PARAM_VERSION;
+        ConfigSetParameter(l_ConfigRspHle, "Version", M64TYPE_FLOAT, &fVersion);
+        HleInfoMessage(NULL, "Updating parameter set version in '" RSP_HLE_CONFIG_SECTION "' config section to %.2f", fVersion);
+    }
+
+    /* set the default values for this plugin */
+    ConfigSetDefaultFloat(l_ConfigRspHle, RSP_HLE_CONFIG_VERSION, CONFIG_PARAM_VERSION,
+        "Mupen64Plus RSP HLE Plugin config parameter version number");
+    ConfigSetDefaultString(l_ConfigRspHle, RSP_HLE_CONFIG_FALLBACK, "",
+        "Path to a RSP plugin which will be used when encountering an unknown ucode."
+        "You can disable this by letting an empty string.");
+    ConfigSetDefaultBool(l_ConfigRspHle, RSP_HLE_CONFIG_HLE_GFX, 1,
+        "Send display lists to the graphics plugin");
+    ConfigSetDefaultBool(l_ConfigRspHle, RSP_HLE_CONFIG_HLE_AUD, 0,
+        "Send audio lists to the audio plugin");
+
+    l_CoreHandle = CoreLibHandle;
 
     l_PluginInit = 1;
     return M64ERR_SUCCESS;
@@ -151,6 +392,9 @@ EXPORT m64p_error CALL PluginShutdown(void)
     /* reset some local variable */
     l_DebugCallback = NULL;
     l_DebugCallContext = NULL;
+    l_CoreHandle = NULL;
+
+    teardown_rsp_fallback();
 
     l_PluginInit = 0;
     return M64ERR_SUCCESS;
@@ -183,7 +427,7 @@ EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles)
     return Cycles;
 }
 
-EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int* UNUSED(CycleCount))
+EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int* CycleCount)
 {
     hle_init(&g_hle,
              Rsp_Info.RDRAM,
@@ -214,9 +458,25 @@ EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int* UNUSED(CycleCount)
     l_ProcessAlistList = Rsp_Info.ProcessAlistList;
     l_ProcessRdpList = Rsp_Info.ProcessRdpList;
     l_ShowCFB = Rsp_Info.ShowCFB;
+
+    setup_rsp_fallback(ConfigGetParamString(l_ConfigRspHle, RSP_HLE_CONFIG_FALLBACK));
+
+    m64p_rom_header rom_header;
+    CoreDoCommand(M64CMD_ROM_GET_HEADER, sizeof(rom_header), &rom_header);
+
+    g_hle.hle_gfx = ConfigGetParamBool(l_ConfigRspHle, RSP_HLE_CONFIG_HLE_GFX);
+    g_hle.hle_aud = ConfigGetParamBool(l_ConfigRspHle, RSP_HLE_CONFIG_HLE_AUD);
+
+    /* notify fallback plugin */
+    if (l_InitiateRSP) {
+        l_InitiateRSP(Rsp_Info, CycleCount);
+    }
 }
 
 EXPORT void CALL RomClosed(void)
 {
-    /* do nothing */
+    /* notify fallback plugin */
+    if (l_RomClosed) {
+        l_RomClosed();
+    }
 }
diff --git a/src/re2.c b/src/re2.c
new file mode 100644
index 0000000..8ae1788
--- /dev/null
+++ b/src/re2.c
@@ -0,0 +1,224 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-rsp-hle - re2.c                                           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
+ *   Copyright (C) 2016 Gilles Siberlin                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+
+#define SATURATE8(x) ((unsigned int) x <= 255 ? x : (x < 0 ? 0: 255))
+
+/**************************************************************************
+ * Resident evil 2 ucodes
+ **************************************************************************/
+void resize_bilinear_task(struct hle_t* hle)
+{
+    int data_ptr = *dmem_u32(hle, TASK_UCODE_DATA);
+
+    int src_addr = *dram_u32(hle, data_ptr);
+    int dst_addr = *dram_u32(hle, data_ptr + 4);
+    int dst_width = *dram_u32(hle, data_ptr + 8);
+    int dst_height = *dram_u32(hle, data_ptr + 12);
+    int x_ratio = *dram_u32(hle, data_ptr + 16);
+    int y_ratio = *dram_u32(hle, data_ptr + 20);
+#if 0 /* unused, but keep it for documentation purpose */
+    int dst_stride = *dram_u32(hle, data_ptr + 24);
+#endif
+    int src_offset = *dram_u32(hle, data_ptr + 36);
+
+    int a, b, c ,d, index, y_index, xr, yr, blue, green, red, addr, i, j;
+    long long x, y, x_diff, y_diff, one_min_x_diff, one_min_y_diff;
+    unsigned short pixel;
+
+    src_addr += (src_offset >> 16) * (320 * 3);
+    x = y = 0;
+
+    for(i = 0; i < dst_height; i++)
+    {
+        yr = (int)(y >> 16);
+        y_diff = y - (yr << 16);
+        one_min_y_diff = 65536 - y_diff;
+        y_index = yr * 320;
+        x = 0;
+
+        for(j = 0; j < dst_width; j++)
+        {
+            xr = (int)(x >> 16);
+            x_diff = x - (xr << 16);
+            one_min_x_diff = 65536 - x_diff;
+            index = y_index + xr;
+            addr = src_addr + (index * 3);
+
+            dram_load_u8(hle, (uint8_t*)&a, addr, 3);
+            dram_load_u8(hle, (uint8_t*)&b, (addr + 3), 3);
+            dram_load_u8(hle, (uint8_t*)&c, (addr + (320 * 3)), 3);
+            dram_load_u8(hle, (uint8_t*)&d, (addr + (320 * 3) + 3), 3);
+
+            blue = (int)(((a&0xff)*one_min_x_diff*one_min_y_diff + (b&0xff)*x_diff*one_min_y_diff +
+                          (c&0xff)*y_diff*one_min_x_diff         + (d&0xff)*x_diff*y_diff) >> 32);
+
+            green = (int)((((a>>8)&0xff)*one_min_x_diff*one_min_y_diff + ((b>>8)&0xff)*x_diff*one_min_y_diff +
+                           ((c>>8)&0xff)*y_diff*one_min_x_diff         + ((d>>8)&0xff)*x_diff*y_diff) >> 32);
+
+            red = (int)((((a>>16)&0xff)*one_min_x_diff*one_min_y_diff + ((b>>16)&0xff)*x_diff*one_min_y_diff +
+                         ((c>>16)&0xff)*y_diff*one_min_x_diff         + ((d>>16)&0xff)*x_diff*y_diff) >> 32);
+
+            blue = (blue >> 3) & 0x001f;
+            green = (green >> 3) & 0x001f;
+            red = (red >> 3) & 0x001f;
+            pixel = (red << 11) | (green << 6) | (blue << 1) | 1;
+
+            dram_store_u16(hle, &pixel, dst_addr, 1);
+            dst_addr += 2;
+
+            x += x_ratio;
+        }
+        y += y_ratio;
+    }
+
+    rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+static uint32_t YCbCr_to_RGBA(uint8_t Y, uint8_t Cb, uint8_t Cr)
+{
+    int r, g, b;
+
+    r = (int)(((double)Y * 0.582199097) + (0.701004028 * (double)(Cr - 128)));
+    g = (int)(((double)Y * 0.582199097) - (0.357070923 * (double)(Cr - 128)) - (0.172073364 * (double)(Cb - 128)));
+    b = (int)(((double)Y * 0.582199097) + (0.886001587 * (double)(Cb - 128)));
+    
+    r = SATURATE8(r);
+    g = SATURATE8(g);
+    b = SATURATE8(b);
+    
+    return (r << 24) | (g << 16) | (b << 8) | 0;
+}
+
+void decode_video_frame_task(struct hle_t* hle)
+{
+    int data_ptr = *dmem_u32(hle, TASK_UCODE_DATA);
+
+    int pLuminance = *dram_u32(hle, data_ptr);
+    int pCb = *dram_u32(hle, data_ptr + 4);
+    int pCr = *dram_u32(hle, data_ptr + 8);
+    int pDestination = *dram_u32(hle, data_ptr + 12);
+    int nMovieWidth = *dram_u32(hle, data_ptr + 16);
+    int nMovieHeight = *dram_u32(hle, data_ptr + 20);
+#if 0 /* unused, but keep it for documentation purpose */
+    int nRowsPerDMEM = *dram_u32(hle, data_ptr + 24);
+    int nDMEMPerFrame = *dram_u32(hle, data_ptr + 28);
+    int nLengthSkipCount = *dram_u32(hle, data_ptr + 32);
+#endif
+    int nScreenDMAIncrement = *dram_u32(hle, data_ptr + 36);
+
+    int i, j;
+    uint8_t Y, Cb, Cr;
+    uint32_t pixel;
+    int pY_1st_row, pY_2nd_row, pDest_1st_row, pDest_2nd_row;
+
+    for (i = 0; i < nMovieHeight; i += 2)
+    {
+        pY_1st_row = pLuminance;
+        pY_2nd_row = pLuminance + nMovieWidth;
+        pDest_1st_row = pDestination;
+        pDest_2nd_row = pDestination + (nScreenDMAIncrement >> 1);
+
+        for (j = 0; j < nMovieWidth; j += 2)
+        {
+            dram_load_u8(hle, (uint8_t*)&Cb, pCb++, 1);
+            dram_load_u8(hle, (uint8_t*)&Cr, pCr++, 1);
+
+            /*1st row*/
+            dram_load_u8(hle, (uint8_t*)&Y, pY_1st_row++, 1);
+            pixel = YCbCr_to_RGBA(Y, Cb, Cr);
+            dram_store_u32(hle, &pixel, pDest_1st_row, 1);
+            pDest_1st_row += 4;
+
+            dram_load_u8(hle, (uint8_t*)&Y, pY_1st_row++, 1);
+            pixel = YCbCr_to_RGBA(Y, Cb, Cr);
+            dram_store_u32(hle, &pixel, pDest_1st_row, 1);
+            pDest_1st_row += 4;
+
+            /*2nd row*/
+            dram_load_u8(hle, (uint8_t*)&Y, pY_2nd_row++, 1);
+            pixel = YCbCr_to_RGBA(Y, Cb, Cr);
+            dram_store_u32(hle, &pixel, pDest_2nd_row, 1);
+            pDest_2nd_row += 4;
+
+            dram_load_u8(hle, (uint8_t*)&Y, pY_2nd_row++, 1);
+            pixel = YCbCr_to_RGBA(Y, Cb, Cr);
+            dram_store_u32(hle, &pixel, pDest_2nd_row, 1);
+            pDest_2nd_row += 4;
+        }
+
+        pLuminance += (nMovieWidth << 1);
+        pDestination += nScreenDMAIncrement;
+    }
+
+    rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void fill_video_double_buffer_task(struct hle_t* hle)
+{
+    int data_ptr = *dmem_u32(hle, TASK_UCODE_DATA);
+
+    int pSrc = *dram_u32(hle, data_ptr);
+    int pDest = *dram_u32(hle, data_ptr + 0x4);
+    int width = *dram_u32(hle, data_ptr + 0x8) >> 1;
+    int height = *dram_u32(hle, data_ptr + 0x10) << 1;
+    int stride = *dram_u32(hle, data_ptr + 0x1c) >> 1;
+
+    assert((*dram_u32(hle, data_ptr + 0x28) >> 16) == 0x8000);
+
+#if 0 /* unused, but keep it for documentation purpose */
+    int arg3 = *dram_u32(hle, data_ptr + 0xc);
+    int arg5 = *dram_u32(hle, data_ptr + 0x14);
+    int arg6 = *dram_u32(hle, data_ptr + 0x18);
+#endif
+
+    int i, j;
+    int r, g, b;
+    uint32_t pixel, pixel1, pixel2;
+
+    for(i = 0; i < height; i++)
+    {
+      for(j = 0; j < width; j=j+4)
+      {
+        pixel1 = *dram_u32(hle, pSrc+j);
+        pixel2 = *dram_u32(hle, pDest+j);
+      
+        r = (((pixel1 >> 24) & 0xff) + ((pixel2 >> 24) & 0xff)) >> 1;
+        g = (((pixel1 >> 16) & 0xff) + ((pixel2 >> 16) & 0xff)) >> 1;
+        b = (((pixel1 >> 8) & 0xff) + ((pixel2 >> 8) & 0xff)) >> 1;
+      
+        pixel = (r << 24) | (g << 16) | (b << 8) | 0;
+      
+        dram_store_u32(hle, &pixel, pDest+j, 1);
+      }
+      pSrc += stride;
+      pDest += stride;
+    }
+
+    rsp_break(hle, SP_STATUS_TASKDONE);
+}
diff --git a/src/ucodes.h b/src/ucodes.h
index 1a12bf9..1150cf6 100644
--- a/src/ucodes.h
+++ b/src/ucodes.h
@@ -1,6 +1,6 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   Mupen64plus-rsp-hle - ucodes.h                                        *
- *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Mupen64Plus homepage: https://mupen64plus.org/                        *
  *   Copyright (C) 2014 Bobby Smiles                                       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -126,7 +126,8 @@ void alist_process_nead_oot (struct hle_t* hle);
 void alist_process_nead_mm  (struct hle_t* hle);
 void alist_process_nead_mmb (struct hle_t* hle);
 void alist_process_nead_ac  (struct hle_t* hle);
-
+void alist_process_nead_mats(struct hle_t* hle);
+void alist_process_nead_efz (struct hle_t* hle);
 
 /* mp3 ucode */
 void mp3_task(struct hle_t* hle, unsigned int index, uint32_t address);
@@ -142,5 +143,10 @@ void jpeg_decode_PS0(struct hle_t* hle);
 void jpeg_decode_PS(struct hle_t* hle);
 void jpeg_decode_OB(struct hle_t* hle);
 
+/* Resident evil 2 ucode */
+void resize_bilinear_task(struct hle_t* hle);
+void decode_video_frame_task(struct hle_t* hle);
+void fill_video_double_buffer_task(struct hle_t* hle);
+
 #endif