mirror of https://github.com/stella-emu/stella.git
improved controller detection and added Genesis
adapted GameInfoDialog to controller detection moved detection from OSystem to Console
This commit is contained in:
parent
854a891a36
commit
a4456e6af8
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Controller> leftC = getControllerPort(rommd5, left, Controller::Left),
|
||||
rightC = getControllerPort(rommd5, right, Controller::Right);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Console> 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<Console> 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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue