diff --git a/src/config.c b/src/config.c index 3d4ee41..5eaeded 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. * - * Version: @(#)config.c 1.0.3 2018/03/08 + * Version: @(#)config.c 1.0.4 2018/03/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,30 +41,30 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include #include -#include #include "emu.h" -#include "cpu/cpu.h" -#include "nvr.h" #include "config.h" +#include "cpu/cpu.h" +#include "machine/machine.h" +#include "nvr.h" #include "device.h" #include "lpt.h" -#include "cdrom/cdrom.h" +#include "mouse.h" +#include "game/gameport.h" +#include "floppy/fdd.h" +#include "floppy/fdc.h" #include "disk/hdd.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" #include "disk/zip.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "game/gameport.h" -#include "machine/machine.h" -#include "mouse.h" -#include "network/network.h" +#include "cdrom/cdrom.h" #include "scsi/scsi.h" +#include "network/network.h" #include "sound/sound.h" #include "sound/midi.h" #include "sound/snd_dbopl.h" @@ -73,8 +73,6 @@ #include "sound/sound.h" #include "video/video.h" #include "plat.h" -#include "plat_joystick.h" -#include "plat_midi.h" #include "ui.h" diff --git a/src/emu.h b/src/emu.h index 125a1d7..7a91782 100644 --- a/src/emu.h +++ b/src/emu.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)emu.h 1.0.5 2018/03/07 + * Version: @(#)emu.h 1.0.6 2018/03/11 * * Author: Fred N. van Kempen, * @@ -137,6 +137,7 @@ extern int cpu_manufacturer, /* (C) cpu manufacturer */ cpu, /* (C) cpu type */ cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ enable_external_fpu; /* (C) enable external FPU */ +extern int enable_sync; /* (C) enable time sync */ #ifdef ENABLE_LOG_TOGGLES diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 1644416..d8b128a 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -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: @(#)fdd_86f.c 1.0.2 2018/03/08 + * Version: @(#)fdd_86f.c 1.0.3 2018/03/11 * * Author: Miran Grca, * @@ -41,7 +41,6 @@ #include #include #include -#include "../lzf/lzf.h" #define HAVE_STDARG_H #include "../emu.h" #include "../config.h" @@ -53,6 +52,7 @@ #include "fdd.h" #include "fdc.h" #include "fdd_86f.h" +#include "lzf/lzf.h" #define CHUNK 16384 diff --git a/src/lzf/Changes b/src/floppy/lzf/Changes similarity index 100% rename from src/lzf/Changes rename to src/floppy/lzf/Changes diff --git a/src/lzf/LICENSE b/src/floppy/lzf/LICENSE similarity index 100% rename from src/lzf/LICENSE rename to src/floppy/lzf/LICENSE diff --git a/src/lzf/Makefile.in b/src/floppy/lzf/Makefile.in similarity index 100% rename from src/lzf/Makefile.in rename to src/floppy/lzf/Makefile.in diff --git a/src/lzf/README b/src/floppy/lzf/README similarity index 100% rename from src/lzf/README rename to src/floppy/lzf/README diff --git a/src/lzf/config.h b/src/floppy/lzf/config.h similarity index 100% rename from src/lzf/config.h rename to src/floppy/lzf/config.h diff --git a/src/lzf/configure b/src/floppy/lzf/configure similarity index 100% rename from src/lzf/configure rename to src/floppy/lzf/configure diff --git a/src/lzf/configure.ac b/src/floppy/lzf/configure.ac similarity index 100% rename from src/lzf/configure.ac rename to src/floppy/lzf/configure.ac diff --git a/src/lzf/crc32.h b/src/floppy/lzf/crc32.h similarity index 100% rename from src/lzf/crc32.h rename to src/floppy/lzf/crc32.h diff --git a/src/lzf/install-sh b/src/floppy/lzf/install-sh similarity index 100% rename from src/lzf/install-sh rename to src/floppy/lzf/install-sh diff --git a/src/lzf/lzf.c b/src/floppy/lzf/lzf.c similarity index 100% rename from src/lzf/lzf.c rename to src/floppy/lzf/lzf.c diff --git a/src/lzf/lzf.h b/src/floppy/lzf/lzf.h similarity index 100% rename from src/lzf/lzf.h rename to src/floppy/lzf/lzf.h diff --git a/src/lzf/lzfP.h b/src/floppy/lzf/lzfP.h similarity index 100% rename from src/lzf/lzfP.h rename to src/floppy/lzf/lzfP.h diff --git a/src/lzf/lzf_c.c b/src/floppy/lzf/lzf_c.c similarity index 100% rename from src/lzf/lzf_c.c rename to src/floppy/lzf/lzf_c.c diff --git a/src/lzf/lzf_d.c b/src/floppy/lzf/lzf_d.c similarity index 100% rename from src/lzf/lzf_d.c rename to src/floppy/lzf/lzf_d.c diff --git a/src/game/gameport.c b/src/game/gameport.c index 02d7d37..abbc58c 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -8,7 +8,7 @@ * * Implementation of a generic Game Port. * - * Version: @(#)gameport.c 1.0.1 2018/02/14 + * Version: @(#)gameport.c 1.0.2 2018/03/10 * * Authors: Miran Grca, * Sarah Walker, @@ -50,7 +50,6 @@ #include "joystick_standard.h" #include "joystick_sw_pad.h" #include "joystick_tm_fcs.h" -#include "../plat_joystick.h" int joystick_type; diff --git a/src/game/gameport.h b/src/game/gameport.h index 75bdd4f..1b1be36 100644 --- a/src/game/gameport.h +++ b/src/game/gameport.h @@ -8,7 +8,9 @@ * * Definitions for the generic game port handlers. * - * Version: @(#)gameport.h 1.0.1 2018/02/14 + * NOTE: This module needs a good cleanup someday. + * + * Version: @(#)gameport.h 1.0.2 2018/02/10 * * Authors: Miran Grca, * Sarah Walker, @@ -38,36 +40,94 @@ # define EMU_GAMEPORT_H -#define AXIS_NOT_PRESENT -99999 +#define MAX_PLAT_JOYSTICKS 8 +#define MAX_JOYSTICKS 4 + +#define POV_X 0x80000000 +#define POV_Y 0x40000000 + +#define AXIS_NOT_PRESENT -99999 + +#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) -typedef struct -{ - const char *name; - void *(*init)(void); - void (*close)(void *p); - uint8_t (*read)(void *p); - void (*write)(void *p); - int (*read_axis)(void *p, int axis); - void (*a0_over)(void *p); - int axis_count, button_count, pov_count; - int max_joysticks; - const char *axis_names[8]; - const char *button_names[32]; - const char *pov_names[4]; +typedef struct { + char name[64]; + + int a[8]; + int b[32]; + int p[4]; + + struct { + char name[32]; + int id; + } axis[8]; + + struct { + char name[32]; + int id; + } button[32]; + + struct { + char name[32]; + int id; + } pov[4]; + + int nr_axes; + int nr_buttons; + int nr_povs; +} plat_joystick_t; + +typedef struct { + int axis[8]; + int button[32]; + int pov[4]; + + int plat_joystick_nr; + int axis_mapping[8]; + int button_mapping[32]; + int pov_mapping[4][2]; +} joystick_t; + +typedef struct { + const char *name; + + void *(*init)(void); + void (*close)(void *p); + uint8_t (*read)(void *p); + void (*write)(void *p); + int (*read_axis)(void *p, int axis); + void (*a0_over)(void *p); + + int axis_count, + button_count, + pov_count; + int max_joysticks; + const char *axis_names[8]; + const char *button_names[32]; + const char *pov_names[4]; } joystick_if_t; - #ifdef __cplusplus extern "C" { #endif -extern device_t gameport_device; +#ifdef EMU_DEVICE_H +extern device_t gameport_device; extern device_t gameport_201_device; +#endif -extern int joystick_type; +extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +extern joystick_t joystick_state[MAX_JOYSTICKS]; +extern int joysticks_present; +extern int joystick_type; + + +extern void joystick_init(void); +extern void joystick_close(void); +extern void joystick_process(void); extern char *joystick_get_name(int64_t joystick); extern int64_t joystick_get_max_joysticks(int64_t joystick); diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index b92337c..948e40c 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -8,7 +8,7 @@ * * Implementation of the Flight Stick Pro. * - * Version: @(#)flightstick_pro.c 1.0.2 2018/02/21 + * Version: @(#)flightstick_pro.c 1.0.3 2018/03/10 * * Authors: Miran Grca, * Sarah Walker, @@ -42,7 +42,6 @@ #include "../emu.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 48890c2..e2934c5 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -8,7 +8,7 @@ * * Implementation of a standard joystick. * - * Version: @(#)joystick_standard.c 1.0.2 2018/02/21 + * Version: @(#)joystick_standard.c 1.0.3 2018/03/10 * * Authors: Miran Grca, * Sarah Walker, @@ -42,7 +42,6 @@ #include "../emu.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index aa0358c..1c65190 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -29,7 +29,7 @@ * - Some DOS stuff will write to 0x201 while a packet is * being transferred. This seems to be ignored. * - * Version: @(#)sw_pad.c 1.0.2 2018/02/21 + * Version: @(#)sw_pad.c 1.0.3 2018/03/10 * * Authors: Miran Grca, * Sarah Walker, @@ -63,7 +63,6 @@ #include "../emu.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_sw_pad.h" diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 135f31f..5d42576 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -8,7 +8,7 @@ * * Implementation of Thrust Master Flight Control System. * - * Version: @(#)tm_fcs.c 1.0.1 2018/02/14 + * Version: @(#)tm_fcs.c 1.0.2 2018/03/10 * * Authors: Miran Grca, * Sarah Walker, @@ -42,7 +42,6 @@ #include "../emu.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 1aab899..6d4de96 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,7 +8,7 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.2 2018/03/04 + * Version: @(#)keyboard_at.c 1.0.3 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,7 +50,6 @@ #include "pit.h" #include "ppi.h" #include "mem.h" -#include "rom.h" #include "device.h" #include "timer.h" #include "machine/machine.h" diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 5cb4b1d..0cee757 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.2 2018/03/04 + * Version: @(#)keyboard_xt.c 1.0.3 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,8 +47,6 @@ #include "pic.h" #include "pit.h" #include "ppi.h" -#include "mem.h" -#include "rom.h" #include "timer.h" #include "device.h" #include "sound/sound.h" diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index a033a69..3726f2d 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -23,16 +23,16 @@ * used for TV and LCD displays, and we're emulating a CRT. * * TODO: This module is not complete yet: - * - * PC1512: The BIOS assumes 512K RAM, because I cannot figure out how to + * PC1512: The BIOS assumes 512K RAM, because I cannot figure out how to * read the status of the LK4 jumper on the mainboard, which is * somehow linked to the bus gate array on the NDMACS line... - * - * PC1612: EGA mode does not seem to work in the PC1640; it works fine + * PC1612: EGA mode does not seem to work in the PC1640; it works fine * in alpha mode, but in highres ("ECD350") mode, it displays * some semi-random junk. Video-memory pointer maybe? + * BIOSES: I need to re-do the bios.txt format so we can load non-BIOS + * ROM files for a given machine, such as font roms here.. * - * Version: @(#)m_amstrad.c 1.0.1 2018/02/14 + * Version: @(#)m_amstrad.c 1.0.2 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -542,6 +542,9 @@ vid_init_1512(amstrad_t *ams) vid->cgacol = 7; vid->cgamode = 0x12; + /* Load the PC1512 CGA Character Set ROM. */ + loadfont(L"roms/machines/amstrad/pc1512/40078", 2); + timer_add(vid_poll_1512, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, @@ -841,6 +844,9 @@ vid_init_200(amstrad_t *ams) cga->vram = malloc(0x4000); cga_init(cga); + /* Load the PC200 CGA Character Set ROM. */ + loadfont(L"roms/machines/amstrad/pc200/40109.bin", 1); + mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 16, @@ -1243,62 +1249,50 @@ machine_amstrad_init(machine_t *model) io_sethandler(0x007a, 1, ms_read, NULL, NULL, ms_write, NULL, NULL, ams); -// device_add(&fdc_at_actlow_device); - - switch(romset) { + switch(model->id) { case ROM_PC1512: device_add(&fdc_xt_device); + if (gfxcard == GFX_INTERNAL) { + vid_init_1512(ams); + device_add_ex(&vid_1512_device, ams->vid); + } break; case ROM_PC1640: device_add(&fdc_xt_device); + if (gfxcard == GFX_INTERNAL) { + vid_init_1640(ams); + device_add_ex(&vid_1640_device, ams->vid); + } break; case ROM_PC200: device_add(&fdc_xt_device); + if (gfxcard == GFX_INTERNAL) { + vid_init_200(ams); + device_add_ex(&vid_200_device, ams->vid); + } break; case ROM_PC2086: device_add(&fdc_at_actlow_device); + if (gfxcard == GFX_INTERNAL) { + device_add(¶dise_pvga1a_pc2086_device); + } break; case ROM_PC3086: device_add(&fdc_at_actlow_device); + if (gfxcard == GFX_INTERNAL) { + device_add(¶dise_pvga1a_pc3086_device); + } break; case ROM_MEGAPC: device_add(&fdc_at_actlow_device); - break; - } - - if (gfxcard == GFX_INTERNAL) switch(romset) { - case ROM_PC1512: - loadfont(L"roms/machines/pc1512/40078", 2); - vid_init_1512(ams); - device_add_ex(&vid_1512_device, ams->vid); - break; - - case ROM_PC1640: - vid_init_1640(ams); - device_add_ex(&vid_1640_device, ams->vid); - break; - - case ROM_PC200: - loadfont(L"roms/machines/pc200/40109.bin", 1); - vid_init_200(ams); - device_add_ex(&vid_200_device, ams->vid); - break; - - case ROM_PC2086: - device_add(¶dise_pvga1a_pc2086_device); - break; - - case ROM_PC3086: - device_add(¶dise_pvga1a_pc3086_device); - break; - - case ROM_MEGAPC: - device_add(¶dise_wd90c11_megapc_device); + if (gfxcard == GFX_INTERNAL) { + device_add(¶dise_wd90c11_megapc_device); + } break; } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 6a9ddd1..3d32936 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -8,7 +8,7 @@ * * Emulation of various Compaq PC's. * - * Version: @(#)m_at_compaq.c 1.0.1 2018/02/14 + * Version: @(#)m_at_compaq.c 1.0.2 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -129,20 +129,13 @@ machine_at_compaq_init(machine_t *model) 0xa0000+ram, MEM_MAPPING_INTERNAL, NULL); switch(model->id) { -#ifdef PORTABLE3 - case ROM_DESKPRO_386: - if (hdc_current == 1) - device_add(&ide_isa_device); - break; -#endif - case ROM_PORTABLE: break; case ROM_PORTABLEII: break; -#ifdef PORTABLE3 +#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) case ROM_PORTABLEIII: machine_olim24_video_init(); break; @@ -152,6 +145,12 @@ machine_at_compaq_init(machine_t *model) if (hdc_current == 1) device_add(&ide_isa_device); break; +#endif +#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) + case ROM_DESKPRO_386: + if (hdc_current == 1) + device_add(&ide_isa_device); + break; #endif } } diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 4975e2e..342d91e 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -27,8 +27,7 @@ * f000:ecc5 801a video setup error * f000:d6c9 copyright output * f000:e1b7 - * f000:e1be DI bits set mean output text!!!, - * (801a) + * f000:e1be DI bits set mean output text!!! (801a) * f000: 0x8000 output * 1 rtc error * 2 rtc time or date error @@ -53,21 +52,23 @@ * output cl at jim 0xa * write ah hinibble as lownibble into jim 0xa * write ah lownibble into jim 0xa - * f000:ef66 RTC read reg cl + * f000:ef66 RTC read reg cl * polls until jim 0xa is zero, * output cl at jim 0xa * read low 4 nibble at jim 0xa * read low 4 nibble at jim 0xa * return first nibble<<4|second nibble in ah - * f000:f046 seldom compares ret - * f000:fe87 0 -> ds - * 0000:0469 bit 0: b0000 memory available + * f000:f046 seldom compares ret + * f000:fe87 0 -> ds + * + * Memory: + * 0000:0469 bit 0: b0000 memory available * bit 1: b8000 memory available - * 0000:046a: 00 jim 250 01 jim 350 + * 0000:046a: 00 jim 250 01 jim 350 * * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. * - * Version: @(#)europc.c 1.0.1 2018/02/14 + * Version: @(#)europc.c 1.0.2 2018/03/11 * * Author: Fred N. van Kempen, * @@ -113,6 +114,7 @@ #include #include #include +#include #include "../emu.h" #include "../io.h" #include "../nmi.h" @@ -120,17 +122,17 @@ #include "../rom.h" #include "../nvr.h" #include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../disk/hdc.h" #include "../keyboard.h" #include "../mouse.h" #include "../game/gameport.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" +#include "../disk/hdc.h" #include "../video/video.h" #include "machine.h" -#define EUROPC_DEBUG 1 /* current debugging level */ +#define EUROPC_DEBUG 0 /* current debugging level */ /* M3002 RTC chip registers. */ @@ -139,7 +141,7 @@ #define MRTC_HOURS 0x02 /* BCD, 00-23 */ #define MRTC_DAYS 0x03 /* BCD, 01-31 */ #define MRTC_MONTHS 0x04 /* BCD, 01-12 */ -#define MRTC_YEARS 0x05 /* BCD, 00-99 (2017 is 0x17) */ +#define MRTC_YEARS 0x05 /* BCD, 00-99 (year only) */ #define MRTC_WEEKDAY 0x06 /* BCD, 01-07 */ #define MRTC_WEEKNO 0x07 /* BCD, 01-52 */ #define MRTC_CONF_A 0x08 /* EuroPC config, binary */ @@ -151,127 +153,232 @@ #define MRTC_CHECK_HI 0x0e /* Checksum, high byte */ #define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */ - typedef struct { uint16_t jim; /* JIM base address */ uint8_t regs[16]; /* JIM internal regs (8) */ - struct { - uint8_t dat[16]; - uint8_t stat; - uint8_t addr; - } rtc; - nvr_t nvr; /* NVR */ -} vm_t; + uint8_t nvr_stat; + uint8_t nvr_addr; +} europc_t; -static vm_t *vm = NULL; +static europc_t europc; -/* Load the relevant portion of the NVR to disk. */ -static int8_t -load_nvr(wchar_t *fn) -{ - FILE *f; - - if (vm == NULL) return(0); - - f = nvr_fopen(fn, L"rb"); - if (f != NULL) { - (void)fread(vm->rtc.dat, 1, 16, f); - (void)fclose(f); - pclog("EuroPC: CMOS data loaded from file %ls !\n", fn); - return(1); - } - - pclog("EuroPC: unable to load NVR !\n"); - return(0); -} - - -/* Save the relevant portion of the NVR to disk. */ -static int8_t -save_nvr(wchar_t *fn) -{ - FILE *f; - - if (vm == NULL) return(0); - - f = nvr_fopen(fn, L"wb"); - if (f != NULL) { - (void)fwrite(vm->rtc.dat, 1, 16, f); - (void)fclose(f); - return(1); - } - - pclog("EuroPC: unable to save NVR !\n"); - return(0); -} - - -/* This is called every second through the NVR/RTC hook. */ +/* + * This is called every second through the NVR/RTC hook. + * + * We fake a 'running' RTC by updating its registers on + * each passing second. Not exactly accurate, but good + * enough. + * + * Note that this code looks nasty because of all the + * BCD to decimal vv going on. + * + * FIXME: should we mark NVR as dirty? + */ static void -rtc_hook(nvr_t *nvr) +rtc_tick(nvr_t *nvr) { -#if 0 - int month, year; + uint8_t *regs; + int mon, yr; - sys->rtc.dat[0] = bcd_adjust(sys->rtc.dat[0]+1); - if (sys->rtc.dat[0] >= 0x60) { - sys->rtc.dat[0] = 0; - sys->rtc.dat[1] = bcd_adjust(sys->rtc.dat[1]+1); - if (sys->rtc.dat[1] >= 0x60) { - sys->rtc.dat[1] = 0; - sys->rtc.dat[2] = bcd_adjust(sys->rtc.dat[2]+1); - if (sys->rtc.dat[2] >= 0x24) { - sys->rtc.dat[2] = 0; - sys->uropc_rtc.data[3]=bcd_adjust(sys->uropc_rtc.data[3]+1); - month = bcd_2_dec(sys->rtc.dat[4]); + /* Only if RTC is running.. */ + regs = nvr->regs; + if (! (regs[MRTC_CTRLSTAT] & 0x01)) return; - /* Save for julian_days_in_month_calculation. */ - year = bcd_2_dec(sys->rtc.dat[5])+2000; - if (sys->rtc.dat[3] > gregorian_days_in_month(month, year)) { - sys->rtc.dat[3] = 1; - sys->rtc.dat[4] = bcd_adjust(sys->rtc.dat[4]+1); - if (sys->rtc.dat[4]>0x12) { - sys->rtc.dat[4] = 1; - sys->rtc.dat[5] = bcd_adjust(sys->rtc.dat[5]+1)&0xff; - } + regs[MRTC_SECONDS] = RTC_BCDINC(nvr->regs[MRTC_SECONDS], 1); + if (regs[MRTC_SECONDS] >= RTC_BCD(60)) { + regs[MRTC_SECONDS] = RTC_BCD(0); + regs[MRTC_MINUTES] = RTC_BCDINC(regs[MRTC_MINUTES], 1); + if (regs[MRTC_MINUTES] >= RTC_BCD(60)) { + regs[MRTC_MINUTES] = RTC_BCD(0); + regs[MRTC_HOURS] = RTC_BCDINC(regs[MRTC_HOURS], 1); + if (regs[MRTC_HOURS] >= RTC_BCD(24)) { + regs[MRTC_HOURS] = RTC_BCD(0); + regs[MRTC_DAYS] = RTC_BCDINC(regs[MRTC_DAYS], 1); + mon = RTC_DCB(regs[MRTC_MONTHS]); + yr = RTC_DCB(regs[MRTC_YEARS]) + 1900; + if (RTC_DCB(regs[MRTC_DAYS]) > nvr_get_days(mon, yr)) { + regs[MRTC_DAYS] = RTC_BCD(1); + regs[MRTC_MONTHS] = RTC_BCDINC(regs[MRTC_MONTHS], 1); + if (regs[MRTC_MONTHS] > RTC_BCD(12)) { + regs[MRTC_MONTHS] = RTC_BCD(1); + regs[MRTC_YEARS] = RTC_BCDINC(regs[MRTC_YEARS], 1) & 0xff; } } } } } +} + + +/* Get the current NVR time. */ +static void +rtc_time_get(uint8_t *regs, struct tm *tm) +{ + /* NVR is in BCD data mode. */ + tm->tm_sec = RTC_DCB(regs[MRTC_SECONDS]); + tm->tm_min = RTC_DCB(regs[MRTC_MINUTES]); + tm->tm_hour = RTC_DCB(regs[MRTC_HOURS]); + tm->tm_wday = (RTC_DCB(regs[MRTC_WEEKDAY]) - 1); + tm->tm_mday = RTC_DCB(regs[MRTC_DAYS]); + tm->tm_mon = (RTC_DCB(regs[MRTC_MONTHS]) - 1); + tm->tm_year = RTC_DCB(regs[MRTC_YEARS]); +#if USE_Y2K + tm->tm_year += (RTC_DCB(regs[MRTC_CENTURY]) * 100) - 1900; #endif } +/* Set the current NVR time. */ +static void +rtc_time_set(uint8_t *regs, struct tm *tm) +{ + /* NVR is in BCD data mode. */ + regs[MRTC_SECONDS] = RTC_BCD(tm->tm_sec); + regs[MRTC_MINUTES] = RTC_BCD(tm->tm_min); + regs[MRTC_HOURS] = RTC_BCD(tm->tm_hour); + regs[MRTC_WEEKDAY] = RTC_BCD(tm->tm_wday + 1); + regs[MRTC_DAYS] = RTC_BCD(tm->tm_mday); + regs[MRTC_MONTHS] = RTC_BCD(tm->tm_mon + 1); + regs[MRTC_YEARS] = RTC_BCD(tm->tm_year % 100); +#if USE_Y2K + regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year+1900) / 100); +#endif +} + + +static void +rtc_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (enable_sync) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + rtc_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + rtc_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + #if 0 -void europc_rtc_init(void) -{ - europc_rtc.data[0xf]=1; - - europc_rtc.timer = timer_alloc(europc_rtc_timer); - timer_adjust(europc_rtc.timer, 0, 0, 1.0); -} + /* Start the RTC - BIOS will do this. */ + nvr->regs[MRTC_CTRLSTAT] = 0x01; #endif +} + + +/* Create a valid checksum for the current NVR data. */ +static uint8_t +rtc_checksum(uint8_t *ptr) +{ + uint8_t sum; + int i; + + /* Calculate all bytes with XOR. */ + sum = 0x00; + for (i=MRTC_CONF_A; i<=MRTC_CONF_E; i++) + sum += ptr[i]; + + return(sum); +} + + +/* Reset the machine's NVR to a sane state. */ +static void +rtc_reset(nvr_t *nvr) +{ + /* Initialize the RTC to a known state. */ + nvr->regs[MRTC_SECONDS] = RTC_BCD(0); /* seconds */ + nvr->regs[MRTC_MINUTES] = RTC_BCD(0); /* minutes */ + nvr->regs[MRTC_HOURS] = RTC_BCD(0); /* hours */ + nvr->regs[MRTC_DAYS] = RTC_BCD(1); /* days */ + nvr->regs[MRTC_MONTHS] = RTC_BCD(1); /* months */ + nvr->regs[MRTC_YEARS] = RTC_BCD(80); /* years */ + nvr->regs[MRTC_WEEKDAY] = RTC_BCD(1); /* weekday */ + nvr->regs[MRTC_WEEKNO] = RTC_BCD(1); /* weekno */ + + /* + * EuroPC System Configuration: + * + * [A] unknown + * + * [B] 7 1 bootdrive extern + * 0 bootdribe intern + * 6:5 11 invalid hard disk type + * 10 hard disk installed, type 2 + * 01 hard disk installed, type 1 + * 00 hard disk not installed + * 4:3 11 invalid external drive type + * 10 external drive 720K + * 01 external drive 360K + * 00 external drive disabled + * 2 unknown + * 1:0 11 invalid internal drive type + * 10 internal drive 360K + * 01 internal drive 720K + * 00 internal drive disabled + * + * [C] 7:6 unknown + * 5 monitor detection OFF + * 4 unknown + * 3:2 11 illegal memory size + * 10 512K + * 01 256K + * 00 640K + * 1:0 11 illegal game port + * 10 gameport as mouse port + * 01 gameport as joysticks + * 00 gameport disabled + * + * [D] 7:6 10 9MHz CPU speed + * 01 7MHz CPU speed + * 00 4.77 MHz CPU + * 5 unknown + * 4 external: color, internal: mono + * 3 unknown + * 2 internal video ON + * 1:0 11 mono + * 10 color80 + * 01 color40 + * 00 special (EGA,VGA etc) + * + * [E] 7:4 unknown + * 3:0 country (00=Deutschland, 0A=ASCII) + */ + nvr->regs[MRTC_CONF_A] = 0x00; /* CONFIG A */ + nvr->regs[MRTC_CONF_B] = 0x0A; /* CONFIG B */ + nvr->regs[MRTC_CONF_C] = 0x28; /* CONFIG C */ + nvr->regs[MRTC_CONF_D] = 0x12; /* CONFIG D */ + nvr->regs[MRTC_CONF_E] = 0x0A; /* CONFIG E */ + + nvr->regs[MRTC_CHECK_LO] = 0x00; /* checksum (LO) */ + nvr->regs[MRTC_CHECK_HI] = 0x00; /* checksum (HI) */ + + nvr->regs[MRTC_CTRLSTAT] = 0x01; /* status/control */ + + /* Generate a valid checksum. */ + nvr->regs[MRTC_CHECK_LO] = rtc_checksum(nvr->regs); +} /* Execute a JIM control command. */ static void -jim_action(vm_t *sys, uint8_t reg, uint8_t val) +jim_set(europc_t *sys, uint8_t reg, uint8_t val) { switch(reg) { case 0: /* MISC control (WO) */ -//pclog("EuroPC: write MISC = %02x\n", val); // bit0: enable MOUSE // bit1: enable joystick break; case 2: /* AGA control */ -//pclog("EuroPC: write AGA = %02x\n", val); if (! (val & 0x80)) { /* Reset AGA. */ break; @@ -306,7 +413,6 @@ jim_action(vm_t *sys, uint8_t reg, uint8_t val) break; case 4: /* CPU Speed control */ -//pclog("EuroPC: write CPUCLK = %02x\n", val); switch(val & 0xc0) { case 0x00: /* 4.77 MHz */ // cpu_set_clockscale(0, 1.0/2); @@ -334,7 +440,7 @@ jim_action(vm_t *sys, uint8_t reg, uint8_t val) static void jim_write(uint16_t addr, uint8_t val, void *priv) { - vm_t *sys = (vm_t *)priv; + europc_t *sys = (europc_t *)priv; uint8_t b; #if EUROPC_DEBUG > 1 @@ -350,28 +456,30 @@ jim_write(uint16_t addr, uint8_t val, void *priv) case 0x05: case 0x06: case 0x07: - jim_action(sys, (addr & 0x07), val); + jim_set(sys, (addr & 0x07), val); break; - case 0x0A: /* M3002 RTC INDEX/DATA register */ - switch(sys->rtc.stat) { + case 0x0a: /* M3002 RTC INDEX/DATA register */ + switch(sys->nvr_stat) { case 0: /* save index */ - sys->rtc.addr = val & 0x0f; - sys->rtc.stat++; + sys->nvr_addr = val & 0x0f; + sys->nvr_stat++; break; case 1: /* save data HI nibble */ - b = sys->rtc.dat[sys->rtc.addr] & 0x0f; + b = sys->nvr.regs[sys->nvr_addr] & 0x0f; b |= (val << 4); - sys->rtc.dat[sys->rtc.addr] = b; - sys->rtc.stat++; + sys->nvr.regs[sys->nvr_addr] = b; + sys->nvr_stat++; + nvr_dosave++; break; case 2: /* save data LO nibble */ - b = sys->rtc.dat[sys->rtc.addr] & 0xf0; + b = sys->nvr.regs[sys->nvr_addr] & 0xf0; b |= (val & 0x0f); - sys->rtc.dat[sys->rtc.addr] = b; - sys->rtc.stat = 0; + sys->nvr.regs[sys->nvr_addr] = b; + sys->nvr_stat = 0; + nvr_dosave++; break; } break; @@ -387,7 +495,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) static uint8_t jim_read(uint16_t addr, void *priv) { - vm_t *sys = (vm_t *)priv; + europc_t *sys = (europc_t *)priv; uint8_t r = 0xff; switch (addr & 0x000f) { @@ -405,20 +513,20 @@ jim_read(uint16_t addr, void *priv) r = sys->regs[addr & 0x07]; break; - case 0x0A: /* M3002 RTC INDEX/DATA register */ - switch(sys->rtc.stat) { + case 0x0a: /* M3002 RTC INDEX/DATA register */ + switch(sys->nvr_stat) { case 0: r = 0x00; break; case 1: /* read data HI nibble */ - r = (sys->rtc.dat[sys->rtc.addr] >> 4); - sys->rtc.stat++; + r = (sys->nvr.regs[sys->nvr_addr] >> 4); + sys->nvr_stat++; break; case 2: /* read data LO nibble */ - r = (sys->rtc.dat[sys->rtc.addr] & 0x0f); - sys->rtc.stat = 0; + r = (sys->nvr.regs[sys->nvr_addr] & 0x0f); + sys->nvr_stat = 0; break; } break; @@ -436,120 +544,29 @@ jim_read(uint16_t addr, void *priv) } -static uint8_t -rtc_checksum(uint8_t *ptr) -{ - uint8_t sum; - int i; - - /* Calculate all bytes with XOR. */ - sum = 0x00; - for (i=MRTC_CONF_A; i<=MRTC_CONF_E; i++) - sum += ptr[i]; - - return(sum); -} - - -/* - * Initialize the mainboard 'device' of the machine. - */ +/* Initialize the mainboard 'device' of the machine. */ static void * europc_boot(device_t *info) { - vm_t *sys = vm; + europc_t *sys = &europc; uint8_t b; #if EUROPC_DEBUG pclog("EuroPC: booting mainboard..\n"); #endif - /* Try to load the NVR from file. */ - if (! nvr_load()) { - /* Load failed, reset to defaults. */ - sys->rtc.dat[0x00] = 0x00; /* RTC seconds */ - sys->rtc.dat[0x01] = 0x00; /* RTC minutes */ - sys->rtc.dat[0x02] = 0x00; /* RTC hours */ - sys->rtc.dat[0x03] = 0x01; /* RTC days */ - sys->rtc.dat[0x04] = 0x01; /* RTC months */ - sys->rtc.dat[0x05] = 0x17; /* RTC years */ - sys->rtc.dat[0x06] = 0x01; /* RTC weekday */ - sys->rtc.dat[0x07] = 0x01; /* RTC weekno */ - - /* - * EuroPC System Configuration: - * - * [A] unknown - * - * [B] 7 1 bootdrive extern - * 0 bootdribe intern - * 6:5 11 invalid hard disk type - * 10 hard disk installed, type 2 - * 01 hard disk installed, type 1 - * 00 hard disk not installed - * 4:3 11 invalid external drive type - * 10 external drive 720K - * 01 external drive 360K - * 00 external drive disabled - * 2 unknown - * 1:0 11 invalid internal drive type - * 10 internal drive 360K - * 01 internal drive 720K - * 00 internal drive disabled - * - * [C] 7:6 unknown - * 5 monitor detection OFF - * 4 unknown - * 3:2 11 illegal memory size - * 10 512K - * 01 256K - * 00 640K - * 1:0 11 illegal game port - * 10 gameport as mouse port - * 01 gameport as joysticks - * 00 gameport disabled - * - * [D] 7:6 10 9MHz CPU speed - * 01 7MHz CPU speed - * 00 4.77 MHz CPU - * 5 unknown - * 4 external: color, internal: mono - * 3 unknown - * 2 internal video ON - * 1:0 11 mono - * 10 color80 - * 01 color40 - * 00 special (EGA,VGA etc) - * - * [E] 7:4 unknown - * 3:0 country (00=Deutschland, 0A=ASCII) - */ - sys->rtc.dat[MRTC_CONF_A] = 0x00; /* CONFIG A */ - sys->rtc.dat[MRTC_CONF_B] = 0x0A; /* CONFIG B */ - sys->rtc.dat[MRTC_CONF_C] = 0x28; /* CONFIG C */ - sys->rtc.dat[MRTC_CONF_D] = 0x12; /* CONFIG D */ - sys->rtc.dat[MRTC_CONF_E] = 0x0A; /* CONFIG E */ - - sys->rtc.dat[MRTC_CHECK_LO] = 0x44; /* checksum (LO) */ - sys->rtc.dat[MRTC_CHECK_HI] = 0x00; /* checksum (HI) */ - - sys->rtc.dat[MRTC_CTRLSTAT] = 0x01; /* status/control */ - - /* Provide correct checksum. */ - sys->rtc.dat[MRTC_CHECK_LO] = rtc_checksum(sys->rtc.dat); - } pclog("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", - sys->rtc.dat[MRTC_CONF_A], sys->rtc.dat[MRTC_CONF_B], - sys->rtc.dat[MRTC_CONF_C], sys->rtc.dat[MRTC_CONF_D], - sys->rtc.dat[MRTC_CONF_E], - (sys->rtc.dat[MRTC_CHECK_LO]!=rtc_checksum(sys->rtc.dat))?"IN":""); + sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], + sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], + sys->nvr.regs[MRTC_CONF_E], + (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); /* * Now that we have initialized the NVR (either from file, * or by setting it to defaults) we can start overriding it * with values set by the user. */ - b = (sys->rtc.dat[MRTC_CONF_D] & ~0x17); + b = (sys->nvr.regs[MRTC_CONF_D] & ~0x17); switch(gfxcard) { case GFX_CGA: /* Color, CGA */ case GFX_COLORPLUS: /* Color, Hercules ColorPlus */ @@ -566,10 +583,10 @@ europc_boot(device_t *info) b |= 0x10; /* external video, special */ } - sys->rtc.dat[MRTC_CONF_D] = b; + sys->nvr.regs[MRTC_CONF_D] = b; /* Update the memory size. */ - b = (sys->rtc.dat[MRTC_CONF_C] & 0xf3); + b = (sys->nvr.regs[MRTC_CONF_C] & 0xf3); switch(mem_size) { case 256: b |= 0x04; @@ -583,10 +600,10 @@ europc_boot(device_t *info) b |= 0x00; break; } - sys->rtc.dat[MRTC_CONF_C] = b; + sys->nvr.regs[MRTC_CONF_C] = b; /* Update CPU speed. */ - b = (sys->rtc.dat[MRTC_CONF_D] & 0x3f); + b = (sys->nvr.regs[MRTC_CONF_D] & 0x3f); switch(cpu) { case 0: /* 8088, 4.77 MHz */ b |= 0x00; @@ -600,26 +617,26 @@ europc_boot(device_t *info) b |= 0x80; break; } - sys->rtc.dat[MRTC_CONF_D] = b; + sys->nvr.regs[MRTC_CONF_D] = b; /* Set up game port. */ - b = (sys->rtc.dat[MRTC_CONF_C] & 0xfc); + b = (sys->nvr.regs[MRTC_CONF_C] & 0xfc); if (mouse_type == MOUSE_TYPE_LOGIBUS) { b |= 0x01; /* enable port as MOUSE */ } else if (joystick_type != 7) { b |= 0x02; /* enable port as joysticks */ device_add(&gameport_device); } - sys->rtc.dat[MRTC_CONF_C] = b; + sys->nvr.regs[MRTC_CONF_C] = b; #if 0 /* Set up floppy types. */ - sys->rtc.dat[MRTC_CONF_B] = 0x2A; + sys->nvr.regs[MRTC_CONF_B] = 0x2a; #endif - /* Validate the NVR checksum. */ - sys->rtc.dat[MRTC_CHECK_LO] = rtc_checksum(sys->rtc.dat); - nvr_save(); + /* Validate the NVR checksum and save. */ + sys->nvr.regs[MRTC_CHECK_LO] = rtc_checksum(sys->nvr.regs); + nvr_dosave++; /* * Allocate the system's I/O handlers. @@ -630,11 +647,10 @@ europc_boot(device_t *info) * the way of other cards that need this range. */ io_sethandler(sys->jim, 16, - jim_read, NULL, NULL, - jim_write, NULL, NULL, sys); + jim_read,NULL,NULL, jim_write,NULL,NULL, sys); /* Only after JIM has been initialized. */ - device_add(&keyboard_xt_device); + (void)device_add(&keyboard_xt_device); /* * Set up and enable the HD20 disk controller. @@ -642,7 +658,7 @@ europc_boot(device_t *info) * We only do this if we have not configured another one. */ if (hdc_current == 1) - device_add(&europc_hdc_device); + (void)device_add(&europc_hdc_device); return(sys); } @@ -651,13 +667,10 @@ europc_boot(device_t *info) static void europc_close(void *priv) { - nvr_t *nvr = &vm->nvr; + nvr_t *nvr = &europc.nvr; - if (nvr->fname != NULL) - free(nvr->fname); - - free(vm); - vm = NULL; + if (nvr->fn != NULL) + free(nvr->fn); } @@ -685,9 +698,7 @@ static device_config_t europc_config[] = { device_t europc_device = { "EuroPC System Board", 0, 0, - europc_boot, /* init */ - europc_close, /* close */ - NULL, + europc_boot, europc_close, NULL, NULL, NULL, NULL, NULL, europc_config }; @@ -704,36 +715,28 @@ device_t europc_device = { void machine_europc_init(machine_t *model) { - vm_t *sys; - - /* Allocate machine data. */ - sys = (vm_t *)malloc(sizeof(vm_t)); - if (sys == NULL) { - pclog("EuroPC: unable to allocate machine data!\n"); - return; - } - memset(sys, 0x00, sizeof(vm_t)); - sys->jim = 0x0250; - vm = sys; + /* Clear the machine state. */ + memset(&europc, 0x00, sizeof(europc_t)); + europc.jim = 0x0250; machine_common_init(model); nmi_init(); mem_add_bios(); /* This is machine specific. */ - vm->nvr.mask = model->nvrmask; - vm->nvr.irq = -1; + europc.nvr.size = model->nvrsz; + europc.nvr.irq = -1; /* Set up any local handlers here. */ - vm->nvr.load = load_nvr; - vm->nvr.save = save_nvr; - vm->nvr.hook = rtc_hook; + europc.nvr.reset = rtc_reset; + europc.nvr.start = rtc_start; + europc.nvr.tick = rtc_tick; /* Initialize the actual NVR. */ - nvr_init(&vm->nvr); + nvr_init(&europc.nvr); /* Enable and set up the FDC. */ - device_add(&fdc_xt_device); + (void)device_add(&fdc_xt_device); /* Enable and set up the mainboard device. */ device_add(&europc_device); diff --git a/src/machine/m_europc_hdc.c b/src/machine/m_europc_hdc.c index b7de832..81f6f8b 100644 --- a/src/machine/m_europc_hdc.c +++ b/src/machine/m_europc_hdc.c @@ -22,7 +22,7 @@ * * Based on the original "xebec.c" from Sarah Walker. * - * Version: @(#)m_europc_hdc.c 1.0.1 2018/02/14 + * Version: @(#)m_europc_hdc.c 1.0.2 2018/03/11 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -81,7 +81,7 @@ #include "machine.h" -#define HDC_DEBUG 1 +#define HDC_DEBUG 0 #define HDC_NEWPARAMS 1 /* use NEW parameter block */ #define HDD_IOADDR 0x0320 diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index 61aa05a..a322b73 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -8,7 +8,7 @@ * * Emulation of the Olivetti M24. * - * Version: @(#)m_olivetti_m24.c 1.0.1 2018/02/14 + * Version: @(#)m_olivetti_m24.c 1.0.2 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -78,7 +78,8 @@ typedef struct { mem_mapping_t mapping; uint8_t crtc[32]; int crtcreg; - uint8_t monitor_type, port_23c6; + uint8_t monitor_type, + port_23c6; uint8_t *vram; uint8_t charbuffer[256]; uint8_t ctrl; @@ -124,8 +125,7 @@ static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; - - + #ifdef ENABLE_M24VID_LOG int m24vid_do_log = ENABLE_M24VID_LOG; #endif @@ -144,8 +144,8 @@ m24_log(const char *fmt, ...) fflush(stdlog); } #endif -} - +} + static void recalc_timings(olim24_t *m24) { @@ -174,11 +174,11 @@ vid_out(uint16_t addr, uint8_t val, void *priv) uint8_t old; switch (addr) { - case 0x3d4: + case 0x03d4: m24->crtcreg = val & 31; break; - case 0x3d5: + case 0x03d5: old = m24->crtc[m24->crtcreg]; m24->crtc[m24->crtcreg] = val & crtcmask[m24->crtcreg]; if (old != val) { @@ -189,23 +189,23 @@ vid_out(uint16_t addr, uint8_t val, void *priv) } break; - case 0x3d8: + case 0x03d8: m24->cgamode = val; break; - case 0x3d9: + case 0x03d9: m24->cgacol = val; break; - case 0x3de: + case 0x03de: m24->ctrl = val; m24->base = (val & 0x08) ? 0x4000 : 0; break; - + case 0x13c6: m24->monitor_type = val; break; - + case 0x23c6: m24->port_23c6 = val; break; @@ -220,22 +220,22 @@ vid_in(uint16_t addr, void *priv) uint8_t ret = 0xff; switch (addr) { - case 0x3d4: + case 0x03d4: ret = m24->crtcreg; break; - case 0x3d5: + case 0x03d5: ret = m24->crtc[m24->crtcreg]; break; - case 0x3da: + case 0x03da: ret = m24->stat; break; - + case 0x13c6: ret = m24->monitor_type; break; - + case 0x23c6: ret = m24->port_23c6; break; @@ -250,7 +250,7 @@ vid_write(uint32_t addr, uint8_t val, void *priv) { olim24_t *m24 = (olim24_t *)priv; - m24->vram[addr & 0x7FFF]=val; + m24->vram[addr & 0x7fff] = val; m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; } @@ -261,7 +261,7 @@ vid_read(uint32_t addr, void *priv) { olim24_t *m24 = (olim24_t *)priv; - return(m24->vram[addr & 0x7FFF]); + return(m24->vram[addr & 0x7fff]); } @@ -291,13 +291,12 @@ vid_poll(void *priv) m24->firstline = m24->displine; } m24->lastline = m24->displine; - for (c = 0; c < 8; c++) - { + for (c = 0; c < 8; c++) { if ((m24->cgamode & 0x12) == 0x12) { buffer->line[m24->displine][c] = 0; if (m24->cgamode & 1) buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = 0; - else + else buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = 0; } else { buffer->line[m24->displine][c] = (m24->cgacol & 15) + 16; @@ -355,13 +354,13 @@ vid_poll(void *priv) buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } } - } else if (!(m24->cgamode & 16)) { + } else if (! (m24->cgamode & 16)) { cols[0] = (m24->cgacol & 15) | 16; col = (m24->cgacol & 16) ? 24 : 16; if (m24->cgamode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; } else if (m24->cgacol & 32) { cols[1] = col | 3; cols[2] = col | 5; @@ -389,7 +388,7 @@ vid_poll(void *priv) dat2 = (m24->sc & 1) * 0x2000; cols[0] = 0; cols[1] = (m24->cgacol & 15) + 16; } - + for (x = 0; x < m24->crtc[1]; x++) { dat = (m24->vram[((m24->ma << 1) & 0x1fff) + dat2] << 8) | m24->vram[((m24->ma << 1) & 0x1fff) + dat2 + 1]; m24->ma++; @@ -407,14 +406,15 @@ vid_poll(void *priv) if (m24->cgamode & 1) x = (m24->crtc[1] << 3) + 16; - else + else x = (m24->crtc[1] << 4) + 16; m24->sc = oldsc; if (m24->vc == m24->crtc[7] && !m24->sc) m24->stat |= 8; m24->displine++; - if (m24->displine >= 720) m24->displine = 0; + if (m24->displine >= 720) + m24->displine = 0; } else { m24->vidtime += m24->dispontime; if (m24->dispon) m24->stat &= ~1; @@ -425,8 +425,8 @@ vid_poll(void *priv) } else { if (m24->vsynctime) { m24->vsynctime--; - if (!m24->vsynctime) - m24->stat &= ~8; + if (! m24->vsynctime) + m24->stat &= ~8; } if (m24->sc == (m24->crtc[11] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[11] & 31) >> 1))) { m24->con = 0; @@ -437,7 +437,7 @@ vid_poll(void *priv) m24->sc &= 31; m24->ma = m24->maback; m24->vadj--; - if (!m24->vadj) { + if (! m24->vadj) { m24->dispon = 1; m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff; m24->sc = 0; @@ -455,11 +455,13 @@ vid_poll(void *priv) if (oldvc == m24->crtc[4]) { m24->vc = 0; m24->vadj = m24->crtc[5]; - if (!m24->vadj) m24->dispon = 1; - if (!m24->vadj) m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff; + if (! m24->vadj) + m24->dispon = 1; + if (! m24->vadj) + m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff; if ((m24->crtc[10] & 0x60) == 0x20) m24->cursoron = 0; - else + else m24->cursoron = m24->blink & 16; } @@ -470,7 +472,7 @@ vid_poll(void *priv) if (m24->crtc[7]) { if (m24->cgamode & 1) x = (m24->crtc[1] << 3) + 16; - else + else x = (m24->crtc[1] << 4) + 16; m24->lastline++; if ((x != xsize) || ((m24->lastline - m24->firstline) != ysize) || video_force_resize_get()) { @@ -493,15 +495,15 @@ vid_poll(void *priv) video_res_x /= 8; video_res_y /= (m24->crtc[9] + 1) * 2; video_bpp = 0; - } else if (!(m24->cgamode & 2)) { + } else if (! (m24->cgamode & 2)) { video_res_x /= 16; video_res_y /= (m24->crtc[9] + 1) * 2; video_bpp = 0; - } else if (!(m24->cgamode & 16)) { + } else if (! (m24->cgamode & 16)) { video_res_x /= 2; video_res_y /= 2; video_bpp = 2; - } else if (!(m24->ctrl & 1)) { + } else if (! (m24->ctrl & 1)) { video_res_y /= 2; video_bpp = 1; } @@ -737,7 +739,7 @@ ms_poll(int x, int y, int z, int b, void *priv) if (((key_queue_end - key_queue_start) & 0xf) > 12) return(0xff); if (!m24->x && !m24->y) return(0xff); - + m24->y = -m24->y; if (m24->x < -127) m24->x = -127; @@ -789,14 +791,16 @@ m24_read(uint16_t port, void *priv) { switch (port) { case 0x66: - return 0x00; + return(0x00); + case 0x67: - return 0x20 | 0x40 | 0x0C; + return(0x20 | 0x40 | 0x0c); } return(0xff); } + static void vid_close(void *priv) { @@ -807,8 +811,9 @@ vid_close(void *priv) free(m24); } + device_t m24_device = { - "Olivetti M24", + "Olivetti M24 Video", 0, 0, NULL, vid_close, NULL, NULL, @@ -829,15 +834,17 @@ machine_olim24_init(machine_t *model) machine_common_init(model); device_add(&fdc_xt_device); - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, m24); + io_sethandler(0x0066, 2, + m24_read,NULL,NULL, NULL,NULL,NULL, m24); /* Initialize the video adapter. */ m24->vram = malloc(0x8000); overscan_x = overscan_y = 16; mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, m24); - io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, m24); + vid_read,NULL,NULL, + vid_write,NULL,NULL, NULL, 0, m24); + io_sethandler(0x03d0, 16, + vid_in,NULL,NULL, vid_out,NULL,NULL, m24); timer_add(vid_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); device_add_ex(&m24_device, m24); @@ -851,10 +858,10 @@ machine_olim24_init(machine_t *model) m24->scan[5] = 0x48; m24->scan[6] = 0x50; io_sethandler(0x0060, 2, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, m24); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, m24); io_sethandler(0x0064, 1, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, m24); - keyboard_set_table(scancode_xt); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, m24); + keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; keyboard_scan = 1; timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, m24); @@ -872,7 +879,11 @@ machine_olim24_init(machine_t *model) nmi_init(); } -void machine_olim24_video_init(void) { + +#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) +void +machine_olim24_video_init(void) +{ olim24_t *m24; m24 = (olim24_t *)malloc(sizeof(olim24_t)); @@ -882,11 +893,15 @@ void machine_olim24_video_init(void) { m24->vram = malloc(0x8000); overscan_x = overscan_y = 16; mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, m24); - io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, m24); - io_sethandler(0x13c6, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, m24); - io_sethandler(0x23c6, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, m24); + vid_read,NULL,NULL, + vid_write,NULL,NULL, NULL, 0, m24); + io_sethandler(0x03d0, 16, + vid_in,NULL,NULL, vid_out,NULL,NULL, m24); + io_sethandler(0x13c6, 1, + vid_in,NULL,NULL, vid_out,NULL,NULL, m24); + io_sethandler(0x23c6, 1, + vid_in,NULL,NULL, vid_out,NULL,NULL, m24); timer_add(vid_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); device_add_ex(&m24_device, m24); } +#endif diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index 7767a66..c55be0c 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -1,713 +1,978 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Toshiba T1000 and T1200 portables. - * - * The T1000 is the T3100e's little brother -- a real laptop - * with a rechargeable battery. - * - * Features: 80C88 at 4.77MHz - * - 512k system RAM - * - 640x200 monochrome LCD - * - 82-key keyboard - * - Real-time clock. Not the normal 146818, but a TC8521, - * which is a 4-bit chip. - * - A ROM drive (128k, 256k or 512k) which acts as a mini - * hard drive and contains a copy of DOS 2.11. - * - 160 bytes of non-volatile RAM for the CONFIG.SYS used - * when booting from the ROM drive. Possibly physically - * located in the keyboard controller RAM. - * - * An optional memory expansion board can be fitted. This adds - * 768k of RAM, which can be used for up to three purposes: - * > Conventional memory -- 128k between 512k and 640k - * > HardRAM -- a battery-backed RAM drive. - * > EMS - * - * This means that there are up to three different - * implementations of non-volatile RAM in the same computer - * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and - * up to 768k of HardRAM). - * - * The T1200 is a slightly upgraded version with a turbo mode - * (double CPU clock, 9.54MHz) and an optional hard drive. - * The interface for this is proprietary both at the physical - * and programming level. - * - * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] - * or 0Dh [10Mb]. - * - * Version: @(#)m_xt_t1000.c 1.0.1 2018/03/05 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2018 Miran Grca. - * Copyright 2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../device.h" -#include "../io.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../mem.h" -#include "../nmi.h" -#include "../nvr.h" -#include "../nvr_tc8521.h" -#include "../pit.h" -#include "../plat.h" -#include "../rom.h" -#include "../cpu/cpu.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "machine.h" -#include "m_xt_t1000.h" - - -static struct t1000_system -{ - /* ROM drive */ - uint8_t *romdrive; - uint8_t rom_ctl; - uint32_t rom_offset; - mem_mapping_t rom_mapping; - - /* System control registers */ - uint8_t sys_ctl[16]; - uint8_t syskeys; - uint8_t turbo; - - /* NVRAM control */ - uint8_t nvr_c0; - uint8_t nvr_tick; - int nvr_addr; - uint8_t nvr_active; - - /* EMS data */ - uint8_t ems_reg[4]; - mem_mapping_t mapping[4]; - uint32_t page_exec[4]; - uint8_t ems_port_index; - uint16_t ems_port; - uint8_t is_640k; - uint32_t ems_base; - int32_t ems_pages; - - fdc_t *fdc; -} t1000; - - -static uint8_t config_sys[160]; - - -#define T1000_ROMSIZE (512 * 1024) /* Maximum ROM drive size is 512k */ - -/* The CONFIG.SYS storage (160 bytes) and battery-backed EMS (all RAM - * above 512k) are implemented as NVR devices */ - -void t1000_configsys_loadnvr(void) -{ - FILE *f; - - memset(config_sys, 0x1A, sizeof(config_sys)); - f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"rb"); - if (f) - { - fread(config_sys, sizeof(config_sys), 1, f); - fclose(f); - } -} - -/* All RAM beyond 512k is non-volatile */ -void t1000_emsboard_loadnvr(void) -{ - FILE *f; - - if (mem_size > 512) - { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"rb"); - if (f) - { - fread(&ram[512 * 1024], - 1024, (mem_size - 512), f); - fclose(f); - } - } -} - -void t1000_configsys_savenvr(void) -{ - FILE *f; - - f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"wb"); - if (f) - { - fwrite(config_sys, sizeof(config_sys), 1, f); - fclose(f); - } -} - - -void t1000_emsboard_savenvr(void) -{ - FILE *f; - - if (mem_size > 512) - { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"wb"); - if (f) - { - fwrite(&ram[512 * 1024], - 1024, (mem_size - 512), f); - fclose(f); - } - } -} - - - -/* Given an EMS page ID, return its physical address in RAM. */ -uint32_t ems_execaddr(struct t1000_system *sys, int pg, uint16_t val) -{ - if (!(val & 0x80)) return 0; /* Bit 7 reset => not mapped */ - if (!sys->ems_pages) return 0; /* No EMS available: all used by - * HardRAM or conventional RAM */ - - val &= 0x7F; - -/* pclog("Select EMS page: %d of %d\n", val, sys->ems_pages); */ - if (val < sys->ems_pages) - { -/* EMS is any memory above 512k, with ems_base giving the start address */ - return (512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val); - } - return 0; -} - - -static uint8_t ems_in(uint16_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - -/* pclog("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); */ - return sys->ems_reg[(addr >> 14) & 3]; -} - -static void ems_out(uint16_t addr, uint8_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = (addr >> 14) & 3; - -/* pclog("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); */ - sys->ems_reg[pg] = val; - sys->page_exec[pg] = ems_execaddr(sys, pg, val); - if (sys->page_exec[pg]) /* Page present */ - { - mem_mapping_enable(&sys->mapping[pg]); - mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); - } - else - { - mem_mapping_disable(&sys->mapping[pg]); - } -} - - -/* Hardram size is in 64k units */ -static void ems_set_hardram(struct t1000_system *sys, uint8_t val) -{ - int n; - - val &= 0x1F; /* Mask off pageframe address */ - if (val && mem_size > 512) - { - sys->ems_base = val; - } - else - { - sys->ems_base = 0; - } -/* pclog("EMS base set to %02x\n", val); */ - sys->ems_pages = 48 - 4 * sys->ems_base; - if (sys->ems_pages < 0) sys->ems_pages = 0; - /* Recalculate EMS mappings */ - for (n = 0; n < 4; n++) - { - ems_out(n << 14, sys->ems_reg[n], sys); - } -} - - -static void ems_set_640k(struct t1000_system *sys, uint8_t val) -{ - if (val && mem_size >= 640) - { - mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); - sys->is_640k = 1; - } - else - { - mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); - sys->is_640k = 0; - } -} - -static void ems_set_port(struct t1000_system *sys, uint8_t val) -{ - int n; - -/* pclog("ems_set_port(%d)", val & 0x0F); */ - if (sys->ems_port) - { - for (n = 0; n <= 0xC000; n += 0x4000) - { - io_removehandler(sys->ems_port + n, 0x01, - ems_in, NULL, NULL, ems_out, NULL, NULL, sys); - } - sys->ems_port = 0; - } - val &= 0x0F; - sys->ems_port_index = val; - if (val == 7) /* No EMS */ - { - sys->ems_port = 0; - } - else - { - sys->ems_port = 0x208 | (val << 4); - for (n = 0; n <= 0xC000; n += 0x4000) - { - io_sethandler(sys->ems_port + n, 0x01, - ems_in, NULL, NULL, ems_out, NULL, NULL, sys); - } - sys->ems_port = 0; - } -/* pclog(" -> %04x\n", sys->ems_port); */ -} - -static int addr_to_page(uint32_t addr) -{ - return (addr - 0xD0000) / 0x4000; -} - -/* Read RAM in the EMS page frame */ -static uint8_t ems_read_ram(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return 0xFF; - addr = sys->page_exec[pg] + (addr & 0x3FFF); - return ram[addr]; -} - - - - -static uint16_t ems_read_ramw(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return 0xFF; - /* pclog("ems_read_ramw addr=%05x ", addr); */ - addr = sys->page_exec[pg] + (addr & 0x3FFF); - /* pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); */ - return *(uint16_t *)&ram[addr]; -} - - -static uint32_t ems_read_raml(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return 0xFF; - addr = sys->page_exec[pg] + (addr & 0x3FFF); - return *(uint32_t *)&ram[addr]; -} - -/* Write RAM in the EMS page frame */ -static void ems_write_ram(uint32_t addr, uint8_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - addr = sys->page_exec[pg] + (addr & 0x3FFF); - if (ram[addr] != val) nvr_dosave = 1; - ram[addr] = val; -} - - -static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - /* pclog("ems_write_ramw addr=%05x ", addr); */ - addr = sys->page_exec[pg] + (addr & 0x3FFF); - /* pclog("-> %06x val=%04x\n", addr, val); */ - - if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; - *(uint16_t *)&ram[addr] = val; -} - - -static void ems_write_raml(uint32_t addr, uint32_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - addr = sys->page_exec[pg] + (addr & 0x3FFF); - if (*(uint32_t *)&ram[addr] != val) nvr_dosave = 1; - *(uint32_t *)&ram[addr] = val; -} - - - - - -void t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) -{ - t1000.syskeys &= ~andmask; - t1000.syskeys |= ormask; - t1000.syskeys ^= xormask; -} - - - -static uint8_t read_t1000_ctl(uint16_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - switch (addr & 0x0F) - { - case 1: return sys->syskeys; -/* Detect EMS board */ - case 0x0F: switch (sys->sys_ctl[0x0E]) - { - case 0x50: if (mem_size <= 512) - return 0xFF; - return 0x90 | sys->ems_port_index; -/* 0x60 is the page frame address: (0xD000 - 0xC400) / 0x20 */ - case 0x51: return sys->ems_base | 0x60; - case 0x52: return sys->is_640k ? 0x80 : 0; - } - return 0xFF; - default: return sys->sys_ctl[addr & 0x0F]; - } -} - -static void t1200_turbo_set(uint8_t value) -{ - if (value == t1000.turbo) - { - return; - } - t1000.turbo = value; - if (!value) - { - cpu_dynamic_switch(0); - } - else - { - cpu_dynamic_switch(cpu); - } -} - -static void write_t1000_ctl(uint16_t addr, uint8_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - sys->sys_ctl[addr & 0x0F] = val; - switch (addr & 0x0F) - { - /* Video control */ - case 4: if (sys->sys_ctl[3] == 0x5A) - { - t1000_video_options_set((val & 0x20) ? 1 : 0); - t1000_display_set((val & 0x40) ? 0 : 1); - if (romset == ROM_T1200) - { - t1200_turbo_set((val & 0x80) ? 1 : 0); - } - } - break; - /* EMS control*/ - case 0x0F: - switch (sys->sys_ctl[0x0E]) - { - case 0x50: ems_set_port(sys, val); break; - case 0x51: ems_set_hardram(sys, val); break; - case 0x52: ems_set_640k(sys, val); break; - } - break; - - } -} - -/* Ports 0xC0 to 0xC3 appear to have two purposes: - * - * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS - * > Reading the floppy changeline. I don't know why the Toshiba doesn't - * use the normal port 0x3F7 for this, but it doesn't. - * - */ -static uint8_t read_t1000_nvram(uint16_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - uint8_t tmp; - - switch (addr) - { - case 0xC2: /* Read next byte from NVRAM */ - tmp = 0xFF; - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) - tmp = config_sys[sys->nvr_addr]; - ++sys->nvr_addr; - return tmp; - - case 0xC3: /* Read floppy changeline and NVRAM ready state */ - tmp = fdc_read(0x3F7, t1000.fdc); - - tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ - tmp |= (sys->nvr_active & 0xC0);/* Bits 6,7 are r/w mode */ - tmp |= 0x2E; /* Bits 5,3,2,1 always 1 */ - tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ - return tmp; - } - return 0xFF; -} - -static void write_t1000_nvram(uint16_t addr, uint8_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - switch (addr) - { -/* On the real T1000, port 0xC1 is only usable as the high byte of a 16-bit - * write to port 0xC0, with 0x5A in the low byte. */ - case 0xC0: sys->nvr_c0 = val; - break; -/* Write next byte to NVRAM */ - case 0xC1: if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) - { - if (config_sys[sys->nvr_addr] != val) - nvr_dosave = 1; - config_sys[sys->nvr_addr] = val; - } - ++sys->nvr_addr; - break; - case 0xC2: break; -/* At start of NVRAM read / write, 0x80 is written to port 0xC3. This seems - * to reset the NVRAM address counter. A single byte is then written (0xFF - * for write, 0x00 for read) which appears to be ignored. Simulate that by - * starting the address counter off at -1 */ - case 0xC3: sys->nvr_active = val; - if (val == 0x80) sys->nvr_addr = -1; - break; - } -} - -/* Port 0xC8 controls the ROM drive */ -static uint8_t read_t1000_rom_ctl(uint16_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - return sys->rom_ctl; -} - -static void write_t1000_rom_ctl(uint16_t addr, uint8_t val, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - sys->rom_ctl = val; - if (sys->romdrive && (val & 0x80)) /* Enable */ - { - sys->rom_offset = ((val & 0x7F) * 0x10000) % T1000_ROMSIZE; - mem_mapping_set_addr(&sys->rom_mapping, 0xA0000, 0x10000); - mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + - sys->rom_offset); - mem_mapping_enable(&sys->rom_mapping); - } - else - { - mem_mapping_disable(&sys->rom_mapping); - } -} - - -/* Read the ROM drive */ -static uint8_t t1000_read_rom(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - if (!sys->romdrive) return 0xFF; - return sys->romdrive[sys->rom_offset + (addr & 0xFFFF)]; -} - -static uint16_t t1000_read_romw(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - if (!sys->romdrive) return 0xFFFF; - return *(uint16_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xFFFF)]); -} - - -static uint32_t t1000_read_roml(uint32_t addr, void *priv) -{ - struct t1000_system *sys = (struct t1000_system *)priv; - - if (!sys->romdrive) return 0xFFFFFFFF; - return *(uint32_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xFFFF)]); -} - - -device_t * -t1000_get_device(void) -{ - return &t1000_device; -} - - -void machine_xt_t1000_init(machine_t *model) -{ - FILE *f; - int pg; - - memset(&t1000, 0, sizeof(t1000)); - t1000.turbo = 0xff; - t1000.ems_port_index = 7; /* EMS disabled */ -/* The ROM drive is optional. If the file is missing, continue to boot; the - * BIOS will complain 'No ROM drive' but boot normally from floppy. */ - - f = rom_fopen(L"roms/machines/toshiba/t1000/t1000dos.rom"); - if (f) - { - t1000.romdrive = malloc(T1000_ROMSIZE); - if (t1000.romdrive) - { - memset(t1000.romdrive, 0xFF, T1000_ROMSIZE); - fread(t1000.romdrive, T1000_ROMSIZE, 1, f); - } - fclose(f); - } - mem_mapping_add(&t1000.rom_mapping, 0xA0000, 0x10000, - t1000_read_rom, t1000_read_romw, t1000_read_roml, - NULL, NULL, NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); - mem_mapping_disable(&t1000.rom_mapping); - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) - { - mem_mapping_add(&t1000.mapping[pg], - 0xD0000 + (0x4000 * pg), 16384, - ems_read_ram, ems_read_ramw, ems_read_raml, - ems_write_ram, ems_write_ramw, ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, - &t1000); - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); - } - - /* Non-volatile RAM for CONFIG.SYS */ - io_sethandler(0xC0, 4, read_t1000_nvram, NULL, NULL, - write_t1000_nvram, NULL, NULL, &t1000); - /* ROM drive */ - io_sethandler(0xC8, 1, read_t1000_rom_ctl, NULL, NULL, - write_t1000_rom_ctl, NULL, NULL, &t1000); - /* System control functions, and add-on memory board */ - io_sethandler(0xE0, 0x10, read_t1000_ctl, NULL, NULL, - write_t1000_ctl, NULL, NULL, &t1000); - - machine_common_init(model); - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_device); - nmi_init(); - nvr_tc8521_init(); -/* No gameport, and no provision to fit one device_add(&gameport_device); */ - device_add(&t1000_device); -} - - -device_t * -t1200_get_device(void) -{ - return &t1200_device; -} - - -void machine_xt_t1200_init(machine_t *model) -{ - int pg; - - memset(&t1000, 0, sizeof(t1000)); - t1000.ems_port_index = 7; /* EMS disabled */ - - mem_mapping_add(&t1000.rom_mapping, 0xA0000, 0x10000, - t1000_read_rom, t1000_read_romw, t1000_read_roml, - NULL, NULL, NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); - mem_mapping_disable(&t1000.rom_mapping); - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) - { - mem_mapping_add(&t1000.mapping[pg], - 0xD0000 + (0x4000 * pg), 16384, - ems_read_ram, ems_read_ramw, ems_read_raml, - ems_write_ram, ems_write_ramw, ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, - &t1000); - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); - } - - /* System control functions, and add-on memory board */ - io_sethandler(0xE0, 0x10, read_t1000_ctl, NULL, NULL, - write_t1000_ctl, NULL, NULL, &t1000); - - machine_common_init(model); - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_device); - nmi_init(); - nvr_tc8521_init(); -/* No gameport, and no provision to fit one device_add(&gameport_device); */ - device_add(&t1200_device); -} +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Toshiba T1000 and T1200 portables. + * + * The T1000 is the T3100e's little brother -- a real laptop + * with a rechargeable battery. + * + * Features: 80C88 at 4.77MHz + * - 512k system RAM + * - 640x200 monochrome LCD + * - 82-key keyboard + * - Real-time clock. Not the normal 146818, but a TC8521, + * which is a 4-bit chip. + * - A ROM drive (128k, 256k or 512k) which acts as a mini + * hard drive and contains a copy of DOS 2.11. + * - 160 bytes of non-volatile RAM for the CONFIG.SYS used + * when booting from the ROM drive. Possibly physically + * located in the keyboard controller RAM. + * + * An optional memory expansion board can be fitted. This adds + * 768k of RAM, which can be used for up to three purposes: + * > Conventional memory -- 128k between 512k and 640k + * > HardRAM -- a battery-backed RAM drive. + * > EMS + * + * This means that there are up to three different + * implementations of non-volatile RAM in the same computer + * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and + * up to 768k of HardRAM). + * + * The T1200 is a slightly upgraded version with a turbo mode + * (double CPU clock, 9.54MHz) and an optional hard drive. + * The interface for this is proprietary both at the physical + * and programming level. + * + * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] + * or 0Dh [10Mb]. + * + * The hard drive is a 20MB (615/2/26) RLL 3.5" drive. + * + * The TC8521 is a 4-bit RTC, so each memory location can only + * hold a single BCD digit. Hence everything has 'ones' and + * 'tens' digits. + * + * NOTE: Still need to figure out a way to load/save ConfigSys and + * HardRAM stuff. Needs to be linked in to the NVR code. + * + * Version: @(#)m_xt_t1000.c 1.0.2 2018/03/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Miran Grca. + * Copyright 2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../cpu/cpu.h" +#include "../io.h" +#include "../pit.h" +#include "../nmi.h" +#include "../mem.h" +#include "../rom.h" +#include "../nvr.h" +#include "../device.h" +#include "../keyboard.h" +#include "../lpt.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" +#include "../game/gameport.h" +#include "../video/video.h" +#include "../plat.h" +#include "machine.h" +#include "m_xt_t1000.h" + + +#define T1000_ROMSIZE (512*1024UL) /* Maximum ROM drive size is 512k */ + + +enum TC8521_ADDR { + /* Page 0 registers */ + TC8521_SECOND1 = 0, + TC8521_SECOND10, + TC8521_MINUTE1, + TC8521_MINUTE10, + TC8521_HOUR1, + TC8521_HOUR10, + TC8521_WEEKDAY, + TC8521_DAY1, + TC8521_DAY10, + TC8521_MONTH1, + TC8521_MONTH10, + TC8521_YEAR1, + TC8521_YEAR10, + TC8521_PAGE, /* PAGE register */ + TC8521_TEST, /* TEST register */ + TC8521_RESET, /* RESET register */ + + /* Page 1 registers */ + TC8521_24HR = 0x1A, + TC8521_LEAPYEAR = 0x1B +}; + + +typedef struct { + /* ROM drive */ + uint8_t *romdrive; + uint8_t rom_ctl; + uint32_t rom_offset; + mem_mapping_t rom_mapping; + + /* CONFIG.SYS drive. */ + uint8_t config[160]; + + /* System control registers */ + uint8_t sys_ctl[16]; + uint8_t syskeys; + uint8_t turbo; + + /* NVRAM control */ + uint8_t nvr_c0; + uint8_t nvr_tick; + int nvr_addr; + uint8_t nvr_active; + + /* EMS data */ + uint8_t ems_reg[4]; + mem_mapping_t mapping[4]; + uint32_t page_exec[4]; + uint8_t ems_port_index; + uint16_t ems_port; + uint8_t is_640k; + uint32_t ems_base; + int32_t ems_pages; + + fdc_t *fdc; + + nvr_t nvr; +} t1000_t; + + +static t1000_t t1000; + + +/* Set the chip time. */ +static void +tc8521_time_set(uint8_t *regs, struct tm *tm) +{ + regs[TC8521_SECOND1] = (tm->tm_sec % 10); + regs[TC8521_SECOND10] = (tm->tm_sec / 10); + regs[TC8521_MINUTE1] = (tm->tm_min % 10); + regs[TC8521_MINUTE10] = (tm->tm_min / 10); + if (regs[TC8521_24HR] & 0x01) { + regs[TC8521_HOUR1] = (tm->tm_hour % 10); + regs[TC8521_HOUR10] = (tm->tm_hour / 10); + } else { + regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); + regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | + ((tm->tm_hour >= 12) ? 2 : 0)); + } + regs[TC8521_WEEKDAY] = tm->tm_wday; + regs[TC8521_DAY1] = (tm->tm_mday % 10); + regs[TC8521_DAY10] = (tm->tm_mday / 10); + regs[TC8521_MONTH1] = ((tm->tm_mon + 1) / 10); + regs[TC8521_MONTH10] = ((tm->tm_mon + 1) % 10); + regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); + regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); +} + + +/* Get the chip time. */ +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +static void +tc8521_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(TC8521_SECOND); + tm->tm_min = nibbles(TC8521_MINUTE); + if (regs[TC8521_24HR] & 0x01) + tm->tm_hour = nibbles(TC8521_HOUR); + else + tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + + (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); +//FIXME: wday + tm->tm_mday = nibbles(TC8521_DAY); + tm->tm_mon = (nibbles(TC8521_MONTH) - 1); + tm->tm_year = (nibbles(TC8521_YEAR) + 1980); +} + + +/* This is called every second through the NVR/RTC hook. */ +static void +tc8521_tick(nvr_t *nvr) +{ + pclog("TC8521: ping\n"); +} + + +static void +tc8521_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (enable_sync) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + tc8521_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + tc8521_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + +#if 0 + /* Start the RTC - BIOS will do this. */ + nvr->regs[TC8521_PAGE] |= 0x80; +#endif +} + + +/* Write to one of the chip registers. */ +static void +tc8521_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t page; + + /* Get to the correct register page. */ + addr &= 0x0f; + page = nvr->regs[0x0d] & 0x03; + if (addr < 0x0d) + addr += (16 * page); + + if (addr >= 0x10 && nvr->regs[addr] != val) + nvr_dosave = 1; + + /* Store the new value. */ + nvr->regs[addr] = val; +} + + +/* Read from one of the chip registers. */ +static uint8_t +tc8521_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t page; + + /* Get to the correct register page. */ + addr &= 0x0f; + page = nvr->regs[0x0d] & 0x03; + if (addr < 0x0d) + addr += (16 * page); + + /* Grab and return the desired value. */ + return(nvr->regs[addr]); +} + + +/* Reset the 8521 to a default state. */ +static void +tc8521_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 16); + nvr->regs[TC8521_WEEKDAY] = 0x01; + nvr->regs[TC8521_DAY1] = 0x01; + nvr->regs[TC8521_MONTH1] = 0x01; +} + + +static void +tc8521_init(nvr_t *nvr, int size) +{ + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + + /* Set up any local handlers here. */ + nvr->reset = tc8521_reset; + nvr->start = tc8521_start; + nvr->tick = tc8521_tick; + + /* Initialize the actual NVR. */ + nvr_init(nvr); + + io_sethandler(0x02c0, 16, + tc8521_read,NULL,NULL, tc8521_write,NULL,NULL, nvr); +} + + +/* Given an EMS page ID, return its physical address in RAM. */ +static uint32_t +ems_execaddr(t1000_t *sys, int pg, uint16_t val) +{ + if (!(val & 0x80)) return(0); /* Bit 7 reset => not mapped */ + if (!sys->ems_pages) return(0); /* No EMS available: all used by + * HardRAM or conventional RAM */ + val &= 0x7f; + +#if 0 + pclog("Select EMS page: %d of %d\n", val, sys->ems_pages); +#endif + if (val < sys->ems_pages) { + /* EMS is any memory above 512k, + with ems_base giving the start address */ + return((512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val)); + } + + return(0); +} + + +static uint8_t +ems_in(uint16_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + +#if 0 + pclog("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); +#endif + return(sys->ems_reg[(addr >> 14) & 3]); +} + + +static void +ems_out(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = (addr >> 14) & 3; + +#if 0 + pclog("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); +#endif + sys->ems_reg[pg] = val; + sys->page_exec[pg] = ems_execaddr(sys, pg, val); + if (sys->page_exec[pg]) { + /* Page present */ + mem_mapping_enable(&sys->mapping[pg]); + mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); + } else { + mem_mapping_disable(&sys->mapping[pg]); + } +} + + +/* Hardram size is in 64k units */ +static void +ems_set_hardram(t1000_t *sys, uint8_t val) +{ + int n; + + val &= 0x1f; /* Mask off pageframe address */ + if (val && mem_size > 512) + sys->ems_base = val; + else + sys->ems_base = 0; + +#if 0 + pclog("EMS base set to %02x\n", val); +#endif + sys->ems_pages = 48 - 4 * sys->ems_base; + if (sys->ems_pages < 0) sys->ems_pages = 0; + + /* Recalculate EMS mappings */ + for (n = 0; n < 4; n++) + ems_out(n << 14, sys->ems_reg[n], sys); +} + + +static void +ems_set_640k(t1000_t *sys, uint8_t val) +{ + if (val && mem_size >= 640) { + mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); + sys->is_640k = 1; + } else { + mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); + sys->is_640k = 0; + } +} + + +static void +ems_set_port(t1000_t *sys, uint8_t val) +{ + int n; + +#if 0 + pclog("ems_set_port(%d)", val & 0x0f); +#endif + if (sys->ems_port) { + for (n = 0; n <= 0xc000; n += 0x4000) { + io_removehandler(sys->ems_port+n, 1, + ems_in,NULL,NULL, ems_out,NULL,NULL, sys); + } + sys->ems_port = 0; + } + + val &= 0x0f; + sys->ems_port_index = val; + if (val == 7) { + /* No EMS */ + sys->ems_port = 0; + } else { + sys->ems_port = 0x208 | (val << 4); + for (n = 0; n <= 0xc000; n += 0x4000) { + io_sethandler(sys->ems_port+n, 1, + ems_in,NULL,NULL, ems_out,NULL,NULL, sys); + } + sys->ems_port = 0; + } + +#if 0 + pclog(" -> %04x\n", sys->ems_port); +#endif +} + + +static int +addr_to_page(uint32_t addr) +{ + return((addr - 0xd0000) / 0x4000); +} + + +/* Read RAM in the EMS page frame. */ +static uint8_t +ems_read_ram(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return(0xff); + addr = sys->page_exec[pg] + (addr & 0x3fff); + + return(ram[addr]); +} + + +static uint16_t +ems_read_ramw(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return(0xff); + +#if 0 + pclog("ems_read_ramw addr=%05x ", addr); +#endif + addr = sys->page_exec[pg] + (addr & 0x3FFF); + +#if 0 + pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); +#endif + + return(*(uint16_t *)&ram[addr]); +} + + +static uint32_t +ems_read_raml(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return(0xff); + addr = sys->page_exec[pg] + (addr & 0x3fff); + + return(*(uint32_t *)&ram[addr]); +} + + +/* Write RAM in the EMS page frame. */ +static void +ems_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + + addr = sys->page_exec[pg] + (addr & 0x3fff); + if (ram[addr] != val) nvr_dosave = 1; + + ram[addr] = val; +} + + +static void +ems_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + +#if 0 + pclog("ems_write_ramw addr=%05x ", addr); +#endif + addr = sys->page_exec[pg] + (addr & 0x3fff); + +#if 0 + pclog("-> %06x val=%04x\n", addr, val); +#endif + + if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; + + *(uint16_t *)&ram[addr] = val; +} + + +static void +ems_write_raml(uint32_t addr, uint32_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + int pg = addr_to_page(addr); + + if (pg < 0) return; + + addr = sys->page_exec[pg] + (addr & 0x3fff); + if (*(uint32_t *)&ram[addr] != val) nvr_dosave = 1; + + *(uint32_t *)&ram[addr] = val; +} + + +static uint8_t +read_ctl(uint16_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + uint8_t ret = 0xff; + + switch (addr & 0x0f) { + case 1: + ret = sys->syskeys; + break; + + case 0x0f: /* Detect EMS board */ + switch (sys->sys_ctl[0x0e]) { + case 0x50: + if (mem_size > 512) break; + ret = (0x90 | sys->ems_port_index); + break; + + case 0x51: + /* 0x60 is the page frame address: + (0xd000 - 0xc400) / 0x20 */ + ret = (sys->ems_base | 0x60); + break; + + case 0x52: + ret = (sys->is_640k ? 0x80 : 0); + break; + } + break; + + default: + ret = (sys->sys_ctl[addr & 0x0f]); + } + + return(ret); +} + + +static void +t1200_turbo_set(uint8_t value) +{ + if (value == t1000.turbo) return; + + t1000.turbo = value; + if (! value) + cpu_dynamic_switch(0); + else + cpu_dynamic_switch(cpu); +} + + +static void +write_ctl(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + sys->sys_ctl[addr & 0x0f] = val; + switch (addr & 0x0f) { + case 4: /* Video control */ + if (sys->sys_ctl[3] == 0x5A) { + t1000_video_options_set((val & 0x20) ? 1 : 0); + t1000_display_set((val & 0x40) ? 0 : 1); + if (romset == ROM_T1200) + t1200_turbo_set((val & 0x80) ? 1 : 0); + } + break; + + case 0x0f: /* EMS control */ + switch (sys->sys_ctl[0x0e]) { + case 0x50: + ems_set_port(sys, val); + break; + + case 0x51: + ems_set_hardram(sys, val); + break; + + case 0x52: + ems_set_640k(sys, val); + break; + } + break; + } +} + + +/* Ports 0xC0 to 0xC3 appear to have two purposes: + * + * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS + * > Reading the floppy changeline. I don't know why the Toshiba doesn't + * use the normal port 0x3F7 for this, but it doesn't. + * + */ +static uint8_t +t1000_read_nvram(uint16_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + uint8_t tmp = 0xff; + + switch (addr) { + case 0xc2: /* Read next byte from NVRAM */ + if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) + tmp = sys->config[sys->nvr_addr]; + sys->nvr_addr++; + break; + + case 0xc3: /* Read floppy changeline and NVRAM ready state */ + tmp = fdc_read(0x03f7, t1000.fdc); + + tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ + tmp |= (sys->nvr_active & 0xc0);/* Bits 6,7 are r/w mode */ + tmp |= 0x2e; /* Bits 5,3,2,1 always 1 */ + tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ + break; + } + + return(tmp); +} + + +static void +t1000_write_nvram(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + /* + * On the real T1000, port 0xC1 is only usable as the high byte + * of a 16-bit write to port 0xC0, with 0x5A in the low byte. + */ + switch (addr) { + case 0xc0: + sys->nvr_c0 = val; + break; + + case 0xc1: /* Write next byte to NVRAM */ + if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) { + if (sys->config[sys->nvr_addr] != val) + nvr_dosave = 1; + sys->config[sys->nvr_addr] = val; + } + sys->nvr_addr++; + break; + + case 0xc2: + break; + + case 0xc3: + /* + * At start of NVRAM read / write, 0x80 is written to + * port 0xC3. This seems to reset the NVRAM address + * counter. A single byte is then written (0xff for + * write, 0x00 for read) which appears to be ignored. + * Simulate that by starting the address counter off + * at -1. + */ + sys->nvr_active = val; + if (val == 0x80) sys->nvr_addr = -1; + break; + } +} + + +/* Port 0xC8 controls the ROM drive */ +static uint8_t +t1000_read_rom_ctl(uint16_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + return(sys->rom_ctl); +} + + +static void +t1000_write_rom_ctl(uint16_t addr, uint8_t val, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + sys->rom_ctl = val; + if (sys->romdrive && (val & 0x80)) { + /* Enable */ + sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMSIZE; + mem_mapping_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); + mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); + mem_mapping_enable(&sys->rom_mapping); + } else { + mem_mapping_disable(&sys->rom_mapping); + } +} + + +/* Read the ROM drive */ +static uint8_t +t1000_read_rom(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + if (! sys->romdrive) return(0xff); + + return(sys->romdrive[sys->rom_offset + (addr & 0xffff)]); +} + + +static uint16_t +t1000_read_romw(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + if (! sys->romdrive) return(0xffff); + + return(*(uint16_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); +} + + +static uint32_t +t1000_read_roml(uint32_t addr, void *priv) +{ + t1000_t *sys = (t1000_t *)priv; + + if (! sys->romdrive) return(0xffffffff); + + return(*(uint32_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); +} + + +device_t * +t1000_get_device(void) +{ + return(&t1000_video_device); +} + + +void +machine_xt_t1000_init(machine_t *model) +{ + FILE *f; + int pg; + + memset(&t1000, 0x00, sizeof(t1000)); + t1000.turbo = 0xff; + t1000.ems_port_index = 7; /* EMS disabled */ + + /* Load the T1000 CGA Font ROM. */ + loadfont(L"roms/machines/toshiba/t1000/t1000font.rom", 2); + + /* + * The ROM drive is optional. + * + * If the file is missing, continue to boot; the BIOS will + * complain 'No ROM drive' but boot normally from floppy. + */ + f = rom_fopen(L"roms/machines/toshiba/t1000/t1000dos.rom"); + if (f != NULL) { + t1000.romdrive = malloc(T1000_ROMSIZE); + if (t1000.romdrive) { + memset(t1000.romdrive, 0xff, T1000_ROMSIZE); + fread(t1000.romdrive, T1000_ROMSIZE, 1, f); + } + fclose(f); + } + mem_mapping_add(&t1000.rom_mapping, 0xa0000, 0x10000, + t1000_read_rom,t1000_read_romw,t1000_read_roml, + NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); + mem_mapping_disable(&t1000.rom_mapping); + + /* Map the EMS page frame */ + for (pg = 0; pg < 4; pg++) { + mem_mapping_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram,ems_read_ramw,ems_read_raml, + ems_write_ram,ems_write_ramw,ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); + + /* Start them all off disabled */ + mem_mapping_disable(&t1000.mapping[pg]); + } + + /* Non-volatile RAM for CONFIG.SYS */ + io_sethandler(0xc0, 4, + t1000_read_nvram,NULL,NULL, + t1000_write_nvram,NULL,NULL, &t1000); + + /* ROM drive */ + io_sethandler(0xc8, 1, + t1000_read_rom_ctl,NULL,NULL, + t1000_write_rom_ctl,NULL,NULL, &t1000); + + /* System control functions, and add-on memory board */ + io_sethandler(0xe0, 16, + read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); + + machine_common_init(model); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + device_add(&keyboard_xt_device); + t1000.fdc = device_add(&fdc_xt_device); + nmi_init(); + + tc8521_init(&t1000.nvr, model->nvrsz); + + device_add(&t1000_video_device); +} + + +device_t * +t1200_get_device(void) +{ + return(&t1200_video_device); +} + + +void +machine_xt_t1200_init(machine_t *model) +{ + int pg; + + memset(&t1000, 0x00, sizeof(t1000)); + t1000.ems_port_index = 7; /* EMS disabled */ + + /* Load the T1200 CGA Font ROM. */ + loadfont(L"roms/machines/toshiba/t1200/t1000font.bin", 2); + + /* Map the EMS page frame */ + for (pg = 0; pg < 4; pg++) { + mem_mapping_add(&t1000.mapping[pg], + 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram,ems_read_ramw,ems_read_raml, + ems_write_ram,ems_write_ramw,ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); + + /* Start them all off disabled */ + mem_mapping_disable(&t1000.mapping[pg]); + } + + /* System control functions, and add-on memory board */ + io_sethandler(0xe0, 16, + read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); + + machine_common_init(model); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + device_add(&keyboard_xt_device); + t1000.fdc = device_add(&fdc_xt_device); + nmi_init(); + + tc8521_init(&t1000.nvr, model->nvrsz); + + device_add(&t1200_video_device); +} + + +void +t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) +{ + t1000.syskeys &= ~andmask; + t1000.syskeys |= ormask; + t1000.syskeys ^= xormask; +} + + +#if 0 +void +t1000_configsys_load(void) +{ + FILE *f; + + memset(config_sys, 0x1a, sizeof(config_sys)); + f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"rb"); + if (f != NULL) { + fread(config_sys, sizeof(config_sys), 1, f); + fclose(f); + } +} + + +void +t1000_configsys_save(void) +{ + FILE *f; + + f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"wb"); + if (f != NULL) { + fwrite(config_sys, sizeof(config_sys), 1, f); + fclose(f); + } +} + + +/* All RAM beyond 512k is non-volatile */ +void +t1000_emsboard_load(void) +{ + FILE *f; + + if (mem_size > 512) { + f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"rb"); + if (f != NULL) { + fread(&ram[512 * 1024], 1024, (mem_size - 512), f); + fclose(f); + } + } +} + + +void +t1000_emsboard_save(void) +{ + FILE *f; + + if (mem_size > 512) { + f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"wb"); + if (f != NULL) { + fwrite(&ram[512 * 1024], 1024, (mem_size - 512), f); + fclose(f); + } + } +} +#endif diff --git a/src/machine/m_xt_t1000.h b/src/machine/m_xt_t1000.h index 57ca46d..545861e 100644 --- a/src/machine/m_xt_t1000.h +++ b/src/machine/m_xt_t1000.h @@ -8,7 +8,7 @@ * * Definitions for the Toshiba T1000/T1200 machines. * - * Version: @(#)m_xt_t1000.h 1.0.1 2018/03/05 + * Version: @(#)m_xt_t1000.h 1.0.2 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,20 +40,20 @@ # define MACHINE_T1000_H -extern device_t t1000_device; -extern device_t t1200_device; +extern device_t t1000_video_device; +extern device_t t1200_video_device; -extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); - -extern void t1000_configsys_loadnvr(void); -extern void t1000_emsboard_loadnvr(void); - -extern void t1000_configsys_savenvr(void); -extern void t1000_emsboard_savenvr(void); - extern void t1000_video_options_set(uint8_t options); extern void t1000_display_set(uint8_t internal); +extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); + +extern void t1000_configsys_load(void); +extern void t1000_configsys_save(void); + +extern void t1000_emsboard_load(void); +extern void t1000_emsboard_save(void); + #endif /*MACHINE_T1000_H*/ diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index fe832bf..00b94c3 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -9,7 +9,7 @@ * Implementation of the Toshiba T1000 plasma display, which * has a fixed resolution of 640x200 pixels. * - * Version: @(#)m_xt_t1000_vid.c 1.0.3 2018/03/06 + * Version: @(#)m_xt_t1000_vid.c 1.0.4 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,9 +52,11 @@ #include "../video/vid_cga.h" #include "m_xt_t1000.h" + #define T1000_XSIZE 640 #define T1000_YSIZE 200 + /* Mapping of attributes to colours */ static uint32_t blue, grey; static uint8_t boldcols[256]; /* Which attributes use the bold font */ @@ -62,6 +64,7 @@ static uint32_t blinkcols[256][2]; static uint32_t normcols[256][2]; static uint8_t language; + /* Video options set by the motherboard; they will be picked up by the card * on the next poll. * @@ -726,33 +729,25 @@ static device_config_t t1000_config[] = }; -device_t t1000_device = -{ - "Toshiba T1000", - 0, - 0, - t1000_init, - t1000_close, - NULL, - NULL, - t1000_speed_changed, - NULL, - NULL, - t1000_config +device_t t1000_video_device = { + "Toshiba T1000 Video", + 0, 0, + t1000_init, t1000_close, NULL, + NULL, + t1000_speed_changed, + NULL, + NULL, + t1000_config }; -device_t t1200_device = -{ - "Toshiba T1200", - 0, - 0, - t1000_init, - t1000_close, - NULL, - NULL, - t1000_speed_changed, - NULL, - NULL, - t1000_config +device_t t1200_video_device = { + "Toshiba T1200 Video", + 0, 0, + t1000_init, t1000_close, NULL, + NULL, + t1000_speed_changed, + NULL, + NULL, + t1000_config }; diff --git a/src/machine/machine.c b/src/machine/machine.c index ec9d4c3..79afd27 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -58,6 +58,7 @@ int romset; int machine; int AT, PCI; +int romspresent[ROM_MAX]; void diff --git a/src/machine/machine.h b/src/machine/machine.h index 6bfcf68..f51c7e0 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.6 2018/03/04 + * Version: @(#)machine.h 1.0.8 2018/03/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,6 +40,142 @@ # define EMU_MACHINE_H +/* FIXME: replace these with machine flags! */ +#define PCJR (romset==ROM_IBMPCJR) +#if defined(DEV_BRANCH) && defined(USE_GREENB) +#define AMIBIOS (romset==ROM_AMI386SX || \ + romset==ROM_AMI486 || \ + romset==ROM_WIN486 || \ + romset==ROM_4GPV31) +#else +#define AMIBIOS (romset==ROM_AMI386SX || \ + romset==ROM_AMI486 || \ + romset==ROM_WIN486) +#endif + + +/* FIXME: try to get rid of these... */ +enum { + ROM_IBMPC = 0, /* 301 keyboard error, 131 cassette (!!!) error */ + ROM_AMIXT, /* XT Clone with AMI BIOS */ + ROM_DTKXT, + ROM_IBMXT, /* 301 keyboard error */ + ROM_GENXT, /* 'Generic XT BIOS' */ + ROM_JUKOPC, + ROM_PORTABLE, + ROM_PXXT, +#if defined(DEV_BRANCH) && defined(USE_LASERXT) + ROM_LTXT, + ROM_LXT3, +#endif + ROM_T1000, + ROM_T1200, + ROM_XI8088, + ROM_IBMPCJR, + ROM_TANDY, + ROM_TANDY1000HX, + ROM_EUROPC, + ROM_PC1512, + ROM_PC1640, + ROM_PC200, + ROM_PC2086, + ROM_PC3086, + ROM_OLIM24, + ROM_TANDY1000SL2, + ROM_T3100E, + + ROM_AMI286, + ROM_AWARD286, + ROM_CMDPC30, + ROM_PORTABLEII, +#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) + ROM_PORTABLEIII, +#endif + ROM_GW286CT, + ROM_SUPER286TR, /* Hyundai Super-286TR/SCAT/Award */ + ROM_IBMAT, + ROM_IBMPS1_2011, + ROM_IBMPS2_M30_286, + ROM_IBMXT286, + ROM_SPC4200P, /* Samsung SPC-4200P/SCAT/Phoenix */ + ROM_SPC4216P, /* Samsung SPC-4216P/SCAT */ + + ROM_IBMPS2_M50, + + ROM_AMI386SX, + ROM_KMXC02, + ROM_MEGAPC, + ROM_AWARD386SX_OPTI495, +#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) + ROM_DESKPRO_386, +#endif + ROM_DTK386, + ROM_IBMPS1_2121, + ROM_IBMPS1_2121_ISA,/* IBM PS/1 Model 2121 with ISA expansion bus */ +#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) + ROM_PORTABLEIII386, +#endif + + ROM_IBMPS2_M55SX, + + ROM_AMI386DX_OPTI495, + ROM_MEGAPCDX, /* 386DX mdl - Note: documentation (in German) clearly says such a model exists */ + ROM_AWARD386DX_OPTI495, + ROM_MR386DX_OPTI495, + + ROM_IBMPS2_M80, + + ROM_AMI486, + ROM_WIN486, +#ifdef UNIMPLEMENTED_MACHINES + ROM_VLI486SV2G, /* ASUS VL/I-486SV2G/SiS 471/Award/SiS 85C471 */ /* 51 */ +#endif + ROM_AWARD486_OPTI495, + ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ +#if defined(DEV_BRANCH) && defined(USE_GREENB) + ROM_4GPV31, /* Green-B 4GPV3.1 ISA/VLB 486/Pentium, AMI */ +#endif + ROM_IBMPS1_2133, + + ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ + + ROM_REVENGE, /* Intel Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ + + ROM_PLATO, /* Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ + + ROM_P54TP4XE, /* ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ + ROM_ENDEAVOR, /* Intel Advanced_EV/430FX/AMI/NS PC87306 */ + ROM_ZAPPA, /* Intel Advanced_ZP/430FX/AMI/NS PC87306 */ +#ifdef UNIMPLEMENTED_MACHINES + ROM_POWERMATE_V, /* NEC PowerMate V/430FX/Phoenix/SMC FDC37C66 5*/ +#endif + ROM_MB500N, /* PC Partner MB500N/430FX/Award/SMC FDC37C665 */ + ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ + + ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ +#if defined(DEV_BRANCH) && defined(USE_MRTHOR) + ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ +#endif + + ROM_ACERM3A, /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ + ROM_ACERV35N, /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ + ROM_AP53, /* AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ + ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ + ROM_P55T2S, /* ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ + + ROM_P55TVP4, /* ASUS P/I-P55TVP4/430HX/Award/Winbond W8387F*/ + ROM_430VX, /* Award 430VX PCI/430VX/Award/UMC UM8669F*/ + ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ + +#if defined(DEV_BRANCH) && defined(USE_I686) + ROM_440FX, /* Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ + ROM_S1668, /* Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ +#endif + + ROM_MAX +}; + + /* Machine feature flags. */ #define MACHINE_PC 0x000000 /* PC architecture */ #define MACHINE_AT 0x000001 /* PC/AT architecture */ @@ -76,7 +212,7 @@ typedef struct _machine_ { int flags; int min_ram, max_ram; int ram_granularity; - int nvrmask; + int nvrsz; void (*init)(struct _machine_ *); #ifdef EMU_DEVICE_H device_t *(*get_device)(void); @@ -92,6 +228,7 @@ extern machine_t machines[]; extern int machine; extern int romset; extern int AT, PCI; +extern int romspresent[ROM_MAX]; /* Core functions. */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a0fc2f3..38e4c8e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,7 +11,7 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.6 2018/03/08 + * Version: @(#)machine_table.c 1.0.7 2018/03/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -62,7 +62,7 @@ machine_t machines[] = { { "[8088] Generic XT clone", ROM_GENXT, "genxt", L"generic/genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, { "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", L"juko/jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", L"generic/phoenix/pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", L"schneider/europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 0, machine_europc_init, NULL, NULL }, + { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", L"schneider/europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 16, machine_europc_init, NULL, NULL }, { "[8088] Tandy 1000", ROM_TANDY, "tandy", L"tandy/tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device, NULL }, { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", L"tandy/tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device, NULL }, { "[8088] Toshiba 1000", ROM_T1000, "t1000", L"toshiba/t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 0, machine_xt_t1000_init, t1000_get_device, NULL }, @@ -70,12 +70,12 @@ machine_t machines[] = { { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", L"vtech/ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, #endif - { "[8088] Xi8088", ROM_XI8088, "xi8088", L"generic/xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device, nvr_at_close }, - { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", L"amstrad/pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", L"amstrad/pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", L"amstrad/pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", L"amstrad/pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", L"amstrad/pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL, nvr_at_close }, + { "[8088] Xi8088", ROM_XI8088, "xi8088", L"generic/xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_PS2, 64, 1024, 128, 128, machine_xt_xi8088_init, xi8088_get_device, nvr_at_close }, + { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", L"amstrad/pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_init, NULL, nvr_at_close }, + { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", L"amstrad/pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, nvr_at_close }, + { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", L"amstrad/pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, nvr_at_close }, + { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", L"amstrad/pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, nvr_at_close }, + { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", L"amstrad/pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_init, NULL, nvr_at_close }, { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", L"olivetti/olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL, NULL }, { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", L"tandy/tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL, NULL }, { "[8086] Toshiba 1200", ROM_T1200, "t1200", L"toshiba/t1200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 0, machine_xt_t1200_init, t1200_get_device, NULL }, @@ -83,110 +83,110 @@ machine_t machines[] = { { "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", L"vtech/lxt3", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, #endif - { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", L"generic/ami/ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_ami_init, NULL, nvr_at_close }, - { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", L"generic/award/award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", L"commodore/cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL, nvr_at_close }, - { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "portableii", L"compaq/portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_compaq_init, NULL, nvr_at_close }, + { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", L"generic/ami/ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_neat_ami_init, NULL, nvr_at_close }, + { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", L"generic/award/award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", L"commodore/cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_cmdpc_init, NULL, nvr_at_close }, + { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "portableii", L"compaq/portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_compaq_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "portableiii", L"compaq/portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 127, machine_at_compaq_init, NULL, nvr_at_close }, + { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "portableiii", L"compaq/portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 128, machine_at_compaq_init, NULL, nvr_at_close }, #endif - { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", L"generic/gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", L"hyundai/super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] IBM AT", ROM_IBMAT, "ibmat", L"ibm/ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, - { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", L"ibm/ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 512,16384, 512, 127, machine_ps1_m2011_init, NULL, nvr_at_close }, - { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", L"ibm/ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL, nvr_at_close }, - { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", L"ibm/ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, - { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", L"samsung/spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", L"samsung/spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Toshiba 3100e", ROM_T3100E, "t3100e", L"toshiba/t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL, nvr_at_close }, + { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", L"generic/gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", L"hyundai/super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] IBM AT", ROM_IBMAT, "ibmat", L"ibm/ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, machine_at_ibm_init, NULL, nvr_at_close }, + { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", L"ibm/ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 512,16384, 512, 128, machine_ps1_m2011_init, NULL, nvr_at_close }, + { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", L"ibm/ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 128, machine_ps2_m30_286_init, NULL, nvr_at_close }, + { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", L"ibm/ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, machine_at_ibm_init, NULL, nvr_at_close }, + { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", L"samsung/spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", L"samsung/spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] Toshiba 3100e", ROM_T3100E, "t3100e", L"toshiba/t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 64, machine_at_t3100e_init, NULL, nvr_at_close }, - { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", L"ibm/ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 10, 1, 63, machine_ps2_model_50_init, NULL, nvr_at_close }, + { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", L"ibm/ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 10, 1, 64, machine_ps2_model_50_init, NULL, nvr_at_close }, - { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", L"generic/ami/ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL, nvr_at_close }, - { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", L"amstrad/megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL, nvr_at_close }, - { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", L"generic/award/award495", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", L"dtk/dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_neat_init, NULL, nvr_at_close }, - { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", L"ibm/ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, - { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", L"ibm/ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, + { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", L"generic/ami/ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 128, machine_at_headland_init, NULL, nvr_at_close }, + { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", L"amstrad/megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 128, machine_at_wd76c10_init, NULL, nvr_at_close }, + { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", L"generic/award/award495", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, nvr_at_close }, + { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", L"dtk/dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 128, machine_at_neat_init, NULL, nvr_at_close }, + { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", L"ibm/ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 128, machine_ps1_m2121_init, NULL, nvr_at_close }, + { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", L"ibm/ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 128, machine_ps1_m2121_init, NULL, nvr_at_close }, - { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", L"ibm/ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL, nvr_at_close }, - { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", L"generic/ami/kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_scatsx_init, NULL, nvr_at_close }, + { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", L"ibm/ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 68, machine_ps2_model_55sx_init, NULL, nvr_at_close }, + { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", L"generic/ami/kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 128, machine_at_scatsx_init, NULL, nvr_at_close }, - { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", L"generic/ami/ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL, nvr_at_close }, - { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", L"amstrad/megapc", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 127, machine_at_wd76c10_init, NULL, nvr_at_close }, - { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", L"generic/award/award495", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", L"generic/microid/mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL, nvr_at_close }, + { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", L"generic/ami/ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, nvr_at_close }, + { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", L"amstrad/megapc", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 128, machine_at_wd76c10_init, NULL, nvr_at_close }, + { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", L"generic/award/award495", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, nvr_at_close }, + { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", L"generic/microid/mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portableiii386", L"compaq/deskpro386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_compaq_init, NULL, nvr_at_close }, + { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portableiii386", L"compaq/deskpro386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 128, machine_at_compaq_init, NULL, nvr_at_close }, #endif - { "[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", L"ibm/ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 12, 1, 63, machine_ps2_model_80_init, NULL, nvr_at_close }, + { "[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", L"ibm/ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 12, 1, 64, machine_ps2_model_80_init, NULL, nvr_at_close }, - { "[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", L"generic/ami/ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL, nvr_at_close }, - { "[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", L"generic/ami/win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL, nvr_at_close }, - { "[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", L"generic/award/award495", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", L"dtk/dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_dtk486_init, NULL, nvr_at_close }, - { "[486 ISA] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibmps1_2133", L"ibm/ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 1, 64, 1, 127, machine_ps1_m2133_init, NULL, nvr_at_close }, + { "[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", L"generic/ami/ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, nvr_at_close }, + { "[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", L"generic/ami/win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, nvr_at_close }, + { "[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", L"generic/award/award495", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, nvr_at_close }, + { "[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", L"dtk/dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 128, machine_at_dtk486_init, NULL, nvr_at_close }, + { "[486 ISA] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibmps1_2133", L"ibm/ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 1, 64, 1, 128, machine_ps1_m2133_init, NULL, nvr_at_close }, - { "[486 PCI] Rise Computer R418", ROM_R418, "r418", L"rise/r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL, nvr_at_close }, + { "[486 PCI] Rise Computer R418", ROM_R418, "r418", L"rise/r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 128, machine_at_r418_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_GREENB) - { "[486 VLB] Green-B 4GP V3.1", ROM_4GPV31, "4gpv31", L"addtech/green-b", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT, 1, 128, 1, 127, machine_at_4gpv31_init, NULL, nvr_at_close }, + { "[486 VLB] Green-B 4GP V3.1", ROM_4GPV31, "4gpv31", L"addtech/green-b", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT, 1, 128, 1, 128, machine_at_4gpv31_init, NULL, nvr_at_close }, #endif - { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", L"intel/revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL, nvr_at_close }, + { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", L"intel/revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_batman_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_AMD_K) - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL, nvr_at_close }, + { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, nvr_at_close }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL, nvr_at_close }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL, nvr_at_close }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL, nvr_at_close }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, nvr_at_close }, + { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, + { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, nvr_at_close }, + { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, nvr_at_close }, + { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, nvr_at_close }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_MRTHOR) - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, nvr_at_close }, #endif - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", L"acer/acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL, nvr_at_close }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", L"acer/acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL, nvr_at_close }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL, nvr_at_close }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL, nvr_at_close }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", L"acer/acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", L"acer/acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, nvr_at_close }, + { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, nvr_at_close }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, nvr_at_close }, + { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, nvr_at_close }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL, nvr_at_close }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, nvr_at_close }, + { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, nvr_at_close }, + { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, nvr_at_close }, #else - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL, nvr_at_close }, + { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, nvr_at_close }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL, nvr_at_close }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL, nvr_at_close }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL, nvr_at_close }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, nvr_at_close }, + { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, + { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, nvr_at_close }, + { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, nvr_at_close }, + { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, nvr_at_close }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, nvr_at_close }, #if defined(DEV_BRANCH) && defined(USE_MRTHOR) - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, nvr_at_close }, #endif - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", L"acer/acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL, nvr_at_close }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", L"acer/acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL, nvr_at_close }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL, nvr_at_close }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL, nvr_at_close }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", L"acer/acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", L"acer/acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, nvr_at_close }, + { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, nvr_at_close }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, nvr_at_close }, + { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, nvr_at_close }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL, nvr_at_close }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, nvr_at_close }, + { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, nvr_at_close }, + { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, nvr_at_close }, #endif #if defined(DEV_BRANCH) && defined(USE_I686) - { "[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", L"tyan/440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL, nvr_at_close }, - { "[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", L"tyan/tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL, nvr_at_close }, + { "[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", L"tyan/440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_i440fx_init, NULL, nvr_at_close }, + { "[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", L"tyan/tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_s1668_init, NULL, nvr_at_close }, #endif { "", -1, "", NULL, {{"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; @@ -259,13 +259,6 @@ machine_get_internal_name_ex(int m) } -int -machine_get_nvrmask(int m) -{ - return(machines[m].nvrmask); -} - - int machine_get_machine_from_internal_name(char *s) { diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index c640b11..6b727a9 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -8,7 +8,7 @@ * * Handle WinPcap library processing. * - * Version: @(#)net_pcap.c 1.0.1 2018/02/14 + * Version: @(#)net_pcap.c 1.0.2 2018/03/10 * * Author: Fred N. van Kempen, * @@ -54,7 +54,6 @@ #include "../config.h" #include "../device.h" #include "../plat.h" -#include "../plat_dynld.h" #include "network.h" diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c index f2b83f3..83d318b 100644 --- a/src/network/pcap_if.c +++ b/src/network/pcap_if.c @@ -10,7 +10,7 @@ * * Based on the "libpcap" examples. * - * Version: @(#)pcap_if.c 1.0.9 2018/02/24 + * Version: @(#)pcap_if.c 1.0.10 2018/03/10 * * Author: Fred N. van Kempen, * @@ -56,7 +56,6 @@ #include #include "../emu.h" #include "../plat.h" -#include "../plat_dynld.h" static void *pcap_handle; /* handle to WinPcap DLL */ diff --git a/src/nvr.c b/src/nvr.c index 61ac59b..d092cb6 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -6,212 +6,45 @@ * * This file is part of the VARCem Project. * - * Implement a more-or-less defacto-standard RTC/NVRAM. + * Implement a generic NVRAM/CMOS/RTC device. * - * When IBM released the PC/AT machine, it came standard with a - * battery-backed RTC chip to keep the time of day, something - * that was optional on standard PC's with a myriad variants - * being put on the market, often on cheap multi-I/O cards. + * NOTE: I should re-do 'intclk' using a TM struct. * - * The PC/AT had an on-board DS12885-series chip ("the black - * block") which was an RTC/clock chip with onboard oscillator - * and a backup battery (hence the big size.) The chip also had - * a smal amount of RAM bytes available to the user, which was - * used by IBM's ROM BIOS to store machine configuration data. + * Version: @(#)nvr.c 1.0.2 2018/03/11 * - * Since then, pretty much any PC has an implementation of that - * device, which became known as the "nvr" or "cmos". - * - * NOTES Info extracted from the data sheets: - * - * * 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. - * - * * Rate Selector (RS3: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. - * - * * Oscillator (DV2: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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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 b any internal device functions, - * but is cleared to 0 on !RESET. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * * 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. - * - * This file implements an internal RTC clock, plus a generic - * version of the RTC/NVRAM chip, including the later update - * (DS12887A) which implemented a "century" register to be - * compatible with Y2K. - * - * Version: @(#)nvr.c 1.0.1 2018/02/14 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Mahod, + * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include @@ -220,33 +53,37 @@ #include #include #include "emu.h" +#include "machine/machine.h" #include "pic.h" #include "pit.h" #include "timer.h" -#include "machine/machine.h" #include "plat.h" #include "nvr.h" -int enable_sync; /* configuration variable: enable time sync */ -int nvr_dosave; /* NVR is dirty, needs saved */ - - -static nvr_t *saved_nvr = NULL; -static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; -static struct { +/* 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; /* the internal clock */ +} 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 nvr_t *saved_nvr = NULL; /* Determine whether or not the year is leap. */ -static int8_t -is_leap(int8_t year) +int +nvr_is_leap(int year) { if (year % 400 == 0) return(1); if (year % 100 == 0) return(0); @@ -257,13 +94,13 @@ is_leap(int8_t year) /* Determine the days in the current month. */ -static int8_t -get_days(int8_t month, int8_t year) +int +nvr_get_days(int month, int year) { if (month != 2) return(days_in_month[month - 1]); - return(is_leap(year) ? 29 : 28); + return(nvr_is_leap(year) ? 29 : 28); } @@ -284,7 +121,7 @@ rtc_tick(void) intclk.hour = 0; intclk.mday++; } - if (intclk.mday == (get_days(intclk.mon, intclk.year) + 1)) { + if (intclk.mday == (nvr_get_days(intclk.mon, intclk.year) + 1)) { intclk.mday = 1; intclk.mon++; } @@ -295,107 +132,6 @@ rtc_tick(void) } -/* Store the broken-down local time into the NVR. */ -static void -rtc_getnvr(uint8_t *nvr, struct tm *tm) -{ - if (nvr[RTC_REGB] & REGB_DM) { - /* NVR is in Binary data mode. */ - nvr[RTC_SECONDS] = tm->tm_sec; - nvr[RTC_MINUTES] = tm->tm_min; - nvr[RTC_DOW] = tm->tm_wday+1; - nvr[RTC_DOM] = tm->tm_mday; - nvr[RTC_MONTH] = tm->tm_mon+1; - nvr[RTC_YEAR] = tm->tm_year%100; - - if (nvr[RTC_REGB] & REGB_2412) { - /* NVR is in 24h mode. */ - nvr[RTC_HOURS] = tm->tm_hour; - } else { - /* NVR is in 12h mode. */ - nvr[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; - if (tm->tm_hour > 11) - nvr[RTC_HOURS] |= RTC_AMPM; - } - } else { - /* NVR is in BCD data mode. */ - nvr[RTC_SECONDS] = RTC_BCD(tm->tm_sec); - nvr[RTC_MINUTES] = RTC_BCD(tm->tm_min); - nvr[RTC_DOW] = RTC_BCD(tm->tm_wday+1); - nvr[RTC_DOM] = RTC_BCD(tm->tm_mday); - nvr[RTC_MONTH] = RTC_BCD(tm->tm_mon+1); - nvr[RTC_YEAR] = RTC_BCD(tm->tm_year%100); - - if (nvr[RTC_REGB] & REGB_2412) { - /* NVR is in 24h mode. */ - nvr[RTC_HOURS] = RTC_BCD(tm->tm_hour); - } else { - /* NVR is in 12h mode. */ - nvr[RTC_HOURS] = (tm->tm_hour % 12) - ? RTC_BCD(tm->tm_hour % 12) - : RTC_BCD(12); - if (tm->tm_hour > 11) - nvr[RTC_HOURS] |= RTC_AMPM; - } - } -} - - -/* Load local time from the NVR. */ -static void -rtc_setnvr(uint8_t *nvr) -{ - int8_t temp; - - if (nvr[RTC_REGB] & REGB_DM) { - intclk.sec = nvr[RTC_SECONDS]; - intclk.min = nvr[RTC_MINUTES]; - temp = nvr[RTC_HOURS]; - intclk.mday = nvr[RTC_DOM]; - intclk.mon = nvr[RTC_MONTH]; - intclk.year = nvr[RTC_YEAR]; - intclk.year += 1900; - } else { - intclk.sec = RTC_DCB(nvr[RTC_SECONDS]); - intclk.min = RTC_DCB(nvr[RTC_MINUTES]); - temp = RTC_DCB(nvr[RTC_HOURS]); - intclk.mday = RTC_DCB(nvr[RTC_DOM]); - intclk.mon = RTC_DCB(nvr[RTC_MONTH]); - intclk.year = RTC_DCB(nvr[RTC_YEAR]); - intclk.year += (RTC_DCB(nvr[RTC_CENTURY]) * 100); - } - - /* Adjust for 12/24 hour mode. */ - if (nvr[RTC_REGB] & REGB_2412) - intclk.hour = temp; - else - intclk.hour = ((temp & ~RTC_AMPM) % 12) + ((temp & RTC_AMPM) ? 12 : 0); -} - - -static void -rtc_sync(uint8_t *nvr) -{ - struct tm *tm; - time_t now; - - /* Get the current time of day, and convert to local time. */ - (void)time(&now); - tm = localtime(&now); - - /* Set the internal clock. */ - 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; - - /* Set the NVR registers. */ - rtc_getnvr(nvr, tm); -} - - /* This is the RTC one-second timer. */ static void onesec_timer(void *priv) @@ -403,20 +139,13 @@ onesec_timer(void *priv) nvr_t *nvr = (nvr_t *)priv; if (++nvr->onesec_cnt >= 100) { - if (! (nvr->regs[RTC_REGB] & REGB_SET)) { - nvr->upd_stat = REGA_UIP; + /* Update the internal clock. */ + rtc_tick(); - /* Update the system RTC. */ - rtc_tick(); + /* Update the RTC device if needed. */ + if (nvr->tick != NULL) + (*nvr->tick)(nvr); - if (nvr->hook != NULL) - (*nvr->hook)(nvr); - - /* Re-calculate the timer. */ - nvr_recalc(); - - nvr->upd_ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); - } nvr->onesec_cnt = 0; } @@ -424,241 +153,47 @@ onesec_timer(void *priv) } -/* Check if the current time matches a set alarm time. */ -static int8_t -check_alarm(nvr_t *nvr, int8_t addr) -{ -#define ALARM_DONTCARE 0xc0 - return((nvr->regs[addr+1] == nvr->regs[addr]) || - ((nvr->regs[addr+1] & ALARM_DONTCARE) == ALARM_DONTCARE)); -} - - -/* This is the general update timer. */ -static void -update_timer(void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - struct tm tm; - int8_t dom, mon, sum, wd; - int16_t cent, yr; - - if (! (nvr->regs[RTC_REGB] & REGB_SET)) { - /* Get the current time from the internal clock. */ - 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; - rtc_getnvr(nvr->regs, &tm); - - /* Clear update status. */ - nvr->upd_stat = 0; - - if (check_alarm(nvr, RTC_SECONDS) && - check_alarm(nvr, RTC_MINUTES) && - check_alarm(nvr, RTC_HOURS)) { - nvr->regs[RTC_REGC] |= REGC_AF; - if (nvr->regs[RTC_REGB] & REGB_AIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1<irq); - } - } - - /* - * The flag and interrupt should be issued - * on update ended, not started. - */ - nvr->regs[RTC_REGC] |= REGC_UF; - if (nvr->regs[RTC_REGB] & REGB_UIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1<irq); - } - } - - nvr->upd_ecount = 0; -} - - -static void -ticker_timer(void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - int64_t c; - - if (! (nvr->regs[RTC_REGA] & REGA_RS)) { - nvr->rtctime = 0x7fffffff; - return; - } - - /* Update our ticker interval. */ - c = 1 << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); - nvr->rtctime += (int64_t)(RTCCONST*c*(1<regs[RTC_REGC] |= REGC_PF; - if (nvr->regs[RTC_REGB] & REGB_PIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; - - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1<irq); - } -} - - -/* Set one of the chip's registers. */ -static void -nvr_write(nvr_t *nvr, uint16_t reg, uint8_t val) -{ - uint8_t old; - int64_t c; - - old = nvr->regs[reg]; - switch(reg) { - case RTC_REGA: - nvr->regs[reg] = val; - if (val & REGA_RS) { - c = 1 << ((val & REGA_RS) - 1); - nvr->rtctime += (int64_t)(RTCCONST*c*(1<rtctime = 0x7fffffff; - } - break; - - case RTC_REGB: - nvr->regs[reg] = val; - if (((old^val) & REGB_SET) && (val®B_SET)) { - /* This has to be done according to the datasheet. */ - nvr->regs[RTC_REGA] &= ~REGA_UIP; - - /* This also has to happen per the specification. */ - nvr->regs[RTC_REGB] &= ~REGB_UIE; - } - break; - - case RTC_REGC: /* R/O */ - case RTC_REGD: /* R/O */ - break; - - default: /* non-RTC registers are just NVRAM */ - if (nvr->regs[reg] != val) { - nvr->regs[reg] = val; - - nvr_dosave = 1; - } - break; - } - - if ((reg < RTC_REGA) || (reg == RTC_CENTURY)) { - if ((reg != 1) && (reg != 3) && (reg != 5)) { - if ((old != val) && !enable_sync) { - /* Update internal clock. */ - rtc_setnvr(nvr->regs); - - nvr_dosave = 1; - } - } - } -} - - -/* Get one of the chip's registers. */ -static uint8_t -nvr_read(nvr_t *nvr, uint16_t reg) -{ - uint8_t ret = 0xff; - - switch(reg) { - case RTC_REGA: - ret = (nvr->regs[RTC_REGA] & 0x7f) | nvr->upd_stat; - break; - - case RTC_REGC: - picintc(1<irq); - ret = nvr->regs[RTC_REGC]; - nvr->regs[RTC_REGC] = 0x00; - break; - - case RTC_REGD: - nvr->regs[RTC_REGD] |= REGD_VRT; - ret = nvr->regs[RTC_REGD]; - break; - - default: - ret = nvr->regs[reg]; - break; - } - - return(ret); -} - - -/* Initialize the virtual RTC/NVRAM chip. */ +/* Initialize the generic NVRAM/RTC device. */ void nvr_init(nvr_t *nvr) { - char temp[32]; - int64_t c; + char temp[64]; + struct tm *tm; + time_t now; + int c; - /* Clear some of it. */ - nvr->upd_stat = 0; - nvr->upd_ecount = 0; - nvr->onesec_time = 0; - nvr->onesec_cnt = 0; - memset(&intclk, 0x00, sizeof(intclk)); - - /* Pre-initialize the NVR file's name here. */ - sprintf(temp, "%s.nvr", machine_get_internal_name_ex(machine)); + /* Set up the NVR file's name. */ + sprintf(temp, "%s.nvr", machine_get_internal_name()); c = strlen(temp)+1; - nvr->fname = (wchar_t *)malloc(c*sizeof(wchar_t)); - mbstowcs(nvr->fname, temp, c); + nvr->fn = (wchar_t *)malloc(c*sizeof(wchar_t)); + mbstowcs(nvr->fn, temp, c); - /* Set up our local handlers. */ - nvr->get = nvr_read; - nvr->set = nvr_write; + /* Initialize the internal clock as needed. */ + memset(&intclk, 0x00, sizeof(intclk)); + if (enable_sync) { + /* Get the current time of day, and convert to local time. */ + (void)time(&now); + tm = localtime(&now); - /* Set up our timers. */ - timer_add(ticker_timer, &nvr->rtctime, TIMER_ALWAYS_ENABLED, nvr); + /* Set the internal clock. */ + nvr_time_set(tm); + } else { + /* Reset the internal clock to 1980/01/01 00:00. */ + intclk.mon = 1; + intclk.year = 1980; + } + /* Set up our timer. */ timer_add(onesec_timer, &nvr->onesec_time, TIMER_ALWAYS_ENABLED, nvr); - timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, nvr); - /* It does not need saving yet. */ nvr_dosave = 0; /* Save the NVR data pointer. */ saved_nvr = nvr; -} - -/* Re-calculate the timer values. */ -void -nvr_recalc(void) -{ - int64_t c, nt; - - /* Make sure we have been initialized. */ - if (saved_nvr == NULL) return; - - c = 1 << ((saved_nvr->regs[RTC_REGA] & REGA_RS) - 1); - nt = (int64_t)(RTCCONST * c * (1<rtctime > nt) - saved_nvr->rtctime = nt; + /* Try to load the saved data. */ + (void)nvr_load(); } @@ -676,7 +211,6 @@ nvr_recalc(void) int nvr_load(void) { - int64_t c; FILE *f; /* Make sure we have been initialized. */ @@ -686,41 +220,23 @@ nvr_load(void) memset(saved_nvr->regs, 0xff, sizeof(saved_nvr->regs)); /* Set the defaults. */ - memset(saved_nvr->regs, 0x00, RTC_REGS); - saved_nvr->regs[RTC_DOM] = 1; - saved_nvr->regs[RTC_MONTH] = 1; - saved_nvr->regs[RTC_YEAR] = RTC_BCD(80); - saved_nvr->regs[RTC_CENTURY] = RTC_BCD(19); - - if (saved_nvr->load == NULL) { - /* We are responsible for loading. */ - f = NULL; - if (saved_nvr->mask != 0) { - pclog("Opening NVR file: %ls...\n", nvr_path(saved_nvr->fname)); - f = plat_fopen(nvr_path(saved_nvr->fname), L"rb"); - } + 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. */ - fread(saved_nvr->regs, sizeof(saved_nvr->regs), 1, f); + (void)fread(saved_nvr->regs, saved_nvr->size, 1, f); (void)fclose(f); } - } else { - /* OK, use alternate function. */ - (*saved_nvr->load)(saved_nvr->fname); } - /* Update the internal clock state based on the NVR registers. */ - if (enable_sync) - rtc_sync(saved_nvr->regs); - else - rtc_setnvr(saved_nvr->regs); - /* Get the local RTC running! */ - saved_nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1); - saved_nvr->regs[RTC_REGB] = REGB_2412; - c = 1 << ((saved_nvr->regs[RTC_REGA] & REGA_RS) - 1); - saved_nvr->rtctime += (int64_t)(RTCCONST * c * (1<start != NULL) + saved_nvr->start(saved_nvr); return(1); } @@ -735,22 +251,14 @@ nvr_save(void) /* Make sure we have been initialized. */ if (saved_nvr == NULL) return(0); - if (saved_nvr->save == NULL) { - /* We are responsible for saving. */ - f = NULL; - if (saved_nvr->mask != 0) { - pclog("Saving NVR file: %ls...\n", nvr_path(saved_nvr->fname)); - f = plat_fopen(nvr_path(saved_nvr->fname), L"wb"); - } - + 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, sizeof(saved_nvr->regs), 1, f); - (void)fclose(f); + (void)fwrite(saved_nvr->regs, saved_nvr->size, 1, f); + fclose(f); } - } else { - /* OK, use alternate function. */ - (*saved_nvr->save)(saved_nvr->fname); } /* Device is clean again. */ @@ -760,6 +268,42 @@ nvr_save(void) } +/* 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. */ wchar_t * nvr_path(wchar_t *str) @@ -776,11 +320,7 @@ nvr_path(wchar_t *str) plat_dir_create(temp); /* Now append the actual filename. */ -#ifdef _WIN32 - wcscat(temp, L"\\"); -#else - wcscat(temp, L"/"); -#endif + plat_append_slash(temp); wcscat(temp, str); return(temp); diff --git a/src/nvr.h b/src/nvr.h index 7a85b99..8119948 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -1,135 +1,99 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Definitions for a defacto-standard RTC/NVRAM device. - * - * Version: @(#)nvr.h 1.0.1 2018/02/14 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef EMU_NVR_H -# define EMU_NVR_H - - -/* 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 */ - - - -/* Define a (defacto-standard) RTC/NVRAM chip. */ -typedef struct _nvr_ { - uint8_t regs[RTC_REGS+114]; /* these are the registers */ - - int64_t mask, - irq, - addr; - - wchar_t *fname; - - int64_t upd_stat, - upd_ecount, - onesec_time, - onesec_cnt, - rtctime, - oldmachine; - - /* Hooks to internal RTC I/O functions. */ - void (*set)(struct _nvr_ *, uint16_t, uint8_t); - uint8_t (*get)(struct _nvr_ *, uint16_t); - - /* Hooks to alternative load/save functions. */ - int8_t (*load)(wchar_t *fname); - int8_t (*save)(wchar_t *fname); - - /* Hook to RTC ticker handler. */ - void (*hook)(struct _nvr_ *); -} nvr_t; - - -extern int enable_sync; -extern int nvr_dosave; - - -extern void nvr_init(nvr_t *); -extern int nvr_load(void); -extern int nvr_save(void); -extern void nvr_recalc(void); - -extern wchar_t *nvr_path(wchar_t *str); -extern FILE *nvr_fopen(wchar_t *str, wchar_t *mode); - -extern void nvr_at_init(int64_t irq); -extern void nvr_at_close(void); - - -#endif /*EMU_NVR_H*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the generic NVRAM/CMOS driver. + * + * Version: @(#)nvr.h 1.0.2 2018/03/11 + * + * Author: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef EMU_NVR_H +# define EMU_NVR_H + + +#define NVR_MAXSIZE 128 /* max size of NVR data */ + +/* 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)) +#define RTC_BCDINC(x,y) RTC_BCD(RTC_DCB(x) + y) + + +/* Define a generic RTC/NVRAM device. */ +typedef struct _nvr_ { + uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ + wchar_t *fn; /* pathname of image file */ + uint16_t size; /* device configuration */ + int8_t irq; + + int8_t upd_stat, /* FIXME: move to private struct */ + addr; + int64_t upd_ecount, /* FIXME: move to private struct */ + onesec_time, + onesec_cnt, + rtctime; + + /* Hooks to device functions. */ + void (*reset)(struct _nvr_ *); + void (*start)(struct _nvr_ *); + void (*tick)(struct _nvr_ *); +} nvr_t; + + +extern int nvr_dosave; + + +extern void nvr_init(nvr_t *); +extern int nvr_load(void); +extern int nvr_save(void); + +extern int nvr_is_leap(int year); +extern int nvr_get_days(int month, int year); +extern void nvr_time_get(struct tm *); +extern void nvr_time_set(struct tm *); + +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); +extern void nvr_at_close(void); + + +#endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index d3e9375..92e75b9 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -1,145 +1,659 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * 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.2 2018/03/04 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Mahod, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include "cpu/cpu.h" -#include "io.h" -#include "device.h" -#include "machine/machine.h" -#include "mem.h" -#include "nmi.h" -#include "nvr.h" -#include "rom.h" - - -static nvr_t *nvrp; - - -static void -nvr_write(uint16_t addr, uint8_t val, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - - cycles -= ISA_CYCLES(8); - - if (! (addr & 1)) { - nvr->addr = (val & nvr->mask); - if (!(machines[machine].flags & MACHINE_MCA) && (romset != ROM_IBMPS1_2133)) - nmi_mask = (~val & 0x80); - - 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; - - cycles -= ISA_CYCLES(8); - - 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) -{ - if (nvrp == NULL) - return; - - if (nvrp->fname != NULL) - free(nvrp->fname); - - free(nvrp); - - nvrp = NULL; -} - - -void -nvr_at_init(int64_t 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); - - /* Load the NVR into memory! */ - (void)nvr_load(); - - nvrp = nvr; -} +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implement a more-or-less defacto-standard RTC/NVRAM. + * + * When IBM released the PC/AT machine, it came standard with a + * battery-backed RTC chip to keep the time of day, something + * that was optional on standard PC's with a myriad variants + * being put on the market, often on cheap multi-I/O cards. + * + * The PC/AT had an on-board DS12885-series chip ("the black + * block") which was an RTC/clock chip with onboard oscillator + * and a backup battery (hence the big size.) The chip also had + * a small amount of RAM bytes available to the user, which was + * used by IBM's ROM BIOS to store machine configuration data. + * 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... + * + * Since then, pretty much any PC has an implementation of that + * device, which became known as the "nvr" or "cmos". + * + * NOTES Info extracted from the data sheets: + * + * * 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. + * + * * Rate Selector (RS3: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. + * + * * Oscillator (DV2: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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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 b any internal device functions, + * but is cleared to 0 on !RESET. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * * 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. + * + * This file implements a generic version of the RTC/NVRAM chip, + * including the later update (DS12887A) which implemented a + * "century" register to be compatible with Y2K. + * + * Version: @(#)nvr_at.c 1.0.3 2018/03/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Mahod, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "emu.h" +#include "cpu/cpu.h" +#include "machine/machine.h" +#include "io.h" +#include "pic.h" +#include "pit.h" +#include "nmi.h" +#include "timer.h" +#include "device.h" +#include "nvr.h" + + +/* 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 */ + + +static nvr_t *nvrp; + + +/* Get the current NVR time. */ +static void +time_get(uint8_t *regs, struct tm *tm) +{ + int8_t temp; + + if (regs[RTC_REGB] & REGB_DM) { + /* NVR is in Binary data mode. */ + tm->tm_sec = regs[RTC_SECONDS]; + tm->tm_min = regs[RTC_MINUTES]; + temp = regs[RTC_HOURS]; + tm->tm_wday = (regs[RTC_DOW] - 1); + tm->tm_mday = regs[RTC_DOM]; + tm->tm_mon = (regs[RTC_MONTH] - 1); + tm->tm_year = regs[RTC_YEAR]; + tm->tm_year += (regs[RTC_CENTURY] * 100) - 1900; + } else { + /* NVR is in BCD data mode. */ + tm->tm_sec = RTC_DCB(regs[RTC_SECONDS]); + tm->tm_min = RTC_DCB(regs[RTC_MINUTES]); + temp = RTC_DCB(regs[RTC_HOURS]); + tm->tm_wday = (RTC_DCB(regs[RTC_DOW]) - 1); + tm->tm_mday = RTC_DCB(regs[RTC_DOM]); + tm->tm_mon = (RTC_DCB(regs[RTC_MONTH]) - 1); + tm->tm_year = RTC_DCB(regs[RTC_YEAR]); + tm->tm_year += (RTC_DCB(regs[RTC_CENTURY]) * 100) - 1900; + } + + /* Adjust for 12/24 hour mode. */ + if (regs[RTC_REGB] & REGB_2412) + tm->tm_hour = temp; + else + tm->tm_hour = ((temp & ~RTC_AMPM)%12) + ((temp&RTC_AMPM) ? 12 : 0); +} + + +/* Set the current NVR time. */ +static void +time_set(uint8_t *regs, struct tm *tm) +{ + int year = (tm->tm_year + 1900); + + if (regs[RTC_REGB] & REGB_DM) { + /* NVR is in Binary data mode. */ + regs[RTC_SECONDS] = tm->tm_sec; + regs[RTC_MINUTES] = tm->tm_min; + regs[RTC_DOW] = (tm->tm_wday + 1); + regs[RTC_DOM] = tm->tm_mday; + regs[RTC_MONTH] = (tm->tm_mon + 1); + regs[RTC_YEAR] = (year % 100); + regs[RTC_CENTURY] = (year / 100); + + if (regs[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + regs[RTC_HOURS] = tm->tm_hour; + } else { + /* NVR is in 12h mode. */ + regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; + if (tm->tm_hour > 11) + regs[RTC_HOURS] |= RTC_AMPM; + } + } else { + /* NVR is in BCD data mode. */ + regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec); + regs[RTC_MINUTES] = RTC_BCD(tm->tm_min); + regs[RTC_DOW] = (RTC_BCD(tm->tm_wday) + 1); + regs[RTC_DOM] = RTC_BCD(tm->tm_mday); + regs[RTC_MONTH] = (RTC_BCD(tm->tm_mon) + 1); + regs[RTC_YEAR] = RTC_BCD(year % 100); + regs[RTC_CENTURY] = RTC_BCD(year / 100); + + if (regs[RTC_REGB] & REGB_2412) { + /* NVR is in 24h mode. */ + regs[RTC_HOURS] = RTC_BCD(tm->tm_hour); + } else { + /* NVR is in 12h mode. */ + regs[RTC_HOURS] = (tm->tm_hour % 12) + ? RTC_BCD(tm->tm_hour % 12) + : RTC_BCD(12); + if (tm->tm_hour > 11) + regs[RTC_HOURS] |= RTC_AMPM; + } + } +} + + +/* Check if the current time matches a set alarm time. */ +static int8_t +check_alarm(uint8_t *regs, int8_t addr) +{ +#define ALARM_DONTCARE 0xc0 + return((regs[addr+1] == regs[addr]) || + ((regs[addr+1] & ALARM_DONTCARE) == ALARM_DONTCARE)); +} + + +/* Update the NVR registers from the internal clock. */ +static void +update_timer(void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + struct tm tm; + + if (! (nvr->regs[RTC_REGB] & REGB_SET)) { + /* Get the current time from the internal clock. */ + nvr_time_get(&tm); + + /* Update registers with current time. */ + time_set(nvr->regs, &tm); + + /* Clear update status. */ + nvr->upd_stat = 0x00; + + /* Check for any alarms we need to handle. */ + if (check_alarm(nvr->regs, RTC_SECONDS) && + check_alarm(nvr->regs, RTC_MINUTES) && + check_alarm(nvr->regs, RTC_HOURS)) { + nvr->regs[RTC_REGC] |= REGC_AF; + if (nvr->regs[RTC_REGB] & REGB_AIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); + } + } + + /* + * The flag and interrupt should be issued + * on update ended, not started. + */ + nvr->regs[RTC_REGC] |= REGC_UF; + if (nvr->regs[RTC_REGB] & REGB_UIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); + } + } + + nvr->upd_ecount = 0; +} + + +/* Re-calculate the timer values. */ +static void +rtc_timer_recalc(nvr_t *nvr, int add) +{ + int64_t c, nt; + + c = 1 << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); + nt = (int64_t)(RTCCONST * c * (1<rtctime += nt; + else if (nvr->rtctime > nt) + nvr->rtctime = nt; +} + + +static void +rtc_timer(void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + + if (! (nvr->regs[RTC_REGA] & REGA_RS)) { + nvr->rtctime = 0x7fffffff; + return; + } + + /* Update our timer interval. */ + rtc_timer_recalc(nvr, 1); + + nvr->regs[RTC_REGC] |= REGC_PF; + if (nvr->regs[RTC_REGB] & REGB_PIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1<irq); + } +} + + +/* Callback from internal clock, another second passed. */ +static void +tick_timer(nvr_t *nvr) +{ + if (nvr->regs[RTC_REGB] & REGB_SET) return; + + nvr->upd_stat = REGA_UIP; + + nvr->upd_ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); +} + + +/* Write to one of the NVR registers. */ +static void +nvr_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + struct tm tm; + uint8_t old; + + cycles -= ISA_CYCLES(8); + + if (addr & 1) { + old = nvr->regs[nvr->addr]; + switch(nvr->addr) { + case RTC_REGA: + nvr->regs[RTC_REGA] = val; + if (val & REGA_RS) + rtc_timer_recalc(nvr, 1); + else + nvr->rtctime = 0x7fffffff; + break; + + case RTC_REGB: + nvr->regs[RTC_REGB] = val; + if (((old^val) & REGB_SET) && (val®B_SET)) { + /* According to the datasheet... */ + nvr->regs[RTC_REGA] &= ~REGA_UIP; + nvr->regs[RTC_REGB] &= ~REGB_UIE; + } + break; + + case RTC_REGC: /* R/O */ + case RTC_REGD: /* R/O */ + break; + + default: /* non-RTC registers are just NVRAM */ + if (nvr->regs[nvr->addr] != val) { + nvr->regs[nvr->addr] = val; + nvr_dosave = 1; + } + break; + } + + if ((nvr->addr < RTC_REGA) || (nvr->addr == RTC_CENTURY)) { + if ((nvr->addr != 1) && (nvr->addr != 3) && (nvr->addr != 5)) { + if ((old != val) && !enable_sync) { + /* Update internal clock. */ + time_get(nvr->regs, &tm); + nvr_time_set(&tm); + nvr_dosave = 1; + } + } + } + } else { + nvr->addr = (val & (nvr->size - 1)); + if (!(machines[machine].flags & MACHINE_MCA) && + (romset != ROM_IBMPS1_2133)) + nmi_mask = (~val & 0x80); + } +} + + +/* Read from one of the NVR registers. */ +static uint8_t +nvr_read(uint16_t addr, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + uint8_t ret; + + cycles -= ISA_CYCLES(8); + + if (addr & 1) switch(nvr->addr) { + case RTC_REGA: + ret = (nvr->regs[RTC_REGA] & 0x7f) | nvr->upd_stat; + break; + + case RTC_REGC: + picintc(1<irq); + ret = nvr->regs[RTC_REGC]; + nvr->regs[RTC_REGC] = 0x00; + break; + + case RTC_REGD: + nvr->regs[RTC_REGD] |= REGD_VRT; + ret = nvr->regs[RTC_REGD]; + break; + + default: + ret = nvr->regs[nvr->addr]; + break; + } else { + ret = nvr->addr; + } + + return(ret); +} + + +/* Reset the RTC state to 1980/01/01 00:00. */ +static void +nvr_at_reset(nvr_t *nvr) +{ + memset(nvr->regs, 0x00, RTC_REGS); + nvr->regs[RTC_DOM] = 1; + nvr->regs[RTC_MONTH] = 1; + nvr->regs[RTC_YEAR] = RTC_BCD(80); + nvr->regs[RTC_CENTURY] = RTC_BCD(19); +} + + +/* Process after loading from file. */ +static void +nvr_at_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (enable_sync) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } + + /* Start the RTC. */ + nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1); + nvr->regs[RTC_REGB] = REGB_2412; + rtc_timer_recalc(nvr, 0); +} + + +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->size = machines[machine].nvrsz; + nvr->irq = irq; + + /* Set up any local handlers here. */ + nvr->reset = nvr_at_reset; + nvr->start = nvr_at_start; + nvr->tick = tick_timer; + + /* Initialize the generic NVR. */ + nvr_init(nvr); + + /* Start the timers. */ + timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, nvr); + timer_add(rtc_timer, &nvr->rtctime, TIMER_ALWAYS_ENABLED, nvr); + + /* Set up the I/O handler for this device. */ + io_sethandler(0x0070, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + + nvrp = nvr; +} + + +void +nvr_at_close(void) +{ + if (nvrp == NULL) return; + + if (nvrp->fn != NULL) + free(nvrp->fn); + + free(nvrp); + + nvrp = NULL; +} diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index ff6d17b..f3dd35e 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -8,7 +8,7 @@ * * Handling of the PS/2 series CMOS devices. * - * Version: @(#)nvr_ps2.c 1.0.1 2018/02/14 + * Version: @(#)nvr_ps2.c 1.0.3 2018/03/10 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -40,113 +40,121 @@ #include #include #include "emu.h" -#include "machine/machine.h" #include "cpu/cpu.h" +#include "machine/machine.h" #include "device.h" #include "io.h" -#include "mem.h" -#include "rom.h" #include "nvr.h" #include "nvr_ps2.h" -typedef struct ps2_nvr_t -{ - int addr; - uint8_t ram[8192]; +typedef struct { + int addr; + + uint8_t ram[8192]; } ps2_nvr_t; -static uint8_t ps2_nvr_read(uint16_t port, void *p) +static uint8_t +ps2_nvr_read(uint16_t port, void *priv) { - ps2_nvr_t *nvr = (ps2_nvr_t *)p; - - switch (port) - { - case 0x74: - return nvr->addr & 0xff; - case 0x75: - return nvr->addr >> 8; - case 0x76: - return nvr->ram[nvr->addr]; - } - - return 0xff; + ps2_nvr_t *nvr = (ps2_nvr_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x74: + ret = nvr->addr & 0xff; + break; + + case 0x75: + ret = nvr->addr >> 8; + break; + + case 0x76: + ret = nvr->ram[nvr->addr]; + break; + } + + return(ret); } -static void ps2_nvr_write(uint16_t port, uint8_t val, void *p) + +static void +ps2_nvr_write(uint16_t port, uint8_t val, void *priv) { - ps2_nvr_t *nvr = (ps2_nvr_t *)p; - - switch (port) - { - case 0x74: - nvr->addr = (nvr->addr & 0x1f00) | val; - break; - case 0x75: - nvr->addr = (nvr->addr & 0xff) | ((val & 0x1f) << 8); - break; - case 0x76: - nvr->ram[nvr->addr] = val; - break; - } + ps2_nvr_t *nvr = (ps2_nvr_t *)priv; + + switch (port) { + case 0x74: + nvr->addr = (nvr->addr & 0x1f00) | val; + break; + + case 0x75: + nvr->addr = (nvr->addr & 0xff) | ((val & 0x1f) << 8); + break; + + case 0x76: + nvr->ram[nvr->addr] = val; + break; + } } -static void *ps2_nvr_init(device_t *info) + +static void * +ps2_nvr_init(device_t *info) { - ps2_nvr_t *nvr = (ps2_nvr_t *)malloc(sizeof(ps2_nvr_t)); - FILE *f = NULL; + ps2_nvr_t *nvr; + FILE *f = NULL; - memset(nvr, 0, sizeof(ps2_nvr_t)); - - io_sethandler(0x0074, 0x0003, ps2_nvr_read, NULL, NULL, ps2_nvr_write, NULL, NULL, nvr); + nvr = (ps2_nvr_t *)malloc(sizeof(ps2_nvr_t)); + memset(nvr, 0x00, sizeof(ps2_nvr_t)); + + io_sethandler(0x0074, 3, + ps2_nvr_read,NULL,NULL, ps2_nvr_write,NULL,NULL, nvr); - switch (romset) - { - case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"rb"); break; -#ifdef WALTJE - case ROM_IBMPS2_M80_486: f = nvr_fopen(L"ibmps2_m80-486_sec.nvr", L"rb"); break; -#endif - } - if (f) - { - fread(nvr->ram, 8192, 1, f); - fclose(f); - } - else - memset(nvr->ram, 0xFF, 8192); - - return nvr; + switch (romset) { + case ROM_IBMPS2_M80: + f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"rb"); + break; + } + + memset(nvr->ram, 0xff, 8192); + if (f != NULL) { + (void)fread(nvr->ram, 8192, 1, f); + fclose(f); + } + + return(nvr); } -void ps2_nvr_close(void *p) -{ - ps2_nvr_t *nvr = (ps2_nvr_t *)p; - FILE *f = NULL; - switch (romset) - { - case ROM_IBMPS2_M80: f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"wb"); break; -#ifdef WALTJE - case ROM_IBMPS2_M80_486: f = nvr_fopen(L"ibmps2_m80-486_sec.nvr", L"wb"); break; -#endif - } - if (f) - { - fwrite(nvr->ram, 8192, 1, f); - fclose(f); - } - - free(nvr); +static void +ps2_nvr_close(void *priv) +{ + ps2_nvr_t *nvr = (ps2_nvr_t *)priv; + FILE *f = NULL; + + switch (romset) { + case ROM_IBMPS2_M80: + f = nvr_fopen(L"ibmps2_m80_sec.nvr", L"wb"); + break; + } + + if (f != NULL) { + (void)fwrite(nvr->ram, 8192, 1, f); + fclose(f); + } + + free(nvr->ram); + + free(nvr); } -device_t ps2_nvr_device = -{ - "PS/2 NVRRAM", - 0, - 0, - ps2_nvr_init, - ps2_nvr_close, - NULL, - NULL, NULL, NULL, NULL + +device_t ps2_nvr_device = { + "PS/2 Secondary NVRAM", + 0, 0, + ps2_nvr_init, ps2_nvr_close, NULL, + NULL, NULL, NULL, + NULL }; diff --git a/src/nvr_tc8521.c b/src/nvr_tc8521.c deleted file mode 100644 index 7d612f4..0000000 --- a/src/nvr_tc8521.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "emu.h" -#include "mem.h" -#include "io.h" -#include "nvr.h" -#include "nvr_tc8521.h" -#include "rtc_tc8521.h" -#include "pic.h" -#include "pit.h" -#include "plat.h" -#include "rom.h" -#include "timer.h" -#include "config.h" -#include "nmi.h" -#include "machine/machine.h" - -int oldromset; -int nvrmask=63; -uint8_t nvrram[128]; -int nvraddr; - -int nvr_dosave = 0; - -static int64_t nvr_onesec_time = 0, nvr_onesec_cnt = 0; - -static void tc8521_onesec(void *p) -{ - nvr_onesec_cnt++; - if (nvr_onesec_cnt >= 100) - { - tc8521_tick(); - nvr_onesec_cnt = 0; - } - nvr_onesec_time += (int)(10000 * TIMER_USEC); -} - -void write_tc8521(uint16_t addr, uint8_t val, void *priv) -{ - uint8_t page = nvrram[0x0D] & 3; - - addr &= 0x0F; - if (addr < 0x0D) addr += 16 * page; - - if (addr >= 0x10 && nvrram[addr] != val) - nvr_dosave = 1; - - nvrram[addr] = val; -} - - -uint8_t read_tc8521(uint16_t addr, void *priv) -{ - uint8_t page = nvrram[0x0D] & 3; - - addr &= 0x0F; - if (addr < 0x0D) addr += 16 * page; - - return nvrram[addr]; -} - - -void tc8521_loadnvr() -{ - FILE *f; - - nvrmask=63; - oldromset=romset; - switch (romset) - { - case ROM_T1000: f = plat_fopen(nvr_path(L"t1000.nvr"), L"rb"); break; - case ROM_T1200: f = plat_fopen(nvr_path(L"t1200.nvr"), L"rb"); break; - default: return; - } - if (!f) - { - memset(nvrram,0xFF,64); - nvrram[0x0E] = 0; /* Test register */ - if (!enable_sync) - { - memset(nvrram, 0, 16); - } - return; - } - fread(nvrram,64,1,f); - if (enable_sync) - tc8521_internal_sync(nvrram); - else - tc8521_internal_set_nvrram(nvrram); /* Update the internal clock state based on the NVR registers. */ - fclose(f); -} - - -void tc8521_savenvr() -{ - FILE *f; - switch (oldromset) - { - case ROM_T1000: f = plat_fopen(nvr_path(L"t1000.nvr"), L"wb"); break; - case ROM_T1200: f = plat_fopen(nvr_path(L"t1200.nvr"), L"wb"); break; - default: return; - } - fwrite(nvrram,64,1,f); - fclose(f); -} - -void nvr_tc8521_init() -{ - io_sethandler(0x2C0, 0x10, read_tc8521, NULL, NULL, write_tc8521, NULL, NULL, NULL); - timer_add(tc8521_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL); -} diff --git a/src/nvr_tc8521.h b/src/nvr_tc8521.h deleted file mode 100644 index c17342b..0000000 --- a/src/nvr_tc8521.h +++ /dev/null @@ -1,12 +0,0 @@ -void nvr_tc8521_init(); - -extern int enable_sync; - -extern int nvr_dosave; - -void tc8521_loadnvr(); -void tc8521_savenvr(); - -void tc8521_nvr_recalc(); - -FILE *nvrfopen(char *fn, char *mode); diff --git a/src/pc.c b/src/pc.c index 485d5f3..609dc00 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.6 2018/03/07 + * Version: @(#)pc.c 1.0.7 2018/03/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,6 +53,7 @@ # include "cpu/codegen.h" #endif #include "cpu/x86_ops.h" +#include "machine/machine.h" #include "io.h" #include "mem.h" #include "rom.h" @@ -63,7 +64,6 @@ #include "timer.h" #include "device.h" #include "nvr.h" -#include "machine/machine.h" #include "bugger.h" #include "lpt.h" #include "serial.h" @@ -94,8 +94,6 @@ #include "video/video.h" #include "ui.h" #include "plat.h" -#include "plat_joystick.h" -#include "plat_midi.h" /* Commandline options. */ @@ -148,6 +146,7 @@ int cpu_manufacturer = 0, /* (C) cpu manufacturer */ cpu_use_dynarec = 0, /* (C) cpu uses/needs Dyna */ cpu = 3, /* (C) cpu type */ enable_external_fpu = 0; /* (C) enable external FPU */ +int enable_sync = 0; /* (C) enable time sync */ /* Statistics. */ @@ -536,7 +535,7 @@ usage: (void)time(&now); info = localtime(&now); strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info); - pclog("#\n# %s v%s\n\n# Logfile created %s\n#\n", + pclog("#\n# %s v%s\n#\n# Logfile created %s\n#\n", emu_title, emu_version, temp); pclog("# Emulator path: %ls\n", emu_path); pclog("# Userfiles path: %ls\n", usr_path); @@ -575,8 +574,6 @@ pc_full_speed(void) setpitclock(14318184.0); } atfullspeed = 1; - - nvr_recalc(); } @@ -587,8 +584,6 @@ pc_speed_changed(void) setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); else setpitclock(14318184.0); - - nvr_recalc(); } diff --git a/src/plat.h b/src/plat.h index 506e217..70d6e11 100644 --- a/src/plat.h +++ b/src/plat.h @@ -8,7 +8,7 @@ * * Define the various platform support functions. * - * Version: @(#)plat.h 1.0.4 2018/03/07 + * Version: @(#)plat.h 1.0.5 2018/03/10 * * Author: Fred N. van Kempen, * @@ -132,6 +132,17 @@ extern void set_language(int id); extern wchar_t *plat_get_string(int id); +/* Dynamic Module Loader interface. */ +typedef struct { + const char *name; + void *func; +} dllimp_t; + + +extern void *dynld_module(const char *, dllimp_t *); +extern void dynld_close(void *); + + /* Emulator start/stop support functions. */ extern void do_start(void); extern void do_stop(void); @@ -153,6 +164,14 @@ extern int ioctl_open(uint8_t id, char d); extern void ioctl_reset(uint8_t id); extern void ioctl_close(uint8_t id); +extern void plat_midi_init(void); +extern void plat_midi_close(void); +extern void plat_midi_play_msg(uint8_t* val); +extern void plat_midi_play_sysex(uint8_t* data, unsigned int len); +extern int plat_midi_write(uint8_t val); +extern int plat_midi_get_num_devs(); +extern void plat_midi_get_dev_name(int num, char *s); + /* Thread support. */ typedef void thread_t; diff --git a/src/plat_dynld.h b/src/plat_dynld.h deleted file mode 100644 index a059f52..0000000 --- a/src/plat_dynld.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Define the Dynamic Module Loader interface. - * - * Version: @(#)plat_dynld.h 1.0.1 2018/02/14 - * - * Author: Fred N. van Kempen, - * - * Copyright 2017,2018 Fred N. van Kempen. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef PLAT_DYNLD_H -# define PLAT_DYNLD_H - - -typedef struct { - const char *name; - void *func; -} dllimp_t; - - -extern void *dynld_module(const char *, dllimp_t *); -extern void dynld_close(void *); - - -#endif /*PLAT_DYNLD_H*/ diff --git a/src/plat_joystick.h b/src/plat_joystick.h deleted file mode 100644 index e576e1d..0000000 --- a/src/plat_joystick.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Define platform joystick interface. - * - * NOTE: This should be worked into platform code and joystick.h. - * - * Version: @(#)plat_joystick.h 1.0.1 2018/02/14 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef PLAT_JOYSTICK_H -# define PLAT_JOYSTICK_H - - -#define MAX_PLAT_JOYSTICKS 8 -#define MAX_JOYSTICKS 4 - -#define POV_X 0x80000000 -#define POV_Y 0x40000000 - - -typedef struct { - char name[64]; - - int a[8]; - int b[32]; - int p[4]; - - struct { - char name[32]; - int id; - } axis[8]; - - struct { - char name[32]; - int id; - } button[32]; - - struct { - char name[32]; - int id; - } pov[4]; - - int nr_axes; - int nr_buttons; - int nr_povs; -} plat_joystick_t; - -typedef struct { - int axis[8]; - int button[32]; - int pov[4]; - - int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; -} joystick_t; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -extern joystick_t joystick_state[MAX_JOYSTICKS]; -extern int joysticks_present; - - -#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) - - -extern void joystick_init(void); -extern void joystick_close(void); -extern void joystick_process(void); - -#ifdef __cplusplus -} -#endif - - -#endif /*PLAT_JOYSTICK_H*/ diff --git a/src/plat_midi.h b/src/plat_midi.h deleted file mode 100644 index db62de9..0000000 --- a/src/plat_midi.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Define platform MIDI interface. - * - * NOTE: This should be worked into platform code and midi.h. - * - * Version: @(#)plat_midi.h 1.0.1 2018/02/14 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef PLAT_MIDI_H -# define PLAT_MIDI_H - - -extern void plat_midi_init(void); -extern void plat_midi_close(void); - -extern void plat_midi_play_msg(uint8_t* val); -extern void plat_midi_play_sysex(uint8_t* data, unsigned int len); -extern int plat_midi_write(uint8_t val); -extern int plat_midi_get_num_devs(); -extern void plat_midi_get_dev_name(int num, char *s); - - -#endif /*PLAT_MIDI_H*/ diff --git a/src/rom.c b/src/rom.c index cd96449..fafbac1 100644 --- a/src/rom.c +++ b/src/rom.c @@ -11,9 +11,8 @@ * NOTES: - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM) * - pc2386 video BIOS is underdumped (16k instead of 24k) * - c386sx16 BIOS fails checksum - * - the loadfont() calls should be done elsewhere * - * Version: @(#)rom.c 1.0.6 2018/03/07 + * Version: @(#)rom.c 1.0.7 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,13 +50,9 @@ #include "cpu/cpu.h" #include "mem.h" #include "rom.h" -#include "video/video.h" /* for loadfont() */ #include "plat.h" -int romspresent[ROM_MAX]; - - FILE * rom_fopen(wchar_t *fn) { diff --git a/src/rom.h b/src/rom.h index 733c729..c682e12 100644 --- a/src/rom.h +++ b/src/rom.h @@ -8,7 +8,7 @@ * * Definitions for the ROM image handler. * - * Version: @(#)rom.h 1.0.5 2018/03/08 + * Version: @(#)rom.h 1.0.6 2018/03/09 * * Authors: Fred N. van Kempen, * @@ -48,18 +48,6 @@ # define EMU_ROM_H -#define PCJR (romset==ROM_IBMPCJR) -#if defined(DEV_BRANCH) && defined(USE_GREENB) -#define AMIBIOS (romset==ROM_AMI386SX || \ - romset==ROM_AMI486 || \ - romset==ROM_WIN486 || \ - romset==ROM_4GPV31) -#else -#define AMIBIOS (romset==ROM_AMI386SX || \ - romset==ROM_AMI486 || \ - romset==ROM_WIN486) -#endif - #define ROMDEF_NFILES 8 /* max number of rom image files */ @@ -83,129 +71,6 @@ typedef struct { } romdef_t; -enum { - ROM_IBMPC = 0, /* 301 keyboard error, 131 cassette (!!!) error */ - ROM_AMIXT, /* XT Clone with AMI BIOS */ - ROM_DTKXT, - ROM_IBMXT, /* 301 keyboard error */ - ROM_GENXT, /* 'Generic XT BIOS' */ - ROM_JUKOPC, - ROM_PORTABLE, - ROM_PXXT, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - ROM_LTXT, - ROM_LXT3, -#endif - ROM_T1000, - ROM_T1200, - ROM_XI8088, - ROM_IBMPCJR, - ROM_TANDY, - ROM_TANDY1000HX, - ROM_EUROPC, - ROM_PC1512, - ROM_PC1640, - ROM_PC200, - ROM_PC2086, - ROM_PC3086, - ROM_OLIM24, - ROM_TANDY1000SL2, - ROM_T3100E, - - ROM_AMI286, - ROM_AWARD286, - ROM_CMDPC30, - ROM_PORTABLEII, -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - ROM_PORTABLEIII, -#endif - ROM_GW286CT, - ROM_SUPER286TR, /* Hyundai Super-286TR/SCAT/Award */ - ROM_IBMAT, - ROM_IBMPS1_2011, - ROM_IBMPS2_M30_286, - ROM_IBMXT286, - ROM_SPC4200P, /* Samsung SPC-4200P/SCAT/Phoenix */ - ROM_SPC4216P, /* Samsung SPC-4216P/SCAT */ - - ROM_IBMPS2_M50, - - ROM_AMI386SX, - ROM_KMXC02, - ROM_MEGAPC, - ROM_AWARD386SX_OPTI495, -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) - ROM_DESKPRO_386, -#endif - ROM_DTK386, - ROM_IBMPS1_2121, - ROM_IBMPS1_2121_ISA,/* IBM PS/1 Model 2121 with ISA expansion bus */ -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - ROM_PORTABLEIII386, -#endif - - ROM_IBMPS2_M55SX, - - ROM_AMI386DX_OPTI495, - ROM_MEGAPCDX, /* 386DX mdl - Note: documentation (in German) clearly says such a model exists */ - ROM_AWARD386DX_OPTI495, - ROM_MR386DX_OPTI495, - - ROM_IBMPS2_M80, - - ROM_AMI486, - ROM_WIN486, -#ifdef UNIMPLEMENTED_MACHINES - ROM_VLI486SV2G, /* ASUS VL/I-486SV2G/SiS 471/Award/SiS 85C471 */ /* 51 */ -#endif - ROM_AWARD486_OPTI495, - ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ -#if defined(DEV_BRANCH) && defined(USE_GREENB) - ROM_4GPV31, /* Green-B 4GPV3.1 ISA/VLB 486/Pentium, AMI */ -#endif - ROM_IBMPS1_2133, - - ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ - - ROM_REVENGE, /* Intel Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ - - ROM_PLATO, /* Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ - - ROM_P54TP4XE, /* ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ - ROM_ENDEAVOR, /* Intel Advanced_EV/430FX/AMI/NS PC87306 */ - ROM_ZAPPA, /* Intel Advanced_ZP/430FX/AMI/NS PC87306 */ -#ifdef UNIMPLEMENTED_MACHINES - ROM_POWERMATE_V, /* NEC PowerMate V/430FX/Phoenix/SMC FDC37C66 5*/ -#endif - ROM_MB500N, /* PC Partner MB500N/430FX/Award/SMC FDC37C665 */ - ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ - - ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ -#if defined(DEV_BRANCH) && defined(USE_MRTHOR) - ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ -#endif - - ROM_ACERM3A, /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ - ROM_ACERV35N, /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ - ROM_AP53, /* AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ - ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ - ROM_P55T2S, /* ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ - - ROM_P55TVP4, /* ASUS P/I-P55TVP4/430HX/Award/Winbond W8387F*/ - ROM_430VX, /* Award 430VX PCI/430VX/Award/UMC UM8669F*/ - ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ - -#if defined(DEV_BRANCH) && defined(USE_I686) - ROM_440FX, /* Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ - ROM_S1668, /* Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ -#endif - - ROM_MAX -}; - - -extern int romspresent[ROM_MAX]; - extern uint8_t rom_read(uint32_t addr, void *p); extern uint16_t rom_readw(uint32_t addr, void *p); extern uint32_t rom_readl(uint32_t addr, void *p); diff --git a/src/rtc_tc8521.c b/src/rtc_tc8521.c deleted file mode 100644 index f3b64ba..0000000 --- a/src/rtc_tc8521.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Emulation of: - Toshiba TC8521 Real Time Clock */ - -#include -#include -#include -#include -#include -#include "nvr.h" -#include "rtc_tc8521.h" - -#define peek2(a) (nvrram[(a##1)] + 10 * nvrram[(a##10)]) - -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]; - else - return rtc_is_leap(org_year) ? 29 : 28; -} - -/* Called when the internal clock gets updated */ -static void tc8521_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 tc8521_tick() -{ - internal_clock.sec++; - tc8521_recalc(); -} - -/* Called when modifying the NVR registers */ -void tc8521_update(uint8_t *nvrram, int reg) -{ - int temp; - - switch(reg) - { - case TC8521_SECOND1: - case TC8521_SECOND10: - internal_clock.sec = peek2(TC8521_SECOND); - break; - case TC8521_MINUTE1: - case TC8521_MINUTE10: - internal_clock.min = peek2(TC8521_MINUTE); - break; - case TC8521_HOUR1: - case TC8521_HOUR10: - temp = peek2(TC8521_HOUR); - if (nvrram[TC8521_24HR] & 1) - internal_clock.hour = temp; - else - internal_clock.hour = ((temp & ~0x20) % 12) + ((temp & 0x20) ? 12 : 0); - break; - case TC8521_DAY1: - case TC8521_DAY10: - internal_clock.mday = peek2(TC8521_DAY); - break; - case TC8521_MONTH1: - case TC8521_MONTH10: - internal_clock.mon = peek2(TC8521_MONTH); - break; - case TC8521_YEAR1: - case TC8521_YEAR10: - internal_clock.year = 1980 + peek2(TC8521_YEAR); - 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 tc8521_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 tc8521_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 tc8521_set_nvrram(uint8_t *nvrram, struct tm *cur_time_tm) -{ - nvrram[TC8521_SECOND1] = cur_time_tm->tm_sec % 10; - nvrram[TC8521_SECOND10] = cur_time_tm->tm_sec / 10; - nvrram[TC8521_MINUTE1] = cur_time_tm->tm_min % 10; - nvrram[TC8521_MINUTE10] = cur_time_tm->tm_min / 10; - if (nvrram[TC8521_24HR] & 1) - { - nvrram[TC8521_HOUR1] = cur_time_tm->tm_hour % 10; - nvrram[TC8521_HOUR10] = cur_time_tm->tm_hour / 10; - } - else - { - nvrram[TC8521_HOUR1] = (cur_time_tm->tm_hour % 12) % 10; - nvrram[TC8521_HOUR10] = ((cur_time_tm->tm_hour % 12) / 10) - | (cur_time_tm->tm_hour >= 12) ? 2 : 0; - } - nvrram[TC8521_WEEKDAY] = cur_time_tm->tm_wday; - nvrram[TC8521_DAY1] = cur_time_tm->tm_mday % 10; - nvrram[TC8521_DAY10] = cur_time_tm->tm_mday / 10; - nvrram[TC8521_MONTH1] = (cur_time_tm->tm_mon + 1) / 10; - nvrram[TC8521_MONTH10] = (cur_time_tm->tm_mon + 1) % 10; - nvrram[TC8521_YEAR1] = (cur_time_tm->tm_year - 80) % 10; - nvrram[TC8521_YEAR10] = ((cur_time_tm->tm_year - 80) % 100) / 10; -} - - -void tc8521_internal_set_nvrram(uint8_t *nvrram) -{ - /* Load the entire internal clock state from the NVR. */ - internal_clock.sec = peek2(TC8521_SECOND); - internal_clock.min = peek2(TC8521_MINUTE); - if (nvrram[TC8521_24HR] & 1) - { - internal_clock.hour = peek2(TC8521_HOUR); - } - else - { - internal_clock.hour = (peek2(TC8521_HOUR) % 12) - + (nvrram[TC8521_HOUR10] & 2) ? 12 : 0; - } - internal_clock.mday = peek2(TC8521_DAY); - internal_clock.mon = peek2(TC8521_MONTH); - internal_clock.year = 1980 + peek2(TC8521_YEAR); -} - -void tc8521_internal_sync(uint8_t *nvrram) -{ - struct tm *cur_time_tm; - time_t cur_time; - - time(&cur_time); - cur_time_tm = localtime(&cur_time); - - tc8521_internal_set(cur_time_tm); - - tc8521_set_nvrram(nvrram, cur_time_tm); -} - -void tc8521_get(uint8_t *nvrram) -{ - struct tm cur_time_tm; - - tc8521_internal_get(&cur_time_tm); - - tc8521_set_nvrram(nvrram, &cur_time_tm); -} diff --git a/src/rtc_tc8521.h b/src/rtc_tc8521.h deleted file mode 100644 index 61c822a..0000000 --- a/src/rtc_tc8521.h +++ /dev/null @@ -1,33 +0,0 @@ - -/* The TC8521 is a 4-bit RTC, so each memory location can only hold a single - * BCD digit. Hence everything has 'ones' and 'tens' digits. */ -enum TC8521_ADDR -{ - /* Page 0 registers */ - TC8521_SECOND1, - TC8521_SECOND10, - TC8521_MINUTE1, - TC8521_MINUTE10, - TC8521_HOUR1, - TC8521_HOUR10, - TC8521_WEEKDAY, - TC8521_DAY1, - TC8521_DAY10, - TC8521_MONTH1, - TC8521_MONTH10, - TC8521_YEAR1, - TC8521_YEAR10, - TC8521_PAGE, /* PAGE register */ - TC8521_TEST, /* TEST register */ - TC8521_RESET, /* RESET register */ - /* Page 1 registers */ - TC8521_24HR = 0x1A, - TC8521_LEAPYEAR = 0x1B -}; - - -void tc8521_tick(); -void tc8521_update(uint8_t *nvrram, int reg); -void tc8521_get(uint8_t *nvrram); -void tc8521_internal_set_nvrram(uint8_t *nvrram); -void tc8521_internal_sync(uint8_t *nvrram); diff --git a/src/sound/midi.c b/src/sound/midi.c index d952186..a777fe7 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -8,7 +8,7 @@ * * MIDI support module, main file. * - * Version: @(#)midi.c 1.0.1 2018/02/14 + * Version: @(#)midi.c 1.0.2 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,7 +44,6 @@ #include "../emu.h" #include "../device.h" #include "../plat.h" -#include "../plat_midi.h" #include "midi.h" #include "midi_system.h" #ifdef USE_FLUIDSYNTH diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index bfeac4e..10849c5 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -17,7 +17,7 @@ * website (for 32bit and 64bit Windows) are working, and * need no additional support files other than sound fonts. * - * Version: @(#)midi_fluidsynth.c 1.0.2 2018/02/24 + * Version: @(#)midi_fluidsynth.c 1.0.3 2018/03/10 * * Code borrowed from scummvm. * @@ -57,7 +57,6 @@ #include "../config.h" #include "../device.h" #include "../plat.h" -#include "../plat_dynld.h" #include "../ui.h" #include "midi.h" #include "midi_fluidsynth.h" diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index 1f0fd79..6031a25 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -8,7 +8,7 @@ * * Interface to system MIDI driver. * - * Version: @(#)midi_system.c 1.0.1 2018/02/14 + * Version: @(#)midi_system.c 1.0.2 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,7 +44,6 @@ #include "../emu.h" #include "../device.h" #include "../plat.h" -#include "../plat_midi.h" #include "midi.h" #include "midi_system.h" diff --git a/src/sound/openal.c b/src/sound/openal.c index f4e8be3..5024134 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -8,7 +8,7 @@ * * Interface to the OpenAL sound processing library. * - * Version: @(#)openal.c 1.0.3 2018/03/03 + * Version: @(#)openal.c 1.0.4 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,7 +53,6 @@ #endif #include "../emu.h" #include "../plat.h" -#include "../plat_dynld.h" #include "../ui.h" #include "sound.h" #include "midi.h" diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 70d5696..63f34d7 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.6 2018/03/05 + * Version: @(#)vid_table.c 1.0.7 2018/03/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -210,16 +210,16 @@ video_reset(int card) cga_palette = 0; cgapal_rebuild(); - /* Do not initialize internal cards here. */ - if ((card == GFX_NONE) || \ - (card == GFX_INTERNAL) || machines[machine].fixed_gfxcard) return; - /* Initialize the video font tables. */ loadfont(L"roms/video/ibm/mda/mda.rom", 0); loadfont(L"roms/video/wyse/wyse700/wy700.rom", 3); loadfont(L"roms/video/mdsi/genius/8x12.bin", 4); loadfont(FONT_ATIKOR_PATH, 6); + /* Do not initialize internal cards here. */ + if ((card == GFX_NONE) || \ + (card == GFX_INTERNAL) || machines[machine].fixed_gfxcard) return; + /* Initialize the video card. */ device_add(video_cards[video_old_to_new(card)].device); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 271365b..1ef0e00 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.9 2018/03/08 +# Version: @(#)Makefile.mingw 1.0.10 2018/03/11 # # Author: Fred N. van Kempen, # @@ -196,12 +196,12 @@ endif # Nothing should need changing from here on.. # ######################################################################### VPATH := $(EXPATH) . cpu \ - cdrom disk floppy game sio machine \ + cdrom disk floppy floppy/lzf game sio machine \ sound \ sound/munt sound/munt/c_interface sound/munt/sha1 \ sound/munt/srchelper \ sound/resid-fp \ - scsi video lzf network network/slirp win + scsi video network network/slirp win # # Select the required build environment. We have, uhm, many.. @@ -455,8 +455,8 @@ CXXFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ ######################################################################### 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 \ - rom_load.o device.o nvr.o nvr_tc8521.o rtc_tc8521.o \ - nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) + rom_load.o device.o nvr.o nvr_at.o nvr_ps2.o \ + $(VNCOBJ) $(RDPOBJ) INTELOBJ := intel.o \ intel_flash.o \ @@ -501,7 +501,7 @@ DEVOBJ := bugger.o lpt.o $(SERIAL) \ FDDOBJ := fdc.o \ fdd.o \ fdd_common.o fdd_86f.o \ - fdd_fdi.o fdi2raw.o \ + fdd_fdi.o fdi2raw.o lzf_c.o lzf_d.o \ fdd_imd.o fdd_img.o fdd_json.o fdd_td0.o HDDOBJ := hdd.o \ @@ -604,7 +604,6 @@ ifdef EXOBJ OBJ += $(EXOBJ) endif -LZFOBJ := lzf_c.o lzf_d.o LIBS := -mwindows \ -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ @@ -663,9 +662,9 @@ VARCem.res: VARCem.rc VARCem.mpp @echo Processing $< @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o VARCem.res -$(PROG).exe: $(OBJ) $(LZFOBJ) VARCem.res +$(PROG).exe: $(OBJ) VARCem.res @echo Linking $(PROG).exe .. - @$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) VARCem.res $(LIBS) + @$(CC) -o $(PROG).exe $(OBJ) VARCem.res $(LIBS) ifneq ($(DEBUG), y) @strip $(PROG).exe endif diff --git a/src/win/VARCem.rc b/src/win/VARCem.rc index 8065891..554c67a 100644 --- a/src/win/VARCem.rc +++ b/src/win/VARCem.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)VARCem.rc 1.0.6 2018/03/08 + * Version: @(#)VARCem.rc 1.0.7 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -980,7 +980,7 @@ BEGIN IDS_2168 "&Image..." IDS_2169 "Image (&Write-protected)..." IDS_2170 "Check BPB" - IDS_2171 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your program folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll" + IDS_2171 "Unable to initialize FluidSynth, make sure you have the following library\nin your program folder:\n\nlibfluidsynth.dll" IDS_2172 "E&xport to 86F..." IDS_2173 "Surface images (*.86F)\0*.86F\0" IDS_2174 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" diff --git a/src/win/win.c b/src/win/win.c index 6684dea..11fb66d 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.6 2018/03/08 + * Version: @(#)win.c 1.0.7 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,7 +53,6 @@ #include "../video/video.h" #define GLOBAL #include "../plat.h" -#include "../plat_midi.h" #include "../ui.h" #ifdef USE_VNC # include "../vnc.h" diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 4913dcf..e84c6ff 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -8,7 +8,7 @@ * * Imlementation of the Device Configuration dialog. * - * Version: @(#)win_devconf.c 1.0.3 2018/03/07 + * Version: @(#)win_devconf.c 1.0.4 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,7 +48,6 @@ #include "../config.h" #include "../device.h" #include "../plat.h" -#include "../plat_midi.h" #include "../ui.h" #include "win.h" diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 1767f28..fa99aee 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -8,7 +8,7 @@ * * Try to load a support DLL. * - * Version: @(#)win_dynld.c 1.0.2 2018/03/07 + * Version: @(#)win_dynld.c 1.0.3 2018/03/10 * * Authors: Fred N. van Kempen, * @@ -52,7 +52,7 @@ #include #include #include "../emu.h" -#include "../plat_dynld.h" +#include "../plat.h" void * diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index 9f724d8..3189f32 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -11,7 +11,7 @@ * NOTE: Hacks currently needed to compile with MSVC; DX needs to * be updated to 11 or 12 or so. --FvK * - * Version: @(#)win_joystick.cpp 1.0.4 2018/03/08 + * Version: @(#)win_joystick.cpp 1.0.5 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,9 +53,8 @@ #include #include "../emu.h" #include "../device.h" -#include "../plat.h" #include "../game/gameport.h" -#include "../plat_joystick.h" +#include "../plat.h" #include "win.h" diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index 3dce169..b14ea7a 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -8,7 +8,7 @@ * * Implementation of the Joystick Configuration dialog. * - * Version: @(#)win_jsconf.c 1.0.2 2018/03/07 + * Version: @(#)win_jsconf.c 1.0.3 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,7 +48,6 @@ #include "../device.h" #include "../game/gameport.h" #include "../plat.h" -#include "../plat_joystick.h" #include "win.h" diff --git a/src/win/win_midi.c b/src/win/win_midi.c index a5337e4..ca3c278 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -8,7 +8,7 @@ * * Implementation of the System MIDI interface. * - * Version: @(#)win_midi.c 1.0.2 2018/03/07 + * Version: @(#)win_midi.c 1.0.3 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,7 +47,6 @@ #include "../config.h" #include "../sound/midi.h" #include "../plat.h" -#include "../plat_midi.h" #include "win.h" diff --git a/src/win/win_settings.c b/src/win/win_settings.c index e7e91bc..3238286 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings.c 1.0.8 2018/03/08 + * Version: @(#)win_settings.c 1.0.9 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -70,7 +70,6 @@ #include "../video/video.h" #include "../video/vid_voodoo.h" #include "../plat.h" -#include "../plat_midi.h" #include "../ui.h" #include "win.h" diff --git a/src/win/win_ui.c b/src/win/win_ui.c index ee63266..4126047 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * Implement the user Interface module. * - * Version: @(#)win_ui.c 1.0.4 2018/03/07 + * Version: @(#)win_ui.c 1.0.5 2018/03/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,9 +51,8 @@ #include "../keyboard.h" #include "../mouse.h" #include "../video/video.h" -#include "../video/vid_ega.h" // for update_overscan +#include "../video/vid_ega.h" /* for update_overscan */ #include "../plat.h" -#include "../plat_midi.h" #include "../ui.h" #include "win.h" #include "win_d3d.h"