2018-05-20 04:53:34 +00:00
|
|
|
// Pi1541 - A Commodore 1541 disk drive emulator
|
|
|
|
// Copyright(C) 2018 Stephen White
|
|
|
|
//
|
|
|
|
// This file is part of Pi1541.
|
|
|
|
//
|
|
|
|
// Pi1541 is free software : you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Pi1541 is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "options.h"
|
2018-06-12 09:03:29 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2018-05-20 04:53:34 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#define INVALID_VALUE ((unsigned) -1)
|
|
|
|
|
|
|
|
char* TextParser::GetToken(bool includeSpace)
|
|
|
|
{
|
|
|
|
bool isSpace;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
} while (ParseComment());
|
|
|
|
|
|
|
|
while (*data != '\0')
|
|
|
|
{
|
|
|
|
isSpace = isspace(*data);
|
|
|
|
|
|
|
|
if (!isSpace || (includeSpace && isSpace))
|
|
|
|
break;
|
|
|
|
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*data == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
char* pToken = data;
|
|
|
|
|
|
|
|
while (*data != '\0')
|
|
|
|
{
|
|
|
|
isSpace = isspace(*data);
|
|
|
|
|
|
|
|
if ((!includeSpace && isSpace) || (*data == '\n') || (*data == '\r'))
|
|
|
|
{
|
|
|
|
*data++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pToken;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TextParser::SkipWhiteSpace()
|
|
|
|
{
|
|
|
|
while (*data != '\0')
|
|
|
|
{
|
|
|
|
if (!isspace(*data))
|
|
|
|
break;
|
|
|
|
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TextParser::ParseComment()
|
|
|
|
{
|
|
|
|
SkipWhiteSpace();
|
|
|
|
|
|
|
|
if (*data == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (data[0] != '/')
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (data[1] == '/')
|
|
|
|
{
|
|
|
|
// One line comment
|
|
|
|
data += 2;
|
|
|
|
|
|
|
|
while (*data)
|
|
|
|
{
|
|
|
|
if (*data == '\n')
|
|
|
|
break;
|
|
|
|
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
SkipWhiteSpace();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (data[1] == '*')
|
|
|
|
{
|
|
|
|
// Multiline comment
|
|
|
|
data += 2;
|
|
|
|
|
|
|
|
while (*data)
|
|
|
|
{
|
|
|
|
if (*data++ == '*' && *data && *data == '/')
|
|
|
|
{
|
|
|
|
data++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SkipWhiteSpace();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Options::Options(void)
|
|
|
|
: TextParser()
|
|
|
|
, deviceID(8)
|
|
|
|
, onResetChangeToStartingFolder(0)
|
|
|
|
, extraRAM(0)
|
2018-06-03 07:54:36 +00:00
|
|
|
, RAMBOard(0)
|
2018-05-20 04:53:34 +00:00
|
|
|
, disableSD2IECCommands(0)
|
|
|
|
, supportUARTInput(0)
|
|
|
|
, graphIEC(0)
|
|
|
|
, quickBoot(0)
|
2018-06-24 03:39:49 +00:00
|
|
|
, showOptions(0)
|
2018-05-20 04:53:34 +00:00
|
|
|
, displayPNGIcons(0)
|
|
|
|
, soundOnGPIO(0)
|
2018-06-12 11:39:08 +00:00
|
|
|
, soundOnGPIODuration(1000)
|
|
|
|
, soundOnGPIOFreq(1200)
|
2018-05-20 04:53:34 +00:00
|
|
|
, invertIECInputs(0)
|
2018-05-26 22:55:17 +00:00
|
|
|
, invertIECOutputs(1)
|
2018-05-20 04:53:34 +00:00
|
|
|
, splitIECLines(0)
|
2018-05-26 22:55:17 +00:00
|
|
|
, ignoreReset(0)
|
2018-05-27 09:56:53 +00:00
|
|
|
, screenWidth(1024)
|
|
|
|
, screenHeight(768)
|
2018-06-04 09:11:15 +00:00
|
|
|
, i2cBusMaster(1)
|
2018-06-07 09:00:39 +00:00
|
|
|
, i2cLcdAddress(0x3C)
|
2018-07-17 08:25:15 +00:00
|
|
|
, i2cScan(0)
|
2018-06-15 14:01:02 +00:00
|
|
|
, i2cLcdFlip(0)
|
2018-07-04 01:48:55 +00:00
|
|
|
, i2cLcdOnContrast(127)
|
2018-07-26 01:06:21 +00:00
|
|
|
, i2cLcdModel(LCD_UNKNOWN)
|
2018-07-15 08:46:49 +00:00
|
|
|
, scrollHighlightRate(0.125f)
|
2018-06-03 08:11:58 +00:00
|
|
|
, keyboardBrowseLCDScreen(0)
|
2018-05-20 04:53:34 +00:00
|
|
|
{
|
2018-06-24 04:37:11 +00:00
|
|
|
autoMountImageName[0] = 0;
|
2018-05-21 09:12:59 +00:00
|
|
|
strcpy(ROMFontName, "chargen");
|
2018-07-04 01:48:55 +00:00
|
|
|
strcpy(LcdLogoName, "1541ii");
|
2018-07-20 02:30:20 +00:00
|
|
|
strcpy(autoBaseName, "autoname");
|
2018-05-30 10:38:14 +00:00
|
|
|
starFileName[0] = 0;
|
2018-05-20 04:53:34 +00:00
|
|
|
ROMName[0] = 0;
|
|
|
|
ROMNameSlot2[0] = 0;
|
|
|
|
ROMNameSlot3[0] = 0;
|
|
|
|
ROMNameSlot4[0] = 0;
|
|
|
|
ROMNameSlot5[0] = 0;
|
|
|
|
ROMNameSlot6[0] = 0;
|
|
|
|
ROMNameSlot7[0] = 0;
|
|
|
|
ROMNameSlot8[0] = 0;
|
|
|
|
}
|
|
|
|
|
2018-06-03 07:54:36 +00:00
|
|
|
#define ELSE_CHECK_DECIMAL_OPTION(Name) \
|
|
|
|
else if (strcasecmp(pOption, #Name) == 0) \
|
|
|
|
{ \
|
|
|
|
unsigned nValue = 0; \
|
|
|
|
if ((nValue = GetDecimal(pValue)) != INVALID_VALUE) \
|
|
|
|
Name = nValue; \
|
|
|
|
}
|
2018-06-12 09:03:29 +00:00
|
|
|
#define ELSE_CHECK_FLOAT_OPTION(Name) \
|
|
|
|
else if (strcasecmp(pOption, #Name) == 0) \
|
|
|
|
{ \
|
2018-07-15 08:46:49 +00:00
|
|
|
float value = 0; \
|
|
|
|
if ((value = GetFloat(pValue)) != INVALID_VALUE) \
|
|
|
|
Name = value; \
|
2018-06-12 09:03:29 +00:00
|
|
|
}
|
2018-06-03 07:54:36 +00:00
|
|
|
|
2018-05-20 04:53:34 +00:00
|
|
|
void Options::Process(char* buffer)
|
|
|
|
{
|
|
|
|
SetData(buffer);
|
|
|
|
|
|
|
|
char* pOption;
|
|
|
|
while ((pOption = GetToken()) != 0)
|
|
|
|
{
|
|
|
|
/*char* equals = */GetToken();
|
|
|
|
char* pValue = GetToken();
|
|
|
|
|
2018-07-01 00:16:47 +00:00
|
|
|
if ((strcasecmp(pOption, "Font") == 0) || (strcasecmp(pOption, "ChargenFont") == 0))
|
2018-05-21 09:12:59 +00:00
|
|
|
{
|
|
|
|
strncpy(ROMFontName, pValue, 255);
|
|
|
|
}
|
2018-06-24 04:37:11 +00:00
|
|
|
else if ((strcasecmp(pOption, "AutoMountImage") == 0))
|
|
|
|
{
|
|
|
|
strncpy(autoMountImageName, pValue, 255);
|
|
|
|
}
|
2018-06-03 07:54:36 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(deviceID)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(onResetChangeToStartingFolder)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(extraRAM)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(RAMBOard)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(disableSD2IECCommands)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(supportUARTInput)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(graphIEC)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(quickBoot)
|
2018-06-24 03:39:49 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(showOptions)
|
2018-06-03 07:54:36 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(displayPNGIcons)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(soundOnGPIO)
|
2018-06-12 11:39:08 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(soundOnGPIODuration)
|
2018-06-12 01:17:52 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(soundOnGPIOFreq)
|
2018-06-03 07:54:36 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(invertIECInputs)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(invertIECOutputs)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(splitIECLines)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(ignoreReset)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(screenWidth)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(screenHeight)
|
2018-06-04 09:11:15 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cBusMaster)
|
2018-06-07 09:00:39 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cLcdAddress)
|
2018-07-17 08:25:15 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cScan)
|
2018-06-15 14:01:02 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cLcdFlip)
|
2018-06-22 12:32:54 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cLcdOnContrast)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimContrast)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimTime)
|
2018-07-15 08:46:49 +00:00
|
|
|
ELSE_CHECK_FLOAT_OPTION(scrollHighlightRate)
|
2018-06-03 08:11:58 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen)
|
2018-07-20 02:30:20 +00:00
|
|
|
else if ((strcasecmp(pOption, "AutoBaseName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(autoBaseName, pValue, 255);
|
|
|
|
}
|
2018-05-30 10:38:14 +00:00
|
|
|
else if ((strcasecmp(pOption, "StarFileName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(starFileName, pValue, 255);
|
|
|
|
}
|
2018-07-03 11:26:01 +00:00
|
|
|
else if ((strcasecmp(pOption, "LCDLogoName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(LcdLogoName, pValue, 255);
|
|
|
|
}
|
2018-06-03 08:11:58 +00:00
|
|
|
else if ((strcasecmp(pOption, "LCDName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(LCDName, pValue, 255);
|
2018-07-04 01:48:55 +00:00
|
|
|
if (strcasecmp(pValue, "ssd1306_128x64") == 0)
|
2018-07-26 01:06:21 +00:00
|
|
|
i2cLcdModel = LCD_1306_128x64;
|
|
|
|
else if (strcasecmp(pValue, "ssd1306_128x32") == 0)
|
|
|
|
i2cLcdModel = LCD_1306_128x32;
|
2018-07-04 01:48:55 +00:00
|
|
|
else if (strcasecmp(pValue, "sh1106_128x64") == 0)
|
2018-07-26 01:06:21 +00:00
|
|
|
i2cLcdModel = LCD_1106_128x64;
|
2018-07-04 01:48:55 +00:00
|
|
|
|
2018-06-03 08:11:58 +00:00
|
|
|
}
|
2018-05-20 04:53:34 +00:00
|
|
|
else if ((strcasecmp(pOption, "ROM") == 0) || (strcasecmp(pOption, "ROM1") == 0))
|
|
|
|
{
|
|
|
|
strncpy(ROMName, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM2") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot2, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM3") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot3, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM4") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot4, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM5") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot5, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM6") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot6, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM7") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot7, pValue, 255);
|
|
|
|
}
|
|
|
|
else if (strcasecmp(pOption, "ROM8") == 0)
|
|
|
|
{
|
|
|
|
strncpy(ROMNameSlot8, pValue, 255);
|
|
|
|
}
|
|
|
|
}
|
2018-06-03 07:54:36 +00:00
|
|
|
|
|
|
|
if (!SplitIECLines())
|
2018-06-04 09:11:15 +00:00
|
|
|
{
|
2018-06-03 07:54:36 +00:00
|
|
|
invertIECInputs = false;
|
2018-06-07 10:20:57 +00:00
|
|
|
// If using non split lines then only the 1st bus master can be used (as ATN is using the 2nd)
|
|
|
|
i2cBusMaster = 0;
|
2018-06-04 09:11:15 +00:00
|
|
|
}
|
2018-05-20 04:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Options::GetDecimal(char* pString)
|
|
|
|
{
|
|
|
|
if (pString == 0 || *pString == '\0')
|
|
|
|
return INVALID_VALUE;
|
|
|
|
|
|
|
|
unsigned nResult = 0;
|
|
|
|
|
|
|
|
char chChar = *pString++;
|
|
|
|
while (chChar != '\0' && chChar != 13)
|
|
|
|
{
|
|
|
|
if (!('0' <= chChar && chChar <= '9'))
|
|
|
|
return INVALID_VALUE;
|
|
|
|
|
|
|
|
unsigned nPrevResult = nResult;
|
|
|
|
|
|
|
|
nResult = nResult * 10 + (chChar - '0');
|
|
|
|
if (nResult < nPrevResult || nResult == INVALID_VALUE)
|
|
|
|
return INVALID_VALUE;
|
|
|
|
|
|
|
|
chChar = *pString++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nResult;
|
|
|
|
}
|
|
|
|
|
2018-06-12 09:03:29 +00:00
|
|
|
float Options::GetFloat(char* pString)
|
|
|
|
{
|
|
|
|
if (pString == 0 || *pString == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return atof(pString);
|
|
|
|
}
|
|
|
|
|
2018-05-20 04:53:34 +00:00
|
|
|
const char* Options::GetRomName(int index) const
|
|
|
|
{
|
|
|
|
switch (index)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
return ROMNameSlot2;
|
|
|
|
case 2:
|
|
|
|
return ROMNameSlot3;
|
|
|
|
case 3:
|
|
|
|
return ROMNameSlot4;
|
|
|
|
case 4:
|
|
|
|
return ROMNameSlot5;
|
|
|
|
case 5:
|
|
|
|
return ROMNameSlot6;
|
|
|
|
case 6:
|
|
|
|
return ROMNameSlot7;
|
|
|
|
case 7:
|
|
|
|
return ROMNameSlot8;
|
|
|
|
}
|
|
|
|
return ROMName;
|
|
|
|
}
|