~ubuntu-branches/debian/squeeze/stella/squeeze

« back to all changes in this revision

Viewing changes to src/common/FrameBufferSoft.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Kitt
  • Date: 2010-07-12 23:49:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100712234936-juawrr3etzhr2qpv
Tags: 3.1.2-1
* New maintainer (closes: #532039).
* New upstream version (closes: #461121):
  - includes launcher (closes: #396058).
* Fix the reference to the X Window System in the description (closes:
  #411815).
* Move to main, DFSG-free ROMs are available (see README.Debian).
* Enhance the package description.
* Drop the libslang2-dev dependency (closes: #560274).
* Remove the Encoding entry from stella.desktop.
* Avoid ignoring errors when cleaning.
* Add ${misc:Depends} to the package dependencies.
* Provide a doc-base file to install the documentation using doc-base.
* Switch to debhelper 7 with a simplified rules file.
* Use autotools-dev to provide updated configuration files.
* Update to Standards-Version 3.9.0:
  - Move to menu section Applications/Emulators.
  - Move the homepage declaration.
* Re-write the manpage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
//  SS  SS   tt   ee      ll   ll  aa  aa
9
9
//   SSSS     ttt  eeeee llll llll  aaaaa
10
10
//
11
 
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
 
11
// Copyright (c) 1995-2010 by Bradford W. Mott, Stephen Anthony
 
12
// and the Stella Team
12
13
//
13
 
// See the file "license" for information on usage and redistribution of
 
14
// See the file "License.txt" for information on usage and redistribution of
14
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
15
16
//
16
 
// $Id: FrameBufferSoft.cxx,v 1.78 2008/03/24 00:02:16 stephena Exp $
 
17
// $Id: FrameBufferSoft.cxx 2029 2010-04-29 12:46:07Z stephena $
17
18
//============================================================================
18
19
 
19
20
#include <sstream>
23
24
 
24
25
#include "Console.hxx"
25
26
#include "Font.hxx"
26
 
#include "MediaSrc.hxx"
27
27
#include "OSystem.hxx"
28
28
#include "RectList.hxx"
29
29
#include "Settings.hxx"
30
 
#include "Surface.hxx"
 
30
#include "TIA.hxx"
31
31
 
32
32
#include "FrameBufferSoft.hxx"
33
33
 
34
34
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
35
35
FrameBufferSoft::FrameBufferSoft(OSystem* osystem)
36
36
  : FrameBuffer(osystem),
37
 
    myZoomLevel(1),
38
37
    myRenderType(kSoftZoom_16),
39
 
    myDirtyFlag(false),
 
38
    myTiaDirty(false),
40
39
    myInUIMode(false),
41
40
    myRectList(NULL)
42
41
{
49
48
}
50
49
 
51
50
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
52
 
bool FrameBufferSoft::initSubsystem(VideoMode mode)
 
51
bool FrameBufferSoft::initSubsystem(VideoMode& mode)
53
52
{
54
53
  // Set up the rectangle list to be used in the dirty update
55
54
  delete myRectList;
57
56
 
58
57
  if(!myRectList)
59
58
  {
60
 
    cerr << "ERROR: Unable to get memory for SDL rects" << endl;
 
59
    myOSystem->logMessage("ERROR: Unable to get memory for SDL rects\n", 0);
61
60
    return false;
62
61
  }
63
62
 
86
85
}
87
86
 
88
87
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89
 
bool FrameBufferSoft::setVidMode(VideoMode mode)
 
88
bool FrameBufferSoft::setVidMode(VideoMode& mode)
90
89
{
91
 
  myScreenDim.x = myScreenDim.y = 0;
92
 
  myScreenDim.w = mode.screen_w;
93
 
  myScreenDim.h = mode.screen_h;
94
 
 
95
 
  myImageDim.x = mode.image_x;
96
 
  myImageDim.y = mode.image_y;
97
 
  myImageDim.w = mode.image_w;
98
 
  myImageDim.h = mode.image_h;
99
 
 
100
 
  myZoomLevel = mode.zoom;
101
 
 
102
90
  // Make sure to clear the screen
103
91
  if(myScreen)
104
92
  {
105
93
    SDL_FillRect(myScreen, NULL, 0);
106
94
    SDL_UpdateRect(myScreen, 0, 0, 0, 0);
107
95
  }
108
 
  myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
 
96
  myScreen = SDL_SetVideoMode(mode.screen_w, mode.screen_h, 0, mySDLFlags);
109
97
  if(myScreen == NULL)
110
98
  {
111
 
    cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
 
99
    ostringstream buf;
 
100
    buf << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
 
101
    myOSystem->logMessage(buf.str(), 0);
112
102
    return false;
113
103
  }
114
104
  myFormat = myScreen->format;
115
105
  myBytesPerPixel = myFormat->BytesPerPixel;
116
106
 
117
 
  // Make sure drawMediaSource() knows which renderer to use
118
 
  stateChanged(myOSystem->eventHandler().state());
119
 
  myBaseOffset = myImageDim.y * myPitch + myImageDim.x;
 
107
  // Make sure the flags represent the current screen state
 
108
  mySDLFlags = myScreen->flags;
 
109
 
 
110
  // Make sure drawTIA() knows which renderer to use
 
111
  switch(myBytesPerPixel)
 
112
  {
 
113
    case 2:  // 16-bit
 
114
      myPitch = myScreen->pitch >> 1;
 
115
      myRenderType = myUsePhosphor ? kPhosphor_16 : kSoftZoom_16;
 
116
      break;
 
117
    case 3:  // 24-bit
 
118
      myPitch = myScreen->pitch;
 
119
      myRenderType = myUsePhosphor ? kPhosphor_24 : kSoftZoom_24;
 
120
      break;
 
121
    case 4:  // 32-bit
 
122
      myPitch = myScreen->pitch >> 2;
 
123
      myRenderType = myUsePhosphor ? kPhosphor_32 : kSoftZoom_32;
 
124
      break;
 
125
  }
 
126
  myBaseOffset = mode.image_y * myPitch + mode.image_x;
 
127
 
 
128
  // If software mode can open the given screen, it will always be in the
 
129
  // requested format, or not at all; we only update mode when the screen
 
130
  // is successfully created
 
131
  mode.screen_w = myScreen->w;
 
132
  mode.screen_h = myScreen->h;
 
133
  myZoomLevel = mode.gfxmode.zoom;
 
134
// FIXME - look at gfxmode directly
120
135
 
121
136
  // Erase old rects, since they've probably been scaled for
122
137
  // a different sized screen
123
138
  myRectList->start();
124
139
 
 
140
  // Any previously allocated surfaces have probably changed as well,
 
141
  // so we should refresh them
 
142
  resetSurfaces();
 
143
 
125
144
  return true;
126
145
}
127
146
 
128
147
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129
 
void FrameBufferSoft::drawMediaSource()
130
 
{
131
 
  MediaSource& mediasrc = myOSystem->console().mediaSource();
132
 
 
133
 
  uInt8* currentFrame   = mediasrc.currentFrameBuffer();
134
 
  uInt8* previousFrame  = mediasrc.previousFrameBuffer();
135
 
 
136
 
  uInt32 width  = mediasrc.width();
137
 
  uInt32 height = mediasrc.height();
 
148
void FrameBufferSoft::invalidate()
 
149
{
 
150
  if(myScreen)
 
151
    SDL_FillRect(myScreen, NULL, 0);
 
152
}
 
153
 
 
154
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
155
void FrameBufferSoft::drawTIA(bool fullRedraw)
 
156
{
 
157
  const TIA& tia = myOSystem->console().tia();
 
158
 
 
159
  uInt8* currentFrame   = tia.currentFrameBuffer();
 
160
  uInt8* previousFrame  = tia.previousFrameBuffer();
 
161
 
 
162
  uInt32 width  = tia.width();
 
163
  uInt32 height = tia.height();
138
164
 
139
165
  switch(myRenderType)
140
166
  {
158
184
            uInt8 v = currentFrame[bufofs];
159
185
            uInt8 w = previousFrame[bufofs];
160
186
 
161
 
            if(v != w || theRedrawTIAIndicator)
 
187
            if(v != w || fullRedraw)
162
188
            {
163
189
              while(xstride--)
164
190
              {
165
191
                buffer[pos++] = (uInt16) myDefPalette[v];
166
192
                buffer[pos++] = (uInt16) myDefPalette[v];
167
193
              }
168
 
              myDirtyFlag = true;
 
194
              myTiaDirty = true;
169
195
            }
170
196
            else
171
197
              pos += xstride + xstride;
198
224
            uInt8 v = currentFrame[bufofs];
199
225
            uInt8 w = previousFrame[bufofs];
200
226
 
201
 
            if(v != w || theRedrawTIAIndicator)
 
227
            if(v != w || fullRedraw)
202
228
            {
203
 
              uInt32 pixel = myDefPalette[v];
204
 
              uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift;
205
 
              uInt8 g = (pixel & myFormat->Gmask) >> myFormat->Gshift;
206
 
              uInt8 b = (pixel & myFormat->Bmask) >> myFormat->Bshift;
 
229
              uInt8 a = myDefPalette24[v][0],
 
230
                    b = myDefPalette24[v][1],
 
231
                    c = myDefPalette24[v][2];
207
232
 
208
233
              while(xstride--)
209
234
              {
210
 
                buffer[pos++] = r;  buffer[pos++] = g;  buffer[pos++] = b;
211
 
                buffer[pos++] = r;  buffer[pos++] = g;  buffer[pos++] = b;
 
235
                buffer[pos++] = a;  buffer[pos++] = b;  buffer[pos++] = c;
 
236
                buffer[pos++] = a;  buffer[pos++] = b;  buffer[pos++] = c;
212
237
              }
213
 
              myDirtyFlag = true;
 
238
              myTiaDirty = true;
214
239
            }
215
 
            else  // try to eliminate multply whereever possible
 
240
            else  // try to eliminate multiply whereever possible
216
241
              pos += xstride + xstride + xstride + xstride + xstride + xstride;
217
242
          }
218
243
          screenofsY += myPitch;
243
268
            uInt8 v = currentFrame[bufofs];
244
269
            uInt8 w = previousFrame[bufofs];
245
270
 
246
 
            if(v != w || theRedrawTIAIndicator)
 
271
            if(v != w || fullRedraw)
247
272
            {
248
273
              while(xstride--)
249
274
              {
250
275
                buffer[pos++] = (uInt32) myDefPalette[v];
251
276
                buffer[pos++] = (uInt32) myDefPalette[v];
252
277
              }
253
 
              myDirtyFlag = true;
 
278
              myTiaDirty = true;
254
279
            }
255
280
            else
256
281
              pos += xstride + xstride;
294
319
        bufofsY += width;
295
320
      }
296
321
      SDL_UnlockSurface(myScreen);
297
 
      myDirtyFlag = true;
 
322
      myTiaDirty = true;
298
323
      break;  // kPhosphor_16
299
324
    }
300
325
 
317
342
 
318
343
            uInt8 v = currentFrame[bufofs];
319
344
            uInt8 w = previousFrame[bufofs];
 
345
            uInt8 a, b, c;
320
346
            uInt32 pixel = myAvgPalette[v][w];
321
 
            uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift;
322
 
            uInt8 g = (pixel & myFormat->Gmask) >> myFormat->Gshift;
323
 
            uInt8 b = (pixel & myFormat->Bmask) >> myFormat->Bshift;
 
347
            if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
 
348
            {
 
349
              a = (pixel & myFormat->Bmask) >> myFormat->Bshift;
 
350
              b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
 
351
              c = (pixel & myFormat->Rmask) >> myFormat->Rshift;
 
352
            }
 
353
            else
 
354
            {
 
355
              a = (pixel & myFormat->Rmask) >> myFormat->Rshift;
 
356
              b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
 
357
              c = (pixel & myFormat->Bmask) >> myFormat->Bshift;
 
358
            }
324
359
 
325
360
            while(xstride--)
326
361
            {
327
 
              buffer[pos++] = r;  buffer[pos++] = g;  buffer[pos++] = b;
328
 
              buffer[pos++] = r;  buffer[pos++] = g;  buffer[pos++] = b;
 
362
              buffer[pos++] = a;  buffer[pos++] = b;  buffer[pos++] = c;
 
363
              buffer[pos++] = a;  buffer[pos++] = b;  buffer[pos++] = c;
329
364
            }
330
365
          }
331
366
          screenofsY += myPitch;
333
368
        bufofsY += width;
334
369
      }
335
370
      SDL_UnlockSurface(myScreen);
336
 
      myDirtyFlag = true;
 
371
      myTiaDirty = true;
337
372
      break;  // kPhosphor_24
338
373
    }
339
374
 
368
403
        bufofsY += width;
369
404
      }
370
405
      SDL_UnlockSurface(myScreen);
371
 
      myDirtyFlag = true;
 
406
      myTiaDirty = true;
372
407
      break;  // kPhosphor_32
373
408
    }
374
409
  }
375
410
}
376
411
 
377
412
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
378
 
void FrameBufferSoft::preFrameUpdate()
379
 
{
380
 
}
381
 
 
382
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
383
413
void FrameBufferSoft::postFrameUpdate()
384
414
{
385
 
/*
386
 
cerr << "FrameBufferSoft::postFrameUpdate()" << endl
387
 
        << "  myInUIMode:             " << myInUIMode << endl
388
 
        << "  myRectList->numRects(): " << myRectList->numRects() << endl
389
 
        << "  myDirtyFlag:            " << myDirtyFlag << endl
390
 
        << endl;
391
 
*/
392
 
  if(myInUIMode && myRectList->numRects() > 0)
393
 
  {
 
415
  if(myTiaDirty && !myInUIMode)
 
416
  {
 
417
    SDL_UpdateRect(myScreen, 0, 0, 0, 0);
 
418
    myTiaDirty = false;
 
419
  }
 
420
  else if(myRectList->numRects() > 0)
 
421
  {
 
422
//myRectList->print(myScreen->w, myScreen->h);
394
423
    SDL_UpdateRects(myScreen, myRectList->numRects(), myRectList->rects());
395
424
  }
396
 
  else if(myDirtyFlag || myRectList->numRects() > 0)
 
425
  myRectList->start();
 
426
}
 
427
 
 
428
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
429
void FrameBufferSoft::enablePhosphor(bool enable, int blend)
 
430
{
 
431
  myUsePhosphor   = enable;
 
432
  myPhosphorBlend = blend;
 
433
 
 
434
  // Make sure drawMediaSource() knows which renderer to use
 
435
  switch(myBytesPerPixel)
397
436
  {
398
 
    SDL_Flip(myScreen);
399
 
    myDirtyFlag = false;
 
437
    case 2:  // 16-bit
 
438
      myRenderType = myUsePhosphor ? kPhosphor_16 : kSoftZoom_16;
 
439
      break;
 
440
    case 3:  // 24-bit
 
441
      myRenderType = myUsePhosphor ? kPhosphor_24 : kSoftZoom_24;
 
442
      break;
 
443
    case 4:  // 32-bit
 
444
      myRenderType = myUsePhosphor ? kPhosphor_32 : kSoftZoom_32;
 
445
      break;
400
446
  }
401
 
  myRectList->start();
 
447
  myRedrawEntireFrame = true;
 
448
}
 
449
 
 
450
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
451
FBSurface* FrameBufferSoft::createSurface(int w, int h, bool isBase) const
 
452
{
 
453
  // For some unknown reason, OSX in software fullscreen mode doesn't like
 
454
  // to use the underlying surface directly
 
455
  // I suspect it's an SDL compatibility thing, since I get errors
 
456
  // referencing Quartz vs. QuickDraw, and then a program crash
 
457
  // For now, we'll just always use entire surfaces for OSX
 
458
  // I don't think this will have much effect, since OpenGL mode is the
 
459
  // preferred method in OSX (basically, all OSX installations have OpenGL
 
460
  // support)
 
461
#ifdef MAC_OSX
 
462
  isBase = false;
 
463
#endif
 
464
 
 
465
  SDL_Surface* surface = isBase ? myScreen :
 
466
      SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, myFormat->BitsPerPixel,
 
467
                           myFormat->Rmask, myFormat->Gmask, myFormat->Bmask,
 
468
                           myFormat->Amask);
 
469
 
 
470
  return new FBSurfaceSoft(*this, surface, w, h, isBase);
402
471
}
403
472
 
404
473
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
411
480
  uInt8 *p, r, g, b;
412
481
 
413
482
  // Row will be offset by the amount the actual image is shifted down
414
 
  row += myImageDim.y;
 
483
  const GUI::Rect& image = imageRect();
 
484
  row += image.y();
415
485
  for(Int32 x = 0; x < myScreen->w; ++x)
416
486
  {
417
487
    p = (Uint8*) ((uInt8*)myScreen->pixels +              // Start at top of RAM
418
488
                 (row * myScreen->pitch) +                // Go down 'row' lines
419
 
                 ((x + myImageDim.x) * myBytesPerPixel)); // Go in 'x' pixels
 
489
                 ((x + image.x()) * myBytesPerPixel));    // Go in 'x' pixels
420
490
 
421
491
    switch(myBytesPerPixel)
422
492
    {
450
520
  SDL_UnlockSurface(myScreen);
451
521
}
452
522
 
453
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
454
 
void FrameBufferSoft::toggleFilter()
455
 
{
456
 
  // No filter added yet ...
457
 
}
458
 
 
459
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
460
 
void FrameBufferSoft::hLine(uInt32 x, uInt32 y, uInt32 x2, int color)
461
 
{
462
 
  SDL_Rect tmp;
463
 
 
 
523
 
 
524
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
525
//  FBSurfaceSoft implementation follows ...
 
526
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
527
 
 
528
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
529
FBSurfaceSoft::FBSurfaceSoft(const FrameBufferSoft& buffer, SDL_Surface* surface,
 
530
                             uInt32 w, uInt32 h, bool isBase)
 
531
  : myFB(buffer),
 
532
    mySurface(surface),
 
533
    myWidth(w),
 
534
    myHeight(h),
 
535
    myIsBaseSurface(isBase),
 
536
    mySurfaceIsDirty(false),
 
537
    myPitch(0),
 
538
    myXOrig(0),
 
539
    myYOrig(0),
 
540
    myXOffset(0),
 
541
    myYOffset(0)
 
542
{
 
543
  reload();
 
544
}
 
545
 
 
546
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
547
FBSurfaceSoft::~FBSurfaceSoft()
 
548
{
 
549
  if(!myIsBaseSurface)
 
550
    SDL_FreeSurface(mySurface);
 
551
}
 
552
 
 
553
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
554
void FBSurfaceSoft::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color)
 
555
{
464
556
  // Horizontal line
465
 
  tmp.x = myImageDim.x + x * myZoomLevel;
466
 
  tmp.y = myImageDim.y + y * myZoomLevel;
467
 
  tmp.w = (x2 - x + 1) * myZoomLevel;
468
 
  tmp.h = myZoomLevel;
469
 
  SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
 
557
  SDL_Rect tmp;
 
558
  tmp.x = x + myXOffset;
 
559
  tmp.y = y + myYOffset;
 
560
  tmp.w = x2 - x + 1;
 
561
  tmp.h = 1;
 
562
  SDL_FillRect(mySurface, &tmp, myFB.myDefPalette[color]);
470
563
}
471
564
 
472
565
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
473
 
void FrameBufferSoft::vLine(uInt32 x, uInt32 y, uInt32 y2, int color)
 
566
void FBSurfaceSoft::vLine(uInt32 x, uInt32 y, uInt32 y2, uInt32 color)
474
567
{
475
 
  SDL_Rect tmp;
476
 
 
477
568
  // Vertical line
478
 
  tmp.x = myImageDim.x + x * myZoomLevel;
479
 
  tmp.y = myImageDim.y + y * myZoomLevel;
480
 
  tmp.w = myZoomLevel;
481
 
  tmp.h = (y2 - y + 1) * myZoomLevel;
482
 
  SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
 
569
  SDL_Rect tmp;
 
570
  tmp.x = x + myXOffset;
 
571
  tmp.y = y + myYOffset;
 
572
  tmp.w = 1;
 
573
  tmp.h = y2 - y + 1;
 
574
  SDL_FillRect(mySurface, &tmp, myFB.myDefPalette[color]);
483
575
}
484
576
 
485
577
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
486
 
void FrameBufferSoft::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, int color)
 
578
void FBSurfaceSoft::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 color)
487
579
{
488
 
  SDL_Rect tmp;
489
 
 
490
580
  // Fill the rectangle
491
 
  tmp.x = myImageDim.x + x * myZoomLevel;
492
 
  tmp.y = myImageDim.y + y * myZoomLevel;
493
 
  tmp.w = w * myZoomLevel;
494
 
  tmp.h = h * myZoomLevel;
495
 
  SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
 
581
  SDL_Rect tmp;
 
582
  tmp.x = x + myXOffset;
 
583
  tmp.y = y + myYOffset;
 
584
  tmp.w = w;
 
585
  tmp.h = h;
 
586
  SDL_FillRect(mySurface, &tmp, myFB.myDefPalette[color]);
496
587
}
497
588
 
498
589
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
499
 
void FrameBufferSoft::drawChar(const GUI::Font* font, uInt8 chr,
500
 
                               uInt32 xorig, uInt32 yorig, int color)
 
590
void FBSurfaceSoft::drawChar(const GUI::Font* font, uInt8 chr,
 
591
                             uInt32 tx, uInt32 ty, uInt32 color)
501
592
{
502
593
  const FontDesc& desc = font->desc();
503
594
 
507
598
    if (chr == ' ') return;
508
599
    chr = desc.defaultchar;
509
600
  }
510
 
 
511
 
  const Int32 w = font->getCharWidth(chr);
512
 
  const Int32 h = font->getFontHeight();
513
601
  chr -= desc.firstchar;
514
 
  const uInt32* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * h));
515
 
 
516
 
  // Scale the origins to the current zoom
517
 
  xorig *= myZoomLevel;
518
 
  yorig *= myZoomLevel;
519
 
 
520
 
  SDL_LockSurface(myScreen);
521
 
 
522
 
  int screenofsY = 0;
523
 
  switch(myBytesPerPixel)
 
602
 
 
603
  // Get the bounding box of the character
 
604
  int bbw, bbh, bbx, bby;
 
605
  if(!desc.bbx)
 
606
  {
 
607
    bbw = desc.fbbw;
 
608
    bbh = desc.fbbh;
 
609
    bbx = desc.fbbx;
 
610
    bby = desc.fbby;
 
611
  }
 
612
  else
 
613
  {
 
614
    bbw = desc.bbx[chr].w;
 
615
    bbh = desc.bbx[chr].h;
 
616
    bbx = desc.bbx[chr].x;
 
617
    bby = desc.bbx[chr].y;
 
618
  }
 
619
 
 
620
  const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * desc.fbbh));
 
621
  switch(myFB.myBytesPerPixel)
