mirror of https://github.com/stella-emu/stella.git
809 lines
30 KiB
C++
809 lines
30 KiB
C++
//============================================================================
|
|
//
|
|
// 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 "Bankswitch.hxx"
|
|
#include "Console.hxx"
|
|
#include "Cart.hxx"
|
|
#include "MouseControl.hxx"
|
|
#include "SaveKey.hxx"
|
|
#include "Dialog.hxx"
|
|
#include "EditTextWidget.hxx"
|
|
#include "RadioButtonWidget.hxx"
|
|
#include "Launcher.hxx"
|
|
#include "OSystem.hxx"
|
|
#include "CartDetector.hxx"
|
|
#include "ControllerDetector.hxx"
|
|
#include "PopUpWidget.hxx"
|
|
#include "Props.hxx"
|
|
#include "PropsSet.hxx"
|
|
#include "TabWidget.hxx"
|
|
#include "TIAConstants.hxx"
|
|
#include "Widget.hxx"
|
|
#include "Font.hxx"
|
|
|
|
#include "FrameBuffer.hxx"
|
|
#include "TIASurface.hxx"
|
|
#include "TIA.hxx"
|
|
#include "Switches.hxx"
|
|
#include "AudioSettings.hxx"
|
|
|
|
#include "GameInfoDialog.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
GameInfoDialog::GameInfoDialog(
|
|
OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
|
|
GuiObject* boss, int max_w, int max_h)
|
|
: Dialog(osystem, parent, font, "Game properties"),
|
|
CommandSender(boss)
|
|
{
|
|
const GUI::Font& ifont = instance().frameBuffer().infoFont();
|
|
const int lineHeight = font.getLineHeight(),
|
|
fontWidth = font.getMaxCharWidth(),
|
|
fontHeight = font.getFontHeight(),
|
|
buttonHeight = font.getLineHeight() + 4,
|
|
infoLineHeight = ifont.getLineHeight();
|
|
const int VBORDER = 8;
|
|
const int HBORDER = 10;
|
|
const int VGAP = 4;
|
|
|
|
int xpos, ypos, lwidth, fwidth, pwidth, tabID;
|
|
WidgetArray wid;
|
|
VariantList items, ports, ctrls;
|
|
StaticTextWidget* t;
|
|
|
|
// Set real dimensions
|
|
setSize(53 * fontWidth + 8,
|
|
8 * (lineHeight + VGAP) + 1 * (infoLineHeight + VGAP) + VBORDER * 2 + _th +
|
|
buttonHeight + fontHeight + ifont.getLineHeight() + 20,
|
|
max_w, max_h);
|
|
|
|
// The tab widget
|
|
myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2 * 2,
|
|
_h - (_th + buttonHeight + 20));
|
|
addTabWidget(myTab);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// 1) Emulation properties
|
|
tabID = myTab->addTab("Emulation");
|
|
|
|
ypos = VBORDER;
|
|
|
|
t = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "Type (*) ");
|
|
pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)");
|
|
items.clear();
|
|
for(uInt32 i = 0; i < uInt32(Bankswitch::Type::NumSchemes); ++i)
|
|
VarList::push_back(items, Bankswitch::BSList[i].desc, Bankswitch::BSList[i].name);
|
|
myBSType = new PopUpWidget(myTab, font, t->getRight() + 8, ypos,
|
|
pwidth, lineHeight, items, "");
|
|
wid.push_back(myBSType);
|
|
ypos += lineHeight + VGAP;
|
|
|
|
myTypeDetected = new StaticTextWidget(myTab, ifont, t->getRight() + 8, ypos,
|
|
"CM (SpectraVideo CompuMate) detected");
|
|
ypos += ifont.getLineHeight() + VGAP;
|
|
|
|
// Start bank
|
|
myStartBankLabel = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "Start bank (*) ");
|
|
items.clear();
|
|
myStartBank = new PopUpWidget(myTab, font, myStartBankLabel->getRight(), ypos,
|
|
font.getStringWidth("AUTO"), lineHeight, items, "", 0, 0);
|
|
wid.push_back(myStartBank);
|
|
ypos += lineHeight + VGAP * 4;
|
|
|
|
pwidth = font.getStringWidth("Auto-detect");
|
|
t = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "TV format ");
|
|
items.clear();
|
|
VarList::push_back(items, "Auto-detect", "AUTO");
|
|
VarList::push_back(items, "NTSC", "NTSC");
|
|
VarList::push_back(items, "PAL", "PAL");
|
|
VarList::push_back(items, "SECAM", "SECAM");
|
|
VarList::push_back(items, "NTSC50", "NTSC50");
|
|
VarList::push_back(items, "PAL60", "PAL60");
|
|
VarList::push_back(items, "SECAM60", "SECAM60");
|
|
myFormat = new PopUpWidget(myTab, font, t->getRight(), ypos,
|
|
pwidth, lineHeight, items, "", 0, 0);
|
|
wid.push_back(myFormat);
|
|
|
|
myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + 8, ypos + 4, "SECAM60 detected");
|
|
|
|
|
|
// Phosphor
|
|
ypos += lineHeight + VGAP;
|
|
myPhosphor = new CheckboxWidget(myTab, font, HBORDER, ypos + 1, "Phosphor (enabled for all ROMs)", kPhosphorChanged);
|
|
wid.push_back(myPhosphor);
|
|
|
|
ypos += lineHeight + VGAP * 0;
|
|
myPPBlend = new SliderWidget(myTab, font,
|
|
HBORDER + 20, ypos,
|
|
"Blend ", 0, kPPBlendChanged, 4 * fontWidth, "%");
|
|
myPPBlend->setMinValue(0); myPPBlend->setMaxValue(100);
|
|
myPPBlend->setTickmarkIntervals(2);
|
|
wid.push_back(myPPBlend);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
t = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "V-Center ");
|
|
myVCenter = new SliderWidget(myTab, font, t->getRight() + 2, ypos,
|
|
"", 0, kVCenterChanged, 7 * fontWidth, "px");
|
|
|
|
myVCenter->setMinValue(TIAConstants::minVcenter);
|
|
myVCenter->setMaxValue(TIAConstants::maxVcenter);
|
|
myVCenter->setTickmarkIntervals(4);
|
|
wid.push_back(myVCenter);
|
|
|
|
ypos += lineHeight + VGAP * 3;
|
|
mySound = new CheckboxWidget(myTab, font, HBORDER, ypos + 1, "Stereo sound");
|
|
wid.push_back(mySound);
|
|
|
|
// Add message concerning usage
|
|
ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10;
|
|
new StaticTextWidget(myTab, ifont, HBORDER, ypos,
|
|
"(*) Changes require a ROM reload");
|
|
|
|
// Add items for tab 0
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// 2) Console properties
|
|
wid.clear();
|
|
tabID = myTab->addTab("Console");
|
|
|
|
xpos = HBORDER; ypos = VBORDER;
|
|
lwidth = font.getStringWidth(GUI::RIGHT_DIFFICULTY + " ");
|
|
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, "TV type");
|
|
myTVTypeGroup = new RadioButtonGroup();
|
|
RadioButtonWidget* r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"Color", myTVTypeGroup);
|
|
wid.push_back(r);
|
|
ypos += lineHeight;
|
|
r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"B/W", myTVTypeGroup);
|
|
wid.push_back(r);
|
|
ypos += lineHeight + VGAP * 2;
|
|
|
|
new StaticTextWidget(myTab, font, xpos, ypos+1, GUI::LEFT_DIFFICULTY);
|
|
myLeftDiffGroup = new RadioButtonGroup();
|
|
r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"A (Expert)", myLeftDiffGroup);
|
|
wid.push_back(r);
|
|
ypos += lineHeight;
|
|
r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"B (Novice)", myLeftDiffGroup);
|
|
wid.push_back(r);
|
|
ypos += lineHeight + VGAP * 2;
|
|
|
|
new StaticTextWidget(myTab, font, xpos, ypos+1, GUI::RIGHT_DIFFICULTY);
|
|
myRightDiffGroup = new RadioButtonGroup();
|
|
r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"A (Expert)", myRightDiffGroup);
|
|
wid.push_back(r);
|
|
ypos += lineHeight;
|
|
r = new RadioButtonWidget(myTab, font, xpos + lwidth, ypos + 1,
|
|
"B (Novice)", myRightDiffGroup);
|
|
wid.push_back(r);
|
|
|
|
// Add items for tab 1
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// 3) Controller properties
|
|
wid.clear();
|
|
tabID = myTab->addTab("Controllers");
|
|
|
|
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");
|
|
VarList::push_back(ctrls, "Paddles_IAxDr", "PADDLES_IAXDR");
|
|
VarList::push_back(ctrls, "BoosterGrip", "BOOSTERGRIP");
|
|
VarList::push_back(ctrls, "Driving", "DRIVING");
|
|
VarList::push_back(ctrls, "Keyboard", "KEYBOARD");
|
|
VarList::push_back(ctrls, "AmigaMouse", "AMIGAMOUSE");
|
|
VarList::push_back(ctrls, "AtariMouse", "ATARIMOUSE");
|
|
VarList::push_back(ctrls, "Trakball", "TRAKBALL");
|
|
VarList::push_back(ctrls, "AtariVox", "ATARIVOX");
|
|
VarList::push_back(ctrls, "SaveKey", "SAVEKEY");
|
|
VarList::push_back(ctrls, "Sega Genesis", "GENESIS");
|
|
VarList::push_back(ctrls, "KidVid", "KIDVID");
|
|
VarList::push_back(ctrls, "Lightgun", "LIGHTGUN");
|
|
VarList::push_back(ctrls, "MindLink", "MINDLINK");
|
|
|
|
ypos = VBORDER;
|
|
pwidth = font.getStringWidth("Paddles_IAxis");
|
|
myLeftPortLabel = new StaticTextWidget(myTab, font, HBORDER, ypos+1, "Left port ");
|
|
myLeftPort = new PopUpWidget(myTab, font, myLeftPortLabel->getRight(),
|
|
myLeftPortLabel->getTop()-1,
|
|
pwidth, lineHeight, ctrls, "", 0, kLeftCChanged);
|
|
wid.push_back(myLeftPort);
|
|
ypos += lineHeight + VGAP;
|
|
|
|
myLeftPortDetected = new StaticTextWidget(myTab, ifont, myLeftPort->getLeft(), ypos,
|
|
"Sega Genesis detected");
|
|
ypos += ifont.getLineHeight() + VGAP;
|
|
|
|
myRightPortLabel = new StaticTextWidget(myTab, font, HBORDER, ypos+1, "Right port ");
|
|
myRightPort = new PopUpWidget(myTab, font, myRightPortLabel->getRight(),
|
|
myRightPortLabel->getTop()-1,
|
|
pwidth, lineHeight, ctrls, "", 0, kRightCChanged);
|
|
wid.push_back(myRightPort);
|
|
ypos += lineHeight + VGAP;
|
|
myRightPortDetected = new StaticTextWidget(myTab, ifont, myRightPort->getLeft(), ypos,
|
|
"Sega Genesis detected");
|
|
ypos += ifont.getLineHeight() + VGAP + 4;
|
|
|
|
mySwapPorts = new CheckboxWidget(myTab, font, myLeftPort->getRight() + fontWidth*4,
|
|
myLeftPort->getTop()+1, "Swap ports");
|
|
wid.push_back(mySwapPorts);
|
|
mySwapPaddles = new CheckboxWidget(myTab, font, myRightPort->getRight() + fontWidth*4,
|
|
myRightPort->getTop()+1, "Swap paddles");
|
|
wid.push_back(mySwapPaddles);
|
|
|
|
// EEPROM erase button for left/right controller
|
|
//ypos += lineHeight + VGAP + 4;
|
|
pwidth = myRightPort->getWidth(); //font.getStringWidth("Erase EEPROM ") + 23;
|
|
myEraseEEPROMLabel = new StaticTextWidget(myTab, font, HBORDER, ypos, "AtariVox/SaveKey ");
|
|
myEraseEEPROMButton = new ButtonWidget(myTab, font, myEraseEEPROMLabel->getRight(), ypos - 4,
|
|
pwidth, buttonHeight, "Erase EEPROM", kEEButtonPressed);
|
|
wid.push_back(myEraseEEPROMButton);
|
|
myEraseEEPROMInfo = new StaticTextWidget(myTab, ifont, myEraseEEPROMButton->getRight() + 4,
|
|
myEraseEEPROMLabel->getTop() + 3, "(for this game only)");
|
|
|
|
ypos += lineHeight + VGAP * 4;
|
|
myMouseControl = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Specific mouse axes", kMCtrlChanged);
|
|
wid.push_back(myMouseControl);
|
|
|
|
// Mouse controller specific axis
|
|
pwidth = font.getStringWidth("MindLink 0");
|
|
items.clear();
|
|
VarList::push_back(items, "None", static_cast<uInt32>(MouseControl::Type::NoControl));
|
|
VarList::push_back(items, "Paddle 0", static_cast<uInt32>(MouseControl::Type::Paddle0));
|
|
VarList::push_back(items, "Paddle 1", static_cast<uInt32>(MouseControl::Type::Paddle1));
|
|
VarList::push_back(items, "Paddle 2", static_cast<uInt32>(MouseControl::Type::Paddle2));
|
|
VarList::push_back(items, "Paddle 3", static_cast<uInt32>(MouseControl::Type::Paddle3));
|
|
VarList::push_back(items, "Driving 0", static_cast<uInt32>(MouseControl::Type::Driving0));
|
|
VarList::push_back(items, "Driving 1", static_cast<uInt32>(MouseControl::Type::Driving1));
|
|
VarList::push_back(items, "MindLink 0", static_cast<uInt32>(MouseControl::Type::MindLink0));
|
|
VarList::push_back(items, "MindLink 1", static_cast<uInt32>(MouseControl::Type::MindLink1));
|
|
|
|
xpos += 20;
|
|
ypos += lineHeight + VGAP;
|
|
myMouseX = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items,
|
|
"X-Axis is ");
|
|
wid.push_back(myMouseX);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
myMouseY = new PopUpWidget(myTab, font, myMouseX->getLeft(), ypos, pwidth, lineHeight, items,
|
|
"Y-Axis is ");
|
|
wid.push_back(myMouseY);
|
|
|
|
xpos = HBORDER; ypos += lineHeight + VGAP;
|
|
myMouseRange = new SliderWidget(myTab, font, HBORDER, ypos,
|
|
"Mouse axes range ", 0, 0, fontWidth * 4, "%");
|
|
myMouseRange->setMinValue(1); myMouseRange->setMaxValue(100);
|
|
myMouseRange->setTickmarkIntervals(4);
|
|
wid.push_back(myMouseRange);
|
|
|
|
// Add items for tab 2
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// 4) Cartridge properties
|
|
wid.clear();
|
|
tabID = myTab->addTab("Cartridge");
|
|
|
|
xpos = HBORDER; ypos = VBORDER;
|
|
lwidth = font.getStringWidth("Manufacturer ");
|
|
fwidth = _w - lwidth - HBORDER * 2 - 2;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Name");
|
|
myName = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
wid.push_back(myName);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "MD5");
|
|
myMD5 = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
myMD5->setEditable(false);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Manufacturer");
|
|
myManufacturer = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
wid.push_back(myManufacturer);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight,
|
|
"Model", TextAlign::Left);
|
|
myModelNo = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
wid.push_back(myModelNo);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Rarity");
|
|
myRarity = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
wid.push_back(myRarity);
|
|
|
|
ypos += lineHeight + VGAP;
|
|
new StaticTextWidget(myTab, font, xpos, ypos + 1, lwidth, fontHeight, "Note");
|
|
myNote = new EditTextWidget(myTab, font, xpos + lwidth, ypos - 1,
|
|
fwidth, lineHeight, "");
|
|
wid.push_back(myNote);
|
|
|
|
// Add items for tab 3
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
// Activate the first tab
|
|
myTab->setActiveTab(0);
|
|
|
|
// Add Defaults, OK and Cancel buttons
|
|
wid.clear();
|
|
addDefaultsOKCancelBGroup(wid, font);
|
|
addBGroupToFocusList(wid);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::loadConfig()
|
|
{
|
|
if(instance().hasConsole())
|
|
{
|
|
myGameProperties = instance().console().properties();
|
|
}
|
|
else
|
|
{
|
|
const string& md5 = instance().launcher().selectedRomMD5();
|
|
instance().propSet().getMD5(md5, myGameProperties);
|
|
}
|
|
|
|
loadEmulationProperties(myGameProperties);
|
|
loadConsoleProperties(myGameProperties);
|
|
loadControllerProperties(myGameProperties);
|
|
loadCartridgeProperties(myGameProperties);
|
|
|
|
myTab->loadConfig();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::loadEmulationProperties(const Properties& props)
|
|
{
|
|
string bsDetected = "";
|
|
|
|
myBSType->setSelected(props.get(PropType::Cart_Type), "AUTO");
|
|
if(myBSType->getSelectedTag().toString() == "AUTO")
|
|
{
|
|
if(instance().hasConsole())
|
|
{
|
|
string bs = instance().console().about().BankSwitch;
|
|
size_t pos = bs.find_first_of('*');
|
|
// remove '*':
|
|
if(pos != string::npos)
|
|
bs = bs.substr(0, pos) + bs.substr(pos + 1);
|
|
bsDetected = bs + "detected";
|
|
}
|
|
else
|
|
{
|
|
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
|
|
ByteBuffer image;
|
|
string md5 = props.get(PropType::Cart_MD5);
|
|
size_t size = 0;
|
|
|
|
// try to load the image for auto detection
|
|
if(!instance().hasConsole() &&
|
|
node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr)
|
|
{
|
|
bsDetected = Bankswitch::typeToDesc(CartDetector::autodetectType(image, size)) + " detected";
|
|
}
|
|
}
|
|
}
|
|
myTypeDetected->setLabel(bsDetected);
|
|
|
|
// Start bank
|
|
VariantList items;
|
|
|
|
VarList::push_back(items, "Auto", "AUTO");
|
|
if(instance().hasConsole())
|
|
{
|
|
uInt16 numBanks = instance().console().cartridge().bankCount();
|
|
|
|
for(uInt16 i = 0; i < numBanks; ++i)
|
|
VarList::push_back(items, i, i);
|
|
myStartBank->setEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
const string& startBank = props.get(PropType::Cart_StartBank);
|
|
|
|
VarList::push_back(items, startBank, startBank);
|
|
myStartBank->setEnabled(false);
|
|
}
|
|
myStartBank->addItems(items);
|
|
myStartBank->setSelected(props.get(PropType::Cart_StartBank), "AUTO");
|
|
|
|
myFormat->setSelected(props.get(PropType::Display_Format), "AUTO");
|
|
if(instance().hasConsole() && myFormat->getSelectedTag().toString() == "AUTO")
|
|
{
|
|
const string& format = instance().console().about().DisplayFormat;
|
|
string label = format.substr(0, format.length() - 1);
|
|
myFormatDetected->setLabel(label + " detected");
|
|
}
|
|
else
|
|
myFormatDetected->setLabel("");
|
|
|
|
// if phosphor is always enabled, disable game specific phosphor settings
|
|
bool alwaysPhosphor = instance().settings().getString("tv.phosphor") == "always";
|
|
bool usePhosphor = props.get(PropType::Display_Phosphor) == "YES";
|
|
myPhosphor->setState(usePhosphor);
|
|
myPhosphor->setEnabled(!alwaysPhosphor);
|
|
if (alwaysPhosphor)
|
|
myPhosphor->setLabel("Phosphor (enabled for all ROMs)");
|
|
else
|
|
myPhosphor->setLabel("Phosphor");
|
|
myPPBlend->setEnabled(!alwaysPhosphor && usePhosphor);
|
|
|
|
const string& blend = props.get(PropType::Display_PPBlend);
|
|
myPPBlend->setValue(stoi(blend));
|
|
|
|
// set vertical center
|
|
Int32 vcenter = stoi(props.get(PropType::Display_VCenter));
|
|
myVCenter->setValueLabel(vcenter);
|
|
myVCenter->setValue(vcenter);
|
|
myVCenter->setValueUnit(vcenter ? "px" : "");
|
|
|
|
mySound->setState(props.get(PropType::Cart_Sound) == "STEREO");
|
|
// if stereo is always enabled, disable game specific stereo setting
|
|
mySound->setEnabled(!instance().audioSettings().stereo());
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::loadConsoleProperties(const Properties& props)
|
|
{
|
|
myLeftDiffGroup->setSelected(props.get(PropType::Console_LeftDiff) == "A" ? 0 : 1);
|
|
myRightDiffGroup->setSelected(props.get(PropType::Console_RightDiff) == "A" ? 0 : 1);
|
|
myTVTypeGroup->setSelected(props.get(PropType::Console_TVType) == "BW" ? 1 : 0);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::loadControllerProperties(const Properties& props)
|
|
{
|
|
string controller = props.get(PropType::Controller_Left);
|
|
myLeftPort->setSelected(controller, "AUTO");
|
|
controller = props.get(PropType::Controller_Right);
|
|
myRightPort->setSelected(controller, "AUTO");
|
|
|
|
mySwapPorts->setState(props.get(PropType::Console_SwapPorts) == "YES");
|
|
mySwapPaddles->setState(props.get(PropType::Controller_SwapPaddles) == "YES");
|
|
|
|
// MouseAxis property (potentially contains 'range' information)
|
|
istringstream m_axis(props.get(PropType::Controller_MouseAxis));
|
|
string m_control, m_range;
|
|
m_axis >> m_control;
|
|
bool autoAxis = BSPF::equalsIgnoreCase(m_control, "AUTO");
|
|
myMouseControl->setState(!autoAxis);
|
|
if(autoAxis)
|
|
{
|
|
myMouseX->setSelectedIndex(0);
|
|
myMouseY->setSelectedIndex(0);
|
|
}
|
|
else
|
|
{
|
|
myMouseX->setSelected(m_control[0] - '0');
|
|
myMouseY->setSelected(m_control[1] - '0');
|
|
}
|
|
myMouseX->setEnabled(!autoAxis);
|
|
myMouseY->setEnabled(!autoAxis);
|
|
if(m_axis >> m_range)
|
|
{
|
|
myMouseRange->setValue(stoi(m_range));
|
|
}
|
|
else
|
|
{
|
|
myMouseRange->setValue(100);
|
|
}
|
|
|
|
updateControllerStates();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::loadCartridgeProperties(const Properties& props)
|
|
{
|
|
myName->setText(props.get(PropType::Cart_Name));
|
|
myMD5->setText(props.get(PropType::Cart_MD5));
|
|
myManufacturer->setText(props.get(PropType::Cart_Manufacturer));
|
|
myModelNo->setText(props.get(PropType::Cart_ModelNo));
|
|
myRarity->setText(props.get(PropType::Cart_Rarity));
|
|
myNote->setText(props.get(PropType::Cart_Note));
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::saveConfig()
|
|
{
|
|
// Emulation properties
|
|
myGameProperties.set(PropType::Cart_Type, myBSType->getSelectedTag().toString());
|
|
myGameProperties.set(PropType::Cart_StartBank, myStartBank->getSelectedTag().toString());
|
|
myGameProperties.set(PropType::Display_Format, myFormat->getSelectedTag().toString());
|
|
myGameProperties.set(PropType::Display_Phosphor, myPhosphor->getState() ? "YES" : "NO");
|
|
myGameProperties.set(PropType::Display_PPBlend, myPPBlend->getValueLabel() == "Off" ? "0" :
|
|
myPPBlend->getValueLabel());
|
|
Int32 vcenter = myVCenter->getValue();
|
|
|
|
myGameProperties.set(PropType::Display_VCenter, std::to_string(vcenter));
|
|
myGameProperties.set(PropType::Cart_Sound, mySound->getState() ? "STEREO" : "MONO");
|
|
|
|
// Console properties
|
|
myGameProperties.set(PropType::Console_TVType, myTVTypeGroup->getSelected() ? "BW" : "COLOR");
|
|
myGameProperties.set(PropType::Console_LeftDiff, myLeftDiffGroup->getSelected() ? "B" : "A");
|
|
myGameProperties.set(PropType::Console_RightDiff, myRightDiffGroup->getSelected() ? "B" : "A");
|
|
|
|
// Controller properties
|
|
myGameProperties.set(PropType::Controller_Left, myLeftPort->getSelectedTag().toString());
|
|
myGameProperties.set(PropType::Controller_Right, myRightPort->getSelectedTag().toString());
|
|
myGameProperties.set(PropType::Console_SwapPorts, (mySwapPorts->isEnabled() && mySwapPorts->getState()) ? "YES" : "NO");
|
|
myGameProperties.set(PropType::Controller_SwapPaddles, (/*mySwapPaddles->isEnabled() &&*/ mySwapPaddles->getState()) ? "YES" : "NO");
|
|
|
|
// MouseAxis property (potentially contains 'range' information)
|
|
string mcontrol = "AUTO";
|
|
if(myMouseControl->getState())
|
|
mcontrol = myMouseX->getSelectedTag().toString() +
|
|
myMouseY->getSelectedTag().toString();
|
|
string range = myMouseRange->getValueLabel();
|
|
if(range != "100")
|
|
mcontrol += " " + range;
|
|
myGameProperties.set(PropType::Controller_MouseAxis, mcontrol);
|
|
|
|
// Cartridge properties
|
|
myGameProperties.set(PropType::Cart_Name, myName->getText());
|
|
myGameProperties.set(PropType::Cart_Manufacturer, myManufacturer->getText());
|
|
myGameProperties.set(PropType::Cart_ModelNo, myModelNo->getText());
|
|
myGameProperties.set(PropType::Cart_Rarity, myRarity->getText());
|
|
myGameProperties.set(PropType::Cart_Note, myNote->getText());
|
|
|
|
// Always insert; if the properties are already present, nothing will happen
|
|
instance().propSet().insert(myGameProperties);
|
|
instance().saveConfig();
|
|
|
|
// In any event, inform the Console
|
|
if(instance().hasConsole())
|
|
{
|
|
instance().console().setProperties(myGameProperties);
|
|
|
|
// update 'Emulation' tab settings immediately
|
|
instance().console().setFormat(myFormat->getSelected());
|
|
instance().frameBuffer().tiaSurface().enablePhosphor(myPhosphor->getState(), myPPBlend->getValue());
|
|
instance().console().updateVcenter(vcenter);
|
|
instance().console().initializeAudio();
|
|
|
|
// update 'Console' tab settings immediately
|
|
instance().console().switches().setTvColor(myTVTypeGroup->getSelected() == 0);
|
|
instance().console().switches().setLeftDifficultyA(myLeftDiffGroup->getSelected() == 0);
|
|
instance().console().switches().setRightDifficultyA(myRightDiffGroup->getSelected() == 0);
|
|
|
|
// update 'Controllers' tab settings immediately
|
|
instance().console().setControllers(myGameProperties.get(PropType::Cart_MD5));
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::setDefaults()
|
|
{
|
|
// Load the default properties
|
|
Properties defaultProperties;
|
|
const string& md5 = myGameProperties.get(PropType::Cart_MD5);
|
|
|
|
instance().propSet().getMD5(md5, defaultProperties, true);
|
|
|
|
switch(myTab->getActiveTab())
|
|
{
|
|
case 0: // Emulation properties
|
|
loadEmulationProperties(defaultProperties);
|
|
break;
|
|
|
|
case 1: // Console properties
|
|
loadConsoleProperties(defaultProperties);
|
|
break;
|
|
|
|
case 2: // Controller properties
|
|
loadControllerProperties(defaultProperties);
|
|
break;
|
|
|
|
case 3: // Cartridge properties
|
|
loadCartridgeProperties(defaultProperties);
|
|
break;
|
|
|
|
default: // make the compiler happy
|
|
break;
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::updateControllerStates()
|
|
{
|
|
bool swapPorts = mySwapPorts->getState();
|
|
bool autoDetect = false;
|
|
ByteBuffer image;
|
|
string md5 = myGameProperties.get(PropType::Cart_MD5);
|
|
size_t size = 0;
|
|
|
|
// try to load the image for auto detection
|
|
if(!instance().hasConsole())
|
|
{
|
|
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
|
|
|
|
autoDetect = node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr;
|
|
}
|
|
string label = "";
|
|
Controller::Type type = Controller::getType(myLeftPort->getSelectedTag().toString());
|
|
|
|
if(type == Controller::Type::Unknown)
|
|
{
|
|
if(instance().hasConsole())
|
|
label = (!swapPorts ? instance().console().leftController().name()
|
|
: instance().console().rightController().name()) + " detected";
|
|
else if(autoDetect)
|
|
label = ControllerDetector::detectName(image.get(), size, type,
|
|
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
|
|
instance().settings()) + " detected";
|
|
}
|
|
myLeftPortDetected->setLabel(label);
|
|
|
|
label = "";
|
|
type = Controller::getType(myRightPort->getSelectedTag().toString());
|
|
|
|
if(type == Controller::Type::Unknown)
|
|
{
|
|
if(instance().hasConsole())
|
|
label = (!swapPorts ? instance().console().rightController().name()
|
|
: instance().console().leftController().name()) + " detected";
|
|
else if(autoDetect)
|
|
label = ControllerDetector::detectName(image.get(), size, type,
|
|
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
|
|
instance().settings()) + " detected";
|
|
}
|
|
myRightPortDetected->setLabel(label);
|
|
|
|
const string& contrLeft = myLeftPort->getSelectedTag().toString();
|
|
const string& contrRight = myRightPort->getSelectedTag().toString();
|
|
bool enableEEEraseButton = false;
|
|
|
|
// Compumate bankswitching scheme doesn't allow to select controllers
|
|
bool enableSelectControl = myBSType->getSelectedTag() != "CM";
|
|
// Enable Swap Paddles checkbox only for paddle games
|
|
bool enableSwapPaddles = BSPF::startsWithIgnoreCase(contrLeft, "PADDLES") ||
|
|
BSPF::startsWithIgnoreCase(contrRight, "PADDLES") ||
|
|
BSPF::startsWithIgnoreCase(myLeftPortDetected->getLabel(), "Paddles") ||
|
|
BSPF::startsWithIgnoreCase(myRightPortDetected->getLabel(), "Paddles");
|
|
|
|
if(instance().hasConsole())
|
|
{
|
|
const Controller& lport = instance().console().leftController();
|
|
const Controller& rport = instance().console().rightController();
|
|
|
|
// we only enable the button if we have a valid previous and new controller.
|
|
bool enableBtnForLeft =
|
|
(contrLeft == "AUTO" || contrLeft == "SAVEKEY" || contrLeft == "ATARIVOX") &&
|
|
(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox);
|
|
bool enableBtnForRight =
|
|
(contrRight == "AUTO" || contrRight == "SAVEKEY" || contrRight == "ATARIVOX") &&
|
|
(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox);
|
|
enableEEEraseButton = enableBtnForLeft || enableBtnForRight;
|
|
}
|
|
|
|
myLeftPortLabel->setEnabled(enableSelectControl);
|
|
myRightPortLabel->setEnabled(enableSelectControl);
|
|
myLeftPort->setEnabled(enableSelectControl);
|
|
myRightPort->setEnabled(enableSelectControl);
|
|
|
|
mySwapPorts->setEnabled(enableSelectControl);
|
|
mySwapPaddles->setEnabled(enableSwapPaddles);
|
|
|
|
myEraseEEPROMLabel->setEnabled(enableEEEraseButton);
|
|
myEraseEEPROMButton->setEnabled(enableEEEraseButton);
|
|
myEraseEEPROMInfo->setEnabled(enableEEEraseButton);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::eraseEEPROM()
|
|
{
|
|
Controller& lport = instance().console().leftController();
|
|
Controller& rport = instance().console().rightController();
|
|
|
|
if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox)
|
|
{
|
|
SaveKey& skey = static_cast<SaveKey&>(lport);
|
|
skey.eraseCurrent();
|
|
}
|
|
|
|
if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox)
|
|
{
|
|
SaveKey& skey = static_cast<SaveKey&>(rport);
|
|
skey.eraseCurrent();
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
|
|
int data, int id)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case GuiObject::kOKCmd:
|
|
saveConfig();
|
|
close();
|
|
break;
|
|
|
|
case GuiObject::kDefaultsCmd:
|
|
setDefaults();
|
|
break;
|
|
|
|
case TabWidget::kTabChangedCmd:
|
|
if(data == 2) // 'Controllers' tab selected
|
|
updateControllerStates();
|
|
|
|
// The underlying dialog still needs access to this command
|
|
Dialog::handleCommand(sender, cmd, data, 0);
|
|
break;
|
|
|
|
case kLeftCChanged:
|
|
case kRightCChanged:
|
|
updateControllerStates();
|
|
break;
|
|
|
|
case kEEButtonPressed:
|
|
eraseEEPROM();
|
|
break;
|
|
|
|
case kPhosphorChanged:
|
|
{
|
|
bool status = myPhosphor->getState();
|
|
myPPBlend->setEnabled(status);
|
|
break;
|
|
}
|
|
|
|
case kPPBlendChanged:
|
|
if(myPPBlend->getValue() == 0)
|
|
{
|
|
myPPBlend->setValueLabel("Off");
|
|
myPPBlend->setValueUnit("");
|
|
}
|
|
else
|
|
myPPBlend->setValueUnit("%");
|
|
break;
|
|
|
|
case kVCenterChanged:
|
|
if (myVCenter->getValue() == 0)
|
|
{
|
|
myVCenter->setValueLabel("Default");
|
|
myVCenter->setValueUnit("");
|
|
}
|
|
else
|
|
myVCenter->setValueUnit("px");
|
|
break;
|
|
|
|
case kMCtrlChanged:
|
|
{
|
|
bool state = myMouseControl->getState();
|
|
myMouseX->setEnabled(state);
|
|
myMouseY->setEnabled(state);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Dialog::handleCommand(sender, cmd, data, 0);
|
|
break;
|
|
}
|
|
}
|