mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
SNES: Randomize DSP register values on power on, but reset the internal state to 0
This commit is contained in:
parent
83fc79b55e
commit
91b7ebbd60
8 changed files with 51 additions and 25 deletions
|
@ -12,6 +12,7 @@ unordered_map<string, int64_t>& ExpressionEvaluator::GetSpcTokens()
|
|||
{ "ps", EvalValues::RegPS },
|
||||
{ "sp", EvalValues::RegSP },
|
||||
{ "pc", EvalValues::RegPC },
|
||||
{ "dspreg", EvalValues::SpcDspReg },
|
||||
};
|
||||
|
||||
return supportedTokens;
|
||||
|
@ -27,6 +28,7 @@ int64_t ExpressionEvaluator::GetSpcTokenValue(int64_t token, EvalResultType& res
|
|||
case EvalValues::RegSP: return s.SP;
|
||||
case EvalValues::RegPS: return s.PS;
|
||||
case EvalValues::RegPC: return s.PC;
|
||||
case EvalValues::SpcDspReg: return s.DspReg;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
|
@ -143,6 +143,8 @@ enum EvalValues : int64_t
|
|||
VerticalBlank,
|
||||
SpriteOverflow,
|
||||
|
||||
SpcDspReg,
|
||||
|
||||
PceVramTransferDone,
|
||||
PceSatbTransferDone,
|
||||
PceScanlineDetected,
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
#include "pch.h"
|
||||
#include "SNES/DSP/Dsp.h"
|
||||
#include "SNES/Spc.h"
|
||||
#include "SNES/SnesConsole.h"
|
||||
#include "Shared/Emulator.h"
|
||||
#include "Shared/EmuSettings.h"
|
||||
#include "Utilities/Serializer.h"
|
||||
|
||||
//Quoted comments are from anomie's DSP document (with modifications by jwdonal)
|
||||
|
||||
Dsp::Dsp(Emulator* emu, Spc* spc)
|
||||
Dsp::Dsp(Emulator* emu, SnesConsole* console, Spc* spc)
|
||||
{
|
||||
_emu = emu;
|
||||
_spc = spc;
|
||||
|
||||
memcpy(_state.Regs, _initialValues, 0x80);
|
||||
memset(_state.Regs, 0, 0x80);
|
||||
console->InitializeRam(_state.ExternalRegs, 0x80);
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
_voices[i].Init(i, spc, this, _state.Regs + (i * 0x10), &_emu->GetSettings()->GetSnesConfig());
|
||||
|
@ -24,9 +26,22 @@ Dsp::Dsp(Emulator* emu, Spc* spc)
|
|||
Reset();
|
||||
}
|
||||
|
||||
void Dsp::LoadSpcFileRegs(uint8_t* regs)
|
||||
{
|
||||
for(uint8_t i = 0; i < 0x80; i++) {
|
||||
Write(i, regs[i]);
|
||||
}
|
||||
|
||||
_state.NewKeyOn = ReadReg(DspGlobalRegs::KeyOn);
|
||||
_state.DirSampleTableAddress = ReadReg(DspGlobalRegs::DirSampleTableAddress);
|
||||
_state.EchoRingBufferAddress = ReadReg(DspGlobalRegs::EchoRingBufferAddress);
|
||||
}
|
||||
|
||||
void Dsp::Reset()
|
||||
{
|
||||
WriteReg(DspGlobalRegs::Flags, 0xE0);
|
||||
//"FLG will always act as if set to 0xE0 after power on or reset, even if the value read back indicates otherwise"
|
||||
_state.Regs[(int)DspGlobalRegs::Flags] = 0xE0;
|
||||
|
||||
_state.Counter = 0;
|
||||
_state.EchoHistoryPos = 0;
|
||||
_state.EchoOffset = 0;
|
||||
|
@ -88,6 +103,7 @@ void Dsp::UpdateCounter()
|
|||
void Dsp::Write(uint8_t reg, uint8_t value)
|
||||
{
|
||||
_state.Regs[reg] = value;
|
||||
_state.ExternalRegs[reg] = value;
|
||||
switch(reg & 0x0F) {
|
||||
case (int)DspVoiceRegs::Envelope: _state.EnvRegBuffer = value; break;
|
||||
case (int)DspVoiceRegs::Out: _state.OutRegBuffer = value; break;
|
||||
|
@ -98,7 +114,7 @@ void Dsp::Write(uint8_t reg, uint8_t value)
|
|||
|
||||
case (int)DspGlobalRegs::VoiceEnd:
|
||||
_state.VoiceEndBuffer = 0;
|
||||
_state.Regs[(int)DspGlobalRegs::VoiceEnd] = 0;
|
||||
WriteGlobalReg(DspGlobalRegs::VoiceEnd, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -356,6 +372,7 @@ void Dsp::Exec()
|
|||
void Dsp::Serialize(Serializer& s)
|
||||
{
|
||||
SVArray(_state.Regs, 128);
|
||||
SVArray(_state.ExternalRegs, 128);
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
SVI(_voices[i]);
|
||||
|
|
|
@ -5,24 +5,12 @@
|
|||
#include "Utilities/ISerializable.h"
|
||||
|
||||
class Emulator;
|
||||
class SnesConsole;
|
||||
class Spc;
|
||||
|
||||
class Dsp final : public ISerializable
|
||||
{
|
||||
private:
|
||||
//KOF ($5C) must be initialized to $00, some games (Chester Cheetah, King of Dragons) do not initialize its value
|
||||
//This causes missing sound effects in both games.
|
||||
static constexpr uint8_t _initialValues[0x80] = {
|
||||
0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
|
||||
0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
|
||||
0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
|
||||
0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
|
||||
0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
|
||||
0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF,
|
||||
0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
|
||||
0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
|
||||
};
|
||||
|
||||
DspState _state = {};
|
||||
DspVoice _voices[8] = {};
|
||||
Emulator* _emu = nullptr;
|
||||
|
@ -47,8 +35,9 @@ private:
|
|||
void EchoStep30();
|
||||
|
||||
public:
|
||||
Dsp(Emulator* emu, Spc* spc);
|
||||
Dsp(Emulator* emu, SnesConsole* console, Spc* spc);
|
||||
|
||||
void LoadSpcFileRegs(uint8_t* regs);
|
||||
void Reset();
|
||||
|
||||
DspState& GetState() { return _state; }
|
||||
|
@ -60,11 +49,22 @@ public:
|
|||
|
||||
bool CheckCounter(int32_t rate);
|
||||
|
||||
uint8_t Read(uint8_t reg) { return _state.Regs[reg]; }
|
||||
uint8_t Read(uint8_t reg) { return _state.ExternalRegs[reg]; }
|
||||
void Write(uint8_t reg, uint8_t value);
|
||||
|
||||
uint8_t ReadReg(DspGlobalRegs reg) { return _state.Regs[(int)reg]; }
|
||||
void WriteReg(DspGlobalRegs reg, uint8_t value) { _state.Regs[(int)reg] = value; }
|
||||
|
||||
void WriteGlobalReg(DspGlobalRegs reg, uint8_t value)
|
||||
{
|
||||
_state.ExternalRegs[(int)reg] = value;
|
||||
_state.Regs[(int)reg] = value;
|
||||
}
|
||||
|
||||
void WriteVoiceReg(uint8_t voiceIndex, DspVoiceRegs reg, uint8_t value)
|
||||
{
|
||||
_state.ExternalRegs[voiceIndex * 0x10 + (int)reg] = value;
|
||||
_state.Regs[voiceIndex * 0x10 + (int)reg] = value;
|
||||
}
|
||||
|
||||
static int16_t Clamp16(int32_t val)
|
||||
{
|
||||
|
@ -75,6 +75,7 @@ public:
|
|||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void Exec();
|
||||
|
||||
void Serialize(Serializer& s) override;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
struct DspState
|
||||
{
|
||||
uint8_t ExternalRegs[128];
|
||||
uint8_t Regs[128];
|
||||
|
||||
int32_t NoiseLfsr = 0x4000;
|
||||
|
|
|
@ -359,7 +359,7 @@ void DspVoice::Step6()
|
|||
void DspVoice::Step7()
|
||||
{
|
||||
//"The new ENDX.x value may now be read."
|
||||
_dsp->WriteReg(DspGlobalRegs::VoiceEnd, _shared->VoiceEndBuffer);
|
||||
_dsp->WriteGlobalReg(DspGlobalRegs::VoiceEnd, _shared->VoiceEndBuffer);
|
||||
|
||||
//"The new VxENVX value is prepared, and can be overwritten. Reads will not see it yet."
|
||||
_shared->EnvRegBuffer = _envOut;
|
||||
|
@ -368,13 +368,13 @@ void DspVoice::Step7()
|
|||
void DspVoice::Step8()
|
||||
{
|
||||
//"The new VxOUTX value may now be read."
|
||||
WriteReg(DspVoiceRegs::Out, _shared->OutRegBuffer);
|
||||
_dsp->WriteVoiceReg(_voiceIndex, DspVoiceRegs::Out, _shared->OutRegBuffer);
|
||||
}
|
||||
|
||||
void DspVoice::Step9()
|
||||
{
|
||||
//"The new VxENVX value may now be read."
|
||||
WriteReg(DspVoiceRegs::Envelope, _shared->EnvRegBuffer);
|
||||
_dsp->WriteVoiceReg(_voiceIndex, DspVoiceRegs::Envelope, _shared->EnvRegBuffer);
|
||||
}
|
||||
|
||||
void DspVoice::Serialize(Serializer& s)
|
||||
|
|
|
@ -31,7 +31,7 @@ Spc::Spc(SnesConsole* console)
|
|||
_emu->RegisterMemory(MemoryType::SpcRom, _spcBios, Spc::SpcRomSize);
|
||||
|
||||
#ifndef DUMMYSPC
|
||||
_dsp.reset(new Dsp(_emu, this));
|
||||
_dsp.reset(new Dsp(_emu, console, this));
|
||||
#endif
|
||||
|
||||
_state = {};
|
||||
|
@ -579,7 +579,7 @@ void Spc::LoadSpcFile(SpcFileData* data)
|
|||
{
|
||||
memcpy(_ram, data->SpcRam, Spc::SpcRamSize);
|
||||
|
||||
memcpy(_dsp->GetState().Regs, data->DspRegs, sizeof(data->DspRegs));
|
||||
_dsp->LoadSpcFileRegs(data->DspRegs);
|
||||
|
||||
_state.PC = data->PC;
|
||||
_state.A = data->A;
|
||||
|
|
|
@ -267,6 +267,9 @@ namespace Mesen.Interop
|
|||
|
||||
public struct DspState
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] ExternalRegs;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] Regs;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue