mirror of https://github.com/stella-emu/stella.git
Phosphor mode now works with Blargg TV effects! It takes an extra 2-3 MB
RAM to do so, which I agonized over for about a week, but I feel it's a fairly good tradeoff for the features we get. Eventually, I may come up with a more accurate phosphor mode which eliminates this approach entirely. Reverted OpenGL framebuffer to 32-bit colour mode. We're using Blargg effects, so we may as well get the full fidelity out of it. Besides, testing has shown that there's not much speed difference between 16 and 32 bit modes, making me think that 16-bit is probably be swizzled to 32-bit anyway. Bumped release date to June 1, version to rc1. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2501 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
feac57253e
commit
4750c64a17
|
@ -12,7 +12,7 @@
|
|||
Release History
|
||||
===========================================================================
|
||||
|
||||
3.6.1 to 3.7: (May 25, 2012)
|
||||
3.6.1 to 3.7: (June 1, 2012)
|
||||
|
||||
* Added Blargg TV effects, with presets for Composite, S-video, RGB,
|
||||
and badly adjusted TV, and well as a custom mode with full
|
||||
|
|
|
@ -9,4 +9,4 @@ the Stella Website at:
|
|||
Enjoy,
|
||||
|
||||
The Stella Team
|
||||
May 25, 2012
|
||||
June 1, 2012
|
||||
|
|
|
@ -2,7 +2,7 @@ stella (3.7-1) stable; urgency=high
|
|||
|
||||
* Version 3.7 release
|
||||
|
||||
-- Stephen Anthony <stephena@users.sf.net> Fri, 25 May 2012 18:38:25 +0200
|
||||
-- Stephen Anthony <stephena@users.sf.net> Fri, 1 Jun 2012 18:38:25 +0200
|
||||
|
||||
|
||||
stella (3.6.1-1) stable; urgency=high
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
<br><br><br>
|
||||
|
||||
<center><b>February 1999 - May 2012</b></center>
|
||||
<center><b>February 1999 - June 2012</b></center>
|
||||
<center><b>The Stella Team</b></center>
|
||||
<center><b><a href="http://stella.sourceforge.net">Stella Homepage</a></b></center>
|
||||
|
||||
|
|
|
@ -66,18 +66,18 @@ FBSurfaceGL::~FBSurfaceGL()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceGL::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color)
|
||||
{
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels + y * myPitch + x;
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x;
|
||||
while(x++ <= x2)
|
||||
*buffer++ = (uInt16) myFB.myDefPalette[color];
|
||||
*buffer++ = (uInt32) myFB.myDefPalette[color];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceGL::vLine(uInt32 x, uInt32 y, uInt32 y2, uInt32 color)
|
||||
{
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels + y * myPitch + x;
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x;
|
||||
while(y++ <= y2)
|
||||
{
|
||||
*buffer = (uInt16) myFB.myDefPalette[color];
|
||||
*buffer = (uInt32) myFB.myDefPalette[color];
|
||||
buffer += myPitch;
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr,
|
|||
}
|
||||
|
||||
const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * desc.fbbh));
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels +
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels +
|
||||
(ty + desc.ascent - bby - bbh) * myPitch +
|
||||
tx + bbx;
|
||||
|
||||
|
@ -137,7 +137,7 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr,
|
|||
|
||||
for(int x = 0; x < bbw; x++, mask >>= 1)
|
||||
if(ptr & mask)
|
||||
buffer[x] = (uInt16) myFB.myDefPalette[color];
|
||||
buffer[x] = (uInt32) myFB.myDefPalette[color];
|
||||
|
||||
buffer += myPitch;
|
||||
}
|
||||
|
@ -147,14 +147,14 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr,
|
|||
void FBSurfaceGL::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
|
||||
uInt32 color, uInt32 h)
|
||||
{
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myPitch + tx;
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx;
|
||||
|
||||
for(uInt32 y = 0; y < h; ++y)
|
||||
{
|
||||
uInt32 mask = 0xF0000000;
|
||||
for(uInt32 x = 0; x < 8; ++x, mask >>= 4)
|
||||
if(bitmap[y] & mask)
|
||||
buffer[x] = (uInt16) myFB.myDefPalette[color];
|
||||
buffer[x] = (uInt32) myFB.myDefPalette[color];
|
||||
|
||||
buffer += myPitch;
|
||||
}
|
||||
|
@ -163,10 +163,10 @@ void FBSurfaceGL::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceGL::drawPixels(uInt32* data, uInt32 tx, uInt32 ty, uInt32 numpixels)
|
||||
{
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myPitch + tx;
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx;
|
||||
|
||||
for(uInt32 i = 0; i < numpixels; ++i)
|
||||
*buffer++ = (uInt16) data[i];
|
||||
*buffer++ = (uInt32) data[i];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -259,7 +259,7 @@ void FBSurfaceGL::update()
|
|||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myImageW, myImageH,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
myTexture->pixels);
|
||||
|
||||
myGL.EnableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -318,7 +318,7 @@ void FBSurfaceGL::reload()
|
|||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
myTexture->pixels);
|
||||
|
||||
// Cache vertex and texture coordinates using vertex buffer object
|
||||
|
|
|
@ -89,13 +89,13 @@ void FBSurfaceTIA::update()
|
|||
uInt8* previousFrame = myTIA->previousFrameBuffer();
|
||||
uInt32 width = myTIA->width();
|
||||
uInt32 height = myTIA->height();
|
||||
uInt16* buffer = (uInt16*) myTexture->pixels;
|
||||
uInt32* buffer = (uInt32*) myTexture->pixels;
|
||||
|
||||
// TODO - Eventually 'phosphor' won't be a separate mode, and will become
|
||||
// a post-processing filter by blending several frames.
|
||||
switch(myFB.myFilterType)
|
||||
{
|
||||
case FrameBufferGL::kNone:
|
||||
case FrameBufferGL::kNormal:
|
||||
{
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
|
@ -103,14 +103,13 @@ void FBSurfaceTIA::update()
|
|||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
buffer[pos++] = (uInt16) myFB.myDefPalette[currentFrame[bufofsY + x]];
|
||||
buffer[pos++] = (uInt32) myFB.myDefPalette[currentFrame[bufofsY + x]];
|
||||
|
||||
bufofsY += width;
|
||||
screenofsY += myPitch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FrameBufferGL::kPhosphor:
|
||||
{
|
||||
uInt32 bufofsY = 0;
|
||||
|
@ -121,7 +120,7 @@ void FBSurfaceTIA::update()
|
|||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
buffer[pos++] = (uInt16)
|
||||
buffer[pos++] = (uInt32)
|
||||
myFB.myAvgPalette[currentFrame[bufofs]][previousFrame[bufofs]];
|
||||
}
|
||||
bufofsY += width;
|
||||
|
@ -129,10 +128,16 @@ void FBSurfaceTIA::update()
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FrameBufferGL::kBlarggNTSC:
|
||||
case FrameBufferGL::kBlarggNormal:
|
||||
{
|
||||
myFB.myNTSCFilter.blit(currentFrame, width, height, buffer, myTexture->pitch);
|
||||
myFB.myNTSCFilter.blit_single(currentFrame, width, height,
|
||||
buffer, myTexture->pitch);
|
||||
break;
|
||||
}
|
||||
case FrameBufferGL::kBlarggPhosphor:
|
||||
{
|
||||
myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
|
||||
buffer, myTexture->pitch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +151,7 @@ void FBSurfaceTIA::update()
|
|||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
myTexture->pixels);
|
||||
|
||||
if(myFB.myVBOAvailable)
|
||||
|
@ -231,7 +236,7 @@ void FBSurfaceTIA::reload()
|
|||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
myTexture->pixels);
|
||||
|
||||
// Scanline texture (@ index 1)
|
||||
|
@ -241,11 +246,11 @@ void FBSurfaceTIA::reload()
|
|||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
static uInt16 const scanline[4] = { 0x0000, 0x0000, 0x8000, 0x0000 };
|
||||
static uInt32 const scanline[2] = { 0x00000000, 0xff000000 };
|
||||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, 2);
|
||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, 1);
|
||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0,
|
||||
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
scanline);
|
||||
|
||||
// Cache vertex and texture coordinates using vertex buffer object
|
||||
|
@ -302,8 +307,7 @@ void FBSurfaceTIA::updateCoords()
|
|||
{
|
||||
// Normal TIA rendering and TV effects use different widths
|
||||
// We use the same buffer, and only pick the width we need
|
||||
myBaseW = myFB.myFilterType == FrameBufferGL::kBlarggNTSC ?
|
||||
ATARI_NTSC_OUT_WIDTH(160) : 160;
|
||||
myBaseW = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
|
||||
|
||||
myTexCoordW = (GLfloat) myBaseW / myTexWidth;
|
||||
myTexCoordH = (GLfloat) myBaseH / myTexHeight;
|
||||
|
@ -379,7 +383,7 @@ void FBSurfaceTIA::updateCoords()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceTIA::setTIAPalette(const uInt32* palette)
|
||||
{
|
||||
myFB.myNTSCFilter.setTIAPalette(palette);
|
||||
myFB.myNTSCFilter.setTIAPalette(myFB, palette);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBufferGL::FrameBufferGL(OSystem* osystem)
|
||||
: FrameBuffer(osystem),
|
||||
myFilterType(kNone),
|
||||
myFilterType(kNormal),
|
||||
myTiaSurface(NULL),
|
||||
myDirtyFlag(true)
|
||||
{
|
||||
|
@ -48,8 +48,9 @@ FrameBufferGL::FrameBufferGL(OSystem* osystem)
|
|||
// It's done this way (vs directly accessing a FBSurfaceGL object)
|
||||
// since the structure may be needed before any FBSurface's have
|
||||
// been created
|
||||
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1,16,
|
||||
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
|
||||
// Note: alpha disabled for now, since it's not used
|
||||
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
|
||||
|
||||
myPixelFormat = *(s->format);
|
||||
SDL_FreeSurface(s);
|
||||
|
@ -313,7 +314,7 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
|
|||
myTiaSurface->updateCoords(baseHeight, mode.image_x, mode.image_y,
|
||||
mode.image_w, mode.image_h);
|
||||
|
||||
myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC);
|
||||
myTiaSurface->enableScanlines(ntscEnabled());
|
||||
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
||||
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter"));
|
||||
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter"));
|
||||
|
@ -358,7 +359,7 @@ void FrameBufferGL::enablePhosphor(bool enable, int blend)
|
|||
{
|
||||
myUsePhosphor = enable;
|
||||
myPhosphorBlend = blend;
|
||||
myFilterType = enable ? kPhosphor : kNone;
|
||||
myFilterType = FilterType(enable ? myFilterType | 0x01 : myFilterType & 0x10);
|
||||
myRedrawEntireFrame = true;
|
||||
}
|
||||
}
|
||||
|
@ -368,10 +369,10 @@ void FrameBufferGL::enableNTSC(bool enable)
|
|||
{
|
||||
if(myTiaSurface)
|
||||
{
|
||||
myFilterType = enable ? kBlarggNTSC : myUsePhosphor ? kPhosphor : kNone;
|
||||
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
|
||||
myTiaSurface->updateCoords();
|
||||
|
||||
myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC);
|
||||
myTiaSurface->enableScanlines(ntscEnabled());
|
||||
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
||||
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter"));
|
||||
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter"));
|
||||
|
|
|
@ -77,7 +77,7 @@ class FrameBufferGL : public FrameBuffer
|
|||
Enable/disable NTSC filtering effects.
|
||||
*/
|
||||
void enableNTSC(bool enable);
|
||||
bool ntscEnabled() const { return myFilterType == kBlarggNTSC; }
|
||||
bool ntscEnabled() const { return myFilterType & 0x10; }
|
||||
|
||||
/**
|
||||
Set up the TIA/emulation palette for a screen of any depth > 8.
|
||||
|
@ -193,10 +193,13 @@ class FrameBufferGL : public FrameBuffer
|
|||
};
|
||||
bool loadFuncs(GLFunctionality functionality);
|
||||
|
||||
// Enumeration created such that phosphor off/on is in LSB,
|
||||
// and Blargg off/on is in MSB
|
||||
enum FilterType {
|
||||
kNone,
|
||||
kPhosphor,
|
||||
kBlarggNTSC
|
||||
kNormal = 0x00,
|
||||
kPhosphor = 0x01,
|
||||
kBlarggNormal = 0x10,
|
||||
kBlarggPhosphor = 0x11
|
||||
};
|
||||
FilterType myFilterType;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
#define STELLA_VERSION "3.7_beta4"
|
||||
#define STELLA_VERSION "3.7_rc1"
|
||||
#define STELLA_BUILD atoi("$Rev$" + 6)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "Settings.hxx"
|
||||
|
||||
#include "NTSCFilter.hxx"
|
||||
|
||||
#define SCALE_FROM_100(x) ((x/50.0)-1.0)
|
||||
|
@ -36,10 +39,35 @@ NTSCFilter::~NTSCFilter()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void NTSCFilter::setTIAPalette(const uInt32* palette)
|
||||
void NTSCFilter::setTIAPalette(const FrameBuffer& fb, const uInt32* palette)
|
||||
{
|
||||
// Normal TIA palette contains 256 colours, where every odd indexed colour
|
||||
// is used for PAL colour-loss effect
|
||||
// This can't be emulated here, since the memory requirements would be too
|
||||
// great (a 4x increase)
|
||||
// Therefore, we need to skip every second index, since the array passed to
|
||||
// the Blargg code assumes 128 colours
|
||||
uInt8* ptr = myTIAPalette;
|
||||
for(int i = 0; i < 256; i++)
|
||||
|
||||
// Set palette for phosphor effect
|
||||
for(int i = 0; i < 256; i+=2)
|
||||
{
|
||||
for(int j = 0; j < 256; j+=2)
|
||||
{
|
||||
uInt8 ri = (palette[i] >> 16) & 0xff;
|
||||
uInt8 gi = (palette[i] >> 8) & 0xff;
|
||||
uInt8 bi = palette[i] & 0xff;
|
||||
uInt8 rj = (palette[j] >> 16) & 0xff;
|
||||
uInt8 gj = (palette[j] >> 8) & 0xff;
|
||||
uInt8 bj = palette[j] & 0xff;
|
||||
|
||||
*ptr++ = fb.getPhosphor(ri, rj);
|
||||
*ptr++ = fb.getPhosphor(gi, gj);
|
||||
*ptr++ = fb.getPhosphor(bi, bj);
|
||||
}
|
||||
}
|
||||
// Set palette for normal fill
|
||||
for(int i = 0; i < 256; i+=2)
|
||||
{
|
||||
*ptr++ = (palette[i] >> 16) & 0xff;
|
||||
*ptr++ = (palette[i] >> 8) & 0xff;
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
#ifndef NTSC_FILTER_HXX
|
||||
#define NTSC_FILTER_HXX
|
||||
|
||||
class FrameBuffer;
|
||||
class Settings;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Array.hxx"
|
||||
#include "Settings.hxx"
|
||||
#include "atari_ntsc.h"
|
||||
|
||||
/**
|
||||
|
@ -63,7 +64,7 @@ class NTSCFilter
|
|||
uses this as a baseline for calculating its own internal palette
|
||||
in YIQ format.
|
||||
*/
|
||||
void setTIAPalette(const uInt32* palette);
|
||||
void setTIAPalette(const FrameBuffer& fb, const uInt32* palette);
|
||||
|
||||
// The following are meant to be used strictly for toggling from the GUI
|
||||
string setPreset(Preset preset);
|
||||
|
@ -104,11 +105,18 @@ class NTSCFilter
|
|||
// output buffer
|
||||
// In the current implementation, the source pitch is always the
|
||||
// same as the actual width
|
||||
inline void blit(uInt8* src_buf, int src_width, int src_height,
|
||||
uInt16* dest_buf, long dest_pitch)
|
||||
inline void blit_single(uInt8* src_buf, int src_width, int src_height,
|
||||
uInt32* dest_buf, long dest_pitch)
|
||||
{
|
||||
atari_ntsc_blit(&myFilter, src_buf, src_width, src_width, src_height,
|
||||
dest_buf, dest_pitch);
|
||||
atari_ntsc_blit_single(&myFilter, src_buf, src_width, src_width, src_height,
|
||||
dest_buf, dest_pitch);
|
||||
}
|
||||
inline void blit_double(uInt8* src_buf, uInt8* src_back_buf,
|
||||
int src_width, int src_height,
|
||||
uInt32* dest_buf, long dest_pitch)
|
||||
{
|
||||
atari_ntsc_blit_double(&myFilter, src_buf, src_back_buf, src_width, src_width,
|
||||
src_height, dest_buf, dest_pitch);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -131,8 +139,17 @@ class NTSCFilter
|
|||
// Current preset in use
|
||||
Preset myPreset;
|
||||
|
||||
// 128 colours by 3 components per colour
|
||||
uInt8 myTIAPalette[256 * 3];
|
||||
// The base 2600 palette contains 128 colours
|
||||
// However, 'phosphor' mode needs a 128x128 matrix to simulate
|
||||
// low-flicker output, so we need 128x128 + 128, or 129x128
|
||||
// Note that this is a huge hack, which hopefully will go
|
||||
// away once the phosphor effect can be more properly emulated
|
||||
// Memory layout is as follows:
|
||||
//
|
||||
// 128x128 in first bytes of array
|
||||
// 128 in last bytes of array
|
||||
// Each colour is represented by 3 bytes, in R,G,B order
|
||||
uInt8 myTIAPalette[atari_ntsc_palette_size * 3];
|
||||
|
||||
struct AdjustableTag {
|
||||
const char* type;
|
||||
|
|
|
@ -99,15 +99,18 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup,
|
|||
}
|
||||
}
|
||||
|
||||
void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in,
|
||||
void atari_ntsc_blit_single( atari_ntsc_t const* ntsc,
|
||||
atari_ntsc_in_t const* atari_in,
|
||||
long in_row_width, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch )
|
||||
{
|
||||
#define TO_SINGLE(pixel) ((1<<14)+(pixel>>1))
|
||||
|
||||
int const chunk_count = (in_width - 1) / atari_ntsc_in_chunk;
|
||||
while ( in_height-- )
|
||||
{
|
||||
atari_ntsc_in_t const* line_in = atari_in;
|
||||
ATARI_NTSC_BEGIN_ROW( ntsc, atari_ntsc_black, line_in[0] );
|
||||
ATARI_NTSC_BEGIN_ROW( ntsc, TO_SINGLE(atari_ntsc_black), TO_SINGLE(line_in[0]) );
|
||||
atari_ntsc_out_t* restrict line_out = (atari_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
|
@ -115,34 +118,95 @@ void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in,
|
|||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc, line_in[0] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 3, line_out[3] );
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc, TO_SINGLE(line_in[0]) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] );
|
||||
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc, line_in[1] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 6, line_out[6] );
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc, TO_SINGLE(line_in[1]) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] );
|
||||
|
||||
line_in += 2;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc, atari_ntsc_black );
|
||||
ATARI_NTSC_RGB_OUT_1555( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 3, line_out[3] );
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc, TO_SINGLE(atari_ntsc_black) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] );
|
||||
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc, atari_ntsc_black );
|
||||
ATARI_NTSC_RGB_OUT_1555( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_1555( 6, line_out[6] );
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc, TO_SINGLE(atari_ntsc_black) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] );
|
||||
|
||||
atari_in += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void atari_ntsc_blit_double( atari_ntsc_t const* ntsc,
|
||||
atari_ntsc_in_t const* atari_in1, atari_ntsc_in_t const* atari_in2,
|
||||
long in_row_width, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch )
|
||||
{
|
||||
#define TO_DOUBLE(pixel1, pixel2) (((pixel1>>1)<<7)+(pixel2>>1))
|
||||
|
||||
int const chunk_count = (in_width - 1) / atari_ntsc_in_chunk;
|
||||
while ( in_height-- )
|
||||
{
|
||||
atari_ntsc_in_t const* line_in1 = atari_in1;
|
||||
atari_ntsc_in_t const* line_in2 = atari_in2;
|
||||
ATARI_NTSC_BEGIN_ROW( ntsc,
|
||||
TO_DOUBLE(atari_ntsc_black, atari_ntsc_black),
|
||||
TO_DOUBLE(line_in1[0], line_in2[0]) );
|
||||
atari_ntsc_out_t* restrict line_out = (atari_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in1;
|
||||
++line_in2;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc,
|
||||
TO_DOUBLE(line_in1[0], line_in2[0]) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] );
|
||||
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc,
|
||||
TO_DOUBLE(line_in1[1], line_in2[1]) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] );
|
||||
|
||||
line_in1 += 2;
|
||||
line_in2 += 2;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
ATARI_NTSC_COLOR_IN( 0, ntsc,
|
||||
TO_DOUBLE(atari_ntsc_black, atari_ntsc_black) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] );
|
||||
|
||||
ATARI_NTSC_COLOR_IN( 1, ntsc,
|
||||
TO_DOUBLE(atari_ntsc_black, atari_ntsc_black) );
|
||||
ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] );
|
||||
ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] );
|
||||
|
||||
atari_in1 += in_row_width;
|
||||
atari_in2 += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define ATARI_NTSC_H
|
||||
|
||||
typedef unsigned char atari_ntsc_in_t;
|
||||
typedef unsigned short atari_ntsc_out_t;
|
||||
typedef unsigned int atari_ntsc_out_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -55,7 +55,7 @@ extern atari_ntsc_setup_t const atari_ntsc_svideo; /* color bleeding only */
|
|||
extern atari_ntsc_setup_t const atari_ntsc_rgb; /* crisp image */
|
||||
extern atari_ntsc_setup_t const atari_ntsc_bad; /* badly adjusted TV */
|
||||
|
||||
enum { atari_ntsc_palette_size = 256 };
|
||||
enum { atari_ntsc_palette_size = 129 * 128 };
|
||||
|
||||
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
||||
atari_ntsc_t object. Can pass NULL for either parameter. */
|
||||
|
@ -66,7 +66,12 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup,
|
|||
/* Filters one or more rows of pixels. Input pixels are 8-bit Atari palette colors.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. */
|
||||
void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in,
|
||||
void atari_ntsc_blit_single( atari_ntsc_t const* ntsc,
|
||||
atari_ntsc_in_t const* atari_in,
|
||||
long in_row_width, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
void atari_ntsc_blit_double( atari_ntsc_t const* ntsc,
|
||||
atari_ntsc_in_t const* atari_in1, atari_ntsc_in_t const* atari_in2,
|
||||
long in_row_width, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
|
@ -99,23 +104,16 @@ enum { atari_ntsc_black = 0 }; /* palette index for black */
|
|||
#define ATARI_NTSC_COLOR_IN( in_index, ntsc, color_in ) \
|
||||
ATARI_NTSC_COLOR_IN_( in_index, color_in, ATARI_NTSC_ENTRY_, ntsc )
|
||||
|
||||
/* Generates output in the specified 16-bit format (x = junk bits).
|
||||
1555: xRRRRRGG GGGBBBBB (1-5-5-5 16-bit RGB)
|
||||
/* Generates output in the specified 32-bit format (x = junk bits).
|
||||
native: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format)
|
||||
8888: 00000000 RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8-8 32-bit ARGB)
|
||||
*/
|
||||
#define ATARI_NTSC_RGB_OUT_1555( index, rgb_out ) {\
|
||||
atari_ntsc_rgb_t raw_ =\
|
||||
kernel0 [index ] + kernel1 [(index+10)%7+14] +\
|
||||
kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\
|
||||
ATARI_NTSC_CLAMP_( raw_, 0 );\
|
||||
rgb_out = (raw_>>(14)& 0x7C00)|(raw_>>(9)&0x03E0)|(raw_>>(4)&0x001F);\
|
||||
}
|
||||
#define ATARI_NTSC_RGB_OUT_8888( index, rgb_out ) {\
|
||||
atari_ntsc_rgb_t raw_ =\
|
||||
kernel0 [index ] + kernel1 [(index+10)%7+14] +\
|
||||
kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\
|
||||
ATARI_NTSC_CLAMP_( raw_, 0 );\
|
||||
rgb_out = (raw_>>(5)& 0x00FF0000)|(raw_>>(3)&0x0000FF00)|(raw_>>(1)&0x000000FF);\
|
||||
rgb_out = (raw_>>5 & 0x00FF0000)|(raw_>>3 & 0x0000FF00)|(raw_>>1 & 0x000000FF);\
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
|
|
@ -495,9 +495,7 @@ void EventHandler::poll(uInt64 time)
|
|||
break;
|
||||
|
||||
case KBDK_p: // Alt-p toggles phosphor effect
|
||||
// FIXME - Currently, phosphor mode cannot be enabled with NTSC filtering
|
||||
if(!myOSystem->frameBuffer().ntscEnabled())
|
||||
myOSystem->console().togglePhosphor();
|
||||
myOSystem->console().togglePhosphor();
|
||||
break;
|
||||
|
||||
case KBDK_l:
|
||||
|
|
|
@ -305,6 +305,16 @@ class FrameBuffer
|
|||
*/
|
||||
void toggleScanlineInterpolation();
|
||||
|
||||
/**
|
||||
Used to calculate an averaged color for the 'phosphor' effect.
|
||||
|
||||
@param c1 Color 1
|
||||
@param c2 Color 2
|
||||
|
||||
@return Averaged value of the two colors
|
||||
*/
|
||||
uInt8 getPhosphor(uInt8 c1, uInt8 c2) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following methods are system-specific and *may* be implemented
|
||||
// in derived classes.
|
||||
|
@ -530,16 +540,6 @@ class FrameBuffer
|
|||
*/
|
||||
void drawMessage();
|
||||
|
||||
/**
|
||||
Used to calculate an averaged color for the 'phosphor' effect.
|
||||
|
||||
@param c1 Color 1
|
||||
@param c2 Color 2
|
||||
|
||||
@return Averaged value of the two colors
|
||||
*/
|
||||
uInt8 getPhosphor(uInt8 c1, uInt8 c2) const;
|
||||
|
||||
/**
|
||||
Calculate the maximum level by which the base window can be zoomed and
|
||||
still fit in the given screen dimensions.
|
||||
|
|
|
@ -51,7 +51,7 @@ stella: support, and an integrated debugger for VCS game developers (with DASM
|
|||
stella: symbol file support).
|
||||
stella:
|
||||
stella: Homepage: http://stella.sourceforge.net/
|
||||
stella: Author: Bradford W. Mott and the Stella Team
|
||||
stella: Author: Bradford W. Mott, Stephen Anthony and the Stella Team
|
||||
stella:
|
||||
stella:
|
||||
EOF
|
||||
|
|
|
@ -108,9 +108,12 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version}
|
|||
%_datadir/icons/large/%{name}.png
|
||||
|
||||
%changelog
|
||||
* Fri May 25 2012 Stephen Anthony <stephena@users.sf.net> 3.7-1
|
||||
* Fri Jun 1 2012 Stephen Anthony <stephena@users.sf.net> 3.7-1
|
||||
- Version 3.7 release
|
||||
|
||||
* Fri Mar 30 2012 Stephen Anthony <stephena@users.sf.net> 3.6.1-1
|
||||
- Version 3.6.1 release
|
||||
|
||||
* Fri Mar 16 2012 Stephen Anthony <stephena@users.sf.net> 3.6-1
|
||||
- Version 3.6 release
|
||||
|
||||
|
|
Loading…
Reference in New Issue