DSP NULL now works with Wii games.

Something seriously needs to be done about DSP NULL, so many lines of computation are absolutely redundant over there, since the plugin does practically nothing.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2006 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
XTra.KrazzY 2009-01-24 22:53:25 +00:00
parent 2e92b94e4a
commit beaf8138f2
14 changed files with 425 additions and 380 deletions

View file

@ -37,7 +37,6 @@ extern CDebugger* m_frame;
#include "UCode_AX.h" #include "UCode_AX.h"
#include "UCode_AX_Voice.h" #include "UCode_AX_Voice.h"
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// Externals // Externals
// ----------- // -----------

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9,00" Version="9.00"
Name="Plugin_DSP_NULL" Name="Plugin_DSP_NULL"
ProjectGUID="{C6CC7A52-0FDD-433A-B2CF-9C6F187DA807}" ProjectGUID="{C6CC7A52-0FDD-433A-B2CF-9C6F187DA807}"
RootNamespace="Plugin_DSP" RootNamespace="Plugin_DSP"
@ -636,10 +636,26 @@
RelativePath=".\Src\UCodes\UCode_AX.h" RelativePath=".\Src\UCodes\UCode_AX.h"
> >
</File> </File>
<File
RelativePath=".\Src\UCodes\UCode_AX_ADPCM.h"
>
</File>
<File
RelativePath=".\Src\UCodes\UCode_AX_Voice.h"
>
</File>
<File <File
RelativePath=".\Src\UCodes\UCode_AXStructs.h" RelativePath=".\Src\UCodes\UCode_AXStructs.h"
> >
</File> </File>
<File
RelativePath=".\Src\UCodes\UCode_AXWii.cpp"
>
</File>
<File
RelativePath=".\Src\UCodes\UCode_AXWii.h"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<File <File

View file

@ -4,6 +4,16 @@
#include "Common.h" #include "Common.h"
#include "Globals.h" #include "Globals.h"
// debugger externals that are needed even in Release builds
bool gSSBM = true;
bool gSSBMremedy1 = true;
bool gSSBMremedy2 = true;
bool gSequenced = true;
bool gVolume = true;
bool gReset = false;
float ratioFactor; // a global to get the ratio factor from MixAdd
void __Log(int, const char *fmt, ...) void __Log(int, const char *fmt, ...)
{ {
DebugLog(fmt); DebugLog(fmt);

View file

@ -15,19 +15,37 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "FileUtil.h" // For IsDirectory()
#include "../Globals.h" #include "StringUtil.h" // For StringFromFormat()
#include <sstream>
#include "../MailHandler.h" #include "../MailHandler.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_AXStructs.h" #include "UCode_AXStructs.h"
#include "UCode_AX.h" #include "UCode_AX.h"
#include "UCode_AX_Voice.h"
CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii)
// ------------------------------------------------------------------
// Externals
// -----------
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
extern bool gSequenced;
extern bool gVolume;
extern bool gReset;
extern std::string gpName;
std::vector<std::string> sMailLog, sMailTime;
// -----------
CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler) : IUCode(_rMailHandler)
, m_addressPBs(0xFFFFFFFF) , m_addressPBs(0xFFFFFFFF)
, wii_mode(wii)
{ {
// we got loaded // we got loaded
m_rMailHandler.PushMail(0xDCD10000); m_rMailHandler.PushMail(0xDCD10000);
@ -44,279 +62,211 @@ CUCode_AX::~CUCode_AX()
delete [] temprbuffer; delete [] temprbuffer;
} }
void CUCode_AX::HandleMail(u32 _uMail)
// ============================================
// Save file to harddrive
// ----------------
void CUCode_AX::SaveLogFile(std::string f, int resizeTo, bool type, bool Wii)
{ {
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) if (gpName.length() > 0) // this is currently off in the Release build
{ {
// a new List std::ostringstream ci;
} std::ostringstream cType;
else
{ ci << (resizeTo - 1); // write ci
AXTask(_uMail); cType << type; // write cType
std::string FileName = FULL_MAIL_LOGS_DIR + gpName;
FileName += "_sep"; FileName += ci.str(); FileName += "_sep"; FileName += cType.str();
FileName += Wii ? "_sepWii_sep" : "_sepGC_sep"; FileName += ".log";
FILE* fhandle = fopen(FileName.c_str(), "w");
fprintf(fhandle, "%s", f.c_str());
fflush(fhandle); fhandle = NULL;
} }
} }
s16 CUCode_AX::ADPCM_Step(AXParamBlock& pb, u32& samplePos, u32 newSamplePos, u16 frac)
{
PBADPCMInfo &adpcm = pb.adpcm;
while (samplePos < newSamplePos) // ============================================
// Save the logged AX mail
// ----------------
void CUCode_AX::SaveLog_(bool Wii, const char* _fmt, va_list ap)
{
char Msg[512];
vsprintf(Msg, _fmt, ap);
TmpMailLog += Msg;
TmpMailLog += "\n";
}
// ----------------
// ============================================
// Save the whole AX mail
// ----------------
void CUCode_AX::SaveMail(bool Wii, u32 _uMail)
{
}
// ----------------
int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num)
{
int count = 0;
u32 blockAddr = pbs_address;
// reading and 'halfword' swap
for (int i = 0; i < _num; i++)
{ {
if ((samplePos & 15) == 0) const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
if (pSrc != NULL)
{ {
adpcm.pred_scale = g_dspInitialize.pARAM_Read_U8((samplePos & ~15) >> 1); short *pDest = (short *)&_pPBs[i];
samplePos += 2; for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
newSamplePos += 2; {
pDest[p] = Common::swap16(pSrc[p]);
#if defined(HAVE_WX) && HAVE_WX
#if defined(_DEBUG) || defined(DEBUGFAST)
if(m_frame) m_frame->gLastBlock = blockAddr + p*2 + 2; // save last block location
#endif
#endif
}
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
count++;
// Detect the last mail by checking when next_pb = 0
u32 next_pb = (Common::swap16(pSrc[0]) << 16) | Common::swap16(pSrc[1]);
if(next_pb == 0) break;
}
else
break;
}
// return the number of read PBs
return count;
}
void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num)
{
u32 blockAddr = pbs_address;
// write back and 'halfword'swap
for (int i = 0; i < _num; i++)
{
short* pSrc = (short*)&_pPBs[i];
short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr);
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
pDest[p] = Common::swap16(pSrc[p]);
} }
int scale = 1 << (adpcm.pred_scale & 0xF); // next block
int coef_idx = adpcm.pred_scale >> 4; blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
s32 coef1 = adpcm.coefs[coef_idx * 2 + 0];
s32 coef2 = adpcm.coefs[coef_idx * 2 + 1];
int temp = (samplePos & 1) ?
(g_dspInitialize.pARAM_Read_U8(samplePos >> 1) & 0xF) :
(g_dspInitialize.pARAM_Read_U8(samplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11);
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
adpcm.yn2 = adpcm.yn1;
adpcm.yn1 = val;
samplePos++;
} }
return adpcm.yn1;
}
void ADPCM_Loop(AXParamBlock& pb)
{
if (!pb.is_stream)
{
pb.adpcm.yn1 = pb.adpcm_loop_info.yn1;
pb.adpcm.yn2 = pb.adpcm_loop_info.yn2;
pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale;
}
//else stream and we should not attempt to replace values
} }
void CUCode_AX::MixAdd(short* _pBuffer, int _iSize) void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
{ {
AXParamBlock PBs[NUMBER_OF_PBS]; AXParamBlock PBs[NUMBER_OF_PBS];
// read out pbs
int numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS);
if (_iSize > 1024 * 1024) if (_iSize > 1024 * 1024)
_iSize = 1024 * 1024; _iSize = 1024 * 1024;
memset(templbuffer, 0, _iSize * sizeof(int)); memset(templbuffer, 0, _iSize * sizeof(int));
memset(temprbuffer, 0, _iSize * sizeof(int)); memset(temprbuffer, 0, _iSize * sizeof(int));
// read out pbs
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
float ratioFactor = 32000.0f / 44100.0f; // ---------------------------------------------------------------------------------------
/* Make the updates we are told to do. When there are multiple updates for a block they
are placed in memory directly following updaddr. They are mostly for initial time
delays, sometimes for the FIR filter or channel volumes. We do all of them at once here.
If we get both an on and an off update we chose on. Perhaps that makes the RE1 music
work better. */
// ------------
for (int i = 0; i < numberOfPBs; i++)
{
u16 *pDest = (u16 *)&PBs[i];
u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates
u16 upd3 = pDest[37]; u16 upd4 = pDest[38];
u16 upd_hi = pDest[39]; // update addr
u16 upd_lo = pDest[40];
int numupd = upd0 + upd1 + upd2 + upd3 + upd4;
if(numupd > 64) numupd = 64; // prevent crazy values
const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
int on = false, off = false;
for (int j = 0; j < numupd; j++)
{
const u16 updpar = Memory_Read_U16(updaddr + j);
const u16 upddata = Memory_Read_U16(updaddr + j + 2);
// some safety checks, I hope it's enough
if(updaddr > 0x80000000 && updaddr < 0x817fffff
&& updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
// 0-3, those are important
//&& (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think
// but I don't know how or when
&& gSequenced) // on and off option
{
pDest[updpar] = upddata;
}
if (updpar == 7 && upddata == 1) on++;
if (updpar == 7 && upddata == 1) off++;
}
// hack: if we get both an on and an off select on rather than off
if (on > 0 && off > 0) pDest[7] = 1;
}
//PrintFile(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
// ------------
for (int i = 0; i < numberOfPBs; i++) for (int i = 0; i < numberOfPBs; i++)
{ {
AXParamBlock& pb = PBs[i]; AXParamBlock& pb = PBs[i];
MixAddVoice(pb, templbuffer, temprbuffer, _iSize, false);
if (pb.running)
{
// =======================================================================================
// Set initial parameters
// ---------------------------------------------------------------------------------------
//constants
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor);
//variables
u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo;
u32 frac = pb.src.cur_addr_frac;
// =======================================================================================
// =======================================================================================
// Handle no-src streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0
// and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This
// makes samplePos update in the correct way.
// ---------------------------------------------------------------------------------------
// Stream settings
// src_type = 2 (most other games have src_type = 0)
// ---------------------------------------------------------------------------------------
// Affected games:
// Baten Kaitos - Eternal Wings (2003)
// Baten Kaitos - Origins (2006)?
// ?
// ---------------------------------------------------------------------------------------
if(pb.src_type == 2)
{
pb.src.ratio_hi = 1;
}
// =======================================================================================
// =======================================================================================
// Games that use looping to play non-looping music streams. SSBM has info in all pb.adpcm_loop_info
// parameters but has pb.audio_addr.looping = 0. If we treat these streams like any other looping
// streams the music works.
// ---------------------------------------------------------------------------------------
if(pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2)
{
pb.audio_addr.looping = 1;
}
// =======================================================================================
// =======================================================================================
// Streaming music and volume - A lot of music in Paper Mario use the exat same settings, namely
// these:
// Base settings
// is_stream = 1
// src_type = 0
// coef (unknown1) = 1
// PBAudioAddr
// audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0)
// However. Some of the ingame music and seemingly randomly some other music incorrectly get
// volume = 0 for both left and right. There's also an issue of a hanging very similar to the Baten
// hanging. The Baten issue fixed itself when the music stream was allowed to play to the end and
// then stop. However, all five music streams that is playing when the gate locks up in Paper Mario
// is loooping streams... I don't know what may be wrong.
// ---------------------------------------------------------------------------------------
// A game that may be used as a comparison is Starfox Assault also has is_stream = 1, but it
// has src_type = 1, coef (unknown1) = 0 and its pb.src.ratio_lo (fraction) != 0
// =======================================================================================
// =======================================================================================
// Walk through _iSize
for (int s = 0; s < _iSize; s++)
{
int sample = 0;
frac += ratio;
u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac
// =======================================================================================
// Process sample format
// ---------------------------------------------------------------------------------------
switch (pb.audio_addr.sample_format)
{
case AUDIOFORMAT_PCM8:
pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8;
if (pb.src_type == SRCTYPE_NEAREST)
{
sample = pb.adpcm.yn1;
}
else //linear interpolation
{
sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
}
samplePos = newSamplePos;
break;
case AUDIOFORMAT_PCM16:
pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1))));
if (pb.src_type == SRCTYPE_NEAREST)
sample = pb.adpcm.yn1;
else //linear interpolation
sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
samplePos = newSamplePos;
break;
case AUDIOFORMAT_ADPCM:
sample = ADPCM_Step(pb, samplePos, newSamplePos, frac);
break;
default:
break;
}
// =======================================================================================
// =======================================================================================
// Volume control
frac &= 0xffff;
int vol = pb.vol_env.cur_volume >> 9;
sample = sample * vol >> 8;
if (pb.mixer_control & MIXCONTROL_RAMPING)
{
int x = pb.vol_env.cur_volume;
x += pb.vol_env.cur_volume_delta;
if (x < 0) x = 0;
if (x >= 0x7fff) x = 0x7fff;
pb.vol_env.cur_volume = x; // maybe not per sample?? :P
}
int leftmix = pb.mixer.volume_left >> 5;
int rightmix = pb.mixer.volume_right >> 5;
// =======================================================================================
int left = sample * leftmix >> 8;
int right = sample * rightmix >> 8;
//adpcm has to walk from oldSamplePos to samplePos here
templbuffer[s] += left;
temprbuffer[s] += right;
if (samplePos >= sampleEnd)
{
if (pb.audio_addr.looping == 1)
{
samplePos = loopPos;
if (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM)
ADPCM_Loop(pb);
}
else
{
pb.running = 0;
break;
}
}
} // end of the _iSize loop
// =======================================================================================
pb.src.cur_addr_frac = (u16)frac;
pb.audio_addr.cur_addr_hi = samplePos >> 16;
pb.audio_addr.cur_addr_lo = (u16)samplePos;
}
} }
// write back out pbs
WriteBackPBs(m_addressPBs, PBs, numberOfPBs);
for (int i = 0; i < _iSize; i++) for (int i = 0; i < _iSize; i++)
{ {
// Clamp into 16-bit. Maybe we should add a volume compressor here. // Clamp into 16-bit. Maybe we should add a volume compressor here.
int left = templbuffer[i]; int left = templbuffer[i] + _pBuffer[0];
int right = temprbuffer[i]; int right = temprbuffer[i] + _pBuffer[1];
if (left < -32767) left = -32767; if (left < -32767) left = -32767;
if (left > 32767) left = 32767; if (left > 32767) left = 32767;
if (right < -32767) right = -32767; if (right < -32767) right = -32767;
if (right > 32767) right = 32767; if (right > 32767) right = 32767;
*_pBuffer++ += left; *_pBuffer++ = left;
*_pBuffer++ += right; *_pBuffer++ = right;
} }
// write back out pbs
WriteBackPBs(PBs, numberOfPBs);
} }
// ------------------------------------------------------------------------------
// Handle incoming mail
// -----------
void CUCode_AX::HandleMail(u32 _uMail)
{
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
{
// a new List
DebugLog(" >>>> u32 MAIL : General Mail (%08x)", _uMail);
}
else
{
DebugLog(" >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
AXTask(_uMail);
}
}
// ------------------------------------------------------------------------------
// Update with DSP Interrupt
// -----------
void CUCode_AX::Update() void CUCode_AX::Update()
{ {
// check if we have to sent something // check if we have to sent something
@ -325,14 +275,25 @@ void CUCode_AX::Update()
g_dspInitialize.pGenerateDSPInterrupt(); g_dspInitialize.pGenerateDSPInterrupt();
} }
} }
// -----------
// Shortcut to avoid having to write SaveLog(false, ...) every time
void CUCode_AX::SaveLog(const char* _fmt, ...)
{
}
// ============================================
// AX seems to bootup one task only and waits for resume-callbacks // AX seems to bootup one task only and waits for resume-callbacks
// everytime the DSP has "spare time" it sends a resume-mail to the CPU // everytime the DSP has "spare time" it sends a resume-mail to the CPU
// and the __DSPHandler calls a AX-Callback which generates a new AXFrame // and the __DSPHandler calls a AX-Callback which generates a new AXFrame
bool CUCode_AX::AXTask(u32& _uMail) bool CUCode_AX::AXTask(u32& _uMail)
{ {
u32 uAddress = _uMail; u32 uAddress = _uMail;
DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress); SaveLog("Begin");
SaveLog("=====================================================================");
SaveLog("%08x : AXTask - AXCommandList-Addr:", uAddress);
u32 Addr__AXStudio; u32 Addr__AXStudio;
u32 Addr__AXOutSBuffer; u32 Addr__AXOutSBuffer;
@ -342,6 +303,8 @@ bool CUCode_AX::AXTask(u32& _uMail)
u32 Addr__12; u32 Addr__12;
u32 Addr__4_1; u32 Addr__4_1;
u32 Addr__4_2; u32 Addr__4_2;
// u32 Addr__4_3;
// u32 Addr__4_4;
u32 Addr__5_1; u32 Addr__5_1;
u32 Addr__5_2; u32 Addr__5_2;
u32 Addr__6; u32 Addr__6;
@ -359,12 +322,10 @@ bool CUCode_AX::AXTask(u32& _uMail)
case AXLIST_STUDIOADDR: //00 case AXLIST_STUDIOADDR: //00
Addr__AXStudio = Memory_Read_U32(uAddress); Addr__AXStudio = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
if (wii_mode) SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio);
uAddress += 6;
DebugLog("AXLIST studio address: %08x", Addr__AXStudio);
break; break;
case 0x001: case 0x001: // 2byte x 10
{ {
u32 address = Memory_Read_U32(uAddress); u32 address = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
@ -374,7 +335,7 @@ bool CUCode_AX::AXTask(u32& _uMail)
uAddress += 2; uAddress += 2;
u16 param3 = Memory_Read_U16(uAddress); u16 param3 = Memory_Read_U16(uAddress);
uAddress += 2; uAddress += 2;
DebugLog("AXLIST 1: %08x, %04x, %04x, %04x", address, param1, param2, param3); SaveLog("%08x : AXLIST 1: %08x, %04x, %04x, %04x", uAddress, address, param1, param2, param3);
} }
break; break;
@ -388,20 +349,20 @@ bool CUCode_AX::AXTask(u32& _uMail)
m_addressPBs = Memory_Read_U32(uAddress); m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST PB address: %08x", m_addressPBs); SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs);
} }
break; break;
case 0x0003: case 0x0003:
DebugLog("AXLIST command 0x0003 ????"); SaveLog("%08x : AXLIST command 0x0003 ????");
break; break;
case 0x0004: case 0x0004: // AUX?
Addr__4_1 = Memory_Read_U32(uAddress); Addr__4_1 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
Addr__4_2 = Memory_Read_U32(uAddress); Addr__4_2 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST 4_1 4_2 addresses: %08x %08x", Addr__4_1, Addr__4_2); SaveLog("%08x : AXLIST 4_1 4_2 addresses: %08x %08x", uAddress, Addr__4_1, Addr__4_2);
break; break;
case 0x0005: case 0x0005:
@ -409,56 +370,51 @@ bool CUCode_AX::AXTask(u32& _uMail)
uAddress += 4; uAddress += 4;
Addr__5_2 = Memory_Read_U32(uAddress); Addr__5_2 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST 5_1 5_2 addresses: %08x %08x", Addr__5_1, Addr__5_2); SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2);
break; break;
case 0x0006: case 0x0006:
Addr__6 = Memory_Read_U32(uAddress); Addr__6 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST 6 address: %08x", Addr__6); SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6);
break; break;
case AXLIST_SBUFFER: case AXLIST_SBUFFER:
// Hopefully this is where in main ram to write.
Addr__AXOutSBuffer = Memory_Read_U32(uAddress); Addr__AXOutSBuffer = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
if (wii_mode) { SaveLog("%08x : AXLIST OutSBuffer address: %08x", uAddress, Addr__AXOutSBuffer);
uAddress += 12;
}
DebugLog("AXLIST OutSBuffer address: %08x", Addr__AXOutSBuffer);
break; break;
case 0x0009: case 0x0009:
Addr__9 = Memory_Read_U32(uAddress); Addr__9 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST 6 address: %08x", Addr__9); SaveLog("%08x : AXLIST 6 address: %08x", Addr__9);
break; break;
case AXLIST_COMPRESSORTABLE: // 0xa case AXLIST_COMPRESSORTABLE: // 0xa
Addr__A = Memory_Read_U32(uAddress); Addr__A = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
if (wii_mode) { SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A);
// There's one more here.
// uAddress += 4;
}
DebugLog("AXLIST CompressorTable address: %08x", Addr__A);
break; break;
case 0x000e: case 0x000e:
Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress); Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
// Addr__AXOutSBuffer_2 is the address in RAM that we are supposed to mix to.
// Although we don't, currently.
Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress); Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
DebugLog("AXLIST sbuf2 addresses: %08x %08x", Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2); SaveLog("%08x : AXLIST sbuf2 addresses: %08x %08x", uAddress, Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2);
break; break;
case AXLIST_END: case AXLIST_END:
bExecuteList = false; bExecuteList = false;
DebugLog("AXLIST end"); SaveLog("%08x : AXLIST end", uAddress);
break; break;
case 0x0010: //Super Monkey Ball 2 case 0x0010: //Super Monkey Ball 2
DebugLog("AXLIST unknown"); SaveLog("%08x : AXLIST 0x0010", uAddress);
//should probably read/skip stuff here //should probably read/skip stuff here
uAddress += 8; uAddress += 8;
break; break;
@ -476,22 +432,7 @@ bool CUCode_AX::AXTask(u32& _uMail)
uAddress += 6 * 4; // 6 Addresses. uAddress += 6 * 4; // 6 Addresses.
break; break;
case 0x000d: default:
if (wii_mode) {
uAddress += 4 * 4; // 4 addresses. another aux?
break;
}
// non-wii : fall through
case 0x000b:
if (wii_mode) {
uAddress += 2; // one 0x8000 in rabbids
uAddress += 4 * 2; // then two RAM addressses
break;
}
// non-wii : fall through
default:
{ {
static bool bFirst = true; static bool bFirst = true;
if (bFirst == true) if (bFirst == true)
@ -508,8 +449,9 @@ bool CUCode_AX::AXTask(u32& _uMail)
num += 2; num += 2;
} }
// Wii AX will always show this
PanicAlert(szTemp); PanicAlert(szTemp);
bFirst = false; // bFirst = false;
} }
// unknown command so stop the execution of this TaskList // unknown command so stop the execution of this TaskList
@ -520,55 +462,11 @@ bool CUCode_AX::AXTask(u32& _uMail)
if (bExecuteList) if (bExecuteList)
last_valid_command = iCommand; last_valid_command = iCommand;
} }
DebugLog("AXTask - done, send resume"); SaveLog("AXTask - done, send resume");
SaveLog("=====================================================================");
SaveLog("End");
// i hope resume is okay AX // i hope resume is okay AX
m_rMailHandler.PushMail(0xDCD10001); m_rMailHandler.PushMail(0xDCD10001);
return true; return true;
} }
int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num)
{
int count = 0;
u32 blockAddr = m_addressPBs;
// reading and 'halfword' swap
for (int i = 0; i < _num; i++)
{
const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
if (pSrc != NULL)
{
short *pDest = (short *)&_pPBs[i];
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
pDest[p] = Common::swap16(pSrc[p]);
}
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
count++;
}
else
break;
}
// return the number of readed PBs
return count;
}
void CUCode_AX::WriteBackPBs(AXParamBlock* _pPBs, int _num)
{
u32 blockAddr = m_addressPBs;
// write back and 'halfword'swap
for (int i = 0; i < _num; i++)
{
short* pSrc = (short*)&_pPBs[i];
short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr);
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
pDest[p] = Common::swap16(pSrc[p]);
}
// next block
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
}
}

View file

@ -18,25 +18,40 @@
#ifndef _UCODE_AX #ifndef _UCODE_AX
#define _UCODE_AX #define _UCODE_AX
#include <iostream>
#include "pluginspecs_dsp.h"
#include "UCode_AXStructs.h" #include "UCode_AXStructs.h"
enum
{
NUMBER_OF_PBS = 128
};
class CUCode_AX : public IUCode class CUCode_AX : public IUCode
{ {
public: public:
CUCode_AX(CMailHandler& _rMailHandler, bool wii = false); CUCode_AX(CMailHandler& _rMailHandler);
virtual ~CUCode_AX(); virtual ~CUCode_AX();
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);
void MixAdd(short* _pBuffer, int _iSize); void MixAdd(short* _pBuffer, int _iSize);
void Update(); void Update();
// Logging
//template<class ParamBlockType>
//void Logging(short* _pBuffer, int _iSize, int a, bool Wii, ParamBlockType &PBs, int numberOfPBs);
void Logging(short* _pBuffer, int _iSize, int a, bool Wii);
void SaveLog_(bool Wii, const char* _fmt, va_list ap);
void SaveMail(bool Wii, u32 _uMail);
void SaveLogFile(std::string f, int resizeTo, bool type, bool Wii);
std::string TmpMailLog;
int saveNext;
// PBs
u32 m_addressPBs;
u32 _CRC;
private: private:
enum
{
NUMBER_OF_PBS = 64
};
enum enum
{ {
MAIL_AX_ALIST = 0xBABE0000, MAIL_AX_ALIST = 0xBABE0000,
@ -47,21 +62,17 @@ private:
AXLIST_END = 0x000F AXLIST_END = 0x000F
}; };
// PBs
u32 m_addressPBs;
int *templbuffer; int *templbuffer;
int *temprbuffer; int *temprbuffer;
bool wii_mode;
// ax task message handler // ax task message handler
bool AXTask(u32& _uMail); bool AXTask(u32& _uMail);
void SaveLog(const char* _fmt, ...);
void SendMail(u32 _uMail); void SendMail(u32 _uMail);
int ReadOutPBs(AXParamBlock *_pPBs, int _num);
void WriteBackPBs(AXParamBlock *_pPBs, int _num);
s16 ADPCM_Step(AXParamBlock& pb, u32& samplePos, u32 newSamplePos, u16 frac);
}; };
int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num);
void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num);
#endif // _UCODE_AX #endif // _UCODE_AX

