- Yeeeha! Finally tackled that damn No-ENTER problem!

- Added a Tooltip for the Play button as requested by Thomas :-)
- Items are now sorted even when stella.pro is missing.
-Aded a warning message  when stella.pro is missing.
- Display states are updated: Now correct path and # games are shown.
- Built in Gunfight, Thrust, Jammed & Qb with permission from their authors.
- The usual minor changes here and there...
- updated Cyberstella readme.txt with tons of feature requests and todos...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@87 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
gunfight 2002-05-09 16:11:10 +00:00
parent 6fef5ab191
commit 70ab28879f
14 changed files with 392 additions and 148 deletions

View File

@ -66,9 +66,10 @@ LINK32=link.exe
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /FR /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\games" /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /FR /FD /GZ /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
@ -631,6 +632,26 @@ SOURCE=..\sound\TIASound.c
SOURCE=..\sound\TIASound.h
# End Source File
# End Group
# Begin Group "Games"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\games\Gunfight.h
# End Source File
# Begin Source File
SOURCE=..\..\games\Jammed.h
# End Source File
# Begin Source File
SOURCE=..\..\games\Qb.h
# End Source File
# Begin Source File
SOURCE=..\..\games\Thrust.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\..\emucore\m6502\src\bspf\src\bspf.hxx

View File

@ -125,10 +125,17 @@ BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "Configuration"
POPUP "&Configuration"
BEGIN
MENUITEM "&Cyberstella", IDC_CONFIG
END
POPUP "&Games"
BEGIN
MENUITEM "&Gunfight", IDG_GUNFIGHT
MENUITEM "&Jammed", IDG_JAMMED
MENUITEM "&QB", IDG_QB
MENUITEM "&Thrust", IDG_THRUST
END
POPUP "&Help"
BEGIN
MENUITEM "&About Cyberstella...", ID_APP_ABOUT
@ -143,19 +150,19 @@ END
IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL
"X", ID_EDIT_CUT, VIRTKEY, CONTROL
"C", ID_EDIT_COPY, VIRTKEY, CONTROL
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
VK_F6, ID_NEXT_PANE, VIRTKEY
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT
"C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
"N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
"O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
"S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
"X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
END
@ -166,7 +173,7 @@ END
IDD_CYBERSTELLA_FORM DIALOGEX 0, 0, 409, 169
STYLE WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
FONT 8, "MS Shell Dlg"
BEGIN
CONTROL "&Files found in:",-1,"Static",SS_LEFTNOWORDWRAP |
WS_GROUP,7,7,44,8
@ -338,6 +345,11 @@ BEGIN
ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
END
STRINGTABLE DISCARDABLE
BEGIN
IDC_PLAY "Play the currently selected Game\nPlay"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
@ -457,6 +469,7 @@ STRINGTABLE DISCARDABLE
BEGIN
IDS_STATUSTEXT "%d files found"
IDS_STELLA "StellaX"
IDS_NOTETEXT "Note: %s"
IDS_NODIRECTINPUT "DirectInput could not be initialized. Be sure you have DirectX 5.0 or later installed."
IDS_CANTSTARTCONSOLE "Error starting console. You may have chosen an invalid ROM file."
IDS_COINIT_FAILED "Unable to initialize COM subsystem"

View File

@ -3,7 +3,6 @@
#include "pch.hxx"
#include "Cyberstella.h"
#include "CyberstellaDoc.h"
#ifdef _DEBUG

View File

