aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2007-02-17 18:52:21 +0000
committerMax Horn2007-02-17 18:52:21 +0000
commit7d5d6c2f91287a286a65fe652c62462dce9b2e62 (patch)
treea30232112ba6b756b738bd36828a6a3b9d8c8727
parentf027e2f5626f896f0b9df59f1571da4ebafe0571 (diff)
downloadscummvm-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.cpp235
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;
}