Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/lcd.cpp
2 views
1
// Meteor - A Nintendo Gameboy Advance emulator
2
// Copyright (C) 2009-2011 Philippe Daouadi
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
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 for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
#include "ameteor/lcd.hpp"
18
#include "ameteor/io.hpp"
19
#include "globals.hpp"
20
#include "ameteor.hpp"
21
22
#include "debug.hpp"
23
24
namespace AMeteor
25
{
26
Lcd::Lcd () :
27
m_screen(MEM, IO)
28
{
29
Reset();
30
}
31
32
void Lcd::Reset ()
33
{
34
CLOCK.AddLcd(960); // call me at first H-Blank
35
}
36
37
void Lcd::TimeEvent ()
38
{
39
uint16_t& dispstat = IO.GetRef16(Io::DISPSTAT);
40
uint16_t& vcount = IO.GetRef16(Io::VCOUNT);
41
42
if (dispstat & 0x2) // if we were H-Blanking
43
{
44
//debug("hblank end");
45
// we are not anymore, we're on next line
46
dispstat ^= 0x2;
47
// call me when we are H-Blanking again
48
CLOCK.AddLcd(960);
49
50
// we have finished drawing a line, do our stuff...
51
if (vcount == 227) // this was the last line
52
{
53
vcount = 0; // we're now at first
54
// we reload the reference points
55
m_screen.UpdateBg2RefX(IO.DRead32(Io::BG2X_L));
56
m_screen.UpdateBg2RefY(IO.DRead32(Io::BG2Y_L));
57
m_screen.UpdateBg3RefX(IO.DRead32(Io::BG3X_L));
58
m_screen.UpdateBg3RefY(IO.DRead32(Io::BG3Y_L));
59
// and we draw the line 0
60
m_screen.DrawLine(0);
61
// FIXME see below, vblank finished
62
dispstat ^= 0x1;
63
}
64
else
65
{
66
++vcount; // we're on next line
67
if (vcount < 160) // we draw normally
68
m_screen.DrawLine(vcount);
69
else if (vcount == 160) // We enter V-Blank
70
{
71
dispstat |= 0x1;
72
if (dispstat & (0x1 << 3)) // if V-Blank irq is enabled
73
CPU.SendInterrupt(0x1);
74
DMA.CheckAll(Dma::VBlank);
75
76
KEYPAD.VBlank();
77
78
// we send the vblank signal
79
//sig_vblank.emit();
80
}
81
// NOTE : v-blank finishes on line 227, not 0
82
// FIXME on vba, it finishes on 0
83
//if (vcount == 227) // V-Blank finished
84
//dispstat ^= 0x1;
85
}
86
87
// check for vcount match
88
if (vcount == ((dispstat >> 8) & 0xFF)) // vcount match
89
{
90
dispstat |= 0x4; // enable vcount match bit
91
if (dispstat & (0x1 << 5)) // if V-Counter irq is enabled
92
CPU.SendInterrupt(0x4);
93
}
94
else // no vcount match
95
dispstat &= ~(uint16_t)0x4;
96
// scanline callback for frontend
97
if (slcallbackline == vcount)
98
scanlinecallback_bizhawk();
99
}
100
else // if we were not H-Blanking
101
{
102
//debug("hblank vcount : " << std::dec << vcount);
103
// now, we are
104
dispstat |= 0x2;
105
// call me when we are not H-Blanking anymore
106
CLOCK.AddLcd(272);
107
108
// NOTE : H-Blank interrupts are not generated during V-Blank
109
// FIXME vba generates hblank interrupts even during vblank
110
// if H-Blank irq is enabled //and we're not in V-Blank
111
if ((dispstat & 0x10) == 0x10)
112
CPU.SendInterrupt(0x2);
113
// NOTE : hblank DMAs are not triggered during vblank
114
// (seen on vba)
115
if (!(dispstat & 0x1))
116
// if we're not vblanking
117
DMA.CheckAll(Dma::HBlank);
118
}
119
}
120
121
bool Lcd::SaveState (std::ostream& stream)
122
{
123
if (!m_screen.SaveState(stream))
124
return false;
125
126
return true;
127
}
128
129
bool Lcd::LoadState (std::istream& stream)
130
{
131
if (!m_screen.LoadState(stream))
132
return false;
133
134
UpdateDispCnt (IO.DRead16(Io::DISPCNT));
135
UpdateBg0Cnt (IO.DRead16(Io::BG0CNT));
136
UpdateBg1Cnt (IO.DRead16(Io::BG1CNT));
137
UpdateBg2Cnt (IO.DRead16(Io::BG2CNT));
138
UpdateBg3Cnt (IO.DRead16(Io::BG3CNT));
139
UpdateBg0XOff (IO.DRead16(Io::BG0HOFS));
140
UpdateBg0YOff (IO.DRead16(Io::BG0VOFS));
141
UpdateBg1XOff (IO.DRead16(Io::BG1HOFS));
142
UpdateBg1YOff (IO.DRead16(Io::BG1VOFS));
143
UpdateBg2XOff (IO.DRead16(Io::BG2HOFS));
144
UpdateBg2YOff (IO.DRead16(Io::BG2VOFS));
145
UpdateBg3XOff (IO.DRead16(Io::BG3HOFS));
146
UpdateBg3YOff (IO.DRead16(Io::BG3VOFS));
147
OamWrite (0x07000000, 0x07000400);
148
149
return true;
150
}
151
}
152
153