View file

@ -15,8 +15,8 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef UCODE_AX_STRUCTS #ifndef _UCODE_AX_STRUCTS_H
#define UCODE_AX_STRUCTS #define _UCODE_AX_STRUCTS_H
struct PBMixer struct PBMixer
{ {
@ -29,9 +29,26 @@ struct PBMixer
u16 unknown4[6]; u16 unknown4[6];
}; };
struct PBMixerWii
{
u16 volume_left;
u16 unknown;
u16 volume_right;
u16 unknown2;
u16 unknown3[12];
u16 unknown4[8];
};
struct PBInitialTimeDelay struct PBInitialTimeDelay
{ {
u16 unknown[7]; u16 on;
u16 addrMemHigh;
u16 addrMemLow;
u16 offsetLeft;
u16 offsetRight;
u16 targetLeft;
u16 targetRight;
}; };
// Update data - read these each 1ms subframe and use them! // Update data - read these each 1ms subframe and use them!
@ -45,11 +62,28 @@ struct PBUpdates
u16 data_lo; u16 data_lo;
}; };
struct PBUnknown struct PBUpdatesWii
{
u16 num_updates[3];
u16 data_hi; // These point to main RAM. Not sure about the structure of the data.
u16 data_lo;
};
struct PBDpop
{ {
s16 unknown[9]; s16 unknown[9];
}; };
struct PBDpopWii
{
s16 unknown[12];
};
struct PBDpopWii_ // new CRC version
{
s16 unknown[7];
};
struct PBVolumeEnvelope struct PBVolumeEnvelope
{ {
u16 cur_volume; u16 cur_volume;
@ -76,7 +110,7 @@ struct PBAudioAddr
struct PBADPCMInfo struct PBADPCMInfo
{ {
s16 coefs[16]; s16 coefs[16];
u16 unknown; u16 gain;
u16 pred_scale; u16 pred_scale;
s16 yn1; s16 yn1;
s16 yn2; s16 yn2;
@ -106,23 +140,97 @@ struct AXParamBlock
u16 this_pb_lo; u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, ?, linear) u16 src_type; // Type of sample rate converter (none, ?, linear)
u16 unknown1; u16 coef_select;
u16 mixer_control; u16 mixer_control;
u16 running; // 1=RUN 0=STOP u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot u16 is_stream; // 1 = stream, 0 = one shot
PBMixer mixer; /* 9 */ PBMixer mixer;
PBInitialTimeDelay initial_time_delay; /* 27 */ PBInitialTimeDelay initial_time_delay;
PBUpdates updates; /* 34 */ PBUpdates updates;
PBUnknown unknown2; /* 41 */ PBDpop dpop;
PBVolumeEnvelope vol_env; /* 50 */ PBVolumeEnvelope vol_env;
PBUnknown2 unknown3; /* 52 */ PBUnknown2 unknown3;
PBAudioAddr audio_addr; /* 55 */ PBAudioAddr audio_addr;
PBADPCMInfo adpcm; /* 63 */ PBADPCMInfo adpcm;
PBSampleRateConverter src; /* 83 */ PBSampleRateConverter src;
PBADPCMLoopInfo adpcm_loop_info; /* 90 */ PBADPCMLoopInfo adpcm_loop_info;
u16 unknown_maybe_padding[3]; /* 93 */ u16 unknown_maybe_padding[3];
};
struct PBLpf
{
u16 enabled;
u16 yn1;
u16 a0;
u16 b0;
};
struct PBHpf
{
u16 enabled;
u16 yn1;
u16 a0;
u16 b0;
};
struct AXParamBlockWii
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, ?, linear)
u16 coef_select;
u32 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
/* 10 */ PBMixerWii mixer;
/* 34 */ PBInitialTimeDelay initial_time_delay;
/* 41 */ PBUpdatesWii updates;
/* 46 */ PBDpopWii dpop;
/* 58 */ PBVolumeEnvelope vol_env;
/* 60 */ PBAudioAddr audio_addr;
/* 68 */ PBADPCMInfo adpcm;
/* 88 */ PBSampleRateConverter src;
/* 95 */ PBADPCMLoopInfo adpcm_loop_info;
/* 98 */ PBLpf lpf;
/* 102 */ PBHpf hpf;
/* 106 */ u16 pad[22];
};
struct AXParamBlockWii_ // new CRC version
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, ?, linear)
u16 coef_select;
u32 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
/* 10 */ PBMixerWii mixer;
/* 34 */ PBInitialTimeDelay initial_time_delay;
/* 41 */ PBUpdatesWii updates;
/* 46 */ PBDpopWii_ dpop;
/* 53 */ PBVolumeEnvelope vol_env;
/* 55 */ PBAudioAddr audio_addr;
/* 63 */ PBADPCMInfo adpcm;
/* 83 */ PBSampleRateConverter src;
/* 90 */ PBADPCMLoopInfo adpcm_loop_info;
/* 93 */ PBLpf lpf;
/* 97 */ PBHpf hpf;
/* 101 */ u16 pad[27];
}; };
enum { enum {
@ -137,5 +245,4 @@ enum {
MIXCONTROL_RAMPING = 8, MIXCONTROL_RAMPING = 8,
}; };
#endif // _UCODE_AX_STRUCTS_H
#endif

View file

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "../DSPHandler.h" #include "../DSPHandler.h"
#include "UCodes.h" #include "UCodes.h"

View file

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "../DSPHandler.h" #include "../DSPHandler.h"
#include "UCodes.h" #include "UCodes.h"

View file

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_Jac.h" #include "UCode_Jac.h"
@ -149,7 +148,7 @@ void CUCode_Jac::ExecuteList()
break; break;
default: default:
PanicAlert("UCode Jac unknown cmd: %s (size %)", cmd, m_numSteps); PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps);
DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps); DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
break; break;
} }

