diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 73e569550..7e17d6cd6 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -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 @@ -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; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index c75b8703f..7b0abf82b 100644 --- a/stella/src/emucore/EventHandler.hxx +++ b/stella/src/emucore/EventHandler.hxx @@ -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]; diff --git a/stella/src/emucore/Settings.cxx b/stella/src/emucore/Settings.cxx index 7227354f2..ce607a296 100644 --- a/stella/src/emucore/Settings.cxx +++ b/stella/src/emucore/Settings.cxx @@ -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 +#include #include #include diff --git a/stella/src/emucore/StellaEvent.hxx b/stella/src/emucore/StellaEvent.hxx index 777006e01..d6f85627f 100644 --- a/stella/src/emucore/StellaEvent.hxx +++ b/stella/src/emucore/StellaEvent.hxx @@ -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 { diff --git a/stella/src/emucore/TIA.hxx b/stella/src/emucore/TIA.hxx index f4769cb0c..a7b7c37f5 100644 --- a/stella/src/emucore/TIA.hxx +++ b/stella/src/emucore/TIA.hxx @@ -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 diff --git a/stella/src/emucore/UserInterface.cxx b/stella/src/emucore/UserInterface.cxx index 435b58d65..7bb29df3c 100644 --- a/stella/src/emucore/UserInterface.cxx +++ b/stella/src/emucore/UserInterface.cxx @@ -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" +}; + diff --git a/stella/src/emucore/UserInterface.hxx b/stella/src/emucore/UserInterface.hxx index 21d0fcc20..dc5990747 100644 --- a/stella/src/emucore/UserInterface.hxx +++ b/stella/src/emucore/UserInterface.hxx @@ -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