2019-12-01 18:40:28 +00:00
|
|
|
#include "options.h"
|
2017-11-21 16:10:58 +00:00
|
|
|
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "Common.h"
|
2019-12-31 18:19:45 +00:00
|
|
|
#include "CardManager.h"
|
2017-11-21 16:10:58 +00:00
|
|
|
#include "Applewin.h"
|
|
|
|
#include "Disk.h"
|
|
|
|
#include "Harddisk.h"
|
|
|
|
#include "Registry.h"
|
|
|
|
#include "SaveState.h"
|
|
|
|
#include "CPU.h"
|
2019-11-24 21:06:55 +00:00
|
|
|
#include "Video.h"
|
2017-11-21 16:10:58 +00:00
|
|
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QGamepad>
|
2019-11-30 15:48:48 +00:00
|
|
|
#include <QSettings>
|
2017-11-21 16:10:58 +00:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
const std::vector<size_t> diskIDs = {DRIVE_1, DRIVE_2};
|
|
|
|
const std::vector<size_t> hdIDs = {HARDDISK_1, HARDDISK_2};
|
|
|
|
|
2019-04-20 20:51:19 +01:00
|
|
|
const QString REG_SCREENSHOT_TEMPLATE = QString::fromUtf8("QApple/Screenshot Template");
|
2019-11-24 19:30:34 +00:00
|
|
|
const QString REG_SLOT0_CARD = QString::fromUtf8("QApple/Hardware/Slot 0");
|
|
|
|
const QString REG_RAMWORKS_SIZE = QString::fromUtf8("QApple/Hardware/RamWorks Size");
|
|
|
|
const QString REG_GAMEPAD_NAME = QString::fromUtf8("QApple/Hardware/Gamepad");
|
|
|
|
const QString REG_AUDIO_LATENCY = QString::fromUtf8("QApple/Audio/Latency");
|
|
|
|
const QString REG_SILENCE_DELAY = QString::fromUtf8("QApple/Audio/Silence Delay");
|
|
|
|
const QString REG_VOLUME = QString::fromUtf8("QApple/Audio/Volume");
|
|
|
|
const QString REG_TIMER = QString::fromUtf8("QApple/Emulator/Timer");
|
|
|
|
const QString REG_FULL_SPEED = QString::fromUtf8("QApple/Emulator/Full Speed");
|
2019-04-20 20:51:19 +01:00
|
|
|
|
2017-11-21 16:10:58 +00:00
|
|
|
void insertDisk(const QString & filename, const int disk)
|
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
if (g_CardMgr.QuerySlot(SLOT6) != CT_Disk2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Disk2InterfaceCard* pDisk2Card = dynamic_cast<Disk2InterfaceCard*>(g_CardMgr.GetObj(SLOT6));
|
2017-11-21 16:10:58 +00:00
|
|
|
if (filename.isEmpty())
|
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
pDisk2Card->EjectDisk(disk);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const bool createMissingDisk = true;
|
2019-12-31 18:19:45 +00:00
|
|
|
const ImageError_e result = pDisk2Card->InsertDisk(disk, filename.toStdString().c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, createMissingDisk);
|
2017-11-21 16:10:58 +00:00
|
|
|
if (result != eIMAGE_ERROR_NONE)
|
|
|
|
{
|
|
|
|
const QString message = QString("Error [%1] inserting '%2'").arg(QString::number(result), filename);
|
2019-11-13 21:00:43 +00:00
|
|
|
QMessageBox::warning(nullptr, "Disk error", message);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void insertHD(const QString & filename, const int disk)
|
|
|
|
{
|
|
|
|
if (filename.isEmpty())
|
|
|
|
{
|
|
|
|
HD_Unplug(disk);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-13 21:00:43 +00:00
|
|
|
if (!HD_Insert(disk, filename.toStdString()))
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
|
|
|
const QString message = QString("Error inserting '%1'").arg(filename);
|
2019-11-13 21:00:43 +00:00
|
|
|
QMessageBox::warning(nullptr, "Hard Disk error", message);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-31 18:19:45 +00:00
|
|
|
void SetSlot(UINT slot, SS_CARDTYPE newCardType)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
_ASSERT(slot < NUM_SLOTS);
|
|
|
|
if (slot >= NUM_SLOTS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Two paths:
|
|
|
|
// 1) Via Config dialog: card not inserted yet
|
|
|
|
// 2) Snapshot_LoadState_v2(): card already inserted
|
|
|
|
if (g_CardMgr.QuerySlot(slot) != newCardType)
|
|
|
|
g_CardMgr.Insert(slot, newCardType);
|
|
|
|
|
|
|
|
std::string slotText;
|
|
|
|
switch (slot)
|
|
|
|
{
|
|
|
|
case 0: slotText = REGVALUE_SLOT0; break;
|
|
|
|
case 1: slotText = REGVALUE_SLOT1; break;
|
|
|
|
case 2: slotText = REGVALUE_SLOT2; break;
|
|
|
|
case 3: slotText = REGVALUE_SLOT3; break;
|
|
|
|
case 4: slotText = REGVALUE_SLOT4; break;
|
|
|
|
case 5: slotText = REGVALUE_SLOT5; break;
|
|
|
|
case 6: slotText = REGVALUE_SLOT6; break;
|
|
|
|
case 7: slotText = REGVALUE_SLOT7; break;
|
|
|
|
}
|
2017-11-21 16:10:58 +00:00
|
|
|
|
2019-12-31 18:19:45 +00:00
|
|
|
REGSAVE(slotText.c_str(), (DWORD)newCardType);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
|
2020-04-13 16:46:41 +01:00
|
|
|
const std::vector<eApple2Type> computerTypes = {A2TYPE_APPLE2, A2TYPE_APPLE2PLUS, A2TYPE_APPLE2JPLUS, A2TYPE_APPLE2E,
|
|
|
|
A2TYPE_APPLE2EENHANCED, A2TYPE_PRAVETS82, A2TYPE_PRAVETS8M, A2TYPE_PRAVETS8A,
|
|
|
|
A2TYPE_TK30002E};
|
2017-11-21 16:10:58 +00:00
|
|
|
|
|
|
|
int getApple2ComputerType()
|
|
|
|
{
|
|
|
|
const eApple2Type type = GetApple2Type();
|
|
|
|
const auto it = std::find(computerTypes.begin(), computerTypes.end(), type);
|
|
|
|
if (it != computerTypes.end())
|
|
|
|
{
|
|
|
|
return std::distance(computerTypes.begin(), it);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// default to A2E
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GlobalOptions::GlobalOptions()
|
2019-12-01 18:40:28 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalOptions GlobalOptions::fromQSettings()
|
2019-11-24 19:30:34 +00:00
|
|
|
{
|
|
|
|
QSettings settings;
|
2019-12-01 18:40:28 +00:00
|
|
|
GlobalOptions options;
|
|
|
|
|
|
|
|
options.screenshotTemplate = settings.value(REG_SCREENSHOT_TEMPLATE, "/tmp/qapple_%1.png").toString();
|
|
|
|
options.gamepadName = settings.value(REG_GAMEPAD_NAME, QString()).toString();
|
|
|
|
options.slot0Card = settings.value(REG_SLOT0_CARD, 0).toInt();
|
|
|
|
options.ramWorksMemorySize = settings.value(REG_RAMWORKS_SIZE, 0).toInt();
|
|
|
|
|
|
|
|
options.msGap = settings.value(REG_TIMER, 5).toInt();
|
|
|
|
options.msFullSpeed = settings.value(REG_FULL_SPEED, 5).toInt();
|
|
|
|
options.audioLatency = settings.value(REG_AUDIO_LATENCY, 200).toInt();
|
|
|
|
options.silenceDelay = settings.value(REG_SILENCE_DELAY, 10000).toInt();
|
|
|
|
options.volume = settings.value(REG_VOLUME, 0x0fff).toInt();
|
|
|
|
|
|
|
|
return options;
|
2019-11-24 19:30:34 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
void GlobalOptions::setData(const GlobalOptions & data)
|
2019-11-24 19:30:34 +00:00
|
|
|
{
|
2019-12-01 18:58:32 +00:00
|
|
|
if (this->msGap != data.msGap)
|
|
|
|
{
|
|
|
|
this->msGap = data.msGap;
|
|
|
|
QSettings().setValue(REG_TIMER, this->msGap);
|
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
if (this->msFullSpeed != data.msFullSpeed)
|
2019-12-01 18:58:32 +00:00
|
|
|
{
|
2019-12-01 19:49:11 +00:00
|
|
|
this->msFullSpeed = data.msFullSpeed;
|
|
|
|
QSettings().setValue(REG_FULL_SPEED, this->msFullSpeed);
|
2019-12-01 18:58:32 +00:00
|
|
|
}
|
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
if (this->screenshotTemplate != data.screenshotTemplate)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 19:30:34 +00:00
|
|
|
this->screenshotTemplate = data.screenshotTemplate;
|
|
|
|
QSettings().setValue(REG_SCREENSHOT_TEMPLATE, this->screenshotTemplate);
|
2019-04-20 20:51:19 +01:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
if (this->slot0Card != data.slot0Card)
|
2019-04-20 20:51:19 +01:00
|
|
|
{
|
2019-12-01 19:49:11 +00:00
|
|
|
this->slot0Card = data.slot0Card;
|
2019-11-24 19:30:34 +00:00
|
|
|
QSettings().setValue(REG_SLOT0_CARD, this->slot0Card);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
if (this->ramWorksMemorySize != data.ramWorksMemorySize)
|
2019-04-22 16:02:06 +01:00
|
|
|
{
|
2019-12-01 19:49:11 +00:00
|
|
|
this->ramWorksMemorySize = data.ramWorksMemorySize;
|
2019-11-24 19:30:34 +00:00
|
|
|
QSettings().setValue(REG_RAMWORKS_SIZE, this->ramWorksMemorySize);
|
2019-04-22 16:02:06 +01:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
if (this->gamepadName != data.gamepadName)
|
2019-11-24 19:30:34 +00:00
|
|
|
{
|
2019-12-01 19:49:11 +00:00
|
|
|
this->gamepadName = data.gamepadName;
|
2019-11-24 19:30:34 +00:00
|
|
|
QSettings().setValue(REG_GAMEPAD_NAME, this->gamepadName);
|
|
|
|
}
|
2017-11-21 16:10:58 +00:00
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
if (this->audioLatency != data.audioLatency)
|
|
|
|
{
|
|
|
|
this->audioLatency = data.audioLatency;
|
|
|
|
QSettings().setValue(REG_AUDIO_LATENCY, this->audioLatency);
|
|
|
|
}
|
2017-11-21 16:10:58 +00:00
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
if (this->silenceDelay != data.silenceDelay)
|
|
|
|
{
|
|
|
|
this->silenceDelay = data.silenceDelay;
|
|
|
|
QSettings().setValue(REG_SILENCE_DELAY, this->silenceDelay);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->volume != data.volume)
|
|
|
|
{
|
|
|
|
this->volume = data.volume;
|
|
|
|
QSettings().setValue(REG_VOLUME, this->volume);
|
|
|
|
}
|
2019-04-20 20:51:19 +01:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
void getAppleWinPreferences(PreferenceData & data)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
Disk2InterfaceCard* pDisk2Card = dynamic_cast<Disk2InterfaceCard*>(g_CardMgr.GetObj(SLOT6));
|
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
data.disks.resize(diskIDs.size());
|
2017-11-21 16:10:58 +00:00
|
|
|
for (size_t i = 0; i < diskIDs.size(); ++i)
|
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
const std::string & diskName = pDisk2Card->GetFullName(diskIDs[i]);
|
2019-09-21 09:58:29 +01:00
|
|
|
if (!diskName.empty())
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 19:30:34 +00:00
|
|
|
data.disks[i] = QString::fromStdString(diskName);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
data.hds.resize(hdIDs.size());
|
2017-11-21 16:10:58 +00:00
|
|
|
for (size_t i = 0; i < hdIDs.size(); ++i)
|
|
|
|
{
|
2019-09-21 09:58:29 +01:00
|
|
|
const std::string & diskName = HD_GetFullName(hdIDs[i]);
|
|
|
|
if (!diskName.empty())
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 19:30:34 +00:00
|
|
|
data.hds[i] = QString::fromStdString(diskName);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-31 18:19:45 +00:00
|
|
|
data.enhancedSpeed = pDisk2Card->GetEnhanceDisk();
|
|
|
|
data.mouseInSlot4 = g_CardMgr.QuerySlot(SLOT4) == CT_MouseInterface;
|
|
|
|
data.cpmInSlot5 = g_CardMgr.QuerySlot(SLOT5) == CT_Z80;
|
2019-11-24 19:30:34 +00:00
|
|
|
data.hdInSlot7 = HD_CardIsEnabled();
|
2017-11-21 16:10:58 +00:00
|
|
|
|
2019-11-24 19:30:34 +00:00
|
|
|
data.apple2Type = getApple2ComputerType();
|
2017-11-21 16:10:58 +00:00
|
|
|
|
2019-09-21 09:58:29 +01:00
|
|
|
const std::string & saveState = Snapshot_GetFilename();
|
|
|
|
if (!saveState.empty())
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 19:30:34 +00:00
|
|
|
data.saveState = QString::fromStdString(saveState);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
2019-11-24 21:06:55 +00:00
|
|
|
|
|
|
|
data.videoType = GetVideoType();
|
|
|
|
data.scanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
|
|
|
data.verticalBlend = IsVideoStyle(VS_COLOR_VERTICAL_BLEND);
|
2019-12-02 20:50:51 +00:00
|
|
|
data.hz50 = GetVideoRefreshRate() == VR_50HZ;
|
2019-12-05 21:37:39 +00:00
|
|
|
data.monochromeColor.setRgb(g_nMonochromeRGB);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:49:11 +00:00
|
|
|
void setAppleWinPreferences(const PreferenceData & currentData, const PreferenceData & newData)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-12-31 18:19:45 +00:00
|
|
|
Disk2InterfaceCard* pDisk2Card = dynamic_cast<Disk2InterfaceCard*>(g_CardMgr.GetObj(SLOT6));
|
|
|
|
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.apple2Type != newData.apple2Type)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
const eApple2Type type = computerTypes[newData.apple2Type];
|
2017-11-21 16:10:58 +00:00
|
|
|
SetApple2Type(type);
|
|
|
|
REGSAVE(TEXT(REGVALUE_APPLE2_TYPE), type);
|
|
|
|
const eCpuType cpu = ProbeMainCpuDefault(type);
|
|
|
|
SetMainCpu(cpu);
|
|
|
|
REGSAVE(TEXT(REGVALUE_CPU_TYPE), cpu);
|
|
|
|
}
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.mouseInSlot4 != newData.mouseInSlot4)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
const SS_CARDTYPE card = newData.mouseInSlot4 ? CT_MouseInterface : CT_Empty;
|
2019-12-31 18:19:45 +00:00
|
|
|
SetSlot(SLOT4, card);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.cpmInSlot5 != newData.cpmInSlot5)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
const SS_CARDTYPE card = newData.cpmInSlot5 ? CT_Z80 : CT_Empty;
|
2019-12-31 18:19:45 +00:00
|
|
|
SetSlot(SLOT5, card);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.hdInSlot7 != newData.hdInSlot7)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
REGSAVE(TEXT(REGVALUE_HDD_ENABLED), newData.hdInSlot7 ? 1 : 0);
|
|
|
|
HD_SetEnabled(newData.hdInSlot7);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.enhancedSpeed != newData.enhancedSpeed)
|
2019-04-20 16:43:47 +01:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
REGSAVE(TEXT(REGVALUE_ENHANCE_DISK_SPEED), newData.enhancedSpeed ? 1 : 0);
|
2019-12-31 18:19:45 +00:00
|
|
|
pDisk2Card->SetEnhanceDisk(newData.enhancedSpeed);
|
2019-04-20 16:43:47 +01:00
|
|
|
}
|
|
|
|
|
2017-11-21 16:10:58 +00:00
|
|
|
for (size_t i = 0; i < diskIDs.size(); ++i)
|
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.disks[i] != newData.disks[i])
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
insertDisk(newData.disks[i], diskIDs[i]);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < hdIDs.size(); ++i)
|
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.hds[i] != newData.hds[i])
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
insertHD(newData.hds[i], hdIDs[i]);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-24 17:43:43 +00:00
|
|
|
if (currentData.saveState != newData.saveState)
|
2017-11-21 16:10:58 +00:00
|
|
|
{
|
2019-11-24 17:43:43 +00:00
|
|
|
const std::string name = newData.saveState.toStdString();
|
2017-11-21 16:10:58 +00:00
|
|
|
Snapshot_SetFilename(name);
|
2019-09-21 09:58:29 +01:00
|
|
|
RegSaveString(TEXT(REG_CONFIG), REGVALUE_SAVESTATE_FILENAME, 1, name);
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|
2019-11-24 21:06:55 +00:00
|
|
|
|
2019-12-02 20:50:51 +00:00
|
|
|
if (currentData.videoType != newData.videoType || currentData.scanLines != newData.scanLines || currentData.verticalBlend != newData.verticalBlend
|
2019-12-05 21:37:39 +00:00
|
|
|
|| currentData.hz50 != newData.hz50 || currentData.monochromeColor != newData.monochromeColor)
|
2019-11-24 21:06:55 +00:00
|
|
|
{
|
|
|
|
const VideoType_e videoType = VideoType_e(newData.videoType);
|
|
|
|
SetVideoType(videoType);
|
|
|
|
|
|
|
|
VideoStyle_e videoStyle = VS_NONE;
|
|
|
|
if (newData.scanLines)
|
|
|
|
videoStyle = VideoStyle_e(videoStyle | VS_HALF_SCANLINES);
|
|
|
|
if (newData.verticalBlend)
|
|
|
|
videoStyle = VideoStyle_e(videoStyle | VS_COLOR_VERTICAL_BLEND);
|
|
|
|
SetVideoStyle(videoStyle);
|
|
|
|
|
2019-12-02 20:50:51 +00:00
|
|
|
const VideoRefreshRate_e videoRefreshRate = newData.hz50 ? VR_50HZ : VR_60HZ;
|
|
|
|
SetVideoRefreshRate(videoRefreshRate);
|
|
|
|
|
2019-12-06 20:36:28 +00:00
|
|
|
const QColor color = newData.monochromeColor;
|
2019-12-05 21:37:39 +00:00
|
|
|
// be careful QRgb is opposite way round to COLORREF
|
|
|
|
g_nMonochromeRGB = RGB(color.red(), color.green(), color.blue());
|
|
|
|
|
2019-11-24 21:06:55 +00:00
|
|
|
Config_Save_Video();
|
|
|
|
VideoReinitialize();
|
|
|
|
VideoRedrawScreen();
|
|
|
|
}
|
|
|
|
|
2017-11-21 16:10:58 +00:00
|
|
|
}
|