Applied all relevant PCem commits;
Extensively cleaned up and changed the CD-ROM code; Removed CD-ROM IOCTTL (it was causing performance and stability issues); Turned a lot of things into device_t's; Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem; Numerous FDC fixes for the PS/1 Model 2121; NVR changes ported from Varcem; The PCap code no longer requires libpcap to be compiled; Numerous fixes to various SCSI controllers; Updated NukedOPL to 1.8; Fixes to OpenAL initialization and closing, should give less Audio issues now; Revorked parts of the common (S)VGA code (also based on code from QEMU); Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there); Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future); In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit; Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's); Extensively reworked the IDE code and fixed quite a few bugs; Fixes to XT MFM, AT MFM, and AT ESDI code; Some changes to XTIDE and MCA ESDI code; Some fixes to the CD-ROM image handler.
This commit is contained in:
315
src/nvr.c
315
src/nvr.c
@@ -8,9 +8,7 @@
|
||||
*
|
||||
* Implement a generic NVRAM/CMOS/RTC device.
|
||||
*
|
||||
* NOTE: I should re-do 'intclk' using a TM struct.
|
||||
*
|
||||
* Version: @(#)nvr.c 1.0.3 2018/03/19
|
||||
* Version: @(#)nvr.c 1.0.6 2018/04/11
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
@@ -65,23 +63,11 @@
|
||||
#include "nvr.h"
|
||||
|
||||
|
||||
/* Define the internal clock. */
|
||||
typedef struct {
|
||||
int16_t year;
|
||||
int8_t sec;
|
||||
int8_t min;
|
||||
int8_t hour;
|
||||
int8_t mday;
|
||||
int8_t mon;
|
||||
} intclk_t;
|
||||
|
||||
|
||||
int enable_sync; /* configuration variable: enable time sync */
|
||||
int nvr_dosave; /* NVR is dirty, needs saved */
|
||||
|
||||
|
||||
static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
static intclk_t intclk;
|
||||
static struct tm intclk;
|
||||
static nvr_t *saved_nvr = NULL;
|
||||
|
||||
|
||||
@@ -113,25 +99,23 @@ static void
|
||||
rtc_tick(void)
|
||||
{
|
||||
/* Ping the internal clock. */
|
||||
if (++intclk.sec == 60) {
|
||||
intclk.sec = 0;
|
||||
intclk.min++;
|
||||
}
|
||||
if (intclk.min == 60) {
|
||||
intclk.min = 0;
|
||||
intclk.hour++;
|
||||
}
|
||||
if (intclk.hour == 24) {
|
||||
intclk.hour = 0;
|
||||
intclk.mday++;
|
||||
}
|
||||
if (intclk.mday == (nvr_get_days(intclk.mon, intclk.year) + 1)) {
|
||||
intclk.mday = 1;
|
||||
intclk.mon++;
|
||||
}
|
||||
if (intclk.mon == 13) {
|
||||
intclk.mon = 1;
|
||||
intclk.year++;
|
||||
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;
|
||||
intclk.tm_mon++;
|
||||
if (++intclk.tm_mon == 13) {
|
||||
intclk.tm_mon = 1;
|
||||
intclk.tm_year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,9 +152,9 @@ nvr_init(nvr_t *nvr)
|
||||
|
||||
/* Set up the NVR file's name. */
|
||||
sprintf(temp, "%s.nvr", machine_get_internal_name());
|
||||
c = strlen(temp)+1;
|
||||
nvr->fn = (wchar_t *)malloc(c*sizeof(wchar_t));
|
||||
mbstowcs(nvr->fn, temp, c);
|
||||
c = strlen(temp);
|
||||
nvr->fn = (wchar_t *)malloc((c + 1) * sizeof(wchar_t));
|
||||
mbstowcs(nvr->fn, temp, c + 1);
|
||||
|
||||
/* Initialize the internal clock as needed. */
|
||||
memset(&intclk, 0x00, sizeof(intclk));
|
||||
@@ -183,8 +167,8 @@ nvr_init(nvr_t *nvr)
|
||||
nvr_time_set(tm);
|
||||
} else {
|
||||
/* Reset the internal clock to 1980/01/01 00:00. */
|
||||
intclk.mon = 1;
|
||||
intclk.year = 1980;
|
||||
intclk.tm_mon = 1;
|
||||
intclk.tm_year = 1980;
|
||||
}
|
||||
|
||||
/* Set up our timer. */
|
||||
@@ -201,124 +185,7 @@ nvr_init(nvr_t *nvr)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load an NVR from file.
|
||||
*
|
||||
* This function does two things, really. It clears and initializes
|
||||
* the RTC and NVRAM areas, sets up defaults for the RTC part, and
|
||||
* then attempts to load data from a saved file.
|
||||
*
|
||||
* Either way, after that, it will continue to configure the local
|
||||
* RTC to operate, so it can update either the local RTC, and/or
|
||||
* the one supplied by a client.
|
||||
*/
|
||||
int
|
||||
nvr_load(void)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* Make sure we have been initialized. */
|
||||
if (saved_nvr == NULL) return(0);
|
||||
|
||||
/* Clear out any old data. */
|
||||
memset(saved_nvr->regs, 0xff, sizeof(saved_nvr->regs));
|
||||
|
||||
/* Set the defaults. */
|
||||
if (saved_nvr->reset != NULL)
|
||||
saved_nvr->reset(saved_nvr);
|
||||
|
||||
/* Load the (relevant) part of the NVR contents. */
|
||||
if (saved_nvr->size != 0) {
|
||||
pclog("NVR: loading from '%ls'\n", nvr_path(saved_nvr->fn));
|
||||
f = plat_fopen(nvr_path(saved_nvr->fn), L"rb");
|
||||
if (f != NULL) {
|
||||
/* Read NVR contents from file. */
|
||||
(void)fread(saved_nvr->regs, saved_nvr->size, 1, f);
|
||||
(void)fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (romset == ROM_T1000)
|
||||
t1000_nvr_load();
|
||||
else if (romset == ROM_T1200)
|
||||
t1200_nvr_load();
|
||||
|
||||
/* Get the local RTC running! */
|
||||
if (saved_nvr->start != NULL)
|
||||
saved_nvr->start(saved_nvr);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Save the current NVR to a file. */
|
||||
int
|
||||
nvr_save(void)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* Make sure we have been initialized. */
|
||||
if (saved_nvr == NULL) return(0);
|
||||
|
||||
if (saved_nvr->size != 0) {
|
||||
pclog("NVR: saving to '%ls'\n", nvr_path(saved_nvr->fn));
|
||||
f = plat_fopen(nvr_path(saved_nvr->fn), L"wb");
|
||||
if (f != NULL) {
|
||||
/* Save NVR contents to file. */
|
||||
(void)fwrite(saved_nvr->regs, saved_nvr->size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (romset == ROM_T1000)
|
||||
t1000_nvr_save();
|
||||
else if (romset == ROM_T1200)
|
||||
t1200_nvr_save();
|
||||
|
||||
/* Device is clean again. */
|
||||
nvr_dosave = 0;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Get current time from internal clock. */
|
||||
void
|
||||
nvr_time_get(struct tm *tm)
|
||||
{
|
||||
int8_t dom, mon, sum, wd;
|
||||
int16_t cent, yr;
|
||||
|
||||
tm->tm_sec = intclk.sec;
|
||||
tm->tm_min = intclk.min;
|
||||
tm->tm_hour = intclk.hour;
|
||||
dom = intclk.mday;
|
||||
mon = intclk.mon;
|
||||
yr = (intclk.year % 100);
|
||||
cent = ((intclk.year - yr) / 100) % 4;
|
||||
sum = dom+mon+yr+cent;
|
||||
wd = ((sum + 6) % 7);
|
||||
tm->tm_wday = wd;
|
||||
tm->tm_mday = intclk.mday;
|
||||
tm->tm_mon = (intclk.mon - 1);
|
||||
tm->tm_year = (intclk.year - 1900);
|
||||
}
|
||||
|
||||
|
||||
/* Set internal clock time. */
|
||||
void
|
||||
nvr_time_set(struct tm *tm)
|
||||
{
|
||||
intclk.sec = tm->tm_sec;
|
||||
intclk.min = tm->tm_min;
|
||||
intclk.hour = tm->tm_hour;
|
||||
intclk.mday = tm->tm_mday;
|
||||
intclk.mon = (tm->tm_mon + 1);
|
||||
intclk.year = (tm->tm_year + 1900);
|
||||
}
|
||||
|
||||
|
||||
/* Get an absolute path to the NVR folder. */
|
||||
/* Get path to the NVR folder. */
|
||||
wchar_t *
|
||||
nvr_path(wchar_t *str)
|
||||
{
|
||||
@@ -341,6 +208,138 @@ nvr_path(wchar_t *str)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load an NVR from file.
|
||||
*
|
||||
* This function does two things, really. It clears and initializes
|
||||
* the RTC and NVRAM areas, sets up defaults for the RTC part, and
|
||||
* then attempts to load data from a saved file.
|
||||
*
|
||||
* Either way, after that, it will continue to configure the local
|
||||
* RTC to operate, so it can update either the local RTC, and/or
|
||||
* the one supplied by a client.
|
||||
*/
|
||||
int
|
||||
nvr_load(void)
|
||||
{
|
||||
wchar_t *path;
|
||||
FILE *fp;
|
||||
|
||||
/* Make sure we have been initialized. */
|
||||
if (saved_nvr == NULL) return(0);
|
||||
|
||||
/* Clear out any old data. */
|
||||
memset(saved_nvr->regs, 0x00, sizeof(saved_nvr->regs));
|
||||
|
||||
/* Set the defaults. */
|
||||
if (saved_nvr->reset != NULL)
|
||||
saved_nvr->reset(saved_nvr);
|
||||
|
||||
/* Load the (relevant) part of the NVR contents. */
|
||||
if (saved_nvr->size != 0) {
|
||||
path = nvr_path(saved_nvr->fn);
|
||||
pclog("NVR: loading from '%ls'\n", path);
|
||||
fp = plat_fopen(path, L"rb");
|
||||
if (fp != NULL) {
|
||||
/* Read NVR contents from file. */
|
||||
(void)fread(saved_nvr->regs, saved_nvr->size, 1, fp);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (romset == ROM_T1000)
|
||||
t1000_nvr_load();
|
||||
else if (romset == ROM_T1200)
|
||||
t1200_nvr_load();
|
||||
|
||||
/* Get the local RTC running! */
|
||||
if (saved_nvr->start != NULL)
|
||||
saved_nvr->start(saved_nvr);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Save the current NVR to a file. */
|
||||
int
|
||||
nvr_save(void)
|
||||
{
|
||||
wchar_t *path;
|
||||
FILE *fp;
|
||||
|
||||
/* Make sure we have been initialized. */
|
||||
if (saved_nvr == NULL) return(0);
|
||||
|
||||
if (saved_nvr->size != 0) {
|
||||
path = nvr_path(saved_nvr->fn);
|
||||
pclog("NVR: saving to '%ls'\n", path);
|
||||
fp = plat_fopen(path, L"wb");
|
||||
if (fp != NULL) {
|
||||
/* Save NVR contents to file. */
|
||||
(void)fwrite(saved_nvr->regs, saved_nvr->size, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (romset == ROM_T1000)
|
||||
t1000_nvr_save();
|
||||
else if (romset == ROM_T1200)
|
||||
t1200_nvr_save();
|
||||
|
||||
/* Device is clean again. */
|
||||
nvr_dosave = 0;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nvr_period_recalc(void)
|
||||
{
|
||||
/* Make sure we have been initialized. */
|
||||
if (saved_nvr == NULL) return;
|
||||
|
||||
if (saved_nvr->size != 0)
|
||||
saved_nvr->recalc(saved_nvr);
|
||||
}
|
||||
|
||||
|
||||
/* Get current time from internal clock. */
|
||||
void
|
||||
nvr_time_get(struct tm *tm)
|
||||
{
|
||||
int8_t dom, mon, sum, wd;
|
||||
int16_t cent, yr;
|
||||
|
||||
tm->tm_sec = intclk.tm_sec;
|
||||
tm->tm_min = intclk.tm_min;
|
||||
tm->tm_hour = intclk.tm_hour;
|
||||
dom = intclk.tm_mday;
|
||||
mon = intclk.tm_mon;
|
||||
yr = (intclk.tm_year % 100);
|
||||
cent = ((intclk.tm_year - yr) / 100) % 4;
|
||||
sum = dom+mon+yr+cent;
|
||||
wd = ((sum + 6) % 7);
|
||||
tm->tm_wday = wd;
|
||||
tm->tm_mday = intclk.tm_mday;
|
||||
tm->tm_mon = (intclk.tm_mon - 1);
|
||||
tm->tm_year = (intclk.tm_year - 1900);
|
||||
}
|
||||
|
||||
|
||||
/* Set internal clock time. */
|
||||
void
|
||||
nvr_time_set(struct tm *tm)
|
||||
{
|
||||
intclk.tm_sec = tm->tm_sec;
|
||||
intclk.tm_min = tm->tm_min;
|
||||
intclk.tm_hour = tm->tm_hour;
|
||||
intclk.tm_mday = tm->tm_mday;
|
||||
intclk.tm_mon = (tm->tm_mon + 1);
|
||||
intclk.tm_year = (tm->tm_year + 1900);
|
||||
}
|
||||
|
||||
|
||||
/* Open or create a file in the NVR area. */
|
||||
FILE *
|
||||
nvr_fopen(wchar_t *str, wchar_t *mode)
|
||||
|
||||
Reference in New Issue
Block a user