1
//============================================================================
5
// SS tttttt eeee ll ll aaaa
6
// SSSS tt ee ee ll ll aa
7
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8
// SS SS tt ee ll ll aa aa
9
// SSSS ttt eeeee llll llll aaaaa
11
// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
13
// See the file "license" for information on usage and redistribution of
14
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
// Windows CE Port by Kostas Nakos
17
//============================================================================
20
#include "FrameBufferWinCE.hxx"
21
#include "Console.hxx"
22
#include "OSystem.hxx"
25
#define OPTPIXAVERAGE(pix1,pix2) ( ((((pix1 & optgreenmaskN) + (pix2 & optgreenmaskN)) >> 1) & optgreenmaskN) | ((((pix1 & optgreenmask) + (pix2 & optgreenmask)) >> 1) & optgreenmask) )
27
FrameBufferWinCE::FrameBufferWinCE(OSystem *osystem)
28
: FrameBuffer(osystem), myDstScreen(NULL), SubsystemInited(false), displacement(0),
29
issmartphone(true), islandscape(false), displaymode(0), legacygapi(true), devres(SM_LOW)
31
gxdp.cxWidth = gxdp.cyHeight = gxdp.cbxPitch = gxdp.cbyPitch = gxdp.cBPP = gxdp.ffFormat = 0;
34
FrameBufferWinCE::~FrameBufferWinCE()
38
void FrameBufferWinCE::GetDeviceProperties(void)
40
if (gxdp.cxWidth) return;
43
gxdp = GXGetDisplayProperties();
45
if (((unsigned int) GetSystemMetrics(SM_CXSCREEN) != gxdp.cxWidth) || ((unsigned int) GetSystemMetrics(SM_CYSCREEN) != gxdp.cyHeight))
47
// 2003SE+ and lying about the resolution. good luck.
50
RawFrameBufferInfo rfbi;
51
HDC hdc = GetDC(NULL);
52
ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi);
55
if (rfbi.wFormat == FORMAT_565)
56
gxdp.ffFormat = kfDirect565;
57
else if (rfbi.wFormat == FORMAT_555)
58
gxdp.ffFormat = kfDirect555;
61
gxdp.cBPP = rfbi.wBPP;
62
gxdp.cbxPitch = rfbi.cxStride;
63
gxdp.cbyPitch = rfbi.cyStride;
64
gxdp.cxWidth = rfbi.cxPixels;
65
gxdp.cyHeight = rfbi.cyPixels;
68
// device detection (some redundancy here, but nevermind :)
71
if (gxdp.cxWidth == 176 && gxdp.cyHeight == 220)
73
if (SystemParametersInfo(SPI_GETPLATFORMTYPE, 100, platform, 0))
75
if (wcsstr(platform, _T("mart")))
79
issmartphone = true; // most likely
81
if (gxdp.cxWidth == 176 && gxdp.cyHeight == 220)
83
/*else if (gxdp.cxWidth == 480 && gxdp.cyHeight == 640)
89
void FrameBufferWinCE::setPalette(const uInt32* palette)
92
GetDeviceProperties();
93
for (uInt16 i=0; i<256; i++)
95
uInt8 r = (uInt8) ((palette[i] & 0xFF0000) >> 16);
96
uInt8 g = (uInt8) ((palette[i] & 0x00FF00) >> 8);
97
uInt8 b = (uInt8) (palette[i] & 0x0000FF);
98
if(gxdp.ffFormat & kfDirect565)
99
pal[i] = (uInt16) ( ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) );
100
else if(gxdp.ffFormat & kfDirect555)
101
pal[i] = (uInt16) ( ((r & 0xF8) << 7) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 3) );
105
SubsystemInited = false;
108
bool FrameBufferWinCE::initSubsystem()
110
GetDeviceProperties();
111
for (int i=0; i<kNumColors - 256; i++)
113
uInt8 r = (ourGUIColors[i][0] & 0xFF);
114
uInt8 g = (ourGUIColors[i][1] & 0xFF);
115
uInt8 b = (ourGUIColors[i][2] & 0xFF);
116
if(gxdp.ffFormat & kfDirect565)
117
guipal[i] = (uInt16) ( ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) );
118
else if(gxdp.ffFormat & kfDirect555)
119
guipal[i] = (uInt16) ( ((r & 0xF8) << 7) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 3) );
124
if(gxdp.ffFormat & kfDirect565)
126
optgreenmask = 0x7E0;
127
optgreenmaskN = 0xF81F;
131
optgreenmask = 0x3E0;
132
optgreenmaskN = 0x7C1F;
135
scrwidth = gxdp.cxWidth;
136
scrheight = gxdp.cyHeight;
137
scrpixelstep = gxdp.cbxPitch;
138
scrlinestep = gxdp.cbyPitch;
140
// if (scrwidth == 176 && scrheight == 220)
141
// issmartphone = true;
143
// issmartphone = false;
145
setmode(displaymode);
146
SubsystemInited = false;
150
void FrameBufferWinCE::setmode(uInt8 mode)
152
displaymode = mode % 3;
157
pixelstep = gxdp.cbxPitch;
158
linestep = gxdp.cbyPitch;
164
pixelstep = - gxdp.cbyPitch;
165
linestep = gxdp.cbxPitch;
169
// inverted landscape
171
pixelstep = gxdp.cbyPitch;
172
linestep = - gxdp.cbxPitch;
177
pixelsteptimes5 = pixelstep * 5;
178
pixelsteptimes6 = pixelstep * 6;
179
SubsystemInited = false;
182
uInt8 FrameBufferWinCE::rotatedisplay(void)
184
displaymode = (displaymode + 1) % 3;
185
setmode(displaymode);
190
void FrameBufferWinCE::lateinit(void)
194
myWidth = myOSystem->console().mediaSource().width();
195
myHeight = myOSystem->console().mediaSource().height();
196
myWidthdiv4 = myWidth >> 2;
198
if (devres == SM_LOW)
202
w = (int) ((float) myWidth * 11.0f / 8.0f + 0.5f);
203
else //if (devres == QVGA)
205
w = (int) ((float) myWidth * 3.0f / 2.0f + 0.5f);
213
if (devres == SM_LOW && islandscape)
214
h = (int) ((float) myHeight * 4.0f / 5.0f + 0.5f);
222
displacement = (scrwidth - w) / 2 * gxdp.cbxPitch;
227
displacement += (scrheight - h) / 2 * gxdp.cbyPitch;
235
displacement = gxdp.cbyPitch*(gxdp.cyHeight-1);
239
displacement += (scrwidth - h) / 2 * gxdp.cbxPitch;
244
displacement -= (scrheight - w) / 2 * gxdp.cbyPitch;
248
displacement = gxdp.cbxPitch*(gxdp.cxWidth-1);
252
displacement -= (scrwidth - h) / 2 * gxdp.cbxPitch;
257
displacement += (scrheight - w) / 2 * gxdp.cbyPitch;
262
SubsystemInited = true;
265
void FrameBufferWinCE::preFrameUpdate()
268
static RawFrameBufferInfo rfbi;
271
myDstScreen = (uInt8 *) GXBeginDraw();
275
ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *) &rfbi);
276
ReleaseDC(NULL, hdc);
277
myDstScreen = (uInt8 *) rfbi.pFramePointer;
281
void FrameBufferWinCE::drawMediaSource()
283
static uInt8 *sc, *sp, *sc_n, *sp_n;
284
static uInt8 *d, *pl, *p;
285
static uInt16 pix1, pix2, pix3, x, y;
287
if (!SubsystemInited)
290
if ( (d = myDstScreen) == NULL )
295
sc = myOSystem->console().mediaSource().currentFrameBuffer();
296
sp = myOSystem->console().mediaSource().previousFrameBuffer();
298
if (theRedrawTIAIndicator)
301
for (uInt16 y=0; y<myHeight; y++)
302
for (uInt16 x=0; x<myWidth; x += 4, *p = *p + 1, p += 4);
303
theRedrawTIAIndicator = false;
306
if (devres == SM_LOW && !islandscape)
309
for (y=0; y<minydim; y++)
311
for (x=0; x<myWidthdiv4; x++)
313
if ( *((uInt32 *) sc) != *((uInt32 *) sp) )
315
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
316
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
317
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
318
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
323
d += (pixelstep << 2);
331
else if (devres == SM_LOW && islandscape)
333
for (y=0; y<minydim; y++)
338
for (x=0; x<myWidthdiv4; x++)
342
if ( *((uInt32 *) sc) != *((uInt32 *) sp) )
344
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
345
pix1 = pal[*sc++]; pix2 = pal[*sc++];
346
*((uInt16 *)d) = pix1; d += pixelstep;
347
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
348
*((uInt16 *)d) = pix2; d += pixelstep;
349
*((uInt16 *)d) = pal[*sc++]; d += pixelstep;
354
d += pixelsteptimes5;
357
if (++x>=myWidthdiv4) break;
360
if ( *((uInt32 *) sc) != *((uInt32 *) sp) )
362
pix1 = pal[*sc++]; pix2 = pal[*sc++];
363
*((uInt16 *)d) = pix1; d += pixelstep;
364
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
365
*((uInt16 *)d) = pix2; d += pixelstep;
366
pix1 = pal[*sc++]; pix2 = pal[*sc++];
367
*((uInt16 *)d) = pix1; d += pixelstep;
368
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
369
*((uInt16 *)d) = pix2; d += pixelstep;
374
d += pixelsteptimes6;
383
for (x=0; x<myWidthdiv4; x++)
387
if ( (*((uInt32 *) sc) != *((uInt32 *) sp)) || (*((uInt32 *) sc_n) != *((uInt32 *) sp_n)) )
389
pix1 = pal[*sc++]; pix2 = pal[*sc_n++];
390
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
391
pix1 = pal[*sc++]; pix2 = pal[*sc_n++];
392
pix1 = OPTPIXAVERAGE(pix1,pix2);
393
*((uInt16 *)d) = pix1; d += pixelstep;
394
pix2 = pal[*sc++]; pix3 = pal[*sc_n++];
395
pix2 = OPTPIXAVERAGE(pix2,pix3);
396
pix3 = OPTPIXAVERAGE(pix1,pix2);
397
*((uInt16 *)d) = pix3; d += pixelstep;
398
*((uInt16 *)d) = pix2; d += pixelstep;
399
pix1 = pal[*sc++]; pix2 = pal[*sc_n++];
400
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
406
d += pixelsteptimes5;
410
if (++x>=myWidthdiv4) break;
413
if ( (*((uInt32 *) sc) != *((uInt32 *) sp)) || (*((uInt32 *) sc_n) != *((uInt32 *) sp_n)) )
415
pix1 = pal[*sc++]; pix2 = pal[*sc_n++];
416
pix1 = OPTPIXAVERAGE(pix1,pix2);
417
*((uInt16 *)d) = pix1; d += pixelstep;
418
pix2 = pal[*sc++]; pix3 = pal[*sc_n++];
419
pix2 = OPTPIXAVERAGE(pix2,pix3);
420
pix3 = OPTPIXAVERAGE(pix1,pix2);
421
*((uInt16 *)d) = pix3; d += pixelstep;
422
*((uInt16 *)d) = pix2; d += pixelstep;
423
pix1 = pal[*sc++]; pix2 = pal[*sc_n++];
424
pix1 = OPTPIXAVERAGE(pix1,pix2);
425
*((uInt16 *)d) = pix1; d += pixelstep;
426
pix2 = pal[*sc++]; pix3 = pal[*sc_n++];
427
pix2 = OPTPIXAVERAGE(pix2,pix3);
428
pix3 = OPTPIXAVERAGE(pix1,pix2);
429
*((uInt16 *)d) = pix3; d += pixelstep;
430
*((uInt16 *)d) = pix2; d += pixelstep;
436
d += pixelsteptimes6;
448
else if (devres == QVGA && !islandscape)
451
for (y=0; y<minydim; y++)
453
for (x=0; x<myWidthdiv4; x++)
455
if ( *((uInt32 *) sc) != *((uInt32 *) sp) )
457
pix1 = pal[*sc++]; pix2 = pal[*sc++];
458
*((uInt16 *)d) = pix1; d += pixelstep;
459
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
460
*((uInt16 *)d) = pix2; d += pixelstep;
461
pix1 = pal[*sc++]; pix2 = pal[*sc++];
462
*((uInt16 *)d) = pix1; d += pixelstep;
463
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
464
*((uInt16 *)d) = pix2; d += pixelstep;
469
d += pixelsteptimes6;
477
else if (devres == QVGA && islandscape)
480
for (y=0; y<minydim; y++)
482
for (x=0; x<myWidthdiv4; x++)
484
if ( *((uInt32 *) sc) != *((uInt32 *) sp) )
486
pix1 = pal[*sc++]; pix2 = pal[*sc++];
487
*((uInt16 *)d) = pix1; d += pixelstep;
488
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
490
*((uInt16 *)d) = pix2; d += pixelstep;
491
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
493
*((uInt16 *)d) = pix1; d += pixelstep;
494
*((uInt16 *)d) = OPTPIXAVERAGE(pix1,pix2); d += pixelstep;
495
*((uInt16 *)d) = pix2; d += pixelstep;
496
*((uInt16 *)d) = pix2; d += pixelstep;
501
d += (pixelstep << 3);
512
void FrameBufferWinCE::wipescreen(void)
514
if (!SubsystemInited)
517
uInt8 *s = myOSystem->console().mediaSource().currentFrameBuffer();
518
memset(s, 0, myWidth*myHeight-1);
519
s = myOSystem->console().mediaSource().previousFrameBuffer();
520
memset(s, 0, myWidth*myHeight-1);
525
//for (int i=0; i < scrwidth*scrheight; i++, *((uInt16 *)d) = 0, d += scrpixelstep);
526
memset(myDstScreen, 0, scrwidth*scrheight*2);
530
void FrameBufferWinCE::postFrameUpdate()
532
if (legacygapi) GXEndDraw();
535
void FrameBufferWinCE::drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y, OverlayColor color)
537
GUI::Font* myfont = (GUI::Font*)font;
538
const FontDesc& desc = myfont->desc();
540
if (!myDstScreen) return;
542
if(c < desc.firstchar || c >= desc.firstchar + desc.size)
546
c = desc.defaultchar;
549
Int32 w = myfont->getCharWidth(c);
550
const Int32 h = myfont->getFontHeight();
552
const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[c] : (c * h));
554
if (x<0 || y<0 || (x>>1)+w>scrwidth || y+h>scrheight) return;
558
if (devres == SM_LOW)
560
d = myDstScreen + y * scrlinestep + ((x+1) >> 1) * scrpixelstep;
561
stride = (scrwidth - w) * scrpixelstep;
565
if (displaymode != 2)
566
d = myDstScreen + (scrheight-x-1) * scrlinestep + (y-1) * scrpixelstep;
568
d = myDstScreen + x * scrlinestep + (scrwidth-y-1) * scrpixelstep;
571
uInt16 col = guipal[((int) color) - 256];
573
for(int y2 = 0; y2 < h; y2++)
575
const uInt16 buffer = *tmp++;
576
if (devres == SM_LOW)
578
uInt16 mask = 0xC000;
579
for(int x2 = 0; x2 < w; x2++, mask >>= 2)
582
*((uInt16 *)d) = col;
589
uInt16 mask = 0x8000;
591
for(int x2 = 0; x2 < w; x2++, mask >>= 1)
594
*((uInt16 *)d) = col;
595
if (displaymode != 2)
600
if (displaymode != 2)
601
d = tmp + scrpixelstep;
603
d = tmp - scrpixelstep;
608
void FrameBufferWinCE::scanline(uInt32 row, uInt8* data)
613
void FrameBufferWinCE::setAspectRatio()
618
bool FrameBufferWinCE::createScreen()
623
void FrameBufferWinCE::toggleFilter()
628
uInt32 FrameBufferWinCE::mapRGB(Uint8 r, Uint8 g, Uint8 b)
633
void FrameBufferWinCE::hLine(uInt32 x, uInt32 y, uInt32 x2, OverlayColor color)
635
if (devres == SM_LOW)
637
int kx = x >> 1; int ky = y; int kx2 = x2>> 1;
638
if (kx<0) kx=0; if (ky<0) ky=0; if (ky>scrheight-1) return; if (kx2>scrwidth-1) kx2=scrwidth-1;
639
PlothLine(kx, ky, kx2, color);
642
if (displaymode != 2)
643
PlotvLine(y, scrheight-x, scrheight-x2-1, color);
645
PlotvLine(scrwidth-y-1, x, x2+1, color);
648
void FrameBufferWinCE::PlothLine(uInt32 x, uInt32 y, uInt32 x2, OverlayColor color)
650
if (!myDstScreen) return;
651
if (x>x2) { x2 ^= x; x ^= x2; x2 ^= x;} //lazy swap
652
uInt8 *d = myDstScreen + y * scrlinestep + x * scrpixelstep;
653
uInt16 col = guipal[((int) color) - 256];
654
for (;x < x2; x++, *((uInt16 *)d) = col, d += scrpixelstep);
657
void FrameBufferWinCE::vLine(uInt32 x, uInt32 y, uInt32 y2, OverlayColor color)
659
if (devres == SM_LOW)
661
int kx = x >> 1; int ky = y; int ky2 = y2;
662
if (kx<0) kx=0; if (ky<0) ky=0; if (kx>scrwidth-1) return; if (ky>scrheight-1) ky=scrheight-1; if (ky2>scrheight-1) ky2=scrheight-1;
663
PlotvLine(kx, ky, ky2, color);
666
if (displaymode != 2)
667
PlothLine(y, scrheight-x-1, y2, color);
669
PlothLine(scrwidth-y, x, scrwidth-y2, color);
673
void FrameBufferWinCE::PlotvLine(uInt32 x, uInt32 y, uInt32 y2, OverlayColor color)
675
if (y>y2) { y2 ^= y; y ^= y2; y2 ^= y;} //lazy swap
676
if (!myDstScreen) return;
677
uInt8 *d = myDstScreen + y * scrlinestep + x * scrpixelstep;
678
uInt16 col = guipal[((int) color) - 256];
679
for (;y < y2; y++, *((uInt16 *)d) = col, d += scrlinestep);
682
void FrameBufferWinCE::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, OverlayColor color)
684
if (devres == SM_LOW)
686
int kx = x >> 1; int ky = y; int kw = (w >> 1); int kh = h;
687
if (ky>scrheight-1) return; if (kx>scrwidth-1) return;
688
if (kx<0) kx=0; if (ky<0) ky=0;if (kw<0) kw=0; if (kh<0) kh=0;
689
if (kx+kw>scrwidth-1) kw=scrwidth-kx-1; if (ky+kh>scrheight-1) kh=scrheight-ky-1;
690
PlotfillRect(kx, ky, kw, kh, color);
694
if (x>scrheight) return; if (y>scrwidth) return;
695
if (x+w>scrheight) w=scrheight-x; if (y+h>scrwidth) h=scrwidth-y;
696
if (displaymode != 2)
697
PlotfillRect(y, scrheight-x-w, h-1, w-1, color);
699
PlotfillRect(scrwidth-y-h, x, h-1, w-1, color);
704
void FrameBufferWinCE::PlotfillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, OverlayColor color)
706
if (!myDstScreen) return;
707
uInt8 *d = myDstScreen + y * scrlinestep + x * scrpixelstep;
708
uInt16 col = guipal[((int) color) - 256];
709
uInt32 stride = (scrwidth - w - 1) * scrpixelstep;
710
for (h++; h != 0; h--, d += stride)
711
for (int w2=w; w2>=0; w2--, *((uInt16 *)d) = col, d += scrpixelstep);
714
void FrameBufferWinCE::drawBitmap(uInt32* bitmap, Int32 x, Int32 y, OverlayColor color, Int32 h)
719
void FrameBufferWinCE::translateCoords(Int32* x, Int32* y)
723
if ((displaymode == 1) || (displaymode==0 && myOSystem->eventHandler().state() != 1))
729
else if (displaymode == 2)
739
void FrameBufferWinCE::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
741
static bool initflag = false;
743
if (myOSystem->eventHandler().state() == 3)
746
if (myOSystem->eventHandler().state()==1 && initflag)
748
// TODO: optimize here
749
theRedrawTIAIndicator = true;
755
uInt32 FrameBufferWinCE::lineDim()