mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 01:25:33 -07:00
Another big change, this time to the NVR. It has been re-done, integrated with the RTC code, and is now ready to be used by other, non-AT-compatible systems, including an ISA card for PC/XT.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# Modified Makefile for Win32 (MinGW32) environment.
|
||||
#
|
||||
# Version: @(#)Makefile.mingw 1.0.51 2017/10/01
|
||||
# Version: @(#)Makefile.mingw 1.0.52 2017/10/02
|
||||
#
|
||||
# Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
# Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -224,8 +224,8 @@ endif
|
||||
|
||||
MAINOBJ := pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o \
|
||||
pit.o ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \
|
||||
device.o rtc.o nvr.o nvr_ps2.o intel.o intel_flash.o \
|
||||
intel_sio.o
|
||||
device.o nvr.o nvr_at.o nvr_ps2.o \
|
||||
intel.o intel_flash.o intel_sio.o
|
||||
|
||||
CPUOBJ := cpu.o 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o \
|
||||
codegen.o \
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the CD-ROM drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)cdrom.c 1.0.8 2017/10/01
|
||||
* Version: @(#)cdrom.c 1.0.9 2017/10/02
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
@@ -990,16 +990,16 @@ void cdrom_mode_sense_load(uint8_t id)
|
||||
switch(id)
|
||||
{
|
||||
case 0:
|
||||
f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"rb");
|
||||
f = _wfopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"rb");
|
||||
break;
|
||||
case 1:
|
||||
f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"rb");
|
||||
f = _wfopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"rb");
|
||||
break;
|
||||
case 2:
|
||||
f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"rb");
|
||||
f = _wfopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"rb");
|
||||
break;
|
||||
case 3:
|
||||
f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"rb");
|
||||
f = _wfopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"rb");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -1018,16 +1018,16 @@ void cdrom_mode_sense_save(uint8_t id)
|
||||
switch(id)
|
||||
{
|
||||
case 0:
|
||||
f = _wfopen(nvr_concat(L"cdrom_1_mode_sense.bin"), L"wb");
|
||||
f = _wfopen(nvr_path(L"cdrom_1_mode_sense.bin"), L"wb");
|
||||
break;
|
||||
case 1:
|
||||
f = _wfopen(nvr_concat(L"cdrom_2_mode_sense.bin"), L"wb");
|
||||
f = _wfopen(nvr_path(L"cdrom_2_mode_sense.bin"), L"wb");
|
||||
break;
|
||||
case 2:
|
||||
f = _wfopen(nvr_concat(L"cdrom_3_mode_sense.bin"), L"wb");
|
||||
f = _wfopen(nvr_path(L"cdrom_3_mode_sense.bin"), L"wb");
|
||||
break;
|
||||
case 3:
|
||||
f = _wfopen(nvr_concat(L"cdrom_4_mode_sense.bin"), L"wb");
|
||||
f = _wfopen(nvr_path(L"cdrom_4_mode_sense.bin"), L"wb");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
44
src/config.c
44
src/config.c
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Configuration file handler.
|
||||
*
|
||||
* Version: @(#)config.c 1.0.10 2017/10/01
|
||||
* Version: @(#)config.c 1.0.12 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -30,10 +30,10 @@
|
||||
#include <inttypes.h>
|
||||
#include "ibm.h"
|
||||
#include "cpu/cpu.h"
|
||||
#include "nvr.h"
|
||||
#include "config.h"
|
||||
#include "device.h"
|
||||
#include "lpt.h"
|
||||
#include "nvr.h"
|
||||
#include "cdrom/cdrom.h"
|
||||
#include "disk/hdd.h"
|
||||
#include "disk/hdc.h"
|
||||
@@ -493,7 +493,6 @@ static void
|
||||
load_machine(void)
|
||||
{
|
||||
char *cat = "Machine";
|
||||
wchar_t *wp;
|
||||
char *p;
|
||||
|
||||
p = config_get_string(cat, "machine", NULL);
|
||||
@@ -537,42 +536,15 @@ load_machine(void)
|
||||
mem_size = 1048576;
|
||||
}
|
||||
|
||||
memset(nvr_path, 0x00, sizeof(nvr_path));
|
||||
wp = config_get_wstring(cat, "nvr_path", L"");
|
||||
if (wp != NULL) {
|
||||
if (wcslen(wp) && (wcslen(wp) <= 992))
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
* NOTE:
|
||||
* Temporary hack to remove the absolute
|
||||
* path currently saved in most config
|
||||
* files. We should remove this before
|
||||
* finalizing this release! --FvK
|
||||
*/
|
||||
if (! wcsnicmp(wp, exe_path, wcslen(exe_path))) {
|
||||
/*
|
||||
* Yep, its absolute and prefixed
|
||||
* with the EXE path. Just strip
|
||||
* that off for now...
|
||||
*/
|
||||
wcscpy(nvr_path, &wp[wcslen(exe_path)]);
|
||||
} else
|
||||
#endif
|
||||
wcscpy(nvr_path, wp);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(nvr_path, L"nvr\\");
|
||||
}
|
||||
}
|
||||
else wcscpy(nvr_path, L"nvr\\");
|
||||
|
||||
cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0);
|
||||
|
||||
enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0);
|
||||
|
||||
enable_sync = !!config_get_int(cat, "enable_sync", 1);
|
||||
|
||||
/* Remove this after a while.. */
|
||||
if (config_get_string(cat, "nvr_path", NULL) != NULL)
|
||||
config_delete_var(cat, "nvr_path");
|
||||
}
|
||||
|
||||
|
||||
@@ -1433,7 +1405,7 @@ config_load(wchar_t *fn)
|
||||
|
||||
if (fn == NULL)
|
||||
fn = config_file_default;
|
||||
pclog("Loading config file '%S'..\n", fn);
|
||||
pclog("Loading config file '%ws'..\n", fn);
|
||||
i = config_read(fn);
|
||||
|
||||
if (i == 0)
|
||||
@@ -1667,8 +1639,6 @@ save_machine(void)
|
||||
config_set_int(cat, "mem_size", mem_size);
|
||||
}
|
||||
|
||||
config_set_wstring(cat, "nvr_path", nvr_path);
|
||||
|
||||
config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec);
|
||||
|
||||
if (enable_external_fpu == 0)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* x86 CPU segment emulation.
|
||||
*
|
||||
* Version: @(#)x86seg.c 1.0.1 2017/09/24
|
||||
* Version: @(#)x86seg.c 1.0.2 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "386_common.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
/*Controls whether the accessed bit in a descriptor is set when CS is loaded.*/
|
||||
#define CS_ACCESSED
|
||||
|
||||
@@ -63,7 +64,7 @@ void x86abort(const char *format, ...)
|
||||
vprintf(format, ap);
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
savenvr();
|
||||
nvr_save();
|
||||
dumpregs(1);
|
||||
fflush(stdout);
|
||||
exit(-1);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Generic floppy disk interface that communicates with the
|
||||
* other handlers.
|
||||
*
|
||||
* Version: @(#)floppy.c 1.0.4 2017/09/24
|
||||
* Version: @(#)floppy.c 1.0.5 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -153,7 +153,7 @@ void floppy_load(int drive, wchar_t *fn)
|
||||
}
|
||||
c++;
|
||||
}
|
||||
pclog_w(L"Couldn't load %s %s\n",fn,p);
|
||||
pclog("Couldn't load %ws %s\n",fn,p);
|
||||
drive_empty[drive] = 1;
|
||||
fdd_set_head(real_drive(drive), 0);
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* data in the form of FM/MFM-encoded transitions) which also
|
||||
* forms the core of the emulator's floppy disk emulation.
|
||||
*
|
||||
* Version: @(#)floppy_86f.c 1.0.4 2017/09/24
|
||||
* Version: @(#)floppy_86f.c 1.0.5 2017/10/02
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
@@ -3471,7 +3471,7 @@ void d86f_load(int drive, wchar_t *fn)
|
||||
|
||||
if (d86f[drive].is_compressed)
|
||||
{
|
||||
memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 256);
|
||||
memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256);
|
||||
memcpy(d86f[drive].original_file_name, fn, (wcslen(fn) << 1) + 2);
|
||||
|
||||
fclose(d86f[drive].f);
|
||||
@@ -3666,7 +3666,7 @@ void d86f_close(int drive)
|
||||
{
|
||||
wchar_t temp_file_name[2048];
|
||||
|
||||
memcpy(temp_file_name, drive ? nvr_concat(L"TEMP$$$1.$$$") : nvr_concat(L"TEMP$$$0.$$$"), 26);
|
||||
memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26);
|
||||
|
||||
if (d86f[drive].f)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
* !!!NOTE!!! The goal is to GET RID of this file. Do NOT add stuff !!
|
||||
*
|
||||
* Version: @(#)ibm.h 1.0.7 2017/10/01
|
||||
* Version: @(#)ibm.h 1.0.7 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -480,7 +480,6 @@ extern int gated,speakval,speakon;
|
||||
|
||||
extern wchar_t exe_path[1024];
|
||||
extern wchar_t cfg_path[1024];
|
||||
extern wchar_t nvr_path[1024];
|
||||
|
||||
|
||||
/*Keyboard*/
|
||||
@@ -586,8 +585,8 @@ extern int scale;
|
||||
|
||||
/* Function prototypes. */
|
||||
extern void pclog(const char *format, ...);
|
||||
extern void pclog_w(const wchar_t *format, ...);
|
||||
extern void fatal(const char *format, ...);
|
||||
extern wchar_t *pc_concat(wchar_t *str);
|
||||
extern void pc_init_modules(void);
|
||||
extern void pc_init(int argc, wchar_t *argv[]);
|
||||
extern void pc_close(void);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Implementation of the Intel 2 Mbit 8-bit flash devices.
|
||||
*
|
||||
* Version: @(#)intel_flash.c 1.0.3 2017/09/24
|
||||
* Version: @(#)intel_flash.c 1.0.4 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -193,7 +193,7 @@ void *intel_flash_init(uint8_t type)
|
||||
|
||||
wcscpy(flash_path, flash_name);
|
||||
|
||||
pclog_w(L"Flash path: %s\n", flash_name);
|
||||
pclog("Flash path: %ws\n", flash_name);
|
||||
|
||||
flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94;
|
||||
flash->invert_high_pin = (type & FLASH_INVERT);
|
||||
@@ -255,7 +255,7 @@ void *intel_flash_init(uint8_t type)
|
||||
flash->command = CMD_READ_ARRAY;
|
||||
flash->status = 0;
|
||||
|
||||
f = nvrfopen(flash_path, L"rb");
|
||||
f = nvr_fopen(flash_path, L"rb");
|
||||
if (f)
|
||||
{
|
||||
fread(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
|
||||
@@ -298,7 +298,7 @@ void intel_flash_close(void *p)
|
||||
FILE *f;
|
||||
flash_t *flash = (flash_t *)p;
|
||||
|
||||
f = nvrfopen(flash_path, L"wb");
|
||||
f = nvr_fopen(flash_path, L"wb");
|
||||
fwrite(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
|
||||
fwrite(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f);
|
||||
fwrite(&(flash->array[flash->block_start[BLOCK_DATA2]]), flash->block_len[BLOCK_DATA2], 1, f);
|
||||
|
||||
@@ -144,7 +144,10 @@ void machine_amstrad_init(void)
|
||||
mem_add_bios();
|
||||
amstrad_init();
|
||||
keyboard_amstrad_init();
|
||||
nvr_init();
|
||||
|
||||
/* FIXME: make sure this is correct? */
|
||||
nvr_at_init(1);
|
||||
|
||||
nmi_init();
|
||||
fdc_set_dskchg_activelow();
|
||||
if (joystick_type != 7)
|
||||
|
||||
@@ -30,7 +30,7 @@ void machine_at_init(void)
|
||||
pit_set_out_func(&pit, 1, pit_refresh_timer_at);
|
||||
dma16_init();
|
||||
keyboard_at_init();
|
||||
nvr_init();
|
||||
nvr_at_init(8);
|
||||
pic2_init();
|
||||
if (joystick_type != 7)
|
||||
device_add(&gameport_device);
|
||||
|
||||
@@ -42,7 +42,10 @@ void machine_olim24_init(void)
|
||||
machine_common_init();
|
||||
mem_add_bios();
|
||||
keyboard_olim24_init();
|
||||
nvr_init();
|
||||
|
||||
/* FIXME: make sure this is correct?? */
|
||||
nvr_at_init(8);
|
||||
|
||||
olivetti_m24_init();
|
||||
nmi_init();
|
||||
if (joystick_type != 7) device_add(&gameport_device);
|
||||
|
||||
@@ -348,7 +348,7 @@ static void machine_ps1_common_init(void)
|
||||
ide_init();
|
||||
}
|
||||
keyboard_at_init();
|
||||
nvr_init();
|
||||
nvr_at_init(8);
|
||||
pic2_init();
|
||||
if (romset != ROM_IBMPS1_2133)
|
||||
{
|
||||
|
||||
@@ -163,7 +163,7 @@ void machine_ps2_m30_286_init(void)
|
||||
pit_set_out_func(&pit, 1, pit_refresh_timer_at);
|
||||
dma16_init();
|
||||
keyboard_at_init();
|
||||
nvr_init();
|
||||
nvr_at_init(8);
|
||||
pic2_init();
|
||||
ps2board_init();
|
||||
fdc_set_dskchg_activelow();
|
||||
|
||||
@@ -813,7 +813,7 @@ static void machine_ps2_common_init(void)
|
||||
keyboard_at_init();
|
||||
keyboard_at_init_ps2();
|
||||
mouse_ps2_init();
|
||||
nvr_init();
|
||||
nvr_at_init(8);
|
||||
pic2_init();
|
||||
|
||||
pit_ps2_init();
|
||||
|
||||
95
src/nvr.h
95
src/nvr.h
@@ -6,32 +6,107 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* CMOS NVRAM emulation.
|
||||
* Definitions for a defacto-standard RTC/NVRAM device.
|
||||
*
|
||||
* Version: @(#)nvr.h 1.0.2 2017/06/19
|
||||
* Version: @(#)nvr.h 1.0.3 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Mahod,
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
* Copyright 2016-2017 Mahod.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_NVR_H
|
||||
# define EMU_NVR_H
|
||||
|
||||
|
||||
extern int enable_sync;
|
||||
extern int nvr_dosave;
|
||||
/* Conversion from BCD to Binary and vice versa. */
|
||||
#define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4))
|
||||
#define RTC_DCB(x) ((((x) & 0xf0) >> 4) * 10 + ((x) & 0x0f))
|
||||
|
||||
/* RTC registers and bit definitions. */
|
||||
#define RTC_SECONDS 0
|
||||
#define RTC_ALSECONDS 1
|
||||
#define RTC_MINUTES 2
|
||||
#define RTC_ALMINUTES 3
|
||||
#define RTC_HOURS 4
|
||||
# define RTC_AMPM 0x80 /* PM flag if 12h format in use */
|
||||
#define RTC_ALHOURS 5
|
||||
#define RTC_DOW 6
|
||||
#define RTC_DOM 7
|
||||
#define RTC_MONTH 8
|
||||
#define RTC_YEAR 9
|
||||
#define RTC_REGA 10
|
||||
# define REGA_UIP 0x80
|
||||
# define REGA_DV2 0x40
|
||||
# define REGA_DV1 0x20
|
||||
# define REGA_DV0 0x10
|
||||
# define REGA_DV 0x70
|
||||
# define REGA_RS3 0x08
|
||||
# define REGA_RS2 0x04
|
||||
# define REGA_RS1 0x02
|
||||
# define REGA_RS0 0x01
|
||||
# define REGA_RS 0x0f
|
||||
#define RTC_REGB 11
|
||||
# define REGB_SET 0x80
|
||||
# define REGB_PIE 0x40
|
||||
# define REGB_AIE 0x20
|
||||
# define REGB_UIE 0x10
|
||||
# define REGB_SQWE 0x08
|
||||
# define REGB_DM 0x04
|
||||
# define REGB_2412 0x02
|
||||
# define REGB_DSE 0x01
|
||||
#define RTC_REGC 12
|
||||
# define REGC_IRQF 0x80
|
||||
# define REGC_PF 0x40
|
||||
# define REGC_AF 0x20
|
||||
# define REGC_UF 0x10
|
||||
#define RTC_REGD 13
|
||||
# define REGD_VRT 0x80
|
||||
#define RTC_CENTURY 0x32 /* century register */
|
||||
#define RTC_REGS 14 /* number of registers */
|
||||
|
||||
|
||||
extern wchar_t *nvr_concat(wchar_t *to_concat);
|
||||
extern void nvr_init(void);
|
||||
extern FILE *nvrfopen(wchar_t *fn, wchar_t *mode);
|
||||
extern void time_get(char *nvrram);
|
||||
|
||||
/* Define a (defacto-standard) RTC/NVRAM chip. */
|
||||
typedef struct _nvr_ {
|
||||
uint8_t regs[RTC_REGS+114]; /* these are the registers */
|
||||
|
||||
int upd_stat,
|
||||
upd_ecount,
|
||||
onesec_time,
|
||||
onesec_cnt,
|
||||
rtctime,
|
||||
oldmachine;
|
||||
|
||||
int mask,
|
||||
irq,
|
||||
addr;
|
||||
|
||||
void (*set)(struct _nvr_ *, uint16_t, uint8_t);
|
||||
uint8_t (*get)(struct _nvr_ *, uint16_t);
|
||||
|
||||
wchar_t *fname;
|
||||
} nvr_t;
|
||||
|
||||
|
||||
extern int enable_sync;
|
||||
extern int nvr_dosave;
|
||||
|
||||
|
||||
extern void nvr_init(nvr_t *);
|
||||
extern void nvr_load(void);
|
||||
extern void nvr_save(void);
|
||||
extern void nvr_recalc(void);
|
||||
extern void loadnvr(void);
|
||||
extern void savenvr(void);
|
||||
|
||||
extern wchar_t *nvr_path(wchar_t *str);
|
||||
extern FILE *nvr_fopen(wchar_t *str, wchar_t *mode);
|
||||
|
||||
extern void nvr_at_init(int irq);
|
||||
|
||||
|
||||
#endif /*EMU_NVR_H*/
|
||||
|
||||
108
src/nvr_at.c
Normal file
108
src/nvr_at.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* IBM PC/AT RTC/NVRAM ("CMOS") emulation.
|
||||
*
|
||||
* The original PC/AT series had DS12885 series modules; later
|
||||
* versions and clones used the 12886 and/or 1288(C)7 series,
|
||||
* or the MC146818 series, all with an external battery. Many
|
||||
* of those batteries would create corrosion issues later on
|
||||
* in mainboard life...
|
||||
*
|
||||
* Version: @(#)nvr_at.c 1.0.5 2017/10/02
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "ibm.h"
|
||||
#include "cpu/cpu.h"
|
||||
#include "io.h"
|
||||
#include "device.h"
|
||||
#include "machine/machine.h"
|
||||
#include "nvr.h"
|
||||
|
||||
|
||||
static void
|
||||
nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
|
||||
if (! (addr & 1)) {
|
||||
nvr->addr = (val & nvr->mask);
|
||||
#if 0
|
||||
nvr->nmi_mask = (~val & 0x80);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the chip's registers. */
|
||||
(*nvr->set)(nvr, nvr->addr, val);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
nvr_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
uint8_t ret;
|
||||
|
||||
if (addr & 1) {
|
||||
/* Read from the chip's registers. */
|
||||
ret = (*nvr->get)(nvr, nvr->addr);
|
||||
} else {
|
||||
ret = nvr->addr;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nvr_at_close(void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
|
||||
if (nvr->fname != NULL)
|
||||
free(nvr->fname);
|
||||
|
||||
free(nvr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nvr_at_init(int irq)
|
||||
{
|
||||
nvr_t *nvr;
|
||||
|
||||
/* Allocate an NVR for this machine. */
|
||||
nvr = (nvr_t *)malloc(sizeof(nvr_t));
|
||||
if (nvr == NULL) return;
|
||||
memset(nvr, 0x00, sizeof(nvr_t));
|
||||
|
||||
/* This is machine specific. */
|
||||
nvr->mask = machines[machine].nvrmask;
|
||||
nvr->irq = irq;
|
||||
|
||||
/* Set up any local handlers here. */
|
||||
|
||||
/* Initialize the actual NVR. */
|
||||
nvr_init(nvr);
|
||||
|
||||
/* Set up the PC/AT handler for this device. */
|
||||
io_sethandler(0x0070, 2,
|
||||
nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ static void *ps2_nvr_init()
|
||||
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPS2_M80: f = nvrfopen(L"ibmps2_m80_sec.nvr", L"rb"); break;
|
||||
case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"rb"); break;
|
||||
}
|
||||
if (f)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ static void ps2_nvr_close(void *p)
|
||||
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_IBMPS2_M80: f = nvrfopen(L"ibmps2_m80_sec.nvr", L"wb"); break;
|
||||
case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"wb"); break;
|
||||
}
|
||||
if (f)
|
||||
{
|
||||
|
||||
84
src/pc.c
84
src/pc.c
@@ -70,6 +70,7 @@
|
||||
#include "win/plat_midi.h"
|
||||
#include "win/plat_mouse.h"
|
||||
#include "win/plat_ui.h"
|
||||
#include "win/win.h"
|
||||
#include "scsi/scsi.h"
|
||||
#include "serial.h"
|
||||
#include "sound/sound.h"
|
||||
@@ -87,10 +88,6 @@
|
||||
#include "cpu/x86_ops.h"
|
||||
|
||||
|
||||
wchar_t exe_path[1024];
|
||||
wchar_t cfg_path[1024];
|
||||
wchar_t nvr_path[1024];
|
||||
|
||||
int window_w, window_h, window_x, window_y, window_remember;
|
||||
int dump_on_exit = 0;
|
||||
int start_in_fullscreen = 0;
|
||||
@@ -109,6 +106,8 @@ int pollmouse_delay = 2;
|
||||
int mousecapture;
|
||||
int suppress_overscan = 0;
|
||||
int cpuspeed2;
|
||||
wchar_t exe_path[1024];
|
||||
wchar_t cfg_path[1024];
|
||||
|
||||
|
||||
extern int mmuflush;
|
||||
@@ -129,20 +128,6 @@ pclog(const char *format, ...)
|
||||
}
|
||||
|
||||
|
||||
/* Log something to the logfile or stdout. */
|
||||
void
|
||||
pclog_w(const wchar_t *format, ...)
|
||||
{
|
||||
#ifndef RELEASE_BUILD
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vwprintf(format, ap);
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Log a fatal error, and display a UI message before exiting. */
|
||||
void
|
||||
fatal(const char *format, ...)
|
||||
@@ -157,7 +142,7 @@ fatal(const char *format, ...)
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
|
||||
savenvr();
|
||||
nvr_save();
|
||||
|
||||
config_save();
|
||||
|
||||
@@ -177,6 +162,33 @@ fatal(const char *format, ...)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function returns the absolute pathname to a file (str)
|
||||
* that is to be found in the user (formerly 'nvr_path' area.
|
||||
*/
|
||||
wchar_t *
|
||||
pc_concat(wchar_t *str)
|
||||
{
|
||||
static wchar_t temp[1024];
|
||||
|
||||
/* Get the full prefix in place. */
|
||||
memset(temp, 0x00, sizeof(temp));
|
||||
wcscpy(temp, cfg_path);
|
||||
|
||||
#ifndef __unix
|
||||
/* Create the directory if needed. */
|
||||
if (! DirectoryExists(temp))
|
||||
CreateDirectory(temp, NULL);
|
||||
#endif
|
||||
|
||||
/* Now append the actual filename. */
|
||||
wcscat(temp, L"\\");
|
||||
wcscat(temp, str);
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
@@ -201,7 +213,7 @@ usage(void)
|
||||
void
|
||||
pc_init(int argc, wchar_t *argv[])
|
||||
{
|
||||
wchar_t *config_file = NULL;
|
||||
wchar_t *cfg = NULL;
|
||||
wchar_t *p;
|
||||
#ifdef WALTJE
|
||||
struct direct *dp;
|
||||
@@ -213,7 +225,7 @@ pc_init(int argc, wchar_t *argv[])
|
||||
get_executable_name(exe_path, sizeof(exe_path)-1);
|
||||
p = get_filename_w(exe_path);
|
||||
*p = L'\0';
|
||||
pclog("exe_path=%S\n", exe_path);
|
||||
pclog("exe_path=%ws\n", exe_path);
|
||||
|
||||
/*
|
||||
* Get the current working directory.
|
||||
@@ -233,7 +245,7 @@ usage:
|
||||
!_wcsicmp(argv[c], L"-C")) {
|
||||
if ((c+1) == argc) break;
|
||||
|
||||
config_file = argv[++c];
|
||||
cfg = argv[++c];
|
||||
} else if (!_wcsicmp(argv[c], L"--dump") ||
|
||||
!_wcsicmp(argv[c], L"-D")) {
|
||||
dump_on_exit = 1;
|
||||
@@ -245,15 +257,15 @@ usage:
|
||||
#ifdef WALTJE
|
||||
dir = opendirw(exe_path);
|
||||
if (dir != NULL) {
|
||||
printf("Directory '%S':\n", exe_path);
|
||||
printf("Directory '%ws':\n", exe_path);
|
||||
for (;;) {
|
||||
dp = readdir(dir);
|
||||
if (dp == NULL) break;
|
||||
printf(">> '%S'\n", dp->d_name);
|
||||
printf(">> '%ws'\n", dp->d_name);
|
||||
}
|
||||
closedir(dir);
|
||||
} else {
|
||||
printf("Could not open '%S'..\n", exe_path);
|
||||
printf("Could not open '%ws'..\n", exe_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -276,9 +288,9 @@ usage:
|
||||
(cfg_path[wcslen(cfg_path)-1] != L'/')) {
|
||||
wcscat(cfg_path, L"\\");
|
||||
}
|
||||
pclog("cwd_path=%S\n", cfg_path);
|
||||
pclog("cfg_path=%ws\n", cfg_path);
|
||||
|
||||
if (config_file != NULL) {
|
||||
if (cfg != NULL) {
|
||||
/*
|
||||
* The user specified a configuration file.
|
||||
*
|
||||
@@ -287,14 +299,14 @@ usage:
|
||||
* Otherwise, assume the pathname given is
|
||||
* relative to whatever the cfg_path is.
|
||||
*/
|
||||
if ((config_file[1] == L':') || /* drive letter present */
|
||||
(config_file[0] == L'\\')) /* backslash, root dir */
|
||||
if ((cfg[1] == L':') || /* drive letter present */
|
||||
(cfg[0] == L'\\')) /* backslash, root dir */
|
||||
append_filename_w(config_file_default,
|
||||
NULL, config_file, 511);
|
||||
NULL, cfg, 511);
|
||||
else
|
||||
append_filename_w(config_file_default,
|
||||
cfg_path, config_file, 511);
|
||||
config_file = NULL;
|
||||
cfg_path, cfg, 511);
|
||||
cfg = NULL;
|
||||
} else {
|
||||
append_filename_w(config_file_default, cfg_path, CONFIG_FILE_W, 511);
|
||||
}
|
||||
@@ -307,7 +319,7 @@ usage:
|
||||
*/
|
||||
hdd_init();
|
||||
|
||||
config_load(config_file);
|
||||
config_load(cfg);
|
||||
}
|
||||
|
||||
|
||||
@@ -407,7 +419,7 @@ pc_init_modules(void)
|
||||
floppy_load(3, floppyfns[3]);
|
||||
#endif
|
||||
|
||||
loadnvr();
|
||||
nvr_load();
|
||||
|
||||
sound_init();
|
||||
|
||||
@@ -490,7 +502,7 @@ resetpchard_close(void)
|
||||
{
|
||||
suppress_overscan = 0;
|
||||
|
||||
savenvr();
|
||||
nvr_save();
|
||||
|
||||
device_close_all();
|
||||
mouse_emu_close();
|
||||
@@ -554,7 +566,7 @@ resetpchard_init(void)
|
||||
|
||||
mouse_emu_init();
|
||||
|
||||
loadnvr();
|
||||
nvr_load();
|
||||
|
||||
shadowbios = 0;
|
||||
|
||||
|
||||
249
src/rtc.c
249
src/rtc.c
@@ -1,249 +0,0 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.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;
|
||||
|
||||
/* 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 - 1];
|
||||
else
|
||||
return rtc_is_leap(org_year) ? 29 : 28;
|
||||
}
|
||||
|
||||
/* Called when the internal clock gets updated */
|
||||
static void rtc_recalc(void)
|
||||
{
|
||||
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(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called to obtain the current day of the week based on the internal clock */
|
||||
static int time_week_day(void)
|
||||
{
|
||||
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_get(struct tm *time_var)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
|
||||
static void time_set_nvrram(char *nvrram, struct tm *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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
174
src/rtc.h
174
src/rtc.h
@@ -1,174 +0,0 @@
|
||||
#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 0x80
|
||||
|
||||
/* 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 = 0xF,
|
||||
/* 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 = 0x70,
|
||||
/* 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 = 0x80
|
||||
};
|
||||
|
||||
/* 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 = 0x1,
|
||||
/* 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 = 0x2,
|
||||
/* 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 = 0x4,
|
||||
/* 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 = 0x8,
|
||||
/* 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 = 0x10,
|
||||
/* 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 = 0x20,
|
||||
/* 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 = 0x40,
|
||||
/* 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 = 0x80
|
||||
};
|
||||
|
||||
/* 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 = 0xF,
|
||||
/* 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 = 0x10,
|
||||
/* 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 = 0x20,
|
||||
/* 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 = 0x40,
|
||||
/* 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 = 0x80
|
||||
};
|
||||
|
||||
/* 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 = 0x7F,
|
||||
/* 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 = 0x80
|
||||
};
|
||||
|
||||
extern void rtc_tick(void);
|
||||
extern void time_update(char *nvrram, int reg);
|
||||
extern void time_get(char *nvrram);
|
||||
extern void time_internal_set_nvrram(char *nvrram);
|
||||
extern void time_internal_sync(char *nvrram);
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* NOTE: THIS IS CURRENTLY A MESS, but will be cleaned up as I go.
|
||||
*
|
||||
* Version: @(#)scsi_aha154x.c 1.0.18 2017/09/24
|
||||
* Version: @(#)scsi_aha154x.c 1.0.19 2017/10/02
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Original Buslogic version by SA1988 and Miran Grca.
|
||||
@@ -1838,7 +1838,7 @@ aha_setbios(aha_t *dev)
|
||||
if (dev->bios_path == NULL) return;
|
||||
|
||||
/* Open the BIOS image file and make sure it exists. */
|
||||
pclog_w(L"%S: loading BIOS from '%s'\n", dev->name, dev->bios_path);
|
||||
pclog("%s: loading BIOS from '%ws'\n", dev->name, dev->bios_path);
|
||||
if ((f = rom_fopen(dev->bios_path, L"rb")) == NULL) {
|
||||
pclog("%s: BIOS ROM not found!\n", dev->name);
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* 0 - BT-545C ISA;
|
||||
* 1 - BT-958D PCI (but BT-545C ISA on non-PCI machines)
|
||||
*
|
||||
* Version: @(#)scsi_buslogic.c 1.0.14 2017/09/24
|
||||
* Version: @(#)scsi_buslogic.c 1.0.15 2017/10/02
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -733,7 +733,7 @@ static void BuslogicInitializeAutoSCSIRam(Buslogic_t *bl)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = nvrfopen(BuslogicGetNVRFileName(bl), L"rb");
|
||||
f = nvr_fopen(BuslogicGetNVRFileName(bl), L"rb");
|
||||
if (f)
|
||||
{
|
||||
fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f);
|
||||
@@ -2068,7 +2068,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
|
||||
BuslogicAutoSCSIRamSetDefaults(bl, 3);
|
||||
break;
|
||||
case 1:
|
||||
f = nvrfopen(BuslogicGetNVRFileName(bl), L"wb");
|
||||
f = nvr_fopen(BuslogicGetNVRFileName(bl), L"wb");
|
||||
if (f)
|
||||
{
|
||||
fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f);
|
||||
|
||||
@@ -777,7 +777,7 @@ void *adgold_init()
|
||||
for (; c >= 0; c--)
|
||||
attenuation[c] = 0;
|
||||
|
||||
f = nvrfopen(L"adgold.bin", L"rb");
|
||||
f = nvr_fopen(L"adgold.bin", L"rb");
|
||||
if (f)
|
||||
{
|
||||
fread(adgold->adgold_eeprom, 0x18, 1, f);
|
||||
@@ -817,7 +817,7 @@ void adgold_close(void *p)
|
||||
FILE *f;
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
|
||||
f = nvrfopen(L"adgold.bin", L"wb");
|
||||
f = nvr_fopen(L"adgold.bin", L"wb");
|
||||
if (f)
|
||||
{
|
||||
fwrite(adgold->adgold_eeprom, 0x18, 1, f);
|
||||
|
||||
@@ -136,10 +136,10 @@ static void *tandy_eeprom_init(void)
|
||||
switch (romset)
|
||||
{
|
||||
case ROM_TANDY1000HX:
|
||||
f = nvrfopen(L"tandy1000hx.bin", L"rb");
|
||||
f = nvr_fopen(L"tandy1000hx.bin", L"rb");
|
||||
break;
|
||||
case ROM_TANDY1000SL2:
|
||||
f = nvrfopen(L"tandy1000sl2.bin", L"rb");
|
||||
f = nvr_fopen(L"tandy1000sl2.bin", L"rb");
|
||||
break;
|
||||
}
|
||||
if (f)
|
||||
@@ -164,10 +164,10 @@ void tandy_eeprom_close(void *p)
|
||||
switch (eeprom->romset)
|
||||
{
|
||||
case ROM_TANDY1000HX:
|
||||
f = nvrfopen(L"tandy1000hx.bin", L"wb");
|
||||
f = nvr_fopen(L"tandy1000hx.bin", L"wb");
|
||||
break;
|
||||
case ROM_TANDY1000SL2:
|
||||
f = nvrfopen(L"tandy1000sl2.bin", L"wb");
|
||||
f = nvr_fopen(L"tandy1000sl2.bin", L"wb");
|
||||
break;
|
||||
}
|
||||
fwrite(eeprom->store, 128, 1, f);
|
||||
|
||||
@@ -43,7 +43,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type)
|
||||
FILE *f;
|
||||
eeprom->type = type;
|
||||
wcscpy(eeprom->fn, fn);
|
||||
f = nvrfopen(eeprom->fn, L"rb");
|
||||
f = nvr_fopen(eeprom->fn, L"rb");
|
||||
if (!f)
|
||||
{
|
||||
memset(eeprom->data, 0, eeprom->type ? 512 : 128);
|
||||
@@ -55,7 +55,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type)
|
||||
|
||||
void ati_eeprom_save(ati_eeprom_t *eeprom)
|
||||
{
|
||||
FILE *f = nvrfopen(eeprom->fn, L"wb");
|
||||
FILE *f = nvr_fopen(eeprom->fn, L"wb");
|
||||
if (!f) return;
|
||||
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
|
||||
fclose(f);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* This is intended to be used by another SVGA driver,
|
||||
* and not as a card in it's own right.
|
||||
*
|
||||
* Version: @(#)vid_svga.c 1.0.3 2017/09/24
|
||||
* Version: @(#)vid_svga.c 1.0.4 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -1939,7 +1939,7 @@ void svga_dump_vram()
|
||||
return;
|
||||
}
|
||||
|
||||
f = nvrfopen(L"svga_vram.dmp", L"wb");
|
||||
f = nvr_fopen(L"svga_vram.dmp", L"wb");
|
||||
if (f == NULL)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Windows resource script.
|
||||
*
|
||||
* Version: @(#)86Box.rc 1.0.13 2017/10/01
|
||||
* Version: @(#)86Box.rc 1.0.14 2017/10/01
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -266,9 +266,6 @@ BEGIN
|
||||
12,12
|
||||
LTEXT "MB",IDT_1705,123,64,10,10
|
||||
LTEXT "Memory:",IDT_1706,7,64,30,10
|
||||
LTEXT "NVR Path:",IDT_1700,7,83,60,10
|
||||
EDITTEXT IDC_EDIT_NVR_PATH,71,82,138,12,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "&Specify...",IDC_BUTTON_NVR_PATH,214,82,46,12
|
||||
CONTROL "Dynamic Recompiler",IDC_CHECK_DYNAREC,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,7,100,94,10
|
||||
CONTROL "Enable FPU",IDC_CHECK_FPU,"Button",BS_AUTOCHECKBOX |
|
||||
@@ -689,7 +686,9 @@ BEGIN
|
||||
IDS_2053 "Invalid number of sectors (valid values are between 1 and 63)"
|
||||
IDS_2054 "Invalid number of heads (valid values are between 1 and 16)"
|
||||
IDS_2055 "Invalid number of cylinders (valid values are between 1 and 266305)"
|
||||
IDS_2056 "Specify the NVR Path"
|
||||
#if NOTUSED
|
||||
IDS_2056
|
||||
#endif
|
||||
IDS_2057 "(empty)"
|
||||
IDS_2058 "(host drive %c:)"
|
||||
IDS_2059 "Turbo"
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
* Windows resource defines.
|
||||
*
|
||||
* NOTE: FIXME: Strings 2176 and 2193 are same.
|
||||
* NOTE: FIXME: string 2052 not in use.
|
||||
* NOTE: FIXME: string 2095 not in use.
|
||||
* NOTE: FIXME: strings 2152-2154 not in use.
|
||||
* NOTE: FIXME: strings 2153-2154 not in use.
|
||||
*
|
||||
* Version: @(#)resource.h 1.0.8 2017/10/01
|
||||
* Version: @(#)resource.h 1.0.9 2017/10/01
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -105,8 +106,6 @@
|
||||
#define IDC_MEMTEXT 1017
|
||||
#define IDC_MEMSPIN 1018
|
||||
#define IDC_TEXT_MB IDT_1705
|
||||
#define IDC_EDIT_NVR_PATH 1019
|
||||
#define IDC_BUTTON_NVR_PATH 1020
|
||||
|
||||
#define IDC_VIDEO 1030 /* video config */
|
||||
#define IDC_COMBO_VIDEO 1031
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* The Emulator's Windows core.
|
||||
*
|
||||
* Version: @(#)win.c 1.0.14 2017/10/01
|
||||
* Version: @(#)win.c 1.0.14 2017/10/02
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -338,8 +338,8 @@ void mainthread(LPVOID param)
|
||||
if (frames >= 200 && nvr_dosave)
|
||||
{
|
||||
frames = 0;
|
||||
nvr_save();
|
||||
nvr_dosave = 0;
|
||||
savenvr();
|
||||
}
|
||||
end_time = timer_read();
|
||||
main_time += end_time - start_time;
|
||||
@@ -1904,7 +1904,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpsz
|
||||
Sleep(200);
|
||||
TerminateThread(mainthreadh, 0);
|
||||
|
||||
savenvr();
|
||||
nvr_save();
|
||||
|
||||
config_save();
|
||||
|
||||
@@ -2022,7 +2022,7 @@ win_pc_reset(int hard)
|
||||
|
||||
Sleep(100);
|
||||
|
||||
savenvr();
|
||||
nvr_save();
|
||||
|
||||
config_save();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Windows 86Box Settings dialog handler.
|
||||
*
|
||||
* Version: @(#)win_settings.c 1.0.17 2017/10/01
|
||||
* Version: @(#)win_settings.c 1.0.17 2017/10/02
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
/* Machine category */
|
||||
static int temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_mem_size, temp_dynarec, temp_fpu, temp_sync;
|
||||
static wchar_t temp_nvr_path[520];
|
||||
|
||||
/* Video category */
|
||||
static int temp_gfxcard, temp_video_speed, temp_voodoo;
|
||||
@@ -115,8 +114,6 @@ static void win_settings_init(void)
|
||||
temp_wait_states = cpu_waitstates;
|
||||
temp_cpu = cpu;
|
||||
temp_mem_size = mem_size;
|
||||
memset(temp_nvr_path, 0, sizeof(temp_nvr_path));
|
||||
wcscpy(temp_nvr_path, nvr_path);
|
||||
temp_dynarec = cpu_use_dynarec;
|
||||
temp_fpu = enable_external_fpu;
|
||||
temp_sync = enable_sync;
|
||||
@@ -187,7 +184,6 @@ static int win_settings_changed(void)
|
||||
i = i || (cpu_waitstates != temp_wait_states);
|
||||
i = i || (cpu != temp_cpu);
|
||||
i = i || (mem_size != temp_mem_size);
|
||||
i = i || wcscmp(temp_nvr_path, nvr_path);
|
||||
i = i || (temp_dynarec != cpu_use_dynarec);
|
||||
i = i || (temp_fpu != enable_external_fpu);
|
||||
i = i || (temp_sync != enable_sync);
|
||||
@@ -292,8 +288,6 @@ static void win_settings_save(void)
|
||||
cpu_waitstates = temp_wait_states;
|
||||
cpu = temp_cpu;
|
||||
mem_size = temp_mem_size;
|
||||
memset(nvr_path, 0, sizeof(nvr_path));
|
||||
wcscpy(nvr_path, temp_nvr_path);
|
||||
cpu_use_dynarec = temp_dynarec;
|
||||
enable_external_fpu = temp_fpu;
|
||||
enable_sync = temp_sync;
|
||||
@@ -548,7 +542,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w
|
||||
int d = 0;
|
||||
LPTSTR lptsTemp;
|
||||
char *stransi;
|
||||
wchar_t *p;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
@@ -600,9 +593,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w
|
||||
|
||||
win_settings_machine_recalc_machine(hdlg);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_EDIT_NVR_PATH);
|
||||
SendMessage(h, WM_SETTEXT, 0, (LPARAM) temp_nvr_path);
|
||||
|
||||
free(lptsTemp);
|
||||
|
||||
return TRUE;
|
||||
@@ -644,24 +634,6 @@ static BOOL CALLBACK win_settings_machine_proc(HWND hdlg, UINT message, WPARAM w
|
||||
|
||||
deviceconfig_open(hdlg, (void *)machine_getdevice(temp_machine));
|
||||
break;
|
||||
case IDC_BUTTON_NVR_PATH:
|
||||
p = BrowseFolder(temp_nvr_path, win_language_get_string_from_id(IDS_2056));
|
||||
if (wcscmp(p, L""))
|
||||
{
|
||||
memset(temp_nvr_path, 0, sizeof(temp_nvr_path));
|
||||
wcscpy(temp_nvr_path, p);
|
||||
if (temp_nvr_path[wcslen(temp_nvr_path) - 1] == L'/')
|
||||
{
|
||||
temp_nvr_path[wcslen(temp_nvr_path) - 1] = L'\\';
|
||||
}
|
||||
else if (temp_nvr_path[wcslen(temp_nvr_path) - 1] != L'\\')
|
||||
{
|
||||
temp_nvr_path[wcslen(temp_nvr_path)] = L'\\';
|
||||
}
|
||||
h = GetDlgItem(hdlg, IDC_EDIT_NVR_PATH);
|
||||
SendMessage(h, WM_SETTEXT, 0, (LPARAM) temp_nvr_path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
Reference in New Issue
Block a user