diff --git a/Changes.txt b/Changes.txt index b36c67a46..87689b67d 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,27 +14,30 @@ 3.4.1 to 3.5: (December xx, 2011) - FIXME (will I have time for this?) - * Replaced NTSC TV filtering with Blargg NTSC filters. These filters - work in OpenGL mode only, but in contrast to the old filters, they - now work with OpenGL 1.x / OpenGL ES. - * Added several improvements to the joystick management code. Joystick event mapping is now saved per device, meaning that if you map events to a certain joystick device, remove the device and then later insert it again, Stella will remember the original mapping. * The total number of joysticks present and their associated properties - (number of axes, buttons, hats, etc) is now dynamic. That is, there's - no longer a hard-coded limit on number of joysticks that Stella can - use, or the number of buttons, etc that it contains. This fixes a - serious bug with PS3 controllers with 27 buttons, whereby adding a + (number of axes, buttons and hats) is now dynamic. That is, there's + no longer a hard-coded limit on the number of joysticks that Stella + can use, or the number of buttons, etc that it contains. This fixes + a serious bug with PS3 controllers with 27 buttons, whereby adding a mapping for joystick 0 would inadvertantly change settings for - joystick 1, and could potentially lead to a segfault. + joystick 1, and could potentially lead to a program crash. * Huge restructuring of the OpenGL code, making it compatible with OpenGL 2.x+ features (such as vertex buffer objects), while at the same time keeping compatibility with OpenGL 1.5 / OpenGL ES. + Because of the required changes, TV effects were removed (they will + be added again for the next release). + + * Improvements to audio handling, particularly for certain cases of + Windows, ATI video cards, and OpenGL mode. The sound device is now + opened only once when Stella starts, and is paused between loading + different ROMs. This fixes a problem whereby sound could possibly + not be functional after loading the first ROM. * Added logging facility, whereby the output of the application is available within Stella itself. This can still be printed to the @@ -56,7 +59,7 @@ can be disabled by developers for testing reasons. * Updated default snapshot directory to be much saner and easier to - find. For most systems, it now defaults to the users 'Desktop. + find. For most systems, it now defaults to the users 'Desktop'. Note that the commandline argument has changed to 'snapdir'. * The debugger 'print' command now indicates "special" addresses if @@ -72,6 +75,9 @@ * Updated include PNG library to latest stable version. + * Updated the credits list in the documentation, listing people that + have donated hardware to the Stella team. + -Have fun! diff --git a/docs/graphics/options_audio.png b/docs/graphics/options_audio.png index 2bd75b2e0..1bf47fa3e 100644 Binary files a/docs/graphics/options_audio.png and b/docs/graphics/options_audio.png differ diff --git a/docs/index.html b/docs/index.html index aef5e9b48..c35e22585 100644 --- a/docs/index.html +++ b/docs/index.html @@ -267,7 +267,7 @@
  • Supports EEPROM emulation for AtariVox and SaveKey controllers
  • Supports all known bankswitching schemes (let us know if there's one we missed)
  • -
  • Supports DPC+ bankswitching scheme from the Harmony cart, including emulation of the ARM processor
  • +
  • Supports DPC+ bankswitching scheme from the Harmony cart, including partial emulation of the ARM processor
  • Supports cartridge autodetection for almost all bankswitching schemes
  • Supports Supercharger single-load and multi-load games
  • Supports ROMs stored in ZIP and GZIP format, as well as the usual A26/BIN/ROM formats
  • @@ -2232,8 +2232,8 @@ - - + + @@ -3263,6 +3263,12 @@ Ms Pac-Man (Stella extended codes): + + + + + @@ -3344,6 +3350,12 @@ Ms Pac-Man (Stella extended codes): in testing ROMs on a real system + + + + + + + + + + @@ -3536,7 +3554,7 @@ Ms Pac-Man (Stella extended codes): + (http://atariage.com) diff --git a/src/common/FrameBufferSoft.cxx b/src/common/FrameBufferSoft.cxx index e7401e94f..f8fa9d8c1 100644 --- a/src/common/FrameBufferSoft.cxx +++ b/src/common/FrameBufferSoft.cxx @@ -69,15 +69,15 @@ string FrameBufferSoft::about() const { ostringstream buf; - buf << "Video rendering: Software mode" << endl + buf << "Video rendering: Software mode" << endl << setfill('0') << " Color: " << (int)myFormat->BitsPerPixel << " bit" << endl - << " Rmask = " << hex << setw(4) << (int)myFormat->Rmask + << " Rmask = " << hex << setw(8) << (int)myFormat->Rmask << ", Rshift = "<< dec << setw(2) << (int)myFormat->Rshift << ", Rloss = " << dec << setw(2) << (int)myFormat->Rloss << endl - << " Gmask = " << hex << setw(4) << (int)myFormat->Gmask + << " Gmask = " << hex << setw(8) << (int)myFormat->Gmask << ", Gshift = "<< dec << setw(2) << (int)myFormat->Gshift << ", Gloss = " << dec << setw(2) << (int)myFormat->Gloss << endl - << " Bmask = " << hex << setw(4) << (int)myFormat->Bmask + << " Bmask = " << hex << setw(8) << (int)myFormat->Bmask << ", Bshift = "<< dec << setw(2) << (int)myFormat->Bshift << ", Bloss = " << dec << setw(2) << (int)myFormat->Bloss << endl; diff --git a/src/common/SoundNull.hxx b/src/common/SoundNull.hxx index 52a4ff48a..a04923f70 100644 --- a/src/common/SoundNull.hxx +++ b/src/common/SoundNull.hxx @@ -90,13 +90,6 @@ class SoundNull : public Sound */ void close() { } - /** - Return true iff the sound device was successfully initialized. - - @return true iff the sound device was successfully initialized. - */ - bool isSuccessfullyInitialized() const { return false; } - /** Set the mute state of the sound object. While muted no sound is played. diff --git a/src/common/SoundSDL.cxx b/src/common/SoundSDL.cxx index bc82d7759..c0a5d31e1 100644 --- a/src/common/SoundSDL.cxx +++ b/src/common/SoundSDL.cxx @@ -35,39 +35,88 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SoundSDL::SoundSDL(OSystem* osystem) : Sound(osystem), - myIsEnabled(osystem->settings().getBool("sound")), + myIsEnabled(false), myIsInitializedFlag(false), myLastRegisterSetCycle(0), myDisplayFrameRate(60.0), - myNumChannels(1), + myNumChannels(0), myFragmentSizeLogBase2(0), - myIsMuted(false), + myIsMuted(true), myVolume(100) { + myOSystem->logMessage("SoundSDL::SoundSDL started ...\n", 2); + + // The sound system is opened only once per program run, to eliminate + // issues with opening and closing it multiple times + // This fixes a bug most prevalent with ATI video cards in Windows, + // whereby sound stopped working after the first video change + SDL_AudioSpec desired; + desired.freq = myOSystem->settings().getInt("freq"); + desired.format = AUDIO_U8; + desired.channels = 2; + desired.samples = myOSystem->settings().getInt("fragsize"); + desired.callback = callback; + desired.userdata = (void*)this; + + ostringstream buf; + if(SDL_OpenAudio(&desired, &myHardwareSpec) < 0) + { + buf << "WARNING: Couldn't open SDL audio system! " << endl + << " " << SDL_GetError() << endl; + myOSystem->logMessage(buf.str(), 0); + return; + } + + // Make sure the sample buffer isn't to big (if it is the sound code + // will not work so we'll need to disable the audio support) + if(((float)myHardwareSpec.samples / (float)myHardwareSpec.freq) >= 0.25) + { + buf << "WARNING: Sound device doesn't support realtime audio! Make " + << "sure a sound" << endl + << " server isn't running. Audio is disabled." << endl; + myOSystem->logMessage(buf.str(), 0); + + SDL_CloseAudio(); + return; + } + + myIsInitializedFlag = true; + SDL_PauseAudio(1); + + myOSystem->logMessage("SoundSDL::SoundSDL initialized\n", 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SoundSDL::~SoundSDL() { // Close the SDL audio system if it's initialized - close(); + if(myIsInitializedFlag) + { + SDL_CloseAudio(); + myIsEnabled = myIsInitializedFlag = false; + } + + myOSystem->logMessage("SoundSDL destroyed\n", 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL::setEnabled(bool state) { - myIsEnabled = state; myOSystem->settings().setBool("sound", state); + + myOSystem->logMessage(state ? "SoundSDL::setEnabled(true)\n" : + "SoundSDL::setEnabled(false)\n", 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL::open() { - // Check whether to start the sound subsystem - if(!myIsEnabled) + myOSystem->logMessage("SoundSDL::open started ...\n", 2); + myIsEnabled = false; + mute(true); + if(!myIsInitializedFlag || !myOSystem->settings().getBool("sound")) { - close(); - myOSystem->logMessage("Sound disabled.\n\n", 1); + myOSystem->logMessage("Sound disabled\n\n", 1); return; } @@ -75,98 +124,48 @@ void SoundSDL::open() myRegWriteQueue.clear(); myTIASound.reset(); - if(SDL_WasInit(SDL_INIT_AUDIO) == 0) - { - myIsInitializedFlag = false; - myIsMuted = false; - myLastRegisterSetCycle = 0; + myFragmentSizeLogBase2 = log((double)myHardwareSpec.samples) / log(2.0); - uInt32 fragsize = myOSystem->settings().getInt("fragsize"); - Int32 frequency = myOSystem->settings().getInt("freq"); - Int32 tiafreq = myOSystem->settings().getInt("tiafreq"); + // Now initialize the TIASound object which will actually generate sound + int tiafreq = myOSystem->settings().getInt("tiafreq"); + myTIASound.outputFrequency(myHardwareSpec.freq); + myTIASound.tiaFrequency(tiafreq); + const string& chanResult = + myTIASound.channels(myHardwareSpec.channels, myNumChannels == 2); - SDL_AudioSpec desired; - desired.freq = frequency; - #ifndef GP2X - desired.format = AUDIO_U8; - #else - desired.format = AUDIO_U16; - #endif - desired.channels = myNumChannels; - desired.samples = fragsize; - desired.callback = callback; - desired.userdata = (void*)this; + bool clipvol = myOSystem->settings().getBool("clipvol"); + myTIASound.clipVolume(clipvol); - ostringstream buf; - if(SDL_OpenAudio(&desired, &myHardwareSpec) < 0) - { - buf << "WARNING: Couldn't open SDL audio system! " << endl - << " " << SDL_GetError() << endl; - myOSystem->logMessage(buf.str(), 0); - return; - } + // Adjust volume to that defined in settings + myVolume = myOSystem->settings().getInt("volume"); + setVolume(myVolume); - // Make sure the sample buffer isn't to big (if it is the sound code - // will not work so we'll need to disable the audio support) - if(((float)myHardwareSpec.samples / (float)myHardwareSpec.freq) >= 0.25) - { - buf << "WARNING: Sound device doesn't support realtime audio! Make " - << "sure a sound" << endl - << " server isn't running. Audio is disabled." << endl; - myOSystem->logMessage(buf.str(), 0); - - SDL_CloseAudio(); - return; - } - - myIsInitializedFlag = true; - myIsMuted = false; - myFragmentSizeLogBase2 = log((double)myHardwareSpec.samples) / log(2.0); - - // Now initialize the TIASound object which will actually generate sound - myTIASound.outputFrequency(myHardwareSpec.freq); - myTIASound.tiaFrequency(tiafreq); - myTIASound.channels(myHardwareSpec.channels); - - bool clipvol = myOSystem->settings().getBool("clipvol"); - myTIASound.clipVolume(clipvol); - - // Adjust volume to that defined in settings - myVolume = myOSystem->settings().getInt("volume"); - setVolume(myVolume); - - // Show some info - buf << "Sound enabled:" << endl - << " Volume: " << myVolume << endl - << " Frag size: " << fragsize << endl - << " Frequency: " << myHardwareSpec.freq << endl - << " Format: " << myHardwareSpec.format << endl - << " TIA Freq: " << tiafreq << endl - << " Channels: " << myNumChannels << endl - << " Clip volume: " << (int)clipvol << endl - << endl; - myOSystem->logMessage(buf.str(), 1); - } + // Show some info + ostringstream buf; + buf << "Sound enabled:" << endl + << " Volume: " << (int)myVolume << endl + << " Frag size: " << (int)myHardwareSpec.samples << endl + << " Frequency: " << (int)myHardwareSpec.freq << endl + << " Format: " << (int)myHardwareSpec.format << endl + << " TIA Freq: " << (int)tiafreq << endl + << " Channels: " << (int)myHardwareSpec.channels + << " (" << chanResult << ")" << endl + << " Clip volume: " << (clipvol ? "on" : "off") << endl + << endl; + myOSystem->logMessage(buf.str(), 1); // And start the SDL sound subsystem ... - if(myIsInitializedFlag) - SDL_PauseAudio(0); + myIsEnabled = true; + mute(false); + + myOSystem->logMessage("SoundSDL::open finished\n", 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL::close() { - if(myIsInitializedFlag) - { - SDL_CloseAudio(); - myIsInitializedFlag = false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool SoundSDL::isSuccessfullyInitialized() const -{ - return myIsInitializedFlag; + mute(true); + myOSystem->logMessage("SoundSDL::close\n", 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -175,9 +174,7 @@ void SoundSDL::mute(bool state) if(myIsInitializedFlag) { myIsMuted = state; - SDL_PauseAudio(myIsMuted ? 1 : 0); - myRegWriteQueue.clear(); } } @@ -283,7 +280,7 @@ void SoundSDL::set(uInt16 addr, uInt8 value, Int32 cycle) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL::processFragment(uInt8* stream, Int32 length) { - if(!myIsInitializedFlag) + if(!myIsEnabled) return; uInt32 channels = myHardwareSpec.channels; @@ -425,13 +422,12 @@ bool SoundSDL::load(Serializer& in) if(in.getString() != name()) return false; - uInt8 reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg5 = 0, reg6 = 0; - reg1 = (uInt8) in.getByte(); - reg2 = (uInt8) in.getByte(); - reg3 = (uInt8) in.getByte(); - reg4 = (uInt8) in.getByte(); - reg5 = (uInt8) in.getByte(); - reg6 = (uInt8) in.getByte(); + uInt8 reg1 = (uInt8) in.getByte(), + reg2 = (uInt8) in.getByte(), + reg3 = (uInt8) in.getByte(), + reg4 = (uInt8) in.getByte(), + reg5 = (uInt8) in.getByte(), + reg6 = (uInt8) in.getByte(); myLastRegisterSetCycle = (Int32) in.getInt(); diff --git a/src/common/SoundSDL.hxx b/src/common/SoundSDL.hxx index 8ce7add87..a4e80d6f1 100644 --- a/src/common/SoundSDL.hxx +++ b/src/common/SoundSDL.hxx @@ -54,7 +54,7 @@ class SoundSDL : public Sound /** Enables/disables the sound subsystem. - @param state True or false, to enable or disable the sound system + @param state True or false, to enable or disable the sound system */ void setEnabled(bool state); @@ -62,14 +62,18 @@ class SoundSDL : public Sound The system cycle counter is being adjusting by the specified amount. Any members using the system cycle counter should be adjusted as needed. - @param amount The amount the cycle counter is being adjusted by + @param amount The amount the cycle counter is being adjusted by */ void adjustCycleCounter(Int32 amount); /** - Sets the number of channels (mono or stereo sound). + Sets the number of channels (mono or stereo sound). Note that this + determines how the emulation should 'mix' the channels of the TIA sound + system (of which there are always two). It does not specify the actual + number of hardware channels that SDL should use; it will always attempt + to use two channels in hardware. - @param channels The number of channels + @param channels The number of channels */ void setChannels(uInt32 channels); @@ -93,17 +97,10 @@ class SoundSDL : public Sound */ void close(); - /** - Return true iff the sound device was successfully initialized. - - @return true iff the sound device was successfully initialized. - */ - bool isSuccessfullyInitialized() const; - /** Set the mute state of the sound object. While muted no sound is played. - @param state Mutes sound if true, unmute if false + @param state Mutes sound if true, unmute if false */ void mute(bool state); @@ -115,9 +112,9 @@ class SoundSDL : public Sound /** Sets the sound register to a given value. - @param addr The register address - @param value The value to save into the register - @param cycle The system cycle at which the register is being updated + @param addr The register address + @param value The value to save into the register + @param cycle The system cycle at which the register is being updated */ void set(uInt16 addr, uInt8 value, Int32 cycle); @@ -126,15 +123,15 @@ class SoundSDL : public Sound volume is given as a percentage from 0 to 100. Values outside this range indicate that the volume shouldn't be changed at all. - @param percent The new volume percentage level for the sound device + @param percent The new volume percentage level for the sound device */ void setVolume(Int32 percent); /** Adjusts the volume of the sound device based on the given direction. - @param direction Increase or decrease the current volume by a predefined - amount based on the direction (1 = increase, -1 = decrease) + @param direction Increase or decrease the current volume by a predefined + amount based on the direction (1 = increase, -1 = decrease) */ void adjustVolume(Int8 direction); @@ -142,23 +139,23 @@ class SoundSDL : public Sound /** Saves the current state of this device to the given Serializer. - @param out The serializer device to save to. - @return The result of the save. True on success, false on failure. + @param out The serializer device to save to. + @return The result of the save. True on success, false on failure. */ bool save(Serializer& out) const; /** Loads the current state of this device from the given Serializer. - @param in The Serializer device to load from. - @return The result of the load. True on success, false on failure. + @param in The Serializer device to load from. + @return The result of the load. True on success, false on failure. */ bool load(Serializer& in); /** Get a descriptor for this console class (used in error checking). - @return The name of the object + @return The name of the object */ string name() const { return "TIASound"; } @@ -166,8 +163,8 @@ class SoundSDL : public Sound /** Invoked by the sound callback to process the next sound fragment. - @param stream Pointer to the start of the fragment - @param length Length of the fragment + @param stream Pointer to the start of the fragment + @param length Length of the fragment */ void processFragment(uInt8* stream, Int32 length); @@ -223,14 +220,14 @@ class SoundSDL : public Sound /** Return the item at the front on the queue. - @return The item at the front of the queue. + @return The item at the front of the queue. */ RegWrite& front(); /** Answers the number of items currently in the queue. - @return The number of items in the queue. + @return The number of items in the queue. */ uInt32 size() const; diff --git a/src/common/Version.hxx b/src/common/Version.hxx index d1cc7be4a..bac5985fe 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -22,7 +22,7 @@ #include -#define STELLA_VERSION "3.5_svn_test3" +#define STELLA_VERSION "3.5_svn_test4" #define STELLA_BUILD atoi("$Rev$" + 6) #endif diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 6e6eca936..fb2cadcb2 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -487,10 +487,9 @@ void Console::initializeAudio() int framerate = myOSystem->settings().getInt("framerate"); if(framerate > 0) myFramerate = float(framerate); const string& sound = myProperties.get(Cartridge_Sound); - uInt32 channels = (sound == "STEREO" ? 2 : 1); myOSystem->sound().close(); - myOSystem->sound().setChannels(channels); + myOSystem->sound().setChannels(sound == "STEREO" ? 2 : 1); myOSystem->sound().setFrameRate(myFramerate); myOSystem->sound().open(); diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index adf30b27e..11436efc8 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -2649,9 +2649,9 @@ string EventHandler::StellaJoystick::about() const buf << name; if(type == JT_REGULAR) buf << " with:" << endl << " " - << SDL_JoystickNumAxes(stick) << " axes, " - << SDL_JoystickNumButtons(stick) << " buttons, " - << SDL_JoystickNumHats(stick) << " hats"; + << numAxes << " axes, " + << numButtons << " buttons, " + << numHats << " hats"; return buf.str(); } diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index a922b1e7d..47f4bb0e5 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -464,8 +464,8 @@ fallback: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystem::createSound() { - delete mySound; mySound = NULL; - mySound = MediaFactory::createAudio(this); + if(!mySound) + mySound = MediaFactory::createAudio(this); #ifndef SOUND_SUPPORT mySettings->setBool("sound", false); #endif diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index ca8c10687..81af4186c 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -41,11 +41,11 @@ Settings::Settings(OSystem* osystem) // OpenGL specific options setInternal("gl_filter", "nearest"); - setInternal("gl_aspectn", "100"); + setInternal("gl_aspectn", "90"); setInternal("gl_aspectp", "100"); - setInternal("gl_fsmax", "false"); + setInternal("gl_fsmax", "true"); setInternal("gl_lib", "libGL.so"); - setInternal("gl_vsync", "false"); + setInternal("gl_vsync", "true"); setInternal("gl_vbo", "true"); // Framebuffer-related options @@ -99,7 +99,7 @@ Settings::Settings(OSystem* osystem) setInternal("uselauncher", "true"); setInternal("launcherres", "640x480"); setInternal("launcherfont", "medium"); - setInternal("launcherexts", "allfiles"); + setInternal("launcherexts", "allroms"); setInternal("romviewer", "0"); setInternal("lastrom", ""); diff --git a/src/emucore/Sound.hxx b/src/emucore/Sound.hxx index a2512db53..6c65ec8a2 100644 --- a/src/emucore/Sound.hxx +++ b/src/emucore/Sound.hxx @@ -89,13 +89,6 @@ class Sound : public Serializable */ virtual void close() = 0; - /** - Return true iff the sound device was successfully initialized. - - @return true iff the sound device was successfully initialized. - */ - virtual bool isSuccessfullyInitialized() const = 0; - /** Set the mute state of the sound object. While muted no sound is played. diff --git a/src/emucore/TIASnd.cxx b/src/emucore/TIASnd.cxx index daf027805..0e781f8f5 100644 --- a/src/emucore/TIASnd.cxx +++ b/src/emucore/TIASnd.cxx @@ -21,10 +21,10 @@ #include "TIASnd.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TIASound::TIASound(Int32 outputFrequency, Int32 tiaFrequency, uInt32 channels) - : myOutputFrequency(outputFrequency), +TIASound::TIASound(Int32 outputFrequency, Int32 tiaFrequency) + : myChannelMode(Hardware2Stereo), + myOutputFrequency(outputFrequency), myTIAFrequency(tiaFrequency), - myChannels(channels), myOutputCounter(0), myVolumePercentage(100), myVolumeClip(128) @@ -60,9 +60,20 @@ void TIASound::tiaFrequency(Int32 freq) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIASound::channels(uInt32 number) +string TIASound::channels(uInt32 hardware, bool stereo) { - myChannels = number == 2 ? 2 : 1; + if(hardware == 1) + myChannelMode = Hardware1; + else + myChannelMode = stereo ? Hardware2Stereo : Hardware2Mono; + + switch(myChannelMode) + { + case Hardware1: return "Hardware1"; + case Hardware2Mono: return "Hardware2Mono"; + case Hardware2Stereo: return "Hardware2Stereo"; + default: return EmptyString; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -357,27 +368,39 @@ void TIASound::process(uInt8* buffer, uInt32 samples) myOutputCounter += myOutputFrequency; - if(myChannels == 1) + switch(myChannelMode) { - // Handle mono sample generation - while((samples > 0) && (myOutputCounter >= myTIAFrequency)) - { - *(buffer++) = (((myP4[0] & 8) ? v0 : 0) + - ((myP4[1] & 8) ? v1 : 0)) + myVolumeClip; - myOutputCounter -= myTIAFrequency; - samples--; - } - } - else - { - // Handle stereo sample generation - while((samples > 0) && (myOutputCounter >= myTIAFrequency)) - { - *(buffer++) = ((myP4[0] & 8) ? v0 : 0) + myVolumeClip; - *(buffer++) = ((myP4[1] & 8) ? v1 : 0) + myVolumeClip; - myOutputCounter -= myTIAFrequency; - samples--; - } + case Hardware2Mono: // mono sampling with 2 hardware channels + while((samples > 0) && (myOutputCounter >= myTIAFrequency)) + { + uInt8 byte = (((myP4[0] & 8) ? v0 : 0) + + ((myP4[1] & 8) ? v1 : 0)) + myVolumeClip; + *(buffer++) = byte; + *(buffer++) = byte; + myOutputCounter -= myTIAFrequency; + samples--; + } + break; + + case Hardware2Stereo: // stereo sampling with 2 hardware channels + while((samples > 0) && (myOutputCounter >= myTIAFrequency)) + { + *(buffer++) = ((myP4[0] & 8) ? v0 : 0) + myVolumeClip; + *(buffer++) = ((myP4[1] & 8) ? v1 : 0) + myVolumeClip; + myOutputCounter -= myTIAFrequency; + samples--; + } + break; + + case Hardware1: // mono/stereo sampling with only 1 hardware channel + while((samples > 0) && (myOutputCounter >= myTIAFrequency)) + { + *(buffer++) = (((myP4[0] & 8) ? v0 : 0) + + ((myP4[1] & 8) ? v1 : 0)) + myVolumeClip; + myOutputCounter -= myTIAFrequency; + samples--; + } + break; } } } diff --git a/src/emucore/TIASnd.hxx b/src/emucore/TIASnd.hxx index 635b27e34..2bea354d4 100644 --- a/src/emucore/TIASnd.hxx +++ b/src/emucore/TIASnd.hxx @@ -35,8 +35,7 @@ class TIASound /** Create a new TIA Sound object using the specified output frequency */ - TIASound(Int32 outputFrequency = 31400, Int32 tiaFrequency = 31400, - uInt32 channels = 1); + TIASound(Int32 outputFrequency = 31400, Int32 tiaFrequency = 31400); /** Destructor @@ -60,9 +59,16 @@ class TIASound void tiaFrequency(Int32 freq); /** - Selects the number of audio channels per sample (1 = mono, 2 = stereo) + Selects the number of audio channels per sample. There are two factors + to consider: hardware capability and desired mixing. + + @param hardware The number of channels supported by the sound system + @param stereo Whether to output the internal sound signals into 1 + or 2 channels + + @return Status of the channel configuration used */ - void channels(uInt32 number); + string channels(uInt32 hardware, bool stereo); /** Set volume clipping (decrease volume range by half to eliminate popping) @@ -133,6 +139,12 @@ class TIASound uInt32 myCounter; }; + enum ChannelMode { + Hardware1, + Hardware2Mono, + Hardware2Stereo + }; + private: uInt8 myAUDC[2]; uInt8 myAUDF[2]; @@ -142,9 +154,9 @@ class TIASound uInt8 myP4[2]; // 4-bit register LFSR (lower 4 bits used) uInt8 myP5[2]; // 5-bit register LFSR (lower 5 bits used) + ChannelMode myChannelMode; Int32 myOutputFrequency; Int32 myTIAFrequency; - uInt32 myChannels; Int32 myOutputCounter; uInt32 myVolumePercentage; uInt8 myVolumeClip; diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx index be2243a76..09aff51b7 100644 --- a/src/gui/AudioDialog.cxx +++ b/src/gui/AudioDialog.cxx @@ -48,7 +48,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent, buttonWidth = font.getStringWidth("Defaults") + 20, buttonHeight = font.getLineHeight() + 4; int xpos, ypos; - int lwidth = font.getStringWidth("Fragment Size: "), + int lwidth = font.getStringWidth("Sample Size (*): "), pwidth = font.getStringWidth("512 bytes"); WidgetArray wid; StringMap items; @@ -82,7 +82,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent, items.push_back("4 KB", "4096"); myFragsizePopup = new PopUpWidget(this, font, xpos, ypos, pwidth + myVolumeLabel->getWidth() - 4, lineHeight, - items, "Fragment size: ", lwidth); + items, "Sample size (*): ", lwidth); wid.push_back(myFragsizePopup); ypos += lineHeight + 4; @@ -95,7 +95,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent, items.push_back("48000 Hz", "48000"); myFreqPopup = new PopUpWidget(this, font, xpos, ypos, pwidth + myVolumeLabel->getWidth() - 4, lineHeight, - items, "Output freq: ", lwidth); + items, "Output freq (*): ", lwidth); wid.push_back(myFreqPopup); ypos += lineHeight + 4; @@ -108,16 +108,22 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent, ypos += lineHeight + 4; // Clip volume - myClipVolumeCheckbox = new CheckboxWidget(this, font, xpos+50, ypos, + myClipVolumeCheckbox = new CheckboxWidget(this, font, xpos+10, ypos, "Clip volume", 0); wid.push_back(myClipVolumeCheckbox); - ypos += lineHeight + 4; + xpos += myClipVolumeCheckbox->getWidth() + 20; // Enable sound - mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos+50, ypos, + mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos, "Enable sound", kSoundEnableChanged); wid.push_back(mySoundEnableCheckbox); + + // Add message concerning usage ypos += lineHeight + 12; + const GUI::Font& infofont = instance().infoFont(); + new StaticTextWidget(this, infofont, 10, ypos, + font.getStringWidth("(*) Requires application restart"), fontHeight, + "(*) Requires application restart", kTextAlignLeft); // Add Defaults, OK and Cancel buttons ButtonWidget* b; diff --git a/src/gui/LoggerDialog.hxx b/src/gui/LoggerDialog.hxx index 130a0f3ea..10db3c30a 100644 --- a/src/gui/LoggerDialog.hxx +++ b/src/gui/LoggerDialog.hxx @@ -32,7 +32,8 @@ class StringListWidget; class LoggerDialog : public Dialog { public: - LoggerDialog(OSystem* osystem, DialogContainer* parent, const GUI::Font& font, int max_w, int max_h); + LoggerDialog(OSystem* osystem, DialogContainer* parent, + const GUI::Font& font, int max_w, int max_h); virtual ~LoggerDialog(); protected: diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 38d48dd48..a672c3b77 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -449,16 +449,16 @@ void VideoDialog::setDefaults() myFSResPopup->setSelected("auto", ""); myFrameTimingPopup->setSelected("sleep", ""); myGLFilterPopup->setSelected("nearest", ""); - myNAspectRatioSlider->setValue(100); - myNAspectRatioLabel->setLabel("100"); + myNAspectRatioSlider->setValue(90); + myNAspectRatioLabel->setLabel("90"); myPAspectRatioSlider->setValue(100); myPAspectRatioLabel->setLabel("100"); myFrameRateSlider->setValue(0); myFrameRateLabel->setLabel("Auto"); myFullscreenPopup->setSelected("0", ""); - myColorLossCheckbox->setState(false); - myGLStretchCheckbox->setState(false); + myColorLossCheckbox->setState(true); + myGLStretchCheckbox->setState(true); myUseVBOCheckbox->setState(true); myUseVSyncCheckbox->setState(true); myUIMessagesCheckbox->setState(true);
    ItemBrief descriptionFor more information,
    see CommandLine
    Volumeself-explanatory-volume
    Fragment sizeset size of audio buffers-fragsize
    Output freqchange sound output frequency (advanced)-freq
    Sample size (*)set size of audio buffers-fragsize
    Output freq (*)change sound output frequency (advanced)-freq
    TIA freqchange TIA output frequency (advanced)-tiafreq
    Clip volumeEliminate popping in sound generation (advanced)-clipvol
    Enable soundself-explanatory-sound
    Provided technical information on the Supercharger
    "Uncle" Carmine
    + (http://www.carmine.com)
    Generously donated several 2600 games and manuals to help with development
    Piero Cavina Allowed "Oystron" to be included in the Stella distribution
    Nick Montfort and Ian Bogost
    + (Racing the Beam)
    Specifically mentioned Stella in their book
    Kostas Nakos Author/maintainer of the WinCE version of Stella from releases 2.0 @@ -3413,6 +3425,12 @@ Ms Pac-Man (Stella extended codes): Author of the "Game Menu" emulator game shell
    James Randall aka 'toymailman'Generously donated a 7800 console and several games and manuals to help + with development
    RomHunter
    (RomHunter ROMs)
    Provides an updated database of ROM information on a regular basis
    Albert Yarusso
    -http://atariage.com
    Provided helpful feedback for the MacOSX port, and generously donated an AtariVox device to help with development