From 4e299a8038e96f2f58ca37aac425cf2dd8b5cad7 Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 15 Aug 2016 20:28:02 +0100 Subject: [PATCH] Rewrote handling of host time synchronisation. Amstrad machines now boot again. Also fixed a bug where the emulated time ran 100x faster than expected. --- src/nvr.c | 10 +++-- src/rtc.c | 114 +++++++++++++++++++++++++++++------------------------- src/rtc.h | 2 + 3 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/nvr.c b/src/nvr.c index d429960..3a0a62a 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -103,12 +103,11 @@ void nvr_onesec(void *p) if (!(nvrram[RTC_REGB] & RTC_SET)) { nvr_update_status = RTC_UIP; - /* If sync is disabled, move internal clock ahead by 1 second. */ - if (!enable_sync) - rtc_tick(); + rtc_tick(); nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC); } + nvr_onesec_cnt = 0; } nvr_onesec_time += (int)(10000 * TIMER_USEC); } @@ -241,7 +240,10 @@ void loadnvr() return; } fread(nvrram,128,1,f); - if (!enable_sync) time_update(nvrram, 0xFF); /* Update the internal clock state based on the NVR registers. */ + if (enable_sync) + time_internal_sync(nvrram); + else + time_internal_set_nvrram(nvrram); /* Update the internal clock state based on the NVR registers. */ fclose(f); nvrram[RTC_REGA] = 6; nvrram[RTC_REGB] = RTC_2412; diff --git a/src/rtc.c b/src/rtc.c index a3fe581..312556a 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -124,22 +124,6 @@ void time_update(char *nvrram, int reg) internal_clock.year %= 100; internal_clock.year += (DCB(nvrram[RTC_CENTURY]) * 100); break; - case 0xFF: /* Load the entire internal clock state from the NVR. */ - internal_clock.sec = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_SECONDS] : DCB(nvrram[RTC_SECONDS]); - internal_clock.min = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MINUTES] : DCB(nvrram[RTC_MINUTES]); - - temp = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_HOURS] : DCB(nvrram[RTC_HOURS]); - - if (nvrram[RTC_REGB] & RTC_2412) - internal_clock.hour = temp; - else - internal_clock.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); - - internal_clock.mday = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_DOM] : DCB(nvrram[RTC_DOM]); - internal_clock.mon = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MONTH] : DCB(nvrram[RTC_MONTH]); - internal_clock.year = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_YEAR] : DCB(nvrram[RTC_YEAR]); - internal_clock.year += (nvrram[RTC_REGB] & RTC_DM) ? 1900 : (DCB(nvrram[RTC_CENTURY]) * 100); - break; } } @@ -157,50 +141,31 @@ static int time_week_day() } /* Called to get time into the internal clock */ -static void time_internal(struct tm **time_var) +static void time_internal_get(struct tm *time_var) { - if (*time_var == NULL) - *time_var = (struct tm *)malloc(sizeof(struct tm)); - - (*time_var)->tm_sec = internal_clock.sec; - (*time_var)->tm_min = internal_clock.min; - (*time_var)->tm_hour = internal_clock.hour; - (*time_var)->tm_wday = time_week_day(); - (*time_var)->tm_mday = internal_clock.mday; - (*time_var)->tm_mon = internal_clock.mon - 1; - (*time_var)->tm_year = internal_clock.year - 1900; + time_var->tm_sec = internal_clock.sec; + time_var->tm_min = internal_clock.min; + time_var->tm_hour = internal_clock.hour; + time_var->tm_wday = time_week_day(); + time_var->tm_mday = internal_clock.mday; + time_var->tm_mon = internal_clock.mon - 1; + time_var->tm_year = internal_clock.year - 1900; } -static time_t cur_time; -static struct tm *cur_time_tm; +static void time_internal_set(struct tm *time_var) +{ + internal_clock.sec = time_var->tm_sec; + internal_clock.min = time_var->tm_min; + internal_clock.hour = time_var->tm_hour; + internal_clock.mday = time_var->tm_mday; + internal_clock.mon = time_var->tm_mon + 1; + internal_clock.year = time_var->tm_year + 1900; +} -/* Periodic RTC update function - See also: nvr_onesec() in nvr.c - */ -void time_get(char *nvrram) +static void time_set_nvrram(char *nvrram, struct tm *cur_time_tm) { int dow, mon, year; - if (enable_sync) - { - time(&cur_time); - - /* Mingw doesn't support localtime_r */ - #if __MINGW32__ - cur_time_tm = localtime(&cur_time); - #else - #if __MINGW64__ - cur_time_tm = localtime(&cur_time); - #else - localtime_r(&cur_time, &cur_time_tm); - #endif - #endif - } - else - { - time_internal(&cur_time_tm); - } - if (nvrram[RTC_REGB] & RTC_DM) { nvrram[RTC_SECONDS] = cur_time_tm->tm_sec; @@ -242,3 +207,46 @@ void time_get(char *nvrram) } } } + +void time_internal_set_nvrram(char *nvrram) +{ + int temp; + + /* Load the entire internal clock state from the NVR. */ + internal_clock.sec = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_SECONDS] : DCB(nvrram[RTC_SECONDS]); + internal_clock.min = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MINUTES] : DCB(nvrram[RTC_MINUTES]); + + temp = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_HOURS] : DCB(nvrram[RTC_HOURS]); + + if (nvrram[RTC_REGB] & RTC_2412) + internal_clock.hour = temp; + else + internal_clock.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); + + internal_clock.mday = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_DOM] : DCB(nvrram[RTC_DOM]); + internal_clock.mon = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MONTH] : DCB(nvrram[RTC_MONTH]); + internal_clock.year = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_YEAR] : DCB(nvrram[RTC_YEAR]); + internal_clock.year += (nvrram[RTC_REGB] & RTC_DM) ? 1900 : (DCB(nvrram[RTC_CENTURY]) * 100); +} + +void time_internal_sync(char *nvrram) +{ + struct tm *cur_time_tm; + time_t cur_time; + + time(&cur_time); + cur_time_tm = localtime(&cur_time); + + time_internal_set(cur_time_tm); + + time_set_nvrram(nvrram, cur_time_tm); +} + +void time_get(char *nvrram) +{ + struct tm cur_time_tm; + + time_internal_get(&cur_time_tm); + + time_set_nvrram(nvrram, &cur_time_tm); +} diff --git a/src/rtc.h b/src/rtc.h index 91c9304..b99728c 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -170,3 +170,5 @@ enum RTC_RD_BITS void rtc_tick(); void time_update(char *nvrram, int reg); void time_get(char *nvrram); +void time_internal_set_nvrram(char *nvrram); +void time_internal_sync(char *nvrram);