RTC changes :
- Replace linux-time.c and win-time.c with universal rtc.c code - Add RTC binary and 12-hour modes, century register, and alarm support - Cleaned up nvr.c a bit - Fix handling of update ended flag - Add ability to disable host clock synchronisation Changes from Battler and Mahod.
This commit is contained in:
parent
9f4b159121
commit
074de51639
14 changed files with 561 additions and 135 deletions
|
|
@ -21,8 +21,8 @@ codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing
|
|||
dac.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
|
||||
headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c joystick_standard.c joystick_sw_pad.c \
|
||||
keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
|
||||
linux-time.c lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c \
|
||||
olivetti_m24.c opti.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c rom.c scat.c serial.c sis496.c sound.c \
|
||||
lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \
|
||||
opti.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c rom.c rtc.c scat.c serial.c sis496.c sound.c \
|
||||
sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_cms.c sound_emu8k.c sound_gus.c \
|
||||
sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \
|
||||
sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c thread-pthread.c \
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
|
|||
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \
|
||||
i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \
|
||||
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
|
||||
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||
scat.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \
|
||||
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
|
||||
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
|
||||
|
|
@ -20,7 +20,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
|
|||
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
|
||||
vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
|
||||
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
DBOBJ = dbopl.o vid_cga_comp.o
|
||||
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
|
|||
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \
|
||||
i430vx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \
|
||||
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
|
||||
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||
scat.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \
|
||||
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
|
||||
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
|
||||
|
|
@ -20,7 +20,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad
|
|||
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
|
||||
vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
|
||||
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
DBOBJ = dbopl.o vid_cga_comp.o
|
||||
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
||||
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include "ibm.h"
|
||||
#include "nvr.h"
|
||||
|
||||
void time_get(char *nvrram)
|
||||
{
|
||||
int c,d;
|
||||
uint8_t baknvr[10];
|
||||
time_t cur_time;
|
||||
struct tm cur_time_tm;
|
||||
|
||||
memcpy(baknvr,nvrram,10);
|
||||
|
||||
cur_time = time(NULL);
|
||||
localtime_r(&cur_time, &cur_time_tm);
|
||||
|
||||
d = cur_time_tm.tm_sec % 10;
|
||||
c = cur_time_tm.tm_sec / 10;
|
||||
nvrram[0] = d | (c << 4);
|
||||
d = cur_time_tm.tm_min % 10;
|
||||
c = cur_time_tm.tm_min / 10;
|
||||
nvrram[2] = d | (c << 4);
|
||||
d = cur_time_tm.tm_hour % 10;
|
||||
c = cur_time_tm.tm_hour / 10;
|
||||
nvrram[4] = d | (c << 4);
|
||||
d = cur_time_tm.tm_wday % 10;
|
||||
c = cur_time_tm.tm_wday / 10;
|
||||
nvrram[6] = d | (c << 4);
|
||||
d = cur_time_tm.tm_mday % 10;
|
||||
c = cur_time_tm.tm_mday / 10;
|
||||
nvrram[7] = d | (c << 4);
|
||||
d = cur_time_tm.tm_mon % 10;
|
||||
c = cur_time_tm.tm_mon / 10;
|
||||
nvrram[8] = d | (c << 4);
|
||||
d = cur_time_tm.tm_year % 10;
|
||||
c = (cur_time_tm.tm_year / 10) % 10;
|
||||
nvrram[9] = d | (c << 4);
|
||||
if (baknvr[0] != nvrram[0] ||
|
||||
baknvr[2] != nvrram[2] ||
|
||||
baknvr[4] != nvrram[4] ||
|
||||
baknvr[6] != nvrram[6] ||
|
||||
baknvr[7] != nvrram[7] ||
|
||||
baknvr[8] != nvrram[8] ||
|
||||
baknvr[9] != nvrram[9])
|
||||
nvrram[0xA] |= 0x80;
|
||||
}
|
||||
|
||||
146
src/nvr.c
146
src/nvr.c
|
|
@ -4,6 +4,7 @@
|
|||
#include "nvr.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "rtc.h"
|
||||
|
||||
int oldromset;
|
||||
int nvrmask=63;
|
||||
|
|
@ -23,7 +24,7 @@ void nvr_recalc()
|
|||
{
|
||||
int c;
|
||||
int newrtctime;
|
||||
c=1<<((nvrram[0xA]&0xF)-1);
|
||||
c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
|
||||
newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT));
|
||||
if (rtctime>newrtctime) rtctime=newrtctime;
|
||||
}
|
||||
|
|
@ -31,64 +32,136 @@ void nvr_recalc()
|
|||
void nvr_rtc(void *p)
|
||||
{
|
||||
int c;
|
||||
if (!(nvrram[0xA]&0xF))
|
||||
if (!(nvrram[RTC_REGA] & RTC_RS))
|
||||
{
|
||||
rtctime=0x7fffffff;
|
||||
return;
|
||||
}
|
||||
c=1<<((nvrram[0xA]&0xF)-1);
|
||||
c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
|
||||
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
|
||||
// pclog("RTCtime now %f\n",rtctime);
|
||||
nvrram[0xC] |= 0x40;
|
||||
if (nvrram[0xB]&0x40)
|
||||
nvrram[RTC_REGC] |= RTC_PF;
|
||||
if (nvrram[RTC_REGB] & RTC_PIE)
|
||||
{
|
||||
nvrram[0xC]|=0x80;
|
||||
nvrram[RTC_REGC] |= RTC_IRQF;
|
||||
if (AMSTRAD) picint(2);
|
||||
else picint(0x100);
|
||||
// pclog("RTC int\n");
|
||||
}
|
||||
}
|
||||
|
||||
int nvr_update_status = 0;
|
||||
|
||||
#define ALARM_DONTCARE 0xc0
|
||||
|
||||
int nvr_check_alarm(int nvraddr)
|
||||
{
|
||||
return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE);
|
||||
}
|
||||
|
||||
int nvr_update_end_count = 0;
|
||||
|
||||
void nvr_update_end(void *p)
|
||||
{
|
||||
if (!(nvrram[RTC_REGB] & RTC_SET))
|
||||
{
|
||||
getnvrtime();
|
||||
/* Clear update status. */
|
||||
nvr_update_status = 0;
|
||||
|
||||
if (nvr_check_alarm(RTC_SECONDS) && nvr_check_alarm(RTC_MINUTES) && nvr_check_alarm(RTC_HOURS))
|
||||
{
|
||||
nvrram[RTC_REGC] |= RTC_AF;
|
||||
if (nvrram[RTC_REGB] & RTC_AIE)
|
||||
{
|
||||
nvrram[RTC_REGC] |= RTC_IRQF;
|
||||
if (AMSTRAD) picint(2);
|
||||
else picint(0x100);
|
||||
}
|
||||
}
|
||||
|
||||
/* The flag and interrupt should be issued on update ended, not started. */
|
||||
nvrram[RTC_REGC] |= RTC_UF;
|
||||
if (nvrram[RTC_REGB] & RTC_UIE)
|
||||
{
|
||||
nvrram[RTC_REGC] |= RTC_IRQF;
|
||||
if (AMSTRAD) picint(2);
|
||||
else picint(0x100);
|
||||
}
|
||||
}
|
||||
|
||||
// pclog("RTC onesec\n");
|
||||
|
||||
nvr_update_end_count = 0;
|
||||
}
|
||||
|
||||
void nvr_onesec(void *p)
|
||||
{
|
||||
nvr_onesec_cnt++;
|
||||
if (nvr_onesec_cnt >= 100)
|
||||
{
|
||||
nvr_onesec_cnt = 0;
|
||||
nvrram[0xC] |= 0x10;
|
||||
if (nvrram[0xB] & 0x10)
|
||||
if (!(nvrram[RTC_REGB] & RTC_SET))
|
||||
{
|
||||
nvrram[0xC] |= 0x80;
|
||||
if (AMSTRAD) picint(2);
|
||||
else picint(0x100);
|
||||
nvr_update_status = RTC_UIP;
|
||||
/* If sync is disabled, move internal clock ahead by 1 second. */
|
||||
if (!enable_sync)
|
||||
rtc_tick();
|
||||
|
||||
nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC);
|
||||
}
|
||||
// pclog("RTC onesec\n");
|
||||
}
|
||||
nvr_onesec_time += (int)(10000 * TIMER_USEC);
|
||||
}
|
||||
|
||||
void writenvr(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
int c;
|
||||
int c, old;
|
||||
// printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins);
|
||||
if (addr&1)
|
||||
{
|
||||
if (nvraddr==RTC_REGC || nvraddr==RTC_REGD)
|
||||
return; /* Registers C and D are read-only. There's no reason to continue. */
|
||||
// if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins);
|
||||
if (nvraddr >= 0xe && nvrram[nvraddr] != val)
|
||||
if (nvraddr > RTC_REGD && nvrram[nvraddr] != val)
|
||||
nvr_dosave = 1;
|
||||
if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val;
|
||||
|
||||
if (nvraddr==0xA)
|
||||
old = nvrram[nvraddr];
|
||||
nvrram[nvraddr]=val;
|
||||
|
||||
if (nvraddr == RTC_REGA)
|
||||
{
|
||||
// pclog("NVR rate %i\n",val&0xF);
|
||||
if (val&0xF)
|
||||
if (val & RTC_RS)
|
||||
{
|
||||
c=1<<((val&0xF)-1);
|
||||
c = 1 << ((val & RTC_RS) - 1);
|
||||
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
|
||||
}
|
||||
else
|
||||
rtctime = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nvraddr == RTC_REGB)
|
||||
{
|
||||
if (((old ^ val) & RTC_SET) && (val & RTC_SET))
|
||||
{
|
||||
nvrram[RTC_REGA] &= ~RTC_UIP; /* This has to be done according to the datasheet. */
|
||||
nvrram[RTC_REGB] &= ~RTC_UIE; /* This also has to happen per the specification. */
|
||||
}
|
||||
}
|
||||
|
||||
if ((nvraddr < RTC_REGA) || (nvraddr == RTC_CENTURY))
|
||||
{
|
||||
if ((nvraddr != 1) && (nvraddr != 3) && (nvraddr != 5))
|
||||
{
|
||||
if ((old != val) && !enable_sync)
|
||||
{
|
||||
time_update(nvrram, nvraddr);
|
||||
nvr_dosave = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else nvraddr=val&nvrmask;
|
||||
}
|
||||
|
|
@ -99,20 +172,16 @@ uint8_t readnvr(uint16_t addr, void *priv)
|
|||
// printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
|
||||
if (addr&1)
|
||||
{
|
||||
if (nvraddr<=0xA) getnvrtime();
|
||||
if (nvraddr==0xD) nvrram[0xD]|=0x80;
|
||||
if (nvraddr==0xA)
|
||||
{
|
||||
temp=nvrram[0xA];
|
||||
nvrram[0xA]&=~0x80;
|
||||
return temp;
|
||||
}
|
||||
if (nvraddr==0xC)
|
||||
if (nvraddr == RTC_REGA)
|
||||
return ((nvrram[RTC_REGA] & 0x7F) | nvr_update_status);
|
||||
if (nvraddr == RTC_REGD)
|
||||
nvrram[RTC_REGD] |= RTC_VRT;
|
||||
if (nvraddr == RTC_REGC)
|
||||
{
|
||||
if (AMSTRAD) picintc(2);
|
||||
else picintc(0x100);
|
||||
temp=nvrram[0xC];
|
||||
nvrram[0xC]=0;
|
||||
temp = nvrram[RTC_REGC];
|
||||
nvrram[RTC_REGC] = 0;
|
||||
return temp;
|
||||
}
|
||||
// if (AMIBIOS && nvraddr==0x36) return 0;
|
||||
|
|
@ -161,13 +230,22 @@ void loadnvr()
|
|||
if (!f)
|
||||
{
|
||||
memset(nvrram,0xFF,128);
|
||||
if (!enable_sync)
|
||||
{
|
||||
nvrram[RTC_SECONDS] = nvrram[RTC_MINUTES] = nvrram[RTC_HOURS] = 0;
|
||||
nvrram[RTC_DOM] = nvrram[RTC_MONTH] = 1;
|
||||
nvrram[RTC_YEAR] = BCD(80);
|
||||
nvrram[RTC_CENTURY] = BCD(19);
|
||||
nvrram[RTC_REGB] = RTC_2412;
|
||||
}
|
||||
return;
|
||||
}
|
||||
fread(nvrram,128,1,f);
|
||||
if (!enable_sync) time_update(nvrram, 0xFF); /* Update the internal clock state based on the NVR registers. */
|
||||
fclose(f);
|
||||
nvrram[0xA]=6;
|
||||
nvrram[0xB]=0;
|
||||
c=1<<((6&0xF)-1);
|
||||
nvrram[RTC_REGA] = 6;
|
||||
nvrram[RTC_REGB] = RTC_2412;
|
||||
c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
|
||||
rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
|
||||
}
|
||||
void savenvr()
|
||||
|
|
@ -212,4 +290,6 @@ void nvr_init()
|
|||
io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL);
|
||||
timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL);
|
||||
timer_add(nvr_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL);
|
||||
timer_add(nvr_update_end, &nvr_update_end_count, &nvr_update_end_count, NULL);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
void nvr_init();
|
||||
|
||||
extern int enable_sync;
|
||||
|
||||
extern int nvr_dosave;
|
||||
|
||||
void time_get(char *nvrram);
|
||||
|
|
|
|||
5
src/pc.c
5
src/pc.c
|
|
@ -97,6 +97,7 @@ void fatal(const char *format, ...)
|
|||
va_end(ap);
|
||||
fputs(buf,pclogf);
|
||||
fflush(pclogf);
|
||||
savenvr();
|
||||
dumppic();
|
||||
dumpregs();
|
||||
exit(-1);
|
||||
|
|
@ -679,6 +680,8 @@ void loadconfig(char *fn)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
enable_sync = config_get_int(NULL, "enable_sync", 1);
|
||||
}
|
||||
|
||||
void saveconfig()
|
||||
|
|
@ -764,6 +767,8 @@ void saveconfig()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
config_set_int(NULL, "enable_sync", enable_sync);
|
||||
|
||||
config_save(config_file_default);
|
||||
}
|
||||
|
|
|
|||
11
src/pc.rc
11
src/pc.rc
|
|
@ -57,13 +57,13 @@ BEGIN
|
|||
END
|
||||
END
|
||||
|
||||
ConfigureDlg DIALOGEX 0, 0, 232+40, 292+40+40
|
||||
ConfigureDlg DIALOGEX 0, 0, 232+40, 308+40+40
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Configure PCem"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,64,308+40,50,14, WS_TABSTOP
|
||||
PUSHBUTTON "Cancel",IDCANCEL,128,308+40,50,14, WS_TABSTOP
|
||||
DEFPUSHBUTTON "OK",IDOK,64,324+40,50,14, WS_TABSTOP
|
||||
PUSHBUTTON "Cancel",IDCANCEL,128,324+40,50,14, WS_TABSTOP
|
||||
COMBOBOX IDC_COMBO1,62,16,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMBOVID,62,36,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "Configure", IDC_CONFIGUREVID, 224, 36, 40, 14, WS_TABSTOP
|
||||
|
|
@ -81,8 +81,9 @@ BEGIN
|
|||
CONTROL "Gravis Ultrasound",IDC_CHECKGUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,288,118,10
|
||||
CONTROL "Innovation SSI-2001",IDC_CHECKSSI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,304,118,10
|
||||
CONTROL "Composite CGA",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,320,118,10
|
||||
CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,336,118,10
|
||||
PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 336, 40, 14, WS_TABSTOP
|
||||
CONTROL "Synchronise time to host clock",IDC_CHECKSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,336,118,10
|
||||
CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,352,118,10
|
||||
PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 352, 40, 14, WS_TABSTOP
|
||||
LTEXT "Machine :",IDC_STATIC,15,16,40,10
|
||||
LTEXT "Video :",IDC_STATIC,15,36,34,10
|
||||
LTEXT "CPU type :",IDC_STATIC,15,56,34,10
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#define IDC_CHECKSSI 1015
|
||||
#define IDC_CHECKVOODOO 1016
|
||||
#define IDC_CHECKDYNAREC 1017
|
||||
#define IDC_CHECKSYNC 1018
|
||||
#define IDC_STATIC 1020
|
||||
#define IDC_EDIT1 1030
|
||||
#define IDC_EDIT2 1031
|
||||
|
|
|
|||
244
src/rtc.c
Normal file
244
src/rtc.c
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/* Emulation of:
|
||||
Dallas Semiconductor DS12C887 Real Time Clock
|
||||
|
||||
http://datasheets.maximintegrated.com/en/ds/DS12885-DS12C887A.pdf
|
||||
|
||||
http://dev-docs.atariforge.org/files/MC146818A_RTC_1984.pdf
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "nvr.h"
|
||||
#include "rtc.h"
|
||||
|
||||
int enable_sync;
|
||||
|
||||
struct
|
||||
{
|
||||
int sec;
|
||||
int min;
|
||||
int hour;
|
||||
int mday;
|
||||
int mon;
|
||||
int year;
|
||||
} internal_clock;
|
||||
|
||||
/* When the RTC was last updated */
|
||||
static time_t rtc_set_time = 0;
|
||||
|
||||
/* Table for days in each month */
|
||||
static int rtc_days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
/* Called to determine whether the year is leap or not */
|
||||
static int rtc_is_leap(int org_year)
|
||||
{
|
||||
if (org_year % 400 == 0) return 1;
|
||||
if (org_year % 100 == 0) return 0;
|
||||
if (org_year % 4 == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called to determine the days in the current month */
|
||||
static int rtc_get_days(int org_month, int org_year)
|
||||
{
|
||||
if (org_month != 2)
|
||||
return rtc_days_in_month[org_month];
|
||||
else
|
||||
return rtc_is_leap(org_year) ? 29 : 28;
|
||||
}
|
||||
|
||||
/* Called when the internal clock gets updated */
|
||||
static void rtc_recalc()
|
||||
{
|
||||
if (internal_clock.sec == 60)
|
||||
{
|
||||
internal_clock.sec = 0;
|
||||
internal_clock.min++;
|
||||
}
|
||||
if (internal_clock.min == 60)
|
||||
{
|
||||
internal_clock.min = 0;
|
||||
internal_clock.hour++;
|
||||
}
|
||||
if (internal_clock.hour == 24)
|
||||
{
|
||||
internal_clock.hour = 0;
|
||||
internal_clock.mday++;
|
||||
}
|
||||
if (internal_clock.mday == (rtc_get_days(internal_clock.mon, internal_clock.year) + 1))
|
||||
{
|
||||
internal_clock.mday = 1;
|
||||
internal_clock.mon++;
|
||||
}
|
||||
if (internal_clock.mon == 13)
|
||||
{
|
||||
internal_clock.mon = 1;
|
||||
internal_clock.year++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when ticking the second */
|
||||
void rtc_tick()
|
||||
{
|
||||
internal_clock.sec++;
|
||||
rtc_recalc();
|
||||
}
|
||||
|
||||
/* Called when modifying the NVR registers */
|
||||
void time_update(char *nvrram, int reg)
|
||||
{
|
||||
int temp;
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case RTC_SECONDS:
|
||||
internal_clock.sec = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_SECONDS] : DCB(nvrram[RTC_SECONDS]);
|
||||
break;
|
||||
case RTC_MINUTES:
|
||||
internal_clock.min = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MINUTES] : DCB(nvrram[RTC_MINUTES]);
|
||||
break;
|
||||
case RTC_HOURS:
|
||||
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);
|
||||
break;
|
||||
case RTC_DOM:
|
||||
internal_clock.mday = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_DOM] : DCB(nvrram[RTC_DOM]);
|
||||
break;
|
||||
case RTC_MONTH:
|
||||
internal_clock.mon = (nvrram[RTC_REGB] & RTC_DM) ? nvrram[RTC_MONTH] : DCB(nvrram[RTC_MONTH]);
|
||||
break;
|
||||
case RTC_YEAR:
|
||||
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;
|
||||
case RTC_CENTURY:
|
||||
if (nvrram[RTC_REGB] & RTC_DM)
|
||||
return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called to obtain the current day of the week based on the internal clock */
|
||||
static int time_week_day()
|
||||
{
|
||||
int day_of_month = internal_clock.mday;
|
||||
int month2 = internal_clock.mon;
|
||||
int year2 = internal_clock.year % 100;
|
||||
int century = ((internal_clock.year - year2) / 100) % 4;
|
||||
int sum = day_of_month + month2 + year2 + century;
|
||||
/* (Sum mod 7) gives 0 for Saturday, we need it for Sunday, so +6 for Saturday to get 6 and Sunday 0 */
|
||||
int raw_wd = ((sum + 6) % 7);
|
||||
return raw_wd;
|
||||
}
|
||||
|
||||
/* Called to get time into the internal clock */
|
||||
static void time_internal(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;
|
||||
}
|
||||
|
||||
static time_t cur_time;
|
||||
static struct tm *cur_time_tm;
|
||||
|
||||
/* Periodic RTC update function
|
||||
See also: nvr_onesec() in nvr.c
|
||||
*/
|
||||
void time_get(char *nvrram)
|
||||
{
|
||||
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;
|
||||
nvrram[RTC_MINUTES] = cur_time_tm->tm_min;
|
||||
nvrram[RTC_DOW] = cur_time_tm->tm_wday + 1;
|
||||
nvrram[RTC_DOM] = cur_time_tm->tm_mday;
|
||||
nvrram[RTC_MONTH] = cur_time_tm->tm_mon + 1;
|
||||
nvrram[RTC_YEAR] = cur_time_tm->tm_year % 100;
|
||||
|
||||
if (nvrram[RTC_REGB] & RTC_2412)
|
||||
{
|
||||
nvrram[RTC_HOURS] = cur_time_tm->tm_hour;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvrram[RTC_HOURS] = (cur_time_tm->tm_hour % 12) ? (cur_time_tm->tm_hour % 12) : 12;
|
||||
if (cur_time_tm->tm_hour > 11)
|
||||
nvrram[RTC_HOURS] |= RTC_AMPM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nvrram[RTC_SECONDS] = BCD(cur_time_tm->tm_sec);
|
||||
nvrram[RTC_MINUTES] = BCD(cur_time_tm->tm_min);
|
||||
nvrram[RTC_DOW] = BCD(cur_time_tm->tm_wday + 1);
|
||||
nvrram[RTC_DOM] = BCD(cur_time_tm->tm_mday);
|
||||
nvrram[RTC_MONTH] = BCD(cur_time_tm->tm_mon + 1);
|
||||
nvrram[RTC_YEAR] = BCD(cur_time_tm->tm_year % 100);
|
||||
|
||||
if (nvrram[RTC_REGB] & RTC_2412)
|
||||
{
|
||||
nvrram[RTC_HOURS] = BCD(cur_time_tm->tm_hour);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvrram[RTC_HOURS] = (cur_time_tm->tm_hour % 12) ? BCD(cur_time_tm->tm_hour % 12) : BCD(12);
|
||||
if (cur_time_tm->tm_hour > 11)
|
||||
nvrram[RTC_HOURS] |= RTC_AMPM;
|
||||
}
|
||||
}
|
||||
}
|
||||
172
src/rtc.h
Normal file
172
src/rtc.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#define BCD(X) (((X) % 10) | (((X) / 10) << 4))
|
||||
#define DCB(X) ((((X) & 0xF0) >> 4) * 10 + ((X) & 0x0F))
|
||||
|
||||
enum RTC_ADDR
|
||||
{
|
||||
RTC_SECONDS,
|
||||
RTC_ALARMSECONDS,
|
||||
RTC_MINUTES,
|
||||
RTC_ALARMMINUTES,
|
||||
RTC_HOURS,
|
||||
RTC_ALARMHOURS,
|
||||
RTC_DOW,
|
||||
RTC_DOM,
|
||||
RTC_MONTH,
|
||||
RTC_YEAR,
|
||||
RTC_REGA,
|
||||
RTC_REGB,
|
||||
RTC_REGC,
|
||||
RTC_REGD
|
||||
};
|
||||
|
||||
/* The century register at location 32h is a BCD register designed to automatically load the BCD value 20 as the year register changes from 99 to 00.
|
||||
The MSB of this register is not affected when the load of 20 occurs, and remains at the value written by the user. */
|
||||
#define RTC_CENTURY 0x32
|
||||
|
||||
/* When the 12-hour format is selected, the higher-order bit of the hours byte represents PM when it is logic 1. */
|
||||
#define RTC_AMPM 0b10000000
|
||||
|
||||
/* Register A bitflags */
|
||||
enum RTC_RA_BITS
|
||||
{
|
||||
/* Rate Selector (RS0)
|
||||
|
||||
These four rate-selection bits select one of the 13 taps on the 15-stage divider or disable the divider output.
|
||||
The tap selected can be used to generate an output square wave (SQW pin) and/or a periodic interrupt.
|
||||
The user can do one of the following:
|
||||
- Enable the interrupt with the PIE bit;
|
||||
- Enable the SQW output pin with the SQWE bit;
|
||||
- Enable both at the same time and the same rate; or
|
||||
- Enable neither.
|
||||
|
||||
Table 3 lists the periodic interrupt rates and the square wave frequencies that can be chosen with the RS bits.
|
||||
These four read/write bits are not affected by !RESET. */
|
||||
RTC_RS = 0b1111,
|
||||
/* DV0
|
||||
|
||||
These three bits are used to turn the oscillator on or off and to reset the countdown chain.
|
||||
A pattern of 010 is the only combination of bits that turn the oscillator on and allow the RTC to keep time.
|
||||
A pattern of 11x enables the oscillator but holds the countdown chain in reset.
|
||||
The next update occurs at 500ms after a pattern of 010 is written to DV0, DV1, and DV2. */
|
||||
RTC_DV0 = 0b1110000,
|
||||
/* Update-In-Progress (UIP)
|
||||
|
||||
This bit is a status flag that can be monitored. When the UIP bit is a 1, the update transfer occurs soon.
|
||||
When UIP is a 0, the update transfer does not occur for at least 244us.
|
||||
The time, calendar, and alarm information in RAM is fully available for access when the UIP bit is 0.
|
||||
The UIP bit is read-only and is not affected by !RESET.
|
||||
Writing the SET bit in Register B to a 1 inhibits any update transfer and clears the UIP status bit. */
|
||||
RTC_UIP = 0b10000000
|
||||
};
|
||||
|
||||
/* Register B bitflags */
|
||||
enum RTC_RB_BITS
|
||||
{
|
||||
/* Daylight Saving Enable (DSE)
|
||||
|
||||
This bit is a read/write bit that enables two daylight saving adjustments when DSE is set to 1.
|
||||
On the first Sunday in April (or the last Sunday in April in the MC146818A), the time increments from 1:59:59 AM to 3:00:00 AM.
|
||||
On the last Sunday in October when the time first reaches 1:59:59 AM, it changes to 1:00:00 AM.
|
||||
When DSE is enabled, the internal logic test for the first/last Sunday condition at midnight.
|
||||
If the DSE bit is not set when the test occurs, the daylight saving function does not operate correctly.
|
||||
These adjustments do not occur when the DSE bit is 0. This bit is not affected by internal functions or !RESET. */
|
||||
RTC_DSE = 0b1,
|
||||
/* 24/12
|
||||
|
||||
The 24/12 control bit establishes the format of the hours byte. A 1 indicates the 24-hour mode and a 0 indicates the 12-hour mode.
|
||||
This bit is read/write and is not affected by internal functions or !RESET. */
|
||||
RTC_2412 = 0b10,
|
||||
/* Data Mode (DM)
|
||||
|
||||
This bit indicates whether time and calendar information is in binary or BCD format.
|
||||
The DM bit is set by the program to the appropriate format and can be read as required.
|
||||
This bit is not modified by internal functions or !RESET. A 1 in DM signifies binary data, while a 0 in DM specifies BCD data. */
|
||||
RTC_DM = 0b100,
|
||||
/* Square-Wave Enable (SQWE)
|
||||
|
||||
When this bit is set to 1, a square-wave signal at the frequency set by the rate-selection bits RS3-RS0 is driven out on the SQW pin.
|
||||
When the SQWE bit is set to 0, the SQW pin is held low. SQWE is a read/write bit and is cleared by !RESET.
|
||||
SQWE is low if disabled, and is high impedance when VCC is below VPF. SQWE is cleared to 0 on !RESET. */
|
||||
RTC_SQWE = 0b1000,
|
||||
/* Update-Ended Interrupt Enable (UIE)
|
||||
|
||||
This bit is a read/write bit that enables the update-end flag (UF) bit in Register C to assert !IRQ.
|
||||
The !RESET pin going low or the SET bit going high clears the UIE bit.
|
||||
The internal functions of the device do not affect the UIE bit, but is cleared to 0 on !RESET. */
|
||||
RTC_UIE = 0b10000,
|
||||
/* Alarm Interrupt Enable (AIE)
|
||||
|
||||
This bit is a read/write bit that, when set to 1, permits the alarm flag (AF) bit in Register C to assert !IRQ.
|
||||
An alarm interrupt occurs for each second that the three time bytes equal the three alarm bytes, including a don't-care alarm code of binary 11XXXXXX.
|
||||
The AF bit does not initiate the !IRQ signal when the AIE bit is set to 0.
|
||||
The internal functions of the device do not affect the AIE bit, but is cleared to 0 on !RESET. */
|
||||
RTC_AIE = 0b100000,
|
||||
/* Periodic Interrupt Enable (PIE)
|
||||
|
||||
The PIE bit is a read/write bit that allows the periodic interrupt flag (PF) bit in Register C to drive the !IRQ pin low.
|
||||
When the PIE bit is set to 1, periodic interrupts are generated by driving the !IRQ pin low at a rate specified by the RS3-RS0 bits of Register A.
|
||||
A 0 in the PIE bit blocks the !IRQ output from being driven by a periodic interrupt, but the PF bit is still set at the periodic rate.
|
||||
PIE is not modified by any internal device functions, but is cleared to 0 on !RESET. */
|
||||
RTC_PIE = 0b1000000,
|
||||
/* SET
|
||||
|
||||
When the SET bit is 0, the update transfer functions normally by advancing the counts once per second.
|
||||
When the SET bit is written to 1, any update transfer is inhibited, and the program can initialize the time and calendar bytes without an update
|
||||
occurring in the midst of initializing. Read cycles can be executed in a similar manner. SET is a read/write bit and is not affected by !RESET or
|
||||
internal functions of the device. */
|
||||
RTC_SET = 0b10000000
|
||||
};
|
||||
|
||||
/* Register C bitflags */
|
||||
enum RTC_RC_BITS
|
||||
{
|
||||
/* Unused
|
||||
|
||||
These bits are unused in Register C. These bits always read 0 and cannot be written. */
|
||||
RTC_RC = 0b1111,
|
||||
/* Update-Ended Interrupt Flag (UF)
|
||||
|
||||
This bit is set after each update cycle. When the UIE bit is set to 1, the 1 in UF causes the IRQF bit to be a 1, which asserts the !IRQ pin.
|
||||
This bit can be cleared by reading Register C or with a !RESET. */
|
||||
RTC_UF = 0b10000,
|
||||
/* Alarm Interrupt Flag (AF)
|
||||
|
||||
A 1 in the AF bit indicates that the current time has matched the alarm time.
|
||||
If the AIE bit is also 1, the !IRQ pin goes low and a 1 appears in the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */
|
||||
RTC_AF = 0b100000,
|
||||
/* Periodic Interrupt Flag (PF)
|
||||
|
||||
This bit is read-only and is set to 1 when an edge is detected on the selected tap of the divider chain.
|
||||
The RS3 through RS0 bits establish the periodic rate. PF is set to 1 independent of the state of the PIE bit.
|
||||
When both PF and PIE are 1s, the !IRQ signal is active and sets the IRQF bit. This bit can be cleared by reading Register C or with a !RESET. */
|
||||
RTC_PF = 0b1000000,
|
||||
/* Interrupt Request Flag (IRQF)
|
||||
|
||||
The interrupt request flag (IRQF) is set to a 1 when one or more of the following are true:
|
||||
- PF == PIE == 1
|
||||
- AF == AIE == 1
|
||||
- UF == UIE == 1
|
||||
|
||||
Any time the IRQF bit is a 1, the !IRQ pin is driven low.
|
||||
All flag bits are cleared after Register C is read by the program or when the !RESET pin is low. */
|
||||
RTC_IRQF = 0b10000000
|
||||
};
|
||||
|
||||
/* Register D bitflags */
|
||||
enum RTC_RD_BITS
|
||||
{
|
||||
/* Unused
|
||||
|
||||
The remaining bits of Register D are not usable. They cannot be written and they always read 0. */
|
||||
RTC_RD = 0b1111111,
|
||||
/* Valid RAM and Time (VRT)
|
||||
|
||||
This bit indicates the condition of the battery connected to the VBAT pin. This bit is not writeable and should always be 1 when read.
|
||||
If a 0 is ever present, an exhausted internal lithium energy source is indicated and both the contents of the RTC data and RAM data are questionable.
|
||||
This bit is unaffected by !RESET. */
|
||||
RTC_VRT = 0b10000000
|
||||
};
|
||||
|
||||
void rtc_tick();
|
||||
void time_update(char *nvrram, int reg);
|
||||
void time_get(char *nvrram);
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include "fdd.h"
|
||||
#include "gameport.h"
|
||||
#include "model.h"
|
||||
#include "nvr.h"
|
||||
#include "resources.h"
|
||||
#include "sound.h"
|
||||
#include "video.h"
|
||||
|
|
@ -142,6 +143,9 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
h=GetDlgItem(hdlg, IDC_CHECK4);
|
||||
SendMessage(h, BM_SETCHECK, cga_comp, 0);
|
||||
|
||||
h=GetDlgItem(hdlg, IDC_CHECKSYNC);
|
||||
SendMessage(h, BM_SETCHECK, enable_sync, 0);
|
||||
|
||||
h=GetDlgItem(hdlg, IDC_CHECKVOODOO);
|
||||
SendMessage(h, BM_SETCHECK, voodoo_enabled, 0);
|
||||
|
||||
|
|
@ -277,6 +281,9 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
h = GetDlgItem(hdlg, IDC_CHECKSSI);
|
||||
temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_CHECKSYNC);
|
||||
enable_sync = SendMessage(h, BM_GETCHECK, 0, 0);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_CHECKVOODOO);
|
||||
temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0);
|
||||
|
||||
|
|
@ -302,6 +309,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
{
|
||||
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK)
|
||||
{
|
||||
savenvr();
|
||||
model = temp_model;
|
||||
romset = model_getromset();
|
||||
gfxcard = gfx;
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
#include <windows.h>
|
||||
#include "ibm.h"
|
||||
#include "nvr.h"
|
||||
|
||||
void time_get(char *nvrram)
|
||||
{
|
||||
SYSTEMTIME systemtime;
|
||||
int c, d;
|
||||
uint8_t baknvr[10];
|
||||
|
||||
memcpy(baknvr,nvrram,10);
|
||||
GetLocalTime(&systemtime);
|
||||
|
||||
d = systemtime.wSecond % 10;
|
||||
c = systemtime.wSecond / 10;
|
||||
nvrram[0] = d | (c << 4);
|
||||
d = systemtime.wMinute % 10;
|
||||
c = systemtime.wMinute / 10;
|
||||
nvrram[2] = d | (c << 4);
|
||||
d = systemtime.wHour % 10;
|
||||
c = systemtime.wHour / 10;
|
||||
nvrram[4] = d | (c << 4);
|
||||
d = systemtime.wDayOfWeek % 10;
|
||||
c = systemtime.wDayOfWeek / 10;
|
||||
nvrram[6] = d | (c << 4);
|
||||
d = systemtime.wDay % 10;
|
||||
c = systemtime.wDay / 10;
|
||||
nvrram[7] = d | (c << 4);
|
||||
d = systemtime.wMonth % 10;
|
||||
c = systemtime.wMonth / 10;
|
||||
nvrram[8] = d | (c << 4);
|
||||
d = systemtime.wYear % 10;
|
||||
c = (systemtime.wYear / 10) % 10;
|
||||
nvrram[9] = d | (c << 4);
|
||||
if (baknvr[0] != nvrram[0] ||
|
||||
baknvr[2] != nvrram[2] ||
|
||||
baknvr[4] != nvrram[4] ||
|
||||
baknvr[6] != nvrram[6] ||
|
||||
baknvr[7] != nvrram[7] ||
|
||||
baknvr[8] != nvrram[8] ||
|
||||
baknvr[9] != nvrram[9])
|
||||
nvrram[0xA]|=0x80;
|
||||
}
|
||||
|
|
@ -717,6 +717,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
|
|||
TerminateThread(mainthreadh,0);
|
||||
// pclog("Quited? %i\n",quited);
|
||||
// pclog("Closepc\n");
|
||||
savenvr();
|
||||
if (save_window_pos && window_remember)
|
||||
saveconfig();
|
||||
closepc();
|
||||
|
|
@ -877,18 +878,21 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
case IDM_FILE_RESET:
|
||||
pause=1;
|
||||
Sleep(100);
|
||||
savenvr();
|
||||
resetpc();
|
||||
pause=0;
|
||||
break;
|
||||
case IDM_FILE_HRESET:
|
||||
pause=1;
|
||||
Sleep(100);
|
||||
savenvr();
|
||||
resetpchard();
|
||||
pause=0;
|
||||
break;
|
||||
case IDM_FILE_RESET_CAD:
|
||||
pause=1;
|
||||
Sleep(100);
|
||||
savenvr();
|
||||
resetpc_cad();
|
||||
pause=0;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue