The first version of a GUI for event remapping is here!

Now for the things that aren't finished yet:

 - Only the most basic functions can be remapped.  If you
erase the mapping for those that can't yet be remapped,
you'll have to delete the 'keymap' line from stellarc and
start over.

 - Core events can only be remapped to other keys on the keyboard.
I haven't got the joystick remapping working yet (but it should
be easy to do).

 - The TIA needs to be modified to show 320 pixels horizontally.
Right now, I'm using 8 pixel-width fonts on a framebuffer of
160 pixels, so there's not a lot of horizontal real estate.
So text will probably overwrite other stuff.  This is cosmetic,
and WILL be fixed.

 - Modification of the TIA will break every frontends rendering
code.  It had to be done sometime ...

 - I haven't yet added any user feedback mechanism for the user.  So when
you go into remap mode and are about to remap a key, you won't
know it :)  I'll be adding arrows (like in XMAME) ...

I've added a "Game Information" menu, which shows things like Game name,
manufacturer, rarity, type, etc.  Basically stuff from the stella.pro file.
It has no purpose other than for coolness :)


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@193 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2003-09-28 21:59:24 +00:00
parent b9f5cbb1fe
commit 4b7a2c475c
7 changed files with 434 additions and 274 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: EventHandler.cxx,v 1.13 2003-09-26 22:39:36 stephena Exp $ // $Id: EventHandler.cxx,v 1.14 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#include <algorithm> #include <algorithm>
@ -49,9 +49,8 @@ EventHandler::EventHandler(Console* console)
myKeyTable[i] = Event::NoType; myKeyTable[i] = Event::NoType;
// Erase the JoyEvent array // Erase the JoyEvent array
for(i = 0; i < StellaEvent::LastJSTICK; ++i) for(i = 0; i < StellaEvent::LastJSTICK*StellaEvent::LastJCODE; ++i)
for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j) myJoyTable[i] = Event::NoType;
myJoyTable[i][j] = Event::NoType;
// Erase the Message array // Erase the Message array
for(i = 0; i < Event::LastType; ++i) for(i = 0; i < Event::LastType; ++i)
@ -67,6 +66,9 @@ EventHandler::EventHandler(Console* console)
setKeymap(); setKeymap();
setJoymap(); setJoymap();
// Now send the filled event arrays to the GUI for display and remapping
// myConsole->gui().
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -74,8 +76,6 @@ EventHandler::~EventHandler()
{ {
if(myEvent) if(myEvent)
delete myEvent; delete myEvent;
myEvent = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -110,7 +110,7 @@ void EventHandler::sendJoyEvent(StellaEvent::JoyStick stick,
if(myMenuStatus) if(myMenuStatus)
myConsole->gui().sendJoyEvent(stick, code, state); myConsole->gui().sendJoyEvent(stick, code, state);
else else
sendEvent(myJoyTable[stick][code], state); sendEvent(myJoyTable[stick*StellaEvent::LastJCODE + code], state);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -202,13 +202,10 @@ void EventHandler::setJoymap()
string key; string key;
// Fill the joymap table with events // Fill the joymap table with events
for(Int32 i = 0; i < StellaEvent::LastJSTICK; ++i) for(Int32 i = 0; i < StellaEvent::LastJSTICK*StellaEvent::LastJCODE; ++i)
{
for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j)
{ {
buf >> key; buf >> key;
myJoyTable[i][j] = (Event::Type) atoi(key.c_str()); myJoyTable[i] = (Event::Type) atoi(key.c_str());
}
} }
} }
else else
@ -234,14 +231,28 @@ string EventHandler::getJoymap()
ostringstream buf; ostringstream buf;
// Iterate through the joymap table and create a colon-separated list // Iterate through the joymap table and create a colon-separated list
for(Int32 i = 0; i < StellaEvent::LastJSTICK; ++i) for(Int32 i = 0; i < StellaEvent::LastJSTICK*StellaEvent::LastJCODE; ++i)
for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j) buf << myJoyTable[i] << ":";
buf << myJoyTable[i][j] << ":";
myJoymapString = buf.str(); myJoymapString = buf.str();
return myJoymapString; return myJoymapString;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::getKeymapArray(Event::Type** array, uInt32* sizex)
{
*array = myKeyTable;
*sizex = StellaEvent::LastKCODE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::getJoymapArray(Event::Type** array, uInt32* sizex, uInt32* sizey)
{
*array = myJoyTable;
*sizex = StellaEvent::LastJSTICK;
*sizey = StellaEvent::LastJCODE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setDefaultKeymap() void EventHandler::setDefaultKeymap()
{ {
@ -313,19 +324,20 @@ void EventHandler::setDefaultKeymap()
void EventHandler::setDefaultJoymap() void EventHandler::setDefaultJoymap()
{ {
// Left joystick // Left joystick
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JBUTTON_9 ] = Event::ConsoleSelect; uInt32 i = StellaEvent::JSTICK_0 * StellaEvent::LastJCODE;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_UP] = Event::JoystickZeroUp; myJoyTable[i + StellaEvent::JAXIS_UP] = Event::JoystickZeroUp;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_DOWN] = Event::JoystickZeroDown; myJoyTable[i + StellaEvent::JAXIS_DOWN] = Event::JoystickZeroDown;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_LEFT] = Event::JoystickZeroLeft; myJoyTable[i + StellaEvent::JAXIS_LEFT] = Event::JoystickZeroLeft;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_RIGHT] = Event::JoystickZeroRight; myJoyTable[i + StellaEvent::JAXIS_RIGHT] = Event::JoystickZeroRight;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JBUTTON_0] = Event::JoystickZeroFire; myJoyTable[i + StellaEvent::JBUTTON_0] = Event::JoystickZeroFire;
// Right joystick // Right joystick
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_UP] = Event::JoystickOneUp; i = StellaEvent::JSTICK_1 * StellaEvent::LastJCODE;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_DOWN] = Event::JoystickOneDown; myJoyTable[i + StellaEvent::JAXIS_UP] = Event::JoystickOneUp;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_LEFT] = Event::JoystickOneLeft; myJoyTable[i + StellaEvent::JAXIS_DOWN] = Event::JoystickOneDown;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_RIGHT] = Event::JoystickOneRight; myJoyTable[i + StellaEvent::JAXIS_LEFT] = Event::JoystickOneLeft;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JBUTTON_0] = Event::JoystickOneFire; myJoyTable[i + StellaEvent::JAXIS_RIGHT] = Event::JoystickOneRight;
myJoyTable[i + StellaEvent::JBUTTON_0] = Event::JoystickOneFire;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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: EventHandler.hxx,v 1.8 2003-09-26 17:35:05 stephena Exp $ // $Id: EventHandler.hxx,v 1.9 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#ifndef EVENTHANDLER_HXX #ifndef EVENTHANDLER_HXX
@ -41,7 +41,7 @@ class MediaSource;
mapping can take place. mapping can take place.
@author Stephen Anthony @author Stephen Anthony
@version $Id: EventHandler.hxx,v 1.8 2003-09-26 17:35:05 stephena Exp $ @version $Id: EventHandler.hxx,v 1.9 2003-09-28 21:59:24 stephena Exp $
*/ */
class EventHandler class EventHandler
{ {
@ -98,19 +98,21 @@ class EventHandler
void setMediaSource(MediaSource* mediaSource); void setMediaSource(MediaSource* mediaSource);
/** /**
Get the current keymapping being used Get the current keymapping being used in string form
@return The keymap list in string form @return The keymap list in string form
*/ */
string getKeymap(); string getKeymap();
/** /**
Get the current joymapping being used Get the current joymapping being used in string form
@return The joymap list in string form @return The joymap list in string form
*/ */
string getJoymap(); string getJoymap();
void getKeymapArray(Event::Type** array, uInt32* sizex);
void getJoymapArray(Event::Type** array, uInt32* sizex, uInt32* sizey);
private: private:
void setKeymap(); void setKeymap();
@ -125,14 +127,12 @@ class EventHandler
void loadState(); void loadState();
void takeSnapshot(); void takeSnapshot();
void processMenuEvent(StellaEvent::KeyCode key);
private: private:
// Array of key events // Array of key events
Event::Type myKeyTable[StellaEvent::LastKCODE]; Event::Type myKeyTable[StellaEvent::LastKCODE];
// Array of joystick events // Array of joystick events
Event::Type myJoyTable[StellaEvent::LastJSTICK][StellaEvent::LastJCODE]; Event::Type myJoyTable[StellaEvent::LastJSTICK*StellaEvent::LastJCODE];
// Array of messages for each Event // Array of messages for each Event
string ourMessageTable[Event::LastType]; string ourMessageTable[Event::LastType];

View File

@ -13,10 +13,10 @@
// 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: Settings.cxx,v 1.9 2003-09-25 16:20:34 stephena Exp $ // $Id: Settings.cxx,v 1.10 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#include <assert.h> #include <cassert>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>

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: StellaEvent.hxx,v 1.4 2003-09-26 00:32:00 stephena Exp $ // $Id: StellaEvent.hxx,v 1.5 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#ifndef STELLAEVENT_HXX #ifndef STELLAEVENT_HXX
@ -28,13 +28,17 @@
by the frontends directly. by the frontends directly.
@author Stephen Anthony @author Stephen Anthony
@version $Id: StellaEvent.hxx,v 1.4 2003-09-26 00:32:00 stephena Exp $ @version $Id: StellaEvent.hxx,v 1.5 2003-09-28 21:59:24 stephena Exp $
*/ */
class StellaEvent class StellaEvent
{ {
public: public:
/** /**
Enumeration of keyboard keycodes Enumeration of keyboard keycodes
Note that the order of these codes is related to
UserInterface::ourEventName. If these are ever changed or rearranged,
that array must be updated as well.
*/ */
enum KeyCode enum KeyCode
{ {

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: TIA.hxx,v 1.8 2003-09-26 17:35:05 stephena Exp $ // $Id: TIA.hxx,v 1.9 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#ifndef TIA_HXX #ifndef TIA_HXX
@ -43,7 +43,7 @@ class Deserializer;
in a bounded queue. in a bounded queue.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: TIA.hxx,v 1.8 2003-09-26 17:35:05 stephena Exp $ @version $Id: TIA.hxx,v 1.9 2003-09-28 21:59:24 stephena Exp $
*/ */
class TIA : public Device , public MediaSource class TIA : public Device , public MediaSource
{ {
@ -244,9 +244,6 @@ class TIA : public Device , public MediaSource
// Waste cycles until the current scanline is finished // Waste cycles until the current scanline is finished
void waitHorizontalSync(); void waitHorizontalSync();
// Draw message to framebuffer
void drawMessageText();
private: private:
/** /**
A bounded queue class used to hold audio samples after they are A bounded queue class used to hold audio samples after they are

View File

@ -13,23 +13,25 @@
// 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: UserInterface.cxx,v 1.4 2003-09-26 22:39:36 stephena Exp $ // $Id: UserInterface.cxx,v 1.5 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
#include "Console.hxx" #include "Console.hxx"
#include "Event.hxx" #include "Event.hxx"
#include "EventHandler.hxx"
#include "StellaEvent.hxx"
#include "Settings.hxx" #include "Settings.hxx"
#include "MediaSrc.hxx" #include "MediaSrc.hxx"
#include "UserInterface.hxx" #include "UserInterface.hxx"
// Eventually, these may become variables // Eventually, these may become variables
#define FGCOLOR 10 #define FGCOLOR 10 // A white color in NTSC and PAL mode
#define BGCOLOR 0 #define BGCOLOR 0 // A black color in NTSC and PAL mode
#define FONTWIDTH 8 #define FONTWIDTH 8 // FIXME - TIA framebuffers must be updated for this
#define FONTHEIGHT 8 #define FONTHEIGHT 8
#define YOFFSET 12 // FONTHEIGHT + 2 pixels on top and bottom #define LINEOFFSET 10 // FONTHEIGHT + 1 pixel on top and bottom
#define XBOXOFFSET 8 // 4 pixels to the left and right of text #define XBOXOFFSET 8 // 4 pixels to the left and right of text
#define YBOXOFFSET 8 // 4 pixels to the top and bottom of text #define YBOXOFFSET 8 // 4 pixels to the top and bottom of text
@ -40,6 +42,14 @@ UserInterface::UserInterface(Console* console, MediaSource* mediasrc)
myCurrentWidget(W_NONE), myCurrentWidget(W_NONE),
myRemapEventSelectedFlag(false), myRemapEventSelectedFlag(false),
mySelectedEvent(Event::NoType), mySelectedEvent(Event::NoType),
myMaxLines(0),
myMainMenuIndex(0),
myMainMenuItems(sizeof(ourMainMenu)/sizeof(MainMenuItem)),
myRemapMenuIndex(0),
myRemapMenuLowIndex(0),
myRemapMenuHighIndex(0),
myRemapMenuItems(sizeof(ourRemapMenu)/sizeof(RemapMenuItem)),
myRemapMenuMaxLines(0),
myMessageTime(0), myMessageTime(0),
myMessageText(""), myMessageText(""),
myInfoMenuWidth(0) myInfoMenuWidth(0)
@ -58,30 +68,38 @@ UserInterface::UserInterface(Console* console, MediaSource* mediasrc)
} }
// Fill the properties info array with game information // Fill the properties info array with game information
string info; ourPropertiesInfo[0] = myConsole->properties().get("Cartridge.Name");
info = "NAME: " + myConsole->properties().get("Cartridge.Name"); if(ourPropertiesInfo[0].length() > myInfoMenuWidth)
ourPropertiesInfo[0] = info; myInfoMenuWidth = ourPropertiesInfo[0].length();
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length(); ourPropertiesInfo[1] = myConsole->properties().get("Cartridge.Manufacturer");
if(ourPropertiesInfo[1].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[1].length();
ourPropertiesInfo[2] = myConsole->properties().get("Cartridge.Rarity");
if(ourPropertiesInfo[2].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[2].length();
ourPropertiesInfo[3] = myConsole->properties().get("Cartridge.MD5");
if(ourPropertiesInfo[3].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[3].length();
ourPropertiesInfo[4] = myConsole->properties().get("Cartridge.Type");
if(ourPropertiesInfo[4].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[4].length();
ourPropertiesInfo[5] = myConsole->properties().get("Cartridge.ModelNo");
if(ourPropertiesInfo[5].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[5].length();
info = "MANUFACTURER: " + myConsole->properties().get("Cartridge.Manufacturer"); // Determine the maximum number of items that can be onscreen vertically
ourPropertiesInfo[1] = info; myMaxLines = myHeight / LINEOFFSET - 2;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
info = "RARITY: " + myConsole->properties().get("Cartridge.Rarity"); // Set up the correct bounds for the remap menu
ourPropertiesInfo[2] = info; myRemapMenuMaxLines = myRemapMenuItems > myMaxLines ? myMaxLines : myRemapMenuItems;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length(); myRemapMenuLowIndex = 0;
myRemapMenuHighIndex = myRemapMenuMaxLines;
info = "MD5SUM: " + myConsole->properties().get("Cartridge.MD5"); // Get the arrays containing key and joystick mappings
ourPropertiesInfo[3] = info; myConsole->eventHandler().getKeymapArray(&myKeyTable, &myKeyTableSize);
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length(); // myConsole->eventHandler().getJoymapArray(&myJoyTable, &jsize);
info = "MODEL NO: " + myConsole->properties().get("Cartridge.ModelNo"); loadRemapMenu();
ourPropertiesInfo[4] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
info = "TYPE: " + myConsole->properties().get("Cartridge.Type");
ourPropertiesInfo[5] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -93,6 +111,8 @@ UserInterface::~UserInterface(void)
void UserInterface::showMainMenu(bool show) void UserInterface::showMainMenu(bool show)
{ {
myCurrentWidget = show ? MAIN_MENU : W_NONE; myCurrentWidget = show ? MAIN_MENU : W_NONE;
myRemapEventSelectedFlag = false;
mySelectedEvent = Event::NoType;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -118,19 +138,17 @@ void UserInterface::sendKeyEvent(StellaEvent::KeyCode key, Int32 state)
if(myRemapEventSelectedFlag) if(myRemapEventSelectedFlag)
{ {
if(key == StellaEvent::KCODE_ESCAPE) if(key == StellaEvent::KCODE_ESCAPE)
// associate nothing with the selected event deleteBinding(mySelectedEvent);
cerr << "delete binding for " << mySelectedEvent << endl;
else else
// associate this stellaevent with the selected event addKeyBinding(mySelectedEvent, key);
cerr << "add binding " << key << " for " << mySelectedEvent << endl;
myRemapEventSelectedFlag = false; myRemapEventSelectedFlag = false;
} }
else if(key == StellaEvent::KCODE_RETURN) else if(key == StellaEvent::KCODE_RETURN)
{ {
cerr << "event selected for remapping\n";
mySelectedEvent = currentSelectedEvent(); mySelectedEvent = currentSelectedEvent();
myRemapEventSelectedFlag = true; myRemapEventSelectedFlag = true;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "' selected for remapping\n";
} }
else if(key == StellaEvent::KCODE_UP) else if(key == StellaEvent::KCODE_UP)
moveCursorUp(); moveCursorUp();
@ -142,7 +160,6 @@ void UserInterface::sendKeyEvent(StellaEvent::KeyCode key, Int32 state)
break; // REMAP_MENU break; // REMAP_MENU
case INFO_MENU: case INFO_MENU:
cerr << "key received while in info menu\n";
if(key == StellaEvent::KCODE_ESCAPE) if(key == StellaEvent::KCODE_ESCAPE)
myCurrentWidget = MAIN_MENU; myCurrentWidget = MAIN_MENU;
@ -162,46 +179,85 @@ void UserInterface::sendJoyEvent(StellaEvent::JoyStick stick,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::update() void UserInterface::update()
{ {
uInt32 width, height; // I know this method is hideous :)
uInt32 x, y, width, height, i;
// A message is a special case of interface element
// It can overwrite even a menu, so we should check for that first
if(myMessageTime > 0)
{
width = myMessageText.length()*FONTWIDTH + FONTWIDTH;
height = LINEOFFSET + FONTHEIGHT;
x = (myWidth >> 1) - (width >> 1);
y = myHeight - height - LINEOFFSET/2;
// Draw the bounded box and text
drawBoundedBox(x, y, width, height);
drawText(x + XBOXOFFSET/2, LINEOFFSET/2 + y, myMessageText);
myMessageTime--;
return;
}
switch(myCurrentWidget) switch(myCurrentWidget)
{ {
case W_NONE: case W_NONE:
return; // this shouldn't happen return;
cerr << "W_NONE\n";
break; // NONE break; // NONE
case MAIN_MENU: case MAIN_MENU:
// draw main menu width = 16*FONTWIDTH + 2*FONTWIDTH;
cerr << "MAIN_MENU\n"; height = myMainMenuItems*LINEOFFSET + 2*FONTHEIGHT;
x = (myWidth >> 1) - (width >> 1);
y = (myHeight >> 1) - (height >> 1);
// Draw the bounded box and text
drawBoundedBox(x, y, width, height);
for(i = 0; i < myMainMenuItems; i++)
drawText(x + XBOXOFFSET, LINEOFFSET*i + y + YBOXOFFSET, ourMainMenu[i].action);
// FIXME - change the '~' to an arrow on each end of the line
// Now draw the selection arrow around the currently selected item
drawText(x + 2, LINEOFFSET*myMainMenuIndex + y + YBOXOFFSET, "~");
break; // MAIN_MENU break; // MAIN_MENU
case REMAP_MENU: case REMAP_MENU:
// draw remap menu width = 16*FONTWIDTH + 2*FONTWIDTH; // FIXME - change 16 to maximum in new framebuffer (~ 40)
cerr << "REMAP_MENU\n"; height = myMaxLines*LINEOFFSET + 2*FONTHEIGHT;
x = (myWidth >> 1) - (width >> 1);
y = (myHeight >> 1) - (height >> 1);
// Draw the bounded box and text
drawBoundedBox(x, y, width, height);
for(i = myRemapMenuLowIndex; i < myRemapMenuHighIndex; i++)
{
drawText(x + XBOXOFFSET, LINEOFFSET*(i-myRemapMenuLowIndex) + y + YBOXOFFSET,
ourRemapMenu[i].action);
drawText(x + XBOXOFFSET+100, LINEOFFSET*(i-myRemapMenuLowIndex) + y + YBOXOFFSET,
ourRemapMenu[i].key);
}
// FIXME - change the '~' to an arrow on each end of the line
// Now draw the selection arrow around the currently selected item
drawText(x + 2, LINEOFFSET*(myRemapMenuIndex-myRemapMenuLowIndex) + y + YBOXOFFSET, "~");
break; // REMAP_MENU break; // REMAP_MENU
case INFO_MENU: case INFO_MENU:
// Calculate the bounds for the box width = myInfoMenuWidth*FONTWIDTH + 2*FONTWIDTH;
width = myInfoMenuWidth * FONTWIDTH + XBOXOFFSET; height = 6*LINEOFFSET + 2*FONTHEIGHT;
height = 6 * YOFFSET + YBOXOFFSET; x = (myWidth >> 1) - (width >> 1);
drawBoundedBox(width, height); y = (myHeight >> 1) - (height >> 1);
drawText("HELLO", width, height);
// Draw the bounded box and text
drawBoundedBox(x, y, width, height);
for(i = 0; i < 6; i++)
drawText(x + XBOXOFFSET, LINEOFFSET*i + y + YBOXOFFSET, ourPropertiesInfo[i]);
break; // INFO_MENU break; // INFO_MENU
case MESSAGE:
if(myMessageTime > 0)
{
drawText(myMessageText, 0, 0); // FIXME - change to draw bounding box and text at correct coords
myMessageTime--;
cerr << "MESSAGE = " << myMessageText << ": " << myMessageTime << endl;
}
break; // MESSAGE
default: default:
cerr << "NOT DEFINED\n";
break; break;
} }
} }
@ -209,56 +265,114 @@ cerr << "NOT DEFINED\n";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UserInterface::Widget UserInterface::currentSelectedWidget() UserInterface::Widget UserInterface::currentSelectedWidget()
{ {
return INFO_MENU; // FIXME if(myMainMenuIndex >= 0 && myMainMenuIndex < myMainMenuItems)
return ourMainMenu[myMainMenuIndex].widget;
else
return W_NONE;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type UserInterface::currentSelectedEvent() Event::Type UserInterface::currentSelectedEvent()
{ {
return Event::ConsoleSelect; // FIXME if(myRemapMenuIndex >= 0 && myRemapMenuIndex < myRemapMenuItems)
return ourRemapMenu[myRemapMenuIndex].event;
else
return Event::NoType;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::moveCursorUp() void UserInterface::moveCursorUp()
{ {
cerr << "cursor up\n"; switch(myCurrentWidget)
{
case MAIN_MENU:
if(myMainMenuIndex > 0)
myMainMenuIndex--;
break;
case REMAP_MENU:
// Since this menu will have more options than can fit it one screen,
// we have to implement a sliding window
if(myRemapMenuIndex > myRemapMenuLowIndex)
{
myRemapMenuIndex--;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "'\n";
}
else if(myRemapMenuIndex == myRemapMenuLowIndex)
{
if(myRemapMenuLowIndex > 0)
{
myRemapMenuLowIndex--;
myRemapMenuHighIndex--;
myRemapMenuIndex--;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "'\n";
}
}
break;
default: // This should never happen
break;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::moveCursorDown() void UserInterface::moveCursorDown()
{ {
cerr << "cursor down\n"; switch(myCurrentWidget)
{
case MAIN_MENU:
if(myMainMenuIndex < myMainMenuItems - 1)
myMainMenuIndex++;
break;
case REMAP_MENU:
// Since this menu will have more options than can fit it one screen,
// we have to implement a sliding window
if(myRemapMenuIndex < myRemapMenuHighIndex - 1)
{
myRemapMenuIndex++;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "'\n";
}
else if(myRemapMenuIndex == myRemapMenuHighIndex - 1)
{
if(myRemapMenuHighIndex < myRemapMenuItems)
{
myRemapMenuLowIndex++;
myRemapMenuHighIndex++;
myRemapMenuIndex++;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "'\n";
}
}
break;
default: // This should never happen
break;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::showMessage(const string& message) void UserInterface::showMessage(const string& message)
{ {
myCurrentWidget = MESSAGE;
myMessageText = message; myMessageText = message;
myMessageTime = 120; // FIXME - changes to 2 * framerate myMessageTime = 2 * myConsole->settings().getInt("framerate");
// Make message uppercase, since there are no lowercase fonts defined
uInt32 length = myMessageText.length();
for(uInt32 i = 0; i < length; ++i)
myMessageText[i] = toupper(myMessageText[i]);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::drawBoundedBox(uInt32 width, uInt32 height) void UserInterface::drawBoundedBox(uInt32 x, uInt32 y, uInt32 width, uInt32 height)
{ {
// Center the box horizontally
uInt32 xBoxOffSet = (myWidth >> 1) - (width >> 1);
uInt32 yBoxOffSet = (myHeight >> 1) - (height >> 1);
uInt8* buffer = myMediaSource->currentFrameBuffer(); uInt8* buffer = myMediaSource->currentFrameBuffer();
for(uInt32 x = 0; x < width; ++x)
{
for(uInt32 y = 0; y < height; ++y)
{
uInt32 position = ((yBoxOffSet + y) * myWidth) + x + xBoxOffSet;
if((x == 0) || (x == width - 1) || (y == 0) || (y == height - 1)) for(uInt32 col = 0; col < width; ++col)
{
for(uInt32 row = 0; row < height; ++row)
{
uInt32 position = ((y + row) * myWidth) + col + x;
if((col == 0) || (col == width - 1) || (row == 0) || (row == height - 1))
buffer[position] = FGCOLOR; buffer[position] = FGCOLOR;
else else
buffer[position] = BGCOLOR; buffer[position] = BGCOLOR;
@ -267,160 +381,140 @@ void UserInterface::drawBoundedBox(uInt32 width, uInt32 height)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::drawText(const string& message, uInt32 xorig, uInt32 yorig) void UserInterface::drawText(uInt32 xorig, uInt32 yorig, const string& message)
{ {
// First, get access to the framebuffer
uInt8* buffer = myMediaSource->currentFrameBuffer(); uInt8* buffer = myMediaSource->currentFrameBuffer();
/*
// Set up the correct coordinates to draw the surrounding box
uInt32 xBoxOffSet = 2 + myXStart;
uInt32 yBoxOffSet = myHeight - 18;
uInt32 boxToTextXOffSet = 2;
uInt32 boxToTextYOffSet = 4;
// Set up the correct coordinates to print the message
uInt32 xTextOffSet = xBoxOffSet + boxToTextXOffSet;
uInt32 yTextOffSet = yBoxOffSet + boxToTextYOffSet;
// Used to indicate the current x/y position of a pixel
uInt32 xPos, yPos;
// The actual font data for a letter
uInt32 data;
// The index into the palette to color the current text and background
uInt8 fontColor, backColor;
// These will probably change in the future ...
fontColor = 10;
backColor = 0;
// Clip the length if its wider than the screen
uInt8 length = message.length();
if(((length * 5) + xTextOffSet) >= myWidth)
length = (myWidth - xTextOffSet) / 5;
// Reset the offsets to center the message
uInt32 boxWidth = (5 * length) + boxToTextXOffSet;
uInt32 boxHeight = 8 + (2 * (yTextOffSet - yBoxOffSet));
xBoxOffSet = (myWidth >> 1) - (boxWidth >> 1);
xTextOffSet = xBoxOffSet + boxToTextXOffSet;
// First, draw the surrounding box
for(uInt32 x = 0; x < boxWidth; ++x)
{
for(uInt32 y = 0; y < boxHeight; ++y)
{
uInt32 position = ((yBoxOffSet + y) * myWidth) + x + xBoxOffSet;
if((x == 0) || (x == boxWidth - 1) || (y == 0) || (y == boxHeight - 1))
buffer[position] = fontColor;
else
buffer[position] = backColor;
}
}*/
// Used to indicate the current x/y position of a pixel
uInt32 xPos, yPos;
// The actual font data for a letter
uInt32 data;
uInt32 xTextOffSet = xorig + 4;
uInt32 yTextOffSet = yorig + 4;
uInt8 length = message.length(); uInt8 length = message.length();
// Then, draw the text for(uInt32 x = 0; x < length; x++)
for(uInt8 x = 0; x < length; ++x) {
for(uInt32 y = 0; y < FONTHEIGHT; y++)
{
for(uInt32 z = 0; z < FONTWIDTH; z++)
{ {
char letter = message[x]; char letter = message[x];
if((ourFontData[(letter << 3) + y] >> z) & 1)
if((letter >= 'A') && (letter <= 'Z')) buffer[(y + yorig)*myWidth + (x<<3) + z + xorig] = FGCOLOR;
data = ourFontData[(int)letter - 65];
else if((letter >= '0') && (letter <= '9'))
data = ourFontData[(int)letter - 48 + 26];
else // unknown character or space
{
xTextOffSet += 4;
continue;
}
// start scanning the font data from the bottom up
yPos = 7;
for(uInt8 y = 0; y < 32; ++y)
{
// determine the correct scanline
xPos = y % 4;
if(xPos == 0)
--yPos;
if((data >> y) & 1)
{
uInt32 position = (yPos + yTextOffSet) * myWidth + (4 - xPos) + xTextOffSet;
buffer[position] = FGCOLOR;
} }
} }
// move left to the next character
xTextOffSet += 5;
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32 UserInterface::ourFontData[36] = { void UserInterface::loadRemapMenu()
0x699f999, // A {
0xe99e99e, // B // Fill the remap menu with the current key mappings
0x6988896, // C for(uInt32 i = 0; i < myRemapMenuItems; ++i)
0xe99999e, // D {
0xf88e88f, // E Event::Type event = ourRemapMenu[i].event;
0xf88e888, // F ourRemapMenu[i].key = "None";
0x698b996, // G string key = "";
0x999f999, // H for(uInt32 j = 0; j < myKeyTableSize; ++j)
0x7222227, // I {
0x72222a4, // J if(myKeyTable[j] == event)
0x9accaa9, // K {
0x888888f, // L if(key == "")
0x9ff9999, // M key = key + ourEventName[j];
0x9ddbb99, // N else
0x6999996, // O key = key + ", " + ourEventName[j];
0xe99e888, // P
0x69999b7, // Q ourRemapMenu[i].key = key;
0xe99ea99, // R }
0x6986196, // S }
0x7222222, // T }
0x9999996, // U }
0x9999966, // V
0x9999ff9, // W // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0x99fff99, // X void UserInterface::addKeyBinding(Event::Type event, StellaEvent::KeyCode key)
0x9996244, // Y {
0xf12488f, // Z myKeyTable[key] = event;
0x69bd996, // 0
0x2622227, // 1 loadRemapMenu();
0x691248f, // 2 }
0x6916196, // 3
0xaaaf222, // 4 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0xf88e11e, // 5 void UserInterface::deleteBinding(Event::Type event)
0x698e996, // 6 {
0xf112244, // 7 for(uInt32 i = 0; i < myKeyTableSize; ++i)
0x6996996, // 8 if(myKeyTable[i] == event)
0x6997196 // 9 myKeyTable[i] = Event::NoType;
loadRemapMenu();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8 UserInterface::ourFontData[2048] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00,0x1c,0x3e,0x1c,0x7f,0x7f,0x3e,0x1c,0x3e,0x08,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07,0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00,0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00,0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x33,0x1e,0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00,0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x1e,0x0c,0x0c,0x00,0x0c,0x00,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00,0x0c,0x3e,0x03,0x1e,0x30,0x1f,0x0c,0x00,0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00,0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00,0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x3e,0x63,0x73,0x7b,0x6f,0x67,0x3e,0x00,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00,0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00,0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00,0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00,0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x06,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00,0x00,0x00,0x3f,0x00,0x00,0x3f,0x00,0x00,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00,0x1e,0x33,0x30,0x18,0x0c,0x00,0x0c,0x00,
0x3e,0x63,0x7b,0x7b,0x7b,0x03,0x1e,0x00,0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00,0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00,0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00,0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00,0x3c,0x66,0x03,0x03,0x73,0x66,0x7c,0x00,0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00,0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00,0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00,0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00,0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00,0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00,0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00,0x1e,0x33,0x33,0x33,0x3b,0x1e,0x38,0x00,0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00,0x1e,0x33,0x07,0x0e,0x38,0x33,0x1e,0x00,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00,0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00,0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00,0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00,0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00,0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00,0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x1c,0x36,0x06,0x0f,0x06,0x06,0x0f,0x00,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f,0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00,0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1e,0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x33,0x7f,0x7f,0x6b,0x63,0x00,0x00,0x00,0x1f,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00,0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78,0x00,0x00,0x3b,0x6e,0x66,0x06,0x0f,0x00,0x00,0x00,0x3e,0x03,0x1e,0x30,0x1f,0x00,0x08,0x0c,0x3e,0x0c,0x0c,0x2c,0x18,0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00,0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00,0x00,0x00,0x63,0x6b,0x7f,0x7f,0x36,0x00,0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00,0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f,0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00,0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,
0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e,0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00,0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c,0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00,0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00,0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00,0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00,0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00,0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00,0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00,0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f,0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00,0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18,0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00,0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c,0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3,0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e,
0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00,0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00,0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00,0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00,0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00,0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0,0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00,0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03,0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00,0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00,0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00,0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03,0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00,0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f,0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00,0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00,0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03,0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00,0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00,0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e,0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00,0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38,0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}; };
/* uInt8* frontbuffer = myMediaSource->currentFrameBuffer(); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8* backbuffer = myMediaSource->previousFrameBuffer(); UserInterface::MainMenuItem UserInterface::ourMainMenu[2] = {
{ REMAP_MENU, "Key Remapping" },
{ INFO_MENU, "Game Information" }
};
// First, draw the surrounding box // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
for(uInt32 x = 0; x < 100; ++x) UserInterface::RemapMenuItem UserInterface::ourRemapMenu[23] = {
{ { Event::ConsoleSelect, "Select", "" },
for(uInt32 y = 0; y < 100; ++y) { Event::ConsoleReset, "Reset", "" },
{ { Event::ConsoleColor, "Color TV", "" },
uInt32 position = ((20 + y) * myWidth) + x + 20; { Event::ConsoleBlackWhite, "B/W TV", "" },
{ Event::ConsoleLeftDifficultyB, "P1 Diff. B", "" },
{ Event::ConsoleLeftDifficultyA, "P1 Diff. A", "" },
{ Event::ConsoleRightDifficultyB, "P2 Diff. B", "" },
{ Event::ConsoleRightDifficultyA, "P2 Diff. A", "" },
{ Event::SaveState, "Save State", "" },
{ Event::ChangeState, "Change State", "" },
{ Event::LoadState, "Load State", "" },
{ Event::TakeSnapshot, "Snapshot", "" },
{ Event::Pause, "Pause", "" },
if((x == 0) || (x == 200 - 1) || (y == 0) || (y == 200 - 1)) { Event::JoystickZeroUp, "P1 Up", "" },
frontbuffer[position] = backbuffer[position] = 10; { Event::JoystickZeroDown, "P1 Down", "" },
else { Event::JoystickZeroLeft, "P1 Left", "" },
frontbuffer[position] = backbuffer[position] = 0; { Event::JoystickZeroRight, "P1 Right", "" },
} { Event::JoystickZeroFire, "P1 Fire", "" },
}
{ Event::JoystickOneUp, "P2 Up", "" },
{ Event::JoystickOneDown, "P2 Down", "" },
{ Event::JoystickOneLeft, "P2 Left", "" },
{ Event::JoystickOneRight, "P2 Right", "" },
{ Event::JoystickOneFire, "P2 Fire", "" }
// { Event::, "" },
};
/**
This array must be initialized in a specific order, matching
there initialization in StellaEvent::KeyCode.
The other option would be to create an array of structures
(in StellaEvent.hxx) containing event/string pairs.
This would eliminate the use of enumerations and slow down
lookups. So I do it this way instead.
*/ */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* UserInterface::ourEventName[StellaEvent::LastKCODE] = {
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"KP 0", "KP 1", "KP 2", "KP 3", "KP 4", "KP 5", "KP 6", "KP 7", "KP 8",
"KP 9", "KP .", "KP /", "KP *", "KP -", "KP +", "KP ENTER", "KP =",
"BACKSP", "TAB", "ENTER", "PAUSE", "ESC", ",", ".", "/", ";", "\\", "\"",
"[", "]", "`",
"CTRL", "ALT", "UP", "DOWN", "LEFT", "RIGHT", "SPACE",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"
};

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: UserInterface.hxx,v 1.4 2003-09-26 22:39:36 stephena Exp $ // $Id: UserInterface.hxx,v 1.5 2003-09-28 21:59:24 stephena Exp $
//============================================================================ //============================================================================
#ifndef USERINTERFACE_HXX #ifndef USERINTERFACE_HXX
@ -31,7 +31,7 @@ class MediaSource;
can be changed. can be changed.
@author Stephen Anthony @author Stephen Anthony
@version $Id: UserInterface.hxx,v 1.4 2003-09-26 22:39:36 stephena Exp $ @version $Id: UserInterface.hxx,v 1.5 2003-09-28 21:59:24 stephena Exp $
*/ */
class UserInterface class UserInterface
{ {
@ -67,9 +67,6 @@ class UserInterface
void sendJoyEvent(StellaEvent::JoyStick stick, StellaEvent::JoyCode code, void sendJoyEvent(StellaEvent::JoyStick stick, StellaEvent::JoyCode code,
Int32 state); Int32 state);
void sendKeymap(Event::Type table[StellaEvent::LastKCODE]);
void sendJoymap(Event::Type table[StellaEvent::LastJSTICK][StellaEvent::LastJCODE]);
public: public:
void showMainMenu(bool show); void showMainMenu(bool show);
void showMessage(const string& message); void showMessage(const string& message);
@ -77,7 +74,7 @@ class UserInterface
private: private:
// Enumeration representing the different types of user interface widgets // Enumeration representing the different types of user interface widgets
enum Widget { W_NONE, MAIN_MENU, REMAP_MENU, INFO_MENU, MESSAGE }; enum Widget { W_NONE, MAIN_MENU, REMAP_MENU, INFO_MENU };
Widget currentSelectedWidget(); Widget currentSelectedWidget();
Event::Type currentSelectedEvent(); Event::Type currentSelectedEvent();
@ -85,11 +82,21 @@ class UserInterface
void moveCursorUp(); void moveCursorUp();
void moveCursorDown(); void moveCursorDown();
// Draw a bounded box centered horizontally // Draw a bounded box at the specified coordinates
void drawBoundedBox(uInt32 width, uInt32 height); void drawBoundedBox(uInt32 x, uInt32 y, uInt32 width, uInt32 height);
// Draw message text at specified coordinates // Draw message text at specified coordinates
void drawText(const string& message, uInt32 x, uInt32 y); void drawText(uInt32 x, uInt32 y, const string& message);
// scan the mapping arrays and update the remap menu
void loadRemapMenu();
// Add binding between a StellaEvent key and a core event
void addKeyBinding(Event::Type event, StellaEvent::KeyCode key);
// Remove all bindings for this core event
void deleteBinding(Event::Type event);
private: private:
// The Console for the system // The Console for the system
@ -98,11 +105,29 @@ class UserInterface
// The Mediasource for the system // The Mediasource for the system
MediaSource* myMediaSource; MediaSource* myMediaSource;
// Structure used for main menu items
struct MainMenuItem
{
Widget widget;
string action;
};
// Structure used for remap menu items
struct RemapMenuItem
{
Event::Type event;
string action;
string key;
};
// Bounds for the window frame // Bounds for the window frame
uInt32 myXStart, myYStart, myWidth, myHeight; uInt32 myXStart, myYStart, myWidth, myHeight;
// Table of bitmapped fonts. Holds A..Z and 0..9. // Table of bitmapped fonts.
static const uInt32 ourFontData[36]; static const uInt8 ourFontData[2048];
// Table of strings representing the various StellaEvent codes
static const char* ourEventName[StellaEvent::LastKCODE];
// Type of interface item currently slated for redraw // Type of interface item currently slated for redraw
Widget myCurrentWidget; Widget myCurrentWidget;
@ -113,17 +138,45 @@ class UserInterface
// Indicates the current selected event being remapped // Indicates the current selected event being remapped
Event::Type mySelectedEvent; Event::Type mySelectedEvent;
// The maximum number of vertical lines of text that can be onscreen
uInt32 myMaxLines;
// Keep track of current selected main menu item
uInt32 myMainMenuIndex, myMainMenuItems;
// Keep track of current selected remap menu item
uInt32 myRemapMenuIndex, myRemapMenuLowIndex, myRemapMenuHighIndex;
uInt32 myRemapMenuItems, myRemapMenuMaxLines;
// Message timer // Message timer
Int32 myMessageTime; Int32 myMessageTime;
// Message text // Message text
string myMessageText; string myMessageText;
// The width of the information menu, determined by the longest string
uInt32 myInfoMenuWidth;
// Holds information about the current selected ROM image // Holds information about the current selected ROM image
string ourPropertiesInfo[6]; string ourPropertiesInfo[6];
// The width of the information menu, determined by the longest string // Holds static strings for the main menu
uInt32 myInfoMenuWidth; static MainMenuItem ourMainMenu[2];
// Holds static strings for the remap menu
static RemapMenuItem ourRemapMenu[23];
// Holds the current key mappings
Event::Type* myKeyTable;
// Holds the number of items in the keytable array
uInt32 myKeyTableSize;
// Holds the current joystick mappings
Event::Type* myJoyTable;
// Holds the number of items in the joytable array
uInt32 myJoyTableSize;
}; };
#endif #endif