Updated LazyUSF

CQTexperiment
Chris Moeller 2014-03-08 18:36:59 -08:00
parent c6e4436366
commit ec40c5041c
31 changed files with 2048 additions and 1718 deletions

View File

@ -14,21 +14,22 @@
8378416E18C6E56B002C4FE5 /* alist_naudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415818C6E56B002C4FE5 /* alist_naudio.c */; };
8378416F18C6E56B002C4FE5 /* alist_nead.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415918C6E56B002C4FE5 /* alist_nead.c */; };
8378417018C6E56B002C4FE5 /* arithmetics.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378415A18C6E56B002C4FE5 /* arithmetics.h */; };
8378417118C6E56B002C4FE5 /* audio_hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415B18C6E56B002C4FE5 /* audio_hle.c */; };
8378417218C6E56B002C4FE5 /* audio_hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378415C18C6E56B002C4FE5 /* audio_hle.h */; };
8378417318C6E56B002C4FE5 /* cicx105.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415D18C6E56B002C4FE5 /* cicx105.c */; };
8378417418C6E56B002C4FE5 /* cicx105.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378415E18C6E56B002C4FE5 /* cicx105.h */; };
8378417518C6E56B002C4FE5 /* jpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378415F18C6E56B002C4FE5 /* jpeg.c */; };
8378417618C6E56B002C4FE5 /* jpeg.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378416018C6E56B002C4FE5 /* jpeg.h */; };
8378417718C6E56B002C4FE5 /* main_hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378416118C6E56B002C4FE5 /* main_hle.c */; };
8378417818C6E56B002C4FE5 /* main_hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378416218C6E56B002C4FE5 /* main_hle.h */; };
8378417918C6E56B002C4FE5 /* memory_hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378416318C6E56B002C4FE5 /* memory_hle.c */; };
8378417A18C6E56B002C4FE5 /* memory_hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378416418C6E56B002C4FE5 /* memory_hle.h */; };
8378417B18C6E56B002C4FE5 /* mp3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378416518C6E56B002C4FE5 /* mp3.c */; };
8378417C18C6E56B002C4FE5 /* musyx.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378416618C6E56B002C4FE5 /* musyx.c */; };
8378417D18C6E56B002C4FE5 /* musyx.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378416718C6E56B002C4FE5 /* musyx.h */; };
8378417E18C6E56B002C4FE5 /* plugin_hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 8378416818C6E56B002C4FE5 /* plugin_hle.c */; };
8378417F18C6E56B002C4FE5 /* plugin_hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 8378416918C6E56B002C4FE5 /* plugin_hle.h */; };
837841C018C847B2002C4FE5 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 837841B818C847B2002C4FE5 /* audio.c */; };
837841C118C847B2002C4FE5 /* audio.h in Headers */ = {isa = PBXBuildFile; fileRef = 837841B918C847B2002C4FE5 /* audio.h */; };
837841C418C847B2002C4FE5 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 837841BC18C847B2002C4FE5 /* memory.c */; };
837841C518C847B2002C4FE5 /* memory.h in Headers */ = {isa = PBXBuildFile; fileRef = 837841BD18C847B2002C4FE5 /* memory.h */; };
837841C618C847B2002C4FE5 /* plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 837841BE18C847B2002C4FE5 /* plugin.c */; };
83A2249218CAC28500FE4173 /* hle_external.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A2248E18CAC28500FE4173 /* hle_external.h */; };
83A2249318CAC28500FE4173 /* hle_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A2248F18CAC28500FE4173 /* hle_internal.h */; };
83A2249418CAC28500FE4173 /* hle.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A2249018CAC28500FE4173 /* hle.c */; };
83A2249518CAC28500FE4173 /* hle.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A2249118CAC28500FE4173 /* hle.h */; };
83C8B6AB18AF58080071B040 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B65918AF58080071B040 /* audio.c */; };
83C8B6AC18AF58080071B040 /* audio.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65A18AF58080071B040 /* audio.h */; };
83C8B6AD18AF58080071B040 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65B18AF58080071B040 /* config.h */; };
@ -119,21 +120,22 @@
8378415818C6E56B002C4FE5 /* alist_naudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist_naudio.c; sourceTree = "<group>"; };
8378415918C6E56B002C4FE5 /* alist_nead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alist_nead.c; sourceTree = "<group>"; };
8378415A18C6E56B002C4FE5 /* arithmetics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arithmetics.h; sourceTree = "<group>"; };
8378415B18C6E56B002C4FE5 /* audio_hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio_hle.c; sourceTree = "<group>"; };
8378415C18C6E56B002C4FE5 /* audio_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_hle.h; sourceTree = "<group>"; };
8378415D18C6E56B002C4FE5 /* cicx105.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cicx105.c; sourceTree = "<group>"; };
8378415E18C6E56B002C4FE5 /* cicx105.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cicx105.h; sourceTree = "<group>"; };
8378415F18C6E56B002C4FE5 /* jpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jpeg.c; sourceTree = "<group>"; };
8378416018C6E56B002C4FE5 /* jpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpeg.h; sourceTree = "<group>"; };
8378416118C6E56B002C4FE5 /* main_hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main_hle.c; sourceTree = "<group>"; };
8378416218C6E56B002C4FE5 /* main_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main_hle.h; sourceTree = "<group>"; };
8378416318C6E56B002C4FE5 /* memory_hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory_hle.c; sourceTree = "<group>"; };
8378416418C6E56B002C4FE5 /* memory_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_hle.h; sourceTree = "<group>"; };
8378416518C6E56B002C4FE5 /* mp3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mp3.c; sourceTree = "<group>"; };
8378416618C6E56B002C4FE5 /* musyx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = musyx.c; sourceTree = "<group>"; };
8378416718C6E56B002C4FE5 /* musyx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = musyx.h; sourceTree = "<group>"; };
8378416818C6E56B002C4FE5 /* plugin_hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = plugin_hle.c; sourceTree = "<group>"; };
8378416918C6E56B002C4FE5 /* plugin_hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = plugin_hle.h; sourceTree = "<group>"; };
837841B818C847B2002C4FE5 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = "<group>"; };
837841B918C847B2002C4FE5 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = "<group>"; };
837841BC18C847B2002C4FE5 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = "<group>"; };
837841BD18C847B2002C4FE5 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = "<group>"; };
837841BE18C847B2002C4FE5 /* plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = plugin.c; sourceTree = "<group>"; };
83A2248E18CAC28500FE4173 /* hle_external.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hle_external.h; sourceTree = "<group>"; };
83A2248F18CAC28500FE4173 /* hle_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hle_internal.h; sourceTree = "<group>"; };
83A2249018CAC28500FE4173 /* hle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hle.c; sourceTree = "<group>"; };
83A2249118CAC28500FE4173 /* hle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hle.h; sourceTree = "<group>"; };
83C8B62218AF57770071B040 /* lazyusf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = lazyusf.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83C8B65918AF58080071B040 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = "<group>"; };
83C8B65A18AF58080071B040 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = "<group>"; };
@ -232,6 +234,15 @@
8378415318C6E56B002C4FE5 /* rsp_hle */ = {
isa = PBXGroup;
children = (
83A2248E18CAC28500FE4173 /* hle_external.h */,
83A2248F18CAC28500FE4173 /* hle_internal.h */,
83A2249018CAC28500FE4173 /* hle.c */,
83A2249118CAC28500FE4173 /* hle.h */,
837841B818C847B2002C4FE5 /* audio.c */,
837841B918C847B2002C4FE5 /* audio.h */,
837841BC18C847B2002C4FE5 /* memory.c */,
837841BD18C847B2002C4FE5 /* memory.h */,
837841BE18C847B2002C4FE5 /* plugin.c */,
8378415418C6E56B002C4FE5 /* alist.c */,
8378415518C6E56B002C4FE5 /* alist.h */,
8378415618C6E56B002C4FE5 /* alist_audio.c */,
@ -239,21 +250,13 @@
8378415818C6E56B002C4FE5 /* alist_naudio.c */,
8378415918C6E56B002C4FE5 /* alist_nead.c */,
8378415A18C6E56B002C4FE5 /* arithmetics.h */,
8378415B18C6E56B002C4FE5 /* audio_hle.c */,
8378415C18C6E56B002C4FE5 /* audio_hle.h */,
8378415D18C6E56B002C4FE5 /* cicx105.c */,
8378415E18C6E56B002C4FE5 /* cicx105.h */,
8378415F18C6E56B002C4FE5 /* jpeg.c */,
8378416018C6E56B002C4FE5 /* jpeg.h */,
8378416118C6E56B002C4FE5 /* main_hle.c */,
8378416218C6E56B002C4FE5 /* main_hle.h */,
8378416318C6E56B002C4FE5 /* memory_hle.c */,
8378416418C6E56B002C4FE5 /* memory_hle.h */,
8378416518C6E56B002C4FE5 /* mp3.c */,
8378416618C6E56B002C4FE5 /* musyx.c */,
8378416718C6E56B002C4FE5 /* musyx.h */,
8378416818C6E56B002C4FE5 /* plugin_hle.c */,
8378416918C6E56B002C4FE5 /* plugin_hle.h */,
);
path = rsp_hle;
sourceTree = "<group>";
@ -413,10 +416,12 @@
83C8B6FA18AF58090071B040 /* usf.h in Headers */,
83C8B6AC18AF58080071B040 /* audio.h in Headers */,
8378416D18C6E56B002C4FE5 /* alist_internal.h in Headers */,
837841C118C847B2002C4FE5 /* audio.h in Headers */,
8378417618C6E56B002C4FE5 /* jpeg.h in Headers */,
83C8B6B118AF58080071B040 /* dma.h in Headers */,
83A2249518CAC28500FE4173 /* hle.h in Headers */,
83C8B6AD18AF58080071B040 /* config.h in Headers */,
8378417F18C6E56B002C4FE5 /* plugin_hle.h in Headers */,
83A2249318CAC28500FE4173 /* hle_internal.h in Headers */,
83C8B6B518AF58080071B040 /* interpreter_cpu.h in Headers */,
83C8B6B918AF58080071B040 /* main.h in Headers */,
83C8B6F418AF58090071B040 /* rsp.h in Headers */,
@ -430,16 +435,13 @@
83C8B6B718AF58080071B040 /* interpreter_ops.h in Headers */,
83C8B6B318AF58080071B040 /* exception.h in Headers */,
83C8B6AF18AF58080071B040 /* cpu.h in Headers */,
8378417818C6E56B002C4FE5 /* main_hle.h in Headers */,
83C8B6F118AF58090071B040 /* vsubc.h in Headers */,
83C8B6F018AF58090071B040 /* vsub.h in Headers */,
8378417218C6E56B002C4FE5 /* audio_hle.h in Headers */,
83C8B6E018AF58080071B040 /* vmudn.h in Headers */,
83C8B6EF18AF58090071B040 /* vsaw.h in Headers */,
83C8B6C918AF58080071B040 /* shuffle.h in Headers */,
83C8B6DD18AF58080071B040 /* vmudh.h in Headers */,
83C8B6E118AF58080071B040 /* vmulf.h in Headers */,
8378417A18C6E56B002C4FE5 /* memory_hle.h in Headers */,
83C8B6CE18AF58080071B040 /* vch.h in Headers */,
83C8B6CB18AF58080071B040 /* vadd.h in Headers */,
83C8B6D618AF58080071B040 /* vmacu.h in Headers */,
@ -456,9 +458,11 @@
83C8B6D418AF58080071B040 /* vmacf.h in Headers */,
83C8B6DC18AF58080071B040 /* vmrg.h in Headers */,
83C8B6C718AF58080071B040 /* clamp.h in Headers */,
83A2249218CAC28500FE4173 /* hle_external.h in Headers */,
83C8B6D718AF58080071B040 /* vmadh.h in Headers */,
83C8B6F318AF58090071B040 /* vxor.h in Headers */,
83C8B6EC18AF58090071B040 /* vrsq.h in Headers */,
837841C518C847B2002C4FE5 /* memory.h in Headers */,
83C8B6D018AF58080071B040 /* vcr.h in Headers */,
8378416B18C6E56B002C4FE5 /* alist.h in Headers */,
83C8B6EA18AF58090071B040 /* vrcph.h in Headers */,
@ -552,15 +556,17 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
837841C618C847B2002C4FE5 /* plugin.c in Sources */,
83C8B6F518AF58090071B040 /* tlb.c in Sources */,
83C8B6C318AF58080071B040 /* rsp.c in Sources */,
83C8B6BD18AF58080071B040 /* pif.c in Sources */,
83C8B6B418AF58080071B040 /* interpreter_cpu.c in Sources */,
8378417118C6E56B002C4FE5 /* audio_hle.c in Sources */,
837841C018C847B2002C4FE5 /* audio.c in Sources */,
8378417518C6E56B002C4FE5 /* jpeg.c in Sources */,
8378417C18C6E56B002C4FE5 /* musyx.c in Sources */,
8378417B18C6E56B002C4FE5 /* mp3.c in Sources */,
8378416F18C6E56B002C4FE5 /* alist_nead.c in Sources */,
837841C418C847B2002C4FE5 /* memory.c in Sources */,
83C8B6B618AF58080071B040 /* interpreter_ops.c in Sources */,
8378416C18C6E56B002C4FE5 /* alist_audio.c in Sources */,
83C8B6BA18AF58080071B040 /* memory.c in Sources */,
@ -569,13 +575,11 @@
8378416A18C6E56B002C4FE5 /* alist.c in Sources */,
83C8B6AE18AF58080071B040 /* cpu.c in Sources */,
83C8B6AB18AF58080071B040 /* audio.c in Sources */,
83A2249418CAC28500FE4173 /* hle.c in Sources */,
8378416E18C6E56B002C4FE5 /* alist_naudio.c in Sources */,
8378417718C6E56B002C4FE5 /* main_hle.c in Sources */,
83C8B6B218AF58080071B040 /* exception.c in Sources */,
8378417918C6E56B002C4FE5 /* memory_hle.c in Sources */,
83C8B6BF18AF58080071B040 /* registers.c in Sources */,
83C8B6F918AF58090071B040 /* usf.c in Sources */,
8378417E18C6E56B002C4FE5 /* plugin_hle.c in Sources */,
83C8B6B818AF58080071B040 /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -33,7 +33,7 @@
#include "rsp.h"
#include "../rsp_hle/main.h"
#include "../rsp_hle/hle.h"
void real_run_rsp(usf_state_t * state, uint32_t cycles)
{
@ -49,7 +49,7 @@ void real_run_rsp(usf_state_t * state, uint32_t cycles)
case 0x00000002: /* OSTask.type == M_AUDTASK */
if (state->enable_hle_audio == 0)
break;
hle_execute(state);
hle_execute(&state->hle);
SP_STATUS_REG |= 0x00000203;
if (SP_STATUS_REG & 0x00000040) /* SP_STATUS_INTR_BREAK */
{
@ -80,5 +80,30 @@ int32_t init_rsp(usf_state_t * state)
state->CR[0xD] = &DPC_BUFBUSY_REG;
state->CR[0xE] = &DPC_PIPEBUSY_REG;
state->CR[0xF] = &DPC_TMEM_REG;
hle_init(&state->hle,
state->N64MEM,
state->DMEM,
state->IMEM,
&MI_INTR_REG,
&SP_MEM_ADDR_REG,
&SP_DRAM_ADDR_REG,
&SP_RD_LEN_REG,
&SP_WR_LEN_REG,
&SP_STATUS_REG,
&SP_DMA_FULL_REG,
&SP_DMA_BUSY_REG,
&SP_PC_REG,
&SP_SEMAPHORE_REG,
&DPC_START_REG,
&DPC_END_REG,
&DPC_CURRENT_REG,
&DPC_STATUS_REG,
&DPC_CLOCK_REG,
&DPC_BUFBUSY_REG,
&DPC_PIPEBUSY_REG,
&DPC_TMEM_REG,
state);
return 0;
}

View File

@ -15,7 +15,7 @@
#define _RSP_H_
#ifdef _MSC_VER
#define INLINE __inline
#define INLINE __forceinline
#define NOINLINE __declspec(noinline)
#define ALIGNED _declspec(align(16))
#else
@ -42,7 +42,7 @@ typedef unsigned char byte;
typedef uint32_t RCPREG;
#endif
NOINLINE void message(usf_state_t * state, const char* body, int priority)
NOINLINE static void message(usf_state_t * state, const char* body, int priority)
{
(void)body;
(void)priority;
@ -55,7 +55,7 @@ NOINLINE void message(usf_state_t * state, const char* body, int priority)
*/
#define CHARACTERS_PER_LINE (80)
/* typical standard DOS text file limit per line */
NOINLINE void update_conf(const char* source)
NOINLINE static void update_conf(const char* source)
{
(void)source;
}
@ -68,7 +68,7 @@ extern void step_SP_commands(usf_state_t * state, int PC, uint32_t inst);
#include "vu/vu.h"
/* Allocate the RSP CPU loop to its own functional space. */
NOINLINE extern void run_task(usf_state_t * state);
NOINLINE static void run_task(usf_state_t * state);
#include "execute.h"
#ifdef SP_EXECUTE_LOG

View File

@ -44,7 +44,7 @@ NOINLINE static void res_S(usf_state_t * state)
#define SLOT_OFF (BASE_OFF + 0x000)
#define LINK_OFF (BASE_OFF + 0x004)
void set_PC(usf_state_t * state, int address)
static void set_PC(usf_state_t * state, int address)
{
state->temp_PC = 0x04001000 + (address & 0xFFC);
#ifndef EMULATE_STATIC_PC
@ -72,11 +72,11 @@ void set_PC(usf_state_t * state, int address)
#define WES(address) ((address) ^ ((ENDIAN) & 00))
#define SR_B(s, i) (*(byte *)(((byte *)(state->SR + s)) + BES(i)))
#define SR_S(s, i) (*(short *)(((byte *)(state->SR + s)) + HES(i)))
#define SE(x, b) (-(x & (1 << b)) | (x & ~(~0 << b)))
#define SE(x, b) (-((signed int)x & (1 << b)) | (x & ~(~0 << b)))
#define ZE(x, b) (+(x & (1 << b)) | (x & ~(~0 << b)))
extern void ULW(usf_state_t *, int rd, uint32_t addr);
extern void USW(usf_state_t *, int rs, uint32_t addr);
static void ULW(usf_state_t *, int rd, uint32_t addr);
static void USW(usf_state_t *, int rs, uint32_t addr);
/*
* All other behaviors defined below this point in the file are specific to
@ -320,21 +320,21 @@ void SP_DMA_WRITE(usf_state_t * state)
*/
#define VR_S(vt,element) (*(short *)((byte *)(state->VR[vt]) + element))
extern unsigned short get_VCO(usf_state_t * state);
extern unsigned short get_VCC(usf_state_t * state);
extern unsigned char get_VCE(usf_state_t * state);
extern void set_VCO(usf_state_t * state, unsigned short VCO);
extern void set_VCC(usf_state_t * state, unsigned short VCC);
extern void set_VCE(usf_state_t * state, unsigned char VCE);
static unsigned short get_VCO(usf_state_t * state);
static unsigned short get_VCC(usf_state_t * state);
static unsigned char get_VCE(usf_state_t * state);
static void set_VCO(usf_state_t * state, unsigned short VCO);
static void set_VCC(usf_state_t * state, unsigned short VCC);
static void set_VCE(usf_state_t * state, unsigned char VCE);
unsigned short rwR_VCE(usf_state_t * state)
static unsigned short rwR_VCE(usf_state_t * state)
{ /* never saw a game try to read VCE out to a scalar GPR yet */
register unsigned short ret_slot;
ret_slot = 0x00 | (unsigned short)get_VCE(state);
return (ret_slot);
}
void rwW_VCE(usf_state_t * state, unsigned short VCE)
static void rwW_VCE(usf_state_t * state, unsigned short VCE)
{ /* never saw a game try to write VCE using a scalar GPR yet */
register int i;

View File

@ -21,19 +21,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include <string.h>
#include "../usf.h"
#include "alist_internal.h"
#include "arithmetics.h"
#include "audio.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "plugin.h"
#include "../usf_internal.h"
struct ramp_t
{
@ -50,9 +51,9 @@ static void swap(int16_t **a, int16_t **b)
*a = tmp;
}
static int16_t* sample(usf_state_t * state, unsigned pos)
static int16_t* sample(struct hle_t* hle, unsigned pos)
{
return (int16_t*)state->BufferSpace + (pos ^ S);
return (int16_t*)hle->alist_buffer + (pos ^ S);
}
static void sample_mix(int16_t* dst, int16_t src, int16_t gain)
@ -70,11 +71,13 @@ static void alist_envmix_mix(size_t n, int16_t** dst, const int16_t* gains, int1
static int16_t ramp_step(struct ramp_t* ramp)
{
bool target_reached;
ramp->value += ramp->step;
bool target_reached = (ramp->step <= 0)
? (ramp->value <= ramp->target)
: (ramp->value >= ramp->target);
target_reached = (ramp->step <= 0)
? (ramp->value <= ramp->target)
: (ramp->value >= ramp->target);
if (target_reached)
{
@ -82,17 +85,17 @@ static int16_t ramp_step(struct ramp_t* ramp)
ramp->step = 0;
}
return (ramp->value >> 16);
return (int16_t)(ramp->value >> 16);
}
/* global functions */
void alist_process(usf_state_t* state, const acmd_callback_t abi[], unsigned int abi_size)
void alist_process(struct hle_t* hle, const acmd_callback_t abi[], unsigned int abi_size)
{
uint32_t w1, w2;
unsigned int acmd;
const uint32_t *alist = dram_u32(state, *dmem_u32(state, TASK_DATA_PTR));
const uint32_t *const alist_end = alist + (*dmem_u32(state, TASK_DATA_SIZE) >> 2);
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++);
@ -101,96 +104,96 @@ void alist_process(usf_state_t* state, const acmd_callback_t abi[], unsigned int
acmd = (w1 >> 24) & 0x7f;
if (acmd < abi_size)
(*abi[acmd])(state, w1, w2);
(*abi[acmd])(hle, w1, w2);
else
DebugMessage(state, M64MSG_WARNING, "Invalid ABI command %u", acmd);
HleWarnMessage(hle->user_defined, "Invalid ABI command %u", acmd);
}
}
uint32_t alist_get_address(usf_state_t* state, uint32_t so, const uint32_t *segments, size_t n)
uint32_t alist_get_address(struct hle_t* hle, uint32_t so, const uint32_t *segments, size_t n)
{
uint8_t segment = (so >> 24);
uint32_t offset = (so & 0xffffff);
if (segment >= n) {
DebugMessage(state, M64MSG_WARNING, "Invalid segment %u", segment);
HleWarnMessage(hle->user_defined, "Invalid segment %u", segment);
return offset;
}
return segments[segment] + offset;
}
void alist_set_address(usf_state_t* state, uint32_t so, uint32_t *segments, size_t n)
void alist_set_address(struct hle_t* hle, uint32_t so, uint32_t *segments, size_t n)
{
uint8_t segment = (so >> 24);
uint32_t offset = (so & 0xffffff);
if (segment >= n) {
DebugMessage(state, M64MSG_WARNING, "Invalid segment %u", segment);
HleWarnMessage(hle->user_defined, "Invalid segment %u", segment);
return;
}
segments[segment] = offset;
}
void alist_clear(usf_state_t* state, uint16_t dmem, uint16_t count)
void alist_clear(struct hle_t* hle, uint16_t dmem, uint16_t count)
{
while(count != 0) {
state->BufferSpace[(dmem++)^S8] = 0;
hle->alist_buffer[(dmem++)^S8] = 0;
--count;
}
}
void alist_load(usf_state_t* state, uint16_t dmem, uint32_t address, uint16_t 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(state->BufferSpace + dmem, state->N64MEM + address, count);
memcpy(hle->alist_buffer + dmem, hle->dram + address, count);
}
void alist_save(usf_state_t* state, 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)
{
/* enforce DMA alignment constraints */
dmem &= ~3;
address &= ~7;
count = align(count, 8);
memcpy(state->N64MEM + address, state->BufferSpace + dmem, count);
memcpy(hle->dram + address, hle->alist_buffer + dmem, count);
}
void alist_move(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count)
void alist_move(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count)
{
while (count != 0) {
state->BufferSpace[(dmemo++)^S8] = state->BufferSpace[(dmemi++)^S8];
hle->alist_buffer[(dmemo++)^S8] = hle->alist_buffer[(dmemi++)^S8];
--count;
}
}
void alist_copy_every_other_sample(usf_state_t* state, 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)
{
while (count != 0) {
*(uint16_t*)(state->BufferSpace + (dmemo^S8)) = *(uint16_t*)(state->BufferSpace + (dmemi^S8));
*(uint16_t*)(hle->alist_buffer + (dmemo^S8)) = *(uint16_t*)(hle->alist_buffer + (dmemi^S8));
dmemo += 2;
dmemi += 4;
--count;
}
}
void alist_repeat64(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint8_t count)
void alist_repeat64(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint8_t count)
{
uint16_t buffer[64];
memcpy(buffer, state->BufferSpace + dmemi, 128);
memcpy(buffer, hle->alist_buffer + dmemi, 128);
while(count != 0) {
memcpy(state->BufferSpace + dmemo, buffer, 128);
memcpy(hle->alist_buffer + dmemo, buffer, 128);
dmemo += 128;
--count;
}
}
void alist_copy_blocks(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t block_size, uint8_t 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;
@ -200,7 +203,7 @@ void alist_copy_blocks(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint1
do
{
memcpy(state->BufferSpace + dmemo, state->BufferSpace + dmemi, 0x20);
memcpy(hle->alist_buffer + dmemo, hle->alist_buffer + dmemi, 0x20);
bytes_left -= 0x20;
dmemi += 0x20;
@ -212,11 +215,11 @@ void alist_copy_blocks(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint1
} while(block_left > 0);
}
void alist_interleave(usf_state_t* state, uint16_t dmemo, uint16_t left, uint16_t right, uint16_t count)
void alist_interleave(struct hle_t* hle, uint16_t dmemo, uint16_t left, uint16_t right, uint16_t count)
{
uint16_t *dst = (uint16_t*)(state->BufferSpace + dmemo);
const uint16_t *srcL = (uint16_t*)(state->BufferSpace + left);
const uint16_t *srcR = (uint16_t*)(state->BufferSpace + right);
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;
@ -243,7 +246,7 @@ void alist_interleave(usf_state_t* state, uint16_t dmemo, uint16_t left, uint16_
void alist_envmix_exp(
usf_state_t* state,
struct hle_t* hle,
bool init,
bool aux,
uint16_t dmem_dl, uint16_t dmem_dr,
@ -257,11 +260,11 @@ void alist_envmix_exp(
{
size_t n = (aux) ? 4 : 2;
const int16_t* const in = (int16_t*)(state->BufferSpace + dmemi);
int16_t* const dl = (int16_t*)(state->BufferSpace + dmem_dl);
int16_t* const dr = (int16_t*)(state->BufferSpace + dmem_dr);
int16_t* const wl = (int16_t*)(state->BufferSpace + dmem_wl);
int16_t* const wr = (int16_t*)(state->BufferSpace + dmem_wr);
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];
@ -281,7 +284,7 @@ void alist_envmix_exp(
exp_seq[0] = (vol[0] * rate[0]);
exp_seq[1] = (vol[1] * rate[1]);
} else {
memcpy((uint8_t *)save_buffer, (state->N64MEM + address), 80);
memcpy((uint8_t *)save_buffer, (hle->dram + address), 80);
wet = *(int16_t *)(save_buffer + 0); /* 0-1 */
dry = *(int16_t *)(save_buffer + 2); /* 2-3 */
ramps[0].target = *(int32_t *)(save_buffer + 4); /* 4-5 */
@ -335,19 +338,19 @@ void alist_envmix_exp(
*(int16_t *)(save_buffer + 0) = wet; /* 0-1 */
*(int16_t *)(save_buffer + 2) = dry; /* 2-3 */
*(int32_t *)(save_buffer + 4) = ramps[0].target; /* 4-5 */
*(int32_t *)(save_buffer + 6) = ramps[1].target; /* 6-7 */
*(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) = ramps[0].value; /* 12-13 */
*(int32_t *)(save_buffer + 18) = ramps[1].value; /* 14-15 */
memcpy(state->N64MEM + address, (uint8_t *)save_buffer, 80);
*(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(
usf_state_t* state,
struct hle_t* hle,
bool init,
uint16_t dmem_dl, uint16_t dmem_dr,
uint16_t dmem_wl, uint16_t dmem_wr,
@ -362,11 +365,11 @@ void alist_envmix_lin(
struct ramp_t ramps[2];
int16_t save_buffer[40];
const int16_t * const in = (int16_t*)(state->BufferSpace + dmemi);
int16_t* const dl = (int16_t*)(state->BufferSpace + dmem_dl);
int16_t* const dr = (int16_t*)(state->BufferSpace + dmem_dr);
int16_t* const wl = (int16_t*)(state->BufferSpace + dmem_wl);
int16_t* const wr = (int16_t*)(state->BufferSpace + dmem_wr);
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);
if (init) {
ramps[0].step = rate[0] / 8;
@ -377,7 +380,7 @@ void alist_envmix_lin(
ramps[1].target = (target[1] << 16);
}
else {
memcpy((uint8_t *)save_buffer, state->N64MEM + address, 80);
memcpy((uint8_t *)save_buffer, hle->dram + address, 80);
wet = *(int16_t *)(save_buffer + 0); /* 0-1 */
dry = *(int16_t *)(save_buffer + 2); /* 2-3 */
ramps[0].target = *(int16_t *)(save_buffer + 4) << 16; /* 4-5 */
@ -410,17 +413,17 @@ void alist_envmix_lin(
*(int16_t *)(save_buffer + 0) = wet; /* 0-1 */
*(int16_t *)(save_buffer + 2) = dry; /* 2-3 */
*(int16_t *)(save_buffer + 4) = ramps[0].target >> 16; /* 4-5 */
*(int16_t *)(save_buffer + 6) = ramps[1].target >> 16; /* 6-7 */
*(int32_t *)(save_buffer + 8) = ramps[0].step; /* 8-9 (save_buffer is a 16bit pointer) */
*(int32_t *)(save_buffer + 10) = ramps[1].step; /* 10-11 */
*(int32_t *)(save_buffer + 16) = ramps[0].value; /* 16-17 */
*(int32_t *)(save_buffer + 18) = ramps[1].value; /* 18-19 */
memcpy(state->N64MEM + address, (uint8_t *)save_buffer, 80);
*(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(
usf_state_t* state,
struct hle_t* hle,
bool swap_wet_LR,
uint16_t dmem_dl,
uint16_t dmem_dr,
@ -432,15 +435,15 @@ void alist_envmix_nead(
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);
int16_t *in = (int16_t*)(state->BufferSpace + dmemi);
int16_t *dl = (int16_t*)(state->BufferSpace + dmem_dl);
int16_t *dr = (int16_t*)(state->BufferSpace + dmem_dr);
int16_t *wl = (int16_t*)(state->BufferSpace + dmem_wl);
int16_t *wr = (int16_t*)(state->BufferSpace + dmem_wr);
if (swap_wet_LR)
swap(&wl, &wr);
@ -472,10 +475,10 @@ void alist_envmix_nead(
}
void alist_mix(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t gain)
void alist_mix(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t gain)
{
int16_t *dst = (int16_t*)(state->BufferSpace + dmemo);
const int16_t *src = (int16_t*)(state->BufferSpace + dmemi);
int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
const int16_t *src = (int16_t*)(hle->alist_buffer + dmemi);
count >>= 1;
@ -488,9 +491,9 @@ void alist_mix(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t coun
}
}
void alist_multQ44(usf_state_t* state, uint16_t dmem, uint16_t count, int8_t gain)
void alist_multQ44(struct hle_t* hle, uint16_t dmem, uint16_t count, int8_t gain)
{
int16_t *dst = (int16_t*)(state->BufferSpace + dmem);
int16_t *dst = (int16_t*)(hle->alist_buffer + dmem);
count >>= 1;
@ -502,10 +505,10 @@ void alist_multQ44(usf_state_t* state, uint16_t dmem, uint16_t count, int8_t gai
}
}
void alist_add(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count)
void alist_add(struct hle_t* hle, uint16_t dmemo, uint16_t dmemi, uint16_t count)
{
int16_t *dst = (int16_t*)(state->BufferSpace + dmemo);
const int16_t *src = (int16_t*)(state->BufferSpace + dmemi);
int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
const int16_t *src = (int16_t*)(hle->alist_buffer + dmemi);
count >>= 1;
@ -518,38 +521,38 @@ void alist_add(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t coun
}
}
static void alist_resample_reset(usf_state_t* state, uint16_t pos, uint32_t* pitch_accu)
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(state, pos + k) = 0;
*sample(hle, pos + k) = 0;
*pitch_accu = 0;
}
static void alist_resample_load(usf_state_t* state, uint32_t address, uint16_t pos, uint32_t* pitch_accu)
static void alist_resample_load(struct hle_t* hle, uint32_t address, uint16_t pos, uint32_t* pitch_accu)
{
*sample(state, pos + 0) = *dram_u16(state, address + 0);
*sample(state, pos + 1) = *dram_u16(state, address + 2);
*sample(state, pos + 2) = *dram_u16(state, address + 4);
*sample(state, pos + 3) = *dram_u16(state, address + 6);
*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(state, address + 8);
*pitch_accu = *dram_u16(hle, address + 8);
}
static void alist_resample_save(usf_state_t* state, uint32_t address, uint16_t pos, uint32_t pitch_accu)
static void alist_resample_save(struct hle_t* hle, uint32_t address, uint16_t pos, uint32_t pitch_accu)
{
*dram_u16(state, address + 0) = *sample(state, pos + 0);
*dram_u16(state, address + 2) = *sample(state, pos + 1);
*dram_u16(state, address + 4) = *sample(state, pos + 2);
*dram_u16(state, address + 6) = *sample(state, pos + 3);
*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(state, address + 8) = pitch_accu;
*dram_u16(hle, address + 8) = pitch_accu;
}
void alist_resample(
usf_state_t* state,
struct hle_t* hle,
bool init,
bool flag2,
uint16_t dmemo,
@ -566,21 +569,21 @@ void alist_resample(
ipos -= 4;
if (flag2)
DebugMessage(state, M64MSG_WARNING, "alist_resample: flag2 is not implemented");
HleWarnMessage(hle->user_defined, "alist_resample: flag2 is not implemented");
if (init)
alist_resample_reset(state, ipos, &pitch_accu);
alist_resample_reset(hle, ipos, &pitch_accu);
else
alist_resample_load(state, address, ipos, &pitch_accu);
alist_resample_load(hle, address, ipos, &pitch_accu);
while (count != 0) {
const int16_t* lut = RESAMPLE_LUT + ((pitch_accu & 0xfc00) >> 8);
*sample(state, opos++) = clamp_s16(
((*sample(state, ipos ) * lut[0]) >> 15) +
((*sample(state, ipos + 1) * lut[1]) >> 15) +
((*sample(state, ipos + 2) * lut[2]) >> 15) +
((*sample(state, ipos + 3) * lut[3]) >> 15));
*sample(hle, opos++) = clamp_s16(
((*sample(hle, ipos ) * lut[0]) >> 15) +
((*sample(hle, ipos + 1) * lut[1]) >> 15) +
((*sample(hle, ipos + 2) * lut[2]) >> 15) +
((*sample(hle, ipos + 3) * lut[3]) >> 15));
pitch_accu += pitch;
ipos += (pitch_accu >> 16);
@ -588,11 +591,11 @@ void alist_resample(
--count;
}
alist_resample_save(state, address, ipos, pitch_accu);
alist_resample_save(hle, address, ipos, pitch_accu);
}
void alist_resample_zoh(
usf_state_t* state,
struct hle_t* hle,
uint16_t dmemo,
uint16_t dmemi,
uint16_t count,
@ -605,7 +608,7 @@ void alist_resample_zoh(
while(count != 0) {
*sample(state, opos++) = *sample(state, ipos);
*sample(hle, opos++) = *sample(hle, ipos);
pitch_accu += pitch;
ipos += (pitch_accu >> 16);
@ -614,15 +617,17 @@ void alist_resample_zoh(
}
}
typedef unsigned int (*adpcm_predict_frame_t)(usf_state_t* state, int16_t* dst, uint16_t dmemi, unsigned char scale);
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(usf_state_t* state, 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 = state->BufferSpace[(dmemi++)^S8];
uint8_t byte = hle->alist_buffer[(dmemi++)^S8];
*(dst++) = adpcm_predict_sample(byte, 0xf0, 8, rshift);
*(dst++) = adpcm_predict_sample(byte, 0x0f, 12, rshift);
@ -631,13 +636,14 @@ static unsigned int adpcm_predict_frame_4bits(usf_state_t* state, int16_t* dst,
return 8;
}
static unsigned int adpcm_predict_frame_2bits(usf_state_t* state, int16_t* dst, uint16_t dmemi, unsigned char scale)
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 = state->BufferSpace[(dmemi++)^S8];
uint8_t byte = hle->alist_buffer[(dmemi++)^S8];
*(dst++) = adpcm_predict_sample(byte, 0xc0, 8, rshift);
*(dst++) = adpcm_predict_sample(byte, 0x30, 10, rshift);
@ -649,7 +655,7 @@ static unsigned int adpcm_predict_frame_2bits(usf_state_t* state, int16_t* dst,
}
void alist_adpcm(
usf_state_t* state,
struct hle_t* hle,
bool init,
bool loop,
bool two_bit_per_sample,
@ -660,55 +666,60 @@ void alist_adpcm(
uint32_t loop_address,
uint32_t last_frame_address)
{
assert((count & 0x1f) == 0);
int16_t last_frame[16];
size_t i;
if (init)
memset(last_frame, 0, 16*sizeof(last_frame[0]));
else
dram_load_u16(state, (uint16_t*)last_frame, (loop) ? loop_address : last_frame_address, 16);
for(i = 0; i < 16; ++i, dmemo += 2)
*(int16_t*)(state->BufferSpace + (dmemo ^ S16)) = last_frame[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)
*(int16_t*)(hle->alist_buffer + (dmemo ^ S16)) = last_frame[i];
while (count != 0) {
int16_t frame[16];
uint8_t code = state->BufferSpace[(dmemi++)^S8];
uint8_t code = hle->alist_buffer[(dmemi++)^S8];
unsigned char scale = (code & 0xf0) >> 4;
const int16_t* const cb_entry = codebook + ((code & 0xf) << 4);
dmemi += predict_frame(state, frame, dmemi, scale);
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)
*(int16_t*)(state->BufferSpace + (dmemo ^ S16)) = last_frame[i];
*(int16_t*)(hle->alist_buffer + (dmemo ^ S16)) = last_frame[i];
count -= 32;
}
dram_store_u16(state, (uint16_t*)last_frame, last_frame_address, 16);
dram_store_u16(hle, (uint16_t*)last_frame, last_frame_address, 16);
}
void alist_filter(usf_state_t* state, uint16_t dmem, uint16_t count, uint32_t address, const uint32_t* lut_address)
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*)(state->N64MEM + lut_address[0]);
int16_t* const lutt5 = (int16_t*)(state->N64MEM + lut_address[1]);
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*)(state->N64MEM + address);
int16_t* in2 = (int16_t*)(state->BufferSpace + dmem);
int16_t* in1 = (int16_t*)(hle->dram + address);
int16_t* in2 = (int16_t*)(hle->alist_buffer + dmem);
for (x = 0; x < 8; ++x) {
@ -804,12 +815,12 @@ void alist_filter(usf_state_t* state, uint16_t dmem, uint16_t count, uint32_t ad
outp += 8;
}
memcpy(state->N64MEM + address, in2 - 8, 16);
memcpy(state->BufferSpace + dmem, outbuff, count);
memcpy(hle->dram + address, in2 - 8, 16);
memcpy(hle->alist_buffer + dmem, outbuff, count);
}
void alist_polef(
usf_state_t* state,
struct hle_t* hle,
bool init,
uint16_t dmemo,
uint16_t dmemi,
@ -818,7 +829,7 @@ void alist_polef(
int16_t* table,
uint32_t address)
{
int16_t *dst = (int16_t*)(state->BufferSpace + dmemo);
int16_t *dst = (int16_t*)(hle->alist_buffer + dmemo);
const int16_t* const h1 = table;
int16_t* const h2 = table + 8;
@ -834,8 +845,8 @@ void alist_polef(
l2 = 0;
}
else {
l1 = *dram_u16(state, address + 4);
l2 = *dram_u16(state, address + 6);
l1 = *dram_u16(hle, address + 4);
l2 = *dram_u16(hle, address + 6);
}
for(i = 0; i < 8; ++i) {
@ -848,7 +859,7 @@ void alist_polef(
int16_t frame[8];
for(i = 0; i < 8; ++i, dmemi += 2) {
frame[i] = *(int16_t*)(state->BufferSpace + (dmemi ^ S16));
frame[i] = *(int16_t*)(hle->alist_buffer + (dmemi ^ S16));
}
for(i = 0; i < 8; ++i) {
@ -864,5 +875,5 @@ void alist_polef(
count -= 16;
} while (count != 0);
dram_store_u16(state, (uint16_t*)(dst - 4), address, 4);
dram_store_u16(hle, (uint16_t*)(dst - 4), address, 4);
}

View File

@ -22,25 +22,104 @@
#ifndef ALIST_H
#define ALIST_H
void alist_process_audio(usf_state_t* state);
void alist_process_audio_ge(usf_state_t* state);
void alist_process_audio_bc(usf_state_t* state);
void alist_process_nead_mk(usf_state_t* state);
void alist_process_nead_sfj(usf_state_t* state);
void alist_process_nead_sf(usf_state_t* state);
void alist_process_nead_fz(usf_state_t* state);
void alist_process_nead_wrjb(usf_state_t* state);
void alist_process_nead_ys(usf_state_t* state);
void alist_process_nead_1080(usf_state_t* state);
void alist_process_nead_oot(usf_state_t* state);
void alist_process_nead_mm(usf_state_t* state);
void alist_process_nead_mmb(usf_state_t* state);
void alist_process_nead_ac(usf_state_t* state);
void alist_process_naudio(usf_state_t* state);
void alist_process_naudio_bk(usf_state_t* state);
void alist_process_naudio_dk(usf_state_t* state);
void alist_process_naudio_mp3(usf_state_t* state);
void alist_process_naudio_cbfd(usf_state_t* state);
#include <stdint.h>
enum { N_SEGMENTS = 16 };
/* alist_audio state */
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];
};
/* alist_naudio state */
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];
};
/* alist_nead state */
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];
};
struct hle_t;
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);
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_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);
#endif

View File

@ -21,41 +21,42 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include <string.h>
#include "../usf.h"
#include "alist_internal.h"
#include "hle_internal.h"
#include "memory.h"
#include "../usf_internal.h"
/* state moved to usf_internal.h */
enum { DMEM_BASE = 0x5c0 };
/* helper functions */
static uint32_t get_address(usf_state_t* state, uint32_t so)
static uint32_t get_address(struct hle_t* hle, uint32_t so)
{
return alist_get_address(state, so, state->l_alist_audio.segments, N_SEGMENTS);
return alist_get_address(hle, so, hle->alist_audio.segments, N_SEGMENTS);
}
static void set_address(usf_state_t* state, uint32_t so)
static void set_address(struct hle_t* hle, uint32_t so)
{
alist_set_address(state, so, state->l_alist_audio.segments, N_SEGMENTS);
alist_set_address(hle, so, hle->alist_audio.segments, N_SEGMENTS);
}
static void clear_segments(usf_state_t* state)
static void clear_segments(struct hle_t* hle)
{
memset(state->l_alist_audio.segments, 0, N_SEGMENTS*sizeof(state->l_alist_audio.segments[0]));
memset(hle->alist_audio.segments, 0, N_SEGMENTS*sizeof(hle->alist_audio.segments[0]));
}
/* audio commands definition */
static void SPNOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SPNOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
}
static void CLEARBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t dmem = w1 + DMEM_BASE;
uint16_t count = w2;
@ -63,124 +64,124 @@ static void CLEARBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
if (count == 0)
return;
alist_clear(state, dmem, align(count, 16));
alist_clear(hle, dmem, align(count, 16));
}
static void ENVMIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
uint32_t address = get_address(state, w2);
uint32_t address = get_address(hle, w2);
alist_envmix_exp(
state,
hle,
flags & A_INIT,
flags & A_AUX,
state->l_alist_audio.out, state->l_alist_audio.dry_right,
state->l_alist_audio.wet_left, state->l_alist_audio.wet_right,
state->l_alist_audio.in, state->l_alist_audio.count,
state->l_alist_audio.dry, state->l_alist_audio.wet,
state->l_alist_audio.vol,
state->l_alist_audio.target,
state->l_alist_audio.rate,
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(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, w2);
uint32_t address = get_address(hle, w2);
alist_resample(
state,
hle,
flags & 0x1,
flags & 0x2,
state->l_alist_audio.out,
state->l_alist_audio.in,
align(state->l_alist_audio.count, 16),
hle->alist_audio.out,
hle->alist_audio.in,
align(hle->alist_audio.count, 16),
pitch << 1,
address);
}
static void SETVOL(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETVOL(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
if (flags & A_AUX) {
state->l_alist_audio.dry = w1;
state->l_alist_audio.wet = w2;
hle->alist_audio.dry = w1;
hle->alist_audio.wet = w2;
}
else {
unsigned lr = (flags & A_LEFT) ? 0 : 1;
if (flags & A_VOL)
state->l_alist_audio.vol[lr] = w1;
hle->alist_audio.vol[lr] = w1;
else {
state->l_alist_audio.target[lr] = w1;
state->l_alist_audio.rate[lr] = w2;
hle->alist_audio.target[lr] = w1;
hle->alist_audio.rate[lr] = w2;
}
}
}
static void SETLOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETLOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_audio.loop = get_address(state, w2);
hle->alist_audio.loop = get_address(hle, w2);
}
static void ADPCM(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
uint32_t address = get_address(state, w2);
uint32_t address = get_address(hle, w2);
alist_adpcm(
state,
hle,
flags & 0x1,
flags & 0x2,
false, /* unsupported in this ucode */
state->l_alist_audio.out,
state->l_alist_audio.in,
align(state->l_alist_audio.count, 32),
state->l_alist_audio.table,
state->l_alist_audio.loop,
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(usf_state_t* state, uint32_t w1, uint32_t w2)
static void LOADBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint32_t address = get_address(state, w2);
uint32_t address = get_address(hle, w2);
if (state->l_alist_audio.count == 0)
if (hle->alist_audio.count == 0)
return;
alist_load(state, state->l_alist_audio.in, address, state->l_alist_audio.count);
alist_load(hle, hle->alist_audio.in, address, hle->alist_audio.count);
}
static void SAVEBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SAVEBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint32_t address = get_address(state, w2);
uint32_t address = get_address(hle, w2);
if (state->l_alist_audio.count == 0)
if (hle->alist_audio.count == 0)
return;
alist_save(state, state->l_alist_audio.out, address, state->l_alist_audio.count);
alist_save(hle, hle->alist_audio.out, address, hle->alist_audio.count);
}
static void SETBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
if (flags & A_AUX) {
state->l_alist_audio.dry_right = w1 + DMEM_BASE;
state->l_alist_audio.wet_left = (w2 >> 16) + DMEM_BASE;
state->l_alist_audio.wet_right = w2 + DMEM_BASE;
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 {
state->l_alist_audio.in = w1 + DMEM_BASE;
state->l_alist_audio.out = (w2 >> 16) + DMEM_BASE;
state->l_alist_audio.count = w2;
hle->alist_audio.in = w1 + DMEM_BASE;
hle->alist_audio.out = (w2 >> 16) + DMEM_BASE;
hle->alist_audio.count = w2;
}
}
static void DMEMMOVE(usf_state_t* state, uint32_t w1, uint32_t 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;
@ -189,67 +190,67 @@ static void DMEMMOVE(usf_state_t* state, uint32_t w1, uint32_t w2)
if (count == 0)
return;
alist_move(state, dmemo, dmemi, align(count, 16));
alist_move(hle, dmemo, dmemi, align(count, 16));
}
static void LOADADPCM(usf_state_t* state, uint32_t w1, uint32_t w2)
static void LOADADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t count = w1;
uint32_t address = get_address(state, w2);
uint32_t address = get_address(hle, w2);
dram_load_u16(state, (uint16_t*)state->l_alist_audio.table, address, align(count, 8) >> 1);
dram_load_u16(hle, (uint16_t*)hle->alist_audio.table, address, align(count, 8) >> 1);
}
static void INTERLEAVE(usf_state_t* state, uint32_t w1, uint32_t w2)
static void INTERLEAVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t left = (w2 >> 16) + DMEM_BASE;
uint16_t right = w2 + DMEM_BASE;
if (state->l_alist_audio.count == 0)
if (hle->alist_audio.count == 0)
return;
alist_interleave(state, state->l_alist_audio.out, left, right, align(state->l_alist_audio.count, 16));
alist_interleave(hle, hle->alist_audio.out, left, right, align(hle->alist_audio.count, 16));
}
static void MIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
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 (state->l_alist_audio.count == 0)
if (hle->alist_audio.count == 0)
return;
alist_mix(state, dmemo, dmemi, align(state->l_alist_audio.count, 32), gain);
alist_mix(hle, dmemo, dmemi, align(hle->alist_audio.count, 32), gain);
}
static void SEGMENT(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SEGMENT(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
set_address(state, w2);
set_address(hle, w2);
}
static void POLEF(usf_state_t* state, uint32_t w1, uint32_t 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(state, w2);
uint32_t address = get_address(hle, w2);
if (state->l_alist_audio.count == 0)
if (hle->alist_audio.count == 0)
return;
alist_polef(
state,
hle,
flags & A_INIT,
state->l_alist_audio.out,
state->l_alist_audio.in,
align(state->l_alist_audio.count, 16),
hle->alist_audio.out,
hle->alist_audio.in,
align(hle->alist_audio.count, 16),
gain,
state->l_alist_audio.table,
hle->alist_audio.table,
address);
}
/* global functions */
void alist_process_audio(usf_state_t* state)
void alist_process_audio(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x10] = {
SPNOOP, ADPCM , CLEARBUFF, ENVMIXER,
@ -258,11 +259,11 @@ void alist_process_audio(usf_state_t* state)
MIXER, INTERLEAVE, POLEF, SETLOOP
};
clear_segments(state);
alist_process(state, ABI, 0x10);
clear_segments(hle);
alist_process(hle, ABI, 0x10);
}
void alist_process_audio_ge(usf_state_t* state)
void alist_process_audio_ge(struct hle_t* hle)
{
/* TODO: see what differs from alist_process_audio */
static const acmd_callback_t ABI[0x10] = {
@ -272,11 +273,11 @@ void alist_process_audio_ge(usf_state_t* state)
MIXER, INTERLEAVE, POLEF, SETLOOP
};
clear_segments(state);
alist_process(state, ABI, 0x10);
clear_segments(hle);
alist_process(hle, ABI, 0x10);
}
void alist_process_audio_bc(usf_state_t* state)
void alist_process_audio_bc(struct hle_t* hle)
{
/* TODO: see what differs from alist_process_audio */
static const acmd_callback_t ABI[0x10] = {
@ -286,6 +287,6 @@ void alist_process_audio_bc(usf_state_t* state)
MIXER, INTERLEAVE, POLEF, SETLOOP
};
clear_segments(state);
alist_process(state, ABI, 0x10);
clear_segments(hle);
alist_process(hle, ABI, 0x10);
}

View File

@ -22,26 +22,32 @@
#ifndef ALIST_INTERNAL_H
#define ALIST_INTERNAL_H
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include <stddef.h>
typedef void (*acmd_callback_t)(usf_state_t* state, uint32_t w1, uint32_t w2);
struct hle_t;
void alist_process(usf_state_t* state, const acmd_callback_t abi[], unsigned int abi_size);
uint32_t alist_get_address(usf_state_t* state, uint32_t so, const uint32_t *segments, size_t n);
void alist_set_address(usf_state_t* state, uint32_t so, uint32_t *segments, size_t n);
void alist_clear(usf_state_t* state, uint16_t dmem, uint16_t count);
void alist_load(usf_state_t* state, uint16_t dmem, uint32_t address, uint16_t count);
void alist_save(usf_state_t* state, uint16_t dmem, uint32_t address, uint16_t count);
void alist_move(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count);
void alist_copy_every_other_sample(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count);
void alist_repeat64(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint8_t count);
void alist_copy_blocks(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t block_size, uint8_t count);
void alist_interleave(usf_state_t* state, uint16_t dmemo, uint16_t left, uint16_t right, uint16_t count);
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(
usf_state_t* state,
struct hle_t* hle,
bool init,
bool aux,
uint16_t dmem_dl, uint16_t dmem_dr,
@ -54,7 +60,7 @@ void alist_envmix_exp(
uint32_t address);
void alist_envmix_lin(
usf_state_t* state,
struct hle_t* hle,
bool init,
uint16_t dmem_dl, uint16_t dmem_dr,
uint16_t dmem_wl, uint16_t dmem_wr,
@ -66,7 +72,7 @@ void alist_envmix_lin(
uint32_t address);
void alist_envmix_nead(
usf_state_t* state,
struct hle_t* hle,
bool swap_wet_LR,
uint16_t dmem_dl,
uint16_t dmem_dr,
@ -78,12 +84,12 @@ void alist_envmix_nead(
uint16_t *env_steps,
const int16_t *xors);
void alist_mix(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count, int16_t gain);
void alist_multQ44(usf_state_t* state, uint16_t dmem, uint16_t count, int8_t gain);
void alist_add(usf_state_t* state, uint16_t dmemo, uint16_t dmemi, uint16_t count);
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(
usf_state_t* state,
struct hle_t* hle,
bool init,
bool loop,
bool two_bit_per_sample,
@ -95,14 +101,14 @@ void alist_adpcm(
uint32_t last_frame_address);
void alist_resample(
usf_state_t* state,
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(
usf_state_t* state,
struct hle_t* hle,
uint16_t dmemo,
uint16_t dmemi,
uint16_t count,
@ -110,14 +116,14 @@ void alist_resample_zoh(
uint32_t pitch_accu);
void alist_filter(
usf_state_t* state,
struct hle_t* hle,
uint16_t dmem,
uint16_t count,
uint32_t address,
const uint32_t* lut_address);
void alist_polef(
usf_state_t* state,
struct hle_t* hle,
bool init,
uint16_t dmemo,
uint16_t dmemi,

View File

@ -21,49 +21,61 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include "../usf.h"
#include "alist_internal.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "plugin.h"
#include "../usf_internal.h"
void MP3(struct hle_t* hle, uint32_t w1, uint32_t w2);
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
};
void MP3(usf_state_t* state, uint32_t w1, uint32_t w2);
/* audio commands definition */
static void UNKNOWN(usf_state_t* state, uint32_t w1, uint32_t w2)
static void UNKNOWN(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t acmd = (w1 >> 24);
DebugMessage(state, M64MSG_WARNING,
"Unknown audio comand %d: %08x %08x",
acmd, w1, w2);
HleWarnMessage(hle->user_defined,
"Unknown audio command %d: %08x %08x",
acmd, w1, w2);
}
static void SPNOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SPNOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
}
static void NAUDIO_0000(usf_state_t* state, uint32_t w1, uint32_t w2)
static void NAUDIO_0000(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
/* ??? */
UNKNOWN(state, w1, w2);
UNKNOWN(hle, w1, w2);
}
static void NAUDIO_02B0(usf_state_t* state, uint32_t w1, uint32_t w2)
static void NAUDIO_02B0(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
/* ??? */
/* UNKNOWN(state, w1, w2); commented to avoid constant spamming during gameplay */
uint32_t rate = (hle->alist_naudio.rate[1] & 0xffff0000) | (w2 & 0xffff);
hle->alist_naudio.rate[1] = rate;
}
static void NAUDIO_14(usf_state_t* state, uint32_t w1, uint32_t w2)
static void NAUDIO_14(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
if (state->l_alist_naudio.table[0] == 0 && state->l_alist_naudio.table[1] == 0) {
if (hle->alist_naudio.table[0] == 0 && hle->alist_naudio.table[1] == 0) {
uint8_t flags = (w1 >> 16);
uint16_t gain = w1;
@ -73,49 +85,50 @@ static void NAUDIO_14(usf_state_t* state, uint32_t w1, uint32_t w2)
uint16_t dmem = (select_main == 0) ? NAUDIO_MAIN : NAUDIO_MAIN2;
alist_polef(
state,
hle,
flags & A_INIT,
dmem,
dmem,
NAUDIO_COUNT,
gain,
state->l_alist_naudio.table,
hle->alist_naudio.table,
address);
}
else
DebugMessage(state, M64MSG_VERBOSE, "NAUDIO_14: non null codebook[0-3] case not implemented.");
HleWarnMessage(hle->user_defined,
"NAUDIO_14: non null codebook[0-3] case not implemented.");
}
static void SETVOL(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETVOL(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
if (flags & 0x4) {
if (flags & 0x2) {
state->l_alist_naudio.vol[0] = w1;
state->l_alist_naudio.dry = (w2 >> 16);
state->l_alist_naudio.wet = w2;
hle->alist_naudio.vol[0] = w1;
hle->alist_naudio.dry = (w2 >> 16);
hle->alist_naudio.wet = w2;
}
else {
state->l_alist_naudio.target[1] = w1;
state->l_alist_naudio.rate[1] = w2;
hle->alist_naudio.target[1] = w1;
hle->alist_naudio.rate[1] = w2;
}
}
else {
state->l_alist_naudio.target[0] = w1;
state->l_alist_naudio.rate[0] = w2;
hle->alist_naudio.target[0] = w1;
hle->alist_naudio.rate[0] = w2;
}
}
static void ENVMIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ENVMIXER(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t flags = (w1 >> 16);
uint32_t address = (w2 & 0xffffff);
state->l_alist_naudio.vol[1] = w1;
hle->alist_naudio.vol[1] = w1;
alist_envmix_lin(
state,
hle,
flags & 0x1,
NAUDIO_DRY_LEFT,
NAUDIO_DRY_RIGHT,
@ -123,72 +136,72 @@ static void ENVMIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
NAUDIO_WET_RIGHT,
NAUDIO_MAIN,
NAUDIO_COUNT,
state->l_alist_naudio.dry,
state->l_alist_naudio.wet,
state->l_alist_naudio.vol,
state->l_alist_naudio.target,
state->l_alist_naudio.rate,
hle->alist_naudio.dry,
hle->alist_naudio.wet,
hle->alist_naudio.vol,
hle->alist_naudio.target,
hle->alist_naudio.rate,
address);
}
static void CLEARBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t dmem = w1 + NAUDIO_MAIN;
uint16_t count = w2;
alist_clear(state, dmem, count);
alist_clear(hle, dmem, count);
}
static void MIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, NAUDIO_COUNT, gain);
alist_mix(hle, dmemo, dmemi, NAUDIO_COUNT, gain);
}
static void LOADBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmem, address, count);
alist_load(hle, dmem, address, count);
}
static void SAVEBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmem, address, count);
alist_save(hle, dmem, address, count);
}
static void LOADADPCM(usf_state_t* state, uint32_t w1, uint32_t 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(state, (uint16_t*)state->l_alist_naudio.table, address, count >> 1);
dram_load_u16(hle, (uint16_t*)hle->alist_naudio.table, address, count >> 1);
}
static void DMEMMOVE(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, (count + 3) & ~3);
alist_move(hle, dmemo, dmemi, (count + 3) & ~3);
}
static void SETLOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETLOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_naudio.loop = (w2 & 0xffffff);
hle->alist_naudio.loop = (w2 & 0xffffff);
}
static void ADPCM(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ADPCM(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint32_t address = (w1 & 0xffffff);
uint8_t flags = (w2 >> 28);
@ -197,19 +210,19 @@ static void ADPCM(usf_state_t* state, uint32_t w1, uint32_t w2)
uint16_t dmemo = (w2 & 0xfff) + NAUDIO_MAIN;
alist_adpcm(
state,
hle,
flags & 0x1,
flags & 0x2,
false, /* unsuported by this ucode */
dmemo,
dmemi,
(count + 0x1f) & ~0x1f,
state->l_alist_naudio.table,
state->l_alist_naudio.loop,
hle->alist_naudio.table,
hle->alist_naudio.loop,
address);
}
static void RESAMPLE(usf_state_t* state, uint32_t w1, uint32_t w2)
static void RESAMPLE(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint32_t address = (w1 & 0xffffff);
uint8_t flags = (w2 >> 30);
@ -218,7 +231,7 @@ static void RESAMPLE(usf_state_t* state, uint32_t w1, uint32_t w2)
uint16_t dmemo = (w2 & 0x3) ? NAUDIO_MAIN2 : NAUDIO_MAIN;
alist_resample(
state,
hle,
flags & 0x1,
false, /* TODO: check which ABI supports it */
dmemo,
@ -228,17 +241,17 @@ static void RESAMPLE(usf_state_t* state, uint32_t w1, uint32_t w2)
address);
}
static void INTERLEAVE(usf_state_t* state, uint32_t w1, uint32_t w2)
static void INTERLEAVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
alist_interleave(state, NAUDIO_MAIN, NAUDIO_DRY_LEFT, NAUDIO_DRY_RIGHT, NAUDIO_COUNT);
alist_interleave(hle, NAUDIO_MAIN, NAUDIO_DRY_LEFT, NAUDIO_DRY_RIGHT, NAUDIO_COUNT);
}
static void MP3ADDY(usf_state_t* state, uint32_t w1, uint32_t w2)
static void MP3ADDY(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
}
/* global functions */
void alist_process_naudio(usf_state_t* state)
void alist_process_naudio(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x10] = {
SPNOOP, ADPCM, CLEARBUFF, ENVMIXER,
@ -247,10 +260,10 @@ void alist_process_naudio(usf_state_t* state)
MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
};
alist_process(state, ABI, 0x10);
alist_process(hle, ABI, 0x10);
}
void alist_process_naudio_bk(usf_state_t* state)
void alist_process_naudio_bk(struct hle_t* hle)
{
/* TODO: see what differs from alist_process_naudio */
static const acmd_callback_t ABI[0x10] = {
@ -260,10 +273,10 @@ void alist_process_naudio_bk(usf_state_t* state)
MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
};
alist_process(state, ABI, 0x10);
alist_process(hle, ABI, 0x10);
}
void alist_process_naudio_dk(usf_state_t* state)
void alist_process_naudio_dk(struct hle_t* hle)
{
/* TODO: see what differs from alist_process_naudio */
static const acmd_callback_t ABI[0x10] = {
@ -273,10 +286,10 @@ void alist_process_naudio_dk(usf_state_t* state)
MIXER, INTERLEAVE, NAUDIO_02B0, SETLOOP
};
alist_process(state, ABI, 0x10);
alist_process(hle, ABI, 0x10);
}
void alist_process_naudio_mp3(usf_state_t* state)
void alist_process_naudio_mp3(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x10] = {
UNKNOWN, ADPCM, CLEARBUFF, ENVMIXER,
@ -285,10 +298,10 @@ void alist_process_naudio_mp3(usf_state_t* state)
MIXER, INTERLEAVE, NAUDIO_14, SETLOOP
};
alist_process(state, ABI, 0x10);
alist_process(hle, ABI, 0x10);
}
void alist_process_naudio_cbfd(usf_state_t* state)
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] = {
@ -298,5 +311,5 @@ void alist_process_naudio_cbfd(usf_state_t* state)
MIXER, INTERLEAVE, NAUDIO_14, SETLOOP
};
alist_process(state, ABI, 0x10);
alist_process(hle, ABI, 0x10);
}

View File

@ -21,78 +21,77 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include "../usf.h"
#include "alist_internal.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "plugin.h"
#include "../usf_internal.h"
/* remove windows define to 0x06 */
#ifdef DUPLICATE
#undef DUPLICATE
#endif
/* audio commands definition */
static void UNKNOWN(usf_state_t* state, uint32_t w1, uint32_t w2)
static void UNKNOWN(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint8_t acmd = (w1 >> 24);
DebugMessage(state, M64MSG_WARNING,
"Unknown audio comand %d: %08x %08x",
acmd, w1, w2);
HleWarnMessage(hle->user_defined,
"Unknown audio command %d: %08x %08x",
acmd, w1, w2);
}
static void SPNOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SPNOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
}
static void LOADADPCM(usf_state_t* state, uint32_t w1, uint32_t 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(state, (uint16_t*)state->l_alist_nead.table, address, count >> 1);
dram_load_u16(hle, (uint16_t*)hle->alist_nead.table, address, count >> 1);
}
static void SETLOOP(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETLOOP(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_nead.loop = w2 & 0xffffff;
hle->alist_nead.loop = w2 & 0xffffff;
}
static void SETBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SETBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_nead.in = w1;
state->l_alist_nead.out = (w2 >> 16);
state->l_alist_nead.count = w2;
hle->alist_nead.in = w1;
hle->alist_nead.out = (w2 >> 16);
hle->alist_nead.count = w2;
}
static void ADPCM(usf_state_t* state, uint32_t w1, uint32_t 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(
state,
hle,
flags & 0x1,
flags & 0x2,
flags & 0x4,
state->l_alist_nead.out,
state->l_alist_nead.in,
(state->l_alist_nead.count + 0x1f) & ~0x1f,
state->l_alist_nead.table,
state->l_alist_nead.loop,
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(usf_state_t* state, uint32_t w1, uint32_t w2)
static void CLEARBUFF(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t dmem = w1;
uint16_t count = w2;
@ -100,70 +99,70 @@ static void CLEARBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
if (count == 0)
return;
alist_clear(state, dmem, count);
alist_clear(hle, dmem, count);
}
static void LOADBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmem, address, count);
alist_load(hle, dmem, address, count);
}
static void SAVEBUFF(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmem, address, count);
alist_save(hle, dmem, address, count);
}
static void MIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, count, gain);
alist_mix(hle, dmemo, dmemi, count, gain);
}
static void RESAMPLE(usf_state_t* state, uint32_t w1, uint32_t w2)
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(
state,
hle,
flags & 0x1,
false, /* TODO: check which ABI supports it */
state->l_alist_nead.out,
state->l_alist_nead.in,
(state->l_alist_nead.count + 0xf) & ~0xf,
hle->alist_nead.out,
hle->alist_nead.in,
(hle->alist_nead.count + 0xf) & ~0xf,
pitch << 1,
address);
}
static void RESAMPLE_ZOH(usf_state_t* state, uint32_t w1, uint32_t w2)
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(
state,
state->l_alist_nead.out,
state->l_alist_nead.in,
state->l_alist_nead.count,
hle,
hle->alist_nead.out,
hle->alist_nead.in,
hle->alist_nead.count,
pitch << 1,
pitch_accu);
}
static void DMEMMOVE(usf_state_t* state, uint32_t w1, uint32_t w2)
static void DMEMMOVE(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t dmemi = w1;
uint16_t dmemo = (w2 >> 16);
@ -172,194 +171,194 @@ static void DMEMMOVE(usf_state_t* state, uint32_t w1, uint32_t w2)
if (count == 0)
return;
alist_move(state, dmemo, dmemi, (count + 3) & ~3);
alist_move(hle, dmemo, dmemi, (count + 3) & ~3);
}
static void ENVSETUP1_MK(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ENVSETUP1_MK(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_nead.env_values[2] = (w1 >> 8) & 0xff00;
state->l_alist_nead.env_steps[2] = 0;
state->l_alist_nead.env_steps[0] = (w2 >> 16);
state->l_alist_nead.env_steps[1] = 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(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ENVSETUP1(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_nead.env_values[2] = (w1 >> 8) & 0xff00;
state->l_alist_nead.env_steps[2] = w1;
state->l_alist_nead.env_steps[0] = (w2 >> 16);
state->l_alist_nead.env_steps[1] = 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(usf_state_t* state, uint32_t w1, uint32_t w2)
static void ENVSETUP2(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
state->l_alist_nead.env_values[0] = (w2 >> 16);
state->l_alist_nead.env_values[1] = w2;
hle->alist_nead.env_values[0] = (w2 >> 16);
hle->alist_nead.env_values[1] = w2;
}
static void ENVMIXER_MK(usf_state_t* state, uint32_t w1, uint32_t 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;
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) );
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(
state,
hle,
false, /* unsupported by this ucode */
dmem_dl, dmem_dr,
dmem_wl, dmem_wr,
dmemi, count,
state->l_alist_nead.env_values,
state->l_alist_nead.env_steps,
hle->alist_nead.env_values,
hle->alist_nead.env_steps,
xors);
}
static void ENVMIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
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;
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) );
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(
state,
hle,
swap_wet_LR,
dmem_dl, dmem_dr,
dmem_wl, dmem_wr,
dmemi, count,
state->l_alist_nead.env_values,
state->l_alist_nead.env_steps,
hle->alist_nead.env_values,
hle->alist_nead.env_steps,
xors);
}
static void DUPLICATE(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, count);
alist_repeat64(hle, dmemo, dmemi, count);
}
static void INTERL(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, count);
alist_copy_every_other_sample(hle, dmemo, dmemi, count);
}
static void INTERLEAVE_MK(usf_state_t* state, uint32_t w1, uint32_t w2)
static void INTERLEAVE_MK(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
uint16_t left = (w2 >> 16);
uint16_t right = w2;
if (state->l_alist_nead.count == 0)
if (hle->alist_nead.count == 0)
return;
alist_interleave(state, state->l_alist_nead.out, left, right, state->l_alist_nead.count);
alist_interleave(hle, hle->alist_nead.out, left, right, hle->alist_nead.count);
}
static void INTERLEAVE(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, left, right, count);
alist_interleave(hle, dmemo, left, right, count);
}
static void ADDMIXER(usf_state_t* state, uint32_t w1, uint32_t w2)
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(state, dmemo, dmemi, count);
alist_add(hle, dmemo, dmemi, count);
}
static void HILOGAIN(usf_state_t* state, uint32_t w1, uint32_t w2)
static void HILOGAIN(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
int8_t gain = (w1 >> 16); /* Q4.4 signed */
uint16_t count = w1;
uint16_t dmem = (w2 >> 16);
alist_multQ44(state, dmem, count, gain);
alist_multQ44(hle, dmem, count, gain);
}
static void FILTER(usf_state_t* state, uint32_t w1, uint32_t w2)
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) {
state->l_alist_nead.filter_count = w1;
state->l_alist_nead.filter_lut_address[0] = address; /* t6 */
hle->alist_nead.filter_count = w1;
hle->alist_nead.filter_lut_address[0] = address; /* t6 */
}
else {
uint16_t dmem = w1;
state->l_alist_nead.filter_lut_address[1] = address + 0x10; /* t5 */
alist_filter(state, dmem, state->l_alist_nead.filter_count, address, state->l_alist_nead.filter_lut_address);
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(usf_state_t* state, uint32_t w1, uint32_t w2)
static void SEGMENT(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
}
static void NEAD_16(usf_state_t* state, uint32_t w1, uint32_t 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(state, dmemo, dmemi, block_size, count);
alist_copy_blocks(hle, dmemo, dmemi, block_size, count);
}
static void POLEF(usf_state_t* state, uint32_t w1, uint32_t 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 = (w2 & 0xffffff);
if (state->l_alist_nead.count == 0)
if (hle->alist_nead.count == 0)
return;
alist_polef(
state,
hle,
flags & A_INIT,
state->l_alist_nead.out,
state->l_alist_nead.in,
state->l_alist_nead.count,
hle->alist_nead.out,
hle->alist_nead.in,
hle->alist_nead.count,
gain,
state->l_alist_nead.table,
hle->alist_nead.table,
address);
}
void alist_process_nead_mk(usf_state_t* state)
void alist_process_nead_mk(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x20] = {
SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
@ -372,10 +371,10 @@ void alist_process_nead_mk(usf_state_t* state)
SPNOOP, SPNOOP, SPNOOP, SPNOOP
};
alist_process(state, ABI, 0x20);
alist_process(hle, ABI, 0x20);
}
void alist_process_nead_sf(usf_state_t* state)
void alist_process_nead_sf(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x20] = {
SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
@ -388,10 +387,10 @@ void alist_process_nead_sf(usf_state_t* state)
SPNOOP, SPNOOP, SPNOOP, SPNOOP
};
alist_process(state, ABI, 0x20);
alist_process(hle, ABI, 0x20);
}
void alist_process_nead_sfj(usf_state_t* state)
void alist_process_nead_sfj(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x20] = {
SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
@ -404,10 +403,10 @@ void alist_process_nead_sfj(usf_state_t* state)
SPNOOP, SPNOOP, SPNOOP, SPNOOP
};
alist_process(state, ABI, 0x20);
alist_process(hle, ABI, 0x20);
}
void alist_process_nead_fz(usf_state_t* state)
void alist_process_nead_fz(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x20] = {
UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
@ -420,10 +419,10 @@ void alist_process_nead_fz(usf_state_t* state)
SPNOOP, SPNOOP, SPNOOP, SPNOOP
};
alist_process(state, ABI, 0x20);
alist_process(hle, ABI, 0x20);
}
void alist_process_nead_wrjb(usf_state_t* state)
void alist_process_nead_wrjb(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x20] = {
SPNOOP, ADPCM, CLEARBUFF, UNKNOWN,
@ -436,10 +435,10 @@ void alist_process_nead_wrjb(usf_state_t* state)
SPNOOP, SPNOOP, SPNOOP, SPNOOP
};
alist_process(state, ABI, 0x20);
alist_process(hle, ABI, 0x20);
}
void alist_process_nead_ys(usf_state_t* state)
void alist_process_nead_ys(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
@ -450,10 +449,10 @@ void alist_process_nead_ys(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}
void alist_process_nead_1080(usf_state_t* state)
void alist_process_nead_1080(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
@ -464,10 +463,10 @@ void alist_process_nead_1080(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}
void alist_process_nead_oot(usf_state_t* state)
void alist_process_nead_oot(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
UNKNOWN, ADPCM, CLEARBUFF, UNKNOWN,
@ -478,10 +477,10 @@ void alist_process_nead_oot(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}
void alist_process_nead_mm(usf_state_t* state)
void alist_process_nead_mm(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
@ -492,10 +491,10 @@ void alist_process_nead_mm(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}
void alist_process_nead_mmb(usf_state_t* state)
void alist_process_nead_mmb(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
SPNOOP, ADPCM, CLEARBUFF, SPNOOP,
@ -506,10 +505,10 @@ void alist_process_nead_mmb(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}
void alist_process_nead_ac(usf_state_t* state)
void alist_process_nead_ac(struct hle_t* hle)
{
static const acmd_callback_t ABI[0x18] = {
UNKNOWN, ADPCM, CLEARBUFF, SPNOOP,
@ -520,5 +519,5 @@ void alist_process_nead_ac(usf_state_t* state)
LOADBUFF, SAVEBUFF, ENVSETUP2, UNKNOWN
};
alist_process(state, ABI, 0x18);
alist_process(hle, ABI, 0x18);
}

View File

@ -24,7 +24,13 @@
#include <stdint.h>
static inline int16_t clamp_s16(int_fast32_t x)
#ifdef _MSC_VER
#define INLINE __forceinline
#else
#define INLINE __attribute__((always_inline))
#endif
INLINE static int16_t clamp_s16(int_fast32_t x)
{
x = (x < INT16_MIN) ? INT16_MIN: x;
x = (x > INT16_MAX) ? INT16_MAX: x;

View File

@ -77,8 +77,6 @@ int32_t rdot(size_t n, const int16_t *x, const int16_t *y)
void adpcm_compute_residuals(int16_t* dst, const int16_t* src,
const int16_t* cb_entry, const int16_t* last_samples, size_t count)
{
assert(count <= 8);
const int16_t* const book1 = cb_entry;
const int16_t* const book2 = cb_entry + 8;
@ -87,6 +85,8 @@ void adpcm_compute_residuals(int16_t* dst, const int16_t* src,
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);

View File

@ -29,7 +29,13 @@ extern const int16_t RESAMPLE_LUT[64 * 4];
int32_t rdot(size_t n, const int16_t *x, const int16_t *y);
static inline int16_t adpcm_predict_sample(uint8_t byte, uint8_t mask,
#ifdef _MSC_VER
#define INLINE __forceinline
#else
#define INLINE __attribute__((always_inline))
#endif
INLINE static int16_t adpcm_predict_sample(uint8_t byte, uint8_t mask,
unsigned lshift, unsigned rshift)
{
int16_t sample = (uint16_t)(byte & mask) << lshift;

View File

@ -23,12 +23,7 @@
#include <string.h>
#include "../usf.h"
#include "plugin.h"
#include "cicx105.h"
#include "../usf_internal.h"
#include "hle_internal.h"
/**
* During IPL3 stage of CIC x105 games, the RSP performs some checks and transactions
@ -38,15 +33,15 @@
*
* Found in Banjo-Tooie, Zelda, Perfect Dark, ...)
**/
void cicx105_ucode(usf_state_t* state)
void cicx105_ucode(struct hle_t* hle)
{
/* memcpy is okay to use because access constrains are met (alignment, size) */
unsigned int i;
unsigned char *dst = state->N64MEM + 0x2fb1f0;
unsigned char *src = state->IMEM + 0x120;
unsigned char *dst = hle->dram + 0x2fb1f0;
unsigned char *src = hle->imem + 0x120;
/* dma_read(0x1120, 0x1e8, 0x1e8) */
memcpy(state->IMEM + 0x120, state->N64MEM + 0x1e8, 0x1f0);
memcpy(hle->imem + 0x120, hle->dram + 0x1e8, 0x1f0);
/* dma_write(0x1120, 0x2fb1f0, 0xfe817000) */
for (i = 0; i < 24; ++i) {

View File

@ -22,7 +22,9 @@
#ifndef CICX105_H
#define CICX105_H
void cicx105_ucode(usf_state_t* state);
struct hle_t;
void cicx105_ucode(struct hle_t* hle);
#endif

View File

@ -0,0 +1,449 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - hle.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#ifdef ENABLE_TASK_DUMP
#include <stdio.h>
#endif
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "alist.h"
#include "cicx105.h"
#include "jpeg.h"
#include "musyx.h"
#define min(a,b) (((a) < (b)) ? (a) : (b))
/* some rsp status flags */
#define SP_STATUS_HALT 0x1
#define SP_STATUS_BROKE 0x2
#define SP_STATUS_INTR_ON_BREAK 0x40
#define SP_STATUS_TASKDONE 0x200
/* some rdp status flags */
#define DP_STATUS_FREEZE 0x2
/* some mips interface interrupt flags */
#define MI_INTR_SP 0x1
/* helper functions prototypes */
static unsigned int sum_bytes(const unsigned char *bytes, unsigned int size);
static bool is_task(struct hle_t* hle);
static void rsp_break(struct hle_t* hle, unsigned int setbits);
static void forward_gfx_task(struct hle_t* hle);
static 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);
#ifdef ENABLE_TASK_DUMP
static void dump_binary(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
/* local variables */
static const bool FORWARD_AUDIO = false, FORWARD_GFX = true;
/* 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);
rsp_break(hle, SP_STATUS_TASKDONE);
} else {
non_task_dispatching(hle);
rsp_break(hle, 0);
}
}
/* 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);
}
static 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 forward_gfx_task(struct hle_t* hle)
{
HleProcessDlistList(hle->user_defined);
*hle->dpc_status &= ~DP_STATUS_FREEZE;
}
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;
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:
if (FORWARD_GFX) {
forward_gfx_task(hle);
return true;
}
break;
case 2:
if (FORWARD_AUDIO) {
HleProcessAlistList(hle->user_defined);
return true;
} else if (try_fast_audio_dispatching(hle))
return true;
break;
case 7:
HleShowCFB(hle->user_defined);
return true;
}
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 */
return;
/* GFX: Twintris [misleading task->type == 0] */
case 0x212ee:
if (FORWARD_GFX) {
forward_gfx_task(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;
}
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, 0x1000 >> 1);
switch (sum) {
/* CIC x105 ucode (used during boot of CIC x105 games) */
case 0x9e2: /* CIC 6105 */
case 0x9f2: /* CIC 7105 */
cicx105_ucode(hle);
return;
}
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
}
#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(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(filename, (void*)dram_u32(hle, ucode), 0xf80);
}
/* dump ucode_data */
if (ucode_data != 0) {
sprintf(&filename[0], "ucode_data_%x.bin", sum);
dump_binary(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(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(filename, hle->imem, 0x1000);
sprintf(&filename[0], "dmem_%x.bin", sum);
dump_binary(filename, hle->dmem, 0x1000);
}
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)
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

View File

@ -0,0 +1,54 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - hle.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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_H
#define HLE_H
#include "hle_internal.h"
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);
void hle_execute(struct hle_t* hle);
#endif

View File

@ -1,5 +1,5 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - main.h *
* Mupen64plus-rsp-hle - hle_external.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2014 Bobby Smiles *
* *
@ -19,10 +19,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef MAIN_H
#define MAIN_H
#ifndef HLE_EXTERNAL_H
#define HLE_EXTERNAL_H
void hle_execute(usf_state_t* state);
/* users of the hle core are expected to define these functions */
void HleVerboseMessage(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);
#endif

View File

@ -0,0 +1,84 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - hle_internal.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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 <stdint.h>
#include "alist.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;
/* 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];
/* FIXME: rewrite mp3 module to avoid these */
uint32_t mp3_inPtr;
uint32_t mp3_outPtr;
uint32_t mp3_t6;
uint32_t mp3_t5;
uint32_t mp3_t4;
};
#endif

View File

@ -25,21 +25,18 @@
#include <stdint.h>
#include <stdlib.h>
#include "../usf.h"
#include "arithmetics.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "plugin.h"
#include "../usf_internal.h"
#define SUBBLOCK_SIZE 64
typedef void (*tile_line_emitter_t)(usf_state_t* state, const int16_t *y, const int16_t *u, uint32_t address);
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(usf_state_t* state,
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,
@ -55,8 +52,8 @@ 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(usf_state_t* state, const int16_t *y, const int16_t *u, uint32_t address);
static void EmitRGBATileLine(usf_state_t* state, 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 decode_macroblock_ob(int16_t *macroblock, int32_t *y_dc, int32_t *u_dc, int32_t *v_dc, const int16_t *qtable);
@ -65,8 +62,8 @@ static void decode_macroblock_std(const subblock_transform_t transform_luma,
int16_t *macroblock,
unsigned int subblock_count,
const int16_t qtables[3][SUBBLOCK_SIZE]);
static void EmitTilesMode0(usf_state_t* state, const tile_line_emitter_t emit_line, const int16_t *macroblock, uint32_t address);
static void EmitTilesMode2(usf_state_t* state, 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);
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);
@ -141,24 +138,24 @@ static const float IDCT_K[10] = {
/***************************************************************************
* JPEG decoding ucode found in Japanese exclusive version of Pokemon Stadium.
**************************************************************************/
void jpeg_decode_PS0(usf_state_t* state)
void jpeg_decode_PS0(struct hle_t* hle)
{
jpeg_decode_std(state, "PS0", RescaleYSubBlock, RescaleUVSubBlock, EmitYUVTileLine);
jpeg_decode_std(hle, "PS0", RescaleYSubBlock, RescaleUVSubBlock, EmitYUVTileLine);
}
/***************************************************************************
* JPEG decoding ucode found in Ocarina of Time, Pokemon Stadium 1 and
* Pokemon Stadium 2.
**************************************************************************/
void jpeg_decode_PS(usf_state_t* state)
void jpeg_decode_PS(struct hle_t* hle)
{
jpeg_decode_std(state, "PS", NULL, NULL, EmitRGBATileLine);
jpeg_decode_std(hle, "PS", NULL, NULL, EmitRGBATileLine);
}
/***************************************************************************
* JPEG decoding ucode found in Ogre Battle and Bottom of the 9th.
**************************************************************************/
void jpeg_decode_OB(usf_state_t* state)
void jpeg_decode_OB(struct hle_t* hle)
{
int16_t qtable[SUBBLOCK_SIZE];
unsigned int mb;
@ -167,15 +164,15 @@ void jpeg_decode_OB(usf_state_t* state)
int32_t u_dc = 0;
int32_t v_dc = 0;
uint32_t address = *dmem_u32(state, TASK_DATA_PTR);
const unsigned int macroblock_count = *dmem_u32(state, TASK_DATA_SIZE);
const int qscale = *dmem_u32(state, 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(state,
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)
@ -187,9 +184,9 @@ void jpeg_decode_OB(usf_state_t* state)
for (mb = 0; mb < macroblock_count; ++mb) {
int16_t macroblock[6 * SUBBLOCK_SIZE];
dram_load_u16(state, (uint16_t *)macroblock, address, 6 * SUBBLOCK_SIZE);
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(state, EmitYUVTileLine, macroblock, address);
EmitTilesMode2(hle, EmitYUVTileLine, macroblock, address);
address += (2 * 6 * SUBBLOCK_SIZE);
}
@ -197,7 +194,7 @@ void jpeg_decode_OB(usf_state_t* state)
/* local functions */
static void jpeg_decode_std(usf_state_t* state,
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,
@ -217,49 +214,52 @@ static void jpeg_decode_std(usf_state_t* state,
int16_t macroblock[6 * SUBBLOCK_SIZE];
uint32_t data_ptr;
if (*dmem_u32(state, TASK_FLAGS) & 0x1) {
DebugMessage(state, 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;
}
data_ptr = *dmem_u32(state, TASK_DATA_PTR);
address = *dram_u32(state, data_ptr);
macroblock_count = *dram_u32(state, data_ptr + 4);
mode = *dram_u32(state, data_ptr + 8);
qtableY_ptr = *dram_u32(state, data_ptr + 12);
qtableU_ptr = *dram_u32(state, data_ptr + 16);
qtableV_ptr = *dram_u32(state, 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(state, 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(state, M64MSG_WARNING, "jpeg_decode_%s: invalid mode %d", version, mode);
HleWarnMessage(hle->user_defined,
"jpeg_decode_%s: invalid mode %d", version, mode);
return;
}
subblock_count = mode + 4;
macroblock_size = subblock_count * SUBBLOCK_SIZE;
dram_load_u16(state, (uint16_t *)qtables[0], qtableY_ptr, SUBBLOCK_SIZE);
dram_load_u16(state, (uint16_t *)qtables[1], qtableU_ptr, SUBBLOCK_SIZE);
dram_load_u16(state, (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);
for (mb = 0; mb < macroblock_count; ++mb) {
dram_load_u16(state, (uint16_t *)macroblock, address, macroblock_size);
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(state, emit_line, macroblock, address);
EmitTilesMode0(hle, emit_line, macroblock, address);
else
EmitTilesMode2(state, emit_line, macroblock, address);
EmitTilesMode2(hle, emit_line, macroblock, address);
address += 2 * macroblock_size;
}
@ -309,7 +309,7 @@ static uint16_t GetRGBA(int16_t y, int16_t u, int16_t v)
return (r << 4) | (g >> 1) | (b >> 6) | 1;
}
static void EmitYUVTileLine(usf_state_t* state, 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];
@ -325,10 +325,10 @@ static void EmitYUVTileLine(usf_state_t* state, const int16_t *y, const int16_t
uyvy[6] = GetUYVY(y2[4], y2[5], u[6], v[6]);
uyvy[7] = GetUYVY(y2[6], y2[7], u[7], v[7]);
dram_store_u32(state, uyvy, address, 8);
dram_store_u32(hle, uyvy, address, 8);
}
static void EmitRGBATileLine(usf_state_t* state, 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];
@ -352,10 +352,10 @@ static void EmitRGBATileLine(usf_state_t* state, const int16_t *y, const int16_t
rgba[14] = GetRGBA(y2[6], u[7], v[7]);
rgba[15] = GetRGBA(y2[7], u[7], v[7]);
dram_store_u16(state, rgba, address, 16);
dram_store_u16(hle, rgba, address, 16);
}
static void EmitTilesMode0(usf_state_t* state, 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;
@ -363,7 +363,7 @@ static void EmitTilesMode0(usf_state_t* state, const tile_line_emitter_t emit_li
unsigned int u_offset = 2 * SUBBLOCK_SIZE;
for (i = 0; i < 8; ++i) {
emit_line(state, &macroblock[y_offset], &macroblock[u_offset], address);
emit_line(hle, &macroblock[y_offset], &macroblock[u_offset], address);
y_offset += 8;
u_offset += 8;
@ -371,7 +371,7 @@ static void EmitTilesMode0(usf_state_t* state, const tile_line_emitter_t emit_li
}
}
static void EmitTilesMode2(usf_state_t* state, 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;
@ -379,8 +379,8 @@ static void EmitTilesMode2(usf_state_t* state, const tile_line_emitter_t emit_li
unsigned int u_offset = 4 * SUBBLOCK_SIZE;
for (i = 0; i < 8; ++i) {
emit_line(state, &macroblock[y_offset], &macroblock[u_offset], address);
emit_line(state, &macroblock[y_offset + 8], &macroblock[u_offset], address + 32);
emit_line(hle, &macroblock[y_offset], &macroblock[u_offset], address);
emit_line(hle, &macroblock[y_offset + 8], &macroblock[u_offset], address + 32);
y_offset += (i == 3) ? SUBBLOCK_SIZE + 16 : 16;
u_offset += 8;

View File

@ -22,9 +22,11 @@
#ifndef JPEG_H
#define JPEG_H
void jpeg_decode_PS0(usf_state_t* state);
void jpeg_decode_PS(usf_state_t* state);
void jpeg_decode_OB(usf_state_t* state);
struct hle_t;
void jpeg_decode_PS0(struct hle_t* hle);
void jpeg_decode_PS(struct hle_t* hle);
void jpeg_decode_OB(struct hle_t* hle);
#endif

View File

@ -1,393 +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 <stdbool.h>
#include <stdint.h>
#ifdef ENABLE_TASK_DUMP
#include <stdio.h>
#endif
#include "../usf.h"
#include "memory.h"
#include "plugin.h"
#include "alist.h"
#include "cicx105.h"
#include "jpeg.h"
#include "musyx.h"
#include "../exception.h"
#include "../registers.h"
#include "../usf_internal.h"
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define SP_STATUS_INTR_ON_BREAK 0x40
#define SP_STATUS_TASKDONE 0x200
/* 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(usf_state_t* state);
static void rsp_break(usf_state_t* state, unsigned int setbits);
static void forward_gfx_task(usf_state_t* state);
static void forward_audio_task(usf_state_t* state);
static void show_cfb(usf_state_t* state);
static bool try_fast_audio_dispatching(usf_state_t* state);
static bool try_fast_task_dispatching(usf_state_t* state);
static void normal_task_dispatching(usf_state_t* state);
static void non_task_dispatching(usf_state_t* state);
#ifdef ENABLE_TASK_DUMP
static void dump_binary(usf_state_t* state, const char *const filename, const unsigned char *const bytes,
unsigned int size);
static void dump_task(usf_state_t* state, const char *const filename);
static void dump_unknown_task(usf_state_t* state, unsigned int sum);
static void dump_unknown_non_task(usf_state_t* state, unsigned int sum);
#endif
/* local variables */
static const bool FORWARD_AUDIO = false, FORWARD_GFX = true;
/* Global functions */
void hle_execute(usf_state_t* state)
{
if (is_task(state)) {
if (!try_fast_task_dispatching(state))
normal_task_dispatching(state);
rsp_break(state, SP_STATUS_TASKDONE);
} else {
non_task_dispatching(state);
rsp_break(state, 0);
}
}
/* 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(usf_state_t* state)
{
return (*dmem_u32(state, TASK_UCODE_BOOT_SIZE) <= 0x1000);
}
static void rsp_break(usf_state_t* state, unsigned int setbits)
{
SP_STATUS_REG |= setbits | SP_STATUS_BROKE | SP_STATUS_HALT;
if ((SP_STATUS_REG & SP_STATUS_INTR_ON_BREAK)) {
MI_INTR_REG |= MI_INTR_SP;
CheckInterrupts(state);
}
}
static bool try_fast_audio_dispatching(usf_state_t* state)
{
/* identify audio ucode by using the content of ucode_data */
uint32_t ucode_data = *dmem_u32(state, TASK_UCODE_DATA);
uint32_t v;
if (*dram_u32(state, ucode_data) == 0x00000001) {
if (*dram_u32(state, ucode_data + 0x30) == 0xf0000f00) {
v = *dram_u32(state, ucode_data + 0x28);
switch(v)
{
case 0x1e24138c: /* audio ABI (most common) */
alist_process_audio(state); return true;
case 0x1dc8138c: /* GoldenEye */
alist_process_audio_ge(state); return true;
case 0x1e3c1390: /* BlastCorp, DiddyKongRacing */
alist_process_audio_bc(state); return true;
default:
DebugMessage(state, M64MSG_WARNING, "ABI1 identification regression: v=%08x", v);
}
} else {
v = *dram_u32(state, ucode_data + 0x10);
switch(v)
{
case 0x11181350: /* MarioKart, WaveRace (E) */
alist_process_nead_mk(state); return true;
case 0x111812e0: /* StarFox (J) */
alist_process_nead_sfj(state); return true;
case 0x110412ac: /* WaveRace (J RevB) */
alist_process_nead_wrjb(state); return true;
case 0x110412cc: /* StarFox/LylatWars (except J) */
alist_process_nead_sf(state); return true;
case 0x1cd01250: /* FZeroX */
alist_process_nead_fz(state); return true;
case 0x1f08122c: /* YoshisStory */
alist_process_nead_ys(state); return true;
case 0x1f38122c: /* 1080° Snowboarding */
alist_process_nead_1080(state); return true;
case 0x1f681230: /* Zelda OoT / Zelda MM (J, J RevA) */
alist_process_nead_oot(state); return true;
case 0x1f801250: /* Zelda MM (except J, J RevA, E Beta), PokemonStadium 2 */
alist_process_nead_mm(state); return true;
case 0x109411f8: /* Zelda MM (E Beta) */
alist_process_nead_mmb(state); return true;
case 0x1eac11b8: /* AnimalCrossing */
alist_process_nead_ac(state); return true;
case 0x00010010: /* MusyX v2 (IndianaJones, BattleForNaboo) */
musyx_v2_task(state); return true;
default:
DebugMessage(state, M64MSG_WARNING, "ABI2 identification regression: v=%08x", v);
}
}
} else {
v = *dram_u32(state, ucode_data + 0x10);
switch(v)
{
case 0x00000001: /* MusyX v1
RogueSquadron, ResidentEvil2, PolarisSnoCross,
TheWorldIsNotEnough, RugratsInParis, NBAShowTime,
HydroThunder, Tarzan, GauntletLegend, Rush2049 */
musyx_v1_task(state); return true;
case 0x0000127c: /* naudio (many games) */
alist_process_naudio(state); return true;
case 0x00001280: /* BanjoKazooie */
alist_process_naudio_bk(state); return true;
case 0x1c58126c: /* DonkeyKong */
alist_process_naudio_dk(state); return true;
case 0x1ae8143c: /* BanjoTooie, JetForceGemini, MickeySpeedWayUSA, PerfectDark */
alist_process_naudio_mp3(state); return true;
case 0x1ab0140c: /* ConkerBadFurDay */
alist_process_naudio_cbfd(state); return true;
default:
DebugMessage(state, M64MSG_WARNING, "ABI3 identification regression: v=%08x", v);
}
}
return false;
}
static bool try_fast_task_dispatching(usf_state_t* state)
{
/* identify task ucode by its type */
switch (*dmem_u32(state, TASK_TYPE)) {
case 1:
/*if (FORWARD_GFX) {
forward_gfx_task();
return true;
}*/
break;
case 2:
/*if (FORWARD_AUDIO) {
forward_audio_task();
return true;
} else*/ if (try_fast_audio_dispatching(state))
return true;
break;
case 7:
/*show_cfb();*/
return true;
}
return false;
}
static void normal_task_dispatching(usf_state_t* state)
{
const unsigned int sum =
sum_bytes((void*)dram_u32(state, *dmem_u32(state, TASK_UCODE)), min(*dmem_u32(state, 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(state);
return;
/* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */
case 0x2caa6:
jpeg_decode_PS(state);
return;
/* JPEG: found in Ogre Battle, Bottom of the 9th */
case 0x130de:
case 0x278b0:
jpeg_decode_OB(state);
return;
}
DebugMessage(state, M64MSG_WARNING, "unknown OSTask: sum: %x PC:%x", sum, SP_PC_REG);
#ifdef ENABLE_TASK_DUMP
dump_unknown_task(state, sum);
#endif
}
static void non_task_dispatching(usf_state_t* state)
{
const unsigned int sum = sum_bytes(state->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(state);
return;
}
DebugMessage(state, M64MSG_WARNING, "unknown RSP code: sum: %x PC:%x", sum, SP_PC_REG);
#ifdef ENABLE_TASK_DUMP
dump_unknown_non_task(state, sum);
#endif
}
#ifdef ENABLE_TASK_DUMP
static void dump_unknown_task(usf_state_t* state, unsigned int sum)
{
char filename[256];
uint32_t ucode = *dmem_u32(state, TASK_UCODE);
uint32_t ucode_data = *dmem_u32(state, TASK_UCODE_DATA);
uint32_t data_ptr = *dmem_u32(state, TASK_DATA_PTR);
sprintf(&filename[0], "task_%x.log", sum);
dump_task(state, filename);
/* dump ucode_boot */
sprintf(&filename[0], "ucode_boot_%x.bin", sum);
dump_binary(state, filename, (void*)dram_u32(state, *dmem_u32(state, TASK_UCODE_BOOT)), *dmem_u32(state, TASK_UCODE_BOOT_SIZE));
/* dump ucode */
if (ucode != 0) {
sprintf(&filename[0], "ucode_%x.bin", sum);
dump_binary(state, filename, (void*)dram_u32(state, ucode), 0xf80);
}
/* dump ucode_data */
if (ucode_data != 0) {
sprintf(&filename[0], "ucode_data_%x.bin", sum);
dump_binary(state, filename, (void*)dram_u32(state, ucode_data), *dmem_u32(state, TASK_UCODE_DATA_SIZE));
}
/* dump data */
if (data_ptr != 0) {
sprintf(&filename[0], "data_%x.bin", sum);
dump_binary(state, filename, (void*)dram_u32(state, data_ptr), *dmem_u32(state, TASK_DATA_SIZE));
}
}
static void dump_unknown_non_task(usf_state_t* state, unsigned int sum)
{
char filename[256];
/* dump IMEM & DMEM for further analysis */
sprintf(&filename[0], "imem_%x.bin", sum);
dump_binary(state, filename, state->IMEM, 0x1000);
sprintf(&filename[0], "dmem_%x.bin", sum);
dump_binary(state, filename, state->DMEM, 0x1000);
}
static void dump_binary(usf_state_t* state, 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(state, M64MSG_ERROR, "Writing error on %s", filename);
fclose(f);
} else
DebugMessage(state, M64MSG_ERROR, "Couldn't open %s for writing !", filename);
} else
fclose(f);
}
static void dump_task(usf_state_t* state, 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(state, TASK_TYPE),
*dmem_u32(state, TASK_FLAGS),
*dmem_u32(state, TASK_UCODE_BOOT), *dmem_u32(state, TASK_UCODE_BOOT_SIZE),
*dmem_u32(state, TASK_UCODE), *dmem_u32(state, TASK_UCODE_SIZE),
*dmem_u32(state, TASK_UCODE_DATA), *dmem_u32(state, TASK_UCODE_DATA_SIZE),
*dmem_u32(state, TASK_DRAM_STACK), *dmem_u32(state, TASK_DRAM_STACK_SIZE),
*dmem_u32(state, TASK_OUTPUT_BUFF), *dmem_u32(state, TASK_OUTPUT_BUFF_SIZE),
*dmem_u32(state, TASK_DATA_PTR), *dmem_u32(state, TASK_DATA_SIZE),
*dmem_u32(state, TASK_YIELD_DATA_PTR), *dmem_u32(state, TASK_YIELD_DATA_SIZE));
fclose(f);
} else
fclose(f);
}
#endif

View File

@ -21,107 +21,103 @@
#include <string.h>
#include "../usf.h"
#include "memory.h"
#include "../usf_internal.h"
/* Global functions */
void dmem_load_u8 (usf_state_t* state, uint8_t* dst, uint16_t address, size_t count)
void dmem_load_u8(struct hle_t* hle, uint8_t* dst, uint16_t address, size_t count)
{
while (count != 0) {
*(dst++) = *dmem_u8(state, address);
*(dst++) = *dmem_u8(hle, address);
address += 1;
--count;
}
}
void dmem_load_u16(usf_state_t* state, uint16_t* dst, uint16_t address, size_t count)
void dmem_load_u16(struct hle_t* hle, uint16_t* dst, uint16_t address, size_t count)
{
while (count != 0) {
*(dst++) = *dmem_u16(state, address);
*(dst++) = *dmem_u16(hle, address);
address += 2;
--count;
}
}
void dmem_load_u32(usf_state_t* state, uint32_t* dst, uint16_t address, size_t count)
void dmem_load_u32(struct hle_t* hle, uint32_t* dst, uint16_t address, size_t count)
{
/* Optimization for uint32_t */
memcpy(dst, dmem_u32(state, address), count * sizeof(uint32_t));
memcpy(dst, dmem_u32(hle, address), count * sizeof(uint32_t));
}
void dmem_store_u8 (usf_state_t* state, const uint8_t* src, uint16_t address, size_t count)
void dmem_store_u8(struct hle_t* hle, const uint8_t* src, uint16_t address, size_t count)
{
while (count != 0) {
*dmem_u8(state, address) = *(src++);
*dmem_u8(hle, address) = *(src++);
address += 1;
--count;
}
}
void dmem_store_u16(usf_state_t* state, const uint16_t* src, uint16_t address, size_t count)
void dmem_store_u16(struct hle_t* hle, const uint16_t* src, uint16_t address, size_t count)
{
while (count != 0) {
*dmem_u16(state, address) = *(src++);
*dmem_u16(hle, address) = *(src++);
address += 2;
--count;
}
}
void dmem_store_u32(usf_state_t* state, const uint32_t* src, uint16_t address, size_t count)
void dmem_store_u32(struct hle_t* hle, const uint32_t* src, uint16_t address, size_t count)
{
/* Optimization for uint32_t */
memcpy(dmem_u32(state, address), src, count * sizeof(uint32_t));
memcpy(dmem_u32(hle, address), src, count * sizeof(uint32_t));
}
void dram_load_u8 (usf_state_t* state, uint8_t* dst, uint32_t address, size_t count)
void dram_load_u8(struct hle_t* hle, uint8_t* dst, uint32_t address, size_t count)
{
while (count != 0) {
*(dst++) = *dram_u8(state, address);
*(dst++) = *dram_u8(hle, address);
address += 1;
--count;
}
}
void dram_load_u16(usf_state_t* state, uint16_t* dst, uint32_t address, size_t count)
void dram_load_u16(struct hle_t* hle, uint16_t* dst, uint32_t address, size_t count)
{
while (count != 0) {
*(dst++) = *dram_u16(state, address);
*(dst++) = *dram_u16(hle, address);
address += 2;
--count;
}
}
void dram_load_u32(usf_state_t* state, uint32_t* dst, uint32_t address, size_t count)
void dram_load_u32(struct hle_t* hle, uint32_t* dst, uint32_t address, size_t count)
{
/* Optimization for uint32_t */
memcpy(dst, dram_u32(state, address), count * sizeof(uint32_t));
memcpy(dst, dram_u32(hle, address), count * sizeof(uint32_t));
}
void dram_store_u8 (usf_state_t* state, const uint8_t* src, uint32_t address, size_t count)
void dram_store_u8(struct hle_t* hle, const uint8_t* src, uint32_t address, size_t count)
{
while (count != 0) {
*dram_u8(state, address) = *(src++);
*dram_u8(hle, address) = *(src++);
address += 1;
--count;
}
}
void dram_store_u16(usf_state_t* state, const uint16_t* src, uint32_t address, size_t count)
void dram_store_u16(struct hle_t* hle, const uint16_t* src, uint32_t address, size_t count)
{
while (count != 0) {
*dram_u16(state, address) = *(src++);
*dram_u16(hle, address) = *(src++);
address += 2;
--count;
}
}
void dram_store_u32(usf_state_t* state, const uint32_t* src, uint32_t address, size_t count)
void dram_store_u32(struct hle_t* hle, const uint32_t* src, uint32_t address, size_t count)
{
/* Optimization for uint32_t */
memcpy(dram_u32(state, address), src, count * sizeof(uint32_t));
memcpy(dram_u32(hle, address), src, count * sizeof(uint32_t));
}

View File

@ -26,10 +26,7 @@
#include <stddef.h>
#include <stdint.h>
#include "../usf.h"
#include "../usf_internal.h"
#include "plugin.h"
#include "hle_internal.h"
#ifdef M64P_BIG_ENDIAN
#define S 0
@ -60,59 +57,65 @@ enum {
TASK_YIELD_DATA_SIZE = 0xffc
};
static inline unsigned int align(unsigned int x, unsigned amount)
#ifdef _MSC_VER
#define INLINE __forceinline
#else
#define INLINE __attribute__((always_inline))
#endif
INLINE static unsigned int align(unsigned int x, unsigned amount)
{
--amount;
return (x + amount) & ~amount;
}
static inline uint8_t* const dmem_u8(usf_state_t* state, uint16_t address)
INLINE static uint8_t* const dmem_u8(struct hle_t* hle, uint16_t address)
{
return (uint8_t*)(&state->DMEM[(address & 0xfff) ^ S8]);
return (uint8_t*)(&hle->dmem[(address & 0xfff) ^ S8]);
}
static inline uint16_t* const dmem_u16(usf_state_t* state, uint16_t address)
INLINE static uint16_t* const dmem_u16(struct hle_t* hle, uint16_t address)
{
assert((address & 1) == 0);
return (uint16_t*)(&state->DMEM[(address & 0xfff) ^ S16]);
return (uint16_t*)(&hle->dmem[(address & 0xfff) ^ S16]);
}
static inline uint32_t* const dmem_u32(usf_state_t* state, uint16_t address)
INLINE static uint32_t* const dmem_u32(struct hle_t* hle, uint16_t address)
{
assert((address & 3) == 0);
return (uint32_t*)(&state->DMEM[(address & 0xfff)]);
return (uint32_t*)(&hle->dmem[(address & 0xfff)]);
}
static inline uint8_t* const dram_u8(usf_state_t* state, uint32_t address)
INLINE static uint8_t* const dram_u8(struct hle_t* hle, uint32_t address)
{
return (uint8_t*)&state->N64MEM[(address & 0xffffff) ^ S8];
return (uint8_t*)&hle->dram[(address & 0xffffff) ^ S8];
}
static inline uint16_t* const dram_u16(usf_state_t* state, uint32_t address)
INLINE static uint16_t* const dram_u16(struct hle_t* hle, uint32_t address)
{
assert((address & 1) == 0);
return (uint16_t*)&state->N64MEM[(address & 0xffffff) ^ S16];
return (uint16_t*)&hle->dram[(address & 0xffffff) ^ S16];
}
static inline uint32_t* const dram_u32(usf_state_t* state, uint32_t address)
INLINE static uint32_t* const dram_u32(struct hle_t* hle, uint32_t address)
{
assert((address & 3) == 0);
return (uint32_t*)&state->N64MEM[address & 0xffffff];
return (uint32_t*)&hle->dram[address & 0xffffff];
}
void dmem_load_u8 (usf_state_t* state, uint8_t* dst, uint16_t address, size_t count);
void dmem_load_u16(usf_state_t* state, uint16_t* dst, uint16_t address, size_t count);
void dmem_load_u32(usf_state_t* state, uint32_t* dst, uint16_t address, size_t count);
void dmem_store_u8 (usf_state_t* state, const uint8_t* src, uint16_t address, size_t count);
void dmem_store_u16(usf_state_t* state, const uint16_t* src, uint16_t address, size_t count);
void dmem_store_u32(usf_state_t* state, const uint32_t* src, uint16_t address, size_t count);
void dmem_load_u8 (struct hle_t* hle, uint8_t* dst, uint16_t address, size_t count);
void dmem_load_u16(struct hle_t* hle, uint16_t* dst, uint16_t address, size_t count);
void dmem_load_u32(struct hle_t* hle, uint32_t* dst, uint16_t address, size_t count);
void dmem_store_u8 (struct hle_t* hle, const uint8_t* src, uint16_t address, size_t count);
void dmem_store_u16(struct hle_t* hle, const uint16_t* src, uint16_t address, size_t count);
void dmem_store_u32(struct hle_t* hle, const uint32_t* src, uint16_t address, size_t count);
void dram_load_u8 (usf_state_t* state, uint8_t* dst, uint32_t address, size_t count);
void dram_load_u16(usf_state_t* state, uint16_t* dst, uint32_t address, size_t count);
void dram_load_u32(usf_state_t* state, uint32_t* dst, uint32_t address, size_t count);
void dram_store_u8 (usf_state_t* state, const uint8_t* src, uint32_t address, size_t count);
void dram_store_u16(usf_state_t* state, const uint16_t* src, uint32_t address, size_t count);
void dram_store_u32(usf_state_t* state, const uint32_t* src, uint32_t address, size_t count);
void dram_load_u8 (struct hle_t* hle, uint8_t* dst, uint32_t address, size_t count);
void dram_load_u16(struct hle_t* hle, uint16_t* dst, uint32_t address, size_t count);
void dram_load_u32(struct hle_t* hle, uint32_t* dst, uint32_t address, size_t count);
void dram_store_u8 (struct hle_t* hle, const uint8_t* src, uint32_t address, size_t count);
void dram_store_u16(struct hle_t* hle, const uint16_t* src, uint32_t address, size_t count);
void dram_store_u32(struct hle_t* hle, const uint32_t* src, uint32_t address, size_t count);
#endif

View File

@ -23,12 +23,9 @@
#include <string.h>
#include <stdint.h>
#include "../usf.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
#include "plugin.h"
#include "../usf_internal.h"
static const uint16_t DeWindowLUT [0x420] = {
0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
@ -165,7 +162,7 @@ static const uint16_t DeWindowLUT [0x420] = {
0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x0000
};
static void MP3AB0(usf_state_t* state)
static void MP3AB0(int32_t* v)
{
/* Part 2 - 100% Accurate */
static const uint16_t LUT2[8] = {
@ -176,35 +173,34 @@ static void MP3AB0(usf_state_t* state)
int i;
for (i = 0; i < 8; i++) {
state->mp3_v[16 + i] = state->mp3_v[0 + i] + state->mp3_v[8 + i];
state->mp3_v[24 + i] = ((state->mp3_v[0 + i] - state->mp3_v[8 + i]) * LUT2[i]) >> 0x10;
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++) {
state->mp3_v[0 + i] = state->mp3_v[16 + i] + state->mp3_v[20 + i];
state->mp3_v[4 + i] = ((state->mp3_v[16 + i] - state->mp3_v[20 + i]) * LUT3[i]) >> 0x10;
v[0 + i] = v[16 + i] + v[20 + i];
v[4 + i] = ((v[16 + i] - v[20 + i]) * LUT3[i]) >> 0x10;
state->mp3_v[8 + i] = state->mp3_v[24 + i] + state->mp3_v[28 + i];
state->mp3_v[12 + i] = ((state->mp3_v[24 + i] - state->mp3_v[28 + 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) {
state->mp3_v[16 + i] = state->mp3_v[0 + i] + state->mp3_v[2 + i];
state->mp3_v[18 + i] = ((state->mp3_v[0 + i] - state->mp3_v[2 + i]) * 0xEC84) >> 0x10;
v[16 + i] = v[0 + i] + v[2 + i];
v[18 + i] = ((v[0 + i] - v[2 + i]) * 0xEC84) >> 0x10;
state->mp3_v[17 + i] = state->mp3_v[1 + i] + state->mp3_v[3 + i];
state->mp3_v[19 + i] = ((state->mp3_v[1 + i] - state->mp3_v[3 + i]) * 0x61F8) >> 0x10;
v[17 + i] = v[1 + i] + v[3 + i];
v[19 + i] = ((v[1 + i] - v[3 + i]) * 0x61F8) >> 0x10;
}
}
static void InnerLoop(usf_state_t* state);
static void InnerLoop(struct hle_t* hle);
void MP3(usf_state_t* state, uint32_t w1, uint32_t w2)
void MP3(struct hle_t* hle, uint32_t w1, uint32_t w2)
{
/* Initialization Code */
uint32_t readPtr; /* s5 */
@ -213,37 +209,37 @@ void MP3(usf_state_t* state, uint32_t w1, uint32_t w2)
int cnt, cnt2;
/* I think these are temporary storage buffers */
state->mp3_t6 = 0x08A0;
state->mp3_t5 = 0x0AC0;
state->mp3_t4 = (w1 & 0x1E);
hle->mp3_t6 = 0x08A0;
hle->mp3_t5 = 0x0AC0;
hle->mp3_t4 = (w1 & 0x1E);
writePtr = w2 & 0xFFFFFF;
readPtr = writePtr;
/* Just do that for efficiency... may remove and use directly later anyway */
memcpy(state->mp3data + 0xCE8, state->N64MEM + readPtr, 8);
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(state->mp3data + 0xCF0, state->N64MEM + readPtr, 0x180);
state->mp3_inPtr = 0xCF0; /* s7 */
state->mp3_outPtr = 0xE70; /* s3 */
memcpy(hle->mp3_buffer + 0xCF0, hle->dram + readPtr, 0x180);
hle->mp3_inPtr = 0xCF0; /* s7 */
hle->mp3_outPtr = 0xE70; /* s3 */
/* --------------- Inner Loop Start -------------------- */
for (cnt2 = 0; cnt2 < 0x180; cnt2 += 0x40) {
state->mp3_t6 &= 0xFFE0;
state->mp3_t5 &= 0xFFE0;
state->mp3_t6 |= state->mp3_t4;
state->mp3_t5 |= state->mp3_t4;
InnerLoop(state);
state->mp3_t4 = (state->mp3_t4 - 2) & 0x1E;
tmp = state->mp3_t6;
state->mp3_t6 = state->mp3_t5;
state->mp3_t5 = tmp;
state->mp3_inPtr += 0x40;
hle->mp3_t6 &= 0xFFE0;
hle->mp3_t5 &= 0xFFE0;
hle->mp3_t6 |= hle->mp3_t4;
hle->mp3_t5 |= hle->mp3_t4;
InnerLoop(hle);
hle->mp3_t4 = (hle->mp3_t4 - 2) & 0x1E;
tmp = hle->mp3_t6;
hle->mp3_t6 = hle->mp3_t5;
hle->mp3_t5 = tmp;
hle->mp3_inPtr += 0x40;
}
/* --------------- Inner Loop End -------------------- */
memcpy(state->N64MEM + writePtr, state->mp3data + 0xe70, 0x180);
memcpy(hle->dram + writePtr, hle->mp3_buffer + 0xe70, 0x180);
writePtr += 0x180;
readPtr += 0x180;
}
@ -251,7 +247,7 @@ void MP3(usf_state_t* state, uint32_t w1, uint32_t w2)
static void InnerLoop(usf_state_t* state)
static void InnerLoop(struct hle_t* hle)
{
/* Part 1: 100% Accurate */
@ -277,310 +273,311 @@ static void InnerLoop(usf_state_t* state)
int32_t hi0;
int32_t hi1;
int32_t vt;
int32_t v[32];
state->mp3_v[0] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x00 ^ S16));
state->mp3_v[31] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3E ^ S16));
state->mp3_v[0] += state->mp3_v[31];
state->mp3_v[1] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x02 ^ S16));
state->mp3_v[30] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3C ^ S16));
state->mp3_v[1] += state->mp3_v[30];
state->mp3_v[2] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x06 ^ S16));
state->mp3_v[28] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x38 ^ S16));
state->mp3_v[2] += state->mp3_v[28];
state->mp3_v[3] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x04 ^ S16));
state->mp3_v[29] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3A ^ S16));
state->mp3_v[3] += state->mp3_v[29];
v[0] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x00 ^ S16));
v[31] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3E ^ S16));
v[0] += v[31];
v[1] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x02 ^ S16));
v[30] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3C ^ S16));
v[1] += v[30];
v[2] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x06 ^ S16));
v[28] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x38 ^ S16));
v[2] += v[28];
v[3] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x04 ^ S16));
v[29] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3A ^ S16));
v[3] += v[29];
state->mp3_v[4] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0E ^ S16));
state->mp3_v[24] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x30 ^ S16));
state->mp3_v[4] += state->mp3_v[24];
state->mp3_v[5] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0C ^ S16));
state->mp3_v[25] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x32 ^ S16));
state->mp3_v[5] += state->mp3_v[25];
state->mp3_v[6] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x08 ^ S16));
state->mp3_v[27] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x36 ^ S16));
state->mp3_v[6] += state->mp3_v[27];
state->mp3_v[7] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0A ^ S16));
state->mp3_v[26] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x34 ^ S16));
state->mp3_v[7] += state->mp3_v[26];
v[4] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0E ^ S16));
v[24] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x30 ^ S16));
v[4] += v[24];
v[5] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0C ^ S16));
v[25] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x32 ^ S16));
v[5] += v[25];
v[6] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x08 ^ S16));
v[27] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x36 ^ S16));
v[6] += v[27];
v[7] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0A ^ S16));
v[26] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x34 ^ S16));
v[7] += v[26];
state->mp3_v[8] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1E ^ S16));
state->mp3_v[16] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x20 ^ S16));
state->mp3_v[8] += state->mp3_v[16];
state->mp3_v[9] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1C ^ S16));
state->mp3_v[17] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x22 ^ S16));
state->mp3_v[9] += state->mp3_v[17];
state->mp3_v[10] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x18 ^ S16));
state->mp3_v[19] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x26 ^ S16));
state->mp3_v[10] += state->mp3_v[19];
state->mp3_v[11] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1A ^ S16));
state->mp3_v[18] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x24 ^ S16));
state->mp3_v[11] += state->mp3_v[18];
v[8] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1E ^ S16));
v[16] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x20 ^ S16));
v[8] += v[16];
v[9] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1C ^ S16));
v[17] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x22 ^ S16));
v[9] += v[17];
v[10] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x18 ^ S16));
v[19] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x26 ^ S16));
v[10] += v[19];
v[11] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1A ^ S16));
v[18] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x24 ^ S16));
v[11] += v[18];
state->mp3_v[12] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x10 ^ S16));
state->mp3_v[23] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2E ^ S16));
state->mp3_v[12] += state->mp3_v[23];
state->mp3_v[13] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x12 ^ S16));
state->mp3_v[22] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2C ^ S16));
state->mp3_v[13] += state->mp3_v[22];
state->mp3_v[14] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x16 ^ S16));
state->mp3_v[20] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x28 ^ S16));
state->mp3_v[14] += state->mp3_v[20];
state->mp3_v[15] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x14 ^ S16));
state->mp3_v[21] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2A ^ S16));
state->mp3_v[15] += state->mp3_v[21];
v[12] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x10 ^ S16));
v[23] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2E ^ S16));
v[12] += v[23];
v[13] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x12 ^ S16));
v[22] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2C ^ S16));
v[13] += v[22];
v[14] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x16 ^ S16));
v[20] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x28 ^ S16));
v[14] += v[20];
v[15] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x14 ^ S16));
v[21] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2A ^ S16));
v[15] += v[21];
/* Part 2-4 */
MP3AB0(state);
MP3AB0(v);
/* Part 5 - 1-Wide Butterflies - 100% Accurate but need SSVs!!! */
t0 = state->mp3_t6 + 0x100;
t1 = state->mp3_t6 + 0x200;
t2 = state->mp3_t5 + 0x100;
t3 = state->mp3_t5 + 0x200;
t0 = hle->mp3_t6 + 0x100;
t1 = hle->mp3_t6 + 0x200;
t2 = hle->mp3_t5 + 0x100;
t3 = hle->mp3_t5 + 0x200;
/* 0x13A8 */
state->mp3_v[1] = 0;
state->mp3_v[11] = ((state->mp3_v[16] - state->mp3_v[17]) * 0xB504) >> 0x10;
v[1] = 0;
v[11] = ((v[16] - v[17]) * 0xB504) >> 0x10;
state->mp3_v[16] = -state->mp3_v[16] - state->mp3_v[17];
state->mp3_v[2] = state->mp3_v[18] + state->mp3_v[19];
/* ** Store state->mp3_v[11] -> (T6 + 0)** */
*(int16_t *)(state->mp3data + ((state->mp3_t6 + (short)0x0))) = (short)state->mp3_v[11];
v[16] = -v[16] - v[17];
v[2] = v[18] + v[19];
/* ** Store v[11] -> (T6 + 0)** */
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_t6 + (short)0x0))) = (short)v[11];
state->mp3_v[11] = -state->mp3_v[11];
/* ** Store state->mp3_v[16] -> (T3 + 0)** */
*(int16_t *)(state->mp3data + ((t3 + (short)0x0))) = (short)state->mp3_v[16];
/* ** Store state->mp3_v[11] -> (T5 + 0)** */
*(int16_t *)(state->mp3data + ((state->mp3_t5 + (short)0x0))) = (short)state->mp3_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 + ((hle->mp3_t5 + (short)0x0))) = (short)v[11];
/* 0x13E8 - Verified.... */
state->mp3_v[2] = -state->mp3_v[2];
/* ** Store state->mp3_v[2] -> (T2 + 0)** */
*(int16_t *)(state->mp3data + ((t2 + (short)0x0))) = (short)state->mp3_v[2];
state->mp3_v[3] = (((state->mp3_v[18] - state->mp3_v[19]) * 0x16A09) >> 0x10) + state->mp3_v[2];
/* ** Store state->mp3_v[3] -> (T0 + 0)** */
*(int16_t *)(state->mp3data + ((t0 + (short)0x0))) = (short)state->mp3_v[3];
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 */
state->mp3_v[4] = -state->mp3_v[20] - state->mp3_v[21];
state->mp3_v[6] = state->mp3_v[22] + state->mp3_v[23];
state->mp3_v[5] = ((state->mp3_v[20] - state->mp3_v[21]) * 0x16A09) >> 0x10;
/* ** Store state->mp3_v[4] -> (T3 + 0xFF80) */
*(int16_t *)(state->mp3data + ((t3 + (short)0xFF80))) = (short)state->mp3_v[4];
state->mp3_v[7] = ((state->mp3_v[22] - state->mp3_v[23]) * 0x2D413) >> 0x10;
state->mp3_v[5] = state->mp3_v[5] - state->mp3_v[4];
state->mp3_v[7] = state->mp3_v[7] - state->mp3_v[5];
state->mp3_v[6] = state->mp3_v[6] + state->mp3_v[6];
state->mp3_v[5] = state->mp3_v[5] - state->mp3_v[6];
state->mp3_v[4] = -state->mp3_v[4] - state->mp3_v[6];
/* *** Store state->mp3_v[7] -> (T1 + 0xFF80) */
*(int16_t *)(state->mp3data + ((t1 + (short)0xFF80))) = (short)state->mp3_v[7];
/* *** Store state->mp3_v[4] -> (T2 + 0xFF80) */
*(int16_t *)(state->mp3data + ((t2 + (short)0xFF80))) = (short)state->mp3_v[4];
/* *** Store state->mp3_v[5] -> (T0 + 0xFF80) */
*(int16_t *)(state->mp3data + ((t0 + (short)0xFF80))) = (short)state->mp3_v[5];
state->mp3_v[8] = state->mp3_v[24] + state->mp3_v[25];
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];
state->mp3_v[9] = ((state->mp3_v[24] - state->mp3_v[25]) * 0x16A09) >> 0x10;
state->mp3_v[2] = state->mp3_v[8] + state->mp3_v[9];
state->mp3_v[11] = ((state->mp3_v[26] - state->mp3_v[27]) * 0x2D413) >> 0x10;
state->mp3_v[13] = ((state->mp3_v[28] - state->mp3_v[29]) * 0x2D413) >> 0x10;
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;
state->mp3_v[10] = state->mp3_v[26] + state->mp3_v[27];
state->mp3_v[10] = state->mp3_v[10] + state->mp3_v[10];
state->mp3_v[12] = state->mp3_v[28] + state->mp3_v[29];
state->mp3_v[12] = state->mp3_v[12] + state->mp3_v[12];
state->mp3_v[14] = state->mp3_v[30] + state->mp3_v[31];
state->mp3_v[3] = state->mp3_v[8] + state->mp3_v[10];
state->mp3_v[14] = state->mp3_v[14] + state->mp3_v[14];
state->mp3_v[13] = (state->mp3_v[13] - state->mp3_v[2]) + state->mp3_v[12];
state->mp3_v[15] = (((state->mp3_v[30] - state->mp3_v[31]) * 0x5A827) >> 0x10) - (state->mp3_v[11] + state->mp3_v[2]);
state->mp3_v[14] = -(state->mp3_v[14] + state->mp3_v[14]) + state->mp3_v[3];
state->mp3_v[17] = state->mp3_v[13] - state->mp3_v[10];
state->mp3_v[9] = state->mp3_v[9] + state->mp3_v[14];
/* ** Store state->mp3_v[9] -> (T6 + 0x40) */
*(int16_t *)(state->mp3data + ((state->mp3_t6 + (short)0x40))) = (short)state->mp3_v[9];
state->mp3_v[11] = state->mp3_v[11] - state->mp3_v[13];
/* ** Store state->mp3_v[17] -> (T0 + 0xFFC0) */
*(int16_t *)(state->mp3data + ((t0 + (short)0xFFC0))) = (short)state->mp3_v[17];
state->mp3_v[12] = state->mp3_v[8] - state->mp3_v[12];
/* ** Store state->mp3_v[11] -> (T0 + 0x40) */
*(int16_t *)(state->mp3data + ((t0 + (short)0x40))) = (short)state->mp3_v[11];
state->mp3_v[8] = -state->mp3_v[8];
/* ** Store state->mp3_v[15] -> (T1 + 0xFFC0) */
*(int16_t *)(state->mp3data + ((t1 + (short)0xFFC0))) = (short)state->mp3_v[15];
state->mp3_v[10] = -state->mp3_v[10] - state->mp3_v[12];
/* ** Store state->mp3_v[12] -> (T2 + 0x40) */
*(int16_t *)(state->mp3data + ((t2 + (short)0x40))) = (short)state->mp3_v[12];
/* ** Store state->mp3_v[8] -> (T3 + 0xFFC0) */
*(int16_t *)(state->mp3data + ((t3 + (short)0xFFC0))) = (short)state->mp3_v[8];
/* ** Store state->mp3_v[14] -> (T5 + 0x40) */
*(int16_t *)(state->mp3data + ((state->mp3_t5 + (short)0x40))) = (short)state->mp3_v[14];
/* ** Store state->mp3_v[10] -> (T2 + 0xFFC0) */
*(int16_t *)(state->mp3data + ((t2 + (short)0xFFC0))) = (short)state->mp3_v[10];
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 + ((hle->mp3_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 + ((hle->mp3_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 */
state->mp3_v[0] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x00 ^ S16));
state->mp3_v[31] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3E ^ S16));
state->mp3_v[0] -= state->mp3_v[31];
state->mp3_v[1] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x02 ^ S16));
state->mp3_v[30] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3C ^ S16));
state->mp3_v[1] -= state->mp3_v[30];
state->mp3_v[2] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x06 ^ S16));
state->mp3_v[28] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x38 ^ S16));
state->mp3_v[2] -= state->mp3_v[28];
state->mp3_v[3] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x04 ^ S16));
state->mp3_v[29] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x3A ^ S16));
state->mp3_v[3] -= state->mp3_v[29];
v[0] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x00 ^ S16));
v[31] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3E ^ S16));
v[0] -= v[31];
v[1] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x02 ^ S16));
v[30] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3C ^ S16));
v[1] -= v[30];
v[2] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x06 ^ S16));
v[28] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x38 ^ S16));
v[2] -= v[28];
v[3] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x04 ^ S16));
v[29] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x3A ^ S16));
v[3] -= v[29];
state->mp3_v[4] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0E ^ S16));
state->mp3_v[24] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x30 ^ S16));
state->mp3_v[4] -= state->mp3_v[24];
state->mp3_v[5] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0C ^ S16));
state->mp3_v[25] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x32 ^ S16));
state->mp3_v[5] -= state->mp3_v[25];
state->mp3_v[6] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x08 ^ S16));
state->mp3_v[27] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x36 ^ S16));
state->mp3_v[6] -= state->mp3_v[27];
state->mp3_v[7] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x0A ^ S16));
state->mp3_v[26] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x34 ^ S16));
state->mp3_v[7] -= state->mp3_v[26];
v[4] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0E ^ S16));
v[24] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x30 ^ S16));
v[4] -= v[24];
v[5] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0C ^ S16));
v[25] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x32 ^ S16));
v[5] -= v[25];
v[6] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x08 ^ S16));
v[27] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x36 ^ S16));
v[6] -= v[27];
v[7] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x0A ^ S16));
v[26] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x34 ^ S16));
v[7] -= v[26];
state->mp3_v[8] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1E ^ S16));
state->mp3_v[16] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x20 ^ S16));
state->mp3_v[8] -= state->mp3_v[16];
state->mp3_v[9] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1C ^ S16));
state->mp3_v[17] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x22 ^ S16));
state->mp3_v[9] -= state->mp3_v[17];
state->mp3_v[10] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x18 ^ S16));
state->mp3_v[19] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x26 ^ S16));
state->mp3_v[10] -= state->mp3_v[19];
state->mp3_v[11] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x1A ^ S16));
state->mp3_v[18] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x24 ^ S16));
state->mp3_v[11] -= state->mp3_v[18];
v[8] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1E ^ S16));
v[16] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x20 ^ S16));
v[8] -= v[16];
v[9] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1C ^ S16));
v[17] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x22 ^ S16));
v[9] -= v[17];
v[10] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x18 ^ S16));
v[19] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x26 ^ S16));
v[10] -= v[19];
v[11] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x1A ^ S16));
v[18] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x24 ^ S16));
v[11] -= v[18];
state->mp3_v[12] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x10 ^ S16));
state->mp3_v[23] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2E ^ S16));
state->mp3_v[12] -= state->mp3_v[23];
state->mp3_v[13] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x12 ^ S16));
state->mp3_v[22] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2C ^ S16));
state->mp3_v[13] -= state->mp3_v[22];
state->mp3_v[14] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x16 ^ S16));
state->mp3_v[20] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x28 ^ S16));
state->mp3_v[14] -= state->mp3_v[20];
state->mp3_v[15] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x14 ^ S16));
state->mp3_v[21] = *(int16_t *)(state->mp3data + state->mp3_inPtr + (0x2A ^ S16));
state->mp3_v[15] -= state->mp3_v[21];
v[12] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x10 ^ S16));
v[23] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2E ^ S16));
v[12] -= v[23];
v[13] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x12 ^ S16));
v[22] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2C ^ S16));
v[13] -= v[22];
v[14] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x16 ^ S16));
v[20] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x28 ^ S16));
v[14] -= v[20];
v[15] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x14 ^ S16));
v[21] = *(int16_t *)(hle->mp3_buffer + hle->mp3_inPtr + (0x2A ^ S16));
v[15] -= v[21];
for (i = 0; i < 16; i++)
state->mp3_v[0 + i] = (state->mp3_v[0 + i] * LUT6[i]) >> 0x10;
state->mp3_v[0] = state->mp3_v[0] + state->mp3_v[0];
state->mp3_v[1] = state->mp3_v[1] + state->mp3_v[1];
state->mp3_v[2] = state->mp3_v[2] + state->mp3_v[2];
state->mp3_v[3] = state->mp3_v[3] + state->mp3_v[3];
state->mp3_v[4] = state->mp3_v[4] + state->mp3_v[4];
state->mp3_v[5] = state->mp3_v[5] + state->mp3_v[5];
state->mp3_v[6] = state->mp3_v[6] + state->mp3_v[6];
state->mp3_v[7] = state->mp3_v[7] + state->mp3_v[7];
state->mp3_v[12] = state->mp3_v[12] + state->mp3_v[12];
state->mp3_v[13] = state->mp3_v[13] + state->mp3_v[13];
state->mp3_v[15] = state->mp3_v[15] + state->mp3_v[15];
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(state);
MP3AB0(v);
/* Part 7: - 100% Accurate + SSV - Unoptimized */
state->mp3_v[0] = (state->mp3_v[17] + state->mp3_v[16]) >> 1;
state->mp3_v[1] = ((state->mp3_v[17] * (int)((short)0xA57E * 2)) + (state->mp3_v[16] * 0xB504)) >> 0x10;
state->mp3_v[2] = -state->mp3_v[18] - state->mp3_v[19];
state->mp3_v[3] = ((state->mp3_v[18] - state->mp3_v[19]) * 0x16A09) >> 0x10;
state->mp3_v[4] = state->mp3_v[20] + state->mp3_v[21] + state->mp3_v[0];
state->mp3_v[5] = (((state->mp3_v[20] - state->mp3_v[21]) * 0x16A09) >> 0x10) + state->mp3_v[1];
state->mp3_v[6] = (((state->mp3_v[22] + state->mp3_v[23]) << 1) + state->mp3_v[0]) - state->mp3_v[2];
state->mp3_v[7] = (((state->mp3_v[22] - state->mp3_v[23]) * 0x2D413) >> 0x10) + state->mp3_v[0] + state->mp3_v[1] + state->mp3_v[3];
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 state->mp3_v[0] -> (T3 + 0xFFE0) */
*(int16_t *)(state->mp3data + ((t3 + (short)0xFFE0))) = (short) - state->mp3_v[0];
state->mp3_v[8] = state->mp3_v[24] + state->mp3_v[25];
state->mp3_v[9] = ((state->mp3_v[24] - state->mp3_v[25]) * 0x16A09) >> 0x10;
state->mp3_v[10] = ((state->mp3_v[26] + state->mp3_v[27]) << 1) + state->mp3_v[8];
state->mp3_v[11] = (((state->mp3_v[26] - state->mp3_v[27]) * 0x2D413) >> 0x10) + state->mp3_v[8] + state->mp3_v[9];
state->mp3_v[12] = state->mp3_v[4] - ((state->mp3_v[28] + state->mp3_v[29]) << 1);
/* 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 *)(state->mp3data + ((t2 + (short)0x20))) = (short)state->mp3_v[12];
state->mp3_v[13] = (((state->mp3_v[28] - state->mp3_v[29]) * 0x2D413) >> 0x10) - state->mp3_v[12] - state->mp3_v[5];
state->mp3_v[14] = state->mp3_v[30] + state->mp3_v[31];
state->mp3_v[14] = state->mp3_v[14] + state->mp3_v[14];
state->mp3_v[14] = state->mp3_v[14] + state->mp3_v[14];
state->mp3_v[14] = state->mp3_v[6] - state->mp3_v[14];
state->mp3_v[15] = (((state->mp3_v[30] - state->mp3_v[31]) * 0x5A827) >> 0x10) - state->mp3_v[7];
*(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 *)(state->mp3data + ((state->mp3_t5 + (short)0x20))) = (short)state->mp3_v[14];
state->mp3_v[14] = state->mp3_v[14] + state->mp3_v[1];
/* Store state->mp3_v[14] -> (T6 + 0x20) */
*(int16_t *)(state->mp3data + ((state->mp3_t6 + (short)0x20))) = (short)state->mp3_v[14];
/* Store state->mp3_v[15] -> (T1 + 0xFFE0) */
*(int16_t *)(state->mp3data + ((t1 + (short)0xFFE0))) = (short)state->mp3_v[15];
state->mp3_v[9] = state->mp3_v[9] + state->mp3_v[10];
state->mp3_v[1] = state->mp3_v[1] + state->mp3_v[6];
state->mp3_v[6] = state->mp3_v[10] - state->mp3_v[6];
state->mp3_v[1] = state->mp3_v[9] - state->mp3_v[1];
/* Store state->mp3_v[6] -> (T5 + 0x60) */
*(int16_t *)(state->mp3data + ((state->mp3_t5 + (short)0x60))) = (short)state->mp3_v[6];
state->mp3_v[10] = state->mp3_v[10] + state->mp3_v[2];
state->mp3_v[10] = state->mp3_v[4] - state->mp3_v[10];
/* Store state->mp3_v[10] -> (T2 + 0xFFA0) */
*(int16_t *)(state->mp3data + ((t2 + (short)0xFFA0))) = (short)state->mp3_v[10];
state->mp3_v[12] = state->mp3_v[2] - state->mp3_v[12];
/* Store state->mp3_v[12] -> (T2 + 0xFFE0) */
*(int16_t *)(state->mp3data + ((t2 + (short)0xFFE0))) = (short)state->mp3_v[12];
state->mp3_v[5] = state->mp3_v[4] + state->mp3_v[5];
state->mp3_v[4] = state->mp3_v[8] - state->mp3_v[4];
/* Store state->mp3_v[4] -> (T2 + 0x60) */
*(int16_t *)(state->mp3data + ((t2 + (short)0x60))) = (short)state->mp3_v[4];
state->mp3_v[0] = state->mp3_v[0] - state->mp3_v[8];
/* Store state->mp3_v[0] -> (T3 + 0xFFA0) */
*(int16_t *)(state->mp3data + ((t3 + (short)0xFFA0))) = (short)state->mp3_v[0];
state->mp3_v[7] = state->mp3_v[7] - state->mp3_v[11];
/* Store state->mp3_v[7] -> (T1 + 0xFFA0) */
*(int16_t *)(state->mp3data + ((t1 + (short)0xFFA0))) = (short)state->mp3_v[7];
state->mp3_v[11] = state->mp3_v[11] - state->mp3_v[3];
/* Store state->mp3_v[1] -> (T6 + 0x60) */
*(int16_t *)(state->mp3data + ((state->mp3_t6 + (short)0x60))) = (short)state->mp3_v[1];
state->mp3_v[11] = state->mp3_v[11] - state->mp3_v[5];
/* Store state->mp3_v[11] -> (T0 + 0x60) */
*(int16_t *)(state->mp3data + ((t0 + (short)0x60))) = (short)state->mp3_v[11];
state->mp3_v[3] = state->mp3_v[3] - state->mp3_v[13];
/* Store state->mp3_v[3] -> (T0 + 0x20) */
*(int16_t *)(state->mp3data + ((t0 + (short)0x20))) = (short)state->mp3_v[3];
state->mp3_v[13] = state->mp3_v[13] + state->mp3_v[2];
/* Store state->mp3_v[13] -> (T0 + 0xFFE0) */
*(int16_t *)(state->mp3data + ((t0 + (short)0xFFE0))) = (short)state->mp3_v[13];
state->mp3_v[2] = (state->mp3_v[5] - state->mp3_v[2]) - state->mp3_v[9];
/* Store state->mp3_v[2] -> (T0 + 0xFFA0) */
*(int16_t *)(state->mp3data + ((t0 + (short)0xFFA0))) = (short)state->mp3_v[2];
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_t5 + (short)0x20))) = (short)v[14];
v[14] = v[14] + v[1];
/* Store v[14] -> (T6 + 0x20) */
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_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 + ((hle->mp3_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 + ((hle->mp3_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 = state->mp3_t6 & 0xFFE0;
addptr = hle->mp3_t6 & 0xFFE0;
offset = 0x10 - (state->mp3_t4 >> 1);
offset = 0x10 - (hle->mp3_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 *)(state->mp3data + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
v4 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
v6 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x20) * (short)DeWindowLUT[offset + 0x20] + 0x4000) >> 0xF;
v8 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x30) * (short)DeWindowLUT[offset + 0x28] + 0x4000) >> 0xF;
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++;
}
@ -589,34 +586,34 @@ static void InnerLoop(usf_state_t* state)
/* Clamp(v0); */
/* Clamp(v18); */
/* clamp??? */
*(int16_t *)(state->mp3data + (state->mp3_outPtr ^ S16)) = v0;
*(int16_t *)(state->mp3data + ((state->mp3_outPtr + 2)^S16)) = v18;
state->mp3_outPtr += 4;
*(int16_t *)(hle->mp3_buffer + (hle->mp3_outPtr ^ S16)) = v0;
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_outPtr + 2)^S16)) = v18;
hle->mp3_outPtr += 4;
addptr += 0x30;
offset += 0x38;
}
offset = 0x10 - (state->mp3_t4 >> 1) + 8 * 0x40;
offset = 0x10 - (hle->mp3_t4 >> 1) + 8 * 0x40;
v2 = v4 = 0;
for (i = 0; i < 4; i++) {
v2 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
v2 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
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 *)(state->mp3data + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
v4 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
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 *)(state->mp3data + 0xCE8);
mult4 = *(int32_t *)(state->mp3data + 0xCEC);
if (state->mp3_t4 & 0x2) {
v2 = (v2 **(uint32_t *)(state->mp3data + 0xCE8)) >> 0x10;
*(int16_t *)(state->mp3data + (state->mp3_outPtr ^ S16)) = v2;
mult6 = *(int32_t *)(hle->mp3_buffer + 0xCE8);
mult4 = *(int32_t *)(hle->mp3_buffer + 0xCEC);
if (hle->mp3_t4 & 0x2) {
v2 = (v2 **(uint32_t *)(hle->mp3_buffer + 0xCE8)) >> 0x10;
*(int16_t *)(hle->mp3_buffer + (hle->mp3_outPtr ^ S16)) = v2;
} else {
v4 = (v4 **(uint32_t *)(state->mp3data + 0xCE8)) >> 0x10;
*(int16_t *)(state->mp3data + (state->mp3_outPtr ^ S16)) = v4;
mult4 = *(uint32_t *)(state->mp3data + 0xCE8);
v4 = (v4 **(uint32_t *)(hle->mp3_buffer + 0xCE8)) >> 0x10;
*(int16_t *)(hle->mp3_buffer + (hle->mp3_outPtr ^ S16)) = v4;
mult4 = *(uint32_t *)(hle->mp3_buffer + 0xCE8);
}
addptr -= 0x50;
@ -625,17 +622,17 @@ static void InnerLoop(usf_state_t* state)
int32_t v18;
v2 = v4 = v6 = v8 = 0;
offset = (0x22F - (state->mp3_t4 >> 1) + x * 0x40);
offset = (0x22F - (hle->mp3_t4 >> 1) + x * 0x40);
for (i = 0; i < 4; i++) {
v2 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x20) * (short)DeWindowLUT[offset + 0x00] + 0x4000) >> 0xF;
v2 -= ((int) * (int16_t *)(state->mp3data + ((addptr + 2)) + 0x20) * (short)DeWindowLUT[offset + 0x01] + 0x4000) >> 0xF;
v4 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x30) * (short)DeWindowLUT[offset + 0x08] + 0x4000) >> 0xF;
v4 -= ((int) * (int16_t *)(state->mp3data + ((addptr + 2)) + 0x30) * (short)DeWindowLUT[offset + 0x09] + 0x4000) >> 0xF;
v6 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x00) * (short)DeWindowLUT[offset + 0x20] + 0x4000) >> 0xF;
v6 -= ((int) * (int16_t *)(state->mp3data + ((addptr + 2)) + 0x00) * (short)DeWindowLUT[offset + 0x21] + 0x4000) >> 0xF;
v8 += ((int) * (int16_t *)(state->mp3data + (addptr) + 0x10) * (short)DeWindowLUT[offset + 0x28] + 0x4000) >> 0xF;
v8 -= ((int) * (int16_t *)(state->mp3data + ((addptr + 2)) + 0x10) * (short)DeWindowLUT[offset + 0x29] + 0x4000) >> 0xF;
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;
}
@ -644,13 +641,13 @@ static void InnerLoop(usf_state_t* state)
/* Clamp(v0); */
/* Clamp(v18); */
/* clamp??? */
*(int16_t *)(state->mp3data + ((state->mp3_outPtr + 2)^S16)) = v0;
*(int16_t *)(state->mp3data + ((state->mp3_outPtr + 4)^S16)) = v18;
state->mp3_outPtr += 4;
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_outPtr + 2)^S16)) = v0;
*(int16_t *)(hle->mp3_buffer + ((hle->mp3_outPtr + 4)^S16)) = v18;
hle->mp3_outPtr += 4;
addptr -= 0x50;
}
tmp = state->mp3_outPtr;
tmp = hle->mp3_outPtr;
hi0 = mult6;
hi1 = mult4;
@ -658,44 +655,44 @@ static void InnerLoop(usf_state_t* state)
hi1 = (int)hi1 >> 0x10;
for (i = 0; i < 8; i++) {
/* v0 */
vt = (*(int16_t *)(state->mp3data + ((tmp - 0x40)^S16)) * hi0);
vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x40)^S16)) * hi0);
if (vt > 32767) {
vt = 32767;
} else {
if (vt < -32767)
vt = -32767;
}
*(int16_t *)((uint8_t *)state->mp3data + ((tmp - 0x40)^S16)) = (int16_t)vt;
*(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x40)^S16)) = (int16_t)vt;
/* v17 */
vt = (*(int16_t *)(state->mp3data + ((tmp - 0x30)^S16)) * hi0);
vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x30)^S16)) * hi0);
if (vt > 32767) {
vt = 32767;
} else {
if (vt < -32767)
vt = -32767;
}
*(int16_t *)((uint8_t *)state->mp3data + ((tmp - 0x30)^S16)) = vt;
*(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x30)^S16)) = vt;
/* v2 */
vt = (*(int16_t *)(state->mp3data + ((tmp - 0x1E)^S16)) * hi1);
vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0x1E)^S16)) * hi1);
if (vt > 32767) {
vt = 32767;
} else {
if (vt < -32767)
vt = -32767;
}
*(int16_t *)((uint8_t *)state->mp3data + ((tmp - 0x1E)^S16)) = vt;
*(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0x1E)^S16)) = vt;
/* v4 */
vt = (*(int16_t *)(state->mp3data + ((tmp - 0xE)^S16)) * hi1);
vt = (*(int16_t *)(hle->mp3_buffer + ((tmp - 0xE)^S16)) * hi1);
if (vt > 32767) {
vt = 32767;
} else {
if (vt < -32767)
vt = -32767;
}
*(int16_t *)((uint8_t *)state->mp3data + ((tmp - 0xE)^S16)) = vt;
*(int16_t *)((uint8_t *)hle->mp3_buffer + ((tmp - 0xE)^S16)) = vt;
tmp += 2;
}
}

