From 407abeb4b6d936745bebaabc4091ca00aa28efd8 Mon Sep 17 00:00:00 2001 From: javi-s Date: Thu, 20 Oct 2022 00:18:02 +0200 Subject: [PATCH 1/3] Olivetti M24 DIP switch settings correction Fix to match RAM --- src/machine/m_xt_olivetti.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 1d53a588e..76e6cac4b 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -667,7 +667,7 @@ m24_read(uint16_t port, void *priv) ret |= 0x1; break; case 256: - ret |= 0x2 | 0x80; + ret |= 0x2; break; case 384: ret |= 0x1 | 0x2 | 0x80; @@ -676,10 +676,12 @@ m24_read(uint16_t port, void *priv) ret |= 0x8; break; case 640: - default: ret |= 0x1 | 0x8 | 0x80; break; + default: + break; } + break; /* * port 67: * DIPSW-1 on mainboard (off=present=1) @@ -721,6 +723,8 @@ m24_read(uint16_t port, void *priv) /* Switch 2 - Set fast startup */ ret |= 0x2; + + break; } return (ret); From a513ea5da5bdfe30760ea00c4530c00dc1b4a2d8 Mon Sep 17 00:00:00 2001 From: javi-s Date: Sun, 23 Oct 2022 15:39:42 +0200 Subject: [PATCH 2/3] Initial emulation of National Semiconductor MM58174 RTC Based on existing Toshiba TC8521 RTC emulation --- src/machine/m_xt_olivetti.c | 200 +++++++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 4 deletions(-) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 76e6cac4b..c3457ee46 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -8,7 +8,7 @@ * * Emulation of the Olivetti XT-compatible machines. * - * + * - Supports MM58174 real-time clock emulation * * Authors: Sarah Walker, * Miran Grca, @@ -69,6 +69,28 @@ #define CGA_RGB 0 #define CGA_COMPOSITE 1 +enum MM58174_ADDR { + /* Registers */ + MM58174_TEST, /* TEST register, write only */ + MM58174_TENTHS, /* Tenths of second, read only */ + MM58174_SECOND1, /* Units of seconds, read only */ + MM58174_SECOND10, /* Tens of seconds, read only */ + MM58174_MINUTE1, + MM58174_MINUTE10, + MM58174_HOUR1, + MM58174_HOUR10, + MM58174_DAY1, + MM58174_DAY10, + MM58174_WEEKDAY, + MM58174_MONTH1, + MM58174_MONTH10, + MM58174_LEAPYEAR, /* Leap year status, write only */ + MM58174_RESET, /* RESET register, write only */ + MM58174_IRQ /* Interrupt register, read / write */ +}; + +static struct tm intclk; + typedef struct { /* Keyboard stuff. */ int wantirq; @@ -120,6 +142,170 @@ m24_log(const char *fmt, ...) # define m24_log(fmt, ...) #endif +/* Set the chip time. */ +static void +mm58174_time_set(uint8_t *regs, struct tm *tm) +{ + regs[MM58174_SECOND1] = (tm->tm_sec % 10); + regs[MM58174_SECOND10] = (tm->tm_sec / 10); + regs[MM58174_MINUTE1] = (tm->tm_min % 10); + regs[MM58174_MINUTE10] = (tm->tm_min / 10); + regs[MM58174_HOUR1] = (tm->tm_hour % 10); + regs[MM58174_HOUR10] = (tm->tm_hour / 10); + regs[MM58174_WEEKDAY] = (tm->tm_wday + 1); + regs[MM58174_DAY1] = (tm->tm_mday % 10); + regs[MM58174_DAY10] = (tm->tm_mday / 10); + regs[MM58174_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[MM58174_MONTH10] = ((tm->tm_mon + 1) / 10); + /* MM87174 does not store the year, M24 uses the IRQ register to count 8 years from leap year */ + regs[MM58174_IRQ] = ((tm->tm_year + 1900) % 8); + regs[MM58174_LEAPYEAR] = 8 >> ((regs[MM58174_IRQ] & 0x07) & 0x03); +} + +/* Get the chip time. */ +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +static void +mm58174_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(MM58174_SECOND); + tm->tm_min = nibbles(MM58174_MINUTE); + tm->tm_hour = nibbles(MM58174_HOUR); + tm->tm_wday = (regs[MM58174_WEEKDAY] - 1); + tm->tm_mday = nibbles(MM58174_DAY); + tm->tm_mon = (nibbles(MM58174_MONTH) - 1); + /* MM87174AN does not store the year */ + tm->tm_year = (1984 + (regs[MM58174_IRQ] & 0x07) - 1900); +} + +/* One more second has passed, update the internal clock. */ +static void +mm58174_recalc() +{ + /* Ping the internal clock. */ + if (++intclk.tm_sec == 60) { + intclk.tm_sec = 0; + if (++intclk.tm_min == 60) { + intclk.tm_min = 0; + if (++intclk.tm_hour == 24) { + intclk.tm_hour = 0; + if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, intclk.tm_year) + 1)) { + intclk.tm_mday = 1; + if (++intclk.tm_mon == 13) { + intclk.tm_mon = 1; + intclk.tm_year++; + } + } + } + } + } +} + +/* This is called every second through the NVR/RTC hook. */ +static void +mm58174_tick(nvr_t *nvr) +{ + mm58174_recalc(); + mm58174_time_set(nvr->regs, &intclk); +} + +static void +mm58174_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync & TIME_SYNC_ENABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + mm58174_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + mm58174_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + mm58174_time_get(nvr->regs, &intclk); +} + +/* Write to one of the chip registers. */ +static void +mm58174_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + val &= 0x0f; + + /* Update non-read-only changed values if not synchronizing time to host */ + if ((addr != MM58174_TENTHS) && (addr != MM58174_SECOND1) && (addr != MM58174_SECOND10)) + if ((nvr->regs[addr] != val) && !(time_sync & TIME_SYNC_ENABLED)) + nvr_dosave = 1; + + if ((addr == MM58174_RESET) && (val & 0x01)) { + /* When timer starts, MM58174 sets seconds and tenths of second to 0 */ + nvr->regs[MM58174_TENTHS] = 0; + if (!(time_sync & TIME_SYNC_ENABLED)) { + /* Only set seconds to 0 if not synchronizing time to host clock */ + nvr->regs[MM58174_SECOND1] = 0; + nvr->regs[MM58174_SECOND10] = 0; + } + } + + /* Store the new value */ + nvr->regs[addr] = val; + + /* Update internal clock with MM58174 time */ + mm58174_time_get(nvr->regs, &intclk); +} + +/* Read from one of the chip registers. */ +static uint8_t +mm58174_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *) priv; + + addr &= 0x0f; + + /* Set IRQ control bit to 0 upon read */ + if (addr == 0x0f) + nvr->regs[addr] &= 0x07; + + /* Grab and return the desired value */ + return (nvr->regs[addr]); +} + +/* Reset the MM58174 to a default state. */ +static void +mm58174_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 16); + nvr->regs[MM58174_WEEKDAY] = 0x01; + nvr->regs[MM58174_DAY1] = 0x01; + nvr->regs[MM58174_MONTH1] = 0x01; +} + +static void +mm58174_init(nvr_t *nvr, int size) +{ + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + + /* Set up any local handlers here. */ + nvr->reset = mm58174_reset; + nvr->start = mm58174_start; + nvr->tick = mm58174_tick; + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + io_sethandler(0x0070, 16, + mm58174_read, NULL, NULL, mm58174_write, NULL, NULL, nvr); +} + static void m24_kbd_poll(void *priv) { @@ -735,6 +921,7 @@ machine_xt_m24_init(const machine_t *model) { int ret; m24_kbd_t *m24_kbd; + nvr_t *nvr; ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_bios_version_1.44_low_even.bin", "roms/machines/m24/olivetti_m24_bios_version_1.44_high_odd.bin", @@ -755,13 +942,18 @@ machine_xt_m24_init(const machine_t *model) /* Address 66-67 = mainboard dip-switch settings */ io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); - /* FIXME: make sure this is correct?? */ - device_add(&at_nvr_device); - standalone_gameport_type = &gameport_device; nmi_init(); + /* Allocate an NVR for this machine. */ + nvr = (nvr_t *) malloc(sizeof(nvr_t)); + if (nvr == NULL) + return (0); + memset(nvr, 0x00, sizeof(nvr_t)); + + mm58174_init(nvr, model->nvrmask + 1); + video_reset(gfxcard); if (gfxcard == VID_INTERNAL) From 470aaccccc7903757f28adb14a918f77fdce5369 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Oct 2022 23:51:22 +0600 Subject: [PATCH 3/3] Fix Linux build --- src/machine/m_xt_olivetti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 014b13d12..a7d68c1f6 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include <86box/86box.h>