ScummVM API documentation
gamerate.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * aint32 with this program; if not, write to the Free Software
19  *
20  *
21  * Based on the original sources
22  * Faery Tale II -- The Halls of the Dead
23  * (c) 1993-1996 The Wyrmkeep Entertainment Co.
24  */
25 
26 #ifndef SAGA2_GAMERATE_H
27 #define SAGA2_GAMERATE_H
28 
29 namespace Saga2 {
30 
31 enum {
32  kGRFramesPerSecond = 0
33 };
34 
35 class frameCounter {
36  uint32 _ticksPerSecond;
37  uint32 _lastTime;
38 
39 protected:
40  uint32 _frames;
41  float _instantFrameCount;
42 
43 public:
44  frameCounter(uint32 perSec, uint32 now) {
45  _ticksPerSecond = perSec;
46  _frames = 0;
47  _lastTime = now;
48  _instantFrameCount = 0;
49  }
50 
51  virtual ~frameCounter() {}
52 
53  virtual void updateFrameCount() {
54  int32 frameTime = gameTime - _lastTime;
55  _lastTime = gameTime;
56  _frames++;
57  _instantFrameCount = frameTime ? _ticksPerSecond / frameTime : 100;
58  }
59 
60  virtual float frameStat(int statID = kGRFramesPerSecond) {
61  return _instantFrameCount;
62  }
63 };
64 
65 
66 enum {
67  kGRFramesPerKilosecond = 1,
68  kGRFPKS1SecAvgNewest = 2,
69  kGRFPKS1SecAvgNew = 3,
70  kGRFPKS1SecAvg = 4,
71  kGRFPKS1SecAvgOld = 5,
72  kGRFPKS1SecAvgOldest = 6,
73  kGRFPKS5SecAvg = 7,
74  kGRFPKSAvg1SecAvg = 8,
75  kGRFPKS1SecVarNewest = 9,
76  kGRFPKS1SecVarNew = 10,
77  kGRFPKS1SecVar = 11,
78  kGRFPKS1SecVarOld = 12,
79  kGRFPKS1SecVarOldest = 13,
80  kGRFPKS5SecVar = 14,
81  kGRFPKSVar1SecAvg = 15
82 };
83 
84 class frameSmoother: public frameCounter {
85  float _desiredFPS;
86 
87  uint32 _historySize;
88  float *_frameHistory;
89 
90  float _avg1Sec[5];
91  float _avg5Sec;
92  float _secAvg;
93  float _dif1Sec[5];
94  float _dif5Sec;
95  float _secDif;
96 
97  float ksHistory(int32 i) {
98  return 1000.0 * _frameHistory[i];
99  }
100 
101  void calculateAverages() {
102  // clear averages
103  for (int i = 0; i < 5; i++)
104  _avg1Sec[i] = 0;
105 
106  _avg5Sec = 0;
107 
108  // get totals
109  for (uint i = 0; i < _historySize; i++)
110  _avg1Sec[i / int(_desiredFPS)] += ksHistory(i);
111 
112  // get averages
113  for (uint i = 0; i < 5; i++) {
114  _avg5Sec += _avg1Sec[i];
115  _avg1Sec[i] /= _desiredFPS;
116  }
117 
118  // get broad averages
119  _secAvg = _avg5Sec / 5;
120  _avg5Sec /= (5 * _desiredFPS);
121  }
122 
123  void calculateVariance() {
124  // clear variances
125  for (int i = 0; i < 5; i++)
126  _dif1Sec[i] = 0;
127 
128  _dif5Sec = 0;
129 
130  // get variance totals
131  for (uint i = 0; i < _historySize; i++) {
132  _dif1Sec[i / int(_desiredFPS)] += ABS(ksHistory(i) - _avg1Sec[i / int(_desiredFPS)]);
133  _dif5Sec += ABS(ksHistory(i) - _avg5Sec);
134  }
135 
136  // get average variances
137  for (uint i = 0; i < 5; i++) {
138  _secDif += _avg1Sec[i] - _secAvg;
139  _dif1Sec[i] /= _desiredFPS;
140  }
141 
142  // get broad variance
143  _dif5Sec /= (5 * _desiredFPS);
144  }
145 
146 
147 public:
148  frameSmoother(int32 fps, uint32 perSec, uint32 now);
149 
150 
151  virtual ~frameSmoother() {
152  if (_frameHistory)
153  delete[] _frameHistory;
154 
155  _frameHistory = nullptr;
156  }
157 
158  virtual void updateFrameCount() {
159  frameCounter::updateFrameCount();
160  _frameHistory[_frames % _historySize] = _instantFrameCount;
161  if (0 == (_frames % int(_desiredFPS))) {
162  calculateAverages();
163  calculateVariance();
164  }
165  }
166 
167  virtual float frameStat(int statID = kGRFramesPerSecond) {
168  int oldestOffset = (_frames % _historySize) / _desiredFPS;
169  switch (statID) {
170  case kGRFramesPerKilosecond :
171  return 1000 * _instantFrameCount;
172  case kGRFPKS1SecAvgNewest :
173  return _avg1Sec[4 + oldestOffset];
174  case kGRFPKS1SecAvgNew :
175  return _avg1Sec[3 + oldestOffset];
176  case kGRFPKS1SecAvg :
177  return _avg1Sec[2 + oldestOffset];
178  case kGRFPKS1SecAvgOld :
179  return _avg1Sec[1 + oldestOffset];
180  case kGRFPKS1SecAvgOldest :
181  return _avg1Sec[0 + oldestOffset];
182  case kGRFPKS5SecAvg :
183  return _avg5Sec;
184  case kGRFPKSAvg1SecAvg :
185  return _secAvg;
186  case kGRFPKS1SecVarNewest :
187  return _dif1Sec[4 + oldestOffset];
188  case kGRFPKS1SecVarNew :
189  return _dif1Sec[3 + oldestOffset];
190  case kGRFPKS1SecVar :
191  return _dif1Sec[2 + oldestOffset];
192  case kGRFPKS1SecVarOld :
193  return _dif1Sec[1 + oldestOffset];
194  case kGRFPKS1SecVarOldest :
195  return _dif1Sec[0 + oldestOffset];
196  case kGRFPKS5SecVar :
197  return _dif5Sec;
198  case kGRFPKSVar1SecAvg :
199  return _secDif;
200  default:
201  return frameCounter::frameStat(statID);
202  }
203  }
204 };
205 
206 frameSmoother::frameSmoother(int32 fps, uint32 perSec, uint32 now)
207  : frameCounter(perSec, now) {
208  assert(fps);
209  _desiredFPS = fps;
210  _historySize = fps * 5;
211  _frameHistory = new float[_historySize];
212 
213  for (uint32 i = 0; i < _historySize; i++)
214  _frameHistory[i] = 0;
215 
216  for (int i = 0; i < 5; i++)
217  _dif1Sec[i] = _avg1Sec[i] = 0;
218 
219  _dif5Sec = 0;
220  _avg5Sec = 0;
221  _secDif = 0;
222  _secAvg = 0;
223 }
224 
225 } // end of namespace Saga2
226 
227 #endif
Definition: gamerate.h:84
Definition: gamerate.h:35
Definition: actor.h:32
T ABS(T x)
Definition: util.h:56