From c1067fde835a83ac7d4add849f1153409fe5e148 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 Feb 2019 15:52:51 +0100 Subject: [PATCH] first shot at automatic controller detection --- src/emucore/ControllerDetector.cxx | 361 +++++++++++++++++++++++++++++ src/emucore/ControllerDetector.hxx | 100 ++++++++ src/emucore/OSystem.cxx | 18 +- src/emucore/Props.cxx | 4 +- src/windows/Stella.vcxproj | 3 + src/windows/Stella.vcxproj.filters | 9 + 6 files changed, 489 insertions(+), 6 deletions(-) create mode 100644 src/emucore/ControllerDetector.cxx create mode 100644 src/emucore/ControllerDetector.hxx diff --git a/src/emucore/ControllerDetector.cxx b/src/emucore/ControllerDetector.cxx new file mode 100644 index 000000000..304d95207 --- /dev/null +++ b/src/emucore/ControllerDetector.cxx @@ -0,0 +1,361 @@ +//============================================================================ +// +// 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-2019 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Settings.hxx" +#include "OSystem.hxx" + +#include "ControllerDetector.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string ControllerDetector::detect(const BytePtr& image, uInt32 size, + const string& controller, const Controller::Jack port, + const OSystem& osystem) +{ + string type(controller); + //string type("AUTO"); // dirty hack for testing!!! + + if(type == "AUTO" || osystem.settings().getBool("rominfo")) + { + string detectedType = autodetectPort(image, size, port, osystem); + + if(type != "AUTO" && type != detectedType) + { + cerr << "Controller auto-detection not consistent: " + << type << ", " << detectedType << endl; + } + type = detectedType; + } + + return type; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string ControllerDetector::autodetectPort(const BytePtr& image, uInt32 size, + Controller::Jack port, const OSystem& osystem) +{ + // default type joystick + string type = "JOYSTICK"; // TODO: remove magic strings + + if(isProbablyAtariVox(image, size, port)) + type = "ATARIVOX"; + else if (isProbablySaveKey(image, size, port)) + type = "SAVEKEY"; + else if(usesJoystickButtons(image, size, port)) + { + if(isProbablyTrakBall(image, size)) + type = "TRAKBALL"; + else if(isProbablyAtariMouse(image, size)) + type = "ATARIMOUSE"; + else if(isProbablyAmigaMouse(image, size)) + type = "AMIGAMOUSE"; + else if(usesPaddleButtons(image, size, port, osystem)) + type = "KEYBOARD"; // only keyboard uses joystick and paddle buttons + // TODO: Big Bird, Brain Games, Cookie Monster Munch (right), + // Game of Concentration, Grover's Music Maker (right) + // Holey Moley, Hunt & Score + // Monster Cise, Oscar's Trash Race (different, Peek-A-Boo + } + else + { + if(usesPaddleButtons(image, size, port, osystem)) + type = "PADDLES"; + } + // TODO: GENESIS, BOOSTERGRIP, DRIVING, MINDLINK, ATARIVOX, KIDVID + // not detectable: PADDLES_IAXIS, PADDLES_IAXDR + return type; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::searchForBytes(const uInt8* image, uInt32 imagesize, + const uInt8* signature, uInt32 sigsize, + uInt32 minhits) +{ + uInt32 count = 0; + for(uInt32 i = 0; i < imagesize - sigsize; ++i) + { + uInt32 matches = 0; + for(uInt32 j = 0; j < sigsize; ++j) + { + if(image[i + j] == signature[j]) + ++matches; + else + break; + } + if(matches == sigsize) + { + ++count; + i += sigsize; // skip past this signature 'window' entirely + } + if(count >= minhits) + break; + } + + return (count >= minhits); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::usesJoystickButtons(const BytePtr& image, uInt32 size, Controller::Jack port) +{ + if(port == Controller::Left) + { + const int NUM_SIGS_0 = 13; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { + { 0x24, 0x0c, 0x10 }, // bit INPT4; bpl (joystick games only) + { 0x24, 0x0c, 0x30 }, // bit INPT4; bmi (joystick games only) + { 0xa5, 0x0c, 0x10 }, // lda INPT4; bpl (joystick games only) + { 0xa5, 0x0c, 0x30 }, // lda INPT4; bmi (joystick games only) + { 0xb5, 0x0c, 0x10 }, // lda INPT4,x; bpl (joystick games only) + { 0xb5, 0x0c, 0x30 }, // lda INPT4,x; bmi (joystick games only) + { 0x24, 0x3c, 0x10 }, // bit INPT4|$30; bpl (joystick games + Compumate) + { 0x24, 0x3c, 0x30 }, // bit INPT4|$30; bmi (joystick, keyboard and mindlink games) + { 0xa5, 0x3c, 0x10 }, // lda INPT4|$30; bpl (joystick and keyboard games) + { 0xa5, 0x3c, 0x30 }, // lda INPT4|$30; bmi (joystick, keyboard and mindlink games) + { 0xb5, 0x3c, 0x10 }, // lda INPT4|$30,x; bpl (joystick, keyboard and driving games) + { 0xb5, 0x3c, 0x30 }, // lda INPT4|$30,x; bmi (joystick and keyboard games) + { 0xb4, 0x0c, 0x30 } // ldy INPT4|$30,x; bmi (joystick games only) + }; + const int NUM_SIGS_1 = 5; + const int SIG_SIZE_1 = 5; + uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xa5, 0x0c, 0x25, 0x0d, 0x10 }, // lda INPT4; and INPT5; bpl (joystick games only) + { 0xa5, 0x0c, 0x25, 0x0d, 0x30 }, // lda INPT4; and INPT5; bmi (joystick games only) + { 0xa5, 0x3c, 0x25, 0x3d, 0x10 }, // lda INPT4|$30; and INPT5|$30; bpl (joystick games only) + { 0xa5, 0x3c, 0x25, 0x3d, 0x30 }, // lda INPT4|$30; and INPT5|$30; bmi (joystick games only) + { 0xb5, 0x38, 0x29, 0x80, 0xd0 }, // lda INPT0|$30,y; and #$80; bne (Basic Programming) + }; + + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_1; ++i) + if(searchForBytes(image.get(), size, signature_1[i], SIG_SIZE_1)) + return true; + } + else if(port == Controller::Right) + { + const int NUM_SIGS = 12; + const int SIG_SIZE = 3; + uInt8 signature[NUM_SIGS][SIG_SIZE] = { + { 0x24, 0x0d, 0x10 }, // bit INPT5; bpl (joystick games only) + { 0x24, 0x0d, 0x30 }, // bit INPT5; bmi (joystick games only) + { 0xa5, 0x0d, 0x10 }, // lda INPT5; bpl (joystick games only) + { 0xa5, 0x0d, 0x30 }, // lda INPT5; bmi (joystick games only) + { 0xb5, 0x0c, 0x10 }, // lda INPT4,x; bpl (joystick games only) + { 0xb5, 0x0c, 0x30 }, // lda INPT4,x; bmi (joystick games only) + { 0x24, 0x3d, 0x10 }, // bit INPT5|$30; bpl (joystick games, Compumate) + { 0x24, 0x3d, 0x30 }, // bit INPT5|$30; bmi (joystick and keyboard games) + { 0xa5, 0x3d, 0x10 }, // lda INPT5|$30; bpl (joystick games only) + { 0xa5, 0x3d, 0x30 }, // lda INPT5|$30; bmi (joystick and keyboard games) + { 0xb5, 0x3c, 0x10 }, // lda INPT4|$30,x; bpl (joystick, keyboard and driving games) + { 0xb5, 0x3c, 0x30 } // lda INPT4|$30,x; bmi (joystick and keyboard games) + }; + + const int NUM_SIGS_1 = 1; + const int SIG_SIZE_1 = 5; + uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xb5, 0x38, 0x29, 0x80, 0xd0 }, // lda INPT0|$30,y; and #$80; bne (Basic Programming) + }; + + for(uInt32 i = 0; i < NUM_SIGS; ++i) + if(searchForBytes(image.get(), size, signature[i], SIG_SIZE)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_1; ++i) + if(searchForBytes(image.get(), size, signature_1[i], SIG_SIZE_1)) + return true; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, + Controller::Jack port, const OSystem& osystem) +{ + // TODO: swap paddles/ports (uses INPT1/INPT3) + if(port == Controller::Left) + { + const int NUM_SIGS_0 = 13; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { + //{ 0x24, 0x08, 0x10 }, // bit INPT0; bpl (many joystick games too!) + //{ 0x24, 0x08, 0x30 }, // bit INPT0; bmi (joystick games: Spike's Peak, Sweat, Turbo!) + { 0xa5, 0x08, 0x10 }, // lda INPT0; bpl (no joystick games) + { 0xa5, 0x08, 0x30 }, // lda INPT0; bmi (no joystick games) + { 0xb5, 0x08, 0x10 }, // lda INPT0,x; bpl (Duck Attack!) + { 0xb5, 0x08, 0x30 }, // lda INPT0,x; bmi (no joystick games) + { 0x24, 0x38, 0x10 }, // bit INPT0|$30; bpl (no joystick games) + { 0x24, 0x38, 0x30 }, // bit INPT0|$30; bmi (no joystick games) + { 0xa5, 0x38, 0x10 }, // lda INPT0|$30; bpl (no joystick games) + { 0xa5, 0x38, 0x30 }, // lda INPT0|$30; bmi (no joystick games) + { 0xb5, 0x38, 0x10 }, // lda INPT0|$30,x; bpl (Circus Atari, old code!) + { 0xb5, 0x38, 0x30 }, // lda INPT0|$30,x; bmi (no joystick games) + { 0x68, 0x48, 0x10 }, // pla; pha; bpl (i.a. Bachelor Party) + { 0xa5, 0x3b, 0x30 }, // lda INPT3|$30; bmi (only Tac Scan, ports and paddles swapped) + { 0xa5, 0x09, 0x30 }, // lda INPT3|$30; bmi (only Backgammon) + }; + const int NUM_SIGS_1 = 2; + const int SIG_SIZE_1 = 4; + uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xb9, 0x08, 0x00, 0x30 }, // lda INPT0,y; bmi (i.a. Encounter at L-5) + { 0xb9, 0x38, 0x00, 0x30 }, // lda INPT0|$30,y; bmi (i.a. SW-Jedi Arena, Video Olympics) + }; + const int NUM_SIGS_2 = 4; + const int SIG_SIZE_2 = 5; + uInt8 signature_2[NUM_SIGS_2][SIG_SIZE_2] = { + { 0xb5, 0x38, 0x29, 0x80, 0xd0 }, // lda INPT0|$30,x; and #$80; bne (Basic Programming) + { 0x24, 0x38, 0x85, 0x08, 0x10 }, // bit INPT0|$30; sta COLUPF, bpl (Fireball) + { 0xb5, 0x38, 0x49, 0xff, 0x0a }, // lda INPT0|$30,x; eor #$ff; asl (Blackjack) + { 0xb1, 0xf2, 0x30, 0x02, 0xe6 } // lda ($f2),y; bmi...; inc (Warplock) + }; + + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_1; ++i) + if(searchForBytes(image.get(), size, signature_1[i], SIG_SIZE_1)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_2; ++i) + if(searchForBytes(image.get(), size, signature_2[i], SIG_SIZE_2)) + return true; + } + else if(port == Controller::Right) + { + const int NUM_SIGS_0 = 16; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { + { 0x24, 0x0a, 0x10 }, // bit INPT2; bpl + { 0x24, 0x0a, 0x30 }, // bit INPT2; bmi + { 0xa5, 0x0a, 0x10 }, // lda INPT2; bpl + { 0xa5, 0x0a, 0x30 }, // lda INPT2; bmi + { 0xb5, 0x0a, 0x10 }, // lda INPT2,x; bpl + { 0xb5, 0x0a, 0x30 }, // lda INPT2,x; bmi + { 0xb5, 0x08, 0x10 }, // lda INPT0,x; bpl (no joystick games) + { 0xb5, 0x08, 0x30 }, // lda INPT0,x; bmi (no joystick games) + { 0x24, 0x3a, 0x10 }, // bit INPT2|$30; bpl + { 0x24, 0x3a, 0x30 }, // bit INPT2|$30; bmi + { 0xa5, 0x3a, 0x10 }, // lda INPT2|$30; bpl + { 0xa5, 0x3a, 0x30 }, // lda INPT2|$30; bmi + { 0xb5, 0x3a, 0x10 }, // lda INPT2|$30,x; bpl + { 0xb5, 0x3a, 0x30 }, // lda INPT2|$30,x; bmi + { 0xb5, 0x38, 0x10 }, // lda INPT0|$30,x; bpl (Circus Atari, old code!) + { 0xb5, 0x38, 0x30 }, // lda INPT0|$30,x; bmi (no joystick games) + }; + const int NUM_SIGS_1 = 1; + const int SIG_SIZE_1 = 4; + uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xb9, 0x38, 0x00, 0x30 }, // lda INPT0|$30,y; bmi (Video Olympics) + }; + const int NUM_SIGS_2 = 3; + const int SIG_SIZE_2 = 5; + uInt8 signature_2[NUM_SIGS_2][SIG_SIZE_2] = { + { 0xb5, 0x38, 0x29, 0x80, 0xd0 }, // lda INPT0|$30,x; and #$80; bne (Basic Programming) + { 0x24, 0x38, 0x85, 0x08, 0x10 }, // bit INPT2|$30; sta COLUPF, bpl (Fireball, patched at runtime!) + { 0xb5, 0x38, 0x49, 0xff, 0x0a } // lda INPT0|$30,x; eor #$ff; asl (Blackjack) + }; + + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_1; ++i) + if(searchForBytes(image.get(), size, signature_1[i], SIG_SIZE_1)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_2; ++i) + if(searchForBytes(image.get(), size, signature_2[i], SIG_SIZE_2)) + return true; + } + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::isProbablyTrakBall(const BytePtr& image, uInt32 size) +{ + const int NUM_SIGS = 1; + const int SIG_SIZE = 8; + uInt8 signature[SIG_SIZE] = { + 0b1010, 0b1000, 0b1000, 0b1010, 0b0010, 0b0000, 0b0000, 0b0010 // NextTrackTbl + // TODO: Omegamatrix's signature (.MovementTab_1) + }; + + if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + return true; + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::isProbablyAtariMouse(const BytePtr& image, uInt32 size) +{ + const int SIG_SIZE = 8; + uInt8 signature[SIG_SIZE] = { + 0b0101, 0b0111, 0b0100, 0b0110, 0b1101, 0b1111, 0b1100, 0b1110 // NextTrackTbl + // TODO: Omegamatrix's signature (.MovementTab_1) + }; + + if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + return true; + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::isProbablyAmigaMouse(const BytePtr& image, uInt32 size) +{ + const int SIG_SIZE = 8; + uInt8 signature[SIG_SIZE] = { + 0b1100, 0b1000, 0b0100, 0b0000, 0b1101, 0b1001, 0b0101, 0b0001 // NextTrackTbl + // TODO: Omegamatrix's signature (.MovementTab_1) + }; + + if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + return true; + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::isProbablyAtariVox(const BytePtr& image, uInt32 size, Controller::Jack port) +{ + // TOOD: analyse example code + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::isProbablySaveKey(const BytePtr& image, uInt32 size, Controller::Jack port) +{ + // known SaveKey code only supports right port + if(port == Controller::Right) + { + const int SIG_SIZE = 9; + uInt8 signature[SIG_SIZE] = { // from I2C_TXNACK + 0xa9, 0x10, // lda #I2C_SCL_MASK*2 + 0x8d, 0x80, 0x02, // sta SWCHA + 0x4a, // lsr + 0x8d, 0x81, 0x02 // sta SWACNT + }; + + return (searchForBytes(image.get(), size, signature, SIG_SIZE)); + } + + return false; +} \ No newline at end of file diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx new file mode 100644 index 000000000..3502aefb7 --- /dev/null +++ b/src/emucore/ControllerDetector.hxx @@ -0,0 +1,100 @@ +//============================================================================ +// +// 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-2019 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + + +#ifndef CONTROLLER_DETECTOR_HXX +#define CONTROLLER_DETECTOR_HXX + +class Cartridge; +class Properties; +class OSystem; + +class FilesystemNode; + +//#include "Bankswitch.hxx" + +#include "Control.hxx" +#include "bspf.hxx" + +class ControllerDetector +{ + public: + /** + Create a new cartridge object allocated on the heap. The + type of cartridge created depends on the properties object. + + @param image A pointer to the ROM image + @param size The size of the ROM image + @param controller The provided left controller type of the ROM image + @param port The port to be checked + @param system The osystem associated with the system + @return The detected controller name + */ + static string detect(const BytePtr& image, uInt32 size, + const string& controller, const Controller::Jack port, + const OSystem& osystem); + + private: + static string autodetectPort(const BytePtr& image, uInt32 size, Controller::Jack port, const OSystem& osystem); + + /** + Search the image for the specified byte signature + + @param image A pointer to the ROM image + @param imagesize The size of the ROM image + @param signature The byte sequence to search for + @param sigsize The number of bytes in the signature + @param minhits The minimum number of times a signature is to be found + + @return True if the signature was found at least 'minhits' time, else false + */ + static bool searchForBytes(const uInt8* image, uInt32 imagesize, + const uInt8* signature, uInt32 sigsize, + uInt32 minhits = 1); + + // Returns true if the port's joystick button access code is found + static bool usesJoystickButtons(const BytePtr& image, uInt32 size, Controller::Jack port); + + // Returns true if the port's paddle button access code is found + static bool usesPaddleButtons(const BytePtr& image, uInt32 size, Controller::Jack port, const OSystem& osystem); + + // Returns true if Trak-Ball table is found + static bool isProbablyTrakBall(const BytePtr& image, uInt32 size); + + // Returns true if Atari Mouse table is found + static bool isProbablyAtariMouse(const BytePtr& image, uInt32 size); + + // Returns true if Amiga Mouse table is found + static bool isProbablyAmigaMouse(const BytePtr& image, uInt32 size); + + // Returns true if the AtariVox code pattern is found (TODO) + static bool isProbablyAtariVox(const BytePtr& image, uInt32 size, Controller::Jack port); + + // Returns true if the SaveKey code pattern is found + static bool isProbablySaveKey(const BytePtr& image, uInt32 size, Controller::Jack port); + + private: + // Following constructors and assignment operators not supported + ControllerDetector() = delete; + ControllerDetector(const ControllerDetector&) = delete; + ControllerDetector(ControllerDetector&&) = delete; + ControllerDetector& operator=(const ControllerDetector&) = delete; + ControllerDetector& operator=(ControllerDetector&&) = delete; +}; + +#endif + diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 5e3bedc87..d7f618364 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -34,6 +34,7 @@ #include "MD5.hxx" #include "Cart.hxx" #include "CartDetector.hxx" +#include "ControllerDetector.hxx" #include "FrameBuffer.hxx" #include "TIASurface.hxx" #include "TIAConstants.hxx" @@ -484,10 +485,7 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& } } - CMDLINE_PROPS_UPDATE("channels", Cartridge_Sound); - CMDLINE_PROPS_UPDATE("ld", Console_LeftDifficulty); - CMDLINE_PROPS_UPDATE("rd", Console_RightDifficulty); - CMDLINE_PROPS_UPDATE("tv", Console_TelevisionType); + // read controller properties... CMDLINE_PROPS_UPDATE("sp", Console_SwapPorts); CMDLINE_PROPS_UPDATE("lc", Controller_Left); CMDLINE_PROPS_UPDATE("rc", Controller_Right); @@ -495,6 +493,18 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& if(s != "") { props.set(Controller_Left, s); props.set(Controller_Right, s); } CMDLINE_PROPS_UPDATE("cp", Controller_SwapPaddles); CMDLINE_PROPS_UPDATE("ma", Controller_MouseAxis); + // ...and try to detect controllers + const string& left = props.get(Controller_Left); + const string& detectedLeft = ControllerDetector::detect(image, size, left, Controller::Left, *this); + props.set(Controller_Left, detectedLeft); + const string& right = props.get(Controller_Right); + const string& detectedRight = ControllerDetector::detect(image, size, right, Controller::Right, *this); + props.set(Controller_Right, detectedRight); + + CMDLINE_PROPS_UPDATE("channels", Cartridge_Sound); + CMDLINE_PROPS_UPDATE("ld", Console_LeftDifficulty); + CMDLINE_PROPS_UPDATE("rd", Console_RightDifficulty); + CMDLINE_PROPS_UPDATE("tv", Console_TelevisionType); CMDLINE_PROPS_UPDATE("format", Display_Format); CMDLINE_PROPS_UPDATE("ystart", Display_YStart); CMDLINE_PROPS_UPDATE("height", Display_Height); diff --git a/src/emucore/Props.cxx b/src/emucore/Props.cxx index e6d93b376..62a96c0e4 100644 --- a/src/emucore/Props.cxx +++ b/src/emucore/Props.cxx @@ -320,8 +320,8 @@ string Properties::ourDefaultProperties[LastPropType] = { "B", // Console.RightDifficulty "COLOR", // Console.TelevisionType "NO", // Console.SwapPorts - "JOYSTICK", // Controller.Left - "JOYSTICK", // Controller.Right + "AUTO", // Controller.Left + "AUTO", // Controller.Right "NO", // Controller.SwapPaddles "AUTO", // Controller.MouseAxis "AUTO", // Display.Format diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 6893ddd8e..7bd61541e 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -348,6 +348,7 @@ + @@ -807,6 +808,7 @@ CompileAsC CompileAsC + @@ -929,6 +931,7 @@ + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index e30a2ea84..925135acc 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -951,6 +951,12 @@ Source Files + + Source Files\emucore + + + Source Files\emucore + @@ -1943,6 +1949,9 @@ Header Files + + Header Files\emucore +