Merge branch '86Box:master' into master

This commit is contained in:
starfrost
2025-05-17 20:11:17 +01:00
committed by GitHub
30 changed files with 1551 additions and 420 deletions

View File

@@ -72,6 +72,7 @@ add_library(chipset OBJECT
sis_5572_usb.c
sis_5595_pmu.c
sis_55xx.c
sl82c461.c
via_vt82c49x.c
via_vt82c505.c
gc100.c

View File

@@ -1656,7 +1656,12 @@ i4x0_init(const device_t *info)
regs[0x57] = 0x31;
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02;
dev->max_drb = 3;
/* At the very least the 420ZX seems to read to 0x64, per the SB486PV. */
if (dev->type == INTEL_420ZX) {
regs[0x64] = 0x02;
dev->max_drb = 4;
} else
dev->max_drb = 3;
dev->drb_unit = 1;
dev->drb_default = 0x02;
break;

362
src/chipset/sl82c461.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Symphony SL82C461 (Haydn II) chipset.
*
* Symphony SL82C461 Configuration Registers (WARNING: May be inaccurate!):
*
* - Register 00h:
* - Bit 6: External cache present (if clear, AMI BIOS'es will not
* allow enabling external cache).
*
* - Register 01h:
* - Bit 0: Fast Gate A20 Enable (Handler mostly).
* Is it? Enabling/disabling fast gate A20 doesn't appear
* to do much to any register at all.
*
* - Register 02h:
* - Bit 0: Optional Chipset Turbo Pin;
* - Bits 4-2:
* - 000 = CLK2/3;
* - 001 = CLK2/4;
* - 010 = CLK2/5;
* - 011 = 7.159 MHz (ATCLK2);
* - 100 = CLK2/6;
* - 110 = CLK2/2.5;
* - 111 = CLK2/2.
*
* - Register 06h:
* - Bit 2: Decoupled Refresh Option.
*
* - Register 08h:
* - Bits 3, 2: I/O Recovery Time (SYSCLK):
* - 0, 0 = 0;
* - 1, 1 = 12.
* - Bit 1: Extended ALE.
*
* - Register 25h:
* Bit 7 here causes AMI 111192 CMOS Setup to return 7168 KB RAM
* instead of 6912 KB. This is 256 KB off. Relocation?
* Also, returning bit 5 clear instead of set, causes the AMI BIOS
* to set bits 0,1 of register 45h to 1,0 instead of 0,1.
*
* - Register 2Dh:
* - Bit 7: Enable 256KB Memory Relocation;
* - Bit 6: Enable 384KB Memory Relocation, bit 7 must also be set.
*
* - Register 2Eh:
* - Bit 7: CC000-CFFFF Shadow Read Enable;
* - Bit 6: CC000-CFFFF Shadow Write Enable;
* - Bit 5: C8000-CBFFF Shadow Read Enable;
* - Bit 4: C8000-CBFFF Shadow Write Enable;
* - Bit 3: C4000-C7FFF Shadow Read Enable;
* - Bit 2: C4000-C7FFF Shadow Write Enable;
* - Bit 1: C0000-C3FFF Shadow Read Enable;
* - Bit 0: C0000-C3FFF Shadow Write Enable.
*
* - Register 2Fh:
* - Bit 7: DC000-DFFFF Shadow Read Enable;
* - Bit 6: DC000-DFFFF Shadow Write Enable;
* - Bit 5: D8000-DBFFF Shadow Read Enable;
* - Bit 4: D8000-DBFFF Shadow Write Enable;
* - Bit 3: D4000-D7FFF Shadow Read Enable;
* - Bit 2: D4000-D7FFF Shadow Write Enable;
* - Bit 1: D0000-D3FFF Shadow Read Enable;
* - Bit 0: D0000-D3FFF Shadow Write Enable.
*
* - Register 30h:
* - Bit 7: E0000-EFFFF Shadow Read Enable;
* - Bit 6: E0000-EFFFF Shadow Write Enable.
*
* - Register 31h:
* - Bit 7: F0000-FFFFF Shadow Read Enable;
* - Bit 6: F0000-FFFFF Shadow Write Enable.
*
* - Register 33h (NOTE: Waitstates also affect register 32h):
* - Bits 3, 0:
* - 0,0 = 0 W/S;
* - 1,0 = 1 W/S;
* - 1,1 = 2 W/S.
*
* - Register 40h:
* - Bit 3: External Cache Enabled (0 = yes, 1 = no);
* I also see bits 5, 4, 3 of register 44h affected:
* - 38h (so all 3 set) when cache is disabled;
* - 00h (all 3 clear) when it's enabled.
*
* - Register 45h:
* - Bit 3: Video Shadow RAM Cacheable;
* - Bit 4: Adapter Shadow RAM Cacheable;
* - Bit 5: BIOS Shadow RAM Cacheable.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
* Copyright 2025 Miran Grca.
* Copyright 2021-2025 Tiseno100.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/chipset.h>
typedef struct {
uint8_t index;
uint8_t regs[256];
uint8_t shadow[4];
} sl82c461_t;
#ifdef ENABLE_SL82C461_LOG
int sl82c461_do_log = ENABLE_SL82C461_LOG;
static void
sl82c461_log(const char *fmt, ...)
{
va_list ap;
if (sl82c461_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define sl82c461_log(fmt, ...)
#endif
static void
sl82c461_recalcmapping(sl82c461_t *dev)
{
int do_shadow = 0;
for (uint32_t i = 0; i < 8; i += 2) {
if ((dev->regs[0x2e] ^ dev->shadow[0x00]) & (3 << i)) {
uint32_t base = 0x000c0000 + ((i >> 1) << 14);
uint32_t read = ((dev->regs[0x2e] >> i) & 0x02) ? MEM_READ_INTERNAL :
MEM_READ_EXTANY;
uint32_t write = ((dev->regs[0x2e] >> i) & 0x01) ? MEM_WRITE_INTERNAL :
MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x00004000, read | write);
do_shadow++;
}
if ((dev->regs[0x2f] ^ dev->shadow[0x01]) & (3 << i)) {
uint32_t base = 0x000d0000 + ((i >> 1) << 14);
uint32_t read = ((dev->regs[0x2f] >> i) & 0x02) ? MEM_READ_INTERNAL :
MEM_READ_EXTANY;
uint32_t write = ((dev->regs[0x2f] >> i) & 0x01) ? MEM_WRITE_INTERNAL :
MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x00004000, read | write);
do_shadow++;
}
}
if ((dev->regs[0x30] ^ dev->shadow[0x02]) & 0xc0) {
uint32_t base = 0x000e0000;
uint32_t read = ((dev->regs[0x30] >> 6) & 0x02) ? MEM_READ_INTERNAL :
MEM_READ_EXTANY;
uint32_t write = ((dev->regs[0x30] >> 6) & 0x01) ? MEM_WRITE_INTERNAL :
MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x00010000, read | write);
do_shadow++;
}
if ((dev->regs[0x31] ^ dev->shadow[0x03]) & 0xc0) {
uint32_t base = 0x000f0000;
uint32_t read = ((dev->regs[0x31] >> 6) & 0x02) ? MEM_READ_INTERNAL :
MEM_READ_EXTANY;
uint32_t write = ((dev->regs[0x31] >> 6) & 0x01) ? MEM_WRITE_INTERNAL :
MEM_WRITE_EXTANY;
shadowbios = !!((dev->regs[0x31] >> 6) & 0x02);
shadowbios_write = !!((dev->regs[0x31] >> 6) & 0x01);
mem_set_mem_state_both(base, 0x00010000, read | write);
do_shadow++;
}
if (do_shadow) {
memcpy(dev->shadow, &(dev->regs[0x2e]), 4 * sizeof(uint8_t));
flushmmucache_nopc();
}
}
static void
sl82c461_write(uint16_t addr, uint8_t val, void *priv)
{
sl82c461_t *dev = (sl82c461_t *) priv;
sl82c461_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
if (addr & 0x0001) {
dev->regs[dev->index] = val;
switch (dev->index) {
case 0x01:
/* NOTE: This is to be verified. */
mem_a20_alt = val & 1;
mem_a20_recalc();
break;
case 0x02: {
double bus_clk;
switch (val & 0x1c) {
case 0x00:
bus_clk = cpu_busspeed / 3.0;
break;
case 0x04:
bus_clk = cpu_busspeed / 4.0;
break;
case 0x08:
bus_clk = cpu_busspeed / 5.0;
break;
default:
case 0x0c:
bus_clk = 7159091.0;
break;
case 0x10:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x18:
bus_clk = cpu_busspeed / 2.5;
break;
case 0x1c:
bus_clk = cpu_busspeed / 2.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
} case 0x2d:
switch (val & 0xc0) {
case 0xc0:
mem_remap_top(384);
break;
case 0x80:
mem_remap_top(256);
break;
default:
case 0x00:
mem_remap_top(0);
break;
}
break;
case 0x2e ... 0x31:
sl82c461_recalcmapping(dev);
break;
case 0x33:
switch (val & 0x09) {
default:
case 0x00:
cpu_waitstates = 0;
break;
case 0x08:
cpu_waitstates = 1;
break;
case 0x09:
cpu_waitstates = 2;
break;
}
cpu_update_waitstates();
break;
case 0x40:
cpu_cache_ext_enabled = !(val & 0x08);
cpu_update_waitstates();
break;
}
} else
dev->index = val;
}
static uint8_t
sl82c461_read(uint16_t addr, void *priv)
{
sl82c461_t *dev = (sl82c461_t *) priv;
uint8_t ret = 0x00;
if (addr & 0x0001)
if (dev->index == 0x00)
ret = dev->regs[dev->index] | 0x40;
else
ret = dev->regs[dev->index];
else
ret = dev->index;
sl82c461_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
return ret;
}
static void
sl82c461_close(void *priv)
{
sl82c461_t *dev = (sl82c461_t *) priv;
free(dev);
}
static void *
sl82c461_init(const device_t *info)
{
sl82c461_t *dev = (sl82c461_t *) calloc(1, sizeof(sl82c461_t));
dev->regs[0x00] = 0x40;
dev->regs[0x02] = 0x0c;
dev->regs[0x40] = 0x08;
memset(dev->shadow, 0xff, 4 * sizeof(uint8_t));
mem_a20_alt = 0x00;
mem_a20_recalc();
cpu_set_isa_speed(7159091.0);
sl82c461_recalcmapping(dev);
cpu_waitstates = 0;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
io_sethandler(0x00a8, 2,
sl82c461_read, NULL, NULL,
sl82c461_write, NULL, NULL, dev);
return dev;
}
const device_t sl82c461_device = {
.name = "Symphony SL82C461 (Haydn II)",
.internal_name = "sis_85c471",
.flags = 0,
.local = 0,
.init = sl82c461_init,
.close = sl82c461_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -24,14 +24,16 @@
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct vl82c480_t {
uint8_t idx;
uint8_t regs[256];
uint8_t idx;
uint8_t regs[256];
uint32_t banks[4];
} vl82c480_t;
static int
@@ -59,7 +61,7 @@ vl82c480_shflags(uint8_t access)
}
static void
vl82c480_recalc(vl82c480_t *dev)
vl82c480_recalc_shadow(vl82c480_t *dev)
{
uint32_t base;
uint8_t access;
@@ -69,8 +71,8 @@ vl82c480_recalc(vl82c480_t *dev)
for (uint8_t i = 0; i < 6; i++) {
for (uint8_t j = 0; j < 8; j += 2) {
base = 0x000a0000 + (i << 16) + (j << 13);
access = (dev->regs[0x0d + i] >> j) & 3;
base = 0x000a0000 + (i << 16) + (j << 13);
access = (dev->regs[0x0d + i] >> j) & 3;
mem_set_mem_state(base, 0x4000, vl82c480_shflags(access));
shadowbios |= ((base >= 0xe0000) && (access & 0x02));
shadowbios_write |= ((base >= 0xe0000) && (access & 0x01));
@@ -80,6 +82,37 @@ vl82c480_recalc(vl82c480_t *dev)
flushmmucache();
}
static void
vl82c480_recalc_banks(vl82c480_t *dev)
{
uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 };
uint8_t shifts[4] = { 0, 4, 0, 4 };
uint8_t regs[4] = { 0x02, 0x02, 0x03, 0x03 };
uint32_t total = 0;
for (uint8_t i = 0; i < 4; i++) {
uint8_t shift = shifts[i];
uint8_t reg = regs[i];
uint8_t cfg = (dev->regs[reg] >> shift) & 0x7;
uint32_t size = sizes[cfg];
total += MIN(dev->banks[i], size);
}
if (total > 1024) {
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10);
} else {
if (total >= 1024)
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
else
mem_mapping_disable(&ram_low_mapping);
mem_mapping_disable(&ram_high_mapping);
}
flushmmucache();
}
static void
vl82c480_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -91,16 +124,24 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0xed:
if (dev->idx >= 0x01 && dev->idx <= 0x24) {
if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) ||
((dev->idx >= 0x20) && (dev->idx <= 0x24))) {
switch (dev->idx) {
default:
dev->regs[dev->idx] = val;
break;
case 0x02: case 0x03:
dev->regs[dev->idx] = val;
if (!strcmp(machine_get_internal_name(), "martin"))
vl82c480_recalc_banks(dev);
break;
case 0x04:
if (dev->regs[0x00] == 0x98)
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7);
else
dev->regs[dev->idx] = val;
if (!strcmp(machine_get_internal_name(), "martin"))
dev->regs[dev->idx] &= 0x1f;
break;
case 0x05:
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef);
@@ -108,14 +149,9 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
case 0x07:
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf);
break;
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
case 0x12:
case 0x0d ... 0x12:
dev->regs[dev->idx] = val;
vl82c480_recalc(dev);
vl82c480_recalc_shadow(dev);
break;
}
}
@@ -124,8 +160,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
/* TODO: This is actually Fast A20 disable. */
#if 0
case 0xee:
if (mem_a20_alt)
outb(0x92, inb(0x92) & ~2);
mem_a20_alt = 0x00;
mem_a20_recalc();
break;
#endif
@@ -146,14 +182,16 @@ vl82c480_read(uint16_t addr, void *priv)
break;
case 0xed:
ret = dev->regs[dev->idx];
if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) ||
((dev->idx >= 0x20) && (dev->idx <= 0x24)))
ret = dev->regs[dev->idx];
break;
/* TODO: This is actually Fast A20 enable. */
#if 0
case 0xee:
if (!mem_a20_alt)
outb(0x92, inb(0x92) | 2);
mem_a20_alt = 0x02;
mem_a20_recalc();
break;
#endif
@@ -180,7 +218,9 @@ vl82c480_close(void *priv)
static void *
vl82c480_init(const device_t *info)
{
vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t));
vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t));
uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 };
uint32_t ms = mem_size;
dev->regs[0x00] = info->local;
dev->regs[0x01] = 0xff;
@@ -191,9 +231,23 @@ vl82c480_init(const device_t *info)
dev->regs[0x07] = 0x21;
dev->regs[0x08] = 0x38;
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t j = 2; j < 7; j++) {
if (ms >= sizes[j])
dev->banks[i] = sizes[j];
else
break;
}
ms -= dev->banks[i];
if ((ms == 0) || (dev->banks[i] == 0))
break;
}
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
device_add(&port_92_device);
device_add(&port_92_pci_device);
return dev;
}

