diff options
author | Max Horn | 2007-02-17 18:52:21 +0000 |
---|---|---|
committer | Max Horn | 2007-02-17 18:52:21 +0000 |
commit | 7d5d6c2f91287a286a65fe652c62462dce9b2e62 (patch) | |
tree | a30232112ba6b756b738bd36828a6a3b9d8c8727 | |
parent | f027e2f5626f896f0b9df59f1571da4ebafe0571 (diff) | |
download | scummvm-rg350-7d5d6c2f91287a286a65fe652c62462dce9b2e62.tar.gz scummvm-rg350-7d5d6c2f91287a286a65fe652c62462dce9b2e62.tar.bz2 scummvm-rg350-7d5d6c2f91287a286a65fe652c62462dce9b2e62.zip |
Speed up the Player_NES code quite a bit (still is rather slow without compiler optimizations on my 1.5Ghz PowerBook G4, but at least it's not unbearably slow anymore, and with -O2 it's running smoothly)
svn-id: r25659
-rw-r--r-- | engines/scumm/player_nes.cpp | 235 |
1 files changed, 123 insertions, 112 deletions
diff --git a/engines/scumm/player_nes.cpp b/engines/scumm/player_nes.cpp index 69ab6d8eb1..5525a21e51 100644 --- a/engines/scumm/player_nes.cpp +++ b/engines/scumm/player_nes.cpp @@ -89,30 +89,36 @@ static const byte LengthCounts[32] = { 0x20,0x1E }; - -class Square { +class SoundGen { protected: - byte volume, envelope, wavehold, duty, swpspeed, swpdir, swpstep, swpenab; + byte wavehold; uint32 freq; // short - byte Vol; - byte CurD; + uint32 CurD; + +public: byte Timer; + int32 Pos; + uint32 Cycles; // short + + inline byte GetTimer() const { return Timer; }; +}; + +class Square : public SoundGen { +protected: + byte volume, envelope, duty, swpspeed, swpdir, swpstep, swpenab; + byte Vol; byte EnvCtr, Envelope, BendCtr; bool Enabled, ValidFreq, Active; bool EnvClk, SwpClk; - uint32 Cycles; // short - int32 Pos; void CheckActive(void); public: void Reset(void); void Write(int Reg, byte Val); - int32 Run(void); + void Run(void); void QuarterFrame(void); void HalfFrame(void); - - inline byte GetTimer() const { return Timer; }; }; static const int8 Duties[4][8] = { @@ -177,16 +183,12 @@ void Square::Write(int Reg, byte Val) { CheckActive(); } -int32 Square::Run(void) { - Cycles--; - if (!Cycles) { - Cycles = (freq + 1) << 1; - CurD = (CurD + 1) & 0x7; - - if (Active) - Pos = Duties[duty][CurD] * Vol; - } - return Pos; +void Square::Run(void) { + Cycles = (freq + 1) << 1; + CurD = (CurD + 1) & 0x7; + + if (Active) + Pos = Duties[duty][CurD] * Vol; } void Square::QuarterFrame(void) { @@ -230,27 +232,21 @@ void Square::HalfFrame(void) { } -class Triangle { +class Triangle : public SoundGen { protected: - byte linear, wavehold; - uint32 freq; // short - byte CurD; - byte Timer, LinCtr; + byte linear; + byte LinCtr; bool Enabled, Active; bool LinClk; - uint32 Cycles; // short - int32 Pos; void CheckActive(void); public: void Reset(void); void Write(int Reg, byte Val); - int32 Run(void); + void Run(void); void QuarterFrame(void); void HalfFrame(void); - - inline byte GetTimer() const { return Timer; }; }; static const int8 TriDuty[32] = { @@ -304,22 +300,18 @@ void Triangle::Write(int Reg, byte Val) { CheckActive(); } -int32 Triangle::Run(void) { - Cycles--; - if (!Cycles) { - Cycles = freq + 1; - - if (Active) { - CurD++; - CurD &= 0x1F; - - if (freq < 4) - Pos = 0; // beyond hearing range - else - Pos = TriDuty[CurD] * 8; - } +void Triangle::Run(void) { + Cycles = freq + 1; + + if (Active) { + CurD++; + CurD &= 0x1F; + + if (freq < 4) + Pos = 0; // beyond hearing range + else + Pos = TriDuty[CurD] * 8; } - return Pos; } void Triangle::QuarterFrame(void) { @@ -341,29 +333,22 @@ void Triangle::HalfFrame(void) { CheckActive(); } -class Noise { +class Noise : public SoundGen { protected: - byte volume, envelope, wavehold, datatype; - uint32 freq; // short - uint32 CurD; // short + byte volume, envelope, datatype; byte Vol; - byte Timer; byte EnvCtr, Envelope; bool Enabled; bool EnvClk; - uint32 Cycles; // short - int32 Pos; void CheckActive(void); public: void Reset(void); void Write(int Reg, byte Val); - int32 Run(void); + void Run(void); void QuarterFrame(void); void HalfFrame(void); - - inline byte GetTimer() const { return Timer; }; }; static const uint32 NoiseFreq[16] = { @@ -410,20 +395,16 @@ void Noise::Write(int Reg, byte Val) { } } -int32 Noise::Run(void) { - Cycles--; - if (!Cycles) { - Cycles = NoiseFreq[freq]; /* no + 1 here */ - - if (datatype) - CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 8)) & 0x1); - else - CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 13)) & 0x1); - - if (Timer) - Pos = ((CurD & 0x4000) ? -2 : 2) * Vol; - } - return Pos; +void Noise::Run(void) { + Cycles = NoiseFreq[freq]; /* no + 1 here */ + + if (datatype) + CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 8)) & 0x1); + else + CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 13)) & 0x1); + + if (Timer) + Pos = ((CurD & 0x4000) ? -2 : 2) * Vol; } void Noise::QuarterFrame(void) { @@ -466,8 +447,6 @@ protected: int Num; } Frame; - void Frame_Run(void); - public: APU(int rate) : SampleRate(rate) { Reset(); @@ -479,33 +458,6 @@ public: int16 GetSample(void); }; -void APU::Frame_Run(void) { - Frame.Cycles = 7457; - - if (Frame.Num < 4) { - _square0.QuarterFrame(); - _square1.QuarterFrame(); - _triangle.QuarterFrame(); - _noise.QuarterFrame(); - - if (!(Frame.Num & 1)) { - _square0.HalfFrame(); - _square1.HalfFrame(); - _triangle.HalfFrame(); - _noise.HalfFrame(); - } - } - - if (Frame.Num & 1) - Frame.Cycles++; - - Frame.Num++; - - if (Frame.Num == 5) - Frame.Num = 0; -} - - void APU::WriteReg(int Addr, byte Val) { switch (Addr) { case 0x000: _square0.Write(0,Val); break; @@ -553,25 +505,84 @@ void APU::Reset (void) { Frame.Cycles = 1; } -int16 APU::GetSample(void) { - int sampcycles = 0, samppos = 0; +template <class T> +int step(T &obj, int sampcycles, uint frame_Cycles, int frame_Num) { + int samppos = 0; + while (sampcycles) { + // Compute the maximal amount we can step ahead before triggering + // an action (i.e. compute the minimum of sampcycles, frame_Cycles + // and obj.Cycles). + uint max_step = sampcycles; + if (max_step > frame_Cycles) + max_step = frame_Cycles; + if (max_step > obj.Cycles) + max_step = obj.Cycles; + + // During all but the last of these steps, we just add the value of obj.Pos + // to samppos -- so we can to that all at once with a simple multiplication: + samppos += obj.Pos * (max_step - 1); + + // Now step ahead... + sampcycles -= max_step; + frame_Cycles -= max_step; + obj.Cycles -= max_step; + + if (!frame_Cycles) { + frame_Cycles = 7457; + + if (frame_Num < 4) { + obj.QuarterFrame(); + + if (!(frame_Num & 1)) { + obj.HalfFrame(); + } + } + + if (frame_Num & 1) + frame_Cycles++; + + if (frame_Num == 4) + frame_Num = 0; + else + frame_Num++; + } - while (BufPos < 1789773) { - BufPos += SampleRate; - - if (!--Frame.Cycles) - Frame_Run(); - - samppos += _square0.Run(); - samppos += _square1.Run(); - samppos += _triangle.Run(); - samppos += _noise.Run(); + if (!obj.Cycles) + obj.Run(); - sampcycles++; + samppos += obj.Pos; } - BufPos -= 1789773; + return samppos; +} +int16 APU::GetSample(void) { + int samppos = 0; + + const int sampcycles = 1+(1789773-BufPos-1)/SampleRate; + BufPos = BufPos + sampcycles * SampleRate - 1789773; + + samppos += step( _square0, sampcycles, Frame.Cycles, Frame.Num); + samppos += step( _square1, sampcycles, Frame.Cycles, Frame.Num); + samppos += step(_triangle, sampcycles, Frame.Cycles, Frame.Num); + samppos += step( _noise, sampcycles, Frame.Cycles, Frame.Num); + + uint tmp = sampcycles; + while (tmp >= Frame.Cycles) { + tmp -= Frame.Cycles; + Frame.Cycles = 7457; + + if (Frame.Num & 1) + Frame.Cycles++; + + if (Frame.Num == 4) + Frame.Num = 0; + else + Frame.Num++; + } + + Frame.Cycles -= tmp; + return (samppos << 6) / sampcycles; } |