From 54e564692b94aa003bccdbb9d2f838e066e7b794 Mon Sep 17 00:00:00 2001 From: Jonathan Campbell Date: Fri, 6 Oct 2023 12:13:47 -0700 Subject: [PATCH] BIOS CMOS date/time interrupt calls now CPU idle in order for CPU time and RTC clock ticks to proceed normally, which fixes Pizza Tycoon [https://github.com/joncampbell123/dosbox-x/issues/4502] --- CHANGELOG | 4 ++++ src/ints/bios.cpp | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7a96fb2b47..c9090fd664 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -46,6 +46,10 @@ Next version: shortcut triggers execution to stop whether in RUN or RUNWATCH mode. - Fix SETCOLORS command didn't change color when output=ttf.(Issue #4503) Also fixed the values reported were wrong. (maron2000) + - BIOS CMOS date/time functions will now idle the CPU 4 times after reading + or setting the clock to allow interrupts, CPU time, and RTC clock ticks + to proceed normally. This fixes "Pizza Tycoon" and allows it to continue + past the initial logo. (joncampbell123) 2023.09.01 - Disable by default message confirmation after snapshot and AVI video diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 7a7bf0adba..e204b1532e 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -2631,16 +2631,26 @@ static Bitu INT1A_Handler(void) { reg_cl = ReadCmosByte(0x02); // minutes reg_dh = ReadCmosByte(0x00); // seconds reg_dl = ReadCmosByte(0x0b) & 0x01; // daylight saving time + /* 2023/10/06 - Let interrupts and CPU cycles catch up and the RTC clock a chance to tick. This is needed for + * "Pizza Tycoon" which appears to start by running in a loop reading time from the BIOS and writing + * time to INT 21h in a loop until the second value changes. */ + for (unsigned int c=0;c < 4;c++) CALLBACK_Idle(); } CALLBACK_SCF(false); break; case 0x03: // set RTC time InitRtc(); // make sure BCD and no am/pm - WriteCmosByte(0x0b, ReadCmosByte(0x0b) | 0x80u); // prohibit updates - WriteCmosByte(0x04, reg_ch); // hours - WriteCmosByte(0x02, reg_cl); // minutes - WriteCmosByte(0x00, reg_dh); // seconds - WriteCmosByte(0x0b, (ReadCmosByte(0x0b) & 0x7eu) | (reg_dh & 0x01u)); // dst + implicitly allow updates + if (RtcUpdateDone()) { // make sure it's safe to read + WriteCmosByte(0x0b, ReadCmosByte(0x0b) | 0x80u); // prohibit updates + WriteCmosByte(0x04, reg_ch); // hours + WriteCmosByte(0x02, reg_cl); // minutes + WriteCmosByte(0x00, reg_dh); // seconds + WriteCmosByte(0x0b, (ReadCmosByte(0x0b) & 0x7eu) | (reg_dh & 0x01u)); // dst + implicitly allow updates + /* 2023/10/06 - Let interrupts and CPU cycles catch up and the RTC clock a chance to tick. This is needed for + * "Pizza Tycoon" which appears to start by running in a loop reading time from the BIOS and writing + * time to INT 21h in a loop until the second value changes. */ + for (unsigned int c=0;c < 4;c++) CALLBACK_Idle(); + } break; case 0x04: /* GET REAL-TIME ClOCK DATE (AT,XT286,PS) */ InitRtc(); // make sure BCD and no am/pm @@ -2649,17 +2659,27 @@ static Bitu INT1A_Handler(void) { reg_cl = ReadCmosByte(0x09); // year reg_dh = ReadCmosByte(0x08); // month reg_dl = ReadCmosByte(0x07); // day + /* 2023/10/06 - Let interrupts and CPU cycles catch up and the RTC clock a chance to tick. This is needed for + * "Pizza Tycoon" which appears to start by running in a loop reading time from the BIOS and writing + * time to INT 21h in a loop until the second value changes. */ + for (unsigned int c=0;c < 4;c++) CALLBACK_Idle(); } CALLBACK_SCF(false); break; case 0x05: // set RTC date InitRtc(); // make sure BCD and no am/pm - WriteCmosByte(0x0b, ReadCmosByte(0x0b) | 0x80); // prohibit updates - WriteCmosByte(0x32, reg_ch); // century - WriteCmosByte(0x09, reg_cl); // year - WriteCmosByte(0x08, reg_dh); // month - WriteCmosByte(0x07, reg_dl); // day - WriteCmosByte(0x0b, (ReadCmosByte(0x0b) & 0x7f)); // allow updates + if (RtcUpdateDone()) { // make sure it's safe to read + WriteCmosByte(0x0b, ReadCmosByte(0x0b) | 0x80); // prohibit updates + WriteCmosByte(0x32, reg_ch); // century + WriteCmosByte(0x09, reg_cl); // year + WriteCmosByte(0x08, reg_dh); // month + WriteCmosByte(0x07, reg_dl); // day + WriteCmosByte(0x0b, (ReadCmosByte(0x0b) & 0x7f)); // allow updates + /* 2023/10/06 - Let interrupts and CPU cycles catch up and the RTC clock a chance to tick. This is needed for + * "Pizza Tycoon" which appears to start by running in a loop reading time from the BIOS and writing + * time to INT 21h in a loop until the second value changes. */ + for (unsigned int c=0;c < 4;c++) CALLBACK_Idle(); + } break; case 0x80: /* Pcjr Setup Sound Multiplexer */ LOG(LOG_BIOS,LOG_ERROR)("INT1A:80:Setup tandy sound multiplexer to %d",reg_al);