This repository has been archived on 2025-05-24. You can view files and clone it, but cannot push or open issues or pull requests.
Files
VARCem/src/machines/m_europc.c

817 lines
21 KiB
C
Raw Normal View History

2018-02-20 21:44:51 -05:00
/*
2018-03-08 15:58:46 -05:00
* VARCem Virtual ARchaeological Computer EMulator.
2018-02-20 21:44:51 -05:00
* 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 Schneider EuroPC system.
*
* NOTES: BIOS info (taken from MAME, thanks guys!!)
*
* f000:e107 bios checksum test
* memory test
* f000:e145 irq vector init
* f000:e156
* f000:e169-d774 test of special registers 254/354
* f000:e16c-e817
* f000:e16f
* f000:ec08 test of special registers 800a rtc time
* or date error, rtc corrected
* f000:ef66 0xf
* f000:db3e 0x8..0xc
* f000:d7f8
* f000:db5f
* f000:e172
* f000:ecc5 801a video setup error
* f000:d6c9 copyright output
* f000:e1b7
* f000:e1be DI bits set mean output text!!! (801a)
2018-02-20 21:44:51 -05:00
* f000: 0x8000 output
* 1 rtc error
* 2 rtc time or date error
* 4 checksum error in setup
* 8 rtc status corrected
* 10 video setup error
* 20 video ram bad
* 40 monitor type not recogniced
* 80 mouse port enabled
* 100 joystick port enabled
* f000:e1e2-dc0c CPU speed is 4.77 mhz
* f000:e1e5-f9c0 keyboard processor error
* f000:e1eb-c617 external LPT1 at 0x3bc
2018-02-20 21:44:51 -05:00
* f000:e1ee-e8ee external coms at
*
* Routines:
* f000:c92d output text at bp
* f000:db3e RTC read reg cl
* f000:e8ee piep
* f000:e95e RTC write reg cl
* polls until JIM 0xa is zero,
* 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
2018-02-20 21:44:51 -05:00
* 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
*
* Memory:
* 0000:0469 bit 0: b0000 memory available
2018-02-20 21:44:51 -05:00
* bit 1: b8000 memory available
* 0000:046a: 00 jim 250 01 jim 350
2018-02-20 21:44:51 -05:00
*
2018-10-06 18:20:09 -04:00
* FIXME: Find a new way to handle the switching of color/mono on
* external cards. New video_get_type(int card) function?
*
* Version: @(#)m_europc.c 1.0.23 2019/04/29
2018-02-20 21:44:51 -05:00
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Inspired by the "jim.c" file originally present, but a
* fully re-written module, based on the information from
* Schneider's schematics and technical manuals, and the
* input from people with real EuroPC hardware.
*
* Copyright 2017-2019 Fred N. van Kempen.
2018-02-20 21:44:51 -05:00
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
2018-10-06 18:20:09 -04:00
#include <string.h>
2018-02-20 21:44:51 -05:00
#include <wchar.h>
#include <time.h>
2018-02-20 21:44:51 -05:00
#include "../emu.h"
#include "../cpu/cpu.h"
2018-02-20 21:44:51 -05:00
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
2018-10-06 18:20:09 -04:00
#include "../nvr.h"
#include "../devices/system/pit.h"
#include "../devices/system/nmi.h"
#include "../devices/ports/parallel.h"
#include "../devices/input/keyboard.h"
#include "../devices/input/mouse.h"
#include "../devices/floppy/fdd.h"
#include "../devices/floppy/fdc.h"
#include "../devices/disk/hdc.h"
#include "../devices/video/video.h"
2018-02-20 21:44:51 -05:00
#include "machine.h"
/* M3002 RTC chip registers. */
#define MRTC_SECONDS 0x00 /* BCD, 00-59 */
#define MRTC_MINUTES 0x01 /* BCD, 00-59 */
#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 (year only) */
2018-02-20 21:44:51 -05:00
#define MRTC_WEEKDAY 0x06 /* BCD, 01-07 */
#define MRTC_WEEKNO 0x07 /* BCD, 01-52 */
#define MRTC_CONF_A 0x08 /* EuroPC config, binary */
#define MRTC_CONF_B 0x09 /* EuroPC config, binary */
#define MRTC_CONF_C 0x0a /* EuroPC config, binary */
#define MRTC_CONF_D 0x0b /* EuroPC config, binary */
#define MRTC_CONF_E 0x0c /* EuroPC config, binary */
#define MRTC_CHECK_LO 0x0d /* Checksum, low byte */
#define MRTC_CHECK_HI 0x0e /* Checksum, high byte */
#define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */
2018-10-06 18:20:09 -04:00
2018-02-20 21:44:51 -05:00
typedef struct {
uint16_t jim; /* JIM base address */
uint8_t regs[16]; /* JIM internal regs (8) */
nvr_t nvr; /* NVR */
uint8_t nvr_stat;
uint8_t nvr_addr;
} europc_t;
2018-02-20 21:44:51 -05:00
/*
* 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
2018-10-06 18:20:09 -04:00
rtc_ticker(nvr_t *nvr)
2018-02-20 21:44:51 -05:00
{
uint8_t *regs;
int mon, yr;
/* Only if RTC is running.. */
regs = nvr->regs;
if (! (regs[MRTC_CTRLSTAT] & 0x01)) return;
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;
}
}
}
}
2018-02-20 21:44:51 -05:00
}
}
/* Get the current NVR time. */
static void
rtc_time_get(uint8_t *regs, struct tm *tm)
2018-02-20 21:44:51 -05:00
{
/* 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]);
2018-10-06 18:20:09 -04:00
#ifdef MRTC_CENTURY
tm->tm_year += (RTC_DCB(regs[MRTC_CENTURY]) * 100) - 1900;
#endif
}
2018-02-20 21:44:51 -05:00
/* 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);
2018-10-06 18:20:09 -04:00
#ifdef MRTC_CENTURY
regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year+1900) / 100);
#endif
2018-02-20 21:44:51 -05:00
}
static void
rtc_start(nvr_t *nvr)
2018-02-20 21:44:51 -05:00
{
struct tm tm;
/* Initialize the internal and chip times. */
2018-10-06 18:20:09 -04:00
if (time_sync != TIME_SYNC_DISABLED) {
/* 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);
2018-02-20 21:44:51 -05:00
}
}
/* 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)
2018-02-20 21:44:51 -05:00
{
/* 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 */
2018-02-20 21:44:51 -05:00
/*
* EuroPC System Configuration:
*
* [A] unknown
*
* [B] 7 1 bootdrive extern
* 0 bootdrive 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 720K
* 01 internal drive 360K
* 00 internal drive disabled
*
* [C] 7:6 unknown
* 5 monitor detection OFF
* 4 unknown
* 3:2 11 illegal memory size (768K ?)
* 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);
2018-02-20 21:44:51 -05:00
}
/* Execute a JIM control command. */
static void
jim_set(europc_t *dev, uint8_t reg, uint8_t val)
2018-02-20 21:44:51 -05:00
{
switch(reg) {
case 0: /* MISC control (WO) */
2018-10-06 18:20:09 -04:00
/* bit0: enable MOUSE */
/* bit1: enable joystick */
2018-02-20 21:44:51 -05:00
break;
case 2: /* AGA control */
if (! (val & 0x80)) {
/* Reset AGA. */
break;
}
switch (val) {
case 0x1f: /* 0001 1111 */
case 0x0b: /* 0000 1011 */
2018-10-06 18:20:09 -04:00
/*europc_jim.mode=AGA_MONO; */
DEBUG("EuroPC: AGA Monochrome mode!\n");
2018-02-20 21:44:51 -05:00
break;
case 0x18: /* 0001 1000 */
case 0x1a: /* 0001 1010 */
2018-10-06 18:20:09 -04:00
/*europc_jim.mode=AGA_COLOR; */
2018-02-20 21:44:51 -05:00
break;
case 0x0e: /* 0000 1100 */
/*80 columns? */
2018-10-06 18:20:09 -04:00
DEBUG("EuroPC: AGA 80-column mode!\n");
2018-02-20 21:44:51 -05:00
break;
case 0x0d: /* 0000 1011 */
/*40 columns? */
2018-10-06 18:20:09 -04:00
DEBUG("EuroPC: AGA 40-column mode!\n");
2018-02-20 21:44:51 -05:00
break;
default:
2018-10-06 18:20:09 -04:00
/*europc_jim.mode=AGA_OFF; */
2018-02-20 21:44:51 -05:00
break;
}
break;
case 4: /* CPU Speed control */
switch(val & 0xc0) {
case 0x00: /* 4.77 MHz */
2018-10-06 18:20:09 -04:00
/*FIXME: cpu_set_clockscale(0, 1.0/2); */
2018-02-20 21:44:51 -05:00
break;
case 0x40: /* 7.16 MHz */
2018-10-06 18:20:09 -04:00
/*FIXME: cpu_set_clockscale(0, 3.0/4); */
2018-02-20 21:44:51 -05:00
break;
default: /* 9.54 MHz */
2018-10-06 18:20:09 -04:00
/*FIXME: cpu_set_clockscale(0, 1);break; */
2018-02-20 21:44:51 -05:00
break;
}
break;
default:
break;
}
dev->regs[reg] = val;
2018-02-20 21:44:51 -05:00
}
/* Write to one of the JIM registers. */
static void
jim_write(uint16_t addr, uint8_t val, void *priv)
{
europc_t *dev = (europc_t *)priv;
2018-02-20 21:44:51 -05:00
uint8_t b;
2018-10-06 18:20:09 -04:00
DBGLOG(2, "EuroPC: jim_wr(%04x, %02x)\n", addr, val);
2018-02-20 21:44:51 -05:00
switch (addr & 0x000f) {
case 0x00: /* JIM internal registers (WRONLY) */
case 0x01:
case 0x02:
case 0x03:
case 0x04: /* JIM internal registers (R/W) */
case 0x05:
case 0x06:
case 0x07:
jim_set(dev, (addr & 0x07), val);
2018-02-20 21:44:51 -05:00
break;
case 0x0a: /* M3002 RTC INDEX/DATA register */
switch(dev->nvr_stat) {
2018-02-20 21:44:51 -05:00
case 0: /* save index */
dev->nvr_addr = val & 0x0f;
dev->nvr_stat++;
2018-02-20 21:44:51 -05:00
break;
case 1: /* save data HI nibble */
b = dev->nvr.regs[dev->nvr_addr] & 0x0f;
2018-02-20 21:44:51 -05:00
b |= (val << 4);
dev->nvr.regs[dev->nvr_addr] = b;
dev->nvr_stat++;
nvr_dosave++;
2018-02-20 21:44:51 -05:00
break;
case 2: /* save data LO nibble */
b = dev->nvr.regs[dev->nvr_addr] & 0xf0;
2018-02-20 21:44:51 -05:00
b |= (val & 0x0f);
dev->nvr.regs[dev->nvr_addr] = b;
dev->nvr_stat = 0;
nvr_dosave++;
2018-02-20 21:44:51 -05:00
break;
}
break;
default:
2018-10-06 18:20:09 -04:00
ERRLOG("EuroPC: invalid JIM write %02x, val %02x\n", addr, val);
2018-02-20 21:44:51 -05:00
break;
}
}
/* Read from one of the JIM registers. */
static uint8_t
jim_read(uint16_t addr, void *priv)
{
europc_t *dev = (europc_t *)priv;
2018-02-20 21:44:51 -05:00
uint8_t r = 0xff;
switch (addr & 0x000f) {
case 0x00: /* JIM internal registers (WRONLY) */
case 0x01:
case 0x02:
case 0x03:
r = 0x00;
break;
case 0x04: /* JIM internal registers (R/W) */
case 0x05:
case 0x06:
case 0x07:
r = dev->regs[addr & 0x07];
2018-02-20 21:44:51 -05:00
break;
case 0x0a: /* M3002 RTC INDEX/DATA register */
switch(dev->nvr_stat) {
2018-02-20 21:44:51 -05:00
case 0:
r = 0x00;
break;
case 1: /* read data HI nibble */
r = (dev->nvr.regs[dev->nvr_addr] >> 4);
dev->nvr_stat++;
2018-02-20 21:44:51 -05:00
break;
case 2: /* read data LO nibble */
r = (dev->nvr.regs[dev->nvr_addr] & 0x0f);
dev->nvr_stat = 0;
2018-02-20 21:44:51 -05:00
break;
}
break;
default:
2018-10-06 18:20:09 -04:00
ERRLOG("EuroPC: invalid JIM read %02x\n", addr);
2018-02-20 21:44:51 -05:00
break;
}
2018-10-06 18:20:09 -04:00
DBGLOG(2, "EuroPC: jim_rd(%04x): %02x\n", addr, r);
2018-02-20 21:44:51 -05:00
return(r);
}
/*
* Initialize the mainboard 'device' of the machine.
*
* Its task is to allocate a clean machine data block,
* and then simply enable the mainboard "device" which
* allows it to reset (dev init) and configured by the
* user.
*/
2018-02-20 21:44:51 -05:00
static void *
europc_init(const device_t *info, void *arg)
2018-02-20 21:44:51 -05:00
{
europc_t *dev;
void *priv;
2018-02-20 21:44:51 -05:00
uint8_t b;
int i;
/* Clear the machine state. */
dev = (europc_t *)mem_alloc(sizeof(europc_t));
memset(dev, 0x00, sizeof(europc_t));
2018-02-20 21:44:51 -05:00
/* Add the machine device. */
device_add_ex(info, dev);
/* Get configurable things. */
i = machine_get_config_int("js9");
dev->jim = (i == 1) ? 0x0350 : 0x0250;
/* Set up and initialize the NVR. */
dev->nvr.size = machine_get_nvrsize();
dev->nvr.irq = -1;
dev->nvr.reset = rtc_reset;
dev->nvr.start = rtc_start;
dev->nvr.tick = rtc_ticker;
nvr_init(&dev->nvr);
2018-02-20 21:44:51 -05:00
2018-10-06 18:20:09 -04:00
/*
* This is not quite correct, but it works.
*
* The EuroPC has an onboard CGA-class video controller
* (AGA) which is normally used. We currently do not yet
* support it. To keep the NVRAM valid, however, we act
* like we have it configured.
*/
if (video_card == VID_INTERNAL) {
INFO("EuroPC: enabling CGA in place of AGA!\n");
device_add(&cga_device);
}
DEBUG("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n",
dev->nvr.regs[MRTC_CONF_A], dev->nvr.regs[MRTC_CONF_B],
dev->nvr.regs[MRTC_CONF_C], dev->nvr.regs[MRTC_CONF_D],
dev->nvr.regs[MRTC_CONF_E],
(dev->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(dev->nvr.regs))?"IN":"");
2018-02-20 21:44:51 -05:00
/*
* 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 = (dev->nvr.regs[MRTC_CONF_D] & ~0x17);
2018-10-06 18:20:09 -04:00
if (video_card != VID_INTERNAL) {
/*
* OK, this is not exactly correct, either.
*
* If we use an external video card, that will not be
* installed until after we boot the mainboard, so we
* do not know about it yet. Therefore, we just peek
* at the configured video card type, and perform an
* "educated guess" as to its type..
*/
switch(video_card) {
case VID_MDA: /* MDA */
case VID_HERCULES: /* Hercules */
b |= 0x03; /* external video, mono */
break;
2018-02-20 21:44:51 -05:00
2018-10-06 18:20:09 -04:00
case VID_CGA: /* Color, CGA */
b |= 0x12; /* external video, CGA80 */
break;
default: /* all others */
b |= 0x10; /* external video, special */
}
} else {
i = video_type();
switch(i) {
2018-10-06 18:20:09 -04:00
case VID_TYPE_MDA: /* Monochrome, MDA, Hercules */
b |= 0x03; /* external video, mono */
break;
2018-02-20 21:44:51 -05:00
2018-10-06 18:20:09 -04:00
case VID_TYPE_CGA: /* Color, CGA */
b |= 0x12; /* external video, CGA80 */
break;
2018-02-20 21:44:51 -05:00
2018-10-06 18:20:09 -04:00
case VID_TYPE_SPEC: /* EGA, VGA etc */
b |= 0x10; /* external video, special */
break;
default:
ERRLOG("EuroPC: unknown video type %i !\n", i);
2018-10-06 18:20:09 -04:00
break;
}
2018-02-20 21:44:51 -05:00
}
dev->nvr.regs[MRTC_CONF_D] = b;
2018-02-20 21:44:51 -05:00
/* Update the memory size. */
b = (dev->nvr.regs[MRTC_CONF_C] & 0xf3);
2018-02-20 21:44:51 -05:00
switch(mem_size) {
case 256:
b |= 0x04;
break;
case 512:
b |= 0x08;
break;
case 640:
b |= 0x00;
break;
}
dev->nvr.regs[MRTC_CONF_C] = b;
2018-02-20 21:44:51 -05:00
/* Update CPU speed. */
b = (dev->nvr.regs[MRTC_CONF_D] & 0x3f);
switch(cpu_type) {
2018-02-20 21:44:51 -05:00
case 0: /* 8088, 4.77 MHz */
b |= 0x00;
break;
case 1: /* 8088, 7.15 MHz */
b |= 0x40;
break;
case 2: /* 8088, 9.56 MHz */
b |= 0x80;
break;
}
dev->nvr.regs[MRTC_CONF_D] = b;
2018-02-20 21:44:51 -05:00
/* Set up game port. */
b = (dev->nvr.regs[MRTC_CONF_C] & 0xfc);
if (mouse_type == MOUSE_INTERNAL) {
/* Enable the Logitech Bus Mouse device. */
priv = device_add(&mouse_logibus_onboard_device);
mouse_bus_set_irq(priv, 2);
/* Configure the port for (Bus Mouse Compatible) Mouse. */
b |= 0x01;
} else if (game_enabled) {
2018-02-20 21:44:51 -05:00
b |= 0x02; /* enable port as joysticks */
}
dev->nvr.regs[MRTC_CONF_C] = b;
2018-02-20 21:44:51 -05:00
/* Set up hard disks. */
b = dev->nvr.regs[MRTC_CONF_B] & 0x84;
if (hdc_type != HDC_NONE)
b |= 0x20; /* HD20 #1 */
2018-02-20 21:44:51 -05:00
/* Set up floppy types. */
if (fdd_get_type(0) != 0) {
/* We have floppy A: */
if (fdd_is_dd(0)) {
if (fdd_is_525(0))
b |= 0x01; /* 5.25" DD */
else
b |= 0x02; /* 3.5" DD */
} else
2018-10-06 18:20:09 -04:00
ERRLOG("EuroPC: unsupported HD type for floppy drive 0\n");
}
if (fdd_get_type(1) != 0) {
/* We have floppy B: */
if (fdd_is_dd(1)) {
b |= 0x04; /* EXTERNAL */
if (fdd_is_525(1))
b |= 0x08; /* 5.25" DD */
else
b |= 0x10; /* 3.5" DD */
} else
2018-10-06 18:20:09 -04:00
ERRLOG("EuroPC: unsupported HD type for floppy drive 1\n");
}
dev->nvr.regs[MRTC_CONF_B] = b;
2018-02-20 21:44:51 -05:00
/* Validate the NVR checksum and save. */
dev->nvr.regs[MRTC_CHECK_LO] = rtc_checksum(dev->nvr.regs);
nvr_dosave++;
2018-02-20 21:44:51 -05:00
machine_common_init();
nmi_init();
pit_set_out_func(&pit, 1, pit_refresh_timer_xt);
2018-02-20 21:44:51 -05:00
/*
* Allocate the system's I/O handlers.
*
* The first one is for the JIM. Note that although JIM usually
* resides at 0x0250, a special solder jumper on the mainboard
* (JS9) can be used to "move" it to 0x0350, to get it out of
* the way of other cards that need this range.
*/
io_sethandler(dev->jim, 16,
jim_read,NULL,NULL, jim_write,NULL,NULL, dev);
2018-02-20 21:44:51 -05:00
/* Only after JIM has been initialized. */
device_add(&keyboard_xt_device);
2018-02-20 21:44:51 -05:00
/* Enable and set up the FDC. */
device_add(&fdc_xt_device);
2018-02-20 21:44:51 -05:00
/*
* Set up and enable the HD20 disk controller.
*
* We only do this if we have not configured another one.
*/
2018-10-06 18:20:09 -04:00
if (hdc_type == HDC_INTERNAL)
(void)device_add(&xta_hd20_device);
2018-02-20 21:44:51 -05:00
return(dev);
2018-02-20 21:44:51 -05:00
}
static void
europc_close(void *priv)
{
europc_t *dev = (europc_t *)priv;
nvr_t *nvr = &dev->nvr;
2018-02-20 21:44:51 -05:00
if (nvr->fn != NULL) {
free((wchar_t *)nvr->fn);
nvr->fn = NULL;
}
free(dev);
2018-02-20 21:44:51 -05:00
}
static const device_config_t europc_config[] = {
2018-02-20 21:44:51 -05:00
{
"js9", "JS9 Jumper (JIM)", CONFIG_INT, "", 0,
{
{
"Disabled (250h)", 0
},
{
"Enabled (350h)", 1
},
{
NULL
2018-02-20 21:44:51 -05:00
}
},
},
{
NULL
2018-02-20 21:44:51 -05:00
}
};
static const CPU cpus_europc[] = {
{ "8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 },
{ "8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1 },
{ "8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1 },
{ NULL }
};
static const machine_t europc_info = {
MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE,
2018-10-06 18:20:09 -04:00
0,
512, 640, 128, 16, 0,
{{"Siemens",cpus_europc}}
};
const device_t m_europc = {
"Schneider EuroPC",
DEVICE_ROOT,
2018-10-06 18:20:09 -04:00
0,
L"schneider/europc",
europc_init, europc_close, NULL,
NULL, NULL, NULL,
&europc_info,
2018-02-20 21:44:51 -05:00
europc_config
};