View File

@@ -390,6 +390,8 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUS
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5);
uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
SUB_SP(ir, 2);
@@ -406,6 +408,8 @@ ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNU
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5);
uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002);
if (cpu_CR4_mask & CR4_VME)
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c);
else if (CPUID)

View File

@@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
if (cpu_state.eflags & VIF_FLAG)
temp |= I_FLAG;
temp = (temp & 0x7fd5) | 2;
PUSH_W(temp);
} else {
x86gpf(NULL, 0);
@@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
}
} else {
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
PUSH_W(cpu_state.flags);
}
CLOCK_CYCLES(4);
@@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat))
else
tempw = cpu_state.eflags & 4;
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
PUSH_L(cpu_state.flags | (tempw << 16));
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
@@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat))
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
flags_extract();
#ifdef USE_DEBUG_REGS_486
rf_flag_no_clear = 1;

View File

@@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
if (cpu_state.eflags & VIF_FLAG)
temp |= I_FLAG;
temp = (temp & 0x7fd5) | 2;
PUSH_W(temp);
} else {
x86gpf(NULL, 0);
@@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
}
} else {
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
PUSH_W(cpu_state.flags);
}
CLOCK_CYCLES(4);
@@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat))
else
tempw = cpu_state.eflags & 4;
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
PUSH_L(cpu_state.flags | (tempw << 16));
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
@@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat))
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
flags_extract();
rf_flag_no_clear = 1;

