diff --git a/stella/src/build/makefile b/stella/src/build/makefile index 04093d9a5..9e41e6e3a 100644 --- a/stella/src/build/makefile +++ b/stella/src/build/makefile @@ -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: makefile,v 1.43 2003-10-26 19:40:39 stephena Exp $ +## $Id: makefile,v 1.44 2003-11-06 22:22:32 stephena Exp $ ##============================================================================ ##============================================================================ @@ -34,10 +34,10 @@ SOUND_OSS = 1 #SOUND_SDL = 1 ### to include OpenGL video support (SDL) -#DISPLAY_OPENGL = 1 +DISPLAY_OPENGL = 0 ### to include joystick support (SDL) - JOYSTICK_SUPPORT = 1 +# JOYSTICK_SUPPORT = 1 ### to include support for saving snapshots in png format ### (requires PNG library) FIXME @@ -142,10 +142,14 @@ endif ifeq ($(DISPLAY_OPENGL), 1) OPTS.SDL += -DDISPLAY_OPENGL=1 - OBJS.SDL += DispGLSDL.o + OBJS.SDL += FrameBufferGL.o LIBS.SDL += -lGL -lGLU endif +ifeq ($(DISPLAY_OPENGL), 0) + OBJS.SDL += FrameBufferSDL.o +endif + default: @echo "" @@ -181,7 +185,7 @@ linux-sdl: LDFLAGS+="$(CFLAGS.SDL)" \ LDLIBS="-lX11 -lXext" \ LDLIBS+="$(LIBS.SDL)" \ - OBJS="mainSDL.o FrameBufferSDL.o RectList.o SettingsUNIX.o" \ + OBJS="mainSDL.o SettingsUNIX.o" \ OBJS+="$(OBJS.SDL)" ############################################################################### diff --git a/stella/src/emucore/Console.cxx b/stella/src/emucore/Console.cxx index a577262a8..41a164d5e 100644 --- a/stella/src/emucore/Console.cxx +++ b/stella/src/emucore/Console.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: Console.cxx,v 1.19 2003-10-26 19:40:39 stephena Exp $ +// $Id: Console.cxx,v 1.20 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -39,6 +39,7 @@ #include "Props.hxx" #include "PropsSet.hxx" #include "Settings.hxx" +#include "Sound.hxx" #include "Switches.hxx" #include "System.hxx" #include "TIA.hxx" @@ -50,11 +51,12 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Console::Console(const uInt8* image, uInt32 size, const char* filename, - Settings& rcsettings, PropertiesSet& propertiesSet, - FrameBuffer& framebuffer, uInt32 sampleRate) - : mySettings(rcsettings), + Settings& settings, PropertiesSet& propertiesSet, + FrameBuffer& framebuffer, Sound& sound) + : mySettings(settings), myPropSet(propertiesSet), - myFrameBuffer(framebuffer) + myFrameBuffer(framebuffer), + mySound(sound) { myControllers[0] = 0; myControllers[1] = 0; @@ -158,7 +160,7 @@ Console::Console(const uInt8* image, uInt32 size, const char* filename, } M6532* m6532 = new M6532(*this); - TIA* tia = new TIA(*this, sampleRate); + TIA* tia = new TIA(*this, mySound.getSampleRate()); Cartridge* cartridge = Cartridge::create(image, size, myProperties); mySystem->attach(m6502); @@ -181,7 +183,8 @@ Console::Console(const uInt8* image, uInt32 size, const char* filename, Console::Console(const Console& console) : mySettings(console.mySettings), myPropSet(console.myPropSet), - myFrameBuffer(console.myFrameBuffer) + myFrameBuffer(console.myFrameBuffer), + mySound(console.mySound) { // TODO: Write this method assert(false); @@ -215,6 +218,12 @@ FrameBuffer& Console::frameBuffer() const return myFrameBuffer; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Sound& Console::sound() const +{ + return mySound; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Console& Console::operator = (const Console&) { diff --git a/stella/src/emucore/Console.hxx b/stella/src/emucore/Console.hxx index 34b8ee96e..ae62de878 100644 --- a/stella/src/emucore/Console.hxx +++ b/stella/src/emucore/Console.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: Console.hxx,v 1.14 2003-10-26 19:40:39 stephena Exp $ +// $Id: Console.hxx,v 1.15 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef CONSOLE_HXX @@ -41,7 +41,7 @@ class FrameBuffer; This class represents the entire game console. @author Bradford W. Mott - @version $Id: Console.hxx,v 1.14 2003-10-26 19:40:39 stephena Exp $ + @version $Id: Console.hxx,v 1.15 2003-11-06 22:22:32 stephena Exp $ */ class Console { @@ -50,17 +50,17 @@ class Console Create a new console for emulating the specified game using the given event object and game profiles. - @param image The ROM image of the game to emulate - @param size The size of the ROM image - @param filename The name of the file that contained the ROM image - @param rcsettings The settings object to use - @param profiles The game profiles object to use + @param image The ROM image of the game to emulate + @param size The size of the ROM image + @param filename The name of the file that contained the ROM image + @param settings The settings object to use + @param profiles The game profiles object to use @param framebuffer The framebuffer object to use - @param sampleRate The rate to create audio samples at + @param sound The sound object to use */ Console(const uInt8* image, uInt32 size, const char* filename, - Settings& rcsettings, PropertiesSet& propertiesSet, - FrameBuffer& framebuffer, uInt32 sampleRate); + Settings& settings, PropertiesSet& propertiesSet, + FrameBuffer& framebuffer, Sound& sound); /** Create a new console object by copying another one @@ -106,6 +106,13 @@ class Console */ FrameBuffer& frameBuffer() const; + /** + Get the sound object of the console + + @return The sound object for this console + */ + Sound& sound() const; + /** Get the console switches @@ -246,6 +253,9 @@ class Console // Reference to the FrameBuffer object FrameBuffer& myFrameBuffer; + // Reference to the Sound object + Sound& mySound; + // Pointer to the EventHandler object EventHandler* myEventHandler; diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 557c3e22d..f623de08b 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.17 2003-10-26 19:40:39 stephena Exp $ +// $Id: EventHandler.cxx,v 1.18 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -27,6 +27,7 @@ #include "StellaEvent.hxx" #include "System.hxx" #include "FrameBuffer.hxx" +#include "Sound.hxx" #include "bspf.hxx" #ifdef SNAPSHOT_SUPPORT @@ -38,6 +39,7 @@ EventHandler::EventHandler(Console* console) : myConsole(console), myCurrentState(0), myPauseStatus(false), + myQuitStatus(false), myMenuStatus(false), myRemapEnabledFlag(true) { @@ -84,11 +86,13 @@ Event* EventHandler::event() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::sendKeyEvent(StellaEvent::KeyCode key, Int32 state) { - // First check if we are entering menu mode - if(myRemapEnabledFlag && key == StellaEvent::KCODE_TAB && state == 1) + // First check if we are changing menu mode, and only change when not paused + // Sound is paused when entering menu mode, but the framebuffer is kept active + if(myRemapEnabledFlag && key == StellaEvent::KCODE_TAB && state == 1 && !myPauseStatus) { myMenuStatus = !myMenuStatus; - myConsole->frameBuffer().showMainMenu(myMenuStatus); + myConsole->frameBuffer().showMenu(myMenuStatus); + myConsole->sound().pause(myMenuStatus); return; } @@ -145,13 +149,13 @@ void EventHandler::sendEvent(Event::Type event, Int32 state) { myPauseStatus = !myPauseStatus; myConsole->frameBuffer().pause(myPauseStatus); -//FIXME myConsole->sound().pause(myPauseStatus); + myConsole->sound().pause(myPauseStatus); return; } else if(event == Event::Quit) { + myQuitStatus = !myQuitStatus; myConsole->settings().saveConfig(); - myConsole->settings().setQuitEvent(); return; } diff --git a/stella/src/emucore/EventHandler.hxx b/stella/src/emucore/EventHandler.hxx index cc92d801f..8b039b693 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.11 2003-10-26 19:40:39 stephena Exp $ +// $Id: EventHandler.hxx,v 1.12 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef EVENTHANDLER_HXX @@ -41,7 +41,7 @@ class MediaSource; mapping can take place. @author Stephen Anthony - @version $Id: EventHandler.hxx,v 1.11 2003-10-26 19:40:39 stephena Exp $ + @version $Id: EventHandler.hxx,v 1.12 2003-11-06 22:22:32 stephena Exp $ */ class EventHandler { @@ -118,6 +118,16 @@ class EventHandler */ void enableRemapping(bool status) { myRemapEnabledFlag = status; } + /** + This method indicated whether a pause event has been received. + */ + bool doPause() { return myPauseStatus; } + + /** + This method indicated whether a quit event has been received. + */ + bool doQuit() { return myQuitStatus; } + void getKeymapArray(Event::Type** array, uInt32* size); void getJoymapArray(Event::Type** array, uInt32* size); @@ -159,6 +169,9 @@ class EventHandler // Indicates the current pause status bool myPauseStatus; + // Indicates the current quit status + bool myQuitStatus; + // The current keymap in string form string myKeymapString; diff --git a/stella/src/emucore/FrameBuffer.cxx b/stella/src/emucore/FrameBuffer.cxx index 02c767920..d7a660546 100644 --- a/stella/src/emucore/FrameBuffer.cxx +++ b/stella/src/emucore/FrameBuffer.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: FrameBuffer.cxx,v 1.2 2003-10-26 19:40:39 stephena Exp $ +// $Id: FrameBuffer.cxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -57,6 +57,8 @@ FrameBuffer::FrameBuffer() myCurrentWidget(W_NONE), myRemapEventSelectedFlag(false), mySelectedEvent(Event::NoType), + myMenuMode(false), + theMenuChangedIndicator(false), myMaxLines(0), myMainMenuIndex(0), myMainMenuItems(sizeof(ourMainMenu)/sizeof(MainMenuItem)), @@ -84,23 +86,19 @@ void FrameBuffer::initDisplay(Console* console, MediaSource* mediasrc) // Fill the properties info array with game information 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(); + ourPropertiesInfo[1] = ""; + ourPropertiesInfo[2] = "Manufacturer: " + myConsole->properties().get("Cartridge.Manufacturer"); + ourPropertiesInfo[3] = "Model: " + myConsole->properties().get("Cartridge.ModelNo"); + ourPropertiesInfo[4] = "Rarity: " + myConsole->properties().get("Cartridge.Rarity"); + ourPropertiesInfo[5] = "Type: " + myConsole->properties().get("Cartridge.Type"); + ourPropertiesInfo[6] = ""; + ourPropertiesInfo[7] = "MD5SUM:"; + ourPropertiesInfo[8] = myConsole->properties().get("Cartridge.MD5"); + + // Figure out the longest string + for(uInt8 i = 0; i < 9; i++) + if(ourPropertiesInfo[i].length() > myInfoMenuWidth) + myInfoMenuWidth = ourPropertiesInfo[i].length(); // Get the arrays containing key and joystick mappings myConsole->eventHandler().getKeymapArray(&myKeyTable, &myKeyTableSize); @@ -128,51 +126,75 @@ void FrameBuffer::update() // Do any pre-frame stuff preFrameUpdate(); - // Draw changes to the mediasource - if(!myPauseStatus) // FIXME - sound class - myMediaSource->update(); - - drawMediaSource(); - - // Then overlay any menu items - switch(myCurrentWidget) + // Determine which mode we are in (normal or menu mode) + // In normal mode, only the mediasource or messages are shown, + // and they are shown per-frame + // In menu mode, any of the menus are shown, but the mediasource + // is not updated, and all updates depend on whether the screen is dirty + if(!myMenuMode) { - case W_NONE: - break; + // Draw changes to the mediasource + if(!myPauseStatus) + myMediaSource->update(); - case MAIN_MENU: - drawMainMenu(); - break; + // We always draw the screen, even if the core is paused + drawMediaSource(); - case REMAP_MENU: - drawRemapMenu(); - break; + if(!myPauseStatus) + { + // Draw any pending messages + if(myMessageTime > 0) + { + uInt32 width = myMessageText.length()*FONTWIDTH + FONTWIDTH; + uInt32 height = LINEOFFSET + FONTHEIGHT; + uInt32 x = (myWidth >> 1) - (width >> 1); + uInt32 y = myHeight - height - LINEOFFSET/2; - case INFO_MENU: - drawInfoMenu(); - break; + // Draw the bounded box and text + drawBoundedBox(x, y, width, height, FGCOLOR, BGCOLOR); + drawText(x + XBOXOFFSET/2, LINEOFFSET/2 + y, myMessageText, FGCOLOR); + myMessageTime--; - default: - break; + // Erase this message on next update + if(myMessageTime == 0) + theRedrawEntireFrameIndicator = true; + } + } } - - // A message is a special case of interface element - // It can overwrite even a menu - if(myMessageTime > 0) + else // we are in MENU_MODE { - uInt32 width = myMessageText.length()*FONTWIDTH + FONTWIDTH; - uInt32 height = LINEOFFSET + FONTHEIGHT; - uInt32 x = (myWidth >> 1) - (width >> 1); - uInt32 y = myHeight - height - LINEOFFSET/2; + // Only update the screen if it's been invalidated + // or the menus have changed + if(theMenuChangedIndicator || theRedrawEntireFrameIndicator) + { +cerr << "redrawing screen and menus\n"; + drawMediaSource(); - // Draw the bounded box and text - drawBoundedBox(x, y, width, height, FGCOLOR, BGCOLOR); - drawText(x + XBOXOFFSET/2, LINEOFFSET/2 + y, myMessageText, FGCOLOR); - myMessageTime--; + // Then overlay any menu items + switch(myCurrentWidget) + { + case W_NONE: + break; - // Erase this message on next update - if(myMessageTime == 0) - theRedrawEntireFrameIndicator = true; + case MAIN_MENU: + drawMainMenu(); + break; + + case REMAP_MENU: + drawRemapMenu(); + break; + + case INFO_MENU: + drawInfoMenu(); + break; + + default: + break; + } + + // Now the screen is up to date + theMenuChangedIndicator = theRedrawEntireFrameIndicator = false; + } } // Do any post-frame stuff @@ -180,8 +202,10 @@ void FrameBuffer::update() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBuffer::showMainMenu(bool show) +void FrameBuffer::showMenu(bool show) { + myMenuMode = show; + myCurrentWidget = show ? MAIN_MENU : W_NONE; myRemapEventSelectedFlag = false; mySelectedEvent = Event::NoType; @@ -192,7 +216,7 @@ void FrameBuffer::showMainMenu(bool show) void FrameBuffer::showMessage(const string& message) { myMessageText = message; - myMessageTime = myFrameRate << 1; + myMessageTime = myFrameRate << 1; // Show message for 2 seconds theRedrawEntireFrameIndicator = true; } @@ -202,7 +226,7 @@ inline void FrameBuffer::drawMainMenu() uInt32 x, y, width, height, i, xpos, ypos; width = 16*FONTWIDTH + (FONTWIDTH << 1); - height = myMainMenuItems*LINEOFFSET + 2*FONTHEIGHT; + height = myMainMenuItems*LINEOFFSET + (FONTHEIGHT << 1); x = (myWidth >> 1) - (width >> 1); y = (myHeight >> 1) - (height >> 1); @@ -224,7 +248,7 @@ inline void FrameBuffer::drawRemapMenu() uInt32 x, y, width, height, i, xpos, ypos; width = (myWidth >> 3) * FONTWIDTH - (FONTWIDTH << 1); - height = myMaxLines*LINEOFFSET + 2*FONTHEIGHT; + height = myMaxLines*LINEOFFSET + (FONTHEIGHT << 1); x = (myWidth >> 1) - (width >> 1); y = (myHeight >> 1) - (height >> 1); @@ -260,12 +284,12 @@ inline void FrameBuffer::drawRemapMenu() } // Finally, indicate that there are more items to the top or bottom - xpos = (width >> 1) - FONTWIDTH/2; + xpos = (width >> 1) - (FONTWIDTH >> 1); if(myRemapMenuHighIndex - myMaxLines > 0) drawChar(xpos, y, UPARROW, FGCOLOR); if(myRemapMenuLowIndex + myMaxLines < myRemapMenuItems) - drawChar(xpos, height - FONTWIDTH/2, DOWNARROW, FGCOLOR); + drawChar(xpos, height - (FONTWIDTH >> 1), DOWNARROW, FGCOLOR); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -273,15 +297,15 @@ inline void FrameBuffer::drawInfoMenu() { uInt32 x, y, width, height, i, xpos; - width = myInfoMenuWidth*FONTWIDTH + 2*FONTWIDTH; - height = 6*LINEOFFSET + 2*FONTHEIGHT; + width = myInfoMenuWidth*FONTWIDTH + (FONTWIDTH << 1); + height = 9*LINEOFFSET + (FONTHEIGHT << 1); x = (myWidth >> 1) - (width >> 1); y = (myHeight >> 1) - (height >> 1); // Draw the bounded box and text xpos = x + XBOXOFFSET; drawBoundedBox(x, y, width, height, FGCOLOR, BGCOLOR); - for(i = 0; i < 6; i++) + for(i = 0; i < 9; i++) drawText(xpos, LINEOFFSET*i + y + YBOXOFFSET, ourPropertiesInfo[i], FGCOLOR); } @@ -291,6 +315,9 @@ void FrameBuffer::sendKeyEvent(StellaEvent::KeyCode key, Int32 state) if(myCurrentWidget == W_NONE || state != 1) return; + // Redraw the menus whenever a key event is received + theMenuChangedIndicator = true; + // Check which type of widget is pending switch(myCurrentWidget) { @@ -357,6 +384,8 @@ void FrameBuffer::sendJoyEvent(StellaEvent::JoyStick stick, return; cerr << "stick = " << stick << ", button = " << code << endl; + // Redraw the menus whenever a joy event is received + theMenuChangedIndicator = true; // Check which type of widget is pending switch(myCurrentWidget) @@ -663,7 +692,7 @@ const uInt8 FrameBuffer::ourFontData[2048] = { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBuffer::MainMenuItem FrameBuffer::ourMainMenu[2] = { - { REMAP_MENU, "Key Remapping" }, + { REMAP_MENU, "Event Remapping" }, { INFO_MENU, "Game Information" } }; diff --git a/stella/src/emucore/FrameBuffer.hxx b/stella/src/emucore/FrameBuffer.hxx index ea7d0f785..f00142241 100644 --- a/stella/src/emucore/FrameBuffer.hxx +++ b/stella/src/emucore/FrameBuffer.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: FrameBuffer.hxx,v 1.2 2003-10-26 19:40:39 stephena Exp $ +// $Id: FrameBuffer.hxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_HXX @@ -35,7 +35,7 @@ class Console; can be changed. @author Stephen Anthony - @version $Id: FrameBuffer.hxx,v 1.2 2003-10-26 19:40:39 stephena Exp $ + @version $Id: FrameBuffer.hxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ */ class FrameBuffer { @@ -70,7 +70,7 @@ class FrameBuffer @param show Show/hide the menu based on the boolean value */ - void showMainMenu(bool show); + void showMenu(bool show); /** Shows a message onscreen. @@ -280,6 +280,12 @@ class FrameBuffer // Indicates the current selected event being remapped Event::Type mySelectedEvent; + // Indicates if we are in menu mode + bool myMenuMode; + + // Indicates if the menus should be redrawn + bool theMenuChangedIndicator; + // The maximum number of vertical lines of text that can be onscreen uInt32 myMaxLines; @@ -300,7 +306,7 @@ class FrameBuffer uInt32 myInfoMenuWidth; // Holds information about the current selected ROM image - string ourPropertiesInfo[6]; + string ourPropertiesInfo[9]; // Holds static strings for the main menu static MainMenuItem ourMainMenu[2]; diff --git a/stella/src/emucore/Settings.cxx b/stella/src/emucore/Settings.cxx index ce607a296..9e239102b 100644 --- a/stella/src/emucore/Settings.cxx +++ b/stella/src/emucore/Settings.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: Settings.cxx,v 1.10 2003-09-28 21:59:24 stephena Exp $ +// $Id: Settings.cxx,v 1.11 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -32,9 +32,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Settings::Settings() - : myPauseIndicator(false), - myQuitIndicator(false), - myConsole(0) + : myConsole(0) { // First create the settings array myCapacity = 30; diff --git a/stella/src/emucore/Settings.hxx b/stella/src/emucore/Settings.hxx index 25e7bf8e3..d59bda314 100644 --- a/stella/src/emucore/Settings.hxx +++ b/stella/src/emucore/Settings.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: Settings.hxx,v 1.8 2003-10-26 19:40:39 stephena Exp $ +// $Id: Settings.hxx,v 1.9 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef SETTINGS_HXX @@ -32,7 +32,7 @@ class Console; This class provides an interface for accessing frontend specific settings. @author Stephen Anthony - @version $Id: Settings.hxx,v 1.8 2003-10-26 19:40:39 stephena Exp $ + @version $Id: Settings.hxx,v 1.9 2003-11-06 22:22:32 stephena Exp $ */ class Settings { @@ -134,32 +134,6 @@ class Settings */ void setConsole(Console* console) { myConsole = console; } - /** - This method should be called when the emulation core receives - a QUIT event. - */ - void setQuitEvent() { myQuitIndicator = true; } - - /** - This method determines whether the QUIT event has been received. - - @return Boolean representing whether a QUIT event has been received - */ - bool quit() { return myQuitIndicator; } - - /** - This method should be called at when the emulation core receives - a PAUSE event. - */ - void setPauseEvent(bool status) { myPauseIndicator = status; } - - /** - This method determines whether the PAUSE event has been received. - - @return Boolean representing whether a PAUSE event has been received - */ - bool pause() { return myPauseIndicator; } - /** This method should be called to get the filename of the users' properties (stella.pro) file. @@ -204,9 +178,6 @@ class Settings #endif protected: - bool myPauseIndicator; - bool myQuitIndicator; - string myBaseDir; string myStateDir; string myStateFile; diff --git a/stella/src/emucore/Sound.cxx b/stella/src/emucore/Sound.cxx index 23a40aa85..987d78384 100644 --- a/stella/src/emucore/Sound.cxx +++ b/stella/src/emucore/Sound.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: Sound.cxx,v 1.5 2003-02-25 03:12:54 stephena Exp $ +// $Id: Sound.cxx,v 1.6 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include "Sound.hxx" @@ -50,6 +50,11 @@ void Sound::setSoundVolume(Int32 volume) { } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Sound::pause(bool status) +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Sound::updateSound(MediaSource& mediaSource) { diff --git a/stella/src/emucore/Sound.hxx b/stella/src/emucore/Sound.hxx index b72981934..fbe8412fe 100644 --- a/stella/src/emucore/Sound.hxx +++ b/stella/src/emucore/Sound.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: Sound.hxx,v 1.5 2003-02-25 03:12:55 stephena Exp $ +// $Id: Sound.hxx,v 1.6 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef SOUND_HXX @@ -28,7 +28,7 @@ to compile Stella with no sound support whatsoever. @author Stephen Anthony - @version $Id: Sound.hxx,v 1.5 2003-02-25 03:12:55 stephena Exp $ + @version $Id: Sound.hxx,v 1.6 2003-11-06 22:22:32 stephena Exp $ */ class Sound { @@ -72,6 +72,14 @@ class Sound */ virtual void setSoundVolume(Int32 percent); + /** + Sets the pause status. While pause is selected, updateSound() + should not play any sound. + + @param status Toggle pause based on status + */ + virtual void pause(bool status); + /** Update the sound device using the audio sample from the specified media source. diff --git a/stella/src/ui/common/Snapshot.cxx b/stella/src/ui/common/Snapshot.cxx index e654970ac..4f3f5a5c0 100644 --- a/stella/src/ui/common/Snapshot.cxx +++ b/stella/src/ui/common/Snapshot.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: Snapshot.cxx,v 1.6 2003-10-17 18:02:16 stephena Exp $ +// $Id: Snapshot.cxx,v 1.7 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -22,6 +22,7 @@ #include "bspf.hxx" #include "FrameBuffer.hxx" +#include "MediaSrc.hxx" #include "Snapshot.hxx" @@ -62,20 +63,19 @@ void Snapshot::png_user_error(png_structp ctx, png_const_charp str) This routine saves the current frame buffer to a 256 color PNG file, appropriately scaled by the amount specified in 'multiplier'. */ -int Snapshot::savePNG(string filename, FrameBuffer& frameBuffer, uInt32 multiplier) +int Snapshot::savePNG(string filename, FrameBuffer& framebuffer, uInt32 multiplier) { -#if 0 -// FIXME png_structp png_ptr = 0; png_infop info_ptr = 0; + MediaSource* source = framebuffer.mediaSource(); - uInt8* pixels = frameBuffer.current(); + uInt8* pixels = source->currentFrameBuffer(); // PNG and window dimensions will be different because of scaling - int picWidth = frameBuffer.width() * 2 * multiplier; - int picHeight = frameBuffer.height() * multiplier; - int width = frameBuffer.width(); - int height = frameBuffer.height(); + int picWidth = framebuffer.width() * multiplier; + int picHeight = framebuffer.height() * multiplier; + int width = source->width(); + int height = source->height(); ofstream* out = new ofstream(filename.c_str()); if(!out) @@ -93,7 +93,7 @@ int Snapshot::savePNG(string filename, FrameBuffer& frameBuffer, uInt32 multipli return 0; } - const uInt32* gamePalette = frameBuffer.palette(); + const uInt32* gamePalette = source->palette(); for(uInt32 i = 0; i < 256; ++i) { palette[i].red = (uInt8) ((gamePalette[i] & 0x00ff0000) >> 16); @@ -138,7 +138,7 @@ int Snapshot::savePNG(string filename, FrameBuffer& frameBuffer, uInt32 multipli // The width has to be scaled by 2 * multiplier. Each pixel must be // present scaleX times. Each scanline must be present scaleY times. - int scaleX = 2 * multiplier; + int scaleX = multiplier << 1; int scaleY = multiplier; // Create a buffer to hold the new scanline. @@ -172,6 +172,6 @@ int Snapshot::savePNG(string filename, FrameBuffer& frameBuffer, uInt32 multipli out->close(); delete out; -#endif + return 1; } diff --git a/stella/src/ui/common/Snapshot.hxx b/stella/src/ui/common/Snapshot.hxx index de125285a..9b403ac9a 100644 --- a/stella/src/ui/common/Snapshot.hxx +++ b/stella/src/ui/common/Snapshot.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: Snapshot.hxx,v 1.3 2003-10-17 18:02:16 stephena Exp $ +// $Id: Snapshot.hxx,v 1.4 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef SNAPSHOT_HXX @@ -31,7 +31,7 @@ class Snapshot Snapshot(); ~Snapshot(); - int savePNG(string filename, FrameBuffer& mediaSource, uInt32 multiplier = 1); + int savePNG(string filename, FrameBuffer& framebuffer, uInt32 multiplier = 1); private: static void png_write_data(png_structp ctx, png_bytep area, png_size_t size); diff --git a/stella/src/ui/sdl/FrameBufferGL.cxx b/stella/src/ui/sdl/FrameBufferGL.cxx new file mode 100644 index 000000000..bd3574c6c --- /dev/null +++ b/stella/src/ui/sdl/FrameBufferGL.cxx @@ -0,0 +1,586 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-1999 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: FrameBufferGL.cxx,v 1.1 2003-11-06 22:22:32 stephena Exp $ +//============================================================================ + +#include +#include +#include + +#include "Console.hxx" +#include "FrameBuffer.hxx" +#include "FrameBufferGL.hxx" +#include "MediaSrc.hxx" +#include "Settings.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FrameBufferGL::FrameBufferGL() + : myScreen(0), + myTexture(0), + x11Available(false), + theZoomLevel(1), + theMaxZoomLevel(1), + theGrabMouseIndicator(false), + theHideCursorIndicator(false), + isFullscreen(false) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FrameBufferGL::~FrameBufferGL() +{ + if(myTexture) + SDL_FreeSurface(myTexture); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferGL::init() +{ + // Get the desired width and height of the display + myWidth = myMediaSource->width() << 1; + myHeight = myMediaSource->height(); + + // Now create the OpenGL SDL screen + Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER; + if(SDL_Init(initflags) < 0) + return false; + + // Check which system we are running under + x11Available = false; + SDL_VERSION(&myWMInfo.version); + if(SDL_GetWMInfo(&myWMInfo) > 0) + if(myWMInfo.subsystem == SDL_SYSWM_X11) + x11Available = true; + + // Get the maximum size of a window for THIS screen + theMaxZoomLevel = maxWindowSizeForScreen(); + + // Check to see if window size will fit in the screen + if((uInt32)myConsole->settings().getInt("zoom") > theMaxZoomLevel) + theZoomLevel = theMaxZoomLevel; + else + theZoomLevel = myConsole->settings().getInt("zoom"); + + mySDLFlags = SDL_OPENGL; + mySDLFlags |= myConsole->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0; + + // Set the window title and icon + ostringstream name; + name << "Stella: \"" << myConsole->properties().get("Cartridge.Name") << "\""; + SDL_WM_SetCaption(name.str().c_str(), "stella"); + + // Set up the OpenGL attributes + int rgb_size[3]; + int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel; + switch(bpp) + { + case 8: + rgb_size[0] = 3; + rgb_size[1] = 3; + rgb_size[2] = 2; + break; + + case 15: + case 16: + rgb_size[0] = 5; + rgb_size[1] = 5; + rgb_size[2] = 5; + break; + + default: + rgb_size[0] = 8; + rgb_size[1] = 8; + rgb_size[2] = 8; + break; + } + SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] ); + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] ); + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] ); + SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp ); + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + // Create the screen + if(!createScreen()) + return false; + setupPalette(1.0); + + // Show some OpenGL info + if(myConsole->settings().getBool("showinfo")) + { + cout << endl + << "Vendor : " << glGetString(GL_VENDOR) << endl + << "Renderer: " << glGetString(GL_RENDERER) << endl + << "Version : " << glGetString(GL_VERSION) << endl; + } + + // Create the texture surface and texture fonts + createTextures(); + + // Make sure that theUseFullScreenFlag sets up fullscreen mode correctly + theGrabMouseIndicator = myConsole->settings().getBool("grabmouse"); + theHideCursorIndicator = myConsole->settings().getBool("hidecursor"); + if(myConsole->settings().getBool("fullscreen")) + { + grabMouse(true); + showCursor(false); + isFullscreen = true; + } + else + { + // Keep mouse in game window if grabmouse is selected + grabMouse(theGrabMouseIndicator); + + // Show or hide the cursor depending on the 'hidecursor' argument + showCursor(!theHideCursorIndicator); + } + + // Set up global GL stuff + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_LINE_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::drawMediaSource() // FIXME - maybe less copying can be done? +{ + // Copy the mediasource framebuffer to the RGB texture + uInt8* currentFrame = myMediaSource->currentFrameBuffer(); + uInt8* previousFrame = myMediaSource->previousFrameBuffer(); + uInt32 width = myMediaSource->width(); + uInt32 height = myMediaSource->height(); + uInt32* buffer = (uInt32*) myTexture->pixels; + + register uInt32 y; + for(y = 0; y < height; ++y ) + { + const uInt32 bufofsY = y * width; + const uInt32 screenofsY = y * myTexture->w; + + register uInt32 x; + for(x = 0; x < width; ++x ) + { + const uInt32 bufofs = bufofsY + x; + uInt8 v = currentFrame[bufofs]; + if(v == previousFrame[bufofs] && !theRedrawEntireFrameIndicator) + continue; + + // x << 1 is times 2 ( doubling width ) WIDTH_FACTOR + const uInt32 pos = screenofsY + (x << 1); + buffer[pos] = buffer[pos+1] = myPalette[v]; + } + } + + // Texturemap complete texture to surface so we have free scaling + // and antialiasing + glBindTexture(GL_TEXTURE_2D, myTextureID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myTexture->w, myTexture->h, + GL_RGBA, GL_UNSIGNED_BYTE, myTexture->pixels); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + + glBegin(GL_QUADS); + glTexCoord2f(myTexCoord[0], myTexCoord[1]); glVertex2i(0, 0); + glTexCoord2f(myTexCoord[2], myTexCoord[1]); glVertex2i(myWidth, 0); + glTexCoord2f(myTexCoord[2], myTexCoord[3]); glVertex2i(myWidth, myHeight); + glTexCoord2f(myTexCoord[0], myTexCoord[3]); glVertex2i(0, myHeight); + glEnd(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::preFrameUpdate() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::postFrameUpdate() +{ + // Now show all changes made to the textures + SDL_GL_SwapBuffers(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferGL::createScreen() +{ + int w = myWidth * theZoomLevel; + int h = myHeight * theZoomLevel; + + myScreen = SDL_SetVideoMode(w, h, 0, mySDLFlags); + if(myScreen == NULL) + { + cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; + return false; + } + + glPushAttrib(GL_ENABLE_BIT); + glViewport(0, 0, myScreen->w, myScreen->h); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, (GLdouble) myScreen->w/theZoomLevel, + (GLdouble) myScreen->h/theZoomLevel, 0.0, 0.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + theRedrawEntireFrameIndicator = true; + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::setupPalette(float shade) +{ +// FIXME - OpenGL should be able to shade the texture itself + const uInt32* gamePalette = myMediaSource->palette(); + for(uInt32 i = 0; i < 256; ++i) + { + Uint8 r, g, b, a; + + r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade); + g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade); + b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade); + a = 0xff; + + #if SDL_BYTEORDER == SDL_LIL_ENDIAN + myPalette[i] = (a << 24) | (b << 16) | (g << 8) | r; + #else + myPalette[i] = (r << 24) | (g << 16) | (b << 8) | a; + #endif + } + + theRedrawEntireFrameIndicator = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::pause(bool status) +{ + myPauseStatus = status; + + // Shade the palette to 75% normal value in pause mode + // FIXME - this seems like cheating, we should be using OpenGL instead + if(myPauseStatus) + setupPalette(0.75); + else + setupPalette(1.0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::toggleFullscreen() +{ + isFullscreen = !isFullscreen; + if(isFullscreen) + mySDLFlags |= SDL_FULLSCREEN; + else + mySDLFlags &= ~SDL_FULLSCREEN; + + if(!createScreen()) + return; + + if(isFullscreen) // now in fullscreen mode + { + grabMouse(true); + showCursor(false); + } + else // now in windowed mode + { + grabMouse(theGrabMouseIndicator); + showCursor(!theHideCursorIndicator); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::resize(int mode) +{ + // reset size to that given in properties + // this is a special case of allowing a resize while in fullscreen mode + if(mode == 0) + { + myWidth = myMediaSource->width() << 1; + myHeight = myMediaSource->height(); + } + else if(mode == 1) // increase size + { + if(isFullscreen) + return; + + if(theZoomLevel == theMaxZoomLevel) + theZoomLevel = 1; + else + theZoomLevel++; + } + else if(mode == -1) // decrease size + { + if(isFullscreen) + return; + + if(theZoomLevel == 1) + theZoomLevel = theMaxZoomLevel; + else + theZoomLevel--; + } + + if(!createScreen()) + return; + + // Now update the settings + ostringstream tmp; + tmp << theZoomLevel; + myConsole->settings().set("zoom", tmp.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::showCursor(bool show) +{ + if(isFullscreen) + return; + + if(show) + SDL_ShowCursor(SDL_ENABLE); + else + SDL_ShowCursor(SDL_DISABLE); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::grabMouse(bool grab) +{ + if(isFullscreen) + return; + + if(grab) + SDL_WM_GrabInput(SDL_GRAB_ON); + else + SDL_WM_GrabInput(SDL_GRAB_OFF); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 FrameBufferGL::maxWindowSizeForScreen() +{ + if(!x11Available) + return 1; + +#ifdef UNIX + // Otherwise, lock the screen and get the width and height + myWMInfo.info.x11.lock_func(); + Display* theX11Display = myWMInfo.info.x11.display; + myWMInfo.info.x11.unlock_func(); + + int screenWidth = DisplayWidth(theX11Display, DefaultScreen(theX11Display)); + int screenHeight = DisplayHeight(theX11Display, DefaultScreen(theX11Display)); + + uInt32 multiplier = screenWidth / myWidth; + bool found = false; + + while(!found && (multiplier > 0)) + { + // Figure out the desired size of the window + int width = myWidth * multiplier; + int height = myHeight * multiplier; + + if((width < screenWidth) && (height < screenHeight)) + found = true; + else + multiplier--; + } + + if(found) + return multiplier; + else + return 1; +#else + return 1; +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h, + uInt8 fg, uInt8 bg) +{ + // First draw the box in the background, alpha-blended + // We don't care about the specified bg color, since + // we always want black with alpha + glEnable(GL_BLEND); + glColor4f(0.0, 0.0, 0.0, 0.7); + glRecti(x, y, x+w, y+h); + + // Now draw the outer edges + // Again, we don't care about the provided fg color, since + // we always want a light grey with no alpha + glDisable(GL_BLEND); + glColor3f(0.8, 0.8, 0.8); + glBegin(GL_LINE_LOOP); + glVertex2i(x, y ); // Top Left + glVertex2i(x+w, y ); // Top Right + glVertex2i(x+w, y+h); // Bottom Right + glVertex2i(x, y+h); // Bottom Left + glEnd(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::drawText(uInt32 xorig, uInt32 yorig, + const string& message, uInt8 fg) +{ + glBindTexture(GL_TEXTURE_2D, myFontTextureID); + glEnable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + + // We place the loop here to avoid multiple calls to glBegin/glEnd + glBegin(GL_QUADS); + for(uInt32 i = 0; i < message.length(); i++) + { + uInt32 x = xorig + i*8; + uInt32 y = yorig; + uInt8 c = message[i]; + + glTexCoord2f(myFontCoord[c].minX, myFontCoord[c].minY); glVertex2i(x, y ); + glTexCoord2f(myFontCoord[c].maxX, myFontCoord[c].minY); glVertex2i(x+8, y ); + glTexCoord2f(myFontCoord[c].maxX, myFontCoord[c].maxY); glVertex2i(x+8, y+8); + glTexCoord2f(myFontCoord[c].minX, myFontCoord[c].maxY); glVertex2i(x, y+8); + } + glEnd(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferGL::drawChar(uInt32 x, uInt32 y, uInt32 c, uInt8 fg) +{ + if(c >= 256 ) + return; + + glBindTexture(GL_TEXTURE_2D, myFontTextureID); + glEnable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + glBegin(GL_QUADS); + glTexCoord2f(myFontCoord[c].minX, myFontCoord[c].minY); glVertex2i(x, y ); + glTexCoord2f(myFontCoord[c].maxX, myFontCoord[c].minY); glVertex2i(x+8, y ); + glTexCoord2f(myFontCoord[c].maxX, myFontCoord[c].maxY); glVertex2i(x+8, y+8); + glTexCoord2f(myFontCoord[c].minX, myFontCoord[c].maxY); glVertex2i(x, y+8); + glEnd(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferGL::createTextures() +{ + uInt32 w = power_of_two(myWidth); + uInt32 h = power_of_two(myHeight); + + myTexCoord[0] = 0.0f; + myTexCoord[1] = 0.0f; + myTexCoord[2] = (GLfloat) myWidth / w; + myTexCoord[3] = (GLfloat) myHeight / h; + + myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, + #if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); + #else + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + #endif + + if(myTexture == NULL) + return false; + + // Create an OpenGL texture from the SDL texture + bool showinfo = myConsole->settings().getBool("showinfo"); + string filter = myConsole->settings().getString("gl_filter"); + GLint param = GL_NEAREST; + if(filter == "linear") + { + param = GL_LINEAR; + if(showinfo) + cout << "Using GL_LINEAR filtering.\n\n"; + } + else if(filter == "nearest") + { + param = GL_NEAREST; + if(showinfo) + cout << "Using GL_NEAREST filtering.\n\n"; + } + + glGenTextures(1, &myTextureID); + glBindTexture(GL_TEXTURE_2D, myTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, + myTexture->pixels); + + // Now create the font texture. There are 256 fonts of 8x8 pixels. + // These will be stored in a texture of size 256x64, which is 32 characters + // per line, and 8 lines. + SDL_Surface* fontTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, 256, 64, 32, + #if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); + #else + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + #endif + + if(fontTexture == NULL) + return false; + + // First clear the texture + SDL_Rect tmp; + tmp.x = 0; tmp.y = 0; tmp.w = 256; tmp.h = 64; + SDL_FillRect(fontTexture, &tmp, + SDL_MapRGBA(fontTexture->format, 0xff, 0xff, 0xff, 0x0)); + + // Now fill the texture with font data + for(uInt32 lines = 0; lines < 8; lines++) + { + for(uInt32 x = lines*32; x < (lines+1)*32; x++) + { + for(uInt32 y = 0; y < 8; y++) + { + for(uInt32 z = 0; z < 8; z++) + { + if((ourFontData[(x << 3) + y] >> z) & 1) + { + tmp.x = ((x-lines*32)<<3) + z; + tmp.y = y + lines*8; + tmp.w = tmp.h = 1; + SDL_FillRect(fontTexture, &tmp, + SDL_MapRGBA(fontTexture->format, 0x10, 0x10, 0x10, 0xff)); + } + } + } + } + } + + // Generate the character coordinates + for(uInt32 i = 0; i < 256; i++) + { + uInt32 row = i / 32; + uInt32 col = i - (row*32); + + myFontCoord[i].minX = (GLfloat) (col*8) / 256; + myFontCoord[i].maxX = (GLfloat) (col*8+8) / 256; + myFontCoord[i].minY = (GLfloat) (row*8) / 64; + myFontCoord[i].maxY = (GLfloat) (row*8+8) / 64; + } + + glGenTextures(1, &myFontTextureID); + glBindTexture(GL_TEXTURE_2D, myFontTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, + fontTexture->pixels); + + SDL_FreeSurface(fontTexture); + + return true; +} diff --git a/stella/src/ui/sdl/FrameBufferGL.hxx b/stella/src/ui/sdl/FrameBufferGL.hxx new file mode 100644 index 000000000..ea7d141cd --- /dev/null +++ b/stella/src/ui/sdl/FrameBufferGL.hxx @@ -0,0 +1,232 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-1999 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: FrameBufferGL.hxx,v 1.1 2003-11-06 22:22:32 stephena Exp $ +//============================================================================ + +#ifndef FRAMEBUFFER_GL_HXX +#define FRAMEBUFFER_GL_HXX + +#include +#include +#include + +#include "FrameBuffer.hxx" +#include "bspf.hxx" + +class Console; +class MediaSource; + +class FrameBufferGL : public FrameBuffer +{ + public: + /** + Creates a new SDL OpenGL framebuffer + */ + FrameBufferGL(); + + /** + Destructor + */ + virtual ~FrameBufferGL(); + + /** + This routine should be called once the console is created to setup + the video system for us to use. Return false if any operation fails, + otherwise return true. + */ + virtual bool init(); + + /** + This routine should be called anytime the MediaSource needs to be redrawn + to the screen. + */ + virtual void drawMediaSource(); + + /** + This routine should be called to draw a rectangular box with sides + at the specified coordinates. + + @param x The x coordinate + @param y The y coordinate + @param w The width of the box + @param h The height of the box + @param fg The color of the bounding sides + @param bg The color of the background + */ + virtual void drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt8 fg, uInt8 bg); + + /** + This routine should be called to draw text at the specified coordinates. + + @param x The x coordinate + @param y The y coordinate + @param message The message text + @param fg The color of the text + */ + virtual void drawText(uInt32 x, uInt32 y, const string& message, uInt8 fg); + + /** + This routine should be called to draw character 'c' at the specified coordinates. + + @param x The x coordinate + @param y The y coordinate + @param c The character to draw + @param fg The color of the character + */ + virtual void drawChar(uInt32 x, uInt32 y, uInt32 c, uInt8 fg); + + /** + This routine is called before any drawing is done (per-frame). + */ + virtual void preFrameUpdate(); + + /** + This routine is called after any drawing is done (per-frame). + */ + virtual void postFrameUpdate(); + + /** + This routine is called when the emulation has been paused. + + @param status Toggle pause based on status + */ + virtual void pause(bool status); + + /** + Toggles between fullscreen and window mode. Grabmouse and hidecursor + activated when in fullscreen mode. + */ + void toggleFullscreen(); + + /** + This routine is called when the user wants to resize the window. + A '1' argument indicates that the window should increase in size, while '-1' + indicates that the windows should decrease in size. A '0' indicates that + the window should be sized according to the current properties. + Can't resize in fullscreen mode. Will only resize up to the maximum size + of the screen. + */ + void resize(int mode); + + /** + Shows or hides the cursor based on the given boolean value. + */ + void showCursor(bool show); + + /** + Grabs or ungrabs the mouse based on the given boolean value. + */ + void grabMouse(bool grab); + + /** + Set up the palette for a screen of any depth > 8. + Scales the palette by 'shade'. + */ + void setupPalette(float shade); + + /** + Answers if the display is currently in fullscreen mode. + */ + bool fullScreen() { return isFullscreen; } + + /** + Answers the current zoom level of the SDL window + */ + uInt32 zoomLevel() { return theZoomLevel; } + + private: + /** + This routine is called whenever the screen needs to be recreated. + It updates the global screen variable. + */ + bool createScreen(); + + /** + Calculate the maximum window size that the current screen can hold. + Only works in X11 for now. If not running under X11, always return 1. + */ + uInt32 maxWindowSizeForScreen(); + + bool createTextures(); + + uInt32 power_of_two(uInt32 input) + { + uInt32 value = 1; + while( value < input ) + value <<= 1; + return value; + } + + private: + // The SDL video buffer + SDL_Surface* myScreen; + + // The main texture buffer + SDL_Surface* myTexture; + + // The OpenGL main texture handle + GLuint myTextureID; + + // OpenGL texture coordinates for the main surface + GLfloat myTexCoord[4]; + + // The OpenGL font texture handle + GLuint myFontTextureID; + + // Structure to hold a characters coordinates + struct Coordinates + { + GLfloat minX; + GLfloat maxX; + GLfloat minY; + GLfloat maxY; + }; + + // OpenGL texture coordinates for the font surface + Coordinates myFontCoord[256]; + + // SDL initialization flags + uInt32 mySDLFlags; + + // SDL palette + uInt32 myPalette[256]; + + // Used to get window-manager specifics + SDL_SysWMinfo myWMInfo; + + // Indicates if we are running under X11 + bool x11Available; + + // Indicates the current zoom level of the SDL screen + uInt32 theZoomLevel; + + // Indicates the maximum zoom of the SDL screen + uInt32 theMaxZoomLevel; + + // Indicates whether the window is currently centered + bool isCentered; + + // Indicates if the mouse should be grabbed + bool theGrabMouseIndicator; + + // Indicates if the mouse cursor should be hidden + bool theHideCursorIndicator; + + // Indicates whether the game is currently in fullscreen + bool isFullscreen; +}; + +#endif diff --git a/stella/src/ui/sdl/FrameBufferSDL.cxx b/stella/src/ui/sdl/FrameBufferSDL.cxx index 1d9492492..c4cf26ebe 100644 --- a/stella/src/ui/sdl/FrameBufferSDL.cxx +++ b/stella/src/ui/sdl/FrameBufferSDL.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: FrameBufferSDL.cxx,v 1.1 2003-10-26 19:40:39 stephena Exp $ +// $Id: FrameBufferSDL.cxx,v 1.2 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -24,7 +24,6 @@ #include "FrameBuffer.hxx" #include "FrameBufferSDL.hxx" #include "MediaSrc.hxx" -#include "RectList.hxx" #include "Settings.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -609,3 +608,59 @@ void FrameBufferSDL::drawChar(uInt32 xorig, uInt32 yorig, uInt32 c, uInt8 fg) } } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RectList::RectList(Uint32 size) +{ + currentSize = size; + currentRect = 0; + + rectArray = new SDL_Rect[currentSize]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RectList::~RectList() +{ + delete[] rectArray; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RectList::add(SDL_Rect* newRect) +{ + if(currentRect >= currentSize) + { + currentSize = currentSize * 2; + SDL_Rect *temp = new SDL_Rect[currentSize]; + + for(Uint32 i = 0; i < currentRect; ++i) + temp[i] = rectArray[i]; + + delete[] rectArray; + rectArray = temp; + } + + rectArray[currentRect].x = newRect->x; + rectArray[currentRect].y = newRect->y; + rectArray[currentRect].w = newRect->w; + rectArray[currentRect].h = newRect->h; + + ++currentRect; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SDL_Rect* RectList::rects() +{ + return rectArray; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Uint32 RectList::numRects() +{ + return currentRect; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RectList::start() +{ + currentRect = 0; +} diff --git a/stella/src/ui/sdl/FrameBufferSDL.hxx b/stella/src/ui/sdl/FrameBufferSDL.hxx index d021e6362..763e43eb4 100644 --- a/stella/src/ui/sdl/FrameBufferSDL.hxx +++ b/stella/src/ui/sdl/FrameBufferSDL.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: FrameBufferSDL.hxx,v 1.1 2003-10-26 19:40:39 stephena Exp $ +// $Id: FrameBufferSDL.hxx,v 1.2 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_SDL_HXX @@ -202,4 +202,25 @@ class FrameBufferSDL : public FrameBuffer bool isFullscreen; }; +/** + + */ +class RectList +{ + public: + RectList(Uint32 size = 512); + ~RectList(); + + void add(SDL_Rect* rect); + + SDL_Rect* rects(); + Uint32 numRects(); + void start(); + + private: + Uint32 currentSize, currentRect; + + SDL_Rect* rectArray; +}; + #endif diff --git a/stella/src/ui/sdl/RectList.cxx b/stella/src/ui/sdl/RectList.cxx deleted file mode 100644 index 067f7a1d0..000000000 --- a/stella/src/ui/sdl/RectList.cxx +++ /dev/null @@ -1,72 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-1999 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: RectList.cxx,v 1.1 2002-03-05 22:39:47 stephena Exp $ -//============================================================================ - -#include - -#include "RectList.hxx" - - -RectList::RectList(Uint32 size) -{ - currentSize = size; - currentRect = 0; - - rectArray = new SDL_Rect[currentSize]; -} - -RectList::~RectList() -{ - delete[] rectArray; -} - -void RectList::add(SDL_Rect* newRect) -{ - if(currentRect >= currentSize) - { - currentSize = currentSize * 2; - SDL_Rect *temp = new SDL_Rect[currentSize]; - - for(Uint32 i = 0; i < currentRect; ++i) - temp[i] = rectArray[i]; - - delete[] rectArray; - rectArray = temp; - } - - rectArray[currentRect].x = newRect->x; - rectArray[currentRect].y = newRect->y; - rectArray[currentRect].w = newRect->w; - rectArray[currentRect].h = newRect->h; - - ++currentRect; -} - -SDL_Rect* RectList::rects() -{ - return rectArray; -} - -Uint32 RectList::numRects() -{ - return currentRect; -} - -void RectList::start() -{ - currentRect = 0; -} diff --git a/stella/src/ui/sdl/RectList.hxx b/stella/src/ui/sdl/RectList.hxx deleted file mode 100644 index 56f0d8c38..000000000 --- a/stella/src/ui/sdl/RectList.hxx +++ /dev/null @@ -1,42 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-1999 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: RectList.hxx,v 1.1 2002-03-05 22:39:47 stephena Exp $ -//============================================================================ - -#ifndef RECT_LIST_HXX -#define RECT_LIST_HXX - -#include - -class RectList -{ - public: - RectList(Uint32 size = 512); - ~RectList(); - - void add(SDL_Rect* rect); - - SDL_Rect* rects(); - Uint32 numRects(); - void start(); - - private: - Uint32 currentSize, currentRect; - - SDL_Rect* rectArray; -}; - -#endif diff --git a/stella/src/ui/sdl/SettingsUNIX.cxx b/stella/src/ui/sdl/SettingsUNIX.cxx index b347ebe7f..40dfad451 100644 --- a/stella/src/ui/sdl/SettingsUNIX.cxx +++ b/stella/src/ui/sdl/SettingsUNIX.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: SettingsUNIX.cxx,v 1.1 2003-10-26 19:40:39 stephena Exp $ +// $Id: SettingsUNIX.cxx,v 1.2 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -63,11 +63,15 @@ SettingsUNIX::SettingsUNIX() // Now create UNIX specific settings #ifdef DISPLAY_OPENGL - set("opengl", "false"); + set("gl_filter", "nearest"); +#endif +#ifdef SNAPSHOT_SUPPORT + set("ssname", "romname"); + set("ssdir", "./"); + set("ssingle", "false"); #endif set("fullscreen", "false"); set("grabmouse", "false"); - set("center", "false"); set("hidecursor", "false"); set("accurate", "true"); set("volume", "-1"); @@ -89,6 +93,24 @@ void SettingsUNIX::usage(string& message) << endl << "Valid options are:" << endl << endl +#ifdef DISPLAY_OPENGL + << " -gl_filter Type is one of the following:\n" + << " nearest Normal scaling (GL_NEAREST)\n" + << " linear Blurred scaling (GL_LINEAR)\n" + << endl +#endif + << " -sound Type is one of the following:\n" + << " 0 Disables all sound generation\n" + #ifdef SOUND_ALSA + << " alsa ALSA version 0.9 driver\n" + #endif + #ifdef SOUND_OSS + << " oss Open Sound System driver\n" + #endif + #ifdef SOUND_SDL + << " SDL Native SDL driver\n" + #endif + << endl << " -framerate Display the given number of frames per second\n" << " -zoom Makes window be 'size' times normal\n" << " -fullscreen <0|1> Play the game in fullscreen mode\n" @@ -96,9 +118,6 @@ void SettingsUNIX::usage(string& message) << " -hidecursor <0|1> Hides the mouse cursor in the game window\n" << " -center <0|1> Centers the game window onscreen\n" << " -volume Set the volume (0 - 100)\n" -#ifdef DISPLAY_OPENGL - << " -opengl <0|1> Use OpenGL mode.\n" -#endif #ifdef HAVE_JOYSTICK << " -paddle <0|1|2|3|real> Indicates which paddle the mouse should emulate\n" << " or that real Atari 2600 paddles are being used\n" @@ -114,15 +133,6 @@ void SettingsUNIX::usage(string& message) << " -ssdir The directory to save snapshot files to\n" << " -ssname How to name the snapshot (romname or md5sum)\n" << " -sssingle <0|1> Generate single snapshot instead of many\n" - #endif - << endl - << " -sound Type is one of the following:\n" - << " 0 Disables all sound generation\n" - #ifdef SOUND_ALSA - << " alsa ALSA version 0.9 driver\n" - #endif - #ifdef SOUND_OSS - << " oss Open Sound System driver\n" #endif << endl #ifdef DEVELOPER_SUPPORT diff --git a/stella/src/ui/sdl/mainSDL.cxx b/stella/src/ui/sdl/mainSDL.cxx index 3f43db738..a2f7c0928 100644 --- a/stella/src/ui/sdl/mainSDL.cxx +++ b/stella/src/ui/sdl/mainSDL.cxx @@ -13,13 +13,14 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: mainSDL.cxx,v 1.56 2003-10-26 19:40:39 stephena Exp $ +// $Id: mainSDL.cxx,v 1.57 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include #include #include #include +#include #ifdef HAVE_GETTIMEOFDAY #include @@ -34,13 +35,18 @@ #include "StellaEvent.hxx" #include "EventHandler.hxx" #include "FrameBuffer.hxx" -#include "FrameBufferSDL.hxx" #include "PropsSet.hxx" #include "Sound.hxx" #include "Settings.hxx" #ifdef DISPLAY_OPENGL #include "FrameBufferGL.hxx" + // Pointer to the OpenGL display object or the null pointer + static FrameBufferGL* theDisplay = (FrameBufferGL*) NULL; +#else + #include "FrameBufferSDL.hxx" + // Pointer to the software display object or the null pointer + static FrameBufferSDL* theDisplay = (FrameBufferSDL*) NULL; #endif #ifdef SOUND_ALSA @@ -83,9 +89,6 @@ static Sound* theSound = (Sound*) NULL; // Pointer to the settings object or the null pointer static Settings* theSettings = (Settings*) NULL; -// Pointer to the display object or the null pointer -static FrameBufferSDL* theDisplay = (FrameBufferSDL*) NULL; - // Indicates if the mouse should be grabbed static bool theGrabMouseIndicator = false; @@ -201,7 +204,6 @@ static Switches keyList[] = { { SDLK_CLEAR, StellaEvent::KCODE_CLEAR }, { SDLK_RETURN, StellaEvent::KCODE_RETURN }, { SDLK_ESCAPE, StellaEvent::KCODE_ESCAPE }, - { SDLK_SPACE, StellaEvent::KCODE_SPACE }, { SDLK_COMMA, StellaEvent::KCODE_COMMA }, { SDLK_MINUS, StellaEvent::KCODE_MINUS }, { SDLK_PERIOD, StellaEvent::KCODE_PERIOD }, @@ -506,7 +508,7 @@ void handleEvents() { if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0)) { - if(!theSettings->pause()) + if(!theConsole->eventHandler().doPause()) { theConsole->eventHandler().sendEvent(Event::Pause, 1); } @@ -671,6 +673,10 @@ int main(int argc, char* argv[]) thePaddleMode = theSettings->getInt("paddle"); theShowInfoFlag = theSettings->getBool("showinfo"); + // Request that the SDL window be centered, if possible + // This will probably only work under Linux + setenv("SDL_VIDEO_CENTERED", "1", 1); + // Get a pointer to the file which contains the cartridge ROM const char* file = argv[argc - 1]; @@ -697,6 +703,24 @@ int main(int argc, char* argv[]) return 0; } + // Create an SDL window +#ifdef DISPLAY_OPENGL + theDisplay = new FrameBufferGL(); + if(theShowInfoFlag) + cout << "Using OpenGL SDL for video.\n"; +#else + theDisplay = new FrameBufferSDL(); + if(theShowInfoFlag) + cout << "Using software SDL for video.\n"; +#endif + + if(!theDisplay) + { + cerr << "ERROR: Couldn't set up display.\n"; + cleanup(); + return 0; + } + // Create a sound object for playing audio string driver = theSettings->getString("sound"); if(driver == "0") @@ -741,25 +765,9 @@ int main(int argc, char* argv[]) // Get just the filename of the file containing the ROM image const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1; - // Setup the SDL window -#ifdef DISPLAY_OPENGL - bool useGL = theSettings->getBool("opengl"); - if(useGL) - theDisplay = new FrameBufferGL(); - else -#endif - theDisplay = new FrameBufferSDL(); - - if(!theDisplay) - { - cerr << "ERROR: Couldn't set up display.\n"; - cleanup(); - return 0; - } - // Create the 2600 game console theConsole = new Console(image, size, filename, *theSettings, propertiesSet, - *theDisplay, theSound->getSampleRate()); + *theDisplay, *theSound); // Free the image since we don't need it any longer delete[] image; @@ -790,21 +798,13 @@ int main(int argc, char* argv[]) for(;;) { // Exit if the user wants to quit - if(theSettings->quit()) + if(theConsole->eventHandler().doQuit()) { break; } - // Call handleEvents here to see if user pressed pause startTime = getTicks(); handleEvents(); - if(theSettings->pause()) - { - theDisplay->update(); - SDL_Delay(10); - continue; - } - theDisplay->update(); theSound->updateSound(*theDisplay->mediaSource()); @@ -835,24 +835,16 @@ int main(int argc, char* argv[]) for(;;) { // Exit if the user wants to quit - if(theSettings->quit()) + if(theConsole->eventHandler().doQuit()) { break; } -/* - startTime = getTicks(); - handleEvents(); - if(!theSettings->pause()) - { - theSound->updateSound(*theDisplay->mediaSource()); - } - theDisplay->update(); -*/ + startTime = getTicks(); handleEvents(); theDisplay->update(); theSound->updateSound(*theDisplay->mediaSource()); -/// + currentTime = getTicks(); virtualTime += timePerFrame; if(currentTime < virtualTime) diff --git a/stella/src/ui/sound/SoundALSA.cxx b/stella/src/ui/sound/SoundALSA.cxx index b93a69f6d..4943d0f08 100644 --- a/stella/src/ui/sound/SoundALSA.cxx +++ b/stella/src/ui/sound/SoundALSA.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: SoundALSA.cxx,v 1.3 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundALSA.cxx,v 1.4 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -30,7 +30,8 @@ SoundALSA::SoundALSA() myOriginalVolumeLeft(-1), myOriginalVolumeRight(-1), myBufferSize(0), - mySampleRate(0) + mySampleRate(0), + myPauseStatus(false) { Int32 err; char pcmName[] = "plughw:0,0"; @@ -242,6 +243,9 @@ void SoundALSA::updateSound(MediaSource& mediaSource) { if(myIsInitializedFlag) { + if(myPauseStatus) + return; + snd_pcm_sframes_t frames; uInt8 periodCount = 0; diff --git a/stella/src/ui/sound/SoundALSA.hxx b/stella/src/ui/sound/SoundALSA.hxx index 866af13da..fd8f04fca 100644 --- a/stella/src/ui/sound/SoundALSA.hxx +++ b/stella/src/ui/sound/SoundALSA.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: SoundALSA.hxx,v 1.3 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundALSA.hxx,v 1.4 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef SOUNDALSA_HXX @@ -30,7 +30,7 @@ Advanced Linux Sound Architecture (ALSA) version 0.9.x API. @author Stephen Anthony - @version $Id: SoundALSA.hxx,v 1.3 2003-02-25 03:12:55 stephena Exp $ + @version $Id: SoundALSA.hxx,v 1.4 2003-11-06 22:22:32 stephena Exp $ */ class SoundALSA : public Sound { @@ -74,6 +74,14 @@ class SoundALSA : public Sound */ void setSoundVolume(Int32 percent); + /** + Sets the pause status. While pause is selected, updateSound() + should not play any sound. + + @param status Toggle pause based on status + */ + void pause(bool status) { myPauseStatus = status; } + /** Update the sound device using the audio sample from the specified media source. @@ -110,5 +118,8 @@ class SoundALSA : public Sound // PCM sample rate uInt32 mySampleRate; + + // The pause status + bool myPauseStatus; }; #endif diff --git a/stella/src/ui/sound/SoundOSS.cxx b/stella/src/ui/sound/SoundOSS.cxx index 189a8c926..3541e014b 100644 --- a/stella/src/ui/sound/SoundOSS.cxx +++ b/stella/src/ui/sound/SoundOSS.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: SoundOSS.cxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundOSS.cxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #include @@ -39,7 +39,8 @@ SoundOSS::SoundOSS() myDspFd(-1), myMixerFd(-1), myOriginalVolume(-1), - mySampleRate(0) + mySampleRate(0), + myPauseStatus(false) { // Open the sound device for writing if((myDspFd = open(DSP_DEVICE, O_WRONLY, 0)) == -1) @@ -197,6 +198,9 @@ void SoundOSS::updateSound(MediaSource& mediaSource) { if(myIsInitializedFlag) { + if(myPauseStatus) + return; + // Get audio buffer information audio_buf_info info; if(ioctl(myDspFd, SNDCTL_DSP_GETOSPACE, &info) == -1) diff --git a/stella/src/ui/sound/SoundOSS.hxx b/stella/src/ui/sound/SoundOSS.hxx index f5fe1a3c5..274399e02 100644 --- a/stella/src/ui/sound/SoundOSS.hxx +++ b/stella/src/ui/sound/SoundOSS.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: SoundOSS.hxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundOSS.hxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ //============================================================================ #ifndef SOUNDOSS_HXX @@ -28,7 +28,7 @@ Open Sound System (OSS) API. @author Bradford W. Mott - @version $Id: SoundOSS.hxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ + @version $Id: SoundOSS.hxx,v 1.3 2003-11-06 22:22:32 stephena Exp $ */ class SoundOSS : public Sound { @@ -72,6 +72,14 @@ class SoundOSS : public Sound */ void setSoundVolume(Int32 percent); + /** + Sets the pause status. While pause is selected, updateSound() + should not play any sound. + + @param status Toggle pause based on status + */ + void pause(bool status) { myPauseStatus = status; } + /** Update the sound device using the audio sample from the specified media source. @@ -95,5 +103,8 @@ class SoundOSS : public Sound // DSP sample rate uInt32 mySampleRate; + + // The pause status + bool myPauseStatus; }; #endif diff --git a/stella/src/ui/sound/SoundSDL.cxx b/stella/src/ui/sound/SoundSDL.cxx index 5bd892b68..4f67fd81f 100644 --- a/stella/src/ui/sound/SoundSDL.cxx +++ b/stella/src/ui/sound/SoundSDL.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: SoundSDL.cxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundSDL.cxx,v 1.3 2003-11-06 22:22:33 stephena Exp $ //============================================================================ #include @@ -27,7 +27,8 @@ SoundSDL::SoundSDL(bool activate) myIsInitializedFlag(false), myIsMuted(false), mySampleRate(31400), - mySampleQueue(mySampleRate) + mySampleQueue(mySampleRate), + myPauseStatus(false) { if(activate) { @@ -165,6 +166,9 @@ void SoundSDL::updateSound(MediaSource& mediaSource) { if(myIsInitializedFlag) { + if(myPauseStatus) + return; + // Make sure we have exclusive access to the sample queue SDL_LockAudio(); diff --git a/stella/src/ui/sound/SoundSDL.hxx b/stella/src/ui/sound/SoundSDL.hxx index b7016d335..97233c09c 100644 --- a/stella/src/ui/sound/SoundSDL.hxx +++ b/stella/src/ui/sound/SoundSDL.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: SoundSDL.hxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ +// $Id: SoundSDL.hxx,v 1.3 2003-11-06 22:22:33 stephena Exp $ //============================================================================ #ifndef SOUNDSDL_HXX @@ -29,7 +29,7 @@ This class implements the sound API for SDL. @author Stephen Anthony and Bradford W. Mott - @version $Id: SoundSDL.hxx,v 1.2 2003-02-25 03:12:55 stephena Exp $ + @version $Id: SoundSDL.hxx,v 1.3 2003-11-06 22:22:33 stephena Exp $ */ class SoundSDL : public Sound { @@ -80,6 +80,14 @@ class SoundSDL : public Sound */ void setSoundVolume(Int32 percent); + /** + Sets the pause status. While pause is selected, updateSound() + should not play any sound. + + @param status Toggle pause based on status + */ + void pause(bool status) { myPauseStatus = status; } + /** Update the sound device using the audio sample from the specified media source. @@ -165,6 +173,9 @@ class SoundSDL : public Sound // Queue which holds samples from the media source before they are played SampleQueue mySampleQueue; + // The pause status + bool myPauseStatus; + private: // Callback function invoked by the SDL Audio library when it needs data static void callback(void* udata, uInt8* stream, int len); diff --git a/stella/src/ui/x11/mainX11.cxx b/stella/src/ui/x11/mainX11.cxx index 473d6fe36..14a3000a5 100644 --- a/stella/src/ui/x11/mainX11.cxx +++ b/stella/src/ui/x11/mainX11.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: mainX11.cxx,v 1.42 2003-09-19 15:45:01 stephena Exp $ +// $Id: mainX11.cxx,v 1.43 2003-11-06 22:22:33 stephena Exp $ //============================================================================ #include @@ -64,7 +64,7 @@ #endif // function prototypes -// FIXME the following will be placed in a Display class eventually ... +// the following will be placed in a Display class eventually ... // A graphic context for each of the 2600's colors static GC theGCTable[256]; static bool setupDisplay(); @@ -647,7 +647,7 @@ void handleEvents() { resizeWindow(0); } -// FIXME - change x to Ctrl-x +// change x to Ctrl-x else if((key == XK_g) && (event.type == KeyPress)) { // don't change grabmouse in fullscreen mode