rlm@1
|
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
rlm@1
|
2 // Copyright (C) 1999-2003 Forgotten
|
rlm@1
|
3 // Copyright (C) 2004 Forgotten and the VBA development team
|
rlm@1
|
4
|
rlm@1
|
5 // This program is free software; you can redistribute it and/or modify
|
rlm@1
|
6 // it under the terms of the GNU General Public License as published by
|
rlm@1
|
7 // the Free Software Foundation; either version 2, or(at your option)
|
rlm@1
|
8 // any later version.
|
rlm@1
|
9 //
|
rlm@1
|
10 // This program is distributed in the hope that it will be useful,
|
rlm@1
|
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rlm@1
|
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
rlm@1
|
13 // GNU General Public License for more details.
|
rlm@1
|
14 //
|
rlm@1
|
15 // You should have received a copy of the GNU General Public License
|
rlm@1
|
16 // along with this program; if not, write to the Free Software Foundation,
|
rlm@1
|
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
rlm@1
|
18
|
rlm@1
|
19 #include "screenarea.h"
|
rlm@1
|
20
|
rlm@1
|
21 #include <string.h>
|
rlm@1
|
22
|
rlm@1
|
23 namespace VBA
|
rlm@1
|
24 {
|
rlm@1
|
25
|
rlm@1
|
26 ScreenArea::ScreenArea(int _iWidth, int _iHeight, int _iScale) :
|
rlm@1
|
27 m_puiPixels(NULL),
|
rlm@1
|
28 m_puiDelta(NULL),
|
rlm@1
|
29 m_vFilter2x(NULL),
|
rlm@1
|
30 m_vFilterIB(NULL),
|
rlm@1
|
31 m_bShowCursor(true)
|
rlm@1
|
32 {
|
rlm@1
|
33 g_assert(_iWidth >= 1 && _iHeight >= 1 && _iScale >= 1);
|
rlm@1
|
34
|
rlm@1
|
35 m_iWidth = _iWidth;
|
rlm@1
|
36 m_iHeight = _iHeight;
|
rlm@1
|
37 m_iScale = _iScale;
|
rlm@1
|
38 vUpdateSize();
|
rlm@1
|
39
|
rlm@1
|
40 set_events(Gdk::EXPOSURE_MASK
|
rlm@1
|
41 | Gdk::POINTER_MOTION_MASK
|
rlm@1
|
42 | Gdk::ENTER_NOTIFY_MASK
|
rlm@1
|
43 | Gdk::LEAVE_NOTIFY_MASK);
|
rlm@1
|
44
|
rlm@1
|
45 char aiEmptyData[8];
|
rlm@1
|
46 memset(aiEmptyData, 0, sizeof(aiEmptyData));
|
rlm@1
|
47 Glib::RefPtr<Gdk::Bitmap> poSource = Gdk::Bitmap::create(aiEmptyData, 8, 8);
|
rlm@1
|
48 Glib::RefPtr<Gdk::Bitmap> poMask = Gdk::Bitmap::create(aiEmptyData, 8, 8);
|
rlm@1
|
49 Gdk::Color oFg;
|
rlm@1
|
50 Gdk::Color oBg;
|
rlm@1
|
51 oFg.set_rgb(0, 0, 0);
|
rlm@1
|
52 oBg.set_rgb(0, 0, 0);
|
rlm@1
|
53
|
rlm@1
|
54 m_poEmptyCursor = new Gdk::Cursor(poSource, poMask, oFg, oBg, 0, 0);
|
rlm@1
|
55 }
|
rlm@1
|
56
|
rlm@1
|
57 ScreenArea::~ScreenArea()
|
rlm@1
|
58 {
|
rlm@1
|
59 if (m_puiPixels != NULL)
|
rlm@1
|
60 {
|
rlm@1
|
61 delete[] m_puiPixels;
|
rlm@1
|
62 }
|
rlm@1
|
63
|
rlm@1
|
64 if (m_puiDelta != NULL)
|
rlm@1
|
65 {
|
rlm@1
|
66 delete[] m_puiDelta;
|
rlm@1
|
67 }
|
rlm@1
|
68
|
rlm@1
|
69 if (m_poEmptyCursor != NULL)
|
rlm@1
|
70 {
|
rlm@1
|
71 delete m_poEmptyCursor;
|
rlm@1
|
72 }
|
rlm@1
|
73 }
|
rlm@1
|
74
|
rlm@1
|
75 void ScreenArea::vSetSize(int _iWidth, int _iHeight)
|
rlm@1
|
76 {
|
rlm@1
|
77 g_return_if_fail(_iWidth >= 1 && _iHeight >= 1);
|
rlm@1
|
78
|
rlm@1
|
79 if (_iWidth != m_iWidth || _iHeight != m_iHeight)
|
rlm@1
|
80 {
|
rlm@1
|
81 m_iWidth = _iWidth;
|
rlm@1
|
82 m_iHeight = _iHeight;
|
rlm@1
|
83 vUpdateSize();
|
rlm@1
|
84 }
|
rlm@1
|
85 }
|
rlm@1
|
86
|
rlm@1
|
87 void ScreenArea::vSetScale(int _iScale)
|
rlm@1
|
88 {
|
rlm@1
|
89 g_return_if_fail(_iScale >= 1);
|
rlm@1
|
90
|
rlm@1
|
91 if (_iScale != m_iScale)
|
rlm@1
|
92 {
|
rlm@1
|
93 m_iScale = _iScale;
|
rlm@1
|
94 vUpdateSize();
|
rlm@1
|
95 }
|
rlm@1
|
96 }
|
rlm@1
|
97
|
rlm@1
|
98 void ScreenArea::vSetFilter2x(EFilter2x _eFilter2x)
|
rlm@1
|
99 {
|
rlm@1
|
100 m_vFilter2x = pvGetFilter2x(_eFilter2x, FilterDepth32);
|
rlm@1
|
101 }
|
rlm@1
|
102
|
rlm@1
|
103 void ScreenArea::vSetFilterIB(EFilterIB _eFilterIB)
|
rlm@1
|
104 {
|
rlm@1
|
105 m_vFilterIB = pvGetFilterIB(_eFilterIB, FilterDepth32);
|
rlm@1
|
106 }
|
rlm@1
|
107
|
rlm@1
|
108 void ScreenArea::vDrawPixels(u8 * _puiData)
|
rlm@1
|
109 {
|
rlm@1
|
110 if (m_vFilterIB != NULL)
|
rlm@1
|
111 {
|
rlm@1
|
112 m_vFilterIB(_puiData + m_iAreaWidth * 2 + 4,
|
rlm@1
|
113 m_iAreaWidth * 2 + 4,
|
rlm@1
|
114 m_iWidth,
|
rlm@1
|
115 m_iHeight);
|
rlm@1
|
116 }
|
rlm@1
|
117
|
rlm@1
|
118 if (m_iScale == 1)
|
rlm@1
|
119 {
|
rlm@1
|
120 u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1;
|
rlm@1
|
121 u32 * puiPixel = m_puiPixels;
|
rlm@1
|
122 for (int y = 0; y < m_iHeight; y++)
|
rlm@1
|
123 {
|
rlm@1
|
124 for (int x = 0; x < m_iWidth; x++)
|
rlm@1
|
125 {
|
rlm@1
|
126 *puiPixel++ = *puiSrc++;
|
rlm@1
|
127 }
|
rlm@1
|
128 puiSrc++;
|
rlm@1
|
129 }
|
rlm@1
|
130 }
|
rlm@1
|
131 else if (m_iScale == 2 && m_vFilter2x != NULL)
|
rlm@1
|
132 {
|
rlm@1
|
133 m_vFilter2x(_puiData + m_iAreaWidth * 2 + 4,
|
rlm@1
|
134 m_iAreaWidth * 2 + 4,
|
rlm@1
|
135 m_puiDelta,
|
rlm@1
|
136 (u8 *)m_puiPixels,
|
rlm@1
|
137 m_iRowStride,
|
rlm@1
|
138 m_iWidth,
|
rlm@1
|
139 m_iHeight);
|
rlm@1
|
140 }
|
rlm@1
|
141 else
|
rlm@1
|
142 {
|
rlm@1
|
143 u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1;
|
rlm@1
|
144 u32 * puiSrc2;
|
rlm@1
|
145 u32 * puiPixel = m_puiPixels;
|
rlm@1
|
146 for (int y = 0; y < m_iHeight; y++)
|
rlm@1
|
147 {
|
rlm@1
|
148 for (int j = 0; j < m_iScale; j++)
|
rlm@1
|
149 {
|
rlm@1
|
150 puiSrc2 = puiSrc;
|
rlm@1
|
151 for (int x = 0; x < m_iWidth; x++)
|
rlm@1
|
152 {
|
rlm@1
|
153 for (int i = 0; i < m_iScale; i++)
|
rlm@1
|
154 {
|
rlm@1
|
155 *puiPixel++ = *puiSrc2;
|
rlm@1
|
156 }
|
rlm@1
|
157 puiSrc2++;
|
rlm@1
|
158 }
|
rlm@1
|
159 }
|
rlm@1
|
160 puiSrc = puiSrc2 + 1;
|
rlm@1
|
161 }
|
rlm@1
|
162 }
|
rlm@1
|
163
|
rlm@1
|
164 queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight);
|
rlm@1
|
165 }
|
rlm@1
|
166
|
rlm@1
|
167 void ScreenArea::vDrawColor(u32 _uiColor)
|
rlm@1
|
168 {
|
rlm@1
|
169 _uiColor = GUINT32_TO_BE(_uiColor) << 8;
|
rlm@1
|
170
|
rlm@1
|
171 u32 * puiPixel = m_puiPixels;
|
rlm@1
|
172 u32 * puiEnd = m_puiPixels + m_iAreaWidth * m_iAreaHeight;
|
rlm@1
|
173 while (puiPixel != puiEnd)
|
rlm@1
|
174 {
|
rlm@1
|
175 *puiPixel++ = _uiColor;
|
rlm@1
|
176 }
|
rlm@1
|
177
|
rlm@1
|
178 queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight);
|
rlm@1
|
179 }
|
rlm@1
|
180
|
rlm@1
|
181 void ScreenArea::vUpdateSize()
|
rlm@1
|
182 {
|
rlm@1
|
183 if (m_puiPixels != NULL)
|
rlm@1
|
184 {
|
rlm@1
|
185 delete[] m_puiPixels;
|
rlm@1
|
186 }
|
rlm@1
|
187
|
rlm@1
|
188 if (m_puiDelta != NULL)
|
rlm@1
|
189 {
|
rlm@1
|
190 delete[] m_puiDelta;
|
rlm@1
|
191 }
|
rlm@1
|
192
|
rlm@1
|
193 m_iAreaWidth = m_iScale * m_iWidth;
|
rlm@1
|
194 m_iAreaHeight = m_iScale * m_iHeight;
|
rlm@1
|
195 m_iRowStride = m_iAreaWidth * 4;
|
rlm@1
|
196
|
rlm@1
|
197 m_puiPixels = new u32[m_iAreaWidth * m_iAreaHeight];
|
rlm@1
|
198
|
rlm@1
|
199 m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * 4];
|
rlm@1
|
200 memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * 4);
|
rlm@1
|
201
|
rlm@1
|
202 set_size_request(m_iAreaWidth, m_iAreaHeight);
|
rlm@1
|
203 }
|
rlm@1
|
204
|
rlm@1
|
205 void ScreenArea::vStartCursorTimeout()
|
rlm@1
|
206 {
|
rlm@1
|
207 m_oCursorSig.disconnect();
|
rlm@1
|
208 m_oCursorSig = Glib::signal_timeout().connect(
|
rlm@1
|
209 SigC::slot(*this, &ScreenArea::bOnCursorTimeout),
|
rlm@1
|
210 2000);
|
rlm@1
|
211 }
|
rlm@1
|
212
|
rlm@1
|
213 void ScreenArea::vStopCursorTimeout()
|
rlm@1
|
214 {
|
rlm@1
|
215 m_oCursorSig.disconnect();
|
rlm@1
|
216 }
|
rlm@1
|
217
|
rlm@1
|
218 void ScreenArea::vHideCursor()
|
rlm@1
|
219 {
|
rlm@1
|
220 get_window()->set_cursor(*m_poEmptyCursor);
|
rlm@1
|
221 m_bShowCursor = false;
|
rlm@1
|
222 }
|
rlm@1
|
223
|
rlm@1
|
224 void ScreenArea::vShowCursor()
|
rlm@1
|
225 {
|
rlm@1
|
226 get_window()->set_cursor();
|
rlm@1
|
227 m_bShowCursor = true;
|
rlm@1
|
228 }
|
rlm@1
|
229
|
rlm@1
|
230 bool ScreenArea::on_expose_event(GdkEventExpose * _pstEvent)
|
rlm@1
|
231 {
|
rlm@1
|
232 if (_pstEvent->area.x + _pstEvent->area.width > m_iAreaWidth
|
rlm@1
|
233 || _pstEvent->area.y + _pstEvent->area.height > m_iAreaHeight)
|
rlm@1
|
234 {
|
rlm@1
|
235 return false;
|
rlm@1
|
236 }
|
rlm@1
|
237
|
rlm@1
|
238 guchar * puiAreaPixels = (guchar *)m_puiPixels;
|
rlm@1
|
239
|
rlm@1
|
240 if (_pstEvent->area.x != 0)
|
rlm@1
|
241 {
|
rlm@1
|
242 puiAreaPixels += _pstEvent->area.x << 2;
|
rlm@1
|
243 }
|
rlm@1
|
244
|
rlm@1
|
245 if (_pstEvent->area.y != 0)
|
rlm@1
|
246 {
|
rlm@1
|
247 puiAreaPixels += _pstEvent->area.y * m_iRowStride;
|
rlm@1
|
248 }
|
rlm@1
|
249
|
rlm@1
|
250 get_window()->draw_rgb_32_image(get_style()->get_fg_gc(get_state()),
|
rlm@1
|
251 _pstEvent->area.x,
|
rlm@1
|
252 _pstEvent->area.y,
|
rlm@1
|
253 _pstEvent->area.width,
|
rlm@1
|
254 _pstEvent->area.height,
|
rlm@1
|
255 Gdk::RGB_DITHER_MAX,
|
rlm@1
|
256 puiAreaPixels,
|
rlm@1
|
257 m_iRowStride);
|
rlm@1
|
258 return true;
|
rlm@1
|
259 }
|
rlm@1
|
260
|
rlm@1
|
261 bool ScreenArea::on_motion_notify_event(GdkEventMotion * _pstEvent)
|
rlm@1
|
262 {
|
rlm@1
|
263 if (! m_bShowCursor)
|
rlm@1
|
264 {
|
rlm@1
|
265 vShowCursor();
|
rlm@1
|
266 }
|
rlm@1
|
267 vStartCursorTimeout();
|
rlm@1
|
268 return false;
|
rlm@1
|
269 }
|
rlm@1
|
270
|
rlm@1
|
271 bool ScreenArea::on_enter_notify_event(GdkEventCrossing * _pstEvent)
|
rlm@1
|
272 {
|
rlm@1
|
273 vStartCursorTimeout();
|
rlm@1
|
274 return false;
|
rlm@1
|
275 }
|
rlm@1
|
276
|
rlm@1
|
277 bool ScreenArea::on_leave_notify_event(GdkEventCrossing * _pstEvent)
|
rlm@1
|
278 {
|
rlm@1
|
279 vStopCursorTimeout();
|
rlm@1
|
280 if (! m_bShowCursor)
|
rlm@1
|
281 {
|
rlm@1
|
282 vShowCursor();
|
rlm@1
|
283 }
|
rlm@1
|
284 return false;
|
rlm@1
|
285 }
|
rlm@1
|
286
|
rlm@1
|
287 bool ScreenArea::bOnCursorTimeout()
|
rlm@1
|
288 {
|
rlm@1
|
289 vHideCursor();
|
rlm@1
|
290 return false;
|
rlm@1
|
291 }
|
rlm@1
|
292
|
rlm@1
|
293 } // namespace VBA
|