Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libgambatte/src/video/lyc_irq.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 "lyc_irq.h"
20
#include "counterdef.h"
21
#include "ly_counter.h"
22
#include "savestate.h"
23
#include <algorithm>
24
25
namespace gambatte {
26
27
LycIrq::LycIrq() :
28
time_(DISABLED_TIME),
29
lycRegSrc_(0),
30
statRegSrc_(0),
31
lycReg_(0),
32
statReg_(0),
33
cgb_(false)
34
{
35
}
36
37
static unsigned long schedule(const unsigned statReg, const unsigned lycReg, const LyCounter &lyCounter, const unsigned long cc) {
38
return (statReg & 0x40) && lycReg < 154
39
? lyCounter.nextFrameCycle(lycReg ? lycReg * 456 : 153 * 456 + 8, cc)
40
: static_cast<unsigned long>(DISABLED_TIME);
41
}
42
43
void LycIrq::regChange(const unsigned statReg, const unsigned lycReg, const LyCounter &lyCounter, const unsigned long cc) {
44
const unsigned long timeSrc = schedule(statReg, lycReg, lyCounter, cc);
45
statRegSrc_ = statReg;
46
lycRegSrc_ = lycReg;
47
time_ = std::min(time_, timeSrc);
48
49
if (cgb_) {
50
if (time_ - cc > 8 || (timeSrc != time_ && time_ - cc > 4U - lyCounter.isDoubleSpeed() * 4U))
51
lycReg_ = lycReg;
52
53
if (time_ - cc > 4U - lyCounter.isDoubleSpeed() * 4U)
54
statReg_ = statReg;
55
} else {
56
if (time_ - cc > 4 || timeSrc != time_)
57
lycReg_ = lycReg;
58
59
if (time_ - cc > 4 || lycReg_ != 0)
60
statReg_ = statReg;
61
62
statReg_ = (statReg_ & 0x40) | (statReg & ~0x40);
63
}
64
}
65
66
void LycIrq::doEvent(unsigned char *const ifreg, const LyCounter &lyCounter) {
67
if ((statReg_ | statRegSrc_) & 0x40) {
68
const unsigned cmpLy = lyCounter.time() - time_ < lyCounter.lineTime() ? 0 : lyCounter.ly();
69
70
if (lycReg_ == cmpLy &&
71
(lycReg_ - 1U < 144U - 1U ? !(statReg_ & 0x20) : !(statReg_ & 0x10))) {
72
*ifreg |= 2;
73
}
74
}
75
76
lycReg_ = lycRegSrc_;
77
statReg_ = statRegSrc_;
78
time_ = schedule(statReg_, lycReg_, lyCounter, time_);
79
}
80
81
void LycIrq::loadState(const SaveState &state) {
82
lycRegSrc_ = state.mem.ioamhram.get()[0x145];
83
statRegSrc_ = state.mem.ioamhram.get()[0x141];
84
lycReg_ = state.ppu.lyc;
85
statReg_ = statRegSrc_;
86
}
87
88
void LycIrq::reschedule(const LyCounter & lyCounter, const unsigned long cc) {
89
time_ = std::min(schedule(statReg_ , lycReg_ , lyCounter, cc),
90
schedule(statRegSrc_, lycRegSrc_, lyCounter, cc));
91
}
92
93
void LycIrq::lcdReset() {
94
statReg_ = statRegSrc_;
95
lycReg_ = lycRegSrc_;
96
}
97
98
SYNCFUNC(LycIrq)
99
{
100
NSS(time_);
101
NSS(lycRegSrc_);
102
NSS(statRegSrc_);
103
NSS(lycReg_);
104
NSS(statReg_);
105
NSS(cgb_);
106
}
107
108
}
109
110