Skip to content

Commit

Permalink
Patches for the 2010 problem
Browse files Browse the repository at this point in the history
- Adjust the time base for NewtonScript time related functions to
  2008-01-01T00:00:00 from 1993-01-01T00:00:00
- Set the Newton's time to the host time
  • Loading branch information
ekoeppen committed Jan 14, 2022
1 parent f64ccb9 commit 68373f9
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 25 deletions.
75 changes: 75 additions & 0 deletions Emulator/JIT/Generic/TJITGenericROMPatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,81 @@ T_ROM_PATCH(0x0038CE70, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid, "Debugger"
return 0L;
}

/*
* Set the time to the host time
*/

static const KUInt32 delta1904to1970 = 2082844800;

T_ROM_PATCH(0x00255578, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid, "RealClockSeconds")
{
(void) ioUnit;
time_t t = time(NULL);
struct tm gm;
struct tm local;
#if TARGET_OS_WIN32
gmtime_s(&gm, &t);
localtime_s(&local, &t);
#else
gmtime_r(&t, &gm);
localtime_r(&t, &local);
#endif
double tzoffset = difftime(mktime(&local), mktime(&gm));
ioCPU->SetRegister(0, t + tzoffset + delta1904to1970);
ioCPU->SetRegister(15, ioCPU->GetRegister(14) + 4);
return 0L;
}

/* Patches for the 2010 problem:
*
* The low level NewtonOS clock will continue to run with seconds since
* 1904-01-01T00:00:00. The NewtonScript functions which have been using a time
* base of 1993-01-01T00:00:00 will however be patched so that they will use a
* new time base of 2008-01-01T00:00:00. The patches will add or substract the
* delta between the time bases.
*
* The base year will need to be updated in 2026.
*/

/* Delta from 2008-01-01T00:00:00 to 1993-01-01T00:00:00 */

static const KUInt32 safeIntervalDeltaSeconds = 473299200;

/*
* Adjust seconds values returned to NS layer into safe interval
*/

T_ROM_PATCH(0x00089B80, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid, "FTimeInSeconds")
{
ioCPU->SetRegister(0, (ioCPU->GetRegister(0) - safeIntervalDeltaSeconds) << 2);
return ioUnit;
}

/*
* Fix date from seconds returned to NS layer
*/

T_ROM_PATCH(0x0008A8A8, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid, "FDateFromSeconds")
{
ioCPU->SetRegister(1, ioCPU->GetRegister(1) + safeIntervalDeltaSeconds);
ioCPU->SetRegister(0, ioCPU->GetRegister(13));
return ioUnit;
}

static const KUInt32 newTimeBaseMinutes = 218799360; /* 2008/1/1 in minutes from 1904/1/1 as NS integer */
static const KUInt32 newTimeBaseSeconds = 3281990400; /* 2008/1/1 in seconds from 1904/1/1 as NS integer */

TJITGenericPatch timeBase1(0x420750, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid,
newTimeBaseMinutes, "Time base (1/4)");
TJITGenericPatch timeBase2(0x420798, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid,
newTimeBaseMinutes, "Time base (2/4)");
TJITGenericPatch timeBase3(0x4dca14, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid,
newTimeBaseMinutes, "Time base (3/4)");
TJITGenericPatch timeBase4(0x30F088, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid,
newTimeBaseSeconds, "Time base (4/4)");
TJITGenericPatch ignoreSettingTime(0x0008A20C, kROMPatchVoid, kROMPatchVoid, kROMPatchVoid,
0xe1a0f00e, "Ignore setting time"); // mov pc, lr

// ========================================================================== //
// MARK: -
// TJITGenericPatchManager
Expand Down
28 changes: 3 additions & 25 deletions app/FLTK/TFLApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,20 +877,16 @@ void TFLApp::UserActionInstallEssentials()
// Y2K10
addInstallerGroup("NewtonOS Y2K10 Fix");
addInstallerText("NewtonOS has a bug in handling years past 18:48:31 on January 5, 2010. "
"The patch below will fix all date issues until 2026.\n\n"
"Einstein contains a fix for US MP2x00 MessagePads, but "
"for eMates and German MP2x00 MessagePads, "
"the patch below will fix all date issues until 2026.\n\n"
"Please install this patch before installing anything else, "
"as this will wipe your Newton's memory.");
addInstallerLink("explained by Eckhart Köppen", new StringList {
":https://40hz.org/Pages/newton/hacking/newton-year-2010-problem/"} );
addInstallerLink("Readme file for the patch", new StringList {
"MDownloads/Einstein/Essentials/y2k10/README.txt"} );
addInstallerText("Please select the patch that matches the ROM image of your machine:");
addInstallerPackage("US MP2x00 patch", new StringList {
"WInstalling this patch may irreversibly erase all data\n"
"on your MessagePad.\n\n"
"Please proceed only if this a new device, or if your\n"
"data is securely backed up!",
"MDownloads/Einstein/Essentials/y2k10/Patch_US.pkg"} );
addInstallerPackage("German MP2x00 patch", new StringList {
"WInstalling this patch may irreversibly erase all data\n"
"on your MessagePad.\n\n"
Expand Down Expand Up @@ -1318,24 +1314,6 @@ void TFLApp::StoreAppWindowSize()
*/
void TFLApp::DeferredOnPowerRestored()
{
static bool beenHere = false;

// We run this once at boot time. It would be correct to reset this whenever
// we reboot or load a different configuration.
if (!beenHere) {
if (mFLSettings->mFetchDateAndTime) {
std::time_t now = time(nullptr);
struct std::tm then_tm = { 0, 0, 0, 1, 0, 4 }; /* Midnight Jan 1 1904 */
std::time_t then = std::mktime(&then_tm);
auto diff_secs = std::difftime(now, then);

KUInt32 minutesSince1904 = (KUInt32)(diff_secs / 60);
char setTimeAndDateScript[256];
::snprintf(setTimeAndDateScript, 256, "SetTime(%u);", minutesSince1904);
mPlatformManager->EvalNewtonScript(setTimeAndDateScript);
}
beenHere = true;
}
}


Expand Down

0 comments on commit 68373f9

Please sign in to comment.