@ -9,6 +9,10 @@
#include "StellaConfig.h"
#include "Console.hxx"
#include "SoundWin32.hxx"
#include "Gunfight.h"
#include "Jammed.h"
#include "Qb.h"
#include "Thrust.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@ -41,6 +45,12 @@ BEGIN_MESSAGE_MAP(CCyberstellaView, CFormView)
ON_BN_CLICKED(IDC_CONFIG, OnConfig)
ON_BN_CLICKED(IDC_PLAY, OnPlay)
ON_WM_DESTROY()
ON_COMMAND(IDG_GUNFIGHT, OnGunfight)
ON_COMMAND(IDG_JAMMED, OnJammed)
ON_COMMAND(IDG_QB, OnQb)
ON_COMMAND(IDG_THRUST, OnThrust)
ON_MESSAGE(MSG_GAMELIST_UPDATE, updateListInfos)
ON_MESSAGE(MSG_GAMELIST_DISPLAYNOTE, displayNote)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
@ -88,14 +98,6 @@ void CCyberstellaView::OnInitialUpdate()
// Init ListControl, parse stella.pro
Initialize();
// Show status text
CString status;
status.Format(IDS_STATUSTEXT, m_List.GetItemCount());
SetDlgItemText(IDC_ROMCOUNT,status);
// Show rom path
//ToDo: SetDlgItemText(IDC_ROMPATH, m_pGlobalData->romDir);
}
/////////////////////////////////////////////////////////////////////////////
@ -125,107 +127,27 @@ void CCyberstellaView::OnConfig()
dlg.DoModal();
}
void CCyberstellaView::OnPlay()
void CCyberstellaView::OnPlay(LONG gameID)
{
EnableWindow(FALSE);
CString fileName = m_List.getCurrentFile();
// Safety Bail Out
if(fileName.GetLength() <= 0) return;
#ifdef USE_FS
CDirectXFullScreen* pwnd = NULL;
#else
CDirectXWindow* pwnd = NULL;
#endif
CString fileName;
BYTE* pImage = NULL;
LPCTSTR pszFileName = NULL;
Console* pConsole = NULL;
Sound* pSound = NULL;
DWORD dwImageSize;
DWORD dwActualSize;
Event rEvent;
// show wait cursor while loading
HCURSOR hcur = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
// Load the rom file
HANDLE hFile;
DWORD dwImageSize;
hFile = ::CreateFile( fileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwLastError = ::GetLastError();
TCHAR pszCurrentDirectory[ MAX_PATH + 1 ];
::GetCurrentDirectory( MAX_PATH, pszCurrentDirectory );
// ::MessageBoxFromGetLastError( pszPathName );
TCHAR pszFormat[ 1024 ];
LoadString(GetModuleHandle(NULL),
IDS_ROM_LOAD_FAILED,
pszFormat, 1023 );
LPTSTR pszLastError = NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pszLastError,
0,
NULL);
TCHAR pszError[ 1024 ];
wsprintf( pszError,
pszFormat,
pszCurrentDirectory,
fileName,
dwLastError,
pszLastError );
::MessageBox( *this,
pszError,
_T("Error"),
MB_OK | MB_ICONEXCLAMATION );
::LocalFree( pszLastError );
goto exit;
}
dwImageSize = ::GetFileSize( hFile, NULL );
pImage = new BYTE[dwImageSize + 1];
if ( pImage == NULL )
{
goto exit;
}
DWORD dwActualSize;
if ( ! ::ReadFile( hFile, pImage, dwImageSize, &dwActualSize, NULL ) )
{
VERIFY( ::CloseHandle( hFile ) );
MessageBoxFromGetLastError(fileName);
goto exit;
}
VERIFY( ::CloseHandle(hFile) );
//
// Create Sound driver object
// (Will be initialized once we have a window handle below)
//
if (m_pGlobalData->bNoSound)
{
TRACE("Creating Sound driver");
@ -241,24 +163,146 @@ void CCyberstellaView::OnPlay()
goto exit;
}
//
// get just the filename
//
// Special handling for special games
switch(gameID)
{
case IDG_GUNFIGHT:
{
pszFileName = "Gunfight";
dwActualSize = sizeof gunfight;
pImage = new BYTE[dwActualSize];
for(int i=0; i<dwActualSize; i++)
{
pImage[i] = gunfight[i]^(pszFileName[i%strlen(pszFileName)]);
}
break;
}
case IDG_JAMMED:
{
pszFileName = "Jammed";
dwActualSize = sizeof jammed;
pImage = new BYTE[dwActualSize];
for(int i=0; i<dwActualSize; i++)
{
pImage[i] = jammed[i]^(pszFileName[i%strlen(pszFileName)]);
}
break;
}
case IDG_QB:
{
pszFileName = "Qb";
dwActualSize = sizeof qb;
pImage = new BYTE[dwActualSize];
for(int i=0; i<dwActualSize; i++)
{
pImage[i] = qb[i]^(pszFileName[i%strlen(pszFileName)]);
}
break;
}
case IDG_THRUST:
{
pszFileName = "Thrust";
dwActualSize = sizeof thrust;
pImage = new BYTE[dwActualSize];
for(int i=0; i<dwActualSize; i++)
{
pImage[i] = thrust[i]^(pszFileName[i%strlen(pszFileName)]);
}
break;
}
default:
{
fileName = m_List.getCurrentFile();
pszFileName = _tcsrchr( fileName, _T('\\') );
if ( pszFileName )
{
++pszFileName;
}
else
{
pszFileName = fileName;
// Safety Bail Out
if(fileName.GetLength() <= 0) return;
// Load the rom file
HANDLE hFile;
hFile = ::CreateFile( fileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwLastError = ::GetLastError();
TCHAR pszCurrentDirectory[ MAX_PATH + 1 ];
::GetCurrentDirectory( MAX_PATH, pszCurrentDirectory );
// ::MessageBoxFromGetLastError( pszPathName );
TCHAR pszFormat[ 1024 ];
LoadString(GetModuleHandle(NULL),
IDS_ROM_LOAD_FAILED,
pszFormat, 1023 );
LPTSTR pszLastError = NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pszLastError,
0,
NULL);
TCHAR pszError[ 1024 ];
wsprintf( pszError,
pszFormat,
pszCurrentDirectory,
fileName,
dwLastError,
pszLastError );
::MessageBox( *this,
pszError,
_T("Error"),
MB_OK | MB_ICONEXCLAMATION );
::LocalFree( pszLastError );
goto exit;
}
dwImageSize = ::GetFileSize( hFile, NULL );
pImage = new BYTE[dwImageSize + 1];
if ( pImage == NULL )
{
goto exit;
}
if ( ! ::ReadFile( hFile, pImage, dwImageSize, &dwActualSize, NULL ) )
{
VERIFY( ::CloseHandle( hFile ) );
MessageBoxFromGetLastError(fileName);
goto exit;
}
VERIFY( ::CloseHandle(hFile) );
}
// get just the filename
pszFileName = _tcsrchr( fileName, _T('\\') );
if ( pszFileName )
{
++pszFileName;
}
else
{
pszFileName = fileName;
}
}
try
{
// If this throws an exception, then it's probably a bad cartridge
pConsole = new Console( pImage,
dwActualSize,
pszFileName,
@ -334,11 +378,6 @@ void CCyberstellaView::OnPlay()
}
}
// restore cursor
::SetCursor( hcur );
hcur = NULL;
::ShowWindow( *this, SW_HIDE );
(void)pwnd->Run();
@ -346,14 +385,7 @@ void CCyberstellaView::OnPlay()
::ShowWindow( *this, SW_SHOW );
exit:
if ( hcur )
{
::SetCursor( hcur );
}
delete pwnd;
delete pConsole;
delete pSound;
delete pImage;
@ -398,7 +430,7 @@ void CCyberstellaView::Initialize()
m_List.init(m_pPropertiesSet,this);
// Try to load the file stella.pro file
string filename( "stella.pro" );
string filename("stella.pro");
// See if we can open the file and load properties from it
ifstream stream(filename.c_str());
@ -411,6 +443,7 @@ void CCyberstellaView::Initialize()
else
{
m_pPropertiesSet->load("", &Console::defaultProperties());
MessageBox("stella.pro not found in working directory!", "Warning!", MB_OK|MB_ICONEXCLAMATION);
}
// Fill our game list
@ -422,3 +455,46 @@ void CCyberstellaView::OnDestroy()
CFormView::OnDestroy();
m_List.deleteItemsAndProperties();
}
void CCyberstellaView::updateListInfos()
{
// Show status text
CString status;
status.Format(IDS_STATUSTEXT, m_List.getRomCount());
SetDlgItemText(IDC_ROMCOUNT,status);
// Show rom path
SetDlgItemText(IDC_ROMPATH, m_List.getPath());
}
void CCyberstellaView::displayNote()
{
// Show rom path
CString note;
note.Format(IDS_NOTETEXT, m_List.getCurrentNote());
((CMainFrame*)AfxGetMainWnd())->setStatusText(note);
}
void CCyberstellaView::OnGunfight()
{
OnPlay(IDG_GUNFIGHT);
MessageBox("If you'd like to play Gunfight on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK);
}
void CCyberstellaView::OnJammed()
{
OnPlay(IDG_JAMMED);
MessageBox("If you'd like to play Jammed on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK);
}
void CCyberstellaView::OnQb()
{
OnPlay(IDG_QB);
MessageBox("If you'd like to play Qb on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK);
}
void CCyberstellaView::OnThrust()
{
OnPlay(IDG_THRUST);
MessageBox("If you'd like to play Thrust on a real VCS, you can order a cartridge for only $25\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK);
}

View File

@ -58,8 +58,12 @@ protected:
protected:
//{{AFX_MSG(CCyberstellaView)
afx_msg void OnConfig();
afx_msg void OnPlay();
afx_msg void OnPlay(LONG gameID);
afx_msg void OnDestroy();
afx_msg void OnGunfight();
afx_msg void OnJammed();
afx_msg void OnQb();
afx_msg void OnThrust();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
@ -67,6 +71,9 @@ private:
// methods
void togglePause();
void Initialize();
void updateListInfos();
void displayNote();
// members
PropertiesSet* m_pPropertiesSet;
bool m_bIsPause;

View File

@ -29,7 +29,7 @@ BEGIN_MESSAGE_MAP(GameList, CListCtrl)
//{{AFX_MSG_MAP(GameList)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
ON_NOTIFY_REFLECT(LVN_ITEMACTIVATE, OnItemActivate)
ON_WM_KEYDOWN()
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
@ -126,6 +126,8 @@ void GameList::populateRomList()
// Select first item
SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
m_pParent->SendMessage(MSG_GAMELIST_UPDATE);
}
void GameList::displayPath()
@ -145,6 +147,9 @@ void GameList::displayPath()
bFind = find.FindFile(searchpath);
// Init Rom count
m_RomCount = 0;
while (bFind)
{
bFind = find.FindNextFile();
@ -197,6 +202,13 @@ void GameList::displayPath()
lvi.iSubItem = 1;
name = props->get("Cartridge.Name").c_str();
// If entry is not found in stella.pro, set filename
if(strcmpi(name,"untitled") == 0)
{
props->set("Cartridge.Name", find.GetFileName().GetBuffer(name.GetLength()));
}
lvi.pszText = name.GetBuffer(name.GetLength());
SetItem(&lvi);
@ -209,6 +221,8 @@ void GameList::displayPath()
name = props->get("Cartridge.Rarity").c_str();
lvi.pszText = name.GetBuffer(name.GetLength());
SetItem(&lvi);
m_RomCount++;
}
}
@ -380,7 +394,17 @@ CString GameList::getCurrentName()
{
return GetItemText(curSel,1);
}
return "";
}
CString GameList::getCurrentNote()
{
int curSel = GetSelectionMark();
if(curSel >= 0)
{
Properties* props = (Properties*)GetItemData(curSel);
return props->get("Cartridge.Note").c_str();
}
return "";
}
@ -390,4 +414,29 @@ void GameList::init(PropertiesSet* newPropertiesSet, CWnd* newParent)
m_pPropertiesSet = newPropertiesSet;
SetExtendedStyle(LVS_EX_FULLROWSELECT);
insertColumns();
}
void GameList::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
m_pParent->SendMessage(MSG_GAMELIST_DISPLAYNOTE);
*pResult = 0;
}
BOOL GameList::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_RETURN)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
return TRUE; // DO NOT process further
}
}
return CListCtrl::PreTranslateMessage(pMsg);
}

View File

@ -18,6 +18,7 @@ class GameList : public CListCtrl
private:
// memebers saved in registry
CString m_Path;
int m_RomCount;
CWnd* m_pParent;
PropertiesSet* m_pPropertiesSet;
@ -33,6 +34,11 @@ private:
public:
GameList();
virtual ~GameList();
// Methods
CString getCurrentNote();
CString getPath() {return m_Path;}
int getRomCount() {return m_RomCount;}
// Operations
public:
@ -40,6 +46,8 @@ public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(GameList)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
// Implementation
@ -56,6 +64,7 @@ protected:
//{{AFX_MSG(GameList)
afx_msg void OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnItemActivate(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

View File

@ -157,7 +157,7 @@ void CHyperLink::PreSubclassWindow()
SetDefaultCursor(); // Try and load up a "hand" cursor
// Create the tooltip
CRect rect;
CRect rect;
GetClientRect(rect);
m_ToolTip.Create(this);
m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

View File

@ -98,9 +98,9 @@ void CMainFrame::Dump(CDumpContext& dc) const
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
void CMainFrame::setStatusText(CString text)
{
m_wndStatusBar.SetWindowText(text);
}
#endif //_DEBUG
}

View File

@ -31,7 +31,6 @@ public:
// Implementation
public:
virtual ~CMainFrame();
void setStatusText(CString text);
#ifdef _DEBUG

View File

@ -2,10 +2,6 @@ Cyberstella V1.2
Currently Open Todos:
Urgent:
- Make Listcontrol react on ENTER
- Update Displays when list changes
Later:
- More Columns / Advanced sorting
- Clean OnPlay Routine
@ -15,4 +11,71 @@ Later:
- Add Screenshots - F12
- Add Pause - F3
- Add Fullscreen / Windowed mode -F4
- Check Direct Draw implementation
- Check Direct Draw implementation / upgrade to DX8
ToDos from Brad Mott:
- Is the keyboard mapping correct (e.g., do both of the Joysticks
work via the keyboard)
- Can you have two PC controllers connected?
- Finish the windowed version of StellaX (e.g., so that it'll run in
a window as well as fullscreen)
- Improve the DirectSound support
- Provide custom keyboard / controller mapping (e.g., be able to
map joystick buttons to the 2600 Select/Reset as well as the
other 2600 functions...)
Own Ideas:
->Private Mail to Stephen Anthony
Suggestions from Brian Luttrull:
Are you planning or would you be interested in adding
more features to the front end of Stella? For
example, the ability to display screenshots, cart
pics, docs, details, etc. The Kstella frontend has
these features and the very friendly and helpful
author, Stephen Anthony, said you would be free to
take ideas and code from his frontend (under GPL).
Suggestions from Glenn Saunders:
A couple things I'd like to see in a 2600 emulator that Brad was working on
in ActiveStella are scanline emulation and better controller mapping.
Scanline emulation is pretty easy. You just use a 256 color palette where
the scanline emulation lines are half the brightness as the regular palette
items the 2600 uses. I think with scanline emulation it looks a lot more
authentic and less sterile. That's what they did with Atari Arcade Hits.
Brad should have some of that code already. Maybe he'll give the code to
you.
As for controller mapping, are you using Direct Input at all? With Direct
Input you'd be able to support anything the OS does rather than, let's say,
directly polling the mouse port or the joystick port and expecting
something to be there. A lot of people (myself included) use USB
peripherals. Via a USB hub it might be possible to, for instance, connect
4 trackballs at once to use as paddles for Warlords. So Direct Input
automatically polls the system for controllers so you just ask Direct Input
what's available. You don't have to hardcode anything in there. You get
an inventory of what the system has, and from that you can present various
mapping choices.
P.S. The coolest part of ActiveStella, of course, was it being an ActiveX
control. So the GUI is not built into it. You could put it on a webpage
and drive it with Javascript or put it into a Director projector file or
write a skinnable UI container. It supported both a windowed and
fullscreen mode. Brad never got ActiveStella running stable. This was the
time when DirectX was in a lot of transition as well as operating systems
(98->2000). I think it's a little easier to write stable code that works
on XP/2000/Me these days.
He was also talking about a way to hook a scripting language into the
emulator that you could use almost like a software logic analyzer. You
could configure the script to trigger on certain events, like accesses to
various memory locations. This would have a lot of uses for debugging, of
course, but also provide the foundation for high score saving. If you knew
where the score was stored in each game, and where the level byte was, and
you knew the state of the machine when the game ends, then you could
trigger script that plucks the score out to save it into a global high
score table. At the time we were discussing it we were concerned that this
might slow the emulator down too much but today I think it wouldn't be an
issue. I'd really like to see this happen...