View File

@ -19,19 +19,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef _MSC_VER
#include <stdbool.h>
#else
#include "mystdbool.h"
#endif
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include "../usf.h"
#include "arithmetics.h"
#include "memory.h"
#include "plugin.h"
#include "audio.h"
#include "../usf_internal.h"
#include "hle_external.h"
#include "hle_internal.h"
#include "memory.h"
/* various constants */
enum { SUBFRAME_SIZE = 192 };
@ -134,27 +135,28 @@ typedef void (*mix_sfx_with_main_subframes_t)(musyx_t *musyx, const int16_t *sub
const uint16_t* gains);
/* helper functions prototypes */
static void load_base_vol(usf_state_t* state, int32_t *base_vol, uint32_t address);
static void save_base_vol(usf_state_t* state, const int32_t *base_vol, uint32_t address);
static void update_base_vol(usf_state_t* state, int32_t *base_vol,
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(usf_state_t* state, musyx_t *musyx, uint32_t voice_ptr,
uint32_t last_sample_ptr);
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(usf_state_t* state, uint8_t *dst, uint32_t catsrc_ptr);
static void dma_cat16(usf_state_t* state, uint16_t *dst, uint32_t catsrc_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(usf_state_t* state, uint32_t voice_ptr, int16_t *samples,
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(usf_state_t* state, uint32_t voice_ptr, int16_t *samples,
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(usf_state_t* state, int16_t *dst, const uint8_t *src,
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);
@ -162,11 +164,12 @@ static void adpcm_predict_frame(int16_t *dst, const uint8_t *src,
const uint8_t *nibbles,
unsigned int rshift);
static void mix_voice_samples(usf_state_t* state, musyx_t *musyx, uint32_t voice_ptr,
const int16_t *samples, unsigned segbase,
unsigned offset, uint32_t last_sample_ptr);
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(usf_state_t* state, mix_sfx_with_main_subframes_t mix_sfx_with_main_subframes,
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,
@ -179,9 +182,11 @@ 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(usf_state_t* state, musyx_t *musyx, uint32_t output_ptr);
static void interleave_stage_v1(struct hle_t* hle, musyx_t *musyx,
uint32_t output_ptr);
static void interleave_stage_v2(usf_state_t* state, musyx_t *musyx, uint16_t mask_16, uint32_t ptr_18,
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)
@ -198,129 +203,132 @@ static int32_t dot4(const int16_t *x, const int16_t *y)
/**************************************************************************
* MusyX v1 audio ucode
**************************************************************************/
void musyx_v1_task(usf_state_t* state)
void musyx_v1_task(struct hle_t* hle)
{
uint32_t sfd_ptr = *dmem_u32(state, TASK_DATA_PTR);
uint32_t sfd_count = *dmem_u32(state, TASK_DATA_SIZE);
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;
DebugMessage(state, M64MSG_VERBOSE, "musyx_v1_task: *data=%x, #SF=%d",
sfd_ptr,
sfd_count);
HleVerboseMessage(hle->user_defined,
"musyx_v1_task: *data=%x, #SF=%d",
sfd_ptr,
sfd_count);
state_ptr = *dram_u32(state, sfd_ptr + SFD_STATE_PTR);
state_ptr = *dram_u32(hle, sfd_ptr + SFD_STATE_PTR);
/* load initial state */
load_base_vol(state, musyx.base_vol, state_ptr + STATE_BASE_VOL);
dram_load_u16(state, (uint16_t *)musyx.cc0, state_ptr + STATE_CC0, SUBFRAME_SIZE);
dram_load_u16(state, (uint16_t *)musyx.subframe_740_last4, state_ptr + STATE_740_LAST4_V1,
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(state, sfd_ptr + SFD_SFX_INDEX);
uint32_t voice_mask = *dram_u32(state, sfd_ptr + SFD_VOICE_BITMASK);
uint32_t sfx_ptr = *dram_u32(state, sfd_ptr + SFD_SFX_PTR);
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(state, musyx.base_vol, voice_mask, last_sample_ptr, 0, 0);
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(state, &musyx, voice_ptr, last_sample_ptr);
output_ptr = voice_stage(hle, &musyx, voice_ptr, last_sample_ptr);
/* apply delay-based effects (optional) */
sfx_stage(state, mix_sfx_with_main_subframes_v1,
sfx_stage(hle, mix_sfx_with_main_subframes_v1,
&musyx, sfx_ptr, sfx_index);
/* emit interleaved L,R subframes */
interleave_stage_v1(state, &musyx, output_ptr);
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(state, sfd_ptr + SFD_STATE_PTR);
state_ptr = *dram_u32(hle, sfd_ptr + SFD_STATE_PTR);
}
/* writeback updated state */
save_base_vol(state, musyx.base_vol, state_ptr + STATE_BASE_VOL);
dram_store_u16(state, (uint16_t *)musyx.cc0, state_ptr + STATE_CC0, SUBFRAME_SIZE);
dram_store_u16(state, (uint16_t *)musyx.subframe_740_last4, state_ptr + STATE_740_LAST4_V1,
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);
}
/**************************************************************************
* MusyX v2 audio ucode
**************************************************************************/
void musyx_v2_task(usf_state_t* state)
void musyx_v2_task(struct hle_t* hle)
{
uint32_t sfd_ptr = *dmem_u32(state, TASK_DATA_PTR);
uint32_t sfd_count = *dmem_u32(state, TASK_DATA_SIZE);
uint32_t sfd_ptr = *dmem_u32(hle, TASK_DATA_PTR);
uint32_t sfd_count = *dmem_u32(hle, TASK_DATA_SIZE);
musyx_t musyx;
DebugMessage(state, M64MSG_VERBOSE, "musyx_v2_task: *data=%x, #SF=%d",
sfd_ptr,
sfd_count);
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(state, sfd_ptr + SFD_SFX_INDEX);
uint32_t voice_mask = *dram_u32(state, sfd_ptr + SFD_VOICE_BITMASK);
uint32_t state_ptr = *dram_u32(state, sfd_ptr + SFD_STATE_PTR);
uint32_t sfx_ptr = *dram_u32(state, sfd_ptr + SFD_SFX_PTR);
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(state, sfd_ptr + SFD2_10_PTR);
uint8_t mask_14 = *dram_u8 (state, sfd_ptr + SFD2_14_BITMASK);
uint8_t mask_15 = *dram_u8 (state, sfd_ptr + SFD2_15_BITMASK);
uint16_t mask_16 = *dram_u16(state, sfd_ptr + SFD2_16_BITMASK);
uint32_t ptr_18 = *dram_u32(state, sfd_ptr + SFD2_18_PTR);
uint32_t ptr_1c = *dram_u32(state, sfd_ptr + SFD2_1C_PTR);
uint32_t ptr_20 = *dram_u32(state, sfd_ptr + SFD2_20_PTR);
uint32_t ptr_24 = *dram_u32(state, sfd_ptr + SFD2_24_PTR);
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(state, musyx.base_vol, state_ptr + STATE_BASE_VOL);
dram_load_u16(state, (uint16_t *)musyx.subframe_740_last4,
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(state, musyx.base_vol, voice_mask, last_sample_ptr, mask_15, ptr_24);
update_base_vol(hle, musyx.base_vol, voice_mask, last_sample_ptr, mask_15, ptr_24);
init_subframes_v2(&musyx);
if (ptr_10) {
/* TODO */
DebugMessage(state, M64MSG_WARNING, "ptr_10=%08x mask_14=%02x ptr_24=%08x",
ptr_10, mask_14, ptr_24);
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(state, &musyx, voice_ptr, last_sample_ptr);
output_ptr = voice_stage(hle, &musyx, voice_ptr, last_sample_ptr);
/* apply delay-based effects (optional) */
sfx_stage(state, mix_sfx_with_main_subframes_v2,
sfx_stage(hle, mix_sfx_with_main_subframes_v2,
&musyx, sfx_ptr, sfx_index);
dram_store_u16(state, (uint16_t*)musyx.left, output_ptr , SUBFRAME_SIZE);
dram_store_u16(state, (uint16_t*)musyx.right, output_ptr + 2*SUBFRAME_SIZE, SUBFRAME_SIZE);
dram_store_u16(state, (uint16_t*)musyx.cc0, output_ptr + 4*SUBFRAME_SIZE, SUBFRAME_SIZE);
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(state, musyx.base_vol, state_ptr + STATE_BASE_VOL);
dram_store_u16(state, (uint16_t*)musyx.subframe_740_last4,
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(state, &musyx, mask_16, ptr_18, ptr_1c, ptr_20);
interleave_stage_v2(hle, &musyx, mask_16, ptr_18, ptr_1c, ptr_20);
--sfd_count;
if (sfd_count == 0)
@ -334,39 +342,40 @@ void musyx_v2_task(usf_state_t* state)
static void load_base_vol(usf_state_t* state, int32_t *base_vol, uint32_t address)
static void load_base_vol(struct hle_t* hle, int32_t *base_vol, uint32_t address)
{
base_vol[0] = ((uint32_t)(*dram_u16(state, address)) << 16) | (*dram_u16(state, address + 8));
base_vol[1] = ((uint32_t)(*dram_u16(state, address + 2)) << 16) | (*dram_u16(state, address + 10));
base_vol[2] = ((uint32_t)(*dram_u16(state, address + 4)) << 16) | (*dram_u16(state, address + 12));
base_vol[3] = ((uint32_t)(*dram_u16(state, address + 6)) << 16) | (*dram_u16(state, address + 14));
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(usf_state_t* state, const int32_t *base_vol, uint32_t address)
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(state, address) = (uint16_t)(base_vol[k] >> 16);
*dram_u16(hle, address) = (uint16_t)(base_vol[k] >> 16);
address += 2;
}
for (k = 0; k < 4; ++k) {
*dram_u16(state, address) = (uint16_t)(base_vol[k]);
*dram_u16(hle, address) = (uint16_t)(base_vol[k]);
address += 2;
}
}
static void update_base_vol(usf_state_t* state, int32_t *base_vol,
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;
DebugMessage(state, M64MSG_VERBOSE, "base_vol voice_mask = %08x", voice_mask);
DebugMessage(state, M64MSG_VERBOSE, "BEFORE: base_vol = %08x %08x %08x %08x",
base_vol[0], base_vol[1], base_vol[2], base_vol[3]);
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) {
@ -376,7 +385,7 @@ static void update_base_vol(usf_state_t* state, int32_t *base_vol,
continue;
for (k = 0; k < 4; ++k)
base_vol[k] += (int16_t)*dram_u16(state, last_sample_ptr + k * 2);
base_vol[k] += (int16_t)*dram_u16(hle, last_sample_ptr + k * 2);
}
}
@ -388,7 +397,7 @@ static void update_base_vol(usf_state_t* state, int32_t *base_vol,
continue;
for(k = 0; k < 4; ++k)
base_vol[k] += (int16_t)*dram_u16(state, ptr_24 + k * 2);
base_vol[k] += (int16_t)*dram_u16(hle, ptr_24 + k * 2);
}
}
@ -396,8 +405,9 @@ static void update_base_vol(usf_state_t* state, int32_t *base_vol,
for (k = 0; k < 4; ++k)
base_vol[k] = (base_vol[k] * 0x0000f850) >> 16;
DebugMessage(state, M64MSG_VERBOSE, "AFTER: base_vol = %08x %08x %08x %08x",
base_vol[0], base_vol[1], base_vol[2], base_vol[3]);
HleVerboseMessage(hle->user_defined,
"AFTER: base_vol = %08x %08x %08x %08x",
base_vol[0], base_vol[1], base_vol[2], base_vol[3]);
}
@ -449,16 +459,16 @@ static void init_subframes_v2(musyx_t *musyx)
}
/* Process voices, and returns interleaved subframe destination address */
static uint32_t voice_stage(usf_state_t* state, musyx_t *musyx, uint32_t voice_ptr,
uint32_t last_sample_ptr)
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(state, voice_ptr + VOICE_CATSRC_0 + CATSRC_SIZE1) == 0) {
DebugMessage(state, M64MSG_VERBOSE, "Skipping Voice stage");
output_ptr = *dram_u32(state, voice_ptr + VOICE_INTERLEAVED_PTR);
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 (;;) {
@ -467,19 +477,19 @@ static uint32_t voice_stage(usf_state_t* state, musyx_t *musyx, uint32_t voice_p
unsigned segbase;
unsigned offset;
DebugMessage(state, M64MSG_VERBOSE, "Processing Voice #%d", i);
HleVerboseMessage(hle->user_defined, "Processing Voice #%d", i);
if (*dram_u8(state, voice_ptr + VOICE_ADPCM_FRAMES) == 0)
load_samples_PCM16(state, voice_ptr, samples, &segbase, &offset);
if (*dram_u8(hle, voice_ptr + VOICE_ADPCM_FRAMES) == 0)
load_samples_PCM16(hle, voice_ptr, samples, &segbase, &offset);
else
load_samples_ADPCM(state, voice_ptr, samples, &segbase, &offset);
load_samples_ADPCM(hle, voice_ptr, samples, &segbase, &offset);
/* mix them with each internal subframes */
mix_voice_samples(state, musyx, voice_ptr, samples, segbase, offset,
mix_voice_samples(hle, musyx, voice_ptr, samples, segbase, offset,
last_sample_ptr + i * 8);
/* check break condition */
output_ptr = *dram_u32(state, voice_ptr + VOICE_INTERLEAVED_PTR);
output_ptr = *dram_u32(hle, voice_ptr + VOICE_INTERLEAVED_PTR);
if (output_ptr != 0)
break;
@ -492,76 +502,78 @@ static uint32_t voice_stage(usf_state_t* state, musyx_t *musyx, uint32_t voice_p
return output_ptr;
}
static void dma_cat8(usf_state_t* state, uint8_t *dst, uint32_t catsrc_ptr)
static void dma_cat8(struct hle_t* hle, uint8_t *dst, uint32_t catsrc_ptr)
{
uint32_t ptr1 = *dram_u32(state, catsrc_ptr + CATSRC_PTR1);
uint32_t ptr2 = *dram_u32(state, catsrc_ptr + CATSRC_PTR2);
uint16_t size1 = *dram_u16(state, catsrc_ptr + CATSRC_SIZE1);
uint16_t size2 = *dram_u16(state, catsrc_ptr + CATSRC_SIZE2);
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;
DebugMessage(state, M64MSG_VERBOSE, "dma_cat: %08x %08x %04x %04x",
ptr1,
ptr2,
size1,
size2);
HleVerboseMessage(hle->user_defined,
"dma_cat: %08x %08x %04x %04x",
ptr1,
ptr2,
size1,
size2);
dram_load_u8(state, dst, ptr1, count1);
dram_load_u8(hle, dst, ptr1, count1);
if (size2 == 0)
return;
dram_load_u8(state, dst + count1, ptr2, count2);
dram_load_u8(hle, dst + count1, ptr2, count2);
}
static void dma_cat16(usf_state_t* state, uint16_t *dst, uint32_t catsrc_ptr)
static void dma_cat16(struct hle_t* hle, uint16_t *dst, uint32_t catsrc_ptr)
{
uint32_t ptr1 = *dram_u32(state, catsrc_ptr + CATSRC_PTR1);
uint32_t ptr2 = *dram_u32(state, catsrc_ptr + CATSRC_PTR2);
uint16_t size1 = *dram_u16(state, catsrc_ptr + CATSRC_SIZE1);
uint16_t size2 = *dram_u16(state, catsrc_ptr + CATSRC_SIZE2);
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;
DebugMessage(state, M64MSG_VERBOSE, "dma_cat: %08x %08x %04x %04x",
ptr1,
ptr2,
size1,
size2);
HleVerboseMessage(hle->user_defined,
"dma_cat: %08x %08x %04x %04x",
ptr1,
ptr2,
size1,
size2);
dram_load_u16(state, dst, ptr1, count1);
dram_load_u16(hle, dst, ptr1, count1);
if (size2 == 0)
return;
dram_load_u16(state, dst + count1, ptr2, count2);
dram_load_u16(hle, dst + count1, ptr2, count2);
}
static void load_samples_PCM16(usf_state_t* state, uint32_t voice_ptr, int16_t *samples,
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(state, voice_ptr + VOICE_SKIP_SAMPLES);
uint16_t u16_40 = *dram_u16(state, voice_ptr + VOICE_U16_40);
uint16_t u16_42 = *dram_u16(state, voice_ptr + VOICE_U16_42);
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);
DebugMessage(state, M64MSG_VERBOSE, "Format: PCM16");
HleVerboseMessage(hle->user_defined, "Format: PCM16");
*segbase = SAMPLE_BUFFER_SIZE - count;
*offset = u8_3e;
dma_cat16(state, (uint16_t *)samples + *segbase, voice_ptr + VOICE_CATSRC_0);
dma_cat16(hle, (uint16_t *)samples + *segbase, voice_ptr + VOICE_CATSRC_0);
if (u16_42 != 0)
dma_cat16(state, (uint16_t *)samples, voice_ptr + VOICE_CATSRC_1);
dma_cat16(hle, (uint16_t *)samples, voice_ptr + VOICE_CATSRC_1);
}
static void load_samples_ADPCM(usf_state_t* state, uint32_t voice_ptr, int16_t *samples,
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;
@ -569,33 +581,34 @@ static void load_samples_ADPCM(usf_state_t* state, uint32_t voice_ptr, int16_t *
uint8_t buffer[SAMPLE_BUFFER_SIZE * 2 * 5 / 16];
int16_t adpcm_table[128];
uint8_t u8_3c = *dram_u8(state, voice_ptr + VOICE_ADPCM_FRAMES );
uint8_t u8_3d = *dram_u8(state, voice_ptr + VOICE_ADPCM_FRAMES + 1);
uint8_t u8_3e = *dram_u8(state, voice_ptr + VOICE_SKIP_SAMPLES );
uint8_t u8_3f = *dram_u8(state, voice_ptr + VOICE_SKIP_SAMPLES + 1);
uint32_t adpcm_table_ptr = *dram_u32(state, voice_ptr + VOICE_ADPCM_TABLE_PTR);
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;
DebugMessage(state, M64MSG_VERBOSE, "Format: ADPCM");
HleVerboseMessage(hle->user_defined, "Format: ADPCM");
DebugMessage(state, M64MSG_VERBOSE, "Loading ADPCM table: %08x", adpcm_table_ptr);
dram_load_u16(state, (uint16_t *)adpcm_table, adpcm_table_ptr, 128);
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(state, buffer, voice_ptr + VOICE_CATSRC_0);
adpcm_decode_frames(state, samples + *segbase, buffer, adpcm_table, u8_3c, u8_3e);
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(state, buffer, voice_ptr + VOICE_CATSRC_1);
adpcm_decode_frames(state, samples, buffer, adpcm_table, u8_3d, u8_3f);
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(usf_state_t* state, int16_t *dst, const uint8_t *src,
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)
{
@ -604,8 +617,9 @@ static void adpcm_decode_frames(usf_state_t* state, int16_t *dst, const uint8_t
unsigned i;
bool jump_gap = false;
DebugMessage(state, M64MSG_VERBOSE, "ADPCM decode: count=%d, skip=%d", count,
skip_samples);
HleVerboseMessage(hle->user_defined,
"ADPCM decode: count=%d, skip=%d",
count, skip_samples);
if (skip_samples >= 32) {
jump_gap = true;
@ -656,20 +670,20 @@ static void adpcm_predict_frame(int16_t *dst, const uint8_t *src,
}
}
static void mix_voice_samples(usf_state_t* state, musyx_t *musyx, uint32_t voice_ptr,
const int16_t *samples, unsigned segbase,
unsigned offset, uint32_t last_sample_ptr)
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(state, voice_ptr + VOICE_PITCH_Q16);
const uint16_t pitch_shift = *dram_u16(state, voice_ptr + VOICE_PITCH_SHIFT); /* Q4.12 */
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(state, voice_ptr + VOICE_END_POINT);
const uint16_t restart_point = *dram_u16(state, voice_ptr + VOICE_RESTART_POINT);
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(state, voice_ptr + VOICE_U16_4E);
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;
@ -686,27 +700,27 @@ static void mix_voice_samples(usf_state_t* state, musyx_t *musyx, uint32_t voice
int16_t *v4_dst[4];
int16_t v4[4];
dram_load_u32(state, (uint32_t *)v4_env, voice_ptr + VOICE_ENV_BEGIN, 4);
dram_load_u32(state, (uint32_t *)v4_env_step, voice_ptr + VOICE_ENV_STEP, 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;
DebugMessage(state, M64MSG_VERBOSE,
"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]);
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 */
@ -739,14 +753,15 @@ static void mix_voice_samples(usf_state_t* state, musyx_t *musyx, uint32_t voice
}
/* save last resampled sample */
dram_store_u16(state, (uint16_t *)v4, last_sample_ptr, 4);
dram_store_u16(hle, (uint16_t *)v4, last_sample_ptr, 4);
DebugMessage(state, M64MSG_VERBOSE, "last_sample = %04x %04x %04x %04x",
v4[0], v4[1], v4[2], v4[3]);
HleVerboseMessage(hle->user_defined,
"last_sample = %04x %04x %04x %04x",
v4[0], v4[1], v4[2], v4[3]);
}
static void sfx_stage(usf_state_t* state, mix_sfx_with_main_subframes_t mix_sfx_with_main_subframes,
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;
@ -769,44 +784,46 @@ static void sfx_stage(usf_state_t* state, mix_sfx_with_main_subframes_t mix_sfx_
int16_t fir4_hgain;
uint16_t sfx_gains[2];
DebugMessage(state, M64MSG_VERBOSE, "SFX: %08x, idx=%d", sfx_ptr, idx);
HleVerboseMessage(hle->user_defined, "SFX: %08x, idx=%d", sfx_ptr, idx);
if (sfx_ptr == 0)
return;
/* load sfx parameters */
cbuffer_ptr = *dram_u32(state, sfx_ptr + SFX_CBUFFER_PTR);
cbuffer_length = *dram_u32(state, sfx_ptr + SFX_CBUFFER_LENGTH);
cbuffer_ptr = *dram_u32(hle, sfx_ptr + SFX_CBUFFER_PTR);
cbuffer_length = *dram_u32(hle, sfx_ptr + SFX_CBUFFER_LENGTH);
tap_count = *dram_u16(state, sfx_ptr + SFX_TAP_COUNT);
tap_count = *dram_u16(hle, sfx_ptr + SFX_TAP_COUNT);
dram_load_u32(state, tap_delays, sfx_ptr + SFX_TAP_DELAYS, 8);
dram_load_u16(state, (uint16_t *)tap_gains, sfx_ptr + SFX_TAP_GAINS, 8);
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(state, sfx_ptr + SFX_FIR4_HGAIN);
dram_load_u16(state, (uint16_t *)fir4_hcoeffs, sfx_ptr + SFX_FIR4_HCOEFFS, 4);
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(state, sfx_ptr + SFX_U16_3C);
sfx_gains[1] = *dram_u16(state, sfx_ptr + SFX_U16_3E);
sfx_gains[0] = *dram_u16(hle, sfx_ptr + SFX_U16_3C);
sfx_gains[1] = *dram_u16(hle, sfx_ptr + SFX_U16_3E);
DebugMessage(state, M64MSG_VERBOSE, "cbuffer: ptr=%08x length=%x", cbuffer_ptr,
cbuffer_length);
HleVerboseMessage(hle->user_defined,
"cbuffer: ptr=%08x length=%x", cbuffer_ptr,
cbuffer_length);
DebugMessage(state, M64MSG_VERBOSE, "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,
"fir4: hgain=%04x hcoeff=%04x %04x %04x %04x",
fir4_hgain,
fir4_hcoeffs[0], fir4_hcoeffs[1], fir4_hcoeffs[2], fir4_hcoeffs[3]);
DebugMessage(state, M64MSG_VERBOSE,
"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,
"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]);
DebugMessage(state, M64MSG_VERBOSE, "sfx_gains=%04x %04x", sfx_gains[0], sfx_gains[1]);
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]));
@ -817,12 +834,12 @@ static void sfx_stage(usf_state_t* state, mix_sfx_with_main_subframes_t mix_sfx_
dpos += cbuffer_length;
dlength = SUBFRAME_SIZE;
if (dpos + SUBFRAME_SIZE > cbuffer_length) {
if ((uint32_t)(dpos + SUBFRAME_SIZE) > cbuffer_length) {
dlength = cbuffer_length - dpos;
dram_load_u16(state, (uint16_t *)delayed + dlength, cbuffer_ptr, SUBFRAME_SIZE - dlength);
dram_load_u16(hle, (uint16_t *)delayed + dlength, cbuffer_ptr, SUBFRAME_SIZE - dlength);
}
dram_load_u16(state, (uint16_t *)delayed, cbuffer_ptr + dpos * 2, dlength);
dram_load_u16(hle, (uint16_t *)delayed, cbuffer_ptr + dpos * 2, dlength);
mix_subframes(subframe, delayed, tap_gains[i]);
}
@ -834,7 +851,7 @@ static void sfx_stage(usf_state_t* state, mix_sfx_with_main_subframes_t mix_sfx_
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(state, (uint16_t *)musyx->e50, cbuffer_ptr + pos * 2, SUBFRAME_SIZE);
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,
@ -894,7 +911,7 @@ static void mix_fir4(int16_t *y, const int16_t *x, int16_t hgain, const int16_t
}
}
static void interleave_stage_v1(usf_state_t* state, musyx_t *musyx, uint32_t output_ptr)
static void interleave_stage_v1(struct hle_t* hle, musyx_t *musyx, uint32_t output_ptr)
{
size_t i;
@ -905,14 +922,14 @@ static void interleave_stage_v1(usf_state_t* state, musyx_t *musyx, uint32_t out
int16_t *right;
uint32_t *dst;
DebugMessage(state, M64MSG_VERBOSE, "interleave: %08x", output_ptr);
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(state, output_ptr);
dst = dram_u32(hle, output_ptr);
for (i = 0; i < SUBFRAME_SIZE; ++i) {
uint16_t l = clamp_s16(*(left++) + base_left);
@ -922,7 +939,8 @@ static void interleave_stage_v1(usf_state_t* state, musyx_t *musyx, uint32_t out
}
}
static void interleave_stage_v2(usf_state_t* state, musyx_t *musyx, uint16_t mask_16, uint32_t ptr_18,
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;
@ -930,14 +948,15 @@ static void interleave_stage_v2(usf_state_t* state, musyx_t *musyx, uint16_t mas
uint32_t *dst;
uint16_t mask;
DebugMessage(state, M64MSG_VERBOSE, "mask_16=%04x ptr_18=%08x ptr_1c=%08x output_ptr=%08x",
mask_16, ptr_18, ptr_1c, output_ptr);
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(state, ptr_1c + i*2);
int16_t v = *dram_u16(hle, ptr_1c + i*2);
musyx->left[i] = v;
musyx->right[i] = clamp_s16(-v);
}
@ -949,18 +968,18 @@ static void interleave_stage_v2(usf_state_t* state, musyx_t *musyx, uint16_t mas
if ((mask_16 & mask) == 0)
continue;
address = *dram_u32(state, ptr_18);
hgain = *dram_u16(state, ptr_18 + 4);
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(state, address), hgain);
mix_samples(&musyx->right[i], *dram_u16(state, address + 2*SUBFRAME_SIZE), hgain);
mix_samples(&subframe[i], *dram_u16(state, address + 4*SUBFRAME_SIZE), hgain);
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(state, output_ptr);
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];
@ -968,5 +987,5 @@ static void interleave_stage_v2(usf_state_t* state, musyx_t *musyx, uint16_t mas
}
/* writeback subframe @ptr_1c */
dram_store_u16(state, (uint16_t*)subframe, ptr_1c, SUBFRAME_SIZE);
dram_store_u16(hle, (uint16_t*)subframe, ptr_1c, SUBFRAME_SIZE);
}

View File

@ -22,7 +22,9 @@
#ifndef MUSYX_H
#define MUSYX_H
void musyx_v1_task(usf_state_t* state);
void musyx_v2_task(usf_state_t* state);
struct hle_t;
void musyx_v1_task(struct hle_t* hle);
void musyx_v2_task(struct hle_t* hle);
#endif

View File

@ -1,5 +1,5 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-rsp-hle - plugin.h *
* Mupen64plus-rsp-hle - alist_internal.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2014 Bobby Smiles *
* *
@ -19,14 +19,21 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef PLUGIN_H
#define PLUGIN_H
#ifndef _MYSTDBOOL_H_
#define _MYSTDBOOL_H_
#define M64MSG_VERBOSE 0
#define M64MSG_WARNING 1
#define M64MSG_ERROR 2
void DebugMessage(usf_state_t * state, int level, const char *message, ...);
#endif
#pragma once
typedef unsigned char my_bool;
enum { my_b_false = 0 };
enum { my_b_true = 1 };
#undef bool
#undef true
#undef false
#define bool my_bool
#define true my_b_true
#define false my_b_false
#endif

View File

@ -26,26 +26,44 @@
#include <stdio.h>
#include "../usf.h"
#include "main.h"
#include "plugin.h"
#include "../main.h"
#include "../usf_internal.h"
/* Global functions */
void DebugMessage(usf_state_t* state, int level, const char *message, ...)
#include "hle.h"
/* Global functions needed by HLE core */
void HleVerboseMessage(void* user_defined, const char *message, ...)
{
char msgbuf[1024];
va_list args;
/* discard verbose message */
}
void HleErrorMessage(void* user_defined, const char *message, ...)
{
usf_state_t* state;
va_list ap;
size_t len;
if ( level < M64MSG_WARNING )
return;
state = (usf_state_t*)user_defined;
len = strlen( state->error_message );
if ( len )
state->error_message[ len++ ] = '\n';
va_start( ap, message );
vsprintf( state->error_message + len, message, ap );
va_end( ap );
state->last_error = state->error_message;
StopEmulation( state );
}
void HleWarnMessage(void* user_defined, const char *message, ...)
{
usf_state_t* state;
va_list ap;
size_t len;
state = (usf_state_t*)user_defined;
len = strlen( state->error_message );
if ( len )
@ -58,3 +76,28 @@ void DebugMessage(usf_state_t* state, int level, const char *message, ...)
state->last_error = state->error_message;
StopEmulation( state );
}
void HleCheckInterrupts(void* user_defined)
{
CheckInterrupts((usf_state_t*)user_defined);
}
void HleProcessDlistList(void* user_defined)
{
/* disabled */
}
void HleProcessAlistList(void* user_defined)
{
/* disabled */
}
void HleProcessRdpList(void* user_defined)
{
/* disabled */
}
void HleShowCFB(void* user_defined)
{
/* disabled */
}

View File

@ -2,6 +2,7 @@
#define _USF_INTERNAL_H_
#include "cpu.h"
#include "rsp_hle/hle.h"
struct usf_state_helper
{
@ -15,21 +16,6 @@ typedef uint32_t RCPREG;
#include <stdio.h>
// rsp_hle/alist_audio.c
enum { DMEM_BASE = 0x5c0 };
enum { N_SEGMENTS = 16 };
// rsp_hle/alist_naudio.c
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
};
struct usf_state
{
// RSP vector registers, need to be aligned to 16 bytes
@ -59,14 +45,6 @@ struct usf_state
short comp[8]; /* $vcc: low byte (VEQ, VNE, VLT, VGE, VCL, VCH, VCR) */
short vce[8]; /* $vce: vector compare extension register */
// rsp_hle/mp3.c, let's see if aligning this helps anything
uint8_t mp3data[0x1000];
int32_t mp3_v[32];
uint32_t mp3_inPtr, mp3_outPtr;
uint32_t mp3_t6;/* = 0x08A0; - I think these are temporary storage buffers */
uint32_t mp3_t5;/* = 0x0AC0; */
uint32_t mp3_t4;/* = (w1 & 0x1E); */
// All further members of the structure need not be aligned
// rsp/vu/divrom.h
@ -83,78 +61,8 @@ struct usf_state
int temp_PC;
short MFC0_count[32];
// rsp_hle/alist.c
uint8_t BufferSpace[0x10000];
// rsp_hle/alist_audio.c
/* alist audio state */
struct {
/* 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];
} l_alist_audio;
struct {
/* 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];
} l_alist_naudio;
struct {
/* 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];
} l_alist_nead;
// rsp_hle
struct hle_t hle;
uint32_t cpu_running, cpu_stopped;

View File

@ -1014,6 +1014,8 @@ static int usf_info(void * context, const char * name, const char * value)
usf_clear( state.emu_state );
//usf_set_hle_audio( state.emu_state, 1 );
emulatorCore = ( uint8_t * ) state.emu_state;
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x21, usf_loader, &state, usf_info, &state, 1 ) <= 0 )