This is the first pass at getting the Cyberstella port working.

It now partially compiles again, but many features are still
missing.

Added a FrameBufferWin32 class.  This will eventually contain
DirectDraw windowed and fullscreen code, but for now it does
nothing.

Upgraded the project to Visual Studio .NET.  It will no longer
compile with VC++ 6.

Now for the parts that will definitely change:

1) Right now, the MainWin32 class is also acting as the FrameBuffer.
The relevant code will be moved to FrameBufferWin32.

2) The DirectInput class will be completely rewritten to use
DirectInput8.  Also, I'll be moving to event-based input where
the state is taken into account.  The rewrite will also allow
multiple joysticks, and selecting which joystick input device
is mapped to which internal Atari joystick.

3) The SettingsWin32 class does nothing ATM.  It will be expanded,
and will replace using the registry (the associated registry class
will be removed).

4) I haven't even looked at the sound yet.  I want to get all
other stuff working before I even attempt it.  It *did* make
some noise the last time I tried it, but something wasn't quite
right.

So, bottom line is that this compiles without sound, mouse,
joystick, windowed modes, and any of the 1.4 core enhancements.
But at least it compiles :)  I expect the extras to be worked
out quite soon (except for sound), since I've already done
most of the same thing in Linux.

And to potential porters; its still not ready, and you should
probably be looking at the SDL port anyway ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@202 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2003-11-11 18:55:39 +00:00
parent fc96e5b0d8
commit 34addb87c6
7 changed files with 2822 additions and 249 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
#include "CyberstellaView.h"
#include "StellaConfig.h"
#include "Console.hxx"
#include "MainWin32.hxx"
#include "SoundWin32.hxx"
#include "SettingsWin32.hxx"
@ -20,7 +21,7 @@ static char THIS_FILE[] = __FILE__;
//
// Undefining USE_FS will use the (untested) windowed mode
//
/*
#define USE_FS
#ifdef USE_FS
@ -31,7 +32,7 @@ static char THIS_FILE[] = __FILE__;
#define FORCED_VIDEO_CX 640
#define FORCED_VIDEO_CY 480
*/
/////////////////////////////////////////////////////////////////////////////
// CCyberstellaView
@ -57,15 +58,46 @@ CCyberstellaView::CCyberstellaView()
//{{AFX_DATA_INIT(CCyberstellaView)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// FIXME - get rid of this
m_pGlobalData = new CGlobalData(GetModuleHandle(NULL));
m_bIsPause = false;
m_pPropertiesSet = NULL;
// Create SettingsWin32 object
// This should be done before any other xxxWin32 objects are created
theSettings = new SettingsWin32();
theSettings->loadConfig();
// Create a properties set for us to use
thePropertiesSet = new PropertiesSet();
// Try to load the file stella.pro file
string filename("stella.pro"); // FIXME look into settings to get path
// See if we can open the file and load properties from it
ifstream stream(filename.c_str());
if(stream)
{
// File was opened so load properties from it
stream.close();
thePropertiesSet->load(filename, &Console::defaultProperties());
}
else
{
thePropertiesSet->load("", &Console::defaultProperties());
MessageBox("stella.pro not found in working directory!", "Warning!", MB_OK|MB_ICONEXCLAMATION);
}
}
CCyberstellaView::~CCyberstellaView()
{
if(m_pGlobalData) delete m_pGlobalData;
if(m_pPropertiesSet) delete m_pPropertiesSet;
if(m_pGlobalData)
delete m_pGlobalData;
if(thePropertiesSet)
delete thePropertiesSet;
if(theSettings)
delete theSettings;
}
void CCyberstellaView::DoDataExchange(CDataExchange* pDX)
@ -126,23 +158,8 @@ void CCyberstellaView::OnPlay()
playRom();
}
// Toggles pausing of the emulator
void CCyberstellaView::togglePause()
{
m_bIsPause = !m_bIsPause;
//TODO: theConsole->mediaSource().pause(m_bIsPause);
}
LRESULT CCyberstellaView::initialize(WPARAM wParam, LPARAM lParam)
{
// Create a properties set for us to use
m_pPropertiesSet = new PropertiesSet();
// Create SettingsWin32 object
pSettings = new SettingsWin32();
pSettings->loadConfig();
// Set up the image list.
HICON hFolder, hAtari;
@ -161,25 +178,7 @@ LRESULT CCyberstellaView::initialize(WPARAM wParam, LPARAM lParam)
m_List.SetImageList (&m_imglist, LVSIL_SMALL);
// Init ListCtrl
m_List.init(m_pPropertiesSet,this);
// Try to load the file stella.pro file
string filename("stella.pro");
// See if we can open the file and load properties from it
ifstream stream(filename.c_str());
if(stream)
{
// File was opened so load properties from it
stream.close();
m_pPropertiesSet->load(filename, &Console::defaultProperties());
}
else
{
m_pPropertiesSet->load("", &Console::defaultProperties());
MessageBox("stella.pro not found in working directory!", "Warning!", MB_OK|MB_ICONEXCLAMATION);
}
m_List.init(thePropertiesSet,this);
m_List.populateRomList();
return 0;
@ -200,58 +199,31 @@ LRESULT CCyberstellaView::updateListInfos(WPARAM wParam, LPARAM lParam)
// Show rom path
SetDlgItemText(IDC_ROMPATH, m_List.getPath());
return 0;
}
LRESULT CCyberstellaView::displayNote(WPARAM wParam, LPARAM lParam)
{
// Show rom path
CString note;
note.Format(IDS_NOTETEXT, m_List.getCurrentNote());
((CMainFrame*)AfxGetMainWnd())->setStatusText(note);
return 0;
}
void CCyberstellaView::playRom(LONG gameID)
{
EnableWindow(FALSE);
#ifdef USE_FS
CDirectXFullScreen* pwnd = NULL;
#else
CDirectXWindow* pwnd = NULL;
#endif
CString fileName;
BYTE* pImage = NULL;
LPCTSTR pszFileName = NULL;
DWORD dwImageSize;
DWORD dwActualSize;
Console* pConsole = NULL;
// Create Sound driver object
// (Will be initialized once we have a window handle below)
if(m_pGlobalData->bNoSound)
{
TRACE("Creating Sound driver");
pSound = new Sound();
}
else
{
TRACE("Creating SoundWin32 driver");
pSound = new SoundWin32();
}
if ( pSound == NULL )
{
goto exit;
}
fileName = m_List.getCurrentFile();
// Safety Bail Out
if(fileName.GetLength() <= 0)
return;
@ -269,9 +241,7 @@ void CCyberstellaView::playRom(LONG gameID)
// ::MessageBoxFromGetLastError( pszPathName );
TCHAR pszFormat[ 1024 ];
LoadString(GetModuleHandle(NULL),
IDS_ROM_LOAD_FAILED,
pszFormat, 1023 );
LoadString(GetModuleHandle(NULL), IDS_ROM_LOAD_FAILED, pszFormat, 1023 );
LPTSTR pszLastError = NULL;
@ -298,23 +268,21 @@ void CCyberstellaView::playRom(LONG gameID)
MB_OK | MB_ICONEXCLAMATION );
::LocalFree( pszLastError );
goto exit;
return;
}
dwImageSize = ::GetFileSize( hFile, NULL );
pImage = new BYTE[dwImageSize + 1];
if(pImage == NULL)
goto exit;
return;
if ( ! ::ReadFile( hFile, pImage, dwImageSize, &dwActualSize, NULL ) )
{
VERIFY( ::CloseHandle( hFile ) );
MessageBoxFromGetLastError(fileName);
goto exit;
delete pImage;
return;
}
VERIFY( ::CloseHandle(hFile) );
@ -330,19 +298,41 @@ void CCyberstellaView::playRom(LONG gameID)
pszFileName = fileName;
}
//::MessageBox(*this, "got here", _T("Error"), MB_OK | MB_ICONEXCLAMATION );
::ShowWindow( *this, SW_HIDE );
// Create a new main instance for this cartridge
MainWin32* mainWin32 = new MainWin32(pImage, dwActualSize, pszFileName,
*theSettings, *thePropertiesSet);
// And start the main emulation loop
mainWin32->run();
::ShowWindow( *this, SW_SHOW );
delete pImage;
delete mainWin32;
EnableWindow(TRUE);
// Set focus back to the rom list
m_List.SetFocus();
}
#if 0 // MainWin32
try
{
// If this throws an exception, then it's probably a bad cartridge
pConsole = new Console( pImage, dwActualSize, pszFileName, *pSettings,
*m_pPropertiesSet, 31400 );
*thePropertiesSet, 31400 );
if ( pConsole == NULL )
goto exit;
}
catch (...)
{
::MessageBox(GetModuleHandle(NULL),
NULL, IDS_CANTSTARTCONSOLE);
// FIXME ::MessageBox(GetModuleHandle(NULL),
// NULL, IDS_CANTSTARTCONSOLE);
goto exit;
}
@ -389,23 +379,4 @@ void CCyberstellaView::playRom(LONG gameID)
TRACE( "Sndwin32 Initialize failed, err = %X", hr );
}
}
::ShowWindow( *this, SW_HIDE );
(void)pwnd->Run();
::ShowWindow( *this, SW_SHOW );
exit:
delete pwnd;
delete pConsole;
delete pSound;
if(pImage)
delete pImage;
EnableWindow(TRUE);
// Set focus back to the rom list
m_List.SetFocus();
}
#endif