View File

@@ -897,8 +897,14 @@ device_is_valid(const device_t *device, int mch)
{
int ret = 1;
if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0))
ret = machine_has_bus(mch, device->flags & DEVICE_BUS);
if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) {
/* Hide PCI devices on machines with only an internal PCI bus. */
if ((device->flags & DEVICE_PCI) &&
machine_has_flags(mch, MACHINE_PCI_INTERNAL))
ret = 0;
else
ret = machine_has_bus(mch, device->flags & DEVICE_BUS);
}
return ret;
}

View File

@@ -1336,7 +1336,10 @@ write64_ami(void *priv, uint8_t val)
kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n");
if (!(dev->flags & DEVICE_PCI))
write_p2(dev, dev->p2 & ~(4 << (val & 0x01)));
kbc_delay_to_ob(dev, dev->ob, 0, 0x00);
if (strstr(machine_get_internal_name(), "sb486pv") != NULL)
kbc_delay_to_ob(dev, 0x03, 0, 0x00);
else
kbc_delay_to_ob(dev, dev->ob, 0, 0x00);
dev->pending++;
return 0;
@@ -2149,6 +2152,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
dev->wantdata = 0;
dev->state = STATE_MAIN_IBF;
/*
Explicitly clear IBF so that any preceding
command is not executed.
*/
dev->status &= ~STAT_IFULL;
return;
}
break;
@@ -2160,11 +2169,36 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
dev->wantdata = 1;
dev->state = STATE_KBC_PARAM;
dev->command = 0xd1;
/*
Explicitly clear IBF so that any preceding
command is not executed.
*/
dev->status &= ~STAT_IFULL;
return;
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
pulse_output(dev, val & 0x0f);
dev->state = STATE_MAIN_IBF;
/*
Explicitly clear IBF so that any preceding
command is not executed.
*/
dev->status &= ~STAT_IFULL;
return;
} else if (val == 0xad) {
/* Fast track it because of the Bochs BIOS. */
kbc_at_log("ATkbc: disable keyboard\n");
set_enable_kbd(dev, 0);
dev->state = STATE_MAIN_IBF;
/*
Explicitly clear IBF so that any preceding
command is not executed.
*/
dev->status &= ~STAT_IFULL;
return;
} else if (val == 0xae) {
/* Fast track it because of the LG MultiNet. */
@@ -2172,6 +2206,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
set_enable_kbd(dev, 1);
dev->state = STATE_MAIN_IBF;
/*
Explicitly clear IBF so that any preceding
command is not executed.
*/
dev->status &= ~STAT_IFULL;
return;
}
break;

View File

@@ -58,7 +58,7 @@ kbc_at_dev_log(const char *fmt, ...)
# define kbc_at_dev_log(fmt, ...)
#endif
static void
void
kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main)
{
if (reset_main) {
@@ -95,10 +95,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main)
dev->cmd_queue[dev->cmd_queue_end] = val;
dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf;
}
/* TODO: This should be done on actual send to host. */
if (val != 0xfe)
dev->last_scan_code = val;
}
static void
@@ -123,6 +119,8 @@ kbc_at_dev_poll(void *priv)
(dev->queue_start != dev->queue_end)) {
kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]);
dev->port->out_new = dev->queue[dev->queue_start];
if (dev->port->out_new != 0xfe)
dev->last_scan_code = dev->port->out_new;
dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask;
}
if (dev->ignore || !(*dev->scan) || dev->port->wantcmd)
@@ -143,6 +141,8 @@ kbc_at_dev_poll(void *priv)
if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) {
kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]);
dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start];
if (dev->port->out_new != 0xfe)
dev->last_scan_code = dev->port->out_new;
dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf;
}
if (dev->cmd_queue_start == dev->cmd_queue_end)
@@ -166,6 +166,8 @@ kbc_at_dev_poll(void *priv)
if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) {
kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]);
dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start];
if (dev->port->out_new != 0xfe)
dev->last_scan_code = dev->port->out_new;
dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf;
}
if (dev->cmd_queue_start == dev->cmd_queue_end)

View File

@@ -428,11 +428,11 @@ static const scancode scancode_set1[512] = {
{ .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */
{ .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */
{ .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */
{ .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */
{ .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xda, 0 } }, /* 15a */
{ .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */
{ .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */
{ .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */
{ .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */
{ .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xde, 0 } }, /* 15e */
{ .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */
{ .mk = { 0 }, .brk = { 0 } }, /* 160 */
{ .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */
@@ -3494,7 +3494,6 @@ keyboard_at_invalid_cmd(atkbc_dev_t *dev)
kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
}
static void
keyboard_at_write(void *priv)
{
@@ -3643,6 +3642,13 @@ keyboard_at_write(void *priv)
case 0xf6: /* set defaults */
keyboard_at_log("%s: set defaults%s\n",
dev->name, (val == 0xf6) ? "" : " and disable keyboard");
dev->port->out_new = -1;
dev->port->wantcmd = 0;
kbc_at_dev_queue_reset(dev, 1);
dev->last_scan_code = 0x00;
keyboard_scan = !(val & 0x01);
keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n",
dev->name, val, keyboard_scan);
@@ -3712,7 +3718,6 @@ keyboard_at_write(void *priv)
/* TODO: This is supposed to resend multiple bytes after some commands. */
case 0xfe: /* resend last scan code */
keyboard_at_log("%s: resend last scan code\n", dev->name);
kbc_at_dev_queue_add(dev, 0xfa, 0);
kbc_at_dev_queue_add(dev, dev->last_scan_code, 0);
break;
@@ -3728,6 +3733,44 @@ keyboard_at_write(void *priv)
}
}
#ifdef SCAN_CODE_TABLES_COMPARISON
/* Non-translated to translated scan codes. */
static const uint8_t nont_to_t[256] = {
0x00, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
/*
* Initialize the device for use by the user.
*
@@ -3777,6 +3820,138 @@ keyboard_at_init(const device_t *info)
inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa;
#ifdef SCAN_CODE_TABLES_COMPARISON
pclog_toggle_suppr();
pclog("Scan code set 01 vs. 81 (make):\n===============================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
do {
if (scancode_set1[i].mk[j] == scancode_set81[i].mk[j])
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set1[i].mk[j], scancode_set81[i].mk[j]);
j++;
} while ((scancode_set1[i].mk[j] != 0) && (scancode_set81[i].mk[j] != 0));
pclog("\n");
}
pclog("\nScan code set 01 vs. 81 (break):\n================================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
do {
if (scancode_set1[i].brk[j] == scancode_set81[i].brk[j])
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set1[i].brk[j], scancode_set81[i].brk[j]);
j++;
} while ((scancode_set1[i].brk[j] != 0) && (scancode_set81[i].brk[j] != 0));
pclog("\n");
}
pclog("\nScan code set 02 vs. 82 (make):\n===============================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
do {
if (scancode_set2[i].mk[j] == scancode_set82[i].mk[j])
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set2[i].mk[j], scancode_set82[i].mk[j]);
j++;
} while ((scancode_set2[i].mk[j] != 0) && (scancode_set82[i].mk[j] != 0));
pclog("\n");
}
pclog("\nScan code set 02 vs. 82 (break):\n================================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
do {
if (scancode_set2[i].brk[j] == scancode_set82[i].brk[j])
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set2[i].brk[j], scancode_set82[i].brk[j]);
j++;
} while ((scancode_set2[i].brk[j] != 0) && (scancode_set82[i].brk[j] != 0));
pclog("\n");
}
pclog("\nScan code set 01 vs. 02 (make):\n===============================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
int k = 0;
int was_f0 = 0;
do {
if (scancode_set2[i].mk[k] == 0xf0)
was_f0 = 1;
else {
uint8_t code = nont_to_t[scancode_set2[i].mk[k]];
if (was_f0) {
if (code & 0x80)
code = 0x00;
else
code |= 0x80;
was_f0 = 0;
}
if (scancode_set1[i].mk[j] == code)
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set1[i].mk[j], code);
j++;
}
k++;
} while ((scancode_set1[i].mk[j] != 0) && (scancode_set2[i].mk[k] != 0));
pclog("\n");
}
pclog("\nScan code set 01 vs. 02 (break):\n================================\n");
for (int i = 0; i < 512; i++) {
pclog("Scan code %03X:", i);
int j = 0;
int k = 0;
int was_f0 = 0;
do {
if (scancode_set2[i].brk[k] == 0xf0)
was_f0 = 1;
else {
uint8_t code = nont_to_t[scancode_set2[i].brk[k]];
if (was_f0) {
if (code & 0x80)
code = 0x00;
else
code |= 0x80;
was_f0 = 0;
}
if (scancode_set1[i].brk[j] == code)
pclog(" --");
else
pclog(" (%02X != %02X)", scancode_set1[i].brk[j], code);
j++;
}
k++;
} while ((scancode_set1[i].brk[j] != 0) && (scancode_set2[i].brk[k] != 0));
pclog("\n");
}
pclog_toggle_suppr();
fatal("Comparison finished\n");
#endif
/* Return our private data to the I/O layer. */
return dev;
}

View File

@@ -333,13 +333,13 @@ ps2_poll(void *priv)
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3;
int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) ||
((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size)));
int cond = (mouse_capture || video_fullscreen) && mouse_scan && (dev->mode == MODE_STREAM) &&
mouse_state_changed() && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size));
if (!cond && (dev->mode == MODE_STREAM))
if (cond)
ps2_report_coordinates(dev, 1);
return cond;
return !cond;
}
/*

View File

@@ -147,14 +147,17 @@ postcard_init(UNUSED(const device_t *info))
if (machine_has_bus(machine, MACHINE_BUS_MCA))
postcard_port = 0x680; /* MCA machines */
else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 "))
else if (strstr(machines[machine].name, " PS/2 ") ||
strstr(machine_getname_ex(machine), " PS/1 "))
postcard_port = 0x190; /* ISA PS/2 machines */
else if (strstr(machines[machine].name, " IBM XT "))
postcard_port = 0x60; /* IBM XT */
else if (strstr(machines[machine].name, " IBM PCjr")) {
postcard_port = 0x10; /* IBM PCjr */
postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */
} else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI))
} else if (strstr(machines[machine].name, " Compaq ") &&
!strstr(machines[machine].name, " Presario ") &&
!strstr(machines[machine].name, " ProSignia "))
postcard_port = 0x84; /* ISA Compaq machines */
else if (strstr(machines[machine].name, "Olivetti"))
postcard_port = 0x378; /* Olivetti machines */

