Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libgambatte/src/tima.cpp
2 views
1
/***************************************************************************
2
* Copyright (C) 2007 by Sindre AamÄs *
3
* [email protected] *
4
* *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License version 2 as *
7
* published by the Free Software Foundation. *
8
* *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License version 2 for more details. *
13
* *
14
* You should have received a copy of the GNU General Public License *
15
* version 2 along with this program; if not, write to the *
16
* Free Software Foundation, Inc., *
17
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18
***************************************************************************/
19
#include "tima.h"
20
#include "savestate.h"
21
22
static const unsigned char timaClock[4] = { 10, 4, 6, 8 };
23
24
namespace gambatte {
25
26
Tima::Tima() :
27
lastUpdate_(0),
28
tmatime_(DISABLED_TIME),
29
tima_(0),
30
tma_(0),
31
tac_(0)
32
{}
33
34
void Tima::loadState(const SaveState &state, const TimaInterruptRequester timaIrq) {
35
lastUpdate_ = state.mem.timaLastUpdate;
36
tmatime_ = state.mem.tmatime;
37
38
tima_ = state.mem.ioamhram.get()[0x105];
39
tma_ = state.mem.ioamhram.get()[0x106];
40
tac_ = state.mem.ioamhram.get()[0x107];
41
42
timaIrq.setNextIrqEventTime((tac_ & 4)
43
?
44
(tmatime_ != DISABLED_TIME && tmatime_ > state.cpu.cycleCounter
45
? tmatime_
46
: lastUpdate_ + ((256u - tima_) << timaClock[tac_ & 3]) + 3)
47
:
48
static_cast<unsigned long>(DISABLED_TIME)
49
);
50
}
51
52
void Tima::resetCc(const unsigned long oldCc, const unsigned long newCc, const TimaInterruptRequester timaIrq) {
53
const unsigned long dec = oldCc - newCc;
54
55
if (tac_ & 0x04) {
56
updateIrq(oldCc, timaIrq);
57
updateTima(oldCc);
58
59
lastUpdate_ -= dec;
60
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() - dec);
61
62
if (tmatime_ != DISABLED_TIME)
63
tmatime_ -= dec;
64
}
65
}
66
67
void Tima::updateTima(const unsigned long cycleCounter) {
68
const unsigned long ticks = (cycleCounter - lastUpdate_) >> timaClock[tac_ & 3];
69
70
lastUpdate_ += ticks << timaClock[tac_ & 3];
71
72
if (cycleCounter >= tmatime_) {
73
if (cycleCounter >= tmatime_ + 4)
74
tmatime_ = DISABLED_TIME;
75
76
tima_ = tma_;
77
}
78
79
unsigned long tmp = tima_ + ticks;
80
81
while (tmp > 0x100)
82
tmp -= 0x100 - tma_;
83
84
if (tmp == 0x100) {
85
tmp = 0;
86
tmatime_ = lastUpdate_ + 3;
87
88
if (cycleCounter >= tmatime_) {
89
if (cycleCounter >= tmatime_ + 4)
90
tmatime_ = DISABLED_TIME;
91
92
tmp = tma_;
93
}
94
}
95
96
tima_ = tmp;
97
}
98
99
void Tima::setTima(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
100
if (tac_ & 0x04) {
101
updateIrq(cycleCounter, timaIrq);
102
updateTima(cycleCounter);
103
104
if (tmatime_ - cycleCounter < 4)
105
tmatime_ = DISABLED_TIME;
106
107
timaIrq.setNextIrqEventTime(lastUpdate_ + ((256u - data) << timaClock[tac_ & 3]) + 3);
108
}
109
110
tima_ = data;
111
}
112
113
void Tima::setTma(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
114
if (tac_ & 0x04) {
115
updateIrq(cycleCounter, timaIrq);
116
updateTima(cycleCounter);
117
}
118
119
tma_ = data;
120
}
121
122
void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
123
if (tac_ ^ data) {
124
unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime();
125
126
if (tac_ & 0x04) {
127
updateIrq(cycleCounter, timaIrq);
128
updateTima(cycleCounter);
129
130
lastUpdate_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
131
tmatime_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
132
nextIrqEventTime -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
133
134
if (cycleCounter >= nextIrqEventTime)
135
timaIrq.flagIrq();
136
137
updateTima(cycleCounter);
138
139
tmatime_ = DISABLED_TIME;
140
nextIrqEventTime = DISABLED_TIME;
141
}
142
143
if (data & 4) {
144
lastUpdate_ = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3];
145
nextIrqEventTime = lastUpdate_ + ((256u - tima_) << timaClock[data & 3]) + 3;
146
}
147
148
timaIrq.setNextIrqEventTime(nextIrqEventTime);
149
}
150
151
tac_ = data;
152
}
153
154
unsigned Tima::tima(unsigned long cycleCounter) {
155
if (tac_ & 0x04)
156
updateTima(cycleCounter);
157
158
return tima_;
159
}
160
161
void Tima::doIrqEvent(const TimaInterruptRequester timaIrq) {
162
timaIrq.flagIrq();
163
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3]));
164
}
165
166
SYNCFUNC(Tima)
167
{
168
NSS(lastUpdate_);
169
NSS(tmatime_);
170
NSS(tima_);
171
NSS(tma_);
172
NSS(tac_);
173
}
174
175
}
176
177