1 |
dpavlin |
1 |
/* |
2 |
|
|
* PearPC |
3 |
|
|
* display.cc |
4 |
|
|
* |
5 |
|
|
* Copyright (C) 1999-2002 Stefan Weyergraf |
6 |
|
|
* Copyright (C) 2003,2004 Sebastian Biallas (sb@biallas.net) |
7 |
|
|
* |
8 |
|
|
* This program is free software; you can redistribute it and/or modify |
9 |
|
|
* it under the terms of the GNU General Public License version 2 as |
10 |
|
|
* published by the Free Software Foundation. |
11 |
|
|
* |
12 |
|
|
* This program is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
|
* GNU General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include <new> |
23 |
|
|
#include <cstdarg> |
24 |
|
|
#include <cstdlib> |
25 |
|
|
#include <cstring> |
26 |
|
|
|
27 |
|
|
#include "display.h" |
28 |
|
|
#include "tools/snprintf.h" |
29 |
|
|
#include "gif.h" |
30 |
|
|
|
31 |
|
|
// For key support |
32 |
|
|
#include "io/cuda/cuda.h" |
33 |
|
|
#include "system/sys.h" |
34 |
|
|
#include "system/keyboard.h" |
35 |
|
|
|
36 |
|
|
byte * gFrameBuffer = NULL; |
37 |
|
|
int gDamageAreaFirstAddr, gDamageAreaLastAddr; |
38 |
|
|
|
39 |
|
|
#define IS_FGTRANS(c) (VC_GET_BASECOLOR(VCP_FOREGROUND((c)))==VC_TRANSPARENT) |
40 |
|
|
#define IS_BGTRANS(c) (VC_GET_BASECOLOR(VCP_BACKGROUND((c)))==VC_TRANSPARENT) |
41 |
|
|
|
42 |
|
|
static vcp mixColors(vcp base, vcp layer) |
43 |
|
|
{ |
44 |
|
|
vc fg, bg; |
45 |
|
|
if (IS_FGTRANS(layer)) { |
46 |
|
|
fg = VCP_FOREGROUND(base); |
47 |
|
|
} else { |
48 |
|
|
fg = VCP_FOREGROUND(layer); |
49 |
|
|
} |
50 |
|
|
if (IS_BGTRANS(layer)) { |
51 |
|
|
bg = VCP_BACKGROUND(base); |
52 |
|
|
} else { |
53 |
|
|
bg = VCP_BACKGROUND(layer); |
54 |
|
|
} |
55 |
|
|
if (IS_FGTRANS(layer) && (fg != VC_TRANSPARENT) && (fg == bg)) fg=(fg+1)%8; |
56 |
|
|
if (IS_BGTRANS(layer) && (bg != VC_TRANSPARENT) && (fg == bg)) bg=(bg+1)%8; |
57 |
|
|
return VCP(fg, bg); |
58 |
|
|
} |
59 |
|
|
|
60 |
|
|
SystemDisplay *gDisplay = NULL; |
61 |
|
|
|
62 |
|
|
class MenuEntry: public Object { |
63 |
|
|
int x, y, w, h; |
64 |
|
|
void (*mCallback)(void *); |
65 |
|
|
void *mCallbackParam; |
66 |
|
|
public: |
67 |
|
|
Gif *mPic; |
68 |
|
|
|
69 |
|
|
MenuEntry(int X, int Y, Gif *pic, void (*callback)(void *), void *callbackparam) |
70 |
|
|
{ |
71 |
|
|
x = X; y = Y; w = pic->mWidth; h = pic->mHeight; |
72 |
|
|
mPic = pic; |
73 |
|
|
mCallback = callback; |
74 |
|
|
mCallbackParam = callbackparam; |
75 |
|
|
} |
76 |
|
|
|
77 |
|
|
virtual ~MenuEntry() |
78 |
|
|
{ |
79 |
|
|
delete mPic; |
80 |
|
|
} |
81 |
|
|
|
82 |
|
|
void check(int cx, int cy) |
83 |
|
|
{ |
84 |
|
|
if (cx >= x && cy >= y && cx <= (x+w) && cy <= (y+h)) { |
85 |
|
|
mCallback(mCallbackParam); |
86 |
|
|
} |
87 |
|
|
} |
88 |
|
|
}; |
89 |
|
|
|
90 |
|
|
|
91 |
|
|
#include "vt100.h" |
92 |
|
|
#include "font.h" |
93 |
|
|
|
94 |
|
|
static RGBA _16toRGBA[16] = { |
95 |
|
|
MK_RGBA(0x22, 0x22, 0x22, 0xff), |
96 |
|
|
MK_RGBA(0x00, 0x00, 0xaa, 0xff), |
97 |
|
|
MK_RGBA(0x00, 0xaa, 0x00, 0xff), |
98 |
|
|
MK_RGBA(0x00, 0xaa, 0xaa, 0xff), |
99 |
|
|
MK_RGBA(0xaa, 0x00, 0x00, 0xff), |
100 |
|
|
MK_RGBA(0xaa, 0x00, 0xaa, 0xff), |
101 |
|
|
MK_RGBA(0xaa, 0xaa, 0x00, 0xff), |
102 |
|
|
MK_RGBA(0xaa, 0xaa, 0xaa, 0xff), |
103 |
|
|
MK_RGBA(0x55, 0x55, 0x55, 0xff), |
104 |
|
|
MK_RGBA(0x55, 0x55, 0xff, 0xff), |
105 |
|
|
MK_RGBA(0x55, 0xff, 0x55, 0xff), |
106 |
|
|
MK_RGBA(0x55, 0xff, 0xff, 0xff), |
107 |
|
|
MK_RGBA(0xff, 0x55, 0x55, 0xff), |
108 |
|
|
MK_RGBA(0xff, 0x55, 0xff, 0xff), |
109 |
|
|
MK_RGBA(0xff, 0xff, 0x55, 0xff), |
110 |
|
|
MK_RGBA(0xff, 0xff, 0xff, 0xff) |
111 |
|
|
}; |
112 |
|
|
|
113 |
|
|
#define MASK(shift, size) (((1 << (size))-1)<<(shift)) |
114 |
|
|
void dumpDisplayChar(const DisplayCharacteristics &chr) |
115 |
|
|
{ |
116 |
|
|
fprintf(stderr, "\tdimensions: %d x %d pixels\n", chr.width, chr.height); |
117 |
|
|
fprintf(stderr, "\tpixel size in bytes: %d\n", chr.bytesPerPixel); |
118 |
|
|
fprintf(stderr, "\tpixel size in bits: %d\n", chr.bytesPerPixel*8); |
119 |
|
|
fprintf(stderr, "\tred_mask: %08x (%d bits)\n", MASK(chr.redShift, chr.redSize), chr.redSize); |
120 |
|
|
fprintf(stderr, "\tgreen_mask: %08x (%d bits)\n", MASK(chr.greenShift, chr.greenSize), chr.greenSize); |
121 |
|
|
fprintf(stderr, "\tblue_mask: %08x (%d bits)\n", MASK(chr.blueShift, chr.blueSize), chr.blueSize); |
122 |
|
|
fprintf(stderr, "\tdepth: %d\n", chr.redSize + chr.greenSize + chr.blueSize); |
123 |
|
|
} |
124 |
|
|
|
125 |
|
|
SystemDisplay::SystemDisplay(const DisplayCharacteristics &aClientChr, int redraw_ms) |
126 |
|
|
{ |
127 |
|
|
mClientChar = aClientChr; |
128 |
|
|
mRedraw_ms = redraw_ms; |
129 |
|
|
mHWCursorX = 0; |
130 |
|
|
mHWCursorY = 0; |
131 |
|
|
mHWCursorVisible = false; |
132 |
|
|
mHWCursorData = NULL; |
133 |
|
|
|
134 |
|
|
mMenu = new Array(true); |
135 |
|
|
mMenuX = 0; |
136 |
|
|
mMenuHeight = 20; |
137 |
|
|
mMouseGrabbed = false; |
138 |
|
|
|
139 |
|
|
mFullscreenChanged = false; |
140 |
|
|
mFullscreen = false; |
141 |
|
|
|
142 |
|
|
mExposed = false; |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
SystemDisplay::~SystemDisplay() |
146 |
|
|
{ |
147 |
|
|
delete mMenu; |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
bool SystemDisplay::openVT(int width, int height, int dx, int dy, File &font) |
151 |
|
|
{ |
152 |
|
|
mVTWidth = width; |
153 |
|
|
mVTHeight = height; |
154 |
|
|
mVTDX = dx; |
155 |
|
|
mVTDY = dy; |
156 |
|
|
mFont = new Font(); |
157 |
|
|
if (!((Font*)mFont)->loadFromFile(font)) return false; |
158 |
|
|
buf = (BufferedChar*)malloc(sizeof (BufferedChar) * width * height); |
159 |
|
|
vt = new VT100Display(width, height, this); |
160 |
|
|
((VT100Display*)vt)->setAutoNewLine(true); |
161 |
|
|
return true; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
void SystemDisplay::closeVT() |
165 |
|
|
{ |
166 |
|
|
delete vt; |
167 |
|
|
free(buf); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
void SystemDisplay::setHWCursor(int x, int y, bool visible, byte *data) |
171 |
|
|
{ |
172 |
|
|
mHWCursorX = x; |
173 |
|
|
mHWCursorY = y; |
174 |
|
|
mHWCursorVisible = visible; |
175 |
|
|
mHWCursorData = data; |
176 |
|
|
displayShow(); |
177 |
|
|
} |
178 |
|
|
|
179 |
|
|
void SystemDisplay::print(const char *s) |
180 |
|
|
{ |
181 |
|
|
const void *x = s; |
182 |
|
|
int xl = strlen(s); |
183 |
|
|
((VT100Display*)vt)->termWrite(x, xl); |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
void SystemDisplay::printf(const char *s, ...) |
187 |
|
|
{ |
188 |
|
|
va_list ap; |
189 |
|
|
va_start(ap, s); |
190 |
|
|
char buf[1024]; |
191 |
|
|
ht_vsnprintf(buf, sizeof buf, s, ap); |
192 |
|
|
print(buf); |
193 |
|
|
va_end(ap); |
194 |
|
|
} |
195 |
|
|
|
196 |
|
|
void SystemDisplay::setAnsiColor(vcp color) |
197 |
|
|
{ |
198 |
|
|
char ansiseq[32]; |
199 |
|
|
vcpToAnsi(ansiseq, color); |
200 |
|
|
print(ansiseq); |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
void SystemDisplay::fillAllVT(vcp color, byte chr) |
204 |
|
|
{ |
205 |
|
|
fillVT(0, 0, mVTWidth, mVTHeight, color, chr); |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
void SystemDisplay::drawChar(int x, int y, vcp color, byte chr) |
209 |
|
|
{ |
210 |
|
|
buf[y*mVTWidth+x].rawchar = chr; |
211 |
|
|
buf[y*mVTWidth+x].color = color; |
212 |
|
|
|
213 |
|
|
uint bg = VCP_BACKGROUND(color); |
214 |
|
|
uint fg = VCP_FOREGROUND(color); |
215 |
|
|
if (VC_GET_LIGHT(bg)) { |
216 |
|
|
bg &= 0xf; |
217 |
|
|
bg += 8; |
218 |
|
|
} |
219 |
|
|
if (VC_GET_LIGHT(fg)) { |
220 |
|
|
fg &= 0xf; |
221 |
|
|
fg += 8; |
222 |
|
|
} |
223 |
|
|
RGBA bg2 = _16toRGBA[bg]; |
224 |
|
|
RGBA fg2 = _16toRGBA[fg]; |
225 |
|
|
((Font*)mFont)->drawFixedChar2(this, x, y, mVTDX, mVTDY, chr, fg2, bg2); |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
void SystemDisplay::fillVT(int x, int y, int w, int h, vcp color, byte chr) |
229 |
|
|
{ |
230 |
|
|
for (int iy = y; iy < y+h; iy++) { |
231 |
|
|
if (iy >= mVTHeight) break; |
232 |
|
|
BufferedChar *b = buf+x+ iy * mVTWidth; |
233 |
|
|
for (int ix = x; ix < x+w; ix++) { |
234 |
|
|
b->rawchar = chr; |
235 |
|
|
b->color = mixColors(b->color, color); |
236 |
|
|
b++; |
237 |
|
|
} |
238 |
|
|
} |
239 |
|
|
for (int iy = 0; iy < mVTHeight; iy++) { |
240 |
|
|
BufferedChar *b = buf+x+ iy * mVTWidth; |
241 |
|
|
for (int ix = x; ix < mVTWidth; ix++) { |
242 |
|
|
uint bg = VCP_BACKGROUND(b->color); |
243 |
|
|
uint fg = VCP_FOREGROUND(b->color); |
244 |
|
|
if (VC_GET_LIGHT(bg)) { |
245 |
|
|
bg &= 0xf; |
246 |
|
|
bg += 8; |
247 |
|
|
} |
248 |
|
|
if (VC_GET_LIGHT(fg)) { |
249 |
|
|
fg &= 0xf; |
250 |
|
|
fg += 8; |
251 |
|
|
} |
252 |
|
|
RGBA bg2 = _16toRGBA[bg]; |
253 |
|
|
RGBA fg2 = _16toRGBA[fg]; |
254 |
|
|
((Font*)mFont)->drawFixedChar2(this, ix, iy, mVTDX, mVTDY, b->rawchar, fg2, bg2); |
255 |
|
|
b++; |
256 |
|
|
} |
257 |
|
|
} |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
/*void SystemDisplay::fill(int x, int y, int w, int h, RGB c) |
261 |
|
|
{ |
262 |
|
|
uint color; |
263 |
|
|
c = MK_RGB(0xff, 0xff, 0xff); |
264 |
|
|
mixRGB((byte*)&color, c); |
265 |
|
|
if (x > mClientChar.width) return; |
266 |
|
|
if (y > mClientChar.height) return; |
267 |
|
|
if (x < 0) { |
268 |
|
|
w += x; |
269 |
|
|
x = 0; |
270 |
|
|
} |
271 |
|
|
if (y < 0) { |
272 |
|
|
h += y; |
273 |
|
|
y = 0; |
274 |
|
|
} |
275 |
|
|
if (w <= 0) return; |
276 |
|
|
if (h <= 0) return; |
277 |
|
|
if (x+w > mClientChar.width) { |
278 |
|
|
w = mClientChar.width-x; |
279 |
|
|
if (!w) return; |
280 |
|
|
} |
281 |
|
|
if (y+h > mClientChar.height) { |
282 |
|
|
h = mClientChar.height-y; |
283 |
|
|
if (!h) return; |
284 |
|
|
} |
285 |
|
|
byte *f = framebuffer + ((y*mClientChar.width)+x)*mClientChar.bytesPerPixel; |
286 |
|
|
switch (mClientChar.bytesPerPixel) { |
287 |
|
|
case 2: |
288 |
|
|
while (h--) { |
289 |
|
|
for (int i=0; i<w; i++) { |
290 |
|
|
*(f++) = (((color>>8)>>1)&0x7c)|(((color>>16)>>6) & 3); |
291 |
|
|
*(f++) = (((color>>16)<<2)&0xe0)|(((color>>24)>>3) & 0x1f); |
292 |
|
|
} |
293 |
|
|
f += (mClientChar.width-w)*2; |
294 |
|
|
} |
295 |
|
|
break; |
296 |
|
|
case 4: |
297 |
|
|
while (h--) { |
298 |
|
|
for (int i=0; i<w; i++) { |
299 |
|
|
*(f++) = 0; |
300 |
|
|
*(f++) = color>>8; |
301 |
|
|
*(f++) = color>>16; |
302 |
|
|
*(f++) = color>>24; |
303 |
|
|
} |
304 |
|
|
f += (mClientChar.width-w)*4; |
305 |
|
|
} |
306 |
|
|
break; |
307 |
|
|
} |
308 |
|
|
}*/ |
309 |
|
|
|
310 |
|
|
void SystemDisplay::fillRGB(int x, int y, int w, int h, RGB rgb) |
311 |
|
|
{ |
312 |
|
|
while (h--) { |
313 |
|
|
for (int i=0; i<w; i++) { |
314 |
|
|
putPixelRGB(x+i, y, rgb); |
315 |
|
|
} |
316 |
|
|
y++; |
317 |
|
|
} |
318 |
|
|
} |
319 |
|
|
|
320 |
|
|
void SystemDisplay::setColor(int idx, RGB color) |
321 |
|
|
{ |
322 |
|
|
if (idx >= 0 && idx < 256) palette[idx] = color; |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
RGB SystemDisplay::getColor(int idx) |
326 |
|
|
{ |
327 |
|
|
if (idx >= 0 && idx < 256) return palette[idx]; |
328 |
|
|
return 0; |
329 |
|
|
} |
330 |
|
|
|
331 |
|
|
void SystemDisplay::fillRGBA(int x, int y, int w, int h, RGBA rgba) |
332 |
|
|
{ |
333 |
|
|
while (h--) { |
334 |
|
|
for (int i=0; i<w; i++) { |
335 |
|
|
putPixelRGBA(x+i, y, rgba); |
336 |
|
|
} |
337 |
|
|
y++; |
338 |
|
|
} |
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
#include <math.h> |
342 |
|
|
void SystemDisplay::drawCircleFilled(int x, int y, int w, int h, int cx, int cy, int r, RGBA fg, RGBA bg) |
343 |
|
|
{ |
344 |
|
|
for (int iy=y; iy<y+h; iy++) { |
345 |
|
|
for (int ix=x; ix<x+h; ix++) { |
346 |
|
|
int rx = ix-cx; |
347 |
|
|
int ry = iy-cy; |
348 |
|
|
int d = rx*rx + ry*ry; |
349 |
|
|
int c = 6; |
350 |
|
|
if (d < r*r) { |
351 |
|
|
putPixelRGBA(ix, iy, bg); |
352 |
|
|
} |
353 |
|
|
if ((d >= r*r-c*c) && (d <= r*r+c*c)) { |
354 |
|
|
RGBA fg2 = fg; |
355 |
|
|
int z = RGBA_A(fg); |
356 |
|
|
// int q = (3*c*r-sqrt(3*3*c*c*d)); |
357 |
|
|
// if (q<0) z+=q; else z-=q; |
358 |
|
|
// if (z < 0) z = 0; else if (z>255) z = 255; |
359 |
|
|
fg2 = RGBA_SETA(fg2, z); |
360 |
|
|
putPixelRGBA(ix, iy, fg2); |
361 |
|
|
} |
362 |
|
|
} |
363 |
|
|
} |
364 |
|
|
} |
365 |
|
|
|
366 |
|
|
void SystemDisplay::drawBox(int x, int y, int w, int h, RGBA fg, RGBA bg) |
367 |
|
|
{ |
368 |
|
|
#if 1 |
369 |
|
|
fillRGBA(x, y, w, h, bg); |
370 |
|
|
for (int xi=0; xi<w; xi++) { |
371 |
|
|
putPixelRGBA(x+xi, y, fg); |
372 |
|
|
putPixelRGBA(x+xi, y+h-1, fg); |
373 |
|
|
} |
374 |
|
|
for (int yi=1; yi<h-1; yi++) { |
375 |
|
|
putPixelRGBA(x, y+yi, fg); |
376 |
|
|
putPixelRGBA(x+w-1, y+yi, fg); |
377 |
|
|
} |
378 |
|
|
#else |
379 |
|
|
uint RE = 5; |
380 |
|
|
fillRGBA(x, y, w, h, bg); |
381 |
|
|
// drawCircleFilled(x, y, RE, RE, x+RE, y+RE, RE, fg, bg); |
382 |
|
|
drawCircleFilled(0, 0, 100, 100, 50, 50, 50, fg, bg); |
383 |
|
|
for (uint xi=RE; xi<w-RE; xi++) { |
384 |
|
|
putPixelRGBA(x+xi, y, fg); |
385 |
|
|
putPixelRGBA(x+xi, y+h-1, fg); |
386 |
|
|
} |
387 |
|
|
for (uint yi=1+RE; yi<h-1-RE; yi++) { |
388 |
|
|
putPixelRGBA(x, y+yi, fg); |
389 |
|
|
putPixelRGBA(x+w-1, y+yi, fg); |
390 |
|
|
} |
391 |
|
|
#endif |
392 |
|
|
} |
393 |
|
|
|
394 |
|
|
void SystemDisplay::insertMenuButton(Stream &str, void (*callback)(void *), void *p) |
395 |
|
|
{ |
396 |
|
|
Gif *pic = new Gif(str); |
397 |
|
|
mMenu->insert(new MenuEntry(mMenuX, 0, pic, callback, p)); |
398 |
|
|
mMenuX += pic->mWidth; |
399 |
|
|
mMenuHeight = MAX(mMenuHeight, pic->mHeight); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
void SystemDisplay::drawMenu() |
403 |
|
|
{ |
404 |
|
|
int x = 0; |
405 |
|
|
for (int i=0; i < (int)mMenu->count(); i++) { |
406 |
|
|
MenuEntry *e = (MenuEntry*)(*mMenu)[i]; |
407 |
|
|
e->mPic->draw(gDisplay, x, (mMenuHeight - e->mPic->mHeight) / 2); |
408 |
|
|
x += e->mPic->mWidth; |
409 |
|
|
} |
410 |
|
|
} |
411 |
|
|
|
412 |
|
|
void SystemDisplay::clickMenu(int x, int y) |
413 |
|
|
{ |
414 |
|
|
for (int i=0; i < (int)mMenu->count(); i++) { |
415 |
|
|
MenuEntry *e = (MenuEntry*)(*mMenu)[i]; |
416 |
|
|
e->check(x, y); |
417 |
|
|
} |
418 |
|
|
} |
419 |
|
|
|
420 |
|
|
void SystemDisplay::composeKeyDialog() |
421 |
|
|
{ |
422 |
|
|
return; |
423 |
|
|
// Doesn't work since should get executed in the CPU thread |
424 |
|
|
#if 0 |
425 |
|
|
byte *oldframebuffer = (byte*)malloc(mClientChar.scanLineLength * mClientChar.height); |
426 |
|
|
memcpy(oldframebuffer, gFrameBuffer, mClientChar.scanLineLength * mClientChar.height); |
427 |
|
|
|
428 |
|
|
const int w = 400; |
429 |
|
|
const int h = 200; |
430 |
|
|
int x = (mClientChar.width-w)/2; |
431 |
|
|
int y = (mClientChar.height-h)/2; |
432 |
|
|
|
433 |
|
|
uint keys[4]; |
434 |
|
|
int k=0; |
435 |
|
|
const RGBA fg = MK_RGBA(0,0,0,0xff); |
436 |
|
|
const RGBA bg = MK_RGBA(0xaa,0xee,0xee,0xb0); |
437 |
|
|
const RGBA tr = MK_RGBA(0,0,0,0); |
438 |
|
|
|
439 |
|
|
bool regrabMouse = false; |
440 |
|
|
if (isMouseGrabbed()) { |
441 |
|
|
regrabMouse = true; |
442 |
|
|
setMouseGrab(false); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
while (1) { |
446 |
|
|
redo: |
447 |
|
|
memcpy(gFrameBuffer, oldframebuffer, mClientChar.scanLineLength * mClientChar.height); |
448 |
|
|
drawBox(x, y, w, h, fg, bg); |
449 |
|
|
outText(x+10, y+10, fg, tr, "Press keys to compose key sequence..."); |
450 |
|
|
|
451 |
|
|
String name; |
452 |
|
|
for (int i=0; i<k; i++) { |
453 |
|
|
String key_name; |
454 |
|
|
SystemKeyboard::convertKeycodeToString(key_name, keys[i]); |
455 |
|
|
name += key_name; |
456 |
|
|
if (i+1 < k) name += " + "; |
457 |
|
|
} |
458 |
|
|
|
459 |
|
|
outText(x+10, y+50, fg, tr, name); |
460 |
|
|
|
461 |
|
|
uint32 keycode; |
462 |
|
|
do { |
463 |
|
|
while (!cuda_prom_get_key(keycode)) sys_suspend(); |
464 |
|
|
} while (keycode & 0x80); |
465 |
|
|
|
466 |
|
|
if (keycode == KEY_F11) break; |
467 |
|
|
|
468 |
|
|
for (int i=0; i<k; i++) { |
469 |
|
|
if (keys[i] == keycode) { |
470 |
|
|
for (int j=i+1; j<k; j++) { |
471 |
|
|
keys[j-1] = keys[j]; |
472 |
|
|
} |
473 |
|
|
k--; |
474 |
|
|
goto redo; |
475 |
|
|
} |
476 |
|
|
} |
477 |
|
|
|
478 |
|
|
if (k<4) { |
479 |
|
|
keys[k] = keycode; |
480 |
|
|
k++; |
481 |
|
|
} |
482 |
|
|
} |
483 |
|
|
|
484 |
|
|
SystemEvent ev; |
485 |
|
|
ev.type = sysevKey; |
486 |
|
|
ev.key.pressed = true; |
487 |
|
|
for (int i=0; i<k; i++) { |
488 |
|
|
ev.key.keycode = keys[i]; |
489 |
|
|
gKeyboard->handleEvent(ev); |
490 |
|
|
} |
491 |
|
|
ev.key.pressed = false; |
492 |
|
|
for (int i=k-1; i>=0; i--) { |
493 |
|
|
ev.key.keycode = keys[i]; |
494 |
|
|
gKeyboard->handleEvent(ev); |
495 |
|
|
} |
496 |
|
|
|
497 |
|
|
memcpy(gFrameBuffer, oldframebuffer, mClientChar.scanLineLength * mClientChar.height); |
498 |
|
|
free(oldframebuffer); |
499 |
|
|
if (regrabMouse) setMouseGrab(true); |
500 |
|
|
damageFrameBufferAll(); |
501 |
|
|
#endif |
502 |
|
|
} |
503 |
|
|
|
504 |
|
|
void SystemDisplay::outText(int x, int y, RGBA fg, RGBA bg, const char *text) |
505 |
|
|
{ |
506 |
|
|
while (*text) { |
507 |
|
|
((Font*)mFont)->drawChar2(this, x, y, *text, fg, bg); |
508 |
|
|
text++; |
509 |
|
|
x+=8; |
510 |
|
|
} |
511 |
|
|
} |
512 |
|
|
|
513 |
|
|
void SystemDisplay::mixRGB(byte *pixel, RGB rgb) |
514 |
|
|
{ |
515 |
|
|
uint r = RGB_R(rgb); |
516 |
|
|
uint g = RGB_G(rgb); |
517 |
|
|
uint b = RGB_B(rgb); |
518 |
|
|
convertBaseColor(r, 8, mClientChar.redSize); |
519 |
|
|
convertBaseColor(g, 8, mClientChar.greenSize); |
520 |
|
|
convertBaseColor(b, 8, mClientChar.blueSize); |
521 |
|
|
uint p = (r << mClientChar.redShift) | (g << mClientChar.greenShift) |
522 |
|
|
| (b << mClientChar.blueShift); |
523 |
|
|
switch (mClientChar.bytesPerPixel) { |
524 |
|
|
case 1: |
525 |
|
|
pixel[0] = rgb; |
526 |
|
|
break; |
527 |
|
|
case 2: |
528 |
|
|
pixel[0] = p>>8; |
529 |
|
|
pixel[1] = p; |
530 |
|
|
break; |
531 |
|
|
case 4: |
532 |
|
|
pixel[0] = p>>24; |
533 |
|
|
pixel[1] = p>>16; |
534 |
|
|
pixel[2] = p>>8; |
535 |
|
|
pixel[3] = p; |
536 |
|
|
break; |
537 |
|
|
} |
538 |
|
|
} |
539 |
|
|
|
540 |
|
|
void SystemDisplay::mixRGBA(byte *pixel, RGBA rgba) |
541 |
|
|
{ |
542 |
|
|
uint r = RGBA_R(rgba); |
543 |
|
|
uint g = RGBA_G(rgba); |
544 |
|
|
uint b = RGBA_B(rgba); |
545 |
|
|
uint a = RGBA_A(rgba); |
546 |
|
|
convertBaseColor(r, 8, mClientChar.redSize); |
547 |
|
|
convertBaseColor(g, 8, mClientChar.greenSize); |
548 |
|
|
convertBaseColor(b, 8, mClientChar.blueSize); |
549 |
|
|
uint p; |
550 |
|
|
switch (mClientChar.bytesPerPixel) { |
551 |
|
|
case 1: |
552 |
|
|
p = pixel[0]; |
553 |
|
|
break; |
554 |
|
|
case 2: |
555 |
|
|
p = (pixel[0] << 8) | pixel[1]; |
556 |
|
|
break; |
557 |
|
|
case 4: |
558 |
|
|
p = (pixel[0] << 24) | (pixel[1] << 16) | (pixel[2] << 8) | pixel[3]; |
559 |
|
|
break; |
560 |
|
|
default: |
561 |
|
|
ht_printf("internal error in %s:%d\n", __FILE__, __LINE__); |
562 |
|
|
exit(1); |
563 |
|
|
break; |
564 |
|
|
} |
565 |
|
|
uint sr = (p>>mClientChar.redShift) & ((1<<mClientChar.redSize)-1); |
566 |
|
|
uint sg = (p>>mClientChar.greenShift) & ((1<<mClientChar.greenSize)-1); |
567 |
|
|
uint sb = (p>>mClientChar.blueShift) & ((1<<mClientChar.blueSize)-1); |
568 |
|
|
sr = (r*a + sr*(255-a))/255; |
569 |
|
|
sg = (g*a + sg*(255-a))/255; |
570 |
|
|
sb = (b*a + sb*(255-a))/255; |
571 |
|
|
p = (sr << mClientChar.redShift) | (sg << mClientChar.greenShift) |
572 |
|
|
| (sb << mClientChar.blueShift); |
573 |
|
|
switch (mClientChar.bytesPerPixel) { |
574 |
|
|
case 1: |
575 |
|
|
pixel[0] = p; |
576 |
|
|
break; |
577 |
|
|
case 2: |
578 |
|
|
pixel[0] = p>>8; |
579 |
|
|
pixel[1] = p; |
580 |
|
|
break; |
581 |
|
|
case 4: |
582 |
|
|
pixel[0] = p>>24; |
583 |
|
|
pixel[1] = p>>16; |
584 |
|
|
pixel[2] = p>>8; |
585 |
|
|
pixel[3] = p; |
586 |
|
|
break; |
587 |
|
|
} |
588 |
|
|
} |
589 |
|
|
|
590 |
|
|
void SystemDisplay::putPixelRGB(int x, int y, RGB rgb) |
591 |
|
|
{ |
592 |
|
|
uint addr = x*mClientChar.bytesPerPixel + y*mClientChar.scanLineLength; |
593 |
|
|
mixRGB(&gFrameBuffer[addr], rgb); |
594 |
|
|
damageFrameBuffer(addr); |
595 |
|
|
} |
596 |
|
|
|
597 |
|
|
void SystemDisplay::putPixelRGBA(int x, int y, RGBA rgba) |
598 |
|
|
{ |
599 |
|
|
uint addr = x*mClientChar.bytesPerPixel + y*mClientChar.scanLineLength; |
600 |
|
|
mixRGBA(&gFrameBuffer[addr], rgba); |
601 |
|
|
damageFrameBuffer(addr); |
602 |
|
|
} |
603 |
|
|
|
604 |
|
|
void SystemDisplay::setMouseGrab(bool mouseGrab) |
605 |
|
|
{ |
606 |
|
|
mMouseGrabbed = mouseGrab; |
607 |
|
|
if (!mFullscreenChanged) updateTitle(); |
608 |
|
|
} |
609 |
|
|
|
610 |
|
|
bool SystemDisplay::setFullscreenMode(bool fullscreen) |
611 |
|
|
{ |
612 |
|
|
mFullscreen = fullscreen; |
613 |
|
|
changeResolution(mClientChar); |
614 |
|
|
if (mFullscreenChanged) { |
615 |
|
|
setMouseGrab(true); |
616 |
|
|
} else { |
617 |
|
|
setMouseGrab(false); |
618 |
|
|
} |
619 |
|
|
return mFullscreenChanged; |
620 |
|
|
} |