View File

@@ -81,7 +81,6 @@ int fdc_current[FDC_MAX] = { 0, 0 };
volatile int fdcinited = 0;
// #define ENABLE_FDC_LOG 1
#ifdef ENABLE_FDC_LOG
int fdc_do_log = ENABLE_FDC_LOG;

View File

@@ -159,6 +159,9 @@ extern const device_t stpc_atlas_device;
extern const device_t stpc_serial_device;
extern const device_t stpc_lpt_device;
/* Symphony */
extern const device_t sl82c461_device;
/* UMC */
extern const device_t umc_8886f_device;
extern const device_t umc_8886af_device;

View File

@@ -291,6 +291,7 @@ extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t v
extern void kbc_at_set_fast_reset(uint8_t new_fast_reset);
extern void kbc_at_handler(int set, void *priv);
extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main);
extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main);
extern void kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main);
extern void kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa);

View File

@@ -105,7 +105,7 @@
/* Feature flags for advanced devices. */
#define MACHINE_APM 0x00080000 /* sys has APM */
#define MACHINE_ACPI 0x00100000 /* sys has ACPI */
#define MACHINE_HWM 0x00200000 /* sys has hw monitor */
#define MACHINE_PCI_INTERNAL 0x00200000 /* sys has only internal PCI */
#define MACHINE_CARTRIDGE 0x00400000 /* sys has cartridge bays */
/* Feature flags for internal storage controllers. */
#define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */
@@ -519,6 +519,7 @@ extern int machine_at_asus386_init(const machine_t *);
extern int machine_at_ecs386_init(const machine_t *);
extern int machine_at_spc6000a_init(const machine_t *);
extern int machine_at_micronics386_init(const machine_t *);
extern int machine_at_micronics386px_init(const machine_t *);
extern int machine_at_ecs386v_init(const machine_t *);
extern int machine_at_tandy4000_init(const machine_t *);
@@ -544,6 +545,7 @@ extern int machine_at_exp4349_init(const machine_t *);
extern int machine_at_vect486vl_init(const machine_t *);
extern int machine_at_d824_init(const machine_t *);
extern int machine_at_martin_init(const machine_t *);
extern int machine_at_403tg_init(const machine_t *);
extern int machine_at_403tg_d_init(const machine_t *);
@@ -554,6 +556,7 @@ extern int machine_at_aptiva510_init(const machine_t *);
extern int machine_at_pc330_6573_init(const machine_t *);
extern int machine_at_mvi486_init(const machine_t *);
extern int machine_at_dtk461_init(const machine_t *);
extern int machine_at_sis401_init(const machine_t *);
extern int machine_at_isa486_init(const machine_t *);
extern int machine_at_av4_init(const machine_t *);
@@ -585,6 +588,7 @@ extern int machine_at_sb486p_init(const machine_t *);
extern int machine_at_486sp3_init(const machine_t *);
extern int machine_at_486sp3c_init(const machine_t *);
extern int machine_at_486sp3g_init(const machine_t *);
extern int machine_at_sb486pv_init(const machine_t *);
extern int machine_at_486ap4_init(const machine_t *);
extern int machine_at_g486vpa_init(const machine_t *);
extern int machine_at_486vipio2_init(const machine_t *);

View File

@@ -99,6 +99,7 @@ extern const device_t ami_1994_nvr_device;
extern const device_t ami_1995_nvr_device;
extern const device_t via_nvr_device;
extern const device_t p6rp4_nvr_device;
extern const device_t martin_nvr_device;
extern const device_t elt_nvr_device;
#endif

View File

@@ -71,7 +71,10 @@ extern const device_t fdc37m60x_370_device;
/* ITE */
extern const device_t it8661f_device;
extern const device_t it8671f_device;
/* Intel */
extern const device_t i82091aa_device;
extern const device_t i82091aa_26e_device;
extern const device_t i82091aa_398_device;
extern const device_t i82091aa_ide_pri_device;
extern const device_t i82091aa_ide_device;

View File

@@ -100,6 +100,7 @@
#define AC97_CODEC_STAC9708 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08)
#define AC97_CODEC_STAC9721 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09)
#define AC97_CODEC_TR28023 AC97_VENDOR_ID('T', 'R', 'A', 0x03)
#define AC97_CODEC_W83971D AC97_VENDOR_ID('W', 'E', 'C', 0x01)
#define AC97_CODEC_WM9701A AC97_VENDOR_ID('W', 'M', 'L', 0x00)
typedef struct ac97_vendor_reg_t {
@@ -150,6 +151,7 @@ extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t tr28023_device;
extern const device_t w83971d_device;
extern const device_t wm9701a_device;
extern const device_t ac97_via_device;

View File

@@ -281,6 +281,26 @@ machine_at_micronics386_init(const machine_t *model)
return ret;
}
int
machine_at_micronics386px_init(const machine_t *model)
{
int ret;
ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-LO.BIN",
"roms/machines/micronics386/386-Micronics-09-00021-HI.BIN",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_init(model);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
return ret;
}
static void
machine_at_scat_init(const machine_t *model, int is_v4, int is_ami)
{
@@ -704,7 +724,9 @@ machine_at_cmdsl386sx25_init(const machine_t *model)
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5402_onboard_device);
machine_at_common_ide_init(model);
machine_at_common_init_ex(model, 2);
device_add(&ide_isa_device);
device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */
device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */

View File

