Fixed issue with 24-bit colour mode. This isn't as fast as 16/32 mode,

and will likely never be (24-bit mode is really a hack).  I can
possibly speed it up a little more, but probably not *much* more.

This has been broken for quite some time, and it's only now I've
realized that 24-bit mode can be emulated in a virtualized XP
install in VirtualBox.  But I suspect it's been broken for years.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1670 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-02-05 23:22:54 +00:00
parent e143a2a330
commit 968853c646
2 changed files with 73 additions and 54 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBufferSoft.cxx,v 1.94 2009-01-19 16:52:32 stephena Exp $ // $Id: FrameBufferSoft.cxx,v 1.95 2009-02-05 23:22:54 stephena Exp $
//============================================================================ //============================================================================
#include <sstream> #include <sstream>
@ -210,15 +210,25 @@ void FrameBufferSoft::drawTIA(bool fullRedraw)
if(v != w || fullRedraw) if(v != w || fullRedraw)
{ {
uInt8 a, b, c;
uInt32 pixel = myDefPalette[v]; uInt32 pixel = myDefPalette[v];
uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift; if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
uInt8 g = (pixel & myFormat->Gmask) >> myFormat->Gshift; {
uInt8 b = (pixel & myFormat->Bmask) >> myFormat->Bshift; a = (pixel & myFormat->Bmask) >> myFormat->Bshift;
b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
c = (pixel & myFormat->Rmask) >> myFormat->Rshift;
}
else
{
a = (pixel & myFormat->Rmask) >> myFormat->Rshift;
b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
c = (pixel & myFormat->Bmask) >> myFormat->Bshift;
}
while(xstride--) while(xstride--)
{ {
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b; buffer[pos++] = a; buffer[pos++] = b; buffer[pos++] = c;
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b; buffer[pos++] = a; buffer[pos++] = b; buffer[pos++] = c;
} }
myTiaDirty = true; myTiaDirty = true;
} }
@ -327,15 +337,25 @@ void FrameBufferSoft::drawTIA(bool fullRedraw)
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
uInt32 pixel = myAvgPalette[v][w]; uInt8 a, b, c;
uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift; uInt32 pixel = myAvgPalette[v][w];
uInt8 g = (pixel & myFormat->Gmask) >> myFormat->Gshift; if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
uInt8 b = (pixel & myFormat->Bmask) >> myFormat->Bshift; {
a = (pixel & myFormat->Bmask) >> myFormat->Bshift;
b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
c = (pixel & myFormat->Rmask) >> myFormat->Rshift;
}
else
{
a = (pixel & myFormat->Rmask) >> myFormat->Rshift;
b = (pixel & myFormat->Gmask) >> myFormat->Gshift;
c = (pixel & myFormat->Bmask) >> myFormat->Bshift;
}
while(xstride--) while(xstride--)
{ {
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b; buffer[pos++] = a; buffer[pos++] = b; buffer[pos++] = c;
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b; buffer[pos++] = a; buffer[pos++] = b; buffer[pos++] = c;
} }
} }
screenofsY += myPitch; screenofsY += myPitch;
@ -509,7 +529,6 @@ FBSurfaceSoft::FBSurfaceSoft(const FrameBufferSoft& buffer, SDL_Surface* surface
myHeight(h), myHeight(h),
myIsBaseSurface(isBase), myIsBaseSurface(isBase),
mySurfaceIsDirty(false), mySurfaceIsDirty(false),
myBaseOffset(0),
myPitch(0), myPitch(0),
myXOrig(0), myXOrig(0),
myYOrig(0), myYOrig(0),
@ -599,9 +618,7 @@ void FBSurfaceSoft::drawChar(const GUI::Font* font, uInt8 chr,
case 2: case 2:
{ {
// Get buffer position where upper-left pixel of the character will be drawn // Get buffer position where upper-left pixel of the character will be drawn
uInt16* buffer = (uInt16*) mySurface->pixels + myBaseOffset + uInt16* buffer = (uInt16*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
(ty + desc.ascent - bby - bbh) * myPitch +
tx + bbx;
for(int y = 0; y < bbh; y++) for(int y = 0; y < bbh; y++)
{ {
@ -616,54 +633,57 @@ void FBSurfaceSoft::drawChar(const GUI::Font* font, uInt8 chr,
} }
break; break;
} }
case 3: // TODO - check if this actually works; I don't have access to a 24-bit video card case 3:
{ {
// Get buffer position where upper-left pixel of the character will be drawn // Get buffer position where upper-left pixel of the character will be drawn
uInt8* buffer = (uInt8*) mySurface->pixels + myBaseOffset + uInt8* buffer = (uInt8*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
(ty + desc.ascent - bby - bbh) * myPitch +
tx + bbx;
uInt8 a, b, c;
uInt32 pixel = myFB.myDefPalette[color]; uInt32 pixel = myFB.myDefPalette[color];
uInt8 r = (pixel & myFB.myFormat->Rmask) >> myFB.myFormat->Rshift; if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
uInt8 g = (pixel & myFB.myFormat->Gmask) >> myFB.myFormat->Gshift;
uInt8 b = (pixel & myFB.myFormat->Bmask) >> myFB.myFormat->Bshift;
for(int y = 0; y < bbh; y++)
{ {
const uInt32 ptr = *tmp++; a = (pixel & myFB.myFormat->Bmask) >> myFB.myFormat->Bshift;
uInt32 mask = 0x8000; b = (pixel & myFB.myFormat->Gmask) >> myFB.myFormat->Gshift;
c = (pixel & myFB.myFormat->Rmask) >> myFB.myFormat->Rshift;
}
else
{
a = (pixel & myFB.myFormat->Rmask) >> myFB.myFormat->Rshift;
b = (pixel & myFB.myFormat->Gmask) >> myFB.myFormat->Gshift;
c = (pixel & myFB.myFormat->Bmask) >> myFB.myFormat->Bshift;
}
for(int y = 0; y < bbh; y++, buffer += myPitch)
{
const uInt16 ptr = *tmp++;
uInt16 mask = 0x8000;
uInt8* buf_ptr = buffer; uInt8* buf_ptr = buffer;
for(int x = 0; x < bbw; x++, mask >>= 1) for(int x = 0; x < bbw; x++, mask >>= 1)
{ {
if(ptr & mask) if(ptr & mask)
{ {
*buf_ptr++ = r; *buf_ptr++ = g; *buf_ptr++ = b; *buf_ptr++ = a; *buf_ptr++ = b; *buf_ptr++ = c;
} }
else else
buf_ptr += 3; buf_ptr += 3;
} }
buffer += myPitch;
} }
break; break;
} }
case 4: case 4:
{ {
// Get buffer position where upper-left pixel of the character will be drawn // Get buffer position where upper-left pixel of the character will be drawn
uInt32* buffer = (uInt32*) mySurface->pixels + myBaseOffset + uInt32* buffer = (uInt32*)getBasePtr(tx + bbx, ty + desc.ascent - bby - bbh);
(ty + desc.ascent - bby - bbh) * myPitch +
tx + bbx;
for(int y = 0; y < bbh; y++) for(int y = 0; y < bbh; y++, buffer += myPitch)
{ {
const uInt32 ptr = *tmp++; const uInt16 ptr = *tmp++;
uInt32 mask = 0x8000; uInt16 mask = 0x8000;
for(int x = 0; x < bbw; x++, mask >>= 1) for(int x = 0; x < bbw; x++, mask >>= 1)
if(ptr & mask) if(ptr & mask)
buffer[x] = (uInt32) myFB.myDefPalette[color]; buffer[x] = (uInt32) myFB.myDefPalette[color];
buffer += myPitch;
} }
break; break;
} }
@ -773,22 +793,17 @@ void FBSurfaceSoft::getPos(uInt32& x, uInt32& y) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSoft::setPos(uInt32 x, uInt32 y) void FBSurfaceSoft::setPos(uInt32 x, uInt32 y)
{ {
// Make sure pitch is valid
recalc();
myXOrig = x; myXOrig = x;
myYOrig = y; myYOrig = y;
if(myIsBaseSurface) if(myIsBaseSurface)
{ {
const GUI::Rect& image = myFB.imageRect(); myXOffset = myFB.imageRect().x();
myXOffset = image.x(); myYOffset = myFB.imageRect().y();
myYOffset = image.y();
myBaseOffset = myYOffset * myPitch + myXOffset;
} }
else else
{ {
myXOffset = myYOffset = myBaseOffset = 0; myXOffset = myYOffset = 0;
} }
} }
@ -841,13 +856,13 @@ void FBSurfaceSoft::recalc()
switch(mySurface->format->BytesPerPixel) switch(mySurface->format->BytesPerPixel)
{ {
case 2: // 16-bit case 2: // 16-bit
myPitch = mySurface->pitch/2; myPitch = mySurface->pitch >> 1;
break; break;
case 3: // 24-bit case 3: // 24-bit
myPitch = mySurface->pitch; myPitch = mySurface->pitch;
break; break;
case 4: // 32-bit case 4: // 32-bit
myPitch = mySurface->pitch/4; myPitch = mySurface->pitch >> 2;
break; break;
} }
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ // $Id: FrameBufferSoft.hxx,v 1.66 2009-02-05 23:22:54 stephena Exp $
//============================================================================ //============================================================================
#ifndef FRAMEBUFFER_SOFT_HXX #ifndef FRAMEBUFFER_SOFT_HXX
@ -32,7 +32,7 @@ class RectList;
This class implements an SDL software framebuffer. This class implements an SDL software framebuffer.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ @version $Id: FrameBufferSoft.hxx,v 1.66 2009-02-05 23:22:54 stephena Exp $
*/ */
class FrameBufferSoft : public FrameBuffer class FrameBufferSoft : public FrameBuffer
{ {
@ -172,7 +172,7 @@ class FrameBufferSoft : public FrameBuffer
A surface suitable for software rendering mode. A surface suitable for software rendering mode.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ @version $Id: FrameBufferSoft.hxx,v 1.66 2009-02-05 23:22:54 stephena Exp $
*/ */
class FBSurfaceSoft : public FBSurface class FBSurfaceSoft : public FBSurface
{ {
@ -202,6 +202,11 @@ class FBSurfaceSoft : public FBSurface
private: private:
void recalc(); void recalc();
inline void* getBasePtr(uInt32 x, uInt32 y) {
return static_cast<void *>(static_cast<uInt8*>(mySurface->pixels) +
(myYOffset + y) * mySurface->pitch + (myXOffset + x) *
mySurface->format->BytesPerPixel);
}
private: private:
const FrameBufferSoft& myFB; const FrameBufferSoft& myFB;
@ -209,7 +214,6 @@ class FBSurfaceSoft : public FBSurface
uInt32 myWidth, myHeight; uInt32 myWidth, myHeight;
bool myIsBaseSurface; bool myIsBaseSurface;
bool mySurfaceIsDirty; bool mySurfaceIsDirty;
int myBaseOffset;
int myPitch; int myPitch;
uInt32 myXOrig, myYOrig; uInt32 myXOrig, myYOrig;