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
// 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>
@ -49,9 +49,8 @@ EventHandler::EventHandler(Console* console)
myKeyTable[i] = Event::NoType;
// Erase the JoyEvent array
for(i = 0; i < StellaEvent::LastJSTICK; ++i)
for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j)
myJoyTable[i][j] = Event::NoType;
for(i = 0; i < StellaEvent::LastJSTICK*StellaEvent::LastJCODE; ++i)
myJoyTable[i] = Event::NoType;
// Erase the Message array
for(i = 0; i < Event::LastType; ++i)
@ -67,6 +66,9 @@ EventHandler::EventHandler(Console* console)
setKeymap();
setJoymap();
// Now send the filled event arrays to the GUI for display and remapping
// myConsole->gui().
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -74,8 +76,6 @@ EventHandler::~EventHandler()
{
if(myEvent)
delete myEvent;
myEvent = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -110,7 +110,7 @@ void EventHandler::sendJoyEvent(StellaEvent::JoyStick stick,
if(myMenuStatus)
myConsole->gui().sendJoyEvent(stick, code, state);
else
sendEvent(myJoyTable[stick][code], state);
sendEvent(myJoyTable[stick*StellaEvent::LastJCODE + code], state);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -202,13 +202,10 @@ void EventHandler::setJoymap()
string key;
// 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;
myJoyTable[i][j] = (Event::Type) atoi(key.c_str());
}
buf >> key;
myJoyTable[i] = (Event::Type) atoi(key.c_str());
}
}
else
@ -234,14 +231,28 @@ string EventHandler::getJoymap()
ostringstream buf;
// Iterate through the joymap table and create a colon-separated list
for(Int32 i = 0; i < StellaEvent::LastJSTICK; ++i)
for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j)
buf << myJoyTable[i][j] << ":";
for(Int32 i = 0; i < StellaEvent::LastJSTICK*StellaEvent::LastJCODE; ++i)
buf << myJoyTable[i] << ":";
myJoymapString = buf.str();
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()
{
@ -313,19 +324,20 @@ void EventHandler::setDefaultKeymap()
void EventHandler::setDefaultJoymap()
{
// Left joystick
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JBUTTON_9 ] = Event::ConsoleSelect;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_UP] = Event::JoystickZeroUp;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_DOWN] = Event::JoystickZeroDown;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_LEFT] = Event::JoystickZeroLeft;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JAXIS_RIGHT] = Event::JoystickZeroRight;
myJoyTable[StellaEvent::JSTICK_0][StellaEvent::JBUTTON_0] = Event::JoystickZeroFire;
uInt32 i = StellaEvent::JSTICK_0 * StellaEvent::LastJCODE;
myJoyTable[i + StellaEvent::JAXIS_UP] = Event::JoystickZeroUp;
myJoyTable[i + StellaEvent::JAXIS_DOWN] = Event::JoystickZeroDown;
myJoyTable[i + StellaEvent::JAXIS_LEFT] = Event::JoystickZeroLeft;
myJoyTable[i + StellaEvent::JAXIS_RIGHT] = Event::JoystickZeroRight;
myJoyTable[i + StellaEvent::JBUTTON_0] = Event::JoystickZeroFire;
// Right joystick
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_UP] = Event::JoystickOneUp;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_DOWN] = Event::JoystickOneDown;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_LEFT] = Event::JoystickOneLeft;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JAXIS_RIGHT] = Event::JoystickOneRight;
myJoyTable[StellaEvent::JSTICK_1][StellaEvent::JBUTTON_0] = Event::JoystickOneFire;
i = StellaEvent::JSTICK_1 * StellaEvent::LastJCODE;
myJoyTable[i + StellaEvent::JAXIS_UP] = Event::JoystickOneUp;
myJoyTable[i + StellaEvent::JAXIS_DOWN] = Event::JoystickOneDown;
myJoyTable[i + StellaEvent::JAXIS_LEFT] = Event::JoystickOneLeft;
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
// 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
@ -41,7 +41,7 @@ class MediaSource;
mapping can take place.
@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
{
@ -98,19 +98,21 @@ class EventHandler
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
*/
string getKeymap();
/**
Get the current joymapping being used
Get the current joymapping being used in string form
@return The joymap list in string form
*/
string getJoymap();
void getKeymapArray(Event::Type** array, uInt32* sizex);
void getJoymapArray(Event::Type** array, uInt32* sizex, uInt32* sizey);
private:
void setKeymap();
@ -125,14 +127,12 @@ class EventHandler
void loadState();
void takeSnapshot();
void processMenuEvent(StellaEvent::KeyCode key);
private:
// Array of key events
Event::Type myKeyTable[StellaEvent::LastKCODE];
// Array of joystick events
Event::Type myJoyTable[StellaEvent::LastJSTICK][StellaEvent::LastJCODE];
Event::Type myJoyTable[StellaEvent::LastJSTICK*StellaEvent::LastJCODE];
// Array of messages for each Event
string ourMessageTable[Event::LastType];

View File

@ -13,10 +13,10 @@
// See the file "license" for information on usage and redistribution of
// 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 <fstream>

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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
@ -28,13 +28,17 @@
by the frontends directly.
@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
{
public:
/**
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
{

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// 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
@ -43,7 +43,7 @@ class Deserializer;
in a bounded queue.
@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
{
@ -244,9 +244,6 @@ class TIA : public Device , public MediaSource
// Waste cycles until the current scanline is finished
void waitHorizontalSync();
// Draw message to framebuffer
void drawMessageText();
private:
/**
A bounded queue class used to hold audio samples after they are

View File

@ -13,25 +13,27 @@
// See the file "license" for information on usage and redistribution of
// 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 "Console.hxx"
#include "Event.hxx"
#include "EventHandler.hxx"
#include "StellaEvent.hxx"
#include "Settings.hxx"
#include "MediaSrc.hxx"
#include "UserInterface.hxx"
// Eventually, these may become variables
#define FGCOLOR 10
#define BGCOLOR 0
#define FONTWIDTH 8
#define FGCOLOR 10 // A white color in NTSC and PAL mode
#define BGCOLOR 0 // A black color in NTSC and PAL mode
#define FONTWIDTH 8 // FIXME - TIA framebuffers must be updated for this
#define FONTHEIGHT 8
#define YOFFSET 12 // FONTHEIGHT + 2 pixels on top and bottom
#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 LINEOFFSET 10 // FONTHEIGHT + 1 pixel on top and bottom
#define XBOXOFFSET 8 // 4 pixels to the left and right of text
#define YBOXOFFSET 8 // 4 pixels to the top and bottom of text
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UserInterface::UserInterface(Console* console, MediaSource* mediasrc)
@ -40,6 +42,14 @@ UserInterface::UserInterface(Console* console, MediaSource* mediasrc)
myCurrentWidget(W_NONE),
myRemapEventSelectedFlag(false),
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),
myMessageText(""),
myInfoMenuWidth(0)
@ -58,30 +68,38 @@ UserInterface::UserInterface(Console* console, MediaSource* mediasrc)
}
// Fill the properties info array with game information
string info;
info = "NAME: " + myConsole->properties().get("Cartridge.Name");
ourPropertiesInfo[0] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
ourPropertiesInfo[0] = myConsole->properties().get("Cartridge.Name");
if(ourPropertiesInfo[0].length() > myInfoMenuWidth)
myInfoMenuWidth = ourPropertiesInfo[0].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");
ourPropertiesInfo[1] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
// Determine the maximum number of items that can be onscreen vertically
myMaxLines = myHeight / LINEOFFSET - 2;
info = "RARITY: " + myConsole->properties().get("Cartridge.Rarity");
ourPropertiesInfo[2] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
// Set up the correct bounds for the remap menu
myRemapMenuMaxLines = myRemapMenuItems > myMaxLines ? myMaxLines : myRemapMenuItems;
myRemapMenuLowIndex = 0;
myRemapMenuHighIndex = myRemapMenuMaxLines;
info = "MD5SUM: " + myConsole->properties().get("Cartridge.MD5");
ourPropertiesInfo[3] = info;
if(info.length() > myInfoMenuWidth) myInfoMenuWidth = info.length();
// Get the arrays containing key and joystick mappings
myConsole->eventHandler().getKeymapArray(&myKeyTable, &myKeyTableSize);
// myConsole->eventHandler().getJoymapArray(&myJoyTable, &jsize);
info = "MODEL NO: " + myConsole->properties().get("Cartridge.ModelNo");
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();
loadRemapMenu();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -93,6 +111,8 @@ UserInterface::~UserInterface(void)
void UserInterface::showMainMenu(bool show)
{
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(key == StellaEvent::KCODE_ESCAPE)
// associate nothing with the selected event
cerr << "delete binding for " << mySelectedEvent << endl;
deleteBinding(mySelectedEvent);
else
// associate this stellaevent with the selected event
cerr << "add binding " << key << " for " << mySelectedEvent << endl;
addKeyBinding(mySelectedEvent, key);
myRemapEventSelectedFlag = false;
}
else if(key == StellaEvent::KCODE_RETURN)
{
cerr << "event selected for remapping\n";
mySelectedEvent = currentSelectedEvent();
myRemapEventSelectedFlag = true;
cerr << "'" << ourRemapMenu[myRemapMenuIndex].action << "' selected for remapping\n";
}
else if(key == StellaEvent::KCODE_UP)
moveCursorUp();
@ -142,7 +160,6 @@ void UserInterface::sendKeyEvent(StellaEvent::KeyCode key, Int32 state)
break; // REMAP_MENU
case INFO_MENU:
cerr << "key received while in info menu\n";
if(key == StellaEvent::KCODE_ESCAPE)
myCurrentWidget = MAIN_MENU;
@ -162,46 +179,85 @@ void UserInterface::sendJoyEvent(StellaEvent::JoyStick stick,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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)
{
case W_NONE:
return; // this shouldn't happen
cerr << "W_NONE\n";
return;
break; // NONE
case MAIN_MENU:
// draw main menu
cerr << "MAIN_MENU\n";
width = 16*FONTWIDTH + 2*FONTWIDTH;
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
case REMAP_MENU:
// draw remap menu
cerr << "REMAP_MENU\n";
width = 16*FONTWIDTH + 2*FONTWIDTH; // FIXME - change 16 to maximum in new framebuffer (~ 40)
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
case INFO_MENU:
// Calculate the bounds for the box
width = myInfoMenuWidth * FONTWIDTH + XBOXOFFSET;
height = 6 * YOFFSET + YBOXOFFSET;
drawBoundedBox(width, height);
drawText("HELLO", width, height);
width = myInfoMenuWidth*FONTWIDTH + 2*FONTWIDTH;
height = 6*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 < 6; i++)
drawText(x + XBOXOFFSET, LINEOFFSET*i + y + YBOXOFFSET, ourPropertiesInfo[i]);
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:
cerr << "NOT DEFINED\n";
break;
}
}
@ -209,56 +265,114 @@ cerr << "NOT DEFINED\n";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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()
{
return Event::ConsoleSelect; // FIXME
if(myRemapMenuIndex >= 0 && myRemapMenuIndex < myRemapMenuItems)
return ourRemapMenu[myRemapMenuIndex].event;
else
return Event::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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()
{
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)
{
myCurrentWidget = MESSAGE;
myMessageText = message;
myMessageTime = 120; // FIXME - changes to 2 * 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]);
myMessageTime = 2 * myConsole->settings().getInt("framerate");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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();
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;
else
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();
/*
// 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();
// Then, draw the text
for(uInt8 x = 0; x < length; ++x)
for(uInt32 x = 0; x < length; x++)
{
char letter = message[x];
if((letter >= 'A') && (letter <= 'Z'))
data = ourFontData[(int)letter - 65];
else if((letter >= '0') && (letter <= '9'))
data = ourFontData[(int)letter - 48 + 26];
else // unknown character or space
for(uInt32 y = 0; y < FONTHEIGHT; y++)
{
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)
for(uInt32 z = 0; z < FONTWIDTH; z++)
{
uInt32 position = (yPos + yTextOffSet) * myWidth + (4 - xPos) + xTextOffSet;
buffer[position] = FGCOLOR;
char letter = message[x];
if((ourFontData[(letter << 3) + y] >> z) & 1)
buffer[(y + yorig)*myWidth + (x<<3) + z + xorig] = FGCOLOR;
}
}
// move left to the next character
xTextOffSet += 5;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32 UserInterface::ourFontData[36] = {
0x699f999, // A
0xe99e99e, // B
0x6988896, // C
0xe99999e, // D
0xf88e88f, // E
0xf88e888, // F
0x698b996, // G
0x999f999, // H
0x7222227, // I
0x72222a4, // J
0x9accaa9, // K
0x888888f, // L
0x9ff9999, // M
0x9ddbb99, // N
0x6999996, // O
0xe99e888, // P
0x69999b7, // Q
0xe99ea99, // R
0x6986196, // S
0x7222222, // T
0x9999996, // U
0x9999966, // V
0x9999ff9, // W
0x99fff99, // X
0x9996244, // Y
0xf12488f, // Z
0x69bd996, // 0
0x2622227, // 1
0x691248f, // 2
0x6916196, // 3
0xaaaf222, // 4
0xf88e11e, // 5
0x698e996, // 6
0xf112244, // 7
0x6996996, // 8
0x6997196 // 9
};
/* uInt8* frontbuffer = myMediaSource->currentFrameBuffer();
uInt8* backbuffer = myMediaSource->previousFrameBuffer();
// First, draw the surrounding box
for(uInt32 x = 0; x < 100; ++x)
void UserInterface::loadRemapMenu()
{
// Fill the remap menu with the current key mappings
for(uInt32 i = 0; i < myRemapMenuItems; ++i)
{
for(uInt32 y = 0; y < 100; ++y)
Event::Type event = ourRemapMenu[i].event;
ourRemapMenu[i].key = "None";
string key = "";
for(uInt32 j = 0; j < myKeyTableSize; ++j)
{
uInt32 position = ((20 + y) * myWidth) + x + 20;
if(myKeyTable[j] == event)
{
if(key == "")
key = key + ourEventName[j];
else
key = key + ", " + ourEventName[j];
if((x == 0) || (x == 200 - 1) || (y == 0) || (y == 200 - 1))
frontbuffer[position] = backbuffer[position] = 10;
else
frontbuffer[position] = backbuffer[position] = 0;
ourRemapMenu[i].key = key;
}
}
}
*/
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::addKeyBinding(Event::Type event, StellaEvent::KeyCode key)
{
myKeyTable[key] = event;
loadRemapMenu();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void UserInterface::deleteBinding(Event::Type event)
{
for(uInt32 i = 0; i < myKeyTableSize; ++i)
if(myKeyTable[i] == event)
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
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UserInterface::MainMenuItem UserInterface::ourMainMenu[2] = {
{ REMAP_MENU, "Key Remapping" },
{ INFO_MENU, "Game Information" }
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UserInterface::RemapMenuItem UserInterface::ourRemapMenu[23] = {
{ Event::ConsoleSelect, "Select", "" },
{ Event::ConsoleReset, "Reset", "" },
{ Event::ConsoleColor, "Color TV", "" },
{ 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", "" },
{ Event::JoystickZeroUp, "P1 Up", "" },
{ Event::JoystickZeroDown, "P1 Down", "" },
{ Event::JoystickZeroLeft, "P1 Left", "" },
{ 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
// 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
@ -31,7 +31,7 @@ class MediaSource;
can be changed.
@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
{
@ -67,9 +67,6 @@ class UserInterface
void sendJoyEvent(StellaEvent::JoyStick stick, StellaEvent::JoyCode code,
Int32 state);
void sendKeymap(Event::Type table[StellaEvent::LastKCODE]);
void sendJoymap(Event::Type table[StellaEvent::LastJSTICK][StellaEvent::LastJCODE]);
public:
void showMainMenu(bool show);
void showMessage(const string& message);
@ -77,7 +74,7 @@ class UserInterface
private:
// 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();
Event::Type currentSelectedEvent();
@ -85,11 +82,21 @@ class UserInterface
void moveCursorUp();
void moveCursorDown();
// Draw a bounded box centered horizontally
void drawBoundedBox(uInt32 width, uInt32 height);
// Draw a bounded box at the specified coordinates
void drawBoundedBox(uInt32 x, uInt32 y, uInt32 width, uInt32 height);
// 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:
// The Console for the system
@ -98,11 +105,29 @@ class UserInterface
// The Mediasource for the system
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
uInt32 myXStart, myYStart, myWidth, myHeight;
// Table of bitmapped fonts. Holds A..Z and 0..9.
static const uInt32 ourFontData[36];
// Table of bitmapped fonts.
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
Widget myCurrentWidget;
@ -113,17 +138,45 @@ class UserInterface
// Indicates the current selected event being remapped
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
Int32 myMessageTime;
// Message text
string myMessageText;
// The width of the information menu, determined by the longest string
uInt32 myInfoMenuWidth;
// Holds information about the current selected ROM image
string ourPropertiesInfo[6];
// The width of the information menu, determined by the longest string
uInt32 myInfoMenuWidth;
// Holds static strings for the main menu
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