~ubuntu-branches/debian/experimental/mednafen/experimental

« back to all changes in this revision

Viewing changes to src/psx/timer.cpp

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2012-01-31 07:21:35 UTC
  • mfrom: (1.2.8)
  • Revision ID: package-import@ubuntu.com-20120131072135-es3dj12y00xcnrsk
Tags: 0.9.19-1
* New upstream WIP version.
* Update copyright information.
* Refresh use-system-tremor.patch and remove psx-big-endian-only.patch.
* Add spelling-fixes.patch based on Lintian's recommendations.
* Build-depend on debhelper 9 or later and remove corresponding Lintian
  override.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Mednafen - Multi-system Emulator
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; either version 2 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program; if not, write to the Free Software
 
15
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 */
 
17
 
1
18
#include "psx.h"
 
19
#include "timer.h"
2
20
 
3
21
/*
4
22
 Notes(some of it may be incomplete or wrong in subtle ways)
45
63
 When the counter == 0, the compare flag is set.  An IRQ will be generated if (Mode & 0x10), and the hidden IRQ done flag will be set.
46
64
*/
47
65
 
 
66
/*
 
67
 Dec. 26, 2011 Note
 
68
        Due to problems I've had with my GPU timing test program, timer2 appears to be unreliable(clocks are skipped?) when target mode is enabled and the full
 
69
        33MHz clock is used(rather than 33MHz / 8).  TODO: Investigate further and confirm(or not).
 
70
*/
 
71
 
 
72
/*
 
73
 FIXME: Clock appropriately(and update events) when using SetRegister() via the debugger.
 
74
*/
 
75
 
48
76
namespace MDFN_IEN_PSX
49
77
{
50
78
 
64
92
static Timer Timers[3];
65
93
static pscpu_timestamp_t lastts;
66
94
 
67
 
void timer_moo(void)
 
95
static int32 CalcNextEvent(int32 next_event)
68
96
{
69
 
// Timers[1].Counter = 0;
 
97
 for(int i = 0; i < 3; i++)
 
98
 {
 
99
  int32 target;
 
100
  int32 count_delta;
 
101
 
 
102
  if((i == 0 || i == 1) && (Timers[i].Mode & 0x100))    // If clocked by GPU, abort for this timer(will result in poor granularity for pixel-clock-derived timer IRQs, but whatever).
 
103
   continue;
 
104
 
 
105
  if(!(Timers[i].Mode & 0x10))  // If IRQ is disabled, abort for this timer.
 
106
   continue;
 
107
 
 
108
  if((Timers[i].Mode & 0x8) && (Timers[i].Counter == 0) && (Timers[i].Target == 0) && !Timers[i].IRQDone)
 
109
  {
 
110
   next_event = 1;
 
111
   continue;
 
112
  }
 
113
 
 
114
  target = ((Timers[i].Mode & 0x8) && (Timers[i].Counter < Timers[i].Target)) ? Timers[i].Target : 0x10000;
 
115
 
 
116
  count_delta = target - Timers[i].Counter;
 
117
  if(count_delta <= 0)
 
118
  {
 
119
   fprintf(stderr, "timer %d count_delta <= 0!!! %d %d\n", i, target, Timers[i].Counter);
 
120
   continue;
 
121
  }
 
122
 
 
123
  {
 
124
   int32 tmp_clocks;
 
125
 
 
126
   if((i == 0x2) && (Timers[i].Mode & 0x1))
 
127
    continue;
 
128
 
 
129
   if((i == 0x2) && (Timers[i].Mode & 0x200))
 
130
   {
 
131
    assert(Timers[i].Div8Counter >= 0 && Timers[i].Div8Counter < 8);
 
132
    tmp_clocks = ((count_delta - 1) * 8) + (8 - Timers[i].Div8Counter);
 
133
   }
 
134
   else
 
135
    tmp_clocks = count_delta;
 
136
 
 
137
   assert(tmp_clocks > 0);
 
138
 
 
139
   if(next_event > tmp_clocks)
 
140
    next_event = tmp_clocks;
 
141
  }
 
142
 }
 
143
 
 
144
 return(next_event);
70
145
}
71
146
 
72
147
static void ClockTimer(int i, uint32 clocks)
103
178
 
104
179
 if((before < target && Timers[i].Counter >= target) || zero_tm || Timers[i].Counter > 0xFFFF)
105
180
 {
 
181
#if 1
 
182
  if(Timers[i].Mode & 0x10)
 
183
  {
 
184
   if((Timers[i].Counter - target) > 3)
 
185
    printf("Timer %d IRQ trigger error: %d\n", i, Timers[i].Counter - target);
 
186
  }
 
187
 
 
188
#endif
 
189
 
 
190
 
106
191
  Timers[i].Mode |= 0x0800;
107
192
 
108
193
  if(Timers[i].Counter > 0xFFFF)
109
194
  {
110
195
   Timers[i].Counter -= 0x10000;
111
 
   Timers[i].Mode |= 0x1000;
 
196
 
 
197
   if(target == 0x10000)
 
198
    Timers[i].Mode |= 0x1000;
112
199
 
113
200
   if(!target)
114
201
    Timers[i].Counter = 0;
143
230
  ClockTimer(1, 1);
144
231
}
145
232
 
146
 
void TIMER_Update(const pscpu_timestamp_t timestamp)
 
233
pscpu_timestamp_t TIMER_Update(const pscpu_timestamp_t timestamp)
147
234
{
148
235
 int32 cpu_clocks = timestamp - lastts;
149
236
 
158
245
 }
159
246
 
160
247
 lastts = timestamp;
 
248
 
 
249
 return(timestamp + CalcNextEvent(1024));
161
250
}
162
251
 
163
252
void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V)
216
305
 }
217
306
 
218
307
 // TIMER_Update(timestamp);
 
308
 
 
309
 PSX_SetEventNT(PSX_EVENT_TIMER, timestamp + CalcNextEvent(1024));
219
310
}
220
311
 
221
312
uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A)