View file

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "../DSPHandler.h" #include "../DSPHandler.h"
#include "UCodes.h" #include "UCodes.h"

View file

@ -16,15 +16,13 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Games that uses this UCode: // Games that uses this UCode:
// Zelda: The Windwaker, Mario Sunshine, Mario Kart // Zelda: The Windwaker, Mario Sunshine, Mario Kart, Twilight Princess
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_Zelda.h" #include "UCode_Zelda.h"
#include "../MailHandler.h" #include "../MailHandler.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler) : IUCode(_rMailHandler)
, m_numSteps(0) , m_numSteps(0)
@ -76,6 +74,10 @@ void CUCode_Zelda::HandleMail(u32 _uMail)
} }
} }
void CUCode_Zelda::MixAdd(short* buffer, int size)
{
//TODO(XK): Zelda UCode MixAdd?
}
void CUCode_Zelda::ExecuteList() void CUCode_Zelda::ExecuteList()
{ {

View file

@ -68,6 +68,7 @@ public:
void HandleMail(u32 _uMail); void HandleMail(u32 _uMail);
void Update(); void Update();
void MixAdd(short* buffer, int size);
}; };
#endif #endif

View file

@ -15,12 +15,12 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h" #include "../Globals.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_AX.h" #include "UCode_AX.h"
#include "UCode_AXWii.h"
#include "UCode_Zelda.h" #include "UCode_Zelda.h"
#include "UCode_Jac.h" #include "UCode_Jac.h"
#include "UCode_ROM.h" #include "UCode_ROM.h"
@ -44,7 +44,7 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
case 0xd73338cf: // IPL case 0xd73338cf: // IPL
case 0x42f64ac4: // Luigi (after fix) case 0x42f64ac4: // Luigi (after fix)
case 0x4be6a5cb: // AC, Pikmin (after fix) case 0x4be6a5cb: // AC, Pikmin (after fix)
DebugLog("JAC ucode chosen"); printf("JAC ucode chosen");
return new CUCode_Jac(_rMailHandler); return new CUCode_Jac(_rMailHandler);
case 0x3ad3b7ac: // Naruto3 case 0x3ad3b7ac: // Naruto3
@ -56,25 +56,28 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
// Zelda:OOT, Tony hawk, viewtiful joe // Zelda:OOT, Tony hawk, viewtiful joe
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
DebugLog("AX ucode chosen, yay!"); printf("AX ucode chosen, yay!");
return new CUCode_AX(_rMailHandler); return new CUCode_AX(_rMailHandler);
case 0x6CA33A6D: // DK Jungle Beat case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // zelda case 0x86840740: // zelda
case 0x56d36052: // mario case 0x56d36052: // mario
case 0x2fcdf1ec: // mariokart, zelda 4 swords case 0x2fcdf1ec: // mariokart, zelda 4 swords
DebugLog("Zelda ucode chosen"); printf("Zelda ucode chosen");
return new CUCode_Zelda(_rMailHandler); return new CUCode_Zelda(_rMailHandler);
// WII CRCs // WII CRCs
case 0x6c3f6f94: // zelda - PAL case 0x6c3f6f94: // zelda - PAL
case 0xd643001f: // mario galaxy - PAL case 0xd643001f: // mario galaxy - PAL
DebugLog("Zelda Wii ucode chosen"); printf("Zelda Wii ucode chosen");
return new CUCode_Zelda(_rMailHandler); return new CUCode_Zelda(_rMailHandler);
case 0x5ef56da3: // AX demo
case 0x347112ba: // raving rabbits case 0x347112ba: // raving rabbits
DebugLog("Wii - AX chosen"); case 0xfa450138: // wii sports - PAL
return new CUCode_AX(_rMailHandler, true); case 0xadbc06bd: // Elebits
printf("Wii - AXWii chosen");
return new CUCode_AXWii(_rMailHandler, _CRC);
default: default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC); PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);

View file

@ -24,6 +24,8 @@
DSPInitialize g_dspInitialize; DSPInitialize g_dspInitialize;
u8* g_pMemory; u8* g_pMemory;
std::string gpName;
struct DSPState struct DSPState
{ {
u32 CPUMailbox; u32 CPUMailbox;