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"
|
|
|
|
#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)
|
|
|
|
, displayPNGIcons(0)
|
|
|
|
, soundOnGPIO(0)
|
|
|
|
, 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-03 08:11:58 +00:00
|
|
|
, keyboardBrowseLCDScreen(0)
|
2018-05-20 04:53:34 +00:00
|
|
|
{
|
2018-05-21 09:12:59 +00:00
|
|
|
strcpy(ROMFontName, "chargen");
|
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-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-06-03 07:54:36 +00:00
|
|
|
if ((strcasecmp(pOption, "Font") == 0))
|
2018-05-21 09:12:59 +00:00
|
|
|
{
|
|
|
|
strncpy(ROMFontName, 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)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(displayPNGIcons)
|
|
|
|
ELSE_CHECK_DECIMAL_OPTION(soundOnGPIO)
|
|
|
|
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-03 08:11:58 +00:00
|
|
|
ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen)
|
2018-05-30 10:38:14 +00:00
|
|
|
else if ((strcasecmp(pOption, "StarFileName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(starFileName, pValue, 255);
|
|
|
|
}
|
2018-06-03 08:11:58 +00:00
|
|
|
else if ((strcasecmp(pOption, "LCDName") == 0))
|
|
|
|
{
|
|
|
|
strncpy(LCDName, pValue, 255);
|
|
|
|
}
|
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-04 09:11:15 +00:00
|
|
|
// If using non split lines then only the 2nd bus master can be used (as ATN is using the 1st)
|
|
|
|
i2cBusMaster = 1;
|
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|