diff --git a/libmupen64plus/mupen64plus-rsp-hle/LICENSES b/libmupen64plus/mupen64plus-rsp-hle/LICENSES
index e1403bd131..4319820ae1 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/LICENSES
+++ b/libmupen64plus/mupen64plus-rsp-hle/LICENSES
@@ -5,7 +5,8 @@ Mupen64Plus-rsp-hle is licensed under the GNU General Public License version 2.
The authors of Mupen64Plus-rsp-hle are:
* Richard Goedeken (Richard42)
- * Bobby Smiles
+ * Bobby Smiles (bsmiles32)
+ * Sven Eckelmann (ecsv)
* John Chadwick (NMN)
* James Hood (Ebenblues)
* Scott Gorman (okaygo)
@@ -29,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/libmupen64plus/mupen64plus-rsp-hle/RELEASE b/libmupen64plus/mupen64plus-rsp-hle/RELEASE
index 7a661112fe..0b19ad2357 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/RELEASE
+++ b/libmupen64plus/mupen64plus-rsp-hle/RELEASE
@@ -1,6 +1,17 @@
RSP High-Level Emulation plugin for Mupen64Plus
-----------------------------------------------
+Mupen64Plus-rsp-hle v2.5 - April 26, 2015
+-------------------------------------------------
+ - Game-specific fixes: Bottom of the 9th, IndianaJones, BattleForNaboo, Conkers Bad Fur Day
+ - Support for MusyX microcodes
+ - Improve audio microcode identification
+ - Huge quantity of code cleanups and refactoring to improve organization
+ - Add support for additional audio commands: #16, POLEF, RESAMPLE_ZOH
+ - Multiple bugfixes in audio processing code
+ - Move global variables into a struct so code is re-entrant
+ - bugfix: microcode detection could sometimes fail after reset
+
Mupen64Plus-rsp-hle v2.0 - July 4, 2013
-------------------------------------------------
- Add support for MusyX ucode detection
diff --git a/libmupen64plus/mupen64plus-rsp-hle/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj b/libmupen64plus/mupen64plus-rsp-hle/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj
new file mode 100644
index 0000000000..3b6349f016
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/projects/VisualStudio2013/mupen64plus-rsp-hle.vcxproj
@@ -0,0 +1,194 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}
+ mupen64plusrsphle
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+ true
+ v120_xp
+
+
+ DynamicLibrary
+ MultiByte
+ true
+ v120
+
+
+ DynamicLibrary
+ MultiByte
+ v120
+
+
+ DynamicLibrary
+ MultiByte
+ v120
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.40219.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+ true
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+ false
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+ Disabled
+ ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ EditAndContinue
+ Default
+
+
+ true
+ Windows
+ MachineX86
+
+
+
+
+ Disabled
+ ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+ Default
+
+
+ true
+ Windows
+
+
+
+
+ ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+ Default
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;inline=__inline;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+ Default
+
+
+ true
+ Windows
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/projects/msvc11/mupen64plus-rsp-hle.vcxproj b/libmupen64plus/mupen64plus-rsp-hle/projects/msvc11/mupen64plus-rsp-hle.vcxproj
index f71023ea49..c73605209c 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/projects/msvc11/mupen64plus-rsp-hle.vcxproj
+++ b/libmupen64plus/mupen64plus-rsp-hle/projects/msvc11/mupen64plus-rsp-hle.vcxproj
@@ -187,22 +187,33 @@
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
+
-
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/projects/msvc8/mupen64plus-rsp-hle.vcproj b/libmupen64plus/mupen64plus-rsp-hle/projects/msvc8/mupen64plus-rsp-hle.vcproj
index 1b9522852c..6ee59896c7 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/projects/msvc8/mupen64plus-rsp-hle.vcproj
+++ b/libmupen64plus/mupen64plus-rsp-hle/projects/msvc8/mupen64plus-rsp-hle.vcproj
@@ -182,32 +182,56 @@
RelativePath="..\..\src\alist.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -221,11 +245,15 @@
>
+
+
+
+
+
+
+
+
+
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/projects/unix/Makefile b/libmupen64plus/mupen64plus-rsp-hle/projects/unix/Makefile
index ca5e657d3c..f9162a2bde 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/projects/unix/Makefile
+++ b/libmupen64plus/mupen64plus-rsp-hle/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
@@ -111,15 +110,20 @@ ifneq ("$(filter arm%,$(HOST_CPU))","")
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
endif
+ifneq ("$(filter mips,$(HOST_CPU))","")
+ CPU := MIPS
+ ARCH_DETECTED := 32BITS
+ PIC ?= 1
+ $(warning Architecture "$(HOST_CPU)" not officially supported.')
+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
OPTFLAGS ?= -O3 -flto
WARNFLAGS ?= -Wall
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src
-CXXFLAGS += -fvisibility-inlines-hidden
LDFLAGS += $(SHARED)
# Since we are building a shared library, we must compile with -fPIC on some architectures
@@ -147,11 +151,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)
@@ -189,26 +192,24 @@ endif
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
Q_CC = @echo ' CC '$@;
- Q_CXX = @echo ' CXX '$@;
Q_LD = @echo ' LD '$@;
endif
endif
# set base program pointers and flags
CC = $(CROSS_COMPILE)gcc
-CXX = $(CROSS_COMPILE)g++
RM ?= rm -f
INSTALL ?= install
MKDIR ?= mkdir -p
COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
-COMPILE.cc = $(Q_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
-LINK.o = $(Q_LD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH)
# set special flags for given Makefile parameters
ifeq ($(DEBUG),1)
CFLAGS += -g
INSTALL_STRIP_FLAG ?=
else
+ CFLAGS += -DNDEBUG
ifneq ($(OS),OSX)
INSTALL_STRIP_FLAG ?= -s
endif
@@ -225,23 +226,41 @@ ifeq ($(PLUGINDIR),)
PLUGINDIR := $(LIBDIR)/mupen64plus
endif
+# enable/disable task dumping support
+ifeq ($(DUMP), 1)
+ CFLAGS += -DENABLE_TASK_DUMP
+endif
+
+
SRCDIR = ../../src
OBJDIR = _obj$(POSTFIX)
# list of source files to compile
SOURCE = \
- $(SRCDIR)/main.c \
$(SRCDIR)/alist.c \
+ $(SRCDIR)/alist_audio.c \
+ $(SRCDIR)/alist_naudio.c \
+ $(SRCDIR)/alist_nead.c \
+ $(SRCDIR)/audio.c \
$(SRCDIR)/cicx105.c \
+ $(SRCDIR)/hle.c \
$(SRCDIR)/jpeg.c \
- $(SRCDIR)/ucode3.cpp \
- $(SRCDIR)/ucode2.cpp \
- $(SRCDIR)/ucode1.cpp \
- $(SRCDIR)/ucode3mp3.cpp
+ $(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)))
-OBJECTS += $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(filter %.cpp, $(SOURCE)))
OBJDIRS = $(dir $(OBJECTS))
$(shell $(MKDIR) $(OBJDIRS))
@@ -263,6 +282,7 @@ targets:
@echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)"
@echo " PIC=(1|0) == Force enable/disable of position independent code"
@echo " POSTFIX=name == String added to the name of the the build (default: '')"
+ @echo " DUMP=(1|0) == Enable/Disable unknown task dumping (default: 0)"
@echo " Install Options:"
@echo " PREFIX=path == install/uninstall prefix (default: /usr/local)"
@echo " LIBDIR=path == library prefix (default: PREFIX/lib)"
@@ -287,18 +307,13 @@ clean:
rebuild: clean all
# build dependency files
-CFLAGS += -MD
+CFLAGS += -MD -MP
-include $(OBJECTS:.o=.d)
-CXXFLAGS += $(CFLAGS)
-
# standard build rules
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -o $@ $<
-$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
- $(COMPILE.cc) -o $@ $<
-
$(TARGET): $(OBJECTS)
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist.c b/libmupen64plus/mupen64plus-rsp-hle/src/alist.c
index c1418939e2..ef3adc2ec4 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/alist.c
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/alist.c
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - alist.c *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2012 Bobby Smiles *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* Copyright (C) 2009 Richard Goedeken *
* Copyright (C) 2002 Hacktarux *
* *
@@ -21,62 +21,1004 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#include "hle.h"
-#include "alist_internal.h"
+#include
+#include
+#include
+#include
-// FIXME: this decomposition into 3 ABI is not accurate,
-// there are a least 9 or 10 different ABI, each with one or a few revisions
-// for a total of almost 16 differents audio ucode.
-//
-// ABI2 in fact is a mix of at least 7 differents ABI which are mostly compatible
-// but not totally, that's why there is a isZeldaABI/isMKABI workaround.
-//
-extern const acmd_callback_t ABI1[0x10];
-extern const acmd_callback_t ABI2[0x20];
-extern const acmd_callback_t ABI3[0x10];
+#include "alist.h"
+#include "arithmetics.h"
+#include "audio.h"
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+
+struct ramp_t
+{
+ int64_t value;
+ int64_t step;
+ int64_t target;
+};
/* local functions */
-static void alist_process(const acmd_callback_t abi[], unsigned int abi_size)
+static void swap(int16_t **a, int16_t **b)
{
- u32 inst1, inst2;
- unsigned int acmd;
- const OSTask_t * const task = get_task();
+ int16_t* tmp = *b;
+ *b = *a;
+ *a = tmp;
+}
- const unsigned int *alist = (unsigned int*)(rsp.RDRAM + task->data_ptr);
- const unsigned int * const alist_end = alist + (task->data_size >> 2);
+static int16_t* sample(struct hle_t* hle, unsigned pos)
+{
+ return (int16_t*)hle->alist_buffer + ((pos ^ S) & 0xfff);
+}
- while (alist != alist_end)
+static uint8_t* alist_u8(struct hle_t* hle, uint16_t 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*)(hle->alist_buffer + ((dmem ^ S16) & 0xfff));
+}
+
+
+static void sample_mix(int16_t* dst, int16_t src, int16_t gain)
+{
+ *dst = clamp_s16(*dst + ((src * gain) >> 15));
+}
+
+static void alist_envmix_mix(size_t n, int16_t** dst, const int16_t* gains, int16_t src)
+{
+ size_t i;
+
+ for(i = 0; i < n; ++i)
+ sample_mix(dst[i], src, gains[i]);
+}
+
+static int16_t ramp_step(struct ramp_t* ramp)
+{
+ bool target_reached;
+
+ ramp->value += ramp->step;
+
+ target_reached = (ramp->step <= 0)
+ ? (ramp->value <= ramp->target)
+ : (ramp->value >= ramp->target);
+
+ if (target_reached)
{
- inst1 = *(alist++);
- inst2 = *(alist++);
-
- acmd = inst1 >> 24;
-
- if (acmd < abi_size)
- {
- (*abi[acmd])(inst1, inst2);
- }
- else
- {
- DebugMessage(M64MSG_WARNING, "Invalid ABI command %u", acmd);
- }
+ ramp->value = ramp->target;
+ ramp->step = 0;
}
+
+ return (int16_t)(ramp->value >> 16);
}
/* global functions */
-void alist_process_ABI1()
+void alist_process(struct hle_t* hle, const acmd_callback_t abi[], unsigned int abi_size)
{
- alist_process(ABI1, 0x10);
+ uint32_t w1, w2;
+ unsigned int acmd;
+
+ const uint32_t *alist = dram_u32(hle, *dmem_u32(hle, TASK_DATA_PTR));
+ const uint32_t *const alist_end = alist + (*dmem_u32(hle, TASK_DATA_SIZE) >> 2);
+
+ while (alist != alist_end) {
+ w1 = *(alist++);
+ w2 = *(alist++);
+
+ acmd = (w1 >> 24) & 0x7f;
+
+ if (acmd < abi_size)
+ (*abi[acmd])(hle, w1, w2);
+ else
+ HleWarnMessage(hle->user_defined, "Invalid ABI command %u", acmd);
+ }
}
-void alist_process_ABI2()
+uint32_t alist_get_address(struct hle_t* hle, uint32_t so, const uint32_t *segments, size_t n)
{
- alist_process(ABI2, 0x20);
+ uint8_t segment = (so >> 24) & 0x3f;
+ uint32_t offset = (so & 0xffffff);
+
+ if (segment >= n) {
+ HleWarnMessage(hle->user_defined, "Invalid segment %u", segment);
+ return offset;
+ }
+
+ return segments[segment] + offset;
}
-void alist_process_ABI3()
+void alist_set_address(struct hle_t* hle, uint32_t so, uint32_t *segments, size_t n)
{
- alist_process(ABI3, 0x10);
+ uint8_t segment = (so >> 24) & 0x3f;
+ uint32_t offset = (so & 0xffffff);
+
+ if (segment >= n) {
+ HleWarnMessage(hle->user_defined, "Invalid segment %u", segment);
+ return;
+ }
+
+ segments[segment] = offset;
+}
+
+void alist_clear(struct hle_t* hle, uint16_t dmem, uint16_t count)
+{
+ while(count != 0) {
+ *alist_u8(hle, dmem++) = 0;
+ --count;
+ }
+}
+
+void alist_load(struct hle_t* hle, uint16_t dmem, uint32_t address, uint16_t count)
+{
+ /* enforce DMA alignment constraints */
+ dmem &= ~3;
+ address &= ~7;
+ count = align(count, 8);
+ memcpy(hle->alist_buffer + dmem, hle->dram + address, count);
+}
+
+void alist_save(struct hle_t* hle, uint16_t dmem, uint32_t address, uint16_t count)
+{
+ /* enforce DMA alignment constraints */
+ dmem &= ~3;
+ address &= ~7;
+ count = align(count, 8);
+ memcpy(hle->dram + address, hle->alist_buffer + dmem, count);
+}
+
+void alist_move(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count)
+{
+ while (count != 0) {
+ *alist_u8(hle, dmemo++) = *alist_u8(hle, dmemi++);
+ --count;
+ }
+}
+
+void alist_copy_every_other_sample(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count)
+{
+ while (count != 0) {
+ *alist_s16(hle, dmemo) = *alist_s16(hle, dmemi);
+ dmemo += 2;
+ dmemi += 4;
+ --count;
+ }
+}
+
+void alist_repeat64(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint8_t count)
+{
+ uint16_t buffer[64];
+
+ memcpy(buffer, hle->alist_buffer + dmemi, 128);
+
+ while(count != 0) {
+ memcpy(hle->alist_buffer + dmemo, buffer, 128);
+ dmemo += 128;
+ --count;
+ }
+}
+
+void alist_copy_blocks(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t block_size, uint8_t count)
+{
+ int block_left = count;
+
+ do
+ {
+ int bytes_left = block_size;
+
+ do
+ {
+ memcpy(hle->alist_buffer + dmemo, hle->alist_buffer + dmemi, 0x20);
+ bytes_left -= 0x20;
+
+ dmemi += 0x20;
+ dmemo += 0x20;
+
+ } while(bytes_left > 0);
+
+ --block_left;
+ } while(block_left > 0);
+}
+
+void alist_interleave(struct hle_t* hle, uint16_t dmemo, uint16_t left, uint16_t right, uint16_t count)
+{
+ uint16_t *dst = (uint16_t*)(hle->alist_buffer + dmemo);
+ const uint16_t *srcL = (uint16_t*)(hle->alist_buffer + left);
+ const uint16_t *srcR = (uint16_t*)(hle->alist_buffer + right);
+
+ count >>= 2;
+
+ while(count != 0) {
+ uint16_t l1 = *(srcL++);
+ uint16_t l2 = *(srcL++);
+ uint16_t r1 = *(srcR++);
+ uint16_t r2 = *(srcR++);
+
+#if M64P_BIG_ENDIAN
+ *(dst++) = l1;
+ *(dst++) = r1;
+ *(dst++) = l2;
+ *(dst++) = r2;
+#else
+ *(dst++) = r2;
+ *(dst++) = l2;
+ *(dst++) = r1;
+ *(dst++) = l1;
+#endif
+ --count;
+ }
}
+void alist_envmix_exp(
+ struct hle_t* hle,
+ bool init,
+ bool aux,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address)
+{
+ size_t n = (aux) ? 4 : 2;
+
+ const int16_t* const in = (int16_t*)(hle->alist_buffer + dmemi);
+ int16_t* const dl = (int16_t*)(hle->alist_buffer + dmem_dl);
+ int16_t* const dr = (int16_t*)(hle->alist_buffer + dmem_dr);
+ int16_t* const wl = (int16_t*)(hle->alist_buffer + dmem_wl);
+ int16_t* const wr = (int16_t*)(hle->alist_buffer + dmem_wr);
+
+ struct ramp_t ramps[2];
+ int32_t exp_seq[2];
+ int32_t exp_rates[2];
+
+ uint32_t ptr = 0;
+ 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);
+ ramps[0].target = (target[0] << 16);
+ ramps[1].target = (target[1] << 16);
+ exp_rates[0] = rate[0];
+ exp_rates[1] = rate[1];
+ exp_seq[0] = (vol[0] * rate[0]);
+ exp_seq[1] = (vol[1] * rate[1]);
+ } else {
+ 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 */
+ ramps[1].target = *(int32_t *)(save_buffer + 6); /* 6-7 */
+ exp_rates[0] = *(int32_t *)(save_buffer + 8); /* 8-9 (save_buffer is a 16bit pointer) */
+ exp_rates[1] = *(int32_t *)(save_buffer + 10); /* 10-11 */
+ exp_seq[0] = *(int32_t *)(save_buffer + 12); /* 12-13 */
+ exp_seq[1] = *(int32_t *)(save_buffer + 14); /* 14-15 */
+ ramps[0].value = *(int32_t *)(save_buffer + 16); /* 12-13 */
+ ramps[1].value = *(int32_t *)(save_buffer + 18); /* 14-15 */
+ }
+
+ /* init which ensure ramp.step != 0 iff ramp.value == ramp.target */
+ ramps[0].step = ramps[0].target - ramps[0].value;
+ ramps[1].step = ramps[1].target - ramps[1].value;
+
+ for (y = 0; y < count; y += 16) {
+
+ if (ramps[0].step != 0)
+ {
+ exp_seq[0] = ((int64_t)exp_seq[0]*(int64_t)exp_rates[0]) >> 16;
+ ramps[0].step = (exp_seq[0] - ramps[0].value) >> 3;
+ }
+
+ if (ramps[1].step != 0)
+ {
+ exp_seq[1] = ((int64_t)exp_seq[1]*(int64_t)exp_rates[1]) >> 16;
+ ramps[1].step = (exp_seq[1] - ramps[1].value) >> 3;
+ }
+
+ for (x = 0; x < 8; ++x) {
+ int16_t gains[4];
+ int16_t* buffers[4];
+ int16_t l_vol = ramp_step(&ramps[0]);
+ int16_t r_vol = ramp_step(&ramps[1]);
+
+ buffers[0] = dl + (ptr^S);
+ buffers[1] = dr + (ptr^S);
+ buffers[2] = wl + (ptr^S);
+ buffers[3] = wr + (ptr^S);
+
+ gains[0] = clamp_s16((l_vol * dry + 0x4000) >> 15);
+ gains[1] = clamp_s16((r_vol * dry + 0x4000) >> 15);
+ gains[2] = clamp_s16((l_vol * wet + 0x4000) >> 15);
+ gains[3] = clamp_s16((r_vol * wet + 0x4000) >> 15);
+
+ alist_envmix_mix(n, buffers, gains, in[ptr^S]);
+ ++ptr;
+ }
+ }
+
+ *(int16_t *)(save_buffer + 0) = wet; /* 0-1 */
+ *(int16_t *)(save_buffer + 2) = dry; /* 2-3 */
+ *(int32_t *)(save_buffer + 4) = (int32_t)ramps[0].target; /* 4-5 */
+ *(int32_t *)(save_buffer + 6) = (int32_t)ramps[1].target; /* 6-7 */
+ *(int32_t *)(save_buffer + 8) = exp_rates[0]; /* 8-9 (save_buffer is a 16bit pointer) */
+ *(int32_t *)(save_buffer + 10) = exp_rates[1]; /* 10-11 */
+ *(int32_t *)(save_buffer + 12) = exp_seq[0]; /* 12-13 */
+ *(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, sizeof(save_buffer));
+}
+
+void alist_envmix_ge(
+ struct hle_t* hle,
+ bool init,
+ bool aux,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address)
+{
+ unsigned k;
+ size_t n = (aux) ? 4 : 2;
+
+ const int16_t* const in = (int16_t*)(hle->alist_buffer + dmemi);
+ int16_t* const dl = (int16_t*)(hle->alist_buffer + dmem_dl);
+ int16_t* const dr = (int16_t*)(hle->alist_buffer + dmem_dr);
+ int16_t* const wl = (int16_t*)(hle->alist_buffer + dmem_wl);
+ int16_t* const wr = (int16_t*)(hle->alist_buffer + dmem_wr);
+
+ 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);
+ ramps[0].target = (target[0] << 16);
+ ramps[1].target = (target[1] << 16);
+ ramps[0].step = rate[0] / 8;
+ ramps[1].step = rate[1] / 8;
+ } else {
+ 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 */
+ ramps[1].target = *(int32_t *)(save_buffer + 6); /* 6-7 */
+ ramps[0].step = *(int32_t *)(save_buffer + 8); /* 8-9 (save_buffer is a 16bit pointer) */
+ ramps[1].step = *(int32_t *)(save_buffer + 10); /* 10-11 */
+ /* *(int32_t *)(save_buffer + 12);*/ /* 12-13 */
+ /* *(int32_t *)(save_buffer + 14);*/ /* 14-15 */
+ ramps[0].value = *(int32_t *)(save_buffer + 16); /* 12-13 */
+ ramps[1].value = *(int32_t *)(save_buffer + 18); /* 14-15 */
+ }
+
+ count >>= 1;
+ for (k = 0; k < count; ++k) {
+ int16_t gains[4];
+ int16_t* buffers[4];
+ int16_t l_vol = ramp_step(&ramps[0]);
+ int16_t r_vol = ramp_step(&ramps[1]);
+
+ buffers[0] = dl + (k^S);
+ buffers[1] = dr + (k^S);
+ buffers[2] = wl + (k^S);
+ buffers[3] = wr + (k^S);
+
+ gains[0] = clamp_s16((l_vol * dry + 0x4000) >> 15);
+ gains[1] = clamp_s16((r_vol * dry + 0x4000) >> 15);
+ gains[2] = clamp_s16((l_vol * wet + 0x4000) >> 15);
+ gains[3] = clamp_s16((r_vol * wet + 0x4000) >> 15);
+
+ alist_envmix_mix(n, buffers, gains, in[k^S]);
+ }
+
+ *(int16_t *)(save_buffer + 0) = wet; /* 0-1 */
+ *(int16_t *)(save_buffer + 2) = dry; /* 2-3 */
+ *(int32_t *)(save_buffer + 4) = (int32_t)ramps[0].target; /* 4-5 */
+ *(int32_t *)(save_buffer + 6) = (int32_t)ramps[1].target; /* 6-7 */
+ *(int32_t *)(save_buffer + 8) = (int32_t)ramps[0].step; /* 8-9 (save_buffer is a 16bit pointer) */
+ *(int32_t *)(save_buffer + 10) = (int32_t)ramps[1].step; /* 10-11 */
+ /**(int32_t *)(save_buffer + 12);*/ /* 12-13 */
+ /**(int32_t *)(save_buffer + 14);*/ /* 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);
+}
+
+void alist_envmix_lin(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address)
+{
+ size_t k;
+ struct ramp_t ramps[2];
+ int16_t save_buffer[40];
+
+ const int16_t * const in = (int16_t*)(hle->alist_buffer + dmemi);
+ int16_t* const dl = (int16_t*)(hle->alist_buffer + dmem_dl);
+ int16_t* const dr = (int16_t*)(hle->alist_buffer + dmem_dr);
+ 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);
+ ramps[0].target = (target[0] << 16);
+ ramps[1].step = rate[1] / 8;
+ ramps[1].value = (vol[1] << 16);
+ ramps[1].target = (target[1] << 16);
+ }
+ else {
+ 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 */
+ ramps[1].target = *(int16_t *)(save_buffer + 6) << 16; /* 6-7 */
+ ramps[0].step = *(int32_t *)(save_buffer + 8); /* 8-9 (save_buffer is a 16bit pointer) */
+ ramps[1].step = *(int32_t *)(save_buffer + 10); /* 10-11 */
+ ramps[0].value = *(int32_t *)(save_buffer + 16); /* 16-17 */
+ ramps[1].value = *(int32_t *)(save_buffer + 18); /* 16-17 */
+ }
+
+ count >>= 1;
+ for(k = 0; k < count; ++k) {
+ int16_t gains[4];
+ int16_t* buffers[4];
+ int16_t l_vol = ramp_step(&ramps[0]);
+ int16_t r_vol = ramp_step(&ramps[1]);
+
+ buffers[0] = dl + (k^S);
+ buffers[1] = dr + (k^S);
+ buffers[2] = wl + (k^S);
+ buffers[3] = wr + (k^S);
+
+ gains[0] = clamp_s16((l_vol * dry + 0x4000) >> 15);
+ gains[1] = clamp_s16((r_vol * dry + 0x4000) >> 15);
+ gains[2] = clamp_s16((l_vol * wet + 0x4000) >> 15);
+ gains[3] = clamp_s16((r_vol * wet + 0x4000) >> 15);
+
+ alist_envmix_mix(4, buffers, gains, in[k^S]);
+ }
+
+ *(int16_t *)(save_buffer + 0) = wet; /* 0-1 */
+ *(int16_t *)(save_buffer + 2) = dry; /* 2-3 */
+ *(int16_t *)(save_buffer + 4) = (int16_t)(ramps[0].target >> 16); /* 4-5 */
+ *(int16_t *)(save_buffer + 6) = (int16_t)(ramps[1].target >> 16); /* 6-7 */
+ *(int32_t *)(save_buffer + 8) = (int32_t)ramps[0].step; /* 8-9 (save_buffer is a 16bit pointer) */
+ *(int32_t *)(save_buffer + 10) = (int32_t)ramps[1].step; /* 10-11 */
+ *(int32_t *)(save_buffer + 16) = (int32_t)ramps[0].value; /* 16-17 */
+ *(int32_t *)(save_buffer + 18) = (int32_t)ramps[1].value; /* 18-19 */
+ memcpy(hle->dram + address, (uint8_t *)save_buffer, 80);
+}
+
+void alist_envmix_nead(
+ struct hle_t* hle,
+ bool swap_wet_LR,
+ uint16_t dmem_dl,
+ uint16_t dmem_dr,
+ uint16_t dmem_wl,
+ uint16_t dmem_wr,
+ uint16_t dmemi,
+ unsigned count,
+ uint16_t *env_values,
+ uint16_t *env_steps,
+ const int16_t *xors)
+{
+ int16_t *in = (int16_t*)(hle->alist_buffer + dmemi);
+ int16_t *dl = (int16_t*)(hle->alist_buffer + dmem_dl);
+ int16_t *dr = (int16_t*)(hle->alist_buffer + dmem_dr);
+ int16_t *wl = (int16_t*)(hle->alist_buffer + dmem_wl);
+ int16_t *wr = (int16_t*)(hle->alist_buffer + dmem_wr);
+
+ /* make sure count is a multiple of 8 */
+ count = align(count, 8);
+
+ if (swap_wet_LR)
+ swap(&wl, &wr);
+
+ while (count != 0) {
+ size_t i;
+ for(i = 0; i < 8; ++i) {
+ int16_t l = (((int32_t)in[i^S] * (uint32_t)env_values[0]) >> 16) ^ xors[0];
+ int16_t r = (((int32_t)in[i^S] * (uint32_t)env_values[1]) >> 16) ^ xors[1];
+ int16_t l2 = (((int32_t)l * (uint32_t)env_values[2]) >> 16) ^ xors[2];
+ int16_t r2 = (((int32_t)r * (uint32_t)env_values[2]) >> 16) ^ xors[3];
+
+ dl[i^S] = clamp_s16(dl[i^S] + l);
+ dr[i^S] = clamp_s16(dr[i^S] + r);
+ wl[i^S] = clamp_s16(wl[i^S] + l2);
+ wr[i^S] = clamp_s16(wr[i^S] + r2);
+ }
+
+ env_values[0] += env_steps[0];
+ env_values[1] += env_steps[1];
+ env_values[2] += env_steps[2];
+
+ dl += 8;
+ dr += 8;
+ wl += 8;
+ wr += 8;
+ in += 8;
+ count -= 8;
+ }
+}
+
+
+void alist_mix(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t gain)
+{
+ int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
+ const int16_t *src = (int16_t*)(hle->alist_buffer + dmemi);
+
+ count >>= 1;
+
+ while(count != 0) {
+ sample_mix(dst, *src, gain);
+
+ ++dst;
+ ++src;
+ --count;
+ }
+}
+
+void alist_multQ44(struct hle_t* hle, uint16_t dmem, uint16_t count, int8_t gain)
+{
+ int16_t *dst = (int16_t*)(hle->alist_buffer + dmem);
+
+ count >>= 1;
+
+ while(count != 0) {
+ *dst = clamp_s16(*dst * gain >> 4);
+
+ ++dst;
+ --count;
+ }
+}
+
+void alist_add(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count)
+{
+ int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
+ const int16_t *src = (int16_t*)(hle->alist_buffer + dmemi);
+
+ count >>= 1;
+
+ while(count != 0) {
+ *dst = clamp_s16(*dst + *src);
+
+ ++dst;
+ ++src;
+ --count;
+ }
+}
+
+static void alist_resample_reset(struct hle_t* hle, uint16_t pos, uint32_t* pitch_accu)
+{
+ unsigned k;
+
+ for(k = 0; k < 4; ++k)
+ *sample(hle, pos + k) = 0;
+
+ *pitch_accu = 0;
+}
+
+static void alist_resample_load(struct hle_t* hle, uint32_t address, uint16_t pos, uint32_t* pitch_accu)
+{
+ *sample(hle, pos + 0) = *dram_u16(hle, address + 0);
+ *sample(hle, pos + 1) = *dram_u16(hle, address + 2);
+ *sample(hle, pos + 2) = *dram_u16(hle, address + 4);
+ *sample(hle, pos + 3) = *dram_u16(hle, address + 6);
+
+ *pitch_accu = *dram_u16(hle, address + 8);
+}
+
+static void alist_resample_save(struct hle_t* hle, uint32_t address, uint16_t pos, uint32_t pitch_accu)
+{
+ *dram_u16(hle, address + 0) = *sample(hle, pos + 0);
+ *dram_u16(hle, address + 2) = *sample(hle, pos + 1);
+ *dram_u16(hle, address + 4) = *sample(hle, pos + 2);
+ *dram_u16(hle, address + 6) = *sample(hle, pos + 3);
+
+ *dram_u16(hle, address + 8) = pitch_accu;
+}
+
+void alist_resample(
+ struct hle_t* hle,
+ bool init,
+ bool flag2,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ uint32_t pitch, /* Q16.16 */
+ uint32_t address)
+{
+ uint32_t pitch_accu;
+
+ uint16_t ipos = dmemi >> 1;
+ uint16_t opos = dmemo >> 1;
+ count >>= 1;
+ ipos -= 4;
+
+ if (flag2)
+ HleWarnMessage(hle->user_defined, "alist_resample: flag2 is not implemented");
+
+ if (init)
+ alist_resample_reset(hle, ipos, &pitch_accu);
+ else
+ alist_resample_load(hle, address, ipos, &pitch_accu);
+
+ while (count != 0) {
+ const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8);
+
+ *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);
+ pitch_accu &= 0xffff;
+ --count;
+ }
+
+ alist_resample_save(hle, address, ipos, pitch_accu);
+}
+
+void alist_resample_zoh(
+ struct hle_t* hle,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ uint32_t pitch,
+ uint32_t pitch_accu)
+{
+ uint16_t ipos = dmemi >> 1;
+ uint16_t opos = dmemo >> 1;
+ count >>= 1;
+
+ while(count != 0) {
+
+ *sample(hle, opos++) = *sample(hle, ipos);
+
+ pitch_accu += pitch;
+ ipos += (pitch_accu >> 16);
+ pitch_accu &= 0xffff;
+ --count;
+ }
+}
+
+typedef unsigned int (*adpcm_predict_frame_t)(struct hle_t* hle,
+ int16_t* dst, uint16_t dmemi, unsigned char scale);
+
+static unsigned int adpcm_predict_frame_4bits(struct hle_t* hle,
+ int16_t* dst, uint16_t dmemi, unsigned char scale)
+{
+ unsigned int i;
+ unsigned int rshift = (scale < 12) ? 12 - scale : 0;
+
+ for(i = 0; i < 8; ++i) {
+ uint8_t byte = *alist_u8(hle, dmemi++);
+
+ *(dst++) = adpcm_predict_sample(byte, 0xf0, 8, rshift);
+ *(dst++) = adpcm_predict_sample(byte, 0x0f, 12, rshift);
+ }
+
+ return 8;
+}
+
+static unsigned int adpcm_predict_frame_2bits(struct hle_t* hle,
+ int16_t* dst, uint16_t dmemi, unsigned char scale)
+{
+ unsigned int i;
+ unsigned int rshift = (scale < 14) ? 14 - scale : 0;
+
+ for(i = 0; i < 4; ++i) {
+ uint8_t byte = *alist_u8(hle, dmemi++);
+
+ *(dst++) = adpcm_predict_sample(byte, 0xc0, 8, rshift);
+ *(dst++) = adpcm_predict_sample(byte, 0x30, 10, rshift);
+ *(dst++) = adpcm_predict_sample(byte, 0x0c, 12, rshift);
+ *(dst++) = adpcm_predict_sample(byte, 0x03, 14, rshift);
+ }
+
+ return 4;
+}
+
+void alist_adpcm(
+ struct hle_t* hle,
+ bool init,
+ bool loop,
+ bool two_bit_per_sample,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ const int16_t* codebook,
+ uint32_t loop_address,
+ uint32_t last_frame_address)
+{
+ int16_t last_frame[16];
+ size_t i;
+
+ adpcm_predict_frame_t predict_frame = (two_bit_per_sample)
+ ? adpcm_predict_frame_2bits
+ : adpcm_predict_frame_4bits;
+
+ assert((count & 0x1f) == 0);
+
+ if (init)
+ memset(last_frame, 0, 16*sizeof(last_frame[0]));
+ else
+ dram_load_u16(hle, (uint16_t*)last_frame, (loop) ? loop_address : last_frame_address, 16);
+
+ for(i = 0; i < 16; ++i, dmemo += 2)
+ *alist_s16(hle, dmemo) = last_frame[i];
+
+ while (count != 0) {
+ int16_t frame[16];
+ uint8_t code = *alist_u8(hle, dmemi++);
+ unsigned char scale = (code & 0xf0) >> 4;
+ const int16_t* const cb_entry = codebook + ((code & 0xf) << 4);
+
+ dmemi += predict_frame(hle, frame, dmemi, scale);
+
+ adpcm_compute_residuals(last_frame , frame , cb_entry, last_frame + 14, 8);
+ adpcm_compute_residuals(last_frame + 8, frame + 8, cb_entry, last_frame + 6 , 8);
+
+ for(i = 0; i < 16; ++i, dmemo += 2)
+ *alist_s16(hle, dmemo) = last_frame[i];
+
+ count -= 32;
+ }
+
+ dram_store_u16(hle, (uint16_t*)last_frame, last_frame_address, 16);
+}
+
+
+void alist_filter(
+ struct hle_t* hle,
+ uint16_t dmem,
+ uint16_t count,
+ uint32_t address,
+ const uint32_t* lut_address)
+{
+ int x;
+ int16_t outbuff[0x3c0];
+ int16_t *outp = outbuff;
+
+ int16_t* const lutt6 = (int16_t*)(hle->dram + lut_address[0]);
+ int16_t* const lutt5 = (int16_t*)(hle->dram + lut_address[1]);
+
+ int16_t* in1 = (int16_t*)(hle->dram + address);
+ int16_t* in2 = (int16_t*)(hle->alist_buffer + dmem);
+
+
+ for (x = 0; x < 8; ++x) {
+ int32_t v = (lutt5[x] + lutt6[x]) >> 1;
+ lutt5[x] = lutt6[x] = v;
+ }
+
+ for (x = 0; x < count; x += 16) {
+ int32_t v[8];
+
+ v[1] = in1[0] * lutt6[6];
+ v[1] += in1[3] * lutt6[7];
+ v[1] += in1[2] * lutt6[4];
+ v[1] += in1[5] * lutt6[5];
+ v[1] += in1[4] * lutt6[2];
+ v[1] += in1[7] * lutt6[3];
+ v[1] += in1[6] * lutt6[0];
+ v[1] += in2[1] * lutt6[1]; /* 1 */
+
+ v[0] = in1[3] * lutt6[6];
+ v[0] += in1[2] * lutt6[7];
+ v[0] += in1[5] * lutt6[4];
+ v[0] += in1[4] * lutt6[5];
+ v[0] += in1[7] * lutt6[2];
+ v[0] += in1[6] * lutt6[3];
+ v[0] += in2[1] * lutt6[0];
+ v[0] += in2[0] * lutt6[1];
+
+ v[3] = in1[2] * lutt6[6];
+ v[3] += in1[5] * lutt6[7];
+ v[3] += in1[4] * lutt6[4];
+ v[3] += in1[7] * lutt6[5];
+ v[3] += in1[6] * lutt6[2];
+ v[3] += in2[1] * lutt6[3];
+ v[3] += in2[0] * lutt6[0];
+ v[3] += in2[3] * lutt6[1];
+
+ v[2] = in1[5] * lutt6[6];
+ v[2] += in1[4] * lutt6[7];
+ v[2] += in1[7] * lutt6[4];
+ v[2] += in1[6] * lutt6[5];
+ v[2] += in2[1] * lutt6[2];
+ v[2] += in2[0] * lutt6[3];
+ v[2] += in2[3] * lutt6[0];
+ v[2] += in2[2] * lutt6[1];
+
+ v[5] = in1[4] * lutt6[6];
+ v[5] += in1[7] * lutt6[7];
+ v[5] += in1[6] * lutt6[4];
+ v[5] += in2[1] * lutt6[5];
+ v[5] += in2[0] * lutt6[2];
+ v[5] += in2[3] * lutt6[3];
+ v[5] += in2[2] * lutt6[0];
+ v[5] += in2[5] * lutt6[1];
+
+ v[4] = in1[7] * lutt6[6];
+ v[4] += in1[6] * lutt6[7];
+ v[4] += in2[1] * lutt6[4];
+ v[4] += in2[0] * lutt6[5];
+ v[4] += in2[3] * lutt6[2];
+ v[4] += in2[2] * lutt6[3];
+ v[4] += in2[5] * lutt6[0];
+ v[4] += in2[4] * lutt6[1];
+
+ v[7] = in1[6] * lutt6[6];
+ v[7] += in2[1] * lutt6[7];
+ v[7] += in2[0] * lutt6[4];
+ v[7] += in2[3] * lutt6[5];
+ v[7] += in2[2] * lutt6[2];
+ v[7] += in2[5] * lutt6[3];
+ v[7] += in2[4] * lutt6[0];
+ v[7] += in2[7] * lutt6[1];
+
+ v[6] = in2[1] * lutt6[6];
+ v[6] += in2[0] * lutt6[7];
+ v[6] += in2[3] * lutt6[4];
+ v[6] += in2[2] * lutt6[5];
+ v[6] += in2[5] * lutt6[2];
+ v[6] += in2[4] * lutt6[3];
+ v[6] += in2[7] * lutt6[0];
+ v[6] += in2[6] * lutt6[1];
+
+ outp[1] = ((v[1] + 0x4000) >> 15);
+ outp[0] = ((v[0] + 0x4000) >> 15);
+ outp[3] = ((v[3] + 0x4000) >> 15);
+ outp[2] = ((v[2] + 0x4000) >> 15);
+ outp[5] = ((v[5] + 0x4000) >> 15);
+ outp[4] = ((v[4] + 0x4000) >> 15);
+ outp[7] = ((v[7] + 0x4000) >> 15);
+ outp[6] = ((v[6] + 0x4000) >> 15);
+ in1 = in2;
+ in2 += 8;
+ outp += 8;
+ }
+
+ memcpy(hle->dram + address, in2 - 8, 16);
+ memcpy(hle->alist_buffer + dmem, outbuff, count);
+}
+
+void alist_polef(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ uint16_t gain,
+ int16_t* table,
+ uint32_t address)
+{
+ int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
+
+ const int16_t* const h1 = table;
+ int16_t* const h2 = table + 8;
+
+ unsigned i;
+ int16_t l1, l2;
+ int16_t h2_before[8];
+
+ count = align(count, 16);
+
+ if (init) {
+ l1 = 0;
+ l2 = 0;
+ }
+ else {
+ l1 = *dram_u16(hle, address + 4);
+ l2 = *dram_u16(hle, address + 6);
+ }
+
+ for(i = 0; i < 8; ++i) {
+ h2_before[i] = h2[i];
+ h2[i] = (((int32_t)h2[i] * gain) >> 14);
+ }
+
+ do
+ {
+ int16_t frame[8];
+
+ for(i = 0; i < 8; ++i, dmemi += 2)
+ frame[i] = *alist_s16(hle, dmemi);
+
+ for(i = 0; i < 8; ++i) {
+ int32_t accu = frame[i] * gain;
+ accu += h1[i]*l1 + h2_before[i]*l2 + rdot(i, h2, frame);
+ dst[i^S] = clamp_s16(accu >> 14);
+ }
+
+ l1 = dst[6^S];
+ l2 = dst[7^S];
+
+ dst += 8;
+ count -= 16;
+ } while (count != 0);
+
+ dram_store_u32(hle, (uint32_t*)(dst - 4), address, 2);
+}
+
+void alist_iirf(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ int16_t* table,
+ uint32_t address)
+{
+ int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
+ int32_t i, prev;
+ int16_t frame[8];
+ int16_t ibuf[4];
+ uint16_t index = 7;
+
+
+ count = align(count, 16);
+
+ if(init)
+ {
+ for(i = 0; i < 8; ++i)
+ frame[i] = 0;
+ ibuf[1] = 0;
+ ibuf[2] = 0;
+ }
+ else
+ {
+ frame[6] = *dram_u16(hle, address + 4);
+ frame[7] = *dram_u16(hle, address + 6);
+ ibuf[1] = (int16_t)*dram_u16(hle, address + 8);
+ ibuf[2] = (int16_t)*dram_u16(hle, address + 10);
+ }
+
+ prev = vmulf(table[9], frame[6]) * 2;
+ do
+ {
+ for(i = 0; i < 8; ++i)
+ {
+ int32_t accu;
+ ibuf[index&3] = *alist_s16(hle, dmemi);
+
+ accu = prev + vmulf(table[0], ibuf[index&3]) + vmulf(table[1], ibuf[(index-1)&3]) + vmulf(table[0], ibuf[(index-2)&3]);
+ accu += vmulf(table[8], frame[index]) * 2;
+ prev = vmulf(table[9], frame[index]) * 2;
+ dst[i^S] = frame[i] = accu;
+
+ index=(index+1)&7;
+ dmemi += 2;
+ }
+ dst += 8;
+ count -= 0x10;
+ } while (count > 0);
+
+ dram_store_u16(hle, (uint16_t*)&frame[6], address + 4, 4);
+ dram_store_u16(hle, (uint16_t*)&ibuf[(index-2)&3], address+8, 2);
+ dram_store_u16(hle, (uint16_t*)&ibuf[(index-1)&3], address+10, 2);
+}
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist.h b/libmupen64plus/mupen64plus-rsp-hle/src/alist.h
index 43f9f04bcb..398cdb8179 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/alist.h
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/alist.h
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - alist.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2002 Hacktarux *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* *
* 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 *
@@ -19,15 +19,152 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifndef ALIST_H
-#define ALIST_H
+#ifndef ALIST_INTERNAL_H
+#define ALIST_INTERNAL_H
-void alist_process_ABI1();
-void alist_process_ABI2();
-void alist_process_ABI3();
+#include
+#include
+#include
-// FIXME: to remove when isZeldaABI/isMKABI workaround is gone
-void init_ucode2();
+struct hle_t;
+
+typedef void (*acmd_callback_t)(struct hle_t* hle, uint32_t w1, uint32_t w2);
+
+void alist_process(struct hle_t* hle, const acmd_callback_t abi[], unsigned int abi_size);
+uint32_t alist_get_address(struct hle_t* hle, uint32_t so, const uint32_t *segments, size_t n);
+void alist_set_address(struct hle_t* hle, uint32_t so, uint32_t *segments, size_t n);
+void alist_clear(struct hle_t* hle, uint16_t dmem, uint16_t count);
+void alist_load(struct hle_t* hle, uint16_t dmem, uint32_t address, uint16_t count);
+void alist_save(struct hle_t* hle, uint16_t dmem, uint32_t address, uint16_t count);
+void alist_move(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count);
+void alist_copy_every_other_sample(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count);
+void alist_repeat64(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint8_t count);
+void alist_copy_blocks(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t block_size, uint8_t count);
+void alist_interleave(struct hle_t* hle, uint16_t dmemo, uint16_t left, uint16_t right, uint16_t count);
+
+void alist_envmix_exp(
+ struct hle_t* hle,
+ bool init,
+ bool aux,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address);
+
+void alist_envmix_ge(
+ struct hle_t* hle,
+ bool init,
+ bool aux,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address);
+
+void alist_envmix_lin(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmem_dl, uint16_t dmem_dr,
+ uint16_t dmem_wl, uint16_t dmem_wr,
+ uint16_t dmemi, uint16_t count,
+ int16_t dry, int16_t wet,
+ const int16_t *vol,
+ const int16_t *target,
+ const int32_t *rate,
+ uint32_t address);
+
+void alist_envmix_nead(
+ struct hle_t* hle,
+ bool swap_wet_LR,
+ uint16_t dmem_dl,
+ uint16_t dmem_dr,
+ uint16_t dmem_wl,
+ uint16_t dmem_wr,
+ uint16_t dmemi,
+ unsigned count,
+ uint16_t *env_values,
+ uint16_t *env_steps,
+ const int16_t *xors);
+
+void alist_mix(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t gain);
+void alist_multQ44(struct hle_t* hle, uint16_t dmem, uint16_t count, int8_t gain);
+void alist_add(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count);
+
+void alist_adpcm(
+ struct hle_t* hle,
+ bool init,
+ bool loop,
+ bool two_bit_per_sample,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ const int16_t* codebook,
+ uint32_t loop_address,
+ uint32_t last_frame_address);
+
+void alist_resample(
+ struct hle_t* hle,
+ bool init,
+ bool flag2,
+ uint16_t dmemo, uint16_t dmemi, uint16_t count,
+ uint32_t pitch, uint32_t address);
+
+void alist_resample_zoh(
+ struct hle_t* hle,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ uint32_t pitch,
+ uint32_t pitch_accu);
+
+void alist_filter(
+ struct hle_t* hle,
+ uint16_t dmem,
+ uint16_t count,
+ uint32_t address,
+ const uint32_t* lut_address);
+
+void alist_polef(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ uint16_t gain,
+ int16_t* table,
+ uint32_t address);
+
+void alist_iirf(
+ struct hle_t* hle,
+ bool init,
+ uint16_t dmemo,
+ uint16_t dmemi,
+ uint16_t count,
+ int16_t* table,
+ uint32_t address);
+
+/*
+ * Audio flags
+ */
+
+#define A_INIT 0x01
+#define A_CONTINUE 0x00
+#define A_LOOP 0x02
+#define A_OUT 0x02
+#define A_LEFT 0x02
+#define A_RIGHT 0x00
+#define A_VOL 0x04
+#define A_RATE 0x00
+#define A_AUX 0x08
+#define A_NOAUX 0x00
+#define A_MAIN 0x00
+#define A_MIX 0x10
#endif
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist_audio.c b/libmupen64plus/mupen64plus-rsp-hle/src/alist_audio.c
new file mode 100644
index 0000000000..0d2dceacfb
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/alist_audio.c
@@ -0,0 +1,310 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - alist_audio.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+#include
+
+#include "alist.h"
+#include "common.h"
+#include "hle_internal.h"
+#include "memory.h"
+#include "ucodes.h"
+
+enum { DMEM_BASE = 0x5c0 };
+
+/* helper functions */
+static uint32_t get_address(struct hle_t* hle, uint32_t so)
+{
+ return alist_get_address(hle, so, hle->alist_audio.segments, N_SEGMENTS);
+}
+
+static void set_address(struct hle_t* hle, uint32_t so)
+{
+ alist_set_address(hle, so, hle->alist_audio.segments, N_SEGMENTS);
+}
+
+static void clear_segments(struct hle_t* hle)
+{
+ memset(hle->alist_audio.segments, 0, N_SEGMENTS*sizeof(hle->alist_audio.segments[0]));
+}
+
+/* audio commands definition */
+static void SPNOOP(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+}
+
+static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmem = w1 + DMEM_BASE;
+ uint16_t count = w2 & 0xfff;
+
+ if (count == 0)
+ return;
+
+ alist_clear(hle, dmem, align(count, 16));
+}
+
+static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = get_address(hle, w2);
+
+ alist_envmix_exp(
+ hle,
+ flags & A_INIT,
+ flags & A_AUX,
+ hle->alist_audio.out, hle->alist_audio.dry_right,
+ hle->alist_audio.wet_left, hle->alist_audio.wet_right,
+ hle->alist_audio.in, hle->alist_audio.count,
+ hle->alist_audio.dry, hle->alist_audio.wet,
+ hle->alist_audio.vol,
+ hle->alist_audio.target,
+ hle->alist_audio.rate,
+ address);
+}
+
+static void ENVMIXER_GE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = get_address(hle, w2);
+
+ alist_envmix_ge(
+ hle,
+ flags & A_INIT,
+ flags & A_AUX,
+ hle->alist_audio.out, hle->alist_audio.dry_right,
+ hle->alist_audio.wet_left, hle->alist_audio.wet_right,
+ hle->alist_audio.in, hle->alist_audio.count,
+ hle->alist_audio.dry, hle->alist_audio.wet,
+ hle->alist_audio.vol,
+ hle->alist_audio.target,
+ hle->alist_audio.rate,
+ address);
+}
+
+static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint16_t pitch = w1;
+ uint32_t address = get_address(hle, w2);
+
+ alist_resample(
+ hle,
+ flags & A_INIT,
+ flags & 0x2,
+ hle->alist_audio.out,
+ hle->alist_audio.in,
+ align(hle->alist_audio.count, 16),
+ pitch << 1,
+ address);
+}
+
+static void SETVOL(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+
+ if (flags & A_AUX) {
+ hle->alist_audio.dry = w1;
+ hle->alist_audio.wet = w2;
+ }
+ else {
+ unsigned lr = (flags & A_LEFT) ? 0 : 1;
+
+ if (flags & A_VOL)
+ hle->alist_audio.vol[lr] = w1;
+ else {
+ hle->alist_audio.target[lr] = w1;
+ hle->alist_audio.rate[lr] = w2;
+ }
+ }
+}
+
+static void SETLOOP(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ hle->alist_audio.loop = get_address(hle, w2);
+}
+
+static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = get_address(hle, w2);
+
+ alist_adpcm(
+ hle,
+ flags & A_INIT,
+ flags & A_LOOP,
+ false, /* unsupported in this ucode */
+ hle->alist_audio.out,
+ hle->alist_audio.in,
+ align(hle->alist_audio.count, 32),
+ hle->alist_audio.table,
+ hle->alist_audio.loop,
+ address);
+}
+
+static void LOADBUFF(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ uint32_t address = get_address(hle, w2);
+
+ if (hle->alist_audio.count == 0)
+ return;
+
+ alist_load(hle, hle->alist_audio.in, address, hle->alist_audio.count);
+}
+
+static void SAVEBUFF(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ uint32_t address = get_address(hle, w2);
+
+ if (hle->alist_audio.count == 0)
+ return;
+
+ alist_save(hle, hle->alist_audio.out, address, hle->alist_audio.count);
+}
+
+static void SETBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+
+ if (flags & A_AUX) {
+ hle->alist_audio.dry_right = w1 + DMEM_BASE;
+ hle->alist_audio.wet_left = (w2 >> 16) + DMEM_BASE;
+ hle->alist_audio.wet_right = w2 + DMEM_BASE;
+ } else {
+ hle->alist_audio.in = w1 + DMEM_BASE;
+ hle->alist_audio.out = (w2 >> 16) + DMEM_BASE;
+ hle->alist_audio.count = w2;
+ }
+}
+
+static void DMEMMOVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmemi = w1 + DMEM_BASE;
+ uint16_t dmemo = (w2 >> 16) + DMEM_BASE;
+ uint16_t count = w2;
+
+ if (count == 0)
+ return;
+
+ alist_move(hle, dmemo, dmemi, align(count, 16));
+}
+
+static void LOADADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = w1;
+ uint32_t address = get_address(hle, w2);
+
+ dram_load_u16(hle, (uint16_t*)hle->alist_audio.table, address, align(count, 8) >> 1);
+}
+
+static void INTERLEAVE(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ uint16_t left = (w2 >> 16) + DMEM_BASE;
+ uint16_t right = w2 + DMEM_BASE;
+
+ if (hle->alist_audio.count == 0)
+ return;
+
+ alist_interleave(hle, hle->alist_audio.out, left, right, align(hle->alist_audio.count, 16));
+}
+
+static void MIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ int16_t gain = w1;
+ uint16_t dmemi = (w2 >> 16) + DMEM_BASE;
+ uint16_t dmemo = w2 + DMEM_BASE;
+
+ if (hle->alist_audio.count == 0)
+ return;
+
+ alist_mix(hle, dmemo, dmemi, align(hle->alist_audio.count, 32), gain);
+}
+
+static void SEGMENT(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ set_address(hle, w2);
+}
+
+static void POLEF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint16_t gain = w1;
+ uint32_t address = get_address(hle, w2);
+
+ if (hle->alist_audio.count == 0)
+ return;
+
+ alist_polef(
+ hle,
+ flags & A_INIT,
+ hle->alist_audio.out,
+ hle->alist_audio.in,
+ align(hle->alist_audio.count, 16),
+ gain,
+ hle->alist_audio.table,
+ address);
+}
+
+/* global functions */
+void alist_process_audio(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM , CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, SEGMENT,
+ SETBUFF, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, POLEF, SETLOOP
+ };
+
+ clear_segments(hle);
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_audio_ge(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM , CLEARBUFF, ENVMIXER_GE,
+ LOADBUFF, RESAMPLE, SAVEBUFF, SEGMENT,
+ SETBUFF, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, POLEF, SETLOOP
+ };
+
+ clear_segments(hle);
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_audio_bc(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM , CLEARBUFF, ENVMIXER_GE,
+ LOADBUFF, RESAMPLE, SAVEBUFF, SEGMENT,
+ SETBUFF, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, POLEF, SETLOOP
+ };
+
+ clear_segments(hle);
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist_naudio.c b/libmupen64plus/mupen64plus-rsp-hle/src/alist_naudio.c
new file mode 100644
index 0000000000..bb53dd77b8
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/alist_naudio.c
@@ -0,0 +1,333 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - alist_naudio.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+
+#include "alist.h"
+#include "common.h"
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+#include "ucodes.h"
+
+enum { NAUDIO_COUNT = 0x170 }; /* ie 184 samples */
+enum {
+ NAUDIO_MAIN = 0x4f0,
+ NAUDIO_MAIN2 = 0x660,
+ NAUDIO_DRY_LEFT = 0x9d0,
+ NAUDIO_DRY_RIGHT = 0xb40,
+ NAUDIO_WET_LEFT = 0xcb0,
+ NAUDIO_WET_RIGHT = 0xe20
+};
+
+
+/* audio commands definition */
+static void UNKNOWN(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t acmd = (w1 >> 24);
+
+ HleWarnMessage(hle->user_defined,
+ "Unknown audio command %d: %08x %08x",
+ acmd, w1, w2);
+}
+
+
+static void SPNOOP(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+}
+
+static void NAUDIO_0000(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ /* ??? */
+ UNKNOWN(hle, w1, w2);
+}
+
+static void NAUDIO_02B0(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ /* emulate code at 0x12b0 (inside SETVOL), because PC always execute in IMEM */
+ hle->alist_naudio.rate[1] &= ~0xffff;
+ hle->alist_naudio.rate[1] |= (w2 & 0xffff);
+}
+
+static void NAUDIO_14(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint16_t gain = w1;
+ uint8_t select_main = (w2 >> 24);
+ uint32_t address = (w2 & 0xffffff);
+
+ uint16_t dmem = (select_main == 0) ? NAUDIO_MAIN : NAUDIO_MAIN2;
+
+ if (hle->alist_naudio.table[0] == 0 && hle->alist_naudio.table[1] == 0) {
+ alist_polef(
+ hle,
+ flags & A_INIT,
+ dmem,
+ dmem,
+ NAUDIO_COUNT,
+ gain,
+ hle->alist_naudio.table,
+ address);
+ }
+ else
+ {
+ alist_iirf(
+ hle,
+ flags & A_INIT,
+ dmem,
+ dmem,
+ NAUDIO_COUNT,
+ hle->alist_naudio.table,
+ address);
+ }
+
+}
+
+static void SETVOL(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+
+ 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 { /* A_RIGHT */
+ hle->alist_naudio.target[1] = w1;
+ hle->alist_naudio.rate[1] = w2;
+ }
+ }
+ else { /* A_RATE */
+ hle->alist_naudio.target[0] = w1;
+ hle->alist_naudio.rate[0] = w2;
+ }
+}
+
+static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = (w2 & 0xffffff);
+
+ hle->alist_naudio.vol[1] = w1;
+
+ alist_envmix_lin(
+ hle,
+ flags & A_INIT,
+ NAUDIO_DRY_LEFT,
+ NAUDIO_DRY_RIGHT,
+ NAUDIO_WET_LEFT,
+ NAUDIO_WET_RIGHT,
+ NAUDIO_MAIN,
+ NAUDIO_COUNT,
+ hle->alist_naudio.dry,
+ hle->alist_naudio.wet,
+ hle->alist_naudio.vol,
+ hle->alist_naudio.target,
+ hle->alist_naudio.rate,
+ address);
+}
+
+static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmem = w1 + NAUDIO_MAIN;
+ uint16_t count = w2 & 0xfff;
+
+ alist_clear(hle, dmem, count);
+}
+
+static void MIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ int16_t gain = w1;
+ uint16_t dmemi = (w2 >> 16) + NAUDIO_MAIN;
+ uint16_t dmemo = w2 + NAUDIO_MAIN;
+
+ alist_mix(hle, dmemo, dmemi, NAUDIO_COUNT, gain);
+}
+
+static void LOADBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xfff;
+ uint16_t dmem = (w1 & 0xfff) + NAUDIO_MAIN;
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_load(hle, dmem, address, count);
+}
+
+static void SAVEBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xfff;
+ uint16_t dmem = (w1 & 0xfff) + NAUDIO_MAIN;
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_save(hle, dmem, address, count);
+}
+
+static void LOADADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = w1;
+ uint32_t address = (w2 & 0xffffff);
+
+ dram_load_u16(hle, (uint16_t*)hle->alist_naudio.table, address, count >> 1);
+}
+
+static void DMEMMOVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmemi = w1 + NAUDIO_MAIN;
+ uint16_t dmemo = (w2 >> 16) + NAUDIO_MAIN;
+ uint16_t count = w2;
+
+ alist_move(hle, dmemo, dmemi, (count + 3) & ~3);
+}
+
+static void SETLOOP(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ hle->alist_naudio.loop = (w2 & 0xffffff);
+}
+
+static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint32_t address = (w1 & 0xffffff);
+ uint8_t flags = (w2 >> 28);
+ uint16_t count = (w2 >> 16) & 0xfff;
+ uint16_t dmemi = ((w2 >> 12) & 0xf) + NAUDIO_MAIN;
+ uint16_t dmemo = (w2 & 0xfff) + NAUDIO_MAIN;
+
+ alist_adpcm(
+ hle,
+ flags & A_INIT,
+ flags & A_LOOP,
+ false, /* unsuported by this ucode */
+ dmemo,
+ dmemi,
+ (count + 0x1f) & ~0x1f,
+ hle->alist_naudio.table,
+ hle->alist_naudio.loop,
+ address);
+}
+
+static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint32_t address = (w1 & 0xffffff);
+ uint8_t flags = (w2 >> 30);
+ uint16_t pitch = (w2 >> 14);
+ uint16_t dmemi = ((w2 >> 2) & 0xfff) + NAUDIO_MAIN;
+ uint16_t dmemo = (w2 & 0x3) ? NAUDIO_MAIN2 : NAUDIO_MAIN;
+
+ alist_resample(
+ hle,
+ flags & A_INIT,
+ false, /* TODO: check which ABI supports it */
+ dmemo,
+ dmemi,
+ NAUDIO_COUNT,
+ pitch << 1,
+ address);
+}
+
+static void INTERLEAVE(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+ alist_interleave(hle, NAUDIO_MAIN, NAUDIO_DRY_LEFT, NAUDIO_DRY_RIGHT, NAUDIO_COUNT);
+}
+
+static void MP3ADDY(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+}
+
+static void MP3(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ unsigned index = (w1 & 0x1e);
+ uint32_t address = (w2 & 0xffffff);
+
+ mp3_task(hle, index, address);
+}
+
+/* global functions */
+void alist_process_naudio(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM, CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, NAUDIO_0000,
+ NAUDIO_0000, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
+ };
+
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_naudio_bk(struct hle_t* hle)
+{
+ /* TODO: see what differs from alist_process_naudio */
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM, CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, NAUDIO_0000,
+ NAUDIO_0000, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
+ };
+
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_naudio_dk(struct hle_t* hle)
+{
+ /* TODO: see what differs from alist_process_naudio */
+ static const acmd_callback_t ABI[0x10] = {
+ SPNOOP, ADPCM, CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, MIXER,
+ MIXER, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
+ };
+
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_naudio_mp3(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x10] = {
+ UNKNOWN, ADPCM, CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, MP3,
+ MP3ADDY, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, NAUDIO_14, SETLOOP
+ };
+
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_naudio_cbfd(struct hle_t* hle)
+{
+ /* TODO: see what differs from alist_process_naudio_mp3 */
+ static const acmd_callback_t ABI[0x10] = {
+ UNKNOWN, ADPCM, CLEARBUFF, ENVMIXER,
+ LOADBUFF, RESAMPLE, SAVEBUFF, MP3,
+ MP3ADDY, SETVOL, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, NAUDIO_14, SETLOOP
+ };
+
+ alist_process(hle, ABI, 0x10);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist_nead.c b/libmupen64plus/mupen64plus-rsp-hle/src/alist_nead.c
new file mode 100644
index 0000000000..11dcb80595
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/alist_nead.c
@@ -0,0 +1,556 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - alist_nead.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+
+#include "alist.h"
+#include "common.h"
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+#include "ucodes.h"
+
+/* remove windows define to 0x06 */
+#ifdef DUPLICATE
+#undef DUPLICATE
+#endif
+
+/* audio commands definition */
+static void UNKNOWN(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t acmd = (w1 >> 24);
+
+ HleWarnMessage(hle->user_defined,
+ "Unknown audio command %d: %08x %08x",
+ acmd, w1, w2);
+}
+
+
+static void SPNOOP(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+}
+
+static void LOADADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = w1;
+ uint32_t address = (w2 & 0xffffff);
+
+ dram_load_u16(hle, (uint16_t*)hle->alist_nead.table, address, count >> 1);
+}
+
+static void SETLOOP(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ hle->alist_nead.loop = w2 & 0xffffff;
+}
+
+static void SETBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ hle->alist_nead.in = w1;
+ hle->alist_nead.out = (w2 >> 16);
+ hle->alist_nead.count = w2;
+}
+
+static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_adpcm(
+ hle,
+ flags & 0x1,
+ flags & 0x2,
+ flags & 0x4,
+ hle->alist_nead.out,
+ hle->alist_nead.in,
+ (hle->alist_nead.count + 0x1f) & ~0x1f,
+ hle->alist_nead.table,
+ hle->alist_nead.loop,
+ address);
+}
+
+static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmem = w1;
+ uint16_t count = w2 & 0xfff;
+
+ if (count == 0)
+ return;
+
+ alist_clear(hle, dmem, count);
+}
+
+static void LOADBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xfff;
+ uint16_t dmem = (w1 & 0xfff);
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_load(hle, dmem, address, count);
+}
+
+static void SAVEBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xfff;
+ uint16_t dmem = (w1 & 0xfff);
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_save(hle, dmem, address, count);
+}
+
+static void MIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xff0;
+ int16_t gain = w1;
+ uint16_t dmemi = (w2 >> 16);
+ uint16_t dmemo = w2;
+
+ alist_mix(hle, dmemo, dmemi, count, gain);
+}
+
+
+static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint16_t pitch = w1;
+ uint32_t address = (w2 & 0xffffff);
+
+ alist_resample(
+ hle,
+ flags & 0x1,
+ false, /* TODO: check which ABI supports it */
+ hle->alist_nead.out,
+ hle->alist_nead.in,
+ (hle->alist_nead.count + 0xf) & ~0xf,
+ pitch << 1,
+ address);
+}
+
+static void RESAMPLE_ZOH(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t pitch = w1;
+ uint16_t pitch_accu = w2;
+
+ alist_resample_zoh(
+ hle,
+ hle->alist_nead.out,
+ hle->alist_nead.in,
+ hle->alist_nead.count,
+ pitch << 1,
+ pitch_accu);
+}
+
+static void DMEMMOVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t dmemi = w1;
+ uint16_t dmemo = (w2 >> 16);
+ uint16_t count = w2;
+
+ if (count == 0)
+ return;
+
+ alist_move(hle, dmemo, dmemi, (count + 3) & ~3);
+}
+
+static void ENVSETUP1_MK(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ hle->alist_nead.env_values[2] = (w1 >> 8) & 0xff00;
+ hle->alist_nead.env_steps[2] = 0;
+ hle->alist_nead.env_steps[0] = (w2 >> 16);
+ hle->alist_nead.env_steps[1] = w2;
+}
+
+static void ENVSETUP1(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ hle->alist_nead.env_values[2] = (w1 >> 8) & 0xff00;
+ hle->alist_nead.env_steps[2] = w1;
+ hle->alist_nead.env_steps[0] = (w2 >> 16);
+ hle->alist_nead.env_steps[1] = w2;
+}
+
+static void ENVSETUP2(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ hle->alist_nead.env_values[0] = (w2 >> 16);
+ hle->alist_nead.env_values[1] = w2;
+}
+
+static void ENVMIXER_MK(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ int16_t xors[4];
+
+ uint16_t dmemi = (w1 >> 12) & 0xff0;
+ uint8_t count = (w1 >> 8) & 0xff;
+ uint16_t dmem_dl = (w2 >> 20) & 0xff0;
+ uint16_t dmem_dr = (w2 >> 12) & 0xff0;
+ uint16_t dmem_wl = (w2 >> 4) & 0xff0;
+ uint16_t dmem_wr = (w2 << 4) & 0xff0;
+
+ xors[2] = 0; /* unsupported by this ucode */
+ xors[3] = 0; /* unsupported by this ucode */
+ xors[0] = 0 - (int16_t)((w1 & 0x2) >> 1);
+ xors[1] = 0 - (int16_t)((w1 & 0x1) );
+
+ alist_envmix_nead(
+ hle,
+ false, /* unsupported by this ucode */
+ dmem_dl, dmem_dr,
+ dmem_wl, dmem_wr,
+ dmemi, count,
+ hle->alist_nead.env_values,
+ hle->alist_nead.env_steps,
+ xors);
+}
+
+static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ int16_t xors[4];
+
+ uint16_t dmemi = (w1 >> 12) & 0xff0;
+ uint8_t count = (w1 >> 8) & 0xff;
+ bool swap_wet_LR = (w1 >> 4) & 0x1;
+ uint16_t dmem_dl = (w2 >> 20) & 0xff0;
+ uint16_t dmem_dr = (w2 >> 12) & 0xff0;
+ uint16_t dmem_wl = (w2 >> 4) & 0xff0;
+ uint16_t dmem_wr = (w2 << 4) & 0xff0;
+
+ xors[2] = 0 - (int16_t)((w1 & 0x8) >> 1);
+ xors[3] = 0 - (int16_t)((w1 & 0x4) >> 1);
+ xors[0] = 0 - (int16_t)((w1 & 0x2) >> 1);
+ xors[1] = 0 - (int16_t)((w1 & 0x1) );
+
+ alist_envmix_nead(
+ hle,
+ swap_wet_LR,
+ dmem_dl, dmem_dr,
+ dmem_wl, dmem_wr,
+ dmemi, count,
+ hle->alist_nead.env_values,
+ hle->alist_nead.env_steps,
+ xors);
+}
+
+static void DUPLICATE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t count = (w1 >> 16);
+ uint16_t dmemi = w1;
+ uint16_t dmemo = (w2 >> 16);
+
+ alist_repeat64(hle, dmemo, dmemi, count);
+}
+
+static void INTERL(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = w1;
+ uint16_t dmemi = (w2 >> 16);
+ uint16_t dmemo = w2;
+
+ alist_copy_every_other_sample(hle, dmemo, dmemi, count);
+}
+
+static void INTERLEAVE_MK(struct hle_t* hle, uint32_t UNUSED(w1), uint32_t w2)
+{
+ uint16_t left = (w2 >> 16);
+ uint16_t right = w2;
+
+ if (hle->alist_nead.count == 0)
+ return;
+
+ alist_interleave(hle, hle->alist_nead.out, left, right, hle->alist_nead.count);
+}
+
+static void INTERLEAVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = ((w1 >> 12) & 0xff0);
+ uint16_t dmemo = w1;
+ uint16_t left = (w2 >> 16);
+ uint16_t right = w2;
+
+ alist_interleave(hle, dmemo, left, right, count);
+}
+
+static void ADDMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint16_t count = (w1 >> 12) & 0xff0;
+ uint16_t dmemi = (w2 >> 16);
+ uint16_t dmemo = w2;
+
+ alist_add(hle, dmemo, dmemi, count);
+}
+
+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 & 0xfff;
+ uint16_t dmem = (w2 >> 16);
+
+ alist_multQ44(hle, dmem, count, gain);
+}
+
+static void FILTER(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint32_t address = (w2 & 0xffffff);
+
+ if (flags > 1) {
+ hle->alist_nead.filter_count = w1;
+ hle->alist_nead.filter_lut_address[0] = address; /* t6 */
+ }
+ else {
+ uint16_t dmem = w1;
+
+ hle->alist_nead.filter_lut_address[1] = address + 0x10; /* t5 */
+ alist_filter(hle, dmem, hle->alist_nead.filter_count, address, hle->alist_nead.filter_lut_address);
+ }
+}
+
+static void SEGMENT(struct hle_t* UNUSED(hle), uint32_t UNUSED(w1), uint32_t UNUSED(w2))
+{
+}
+
+static void NEAD_16(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t count = (w1 >> 16);
+ uint16_t dmemi = w1;
+ uint16_t dmemo = (w2 >> 16);
+ uint16_t block_size = w2;
+
+ alist_copy_blocks(hle, dmemo, dmemi, block_size, count);
+}
+
+static void POLEF(struct hle_t* hle, uint32_t w1, uint32_t w2)
+{
+ uint8_t flags = (w1 >> 16);
+ uint16_t gain = w1;
+ uint32_t address = (w2 & 0xffffff);
+
+ if (hle->alist_nead.count == 0)
+ return;
+
+ alist_polef(
+ hle,
+ flags & A_INIT,
+ hle->alist_nead.out,
+ hle->alist_nead.in,
+ hle->alist_nead.count,
+ gain,
+ hle->alist_nead.table,
+ address);
+}
+
+
+void alist_process_nead_mk(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x20] = {
+ SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
+ SPNOOP, RESAMPLE, SPNOOP, SEGMENT,
+ SETBUFF, SPNOOP, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE_MK, POLEF, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1_MK, ENVMIXER_MK,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, SPNOOP,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP
+ };
+
+ alist_process(hle, ABI, 0x20);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_sf(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x20] = {
+ SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, SPNOOP,
+ SETBUFF, SPNOOP, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE_MK, POLEF, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, SPNOOP,
+ HILOGAIN, UNKNOWN, DUPLICATE, SPNOOP,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP
+ };
+
+ alist_process(hle, ABI, 0x20);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_sfj(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x20] = {
+ SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, SPNOOP,
+ SETBUFF, SPNOOP, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE_MK, POLEF, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN,
+ HILOGAIN, UNKNOWN, DUPLICATE, SPNOOP,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP
+ };
+
+ alist_process(hle, ABI, 0x20);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_fz(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x20] = {
+ UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, SPNOOP, SPNOOP,
+ SETBUFF, SPNOOP, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, SPNOOP, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN,
+ SPNOOP, UNKNOWN, DUPLICATE, SPNOOP,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP
+ };
+
+ alist_process(hle, ABI, 0x20);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_wrjb(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x20] = {
+ SPNOOP, ADPCM, CLEARBUFF, UNKNOWN,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, SPNOOP,
+ SETBUFF, SPNOOP, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, SPNOOP, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN,
+ HILOGAIN, UNKNOWN, DUPLICATE, FILTER,
+ SPNOOP, SPNOOP, SPNOOP, SPNOOP
+ };
+
+ alist_process(hle, ABI, 0x20);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_ys(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ alist_process(hle, ABI, 0x18);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_1080(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ alist_process(hle, ABI, 0x18);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_oot(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ alist_process(hle, ABI, 0x18);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_mm(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ alist_process(hle, ABI, 0x18);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_mmb(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ alist_process(hle, ABI, 0x18);
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+void alist_process_nead_ac(struct hle_t* hle)
+{
+ static const acmd_callback_t ABI[0x18] = {
+ UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
+ ADDMIXER, RESAMPLE, RESAMPLE_ZOH, FILTER,
+ SETBUFF, DUPLICATE, DMEMMOVE, LOADADPCM,
+ MIXER, INTERLEAVE, HILOGAIN, SETLOOP,
+ NEAD_16, INTERL, ENVSETUP1, ENVMIXER,
+ LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
+ };
+
+ 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/libmupen64plus/mupen64plus-rsp-hle/src/jpeg.h b/libmupen64plus/mupen64plus-rsp-hle/src/arithmetics.h
similarity index 71%
rename from libmupen64plus/mupen64plus-rsp-hle/src/jpeg.h
rename to libmupen64plus/mupen64plus-rsp-hle/src/arithmetics.h
index b7deaf6cc4..2250b248fa 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/jpeg.h
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/arithmetics.h
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - jpeg.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2002 Hacktarux *
+ * Mupen64plus-rsp-hle - arithmetics.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* *
* 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 *
@@ -19,12 +19,25 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifndef JPEG_H
-#define JPEG_H
+#ifndef ARITHMETICS_H
+#define ARITHMETICS_H
-void jpeg_decode_PS0();
-void jpeg_decode_PS();
-void jpeg_decode_OB();
+#include
+
+#include "common.h"
+
+static inline int16_t clamp_s16(int_fast32_t x)
+{
+ x = (x < INT16_MIN) ? INT16_MIN: x;
+ x = (x > INT16_MAX) ? INT16_MAX: x;
+
+ return x;
+}
+
+static inline int32_t vmulf(int16_t x, int16_t y)
+{
+ return (((int32_t)(x))*((int32_t)(y))+0x4000)>>15;
+}
#endif
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/audio.c b/libmupen64plus/mupen64plus-rsp-hle/src/audio.c
new file mode 100644
index 0000000000..fac2a101aa
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/audio.c
@@ -0,0 +1,128 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - audio.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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
+#include
+#include
+
+#include "arithmetics.h"
+
+const int16_t RESAMPLE_LUT[64 * 4] = {
+ (int16_t)0x0c39, (int16_t)0x66ad, (int16_t)0x0d46, (int16_t)0xffdf,
+ (int16_t)0x0b39, (int16_t)0x6696, (int16_t)0x0e5f, (int16_t)0xffd8,
+ (int16_t)0x0a44, (int16_t)0x6669, (int16_t)0x0f83, (int16_t)0xffd0,
+ (int16_t)0x095a, (int16_t)0x6626, (int16_t)0x10b4, (int16_t)0xffc8,
+ (int16_t)0x087d, (int16_t)0x65cd, (int16_t)0x11f0, (int16_t)0xffbf,
+ (int16_t)0x07ab, (int16_t)0x655e, (int16_t)0x1338, (int16_t)0xffb6,
+ (int16_t)0x06e4, (int16_t)0x64d9, (int16_t)0x148c, (int16_t)0xffac,
+ (int16_t)0x0628, (int16_t)0x643f, (int16_t)0x15eb, (int16_t)0xffa1,
+ (int16_t)0x0577, (int16_t)0x638f, (int16_t)0x1756, (int16_t)0xff96,
+ (int16_t)0x04d1, (int16_t)0x62cb, (int16_t)0x18cb, (int16_t)0xff8a,
+ (int16_t)0x0435, (int16_t)0x61f3, (int16_t)0x1a4c, (int16_t)0xff7e,
+ (int16_t)0x03a4, (int16_t)0x6106, (int16_t)0x1bd7, (int16_t)0xff71,
+ (int16_t)0x031c, (int16_t)0x6007, (int16_t)0x1d6c, (int16_t)0xff64,
+ (int16_t)0x029f, (int16_t)0x5ef5, (int16_t)0x1f0b, (int16_t)0xff56,
+ (int16_t)0x022a, (int16_t)0x5dd0, (int16_t)0x20b3, (int16_t)0xff48,
+ (int16_t)0x01be, (int16_t)0x5c9a, (int16_t)0x2264, (int16_t)0xff3a,
+ (int16_t)0x015b, (int16_t)0x5b53, (int16_t)0x241e, (int16_t)0xff2c,
+ (int16_t)0x0101, (int16_t)0x59fc, (int16_t)0x25e0, (int16_t)0xff1e,
+ (int16_t)0x00ae, (int16_t)0x5896, (int16_t)0x27a9, (int16_t)0xff10,
+ (int16_t)0x0063, (int16_t)0x5720, (int16_t)0x297a, (int16_t)0xff02,
+ (int16_t)0x001f, (int16_t)0x559d, (int16_t)0x2b50, (int16_t)0xfef4,
+ (int16_t)0xffe2, (int16_t)0x540d, (int16_t)0x2d2c, (int16_t)0xfee8,
+ (int16_t)0xffac, (int16_t)0x5270, (int16_t)0x2f0d, (int16_t)0xfedb,
+ (int16_t)0xff7c, (int16_t)0x50c7, (int16_t)0x30f3, (int16_t)0xfed0,
+ (int16_t)0xff53, (int16_t)0x4f14, (int16_t)0x32dc, (int16_t)0xfec6,
+ (int16_t)0xff2e, (int16_t)0x4d57, (int16_t)0x34c8, (int16_t)0xfebd,
+ (int16_t)0xff0f, (int16_t)0x4b91, (int16_t)0x36b6, (int16_t)0xfeb6,
+ (int16_t)0xfef5, (int16_t)0x49c2, (int16_t)0x38a5, (int16_t)0xfeb0,
+ (int16_t)0xfedf, (int16_t)0x47ed, (int16_t)0x3a95, (int16_t)0xfeac,
+ (int16_t)0xfece, (int16_t)0x4611, (int16_t)0x3c85, (int16_t)0xfeab,
+ (int16_t)0xfec0, (int16_t)0x4430, (int16_t)0x3e74, (int16_t)0xfeac,
+ (int16_t)0xfeb6, (int16_t)0x424a, (int16_t)0x4060, (int16_t)0xfeaf,
+ (int16_t)0xfeaf, (int16_t)0x4060, (int16_t)0x424a, (int16_t)0xfeb6,
+ (int16_t)0xfeac, (int16_t)0x3e74, (int16_t)0x4430, (int16_t)0xfec0,
+ (int16_t)0xfeab, (int16_t)0x3c85, (int16_t)0x4611, (int16_t)0xfece,
+ (int16_t)0xfeac, (int16_t)0x3a95, (int16_t)0x47ed, (int16_t)0xfedf,
+ (int16_t)0xfeb0, (int16_t)0x38a5, (int16_t)0x49c2, (int16_t)0xfef5,
+ (int16_t)0xfeb6, (int16_t)0x36b6, (int16_t)0x4b91, (int16_t)0xff0f,
+ (int16_t)0xfebd, (int16_t)0x34c8, (int16_t)0x4d57, (int16_t)0xff2e,
+ (int16_t)0xfec6, (int16_t)0x32dc, (int16_t)0x4f14, (int16_t)0xff53,
+ (int16_t)0xfed0, (int16_t)0x30f3, (int16_t)0x50c7, (int16_t)0xff7c,
+ (int16_t)0xfedb, (int16_t)0x2f0d, (int16_t)0x5270, (int16_t)0xffac,
+ (int16_t)0xfee8, (int16_t)0x2d2c, (int16_t)0x540d, (int16_t)0xffe2,
+ (int16_t)0xfef4, (int16_t)0x2b50, (int16_t)0x559d, (int16_t)0x001f,
+ (int16_t)0xff02, (int16_t)0x297a, (int16_t)0x5720, (int16_t)0x0063,
+ (int16_t)0xff10, (int16_t)0x27a9, (int16_t)0x5896, (int16_t)0x00ae,
+ (int16_t)0xff1e, (int16_t)0x25e0, (int16_t)0x59fc, (int16_t)0x0101,
+ (int16_t)0xff2c, (int16_t)0x241e, (int16_t)0x5b53, (int16_t)0x015b,
+ (int16_t)0xff3a, (int16_t)0x2264, (int16_t)0x5c9a, (int16_t)0x01be,
+ (int16_t)0xff48, (int16_t)0x20b3, (int16_t)0x5dd0, (int16_t)0x022a,
+ (int16_t)0xff56, (int16_t)0x1f0b, (int16_t)0x5ef5, (int16_t)0x029f,
+ (int16_t)0xff64, (int16_t)0x1d6c, (int16_t)0x6007, (int16_t)0x031c,
+ (int16_t)0xff71, (int16_t)0x1bd7, (int16_t)0x6106, (int16_t)0x03a4,
+ (int16_t)0xff7e, (int16_t)0x1a4c, (int16_t)0x61f3, (int16_t)0x0435,
+ (int16_t)0xff8a, (int16_t)0x18cb, (int16_t)0x62cb, (int16_t)0x04d1,
+ (int16_t)0xff96, (int16_t)0x1756, (int16_t)0x638f, (int16_t)0x0577,
+ (int16_t)0xffa1, (int16_t)0x15eb, (int16_t)0x643f, (int16_t)0x0628,
+ (int16_t)0xffac, (int16_t)0x148c, (int16_t)0x64d9, (int16_t)0x06e4,
+ (int16_t)0xffb6, (int16_t)0x1338, (int16_t)0x655e, (int16_t)0x07ab,
+ (int16_t)0xffbf, (int16_t)0x11f0, (int16_t)0x65cd, (int16_t)0x087d,
+ (int16_t)0xffc8, (int16_t)0x10b4, (int16_t)0x6626, (int16_t)0x095a,
+ (int16_t)0xffd0, (int16_t)0x0f83, (int16_t)0x6669, (int16_t)0x0a44,
+ (int16_t)0xffd8, (int16_t)0x0e5f, (int16_t)0x6696, (int16_t)0x0b39,
+ (int16_t)0xffdf, (int16_t)0x0d46, (int16_t)0x66ad, (int16_t)0x0c39
+};
+
+int32_t rdot(size_t n, const int16_t *x, const int16_t *y)
+{
+ int32_t accu = 0;
+
+ y += n;
+
+ while (n != 0) {
+ accu += *(x++) * *(--y);
+ --n;
+ }
+
+ return accu;
+}
+
+void adpcm_compute_residuals(int16_t* dst, const int16_t* src,
+ const int16_t* cb_entry, const int16_t* last_samples, size_t count)
+{
+ const int16_t* const book1 = cb_entry;
+ const int16_t* const book2 = cb_entry + 8;
+
+ const int16_t l1 = last_samples[0];
+ const int16_t l2 = last_samples[1];
+
+ size_t i;
+
+ assert(count <= 8);
+
+ for(i = 0; i < count; ++i) {
+ int32_t accu = (int32_t)src[i] << 11;
+ accu += book1[i]*l1 + book2[i]*l2 + rdot(i, book2, src);
+ dst[i] = clamp_s16(accu >> 11);
+ }
+}
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/alist_internal.h b/libmupen64plus/mupen64plus-rsp-hle/src/audio.h
similarity index 61%
rename from libmupen64plus/mupen64plus-rsp-hle/src/alist_internal.h
rename to libmupen64plus/mupen64plus-rsp-hle/src/audio.h
index ae39883b45..21c7a09167 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/alist_internal.h
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/audio.h
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - alist_internal.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2002 Hacktarux *
+ * Mupen64plus-rsp-hle - audio.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* *
* 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 *
@@ -19,32 +19,27 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifndef ALIST_INTERNAL_H
-#define ALIST_INTERNAL_H
+#ifndef AUDIO_H
+#define AUDIO_H
-#include "hle.h"
+#include
+#include
-typedef void (*acmd_callback_t)(u32 inst1, u32 inst2);
+#include "common.h"
-/*
- * Audio flags
- */
+extern const int16_t RESAMPLE_LUT[64 * 4];
-#define A_INIT 0x01
-#define A_CONTINUE 0x00
-#define A_LOOP 0x02
-#define A_OUT 0x02
-#define A_LEFT 0x02
-#define A_RIGHT 0x00
-#define A_VOL 0x04
-#define A_RATE 0x00
-#define A_AUX 0x08
-#define A_NOAUX 0x00
-#define A_MAIN 0x00
-#define A_MIX 0x10
+int32_t rdot(size_t n, const int16_t *x, const int16_t *y);
-extern u16 AudioInBuffer, AudioOutBuffer, AudioCount;
-extern u16 AudioAuxA, AudioAuxC, AudioAuxE;
-extern u32 loopval; // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
+static inline int16_t adpcm_predict_sample(uint8_t byte, uint8_t mask,
+ unsigned lshift, unsigned rshift)
+{
+ int16_t sample = (uint16_t)(byte & mask) << lshift;
+ sample >>= rshift; /* signed */
+ return sample;
+}
+
+void adpcm_compute_residuals(int16_t* dst, const int16_t* src,
+ const int16_t* cb_entry, const int16_t* last_samples, size_t count);
#endif
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/cicx105.c b/libmupen64plus/mupen64plus-rsp-hle/src/cicx105.c
index 1e89056915..bda5ecab18 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/cicx105.c
+++ b/libmupen64plus/mupen64plus-rsp-hle/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 *
@@ -23,33 +23,34 @@
#include
-#include "hle.h"
+#include "hle_internal.h"
/**
* During IPL3 stage of CIC x105 games, the RSP performs some checks and transactions
* necessary for booting the game.
- *
+ *
* We only implement the needed DMA transactions for booting.
*
* Found in Banjo-Tooie, Zelda, Perfect Dark, ...)
**/
-void cicx105_ucode()
+void cicx105_ucode(struct hle_t* hle)
{
- // memcpy is okay to use because access constrains are met (alignment, size)
+ /* memcpy is okay to use because access constrains are met (alignment, size) */
unsigned int i;
- unsigned char * dst = rsp.RDRAM + 0x2fb1f0;
- unsigned char * src = rsp.IMEM + 0x120;
+ unsigned char *dst = hle->dram + 0x2fb1f0;
+ unsigned char *src = hle->imem + 0x120;
/* dma_read(0x1120, 0x1e8, 0x1e8) */
- memcpy(rsp.IMEM + 0x120, rsp.RDRAM + 0x1e8, 0x1f0);
+ memcpy(hle->imem + 0x120, hle->dram + 0x1e8, 0x1f0);
/* dma_write(0x1120, 0x2fb1f0, 0xfe817000) */
- for (i = 0; i < 24; ++i)
- {
+ for (i = 0; i < 24; ++i) {
memcpy(dst, src, 8);
dst += 0xff0;
src += 0x8;
}
+
+ rsp_break(hle, 0);
}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/cicx105.h b/libmupen64plus/mupen64plus-rsp-hle/src/common.h
similarity index 73%
rename from libmupen64plus/mupen64plus-rsp-hle/src/cicx105.h
rename to libmupen64plus/mupen64plus-rsp-hle/src/common.h
index fbfcfad0a7..cd5dfa6948 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/cicx105.h
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/common.h
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - cicx105.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2002 Hacktarux *
+ * Mupen64plus-rsp-hle - common.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* *
* 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 *
@@ -19,10 +19,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifndef CICX105_H
-#define CICX105_H
+#ifndef COMMON_H
+#define COMMON_H
-void cicx105_ucode();
+/* macro for unused variable warning suppression */
+#ifdef __GNUC__
+# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
+#else
+# define UNUSED(x) UNUSED_ ## x
+#endif
+
+/* macro for inline keyword */
+#ifdef _MSC_VER
+#define inline __inline
+#endif
#endif
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/hle.c b/libmupen64plus/mupen64plus-rsp-hle/src/hle.c
new file mode 100644
index 0000000000..ddc0404404
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/hle.c
@@ -0,0 +1,489 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - hle.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2012 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+
+#ifdef ENABLE_TASK_DUMP
+#include
+#endif
+
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+#include "ucodes.h"
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/* some rdp status flags */
+#define DP_STATUS_FREEZE 0x2
+
+
+
+/* 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 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,
+ const unsigned char *const bytes, unsigned int size);
+static void dump_task(struct hle_t* hle, const char *const filename);
+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
+
+/* Global functions */
+void hle_init(struct hle_t* hle,
+ unsigned char* dram,
+ unsigned char* dmem,
+ unsigned char* imem,
+ unsigned int* mi_intr,
+ unsigned int* sp_mem_addr,
+ unsigned int* sp_dram_addr,
+ unsigned int* sp_rd_length,
+ unsigned int* sp_wr_length,
+ unsigned int* sp_status,
+ unsigned int* sp_dma_full,
+ unsigned int* sp_dma_busy,
+ unsigned int* sp_pc,
+ unsigned int* sp_semaphore,
+ unsigned int* dpc_start,
+ unsigned int* dpc_end,
+ unsigned int* dpc_current,
+ unsigned int* dpc_status,
+ unsigned int* dpc_clock,
+ unsigned int* dpc_bufbusy,
+ unsigned int* dpc_pipebusy,
+ unsigned int* dpc_tmem,
+ void* user_defined)
+{
+ hle->dram = dram;
+ hle->dmem = dmem;
+ hle->imem = imem;
+ hle->mi_intr = mi_intr;
+ hle->sp_mem_addr = sp_mem_addr;
+ hle->sp_dram_addr = sp_dram_addr;
+ hle->sp_rd_length = sp_rd_length;
+ hle->sp_wr_length = sp_wr_length;
+ hle->sp_status = sp_status;
+ hle->sp_dma_full = sp_dma_full;
+ hle->sp_dma_busy = sp_dma_busy;
+ hle->sp_pc = sp_pc;
+ hle->sp_semaphore = sp_semaphore;
+ hle->dpc_start = dpc_start;
+ hle->dpc_end = dpc_end;
+ hle->dpc_current = dpc_current;
+ hle->dpc_status = dpc_status;
+ hle->dpc_clock = dpc_clock;
+ hle->dpc_bufbusy = dpc_bufbusy;
+ hle->dpc_pipebusy = dpc_pipebusy;
+ hle->dpc_tmem = dpc_tmem;
+ hle->user_defined = user_defined;
+}
+
+void hle_execute(struct hle_t* hle)
+{
+ if (is_task(hle)) {
+ if (!try_fast_task_dispatching(hle))
+ normal_task_dispatching(hle);
+ } else {
+ non_task_dispatching(hle);
+ }
+}
+
+/* local functions */
+static unsigned int sum_bytes(const unsigned char *bytes, unsigned int size)
+{
+ unsigned int sum = 0;
+ const unsigned char *const bytes_end = bytes + size;
+
+ while (bytes != bytes_end)
+ sum += *bytes++;
+
+ return sum;
+}
+
+/**
+ * Try to figure if the RSP was launched using osSpTask* functions
+ * and not run directly (in which case DMEM[0xfc0-0xfff] is meaningless).
+ *
+ * Previously, the ucode_size field was used to determine this,
+ * but it is not robust enough (hi Pokemon Stadium !) because games could write anything
+ * in this field : most ucode_boot discard the value and just use 0xf7f anyway.
+ *
+ * Using ucode_boot_size should be more robust in this regard.
+ **/
+static bool is_task(struct hle_t* hle)
+{
+ return (*dmem_u32(hle, TASK_UCODE_BOOT_SIZE) <= 0x1000);
+}
+
+void rsp_break(struct hle_t* hle, unsigned int setbits)
+{
+ *hle->sp_status |= setbits | SP_STATUS_BROKE | SP_STATUS_HALT;
+
+ if ((*hle->sp_status & SP_STATUS_INTR_ON_BREAK)) {
+ *hle->mi_intr |= MI_INTR_SP;
+ HleCheckInterrupts(hle->user_defined);
+ }
+}
+
+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)
+{
+ /* identify audio ucode by using the content of ucode_data */
+ uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA);
+ uint32_t v;
+
+ if (*dram_u32(hle, ucode_data) == 0x00000001) {
+ if (*dram_u32(hle, ucode_data + 0x30) == 0xf0000f00) {
+ v = *dram_u32(hle, ucode_data + 0x28);
+ switch(v)
+ {
+ case 0x1e24138c: /* audio ABI (most common) */
+ alist_process_audio(hle); return true;
+ case 0x1dc8138c: /* GoldenEye */
+ alist_process_audio_ge(hle); return true;
+ case 0x1e3c1390: /* BlastCorp, DiddyKongRacing */
+ alist_process_audio_bc(hle); return true;
+ default:
+ HleWarnMessage(hle->user_defined, "ABI1 identification regression: v=%08x", v);
+ }
+ } else {
+ v = *dram_u32(hle, ucode_data + 0x10);
+ switch(v)
+ {
+ case 0x11181350: /* MarioKart, WaveRace (E) */
+ alist_process_nead_mk(hle); return true;
+ case 0x111812e0: /* StarFox (J) */
+ alist_process_nead_sfj(hle); return true;
+ case 0x110412ac: /* WaveRace (J RevB) */
+ alist_process_nead_wrjb(hle); return true;
+ case 0x110412cc: /* StarFox/LylatWars (except J) */
+ alist_process_nead_sf(hle); return true;
+ case 0x1cd01250: /* FZeroX */
+ alist_process_nead_fz(hle); return true;
+ case 0x1f08122c: /* YoshisStory */
+ alist_process_nead_ys(hle); return true;
+ case 0x1f38122c: /* 1080° Snowboarding */
+ alist_process_nead_1080(hle); return true;
+ case 0x1f681230: /* Zelda OoT / Zelda MM (J, J RevA) */
+ alist_process_nead_oot(hle); return true;
+ case 0x1f801250: /* Zelda MM (except J, J RevA, E Beta), PokemonStadium 2 */
+ alist_process_nead_mm(hle); return true;
+ case 0x109411f8: /* Zelda MM (E Beta) */
+ alist_process_nead_mmb(hle); return true;
+ case 0x1eac11b8: /* AnimalCrossing */
+ 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);
+ }
+ }
+ } else {
+ v = *dram_u32(hle, ucode_data + 0x10);
+ switch(v)
+ {
+ case 0x00000001: /* MusyX v1
+ RogueSquadron, ResidentEvil2, PolarisSnoCross,
+ TheWorldIsNotEnough, RugratsInParis, NBAShowTime,
+ HydroThunder, Tarzan, GauntletLegend, Rush2049 */
+ musyx_v1_task(hle); return true;
+ case 0x0000127c: /* naudio (many games) */
+ alist_process_naudio(hle); return true;
+ case 0x00001280: /* BanjoKazooie */
+ alist_process_naudio_bk(hle); return true;
+ case 0x1c58126c: /* DonkeyKong */
+ alist_process_naudio_dk(hle); return true;
+ case 0x1ae8143c: /* BanjoTooie, JetForceGemini, MickeySpeedWayUSA, PerfectDark */
+ alist_process_naudio_mp3(hle); return true;
+ case 0x1ab0140c: /* ConkerBadFurDay */
+ alist_process_naudio_cbfd(hle); return true;
+
+ default:
+ HleWarnMessage(hle->user_defined, "ABI3 identification regression: v=%08x", v);
+ }
+ }
+
+ return false;
+}
+
+static bool try_fast_task_dispatching(struct hle_t* hle)
+{
+ /* identify task ucode by its type */
+ switch (*dmem_u32(hle, TASK_TYPE)) {
+ case 1:
+ /* 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 (hle->hle_aud) {
+ send_alist_to_audio_plugin(hle);
+ return true;
+ } else if (try_fast_audio_dispatching(hle))
+ return true;
+ break;
+
+ case 7:
+ HleShowCFB(hle->user_defined);
+ break;
+ }
+
+ return false;
+}
+
+static void normal_task_dispatching(struct hle_t* hle)
+{
+ const unsigned int sum =
+ sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), min(*dmem_u32(hle, TASK_UCODE_SIZE), 0xf80) >> 1);
+
+ switch (sum) {
+ /* 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 (hle->hle_gfx) {
+ send_dlist_to_gfx_plugin(hle);
+ return;
+ }
+ break;
+
+ /* JPEG: found in Pokemon Stadium J */
+ case 0x2c85a:
+ jpeg_decode_PS0(hle);
+ return;
+
+ /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */
+ case 0x2caa6:
+ jpeg_decode_PS(hle);
+ return;
+
+ /* JPEG: found in Ogre Battle, Bottom of the 9th */
+ case 0x130de:
+ case 0x278b0:
+ jpeg_decode_OB(hle);
+ return;
+ }
+
+ /* 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);
+#endif
+ }
+}
+
+static void non_task_dispatching(struct hle_t* hle)
+{
+ const unsigned int sum = sum_bytes(hle->imem, 44);
+
+ if (sum == 0x9e2)
+ {
+ /* CIC x105 ucode (used during boot of CIC x105 games) */
+ cicx105_ucode(hle);
+ return;
+ }
+
+ /* 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);
+#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)
+{
+ char filename[256];
+ uint32_t ucode = *dmem_u32(hle, TASK_UCODE);
+ uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA);
+ uint32_t data_ptr = *dmem_u32(hle, TASK_DATA_PTR);
+
+ sprintf(&filename[0], "task_%x.log", sum);
+ dump_task(hle, filename);
+
+ /* dump ucode_boot */
+ sprintf(&filename[0], "ucode_boot_%x.bin", sum);
+ dump_binary(hle, filename, (void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE_BOOT)), *dmem_u32(hle, TASK_UCODE_BOOT_SIZE));
+
+ /* dump ucode */
+ if (ucode != 0) {
+ sprintf(&filename[0], "ucode_%x.bin", sum);
+ dump_binary(hle, filename, (void*)dram_u32(hle, ucode), 0xf80);
+ }
+
+ /* dump ucode_data */
+ if (ucode_data != 0) {
+ sprintf(&filename[0], "ucode_data_%x.bin", sum);
+ dump_binary(hle, filename, (void*)dram_u32(hle, ucode_data), *dmem_u32(hle, TASK_UCODE_DATA_SIZE));
+ }
+
+ /* dump data */
+ if (data_ptr != 0) {
+ sprintf(&filename[0], "data_%x.bin", sum);
+ dump_binary(hle, filename, (void*)dram_u32(hle, data_ptr), *dmem_u32(hle, TASK_DATA_SIZE));
+ }
+}
+
+static void dump_unknown_non_task(struct hle_t* hle, unsigned int sum)
+{
+ char filename[256];
+
+ /* dump IMEM & DMEM for further analysis */
+ sprintf(&filename[0], "imem_%x.bin", sum);
+ dump_binary(hle, filename, hle->imem, 0x1000);
+
+ sprintf(&filename[0], "dmem_%x.bin", sum);
+ dump_binary(hle, filename, hle->dmem, 0x1000);
+}
+
+static void dump_binary(struct hle_t* hle, const char *const filename,
+ const unsigned char *const bytes, unsigned int size)
+{
+ FILE *f;
+
+ /* if file already exists, do nothing */
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ /* else we write bytes to the file */
+ f = fopen(filename, "wb");
+ if (f != NULL) {
+ if (fwrite(bytes, 1, size, f) != size)
+ HleErrorMessage(hle->user_defined, "Writing error on %s", filename);
+ fclose(f);
+ } else
+ HleErrorMessage(hle->user_defined, "Couldn't open %s for writing !", filename);
+ } else
+ fclose(f);
+}
+
+static void dump_task(struct hle_t* hle, const char *const filename)
+{
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ f = fopen(filename, "w");
+ fprintf(f,
+ "type = %d\n"
+ "flags = %d\n"
+ "ucode_boot = %#08x size = %#x\n"
+ "ucode = %#08x size = %#x\n"
+ "ucode_data = %#08x size = %#x\n"
+ "dram_stack = %#08x size = %#x\n"
+ "output_buff = %#08x *size = %#x\n"
+ "data = %#08x size = %#x\n"
+ "yield_data = %#08x size = %#x\n",
+ *dmem_u32(hle, TASK_TYPE),
+ *dmem_u32(hle, TASK_FLAGS),
+ *dmem_u32(hle, TASK_UCODE_BOOT), *dmem_u32(hle, TASK_UCODE_BOOT_SIZE),
+ *dmem_u32(hle, TASK_UCODE), *dmem_u32(hle, TASK_UCODE_SIZE),
+ *dmem_u32(hle, TASK_UCODE_DATA), *dmem_u32(hle, TASK_UCODE_DATA_SIZE),
+ *dmem_u32(hle, TASK_DRAM_STACK), *dmem_u32(hle, TASK_DRAM_STACK_SIZE),
+ *dmem_u32(hle, TASK_OUTPUT_BUFF), *dmem_u32(hle, TASK_OUTPUT_BUFF_SIZE),
+ *dmem_u32(hle, TASK_DATA_PTR), *dmem_u32(hle, TASK_DATA_SIZE),
+ *dmem_u32(hle, TASK_YIELD_DATA_PTR), *dmem_u32(hle, TASK_YIELD_DATA_SIZE));
+ fclose(f);
+ } else
+ fclose(f);
+}
+#endif
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/hle.h b/libmupen64plus/mupen64plus-rsp-hle/src/hle.h
index ea517e735e..a420b752d3 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/hle.h
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/hle.h
@@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - hle.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2002 Hacktarux *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
* *
* 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 *
@@ -22,68 +22,33 @@
#ifndef HLE_H
#define HLE_H
-#define M64P_PLUGIN_PROTOTYPES 1
-#include "m64p_plugin.h"
+#include "hle_internal.h"
-#define RSP_HLE_VERSION 0x020000
-#define RSP_PLUGIN_API_VERSION 0x020000
+void hle_init(struct hle_t* hle,
+ unsigned char* dram,
+ unsigned char* dmem,
+ unsigned char* imem,
+ unsigned int* mi_intr,
+ unsigned int* sp_mem_addr,
+ unsigned int* sp_dram_addr,
+ unsigned int* sp_rd_length,
+ unsigned int* sp_wr_length,
+ unsigned int* sp_status,
+ unsigned int* sp_dma_full,
+ unsigned int* sp_dma_busy,
+ unsigned int* sp_pc,
+ unsigned int* sp_semaphore,
+ unsigned int* dpc_start,
+ unsigned int* dpc_end,
+ unsigned int* dpc_current,
+ unsigned int* dpc_status,
+ unsigned int* dpc_clock,
+ unsigned int* dpc_bufbusy,
+ unsigned int* dpc_pipebusy,
+ unsigned int* dpc_tmem,
+ void* user_defined);
-#ifdef M64P_BIG_ENDIAN
-#define S 0
-#define S16 0
-#define S8 0
-#else
-#define S 1
-#define S16 2
-#define S8 3
-#endif
-
-// types
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned long long u64;
-
-typedef signed char s8;
-typedef signed short s16;
-typedef signed int s32;
-typedef signed long long s64;
-
-extern RSP_INFO rsp;
-
-typedef struct
-{
- unsigned int type;
- unsigned int flags;
-
- unsigned int ucode_boot;
- unsigned int ucode_boot_size;
-
- unsigned int ucode;
- unsigned int ucode_size;
-
- unsigned int ucode_data;
- unsigned int ucode_data_size;
-
- unsigned int dram_stack;
- unsigned int dram_stack_size;
-
- unsigned int output_buff;
- unsigned int output_buff_size;
-
- unsigned int data_ptr;
- unsigned int data_size;
-
- unsigned int yield_data_ptr;
- unsigned int yield_data_size;
-} OSTask_t;
-
-static const OSTask_t * const get_task()
-{
- return (OSTask_t*)(rsp.DMEM + 0xfc0);
-}
-
-void DebugMessage(int level, const char *message, ...);
+void hle_execute(struct hle_t* hle);
#endif
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/hle_external.h b/libmupen64plus/mupen64plus-rsp-hle/src/hle_external.h
new file mode 100644
index 0000000000..5dcbf2ea47
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/hle_external.h
@@ -0,0 +1,40 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - hle_external.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef HLE_EXTERNAL_H
+#define HLE_EXTERNAL_H
+
+/* 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, ...);
+
+void HleCheckInterrupts(void* user_defined);
+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/libmupen64plus/mupen64plus-rsp-hle/src/hle_internal.h b/libmupen64plus/mupen64plus-rsp-hle/src/hle_internal.h
new file mode 100644
index 0000000000..ad1708bb1b
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/hle_internal.h
@@ -0,0 +1,91 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - hle_internal.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef HLE_INTERNAL_H
+#define HLE_INTERNAL_H
+
+#include
+
+#include "ucodes.h"
+
+/* rsp hle internal state - internal usage only */
+struct hle_t
+{
+ unsigned char* dram;
+ unsigned char* dmem;
+ unsigned char* imem;
+
+ unsigned int* mi_intr;
+
+ unsigned int* sp_mem_addr;
+ unsigned int* sp_dram_addr;
+ unsigned int* sp_rd_length;
+ unsigned int* sp_wr_length;
+ unsigned int* sp_status;
+ unsigned int* sp_dma_full;
+ unsigned int* sp_dma_busy;
+ unsigned int* sp_pc;
+ unsigned int* sp_semaphore;
+
+ unsigned int* dpc_start;
+ unsigned int* dpc_end;
+ unsigned int* dpc_current;
+ unsigned int* dpc_status;
+ unsigned int* dpc_clock;
+ unsigned int* dpc_bufbusy;
+ unsigned int* dpc_pipebusy;
+ unsigned int* dpc_tmem;
+
+ /* 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];
+
+ /* alist_audio.c */
+ struct alist_audio_t alist_audio;
+
+ /* alist_naudio.c */
+ struct alist_naudio_t alist_naudio;
+
+ /* alist_nead.c */
+ struct alist_nead_t alist_nead;
+
+ /* mp3.c */
+ 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/libmupen64plus/mupen64plus-rsp-hle/src/jpeg.c b/libmupen64plus/mupen64plus-rsp-hle/src/jpeg.c
index 28fcc8bdd9..ff424c4033 100644
--- a/libmupen64plus/mupen64plus-rsp-hle/src/jpeg.c
+++ b/libmupen64plus/mupen64plus-rsp-hle/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 *
@@ -22,49 +22,48 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include
-#include
#include
+#include
-#define M64P_PLUGIN_PROTOTYPES 1
-#include "m64p_types.h"
-#include "m64p_plugin.h"
-#include "hle.h"
+#include "arithmetics.h"
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
#define SUBBLOCK_SIZE 64
-typedef void (*tile_line_emitter_t)(const int16_t *y, const int16_t *u, uint32_t address);
-typedef void (*std_macroblock_decoder_t)(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
-
-/* rdram operations */
-// FIXME: these functions deserve their own module
-static void rdram_read_many_u16(uint16_t *dst, uint32_t address, unsigned int count);
-static void rdram_write_many_u16(const uint16_t *src, uint32_t address, unsigned int count);
-static uint32_t rdram_read_u32(uint32_t address);
-static void rdram_write_many_u32(const uint32_t *src, uint32_t address, unsigned int count);
+typedef void (*tile_line_emitter_t)(struct hle_t* hle, const int16_t *y, const int16_t *u, uint32_t address);
+typedef void (*subblock_transform_t)(int16_t *dst, const int16_t *src);
/* standard jpeg ucode decoder */
-static void jpeg_decode_std(const char * const version, const std_macroblock_decoder_t decode_mb, const tile_line_emitter_t emit_line);
+static void jpeg_decode_std(struct hle_t* hle,
+ const char *const version,
+ const subblock_transform_t transform_luma,
+ const subblock_transform_t transform_chroma,
+ const tile_line_emitter_t emit_line);
/* helper functions */
static uint8_t clamp_u8(int16_t x);
static int16_t clamp_s12(int16_t x);
-static int16_t clamp_s16(int32_t x);
static uint16_t clamp_RGBA_component(int16_t x);
-/* pixel conversion & foratting */
+/* pixel conversion & formatting */
static uint32_t GetUYVY(int16_t y1, int16_t y2, int16_t u, int16_t v);
static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v);
/* tile line emitters */
-static void EmitYUVTileLine(const int16_t *y, const int16_t *u, uint32_t address);
-static void EmitRGBATileLine(const int16_t *y, const int16_t *u, uint32_t address);
+static void EmitYUVTileLine(struct hle_t* hle, const int16_t *y, const int16_t *u, uint32_t address);
+static void EmitRGBATileLine(struct hle_t* hle, const int16_t *y, const int16_t *u, uint32_t address);
/* macroblocks operations */
-static void DecodeMacroblock1(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable);
-static void DecodeMacroblock2(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
-static void DecodeMacroblock3(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE]);
-static void EmitTilesMode0(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
-static void EmitTilesMode2(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
+static void decode_macroblock_ob(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable);
+static void decode_macroblock_std(const subblock_transform_t transform_luma,
+ const subblock_transform_t transform_chroma,
+ int16_t *macroblock,
+ unsigned int subblock_count,
+ const int16_t qtables[3][SUBBLOCK_SIZE]);
+static void EmitTilesMode0(struct hle_t* hle, const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
+static void EmitTilesMode2(struct hle_t* hle, const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
/* subblocks operations */
static void TransposeSubBlock(int16_t *dst, const int16_t *src);
@@ -73,14 +72,13 @@ static void ReorderSubBlock(int16_t *dst, const int16_t *src, const unsigned int
static void MultSubBlocks(int16_t *dst, const int16_t *src1, const int16_t *src2, unsigned int shift);
static void ScaleSubBlock(int16_t *dst, const int16_t *src, int16_t scale);
static void RShiftSubBlock(int16_t *dst, const int16_t *src, unsigned int shift);
-static void InverseDCT1D(const float * const x, float *dst, unsigned int stride);
+static void InverseDCT1D(const float *const x, float *dst, unsigned int stride);
static void InverseDCTSubBlock(int16_t *dst, const int16_t *src);
static void RescaleYSubBlock(int16_t *dst, const int16_t *src);
static void RescaleUVSubBlock(int16_t *dst, const int16_t *src);
/* transposed dequantization table */
-static const int16_t DEFAULT_QTABLE[SUBBLOCK_SIZE] =
-{
+static const int16_t DEFAULT_QTABLE[SUBBLOCK_SIZE] = {
16, 12, 14, 14, 18, 24, 49, 72,
11, 12, 13, 17, 22, 35, 64, 92,
10, 14, 16, 22, 37, 55, 78, 95,
@@ -92,8 +90,7 @@ static const int16_t DEFAULT_QTABLE[SUBBLOCK_SIZE] =
};
/* zig-zag indices */
-static const unsigned int ZIGZAG_TABLE[SUBBLOCK_SIZE] =
-{
+static const unsigned int ZIGZAG_TABLE[SUBBLOCK_SIZE] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
@@ -105,8 +102,7 @@ static const unsigned int ZIGZAG_TABLE[SUBBLOCK_SIZE] =
};
/* transposition indices */
-static const unsigned int TRANSPOSE_TABLE[SUBBLOCK_SIZE] =
-{
+static const unsigned int TRANSPOSE_TABLE[SUBBLOCK_SIZE] = {
0, 8, 16, 24, 32, 40, 48, 56,
1, 9, 17, 25, 33, 41, 49, 57,
2, 10, 18, 26, 34, 42, 50, 58,
@@ -123,18 +119,17 @@ static const unsigned int TRANSPOSE_TABLE[SUBBLOCK_SIZE] =
* Cn = alpha * cos(n * PI / 16) (alpha is chosen such as C4 = 1) */
static const float IDCT_C3 = 1.175875602f;
static const float IDCT_C6 = 0.541196100f;
-static const float IDCT_K[10] =
-{
- 0.765366865f, /* C2-C6 */
- -1.847759065f, /* -C2-C6 */
- -0.390180644f, /* C5-C3 */
- -1.961570561f, /* -C5-C3 */
- 1.501321110f, /* C1+C3-C5-C7 */
- 2.053119869f, /* C1+C3-C5+C7 */
- 3.072711027f, /* C1+C3+C5-C7 */
- 0.298631336f, /* -C1+C3+C5-C7 */
- -0.899976223f, /* C7-C3 */
- -2.562915448f /* -C1-C3 */
+static const float IDCT_K[10] = {
+ 0.765366865f, /* C2-C6 */
+ -1.847759065f, /* -C2-C6 */
+ -0.390180644f, /* C5-C3 */
+ -1.961570561f, /* -C5-C3 */
+ 1.501321110f, /* C1+C3-C5-C7 */
+ 2.053119869f, /* C1+C3-C5+C7 */
+ 3.072711027f, /* C1+C3+C5-C7 */
+ 0.298631336f, /* -C1+C3+C5-C7 */
+ -0.899976223f, /* C7-C3 */
+ -2.562915448f /* -C1-C3 */
};
@@ -143,24 +138,26 @@ static const float IDCT_K[10] =
/***************************************************************************
* JPEG decoding ucode found in Japanese exclusive version of Pokemon Stadium.
**************************************************************************/
-void jpeg_decode_PS0()
+void jpeg_decode_PS0(struct hle_t* hle)
{
- jpeg_decode_std("PS0", DecodeMacroblock3, EmitYUVTileLine);
+ jpeg_decode_std(hle, "PS0", RescaleYSubBlock, RescaleUVSubBlock, EmitYUVTileLine);
+ rsp_break(hle, SP_STATUS_TASKDONE);
}
/***************************************************************************
* JPEG decoding ucode found in Ocarina of Time, Pokemon Stadium 1 and
* Pokemon Stadium 2.
**************************************************************************/
-void jpeg_decode_PS()
+void jpeg_decode_PS(struct hle_t* hle)
{
- jpeg_decode_std("PS", DecodeMacroblock2, EmitRGBATileLine);
+ jpeg_decode_std(hle, "PS", NULL, NULL, EmitRGBATileLine);
+ rsp_break(hle, SP_STATUS_TASKDONE);
}
/***************************************************************************
* JPEG decoding ucode found in Ogre Battle and Bottom of the 9th.
**************************************************************************/
-void jpeg_decode_OB()
+void jpeg_decode_OB(struct hle_t* hle)
{
int16_t qtable[SUBBLOCK_SIZE];
unsigned int mb;
@@ -168,45 +165,43 @@ void jpeg_decode_OB()
int32_t y_dc = 0;
int32_t u_dc = 0;
int32_t v_dc = 0;
-
- const OSTask_t * const task = get_task();
- uint32_t address = task->data_ptr;
- const unsigned int macroblock_count = task->data_size;
- const int qscale = task->yield_data_size;
+ uint32_t address = *dmem_u32(hle, TASK_DATA_PTR);
+ const unsigned int macroblock_count = *dmem_u32(hle, TASK_DATA_SIZE);
+ const int qscale = *dmem_u32(hle, TASK_YIELD_DATA_SIZE);
- DebugMessage(M64MSG_VERBOSE, "jpeg_decode_OB: *buffer=%x, #MB=%d, qscale=%d",
- address,
- macroblock_count,
- qscale);
+ HleVerboseMessage(hle->user_defined,
+ "jpeg_decode_OB: *buffer=%x, #MB=%d, qscale=%d",
+ address,
+ macroblock_count,
+ qscale);
- if (qscale != 0)
- {
+ if (qscale != 0) {
if (qscale > 0)
- {
ScaleSubBlock(qtable, DEFAULT_QTABLE, qscale);
- }
else
- {
RShiftSubBlock(qtable, DEFAULT_QTABLE, -qscale);
- }
}
- for (mb = 0; mb < macroblock_count; ++mb)
- {
- int16_t macroblock[6*SUBBLOCK_SIZE];
+ for (mb = 0; mb < macroblock_count; ++mb) {
+ int16_t macroblock[6 * SUBBLOCK_SIZE];
- rdram_read_many_u16((uint16_t*)macroblock, address, 6*SUBBLOCK_SIZE);
- DecodeMacroblock1(macroblock, &y_dc, &u_dc, &v_dc, (qscale != 0) ? qtable : NULL);
- EmitTilesMode2(EmitYUVTileLine, macroblock, address);
+ dram_load_u16(hle, (uint16_t *)macroblock, address, 6 * SUBBLOCK_SIZE);
+ decode_macroblock_ob(macroblock, &y_dc, &u_dc, &v_dc, (qscale != 0) ? qtable : NULL);
+ EmitTilesMode2(hle, EmitYUVTileLine, macroblock, address);
- address += (2*6*SUBBLOCK_SIZE);
+ address += (2 * 6 * SUBBLOCK_SIZE);
}
+ rsp_break(hle, SP_STATUS_TASKDONE);
}
/* local functions */
-static void jpeg_decode_std(const char * const version, const std_macroblock_decoder_t decode_mb, const tile_line_emitter_t emit_line)
+static void jpeg_decode_std(struct hle_t* hle,
+ const char *const version,
+ const subblock_transform_t transform_luma,
+ const subblock_transform_t transform_chroma,
+ const tile_line_emitter_t emit_line)
{
int16_t qtables[3][SUBBLOCK_SIZE];
unsigned int mb;
@@ -218,68 +213,59 @@ static void jpeg_decode_std(const char * const version, const std_macroblock_dec
uint32_t qtableV_ptr;
unsigned int subblock_count;
unsigned int macroblock_size;
- int16_t *macroblock;
- const OSTask_t * const task = get_task();
+ /* macroblock contains at most 6 subblocks */
+ int16_t macroblock[6 * SUBBLOCK_SIZE];
+ uint32_t data_ptr;
- if (task->flags & 0x1)
- {
- DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: task yielding not implemented", version);
+ if (*dmem_u32(hle, TASK_FLAGS) & 0x1) {
+ HleWarnMessage(hle->user_defined,
+ "jpeg_decode_%s: task yielding not implemented", version);
return;
}
- address = rdram_read_u32(task->data_ptr);
- macroblock_count = rdram_read_u32(task->data_ptr + 4);
- mode = rdram_read_u32(task->data_ptr + 8);
- qtableY_ptr = rdram_read_u32(task->data_ptr + 12);
- qtableU_ptr = rdram_read_u32(task->data_ptr + 16);
- qtableV_ptr = rdram_read_u32(task->data_ptr + 20);
+ data_ptr = *dmem_u32(hle, TASK_DATA_PTR);
+ address = *dram_u32(hle, data_ptr);
+ macroblock_count = *dram_u32(hle, data_ptr + 4);
+ mode = *dram_u32(hle, data_ptr + 8);
+ qtableY_ptr = *dram_u32(hle, data_ptr + 12);
+ qtableU_ptr = *dram_u32(hle, data_ptr + 16);
+ qtableV_ptr = *dram_u32(hle, data_ptr + 20);
- DebugMessage(M64MSG_VERBOSE, "jpeg_decode_%s: *buffer=%x, #MB=%d, mode=%d, *Qy=%x, *Qu=%x, *Qv=%x",
- version,
- address,
- macroblock_count,
- mode,
- qtableY_ptr,
- qtableU_ptr,
- qtableV_ptr);
+ HleVerboseMessage(hle->user_defined,
+ "jpeg_decode_%s: *buffer=%x, #MB=%d, mode=%d, *Qy=%x, *Qu=%x, *Qv=%x",
+ version,
+ address,
+ macroblock_count,
+ mode,
+ qtableY_ptr,
+ qtableU_ptr,
+ qtableV_ptr);
- if (mode != 0 && mode != 2)
- {
- DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: invalid mode %d", version, mode);
+ if (mode != 0 && mode != 2) {
+ HleWarnMessage(hle->user_defined,
+ "jpeg_decode_%s: invalid mode %d", version, mode);
return;
}
-
+
subblock_count = mode + 4;
- macroblock_size = 2*subblock_count*SUBBLOCK_SIZE;
+ macroblock_size = subblock_count * SUBBLOCK_SIZE;
- rdram_read_many_u16((uint16_t*)qtables[0], qtableY_ptr, SUBBLOCK_SIZE);
- rdram_read_many_u16((uint16_t*)qtables[1], qtableU_ptr, SUBBLOCK_SIZE);
- rdram_read_many_u16((uint16_t*)qtables[2], qtableV_ptr, SUBBLOCK_SIZE);
+ dram_load_u16(hle, (uint16_t *)qtables[0], qtableY_ptr, SUBBLOCK_SIZE);
+ dram_load_u16(hle, (uint16_t *)qtables[1], qtableU_ptr, SUBBLOCK_SIZE);
+ dram_load_u16(hle, (uint16_t *)qtables[2], qtableV_ptr, SUBBLOCK_SIZE);
- macroblock = malloc(sizeof(*macroblock) * macroblock_size);
- if (!macroblock)
- {
- DebugMessage(M64MSG_WARNING, "jpeg_decode_%s: could not allocate macroblock", version);
- return;
- }
-
- for (mb = 0; mb < macroblock_count; ++mb)
- {
- rdram_read_many_u16((uint16_t*)macroblock, address, macroblock_size >> 1);
- decode_mb(macroblock, subblock_count, (const int16_t (*)[SUBBLOCK_SIZE])qtables);
+ for (mb = 0; mb < macroblock_count; ++mb) {
+ dram_load_u16(hle, (uint16_t *)macroblock, address, macroblock_size);
+ decode_macroblock_std(transform_luma, transform_chroma,
+ macroblock, subblock_count, (const int16_t (*)[SUBBLOCK_SIZE])qtables);
if (mode == 0)
- {
- EmitTilesMode0(emit_line, macroblock, address);
- }
+ EmitTilesMode0(hle, emit_line, macroblock, address);
else
- {
- EmitTilesMode2(emit_line, macroblock, address);
- }
+ EmitTilesMode2(hle, emit_line, macroblock, address);
- address += macroblock_size;
+ address += 2 * macroblock_size;
}
- free(macroblock);
}
static uint8_t clamp_u8(int16_t x)
@@ -289,28 +275,28 @@ static uint8_t clamp_u8(int16_t x)
static int16_t clamp_s12(int16_t x)
{
- if (x < -0x800) { x = -0x800; } else if (x > 0x7f0) { x = 0x7f0; }
- return x;
-}
-
-static int16_t clamp_s16(int32_t x)
-{
- if (x > 32767) { x = 32767; } else if (x < -32768) { x = -32768; }
+ if (x < -0x800)
+ x = -0x800;
+ else if (x > 0x7f0)
+ x = 0x7f0;
return x;
}
static uint16_t clamp_RGBA_component(int16_t x)
{
- if (x > 0xff0) { x = 0xff0; } else if (x < 0) { x = 0; }
+ if (x > 0xff0)
+ x = 0xff0;
+ else if (x < 0)
+ x = 0;
return (x & 0xf80);
}
static uint32_t GetUYVY(int16_t y1, int16_t y2, int16_t u, int16_t v)
{
- return (uint32_t)clamp_u8(u) << 24
- | (uint32_t)clamp_u8(y1) << 16
- | (uint32_t)clamp_u8(v) << 8
- | (uint32_t)clamp_u8(y2);
+ return (uint32_t)clamp_u8(u) << 24 |
+ (uint32_t)clamp_u8(y1) << 16 |
+ (uint32_t)clamp_u8(v) << 8 |
+ (uint32_t)clamp_u8(y2);
}
static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v)
@@ -319,19 +305,19 @@ static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v)
const float fU = (float)u;
const float fV = (float)v;
- const uint16_t r = clamp_RGBA_component((int16_t)(fY + 1.4025*fV));
- const uint16_t g = clamp_RGBA_component((int16_t)(fY - 0.3443*fU - 0.7144*fV));
- const uint16_t b = clamp_RGBA_component((int16_t)(fY + 1.7729*fU ));
+ const uint16_t r = clamp_RGBA_component((int16_t)(fY + 1.4025 * fV));
+ const uint16_t g = clamp_RGBA_component((int16_t)(fY - 0.3443 * fU - 0.7144 * fV));
+ const uint16_t b = clamp_RGBA_component((int16_t)(fY + 1.7729 * fU));
return (r << 4) | (g >> 1) | (b >> 6) | 1;
}
-static void EmitYUVTileLine(const int16_t *y, const int16_t *u, uint32_t address)
+static void EmitYUVTileLine(struct hle_t* hle, const int16_t *y, const int16_t *u, uint32_t address)
{
uint32_t uyvy[8];
- const int16_t * const v = u + SUBBLOCK_SIZE;
- const int16_t * const y2 = y + SUBBLOCK_SIZE;
+ const int16_t *const v = u + SUBBLOCK_SIZE;
+ const int16_t *const y2 = y + SUBBLOCK_SIZE;
uyvy[0] = GetUYVY(y[0], y[1], u[0], v[0]);
uyvy[1] = GetUYVY(y[2], y[3], u[1], v[1]);
@@ -342,15 +328,15 @@ static void EmitYUVTileLine(const int16_t *y, const int16_t *u, uint32_t address
uyvy[6] = GetUYVY(y2[4], y2[5], u[6], v[6]);
uyvy[7] = GetUYVY(y2[6], y2[7], u[7], v[7]);
- rdram_write_many_u32(uyvy, address, 8);
+ dram_store_u32(hle, uyvy, address, 8);
}
-static void EmitRGBATileLine(const int16_t *y, const int16_t *u, uint32_t address)
+static void EmitRGBATileLine(struct hle_t* hle, const int16_t *y, const int16_t *u, uint32_t address)
{
uint16_t rgba[16];
- const int16_t * const v = u + SUBBLOCK_SIZE;
- const int16_t * const y2 = y + SUBBLOCK_SIZE;
+ const int16_t *const v = u + SUBBLOCK_SIZE;
+ const int16_t *const y2 = y + SUBBLOCK_SIZE;
rgba[0] = GetRGBA(y[0], u[0], v[0]);
rgba[1] = GetRGBA(y[1], u[0], v[0]);
@@ -369,19 +355,18 @@ static void EmitRGBATileLine(const int16_t *y, const int16_t *u, uint32_t addres
rgba[14] = GetRGBA(y2[6], u[7], v[7]);
rgba[15] = GetRGBA(y2[7], u[7], v[7]);
- rdram_write_many_u16(rgba, address, 16);
+ dram_store_u16(hle, rgba, address, 16);
}
-static void EmitTilesMode0(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
+static void EmitTilesMode0(struct hle_t* hle, const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
{
unsigned int i;
unsigned int y_offset = 0;
- unsigned int u_offset = 2*SUBBLOCK_SIZE;
+ unsigned int u_offset = 2 * SUBBLOCK_SIZE;
- for (i = 0; i < 8; ++i)
- {
- emit_line(¯oblock[y_offset], ¯oblock[u_offset], address);
+ for (i = 0; i < 8; ++i) {
+ emit_line(hle, ¯oblock[y_offset], ¯oblock[u_offset], address);
y_offset += 8;
u_offset += 8;
@@ -389,95 +374,86 @@ static void EmitTilesMode0(const tile_line_emitter_t emit_line, const int16_t *m
}
}
-static void EmitTilesMode2(const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
+static void EmitTilesMode2(struct hle_t* hle, const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address)
{
unsigned int i;
unsigned int y_offset = 0;
- unsigned int u_offset = 4*SUBBLOCK_SIZE;
+ unsigned int u_offset = 4 * SUBBLOCK_SIZE;
- for (i = 0; i < 8; ++i)
- {
- emit_line(¯oblock[y_offset], ¯oblock[u_offset], address);
- emit_line(¯oblock[y_offset + 8], ¯oblock[u_offset], address + 32);
+ for (i = 0; i < 8; ++i) {
+ emit_line(hle, ¯oblock[y_offset], ¯oblock[u_offset], address);
+ emit_line(hle, ¯oblock[y_offset + 8], ¯oblock[u_offset], address + 32);
- y_offset += (i == 3) ? SUBBLOCK_SIZE+16 : 16;
+ y_offset += (i == 3) ? SUBBLOCK_SIZE + 16 : 16;
u_offset += 8;
address += 64;
}
}
-static void DecodeMacroblock1(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable)
+static void decode_macroblock_ob(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable)
{
int sb;
- for (sb = 0; sb < 6; ++sb)
- {
+ for (sb = 0; sb < 6; ++sb) {
int16_t tmp_sb[SUBBLOCK_SIZE];
/* update DC */
int32_t dc = (int32_t)macroblock[0];
- switch(sb)
- {
- case 0: case 1: case 2: case 3:
- *y_dc += dc; macroblock[0] = *y_dc & 0xffff; break;
- case 4: *u_dc += dc; macroblock[0] = *u_dc & 0xffff; break;
- case 5: *v_dc += dc; macroblock[0] = *v_dc & 0xffff; break;
+ switch (sb) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ *y_dc += dc;
+ macroblock[0] = *y_dc & 0xffff;
+ break;
+ case 4:
+ *u_dc += dc;
+ macroblock[0] = *u_dc & 0xffff;
+ break;
+ case 5:
+ *v_dc += dc;
+ macroblock[0] = *v_dc & 0xffff;
+ break;
}
ZigZagSubBlock(tmp_sb, macroblock);
- if (qtable != NULL) { MultSubBlocks(tmp_sb, tmp_sb, qtable, 0); }
+ if (qtable != NULL)
+ MultSubBlocks(tmp_sb, tmp_sb, qtable, 0);
TransposeSubBlock(macroblock, tmp_sb);
InverseDCTSubBlock(macroblock, macroblock);
-
+
macroblock += SUBBLOCK_SIZE;
}
}
-static void DecodeMacroblock2(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE])
+static void decode_macroblock_std(const subblock_transform_t transform_luma,
+ const subblock_transform_t transform_chroma,
+ int16_t *macroblock,
+ unsigned int subblock_count,
+ const int16_t qtables[3][SUBBLOCK_SIZE])
{
unsigned int sb;
unsigned int q = 0;
- for (sb = 0; sb < subblock_count; ++sb)
- {
+ for (sb = 0; sb < subblock_count; ++sb) {
int16_t tmp_sb[SUBBLOCK_SIZE];
const int isChromaSubBlock = (subblock_count - sb <= 2);
- if (isChromaSubBlock) { ++q; }
-
- MultSubBlocks(macroblock, macroblock, qtables[q], 4);
- ZigZagSubBlock(tmp_sb, macroblock);
- InverseDCTSubBlock(macroblock, tmp_sb);
-
- macroblock += SUBBLOCK_SIZE;
- }
-
-}
-
-static void DecodeMacroblock3(int16_t *macroblock, unsigned int subblock_count, const int16_t qtables[3][SUBBLOCK_SIZE])
-{
- unsigned int sb;
- unsigned int q = 0;
-
- for (sb = 0; sb < subblock_count; ++sb)
- {
- int16_t tmp_sb[SUBBLOCK_SIZE];
- const int isChromaSubBlock = (subblock_count - sb <= 2);
-
- if (isChromaSubBlock) { ++q; }
-
- MultSubBlocks(macroblock, macroblock, qtables[q], 4);
- ZigZagSubBlock(tmp_sb, macroblock);
- InverseDCTSubBlock(macroblock, tmp_sb);
-
if (isChromaSubBlock)
- {
- RescaleUVSubBlock(macroblock, macroblock);
- }
- else
- {
- RescaleYSubBlock(macroblock, macroblock);
+ ++q;
+
+ MultSubBlocks(macroblock, macroblock, qtables[q], 4);
+ ZigZagSubBlock(tmp_sb, macroblock);
+ InverseDCTSubBlock(macroblock, tmp_sb);
+
+ if (isChromaSubBlock) {
+ if (transform_chroma != NULL)
+ transform_chroma(macroblock, macroblock);
+ } else {
+ if (transform_luma != NULL)
+ transform_luma(macroblock, macroblock);
}
macroblock += SUBBLOCK_SIZE;
@@ -499,20 +475,17 @@ 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]];
- }
}
static void MultSubBlocks(int16_t *dst, const int16_t *src1, const int16_t *src2, unsigned int shift)
{
unsigned int i;
- for (i = 0; i < SUBBLOCK_SIZE; ++i)
- {
+ for (i = 0; i < SUBBLOCK_SIZE; ++i) {
int32_t v = src1[i] * src2[i];
dst[i] = clamp_s16(v) << shift;
}
@@ -522,8 +495,7 @@ static void ScaleSubBlock(int16_t *dst, const int16_t *src, int16_t scale)
{
unsigned int i;
- for (i = 0; i < SUBBLOCK_SIZE; ++i)
- {
+ for (i = 0; i < SUBBLOCK_SIZE; ++i) {
int32_t v = src[i] * scale;
dst[i] = clamp_s16(v);
}
@@ -534,9 +506,7 @@ static void RShiftSubBlock(int16_t *dst, const int16_t *src, unsigned int shift)
unsigned int i;
for (i = 0; i < SUBBLOCK_SIZE; ++i)
- {
dst[i] = src[i] >> shift;
- }
}
/***************************************************************************
@@ -545,7 +515,7 @@ static void RShiftSubBlock(int16_t *dst, const int16_t *src, unsigned int shift)
* Implementation based on Wikipedia :
* http://fr.wikipedia.org/wiki/Transform%C3%A9e_en_cosinus_discr%C3%A8te
**************************************************************************/
-static void InverseDCT1D(const float * const x, float *dst, unsigned int stride)
+static void InverseDCT1D(const float *const x, float *dst, unsigned int stride)
{
float e[4];
float f[4];
@@ -560,22 +530,29 @@ static void InverseDCT1D(const float * const x, float *dst, unsigned int stride)
f[0] = x[0] + x[4];
f[1] = x[0] - x[4];
- f[2] = x26 + IDCT_K[0]*x[2];
- f[3] = x26 + IDCT_K[1]*x[6];
+ f[2] = x26 + IDCT_K[0] * x[2];
+ f[3] = x26 + IDCT_K[1] * x[6];
- e[0] = x1357 + x15 + IDCT_K[4]*x[1] + x17;
- e[1] = x1357 + x37 + IDCT_K[6]*x[3] + x35;
- e[2] = x1357 + x15 + IDCT_K[5]*x[5] + x35;
- e[3] = x1357 + x37 + IDCT_K[7]*x[7] + x17;
+ e[0] = x1357 + x15 + IDCT_K[4] * x[1] + x17;
+ e[1] = x1357 + x37 + IDCT_K[6] * x[3] + x35;
+ e[2] = x1357 + x15 + IDCT_K[5] * x[5] + x35;
+ e[3] = x1357 + x37 + IDCT_K[7] * x[7] + x17;
- *dst = f[0] + f[2] + e[0]; dst += stride;
- *dst = f[1] + f[3] + e[1]; dst += stride;
- *dst = f[1] - f[3] + e[2]; dst += stride;
- *dst = f[0] - f[2] + e[3]; dst += stride;
- *dst = f[0] - f[2] - e[3]; dst += stride;
- *dst = f[1] - f[3] - e[2]; dst += stride;
- *dst = f[1] + f[3] - e[1]; dst += stride;
- *dst = f[0] + f[2] - e[0]; dst += stride;
+ *dst = f[0] + f[2] + e[0];
+ dst += stride;
+ *dst = f[1] + f[3] + e[1];
+ dst += stride;
+ *dst = f[1] - f[3] + e[2];
+ dst += stride;
+ *dst = f[0] - f[2] + e[3];
+ dst += stride;
+ *dst = f[0] - f[2] - e[3];
+ dst += stride;
+ *dst = f[1] - f[3] - e[2];
+ dst += stride;
+ *dst = f[1] + f[3] - e[1];
+ dst += stride;
+ *dst = f[0] + f[2] - e[0];
}
static void InverseDCTSubBlock(int16_t *dst, const int16_t *src)
@@ -585,26 +562,20 @@ static void InverseDCTSubBlock(int16_t *dst, const int16_t *src)
unsigned int i, j;
/* idct 1d on rows (+transposition) */
- for (i = 0; i < 8; ++i)
- {
+ for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
- {
- x[j] = (float)src[i*8+j];
- }
+ x[j] = (float)src[i * 8 + j];
InverseDCT1D(x, &block[i], 8);
}
/* idct 1d on columns (thanks to previous transposition) */
- for (i = 0; i < 8; ++i)
- {
- InverseDCT1D(&block[i*8], x, 1);
+ for (i = 0; i < 8; ++i) {
+ InverseDCT1D(&block[i * 8], x, 1);
/* C4 = 1 normalization implies a division by 8 */
for (j = 0; j < 8; ++j)
- {
- dst[i+j*8] = (int16_t)x[j] >> 3;
- }
+ dst[i + j * 8] = (int16_t)x[j] >> 3;
}
}
@@ -613,9 +584,7 @@ static void RescaleYSubBlock(int16_t *dst, const int16_t *src)
unsigned int i;
for (i = 0; i < SUBBLOCK_SIZE; ++i)
- {
dst[i] = (((uint32_t)(clamp_s12(src[i]) + 0x800) * 0xdb0) >> 16) + 0x10;
- }
}
static void RescaleUVSubBlock(int16_t *dst, const int16_t *src)
@@ -623,61 +592,6 @@ static void RescaleUVSubBlock(int16_t *dst, const int16_t *src)
unsigned int i;
for (i = 0; i < SUBBLOCK_SIZE; ++i)
- {
dst[i] = (((int)clamp_s12(src[i]) * 0xe00) >> 16) + 0x80;
- }
-}
-
-
-
-/* FIXME: assume presence of expansion pack */
-#define MEMMASK 0x7fffff
-
-static void rdram_read_many_u16(uint16_t *dst, uint32_t address, unsigned int count)
-{
- while (count != 0)
- {
- uint16_t s = rsp.RDRAM[((address++)^S8) & MEMMASK];
- s <<= 8;
- s |= rsp.RDRAM[((address++)^S8) & MEMMASK];
-
- *(dst++) = s;
-
- --count;
- }
-}
-
-static void rdram_write_many_u16(const uint16_t *src, uint32_t address, unsigned int count)
-{
- while (count != 0)
- {
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 8);
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*(src++) & 0xff);
-
- --count;
- }
-}
-
-static uint32_t rdram_read_u32(uint32_t address)
-{
- uint32_t r = rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
- r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
- r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK]; r <<= 8;
- r |= rsp.RDRAM[((address++) ^ S8) & MEMMASK];
-
- return r;
-}
-
-static void rdram_write_many_u32(const uint32_t *src, uint32_t address, unsigned int count)
-{
- while (count != 0)
- {
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 24);
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 16);
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*src >> 8);
- rsp.RDRAM[((address++)^S8) & MEMMASK] = (uint8_t)(*(src++) & 0xff);
-
- --count;
- }
}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/main.c b/libmupen64plus/mupen64plus-rsp-hle/src/main.c
deleted file mode 100644
index ff6525aefa..0000000000
--- a/libmupen64plus/mupen64plus-rsp-hle/src/main.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - main.c *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2012 Bobby Smiles *
- * Copyright (C) 2009 Richard Goedeken *
- * Copyright (C) 2002 Hacktarux *
- * *
- * 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
-#include
-#include
-
-#define M64P_PLUGIN_PROTOTYPES 1
-#include "m64p_types.h"
-#include "m64p_common.h"
-#include "m64p_plugin.h"
-#include "hle.h"
-#include "alist.h"
-#include "cicx105.h"
-#include "jpeg.h"
-
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-
-/* some rsp status flags */
-#define RSP_STATUS_HALT 0x1
-#define RSP_STATUS_BROKE 0x2
-#define RSP_STATUS_INTR_ON_BREAK 0x40
-#define RSP_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 void dump_binary(const char * const filename, const unsigned char * const bytes,
- unsigned int size);
-static void dump_task(const char * const filename, const OSTask_t * const task);
-
-static void handle_unknown_task(unsigned int sum);
-static void handle_unknown_non_task(unsigned int sum);
-
-/* global variables */
-RSP_INFO rsp;
-
-/* local variables */
-static const int FORWARD_AUDIO = 0, FORWARD_GFX = 1;
-static void (*l_DebugCallback)(void *, int, const char *) = NULL;
-static void *l_DebugCallContext = NULL;
-static int l_PluginInit = 0;
-
-/* local functions */
-
-
-/**
- * Try to figure if the RSP was launched using osSpTask* functions
- * and not run directly (in which case DMEM[0xfc0-0xfff] is meaningless).
- *
- * Previously, the ucode_size field was used to determine this,
- * but it is not robust enough (hi Pokemon Stadium !) because games could write anything
- * in this field : most ucode_boot discard the value and just use 0xf7f anyway.
- *
- * Using ucode_boot_size should be more robust in this regard.
- **/
-static int is_task()
-{
- return (get_task()->ucode_boot_size <= 0x1000);
-}
-
-static void rsp_break(unsigned int setbits)
-{
- *rsp.SP_STATUS_REG |= setbits | RSP_STATUS_BROKE | RSP_STATUS_HALT;
-
- if ((*rsp.SP_STATUS_REG & RSP_STATUS_INTR_ON_BREAK))
- {
- *rsp.MI_INTR_REG |= MI_INTR_SP;
- rsp.CheckInterrupts();
- }
-}
-
-static void forward_gfx_task()
-{
- if (rsp.ProcessDlistList != NULL)
- {
- rsp.ProcessDlistList();
- *rsp.DPC_STATUS_REG &= ~DP_STATUS_FREEZE;
- }
-}
-
-static void forward_audio_task()
-{
- if (rsp.ProcessAlistList != NULL)
- {
- rsp.ProcessAlistList();
- }
-}
-
-static void show_cfb()
-{
- if (rsp.ShowCFB != NULL)
- {
- rsp.ShowCFB();
- }
-}
-
-static int try_fast_audio_dispatching()
-{
- /* identify audio ucode by using the content of ucode_data */
- const OSTask_t * const task = get_task();
- const unsigned char * const udata_ptr = rsp.RDRAM + task->ucode_data;
-
- if (*(unsigned int*)(udata_ptr + 0) == 0x00000001)
- {
- if (*(unsigned int*)(udata_ptr + 0x30) == 0xf0000f00)
- {
- /**
- * Many games including:
- * Super Mario 64, Diddy Kong Racing, BlastCorp, GoldenEye, ... (most common)
- **/
- alist_process_ABI1(); return 1;
- }
- else
- {
- /**
- * Mario Kart / Wave Race,
- * LylatWars,
- * FZeroX,
- * Yoshi Story,
- * 1080 Snowboarding,
- * Zelda Ocarina of Time,
- * Zelda Majoras Mask / Pokemon Stadium 2,
- * Animal Crossing
- *
- * FIXME: in fact, all these games do not share the same ABI.
- * That's the reason of the workaround in ucode2.cpp with isZeldaABI and isMKABI
- **/
- alist_process_ABI2(); return 1;
- }
- }
- else
- {
- if (*(unsigned int*)(udata_ptr + 0x10) == 0x00000001)
- {
- /**
- * Musyx ucode found in following games:
- * RogueSquadron, ResidentEvil2, SnowCrossPolaris, TheWorldIsNotEnough,
- * RugratsInParis, NBAShowTime, HydroThunder, Tarzan,
- * GauntletLegend, Rush2049, IndianaJones, BattleForNaboo
- * TODO: implement ucode
- **/
- DebugMessage(M64MSG_WARNING, "MusyX ucode not implemented.");
- /* return 1; */
- }
- else
- {
- /**
- * Many games including:
- * Pokemon Stadium, Banjo Kazooie, Donkey Kong, Banjo Tooie, Jet Force Gemini,
- * Mickey SpeedWay USA, Perfect Dark, Conker Bad Fur Day ...
- **/
- alist_process_ABI3(); return 1;
- }
- }
-
- return 0;
-}
-
-static int try_fast_task_dispatching()
-{
- /* identify task ucode by its type */
- const OSTask_t * const task = get_task();
-
- switch (task->type)
- {
- case 1: if (FORWARD_GFX) { forward_gfx_task(); return 1; } break;
-
- case 2:
- if (FORWARD_AUDIO) { forward_audio_task(); return 1; }
- else if (try_fast_audio_dispatching()) { return 1; }
- break;
-
- case 7: show_cfb(); return 1;
- }
-
- return 0;
-}
-
-static void normal_task_dispatching()
-{
- const OSTask_t * const task = get_task();
- const unsigned int sum =
- sum_bytes(rsp.RDRAM + task->ucode, min(task->ucode_size, 0xf80) >> 1);
-
- switch (sum)
- {
- /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */
- case 0x278: /* Nothing to emulate */ return;
-
- /* GFX: Twintris [misleading task->type == 0] */
- case 0x212ee:
- if (FORWARD_GFX) { forward_gfx_task(); return; }
- break;
-
- /* JPEG: found in Pokemon Stadium J */
- case 0x2c85a: jpeg_decode_PS0(); return;
-
- /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */
- case 0x2caa6: jpeg_decode_PS(); return;
-
- /* JPEG: found in Ogre Battle, Bottom of the 9th */
- case 0x130de: jpeg_decode_OB(); return;
- }
-
- handle_unknown_task(sum);
-}
-
-static void non_task_dispatching()
-{
- const unsigned int sum = sum_bytes(rsp.IMEM, 0x1000 >> 1);
-
- switch(sum)
- {
- /* CIC x105 ucode (used during boot of CIC x105 games) */
- case 0x9e2: /* CIC 6105 */
- case 0x9f2: /* CIC 7105 */
- cicx105_ucode(); return;
- }
-
- handle_unknown_non_task(sum);
-}
-
-static void handle_unknown_task(unsigned int sum)
-{
- char filename[256];
- const OSTask_t * const task = get_task();
-
- DebugMessage(M64MSG_WARNING, "unknown OSTask: sum %x PC:%x", sum, *rsp.SP_PC_REG);
-
- sprintf(&filename[0], "task_%x.log", sum);
- dump_task(filename, task);
-
- // dump ucode_boot
- sprintf(&filename[0], "ucode_boot_%x.bin", sum);
- dump_binary(filename, rsp.RDRAM + (task->ucode_boot & 0x7fffff), task->ucode_boot_size);
-
- // dump ucode
- if (task->ucode != 0)
- {
- sprintf(&filename[0], "ucode_%x.bin", sum);
- dump_binary(filename, rsp.RDRAM + (task->ucode & 0x7fffff), 0xf80);
- }
-
- // dump ucode_data
- if (task->ucode_data != 0)
- {
- sprintf(&filename[0], "ucode_data_%x.bin", sum);
- dump_binary(filename, rsp.RDRAM + (task->ucode_data & 0x7fffff), task->ucode_data_size);
- }
-
- // dump data
- if (task->data_ptr != 0)
- {
- sprintf(&filename[0], "data_%x.bin", sum);
- dump_binary(filename, rsp.RDRAM + (task->data_ptr & 0x7fffff), task->data_size);
- }
-}
-
-static void handle_unknown_non_task(unsigned int sum)
-{
- char filename[256];
-
- DebugMessage(M64MSG_WARNING, "unknown RSP code: sum: %x PC:%x", sum, *rsp.SP_PC_REG);
-
- // dump IMEM & DMEM for further analysis
- sprintf(&filename[0], "imem_%x.bin", sum);
- dump_binary(filename, rsp.IMEM, 0x1000);
-
- sprintf(&filename[0], "dmem_%x.bin", sum);
- dump_binary(filename, rsp.DMEM, 0x1000);
-}
-
-
-/* Global functions */
-void DebugMessage(int level, const char *message, ...)
-{
- char msgbuf[1024];
- va_list args;
-
- if (l_DebugCallback == NULL)
- return;
-
- va_start(args, message);
- vsprintf(msgbuf, message, args);
-
- (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
-
- va_end(args);
-}
-
-/* DLL-exported functions */
-EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
- void (*DebugCallback)(void *, int, const char *))
-{
- if (l_PluginInit)
- return M64ERR_ALREADY_INIT;
-
- /* first thing is to set the callback function for debug info */
- 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 */
-
- l_PluginInit = 1;
- return M64ERR_SUCCESS;
-}
-
-EXPORT m64p_error CALL PluginShutdown(void)
-{
- if (!l_PluginInit)
- return M64ERR_NOT_INIT;
-
- /* reset some local variable */
- l_DebugCallback = NULL;
- l_DebugCallContext = NULL;
-
- l_PluginInit = 0;
- return M64ERR_SUCCESS;
-}
-
-EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
-{
- /* set version info */
- if (PluginType != NULL)
- *PluginType = M64PLUGIN_RSP;
-
- if (PluginVersion != NULL)
- *PluginVersion = RSP_HLE_VERSION;
-
- if (APIVersion != NULL)
- *APIVersion = RSP_PLUGIN_API_VERSION;
-
- if (PluginNamePtr != NULL)
- *PluginNamePtr = "Hacktarux/Azimer High-Level Emulation RSP Plugin";
-
- if (Capabilities != NULL)
- {
- *Capabilities = 0;
- }
-
- return M64ERR_SUCCESS;
-}
-
-EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles)
-{
- if (is_task())
- {
- if (!try_fast_task_dispatching()) { normal_task_dispatching(); }
- rsp_break(RSP_STATUS_TASKDONE);
- }
- else
- {
- non_task_dispatching();
- rsp_break(0);
- }
-
- return Cycles;
-}
-
-EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount)
-{
- rsp = Rsp_Info;
-}
-
-EXPORT void CALL RomClosed(void)
-{
- memset(rsp.DMEM, 0, 0x1000);
- memset(rsp.IMEM, 0, 0x1000);
-
- init_ucode2();
-}
-
-
-/* local helper functions */
-static unsigned int sum_bytes(const unsigned char *bytes, unsigned int size)
-{
- unsigned int sum = 0;
- const unsigned char * const bytes_end = bytes + size;
-
- while (bytes != bytes_end)
- sum += *bytes++;
-
- return sum;
-}
-
-
-static void dump_binary(const char * const filename, const unsigned char * const bytes,
- unsigned int size)
-{
- FILE *f;
-
- // if file already exists, do nothing
- f = fopen(filename, "r");
- if (f == NULL)
- {
- // else we write bytes to the file
- f= fopen(filename, "wb");
- if (f != NULL) {
- if (fwrite(bytes, 1, size, f) != size)
- {
- DebugMessage(M64MSG_ERROR, "Writing error on %s", filename);
- }
- fclose(f);
- }
- else
- {
- DebugMessage(M64MSG_ERROR, "Couldn't open %s for writing !", filename);
- }
- }
- else
- {
- fclose(f);
- }
-}
-
-static void dump_task(const char * const filename, const OSTask_t * const task)
-{
- FILE *f;
-
- f = fopen(filename, "r");
- if (f == NULL)
- {
- f = fopen(filename, "w");
- fprintf(f,
- "type = %d\n"
- "flags = %d\n"
- "ucode_boot = %#08x size = %#x\n"
- "ucode = %#08x size = %#x\n"
- "ucode_data = %#08x size = %#x\n"
- "dram_stack = %#08x size = %#x\n"
- "output_buff = %#08x *size = %#x\n"
- "data = %#08x size = %#x\n"
- "yield_data = %#08x size = %#x\n",
- task->type, task->flags,
- task->ucode_boot, task->ucode_boot_size,
- task->ucode, task->ucode_size,
- task->ucode_data, task->ucode_data_size,
- task->dram_stack, task->dram_stack_size,
- task->output_buff, task->output_buff_size,
- task->data_ptr, task->data_size,
- task->yield_data_ptr, task->yield_data_size);
- fclose(f);
- }
- else
- {
- fclose(f);
- }
-}
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/memory.c b/libmupen64plus/mupen64plus-rsp-hle/src/memory.c
new file mode 100644
index 0000000000..7d5066bfa1
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/memory.c
@@ -0,0 +1,74 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - memory.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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
+
+#include "memory.h"
+
+/* Global functions */
+void load_u8(uint8_t* dst, const unsigned char* buffer, unsigned address, size_t count)
+{
+ while (count != 0) {
+ *(dst++) = *u8(buffer, address);
+ address += 1;
+ --count;
+ }
+}
+
+void load_u16(uint16_t* dst, const unsigned char* buffer, unsigned address, size_t count)
+{
+ while (count != 0) {
+ *(dst++) = *u16(buffer, address);
+ address += 2;
+ --count;
+ }
+}
+
+void load_u32(uint32_t* dst, const unsigned char* buffer, unsigned address, size_t count)
+{
+ /* Optimization for uint32_t */
+ memcpy(dst, u32(buffer, address), count * sizeof(uint32_t));
+}
+
+void store_u8(unsigned char* buffer, unsigned address, const uint8_t* src, size_t count)
+{
+ while (count != 0) {
+ *u8(buffer, address) = *(src++);
+ address += 1;
+ --count;
+ }
+}
+
+void store_u16(unsigned char* buffer, unsigned address, const uint16_t* src, size_t count)
+{
+ while (count != 0) {
+ *u16(buffer, address) = *(src++);
+ address += 2;
+ --count;
+ }
+}
+
+void store_u32(unsigned char* buffer, unsigned address, const uint32_t* src, size_t count)
+{
+ /* Optimization for uint32_t */
+ memcpy(u32(buffer, address), src, count * sizeof(uint32_t));
+}
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/memory.h b/libmupen64plus/mupen64plus-rsp-hle/src/memory.h
new file mode 100644
index 0000000000..9c85104838
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/memory.h
@@ -0,0 +1,185 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - memory.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#include
+#include
+#include
+
+#include "common.h"
+#include "hle_internal.h"
+
+#ifdef M64P_BIG_ENDIAN
+#define S 0
+#define S16 0
+#define S8 0
+#else
+#define S 1
+#define S16 2
+#define S8 3
+#endif
+
+enum {
+ TASK_TYPE = 0xfc0,
+ TASK_FLAGS = 0xfc4,
+ TASK_UCODE_BOOT = 0xfc8,
+ TASK_UCODE_BOOT_SIZE = 0xfcc,
+ TASK_UCODE = 0xfd0,
+ TASK_UCODE_SIZE = 0xfd4,
+ TASK_UCODE_DATA = 0xfd8,
+ TASK_UCODE_DATA_SIZE = 0xfdc,
+ TASK_DRAM_STACK = 0xfe0,
+ TASK_DRAM_STACK_SIZE = 0xfe4,
+ TASK_OUTPUT_BUFF = 0xfe8,
+ TASK_OUTPUT_BUFF_SIZE = 0xfec,
+ TASK_DATA_PTR = 0xff0,
+ TASK_DATA_SIZE = 0xff4,
+ TASK_YIELD_DATA_PTR = 0xff8,
+ TASK_YIELD_DATA_SIZE = 0xffc
+};
+
+static inline unsigned int align(unsigned int x, unsigned amount)
+{
+ --amount;
+ return (x + amount) & ~amount;
+}
+
+static inline uint8_t* u8(const unsigned char* buffer, unsigned address)
+{
+ return (uint8_t*)(buffer + (address ^ S8));
+}
+
+static inline uint16_t* u16(const unsigned char* buffer, unsigned address)
+{
+ assert((address & 1) == 0);
+ return (uint16_t*)(buffer + (address ^ S16));
+}
+
+static inline uint32_t* u32(const unsigned char* buffer, unsigned address)
+{
+ assert((address & 3) == 0);
+ return (uint32_t*)(buffer + address);
+}
+
+void load_u8 (uint8_t* dst, const unsigned char* buffer, unsigned address, size_t count);
+void load_u16(uint16_t* dst, const unsigned char* buffer, unsigned address, size_t count);
+void load_u32(uint32_t* dst, const unsigned char* buffer, unsigned address, size_t count);
+void store_u8 (unsigned char* buffer, unsigned address, const uint8_t* src, size_t count);
+void store_u16(unsigned char* buffer, unsigned address, const uint16_t* src, size_t count);
+void store_u32(unsigned char* buffer, unsigned address, const uint32_t* src, size_t count);
+
+
+/* convenient functions for DMEM access */
+static inline uint8_t* dmem_u8(struct hle_t* hle, uint16_t address)
+{
+ return u8(hle->dmem, address & 0xfff);
+}
+
+static inline uint16_t* dmem_u16(struct hle_t* hle, uint16_t address)
+{
+ return u16(hle->dmem, address & 0xfff);
+}
+
+static inline uint32_t* dmem_u32(struct hle_t* hle, uint16_t address)
+{
+ return u32(hle->dmem, address & 0xfff);
+}
+
+static inline void dmem_load_u8(struct hle_t* hle, uint8_t* dst, uint16_t address, size_t count)
+{
+ load_u8(dst, hle->dmem, address & 0xfff, count);
+}
+
+static inline void dmem_load_u16(struct hle_t* hle, uint16_t* dst, uint16_t address, size_t count)
+{
+ load_u16(dst, hle->dmem, address & 0xfff, count);
+}
+
+static inline void dmem_load_u32(struct hle_t* hle, uint32_t* dst, uint16_t address, size_t count)
+{
+ load_u32(dst, hle->dmem, address & 0xfff, count);
+}
+
+static inline void dmem_store_u8(struct hle_t* hle, const uint8_t* src, uint16_t address, size_t count)
+{
+ store_u8(hle->dmem, address & 0xfff, src, count);
+}
+
+static inline void dmem_store_u16(struct hle_t* hle, const uint16_t* src, uint16_t address, size_t count)
+{
+ store_u16(hle->dmem, address & 0xfff, src, count);
+}
+
+static inline void dmem_store_u32(struct hle_t* hle, const uint32_t* src, uint16_t address, size_t count)
+{
+ store_u32(hle->dmem, address & 0xfff, src, count);
+}
+
+/* convenient functions DRAM access */
+static inline uint8_t* dram_u8(struct hle_t* hle, uint32_t address)
+{
+ return u8(hle->dram, address & 0xffffff);
+}
+
+static inline uint16_t* dram_u16(struct hle_t* hle, uint32_t address)
+{
+ return u16(hle->dram, address & 0xffffff);
+}
+
+static inline uint32_t* dram_u32(struct hle_t* hle, uint32_t address)
+{
+ return u32(hle->dram, address & 0xffffff);
+}
+
+static inline void dram_load_u8(struct hle_t* hle, uint8_t* dst, uint32_t address, size_t count)
+{
+ load_u8(dst, hle->dram, address & 0xffffff, count);
+}
+
+static inline void dram_load_u16(struct hle_t* hle, uint16_t* dst, uint32_t address, size_t count)
+{
+ load_u16(dst, hle->dram, address & 0xffffff, count);
+}
+
+static inline void dram_load_u32(struct hle_t* hle, uint32_t* dst, uint32_t address, size_t count)
+{
+ load_u32(dst, hle->dram, address & 0xffffff, count);
+}
+
+static inline void dram_store_u8(struct hle_t* hle, const uint8_t* src, uint32_t address, size_t count)
+{
+ store_u8(hle->dram, address & 0xffffff, src, count);
+}
+
+static inline void dram_store_u16(struct hle_t* hle, const uint16_t* src, uint32_t address, size_t count)
+{
+ store_u16(hle->dram, address & 0xffffff, src, count);
+}
+
+static inline void dram_store_u32(struct hle_t* hle, const uint32_t* src, uint32_t address, size_t count)
+{
+ store_u32(hle->dram, address & 0xffffff, src, count);
+}
+
+#endif
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/mp3.c b/libmupen64plus/mupen64plus-rsp-hle/src/mp3.c
new file mode 100644
index 0000000000..4e8ea14afd
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/mp3.c
@@ -0,0 +1,684 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - mp3.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+
+#include "arithmetics.h"
+#include "hle_internal.h"
+#include "memory.h"
+
+static void InnerLoop(struct hle_t* hle,
+ uint32_t outPtr, uint32_t inPtr,
+ uint32_t t6, uint32_t t5, uint32_t t4);
+
+static const uint16_t DeWindowLUT [0x420] = {
+ 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
+ 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
+ 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
+ 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
+ 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
+ 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
+ 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
+ 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
+ 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
+ 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
+ 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
+ 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
+ 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
+ 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
+ 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
+ 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
+ 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
+ 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
+ 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
+ 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
+ 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
+ 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
+ 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
+ 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
+ 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
+ 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
+ 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
+ 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
+ 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
+ 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
+ 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
+ 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
+ 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
+ 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
+ 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
+ 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
+ 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
+ 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
+ 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
+ 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
+ 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
+ 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
+ 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
+ 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
+ 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
+ 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
+ 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
+ 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
+ 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
+ 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
+ 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
+ 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
+ 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
+ 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
+ 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
+ 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
+ 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
+ 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
+ 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
+ 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
+ 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
+ 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
+ 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
+ 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
+ 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
+ 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
+ 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
+ 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
+ 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
+ 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
+ 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
+ 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
+ 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
+ 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
+ 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
+ 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
+ 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
+ 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
+ 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
+ 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
+ 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
+ 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0003,
+ 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
+ 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0004,
+ 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
+ 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
+ 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
+ 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
+ 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
+ 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0004,
+ 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
+ 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0005,
+ 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
+ 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0005,
+ 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
+ 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0006,
+ 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
+ 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
+ 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
+ 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
+ 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
+ 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0006,
+ 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
+ 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0007,
+ 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
+ 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
+ 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
+ 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
+ 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
+ 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0007,
+ 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
+ 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0008,
+ 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
+ 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0008,
+ 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
+ 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0009,
+ 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
+ 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x0009,
+ 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
+ 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x000A,
+ 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
+ 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000A,
+ 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
+ 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000B,
+ 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
+ 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000B,
+ 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
+ 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000D,
+ 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
+ 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x000D,
+ 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
+ 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x0000
+};
+
+static void MP3AB0(int32_t* v)
+{
+ /* Part 2 - 100% Accurate */
+ static const uint16_t LUT2[8] = {
+ 0xFEC4, 0xF4FA, 0xC5E4, 0xE1C4,
+ 0x1916, 0x4A50, 0xA268, 0x78AE
+ };
+ static const uint16_t LUT3[4] = { 0xFB14, 0xD4DC, 0x31F2, 0x8E3A };
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ v[16 + i] = v[0 + i] + v[8 + i];
+ v[24 + i] = ((v[0 + i] - v[8 + i]) * LUT2[i]) >> 0x10;
+ }
+
+ /* Part 3: 4-wide butterflies */
+
+ for (i = 0; i < 4; i++) {
+ v[0 + i] = v[16 + i] + v[20 + i];
+ v[4 + i] = ((v[16 + i] - v[20 + i]) * LUT3[i]) >> 0x10;
+
+ v[8 + i] = v[24 + i] + v[28 + i];
+ v[12 + i] = ((v[24 + i] - v[28 + i]) * LUT3[i]) >> 0x10;
+ }
+
+ /* Part 4: 2-wide butterflies - 100% Accurate */
+
+ for (i = 0; i < 16; i += 4) {
+ v[16 + i] = v[0 + i] + v[2 + i];
+ v[18 + i] = ((v[0 + i] - v[2 + i]) * 0xEC84) >> 0x10;
+
+ v[17 + i] = v[1 + i] + v[3 + i];
+ v[19 + i] = ((v[1 + i] - v[3 + i]) * 0x61F8) >> 0x10;
+ }
+}
+
+void mp3_task(struct hle_t* hle, unsigned int index, uint32_t address)
+{
+ uint32_t inPtr, outPtr;
+ uint32_t t6;/* = 0x08A0; - I think these are temporary storage buffers */
+ uint32_t t5;/* = 0x0AC0; */
+ uint32_t t4;/* = (w1 & 0x1E); */
+
+ /* Initialization Code */
+ uint32_t readPtr; /* s5 */
+ uint32_t writePtr; /* s6 */
+ uint32_t tmp;
+ int cnt, cnt2;
+
+ /* I think these are temporary storage buffers */
+ t6 = 0x08A0;
+ t5 = 0x0AC0;
+ t4 = index;
+
+ writePtr = readPtr = address;
+ /* Just do that for efficiency... may remove and use directly later anyway */
+ memcpy(hle->mp3_buffer + 0xCE8, hle->dram + readPtr, 8);
+ /* This must be a header byte or whatnot */
+ readPtr += 8;
+
+ for (cnt = 0; cnt < 0x480; cnt += 0x180) {
+ /* DMA: 0xCF0 <- RDRAM[s5] : 0x180 */
+ memcpy(hle->mp3_buffer + 0xCF0, hle->dram + readPtr, 0x180);
+ inPtr = 0xCF0; /* s7 */
+ outPtr = 0xE70; /* s3 */
+/* --------------- Inner Loop Start -------------------- */
+ for (cnt2 = 0; cnt2 < 0x180; cnt2 += 0x40) {
+ t6 &= 0xFFE0;
+ t5 &= 0xFFE0;
+ t6 |= t4;
+ t5 |= t4;
+ InnerLoop(hle, outPtr, inPtr, t6, t5, t4);
+ t4 = (t4 - 2) & 0x1E;
+ tmp = t6;
+ t6 = t5;
+ t5 = tmp;
+ inPtr += 0x40;
+ outPtr += 0x40;
+ }
+/* --------------- Inner Loop End -------------------- */
+ memcpy(hle->dram + writePtr, hle->mp3_buffer + 0xe70, 0x180);
+ writePtr += 0x180;
+ readPtr += 0x180;
+ }
+}
+
+static void InnerLoop(struct hle_t* hle,
+ uint32_t outPtr, uint32_t inPtr,
+ uint32_t t6, uint32_t t5, uint32_t t4)
+{
+ /* Part 1: 100% Accurate */
+
+ /* 0, 1, 3, 2, 7, 6, 4, 5, 7, 6, 4, 5, 0, 1, 3, 2 */
+ static const uint16_t LUT6[16] = {
+ 0xFFB2, 0xFD3A, 0xF10A, 0xF854,
+ 0xBDAE, 0xCDA0, 0xE76C, 0xDB94,
+ 0x1920, 0x4B20, 0xAC7C, 0x7C68,
+ 0xABEC, 0x9880, 0xDAE8, 0x839C
+ };
+ int i;
+ uint32_t t0;
+ uint32_t t1;
+ uint32_t t2;
+ uint32_t t3;
+ int32_t v2 = 0, v4 = 0, v6 = 0, v8 = 0;
+ uint32_t offset;
+ uint32_t addptr;
+ int x;
+ int32_t mult6;
+ int32_t mult4;
+ int tmp;
+ int32_t hi0;
+ int32_t hi1;
+ int32_t vt;
+ int32_t v[32];
+
+ v[0] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x00 ^ S16));
+ v[31] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3E ^ S16));
+ v[0] += v[31];
+ v[1] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x02 ^ S16));
+ v[30] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3C ^ S16));
+ v[1] += v[30];
+ v[2] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x06 ^ S16));
+ v[28] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x38 ^ S16));
+ v[2] += v[28];
+ v[3] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x04 ^ S16));
+ v[29] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3A ^ S16));
+ v[3] += v[29];
+
+ v[4] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0E ^ S16));
+ v[24] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x30 ^ S16));
+ v[4] += v[24];
+ v[5] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0C ^ S16));
+ v[25] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x32 ^ S16));
+ v[5] += v[25];
+ v[6] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x08 ^ S16));
+ v[27] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x36 ^ S16));
+ v[6] += v[27];
+ v[7] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0A ^ S16));
+ v[26] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x34 ^ S16));
+ v[7] += v[26];
+
+ v[8] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1E ^ S16));
+ v[16] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x20 ^ S16));
+ v[8] += v[16];
+ v[9] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1C ^ S16));
+ v[17] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x22 ^ S16));
+ v[9] += v[17];
+ v[10] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x18 ^ S16));
+ v[19] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x26 ^ S16));
+ v[10] += v[19];
+ v[11] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1A ^ S16));
+ v[18] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x24 ^ S16));
+ v[11] += v[18];
+
+ v[12] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x10 ^ S16));
+ v[23] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2E ^ S16));
+ v[12] += v[23];
+ v[13] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x12 ^ S16));
+ v[22] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2C ^ S16));
+ v[13] += v[22];
+ v[14] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x16 ^ S16));
+ v[20] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x28 ^ S16));
+ v[14] += v[20];
+ v[15] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x14 ^ S16));
+ v[21] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2A ^ S16));
+ v[15] += v[21];
+
+ /* Part 2-4 */
+
+ MP3AB0(v);
+
+ /* Part 5 - 1-Wide Butterflies - 100% Accurate but need SSVs!!! */
+
+ t0 = t6 + 0x100;
+ t1 = t6 + 0x200;
+ t2 = t5 + 0x100;
+ t3 = t5 + 0x200;
+
+ /* 0x13A8 */
+ v[1] = 0;
+ v[11] = ((v[16] - v[17]) * 0xB504) >> 0x10;
+
+ v[16] = -v[16] - v[17];
+ v[2] = v[18] + v[19];
+ /* ** Store v[11] -> (T6 + 0)** */
+ *(int16_t *)(hle->mp3_buffer + ((t6 + (short)0x0))) = (short)v[11];
+
+
+ v[11] = -v[11];
+ /* ** Store v[16] -> (T3 + 0)** */
+ *(int16_t *)(hle->mp3_buffer + ((t3 + (short)0x0))) = (short)v[16];
+ /* ** Store v[11] -> (T5 + 0)** */
+ *(int16_t *)(hle->mp3_buffer + ((t5 + (short)0x0))) = (short)v[11];
+ /* 0x13E8 - Verified.... */
+ v[2] = -v[2];
+ /* ** Store v[2] -> (T2 + 0)** */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0x0))) = (short)v[2];
+ v[3] = (((v[18] - v[19]) * 0x16A09) >> 0x10) + v[2];
+ /* ** Store v[3] -> (T0 + 0)** */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0x0))) = (short)v[3];
+ /* 0x1400 - Verified */
+ v[4] = -v[20] - v[21];
+ v[6] = v[22] + v[23];
+ v[5] = ((v[20] - v[21]) * 0x16A09) >> 0x10;
+ /* ** Store v[4] -> (T3 + 0xFF80) */
+ *(int16_t *)(hle->mp3_buffer + ((t3 + (short)0xFF80))) = (short)v[4];
+ v[7] = ((v[22] - v[23]) * 0x2D413) >> 0x10;
+ v[5] = v[5] - v[4];
+ v[7] = v[7] - v[5];
+ v[6] = v[6] + v[6];
+ v[5] = v[5] - v[6];
+ v[4] = -v[4] - v[6];
+ /* *** Store v[7] -> (T1 + 0xFF80) */
+ *(int16_t *)(hle->mp3_buffer + ((t1 + (short)0xFF80))) = (short)v[7];
+ /* *** Store v[4] -> (T2 + 0xFF80) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0xFF80))) = (short)v[4];
+ /* *** Store v[5] -> (T0 + 0xFF80) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0xFF80))) = (short)v[5];
+ v[8] = v[24] + v[25];
+
+
+ v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
+ v[2] = v[8] + v[9];
+ v[11] = ((v[26] - v[27]) * 0x2D413) >> 0x10;
+ v[13] = ((v[28] - v[29]) * 0x2D413) >> 0x10;
+
+ v[10] = v[26] + v[27];
+ v[10] = v[10] + v[10];
+ v[12] = v[28] + v[29];
+ v[12] = v[12] + v[12];
+ v[14] = v[30] + v[31];
+ v[3] = v[8] + v[10];
+ v[14] = v[14] + v[14];
+ v[13] = (v[13] - v[2]) + v[12];
+ v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - (v[11] + v[2]);
+ v[14] = -(v[14] + v[14]) + v[3];
+ v[17] = v[13] - v[10];
+ v[9] = v[9] + v[14];
+ /* ** Store v[9] -> (T6 + 0x40) */
+ *(int16_t *)(hle->mp3_buffer + ((t6 + (short)0x40))) = (short)v[9];
+ v[11] = v[11] - v[13];
+ /* ** Store v[17] -> (T0 + 0xFFC0) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0xFFC0))) = (short)v[17];
+ v[12] = v[8] - v[12];
+ /* ** Store v[11] -> (T0 + 0x40) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0x40))) = (short)v[11];
+ v[8] = -v[8];
+ /* ** Store v[15] -> (T1 + 0xFFC0) */
+ *(int16_t *)(hle->mp3_buffer + ((t1 + (short)0xFFC0))) = (short)v[15];
+ v[10] = -v[10] - v[12];
+ /* ** Store v[12] -> (T2 + 0x40) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0x40))) = (short)v[12];
+ /* ** Store v[8] -> (T3 + 0xFFC0) */
+ *(int16_t *)(hle->mp3_buffer + ((t3 + (short)0xFFC0))) = (short)v[8];
+ /* ** Store v[14] -> (T5 + 0x40) */
+ *(int16_t *)(hle->mp3_buffer + ((t5 + (short)0x40))) = (short)v[14];
+ /* ** Store v[10] -> (T2 + 0xFFC0) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0xFFC0))) = (short)v[10];
+ /* 0x14FC - Verified... */
+
+ /* Part 6 - 100% Accurate */
+
+ v[0] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x00 ^ S16));
+ v[31] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3E ^ S16));
+ v[0] -= v[31];
+ v[1] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x02 ^ S16));
+ v[30] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3C ^ S16));
+ v[1] -= v[30];
+ v[2] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x06 ^ S16));
+ v[28] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x38 ^ S16));
+ v[2] -= v[28];
+ v[3] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x04 ^ S16));
+ v[29] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x3A ^ S16));
+ v[3] -= v[29];
+
+ v[4] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0E ^ S16));
+ v[24] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x30 ^ S16));
+ v[4] -= v[24];
+ v[5] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0C ^ S16));
+ v[25] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x32 ^ S16));
+ v[5] -= v[25];
+ v[6] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x08 ^ S16));
+ v[27] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x36 ^ S16));
+ v[6] -= v[27];
+ v[7] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x0A ^ S16));
+ v[26] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x34 ^ S16));
+ v[7] -= v[26];
+
+ v[8] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1E ^ S16));
+ v[16] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x20 ^ S16));
+ v[8] -= v[16];
+ v[9] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1C ^ S16));
+ v[17] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x22 ^ S16));
+ v[9] -= v[17];
+ v[10] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x18 ^ S16));
+ v[19] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x26 ^ S16));
+ v[10] -= v[19];
+ v[11] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x1A ^ S16));
+ v[18] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x24 ^ S16));
+ v[11] -= v[18];
+
+ v[12] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x10 ^ S16));
+ v[23] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2E ^ S16));
+ v[12] -= v[23];
+ v[13] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x12 ^ S16));
+ v[22] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2C ^ S16));
+ v[13] -= v[22];
+ v[14] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x16 ^ S16));
+ v[20] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x28 ^ S16));
+ v[14] -= v[20];
+ v[15] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x14 ^ S16));
+ v[21] = *(int16_t *)(hle->mp3_buffer + inPtr + (0x2A ^ S16));
+ v[15] -= v[21];
+
+ for (i = 0; i < 16; i++)
+ v[0 + i] = (v[0 + i] * LUT6[i]) >> 0x10;
+ v[0] = v[0] + v[0];
+ v[1] = v[1] + v[1];
+ v[2] = v[2] + v[2];
+ v[3] = v[3] + v[3];
+ v[4] = v[4] + v[4];
+ v[5] = v[5] + v[5];
+ v[6] = v[6] + v[6];
+ v[7] = v[7] + v[7];
+ v[12] = v[12] + v[12];
+ v[13] = v[13] + v[13];
+ v[15] = v[15] + v[15];
+
+ MP3AB0(v);
+
+ /* Part 7: - 100% Accurate + SSV - Unoptimized */
+
+ v[0] = (v[17] + v[16]) >> 1;
+ v[1] = ((v[17] * (int)((short)0xA57E * 2)) + (v[16] * 0xB504)) >> 0x10;
+ v[2] = -v[18] - v[19];
+ v[3] = ((v[18] - v[19]) * 0x16A09) >> 0x10;
+ v[4] = v[20] + v[21] + v[0];
+ v[5] = (((v[20] - v[21]) * 0x16A09) >> 0x10) + v[1];
+ v[6] = (((v[22] + v[23]) << 1) + v[0]) - v[2];
+ v[7] = (((v[22] - v[23]) * 0x2D413) >> 0x10) + v[0] + v[1] + v[3];
+ /* 0x16A8 */
+ /* Save v[0] -> (T3 + 0xFFE0) */
+ *(int16_t *)(hle->mp3_buffer + ((t3 + (short)0xFFE0))) = (short) - v[0];
+ v[8] = v[24] + v[25];
+ v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
+ v[10] = ((v[26] + v[27]) << 1) + v[8];
+ v[11] = (((v[26] - v[27]) * 0x2D413) >> 0x10) + v[8] + v[9];
+ v[12] = v[4] - ((v[28] + v[29]) << 1);
+ /* ** Store v12 -> (T2 + 0x20) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0x20))) = (short)v[12];
+ v[13] = (((v[28] - v[29]) * 0x2D413) >> 0x10) - v[12] - v[5];
+ v[14] = v[30] + v[31];
+ v[14] = v[14] + v[14];
+ v[14] = v[14] + v[14];
+ v[14] = v[6] - v[14];
+ v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - v[7];
+ /* Store v14 -> (T5 + 0x20) */
+ *(int16_t *)(hle->mp3_buffer + ((t5 + (short)0x20))) = (short)v[14];
+ v[14] = v[14] + v[1];
+ /* Store v[14] -> (T6 + 0x20) */
+ *(int16_t *)(hle->mp3_buffer + ((t6 + (short)0x20))) = (short)v[14];
+ /* Store v[15] -> (T1 + 0xFFE0) */
+ *(int16_t *)(hle->mp3_buffer + ((t1 + (short)0xFFE0))) = (short)v[15];
+ v[9] = v[9] + v[10];
+ v[1] = v[1] + v[6];
+ v[6] = v[10] - v[6];
+ v[1] = v[9] - v[1];
+ /* Store v[6] -> (T5 + 0x60) */
+ *(int16_t *)(hle->mp3_buffer + ((t5 + (short)0x60))) = (short)v[6];
+ v[10] = v[10] + v[2];
+ v[10] = v[4] - v[10];
+ /* Store v[10] -> (T2 + 0xFFA0) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0xFFA0))) = (short)v[10];
+ v[12] = v[2] - v[12];
+ /* Store v[12] -> (T2 + 0xFFE0) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0xFFE0))) = (short)v[12];
+ v[5] = v[4] + v[5];
+ v[4] = v[8] - v[4];
+ /* Store v[4] -> (T2 + 0x60) */
+ *(int16_t *)(hle->mp3_buffer + ((t2 + (short)0x60))) = (short)v[4];
+ v[0] = v[0] - v[8];
+ /* Store v[0] -> (T3 + 0xFFA0) */
+ *(int16_t *)(hle->mp3_buffer + ((t3 + (short)0xFFA0))) = (short)v[0];
+ v[7] = v[7] - v[11];
+ /* Store v[7] -> (T1 + 0xFFA0) */
+ *(int16_t *)(hle->mp3_buffer + ((t1 + (short)0xFFA0))) = (short)v[7];
+ v[11] = v[11] - v[3];
+ /* Store v[1] -> (T6 + 0x60) */
+ *(int16_t *)(hle->mp3_buffer + ((t6 + (short)0x60))) = (short)v[1];
+ v[11] = v[11] - v[5];
+ /* Store v[11] -> (T0 + 0x60) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0x60))) = (short)v[11];
+ v[3] = v[3] - v[13];
+ /* Store v[3] -> (T0 + 0x20) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0x20))) = (short)v[3];
+ v[13] = v[13] + v[2];
+ /* Store v[13] -> (T0 + 0xFFE0) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0xFFE0))) = (short)v[13];
+ v[2] = (v[5] - v[2]) - v[9];
+ /* Store v[2] -> (T0 + 0xFFA0) */
+ *(int16_t *)(hle->mp3_buffer + ((t0 + (short)0xFFA0))) = (short)v[2];
+ /* 0x7A8 - Verified... */
+
+ /* Step 8 - Dewindowing */
+
+ addptr = t6 & 0xFFE0;
+
+ offset = 0x10 - (t4 >> 1);
+ for (x = 0; x < 8; x++) {
+ int32_t v0;
+ int32_t v18;
+ v2 = v4 = v6 = v8 = 0;
+
+ for (i = 7; i >= 0; i--) {
+ v2 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
+ v4 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
+ v6 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x20) * (short)DeWindowLUT[offset + 0x20] + 0x4000) >> 0xF;
+ v8 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x30) * (short)DeWindowLUT[offset + 0x28] + 0x4000) >> 0xF;
+ addptr += 2;
+ offset++;
+ }
+ v0 = v2 + v4;
+ v18 = v6 + v8;
+ /* Clamp(v0); */
+ /* Clamp(v18); */
+ /* clamp??? */
+ *(int16_t *)(hle->mp3_buffer + (outPtr ^ S16)) = v0;
+ *(int16_t *)(hle->mp3_buffer + ((outPtr + 2)^S16)) = v18;
+ outPtr += 4;
+ addptr += 0x30;
+ offset += 0x38;
+ }
+
+ offset = 0x10 - (t4 >> 1) + 8 * 0x40;
+ v2 = v4 = 0;
+ for (i = 0; i < 4; i++) {
+ v2 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
+ v2 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
+ addptr += 2;
+ offset++;
+ v4 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
+ v4 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
+ addptr += 2;
+ offset++;
+ }
+ mult6 = *(int32_t *)(hle->mp3_buffer + 0xCE8);
+ mult4 = *(int32_t *)(hle->mp3_buffer + 0xCEC);
+ if (t4 & 0x2) {
+ v2 = (v2 **(uint32_t *)(hle->mp3_buffer + 0xCE8)) >> 0x10;
+ *(int16_t *)(hle->mp3_buffer + (outPtr ^ S16)) = v2;
+ } else {
+ v4 = (v4 **(uint32_t *)(hle->mp3_buffer + 0xCE8)) >> 0x10;
+ *(int16_t *)(hle->mp3_buffer + (outPtr ^ S16)) = v4;
+ mult4 = *(uint32_t *)(hle->mp3_buffer + 0xCE8);
+ }
+ addptr -= 0x50;
+
+ for (x = 0; x < 8; x++) {
+ int32_t v0;
+ int32_t v18;
+ v2 = v4 = v6 = v8 = 0;
+
+ offset = (0x22F - (t4 >> 1) + x * 0x40);
+
+ for (i = 0; i < 4; i++) {
+ v2 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x20) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
+ v2 -= ((int) * (int16_t *)(hle->mp3_buffer + ((addptr + 2)) + 0x20) * (short)DeWindowLUT[offset + 0x01] + 0x4000) >> 0xF;
+ v4 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x30) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
+ v4 -= ((int) * (int16_t *)(hle->mp3_buffer + ((addptr + 2)) + 0x30) * (short)DeWindowLUT[offset + 0x09] + 0x4000) >> 0xF;
+ v6 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x20] + 0x4000) >> 0xF;
+ v6 -= ((int) * (int16_t *)(hle->mp3_buffer + ((addptr + 2)) + 0x00) * (short)DeWindowLUT[offset + 0x21] + 0x4000) >> 0xF;
+ v8 += ((int) * (int16_t *)(hle->mp3_buffer + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x28] + 0x4000) >> 0xF;
+ v8 -= ((int) * (int16_t *)(hle->mp3_buffer + ((addptr + 2)) + 0x10) * (short)DeWindowLUT[offset + 0x29] + 0x4000) >> 0xF;
+ addptr += 4;
+ offset += 2;
+ }
+ v0 = v2 + v4;
+ v18 = v6 + v8;
+ /* Clamp(v0); */
+ /* Clamp(v18); */
+ /* clamp??? */
+ *(int16_t *)(hle->mp3_buffer + ((outPtr + 2)^S16)) = v0;
+ *(int16_t *)(hle->mp3_buffer + ((outPtr + 4)^S16)) = v18;
+ outPtr += 4;
+ addptr -= 0x50;
+ }
+
+ tmp = outPtr;
+ hi0 = mult6;
+ hi1 = mult4;
+
+ hi0 = (int)hi0 >> 0x10;
+ hi1 = (int)hi1 >> 0x10;
+ for (i = 0; i < 8; i++) {
+ /* v0 */
+ vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x40)^S16)) * hi0);
+ *(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x40)^S16)) = clamp_s16(vt);
+
+ /* v17 */
+ vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x30)^S16)) * hi0);
+ *(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x30)^S16)) = clamp_s16(vt);
+
+ /* v2 */
+ vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x1E)^S16)) * hi1);
+ *(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x1E)^S16)) = clamp_s16(vt);
+
+ /* v4 */
+ vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0xE)^S16)) * hi1);
+ *(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0xE)^S16)) = clamp_s16(vt);
+
+ tmp += 2;
+ }
+}
+
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/musyx.c b/libmupen64plus/mupen64plus-rsp-hle/src/musyx.c
new file mode 100644
index 0000000000..d5a630a033
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/musyx.c
@@ -0,0 +1,988 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - musyx.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2013 Bobby Smiles *
+ * *
+ * 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
+#include
+#include
+#include
+
+#include "arithmetics.h"
+#include "audio.h"
+#include "common.h"
+#include "hle_external.h"
+#include "hle_internal.h"
+#include "memory.h"
+
+/* various constants */
+enum { SUBFRAME_SIZE = 192 };
+enum { MAX_VOICES = 32 };
+
+enum { SAMPLE_BUFFER_SIZE = 0x200 };
+
+
+enum {
+ SFD_VOICE_COUNT = 0x0,
+ SFD_SFX_INDEX = 0x2,
+ SFD_VOICE_BITMASK = 0x4,
+ SFD_STATE_PTR = 0x8,
+ SFD_SFX_PTR = 0xc,
+ SFD_VOICES = 0x10,
+
+ /* v2 only */
+ SFD2_10_PTR = 0x10,
+ SFD2_14_BITMASK = 0x14,
+ SFD2_15_BITMASK = 0x15,
+ SFD2_16_BITMASK = 0x16,
+ SFD2_18_PTR = 0x18,
+ SFD2_1C_PTR = 0x1c,
+ SFD2_20_PTR = 0x20,
+ SFD2_24_PTR = 0x24,
+ SFD2_VOICES = 0x28
+};
+
+enum {
+ VOICE_ENV_BEGIN = 0x00,
+ VOICE_ENV_STEP = 0x10,
+ VOICE_PITCH_Q16 = 0x20,
+ VOICE_PITCH_SHIFT = 0x22,
+ VOICE_CATSRC_0 = 0x24,
+ VOICE_CATSRC_1 = 0x30,
+ VOICE_ADPCM_FRAMES = 0x3c,
+ VOICE_SKIP_SAMPLES = 0x3e,
+
+ /* for PCM16 */
+ VOICE_U16_40 = 0x40,
+ VOICE_U16_42 = 0x42,
+
+ /* for ADPCM */
+ VOICE_ADPCM_TABLE_PTR = 0x40,
+
+ VOICE_INTERLEAVED_PTR = 0x44,
+ VOICE_END_POINT = 0x48,
+ VOICE_RESTART_POINT = 0x4a,
+ VOICE_U16_4C = 0x4c,
+ VOICE_U16_4E = 0x4e,
+
+ VOICE_SIZE = 0x50
+};
+
+enum {
+ CATSRC_PTR1 = 0x00,
+ CATSRC_PTR2 = 0x04,
+ CATSRC_SIZE1 = 0x08,
+ CATSRC_SIZE2 = 0x0a
+};
+
+enum {
+ STATE_LAST_SAMPLE = 0x0,
+ STATE_BASE_VOL = 0x100,
+ STATE_CC0 = 0x110,
+ STATE_740_LAST4_V1 = 0x290,
+
+ STATE_740_LAST4_V2 = 0x110
+};
+
+enum {
+ SFX_CBUFFER_PTR = 0x00,
+ SFX_CBUFFER_LENGTH = 0x04,
+ SFX_TAP_COUNT = 0x08,
+ SFX_FIR4_HGAIN = 0x0a,
+ SFX_TAP_DELAYS = 0x0c,
+ SFX_TAP_GAINS = 0x2c,
+ SFX_U16_3C = 0x3c,
+ SFX_U16_3E = 0x3e,
+ SFX_FIR4_HCOEFFS = 0x40
+};
+
+
+/* struct definition */
+typedef struct {
+ /* internal subframes */
+ int16_t left[SUBFRAME_SIZE];
+ int16_t right[SUBFRAME_SIZE];
+ int16_t cc0[SUBFRAME_SIZE];
+ int16_t e50[SUBFRAME_SIZE];
+
+ /* internal subframes base volumes */
+ int32_t base_vol[4];
+
+ /* */
+ int16_t subframe_740_last4[4];
+} musyx_t;
+
+typedef void (*mix_sfx_with_main_subframes_t)(musyx_t *musyx, const int16_t *subframe,
+ const uint16_t* gains);
+
+/* helper functions prototypes */
+static void load_base_vol(struct hle_t* hle, int32_t *base_vol, uint32_t address);
+static void save_base_vol(struct hle_t* hle, const int32_t *base_vol, uint32_t address);
+static void update_base_vol(struct hle_t* hle, int32_t *base_vol,
+ uint32_t voice_mask, uint32_t last_sample_ptr,
+ uint8_t mask_15, uint32_t ptr_24);
+
+static void init_subframes_v1(musyx_t *musyx);
+static void init_subframes_v2(musyx_t *musyx);
+
+static uint32_t voice_stage(struct hle_t* hle, musyx_t *musyx,
+ uint32_t voice_ptr, uint32_t last_sample_ptr);
+
+static void dma_cat8(struct hle_t* hle, uint8_t *dst, uint32_t catsrc_ptr);
+static void dma_cat16(struct hle_t* hle, uint16_t *dst, uint32_t catsrc_ptr);
+
+static void load_samples_PCM16(struct hle_t* hle, uint32_t voice_ptr, int16_t *samples,
+ unsigned *segbase, unsigned *offset);
+static void load_samples_ADPCM(struct hle_t* hle, uint32_t voice_ptr, int16_t *samples,
+ unsigned *segbase, unsigned *offset);
+
+static void adpcm_decode_frames(struct hle_t* hle,
+ int16_t *dst, const uint8_t *src,
+ const int16_t *table, uint8_t count,
+ uint8_t skip_samples);
+
+static void adpcm_predict_frame(int16_t *dst, const uint8_t *src,
+ const uint8_t *nibbles,
+ unsigned int rshift);
+
+static void mix_voice_samples(struct hle_t* hle, musyx_t *musyx,
+ uint32_t voice_ptr, const int16_t *samples,
+ unsigned segbase, unsigned offset, uint32_t last_sample_ptr);
+
+static void sfx_stage(struct hle_t* hle,
+ mix_sfx_with_main_subframes_t mix_sfx_with_main_subframes,
+ musyx_t *musyx, uint32_t sfx_ptr, uint16_t idx);
+
+static void mix_sfx_with_main_subframes_v1(musyx_t *musyx, const int16_t *subframe,
+ const uint16_t* gains);
+static void mix_sfx_with_main_subframes_v2(musyx_t *musyx, const int16_t *subframe,
+ const uint16_t* gains);
+
+static void mix_samples(int16_t *y, int16_t x, int16_t hgain);
+static void mix_subframes(int16_t *y, const int16_t *x, int16_t hgain);
+static void mix_fir4(int16_t *y, const int16_t *x, int16_t hgain, const int16_t *hcoeffs);
+
+
+static void interleave_stage_v1(struct hle_t* hle, musyx_t *musyx,
+ uint32_t output_ptr);
+
+static void interleave_stage_v2(struct hle_t* hle, musyx_t *musyx,
+ uint16_t mask_16, uint32_t ptr_18,
+ uint32_t ptr_1c, uint32_t output_ptr);
+
+static int32_t dot4(const int16_t *x, const int16_t *y)
+{
+ size_t i;
+ int32_t accu = 0;
+
+ for (i = 0; i < 4; ++i)
+ accu = clamp_s16(accu + (((int32_t)x[i] * (int32_t)y[i]) >> 15));
+
+ return accu;
+}
+
+/**************************************************************************
+ * MusyX v1 audio ucode
+ **************************************************************************/
+void musyx_v1_task(struct hle_t* hle)
+{
+ uint32_t sfd_ptr = *dmem_u32(hle, TASK_DATA_PTR);
+ uint32_t sfd_count = *dmem_u32(hle, TASK_DATA_SIZE);
+ uint32_t state_ptr;
+ musyx_t musyx;
+
+ HleVerboseMessage(hle->user_defined,
+ "musyx_v1_task: *data=%x, #SF=%d",
+ sfd_ptr,
+ sfd_count);
+
+ state_ptr = *dram_u32(hle, sfd_ptr + SFD_STATE_PTR);
+
+ /* load initial state */
+ load_base_vol(hle, musyx.base_vol, state_ptr + STATE_BASE_VOL);
+ dram_load_u16(hle, (uint16_t *)musyx.cc0, state_ptr + STATE_CC0, SUBFRAME_SIZE);
+ dram_load_u16(hle, (uint16_t *)musyx.subframe_740_last4, state_ptr + STATE_740_LAST4_V1,
+ 4);
+
+ for (;;) {
+ /* parse SFD structure */
+ uint16_t sfx_index = *dram_u16(hle, sfd_ptr + SFD_SFX_INDEX);
+ uint32_t voice_mask = *dram_u32(hle, sfd_ptr + SFD_VOICE_BITMASK);
+ uint32_t sfx_ptr = *dram_u32(hle, sfd_ptr + SFD_SFX_PTR);
+ uint32_t voice_ptr = sfd_ptr + SFD_VOICES;
+ uint32_t last_sample_ptr = state_ptr + STATE_LAST_SAMPLE;
+ uint32_t output_ptr;
+
+ /* initialize internal subframes using updated base volumes */
+ update_base_vol(hle, musyx.base_vol, voice_mask, last_sample_ptr, 0, 0);
+ init_subframes_v1(&musyx);
+
+ /* active voices get mixed into L,R,cc0,e50 subframes (optional) */
+ output_ptr = voice_stage(hle, &musyx, voice_ptr, last_sample_ptr);
+
+ /* apply delay-based effects (optional) */
+ sfx_stage(hle, mix_sfx_with_main_subframes_v1,
+ &musyx, sfx_ptr, sfx_index);
+
+ /* emit interleaved L,R subframes */
+ interleave_stage_v1(hle, &musyx, output_ptr);
+
+ --sfd_count;
+ if (sfd_count == 0)
+ break;
+
+ sfd_ptr += SFD_VOICES + MAX_VOICES * VOICE_SIZE;
+ state_ptr = *dram_u32(hle, sfd_ptr + SFD_STATE_PTR);
+ }
+
+ /* writeback updated state */
+ save_base_vol(hle, musyx.base_vol, state_ptr + STATE_BASE_VOL);
+ 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);
+}
+
+/**************************************************************************
+ * MusyX v2 audio ucode
+ **************************************************************************/
+void musyx_v2_task(struct hle_t* hle)
+{
+ uint32_t sfd_ptr = *dmem_u32(hle, TASK_DATA_PTR);
+ uint32_t sfd_count = *dmem_u32(hle, TASK_DATA_SIZE);
+ musyx_t musyx;
+
+ HleVerboseMessage(hle->user_defined,
+ "musyx_v2_task: *data=%x, #SF=%d",
+ sfd_ptr,
+ sfd_count);
+
+ for (;;) {
+ /* parse SFD structure */
+ uint16_t sfx_index = *dram_u16(hle, sfd_ptr + SFD_SFX_INDEX);
+ uint32_t voice_mask = *dram_u32(hle, sfd_ptr + SFD_VOICE_BITMASK);
+ uint32_t state_ptr = *dram_u32(hle, sfd_ptr + SFD_STATE_PTR);
+ uint32_t sfx_ptr = *dram_u32(hle, sfd_ptr + SFD_SFX_PTR);
+ uint32_t voice_ptr = sfd_ptr + SFD2_VOICES;
+
+ uint32_t ptr_10 = *dram_u32(hle, sfd_ptr + SFD2_10_PTR);
+ uint8_t mask_14 = *dram_u8 (hle, sfd_ptr + SFD2_14_BITMASK);
+ uint8_t mask_15 = *dram_u8 (hle, sfd_ptr + SFD2_15_BITMASK);
+ uint16_t mask_16 = *dram_u16(hle, sfd_ptr + SFD2_16_BITMASK);
+ uint32_t ptr_18 = *dram_u32(hle, sfd_ptr + SFD2_18_PTR);
+ uint32_t ptr_1c = *dram_u32(hle, sfd_ptr + SFD2_1C_PTR);
+ uint32_t ptr_20 = *dram_u32(hle, sfd_ptr + SFD2_20_PTR);
+ uint32_t ptr_24 = *dram_u32(hle, sfd_ptr + SFD2_24_PTR);
+
+ uint32_t last_sample_ptr = state_ptr + STATE_LAST_SAMPLE;
+ uint32_t output_ptr;
+
+ /* load state */
+ load_base_vol(hle, musyx.base_vol, state_ptr + STATE_BASE_VOL);
+ dram_load_u16(hle, (uint16_t *)musyx.subframe_740_last4,
+ state_ptr + STATE_740_LAST4_V2, 4);
+
+ /* initialize internal subframes using updated base volumes */
+ update_base_vol(hle, musyx.base_vol, voice_mask, last_sample_ptr, mask_15, ptr_24);
+ init_subframes_v2(&musyx);
+
+ if (ptr_10) {
+ /* TODO */
+ HleWarnMessage(hle->user_defined,
+ "ptr_10=%08x mask_14=%02x ptr_24=%08x",
+ ptr_10, mask_14, ptr_24);
+ }
+
+ /* active voices get mixed into L,R,cc0,e50 subframes (optional) */
+ output_ptr = voice_stage(hle, &musyx, voice_ptr, last_sample_ptr);
+
+ /* apply delay-based effects (optional) */
+ sfx_stage(hle, mix_sfx_with_main_subframes_v2,
+ &musyx, sfx_ptr, sfx_index);
+
+ dram_store_u16(hle, (uint16_t*)musyx.left, output_ptr , SUBFRAME_SIZE);
+ dram_store_u16(hle, (uint16_t*)musyx.right, output_ptr + 2*SUBFRAME_SIZE, SUBFRAME_SIZE);
+ dram_store_u16(hle, (uint16_t*)musyx.cc0, output_ptr + 4*SUBFRAME_SIZE, SUBFRAME_SIZE);
+
+ /* store state */
+ save_base_vol(hle, musyx.base_vol, state_ptr + STATE_BASE_VOL);
+ dram_store_u16(hle, (uint16_t*)musyx.subframe_740_last4,
+ state_ptr + STATE_740_LAST4_V2, 4);
+
+ if (mask_16)
+ interleave_stage_v2(hle, &musyx, mask_16, ptr_18, ptr_1c, ptr_20);
+
+ --sfd_count;
+ if (sfd_count == 0)
+ break;
+
+ sfd_ptr += SFD2_VOICES + MAX_VOICES * VOICE_SIZE;
+ }
+
+ rsp_break(hle, SP_STATUS_TASKDONE);
+}
+
+
+
+
+
+static void load_base_vol(struct hle_t* hle, int32_t *base_vol, uint32_t address)
+{
+ base_vol[0] = ((uint32_t)(*dram_u16(hle, address)) << 16) | (*dram_u16(hle, address + 8));
+ base_vol[1] = ((uint32_t)(*dram_u16(hle, address + 2)) << 16) | (*dram_u16(hle, address + 10));
+ base_vol[2] = ((uint32_t)(*dram_u16(hle, address + 4)) << 16) | (*dram_u16(hle, address + 12));
+ base_vol[3] = ((uint32_t)(*dram_u16(hle, address + 6)) << 16) | (*dram_u16(hle, address + 14));
+}
+
+static void save_base_vol(struct hle_t* hle, const int32_t *base_vol, uint32_t address)
+{
+ unsigned k;
+
+ for (k = 0; k < 4; ++k) {
+ *dram_u16(hle, address) = (uint16_t)(base_vol[k] >> 16);
+ address += 2;
+ }
+
+ for (k = 0; k < 4; ++k) {
+ *dram_u16(hle, address) = (uint16_t)(base_vol[k]);
+ address += 2;
+ }
+}
+
+static void update_base_vol(struct hle_t* hle, int32_t *base_vol,
+ uint32_t voice_mask, uint32_t last_sample_ptr,
+ uint8_t mask_15, uint32_t ptr_24)
+{
+ unsigned i, k;
+ uint32_t mask;
+
+ HleVerboseMessage(hle->user_defined, "base_vol voice_mask = %08x", voice_mask);
+ HleVerboseMessage(hle->user_defined,
+ "BEFORE: base_vol = %08x %08x %08x %08x",
+ base_vol[0], base_vol[1], base_vol[2], base_vol[3]);
+
+ /* optim: skip voices contributions entirely if voice_mask is empty */
+ if (voice_mask != 0) {
+ for (i = 0, mask = 1; i < MAX_VOICES;
+ ++i, mask <<= 1, last_sample_ptr += 8) {
+ if ((voice_mask & mask) == 0)
+ continue;
+
+ for (k = 0; k < 4; ++k)
+ base_vol[k] += (int16_t)*dram_u16(hle, last_sample_ptr + k * 2);
+ }
+ }
+
+ /* optim: skip contributions entirely if mask_15 is empty */
+ if (mask_15 != 0) {
+ for(i = 0, mask = 1; i < 4;
+ ++i, mask <<= 1, ptr_24 += 8) {
+ if ((mask_15 & mask) == 0)
+ continue;
+
+ for(k = 0; k < 4; ++k)
+ base_vol[k] += (int16_t)*dram_u16(hle, ptr_24 + k * 2);
+ }
+ }
+
+ /* apply 3% decay */
+ for (k = 0; k < 4; ++k)
+ base_vol[k] = (base_vol[k] * 0x0000f850) >> 16;
+
+ HleVerboseMessage(hle->user_defined,
+ "AFTER: base_vol = %08x %08x %08x %08x",
+ base_vol[0], base_vol[1], base_vol[2], base_vol[3]);
+}
+
+
+
+
+static void init_subframes_v1(musyx_t *musyx)
+{
+ unsigned i;
+
+ int16_t base_cc0 = clamp_s16(musyx->base_vol[2]);
+ int16_t base_e50 = clamp_s16(musyx->base_vol[3]);
+
+ int16_t *left = musyx->left;
+ int16_t *right = musyx->right;
+ int16_t *cc0 = musyx->cc0;
+ int16_t *e50 = musyx->e50;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ *(e50++) = base_e50;
+ *(left++) = clamp_s16(*cc0 + base_cc0);
+ *(right++) = clamp_s16(-*cc0 - base_cc0);
+ *(cc0++) = 0;
+ }
+}
+
+static void init_subframes_v2(musyx_t *musyx)
+{
+ unsigned i,k;
+ int16_t values[4];
+ int16_t* subframes[4];
+
+ for(k = 0; k < 4; ++k)
+ values[k] = clamp_s16(musyx->base_vol[k]);
+
+ subframes[0] = musyx->left;
+ subframes[1] = musyx->right;
+ subframes[2] = musyx->cc0;
+ subframes[3] = musyx->e50;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+
+ for(k = 0; k < 4; ++k)
+ *(subframes[k]++) = values[k];
+ }
+}
+
+/* Process voices, and returns interleaved subframe destination address */
+static uint32_t voice_stage(struct hle_t* hle, musyx_t *musyx,
+ uint32_t voice_ptr, uint32_t last_sample_ptr)
+{
+ uint32_t output_ptr;
+ int i = 0;
+
+ /* voice stage can be skipped if first voice has no samples */
+ if (*dram_u16(hle, voice_ptr + VOICE_CATSRC_0 + CATSRC_SIZE1) == 0) {
+ HleVerboseMessage(hle->user_defined, "Skipping Voice stage");
+ output_ptr = *dram_u32(hle, voice_ptr + VOICE_INTERLEAVED_PTR);
+ } else {
+ /* otherwise process voices until a non null output_ptr is encountered */
+ for (;;) {
+ /* load voice samples (PCM16 or APDCM) */
+ int16_t samples[SAMPLE_BUFFER_SIZE];
+ unsigned segbase;
+ unsigned offset;
+
+ HleVerboseMessage(hle->user_defined, "Processing Voice #%d", i);
+
+ if (*dram_u8(hle, voice_ptr + VOICE_ADPCM_FRAMES) == 0)
+ load_samples_PCM16(hle, voice_ptr, samples, &segbase, &offset);
+ else
+ load_samples_ADPCM(hle, voice_ptr, samples, &segbase, &offset);
+
+ /* mix them with each internal subframes */
+ mix_voice_samples(hle, musyx, voice_ptr, samples, segbase, offset,
+ last_sample_ptr + i * 8);
+
+ /* check break condition */
+ output_ptr = *dram_u32(hle, voice_ptr + VOICE_INTERLEAVED_PTR);
+ if (output_ptr != 0)
+ break;
+
+ /* next voice */
+ ++i;
+ voice_ptr += VOICE_SIZE;
+ }
+ }
+
+ return output_ptr;
+}
+
+static void dma_cat8(struct hle_t* hle, uint8_t *dst, uint32_t catsrc_ptr)
+{
+ uint32_t ptr1 = *dram_u32(hle, catsrc_ptr + CATSRC_PTR1);
+ uint32_t ptr2 = *dram_u32(hle, catsrc_ptr + CATSRC_PTR2);
+ uint16_t size1 = *dram_u16(hle, catsrc_ptr + CATSRC_SIZE1);
+ uint16_t size2 = *dram_u16(hle, catsrc_ptr + CATSRC_SIZE2);
+
+ size_t count1 = size1;
+ size_t count2 = size2;
+
+ HleVerboseMessage(hle->user_defined,
+ "dma_cat: %08x %08x %04x %04x",
+ ptr1,
+ ptr2,
+ size1,
+ size2);
+
+ dram_load_u8(hle, dst, ptr1, count1);
+
+ if (size2 == 0)
+ return;
+
+ dram_load_u8(hle, dst + count1, ptr2, count2);
+}
+
+static void dma_cat16(struct hle_t* hle, uint16_t *dst, uint32_t catsrc_ptr)
+{
+ uint32_t ptr1 = *dram_u32(hle, catsrc_ptr + CATSRC_PTR1);
+ uint32_t ptr2 = *dram_u32(hle, catsrc_ptr + CATSRC_PTR2);
+ uint16_t size1 = *dram_u16(hle, catsrc_ptr + CATSRC_SIZE1);
+ uint16_t size2 = *dram_u16(hle, catsrc_ptr + CATSRC_SIZE2);
+
+ size_t count1 = size1 >> 1;
+ size_t count2 = size2 >> 1;
+
+ HleVerboseMessage(hle->user_defined,
+ "dma_cat: %08x %08x %04x %04x",
+ ptr1,
+ ptr2,
+ size1,
+ size2);
+
+ dram_load_u16(hle, dst, ptr1, count1);
+
+ if (size2 == 0)
+ return;
+
+ dram_load_u16(hle, dst + count1, ptr2, count2);
+}
+
+static void load_samples_PCM16(struct hle_t* hle, uint32_t voice_ptr, int16_t *samples,
+ unsigned *segbase, unsigned *offset)
+{
+
+ uint8_t u8_3e = *dram_u8(hle, voice_ptr + VOICE_SKIP_SAMPLES);
+ uint16_t u16_40 = *dram_u16(hle, voice_ptr + VOICE_U16_40);
+ uint16_t u16_42 = *dram_u16(hle, voice_ptr + VOICE_U16_42);
+
+ unsigned count = align(u16_40 + u8_3e, 4);
+
+ HleVerboseMessage(hle->user_defined, "Format: PCM16");
+
+ *segbase = SAMPLE_BUFFER_SIZE - count;
+ *offset = u8_3e;
+
+ dma_cat16(hle, (uint16_t *)samples + *segbase, voice_ptr + VOICE_CATSRC_0);
+
+ if (u16_42 != 0)
+ dma_cat16(hle, (uint16_t *)samples, voice_ptr + VOICE_CATSRC_1);
+}
+
+static void load_samples_ADPCM(struct hle_t* hle, uint32_t voice_ptr, int16_t *samples,
+ unsigned *segbase, unsigned *offset)
+{
+ /* decompressed samples cannot exceed 0x400 bytes;
+ * ADPCM has a compression ratio of 5/16 */
+ uint8_t buffer[SAMPLE_BUFFER_SIZE * 2 * 5 / 16];
+ int16_t adpcm_table[128];
+
+ uint8_t u8_3c = *dram_u8(hle, voice_ptr + VOICE_ADPCM_FRAMES );
+ uint8_t u8_3d = *dram_u8(hle, voice_ptr + VOICE_ADPCM_FRAMES + 1);
+ uint8_t u8_3e = *dram_u8(hle, voice_ptr + VOICE_SKIP_SAMPLES );
+ uint8_t u8_3f = *dram_u8(hle, voice_ptr + VOICE_SKIP_SAMPLES + 1);
+ uint32_t adpcm_table_ptr = *dram_u32(hle, voice_ptr + VOICE_ADPCM_TABLE_PTR);
+ unsigned count;
+
+ HleVerboseMessage(hle->user_defined, "Format: ADPCM");
+
+ HleVerboseMessage(hle->user_defined, "Loading ADPCM table: %08x", adpcm_table_ptr);
+ dram_load_u16(hle, (uint16_t *)adpcm_table, adpcm_table_ptr, 128);
+
+ count = u8_3c << 5;
+
+ *segbase = SAMPLE_BUFFER_SIZE - count;
+ *offset = u8_3e & 0x1f;
+
+ dma_cat8(hle, buffer, voice_ptr + VOICE_CATSRC_0);
+ adpcm_decode_frames(hle, samples + *segbase, buffer, adpcm_table, u8_3c, u8_3e);
+
+ if (u8_3d != 0) {
+ dma_cat8(hle, buffer, voice_ptr + VOICE_CATSRC_1);
+ adpcm_decode_frames(hle, samples, buffer, adpcm_table, u8_3d, u8_3f);
+ }
+}
+
+static void adpcm_decode_frames(struct hle_t* hle,
+ int16_t *dst, const uint8_t *src,
+ const int16_t *table, uint8_t count,
+ uint8_t skip_samples)
+{
+ int16_t frame[32];
+ const uint8_t *nibbles = src + 8;
+ unsigned i;
+ bool jump_gap = false;
+
+ HleVerboseMessage(hle->user_defined,
+ "ADPCM decode: count=%d, skip=%d",
+ count, skip_samples);
+
+ if (skip_samples >= 32) {
+ jump_gap = true;
+ nibbles += 16;
+ src += 4;
+ }
+
+ for (i = 0; i < count; ++i) {
+ uint8_t c2 = nibbles[0];
+
+ const int16_t *book = (c2 & 0xf0) + table;
+ unsigned int rshift = (c2 & 0x0f);
+
+ adpcm_predict_frame(frame, src, nibbles, rshift);
+
+ memcpy(dst, frame, 2 * sizeof(frame[0]));
+ adpcm_compute_residuals(dst + 2, frame + 2, book, dst , 6);
+ adpcm_compute_residuals(dst + 8, frame + 8, book, dst + 6, 8);
+ adpcm_compute_residuals(dst + 16, frame + 16, book, dst + 14, 8);
+ adpcm_compute_residuals(dst + 24, frame + 24, book, dst + 22, 8);
+
+ if (jump_gap) {
+ nibbles += 8;
+ src += 32;
+ }
+
+ jump_gap = !jump_gap;
+ nibbles += 16;
+ src += 4;
+ dst += 32;
+ }
+}
+
+static void adpcm_predict_frame(int16_t *dst, const uint8_t *src,
+ const uint8_t *nibbles,
+ unsigned int rshift)
+{
+ unsigned int i;
+
+ *(dst++) = (src[0] << 8) | src[1];
+ *(dst++) = (src[2] << 8) | src[3];
+
+ for (i = 1; i < 16; ++i) {
+ uint8_t byte = nibbles[i];
+
+ *(dst++) = adpcm_predict_sample(byte, 0xf0, 8, rshift);
+ *(dst++) = adpcm_predict_sample(byte, 0x0f, 12, rshift);
+ }
+}
+
+static void mix_voice_samples(struct hle_t* hle, musyx_t *musyx,
+ uint32_t voice_ptr, const int16_t *samples,
+ unsigned segbase, unsigned offset, uint32_t last_sample_ptr)
+{
+ int i, k;
+
+ /* parse VOICE structure */
+ const uint16_t pitch_q16 = *dram_u16(hle, voice_ptr + VOICE_PITCH_Q16);
+ const uint16_t pitch_shift = *dram_u16(hle, voice_ptr + VOICE_PITCH_SHIFT); /* Q4.12 */
+
+ const uint16_t end_point = *dram_u16(hle, voice_ptr + VOICE_END_POINT);
+ const uint16_t restart_point = *dram_u16(hle, voice_ptr + VOICE_RESTART_POINT);
+
+ const uint16_t u16_4e = *dram_u16(hle, voice_ptr + VOICE_U16_4E);
+
+ /* init values and pointers */
+ const int16_t *sample = samples + segbase + offset + u16_4e;
+ const int16_t *const sample_end = samples + segbase + end_point;
+ const int16_t *const sample_restart = samples + (restart_point & 0x7fff) +
+ (((restart_point & 0x8000) != 0) ? 0x000 : segbase);
+
+
+ uint32_t pitch_accu = pitch_q16;
+ uint32_t pitch_step = pitch_shift << 4;
+
+ int32_t v4_env[4];
+ int32_t v4_env_step[4];
+ int16_t *v4_dst[4];
+ int16_t v4[4];
+
+ dram_load_u32(hle, (uint32_t *)v4_env, voice_ptr + VOICE_ENV_BEGIN, 4);
+ dram_load_u32(hle, (uint32_t *)v4_env_step, voice_ptr + VOICE_ENV_STEP, 4);
+
+ v4_dst[0] = musyx->left;
+ v4_dst[1] = musyx->right;
+ v4_dst[2] = musyx->cc0;
+ v4_dst[3] = musyx->e50;
+
+ HleVerboseMessage(hle->user_defined,
+ "Voice debug: segbase=%d"
+ "\tu16_4e=%04x\n"
+ "\tpitch: frac0=%04x shift=%04x\n"
+ "\tend_point=%04x restart_point=%04x\n"
+ "\tenv = %08x %08x %08x %08x\n"
+ "\tenv_step = %08x %08x %08x %08x\n",
+ segbase,
+ u16_4e,
+ pitch_q16, pitch_shift,
+ end_point, restart_point,
+ v4_env[0], v4_env[1], v4_env[2], v4_env[3],
+ v4_env_step[0], v4_env_step[1], v4_env_step[2], v4_env_step[3]);
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ /* update sample and lut pointers and then pitch_accu */
+ const int16_t *lut = (RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8));
+ int dist;
+ int16_t v;
+
+ sample += (pitch_accu >> 16);
+ pitch_accu &= 0xffff;
+ pitch_accu += pitch_step;
+
+ /* handle end/restart points */
+ dist = sample - sample_end;
+ if (dist >= 0)
+ sample = sample_restart + dist;
+
+ /* apply resample filter */
+ v = clamp_s16(dot4(sample, lut));
+
+ for (k = 0; k < 4; ++k) {
+ /* envmix */
+ int32_t accu = (v * (v4_env[k] >> 16)) >> 15;
+ v4[k] = clamp_s16(accu);
+ *(v4_dst[k]) = clamp_s16(accu + *(v4_dst[k]));
+
+ /* update envelopes and dst pointers */
+ ++(v4_dst[k]);
+ v4_env[k] += v4_env_step[k];
+ }
+ }
+
+ /* save last resampled sample */
+ dram_store_u16(hle, (uint16_t *)v4, last_sample_ptr, 4);
+
+ HleVerboseMessage(hle->user_defined,
+ "last_sample = %04x %04x %04x %04x",
+ v4[0], v4[1], v4[2], v4[3]);
+}
+
+
+static void sfx_stage(struct hle_t* hle, mix_sfx_with_main_subframes_t mix_sfx_with_main_subframes,
+ musyx_t *musyx, uint32_t sfx_ptr, uint16_t idx)
+{
+ unsigned int i;
+
+ int16_t buffer[SUBFRAME_SIZE + 4];
+ int16_t *subframe = buffer + 4;
+
+ uint32_t tap_delays[8];
+ int16_t tap_gains[8];
+ int16_t fir4_hcoeffs[4];
+
+ int16_t delayed[SUBFRAME_SIZE];
+ int dpos, dlength;
+
+ const uint32_t pos = idx * SUBFRAME_SIZE;
+
+ uint32_t cbuffer_ptr;
+ uint32_t cbuffer_length;
+ uint16_t tap_count;
+ int16_t fir4_hgain;
+ uint16_t sfx_gains[2];
+
+ HleVerboseMessage(hle->user_defined, "SFX: %08x, idx=%d", sfx_ptr, idx);
+
+ if (sfx_ptr == 0)
+ return;
+
+ /* load sfx parameters */
+ cbuffer_ptr = *dram_u32(hle, sfx_ptr + SFX_CBUFFER_PTR);
+ cbuffer_length = *dram_u32(hle, sfx_ptr + SFX_CBUFFER_LENGTH);
+
+ tap_count = *dram_u16(hle, sfx_ptr + SFX_TAP_COUNT);
+
+ dram_load_u32(hle, tap_delays, sfx_ptr + SFX_TAP_DELAYS, 8);
+ dram_load_u16(hle, (uint16_t *)tap_gains, sfx_ptr + SFX_TAP_GAINS, 8);
+
+ fir4_hgain = *dram_u16(hle, sfx_ptr + SFX_FIR4_HGAIN);
+ dram_load_u16(hle, (uint16_t *)fir4_hcoeffs, sfx_ptr + SFX_FIR4_HCOEFFS, 4);
+
+ sfx_gains[0] = *dram_u16(hle, sfx_ptr + SFX_U16_3C);
+ sfx_gains[1] = *dram_u16(hle, sfx_ptr + SFX_U16_3E);
+
+ HleVerboseMessage(hle->user_defined,
+ "cbuffer: ptr=%08x length=%x", cbuffer_ptr,
+ cbuffer_length);
+
+ HleVerboseMessage(hle->user_defined,
+ "fir4: hgain=%04x hcoeff=%04x %04x %04x %04x",
+ fir4_hgain,
+ fir4_hcoeffs[0], fir4_hcoeffs[1], fir4_hcoeffs[2], fir4_hcoeffs[3]);
+
+ HleVerboseMessage(hle->user_defined,
+ "tap count=%d\n"
+ "delays: %08x %08x %08x %08x %08x %08x %08x %08x\n"
+ "gains: %04x %04x %04x %04x %04x %04x %04x %04x",
+ tap_count,
+ tap_delays[0], tap_delays[1], tap_delays[2], tap_delays[3],
+ tap_delays[4], tap_delays[5], tap_delays[6], tap_delays[7],
+ tap_gains[0], tap_gains[1], tap_gains[2], tap_gains[3],
+ tap_gains[4], tap_gains[5], tap_gains[6], tap_gains[7]);
+
+ HleVerboseMessage(hle->user_defined, "sfx_gains=%04x %04x", sfx_gains[0], sfx_gains[1]);
+
+ /* mix up to 8 delayed subframes */
+ memset(subframe, 0, SUBFRAME_SIZE * sizeof(subframe[0]));
+ for (i = 0; i < tap_count; ++i) {
+
+ dpos = pos - tap_delays[i];
+ if (dpos <= 0)
+ dpos += cbuffer_length;
+ dlength = SUBFRAME_SIZE;
+
+ if ((uint32_t)(dpos + SUBFRAME_SIZE) > cbuffer_length) {
+ dlength = cbuffer_length - dpos;
+ dram_load_u16(hle, (uint16_t *)delayed + dlength, cbuffer_ptr, SUBFRAME_SIZE - dlength);
+ }
+
+ dram_load_u16(hle, (uint16_t *)delayed, cbuffer_ptr + dpos * 2, dlength);
+
+ mix_subframes(subframe, delayed, tap_gains[i]);
+ }
+
+ /* add resulting subframe to main subframes */
+ mix_sfx_with_main_subframes(musyx, subframe, sfx_gains);
+
+ /* apply FIR4 filter and writeback filtered result */
+ memcpy(buffer, musyx->subframe_740_last4, 4 * sizeof(int16_t));
+ memcpy(musyx->subframe_740_last4, subframe + SUBFRAME_SIZE - 4, 4 * sizeof(int16_t));
+ mix_fir4(musyx->e50, buffer + 1, fir4_hgain, fir4_hcoeffs);
+ dram_store_u16(hle, (uint16_t *)musyx->e50, cbuffer_ptr + pos * 2, SUBFRAME_SIZE);
+}
+
+static void mix_sfx_with_main_subframes_v1(musyx_t *musyx, const int16_t *subframe,
+ const uint16_t* UNUSED(gains))
+{
+ unsigned i;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ int16_t v = subframe[i];
+ musyx->left[i] = clamp_s16(musyx->left[i] + v);
+ musyx->right[i] = clamp_s16(musyx->right[i] + v);
+ }
+}
+
+static void mix_sfx_with_main_subframes_v2(musyx_t *musyx, const int16_t *subframe,
+ const uint16_t* gains)
+{
+ unsigned i;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ int16_t v = subframe[i];
+ int16_t v1 = (int32_t)(v * gains[0]) >> 16;
+ int16_t v2 = (int32_t)(v * gains[1]) >> 16;
+
+ musyx->left[i] = clamp_s16(musyx->left[i] + v1);
+ musyx->right[i] = clamp_s16(musyx->right[i] + v1);
+ musyx->cc0[i] = clamp_s16(musyx->cc0[i] + v2);
+ }
+}
+
+static void mix_samples(int16_t *y, int16_t x, int16_t hgain)
+{
+ *y = clamp_s16(*y + ((x * hgain + 0x4000) >> 15));
+}
+
+static void mix_subframes(int16_t *y, const int16_t *x, int16_t hgain)
+{
+ unsigned int i;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i)
+ mix_samples(&y[i], x[i], hgain);
+}
+
+static void mix_fir4(int16_t *y, const int16_t *x, int16_t hgain, const int16_t *hcoeffs)
+{
+ unsigned int i;
+ int32_t h[4];
+
+ h[0] = (hgain * hcoeffs[0]) >> 15;
+ h[1] = (hgain * hcoeffs[1]) >> 15;
+ h[2] = (hgain * hcoeffs[2]) >> 15;
+ h[3] = (hgain * hcoeffs[3]) >> 15;
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ int32_t v = (h[0] * x[i] + h[1] * x[i + 1] + h[2] * x[i + 2] + h[3] * x[i + 3]) >> 15;
+ y[i] = clamp_s16(y[i] + v);
+ }
+}
+
+static void interleave_stage_v1(struct hle_t* hle, musyx_t *musyx, uint32_t output_ptr)
+{
+ size_t i;
+
+ int16_t base_left;
+ int16_t base_right;
+
+ int16_t *left;
+ int16_t *right;
+ uint32_t *dst;
+
+ HleVerboseMessage(hle->user_defined, "interleave: %08x", output_ptr);
+
+ base_left = clamp_s16(musyx->base_vol[0]);
+ base_right = clamp_s16(musyx->base_vol[1]);
+
+ left = musyx->left;
+ right = musyx->right;
+ dst = dram_u32(hle, output_ptr);
+
+ for (i = 0; i < SUBFRAME_SIZE; ++i) {
+ uint16_t l = clamp_s16(*(left++) + base_left);
+ uint16_t r = clamp_s16(*(right++) + base_right);
+
+ *(dst++) = (l << 16) | r;
+ }
+}
+
+static void interleave_stage_v2(struct hle_t* hle, musyx_t *musyx,
+ uint16_t mask_16, uint32_t ptr_18,
+ uint32_t ptr_1c, uint32_t output_ptr)
+{
+ unsigned i, k;
+ int16_t subframe[SUBFRAME_SIZE];
+ uint32_t *dst;
+ uint16_t mask;
+
+ HleVerboseMessage(hle->user_defined,
+ "mask_16=%04x ptr_18=%08x ptr_1c=%08x output_ptr=%08x",
+ mask_16, ptr_18, ptr_1c, output_ptr);
+
+ /* compute L_total, R_total and update subframe @ptr_1c */
+ memset(subframe, 0, SUBFRAME_SIZE*sizeof(subframe[0]));
+
+ for(i = 0; i < SUBFRAME_SIZE; ++i) {
+ int16_t v = *dram_u16(hle, ptr_1c + i*2);
+ musyx->left[i] = v;
+ musyx->right[i] = clamp_s16(-v);
+ }
+
+ for (k = 0, mask = 1; k < 8; ++k, mask <<= 1, ptr_18 += 8) {
+ int16_t hgain;
+ uint32_t address;
+
+ if ((mask_16 & mask) == 0)
+ continue;
+
+ address = *dram_u32(hle, ptr_18);
+ hgain = *dram_u16(hle, ptr_18 + 4);
+
+ for(i = 0; i < SUBFRAME_SIZE; ++i, address += 2) {
+ mix_samples(&musyx->left[i], *dram_u16(hle, address), hgain);
+ mix_samples(&musyx->right[i], *dram_u16(hle, address + 2*SUBFRAME_SIZE), hgain);
+ mix_samples(&subframe[i], *dram_u16(hle, address + 4*SUBFRAME_SIZE), hgain);
+ }
+ }
+
+ /* interleave L_total and R_total */
+ dst = dram_u32(hle, output_ptr);
+ for(i = 0; i < SUBFRAME_SIZE; ++i) {
+ uint16_t l = musyx->left[i];
+ uint16_t r = musyx->right[i];
+ *(dst++) = (l << 16) | r;
+ }
+
+ /* writeback subframe @ptr_1c */
+ dram_store_u16(hle, (uint16_t*)subframe, ptr_1c, SUBFRAME_SIZE);
+}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib.h b/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib.h
new file mode 100644
index 0000000000..dc5e5bab53
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/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/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib_unix.c b/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib_unix.c
new file mode 100644
index 0000000000..9d937ed370
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/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
+#include
+#include
+#include
+
+#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/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib_win32.c b/libmupen64plus/mupen64plus-rsp-hle/src/osal_dynamiclib_win32.c
new file mode 100644
index 0000000000..fe77cf3aad
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/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
+#include
+#include
+
+#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/libmupen64plus/mupen64plus-rsp-hle/src/plugin.c b/libmupen64plus/mupen64plus-rsp-hle/src/plugin.c
new file mode 100644
index 0000000000..e0818bdb63
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/plugin.c
@@ -0,0 +1,495 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - plugin.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * Copyright (C) 2009 Richard Goedeken *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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
+#include
+#include
+
+#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"
+
+#include "osal_dynamiclib.h"
+
+#define CONFIG_API_VERSION 0x020100
+#define CONFIG_PARAM_VERSION 1.00
+
+#define RSP_API_VERSION 0x20000
+#define RSP_HLE_VERSION 0x020500
+#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;
+static void (*l_ProcessDlistList)(void) = NULL;
+static void (*l_ProcessAlistList)(void) = NULL;
+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_ConfigSaveSection ConfigSaveSection = 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];
+
+ if (l_DebugCallback == NULL)
+ return;
+
+ vsprintf(msgbuf, message, args);
+
+ (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
+}
+
+/* Global functions needed by HLE core */
+void HleVerboseMessage(void* UNUSED(user_defined), const char *message, ...)
+{
+ va_list args;
+ va_start(args, message);
+ DebugMessage(M64MSG_VERBOSE, message, args);
+ 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;
+ va_start(args, message);
+ DebugMessage(M64MSG_ERROR, message, args);
+ va_end(args);
+}
+
+void HleWarnMessage(void* UNUSED(user_defined), const char *message, ...)
+{
+ va_list args;
+ va_start(args, message);
+ DebugMessage(M64MSG_WARNING, message, args);
+ va_end(args);
+}
+
+void HleCheckInterrupts(void* UNUSED(user_defined))
+{
+ if (l_CheckInterrupts == NULL)
+ return;
+
+ (*l_CheckInterrupts)();
+}
+
+void HleProcessDlistList(void* UNUSED(user_defined))
+{
+ if (l_ProcessDlistList == NULL)
+ return;
+
+ (*l_ProcessDlistList)();
+}
+
+void HleProcessAlistList(void* UNUSED(user_defined))
+{
+ if (l_ProcessAlistList == NULL)
+ return;
+
+ (*l_ProcessAlistList)();
+}
+
+void HleProcessRdpList(void* UNUSED(user_defined))
+{
+ if (l_ProcessRdpList == NULL)
+ return;
+
+ (*l_ProcessRdpList)();
+}
+
+void HleShowCFB(void* UNUSED(user_defined))
+{
+ if (l_ShowCFB == NULL)
+ return;
+
+ (*l_ShowCFB)();
+}
+
+
+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 CoreLibHandle, void *Context,
+ void (*DebugCallback)(void *, int, const char *))
+{
+ ptr_CoreGetAPIVersions CoreAPIVersionFunc;
+ int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion, bSaveConfig;
+ float fConfigParamsVersion = 0.0f;
+
+ if (l_PluginInit)
+ return M64ERR_ALREADY_INIT;
+
+ /* first thing is to set the callback function for debug info */
+ l_DebugCallback = DebugCallback;
+ l_DebugCallContext = Context;
+
+ /* 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");
+ ConfigSaveSection = (ptr_ConfigSaveSection) osal_dynlib_getproc(CoreLibHandle, "ConfigSaveSection");
+ 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;
+
+ /* ConfigSaveSection was added in Config API v2.1.0 */
+ if (ConfigAPIVersion >= 0x020100 && !ConfigSaveSection)
+ 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 */
+ bSaveConfig = 0;
+ 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);
+ bSaveConfig = 1;
+ }
+ 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);
+ bSaveConfig = 1;
+ }
+ 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);
+ bSaveConfig = 1;
+ }
+
+ /* 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");
+
+ if (bSaveConfig && ConfigAPIVersion >= 0x020100)
+ ConfigSaveSection(RSP_HLE_CONFIG_SECTION);
+
+ l_CoreHandle = CoreLibHandle;
+
+ l_PluginInit = 1;
+ return M64ERR_SUCCESS;
+}
+
+EXPORT m64p_error CALL PluginShutdown(void)
+{
+ if (!l_PluginInit)
+ return M64ERR_NOT_INIT;
+
+ /* reset some local variable */
+ l_DebugCallback = NULL;
+ l_DebugCallContext = NULL;
+ l_CoreHandle = NULL;
+
+ teardown_rsp_fallback();
+
+ l_PluginInit = 0;
+ return M64ERR_SUCCESS;
+}
+
+EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
+{
+ /* set version info */
+ if (PluginType != NULL)
+ *PluginType = M64PLUGIN_RSP;
+
+ if (PluginVersion != NULL)
+ *PluginVersion = RSP_HLE_VERSION;
+
+ if (APIVersion != NULL)
+ *APIVersion = RSP_PLUGIN_API_VERSION;
+
+ if (PluginNamePtr != NULL)
+ *PluginNamePtr = "Hacktarux/Azimer High-Level Emulation RSP Plugin";
+
+ if (Capabilities != NULL)
+ *Capabilities = 0;
+
+ return M64ERR_SUCCESS;
+}
+
+EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles)
+{
+ hle_execute(&g_hle);
+ return Cycles;
+}
+
+EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int* CycleCount)
+{
+ hle_init(&g_hle,
+ Rsp_Info.RDRAM,
+ Rsp_Info.DMEM,
+ Rsp_Info.IMEM,
+ Rsp_Info.MI_INTR_REG,
+ Rsp_Info.SP_MEM_ADDR_REG,
+ Rsp_Info.SP_DRAM_ADDR_REG,
+ Rsp_Info.SP_RD_LEN_REG,
+ Rsp_Info.SP_WR_LEN_REG,
+ Rsp_Info.SP_STATUS_REG,
+ Rsp_Info.SP_DMA_FULL_REG,
+ Rsp_Info.SP_DMA_BUSY_REG,
+ Rsp_Info.SP_PC_REG,
+ Rsp_Info.SP_SEMAPHORE_REG,
+ Rsp_Info.DPC_START_REG,
+ Rsp_Info.DPC_END_REG,
+ Rsp_Info.DPC_CURRENT_REG,
+ Rsp_Info.DPC_STATUS_REG,
+ Rsp_Info.DPC_CLOCK_REG,
+ Rsp_Info.DPC_BUFBUSY_REG,
+ Rsp_Info.DPC_PIPEBUSY_REG,
+ Rsp_Info.DPC_TMEM_REG,
+ NULL);
+
+ l_CheckInterrupts = Rsp_Info.CheckInterrupts;
+ l_ProcessDlistList = Rsp_Info.ProcessDlistList;
+ 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)
+{
+ /* notify fallback plugin */
+ if (l_RomClosed) {
+ l_RomClosed();
+ }
+}
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/re2.c b/libmupen64plus/mupen64plus-rsp-hle/src/re2.c
new file mode 100644
index 0000000000..8ae178804d
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/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
+#include
+#include
+
+#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/libmupen64plus/mupen64plus-rsp-hle/src/ucode1.cpp b/libmupen64plus/mupen64plus-rsp-hle/src/ucode1.cpp
deleted file mode 100644
index eb869cbb7b..0000000000
--- a/libmupen64plus/mupen64plus-rsp-hle/src/ucode1.cpp
+++ /dev/null
@@ -1,951 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - ucode1.cpp *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2009 Richard Goedeken *
- * Copyright (C) 2002 Hacktarux *
- * *
- * 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
-
-extern "C" {
- #include "hle.h"
- #include "alist_internal.h"
-}
-
-//#include "rsp.h"
-//#define SAFE_MEMORY
-/*
-#ifndef SAFE_MEMORY
-# define wr8 (src , address);
-# define rd8 (dest, address);
-# define wr16 (src, address);
-# define rd16 (dest, address);
-# define wr32 (src, address);
-# define rd32 (dest, address);
-# define wr64 (src, address);
-# define rd64 (dest, address);
-# define dmamem (dest, src, size) memcpy (dest, src, size);
-# define clrmem (dest, size) memset (dest, 0, size);
-#else
- void wr8 (u8 src, void *address);
- void rd8 (u8 dest, void *address);
- void wr16 (u16 src, void *address);
- void rd16 (u16 dest, void *address);
- void wr32 (u16 src, void *address);
- void rd32 (u16 dest, void *address);
- void wr64 (u16 src, void *address);
- void rd64 (u16 dest, void *address);
- void dmamem (void *dest, void *src, int size);
- void clrmem (void *dest, int size);
-#endif
-*/
-/******** DMEM Memory Map for ABI 1 ***************
-Address/Range Description
-------------- -------------------------------
-0x000..0x2BF UCodeData
- 0x000-0x00F Constants - 0000 0001 0002 FFFF 0020 0800 7FFF 4000
- 0x010-0x02F Function Jump Table (16 Functions * 2 bytes each = 32) 0x20
- 0x030-0x03F Constants - F000 0F00 00F0 000F 0001 0010 0100 1000
- 0x040-0x03F Used by the Envelope Mixer (But what for?)
- 0x070-0x07F Used by the Envelope Mixer (But what for?)
-0x2C0..0x31F
-0x320..0x35F Segments
-0x360 Audio In Buffer (Location)
-0x362 Audio Out Buffer (Location)
-0x364 Audio Buffer Size (Location)
-0x366 Initial Volume for Left Channel
-0x368 Initial Volume for Right Channel
-0x36A Auxillary Buffer #1 (Location)
-0x36C Auxillary Buffer #2 (Location)
-0x36E Auxillary Buffer #3 (Location)
-0x370 Loop Value (shared location)
-0x370 Target Volume (Left)
-0x372 Ramp?? (Left)
-0x374 Rate?? (Left)
-0x376 Target Volume (Right)
-0x378 Ramp?? (Right)
-0x37A Rate?? (Right)
-0x37C Dry??
-0x37E Wet??
-0x380..0x4BF Alist data
-0x4C0..0x4FF ADPCM CodeBook
-0x500..0x5BF
-0x5C0..0xF7F Buffers...
-0xF80..0xFFF
-***************************************************/
-#ifdef USE_EXPANSION
- #define MEMMASK 0x7FFFFF
-#else
- #define MEMMASK 0x3FFFFF
-#endif
-
-static void SPNOOP (u32 inst1, u32 inst2) {
- //MessageBox (NULL, "Unknown Audio Command in ABI 1", "Audio HLE Error", MB_OK);
-}
-
-u32 SEGMENTS[0x10]; // 0x0320
-// T8 = 0x360
-u16 AudioInBuffer; // 0x0000(T8)
-u16 AudioOutBuffer; // 0x0002(T8)
-u16 AudioCount; // 0x0004(T8)
-s16 Vol_Left; // 0x0006(T8)
-s16 Vol_Right; // 0x0008(T8)
-u16 AudioAuxA; // 0x000A(T8)
-u16 AudioAuxC; // 0x000C(T8)
-u16 AudioAuxE; // 0x000E(T8)
-u32 loopval; // 0x0010(T8) // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
-s16 VolTrg_Left; // 0x0010(T8)
-s32 VolRamp_Left; // m_LeftVolTarget
-//u16 VolRate_Left; // m_LeftVolRate
-s16 VolTrg_Right; // m_RightVol
-s32 VolRamp_Right; // m_RightVolTarget
-//u16 VolRate_Right; // m_RightVolRate
-s16 Env_Dry; // 0x001C(T8)
-s16 Env_Wet; // 0x001E(T8)
-
-u8 BufferSpace[0x10000];
-
-short hleMixerWorkArea[256];
-u16 adpcmtable[0x88];
-
-extern const u16 ResampleLUT [0x200] = {
- 0x0C39, 0x66AD, 0x0D46, 0xFFDF, 0x0B39, 0x6696, 0x0E5F, 0xFFD8,
- 0x0A44, 0x6669, 0x0F83, 0xFFD0, 0x095A, 0x6626, 0x10B4, 0xFFC8,
- 0x087D, 0x65CD, 0x11F0, 0xFFBF, 0x07AB, 0x655E, 0x1338, 0xFFB6,
- 0x06E4, 0x64D9, 0x148C, 0xFFAC, 0x0628, 0x643F, 0x15EB, 0xFFA1,
- 0x0577, 0x638F, 0x1756, 0xFF96, 0x04D1, 0x62CB, 0x18CB, 0xFF8A,
- 0x0435, 0x61F3, 0x1A4C, 0xFF7E, 0x03A4, 0x6106, 0x1BD7, 0xFF71,
- 0x031C, 0x6007, 0x1D6C, 0xFF64, 0x029F, 0x5EF5, 0x1F0B, 0xFF56,
- 0x022A, 0x5DD0, 0x20B3, 0xFF48, 0x01BE, 0x5C9A, 0x2264, 0xFF3A,
- 0x015B, 0x5B53, 0x241E, 0xFF2C, 0x0101, 0x59FC, 0x25E0, 0xFF1E,
- 0x00AE, 0x5896, 0x27A9, 0xFF10, 0x0063, 0x5720, 0x297A, 0xFF02,
- 0x001F, 0x559D, 0x2B50, 0xFEF4, 0xFFE2, 0x540D, 0x2D2C, 0xFEE8,
- 0xFFAC, 0x5270, 0x2F0D, 0xFEDB, 0xFF7C, 0x50C7, 0x30F3, 0xFED0,
- 0xFF53, 0x4F14, 0x32DC, 0xFEC6, 0xFF2E, 0x4D57, 0x34C8, 0xFEBD,
- 0xFF0F, 0x4B91, 0x36B6, 0xFEB6, 0xFEF5, 0x49C2, 0x38A5, 0xFEB0,
- 0xFEDF, 0x47ED, 0x3A95, 0xFEAC, 0xFECE, 0x4611, 0x3C85, 0xFEAB,
- 0xFEC0, 0x4430, 0x3E74, 0xFEAC, 0xFEB6, 0x424A, 0x4060, 0xFEAF,
- 0xFEAF, 0x4060, 0x424A, 0xFEB6, 0xFEAC, 0x3E74, 0x4430, 0xFEC0,
- 0xFEAB, 0x3C85, 0x4611, 0xFECE, 0xFEAC, 0x3A95, 0x47ED, 0xFEDF,
- 0xFEB0, 0x38A5, 0x49C2, 0xFEF5, 0xFEB6, 0x36B6, 0x4B91, 0xFF0F,
- 0xFEBD, 0x34C8, 0x4D57, 0xFF2E, 0xFEC6, 0x32DC, 0x4F14, 0xFF53,
- 0xFED0, 0x30F3, 0x50C7, 0xFF7C, 0xFEDB, 0x2F0D, 0x5270, 0xFFAC,
- 0xFEE8, 0x2D2C, 0x540D, 0xFFE2, 0xFEF4, 0x2B50, 0x559D, 0x001F,
- 0xFF02, 0x297A, 0x5720, 0x0063, 0xFF10, 0x27A9, 0x5896, 0x00AE,
- 0xFF1E, 0x25E0, 0x59FC, 0x0101, 0xFF2C, 0x241E, 0x5B53, 0x015B,
- 0xFF3A, 0x2264, 0x5C9A, 0x01BE, 0xFF48, 0x20B3, 0x5DD0, 0x022A,
- 0xFF56, 0x1F0B, 0x5EF5, 0x029F, 0xFF64, 0x1D6C, 0x6007, 0x031C,
- 0xFF71, 0x1BD7, 0x6106, 0x03A4, 0xFF7E, 0x1A4C, 0x61F3, 0x0435,
- 0xFF8A, 0x18CB, 0x62CB, 0x04D1, 0xFF96, 0x1756, 0x638F, 0x0577,
- 0xFFA1, 0x15EB, 0x643F, 0x0628, 0xFFAC, 0x148C, 0x64D9, 0x06E4,
- 0xFFB6, 0x1338, 0x655E, 0x07AB, 0xFFBF, 0x11F0, 0x65CD, 0x087D,
- 0xFFC8, 0x10B4, 0x6626, 0x095A, 0xFFD0, 0x0F83, 0x6669, 0x0A44,
- 0xFFD8, 0x0E5F, 0x6696, 0x0B39, 0xFFDF, 0x0D46, 0x66AD, 0x0C39
-};
-
-static void CLEARBUFF (u32 inst1, u32 inst2) {
- u32 addr = (u32)(inst1 & 0xffff);
- u32 count = (u32)(inst2 & 0xffff);
- addr &= 0xFFFC;
- memset(BufferSpace+addr, 0, (count+3)&0xFFFC);
-}
-
-//FILE *dfile = fopen ("d:\\envmix.txt", "wt");
-
-static void ENVMIXER (u32 inst1, u32 inst2) {
- //static int envmixcnt = 0;
- u8 flags = (u8)((inst1 >> 16) & 0xff);
- u32 addy = (inst2 & 0xFFFFFF);// + SEGMENTS[(inst2>>24)&0xf];
- //static
-// ********* Make sure these conditions are met... ***********
- /*if ((AudioInBuffer | AudioOutBuffer | AudioAuxA | AudioAuxC | AudioAuxE | AudioCount) & 0x3) {
- MessageBox (NULL, "Unaligned EnvMixer... please report this to Azimer with the following information: RomTitle, Place in the rom it occurred, and any save state just before the error", "AudioHLE Error", MB_OK);
- }*/
-// ------------------------------------------------------------
- short *inp=(short *)(BufferSpace+AudioInBuffer);
- short *out=(short *)(BufferSpace+AudioOutBuffer);
- short *aux1=(short *)(BufferSpace+AudioAuxA);
- short *aux2=(short *)(BufferSpace+AudioAuxC);
- short *aux3=(short *)(BufferSpace+AudioAuxE);
- s32 MainR;
- s32 MainL;
- s32 AuxR;
- s32 AuxL;
- int i1,o1,a1,a2=0,a3=0;
- unsigned short AuxIncRate=1;
- short zero[8];
- memset(zero,0,16);
- s32 LVol, RVol;
- s32 LAcc, RAcc;
- s32 LTrg, RTrg;
- s16 Wet, Dry;
- u32 ptr = 0;
- s32 RRamp, LRamp;
- s32 LAdderStart, RAdderStart, LAdderEnd, RAdderEnd;
- s32 oMainR, oMainL, oAuxR, oAuxL;
-
- //envmixcnt++;
-
- //fprintf (dfile, "\n----------------------------------------------------\n");
- if (flags & A_INIT) {
- LVol = ((Vol_Left * (s32)VolRamp_Left));
- RVol = ((Vol_Right * (s32)VolRamp_Right));
- Wet = (s16)Env_Wet; Dry = (s16)Env_Dry; // Save Wet/Dry values
- LTrg = (VolTrg_Left << 16); RTrg = (VolTrg_Right << 16); // Save Current Left/Right Targets
- LAdderStart = Vol_Left << 16;
- RAdderStart = Vol_Right << 16;
- LAdderEnd = LVol;
- RAdderEnd = RVol;
- RRamp = VolRamp_Right;
- LRamp = VolRamp_Left;
- } else {
- // Load LVol, RVol, LAcc, and RAcc (all 32bit)
- // Load Wet, Dry, LTrg, RTrg
- memcpy((u8 *)hleMixerWorkArea, (rsp.RDRAM+addy), 80);
- Wet = *(s16 *)(hleMixerWorkArea + 0); // 0-1
- Dry = *(s16 *)(hleMixerWorkArea + 2); // 2-3
- LTrg = *(s32 *)(hleMixerWorkArea + 4); // 4-5
- RTrg = *(s32 *)(hleMixerWorkArea + 6); // 6-7
- LRamp= *(s32 *)(hleMixerWorkArea + 8); // 8-9 (hleMixerWorkArea is a 16bit pointer)
- RRamp= *(s32 *)(hleMixerWorkArea + 10); // 10-11
- LAdderEnd = *(s32 *)(hleMixerWorkArea + 12); // 12-13
- RAdderEnd = *(s32 *)(hleMixerWorkArea + 14); // 14-15
- LAdderStart = *(s32 *)(hleMixerWorkArea + 16); // 12-13
- RAdderStart = *(s32 *)(hleMixerWorkArea + 18); // 14-15
- }
-
- if(!(flags&A_AUX)) {
- AuxIncRate=0;
- aux2=aux3=zero;
- }
-
- oMainL = (Dry * (LTrg>>16) + 0x4000) >> 15;
- oAuxL = (Wet * (LTrg>>16) + 0x4000) >> 15;
- oMainR = (Dry * (RTrg>>16) + 0x4000) >> 15;
- oAuxR = (Wet * (RTrg>>16) + 0x4000) >> 15;
-
- for (int y = 0; y < AudioCount; y += 0x10) {
-
- if (LAdderStart != LTrg) {
- LAcc = LAdderStart;
- LVol = (LAdderEnd - LAdderStart) >> 3;
- LAdderEnd = (s32) (((s64)LAdderEnd * (s64)LRamp) >> 16);
- LAdderStart = (s32) (((s64)LAcc * (s64)LRamp) >> 16);
- } else {
- LAcc = LTrg;
- LVol = 0;
- }
-
- if (RAdderStart != RTrg) {
- RAcc = RAdderStart;
- RVol = (RAdderEnd - RAdderStart) >> 3;
- RAdderEnd = (s32) (((s64)RAdderEnd * (s64)RRamp) >> 16);
- RAdderStart = (s32) (((s64)RAcc * (s64)RRamp) >> 16);
- } else {
- RAcc = RTrg;
- RVol = 0;
- }
-
- for (int x = 0; x < 8; x++) {
- i1=(int)inp[ptr^S];
- o1=(int)out[ptr^S];
- a1=(int)aux1[ptr^S];
- if (AuxIncRate) {
- a2=(int)aux2[ptr^S];
- a3=(int)aux3[ptr^S];
- }
- // TODO: here...
- //LAcc = LTrg;
- //RAcc = RTrg;
-
- LAcc += LVol;
- RAcc += RVol;
-
- if (LVol <= 0) { // Decrementing
- if (LAcc < LTrg) {
- LAcc = LTrg;
- LAdderStart = LTrg;
- MainL = oMainL;
- AuxL = oAuxL;
- } else {
- MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
- AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
- }
- } else {
- if (LAcc > LTrg) {
- LAcc = LTrg;
- LAdderStart = LTrg;
- MainL = oMainL;
- AuxL = oAuxL;
- } else {
- MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
- AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
- }
- }
-
- if (RVol <= 0) { // Decrementing
- if (RAcc < RTrg) {
- RAcc = RTrg;
- RAdderStart = RTrg;
- MainR = oMainR;
- AuxR = oAuxR;
- } else {
- MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
- AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
- }
- } else {
- if (RAcc > RTrg) {
- RAcc = RTrg;
- RAdderStart = RTrg;
- MainR = oMainR;
- AuxR = oAuxR;
- } else {
- MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
- AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
- }
- }
-
- //fprintf (dfile, "%04X ", (LAcc>>16));
-
- /*MainL = (((s64)Dry*2 * (s64)(LAcc>>16)) + 0x8000) >> 16;
- MainR = (((s64)Dry*2 * (s64)(RAcc>>16)) + 0x8000) >> 16;
- AuxL = (((s64)Wet*2 * (s64)(LAcc>>16)) + 0x8000) >> 16;
- AuxR = (((s64)Wet*2 * (s64)(RAcc>>16)) + 0x8000) >> 16;*/
-/*
- if (MainL>32767) MainL = 32767;
- else if (MainL<-32768) MainL = -32768;
- if (MainR>32767) MainR = 32767;
- else if (MainR<-32768) MainR = -32768;
- if (AuxL>32767) AuxL = 32767;
- else if (AuxL<-32768) AuxR = -32768;
- if (AuxR>32767) AuxR = 32767;
- else if (AuxR<-32768) AuxR = -32768;*/
- /*
- MainR = (Dry * RTrg + 0x10000) >> 15;
- MainL = (Dry * LTrg + 0x10000) >> 15;
- AuxR = (Wet * RTrg + 0x8000) >> 16;
- AuxL = (Wet * LTrg + 0x8000) >> 16;*/
-
- o1+=(/*(o1*0x7fff)+*/(i1*MainR)+0x4000)>>15;
- a1+=(/*(a1*0x7fff)+*/(i1*MainL)+0x4000)>>15;
-
-/* o1=((s64)(((s64)o1*0xfffe)+((s64)i1*MainR*2)+0x8000)>>16);
-
- a1=((s64)(((s64)a1*0xfffe)+((s64)i1*MainL*2)+0x8000)>>16);*/
-
- if(o1>32767) o1=32767;
- else if(o1<-32768) o1=-32768;
-
- if(a1>32767) a1=32767;
- else if(a1<-32768) a1=-32768;
-
- out[ptr^S]=o1;
- aux1[ptr^S]=a1;
- if (AuxIncRate) {
- //a2=((s64)(((s64)a2*0xfffe)+((s64)i1*AuxR*2)+0x8000)>>16);
-
- //a3=((s64)(((s64)a3*0xfffe)+((s64)i1*AuxL*2)+0x8000)>>16);
- a2+=(/*(a2*0x7fff)+*/(i1*AuxR)+0x4000)>>15;
- a3+=(/*(a3*0x7fff)+*/(i1*AuxL)+0x4000)>>15;
-
- if(a2>32767) a2=32767;
- else if(a2<-32768) a2=-32768;
-
- if(a3>32767) a3=32767;
- else if(a3<-32768) a3=-32768;
-
- aux2[ptr^S]=a2;
- aux3[ptr^S]=a3;
- }
- ptr++;
- }
- }
-
- /*LAcc = LAdderEnd;
- RAcc = RAdderEnd;*/
-
- *(s16 *)(hleMixerWorkArea + 0) = Wet; // 0-1
- *(s16 *)(hleMixerWorkArea + 2) = Dry; // 2-3
- *(s32 *)(hleMixerWorkArea + 4) = LTrg; // 4-5
- *(s32 *)(hleMixerWorkArea + 6) = RTrg; // 6-7
- *(s32 *)(hleMixerWorkArea + 8) = LRamp; // 8-9 (hleMixerWorkArea is a 16bit pointer)
- *(s32 *)(hleMixerWorkArea + 10) = RRamp; // 10-11
- *(s32 *)(hleMixerWorkArea + 12) = LAdderEnd; // 12-13
- *(s32 *)(hleMixerWorkArea + 14) = RAdderEnd; // 14-15
- *(s32 *)(hleMixerWorkArea + 16) = LAdderStart; // 12-13
- *(s32 *)(hleMixerWorkArea + 18) = RAdderStart; // 14-15
- memcpy(rsp.RDRAM+addy, (u8 *)hleMixerWorkArea,80);
-}
-
-static void RESAMPLE (u32 inst1, u32 inst2) {
- unsigned char Flags=(u8)((inst1>>16)&0xff);
- unsigned int Pitch=((inst1&0xffff))<<1;
- u32 addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- unsigned int Accum=0;
- unsigned int location;
- s16 *lut/*, *lut2*/;
- short *dst;
- s16 *src;
- dst=(short *)(BufferSpace);
- src=(s16 *)(BufferSpace);
- u32 srcPtr=(AudioInBuffer/2);
- u32 dstPtr=(AudioOutBuffer/2);
- s32 temp;
- s32 accum;
-/*
- if (addy > (1024*1024*8))
- addy = (inst2 & 0xffffff);
-*/
- srcPtr -= 4;
-
- if ((Flags & 0x1) == 0) {
- //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8);
- for (int x=0; x < 4; x++)
- src[(srcPtr+x)^S] = ((u16 *)rsp.RDRAM)[((addy/2)+x)^S];
- Accum = *(u16 *)(rsp.RDRAM+addy+10);
- } else {
- for (int x=0; x < 4; x++)
- src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
- }
-
- for(int i=0;i < ((AudioCount+0xf)&0xFFF0)/2;i++) {
- //location = (((Accum * 0x40) >> 0x10) * 8);
- // location is the fractional position between two samples
- location = (Accum >> 0xa) * 4;
- lut = (s16*)ResampleLUT + location;
-
- // mov eax, dword ptr [src+srcPtr];
- // movsx edx, word ptr [lut];
- // shl edx, 1
- // imul edx
- // test eax, 08000h
- // setz ecx
- // shl ecx, 16
- // xor eax, 08000h
- // add eax, ecx
- // and edx, 0f000h
-
- // imul
- temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0])));
- accum = (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3])));
- accum += (s32)(temp >> 15);
-
- if (accum > 32767) accum = 32767;
- if (accum < -32768) accum = -32768;
-
- dst[dstPtr^S] = (accum);
- dstPtr++;
- Accum += Pitch;
- srcPtr += (Accum>>16);
- Accum&=0xffff;
- }
- for (int x=0; x < 4; x++)
- ((u16 *)rsp.RDRAM)[((addy/2)+x)^S] = src[(srcPtr+x)^S];
- //memcpy (RSWORK, src+srcPtr, 0x8);
- *(u16 *)(rsp.RDRAM+addy+10) = Accum;
-}
-
-static void SETVOL (u32 inst1, u32 inst2) {
-// Might be better to unpack these depending on the flags...
- u8 flags = (u8)((inst1 >> 16) & 0xff);
- u16 vol = (s16)(inst1 & 0xffff);
- //u16 voltarg =(u16)((inst2 >> 16)&0xffff);
- u16 volrate = (u16)((inst2 & 0xffff));
-
- if (flags & A_AUX) {
- Env_Dry = (s16)vol; // m_MainVol
- Env_Wet = (s16)volrate; // m_AuxVol
- return;
- }
-
- if(flags & A_VOL) { // Set the Source(start) Volumes
- if(flags & A_LEFT) {
- Vol_Left = (s16)vol; // m_LeftVolume
- } else { // A_RIGHT
- Vol_Right = (s16)vol; // m_RightVolume
- }
- return;
- }
-
-//0x370 Loop Value (shared location)
-//0x370 Target Volume (Left)
-//u16 VolRamp_Left; // 0x0012(T8)
- if(flags & A_LEFT) { // Set the Ramping values Target, Ramp
- //loopval = (((u32)vol << 0x10) | (u32)voltarg);
- VolTrg_Left = (s16)inst1; // m_LeftVol
- //VolRamp_Left = (s32)inst2;
- VolRamp_Left = (s32)inst2;//(u16)(inst2) | (s32)(s16)(inst2 << 0x10);
- //fprintf (dfile, "Ramp Left: %f\n", (float)VolRamp_Left/65536.0);
- //fprintf (dfile, "Ramp Left: %08X\n", inst2);
- //VolRamp_Left = (s16)voltarg; // m_LeftVolTarget
- //VolRate_Left = (s16)volrate; // m_LeftVolRate
- } else { // A_RIGHT
- VolTrg_Right = (s16)inst1; // m_RightVol
- //VolRamp_Right = (s32)inst2;
- VolRamp_Right = (s32)inst2;//(u16)(inst2 >> 0x10) | (s32)(s16)(inst2 << 0x10);
- //fprintf (dfile, "Ramp Right: %f\n", (float)VolRamp_Right/65536.0);
- //fprintf (dfile, "Ramp Right: %08X\n", inst2);
- //VolRamp_Right = (s16)voltarg; // m_RightVolTarget
- //VolRate_Right = (s16)volrate; // m_RightVolRate
- }
-}
-
-static void UNKNOWN (u32 inst1, u32 inst2) {}
-
-static void SETLOOP (u32 inst1, u32 inst2) {
- loopval = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- //VolTrg_Left = (s16)(loopval>>16); // m_LeftVol
- //VolRamp_Left = (s16)(loopval); // m_LeftVolTarget
-}
-
-static void ADPCM (u32 inst1, u32 inst2) { // Work in progress! :)
- unsigned char Flags=(u8)(inst1>>16)&0xff;
- //unsigned short Gain=(u16)(inst1&0xffff);
- unsigned int Address=(inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- unsigned short inPtr=0;
- //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2));
- short *out=(short *)(BufferSpace+AudioOutBuffer);
- //unsigned char *in=(unsigned char *)(BufferSpace+AudioInBuffer);
- short count=(short)AudioCount;
- unsigned char icode;
- unsigned char code;
- int vscale;
- unsigned short index;
- unsigned short j;
- int a[8];
- short *book1,*book2;
-/*
- if (Address > (1024*1024*8))
- Address = (inst2 & 0xffffff);
-*/
- memset(out,0,32);
-
- if(!(Flags&0x1))
- {
- if(Flags&0x2) {
- memcpy(out,&rsp.RDRAM[loopval&MEMMASK],32);
- } else {
- memcpy(out,&rsp.RDRAM[Address],32);
- }
- }
-
- int l1=out[14^S];
- int l2=out[15^S];
- int inp1[8];
- int inp2[8];
- out+=16;
- while(count>0)
- {
- // the first interation through, these values are
- // either 0 in the case of A_INIT, from a special
- // area of memory in the case of A_LOOP or just
- // the values we calculated the last time
-
- code=BufferSpace[(AudioInBuffer+inPtr)^S8];
- index=code&0xf;
- index<<=4; // index into the adpcm code table
- book1=(short *)&adpcmtable[index];
- book2=book1+8;
- code>>=4; // upper nibble is scale
- vscale=(0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
- // so this appears to be a fractional scale based
- // on the 12 based inverse of the scale value. note
- // that this could be negative, in which case we do
- // not use the calculated vscale value... see the
- // if(code>12) check below
-
- inPtr++; // coded adpcm data lies next
- j=0;
- while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
- // which yields 8 short pcm values
- {
- icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
- inPtr++;
-
- inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
- if(code<12)
- inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
-
- inp1[j]=(s16)((icode&0xf)<<12);
- if(code<12)
- inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
- }
- j=0;
- while(j<8)
- {
- icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
- inPtr++;
-
- inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
- if(code<12)
- inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
-
- inp2[j]=(short)((icode&0xf)<<12);
- if(code<12)
- inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
- }
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp1[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp1[0];
- a[1]+=(int)inp1[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp1[0];
- a[2]+=(int)book2[0]*inp1[1];
- a[2]+=(int)inp1[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp1[0];
- a[3]+=(int)book2[1]*inp1[1];
- a[3]+=(int)book2[0]*inp1[2];
- a[3]+=(int)inp1[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp1[0];
- a[4]+=(int)book2[2]*inp1[1];
- a[4]+=(int)book2[1]*inp1[2];
- a[4]+=(int)book2[0]*inp1[3];
- a[4]+=(int)inp1[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp1[0];
- a[5]+=(int)book2[3]*inp1[1];
- a[5]+=(int)book2[2]*inp1[2];
- a[5]+=(int)book2[1]*inp1[3];
- a[5]+=(int)book2[0]*inp1[4];
- a[5]+=(int)inp1[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp1[0];
- a[6]+=(int)book2[4]*inp1[1];
- a[6]+=(int)book2[3]*inp1[2];
- a[6]+=(int)book2[2]*inp1[3];
- a[6]+=(int)book2[1]*inp1[4];
- a[6]+=(int)book2[0]*inp1[5];
- a[6]+=(int)inp1[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp1[0];
- a[7]+=(int)book2[5]*inp1[1];
- a[7]+=(int)book2[4]*inp1[2];
- a[7]+=(int)book2[3]*inp1[3];
- a[7]+=(int)book2[2]*inp1[4];
- a[7]+=(int)book2[1]*inp1[5];
- a[7]+=(int)book2[0]*inp1[6];
- a[7]+=(int)inp1[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- }
- l1=a[6];
- l2=a[7];
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp2[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp2[0];
- a[1]+=(int)inp2[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp2[0];
- a[2]+=(int)book2[0]*inp2[1];
- a[2]+=(int)inp2[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp2[0];
- a[3]+=(int)book2[1]*inp2[1];
- a[3]+=(int)book2[0]*inp2[2];
- a[3]+=(int)inp2[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp2[0];
- a[4]+=(int)book2[2]*inp2[1];
- a[4]+=(int)book2[1]*inp2[2];
- a[4]+=(int)book2[0]*inp2[3];
- a[4]+=(int)inp2[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp2[0];
- a[5]+=(int)book2[3]*inp2[1];
- a[5]+=(int)book2[2]*inp2[2];
- a[5]+=(int)book2[1]*inp2[3];
- a[5]+=(int)book2[0]*inp2[4];
- a[5]+=(int)inp2[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp2[0];
- a[6]+=(int)book2[4]*inp2[1];
- a[6]+=(int)book2[3]*inp2[2];
- a[6]+=(int)book2[2]*inp2[3];
- a[6]+=(int)book2[1]*inp2[4];
- a[6]+=(int)book2[0]*inp2[5];
- a[6]+=(int)inp2[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp2[0];
- a[7]+=(int)book2[5]*inp2[1];
- a[7]+=(int)book2[4]*inp2[2];
- a[7]+=(int)book2[3]*inp2[3];
- a[7]+=(int)book2[2]*inp2[4];
- a[7]+=(int)book2[1]*inp2[5];
- a[7]+=(int)book2[0]*inp2[6];
- a[7]+=(int)inp2[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- }
- l1=a[6];
- l2=a[7];
-
- count-=32;
- }
- out-=16;
- memcpy(&rsp.RDRAM[Address],out,32);
-}
-
-static void LOADBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
- u32 v0;
- //u32 cnt;
- if (AudioCount == 0)
- return;
- v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
- memcpy (BufferSpace+(AudioInBuffer&0xFFFC), rsp.RDRAM+v0, (AudioCount+3)&0xFFFC);
-}
-
-static void SAVEBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
- u32 v0;
- //u32 cnt;
- if (AudioCount == 0)
- return;
- v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
- memcpy (rsp.RDRAM+v0, BufferSpace+(AudioOutBuffer&0xFFFC), (AudioCount+3)&0xFFFC);
-}
-
-static void SETBUFF (u32 inst1, u32 inst2) { // Should work ;-)
- if ((inst1 >> 0x10) & 0x8) { // A_AUX - Auxillary Sound Buffer Settings
- AudioAuxA = u16(inst1);
- AudioAuxC = u16((inst2 >> 0x10));
- AudioAuxE = u16(inst2);
- } else { // A_MAIN - Main Sound Buffer Settings
- AudioInBuffer = u16(inst1); // 0x00
- AudioOutBuffer = u16((inst2 >> 0x10)); // 0x02
- AudioCount = u16(inst2); // 0x04
- }
-}
-
-static void DMEMMOVE (u32 inst1, u32 inst2) { // Doesn't sound just right?... will fix when HLE is ready - 03-11-01
- u32 v0, v1;
- u32 cnt;
- if ((inst2 & 0xffff)==0)
- return;
- v0 = (inst1 & 0xFFFF);
- v1 = (inst2 >> 0x10);
- //assert ((v1 & 0x3) == 0);
- //assert ((v0 & 0x3) == 0);
- u32 count = ((inst2+3) & 0xfffc);
- //v0 = (v0) & 0xfffc;
- //v1 = (v1) & 0xfffc;
-
- //memcpy (BufferSpace+v1, BufferSpace+v0, count-1);
- for (cnt = 0; cnt < count; cnt++) {
- *(u8 *)(BufferSpace+((cnt+v1)^S8)) = *(u8 *)(BufferSpace+((cnt+v0)^S8));
- }
-}
-
-static void LOADADPCM (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01
- u32 v0;
- v0 = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
-/* if (v0 > (1024*1024*8))
- v0 = (inst2 & 0xffffff);*/
- //memcpy (dmem+0x4c0, rsp.RDRAM+v0, inst1&0xffff); // Could prolly get away with not putting this in dmem
- //assert ((inst1&0xffff) <= 0x80);
- u16 *table = (u16 *)(rsp.RDRAM+v0);
- for (u32 x = 0; x < ((inst1&0xffff)>>0x4); x++) {
- adpcmtable[(0x0+(x<<3))^S] = table[0];
- adpcmtable[(0x1+(x<<3))^S] = table[1];
-
- adpcmtable[(0x2+(x<<3))^S] = table[2];
- adpcmtable[(0x3+(x<<3))^S] = table[3];
-
- adpcmtable[(0x4+(x<<3))^S] = table[4];
- adpcmtable[(0x5+(x<<3))^S] = table[5];
-
- adpcmtable[(0x6+(x<<3))^S] = table[6];
- adpcmtable[(0x7+(x<<3))^S] = table[7];
- table += 8;
- }
-}
-
-
-static void INTERLEAVE (u32 inst1, u32 inst2) { // Works... - 3-11-01
- u32 inL, inR;
- u16 *outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
- u16 *inSrcR;
- u16 *inSrcL;
- u16 Left, Right, Left2, Right2;
-
- inL = inst2 & 0xFFFF;
- inR = (inst2 >> 16) & 0xFFFF;
-
- inSrcR = (u16 *)(BufferSpace+inR);
- inSrcL = (u16 *)(BufferSpace+inL);
-
- for (int x = 0; x < (AudioCount/4); x++) {
- Left=*(inSrcL++);
- Right=*(inSrcR++);
- Left2=*(inSrcL++);
- Right2=*(inSrcR++);
-
-#ifdef M64P_BIG_ENDIAN
- *(outbuff++)=Right;
- *(outbuff++)=Left;
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
-#else
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
- *(outbuff++)=Right;
- *(outbuff++)=Left;
-#endif
- }
-}
-
-
-static void MIXER (u32 inst1, u32 inst2) { // Fixed a sign issue... 03-14-01
- u32 dmemin = (u16)(inst2 >> 0x10);
- u32 dmemout = (u16)(inst2 & 0xFFFF);
- //u8 flags = (u8)((inst1 >> 16) & 0xff);
- s32 gain = (s16)(inst1 & 0xFFFF);
- s32 temp;
-
- if (AudioCount == 0)
- return;
-
- for (int x=0; x < AudioCount; x+=2) { // I think I can do this a lot easier
- temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15;
- temp += *(s16 *)(BufferSpace+dmemout+x);
-
- if ((s32)temp > 32767)
- temp = 32767;
- if ((s32)temp < -32768)
- temp = -32768;
-
- *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
- }
-}
-
-// TOP Performance Hogs:
-//Command: ADPCM - Calls: 48 - Total Time: 331226 - Avg Time: 6900.54 - Percent: 31.53%
-//Command: ENVMIXER - Calls: 48 - Total Time: 408563 - Avg Time: 8511.73 - Percent: 38.90%
-//Command: LOADBUFF - Calls: 56 - Total Time: 21551 - Avg Time: 384.84 - Percent: 2.05%
-//Command: RESAMPLE - Calls: 48 - Total Time: 225922 - Avg Time: 4706.71 - Percent: 21.51%
-
-//Command: ADPCM - Calls: 48 - Total Time: 391600 - Avg Time: 8158.33 - Percent: 32.52%
-//Command: ENVMIXER - Calls: 48 - Total Time: 444091 - Avg Time: 9251.90 - Percent: 36.88%
-//Command: LOADBUFF - Calls: 58 - Total Time: 29945 - Avg Time: 516.29 - Percent: 2.49%
-//Command: RESAMPLE - Calls: 48 - Total Time: 276354 - Avg Time: 5757.38 - Percent: 22.95%
-
-
-extern "C" const acmd_callback_t ABI1[0x10] = { // TOP Performace Hogs: MIXER, RESAMPLE, ENVMIXER
- SPNOOP , ADPCM , CLEARBUFF, ENVMIXER , LOADBUFF, RESAMPLE , SAVEBUFF, UNKNOWN,
- SETBUFF, SETVOL, DMEMMOVE , LOADADPCM , MIXER , INTERLEAVE, UNKNOWN , SETLOOP
-};
-
-/* BACKUPS
-void MIXER (u32 inst1, u32 inst2) { // Fixed a sign issue... 03-14-01
- u16 dmemin = (u16)(inst2 >> 0x10);
- u16 dmemout = (u16)(inst2 & 0xFFFF);
- u16 gain = (u16)(inst1 & 0xFFFF);
- u8 flags = (u8)((inst1 >> 16) & 0xff);
- u64 temp;
-
- if (AudioCount == 0)
- return;
-
- for (int x=0; x < AudioCount; x+=2) { // I think I can do this a lot easier
- temp = (s64)(*(s16 *)(BufferSpace+dmemout+x)) * (s64)((s16)(0x7FFF)*2);
-
- if (temp & 0x8000)
- temp = (temp^0x8000) + 0x10000;
- else
- temp = (temp^0x8000);
-
- temp = (temp & 0xFFFFFFFFFFFF);
-
- temp += ((*(s16 *)(BufferSpace+dmemin+x) * (s64)((s16)gain*2))) & 0xFFFFFFFFFFFF;
-
- temp = (s32)(temp >> 16);
- if ((s32)temp > 32767)
- temp = 32767;
- if ((s32)temp < -32768)
- temp = -32768;
-
- *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
- }
-}
-*/
-
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/ucode2.cpp b/libmupen64plus/mupen64plus-rsp-hle/src/ucode2.cpp
deleted file mode 100644
index dd15689fcb..0000000000
--- a/libmupen64plus/mupen64plus-rsp-hle/src/ucode2.cpp
+++ /dev/null
@@ -1,930 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - ucode2.cpp *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2009 Richard Goedeken *
- * Copyright (C) 2002 Hacktarux *
- * *
- * 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
-# include
-
-extern "C" {
- #include "m64p_types.h"
- #include "hle.h"
- #include "alist_internal.h"
-}
-
-extern u8 BufferSpace[0x10000];
-
-static void SPNOOP (u32 inst1, u32 inst2) {
- DebugMessage(M64MSG_ERROR, "Unknown/Unimplemented Audio Command %i in ABI 2", (int)(inst1 >> 24));
-}
-extern u16 AudioInBuffer; // 0x0000(T8)
-extern u16 AudioOutBuffer; // 0x0002(T8)
-extern u16 AudioCount; // 0x0004(T8)
-extern u32 loopval; // 0x0010(T8)
-extern u32 SEGMENTS[0x10];
-
-extern u16 adpcmtable[0x88];
-
-extern const u16 ResampleLUT [0x200];
-
-bool isMKABI = false;
-bool isZeldaABI = false;
-
-extern "C" void init_ucode2() { isMKABI = isZeldaABI = false; }
-
-static void LOADADPCM2 (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01
- u32 v0;
- v0 = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- u16 *table = (u16 *)(rsp.RDRAM+v0); // Zelda2 Specific...
-
- for (u32 x = 0; x < ((inst1&0xffff)>>0x4); x++) {
- adpcmtable[(0x0+(x<<3))^S] = table[0];
- adpcmtable[(0x1+(x<<3))^S] = table[1];
-
- adpcmtable[(0x2+(x<<3))^S] = table[2];
- adpcmtable[(0x3+(x<<3))^S] = table[3];
-
- adpcmtable[(0x4+(x<<3))^S] = table[4];
- adpcmtable[(0x5+(x<<3))^S] = table[5];
-
- adpcmtable[(0x6+(x<<3))^S] = table[6];
- adpcmtable[(0x7+(x<<3))^S] = table[7];
- table += 8;
- }
-}
-
-static void SETLOOP2 (u32 inst1, u32 inst2) {
- loopval = inst2 & 0xffffff; // No segment?
-}
-
-static void SETBUFF2 (u32 inst1, u32 inst2) {
- AudioInBuffer = u16(inst1); // 0x00
- AudioOutBuffer = u16((inst2 >> 0x10)); // 0x02
- AudioCount = u16(inst2); // 0x04
-}
-
-static void ADPCM2 (u32 inst1, u32 inst2) { // Verified to be 100% Accurate...
- unsigned char Flags=(u8)(inst1>>16)&0xff;
- //unsigned short Gain=(u16)(inst1&0xffff);
- unsigned int Address=(inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- unsigned short inPtr=0;
- //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2));
- short *out=(short *)(BufferSpace+AudioOutBuffer);
- //unsigned char *in=(unsigned char *)(BufferSpace+AudioInBuffer);
- short count=(short)AudioCount;
- unsigned char icode;
- unsigned char code;
- int vscale;
- unsigned short index;
- unsigned short j;
- int a[8];
- short *book1,*book2;
-
- u8 srange;
- u8 mask1;
- u8 mask2;
- u8 shifter;
-
- memset(out,0,32);
-
- if (Flags & 0x4) { // Tricky lil Zelda MM and ABI2!!! hahaha I know your secrets! :DDD
- srange = 0xE;
- mask1 = 0xC0;
- mask2 = 0x30;
- shifter = 10;
- } else {
- srange = 0xC;
- mask1 = 0xf0;
- mask2 = 0x0f;
- shifter = 12;
- }
-
- if(!(Flags&0x1))
- {
- if(Flags&0x2)
- {/*
- for(int i=0;i<16;i++)
- {
- out[i]=*(short *)&rsp.RDRAM[(loopval+i*2)^2];
- }*/
- memcpy(out,&rsp.RDRAM[loopval],32);
- }
- else
- {/*
- for(int i=0;i<16;i++)
- {
- out[i]=*(short *)&rsp.RDRAM[(Address+i*2)^2];
- }*/
- memcpy(out,&rsp.RDRAM[Address],32);
- }
- }
-
- int l1=out[14^S];
- int l2=out[15^S];
- int inp1[8];
- int inp2[8];
- out+=16;
- while(count>0) {
- code=BufferSpace[(AudioInBuffer+inPtr)^S8];
- index=code&0xf;
- index<<=4;
- book1=(short *)&adpcmtable[index];
- book2=book1+8;
- code>>=4;
- vscale=(0x8000>>((srange-code)-1));
-
- inPtr++;
- j=0;
-
- while(j<8) {
- icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
- inPtr++;
-
- inp1[j]=(s16)((icode&mask1) << 8); // this will in effect be signed
- if(code>16);
- //else int catchme=1;
- j++;
-
- inp1[j]=(s16)((icode&mask2)<>16);
- //else int catchme=1;
- j++;
-
- if (Flags & 4) {
- inp1[j]=(s16)((icode&0xC) << 12); // this will in effect be signed
- if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- //else int catchme=1;
- j++;
-
- inp1[j]=(s16)((icode&0x3) << 14);
- if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- //else int catchme=1;
- j++;
- } // end flags
- } // end while
-
-
-
- j=0;
- while(j<8) {
- icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
- inPtr++;
-
- inp2[j]=(s16)((icode&mask1) << 8);
- if(code>16);
- //else int catchme=1;
- j++;
-
- inp2[j]=(s16)((icode&mask2)<>16);
- //else int catchme=1;
- j++;
-
- if (Flags & 4) {
- inp2[j]=(s16)((icode&0xC) << 12);
- if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- //else int catchme=1;
- j++;
-
- inp2[j]=(s16)((icode&0x3) << 14);
- if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- //else int catchme=1;
- j++;
- } // end flags
- }
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp1[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp1[0];
- a[1]+=(int)inp1[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp1[0];
- a[2]+=(int)book2[0]*inp1[1];
- a[2]+=(int)inp1[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp1[0];
- a[3]+=(int)book2[1]*inp1[1];
- a[3]+=(int)book2[0]*inp1[2];
- a[3]+=(int)inp1[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp1[0];
- a[4]+=(int)book2[2]*inp1[1];
- a[4]+=(int)book2[1]*inp1[2];
- a[4]+=(int)book2[0]*inp1[3];
- a[4]+=(int)inp1[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp1[0];
- a[5]+=(int)book2[3]*inp1[1];
- a[5]+=(int)book2[2]*inp1[2];
- a[5]+=(int)book2[1]*inp1[3];
- a[5]+=(int)book2[0]*inp1[4];
- a[5]+=(int)inp1[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp1[0];
- a[6]+=(int)book2[4]*inp1[1];
- a[6]+=(int)book2[3]*inp1[2];
- a[6]+=(int)book2[2]*inp1[3];
- a[6]+=(int)book2[1]*inp1[4];
- a[6]+=(int)book2[0]*inp1[5];
- a[6]+=(int)inp1[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp1[0];
- a[7]+=(int)book2[5]*inp1[1];
- a[7]+=(int)book2[4]*inp1[2];
- a[7]+=(int)book2[3]*inp1[3];
- a[7]+=(int)book2[2]*inp1[4];
- a[7]+=(int)book2[1]*inp1[5];
- a[7]+=(int)book2[0]*inp1[6];
- a[7]+=(int)inp1[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- }
- l1=a[6];
- l2=a[7];
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp2[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp2[0];
- a[1]+=(int)inp2[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp2[0];
- a[2]+=(int)book2[0]*inp2[1];
- a[2]+=(int)inp2[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp2[0];
- a[3]+=(int)book2[1]*inp2[1];
- a[3]+=(int)book2[0]*inp2[2];
- a[3]+=(int)inp2[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp2[0];
- a[4]+=(int)book2[2]*inp2[1];
- a[4]+=(int)book2[1]*inp2[2];
- a[4]+=(int)book2[0]*inp2[3];
- a[4]+=(int)inp2[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp2[0];
- a[5]+=(int)book2[3]*inp2[1];
- a[5]+=(int)book2[2]*inp2[2];
- a[5]+=(int)book2[1]*inp2[3];
- a[5]+=(int)book2[0]*inp2[4];
- a[5]+=(int)inp2[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp2[0];
- a[6]+=(int)book2[4]*inp2[1];
- a[6]+=(int)book2[3]*inp2[2];
- a[6]+=(int)book2[2]*inp2[3];
- a[6]+=(int)book2[1]*inp2[4];
- a[6]+=(int)book2[0]*inp2[5];
- a[6]+=(int)inp2[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp2[0];
- a[7]+=(int)book2[5]*inp2[1];
- a[7]+=(int)book2[4]*inp2[2];
- a[7]+=(int)book2[3]*inp2[3];
- a[7]+=(int)book2[2]*inp2[4];
- a[7]+=(int)book2[1]*inp2[5];
- a[7]+=(int)book2[0]*inp2[6];
- a[7]+=(int)inp2[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- }
- l1=a[6];
- l2=a[7];
-
- count-=32;
- }
- out-=16;
- memcpy(&rsp.RDRAM[Address],out,32);
-}
-
-static void CLEARBUFF2 (u32 inst1, u32 inst2) {
- u16 addr = (u16)(inst1 & 0xffff);
- u16 count = (u16)(inst2 & 0xffff);
- if (count > 0)
- memset(BufferSpace+addr, 0, count);
-}
-
-static void LOADBUFF2 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u32 v0;
- u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
- v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
- memcpy (BufferSpace+(inst1&0xfffc), rsp.RDRAM+v0, (cnt+3)&0xFFFC);
-}
-
-static void SAVEBUFF2 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u32 v0;
- u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
- v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
- memcpy (rsp.RDRAM+v0, BufferSpace+(inst1&0xfffc), (cnt+3)&0xFFFC);
-}
-
-
-static void MIXER2 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u16 dmemin = (u16)(inst2 >> 0x10);
- u16 dmemout = (u16)(inst2 & 0xFFFF);
- u32 count = ((inst1 >> 12) & 0xFF0);
- s32 gain = (s16)(inst1 & 0xFFFF);
- s32 temp;
-
- for (unsigned int x=0; x < count; x+=2) { // I think I can do this a lot easier
-
- temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15;
- temp += *(s16 *)(BufferSpace+dmemout+x);
-
- if ((s32)temp > 32767)
- temp = 32767;
- if ((s32)temp < -32768)
- temp = -32768;
-
- *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
- }
-}
-
-
-static void RESAMPLE2 (u32 inst1, u32 inst2) {
- unsigned char Flags=(u8)((inst1>>16)&0xff);
- unsigned int Pitch=((inst1&0xffff))<<1;
- u32 addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- unsigned int Accum=0;
- unsigned int location;
- s16 *lut;
- short *dst;
- s16 *src;
- dst=(short *)(BufferSpace);
- src=(s16 *)(BufferSpace);
- u32 srcPtr=(AudioInBuffer/2);
- u32 dstPtr=(AudioOutBuffer/2);
- s32 temp;
- s32 accum;
-
- if (addy > (1024*1024*8))
- addy = (inst2 & 0xffffff);
-
- srcPtr -= 4;
-
- if ((Flags & 0x1) == 0) {
- for (int x=0; x < 4; x++) //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8);
- src[(srcPtr+x)^S] = ((u16 *)rsp.RDRAM)[((addy/2)+x)^S];
- Accum = *(u16 *)(rsp.RDRAM+addy+10);
- } else {
- for (int x=0; x < 4; x++)
- src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
- }
-
- for(int i=0;i < ((AudioCount+0xf)&0xFFF0)/2;i++) {
- location = (((Accum * 0x40) >> 0x10) * 8);
- //location = (Accum >> 0xa) << 0x3;
- lut = (s16 *)(((u8 *)ResampleLUT) + location);
-
- temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0])));
- accum = (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3])));
- accum += (s32)(temp >> 15);
-
- if (accum > 32767) accum = 32767;
- if (accum < -32768) accum = -32768;
-
- dst[dstPtr^S] = (s16)(accum);
- dstPtr++;
- Accum += Pitch;
- srcPtr += (Accum>>16);
- Accum&=0xffff;
- }
- for (int x=0; x < 4; x++)
- ((u16 *)rsp.RDRAM)[((addy/2)+x)^S] = src[(srcPtr+x)^S];
- *(u16 *)(rsp.RDRAM+addy+10) = (u16)Accum;
- //memcpy (RSWORK, src+srcPtr, 0x8);
-}
-
-static void DMEMMOVE2 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u32 v0, v1;
- u32 cnt;
- if ((inst2 & 0xffff)==0)
- return;
- v0 = (inst1 & 0xFFFF);
- v1 = (inst2 >> 0x10);
- //assert ((v1 & 0x3) == 0);
- //assert ((v0 & 0x3) == 0);
- u32 count = ((inst2+3) & 0xfffc);
- //v0 = (v0) & 0xfffc;
- //v1 = (v1) & 0xfffc;
-
- //memcpy (dmem+v1, dmem+v0, count-1);
- for (cnt = 0; cnt < count; cnt++) {
- *(u8 *)(BufferSpace+((cnt+v1)^S8)) = *(u8 *)(BufferSpace+((cnt+v0)^S8));
- }
-}
-
-static u32 t3, s5, s6;
-static u16 env[8];
-
-static void ENVSETUP1 (u32 inst1, u32 inst2) {
- u32 tmp;
-
- //fprintf (dfile, "ENVSETUP1: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
- t3 = inst1 & 0xFFFF;
- tmp = (inst1 >> 0x8) & 0xFF00;
- env[4] = (u16)tmp;
- tmp += t3;
- env[5] = (u16)tmp;
- s5 = inst2 >> 0x10;
- s6 = inst2 & 0xFFFF;
- //fprintf (dfile, " t3 = %X / s5 = %X / s6 = %X / env[4] = %X / env[5] = %X\n", t3, s5, s6, env[4], env[5]);
-}
-
-static void ENVSETUP2 (u32 inst1, u32 inst2) {
- u32 tmp;
-
- //fprintf (dfile, "ENVSETUP2: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
- tmp = (inst2 >> 0x10);
- env[0] = (u16)tmp;
- tmp += s5;
- env[1] = (u16)tmp;
- tmp = inst2 & 0xffff;
- env[2] = (u16)tmp;
- tmp += s6;
- env[3] = (u16)tmp;
- //fprintf (dfile, " env[0] = %X / env[1] = %X / env[2] = %X / env[3] = %X\n", env[0], env[1], env[2], env[3]);
-}
-
-static void ENVMIXER2 (u32 inst1, u32 inst2) {
- //fprintf (dfile, "ENVMIXER: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
-
- s16 *bufft6, *bufft7, *buffs0, *buffs1;
- s16 *buffs3;
- s32 count;
- u32 adder;
-
- s16 vec9, vec10;
-
- s16 v2[8];
-
- buffs3 = (s16 *)(BufferSpace + ((inst1 >> 0x0c)&0x0ff0));
- bufft6 = (s16 *)(BufferSpace + ((inst2 >> 0x14)&0x0ff0));
- bufft7 = (s16 *)(BufferSpace + ((inst2 >> 0x0c)&0x0ff0));
- buffs0 = (s16 *)(BufferSpace + ((inst2 >> 0x04)&0x0ff0));
- buffs1 = (s16 *)(BufferSpace + ((inst2 << 0x04)&0x0ff0));
-
-
- v2[0] = 0 - (s16)((inst1 & 0x2) >> 1);
- v2[1] = 0 - (s16)((inst1 & 0x1));
- v2[2] = 0 - (s16)((inst1 & 0x8) >> 1);
- v2[3] = 0 - (s16)((inst1 & 0x4) >> 1);
-
- count = (inst1 >> 8) & 0xff;
-
- if (!isMKABI) {
- s5 *= 2; s6 *= 2; t3 *= 2;
- adder = 0x10;
- } else {
- inst1 = 0;
- adder = 0x8;
- t3 = 0;
- }
-
-
- while (count > 0) {
- int temp, x;
- for (x=0; x < 0x8; x++) {
- vec9 = (s16)(((s32)buffs3[x^S] * (u32)env[0]) >> 0x10) ^ v2[0];
- vec10 = (s16)(((s32)buffs3[x^S] * (u32)env[2]) >> 0x10) ^ v2[1];
- temp = bufft6[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- bufft6[x^S] = temp;
- temp = bufft7[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- bufft7[x^S] = temp;
- vec9 = (s16)(((s32)vec9 * (u32)env[4]) >> 0x10) ^ v2[2];
- vec10 = (s16)(((s32)vec10 * (u32)env[4]) >> 0x10) ^ v2[3];
- if (inst1 & 0x10) {
- temp = buffs0[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs0[x^S] = temp;
- temp = buffs1[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs1[x^S] = temp;
- } else {
- temp = buffs0[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs0[x^S] = temp;
- temp = buffs1[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs1[x^S] = temp;
- }
- }
-
- if (!isMKABI)
- for (x=0x8; x < 0x10; x++) {
- vec9 = (s16)(((s32)buffs3[x^S] * (u32)env[1]) >> 0x10) ^ v2[0];
- vec10 = (s16)(((s32)buffs3[x^S] * (u32)env[3]) >> 0x10) ^ v2[1];
- temp = bufft6[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- bufft6[x^S] = temp;
- temp = bufft7[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- bufft7[x^S] = temp;
- vec9 = (s16)(((s32)vec9 * (u32)env[5]) >> 0x10) ^ v2[2];
- vec10 = (s16)(((s32)vec10 * (u32)env[5]) >> 0x10) ^ v2[3];
- if (inst1 & 0x10) {
- temp = buffs0[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs0[x^S] = temp;
- temp = buffs1[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs1[x^S] = temp;
- } else {
- temp = buffs0[x^S] + vec9;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs0[x^S] = temp;
- temp = buffs1[x^S] + vec10;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- buffs1[x^S] = temp;
- }
- }
- bufft6 += adder; bufft7 += adder;
- buffs0 += adder; buffs1 += adder;
- buffs3 += adder; count -= adder;
- env[0] += (u16)s5; env[1] += (u16)s5;
- env[2] += (u16)s6; env[3] += (u16)s6;
- env[4] += (u16)t3; env[5] += (u16)t3;
- }
-}
-
-static void DUPLICATE2(u32 inst1, u32 inst2) {
- unsigned short Count = (inst1 >> 16) & 0xff;
- unsigned short In = inst1&0xffff;
- unsigned short Out = (inst2>>16);
-
- unsigned short buff[64];
-
- memcpy(buff,BufferSpace+In,128);
-
- while(Count) {
- memcpy(BufferSpace+Out,buff,128);
- Out+=128;
- Count--;
- }
-}
-/*
-static void INTERL2 (u32 inst1, u32 inst2) { // Make your own...
- short Count = inst1 & 0xffff;
- unsigned short Out = inst2 & 0xffff;
- unsigned short In = (inst2 >> 16);
-
- short *src,*dst,tmp;
- src=(short *)&BufferSpace[In];
- dst=(short *)&BufferSpace[Out];
- while(Count)
- {
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- *(dst++)=*(src++);
- src++;
- Count-=8;
- }
-}
-*/
-
-static void INTERL2 (u32 inst1, u32 inst2) {
- short Count = inst1 & 0xffff;
- unsigned short Out = inst2 & 0xffff;
- unsigned short In = (inst2 >> 16);
-
- unsigned char *src,*dst/*,tmp*/;
- src=(unsigned char *)(BufferSpace);//[In];
- dst=(unsigned char *)(BufferSpace);//[Out];
- while(Count) {
- *(short *)(dst+(Out^S8)) = *(short *)(src+(In^S8));
- Out += 2;
- In += 4;
- Count--;
- }
-}
-
-static void INTERLEAVE2 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u32 inL, inR;
- u16 *outbuff;
- u16 *inSrcR;
- u16 *inSrcL;
- u16 Left, Right, Left2, Right2;
- u32 count;
- count = ((inst1 >> 12) & 0xFF0);
- if (count == 0) {
- outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
- count = AudioCount;
- } else {
- outbuff = (u16 *)((inst1&0xFFFF)+BufferSpace);
- }
-
- inR = inst2 & 0xFFFF;
- inL = (inst2 >> 16) & 0xFFFF;
-
- inSrcR = (u16 *)(BufferSpace+inR);
- inSrcL = (u16 *)(BufferSpace+inL);
-
- for (u32 x = 0; x < (count/4); x++) {
- Left=*(inSrcL++);
- Right=*(inSrcR++);
- Left2=*(inSrcL++);
- Right2=*(inSrcR++);
-
-#ifdef M64P_BIG_ENDIAN
- *(outbuff++)=Right;
- *(outbuff++)=Left;
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
-#else
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
- *(outbuff++)=Right;
- *(outbuff++)=Left;
-#endif
- }
-}
-
-static void ADDMIXER (u32 inst1, u32 inst2) {
- short Count = (inst1 >> 12) & 0x00ff0;
- u16 InBuffer = (inst2 >> 16);
- u16 OutBuffer = inst2 & 0xffff;
-
- s16 *inp, *outp;
- s32 temp;
- inp = (s16 *)(BufferSpace + InBuffer);
- outp = (s16 *)(BufferSpace + OutBuffer);
- for (int cntr = 0; cntr < Count; cntr+=2) {
- temp = *outp + *inp;
- if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
- *(outp++) = temp;
- inp++;
- }
-}
-
-static void HILOGAIN (u32 inst1, u32 inst2) {
- u16 cnt = inst1 & 0xffff;
- u16 out = (inst2 >> 16) & 0xffff;
- s16 hi = (s16)((inst1 >> 4) & 0xf000);
- u16 lo = (inst1 >> 20) & 0xf;
- s16 *src;
-
- src = (s16 *)(BufferSpace+out);
- s32 tmp, val;
-
- while(cnt) {
- val = (s32)*src;
- //tmp = ((val * (s32)hi) + ((u64)(val * lo) << 16) >> 16);
- tmp = ((val * (s32)hi) >> 16) + (u32)(val * lo);
- if ((s32)tmp > 32767) tmp = 32767;
- else if ((s32)tmp < -32768) tmp = -32768;
- *src = tmp;
- src++;
- cnt -= 2;
- }
-}
-
-static void FILTER2 (u32 inst1, u32 inst2) {
- static int cnt = 0;
- static s16 *lutt6;
- static s16 *lutt5;
- u8 *save = (rsp.RDRAM+(inst2&0xFFFFFF));
- u8 t4 = (u8)((inst1 >> 0x10) & 0xFF);
- int x;
-
- if (t4 > 1) { // Then set the cnt variable
- cnt = (inst1 & 0xFFFF);
- lutt6 = (s16 *)save;
-// memcpy (dmem+0xFE0, rsp.RDRAM+(inst2&0xFFFFFF), 0x10);
- return;
- }
-
- if (t4 == 0) {
-// memcpy (dmem+0xFB0, rsp.RDRAM+(inst2&0xFFFFFF), 0x20);
- lutt5 = (short *)(save+0x10);
- }
-
- lutt5 = (short *)(save+0x10);
-
-// lutt5 = (short *)(dmem + 0xFC0);
-// lutt6 = (short *)(dmem + 0xFE0);
- for (x = 0; x < 8; x++) {
- s32 a;
- a = (lutt5[x] + lutt6[x]) >> 1;
- lutt5[x] = lutt6[x] = (short)a;
- }
- short *inp1, *inp2;
- s32 out1[8];
- s16 outbuff[0x3c0], *outp;
- u32 inPtr = (u32)(inst1&0xffff);
- inp1 = (short *)(save);
- outp = outbuff;
- inp2 = (short *)(BufferSpace+inPtr);
- for (x = 0; x < cnt; x+=0x10) {
- out1[1] = inp1[0]*lutt6[6];
- out1[1] += inp1[3]*lutt6[7];
- out1[1] += inp1[2]*lutt6[4];
- out1[1] += inp1[5]*lutt6[5];
- out1[1] += inp1[4]*lutt6[2];
- out1[1] += inp1[7]*lutt6[3];
- out1[1] += inp1[6]*lutt6[0];
- out1[1] += inp2[1]*lutt6[1]; // 1
-
- out1[0] = inp1[3]*lutt6[6];
- out1[0] += inp1[2]*lutt6[7];
- out1[0] += inp1[5]*lutt6[4];
- out1[0] += inp1[4]*lutt6[5];
- out1[0] += inp1[7]*lutt6[2];
- out1[0] += inp1[6]*lutt6[3];
- out1[0] += inp2[1]*lutt6[0];
- out1[0] += inp2[0]*lutt6[1];
-
- out1[3] = inp1[2]*lutt6[6];
- out1[3] += inp1[5]*lutt6[7];
- out1[3] += inp1[4]*lutt6[4];
- out1[3] += inp1[7]*lutt6[5];
- out1[3] += inp1[6]*lutt6[2];
- out1[3] += inp2[1]*lutt6[3];
- out1[3] += inp2[0]*lutt6[0];
- out1[3] += inp2[3]*lutt6[1];
-
- out1[2] = inp1[5]*lutt6[6];
- out1[2] += inp1[4]*lutt6[7];
- out1[2] += inp1[7]*lutt6[4];
- out1[2] += inp1[6]*lutt6[5];
- out1[2] += inp2[1]*lutt6[2];
- out1[2] += inp2[0]*lutt6[3];
- out1[2] += inp2[3]*lutt6[0];
- out1[2] += inp2[2]*lutt6[1];
-
- out1[5] = inp1[4]*lutt6[6];
- out1[5] += inp1[7]*lutt6[7];
- out1[5] += inp1[6]*lutt6[4];
- out1[5] += inp2[1]*lutt6[5];
- out1[5] += inp2[0]*lutt6[2];
- out1[5] += inp2[3]*lutt6[3];
- out1[5] += inp2[2]*lutt6[0];
- out1[5] += inp2[5]*lutt6[1];
-
- out1[4] = inp1[7]*lutt6[6];
- out1[4] += inp1[6]*lutt6[7];
- out1[4] += inp2[1]*lutt6[4];
- out1[4] += inp2[0]*lutt6[5];
- out1[4] += inp2[3]*lutt6[2];
- out1[4] += inp2[2]*lutt6[3];
- out1[4] += inp2[5]*lutt6[0];
- out1[4] += inp2[4]*lutt6[1];
-
- out1[7] = inp1[6]*lutt6[6];
- out1[7] += inp2[1]*lutt6[7];
- out1[7] += inp2[0]*lutt6[4];
- out1[7] += inp2[3]*lutt6[5];
- out1[7] += inp2[2]*lutt6[2];
- out1[7] += inp2[5]*lutt6[3];
- out1[7] += inp2[4]*lutt6[0];
- out1[7] += inp2[7]*lutt6[1];
-
- out1[6] = inp2[1]*lutt6[6];
- out1[6] += inp2[0]*lutt6[7];
- out1[6] += inp2[3]*lutt6[4];
- out1[6] += inp2[2]*lutt6[5];
- out1[6] += inp2[5]*lutt6[2];
- out1[6] += inp2[4]*lutt6[3];
- out1[6] += inp2[7]*lutt6[0];
- out1[6] += inp2[6]*lutt6[1];
- outp[1] = /*CLAMP*/((out1[1]+0x4000) >> 0xF);
- outp[0] = /*CLAMP*/((out1[0]+0x4000) >> 0xF);
- outp[3] = /*CLAMP*/((out1[3]+0x4000) >> 0xF);
- outp[2] = /*CLAMP*/((out1[2]+0x4000) >> 0xF);
- outp[5] = /*CLAMP*/((out1[5]+0x4000) >> 0xF);
- outp[4] = /*CLAMP*/((out1[4]+0x4000) >> 0xF);
- outp[7] = /*CLAMP*/((out1[7]+0x4000) >> 0xF);
- outp[6] = /*CLAMP*/((out1[6]+0x4000) >> 0xF);
- inp1 = inp2;
- inp2 += 8;
- outp += 8;
- }
-// memcpy (rsp.RDRAM+(inst2&0xFFFFFF), dmem+0xFB0, 0x20);
- memcpy (save, inp2-8, 0x10);
- memcpy (BufferSpace+(inst1&0xffff), outbuff, cnt);
-}
-
-static void SEGMENT2 (u32 inst1, u32 inst2) {
- if (isZeldaABI) {
- FILTER2 (inst1, inst2);
- return;
- }
- if ((inst1 & 0xffffff) == 0) {
- isMKABI = true;
- //SEGMENTS[(inst2>>24)&0xf] = (inst2 & 0xffffff);
- } else {
- isMKABI = false;
- isZeldaABI = true;
- FILTER2 (inst1, inst2);
- }
-}
-
-static void UNKNOWN (u32 inst1, u32 inst2) {
-}
-/*
-void (*ABI2[0x20])(void) = {
- SPNOOP, ADPCM2, CLEARBUFF2, SPNOOP, SPNOOP, RESAMPLE2, SPNOOP, SEGMENT2,
- SETBUFF2, SPNOOP, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2,
- SPNOOP, INTERL2, ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP,
- SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP
-};*/
-
-extern "C" const acmd_callback_t ABI2[0x20] = {
- SPNOOP , ADPCM2, CLEARBUFF2, UNKNOWN, ADDMIXER, RESAMPLE2, UNKNOWN, SEGMENT2,
- SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2,
- SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP,
- HILOGAIN , SPNOOP, DUPLICATE2 , UNKNOWN , SPNOOP , SPNOOP , SPNOOP , SPNOOP
-};
-/*
-void (*ABI2[0x20])(void) = {
- SPNOOP , ADPCM2, CLEARBUFF2, SPNOOP, SPNOOP, RESAMPLE2 , SPNOOP , SEGMENT2,
- SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, SPNOOP, SETLOOP2,
- SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP,
- SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP
-};*/
-/* NOTES:
-
- FILTER/SEGMENT - Still needs to be finished up... add FILTER?
- UNKNOWWN #27 - Is this worth doing? Looks like a pain in the ass just for WaveRace64
-*/
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/ucode3.cpp b/libmupen64plus/mupen64plus-rsp-hle/src/ucode3.cpp
deleted file mode 100644
index b63fbe27c2..0000000000
--- a/libmupen64plus/mupen64plus-rsp-hle/src/ucode3.cpp
+++ /dev/null
@@ -1,834 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - ucode3.cpp *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2009 Richard Goedeken *
- * Copyright (C) 2002 Hacktarux *
- * *
- * 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
-# include
-
-extern "C" {
- #include "m64p_types.h"
- #include "hle.h"
- #include "alist_internal.h"
-}
-
-/*
-static void SPNOOP (u32 inst1, u32 inst2) {
- DebugMessage(M64MSG_ERROR, "Unknown/Unimplemented Audio Command %i in ABI 3", (int)(inst1 >> 24));
-}
-*/
-
-extern const u16 ResampleLUT [0x200];
-
-extern u32 loopval;
-
-extern s16 Env_Dry;
-extern s16 Env_Wet;
-extern s16 Vol_Left;
-extern s16 Vol_Right;
-extern s16 VolTrg_Left;
-extern s32 VolRamp_Left;
-//extern u16 VolRate_Left;
-extern s16 VolTrg_Right;
-extern s32 VolRamp_Right;
-//extern u16 VolRate_Right;
-
-
-extern short hleMixerWorkArea[256];
-extern u16 adpcmtable[0x88];
-
-extern u8 BufferSpace[0x10000];
-
-/*
-static void SETVOL3 (u32 inst1, u32 inst2) { // Swapped Rate_Left and Vol
- u8 Flags = (u8)(inst1 >> 0x10);
- if (Flags & 0x4) { // 288
- if (Flags & 0x2) { // 290
- VolTrg_Left = *(s16*)&inst1;
- VolRamp_Left = *(s32*)&inst2;
- } else {
- VolTrg_Right = *(s16*)&inst1;
- VolRamp_Right = *(s32*)&inst2;
- }
- } else {
- Vol_Left = *(s16*)&inst1;
- Env_Dry = (s16)(*(s32*)&inst2 >> 0x10);
- Env_Wet = *(s16*)&inst2;
- }
-}
-*/
-static void SETVOL3 (u32 inst1, u32 inst2) {
- u8 Flags = (u8)(inst1 >> 0x10);
- if (Flags & 0x4) { // 288
- if (Flags & 0x2) { // 290
- Vol_Left = (s16)inst1; // 0x50
- Env_Dry = (s16)(inst2 >> 0x10); // 0x4E
- Env_Wet = (s16)inst2; // 0x4C
- } else {
- VolTrg_Right = (s16)inst1; // 0x46
- //VolRamp_Right = (u16)(inst2 >> 0x10) | (s32)(s16)(inst2 << 0x10);
- VolRamp_Right = (s32)inst2; // 0x48/0x4A
- }
- } else {
- VolTrg_Left = (s16)inst1; // 0x40
- VolRamp_Left = (s32)inst2; // 0x42/0x44
- }
-}
-
-static void ENVMIXER3 (u32 inst1, u32 inst2) {
- u8 flags = (u8)((inst1 >> 16) & 0xff);
- u32 addy = (inst2 & 0xFFFFFF);
-
- short *inp=(short *)(BufferSpace+0x4F0);
- short *out=(short *)(BufferSpace+0x9D0);
- short *aux1=(short *)(BufferSpace+0xB40);
- short *aux2=(short *)(BufferSpace+0xCB0);
- short *aux3=(short *)(BufferSpace+0xE20);
- s32 MainR;
- s32 MainL;
- s32 AuxR;
- s32 AuxL;
- int i1,o1,a1,a2,a3;
- //unsigned short AuxIncRate=1;
- short zero[8];
- memset(zero,0,16);
-
- s32 LAdder, LAcc, LVol;
- s32 RAdder, RAcc, RVol;
- s16 RSig, LSig; // Most significant part of the Ramp Value
- s16 Wet, Dry;
- s16 LTrg, RTrg;
-
- Vol_Right = (s16)inst1;
-
- if (flags & A_INIT) {
- LAdder = VolRamp_Left / 8;
- LAcc = 0;
- LVol = Vol_Left;
- LSig = (s16)(VolRamp_Left >> 16);
-
- RAdder = VolRamp_Right / 8;
- RAcc = 0;
- RVol = Vol_Right;
- RSig = (s16)(VolRamp_Right >> 16);
-
- Wet = (s16)Env_Wet; Dry = (s16)Env_Dry; // Save Wet/Dry values
- LTrg = VolTrg_Left; RTrg = VolTrg_Right; // Save Current Left/Right Targets
- } else {
- memcpy((u8 *)hleMixerWorkArea, rsp.RDRAM+addy, 80);
- Wet = *(s16 *)(hleMixerWorkArea + 0); // 0-1
- Dry = *(s16 *)(hleMixerWorkArea + 2); // 2-3
- LTrg = *(s16 *)(hleMixerWorkArea + 4); // 4-5
- RTrg = *(s16 *)(hleMixerWorkArea + 6); // 6-7
- LAdder = *(s32 *)(hleMixerWorkArea + 8); // 8-9 (hleMixerWorkArea is a 16bit pointer)
- RAdder = *(s32 *)(hleMixerWorkArea + 10); // 10-11
- LAcc = *(s32 *)(hleMixerWorkArea + 12); // 12-13
- RAcc = *(s32 *)(hleMixerWorkArea + 14); // 14-15
- LVol = *(s32 *)(hleMixerWorkArea + 16); // 16-17
- RVol = *(s32 *)(hleMixerWorkArea + 18); // 18-19
- LSig = *(s16 *)(hleMixerWorkArea + 20); // 20-21
- RSig = *(s16 *)(hleMixerWorkArea + 22); // 22-23
- //u32 test = *(s32 *)(hleMixerWorkArea + 24); // 22-23
- //if (test != 0x13371337)
- }
-
-
- //if(!(flags&A_AUX)) {
- // AuxIncRate=0;
- // aux2=aux3=zero;
- //}
-
- for (int y = 0; y < (0x170/2); y++) {
-
- // Left
- LAcc += LAdder;
- LVol += (LAcc >> 16);
- LAcc &= 0xFFFF;
-
- // Right
- RAcc += RAdder;
- RVol += (RAcc >> 16);
- RAcc &= 0xFFFF;
-// ****************************************************************
- // Clamp Left
- if (LSig >= 0) { // VLT
- if (LVol > LTrg) {
- LVol = LTrg;
- }
- } else { // VGE
- if (LVol < LTrg) {
- LVol = LTrg;
- }
- }
-
- // Clamp Right
- if (RSig >= 0) { // VLT
- if (RVol > RTrg) {
- RVol = RTrg;
- }
- } else { // VGE
- if (RVol < RTrg) {
- RVol = RTrg;
- }
- }
-// ****************************************************************
- MainL = ((Dry * LVol) + 0x4000) >> 15;
- MainR = ((Dry * RVol) + 0x4000) >> 15;
-
- o1 = out [y^S];
- a1 = aux1[y^S];
- i1 = inp [y^S];
-
- o1+=((i1*MainL)+0x4000)>>15;
- a1+=((i1*MainR)+0x4000)>>15;
-
-// ****************************************************************
-
- if(o1>32767) o1=32767;
- else if(o1<-32768) o1=-32768;
-
- if(a1>32767) a1=32767;
- else if(a1<-32768) a1=-32768;
-
-// ****************************************************************
-
- out[y^S]=o1;
- aux1[y^S]=a1;
-
-// ****************************************************************
- //if (!(flags&A_AUX)) {
- a2 = aux2[y^S];
- a3 = aux3[y^S];
-
- AuxL = ((Wet * LVol) + 0x4000) >> 15;
- AuxR = ((Wet * RVol) + 0x4000) >> 15;
-
- a2+=((i1*AuxL)+0x4000)>>15;
- a3+=((i1*AuxR)+0x4000)>>15;
-
- if(a2>32767) a2=32767;
- else if(a2<-32768) a2=-32768;
-
- if(a3>32767) a3=32767;
- else if(a3<-32768) a3=-32768;
-
- aux2[y^S]=a2;
- aux3[y^S]=a3;
- }
- //}
-
- *(s16 *)(hleMixerWorkArea + 0) = Wet; // 0-1
- *(s16 *)(hleMixerWorkArea + 2) = Dry; // 2-3
- *(s16 *)(hleMixerWorkArea + 4) = LTrg; // 4-5
- *(s16 *)(hleMixerWorkArea + 6) = RTrg; // 6-7
- *(s32 *)(hleMixerWorkArea + 8) = LAdder; // 8-9 (hleMixerWorkArea is a 16bit pointer)
- *(s32 *)(hleMixerWorkArea + 10) = RAdder; // 10-11
- *(s32 *)(hleMixerWorkArea + 12) = LAcc; // 12-13
- *(s32 *)(hleMixerWorkArea + 14) = RAcc; // 14-15
- *(s32 *)(hleMixerWorkArea + 16) = LVol; // 16-17
- *(s32 *)(hleMixerWorkArea + 18) = RVol; // 18-19
- *(s16 *)(hleMixerWorkArea + 20) = LSig; // 20-21
- *(s16 *)(hleMixerWorkArea + 22) = RSig; // 22-23
- //*(u32 *)(hleMixerWorkArea + 24) = 0x13371337; // 22-23
- memcpy(rsp.RDRAM+addy, (u8 *)hleMixerWorkArea,80);
-}
-
-static void CLEARBUFF3 (u32 inst1, u32 inst2) {
- u16 addr = (u16)(inst1 & 0xffff);
- u16 count = (u16)(inst2 & 0xffff);
- memset(BufferSpace+addr+0x4f0, 0, count);
-}
-
-static void MIXER3 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u16 dmemin = (u16)(inst2 >> 0x10) + 0x4f0;
- u16 dmemout = (u16)(inst2 & 0xFFFF) + 0x4f0;
- //u8 flags = (u8)((inst1 >> 16) & 0xff);
- s32 gain = (s16)(inst1 & 0xFFFF);
- s32 temp;
-
- for (int x=0; x < 0x170; x+=2) { // I think I can do this a lot easier
- temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15;
- temp += *(s16 *)(BufferSpace+dmemout+x);
-
- if ((s32)temp > 32767)
- temp = 32767;
- if ((s32)temp < -32768)
- temp = -32768;
-
- *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
- }
-}
-
-static void LOADBUFF3 (u32 inst1, u32 inst2) {
- u32 v0;
- u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
- v0 = (inst2 & 0xfffffc);
- u32 src = (inst1&0xffc)+0x4f0;
- memcpy (BufferSpace+src, rsp.RDRAM+v0, cnt);
-}
-
-static void SAVEBUFF3 (u32 inst1, u32 inst2) {
- u32 v0;
- u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
- v0 = (inst2 & 0xfffffc);
- u32 src = (inst1&0xffc)+0x4f0;
- memcpy (rsp.RDRAM+v0, BufferSpace+src, cnt);
-}
-
-static void LOADADPCM3 (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01
- u32 v0;
- v0 = (inst2 & 0xffffff);
- //memcpy (dmem+0x3f0, rsp.RDRAM+v0, inst1&0xffff);
- //assert ((inst1&0xffff) <= 0x80);
- u16 *table = (u16 *)(rsp.RDRAM+v0);
- for (u32 x = 0; x < ((inst1&0xffff)>>0x4); x++) {
- adpcmtable[(0x0+(x<<3))^S] = table[0];
- adpcmtable[(0x1+(x<<3))^S] = table[1];
-
- adpcmtable[(0x2+(x<<3))^S] = table[2];
- adpcmtable[(0x3+(x<<3))^S] = table[3];
-
- adpcmtable[(0x4+(x<<3))^S] = table[4];
- adpcmtable[(0x5+(x<<3))^S] = table[5];
-
- adpcmtable[(0x6+(x<<3))^S] = table[6];
- adpcmtable[(0x7+(x<<3))^S] = table[7];
- table += 8;
- }
-}
-
-static void DMEMMOVE3 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- u32 v0, v1;
- u32 cnt;
- v0 = (inst1 & 0xFFFF) + 0x4f0;
- v1 = (inst2 >> 0x10) + 0x4f0;
- u32 count = ((inst2+3) & 0xfffc);
-
- //memcpy (dmem+v1, dmem+v0, count-1);
- for (cnt = 0; cnt < count; cnt++) {
- *(u8 *)(BufferSpace+((cnt+v1)^S8)) = *(u8 *)(BufferSpace+((cnt+v0)^S8));
- }
-}
-
-static void SETLOOP3 (u32 inst1, u32 inst2) {
- loopval = (inst2 & 0xffffff);
-}
-
-static void ADPCM3 (u32 inst1, u32 inst2) { // Verified to be 100% Accurate...
- unsigned char Flags=(u8)(inst2>>0x1c)&0xff;
- //unsigned short Gain=(u16)(inst1&0xffff);
- unsigned int Address=(inst1 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
- unsigned short inPtr=(inst2>>12)&0xf;
- //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2));
- short *out=(short *)(BufferSpace+(inst2&0xfff)+0x4f0);
- //unsigned char *in=(unsigned char *)(BufferSpace+((inst2>>12)&0xf)+0x4f0);
- short count=(short)((inst2 >> 16)&0xfff);
- unsigned char icode;
- unsigned char code;
- int vscale;
- unsigned short index;
- unsigned short j;
- int a[8];
- short *book1,*book2;
-
- memset(out,0,32);
-
- if(!(Flags&0x1))
- {
- if(Flags&0x2)
- {/*
- for(int i=0;i<16;i++)
- {
- out[i]=*(short *)&rsp.RDRAM[(loopval+i*2)^2];
- }*/
- memcpy(out,&rsp.RDRAM[loopval],32);
- }
- else
- {/*
- for(int i=0;i<16;i++)
- {
- out[i]=*(short *)&rsp.RDRAM[(Address+i*2)^2];
- }*/
- memcpy(out,&rsp.RDRAM[Address],32);
- }
- }
-
- int l1=out[14^S];
- int l2=out[15^S];
- int inp1[8];
- int inp2[8];
- out+=16;
- while(count>0)
- {
- // the first interation through, these values are
- // either 0 in the case of A_INIT, from a special
- // area of memory in the case of A_LOOP or just
- // the values we calculated the last time
-
- code=BufferSpace[(0x4f0+inPtr)^S8];
- index=code&0xf;
- index<<=4; // index into the adpcm code table
- book1=(short *)&adpcmtable[index];
- book2=book1+8;
- code>>=4; // upper nibble is scale
- vscale=(0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
- // so this appears to be a fractional scale based
- // on the 12 based inverse of the scale value. note
- // that this could be negative, in which case we do
- // not use the calculated vscale value... see the
- // if(code>12) check below
-
- inPtr++; // coded adpcm data lies next
- j=0;
- while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
- // which yields 8 short pcm values
- {
- icode=BufferSpace[(0x4f0+inPtr)^S8];
- inPtr++;
-
- inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
- if(code<12)
- inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
-
- inp1[j]=(s16)((icode&0xf)<<12);
- if(code<12)
- inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
- }
- j=0;
- while(j<8)
- {
- icode=BufferSpace[(0x4f0+inPtr)^S8];
- inPtr++;
-
- inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
- if(code<12)
- inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
-
- inp2[j]=(short)((icode&0xf)<<12);
- if(code<12)
- inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
- /*else
- int catchme=1;*/
- j++;
- }
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp1[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp1[0];
- a[1]+=(int)inp1[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp1[0];
- a[2]+=(int)book2[0]*inp1[1];
- a[2]+=(int)inp1[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp1[0];
- a[3]+=(int)book2[1]*inp1[1];
- a[3]+=(int)book2[0]*inp1[2];
- a[3]+=(int)inp1[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp1[0];
- a[4]+=(int)book2[2]*inp1[1];
- a[4]+=(int)book2[1]*inp1[2];
- a[4]+=(int)book2[0]*inp1[3];
- a[4]+=(int)inp1[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp1[0];
- a[5]+=(int)book2[3]*inp1[1];
- a[5]+=(int)book2[2]*inp1[2];
- a[5]+=(int)book2[1]*inp1[3];
- a[5]+=(int)book2[0]*inp1[4];
- a[5]+=(int)inp1[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp1[0];
- a[6]+=(int)book2[4]*inp1[1];
- a[6]+=(int)book2[3]*inp1[2];
- a[6]+=(int)book2[2]*inp1[3];
- a[6]+=(int)book2[1]*inp1[4];
- a[6]+=(int)book2[0]*inp1[5];
- a[6]+=(int)inp1[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp1[0];
- a[7]+=(int)book2[5]*inp1[1];
- a[7]+=(int)book2[4]*inp1[2];
- a[7]+=(int)book2[3]*inp1[3];
- a[7]+=(int)book2[2]*inp1[4];
- a[7]+=(int)book2[1]*inp1[5];
- a[7]+=(int)book2[0]*inp1[6];
- a[7]+=(int)inp1[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- //*(out+j)=a[j^S];
- }
- //out += 0x10;
- l1=a[6];
- l2=a[7];
-
- a[0]= (int)book1[0]*(int)l1;
- a[0]+=(int)book2[0]*(int)l2;
- a[0]+=(int)inp2[0]*(int)2048;
-
- a[1] =(int)book1[1]*(int)l1;
- a[1]+=(int)book2[1]*(int)l2;
- a[1]+=(int)book2[0]*inp2[0];
- a[1]+=(int)inp2[1]*(int)2048;
-
- a[2] =(int)book1[2]*(int)l1;
- a[2]+=(int)book2[2]*(int)l2;
- a[2]+=(int)book2[1]*inp2[0];
- a[2]+=(int)book2[0]*inp2[1];
- a[2]+=(int)inp2[2]*(int)2048;
-
- a[3] =(int)book1[3]*(int)l1;
- a[3]+=(int)book2[3]*(int)l2;
- a[3]+=(int)book2[2]*inp2[0];
- a[3]+=(int)book2[1]*inp2[1];
- a[3]+=(int)book2[0]*inp2[2];
- a[3]+=(int)inp2[3]*(int)2048;
-
- a[4] =(int)book1[4]*(int)l1;
- a[4]+=(int)book2[4]*(int)l2;
- a[4]+=(int)book2[3]*inp2[0];
- a[4]+=(int)book2[2]*inp2[1];
- a[4]+=(int)book2[1]*inp2[2];
- a[4]+=(int)book2[0]*inp2[3];
- a[4]+=(int)inp2[4]*(int)2048;
-
- a[5] =(int)book1[5]*(int)l1;
- a[5]+=(int)book2[5]*(int)l2;
- a[5]+=(int)book2[4]*inp2[0];
- a[5]+=(int)book2[3]*inp2[1];
- a[5]+=(int)book2[2]*inp2[2];
- a[5]+=(int)book2[1]*inp2[3];
- a[5]+=(int)book2[0]*inp2[4];
- a[5]+=(int)inp2[5]*(int)2048;
-
- a[6] =(int)book1[6]*(int)l1;
- a[6]+=(int)book2[6]*(int)l2;
- a[6]+=(int)book2[5]*inp2[0];
- a[6]+=(int)book2[4]*inp2[1];
- a[6]+=(int)book2[3]*inp2[2];
- a[6]+=(int)book2[2]*inp2[3];
- a[6]+=(int)book2[1]*inp2[4];
- a[6]+=(int)book2[0]*inp2[5];
- a[6]+=(int)inp2[6]*(int)2048;
-
- a[7] =(int)book1[7]*(int)l1;
- a[7]+=(int)book2[7]*(int)l2;
- a[7]+=(int)book2[6]*inp2[0];
- a[7]+=(int)book2[5]*inp2[1];
- a[7]+=(int)book2[4]*inp2[2];
- a[7]+=(int)book2[3]*inp2[3];
- a[7]+=(int)book2[2]*inp2[4];
- a[7]+=(int)book2[1]*inp2[5];
- a[7]+=(int)book2[0]*inp2[6];
- a[7]+=(int)inp2[7]*(int)2048;
-
- for(j=0;j<8;j++)
- {
- a[j^S]>>=11;
- if(a[j^S]>32767) a[j^S]=32767;
- else if(a[j^S]<-32768) a[j^S]=-32768;
- *(out++)=a[j^S];
- //*(out+j+0x1f8)=a[j^S];
- }
- l1=a[6];
- l2=a[7];
-
- count-=32;
- }
- out-=16;
- memcpy(&rsp.RDRAM[Address],out,32);
-}
-
-static void RESAMPLE3 (u32 inst1, u32 inst2) {
- unsigned char Flags=(u8)((inst2>>0x1e));
- unsigned int Pitch=((inst2>>0xe)&0xffff)<<1;
- u32 addy = (inst1 & 0xffffff);
- unsigned int Accum=0;
- unsigned int location;
- s16 *lut;
- short *dst;
- s16 *src;
- dst=(short *)(BufferSpace);
- src=(s16 *)(BufferSpace);
- u32 srcPtr=((((inst2>>2)&0xfff)+0x4f0)/2);
- u32 dstPtr;//=(AudioOutBuffer/2);
- s32 temp;
- s32 accum;
-
- //if (addy > (1024*1024*8))
- // addy = (inst2 & 0xffffff);
-
- srcPtr -= 4;
-
- if (inst2 & 0x3) {
- dstPtr = 0x660/2;
- } else {
- dstPtr = 0x4f0/2;
- }
-
- if ((Flags & 0x1) == 0) {
- for (int x=0; x < 4; x++) //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8);
- src[(srcPtr+x)^S] = ((u16 *)rsp.RDRAM)[((addy/2)+x)^S];
- Accum = *(u16 *)(rsp.RDRAM+addy+10);
- } else {
- for (int x=0; x < 4; x++)
- src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
- }
-
- for(int i=0;i < 0x170/2;i++) {
- location = (((Accum * 0x40) >> 0x10) * 8);
- //location = (Accum >> 0xa) << 0x3;
- lut = (s16 *)(((u8 *)ResampleLUT) + location);
-
- temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0])));
- accum = (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2])));
- accum += (s32)(temp >> 15);
-
- temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3])));
- accum += (s32)(temp >> 15);
-/* temp = ((s64)*(s16*)(src+((srcPtr+0)^S))*((s64)((s16)lut[0]<<1)));
- if (temp & 0x8000) temp = (temp^0x8000) + 0x10000;
- else temp = (temp^0x8000);
- temp = (s32)(temp >> 16);
- if ((s32)temp > 32767) temp = 32767;
- if ((s32)temp < -32768) temp = -32768;
- accum = (s32)(s16)temp;
-
- temp = ((s64)*(s16*)(src+((srcPtr+1)^S))*((s64)((s16)lut[1]<<1)));
- if (temp & 0x8000) temp = (temp^0x8000) + 0x10000;
- else temp = (temp^0x8000);
- temp = (s32)(temp >> 16);
- if ((s32)temp > 32767) temp = 32767;
- if ((s32)temp < -32768) temp = -32768;
- accum += (s32)(s16)temp;
-
- temp = ((s64)*(s16*)(src+((srcPtr+2)^S))*((s64)((s16)lut[2]<<1)));
- if (temp & 0x8000) temp = (temp^0x8000) + 0x10000;
- else temp = (temp^0x8000);
- temp = (s32)(temp >> 16);
- if ((s32)temp > 32767) temp = 32767;
- if ((s32)temp < -32768) temp = -32768;
- accum += (s32)(s16)temp;
-
- temp = ((s64)*(s16*)(src+((srcPtr+3)^S))*((s64)((s16)lut[3]<<1)));
- if (temp & 0x8000) temp = (temp^0x8000) + 0x10000;
- else temp = (temp^0x8000);
- temp = (s32)(temp >> 16);
- if ((s32)temp > 32767) temp = 32767;
- if ((s32)temp < -32768) temp = -32768;
- accum += (s32)(s16)temp;*/
-
- if (accum > 32767) accum = 32767;
- if (accum < -32768) accum = -32768;
-
- dst[dstPtr^S] = (accum);
- dstPtr++;
- Accum += Pitch;
- srcPtr += (Accum>>16);
- Accum&=0xffff;
- }
- for (int x=0; x < 4; x++)
- ((u16 *)rsp.RDRAM)[((addy/2)+x)^S] = src[(srcPtr+x)^S];
- *(u16 *)(rsp.RDRAM+addy+10) = Accum;
-}
-
-static void INTERLEAVE3 (u32 inst1, u32 inst2) { // Needs accuracy verification...
- //u32 inL, inR;
- u16 *outbuff = (u16 *)(BufferSpace + 0x4f0);//(u16 *)(AudioOutBuffer+dmem);
- u16 *inSrcR;
- u16 *inSrcL;
- u16 Left, Right, Left2, Right2;
-
- //inR = inst2 & 0xFFFF;
- //inL = (inst2 >> 16) & 0xFFFF;
-
- inSrcR = (u16 *)(BufferSpace+0xb40);
- inSrcL = (u16 *)(BufferSpace+0x9d0);
-
- for (int x = 0; x < (0x170/4); x++) {
- Left=*(inSrcL++);
- Right=*(inSrcR++);
- Left2=*(inSrcL++);
- Right2=*(inSrcR++);
-
-#ifdef M64P_BIG_ENDIAN
- *(outbuff++)=Right;
- *(outbuff++)=Left;
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
-#else
- *(outbuff++)=Right2;
- *(outbuff++)=Left2;
- *(outbuff++)=Right;
- *(outbuff++)=Left;
-#endif
-/*
- Left=*(inSrcL++);
- Right=*(inSrcR++);
- *(outbuff++)=(u16)Left;
- Left >>= 16;
- *(outbuff++)=(u16)Right;
- Right >>= 16;
- *(outbuff++)=(u16)Left;
- *(outbuff++)=(u16)Right;*/
- }
-}
-
-//static void UNKNOWN (u32 inst1, u32 inst2);
-/*
-typedef struct {
- unsigned char sync;
-
- unsigned char error_protection : 1; // 0=yes, 1=no
- unsigned char lay : 2; // 4-lay = layerI, II or III
- unsigned char version : 1; // 3=mpeg 1.0, 2=mpeg 2.5 0=mpeg 2.0
- unsigned char sync2 : 4;
-
- unsigned char extension : 1; // Unknown
- unsigned char padding : 1; // padding
- unsigned char sampling_freq : 2; // see table below
- unsigned char bitrate_index : 4; // see table below
-
- unsigned char emphasis : 2; //see table below
- unsigned char original : 1; // 0=no 1=yes
- unsigned char copyright : 1; // 0=no 1=yes
- unsigned char mode_ext : 2; // used with "joint stereo" mode
- unsigned char mode : 2; // Channel Mode
-} mp3struct;
-
-mp3struct mp3;
-FILE *mp3dat;
-*/
-
-static void WHATISTHIS (u32 inst1, u32 inst2) {
-}
-
-//static FILE *fp = fopen ("d:\\mp3info.txt", "wt");
-u32 setaddr;
-static void MP3ADDY (u32 inst1, u32 inst2) {
- setaddr = (inst2 & 0xffffff);
-}
-
-extern "C" {
- void rsp_run(void);
- void mp3setup (unsigned int inst1, unsigned int inst2, unsigned int t8);
-}
-
-extern u32 base, dmembase;
-extern "C" {
- extern char *pDMEM;
-}
-void MP3 (u32 inst1, u32 inst2);
-/*
- {
-// return;
- // Setup Registers...
- mp3setup (inst1, inst2, 0xFA0);
-
- // Setup Memory Locations...
- //u32 base = ((u32*)dmem)[0xFD0/4]; // Should be 000291A0
- memcpy (BufferSpace, dmembase+rsp.RDRAM, 0x10);
- ((u32*)BufferSpace)[0x0] = base;
- ((u32*)BufferSpace)[0x008/4] += base;
- ((u32*)BufferSpace)[0xFFC/4] = loopval;
- ((u32*)BufferSpace)[0xFF8/4] = dmembase;
-
- memcpy (imem+0x238, rsp.RDRAM+((u32*)BufferSpace)[0x008/4], 0x9C0);
- ((u32*)BufferSpace)[0xFF4/4] = setaddr;
- pDMEM = (char *)BufferSpace;
- rsp_run (void);
- dmembase = ((u32*)BufferSpace)[0xFF8/4];
- loopval = ((u32*)BufferSpace)[0xFFC/4];
-//0x1A98 SW S1, 0x0FF4 (R0)
-//0x1A9C SW S0, 0x0FF8 (R0)
-//0x1AA0 SW T7, 0x0FFC (R0)
-//0x1AA4 SW T3, 0x0FF0 (R0)
- //fprintf (fp, "mp3: inst1: %08X, inst2: %08X\n", inst1, inst2);
-}*/
-/*
-FFT = Fast Fourier Transform
-DCT = Discrete Cosine Transform
-MPEG-1 Layer 3 retains Layer 2's 1152-sample window, as well as the FFT polyphase filter for
-backward compatibility, but adds a modified DCT filter. DCT's advantages over DFTs (discrete
-Fourier transforms) include half as many multiply-accumulate operations and half the
-generated coefficients because the sinusoidal portion of the calculation is absent, and DCT
-generally involves simpler math. The finite lengths of a conventional DCTs' bandpass impulse
-responses, however, may result in block-boundary effects. MDCTs overlap the analysis blocks
-and lowpass-filter the decoded audio to remove aliases, eliminating these effects. MDCTs also
-have a higher transform coding gain than the standard DCT, and their basic functions
-correspond to better bandpass response.
-
-MPEG-1 Layer 3's DCT sub-bands are unequally sized, and correspond to the human auditory
-system's critical bands. In Layer 3 decoders must support both constant- and variable-bit-rate
-bit streams. (However, many Layer 1 and 2 decoders also handle variable bit rates). Finally,
-Layer 3 encoders Huffman-code the quantized coefficients before archiving or transmission for
-additional lossless compression. Bit streams range from 32 to 320 kbps, and 128-kbps rates
-achieve near-CD quality, an important specification to enable dual-channel ISDN
-(integrated-services-digital-network) to be the future high-bandwidth pipe to the home.
-
-*/
-static void DISABLE (u32 inst1, u32 inst2) {
- //MessageBox (NULL, "Help", "ABI 3 Command 0", MB_OK);
- //ChangeABI (5);
-}
-
-
-extern "C" const acmd_callback_t ABI3[0x10] = {
- DISABLE , ADPCM3 , CLEARBUFF3, ENVMIXER3 , LOADBUFF3, RESAMPLE3 , SAVEBUFF3, MP3,
- MP3ADDY, SETVOL3, DMEMMOVE3 , LOADADPCM3 , MIXER3 , INTERLEAVE3, WHATISTHIS , SETLOOP3
-};
-
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/ucode3mp3.cpp b/libmupen64plus/mupen64plus-rsp-hle/src/ucode3mp3.cpp
deleted file mode 100644
index 21caa33772..0000000000
--- a/libmupen64plus/mupen64plus-rsp-hle/src/ucode3mp3.cpp
+++ /dev/null
@@ -1,604 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Mupen64plus-rsp-hle - ucode3mp3.h *
- * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
- * Copyright (C) 2009 Richard Goedeken *
- * Copyright (C) 2002 Hacktarux *
- * *
- * 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
-# include
-
-extern "C" {
- #include "hle.h"
- #include "alist_internal.h"
-}
-
-static const u16 DeWindowLUT [0x420] = {
- 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
- 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
- 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
- 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
- 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
- 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
- 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
- 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
- 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
- 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
- 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
- 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
- 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
- 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
- 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
- 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
- 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
- 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
- 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
- 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
- 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
- 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
- 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
- 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
- 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
- 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
- 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
- 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
- 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
- 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
- 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
- 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
- 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
- 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
- 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
- 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
- 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
- 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
- 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
- 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
- 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
- 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
- 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
- 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
- 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
- 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
- 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
- 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
- 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
- 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
- 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
- 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
- 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
- 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
- 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
- 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
- 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
- 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
- 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
- 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
- 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
- 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
- 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
- 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
- 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
- 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
- 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
- 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
- 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
- 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
- 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
- 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
- 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
- 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
- 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
- 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
- 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
- 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
- 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
- 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
- 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
- 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0003,
- 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
- 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0004,
- 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
- 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
- 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
- 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
- 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
- 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0004,
- 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
- 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0005,
- 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
- 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0005,
- 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
- 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0006,
- 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
- 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
- 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
- 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
- 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
- 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0006,
- 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
- 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0007,
- 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
- 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
- 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
- 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
- 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
- 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0007,
- 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
- 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0008,
- 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
- 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0008,
- 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
- 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0009,
- 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
- 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x0009,
- 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
- 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x000A,
- 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
- 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000A,
- 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
- 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000B,
- 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
- 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000B,
- 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
- 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000D,
- 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
- 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x000D,
- 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
- 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x0000
-};
-
-//static u16 myVector[32][8];
-
-static u8 mp3data[0x1000];
-
-static s32 v[32];
-
-static void MP3AB0 () {
- // Part 2 - 100% Accurate
- const u16 LUT2[8] = { 0xFEC4, 0xF4FA, 0xC5E4, 0xE1C4,
- 0x1916, 0x4A50, 0xA268, 0x78AE };
- const u16 LUT3[4] = { 0xFB14, 0xD4DC, 0x31F2, 0x8E3A };
- int i;
-
- for (i = 0; i < 8; i++) {
- v[16+i] = v[0+i] + v[8+i];
- v[24+i] = ((v[0+i] - v[8+i]) * LUT2[i]) >> 0x10;
- }
-
- // Part 3: 4-wide butterflies
-
- for (i=0; i < 4; i++) {
- v[0+i] = v[16+i] + v[20+i];
- v[4+i] = ((v[16+i] - v[20+i]) * LUT3[i]) >> 0x10;
-
- v[8+i] = v[24+i] + v[28+i];
- v[12+i] = ((v[24+i] - v[28+i]) * LUT3[i]) >> 0x10;
- }
-
- // Part 4: 2-wide butterflies - 100% Accurate
-
- for (i = 0; i < 16; i+=4) {
- v[16+i] = v[0+i] + v[2+i];
- v[18+i] = ((v[0+i] - v[2+i]) * 0xEC84) >> 0x10;
-
- v[17+i] = v[1+i] + v[3+i];
- v[19+i] = ((v[1+i] - v[3+i]) * 0x61F8) >> 0x10;
- }
-}
-
-static void InnerLoop ();
-
-static u32 inPtr, outPtr;
-
-static u32 t6;// = 0x08A0; // I think these are temporary storage buffers
-static u32 t5;// = 0x0AC0;
-static u32 t4;// = (inst1 & 0x1E);
-
-void MP3 (u32 inst1, u32 inst2) {
- // Initialization Code
- u32 readPtr; // s5
- u32 writePtr; // s6
- //u32 Count = 0x0480; // s4
- u32 tmp;
- //u32 inPtr, outPtr;
-
- t6 = 0x08A0; // I think these are temporary storage buffers
- t5 = 0x0AC0;
- t4 = (inst1 & 0x1E);
-
- writePtr = inst2 & 0xFFFFFF;
- readPtr = writePtr;
- memcpy (mp3data+0xCE8, rsp.RDRAM+readPtr, 8); // Just do that for efficiency... may remove and use directly later anyway
- readPtr += 8; // This must be a header byte or whatnot
-
- for (int cnt = 0; cnt < 0x480; cnt += 0x180) {
- memcpy (mp3data+0xCF0, rsp.RDRAM+readPtr, 0x180); // DMA: 0xCF0 <- RDRAM[s5] : 0x180
- inPtr = 0xCF0; // s7
- outPtr = 0xE70; // s3
-// --------------- Inner Loop Start --------------------
- for (int cnt2 = 0; cnt2 < 0x180; cnt2 += 0x40) {
- t6 &= 0xFFE0;
- t5 &= 0xFFE0;
- t6 |= t4;
- t5 |= t4;
- InnerLoop ();
- t4 = (t4-2)&0x1E;
- tmp = t6;
- t6 = t5;
- t5 = tmp;
- //outPtr += 0x40;
- inPtr += 0x40;
- }
-// --------------- Inner Loop End --------------------
- memcpy (rsp.RDRAM+writePtr, mp3data+0xe70, 0x180);
- writePtr += 0x180;
- readPtr += 0x180;
- }
-}
-
-
-
-static void InnerLoop () {
- // Part 1: 100% Accurate
-
- int i;
- v[0] = *(s16 *)(mp3data+inPtr+(0x00^S16)); v[31] = *(s16 *)(mp3data+inPtr+(0x3E^S16)); v[0] += v[31];
- v[1] = *(s16 *)(mp3data+inPtr+(0x02^S16)); v[30] = *(s16 *)(mp3data+inPtr+(0x3C^S16)); v[1] += v[30];
- v[2] = *(s16 *)(mp3data+inPtr+(0x06^S16)); v[28] = *(s16 *)(mp3data+inPtr+(0x38^S16)); v[2] += v[28];
- v[3] = *(s16 *)(mp3data+inPtr+(0x04^S16)); v[29] = *(s16 *)(mp3data+inPtr+(0x3A^S16)); v[3] += v[29];
-
- v[4] = *(s16 *)(mp3data+inPtr+(0x0E^S16)); v[24] = *(s16 *)(mp3data+inPtr+(0x30^S16)); v[4] += v[24];
- v[5] = *(s16 *)(mp3data+inPtr+(0x0C^S16)); v[25] = *(s16 *)(mp3data+inPtr+(0x32^S16)); v[5] += v[25];
- v[6] = *(s16 *)(mp3data+inPtr+(0x08^S16)); v[27] = *(s16 *)(mp3data+inPtr+(0x36^S16)); v[6] += v[27];
- v[7] = *(s16 *)(mp3data+inPtr+(0x0A^S16)); v[26] = *(s16 *)(mp3data+inPtr+(0x34^S16)); v[7] += v[26];
-
- v[8] = *(s16 *)(mp3data+inPtr+(0x1E^S16)); v[16] = *(s16 *)(mp3data+inPtr+(0x20^S16)); v[8] += v[16];
- v[9] = *(s16 *)(mp3data+inPtr+(0x1C^S16)); v[17] = *(s16 *)(mp3data+inPtr+(0x22^S16)); v[9] += v[17];
- v[10]= *(s16 *)(mp3data+inPtr+(0x18^S16)); v[19] = *(s16 *)(mp3data+inPtr+(0x26^S16)); v[10]+= v[19];
- v[11]= *(s16 *)(mp3data+inPtr+(0x1A^S16)); v[18] = *(s16 *)(mp3data+inPtr+(0x24^S16)); v[11]+= v[18];
-
- v[12]= *(s16 *)(mp3data+inPtr+(0x10^S16)); v[23] = *(s16 *)(mp3data+inPtr+(0x2E^S16)); v[12]+= v[23];
- v[13]= *(s16 *)(mp3data+inPtr+(0x12^S16)); v[22] = *(s16 *)(mp3data+inPtr+(0x2C^S16)); v[13]+= v[22];
- v[14]= *(s16 *)(mp3data+inPtr+(0x16^S16)); v[20] = *(s16 *)(mp3data+inPtr+(0x28^S16)); v[14]+= v[20];
- v[15]= *(s16 *)(mp3data+inPtr+(0x14^S16)); v[21] = *(s16 *)(mp3data+inPtr+(0x2A^S16)); v[15]+= v[21];
-
- // Part 2-4
-
- MP3AB0 ();
-
- // Part 5 - 1-Wide Butterflies - 100% Accurate but need SSVs!!!
-
- u32 t0 = t6 + 0x100;
- u32 t1 = t6 + 0x200;
- u32 t2 = t5 + 0x100;
- u32 t3 = t5 + 0x200;
- /*RSP_GPR[0x8].W = t0;
- RSP_GPR[0x9].W = t1;
- RSP_GPR[0xA].W = t2;
- RSP_GPR[0xB].W = t3;
-
- RSP_Vect[0].DW[1] = 0xB504A57E00016A09;
- RSP_Vect[0].DW[0] = 0x0002D4130005A827;
-*/
-
- // 0x13A8
- v[1] = 0;
- v[11] = ((v[16] - v[17]) * 0xB504) >> 0x10;
-
- v[16] = -v[16] -v[17];
- v[2] = v[18] + v[19];
- // ** Store v[11] -> (T6 + 0)**
- *(s16 *)(mp3data+((t6+(short)0x0))) = (short)v[11];
-
-
- v[11] = -v[11];
- // ** Store v[16] -> (T3 + 0)**
- *(s16 *)(mp3data+((t3+(short)0x0))) = (short)v[16];
- // ** Store v[11] -> (T5 + 0)**
- *(s16 *)(mp3data+((t5+(short)0x0))) = (short)v[11];
- // 0x13E8 - Verified....
- v[2] = -v[2];
- // ** Store v[2] -> (T2 + 0)**
- *(s16 *)(mp3data+((t2+(short)0x0))) = (short)v[2];
- v[3] = (((v[18] - v[19]) * 0x16A09) >> 0x10) + v[2];
- // ** Store v[3] -> (T0 + 0)**
- *(s16 *)(mp3data+((t0+(short)0x0))) = (short)v[3];
- // 0x1400 - Verified
- v[4] = -v[20] -v[21];
- v[6] = v[22] + v[23];
- v[5] = ((v[20] - v[21]) * 0x16A09) >> 0x10;
- // ** Store v[4] -> (T3 + 0xFF80)
- *(s16 *)(mp3data+((t3+(short)0xFF80))) = (short)v[4];
- v[7] = ((v[22] - v[23]) * 0x2D413) >> 0x10;
- v[5] = v[5] - v[4];
- v[7] = v[7] - v[5];
- v[6] = v[6] + v[6];
- v[5] = v[5] - v[6];
- v[4] = -v[4] - v[6];
- // *** Store v[7] -> (T1 + 0xFF80)
- *(s16 *)(mp3data+((t1+(short)0xFF80))) = (short)v[7];
- // *** Store v[4] -> (T2 + 0xFF80)
- *(s16 *)(mp3data+((t2+(short)0xFF80))) = (short)v[4];
- // *** Store v[5] -> (T0 + 0xFF80)
- *(s16 *)(mp3data+((t0+(short)0xFF80))) = (short)v[5];
- v[8] = v[24] + v[25];
-
-
- v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
- v[2] = v[8] + v[9];
- v[11] = ((v[26] - v[27]) * 0x2D413) >> 0x10;
- v[13] = ((v[28] - v[29]) * 0x2D413) >> 0x10;
-
- v[10] = v[26] + v[27]; v[10] = v[10] + v[10];
- v[12] = v[28] + v[29]; v[12] = v[12] + v[12];
- v[14] = v[30] + v[31];
- v[3] = v[8] + v[10];
- v[14] = v[14] + v[14];
- v[13] = (v[13] - v[2]) + v[12];
- v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - (v[11] + v[2]);
- v[14] = -(v[14] + v[14]) + v[3];
- v[17] = v[13] - v[10];
- v[9] = v[9] + v[14];
- // ** Store v[9] -> (T6 + 0x40)
- *(s16 *)(mp3data+((t6+(short)0x40))) = (short)v[9];
- v[11] = v[11] - v[13];
- // ** Store v[17] -> (T0 + 0xFFC0)
- *(s16 *)(mp3data+((t0+(short)0xFFC0))) = (short)v[17];
- v[12] = v[8] - v[12];
- // ** Store v[11] -> (T0 + 0x40)
- *(s16 *)(mp3data+((t0+(short)0x40))) = (short)v[11];
- v[8] = -v[8];
- // ** Store v[15] -> (T1 + 0xFFC0)
- *(s16 *)(mp3data+((t1+(short)0xFFC0))) = (short)v[15];
- v[10] = -v[10] -v[12];
- // ** Store v[12] -> (T2 + 0x40)
- *(s16 *)(mp3data+((t2+(short)0x40))) = (short)v[12];
- // ** Store v[8] -> (T3 + 0xFFC0)
- *(s16 *)(mp3data+((t3+(short)0xFFC0))) = (short)v[8];
- // ** Store v[14] -> (T5 + 0x40)
- *(s16 *)(mp3data+((t5+(short)0x40))) = (short)v[14];
- // ** Store v[10] -> (T2 + 0xFFC0)
- *(s16 *)(mp3data+((t2+(short)0xFFC0))) = (short)v[10];
- // 0x14FC - Verified...
-
- // Part 6 - 100% Accurate
-
- v[0] = *(s16 *)(mp3data+inPtr+(0x00^S16)); v[31] = *(s16 *)(mp3data+inPtr+(0x3E^S16)); v[0] -= v[31];
- v[1] = *(s16 *)(mp3data+inPtr+(0x02^S16)); v[30] = *(s16 *)(mp3data+inPtr+(0x3C^S16)); v[1] -= v[30];
- v[2] = *(s16 *)(mp3data+inPtr+(0x06^S16)); v[28] = *(s16 *)(mp3data+inPtr+(0x38^S16)); v[2] -= v[28];
- v[3] = *(s16 *)(mp3data+inPtr+(0x04^S16)); v[29] = *(s16 *)(mp3data+inPtr+(0x3A^S16)); v[3] -= v[29];
-
- v[4] = *(s16 *)(mp3data+inPtr+(0x0E^S16)); v[24] = *(s16 *)(mp3data+inPtr+(0x30^S16)); v[4] -= v[24];
- v[5] = *(s16 *)(mp3data+inPtr+(0x0C^S16)); v[25] = *(s16 *)(mp3data+inPtr+(0x32^S16)); v[5] -= v[25];
- v[6] = *(s16 *)(mp3data+inPtr+(0x08^S16)); v[27] = *(s16 *)(mp3data+inPtr+(0x36^S16)); v[6] -= v[27];
- v[7] = *(s16 *)(mp3data+inPtr+(0x0A^S16)); v[26] = *(s16 *)(mp3data+inPtr+(0x34^S16)); v[7] -= v[26];
-
- v[8] = *(s16 *)(mp3data+inPtr+(0x1E^S16)); v[16] = *(s16 *)(mp3data+inPtr+(0x20^S16)); v[8] -= v[16];
- v[9] = *(s16 *)(mp3data+inPtr+(0x1C^S16)); v[17] = *(s16 *)(mp3data+inPtr+(0x22^S16)); v[9] -= v[17];
- v[10]= *(s16 *)(mp3data+inPtr+(0x18^S16)); v[19] = *(s16 *)(mp3data+inPtr+(0x26^S16)); v[10]-= v[19];
- v[11]= *(s16 *)(mp3data+inPtr+(0x1A^S16)); v[18] = *(s16 *)(mp3data+inPtr+(0x24^S16)); v[11]-= v[18];
-
- v[12]= *(s16 *)(mp3data+inPtr+(0x10^S16)); v[23] = *(s16 *)(mp3data+inPtr+(0x2E^S16)); v[12]-= v[23];
- v[13]= *(s16 *)(mp3data+inPtr+(0x12^S16)); v[22] = *(s16 *)(mp3data+inPtr+(0x2C^S16)); v[13]-= v[22];
- v[14]= *(s16 *)(mp3data+inPtr+(0x16^S16)); v[20] = *(s16 *)(mp3data+inPtr+(0x28^S16)); v[14]-= v[20];
- v[15]= *(s16 *)(mp3data+inPtr+(0x14^S16)); v[21] = *(s16 *)(mp3data+inPtr+(0x2A^S16)); v[15]-= v[21];
-
- //0, 1, 3, 2, 7, 6, 4, 5, 7, 6, 4, 5, 0, 1, 3, 2
- const u16 LUT6[16] = { 0xFFB2, 0xFD3A, 0xF10A, 0xF854,
- 0xBDAE, 0xCDA0, 0xE76C, 0xDB94,
- 0x1920, 0x4B20, 0xAC7C, 0x7C68,
- 0xABEC, 0x9880, 0xDAE8, 0x839C };
- for (i = 0; i < 16; i++) {
- v[0+i] = (v[0+i] * LUT6[i]) >> 0x10;
- }
- v[0] = v[0] + v[0]; v[1] = v[1] + v[1];
- v[2] = v[2] + v[2]; v[3] = v[3] + v[3]; v[4] = v[4] + v[4];
- v[5] = v[5] + v[5]; v[6] = v[6] + v[6]; v[7] = v[7] + v[7];
- v[12] = v[12] + v[12]; v[13] = v[13] + v[13]; v[15] = v[15] + v[15];
-
- MP3AB0 ();
-
- // Part 7: - 100% Accurate + SSV - Unoptimized
-
- v[0] = ( v[17] + v[16] ) >> 1;
- v[1] = ((v[17] * (int)((short)0xA57E * 2)) + (v[16] * 0xB504)) >> 0x10;
- v[2] = -v[18] -v[19];
- v[3] = ((v[18] - v[19]) * 0x16A09) >> 0x10;
- v[4] = v[20] + v[21] + v[0];
- v[5] = (((v[20] - v[21]) * 0x16A09) >> 0x10) + v[1];
- v[6] = (((v[22] + v[23]) << 1) + v[0]) - v[2];
- v[7] = (((v[22] - v[23]) * 0x2D413) >> 0x10) + v[0] + v[1] + v[3];
- // 0x16A8
- // Save v[0] -> (T3 + 0xFFE0)
- *(s16 *)(mp3data+((t3+(short)0xFFE0))) = (short)-v[0];
- v[8] = v[24] + v[25];
- v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
- v[10] = ((v[26] + v[27]) << 1) + v[8];
- v[11] = (((v[26] - v[27]) * 0x2D413) >> 0x10) + v[8] + v[9];
- v[12] = v[4] - ((v[28] + v[29]) << 1);
- // ** Store v12 -> (T2 + 0x20)
- *(s16 *)(mp3data+((t2+(short)0x20))) = (short)v[12];
- v[13] = (((v[28] - v[29]) * 0x2D413) >> 0x10) - v[12] - v[5];
- v[14] = v[30] + v[31];
- v[14] = v[14] + v[14];
- v[14] = v[14] + v[14];
- v[14] = v[6] - v[14];
- v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - v[7];
- // Store v14 -> (T5 + 0x20)
- *(s16 *)(mp3data+((t5+(short)0x20))) = (short)v[14];
- v[14] = v[14] + v[1];
- // Store v[14] -> (T6 + 0x20)
- *(s16 *)(mp3data+((t6+(short)0x20))) = (short)v[14];
- // Store v[15] -> (T1 + 0xFFE0)
- *(s16 *)(mp3data+((t1+(short)0xFFE0))) = (short)v[15];
- v[9] = v[9] + v[10];
- v[1] = v[1] + v[6];
- v[6] = v[10] - v[6];
- v[1] = v[9] - v[1];
- // Store v[6] -> (T5 + 0x60)
- *(s16 *)(mp3data+((t5+(short)0x60))) = (short)v[6];
- v[10] = v[10] + v[2];
- v[10] = v[4] - v[10];
- // Store v[10] -> (T2 + 0xFFA0)
- *(s16 *)(mp3data+((t2+(short)0xFFA0))) = (short)v[10];
- v[12] = v[2] - v[12];
- // Store v[12] -> (T2 + 0xFFE0)
- *(s16 *)(mp3data+((t2+(short)0xFFE0))) = (short)v[12];
- v[5] = v[4] + v[5];
- v[4] = v[8] - v[4];
- // Store v[4] -> (T2 + 0x60)
- *(s16 *)(mp3data+((t2+(short)0x60))) = (short)v[4];
- v[0] = v[0] - v[8];
- // Store v[0] -> (T3 + 0xFFA0)
- *(s16 *)(mp3data+((t3+(short)0xFFA0))) = (short)v[0];
- v[7] = v[7] - v[11];
- // Store v[7] -> (T1 + 0xFFA0)
- *(s16 *)(mp3data+((t1+(short)0xFFA0))) = (short)v[7];
- v[11] = v[11] - v[3];
- // Store v[1] -> (T6 + 0x60)
- *(s16 *)(mp3data+((t6+(short)0x60))) = (short)v[1];
- v[11] = v[11] - v[5];
- // Store v[11] -> (T0 + 0x60)
- *(s16 *)(mp3data+((t0+(short)0x60))) = (short)v[11];
- v[3] = v[3] - v[13];
- // Store v[3] -> (T0 + 0x20)
- *(s16 *)(mp3data+((t0+(short)0x20))) = (short)v[3];
- v[13] = v[13] + v[2];
- // Store v[13] -> (T0 + 0xFFE0)
- *(s16 *)(mp3data+((t0+(short)0xFFE0))) = (short)v[13];
- //v[2] = ;
- v[2] = (v[5] - v[2]) - v[9];
- // Store v[2] -> (T0 + 0xFFA0)
- *(s16 *)(mp3data+((t0+(short)0xFFA0))) = (short)v[2];
- // 0x7A8 - Verified...
-
- // Step 8 - Dewindowing
-
- //u64 *DW = (u64 *)&DeWindowLUT[0x10-(t4>>1)];
- u32 offset = 0x10-(t4>>1);
-
- u32 addptr = t6 & 0xFFE0;
- offset = 0x10-(t4>>1);
-
- s32 v2=0, v4=0, v6=0, v8=0;
- //s32 z2=0, z4=0, z6=0, z8=0;
-
- offset = 0x10-(t4>>1);// + x*0x40;
- int x;
- for (x = 0; x < 8; x++) {
- v2 = v4 = v6 = v8 = 0;
-
- //addptr = t1;
-
- for (i = 7; i >= 0; i--) {
- v2 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
- v4 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
- v6 += ((int)*(s16 *)(mp3data+(addptr)+0x20) * (short)DeWindowLUT[offset+0x20] + 0x4000) >> 0xF;
- v8 += ((int)*(s16 *)(mp3data+(addptr)+0x30) * (short)DeWindowLUT[offset+0x28] + 0x4000) >> 0xF;
- addptr+=2; offset++;
- }
- s32 v0 = v2 + v4;
- s32 v18 = v6 + v8;
- //Clamp(v0);
- //Clamp(v18);
- // clamp???
- *(s16 *)(mp3data+(outPtr^S16)) = v0;
- *(s16 *)(mp3data+((outPtr+2)^S16)) = v18;
- outPtr+=4;
- addptr += 0x30;
- offset += 0x38;
- }
-
- offset = 0x10-(t4>>1) + 8*0x40;
- v2 = v4 = 0;
- for (i = 0; i < 4; i++) {
- v2 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
- v2 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
- addptr+=2; offset++;
- v4 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
- v4 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
- addptr+=2; offset++;
- }
- s32 mult6 = *(s32 *)(mp3data+0xCE8);
- s32 mult4 = *(s32 *)(mp3data+0xCEC);
- if (t4 & 0x2) {
- v2 = (v2 * *(u32 *)(mp3data+0xCE8)) >> 0x10;
- *(s16 *)(mp3data+(outPtr^S16)) = v2;
- } else {
- v4 = (v4 * *(u32 *)(mp3data+0xCE8)) >> 0x10;
- *(s16 *)(mp3data+(outPtr^S16)) = v4;
- mult4 = *(u32 *)(mp3data+0xCE8);
- }
- addptr -= 0x50;
-
- for (x = 0; x < 8; x++) {
- v2 = v4 = v6 = v8 = 0;
-
- offset = (0x22F-(t4>>1) + x*0x40);
-
- for (i = 0; i < 4; i++) {
- v2 += ((int)*(s16 *)(mp3data+(addptr )+0x20) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
- v2 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x20) * (short)DeWindowLUT[offset+0x01] + 0x4000) >> 0xF;
- v4 += ((int)*(s16 *)(mp3data+(addptr )+0x30) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
- v4 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x30) * (short)DeWindowLUT[offset+0x09] + 0x4000) >> 0xF;
- v6 += ((int)*(s16 *)(mp3data+(addptr )+0x00) * (short)DeWindowLUT[offset+0x20] + 0x4000) >> 0xF;
- v6 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x00) * (short)DeWindowLUT[offset+0x21] + 0x4000) >> 0xF;
- v8 += ((int)*(s16 *)(mp3data+(addptr )+0x10) * (short)DeWindowLUT[offset+0x28] + 0x4000) >> 0xF;
- v8 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x10) * (short)DeWindowLUT[offset+0x29] + 0x4000) >> 0xF;
- addptr+=4; offset+=2;
- }
- s32 v0 = v2 + v4;
- s32 v18 = v6 + v8;
- //Clamp(v0);
- //Clamp(v18);
- // clamp???
- *(s16 *)(mp3data+((outPtr+2)^S16)) = v0;
- *(s16 *)(mp3data+((outPtr+4)^S16)) = v18;
- outPtr+=4;
- addptr -= 0x50;
- }
-
- int tmp = outPtr;
- s32 hi0 = mult6;
- s32 hi1 = mult4;
- s32 v;
-
- hi0 = (int)hi0 >> 0x10;
- hi1 = (int)hi1 >> 0x10;
- for (i = 0; i < 8; i++) {
- // v0
- v = (*(s16 *)(mp3data+((tmp-0x40)^S16)) * hi0);
- if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
- *(s16 *)((u8 *)mp3data+((tmp-0x40)^S16)) = (s16)v;
- // v17
- v = (*(s16 *)(mp3data+((tmp-0x30)^S16)) * hi0);
- if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
- *(s16 *)((u8 *)mp3data+((tmp-0x30)^S16)) = v;
- // v2
- v = (*(s16 *)(mp3data+((tmp-0x1E)^S16)) * hi1);
- if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
- *(s16 *)((u8 *)mp3data+((tmp-0x1E)^S16)) = v;
- // v4
- v = (*(s16 *)(mp3data+((tmp-0xE)^S16)) * hi1);
- if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
- *(s16 *)((u8 *)mp3data+((tmp-0xE)^S16)) = v;
- tmp += 2;
- }
-}
-
diff --git a/libmupen64plus/mupen64plus-rsp-hle/src/ucodes.h b/libmupen64plus/mupen64plus-rsp-hle/src/ucodes.h
new file mode 100644
index 0000000000..1150cf6b18
--- /dev/null
+++ b/libmupen64plus/mupen64plus-rsp-hle/src/ucodes.h
@@ -0,0 +1,152 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus-rsp-hle - ucodes.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2014 Bobby Smiles *
+ * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef UCODES_H
+#define UCODES_H
+
+#include
+
+struct hle_t;
+
+
+/* cic_x105 ucode */
+void cicx105_ucode(struct hle_t* hle);
+
+
+/* audio list ucodes - audio */
+enum { N_SEGMENTS = 16 };
+struct alist_audio_t {
+ /* segments */
+ uint32_t segments[N_SEGMENTS];
+
+ /* main buffers */
+ uint16_t in;
+ uint16_t out;
+ uint16_t count;
+
+ /* auxiliary buffers */
+ uint16_t dry_right;
+ uint16_t wet_left;
+ uint16_t wet_right;
+
+ /* gains */
+ int16_t dry;
+ int16_t wet;
+
+ /* envelopes (0:left, 1:right) */
+ int16_t vol[2];
+ int16_t target[2];
+ int32_t rate[2];
+
+ /* ADPCM loop point address */
+ uint32_t loop;
+
+ /* storage for ADPCM table and polef coefficients */
+ int16_t table[16 * 8];
+};
+
+void alist_process_audio (struct hle_t* hle);
+void alist_process_audio_ge(struct hle_t* hle);
+void alist_process_audio_bc(struct hle_t* hle);
+
+
+/* audio list ucodes - naudio */
+struct alist_naudio_t {
+ /* gains */
+ int16_t dry;
+ int16_t wet;
+
+ /* envelopes (0:left, 1:right) */
+ int16_t vol[2];
+ int16_t target[2];
+ int32_t rate[2];
+
+ /* ADPCM loop point address */
+ uint32_t loop;
+
+ /* storage for ADPCM table and polef coefficients */
+ int16_t table[16 * 8];
+};
+
+void alist_process_naudio (struct hle_t* hle);
+void alist_process_naudio_bk (struct hle_t* hle);
+void alist_process_naudio_dk (struct hle_t* hle);
+void alist_process_naudio_mp3 (struct hle_t* hle);
+void alist_process_naudio_cbfd(struct hle_t* hle);
+
+
+/* audio list ucodes - nead */
+struct alist_nead_t {
+ /* main buffers */
+ uint16_t in;
+ uint16_t out;
+ uint16_t count;
+
+ /* envmixer ramps */
+ uint16_t env_values[3];
+ uint16_t env_steps[3];
+
+ /* ADPCM loop point address */
+ uint32_t loop;
+
+ /* storage for ADPCM table and polef coefficients */
+ int16_t table[16 * 8];
+
+ /* filter audio command state */
+ uint16_t filter_count;
+ uint32_t filter_lut_address[2];
+};
+
+void alist_process_nead_mk (struct hle_t* hle);
+void alist_process_nead_sfj (struct hle_t* hle);
+void alist_process_nead_sf (struct hle_t* hle);
+void alist_process_nead_fz (struct hle_t* hle);
+void alist_process_nead_wrjb(struct hle_t* hle);
+void alist_process_nead_ys (struct hle_t* hle);
+void alist_process_nead_1080(struct hle_t* hle);
+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);
+
+
+/* musyx ucodes */
+void musyx_v1_task(struct hle_t* hle);
+void musyx_v2_task(struct hle_t* hle);
+
+
+/* jpeg ucodes */
+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
+
diff --git a/output/dll/mupen64plus-rsp-hle.dll b/output/dll/mupen64plus-rsp-hle.dll
index 777026c971..e94e85f093 100644
Binary files a/output/dll/mupen64plus-rsp-hle.dll and b/output/dll/mupen64plus-rsp-hle.dll differ