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