Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Y2K(20) issue #111

Open
ZXGuesser opened this issue Dec 24, 2022 · 2 comments
Open

Y2K(20) issue #111

ZXGuesser opened this issue Dec 24, 2022 · 2 comments

Comments

@ZXGuesser
Copy link
Contributor

Originally posted on Stardot but for some reason I never opened a bug here 🤦‍♂️

I've recently acquired a Master 128 so have been poking around in Master 128 emulation for the first time and (re)discovered a Y2K issue, that was presumably masked before by the "Y2K adjust" option.
Was the aim of the Y2K adjust to keep dates in the 21st century, but after the 80s for old software's sake? If so it needs updating now!

The following modified code would seem to work to me for reading and setting the time, but maybe I'm missing something about how the RTC is supposed to work.

/*-------------------------------------------------------------------------*/
time_t CMOSConvertClock()
{
	struct tm *CurTime = localtime(&SysTime);
	
	struct tm Base;
	Base.tm_sec = BCDToBin(CMOSRAM[0]);
	Base.tm_min = BCDToBin(CMOSRAM[2]);
	Base.tm_hour = BCDToBin(CMOSRAM[4]);
	Base.tm_mday = BCDToBin(CMOSRAM[7]);
	Base.tm_mon = BCDToBin(CMOSRAM[8])-1;
	Base.tm_year = BCDToBin(CMOSRAM[9]);
	Base.tm_wday = -1;
	Base.tm_yday = -1;
	Base.tm_isdst = -1;
	
	Base.tm_year += (CurTime->tm_year / 100) * 100;

	return mktime(&Base);
}
/*-------------------------------------------------------------------------*/
void RTCInit()
{
	time(&SysTime);
	struct tm *CurTime = localtime(&SysTime);
	CMOSRAM[0] = BCD(static_cast<unsigned char>(CurTime->tm_sec));
	CMOSRAM[2] = BCD(static_cast<unsigned char>(CurTime->tm_min));
	CMOSRAM[4] = BCD(static_cast<unsigned char>(CurTime->tm_hour));
	CMOSRAM[6] = BCD(static_cast<unsigned char>(CurTime->tm_wday + 1));
	CMOSRAM[7] = BCD(static_cast<unsigned char>(CurTime->tm_mday));
	CMOSRAM[8] = BCD(static_cast<unsigned char>(CurTime->tm_mon + 1));
	CMOSRAM[9] = BCD(static_cast<unsigned char>((CurTime->tm_year - (RTCY2KAdjust ? 20 : 0)) % 100));
	RTCTimeOffset = SysTime - CMOSConvertClock();
}
/*-------------------------------------------------------------------------*/
void RTCUpdate()
{
	time(&SysTime);
	SysTime -= RTCTimeOffset;
	struct tm *CurTime = localtime(&SysTime);
	CMOSRAM[0] = BCD(static_cast<unsigned char>(CurTime->tm_sec));
	CMOSRAM[2] = BCD(static_cast<unsigned char>(CurTime->tm_min));
	CMOSRAM[4] = BCD(static_cast<unsigned char>(CurTime->tm_hour));
	CMOSRAM[6] = BCD(static_cast<unsigned char>(CurTime->tm_wday + 1));
	CMOSRAM[7] = BCD(static_cast<unsigned char>(CurTime->tm_mday));
	CMOSRAM[8] = BCD(static_cast<unsigned char>(CurTime->tm_mon + 1));
	CMOSRAM[9] = BCD(static_cast<unsigned char>(CurTime->tm_year % 100));
}
@chrisn
Copy link
Collaborator

chrisn commented Dec 31, 2022

Thanks! I had seen this on Stardot, but posting here is a helpful reminder to look at it.

I'm wondering whether the RTCY2KAdjust option is still needed. The previous code in RTCInit() is:

CMOSRAM[9] = BCD(static_cast<unsigned char>(CurTime->tm_year - (RTCY2KAdjust ? 20 : 0)));

tm_year contains the number of years since 1900, so 100 for the year 2000, which is larger than the maximum two-digit BCD number (99). So it seems that RTCY2KAdjust is intended to map years 2000-2019 to 1980-1999. But this obviously will overflow the BCD range from 2020 onwards.

As the MOS only looks for the last two digits of the year (info here), it seems we could just use the year modulo 100 and remove the RTCY2KAdjust option. Years will always be displayed as 19xx, unless using a patched MOS, though.

chrisn added a commit that referenced this issue Jan 1, 2023
Before this change, the year is stored as the last two digits,
in BCD format. For years after 2000 (or 2020 with the "Master
128 RTC Y2K Adjust" option enabled), the value would be greater
than 100, which overflows two digits.

This change stores the year modulo-100. Note that the Master MOS
still displays years as 19xx, but will accept any century when
setting the time using TIME$.

This change also removes the Master 128 RTC Y2K Adjust menu
option, which is no longer needed.

See #111
@ZXGuesser
Copy link
Contributor Author

My suggestion for dealing with the "configuring RTC to return suitable years for specific things" issue would be to simply store and reload the offset from SysTime as part of the preferences (defaulting to zero offset so a new profile gets the current system time). That way the realtime clock still behaves in a predictable way but can be set to whatever date and time a user wants and persists when the emulated beeb is "off" just as a real machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants