From a4456e6af8687c540d7f5743da1bd814b2e0c185 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 Feb 2019 22:10:30 +0100 Subject: [PATCH] improved controller detection and added Genesis adapted GameInfoDialog to controller detection moved detection from OSystem to Console --- src/debugger/gui/ControllerWidget.hxx | 2 +- src/emucore/Console.cxx | 14 +- src/emucore/ControllerDetector.cxx | 210 ++++++++++++++++---------- src/emucore/ControllerDetector.hxx | 28 ++-- src/emucore/OSystem.cxx | 10 -- src/gui/GameInfoDialog.cxx | 41 ++++- src/gui/GameInfoDialog.hxx | 2 + 7 files changed, 196 insertions(+), 111 deletions(-) diff --git a/src/debugger/gui/ControllerWidget.hxx b/src/debugger/gui/ControllerWidget.hxx index b01b8d517..136cdc7a2 100644 --- a/src/debugger/gui/ControllerWidget.hxx +++ b/src/debugger/gui/ControllerWidget.hxx @@ -51,7 +51,7 @@ class ControllerWidget : public Widget, public CommandSender bool isLeftPort() { bool swappedPorts = instance().console().properties().get(Console_SwapPorts) == "YES"; - + return (myController.jack() == Controller::Left) ^ swappedPorts; } diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 5fe0eb01e..a325db706 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -26,6 +26,7 @@ #include "Driving.hxx" #include "Event.hxx" #include "EventHandler.hxx" +#include "ControllerDetector.hxx" #include "Joystick.hxx" #include "Keyboard.hxx" #include "KidVid.hxx" @@ -845,8 +846,17 @@ void Console::setControllers(const string& rommd5) else { // Setup the controllers based on properties - const string& left = myProperties.get(Controller_Left); - const string& right = myProperties.get(Controller_Right); + string left = myProperties.get(Controller_Left); + string right = myProperties.get(Controller_Right); + uInt32 size = 0; + const uInt8* image = myCart->getImage(size); + + // try to detect controllers + if(image != nullptr || size != 0) + { + left = ControllerDetector::detect(image, size, left, Controller::Left, myOSystem.settings()); + right = ControllerDetector::detect(image, size, right, Controller::Right, myOSystem.settings()); + } unique_ptr leftC = getControllerPort(rommd5, left, Controller::Left), rightC = getControllerPort(rommd5, right, Controller::Right); diff --git a/src/emucore/ControllerDetector.cxx b/src/emucore/ControllerDetector.cxx index 679031413..2ba2c296a 100644 --- a/src/emucore/ControllerDetector.cxx +++ b/src/emucore/ControllerDetector.cxx @@ -16,21 +16,20 @@ //============================================================================ #include "Settings.hxx" -#include "OSystem.hxx" #include "ControllerDetector.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string ControllerDetector::detect(const BytePtr& image, uInt32 size, +string ControllerDetector::detect(const uInt8* image, uInt32 size, const string& controller, const Controller::Jack port, - const OSystem& osystem) + const Settings& settings) { - string type(controller); - //string type("AUTO"); // dirty hack for testing!!! + //string type(controller); + string type("AUTO"); // dirty hack for testing!!! - if(type == "AUTO" || osystem.settings().getBool("rominfo")) + if(type == "AUTO" || settings.getBool("rominfo")) { - string detectedType = autodetectPort(image, size, port, osystem); + string detectedType = autodetectPort(image, size, port, settings); if(type != "AUTO" && type != detectedType) { @@ -44,17 +43,15 @@ string ControllerDetector::detect(const BytePtr& image, uInt32 size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string ControllerDetector::autodetectPort(const BytePtr& image, uInt32 size, - Controller::Jack port, const OSystem& osystem) +string ControllerDetector::autodetectPort(const uInt8* image, uInt32 size, + Controller::Jack port, const Settings& settings) { // default type joystick string type = "JOYSTICK"; // TODO: remove magic strings - if(isProbablyAtariVox(image, size, port)) - type = "ATARIVOX"; - else if (isProbablySaveKey(image, size, port)) + if (isProbablySaveKey(image, size, port)) type = "SAVEKEY"; - else if(usesJoystickButtons(image, size, port)) + else if(usesJoystickButton(image, size, port)) { if(isProbablyTrakBall(image, size)) type = "TRAKBALL"; @@ -62,29 +59,25 @@ string ControllerDetector::autodetectPort(const BytePtr& image, uInt32 size, type = "ATARIMOUSE"; else if(isProbablyAmigaMouse(image, size)) type = "AMIGAMOUSE"; - else if(usesPaddleButtons(image, size, port, osystem)) + else if(usesPaddle(image, size, port, settings)) 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(usesGenesisButton(image, size, port)) + type = "GENESIS"; } else { - if(usesPaddleButtons(image, size, port, osystem)) + if(usesPaddle(image, size, port, settings)) type = "PADDLES"; } - // TODO: GENESIS, BOOSTERGRIP, DRIVING, MINDLINK, ATARIVOX, KIDVID + // TODO: 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) + const uInt8* signature, uInt32 sigsize) { - uInt32 count = 0; for(uInt32 i = 0; i < imagesize - sigsize; ++i) { uInt32 matches = 0; @@ -97,22 +90,19 @@ bool ControllerDetector::searchForBytes(const uInt8* image, uInt32 imagesize, } if(matches == sigsize) { - ++count; - i += sigsize; // skip past this signature 'window' entirely + return true; } - if(count >= minhits) - break; } - return (count >= minhits); + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesJoystickButtons(const BytePtr& image, uInt32 size, Controller::Jack port) +bool ControllerDetector::usesJoystickButton(const uInt8* image, uInt32 size, Controller::Jack port) { if(port == Controller::Left) { - const int NUM_SIGS_0 = 13; + const int NUM_SIGS_0 = 17; const int SIG_SIZE_0 = 3; uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { { 0x24, 0x0c, 0x10 }, // bit INPT4; bpl (joystick games only) @@ -127,11 +117,23 @@ bool ControllerDetector::usesJoystickButtons(const BytePtr& image, uInt32 size, { 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) + { 0xb4, 0x0c, 0x30 }, // ldy INPT4|$30,x; bmi (joystick games only) + { 0xa5, 0x3c, 0x2a }, // ldy INPT4|$30; rol (joystick games only) + { 0xa6, 0x3c, 0x8e }, // ldx INPT4|$30; stx (joystick games only) + { 0xa4, 0x0c, 0x30 }, // ldy INPT4|; bmi (only Game of Concentration) + { 0xa4, 0x3c, 0x30 }, // ldy INPT4|$30; bmi (only Game of Concentration) }; - const int NUM_SIGS_1 = 5; - const int SIG_SIZE_1 = 5; + const int NUM_SIGS_1 = 4; + const int SIG_SIZE_1 = 4; uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xb9, 0x0c, 0x00, 0x10 }, // lda INPT4,y; bpl (joystick games only) + { 0xb9, 0x0c, 0x00, 0x30 }, // lda INPT4,y; bmi (joystick games only) + { 0xb9, 0x3c, 0x00, 0x10 }, // lda INPT4,y; bpl (joystick games only) + { 0xb9, 0x3c, 0x00, 0x30 }, // lda INPT4,y; bmi (joystick games only) + }; + const int NUM_SIGS_2 = 5; + const int SIG_SIZE_2 = 5; + uInt8 signature_2[NUM_SIGS_2][SIG_SIZE_2] = { { 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) @@ -140,18 +142,22 @@ bool ControllerDetector::usesJoystickButtons(const BytePtr& image, uInt32 size, }; for(uInt32 i = 0; i < NUM_SIGS_0; ++i) - if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + if(searchForBytes(image, 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)) + if(searchForBytes(image, size, signature_1[i], SIG_SIZE_1)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_2; ++i) + if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2)) return true; } else if(port == Controller::Right) { - const int NUM_SIGS = 12; - const int SIG_SIZE = 3; - uInt8 signature[NUM_SIGS][SIG_SIZE] = { + const int NUM_SIGS_0 = 13; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { { 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) @@ -163,31 +169,87 @@ bool ControllerDetector::usesJoystickButtons(const BytePtr& image, uInt32 size, { 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) + { 0xb5, 0x3c, 0x30 }, // lda INPT4|$30,x; bmi (joystick and keyboard games) + { 0xa4, 0x3d, 0x30 }, // ldy INPT5; bmi (only Game of Concentration) }; - - const int NUM_SIGS_1 = 1; - const int SIG_SIZE_1 = 5; + const int NUM_SIGS_1 = 4; + const int SIG_SIZE_1 = 4; uInt8 signature_1[NUM_SIGS_1][SIG_SIZE_1] = { + { 0xb9, 0x0c, 0x00, 0x10 }, // lda INPT4,y; bpl (joystick games only) + { 0xb9, 0x0c, 0x00, 0x30 }, // lda INPT4,y; bmi (joystick games only) + { 0xb9, 0x3c, 0x00, 0x10 }, // lda INPT4,y; bpl (joystick games only) + { 0xb9, 0x3c, 0x00, 0x30 }, // lda INPT4,y; bmi (joystick games only) + }; + const int NUM_SIGS_2 = 1; + const int SIG_SIZE_2 = 5; + uInt8 signature_2[NUM_SIGS_2][SIG_SIZE_2] = { { 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)) + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image, 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)) + if(searchForBytes(image, size, signature_1[i], SIG_SIZE_1)) + return true; + + for(uInt32 i = 0; i < NUM_SIGS_2; ++i) + if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2)) return true; } return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, - Controller::Jack port, const OSystem& osystem) +bool ControllerDetector::usesGenesisButton(const uInt8* image, uInt32 size, Controller::Jack port) +{ + if(port == Controller::Left) + { + const int NUM_SIGS_0 = 10; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { + { 0x24, 0x09, 0x10 }, // bit INPT1; bpl + { 0x24, 0x09, 0x30 }, // bit INPT1; bmi + { 0xa5, 0x09, 0x10 }, // lda INPT1; bpl + { 0xa5, 0x09, 0x30 }, // lda INPT1; bmi + { 0x24, 0x39, 0x10 }, // bit INPT1|$30; bpl + { 0x24, 0x39, 0x30 }, // bit INPT1|$30; bmi + { 0xa5, 0x39, 0x10 }, // lda INPT1|$30; bpl + { 0xa5, 0x39, 0x30 }, // lda INPT1|$30; bmi + { 0xa5, 0x39, 0x6a }, // lda INPT1|$30; ror + { 0xa6, 0x39, 0x8e }, // ldx INPT1|$30; stx + }; + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image, size, signature_0[i], SIG_SIZE_0)) + return true; + } + else if(port == Controller::Right) + { + const int NUM_SIGS_0 = 9; + const int SIG_SIZE_0 = 3; + uInt8 signature_0[NUM_SIGS_0][SIG_SIZE_0] = { + { 0x24, 0x0b, 0x10 }, // bit INPT3; bpl + { 0x24, 0x0b, 0x30 }, // bit INPT3; bmi + { 0xa5, 0x0b, 0x10 }, // lda INPT3; bpl + { 0xa5, 0x0b, 0x30 }, // lda INPT3; bmi + { 0x24, 0x3b, 0x10 }, // bit INPT3|$30; bpl + { 0x24, 0x3b, 0x30 }, // bit INPT3|$30; bmi + { 0xa5, 0x3b, 0x10 }, // lda INPT3|$30; bpl + { 0xa5, 0x3b, 0x30 }, // lda INPT3|$30; bmi + { 0xa6, 0x3b, 0x8e }, // ldx INPT3|$30; stx + }; + for(uInt32 i = 0; i < NUM_SIGS_0; ++i) + if(searchForBytes(image, size, signature_0[i], SIG_SIZE_0)) + return true; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool ControllerDetector::usesPaddle(const uInt8* image, uInt32 size, + Controller::Jack port, const Settings& settings) { - // TODO: swap paddles/ports (uses INPT1/INPT3) if(port == Controller::Left) { const int NUM_SIGS_0 = 13; @@ -197,7 +259,7 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, //{ 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, 0x10 }, // lda INPT0,x; bpl (Duck Attack (graphics)!, Toyshop Trouble (Easter Egg)) { 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) @@ -207,13 +269,15 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, { 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) + { 0xa5, 0x08, 0x4c }, // lda INPT0; jmp (only Backgammon) + { 0xa4, 0x38, 0x30 }, // ldy INPT0; bmi (no joystick games) }; - const int NUM_SIGS_1 = 2; + const int NUM_SIGS_1 = 3; 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) + { 0x24, 0x08, 0x30, 0x02 }, // bit INPT0; bmi +2 (Picnic) }; const int NUM_SIGS_2 = 4; const int SIG_SIZE_2 = 5; @@ -225,25 +289,25 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, }; for(uInt32 i = 0; i < NUM_SIGS_0; ++i) - if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + if(searchForBytes(image, 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)) + if(searchForBytes(image, 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)) + if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2)) return true; } else if(port == Controller::Right) { - const int NUM_SIGS_0 = 16; + const int NUM_SIGS_0 = 17; 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 + { 0x24, 0x0a, 0x10 }, // bit INPT2; bpl (no joystick games) + { 0x24, 0x0a, 0x30 }, // bit INPT2; bmi (no joystick games) + { 0xa5, 0x0a, 0x10 }, // lda INPT2; bpl (no joystick games) { 0xa5, 0x0a, 0x30 }, // lda INPT2; bmi { 0xb5, 0x0a, 0x10 }, // lda INPT2,x; bpl { 0xb5, 0x0a, 0x30 }, // lda INPT2,x; bmi @@ -257,6 +321,7 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, { 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) + { 0xa4, 0x3a, 0x30 }, // ldy INPT2|$30; bmi (no joystick games) }; const int NUM_SIGS_1 = 1; const int SIG_SIZE_1 = 4; @@ -272,15 +337,15 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, }; for(uInt32 i = 0; i < NUM_SIGS_0; ++i) - if(searchForBytes(image.get(), size, signature_0[i], SIG_SIZE_0)) + if(searchForBytes(image, 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)) + if(searchForBytes(image, 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)) + if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2)) return true; } @@ -288,7 +353,7 @@ bool ControllerDetector::usesPaddleButtons(const BytePtr& image, uInt32 size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyTrakBall(const BytePtr& image, uInt32 size) +bool ControllerDetector::isProbablyTrakBall(const uInt8* image, uInt32 size) { const int NUM_SIGS = 1; const int SIG_SIZE = 8; @@ -297,14 +362,14 @@ bool ControllerDetector::isProbablyTrakBall(const BytePtr& image, uInt32 size) // TODO: Omegamatrix's signature (.MovementTab_1) }; - if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + if(searchForBytes(image, size, signature, SIG_SIZE)) return true; return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyAtariMouse(const BytePtr& image, uInt32 size) +bool ControllerDetector::isProbablyAtariMouse(const uInt8* image, uInt32 size) { const int SIG_SIZE = 8; uInt8 signature[SIG_SIZE] = { @@ -312,14 +377,14 @@ bool ControllerDetector::isProbablyAtariMouse(const BytePtr& image, uInt32 size) // TODO: Omegamatrix's signature (.MovementTab_1) }; - if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + if(searchForBytes(image, size, signature, SIG_SIZE)) return true; return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyAmigaMouse(const BytePtr& image, uInt32 size) +bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, uInt32 size) { const int SIG_SIZE = 8; uInt8 signature[SIG_SIZE] = { @@ -327,21 +392,14 @@ bool ControllerDetector::isProbablyAmigaMouse(const BytePtr& image, uInt32 size) // TODO: Omegamatrix's signature (.MovementTab_1) }; - if(searchForBytes(image.get(), size, signature, SIG_SIZE)) + if(searchForBytes(image, 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) +bool ControllerDetector::isProbablySaveKey(const uInt8* image, uInt32 size, Controller::Jack port) { // known SaveKey code only supports right port if(port == Controller::Right) @@ -354,7 +412,7 @@ bool ControllerDetector::isProbablySaveKey(const BytePtr& image, uInt32 size, Co 0x8d, 0x81, 0x02 // sta SWACNT }; - return (searchForBytes(image.get(), size, signature, SIG_SIZE)); + return (searchForBytes(image, size, signature, SIG_SIZE)); } return false; diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx index 3c109babe..fbca382ab 100644 --- a/src/emucore/ControllerDetector.hxx +++ b/src/emucore/ControllerDetector.hxx @@ -44,12 +44,13 @@ class ControllerDetector @param osystem The osystem associated with the system @return The detected controller name */ - static string detect(const BytePtr& image, uInt32 size, + static string detect(const uInt8* image, uInt32 size, const string& controller, const Controller::Jack port, - const OSystem& osystem); + const Settings& settings); private: - static string autodetectPort(const BytePtr& image, uInt32 size, Controller::Jack port, const OSystem& osystem); + static string autodetectPort(const uInt8* image, uInt32 size, Controller::Jack port, + const Settings& settings); /** Search the image for the specified byte signature @@ -63,29 +64,28 @@ class ControllerDetector @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); + const uInt8* signature, uInt32 sigsize); // Returns true if the port's joystick button access code is found - static bool usesJoystickButtons(const BytePtr& image, uInt32 size, Controller::Jack port); + static bool usesJoystickButton(const uInt8* image, uInt32 size, Controller::Jack port); + + static bool usesGenesisButton(const uInt8* 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); + static bool usesPaddle(const uInt8* image, uInt32 size, Controller::Jack port, + const Settings& settings); // Returns true if Trak-Ball table is found - static bool isProbablyTrakBall(const BytePtr& image, uInt32 size); + static bool isProbablyTrakBall(const uInt8* image, uInt32 size); // Returns true if Atari Mouse table is found - static bool isProbablyAtariMouse(const BytePtr& image, uInt32 size); + static bool isProbablyAtariMouse(const uInt8* 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); + static bool isProbablyAmigaMouse(const uInt8* image, uInt32 size); // Returns true if the SaveKey code pattern is found - static bool isProbablySaveKey(const BytePtr& image, uInt32 size, Controller::Jack port); + static bool isProbablySaveKey(const uInt8* image, uInt32 size, Controller::Jack port); private: // Following constructors and assignment operators not supported diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index d7f618364..a7f465596 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -34,7 +34,6 @@ #include "MD5.hxx" #include "Cart.hxx" #include "CartDetector.hxx" -#include "ControllerDetector.hxx" #include "FrameBuffer.hxx" #include "TIASurface.hxx" #include "TIAConstants.hxx" @@ -485,7 +484,6 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& } } - // read controller properties... CMDLINE_PROPS_UPDATE("sp", Console_SwapPorts); CMDLINE_PROPS_UPDATE("lc", Controller_Left); CMDLINE_PROPS_UPDATE("rc", Controller_Right); @@ -493,14 +491,6 @@ 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); diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index ae72f6cec..4a7742469 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -51,7 +51,8 @@ GameInfoDialog::GameInfoDialog( const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() + 4; + buttonHeight = font.getLineHeight() + 4, + infoLineHeight = ifont.getLineHeight(); const int VBORDER = 8; const int HBORDER = 10; const int VGAP = 4; @@ -63,7 +64,8 @@ GameInfoDialog::GameInfoDialog( // Set real dimensions setSize(53 * fontWidth + 8, - 8 * (lineHeight + VGAP) + VBORDER * 2 + _th + buttonHeight + fontHeight + ifont.getLineHeight() + 20, + 8 * (lineHeight + VGAP) + 2 * (infoLineHeight + VGAP) + VBORDER * 2 + _th + + buttonHeight + fontHeight + ifont.getLineHeight() + 20, max_w, max_h); // The tab widget @@ -182,6 +184,7 @@ GameInfoDialog::GameInfoDialog( tabID = myTab->addTab("Controller"); ctrls.clear(); + VarList::push_back(ctrls, "Auto-detect", "AUTO"); VarList::push_back(ctrls, "Joystick", "JOYSTICK"); VarList::push_back(ctrls, "Paddles", "PADDLES"); VarList::push_back(ctrls, "Paddles_IAxis", "PADDLES_IAXIS"); @@ -204,24 +207,32 @@ GameInfoDialog::GameInfoDialog( myP0Controller = new PopUpWidget(myTab, font, myP0Label->getRight(), myP0Label->getTop()-1, pwidth, lineHeight, ctrls, "", 0, kLeftCChanged); wid.push_back(myP0Controller); - ypos += lineHeight + VGAP; + + myP0ControllerDetected = new StaticTextWidget(myTab, ifont, myP0Controller->getLeft(), ypos, + "BoosterGrip detected"); + wid.push_back(myP0ControllerDetected); + ypos += ifont.getLineHeight() + VGAP; + myP1Label = new StaticTextWidget(myTab, font, HBORDER, ypos+1, "P1 controller "); myP1Controller = new PopUpWidget(myTab, font, myP1Label->getRight(), myP1Label->getTop()-1, pwidth, lineHeight, ctrls, "", 0, kRightCChanged); wid.push_back(myP1Controller); + ypos += lineHeight + VGAP; + myP1ControllerDetected = new StaticTextWidget(myTab, ifont, myP1Controller->getLeft(), ypos, + "BoosterGrip detected"); + wid.push_back(myP0ControllerDetected); + ypos += ifont.getLineHeight() + VGAP + 4; - //ypos += lineHeight + VGAP; mySwapPorts = new CheckboxWidget(myTab, font, myP0Controller->getRight() + fontWidth*4, myP0Controller->getTop()+1, "Swap ports"); wid.push_back(mySwapPorts); - //ypos += lineHeight + VGAP; mySwapPaddles = new CheckboxWidget(myTab, font, myP1Controller->getRight() + fontWidth*4, myP1Controller->getTop()+1, "Swap paddles"); wid.push_back(mySwapPaddles); // EEPROM erase button for P0/P1 - ypos += lineHeight + VGAP + 4; + //ypos += lineHeight + VGAP + 4; pwidth = myP1Controller->getWidth(); //font.getStringWidth("Erase EEPROM ") + 23; myEraseEEPROMLabel = new StaticTextWidget(myTab, font, HBORDER, ypos, "AtariVox/SaveKey "); myEraseEEPROMButton = new ButtonWidget(myTab, font, myEraseEEPROMLabel->getRight(), ypos - 4, @@ -405,8 +416,22 @@ void GameInfoDialog::loadConsoleProperties(const Properties& props) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::loadControllerProperties(const Properties& props) { - myP0Controller->setSelected(props.get(Controller_Left), "JOYSTICK"); - myP1Controller->setSelected(props.get(Controller_Right), "JOYSTICK"); + myP0Controller->setSelected(props.get(Controller_Left), "AUTO"); + if(instance().hasConsole() && myP0Controller->getSelectedTag().toString() == "AUTO") + { + myP0ControllerDetected->setLabel(instance().console().leftController().name() + " detected"); + } + else + myP0ControllerDetected->setLabel(""); + + myP1Controller->setSelected(props.get(Controller_Right), "AUTO"); + if(instance().hasConsole() && myP1Controller->getSelectedTag().toString() == "AUTO") + { + myP1ControllerDetected->setLabel(instance().console().rightController().name() + " detected"); + } + else + myP1ControllerDetected->setLabel(""); + mySwapPorts->setState(props.get(Console_SwapPorts) == "YES"); mySwapPaddles->setState(props.get(Controller_SwapPaddles) == "YES"); diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index 8a6f67811..5d5d25b20 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -78,7 +78,9 @@ class GameInfoDialog : public Dialog, public CommandSender StaticTextWidget* myP0Label; StaticTextWidget* myP1Label; PopUpWidget* myP0Controller; + StaticTextWidget* myP0ControllerDetected; PopUpWidget* myP1Controller; + StaticTextWidget* myP1ControllerDetected; CheckboxWidget* mySwapPorts; CheckboxWidget* mySwapPaddles; StaticTextWidget* myEraseEEPROMLabel;