View File

@ -11,8 +11,7 @@
#include "GlobalData.hxx"
#include "PropsSet.hxx"
#include "Sound.hxx"
#include "Settings.hxx"
#include "SettingsWin32.hxx"
#include "GameList.h"
class CCyberstellaView : public CFormView
@ -66,8 +65,6 @@ protected:
DECLARE_MESSAGE_MAP()
private:
// methods
void togglePause();
void playRom(LONG gameID = NULL);
LRESULT initialize(WPARAM wParam, LPARAM lParam);
@ -75,10 +72,8 @@ private:
LRESULT updateListInfos(WPARAM wParam, LPARAM lParam);
// members
PropertiesSet* m_pPropertiesSet;
Sound* pSound;
Settings* pSettings;
bool m_bIsPause;
PropertiesSet* thePropertiesSet;
SettingsWin32* theSettings;
};
#ifndef _DEBUG // debug version in CyberstellaView.cpp

View File

@ -1,19 +1,34 @@
//============================================================================
//
// StellaX
// Jeff Miller 05/13/2000
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-1999 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DirectInput.cxx,v 1.2 2003-11-11 18:55:39 stephena Exp $
//============================================================================
#define DIRECTINPUT_VERSION 0x700
#include "pch.hxx"
#include "DirectInput.hxx"
#include "resource.h"
#include "DirectInput.hxx"
//
// CDirectInput
// DirectInput
//
CDirectInput::CDirectInput(HWND hwnd, DWORD dwDevType, int nButtonCount)
DirectInput::DirectInput(HWND hwnd, DWORD dwDevType, int nButtonCount)
: m_hwnd( hwnd )
, m_piDID(NULL)
, m_piDI(NULL)
@ -24,22 +39,22 @@ CDirectInput::CDirectInput(HWND hwnd, DWORD dwDevType, int nButtonCount)
, m_lY(0)
, m_fInitialized( FALSE )
{
TRACE("CDirectInput::CDirectInput");
TRACE("DirectInput::DirectInput");
}
CDirectInput::~CDirectInput(
DirectInput::~DirectInput(
)
{
TRACE("CDirectInput::~CDirectInput");
TRACE("DirectInput::~DirectInput");
Cleanup();
}
HRESULT CDirectInput::Initialize(
HRESULT DirectInput::Initialize(
void
)
{
TRACE("CDirectInput::Initialize");
TRACE("DirectInput::Initialize");
HINSTANCE hInstance = (HINSTANCE)::GetWindowLong( m_hwnd, GWL_HINSTANCE );
@ -142,11 +157,11 @@ cleanup:
return hr;
}
void CDirectInput::Cleanup(
void DirectInput::Cleanup(
void
)
{
TRACE("CDirectInput::Cleanup");
TRACE("DirectInput::Cleanup");
delete[] m_pButtons;
@ -166,13 +181,13 @@ void CDirectInput::Cleanup(
m_fInitialized = FALSE;
}
BOOL CALLBACK CDirectInput::EnumDevicesProc
BOOL CALLBACK DirectInput::EnumDevicesProc
(
const DIDEVICEINSTANCE* lpddi,
LPVOID pvRef
)
{
CDirectInput* pThis = (CDirectInput*)pvRef;
DirectInput* pThis = (DirectInput*)pvRef;
ASSERT(pThis);
const DIDATAFORMAT* pdidf = NULL;
@ -240,7 +255,7 @@ BOOL CALLBACK CDirectInput::EnumDevicesProc
return DIENUM_STOP;
}
BOOL CDirectInput::IsButtonPressed
BOOL DirectInput::IsButtonPressed
(
int nButton
) const
@ -256,15 +271,15 @@ BOOL CDirectInput::IsButtonPressed
// ---------------------------------------------------------------------------
CDirectKeyboard::CDirectKeyboard(
DirectKeyboard::DirectKeyboard(
HWND hwnd
) : \
CDirectInput( hwnd, DIDEVTYPE_KEYBOARD, 256 )
DirectInput( hwnd, DIDEVTYPE_KEYBOARD, 256 )
{
TRACE( "CDirectKeyboard::CDirectKeyboard" );
TRACE( "DirectKeyboard::DirectKeyboard" );
}
HRESULT CDirectKeyboard::Update(
HRESULT DirectKeyboard::Update(
void
)
{
@ -299,23 +314,23 @@ HRESULT CDirectKeyboard::Update(
// ---------------------------------------------------------------------------
CDirectJoystick::CDirectJoystick(
DirectJoystick::DirectJoystick(
HWND hwnd
) : \
CDirectInput( hwnd, DIDEVTYPE_JOYSTICK, 32 )
DirectInput( hwnd, DIDEVTYPE_JOYSTICK, 32 )
{
TRACE( "CDirectJoystick::CDirectJoystick" );
TRACE( "DirectJoystick::DirectJoystick" );
}
HRESULT CDirectJoystick::Initialize(
HRESULT DirectJoystick::Initialize(
void
)
{
TRACE( "CDirectJoystick::Initialize" );
TRACE( "DirectJoystick::Initialize" );
HRESULT hr;
hr = CDirectInput::Initialize();
hr = DirectInput::Initialize();
if ( FAILED(hr) )
{
return hr;
@ -392,7 +407,7 @@ HRESULT CDirectJoystick::Initialize(
return S_OK;
}
HRESULT CDirectJoystick::Update(
HRESULT DirectJoystick::Update(
void
)
{
@ -442,7 +457,7 @@ HRESULT CDirectJoystick::Update(
CDisabledJoystick::CDisabledJoystick(
HWND hwnd
) : \
CDirectInput( NULL, 0, 0 )
DirectInput( NULL, 0, 0 )
{
UNUSED_ALWAYS( hwnd );
@ -458,15 +473,15 @@ HRESULT CDisabledJoystick::Update(
// ---------------------------------------------------------------------------
CDirectMouse::CDirectMouse(
DirectMouse::DirectMouse(
HWND hwnd
) : \
CDirectInput( hwnd, DIDEVTYPE_MOUSE, 4 )
DirectInput( hwnd, DIDEVTYPE_MOUSE, 4 )
{
TRACE( "CDirectMouse::CDirectMouse" );
TRACE( "DirectMouse::DirectMouse" );
}
HRESULT CDirectMouse::Update(
HRESULT DirectMouse::Update(
void
)
{

View File

@ -13,17 +13,19 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DirectInput.hxx,v 1.2 2003-09-21 14:33:34 stephena Exp $
// $Id: DirectInput.hxx,v 1.3 2003-11-11 18:55:39 stephena Exp $
//============================================================================
#ifndef DIRECT_INPUT_HXX
#define DIRECT_INPUT_HXX
class CDirectInput
#include "dinput.h"
class DirectInput
{
public:
CDirectInput( HWND hwnd, DWORD dwDevType, int nButtonCount );
virtual ~CDirectInput( );
DirectInput( HWND hwnd, DWORD dwDevType, int nButtonCount );
virtual ~DirectInput( );
public:
virtual HRESULT Initialize( void );
@ -62,12 +64,12 @@ private:
BOOL m_fInitialized;
CDirectInput( const CDirectInput& ); // no implementation
void operator=( const CDirectInput& ); // no implementation
DirectInput( const DirectInput& ); // no implementation
void operator=( const DirectInput& ); // no implementation
};
inline int CDirectInput::GetButtonCount(
inline int DirectInput::GetButtonCount(
void
) const
{
@ -75,7 +77,7 @@ inline int CDirectInput::GetButtonCount(
}
inline IDirectInputDevice2* CDirectInput::GetDevice(
inline IDirectInputDevice2* DirectInput::GetDevice(
void
) const
{
@ -84,7 +86,7 @@ inline IDirectInputDevice2* CDirectInput::GetDevice(
return m_piDID;
}
inline void CDirectInput::GetPos(
inline void DirectInput::GetPos(
LONG* pX,
LONG* pY
) const
@ -103,41 +105,41 @@ inline void CDirectInput::GetPos(
// ---------------------------------------------------------------------------
class CDirectMouse : public CDirectInput
class DirectMouse : public DirectInput
{
public:
CDirectMouse( HWND hwnd );
DirectMouse( HWND hwnd );
HRESULT Update( void );
private:
CDirectMouse( const CDirectMouse& ); // no implementation
void operator=( const CDirectMouse& ); // no implementation
DirectMouse( const DirectMouse& ); // no implementation
void operator=( const DirectMouse& ); // no implementation
};
// ---------------------------------------------------------------------------
class CDirectJoystick : public CDirectInput
class DirectJoystick : public DirectInput
{
public:
CDirectJoystick( HWND hwnd );
DirectJoystick( HWND hwnd );
HRESULT Initialize( void );
HRESULT Update( void );
private:
CDirectJoystick( const CDirectJoystick& ); // no implementation
void operator=( const CDirectJoystick& ); // no implementation
DirectJoystick( const DirectJoystick& ); // no implementation
void operator=( const DirectJoystick& ); // no implementation
};
class CDisabledJoystick : public CDirectInput
class CDisabledJoystick : public DirectInput
{
public:
@ -154,18 +156,18 @@ private:
// ---------------------------------------------------------------------------
class CDirectKeyboard : public CDirectInput
class DirectKeyboard : public DirectInput
{
public:
CDirectKeyboard( HWND hwnd );
DirectKeyboard( HWND hwnd );
HRESULT Update( void );
private:
CDirectKeyboard( const CDirectKeyboard& ); // no implementation
void operator=( const CDirectKeyboard& ); // no implementation
DirectKeyboard( const DirectKeyboard& ); // no implementation
void operator=( const DirectKeyboard& ); // no implementation
};

View File

@ -0,0 +1,606 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-1999 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferWin32.cxx,v 1.1 2003-11-11 18:55:39 stephena Exp $
//============================================================================
#include <SDL.h>
#include <SDL_syswm.h>
#include <sstream>
#include "Console.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferWin32.hxx"
#include "MediaSrc.hxx"
#include "Settings.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferWin32::FrameBufferWin32()
: theZoomLevel(1),
theMaxZoomLevel(1),
isFullscreen(false)
{
cerr << "FrameBufferWin32::FrameBufferWin32()\n";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferWin32::~FrameBufferWin32()
{
cerr << "FrameBufferWin32::~FrameBufferWin32()\n";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferWin32::init()
{
cerr << "FrameBufferWin32::init()\n";
return false;
#if 0
// Get the desired width and height of the display
myWidth = myMediaSource->width() << 1;
myHeight = myMediaSource->height();
// Now create the software SDL screen
Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
if(SDL_Init(initflags) < 0)
return false;
// Check which system we are running under
x11Available = false;
/* SDL_VERSION(&myWMInfo.version);
if(SDL_GetWMInfo(&myWMInfo) > 0)
if(myWMInfo.subsystem == SDL_SYSWM_X11)
x11Available = true;
*/
// Get the maximum size of a window for THIS screen
theMaxZoomLevel = maxWindowSizeForScreen();
// Check to see if window size will fit in the screen
if((uInt32)myConsole->settings().getInt("zoom") > theMaxZoomLevel)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel = myConsole->settings().getInt("zoom");
mySDLFlags = SDL_SWSURFACE;
mySDLFlags |= myConsole->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0;
// Set up the rectangle list to be used in the dirty update
myRectList = new RectList();
if(!myRectList)
{
cerr << "ERROR: Unable to get memory for SDL rects" << endl;
return false;
}
// Set the window title and icon
ostringstream name;
name << "Stella: \"" << myConsole->properties().get("Cartridge.Name") << "\"";
SDL_WM_SetCaption(name.str().c_str(), "stella");
// Create the screen
if(!createScreen())
return false;
setupPalette(1.0);
// Make sure that theUseFullScreenFlag sets up fullscreen mode correctly
theGrabMouseIndicator = myConsole->settings().getBool("grabmouse");
theHideCursorIndicator = myConsole->settings().getBool("hidecursor");
if(myConsole->settings().getBool("fullscreen"))
{
grabMouse(true);
showCursor(false);
isFullscreen = true;
}
else
{
// Keep mouse in game window if grabmouse is selected
grabMouse(theGrabMouseIndicator);
// Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!theHideCursorIndicator);
}
// Center the window if centering is selected and not fullscreen
if(myConsole->settings().getBool("center") &&
!myConsole->settings().getBool("fullscreen"))
centerScreen();
return true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::drawMediaSource()
{
cerr << "FrameBufferWin32::drawMediaSource()\n";
#if 0
uInt8* currentFrame = myMediaSource->currentFrameBuffer();
uInt8* previousFrame = myMediaSource->previousFrameBuffer();
uInt16 screenMultiple = (uInt16) theZoomLevel;
uInt32 width = myMediaSource->width();
uInt32 height = myMediaSource->height();
struct Rectangle
{
uInt8 color;
uInt16 x, y, width, height;
} rectangles[2][160];
// This array represents the rectangles that need displaying
// on the current scanline we're processing
Rectangle* currentRectangles = rectangles[0];
// This array represents the rectangles that are still active
// from the previous scanlines we have processed
Rectangle* activeRectangles = rectangles[1];
// Indicates the number of active rectangles
uInt16 activeCount = 0;
// This update procedure requires theWidth to be a multiple of four.
// This is validated when the properties are loaded.
for(uInt16 y = 0; y < height; ++y)
{
// Indicates the number of current rectangles
uInt16 currentCount = 0;
// Look at four pixels at a time to see if anything has changed
uInt32* current = (uInt32*)(currentFrame);
uInt32* previous = (uInt32*)(previousFrame);
for(uInt16 x = 0; x < width; x += 4, ++current, ++previous)
{
// Has something changed in this set of four pixels?
if((*current != *previous) || theRedrawEntireFrameIndicator)
{
uInt8* c = (uInt8*)current;
uInt8* p = (uInt8*)previous;
// Look at each of the bytes that make up the uInt32
for(uInt16 i = 0; i < 4; ++i, ++c, ++p)
{
// See if this pixel has changed
if((*c != *p) || theRedrawEntireFrameIndicator)
{
// Can we extend a rectangle or do we have to create a new one?
if((currentCount != 0) &&
(currentRectangles[currentCount - 1].color == *c) &&
((currentRectangles[currentCount - 1].x +
currentRectangles[currentCount - 1].width) == (x + i)))
{
currentRectangles[currentCount - 1].width += 1;
}
else
{
currentRectangles[currentCount].x = x + i;
currentRectangles[currentCount].y = y;
currentRectangles[currentCount].width = 1;
currentRectangles[currentCount].height = 1;
currentRectangles[currentCount].color = *c;
currentCount++;
}
}
}
}
}
// Merge the active and current rectangles flushing any that are of no use
uInt16 activeIndex = 0;
for(uInt16 t = 0; (t < currentCount) && (activeIndex < activeCount); ++t)
{
Rectangle& current = currentRectangles[t];
Rectangle& active = activeRectangles[activeIndex];
// Can we merge the current rectangle with an active one?
if((current.x == active.x) && (current.width == active.width) &&
(current.color == active.color))
{
current.y = active.y;
current.height = active.height + 1;
++activeIndex;
}
// Is it impossible for this active rectangle to be merged?
else if(current.x >= active.x)
{
// Flush the active rectangle
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, palette[active.color]);
++activeIndex;
}
}
// Flush any remaining active rectangles
for(uInt16 s = activeIndex; s < activeCount; ++s)
{
Rectangle& active = activeRectangles[s];
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, palette[active.color]);
}
// We can now make the current rectangles into the active rectangles
Rectangle* tmp = currentRectangles;
currentRectangles = activeRectangles;
activeRectangles = tmp;
activeCount = currentCount;
currentFrame += width;
previousFrame += width;
}
// Flush any rectangles that are still active
for(uInt16 t = 0; t < activeCount; ++t)
{
Rectangle& active = activeRectangles[t];
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, palette[active.color]);
}
// The frame doesn't need to be completely redrawn anymore
theRedrawEntireFrameIndicator = false;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::preFrameUpdate()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::postFrameUpdate()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferWin32::createScreen()
{
return false;
#if 0
int w = myWidth * theZoomLevel;
int h = myHeight * theZoomLevel;
myScreen = SDL_SetVideoMode(w, h, 0, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
return false;
}
theRedrawEntireFrameIndicator = true;
return true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::setupPalette(float shade)
{
#if 0
const uInt32* gamePalette = myMediaSource->palette();
for(uInt32 i = 0; i < 256; ++i)
{
Uint8 r, g, b;
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
switch(myScreen->format->BitsPerPixel)
{
case 15:
palette[i] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
break;
case 16:
palette[i] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
break;
case 24:
case 32:
palette[i] = (r << 16) | (g << 8) | b;
break;
}
}
theRedrawEntireFrameIndicator = true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::pause(bool status)
{
#if 0
myPauseStatus = status;
// Shade the palette to 75% normal value in pause mode
if(myPauseStatus)
setupPalette(0.75);
else
setupPalette(1.0);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::toggleFullscreen()
{
#if 0
isFullscreen = !isFullscreen;
if(isFullscreen)
mySDLFlags |= SDL_FULLSCREEN;
else
mySDLFlags &= ~SDL_FULLSCREEN;
if(!createScreen())
return;
if(isFullscreen) // now in fullscreen mode
{
grabMouse(true);
showCursor(false);
}
else // now in windowed mode
{
grabMouse(theGrabMouseIndicator);
showCursor(!theHideCursorIndicator);
if(myConsole->settings().getBool("center"))
centerScreen();
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::resize(int mode)
{
#if 0
// reset size to that given in properties
// this is a special case of allowing a resize while in fullscreen mode
if(mode == 0)
{
myWidth = myMediaSource->width() << 1;
myHeight = myMediaSource->height();
}
else if(mode == 1) // increase size
{
if(isFullscreen)
return;
if(theZoomLevel == theMaxZoomLevel)
theZoomLevel = 1;
else
theZoomLevel++;
}
else if(mode == -1) // decrease size
{
if(isFullscreen)
return;
if(theZoomLevel == 1)
theZoomLevel = theMaxZoomLevel;
else
theZoomLevel--;
}
if(!createScreen())
return;
// A resize may mean that the window is no longer centered
isCentered = false;
if(myConsole->settings().getBool("center"))
centerScreen();
// Now update the settings
ostringstream tmp;
tmp << theZoomLevel;
myConsole->settings().set("zoom", tmp.str());
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::showCursor(bool show)
{
#if 0
if(isFullscreen)
return;
if(show)
SDL_ShowCursor(SDL_ENABLE);
else
SDL_ShowCursor(SDL_DISABLE);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::grabMouse(bool grab)
{
#if 0
if(isFullscreen)
return;
if(grab)
SDL_WM_GrabInput(SDL_GRAB_ON);
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferWin32::maxWindowSizeForScreen()
{
return 1;
#if 0
if(!x11Available)
return 1;
/* FIXME
// Otherwise, lock the screen and get the width and height
myWMInfo.info.x11.lock_func();
Display* theX11Display = myWMInfo.info.x11.display;
myWMInfo.info.x11.unlock_func();
int screenWidth = DisplayWidth(theX11Display, DefaultScreen(theX11Display));
int screenHeight = DisplayHeight(theX11Display, DefaultScreen(theX11Display));
uInt32 multiplier = screenWidth / myWidth;
bool found = false;
while(!found && (multiplier > 0))
{
// Figure out the desired size of the window
int width = myWidth * multiplier;
int height = myHeight * multiplier;
if((width < screenWidth) && (height < screenHeight))
found = true;
else
multiplier--;
}
if(found)
return multiplier;
else
return 1;
*/
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
cerr << "FrameBufferWin32::drawBoundedBox()\n";
#if 0
SDL_Rect tmp;
// Scale all values to the current window size
x *= theZoomLevel;
y *= theZoomLevel;
w *= theZoomLevel;
h *= theZoomLevel;
// First draw the underlying box
tmp.x = x;
tmp.y = y;
tmp.w = w;
tmp.h = h;
myRectList->add(&tmp);
SDL_FillRect(myScreen, &tmp, palette[bg]);
// Now draw the bounding sides
tmp.x = x;
tmp.y = y;
tmp.w = w;
tmp.h = theZoomLevel;
SDL_FillRect(myScreen, &tmp, palette[fg]); // top
tmp.x = x;
tmp.y = y + h - theZoomLevel;
tmp.w = w;
tmp.h = theZoomLevel;
SDL_FillRect(myScreen, &tmp, palette[fg]); // bottom
tmp.x = x;
tmp.y = y;
tmp.w = theZoomLevel;
tmp.h = h;
SDL_FillRect(myScreen, &tmp, palette[fg]); // left
tmp.x = x + w - theZoomLevel;
tmp.y = y;
tmp.w = theZoomLevel;
tmp.h = h;
SDL_FillRect(myScreen, &tmp, palette[fg]); // right
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::drawText(uInt32 xorig, uInt32 yorig, const string& message)
{
cerr << "FrameBufferWin32::drawText()\n";
#if 0
SDL_Rect tmp;
uInt8 length = message.length();
for(uInt32 x = 0; x < length; x++)
{
for(uInt32 y = 0; y < 8; y++)
{
for(uInt32 z = 0; z < 8; z++)
{
char letter = message[x];
if((ourFontData[(letter << 3) + y] >> z) & 1)
{
// myFrameBuffer[(y + yorig)*myWidth + (x<<3) + z + xorig] = 0xF0F0F0;
tmp.x = ((x<<3) + z + xorig) * theZoomLevel;
tmp.y = (y + yorig) * theZoomLevel;
tmp.w = tmp.h = theZoomLevel;
SDL_FillRect(myScreen, &tmp, palette[fg]);
// FIXME - this can be a lot more efficient
}
}
}
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferWin32::drawChar(uInt32 xorig, uInt32 yorig, uInt32 c)
{
cerr << "FrameBufferWin32::drawChar()\n";
#if 0
if(c >= 256 )
return;
SDL_Rect tmp;
for(uInt32 y = 0; y < 8; y++)
{
for(uInt32 z = 0; z < 8; z++)
{
if((ourFontData[(c << 3) + y] >> z) & 1)
{
// myFrameBuffer[(y + yorig)*myWidth + z + xorig] = 0xF0F0F0;
tmp.x = (z + xorig) * theZoomLevel;
tmp.y = (y + yorig) * theZoomLevel;
tmp.w = tmp.h = theZoomLevel;
myRectList->add(&tmp);
SDL_FillRect(myScreen, &tmp, palette[fg]);
// FIXME - this can be a lot more efficient
}
}
}
#endif
}

View File

@ -0,0 +1,187 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-1999 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferWin32.hxx,v 1.1 2003-11-11 18:55:39 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_WIN32_HXX
#define FRAMEBUFFER_WIN32_HXX
#include "FrameBuffer.hxx"
#include "bspf.hxx"
class Console;
class MediaSource;
class FrameBufferWin32 : public FrameBuffer
{
public:
/**
Creates a new DirectDraw framebuffer
*/
FrameBufferWin32();
/**
Destructor
*/
virtual ~FrameBufferWin32();
/**
This routine should be called once the console is created to setup
the video system for us to use. Return false if any operation fails,
otherwise return true.
*/
virtual bool init();
/**
This routine should be called anytime the MediaSource needs to be redrawn
to the screen.
*/
virtual void drawMediaSource();
/**
This routine should be called to draw a rectangular box with sides
at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param w The width of the box
@param h The height of the box
*/
virtual void drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
/**
This routine should be called to draw text at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param message The message text
*/
virtual void drawText(uInt32 x, uInt32 y, const string& message);
/**
This routine should be called to draw character 'c' at the specified coordinates.
@param x The x coordinate
@param y The y coordinate
@param c The character to draw
*/
virtual void drawChar(uInt32 x, uInt32 y, uInt32 c);
/**
This routine is called before any drawing is done (per-frame).
*/
virtual void preFrameUpdate();
/**
This routine is called after any drawing is done (per-frame).
*/
virtual void postFrameUpdate();
/**
This routine is called when the emulation has been paused.
@param status Toggle pause based on status
*/
virtual void pause(bool status);
/**
Toggles between fullscreen and window mode. Grabmouse and hidecursor
activated when in fullscreen mode.
*/
void toggleFullscreen();
/**
This routine is called when the user wants to resize the window.
A '1' argument indicates that the window should increase in size, while '-1'
indicates that the windows should decrease in size. A '0' indicates that
the window should be sized according to the current properties.
Can't resize in fullscreen mode. Will only resize up to the maximum size
of the screen.
*/
void resize(int mode);
/**
Shows or hides the cursor based on the given boolean value.
*/
void showCursor(bool show);
/**
Grabs or ungrabs the mouse based on the given boolean value.
*/
void grabMouse(bool grab);
/**
Answers if the display is currently in fullscreen mode.
*/
bool fullScreen() { return isFullscreen; }
/**
Answers the current zoom level of the SDL
*/
uInt32 zoomLevel() { return theZoomLevel; }
/**
This routine is called whenever the screen needs to be recreated.
It updates the global screen variable.
*/
bool createScreen();
/**
Calculate the maximum window size that the current screen can hold.
Only works in X11 for now. If not running under X11, always return 4.
*/
uInt32 maxWindowSizeForScreen();
/**
Set up the palette for a screen of any depth > 8.
Scales the palette by 'shade'.
*/
void setupPalette(float shade);
private:
// The SDL video buffer
// SDL_Surface* myScreen;
// Used in the dirty update of the SDL surface
// RectList* myRectList;
// SDL initialization flags
// uInt32 mySDLFlags;
// SDL palette
// Uint32 palette[256];
// Used to get window-manager specifics
// SDL_SysWMinfo myWMInfo;
// Indicates the current zoom level of the SDL screen
uInt32 theZoomLevel;
// Indicates the maximum zoom of the SDL screen
uInt32 theMaxZoomLevel;
// Indicates if the mouse should be grabbed
bool theGrabMouseIndicator;
// Indicates if the mouse cursor should be hidden
bool theHideCursorIndicator;
// Indicates whether the game is currently in fullscreen
bool isFullscreen;
};
#endif