@@ -134,6 +134,27 @@ machine_at_tandy4000_init(const machine_t *model)
return ret;
}
int
machine_at_dtk461_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/dtk461/DTK.BIO",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&sl82c461_device);
device_add(&keyboard_at_ami_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
return ret;
}
static void
machine_at_sis401_common_init(const machine_t *model)
{
@@ -391,14 +412,16 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems
if (bios_only || !ret)
return ret;
machine_at_common_ide_init(model);
device_add(&vl82c480_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5428_onboard_device);
machine_at_common_init_ex(model, 2);
device_add(&vl82c480_device);
device_add(&vl82c113_device);
device_add(&ide_isa_device);
device_add(&fdc37c651_ide_device);
return ret;
@@ -415,14 +438,18 @@ machine_at_d824_init(const machine_t *model)
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&vl82c480_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5428_onboard_device);
device_add(&keyboard_ps2_device);
machine_at_common_init_ex(model, 2);
device_add(&vl82c480_device);
/*
Technically, it should be the VL82C114 but we do not have
a proper datasheet of it that tells us the registers.
*/
device_add(&vl82c113_device);
device_add(&ide_isa_device);
device_add(&fdc37c651_device);
@@ -430,6 +457,30 @@ machine_at_d824_init(const machine_t *model)
return ret;
}
int
machine_at_martin_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/martin/NONSCSI.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
device_add(&vl82c480_device);
device_add(&vl82c113_device);
device_add(&ide_vlb_device);
device_add(&fdc37c651_ide_device);
device_add(&intel_flash_bxt_device);
return ret;
}
int
machine_at_acera1g_init(const machine_t *model)
{
@@ -705,7 +756,6 @@ machine_at_403tg_d_mr_init(const machine_t *model)
return ret;
}
static const device_config_t pb450_config[] = {
// clang-format off
{
@@ -1589,6 +1639,91 @@ machine_at_486sp3g_init(const machine_t *model)
return ret;
}
static const device_config_t sb486pv_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "sb486pv",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "AMI 062594 (0108)", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/41-0108-062594-SATURN2.rom", "" } },
{ .name = "AMI 062594 (0301)", .internal_name = "sb486pv_94", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/0301-062594-SATURN2.rom", "" } },
{ .name = "AMI 071595 (1301)", .internal_name = "sb486pv_95", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/amiboot.rom", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t sb486pv_device = {
.name = "ICS SB486PV",
.internal_name = "sb486pv_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = sb486pv_config
};
int
machine_at_sb486pv_init(const machine_t *model)
{
int ret = 0;
const char* fn;
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0);
if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom"))
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
else
ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init(model);
// machine_at_common_init_ex(model, 2);
// device_add(&amstrad_megapc_nvr_device);
device_add(&ide_pci_device);
pci_init(PCI_CONFIG_TYPE_2);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0e, PCI_CARD_IDE, 0, 0, 0, 0);
pci_register_slot(0x0f, PCI_CARD_VIDEO, 1, 2, 3, 4);
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
device_add(&keyboard_ps2_ami_pci_device);
device_add(&sio_zb_device);
device_add(&ide_rz1000_pci_single_channel_device);
device_add(&i82091aa_26e_device);
if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom"))
device_add(&intel_flash_bxt_device);
else
device_add(&intel_flash_bxt_ami_device);
device_add(&i420zx_device);
return ret;
}
int
machine_at_486ap4_init(const machine_t *model)
{
@@ -1782,12 +1917,11 @@ machine_at_sbc490_init(const machine_t *model)
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
device_add(&ali1489_device);
device_add(&fdc37c665_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&tgui9440_onboard_pci_device);
device_add(&keyboard_ps2_ami_device);
device_add(&sst_flash_29ee010_device);

View File

@@ -61,11 +61,6 @@ enum {
/*Very rough estimate*/
#define VID_CLOCK (double) (651 * 416 * 60)
static uint8_t cga_crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Mapping of attributes to colours */
static uint32_t amber;
static uint32_t black;
@@ -89,17 +84,14 @@ compaq_plasma_display_set(uint8_t internal)
cpq_st_display_internal = internal;
}
static uint8_t
compaq_plasma_display_get(void)
{
return cpq_st_display_internal;
}
typedef struct compaq_plasma_t {
cga_t cga;
mem_mapping_t font_ram_mapping;
uint8_t *font_ram;
uint8_t port_13c6;
uint8_t port_23c6;
uint8_t port_27c6;
uint8_t internal_monitor;
uint8_t attrmap;
} compaq_plasma_t;
static int compaq_machine_type = 0;
@@ -116,14 +108,14 @@ compaq_plasma_recalctimings(compaq_plasma_t *self)
double _dispofftime;
double disptime;
if (!self->internal_monitor && !(self->port_23c6 & 1)) {
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
cga_recalctimings(&self->cga);
return;
}
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
}
@@ -143,10 +135,13 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
self->cga.vram[addr & 0x7fff] = val;
if (self->port_23c6 & 0x08)
self->font_ram[addr & 0x1fff] = val;
else
self->cga.vram[addr & 0x7fff] = val;
compaq_plasma_waitstates(&self->cga);
}
static uint8_t
compaq_plasma_read(uint32_t addr, void *priv)
{
@@ -154,7 +149,11 @@ compaq_plasma_read(uint32_t addr, void *priv)
uint8_t ret;
compaq_plasma_waitstates(&self->cga);
ret = (self->cga.vram[addr & 0x7fff]);
if (self->port_23c6 & 0x08)
ret = (self->font_ram[addr & 0x1fff]);
else
ret = (self->cga.vram[addr & 0x7fff]);
return ret;
}
@@ -163,33 +162,23 @@ static void
compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t old;
switch (addr) {
/* Emulated CRTC, register select */
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
cga_out(addr, val, &self->cga);
break;
/* Emulated CRTC, value */
case 0x3d1:
case 0x3d3:
case 0x3d5:
old = self->cga.crtc[self->cga.crtcreg];
self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg];
/* Register 0x12 controls the attribute mappings for the
* plasma screen. */
if (self->cga.crtcreg == 0x12) {
self->attrmap = val;
compaq_plasma_recalcattrs(self);
break;
}
if (old != val) {
if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) {
self->cga.fullchange = changeframecount;
compaq_plasma_recalctimings(self);
}
}
case 0x3d7:
cga_out(addr, val, &self->cga);
compaq_plasma_recalctimings(self);
break;
case 0x3d8:
case 0x3d9:
@@ -197,15 +186,26 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
break;
case 0x13c6:
compaq_plasma_display_set((val & 8) ? 1 : 0);
self->port_13c6 = val;
compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0);
/*
For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA;
Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA;
This leads me to believe bit 2 is not relevant to the mode.
*/
if ((val & 0x03) == 0x03)
mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000);
else
mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000);
break;
case 0x23c6:
self->port_23c6 = val;
if (val & 8) /* Disable internal CGA */
mem_mapping_disable(&self->cga.mapping);
else
mem_mapping_enable(&self->cga.mapping);
compaq_plasma_recalcattrs(self);
break;
case 0x27c6:
self->port_27c6 = val;
break;
default:
@@ -222,37 +222,44 @@ compaq_plasma_in(uint16_t addr, void *priv)
switch (addr) {
case 0x3d4:
case 0x3da:
case 0x3db:
case 0x3dc:
ret = cga_in(addr, &self->cga);
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
if (self->cga.crtcreg == 0x12) {
ret = self->attrmap & 0x0f;
if (self->internal_monitor)
ret |= 0x30; /* Plasma / CRT */
} else
ret = cga_in(addr, &self->cga);
case 0x3d7:
ret = cga_in(addr, &self->cga);
break;
case 0x3d8:
ret = self->cga.cgamode;
break;
case 0x13c6:
ret = compaq_plasma_display_get() ? 8 : 0;
ret |= 4;
ret = self->port_13c6;
#if 0
if ((self->cga.cgamode & 0x28) == 0x00)
ret |= 0x04;
#endif
break;
case 0x17c6:
ret = 0xe6;
break;
case 0x1bc6:
ret = 0;
if (compaq_plasma_display_get()) {
if ((self->cga.cgamode & 0x12) == 0x12) {
if (self->port_23c6 & 8)
ret |= 0x40;
else
ret |= 0x20;
}
}
ret = 0x40;
break;
case 0x23c6:
ret = 0;
ret = self->port_23c6;
break;
case 0x27c6:
ret = self->port_27c6 & 0x3f;
break;
default:
@@ -276,6 +283,8 @@ compaq_plasma_poll(void *priv)
int cursorline;
int blink = 0;
int underline = 0;
int c;
int x;
uint32_t ink = 0;
uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black;
uint32_t bg = black;
@@ -292,230 +301,303 @@ compaq_plasma_poll(void *priv)
}
/* graphic mode and not mode 40h */
if (!self->internal_monitor && !(self->port_23c6 & 1)) {
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
/* standard cga mode */
cga_poll(&self->cga);
return;
}
} else {
/* mode 40h or text mode */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
if (self->cga.cgadispon) {
if (self->cga.displine == 0)
video_wait_for_buffer();
/* mode 40h or text mode */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
if (self->cga.cgadispon) {
if (self->cga.displine == 0) {
video_wait_for_buffer();
}
if (self->cga.cgamode & 2) {
if (self->cga.cgamode & 0x10) {
/* 640x400 mode */
if (self->port_23c6 & 1) /* 640*400 */ {
addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7FFF];
addr++;
/* 80-col */
if (self->cga.cgamode & 0x01) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1;
ma += (self->cga.displine >> 4) * 80;
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(self->cga.cgamode & 8))
ink = black;
(buffer32->line[self->cga.displine])[x * 8 + c] = ink;
dat <<= 1;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
/* for each text column */
for (x = 0; x < 80; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black);
} else if ((self->port_23c6 >> 5) == 4) {
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16);
}
}
}
ma++;
}
}
/* 40-col */
else if (!(self->cga.cgamode & 0x02)) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1;
ma += (self->cga.displine >> 4) * 40;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
for (x = 0; x < 40; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1)
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black);
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black);
}
else if ((self->port_23c6 >> 5) == 4)
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16);
}
}
ma++;
}
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
if (self->cga.cgamode & 0x10) {
/* 640x400 mode */
if (self->port_23c6 & 0x01) /* 640*400 */ {
addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(self->cga.cgamode & 8))
pattern = 0;
switch (pattern & 3) {
case 0:
ink0 = ink1 = black;
break;
case 1:
if (self->cga.displine & 1) {
ink0 = black;
ink1 = black;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 2:
if (self->cga.displine & 1) {
ink0 = black;
ink1 = amber;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 3:
ink0 = ink1 = amber;
break;
default:
break;
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(self->cga.cgamode & 0x08))
ink = black;
buffer32->line[self->cga.displine][(x << 3) + c] = ink;
dat <<= 1;
}
buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0;
buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1;
dat <<= 2;
}
}
}
} else if (self->cga.cgamode & 1) {
/* 80-col */
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) * 2;
ma += (self->cga.displine >> 4) * 80;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc);
/* for each text column */
for (uint8_t x = 0; x < 80; x++) {
/* video output enabled */
chr = self->cga.vram[(addr + 2 * x) & 0x7FFF];
attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF];
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16));
blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6));
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if (blink) {
/* set blinking */
cols[1] = cols[0];
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0];
}
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
++ma;
}
} else { /* 40-col */
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) * 2;
ma += (self->cga.displine >> 4) * 40;
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(self->cga.cgamode & 0x08))
pattern = 0;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc);
switch (pattern & 3) {
case 0:
ink0 = ink1 = black;
break;
case 1:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = black;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 2:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = amber;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 3:
ink0 = ink1 = amber;
break;
for (uint8_t x = 0; x < 40; x++) {
chr = self->cga.vram[(addr + 2 * x) & 0x7FFF];
attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF];
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16));
blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6));
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if (blink) {
/* set blinking */
cols[1] = cols[0];
default:
break;
}
buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0;
buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1;
dat <<= 2;
}
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c * 2)] = buffer32->line[self->cga.displine][(x << 4) + (c * 2) + 1] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (uint8_t c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0];
}
++ma;
}
}
}
self->cga.displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (self->cga.displine == 400) { /* Start of VSYNC */
self->cga.cgastat |= 8;
self->cga.cgadispon = 0;
}
if (self->cga.displine == 416) { /* End of VSYNC */
self->cga.displine = 0;
self->cga.cgastat &= ~8;
self->cga.cgadispon = 1;
}
} else {
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
self->cga.displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (self->cga.displine == 400) { /* Start of VSYNC */
self->cga.cgastat |= 8;
self->cga.cgadispon = 0;
}
if (self->cga.displine == 416) { /* End of VSYNC */
self->cga.displine = 0;
self->cga.cgastat &= ~8;
self->cga.cgadispon = 1;
}
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
self->cga.linepos = 0;
self->cga.linepos = 0;
if (self->cga.displine == 400) {
/* Hardcode 640x400 window size */
if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) {
if (self->cga.displine == 400) {
xsize = 640;
ysize = 400;
if (xsize < 64)
xsize = 656;
if (ysize < 32)
ysize = 200;
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
if ((self->cga.cgamode & 0x08) || video_force_resize_get()) {
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
/* Plasma specific */
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */
video_res_x = 640;
video_res_y = 400;
if (self->cga.cgamode & 0x02) {
if (self->cga.cgamode & 0x10)
video_bpp = 1;
else
video_bpp = 2;
} else
video_bpp = 0;
self->cga.cgablink++;
}
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */
video_res_x = 640;
video_res_y = 400;
if (self->cga.cgamode & 0x02) {
if (self->cga.cgamode & 0x10)
video_bpp = 1;
else
video_bpp = 2;
} else
video_bpp = 0;
self->cga.cgablink++;
}
}
}
@@ -560,7 +642,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self)
/* Set up colours */
amber = makecol(0xff, 0x7d, 0x00);
black = makecol(0x64, 0x0c, 0x00);
black = makecol(0x64, 0x19, 0x00);
/* Initialize the attribute mapping. Start by defaulting everything
* to black on amber, and with bold set by bit 3 */
@@ -575,7 +657,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self)
for (n = 0x11; n <= 0xFF; n++) {
if ((n & 7) == 0)
continue;
if (self->attrmap & 4) { /* Inverse */
if ((self->port_23c6 >> 5) == 1) { /* Inverse */
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
} else { /* Normal */
@@ -588,7 +670,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self)
for (n = 0x01; n <= 0x0E; n++) {
if (n == 7)
continue;
if (self->attrmap & 1) {
if ((self->port_23c6 >> 5) == 1) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
blinkcols[n + 128][0] = amber;
@@ -631,31 +713,31 @@ compaq_plasma_init(UNUSED(const device_t *info))
{
compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t));
cga_init(&self->cga);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma);
if (compaq_machine_type == COMPAQ_PORTABLEIII)
loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2);
else
loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49);
self->cga.composite = 0;
self->cga.revision = 0;
self->cga.vram = malloc(0x8000);
self->internal_monitor = 1;
self->font_ram = malloc(0x2000);
cga_comp_init(self->cga.revision);
timer_add(&self->cga.timer, compaq_plasma_poll, self, 1);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self);
timer_set_callback(&self->cga.timer, compaq_plasma_poll);
timer_set_p(&self->cga.timer, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000,
compaq_plasma_read, NULL, NULL,
compaq_plasma_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, self);
for (int i = 1; i <= 2; i++) {
io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
}
io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x13c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x1bc6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
/* Default attribute mapping is 4 */
self->attrmap = 4;
compaq_plasma_recalcattrs(self);
self->cga.cgastat = 0xf4;
overscan_x = overscan_y = 16;
self->cga.rgb_type = device_get_config_int("rgb_type");
@@ -672,6 +754,7 @@ compaq_plasma_close(void *priv)
compaq_plasma_t *self = (compaq_plasma_t *) priv;
free(self->cga.vram);
free(self->font_ram);
free(self);
}
@@ -793,7 +876,8 @@ machine_at_compaq_init(const machine_t *model, int type)
switch (type) {
case COMPAQ_PORTABLEII:
machine_at_init(model);
machine_at_common_init(model);
device_add(&keyboard_at_compaq_device);
break;
case COMPAQ_PORTABLEIII:
@@ -801,7 +885,9 @@ machine_at_compaq_init(const machine_t *model, int type)
device_add(&ide_isa_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&compaq_plasma_device);
machine_at_init(model);
machine_at_common_init(model);
device_add(&keyboard_at_compaq_device);
break;
case COMPAQ_PORTABLEIII386:

View File

@@ -69,6 +69,7 @@ extern const device_t pb450_device;
extern const device_t jukopc_device;
extern const device_t vendex_device;
extern const device_t c5sbm2_device;
extern const device_t sb486pv_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -5435,7 +5436,7 @@ const machine_t machines[] = {
},
/* Has IBM AT KBC firmware. */
{
.name = "[ISA] Micronics 09-00021",
.name = "[ISA] Micronics 09-00021 (Tandon BIOS)",
.internal_name = "micronics386",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_DISCRETE,
@@ -5474,6 +5475,46 @@ const machine_t machines[] = {
.net_device = NULL
},
/* Has IBM AT KBC firmware. */
{
.name = "[ISA] Micronics 09-00021 (Phoenix BIOS)",
.internal_name = "micronics386px",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_DISCRETE,
.init = machine_at_micronics386px_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386DX,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_APM,
.ram = {
.min = 512,
.max = 8192,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM AT KBC firmware. */
{
.name = "[ISA] Tandy 4000",
.internal_name = "tandy4000",
@@ -6363,6 +6404,46 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey F KBC firmware. */
{
.name = "[Symphony SL42C460] DTK PKM-0031Y",
.internal_name = "dtk461",
.type = MACHINE_TYPE_486,
.chipset = MACHINE_CHIPSET_SYMPHONY_SL82C460,
.init = machine_at_dtk461_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET1,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_APM,
.ram = {
.min = 1024,
.max = 32768,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends
commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42,
but it does not write a byte after C9, which is consistent with AMIKey, so
@@ -6446,7 +6527,7 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has a standard IBM PS/2 KBC firmware or a clone thereof. */
/* Has a VLSI VL82C114 Combination I/O which holds the KBC. */
{
.name = "[VLSI 82C481] Siemens Nixdorf D824",
.internal_name = "d824",
@@ -6474,7 +6555,7 @@ const machine_t machines[] = {
.max = 32768,
.step = 2048
},
.nvrmask = 127,
.nvrmask = 255,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
@@ -6693,6 +6774,46 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has AMI MegaKey KBC. */
{
.name = "[i420TX] J-Bond PCI400C-A",
.internal_name = "pci400ca",
.type = MACHINE_TYPE_486_S2,
.chipset = MACHINE_CHIPSET_INTEL_420TX,
.init = machine_at_pci400ca_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET3,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PCI,
.flags = MACHINE_SCSI,
.ram = {
.min = 1024,
.max = 65536,
.step = 1024
},
.nvrmask = 127,
.kbc_device = &keyboard_at_ami_device,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* This has a standalone AMI Megakey 1993, which is type 'P'. */
{
.name = "[IMS 8848] Tekram G486IP",
@@ -6854,13 +6975,13 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has AMI MegaKey KBC. */
/* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */
{
.name = "[i420TX] J-Bond PCI400C-A",
.internal_name = "pci400ca",
.name = "[VLSI 82C480] ZEOS Martin",
.internal_name = "martin",
.type = MACHINE_TYPE_486_S2,
.chipset = MACHINE_CHIPSET_INTEL_420TX,
.init = machine_at_pci400ca_init,
.chipset = MACHINE_CHIPSET_VLSI_VL82C480,
.init = machine_at_martin_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
@@ -6875,15 +6996,15 @@ const machine_t machines[] = {
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PCI,
.flags = MACHINE_SCSI,
.bus_flags = MACHINE_PS2_VLB,
.flags = MACHINE_IDE | MACHINE_APM,
.ram = {
.min = 1024,
.min = 2048,
.max = 65536,
.step = 1024
.step = 2048
},
.nvrmask = 127,
.kbc_device = &keyboard_at_ami_device,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
@@ -6895,7 +7016,6 @@ const machine_t machines[] = {
.net_device = NULL
},
/* 486 machines - Socket 3 */
/* 486 machines with just the ISA slot */
/* Has a Fujitsu MBL8042H KBC. */
@@ -8396,6 +8516,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* This has an AMI MEGAKey 'P' or 'R' keyboard controller. */
{
.name = "[i420ZX] ICS SB486PV",
.internal_name = "sb486pv",
.type = MACHINE_TYPE_486_S3_PCI,
.chipset = MACHINE_CHIPSET_INTEL_420ZX,
.init = machine_at_sb486pv_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET3,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
/* Has PCI but no user-facing slots. */
.bus_flags = MACHINE_PCI,
.flags = MACHINE_PS2_KBC | MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_PCI_INTERNAL,
.ram = {
.min = 2048,
.max = 65536,
.step = 2048
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = &sb486pv_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5436_onboard_pci_device,
.snd_device = NULL,
.net_device = NULL
},
/* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */
{
.name = "[IMS 8848] J-Bond PCI400C-B",

View File

@@ -296,6 +296,7 @@
#define FLAG_P6RP4_HACK 0x10
#define FLAG_PIIX4 0x20
#define FLAG_MULTI_BANK 0x40
#define FLAG_MARTIN_HACK 0x80
typedef struct local_t {
int8_t stat;
@@ -733,6 +734,13 @@ nvr_read(uint16_t addr, void *priv)
ret = REGD_VRT;
break;
case 0x11:
if (local->flags & FLAG_MARTIN_HACK)
ret = nvr->regs[local->addr[addr_id]] | 0x02;
else
ret = nvr->regs[local->addr[addr_id]];
break;
case 0x2c:
if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK))
ret = nvr->regs[local->addr[addr_id]] & 0x7f;
@@ -771,6 +779,17 @@ nvr_read(uint16_t addr, void *priv)
ret = checksum >> 8;
else
ret = checksum & 0xff;
} else if (!nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) {
for (i = 0x10; i <= 0x2d; i++) {
if (i == 0x11)
checksum += (nvr->regs[i] | 0x02);
else
checksum += nvr->regs[i];
}
if (local->addr[addr_id] == 0x2e)
ret = checksum >> 8;
else
ret = checksum & 0xff;
} else
ret = nvr->regs[local->addr[addr_id]];
break;
@@ -1123,9 +1142,11 @@ nvr_at_init(const device_t *info)
if (info->local & 0x10) {
local->def = 0x00;
local->flags |= FLAG_AMI_1992_HACK;
} else if (info->local == 36)
} else if ((info->local == 36) || (info->local == 68)) {
local->def = 0x00;
else
if (info->local == 68)
local->flags |= FLAG_MARTIN_HACK;
} else
local->def = 0xff;
nvr->irq = 8;
local->cent = RTC_CENTURY_AT;
@@ -1160,6 +1181,9 @@ nvr_at_init(const device_t *info)
/* Initialize the generic NVR. */
nvr_init(nvr);
if (nvr->is_new && (local->flags & FLAG_MARTIN_HACK))
nvr->regs[0x11] = nvr->regs[0x2f] = 0x02;
if (nvr_at_inited == 0) {
/* Start the timers. */
timer_add(&local->update_timer, timer_update, nvr, 0);
@@ -1426,6 +1450,20 @@ const device_t amstrad_megapc_nvr_device = {
.config = NULL
};
const device_t martin_nvr_device = {
.name = "Zeos Martin NVRAM",
.internal_name = "martin_nvr",
.flags = DEVICE_ISA16,
.local = 68,
.init = nvr_at_init,
.close = nvr_at_close,
.reset = nvr_at_reset,
.available = NULL,
.speed_changed = nvr_at_speed_changed,
.force_redraw = NULL,
.config = NULL
};
const device_t elt_nvr_device = {
.name = "Epson Equity LT NVRAM",
.internal_name = "elt_nvr",

View File

@@ -849,8 +849,8 @@ msgstr "一个旧式计算机模拟器\n\n作者: Miran Grča (OBattler)、Richa
msgid "Hardware not available"
msgstr "硬件不可用"
msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection."
msgstr "请确认 %1 已安装且使用兼容 libpcap 的网络连接。"
msgid "Make sure %1 is installed and that you are on a %1-compatible network connection."
msgstr "请确认 %1 已安装且使用兼容 %1 的网络连接。"
msgid "Invalid configuration"
msgstr "无效配置"
@@ -1240,7 +1240,7 @@ msgid "Host CD/DVD Drive (%1:)"
msgstr "主机 CD/DVD 驱动器 (%1:)"
msgid "&Connected"
msgstr ""
msgstr "已连接(&C)"
msgid "Clear image history"
msgstr "清除映像历史记录"
@@ -1300,7 +1300,7 @@ msgid "\nFalling back to software rendering."
msgstr "\n回到软件渲染。"
msgid "<html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html>"
msgstr "<html><head/><body><p>选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。</p></body></html&gt"
msgstr "<html><head/><body><p>选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。</p></body></html>"
msgid "This machine might have been moved or copied."
msgstr "这台机器可能被移动或复制过。"
@@ -1315,7 +1315,7 @@ msgid "I Copied It"
msgstr "我已复制这台机器"
msgid "86Box Monitor #"
msgstr "86Box 监测器 "
msgstr "86Box 监测器 #"
msgid "No MCA devices."
msgstr "无 MCA 设备。"
@@ -1804,7 +1804,7 @@ msgid "Five + Wheel"
msgstr "五键+滚轮"
msgid "Five + 2 Wheels"
msgstr ""
msgstr "五键+双滚轮"
msgid "A3 - SMT2 Serial / SMT3(R)V"
msgstr "A3 - SMT2 串行 / SMT3RV"
@@ -2050,25 +2050,25 @@ msgid "[Generic] RAM Disk (max. speed)"
msgstr "[Generic] RAM 磁盘 (最大速度)"
msgid "[Generic] 1989 (3500 RPM)"
msgstr ""
msgstr "[Generic] 1989 (3500 RPM)"
msgid "[Generic] 1992 (3600 RPM)"
msgstr ""
msgstr "[Generic] 1992 (3600 RPM)"
msgid "[Generic] 1994 (4500 RPM)"
msgstr ""
msgstr "[Generic] 1994 (4500 RPM)"
msgid "[Generic] 1996 (5400 RPM)"
msgstr ""
msgstr "[Generic] 1996 (5400 RPM)"
msgid "[Generic] 1997 (5400 RPM)"
msgstr ""
msgstr "[Generic] 1997 (5400 RPM)"
msgid "[Generic] 1998 (5400 RPM)"
msgstr ""
msgstr "[Generic] 1998 (5400 RPM)"
msgid "[Generic] 2000 (7200 RPM)"
msgstr ""
msgstr "[Generic] 2000 (7200 RPM)"
msgid "IBM 8514/A clone (ISA)"
msgstr "IBM 8514/A 克隆 (ISA)"
@@ -2076,6 +2076,12 @@ msgstr "IBM 8514/A 克隆 (ISA)"
msgid "Vendor"
msgstr "制造商"
msgid "30 Hz (JMP2 = 1)"
msgstr "30 Hz (JMP2 = 1)"
msgid "60 Hz (JMP2 = 2)"
msgstr "60 Hz (JMP2 = 2)"
msgid "Generic PC/XT Memory Expansion"
msgstr "通用 PC/XT 内存扩展"
@@ -2089,61 +2095,61 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t
msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。"
msgid "Inhibit multimedia keys"
msgstr ""
msgstr "禁止多媒体按键"
msgid "Ask for confirmation before saving settings"
msgstr ""
msgstr "保存设置前要求用户确认"
msgid "Ask for confirmation before hard resetting"
msgstr ""
msgstr "硬重置前要求用户确认"
msgid "Ask for confirmation before quitting"
msgstr ""
msgstr "退出前要求用户确认"
msgid "Options"
msgstr ""
msgstr "选项"
msgid "Model"
msgstr ""
msgstr "模型"
msgid "Model:"
msgstr ""
msgstr "模型:"
msgid "Failed to initialize Vulkan renderer."
msgstr ""
msgstr "Vulkan 渲染器初始化失败。"
msgid "GLSL Error"
msgstr ""
msgstr "GLSL 错误"
msgid "Could not load shader: %1"
msgstr ""
msgstr "无法加载着色器:%1"
msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2"
msgstr ""
msgstr "OpenGL 版本需要达到 3.0 或更高。当前 GLSL 版本为 %1.%2"
msgid "Could not load texture: %1"
msgstr ""
msgstr "无法加载材质:%1"
msgid "Could not compile shader:\n\n%1"
msgstr ""
msgstr "无法编译着色器:\n\n%1"
msgid "Program not linked:\n\n%1"
msgstr ""
msgstr "程序未链接:\n\n%1"
msgid "Shader Manager"
msgstr ""
msgstr "着色器管理器"
msgid "Shader Configuration"
msgstr ""
msgstr "着色器配置"
msgid "Add"
msgstr ""
msgstr "添加"
msgid "Move up"
msgstr ""
msgstr "上移"
msgid "Move down"
msgstr ""
msgstr "下移"
msgid "Could not load file %1"
msgstr ""
msgstr "无法加载文件 %1"

View File

@@ -295,6 +295,20 @@ const device_t i82091aa_device = {
.config = NULL
};
const device_t i82091aa_26e_device = {
.name = "Intel 82091AA Super I/O (Port 26Eh)",
.internal_name = "i82091aa_26e",
.flags = 0,
.local = 0x140,
.init = i82091aa_init,
.close = i82091aa_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t i82091aa_398_device = {
.name = "Intel 82091AA Super I/O (Port 398h)",
.internal_name = "i82091aa_398",

View File

@@ -22,6 +22,7 @@
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/machine.h>
#include <86box/nvr.h>
#include <86box/sio.h>
#include <86box/plat_unused.h>
@@ -133,7 +134,10 @@ vl82c113_init(UNUSED(const device_t *info))
{
vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t));
dev->nvr = device_add(&at_nvr_device);
if (!strcmp(machine_get_internal_name(), "martin"))
dev->nvr = device_add(&martin_nvr_device);
else
dev->nvr = device_add(&amstrad_megapc_nvr_device);
dev->nvr_enabled = 1;
dev->nvr_base = 0x0070;

View File

@@ -68,7 +68,6 @@ static const struct {
.device = &cs4297_device,
.misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = 0,
.pcsr_mask = 0x7f,
.vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5a, 0x0301, 0x0000}, {0}}
},
@@ -100,15 +99,18 @@ static const struct {
{
.device = &tr28023_device,
.misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_POP | AC97_MS | AC97_LPBK,
.reset_flags = 0,
.extid_flags = 0,
.pcsr_mask = 0x3f
},
{
.device = &w83971d_device,
.misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = (27 << AC97_3D_SHIFT),
.pcsr_mask = 0x3f
},
{
.device = &wm9701a_device,
.misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = 0,
.pcsr_mask = 0x3f
}
// clang-format on
@@ -284,8 +286,9 @@ line_gain:
case 0x22: /* 3D Control */
switch (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) {
case 1: /* Analog Devices */
case 6: /* Crystal */
case 1: /* Analog Devices */
case 6: /* Crystal */
case 27: /* Winbond */
val &= 0x000f;
break;
@@ -764,6 +767,20 @@ const device_t tr28023_device = {
.config = NULL
};
const device_t w83971d_device = {
.name = "Winbond W83971D",
.internal_name = "w83971d",
.flags = DEVICE_AC97,
.local = AC97_CODEC_W83971D,
.init = ac97_codec_init,
.close = ac97_codec_close,
.reset = ac97_codec_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t wm9701a_device = {
.name = "Wolfson WM9701A",
.internal_name = "wm9701a",

View File

@@ -33,6 +33,7 @@
#include <86box/pci.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/timer.h>
#include <86box/video.h>
#include <86box/i2c.h>
@@ -4316,7 +4317,8 @@ gd54xx_init(const device_t *info)
break;
case CIRRUS_ID_CLGD5436:
if (info->local & 0x200) {
if ((info->local & 0x200) &&
!strstr(machine_get_internal_name(), "sb486pv")) {
romfn = NULL;
gd54xx->has_bios = 0;
} else
@@ -4461,8 +4463,8 @@ gd54xx_init(const device_t *info)
}
io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx);
if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) {
if (romfn == NULL)
if (gd54xx->pci && (id >= CIRRUS_ID_CLGD5430)) {
if (info->local & 0x200)
pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot);
else
pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot);