2012-11-01 16:19:01 +01:00
// Copyright (c) 2012- PPSSPP Project.
// 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
2012-11-04 23:01:49 +01:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 16:19:01 +01:00
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// SAS is a software mixing engine that runs on the Media Engine CPU. We just HLE it.
// This is a very rough implementation that needs lots of work.
//
2012-12-17 18:05:10 +01:00
// This file just contains the API, the real stuff is in HW/SasAudio.cpp/h.
//
2012-11-01 16:19:01 +01:00
// JPCSP is, as it often is, a pretty good reference although I didn't actually use it much yet:
// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java
# include "base/basictypes.h"
2012-12-16 20:40:49 +01:00
# include "Log.h"
2012-11-01 16:19:01 +01:00
# include "HLE.h"
# include "../MIPS/MIPS.h"
2012-12-16 20:40:49 +01:00
# include "../HW/SasAudio.h"
2012-11-01 16:19:01 +01:00
# include "sceSas.h"
# include "sceKernel.h"
2012-12-17 18:05:10 +01:00
enum {
ERROR_SAS_INVALID_VOICE = 0x80420010 ,
ERROR_SAS_INVALID_ADSR_CURVE_MODE = 0x80420013 ,
ERROR_SAS_INVALID_PARAMETER = 0x80420014 ,
ERROR_SAS_VOICE_PAUSED = 0x80420016 ,
ERROR_SAS_INVALID_SIZE = 0x8042001A ,
ERROR_SAS_BUSY = 0x80420030 ,
ERROR_SAS_NOT_INIT = 0x80420100 ,
} ;
2012-11-01 16:19:01 +01:00
// TODO - allow more than one, associating each with one Core pointer (passed in to all the functions)
// No known games use more than one instance of Sas though.
SasInstance sas ;
2012-12-07 12:45:16 +08:00
u32 sceSasInit ( u32 core , u32 grainSize , u32 maxVoices , u32 outputMode , u32 sampleRate )
2012-11-01 16:19:01 +01:00
{
2012-12-17 20:15:23 +01:00
INFO_LOG ( HLE , " 0=sceSasInit(%08x, grainSize=%i, maxVoices=%i, %i, %i) " , core , grainSize , maxVoices , outputMode , sampleRate ) ;
2012-11-01 16:19:01 +01:00
memset ( & sas , 0 , sizeof ( sas ) ) ;
2012-12-16 20:40:49 +01:00
sas . SetGrainSize ( grainSize ) ;
2012-11-01 16:19:01 +01:00
sas . maxVoices = maxVoices ;
sas . sampleRate = sampleRate ;
2012-12-07 12:45:16 +08:00
sas . outputMode = outputMode ;
2012-11-01 16:19:01 +01:00
for ( int i = 0 ; i < 32 ; i + + ) {
sas . voices [ i ] . playing = false ;
}
return 0 ;
}
2012-12-07 12:45:16 +08:00
u32 sceSasGetEndFlag ( u32 core )
2012-11-01 16:19:01 +01:00
{
u32 endFlag = 0 ;
for ( int i = 0 ; i < sas . maxVoices ; i + + ) {
if ( ! sas . voices [ i ] . playing )
endFlag | = 1 < < i ;
}
DEBUG_LOG ( HLE , " %08x=sceSasGetEndFlag() " , endFlag ) ;
return endFlag ;
}
// Runs the mixer
2012-12-16 20:40:49 +01:00
u32 _sceSasCore ( u32 core , u32 outAddr )
2012-11-01 16:19:01 +01:00
{
2012-12-16 20:40:49 +01:00
DEBUG_LOG ( HLE , " 0=sceSasCore(, %08x) (grain: %i samples) " , outAddr , sas . GetGrainSize ( ) ) ;
2012-12-17 18:05:10 +01:00
if ( ! Memory : : IsValidAddress ( outAddr ) ) {
return ERROR_SAS_INVALID_PARAMETER ;
}
2012-12-16 20:40:49 +01:00
Memory : : Memset ( outAddr , 0 , sas . GetGrainSize ( ) * 2 * 2 ) ;
sas . Mix ( outAddr ) ;
return 0 ;
2012-11-01 16:19:01 +01:00
}
// Another way of running the mixer, what was the difference again?
2012-12-16 20:40:49 +01:00
u32 _sceSasCoreWithMix ( u32 core , u32 outAddr )
2012-11-01 16:19:01 +01:00
{
2012-12-16 20:40:49 +01:00
DEBUG_LOG ( HLE , " 0=sceSasCoreWithMix(, %08x) (grain: %i samples) " , outAddr , sas . GetGrainSize ( ) ) ;
2012-12-17 18:05:10 +01:00
if ( ! Memory : : IsValidAddress ( outAddr ) ) {
return ERROR_SAS_INVALID_PARAMETER ;
}
2012-12-16 20:40:49 +01:00
sas . Mix ( outAddr ) ;
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasSetVoice ( u32 core , int voiceNum , u32 vagAddr , int size , int loop )
2012-11-01 16:19:01 +01:00
{
DEBUG_LOG ( HLE , " 0=sceSasSetVoice(core=%08x, voicenum=%i, vag=%08x, size=%i, loop=%i) " ,
core , voiceNum , vagAddr , size , loop ) ;
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-11-01 16:19:01 +01:00
//Real VAG header is 0x30 bytes behind the vagAddr
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
v . type = VOICETYPE_VAG ;
2012-11-01 16:19:01 +01:00
v . vagAddr = vagAddr ;
2012-12-16 20:40:49 +01:00
v . vagSize = size ;
2012-12-17 18:05:10 +01:00
v . loop = loop ? true : false ;
v . ChangedParams ( ) ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-17 18:05:10 +01:00
u32 sceSasGetPauseFlag ( u32 core )
{
u32 pauseFlag = 0 ;
for ( int i = 0 ; i < sas . maxVoices ; i + + ) {
if ( sas . voices [ i ] . paused )
pauseFlag | = 1 < < i ;
}
DEBUG_LOG ( HLE , " %08x=sceSasGetPauseFlag() " , pauseFlag ) ;
return pauseFlag ;
}
2012-12-07 12:45:16 +08:00
u32 sceSasSetPause ( u32 core , int voicebit , int pause )
{
2012-12-10 00:09:56 -08:00
DEBUG_LOG ( HLE , " 0=sceSasSetPause(core=%08x, voicebit=%08x, pause=%i) " , core , voicebit , pause ) ;
for ( int i = 0 ; voicebit ! = 0 ; i + + , voicebit > > = 1 )
{
2012-12-16 20:40:49 +01:00
if ( i < PSP_SAS_VOICES_MAX & & i > = 0 )
2012-12-10 00:09:56 -08:00
{
if ( ( voicebit & 1 ) ! = 0 )
2012-12-17 18:05:10 +01:00
sas . voices [ i ] . paused = pause ? true : false ;
2012-12-10 00:09:56 -08:00
}
// TODO: Correct error code? Mimana crashes otherwise.
else
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-07 12:45:16 +08:00
}
2012-12-10 00:09:56 -08:00
2012-12-07 12:45:16 +08:00
return 0 ;
}
2012-12-16 20:40:49 +01:00
u32 sceSasSetVolume ( u32 core , int voiceNum , int l , int r , int el , int er )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetVolume(core=%08x, voiceNum=%i, l=%i, r=%i, el=%i, er=%i " , core , voiceNum , l , r , el , er ) ;
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
2012-11-01 16:19:01 +01:00
v . volumeLeft = l ;
v . volumeRight = r ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasSetPitch ( u32 core , int voiceNum , int pitch )
2012-11-01 16:19:01 +01:00
{
2012-12-15 15:04:46 -08:00
DEBUG_LOG ( HLE , " 0=sceSasSetPitch(core=%08x, voiceNum=%i, pitch=%i) " , core , voiceNum , pitch ) ;
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
2012-11-01 16:19:01 +01:00
v . pitch = pitch ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasSetKeyOn ( u32 core , int voiceNum )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetKeyOn(core=%08x, voiceNum=%i) " , core , voiceNum ) ;
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
2012-12-17 18:05:10 +01:00
v . KeyOn ( ) ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
// sceSasSetKeyOff can be used to start sounds, that just sound during the Release phase!
2012-12-16 20:40:49 +01:00
u32 sceSasSetKeyOff ( u32 core , int voiceNum )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetKeyOff(core=%08x, voiceNum=%i) " , core , voiceNum ) ;
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
2012-12-17 18:05:10 +01:00
v . KeyOff ( ) ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-07 01:45:09 +08:00
u32 sceSasSetNoise ( u32 core , int voiceNum , int freq )
2012-12-06 23:05:55 +08:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetNoise(core=%08x, voiceNum=%i, freq=%i) " , core , voiceNum , freq ) ;
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
v . type = VOICETYPE_NOISE ;
v . noiseFreq = freq ;
2012-12-07 12:45:16 +08:00
return 0 ;
2012-12-06 23:05:55 +08:00
}
2012-12-07 01:45:09 +08:00
u32 sceSasSetSL ( u32 core , int voiceNum , int level )
2012-12-06 23:05:55 +08:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetSL(core=%08x, voiceNum=%i, level=%i) " , core , voiceNum , level ) ;
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
v . envelope . sustainLevel = level ;
2012-12-07 12:45:16 +08:00
return 0 ;
2012-12-06 23:05:55 +08:00
}
2012-12-05 23:51:10 +08:00
u32 sceSasSetADSR ( u32 core , int voiceNum , int flag , int a , int d , int s , int r )
2012-11-01 16:19:01 +01:00
{
2012-12-05 23:51:10 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetADSR(core=%08x, voicenum=%i, flag=%i, a=%08x, d=%08x, s=%08x, r=%08x) " , core , voiceNum , flag , a , d , s , r )
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
if ( ( flag & 0x1 ) ! = 0 ) v . envelope . attackRate = a ;
if ( ( flag & 0x2 ) ! = 0 ) v . envelope . decayRate = d ;
if ( ( flag & 0x4 ) ! = 0 ) v . envelope . sustainRate = s ;
if ( ( flag & 0x8 ) ! = 0 ) v . envelope . releaseRate = r ;
2012-12-05 23:51:10 +08:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-06 00:09:01 +08:00
u32 sceSasSetADSRMode ( u32 core , int voiceNum , int flag , int a , int d , int s , int r )
2012-11-01 16:19:01 +01:00
{
2012-12-06 00:09:01 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetADSRMode(core=%08x, voicenum=%i, flag=%i, a=%08x, d=%08x, s=%08x, r=%08x) " , core , voiceNum , flag , a , d , s , r )
2012-12-15 15:04:46 -08:00
2012-12-16 20:40:49 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
2012-12-15 15:04:46 -08:00
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
2012-12-17 18:05:10 +01:00
return ERROR_SAS_INVALID_VOICE ;
2012-12-15 15:04:46 -08:00
}
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
if ( ( flag & 0x1 ) ! = 0 ) v . envelope . attackType = a ;
if ( ( flag & 0x2 ) ! = 0 ) v . envelope . decayType = d ;
if ( ( flag & 0x4 ) ! = 0 ) v . envelope . sustainType = s ;
if ( ( flag & 0x8 ) ! = 0 ) v . envelope . releaseType = r ;
2012-12-07 12:45:16 +08:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-06 22:37:41 +08:00
2012-11-01 16:19:01 +01:00
u32 sceSasSetSimpleADSR ( u32 core , u32 voiceNum , u32 ADSREnv1 , u32 ADSREnv2 )
{
2012-12-07 01:54:06 +08:00
DEBUG_LOG ( HLE , " 0=sasSetSimpleADSR(%08x, %i, %08x, %08x) " , core , voiceNum , ADSREnv1 , ADSREnv2 ) ;
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
v . envelope . SetSimpleEnvelope ( ADSREnv1 & 0xFFFF , ADSREnv2 & 0xFFFF ) ;
2012-11-01 16:19:01 +01:00
return 0 ;
}
u32 sceSasGetEnvelopeHeight ( u32 core , u32 voiceNum )
{
// Spam reduction
if ( voiceNum = = 17 )
{
DEBUG_LOG ( HLE , " UNIMPL 0=sceSasGetEnvelopeHeight(core=%08x, voicenum=%i) " , core , voiceNum ) ;
}
2012-12-17 18:05:10 +01:00
if ( voiceNum > = PSP_SAS_VOICES_MAX | | voiceNum < 0 )
{
WARN_LOG ( HLE , " %s: invalid voicenum %d " , __FUNCTION__ , voiceNum ) ;
return ERROR_SAS_INVALID_VOICE ;
}
2012-11-01 16:19:01 +01:00
2012-12-17 18:05:10 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
return v . envelope . GetHeight ( ) ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasRevType ( u32 core , int type )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasRevType(core=%08x, type=%i) " , core , type ) ;
2012-12-17 18:05:10 +01:00
sas . waveformEffect . type = type ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasRevParam ( u32 core , int delay , int feedback )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasRevParam(core=%08x, delay=%i, feedback=%i) " , core , delay , feedback ) ;
2012-12-08 21:07:21 +08:00
sas . waveformEffect . delay = delay ;
sas . waveformEffect . feedback = feedback ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasRevEVOL ( u32 core , int lv , int rv )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i) " , core , lv , rv ) ;
2012-12-08 21:07:21 +08:00
sas . waveformEffect . leftVol = lv ;
sas . waveformEffect . rightVol = rv ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-05 19:50:25 +08:00
2012-12-16 20:40:49 +01:00
u32 sceSasRevVON ( u32 core , int dry , int wet )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasRevVON(core=%08x, dry=%i, wet=%i) " , core , dry , wet ) ;
2012-12-08 21:07:21 +08:00
sas . waveformEffect . isDryOn = ( dry > 0 ) ;
sas . waveformEffect . isWetOn = ( wet > 0 ) ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-07 12:45:16 +08:00
u32 sceSasGetGrain ( u32 core )
2012-11-01 16:19:01 +01:00
{
2012-12-07 12:45:16 +08:00
DEBUG_LOG ( HLE , " 0=sceSasGetGrain(core=%08x) " , core ) ;
2012-12-16 20:40:49 +01:00
return sas . GetGrainSize ( ) ;
2012-11-01 16:19:01 +01:00
}
2012-12-07 12:45:16 +08:00
u32 sceSasSetGrain ( u32 core , int grain )
{
2012-12-17 20:15:23 +01:00
INFO_LOG ( HLE , " 0=sceSasSetGrain(core=%08x, grain=%i) " , core , grain ) ;
2012-12-16 20:40:49 +01:00
sas . SetGrainSize ( grain ) ;
2012-12-08 14:13:41 +08:00
return 0 ;
2012-12-07 12:45:16 +08:00
}
2012-12-09 07:56:21 +08:00
u32 sceSasGetOutputMode ( u32 core )
{
DEBUG_LOG ( HLE , " 0=sceSasGetOutputMode(core=%08x) " , core ) ;
2012-12-09 15:27:21 +07:00
return sas . outputMode ;
2012-12-09 07:56:21 +08:00
}
u32 sceSasSetOutputMode ( u32 core , u32 outputMode )
{
DEBUG_LOG ( HLE , " 0=sceSasSetOutputMode(core=%08x, outputMode=%i) " , core , outputMode ) ;
2012-12-09 15:27:21 +07:00
sas . outputMode = outputMode ;
2012-12-09 07:56:21 +08:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-16 20:40:49 +01:00
u32 sceSasSetVoicePCM ( u32 core , int voiceNum , u32 pcmAddr , int size , int loop )
2012-11-01 16:19:01 +01:00
{
2012-12-09 07:56:21 +08:00
DEBUG_LOG ( HLE , " 0=sceSasSetVoicePCM(core=%08x, voicenum=%i, pcmAddr=%08x, size=%i, loop=%i) " , core , voiceNum , pcmAddr , size , loop ) ;
2012-12-16 20:40:49 +01:00
SasVoice & v = sas . voices [ voiceNum ] ;
2012-12-17 18:05:10 +01:00
v . type = VOICETYPE_PCM ;
2012-12-09 07:56:21 +08:00
v . pcmAddr = pcmAddr ;
2012-12-16 20:40:49 +01:00
v . pcmSize = size ;
2012-12-17 18:05:10 +01:00
v . loop = loop ? true : false ;
2012-12-09 07:56:21 +08:00
v . playing = true ;
2012-12-16 20:40:49 +01:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-07 12:45:16 +08:00
u32 sceSasGetAllEnvelopeHeights ( u32 core , u32 heightsAddr )
{
DEBUG_LOG ( HLE , " 0=sceSasGetAllEnvelopeHeights(core=%08x, heightsAddr=%i) " , core , heightsAddr ) ;
2012-12-09 15:27:21 +07:00
if ( Memory : : IsValidAddress ( heightsAddr ) ) {
for ( int i = 0 ; i < sas . length ; i + + ) {
2012-12-17 18:05:10 +01:00
int voiceHeight = sas . voices [ i ] . envelope . GetHeight ( ) ;
2012-12-09 15:27:21 +07:00
Memory : : Write_U32 ( voiceHeight , heightsAddr + i * 4 ) ;
}
2012-12-07 12:45:16 +08:00
}
2012-12-09 15:27:21 +07:00
return 0 ;
2012-12-07 12:45:16 +08:00
}
2012-11-01 16:19:01 +01:00
2012-12-17 18:05:10 +01:00
u32 sceSasSetTriangularWave ( u32 sasCore , int voice , int unknown )
{
ERROR_LOG ( HLE , " UNIMPL 0=sceSasSetTriangularWave(core=%08x, voice=%i, unknown=%i) " , sasCore , voice , unknown ) ;
return 0 ;
}
u32 sceSasSetSteepWave ( u32 sasCore , int voice , int unknown )
{
ERROR_LOG ( HLE , " UNIMPL 0=sceSasSetSteepWave(core=%08x, voice=%i, unknown=%i) " , sasCore , voice , unknown ) ;
return 0 ;
}
2012-11-01 16:19:01 +01:00
const HLEFunction sceSasCore [ ] =
{
2012-11-05 10:05:09 +01:00
{ 0x42778a9f , WrapU_UUUUU < sceSasInit > , " __sceSasInit " } , // (SceUID * sasCore, int grain, int maxVoices, int outputMode, int sampleRate)
2012-12-16 20:40:49 +01:00
{ 0xa3589d81 , WrapU_UU < _sceSasCore > , " __sceSasCore " } ,
{ 0x50a14dfc , WrapU_UU < _sceSasCoreWithMix > , " __sceSasCoreWithMix " } , // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume)
2012-12-17 18:05:10 +01:00
{ 0x68a46b95 , WrapU_U < sceSasGetEndFlag > , " __sceSasGetEndFlag " } ,
2012-12-16 20:40:49 +01:00
{ 0x440ca7d8 , WrapU_UIIIII < sceSasSetVolume > , " __sceSasSetVolume " } ,
{ 0xad84d37f , WrapU_UII < sceSasSetPitch > , " __sceSasSetPitch " } ,
2012-12-17 18:05:10 +01:00
{ 0x99944089 , WrapU_UIUII < sceSasSetVoice > , " __sceSasSetVoice " } ,
2012-12-07 01:45:09 +08:00
{ 0xb7660a23 , WrapU_UII < sceSasSetNoise > , " __sceSasSetNoise " } ,
2012-12-05 23:51:10 +08:00
{ 0x019b25eb , WrapU_UIIIIII < sceSasSetADSR > , " __sceSasSetADSR " } ,
2012-12-06 00:17:55 +08:00
{ 0x9ec3676a , WrapU_UIIIIII < sceSasSetADSRMode > , " __sceSasSetADSRmode " } ,
2012-12-07 01:45:09 +08:00
{ 0x5f9529f6 , WrapU_UII < sceSasSetSL > , " __sceSasSetSL " } ,
2012-11-05 10:05:09 +01:00
{ 0x74ae582a , WrapU_UU < sceSasGetEnvelopeHeight > , " __sceSasGetEnvelopeHeight " } ,
{ 0xcbcd4f79 , WrapU_UUUU < sceSasSetSimpleADSR > , " __sceSasSetSimpleADSR " } ,
2012-12-16 20:40:49 +01:00
{ 0xa0cf2fa4 , WrapU_UI < sceSasSetKeyOff > , " __sceSasSetKeyOff " } ,
2012-12-17 18:05:10 +01:00
{ 0x76f01aca , WrapU_UI < sceSasSetKeyOn > , " __sceSasSetKeyOn " } ,
{ 0xf983b186 , WrapU_UII < sceSasRevVON > , " __sceSasRevVON " } ,
{ 0xd5a229c9 , WrapU_UII < sceSasRevEVOL > , " __sceSasRevEVOL " } , // effect volume
{ 0x33d4ab37 , WrapU_UI < sceSasRevType > , " __sceSasRevType " } ,
{ 0x267a6dd2 , WrapU_UII < sceSasRevParam > , " __sceSasRevParam " } ,
{ 0x2c8e6ab3 , WrapU_U < sceSasGetPauseFlag > , " __sceSasGetPauseFlag " } ,
2012-12-07 12:45:16 +08:00
{ 0x787d04d5 , WrapU_UII < sceSasSetPause > , " __sceSasSetPause " } ,
2012-12-17 18:05:10 +01:00
{ 0xa232cbe6 , WrapU_UII < sceSasSetTriangularWave > , " __sceSasSetTriangularWave " } ,
{ 0xd5ebbbcd , WrapU_UII < sceSasSetSteepWave > , " __sceSasSetSteepWave " } ,
2012-12-07 12:45:16 +08:00
{ 0xBD11B7C2 , WrapU_U < sceSasGetGrain > , " __sceSasGetGrain " } ,
{ 0xd1e0a01e , WrapU_UI < sceSasSetGrain > , " __sceSasSetGrain " } ,
{ 0xe175ef66 , WrapU_U < sceSasGetOutputMode > , " __sceSasGetOutputmode " } ,
{ 0xe855bf76 , WrapU_UU < sceSasSetOutputMode > , " __sceSasSetOutputmode " } ,
2012-12-17 18:05:10 +01:00
{ 0x07f58c24 , WrapU_UU < sceSasGetAllEnvelopeHeights > , " __sceSasGetAllEnvelopeHeights " } ,
2012-12-16 20:40:49 +01:00
{ 0xE1CD9561 , WrapU_UIUII < sceSasSetVoicePCM > , " __sceSasSetVoicePCM " } ,
2012-11-01 16:19:01 +01:00
} ;
void Register_sceSasCore ( )
{
RegisterModule ( " sceSasCore " , ARRAY_SIZE ( sceSasCore ) , sceSasCore ) ;
}