524
622
  {
525
623
    case 2:
526
624
    {
527
625
      // Get buffer position where upper-left pixel of the character will be drawn
528
 
      uInt16* buffer = (uInt16*) myScreen->pixels + myBaseOffset + yorig * myPitch + xorig;
529
 
      for(int y = h; y; --y)
 
626
      uInt16* buffer = (uInt16*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
 
627
 
 
628
      for(int y = 0; y < bbh; y++)
530
629
      {
531
 
        const uInt32 fontbuf = *tmp++;
532
 
        int ystride = myZoomLevel;
533
 
        while(ystride--)
534
 
        {
535
 
          if(fontbuf)
536
 
          {
537
 
            uInt32 mask = 0x80000000;
538
 
            int pos = screenofsY;
539
 
            for(int x = 0; x < w; x++, mask >>= 1)
540
 
            {
541
 
              int xstride = myZoomLevel;
542
 
              if((fontbuf & mask) != 0)
543
 
                while(xstride--)
544
 
                  buffer[pos++] = myDefPalette[color];
545
 
              else
546
 
                pos += xstride;
547
 
            }
548
 
          }
549
 
          screenofsY += myPitch;
550
 
        }
 
630
        const uInt16 ptr = *tmp++;
 
631
        uInt16 mask = 0x8000;
 
632
 
 
633
        for(int x = 0; x < bbw; x++, mask >>= 1)
 
634
          if(ptr & mask)
 
635
            buffer[x] = (uInt16) myFB.myDefPalette[color];
 
636
 
 
637
        buffer += myPitch;
551
638
      }
552
639
      break;
553
640
    }
554
641
    case 3:
555
642
    {
556
643
      // Get buffer position where upper-left pixel of the character will be drawn
557
 
      uInt8* buffer = (uInt8*) myScreen->pixels + myBaseOffset + yorig * myPitch + xorig;
558
 
      uInt32 pixel = myDefPalette[color];
559
 
      uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift;
560
 
      uInt8 g = (pixel & myFormat->Gmask) >> myFormat->Gshift;
561
 
      uInt8 b = (pixel & myFormat->Bmask) >> myFormat->Bshift;
562
 
 
563
 
      for(int y = h; y; --y)
 
644
      uInt8* buffer = (uInt8*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
 
645
 
 
646
      uInt8 a = myFB.myDefPalette24[color][0],
 
647
            b = myFB.myDefPalette24[color][1],
 
648
            c = myFB.myDefPalette24[color][2];
 
649
 
 
650
      for(int y = 0; y < bbh; y++, buffer += myPitch)
564
651
      {
565
 
        const uInt32 fontbuf = *tmp++;
566
 
        int ystride = myZoomLevel;
567
 
        while(ystride--)
 
652
        const uInt16 ptr = *tmp++;
 
653
        uInt16 mask = 0x8000;
 
654
 
 
655
        uInt8* buf_ptr = buffer;
 
656
        for(int x = 0; x < bbw; x++, mask >>= 1)
568
657
        {
569
 
          if(fontbuf)
 
658
          if(ptr & mask)
570
659
          {
571
 
            uInt32 mask = 0x80000000;
572
 
            int pos = screenofsY;
573
 
            for(int x = 0; x < w; x++, mask >>= 1)
574
 
            {
575
 
              int xstride = myZoomLevel;
576
 
              if((fontbuf & mask) != 0)
577
 
              {
578
 
                while(xstride--)
579
 
                {
580
 
                  buffer[pos++] = r;  buffer[pos++] = g;  buffer[pos++] = b;
581
 
                }
582
 
              }
583
 
              else
584
 
                pos += xstride + xstride + xstride;
585
 
            }
 
660
            *buf_ptr++ = a;  *buf_ptr++ = b;  *buf_ptr++ = c;
586
661
          }
587
 
          screenofsY += myPitch;
 
662
          else
 
663
            buf_ptr += 3;
588
664
        }
589
665
      }
590
666
      break;
592
668
    case 4:
593
669
    {
594
670
      // Get buffer position where upper-left pixel of the character will be drawn
595
 
      uInt32* buffer = (uInt32*) myScreen->pixels + myBaseOffset + yorig * myPitch + xorig;
596
 
      for(int y = h; y; --y)
 
671
      uInt32* buffer = (uInt32*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
 
672
      for(int y = 0; y < bbh; y++, buffer += myPitch)
597
673
      {
598
 
        const uInt32 fontbuf = *tmp++;
599
 
        int ystride = myZoomLevel;
600
 
        while(ystride--)
601
 
        {
602
 
          if(fontbuf)
603
 
          {
604
 
            uInt32 mask = 0x80000000;
605
 
            int pos = screenofsY;
606
 
            for(int x = 0; x < w; x++, mask >>= 1)
607
 
            {
608
 
              int xstride = myZoomLevel;
609
 
              if((fontbuf & mask) != 0)
610
 
                while(xstride--)
611
 
                  buffer[pos++] = myDefPalette[color];
612
 
              else
613
 
                pos += xstride;
614
 
            }
615
 
          }
616
 
          screenofsY += myPitch;
617
 
        }
 
674
        const uInt16 ptr = *tmp++;
 
675
        uInt16 mask = 0x8000;
 
676
 
 
677
        for(int x = 0; x < bbw; x++, mask >>= 1)
 
678
          if(ptr & mask)
 
679
            buffer[x] = (uInt32) myFB.myDefPalette[color];
618
680
      }
619
681
      break;
620
682
    }
621
683
    default:
622
684
      break;
623
685
  }
624
 
  SDL_UnlockSurface(myScreen);
625
686
}
626
687
 
627
688
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
628
 
void FrameBufferSoft::drawBitmap(uInt32* bitmap, Int32 xorig, Int32 yorig,
629
 
                                 int color, Int32 h)
 
689
void FBSurfaceSoft::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
 
690
                               uInt32 color, uInt32 h)
630
691
{
631
692
  SDL_Rect rect;
632
 
  for(int y = 0; y < h; y++)
 
693
  rect.y = ty + myYOffset;
 
694
  rect.w = rect.h = 1;
 
695
  for(uInt32 y = 0; y < h; y++)
633
696
  {
 
697
    rect.x = tx + myXOffset;
634
698
    uInt32 mask = 0xF0000000;
635
 
 
636
 
    for(int x = 0; x < 8; x++, mask >>= 4)
 
699
    for(uInt32 x = 0; x < 8; x++, mask >>= 4)
637
700
    {
638
701
      if(bitmap[y] & mask)
639
 
      {
640
 
        rect.x = myImageDim.x + (x + xorig) * myZoomLevel;
641
 
        rect.y = myImageDim.y + (y + yorig) * myZoomLevel;
642
 
        rect.w = rect.h = myZoomLevel;
643
 
        SDL_FillRect(myScreen, &rect, myDefPalette[color]);
644
 
      }
 
702
        SDL_FillRect(mySurface, &rect, myFB.myDefPalette[color]);
 
703
 
 
704
      rect.x++;
645
705
    }
646
 
  }
647
 
}
648
 
 
649
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
650
 
void FrameBufferSoft::drawSurface(const GUI::Surface* surface, Int32 x, Int32 y)
651
 
{
 
706
    rect.y++;
 
707
  }
 
708
}
 
709
 
 
710
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
711
void FBSurfaceSoft::drawPixels(uInt32* data, uInt32 tx, uInt32 ty,
 
712
                               uInt32 numpixels)
 
713
{
 
714
  SDL_Rect rect;
 
715
  rect.x = tx + myXOffset;
 
716
  rect.y = ty + myYOffset;
 
717
  rect.w = rect.h = 1;
 
718
  for(uInt32 x = 0; x < numpixels; ++x)
 
719
  {
 
720
    SDL_FillRect(mySurface, &rect, data[x]);
 
721
    rect.x++;
 
722
  }
 
723
}
 
724
 
 
725
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
726
void FBSurfaceSoft::drawSurface(const FBSurface* surface, uInt32 tx, uInt32 ty)
 
727
{
 
728
  const FBSurfaceSoft* s = (const FBSurfaceSoft*) surface;
 
729
 
652
730
  SDL_Rect dstrect;
653
 
  dstrect.x = x * myZoomLevel + myImageDim.x;
654
 
  dstrect.y = y * myZoomLevel + myImageDim.y;
 
731
  dstrect.x = tx + myXOffset;
 
732
  dstrect.y = ty + myYOffset;
655
733
  SDL_Rect srcrect;
656
734
  srcrect.x = 0;
657
735
  srcrect.y = 0;
658
 
  srcrect.w = surface->myClipWidth * myZoomLevel;
659
 
  srcrect.h = surface->myClipHeight * myZoomLevel;
660
 
 
661
 
  SDL_BlitSurface(surface->myData, &srcrect, myScreen, &dstrect);
662
 
}
663
 
 
664
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
665
 
void FrameBufferSoft::bytesToSurface(GUI::Surface* surface, int row,
666
 
                                     uInt8* data, int rowbytes) const
667
 
{
668
 
  // Calculate a scanline of zoomed surface data
669
 
  SDL_Surface* s = surface->myData;
670
 
  SDL_Rect rect;
671
 
  rect.x = 0;
672
 
  rect.y = row * myZoomLevel;
673
 
  for(int c = 0; c < rowbytes; c += 3)
674
 
  {
675
 
    uInt32 pixel = SDL_MapRGB(s->format, data[c], data[c+1], data[c+2]);
676
 
    rect.x += myZoomLevel;
677
 
    rect.w = rect.h = myZoomLevel;
678
 
    SDL_FillRect(surface->myData, &rect, pixel);
679
 
  }
680
 
}
681
 
 
682
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
683
 
void FrameBufferSoft::translateCoords(Int32& x, Int32& y) const
684
 
{
685
 
  x = (x - myImageDim.x) / myZoomLevel;
686
 
  y = (y - myImageDim.y) / myZoomLevel;
687
 
}
688
 
 
689
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
690
 
void FrameBufferSoft::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
691
 
{
692
 
  // Add a dirty rect to the UI rectangle list
693
 
  // TODO - intelligent merging of rectangles, to avoid overlap
694
 
  SDL_Rect temp;
695
 
#if 1
696
 
  temp.x = myImageDim.x + x * myZoomLevel;
697
 
  temp.y = myImageDim.y + y * myZoomLevel;
698
 
  temp.w = w * myZoomLevel;
699
 
  temp.h = h * myZoomLevel;
700
 
#else
701
 
  temp.x = 0;
702
 
  temp.y = 0;
703
 
  temp.w = myScreenDim.w;
704
 
  temp.h = myScreenDim.h;
705
 
#endif
706
 
  myRectList->add(&temp);
707
 
 
708
 
//  cerr << "addDirtyRect():  "
709
 
//       << "x=" << temp.x << ", y=" << temp.y << ", w=" << temp.w << ", h=" << temp.h << endl;
710
 
}
711
 
 
712
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
713
 
void FrameBufferSoft::enablePhosphor(bool enable, int blend)
714
 
{
715
 
  myUsePhosphor   = enable;
716
 
  myPhosphorBlend = blend;
717
 
 
718
 
  stateChanged(myOSystem->eventHandler().state());
719
 
}
720
 
 
721
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
722
 
void FrameBufferSoft::stateChanged(EventHandler::State state)
723
 
{
724
 
  if(!myScreen)
725
 
    return;
726
 
 
727
 
  myInUIMode = (state == EventHandler::S_LAUNCHER ||
728
 
                state == EventHandler::S_DEBUGGER);
729
 
 
730
 
  // Make sure drawMediaSource() knows which renderer to use
731
 
  switch(myBytesPerPixel)
 
736
  srcrect.w = s->myWidth;
 
737
  srcrect.h = s->myHeight;
 
738
 
 
739
  SDL_BlitSurface(s->mySurface, &srcrect, mySurface, &dstrect);
 
740
}
 
741
 
 
742
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
743
void FBSurfaceSoft::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
 
744
{
 
745
//cerr << " -> addDirtyRect: x = " << x << ", y = " << y << ", w = " << w << ", h = " << h << endl;
 
746
 
 
747
  // Base surfaces use dirty-rectangle updates, since they can be quite
 
748
  // large, and updating the entire surface each frame would be too slow
 
749
  // Non-base surfaces are usually smaller, and can be updated entirely
 
750
  if(myIsBaseSurface)
 
751
  {
 
752
    // Add a dirty rect to the UI rectangle list
 
753
    // TODO - intelligent merging of rectangles, to avoid overlap
 
754
    SDL_Rect temp;
 
755
    temp.x = x + myXOrig;  temp.y = y + myYOrig;  temp.w = w;  temp.h = h;
 
756
    myFB.myRectList->add(&temp);
 
757
  }
 
758
  else
 
759
  {
 
760
    SDL_Rect temp;
 
761
    temp.x = myXOrig;  temp.y = myYOrig;  temp.w = myWidth;  temp.h = myHeight;
 
762
    myFB.myRectList->add(&temp);
 
763
 
 
764
    // Indicate that at least one dirty rect has been added
 
765
    // This is an optimization for the update() method
 
766
    mySurfaceIsDirty = true;
 
767
  }
 
768
}
 
769
 
 
770
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
771
void FBSurfaceSoft::getPos(uInt32& x, uInt32& y) const
 
772
{
 
773
  // Return the origin of the 'usable' area of a surface
 
774
  if(myIsBaseSurface)
 
775
  {
 
776
    x = myXOffset;
 
777
    y = myYOffset;
 
778
  }
 
779
  else
 
780
  {
 
781
    x = myXOrig;
 
782
    y = myYOrig;
 
783
  }
 
784
}
 
785
 
 
786
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
787
void FBSurfaceSoft::setPos(uInt32 x, uInt32 y)
 
788
{
 
789
  myXOrig = x;
 
790
  myYOrig = y;
 
791
 
 
792
  if(myIsBaseSurface)
 
793
  {
 
794
    myXOffset = myFB.imageRect().x();
 
795
    myYOffset = myFB.imageRect().y();
 
796
  }
 
797
  else
 
798
  {
 
799
    myXOffset = myYOffset = 0;
 
800
  }
 
801
}
 
802
 
 
803
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
804
void FBSurfaceSoft::setWidth(uInt32 w)
 
805
{
 
806
  myWidth = w;
 
807
}
 
808
 
 
809
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
810
void FBSurfaceSoft::setHeight(uInt32 h)
 
811
{
 
812
  myHeight = h;
 
813
}
 
814
 
 
815
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
816
void FBSurfaceSoft::translateCoords(Int32& x, Int32& y) const
 
817
{
 
818
  x -= myXOrig;
 
819
  y -= myYOrig;
 
820
}
 
821
 
 
822
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
823
void FBSurfaceSoft::update()
 
824
{
 
825
  // Since this method is called each frame, we only blit the surfaces when
 
826
  // absolutely necessary
 
827
  if(mySurfaceIsDirty /* && !myIsBaseSurface */)
 
828
  {
 
829
    SDL_Rect srcrect;
 
830
    srcrect.x = 0;
 
831
    srcrect.y = 0;
 
832
    srcrect.w = myWidth;
 
833
    srcrect.h = myHeight;
 
834
 
 
835
    SDL_Rect dstrect;
 
836
    dstrect.x = myXOrig;
 
837
    dstrect.y = myYOrig;
 
838
    dstrect.w = myWidth;
 
839
    dstrect.h = myHeight;
 
840
 
 
841
    SDL_BlitSurface(mySurface, &srcrect, myFB.myScreen, &dstrect);
 
842
    mySurfaceIsDirty = false;
 
843
  }
 
844
}
 
845
 
 
846
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
847
void FBSurfaceSoft::reload()
 
848
{
 
849
  switch(mySurface->format->BytesPerPixel)
732
850
  {
733
851
    case 2:  // 16-bit
734
 
      myPitch = myScreen->pitch/2;
735
 
      if(myUsePhosphor)
736
 
        myRenderType = kPhosphor_16;
737
 
      else
738
 
        myRenderType = kSoftZoom_16;
 
852
      myPitch = mySurface->pitch >> 1;
739
853
      break;
740
854
    case 3:  // 24-bit
741
 
      myPitch = myScreen->pitch;
742
 
      if(myUsePhosphor)
743
 
        myRenderType = kPhosphor_24;
744
 
      else
745
 
        myRenderType = kSoftZoom_24;
 
855
      myPitch = mySurface->pitch;
746
856
      break;
747
857
    case 4:  // 32-bit
748
 
      myPitch = myScreen->pitch/4;
749
 
      if(myUsePhosphor)
750
 
        myRenderType = kPhosphor_32;
751
 
      else
752
 
        myRenderType = kSoftZoom_32;
753
 
      break;
754
 
    default:
755
 
      myRenderType = kSoftZoom_16; // What else should we do here?
 
858
      myPitch = mySurface->pitch >> 2;
756
859
      break;
757
860
  }
758
 
 
759
 
  // Have the changes take effect
760
 
  myOSystem->eventHandler().refreshDisplay();
761
 
}
762
 
 
763
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
764
 
GUI::Surface* FrameBufferSoft::createSurface(int width, int height) const
765
 
{
766
 
  SDL_Surface* data =
767
 
    SDL_CreateRGBSurface(SDL_SWSURFACE, width*myZoomLevel, height*myZoomLevel,
768
 
                         myBytesPerPixel << 3, myFormat->Rmask, myFormat->Gmask,
769
 
                         myFormat->Bmask, myFormat->Amask);
770
 
 
771
 
  return data ? new GUI::Surface(width, height, data) : NULL;
772
861
}