View File

@ -5,7 +5,6 @@
#include "pch.hxx"
#include <stdio.h>
#include <stdarg.h>
#include "resource.h"
// This will force in the DirectX library

View File

@ -38,6 +38,10 @@
#include <dsound.h>
#include <dinput.h>
// Stella Messages:
#define MSG_GAMELIST_UPDATE WM_USER+0x100
#define MSG_GAMELIST_DISPLAYNOTE WM_USER+0x101
#define _countof(array) (sizeof(array)/sizeof(array[0]))
// ---------------------------------------------------------------------------

View File

@ -27,6 +27,7 @@
#define IDS_RARITY 284
#define IDS_STATUSTEXT 289
#define IDS_STELLA 290
#define IDS_NOTETEXT 291
#define IDS_NODIRECTINPUT 293
#define IDS_CANTSTARTCONSOLE 295
#define IDS_COINIT_FAILED 296
@ -54,6 +55,10 @@
#define IDC_AUTO_SELECT_VIDEOMODE 1020
#define IDC_BROWSE 1021
#define ID_BUTTON32774 32774
#define IDG_GUNFIGHT 32775
#define IDG_JAMMED 32776
#define IDG_QB 32777
#define IDG_THRUST 32778
// Next default values for new objects
//
@ -61,7 +66,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 134
#define _APS_NEXT_COMMAND_VALUE 32775
#define _APS_NEXT_COMMAND_VALUE 32780
#define _APS_NEXT_CONTROL_VALUE 1005
#define _APS_NEXT_SYMED_VALUE 101
#endif