DSPHLE: Decoded most of 0x21. Added real conclusions to the switch case to signal the CPU that the voice has been played. More work on 0x20/0x21/Raw (and probably the end of it) this weekend.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3683 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
36883d6a48
commit
e7ec7d56d5
|
@ -99,16 +99,7 @@ void CUCode_Zelda::Update(int cycles)
|
||||||
void CUCode_Zelda::HandleMail(u32 _uMail)
|
void CUCode_Zelda::HandleMail(u32 _uMail)
|
||||||
{
|
{
|
||||||
// WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail);
|
// WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail);
|
||||||
// When we used to lose sync, the last mails we get before the audio goes bye-bye
|
|
||||||
// 0
|
|
||||||
// 0x00000
|
|
||||||
// 0
|
|
||||||
// 0x10000
|
|
||||||
// 0
|
|
||||||
// 0x20000
|
|
||||||
// 0
|
|
||||||
// 0x30000
|
|
||||||
// And then silence... Looks like some reverse countdown :)
|
|
||||||
if (m_bSyncInProgress)
|
if (m_bSyncInProgress)
|
||||||
{
|
{
|
||||||
if (m_bSyncCmdPending)
|
if (m_bSyncCmdPending)
|
||||||
|
|
|
@ -221,6 +221,7 @@ private:
|
||||||
void RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
void RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size);
|
||||||
void RenderVoice_PCM16(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
void RenderVoice_PCM16(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||||
void RenderVoice_AFC(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
void RenderVoice_AFC(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||||
|
void RenderVoice_Raw(ZeldaVoicePB& PB, s32* _Buffer, int _Size);
|
||||||
|
|
||||||
// Renders a voice and mixes it into LeftBuffer, RightBuffer
|
// Renders a voice and mixes it into LeftBuffer, RightBuffer
|
||||||
void RenderAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size);
|
void RenderAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size);
|
||||||
|
|
|
@ -28,6 +28,8 @@ void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Siz
|
||||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
u32 _ratio = (PB.RatioInt << 16);
|
u32 _ratio = (PB.RatioInt << 16);
|
||||||
s64 ratio = (_ratio * ratioFactor) * 16;
|
s64 ratio = (_ratio * ratioFactor) * 16;
|
||||||
|
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
||||||
|
TrueSamplePosition += PB.CurSampleFrac;
|
||||||
|
|
||||||
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
||||||
|
|
||||||
|
@ -65,10 +67,12 @@ _lRestart:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < _Size;)
|
while(i < _Size)
|
||||||
{
|
{
|
||||||
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
|
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
|
||||||
|
|
||||||
|
TrueSamplePosition += (ratio >> 16);
|
||||||
|
|
||||||
_Buffer[i++] = (s32)sample;
|
_Buffer[i++] = (s32)sample;
|
||||||
|
|
||||||
(*(u64*)&pos) += ratio;
|
(*(u64*)&pos) += ratio;
|
||||||
|
@ -87,7 +91,7 @@ _lRestart:
|
||||||
else
|
else
|
||||||
PB.RemLength -= pos[1];
|
PB.RemLength -= pos[1];
|
||||||
|
|
||||||
//PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
|
|
||||||
|
#include "../Config.h"
|
||||||
|
|
||||||
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
||||||
{
|
{
|
||||||
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
||||||
|
@ -157,18 +159,6 @@ void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
|
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
|
||||||
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
|
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
|
||||||
|
|
||||||
WARN_LOG(DSPHLE, "PB Unk09: %04x", PB.volumeLeft1); // often same value as 0a
|
|
||||||
WARN_LOG(DSPHLE, "PB Unk0a: %04x", PB.volumeLeft2);
|
|
||||||
|
|
||||||
WARN_LOG(DSPHLE, "PB Unk0d: %04x", PB.volumeRight1); // often same value as 0e
|
|
||||||
WARN_LOG(DSPHLE, "PB Unk0e: %04x", PB.volumeRight2);
|
|
||||||
|
|
||||||
WARN_LOG(DSPHLE, "PB UnkVol11: %04x", PB.volumeUnknown1_1);
|
|
||||||
WARN_LOG(DSPHLE, "PB UnkVol12: %04x", PB.volumeUnknown1_2);
|
|
||||||
|
|
||||||
WARN_LOG(DSPHLE, "PB UnkVol21: %04x", PB.volumeUnknown2_1);
|
|
||||||
WARN_LOG(DSPHLE, "PB UnkVol22: %04x", PB.volumeUnknown2_2);
|
|
||||||
|
|
||||||
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
|
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
|
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
|
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
|
||||||
|
@ -280,13 +270,98 @@ restart:
|
||||||
|
|
||||||
// i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
|
// i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
|
||||||
// just decrement them with the number of samples you have played
|
// just decrement them with the number of samples you have played
|
||||||
// and incrrease the ARAM Offset in pTest[0x38], pTest[0x39]
|
// and increase the ARAM Offset in pTest[0x38], pTest[0x39]
|
||||||
|
|
||||||
// end of block (Zelda 03b2)
|
// end of block (Zelda 03b2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Researching what's actually inside the mysterious 0x21 case
|
||||||
|
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
|
{
|
||||||
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
|
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
|
||||||
|
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
|
||||||
|
|
||||||
|
if (PB.NeedsReset != 0)
|
||||||
|
{
|
||||||
|
PB.CurBlock = 0x00;
|
||||||
|
|
||||||
|
// Length in samples.
|
||||||
|
PB.RemLength = PB.Length;
|
||||||
|
|
||||||
|
// Copy ARAM addr from r to rw area.
|
||||||
|
PB.CurAddr = PB.StartAddr;
|
||||||
|
PB.ReachedEnd = 0;
|
||||||
|
PB.CurSampleFrac = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PB.KeyOff != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 *source;
|
||||||
|
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
||||||
|
if (m_CRC == 0xD643001F) {
|
||||||
|
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
|
||||||
|
ram_mask = 1024 * 1024 * 64 - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
source = g_dspInitialize.pGetARAMPointer();
|
||||||
|
|
||||||
|
//restart:
|
||||||
|
if (PB.ReachedEnd)
|
||||||
|
{
|
||||||
|
PB.ReachedEnd = 0;
|
||||||
|
|
||||||
|
// HACK: Looping doesn't work.
|
||||||
|
if (true || PB.RepeatMode == 0)
|
||||||
|
{
|
||||||
|
PB.KeyOff = 1;
|
||||||
|
PB.RemLength = 0;
|
||||||
|
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
||||||
|
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
||||||
|
PB.RestartPos = PB.LoopStartPos;
|
||||||
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
u32 prev_addr = PB.CurAddr;
|
||||||
|
|
||||||
|
// Prefill the decode buffer.
|
||||||
|
//AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||||
|
const char *src = (char *)(source + (PB.CurAddr & ram_mask));
|
||||||
|
PB.CurAddr += 9;
|
||||||
|
|
||||||
|
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
||||||
|
TrueSamplePosition += PB.CurSampleFrac;
|
||||||
|
s64 delta = ratio >> 16; // 0x100000000ULL;
|
||||||
|
int sampleCount = 0, realSample = 0;
|
||||||
|
while (sampleCount < _Size)
|
||||||
|
{
|
||||||
|
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
|
||||||
|
| (src[realSample + 3] << 24);
|
||||||
|
|
||||||
|
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
|
||||||
|
|
||||||
|
sampleCount++;
|
||||||
|
realSample += 4;
|
||||||
|
TrueSamplePosition += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
PB.NeedsReset = 0;
|
||||||
|
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
||||||
{
|
{
|
||||||
|
static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
|
||||||
memset(m_TempBuffer, 0, _Size * sizeof(s32));
|
memset(m_TempBuffer, 0, _Size * sizeof(s32));
|
||||||
|
|
||||||
if (PB.IsBlank)
|
if (PB.IsBlank)
|
||||||
|
@ -297,6 +372,19 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// XK: Use this to disable music (GREAT for testing)
|
||||||
|
//if(g_Config.m_DisableStreaming && PB.SoundType == 0x0d00) {
|
||||||
|
// PB.NeedsReset = 0;
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
|
||||||
|
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
|
||||||
|
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
|
||||||
|
PB.Format, PB.SoundType,
|
||||||
|
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
|
||||||
|
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
|
||||||
|
PB.volumeUnknown2_2);*/
|
||||||
|
|
||||||
switch (PB.Format)
|
switch (PB.Format)
|
||||||
{
|
{
|
||||||
// Synthesized sounds
|
// Synthesized sounds
|
||||||
|
@ -322,9 +410,7 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ
|
||||||
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
|
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
|
||||||
case 0x0009: // AFC with normal bitrate (32:9 compression).
|
case 0x0009: // AFC with normal bitrate (32:9 compression).
|
||||||
|
|
||||||
// XK: Use this to disable music (GREAT for testing)
|
|
||||||
//if(PB.SoundType == 0x0d00)
|
|
||||||
// break;
|
|
||||||
RenderVoice_AFC(PB, m_TempBuffer, _Size);
|
RenderVoice_AFC(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -335,11 +421,15 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ
|
||||||
|
|
||||||
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
|
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
|
||||||
case 0x0020:
|
case 0x0020:
|
||||||
case 0x0021: // Important for Zelda WW. Really need to implement - missing it causes hangs.
|
case 0x0021: // Probably raw sound. Important for Zelda WW. Really need to implement - missing it causes hangs.
|
||||||
WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format);
|
WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format);
|
||||||
PB.ReachedEnd = 1;
|
|
||||||
|
// This is what 0x20 and 0x21 do on end of voice
|
||||||
|
PB.RemLength = 0;
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
PB.Status = 0;
|
|
||||||
|
// Caution: Use at your own risk. Sounds awful :)
|
||||||
|
//RenderVoice_Raw(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -354,13 +444,18 @@ void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _Righ
|
||||||
|
|
||||||
for (int i = 0; i < _Size; i++)
|
for (int i = 0; i < _Size; i++)
|
||||||
{
|
{
|
||||||
|
if(PB.volumeLeft2)
|
||||||
|
lastLeft = PB.volumeLeft2;
|
||||||
|
if(PB.volumeRight2)
|
||||||
|
lastRight = PB.volumeRight2;
|
||||||
|
|
||||||
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
|
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
|
||||||
// Really not sure about the masking here, but it seems to kill off some overly loud
|
// Really not sure about the masking here, but it seems to kill off some overly loud
|
||||||
// sounds in Zelda TP. Needs investigation.
|
// sounds in Zelda TP. Needs investigation.
|
||||||
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
|
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||||
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
|
(lastLeft & 0x1FFF) + (lastLeft & 0x1FFF)) * 0.00005);
|
||||||
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
|
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||||
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
|
(lastRight & 0x1FFF) + (lastRight & 0x1FFF)) * 0.00005);
|
||||||
|
|
||||||
if (left < -32768) left = -32768;
|
if (left < -32768) left = -32768;
|
||||||
if (left > 32767) left = 32767;
|
if (left > 32767) left = 32767;
|
||||||
|
|
|
@ -3441,10 +3441,17 @@ void 0a91_Unk() {
|
||||||
|
|
||||||
//////////////////////////////////////////// 0x20 DECODER
|
//////////////////////////////////////////// 0x20 DECODER
|
||||||
{
|
{
|
||||||
0a9a 8900 clr $ACC1
|
// 0a9a 8900 clr $ACC1
|
||||||
0a9b 0f50 lris $AC1.M, #0x50
|
// 0a9b 0f50 lris $AC1.M, #0x50
|
||||||
0a9c 0083 0520 lri $AR3, #0x0520
|
// 0a9c 0083 0520 lri $AR3, #0x0520
|
||||||
0a9e 02bf 0ab3 call 0x0ab3
|
// 0a9e 02bf 0ab3 call 0x0ab3
|
||||||
|
|
||||||
|
ACC1 = 0;
|
||||||
|
AC1.M = 0x50;
|
||||||
|
AR3 = 0x520;
|
||||||
|
|
||||||
|
0ab3_Decoder0x21Core(AC1.M=0x50, AR3=#0x0580);
|
||||||
|
|
||||||
// 0aa0 029f 02d8 jmp 0x02d8
|
// 0aa0 029f 02d8 jmp 0x02d8
|
||||||
GOTO ContinueWithBlock: // in SyncFrame
|
GOTO ContinueWithBlock: // in SyncFrame
|
||||||
}
|
}
|
||||||
|
@ -3485,64 +3492,133 @@ void 0ab3_Decoder0x21Core(AC1.M, AR3) {
|
||||||
// 0ab8 1f1f mrr $AX0.L, $AC1.M
|
// 0ab8 1f1f mrr $AX0.L, $AC1.M
|
||||||
// 0ab9 0a00 lris $AX0.H, #0x00
|
// 0ab9 0a00 lris $AX0.H, #0x00
|
||||||
// 0aba 5800 subax $ACC0, $AX0.L
|
// 0aba 5800 subax $ACC0, $AX0.L
|
||||||
ACC0 = [3a,3b] - AC1.M;
|
ACC0 = [0x043a,0x043b] - AC1.M;
|
||||||
|
|
||||||
|
|
||||||
0abb 0292 0ad1 jg 0x0ad1
|
// 0abb 0292 0ad1 jg 0x0ad1
|
||||||
if ((prev val of)ACC0 > AX0.L) {
|
if ([0x043a,0x043b] > *0x043a) {
|
||||||
0abd 8900 clr $ACC1
|
// Happens when sound has finished playing?
|
||||||
0abe 00c0 043b lr $AR0, @0x043b
|
|
||||||
0ac0 02bf 0af6 call 0x0af6 // 0af6_Decoder0x21_MoreStuff()
|
// 0abd 8900 clr $ACC1
|
||||||
|
// 0abe 00c0 043b lr $AR0, @0x043b
|
||||||
|
ACC1 = 0;
|
||||||
|
AR0 = 0x043b;
|
||||||
|
|
||||||
|
// 0ac0 02bf 0af6 call 0x0af6 // 0af6_Decoder0x21_MoreStuff()
|
||||||
|
0af6_Decoder0x21_MoreStuff(AR0=0x043b);
|
||||||
|
|
||||||
|
// 0ac2 8100 clr $ACC0
|
||||||
|
// 0ac3 1fd8 mrr $AC0.M, $AX0.L
|
||||||
|
// 0ac4 223b lrs $AX0.H, @0x003b
|
||||||
|
// 0ac5 5400 subr $ACC0, $AX0.H
|
||||||
|
// 0ac6 0007 dar $AR3
|
||||||
|
// 0ac7 1979 lrri $AX1.L, @$AR3
|
||||||
|
|
||||||
|
ACC0 = 0;
|
||||||
|
AX0.H = *0x043b;
|
||||||
|
AC0.M = AX0.L - *0x043b;
|
||||||
|
|
||||||
|
AX1.L = *$AR3;
|
||||||
|
|
||||||
|
// Looks like duplication of the first memory address AC0.M times
|
||||||
|
|
||||||
|
// 0ac8 005e loop $AC0.M
|
||||||
|
for(int i = 0; i < AC0.M; i++) {
|
||||||
|
// 0ac9 1b79 srri @$AR3, $AX1.L
|
||||||
|
*$AR3++ = AX1.L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0aca 0f01 lris $AC1.M, #0x01
|
||||||
|
// 0acb 2f01 srs @0x0001, $AC1.M
|
||||||
|
// 0acc 8900 clr $ACC1
|
||||||
|
// 0acd 2f3b srs @0x003b, $AC1.M
|
||||||
|
|
||||||
|
ACC1 = 0;
|
||||||
|
|
||||||
|
// Looks like some finalization of the PB
|
||||||
|
*0x0401 = 1; // KeyOff
|
||||||
|
*0x043b = 0; // RemLength
|
||||||
|
|
||||||
|
|
||||||
0ac2 8100 clr $ACC0
|
|
||||||
0ac3 1fd8 mrr $AC0.M, $AX0.L
|
|
||||||
0ac4 223b lrs $AX0.H, @0x003b
|
|
||||||
0ac5 5400 subr $ACC0, $AX0.H
|
|
||||||
0ac6 0007 dar $AR3
|
|
||||||
0ac7 1979 lrri $AX1.L, @$AR3
|
|
||||||
0ac8 005e loop $AC0.M
|
|
||||||
0ac9 1b79 srri @$AR3, $AX1.L
|
|
||||||
0aca 0f01 lris $AC1.M, #0x01
|
|
||||||
0acb 2f01 srs @0x0001, $AC1.M
|
|
||||||
0acc 8900 clr $ACC1
|
|
||||||
0acd 2f3b srs @0x003b, $AC1.M
|
|
||||||
0ace 0092 00ff lri $CR, #0x00ff
|
0ace 0092 00ff lri $CR, #0x00ff
|
||||||
0ad0 02df ret
|
//0ad0 02df ret
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
0ad1 2e3a srs @0x003a, $AC0.M
|
|
||||||
0ad2 2c3b srs @0x003b, $AC0.L
|
// 0ad1 2e3a srs @0x003a, $AC0.M
|
||||||
0ad3 8100 clr $ACC0
|
// 0ad2 2c3b srs @0x003b, $AC0.L
|
||||||
0ad4 8900 clr $ACC1
|
|
||||||
0ad5 268a lrs $AC0.M, @0xff8a
|
*0x043a = AC0.M;
|
||||||
0ad6 2734 lrs $AC1.M, @0x0034
|
*0x043b = AC0.L;
|
||||||
0ad7 5c00 sub $ACC0, $AC1.L
|
|
||||||
0ad8 2e36 srs @0x0036, $AC0.M
|
// 0ad3 8100 clr $ACC0
|
||||||
0ad9 5000 subr $ACC0, $AX0.L
|
// 0ad4 8900 clr $ACC1
|
||||||
|
// 0ad5 268a lrs $AC0.M, @0xff8a
|
||||||
|
// 0ad6 2734 lrs $AC1.M, @0x0034
|
||||||
|
|
||||||
|
ACC0 = 0;
|
||||||
|
ACC1 = 0;
|
||||||
|
AC0.M = *0x048a;
|
||||||
|
AC1.M = *0x0434;
|
||||||
|
|
||||||
|
// 0ad7 5c00 sub $ACC0, $AC1.L
|
||||||
|
// 0ad8 2e36 srs @0x0036, $AC0.M
|
||||||
|
|
||||||
|
ACC0 -= AC1.L;
|
||||||
|
*0x0436 = (ACC0 & 0xFFFF0000) >> 16;
|
||||||
|
|
||||||
|
// 0ad9 5000 subr $ACC0, $AX0.L
|
||||||
|
ACC0 -= AX0.L;
|
||||||
|
|
||||||
0ada 0290 0af0 jns 0x0af0
|
0ada 0290 0af0 jns 0x0af0
|
||||||
if () {
|
if (ACC0 < 0) {
|
||||||
// 0adc 00c0 0436 lr $AR0, @0x0436
|
// 0adc 00c0 0436 lr $AR0, @0x0436
|
||||||
// 0ade 02bf 0af6 call 0x0af6
|
// 0ade 02bf 0af6 call 0x0af6
|
||||||
0af6_Decoder0x21_MoreStuff($AR0 = *0x0436);
|
0af6_Decoder0x21_MoreStuff(AR0=*0x0436);
|
||||||
|
|
||||||
// 0ae0 8100 clr $ACC0
|
// 0ae0 8100 clr $ACC0
|
||||||
0ae1 1fd8 mrr $AC0.M, $AX0.L
|
// 0ae1 1fd8 mrr $AC0.M, $AX0.L
|
||||||
0ae2 2236 lrs $AX0.H, @0x0036 // 0x0436
|
|
||||||
0ae3 5400 subr $ACC0, $AX0.H
|
ACC0 = 0;
|
||||||
0ae4 1c1e mrr $AR0, $AC0.M
|
AC0.M = AX0.L;
|
||||||
0ae5 8100 clr $ACC0
|
|
||||||
0ae6 2e34 srs @0x0034, $AC0.M
|
// 0ae2 2236 lrs $AX0.H, @0x0036 // 0x0436
|
||||||
0ae7 2688 lrs $AC0.M, @0xff88 // 0x0488
|
AX0.H = *0x0436;
|
||||||
0ae8 2489 lrs $AC0.L, @0xff89 // 0x0489
|
|
||||||
0ae9 2e8c srs @0xff8c, $AC0.M
|
// 0ae3 5400 subr $ACC0, $AX0.H
|
||||||
0aea 2c8d srs @0xff8d, $AC0.L
|
// 0ae4 1c1e mrr $AR0, $AC0.M
|
||||||
|
// 0ae5 8100 clr $ACC0
|
||||||
|
// 0ae6 2e34 srs @0x0034, $AC0.M
|
||||||
|
|
||||||
|
ACC0 -= AX0.H;
|
||||||
|
AR0 = (ACC0 & 0xFFFF0000) >> 16;
|
||||||
|
ACC0 = 0;
|
||||||
|
*0x0434 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// 0ae7 2688 lrs $AC0.M, @0xff88 // 0x0488
|
||||||
|
// 0ae8 2489 lrs $AC0.L, @0xff89 // 0x0489
|
||||||
|
// 0ae9 2e8c srs @0xff8c, $AC0.M
|
||||||
|
// 0aea 2c8d srs @0xff8d, $AC0.L
|
||||||
|
|
||||||
|
*0x048c = *0x0488;
|
||||||
|
*0x048d = *0x0489;
|
||||||
|
|
||||||
// 0aeb 02bf 0af6 call 0x0af6
|
// 0aeb 02bf 0af6 call 0x0af6
|
||||||
0af6_Decoder0x21_MoreStuff($AR0 = *0x0436);
|
0af6_Decoder0x21_MoreStuff(AR0=*0x0436);
|
||||||
|
|
||||||
0aed 0092 00ff lri $CR, #0x00ff
|
0aed 0092 00ff lri $CR, #0x00ff
|
||||||
// 0aef 02df ret
|
// 0aef 02df ret
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
0af0 1c18 mrr $AR0, $AX0.L
|
|
||||||
0af1 02bf 0af6 call 0x0af6
|
// 0af0 1c18 mrr $AR0, $AX0.L
|
||||||
|
// 0af1 02bf 0af6 call 0x0af6
|
||||||
|
|
||||||
|
AR0 = AX0.L;
|
||||||
|
0af6_Decoder0x21_MoreStuff(AR0=AX0.L);
|
||||||
|
|
||||||
|
|
||||||
0af3 0092 00ff lri $CR, #0x00ff
|
0af3 0092 00ff lri $CR, #0x00ff
|
||||||
// 0af5 02df ret
|
// 0af5 02df ret
|
||||||
}
|
}
|
||||||
|
@ -3552,19 +3628,24 @@ void 0ab3_Decoder0x21Core(AC1.M, AR3) {
|
||||||
// Does strange stuff with PB[0x34] and the address PB[0x8c,d]
|
// Does strange stuff with PB[0x34] and the address PB[0x8c,d]
|
||||||
// Does not touch AX0.L
|
// Does not touch AX0.L
|
||||||
void 0af6_Decoder0x21_MoreStuff($AR0) {
|
void 0af6_Decoder0x21_MoreStuff($AR0) {
|
||||||
0af6 8100 clr $ACC0
|
// 0af6 8100 clr $ACC0
|
||||||
0af7 1fc0 mrr $AC0.M, $AR0
|
// 0af7 1fc0 mrr $AC0.M, $AR0
|
||||||
// 0af8 b100 tst $ACC0
|
// 0af8 b100 tst $ACC0
|
||||||
// 0af9 02d5 retz
|
// 0af9 02d5 retz
|
||||||
if (!AR0)
|
if (!AR0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ACC0 = 0;
|
||||||
|
AC0.M = AR0;
|
||||||
|
|
||||||
// 0afa 8900 clr $ACC1
|
// 0afa 8900 clr $ACC1
|
||||||
// 0afb 2734 lrs $AC1.M, @0x0034
|
// 0afb 2734 lrs $AC1.M, @0x0034
|
||||||
// 0afc 0340 0001 andi $AC1.M, #0x0001
|
// 0afc 0340 0001 andi $AC1.M, #0x0001
|
||||||
// 0afe 0b00 lris $AX1.H, #0x00
|
// 0afe 0b00 lris $AX1.H, #0x00
|
||||||
// 0aff 1f3f mrr $AX1.L, $AC1.M
|
// 0aff 1f3f mrr $AX1.L, $AC1.M
|
||||||
// AX1.L = *0x0434 & 1;
|
|
||||||
|
AX1.L = *0x0434 & 1;
|
||||||
|
|
||||||
// 0b00 268c lrs $AC0.M, @0xff8c
|
// 0b00 268c lrs $AC0.M, @0xff8c
|
||||||
// 0b01 248d lrs $AC0.L, @0xff8d
|
// 0b01 248d lrs $AC0.L, @0xff8d
|
||||||
// 0b02 8900 clr $ACC1
|
// 0b02 8900 clr $ACC1
|
||||||
|
@ -3577,7 +3658,9 @@ void 0af6_Decoder0x21_MoreStuff($AR0) {
|
||||||
|
|
||||||
ACC0 = {8c,8d} + *0x0434 * 2 - (*0x0434 & 1) * 2
|
ACC0 = {8c,8d} + *0x0434 * 2 - (*0x0434 & 1) * 2
|
||||||
|
|
||||||
0b08 1c20 mrr $AR1, $AR0
|
// 0b08 1c20 mrr $AR1, $AR0
|
||||||
|
|
||||||
|
AR1 = AR0;
|
||||||
|
|
||||||
// 0b09 1fe0 mrr $AC1.M, $AR0
|
// 0b09 1fe0 mrr $AC1.M, $AR0
|
||||||
// 0b0a 0502 addis $ACC1, #0x02
|
// 0b0a 0502 addis $ACC1, #0x02
|
||||||
|
|
Loading…
Reference in New Issue