Merge branch '86Box:master' into master

This commit is contained in:
starfrost
2025-05-29 22:07:01 +01:00
committed by GitHub
49 changed files with 2018 additions and 600 deletions

View File

@@ -184,15 +184,11 @@ endif()
# Option Description Def. Condition Otherwise
# ------ ----------- ---- ------------ ---------
cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF)
cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF)
cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF)
cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF)
cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF)
cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF)
cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF)
cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF)
cmake_dependent_option(PCL "Generic PCL5e Printer" ON "DEV_BRANCH" OFF)
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)

View File

@@ -18,6 +18,7 @@
add_library(chipset OBJECT
82c100.c
acc2168.c
cs8220.c
cs8230.c
ali1429.c
ali1435.c
@@ -42,6 +43,7 @@ add_library(chipset OBJECT
isa486c.c
../ioapic.c
neat.c
olivetti_eva.c
opti283.c
opti291.c
opti391.c
@@ -85,7 +87,3 @@ add_library(chipset OBJECT
vl82c480.c
wd76c10.c
)
if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c)
endif()

View File

@@ -61,91 +61,238 @@ ali1409_log(const char *fmt, ...)
#endif
typedef struct ali_1409_t {
uint8_t is_g;
uint8_t index;
uint8_t cfg_locked;
uint8_t reg_57h;
uint8_t regs[256];
uint8_t shadow[4];
uint8_t last_reg;
} ali1409_t;
/*
This here is because from the two BIOS'es I used to reverse engineer this,
it is unclear which of the two interpretations of the shadow RAM register
operation is correct.
The 16 kB interpretation appears to work fine right now but it may be wrong,
so I left the 32 kB interpretation in as well.
*/
#ifdef INTERPRETATION_32KB
#define SHADOW_SIZE 0x00008000
#else
#define SHADOW_SIZE 0x00004000
#endif
static void
ali1409_shadow_recalc(ali1409_t *dev)
{
uint32_t base = 0x000c0000;
for (uint8_t i = 0; i < 4; i++) {
uint8_t reg = 0x08 + i;
#ifdef INTERPRETATION_32KB
for (uint8_t j = 0; j < 4; j += 2) {
uint8_t mask = (0x03 << j);
#else
for (uint8_t j = 0; j < 4; j++) {
uint8_t mask = (0x01 << j);
#endif
uint8_t r_on = dev->regs[reg] & 0x10;
uint8_t w_on = dev->regs[reg] & 0x20;
uint8_t val = dev->regs[reg] & mask;
uint8_t xor = (dev->shadow[i] ^ dev->regs[reg]) & (mask | 0x30);
int read = r_on ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
int write = w_on ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
if (xor) {
#ifdef INTERPRETATION_32KB
switch (val >> j) {
case 0x00:
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0x01:
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | write);
break;
case 0x02:
mem_set_mem_state_both(base, SHADOW_SIZE, read | write);
break;
case 0x03:
mem_set_mem_state_both(base, SHADOW_SIZE, read | MEM_WRITE_EXTANY);
break;
}
#else
switch (val >> j) {
case 0x00:
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0x01:
mem_set_mem_state_both(base, SHADOW_SIZE, read | write);
break;
}
#endif
}
base += SHADOW_SIZE;
}
dev->shadow[i] = dev->regs[reg];
}
flushmmucache_nopc();
}
static void
ali1409_write(uint16_t addr, uint8_t val, void *priv)
{
ali1409_t *dev = (ali1409_t *) priv;
ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val);
ali1409_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
if (addr & 1) {
if (dev->cfg_locked) {
if (dev->last_reg == 0x14 && val == 0x09)
dev->cfg_locked = 0;
if (addr & 0x0001) {
if (dev->cfg_locked) {
if ((dev->last_reg == 0x14) && (val == 0x09))
dev->cfg_locked = 0;
dev->last_reg = val;
return;
}
dev->last_reg = val;
return;
}
if (dev->index == 0xff && val == 0xff)
dev->cfg_locked = 1;
else {
ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs);
dev->regs[dev->index] = val;
/* It appears writing anything at all to register 0xFF locks it again. */
if (dev->index == 0xff)
dev->cfg_locked = 1;
else if (dev->index < 0x44) {
ali1409_log("[%04X:%08X] [W] Register %02X = %02X\n", CS, cpu_state.pc, dev->index, val);
switch (dev->index) {
case 0xa:
switch ((val >> 4) & 3) {
case 0:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
case 1:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
break;
case 2:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
if (dev->index < 0x10) {
dev->regs[dev->index] = val;
/*
There are still a lot of unknown here, but unfortunately, this is
as far as I have been able to come with two BIOS'es that are
available (the Acer 100T and an AMI Color dated 07/07/91).
*/
switch (dev->index) {
case 0x02:
/*
- Bit 7: The RAS address hold time:
- 0: 1/2 T;
- 1: 1 T.
- Bits 6-4: The RAS precharge time:
- 0, 0, 0: 1.5 T;
- 0, 0, 1: 2 T;
- 0, 1, 0: 2.5 T;
- 0, 1, 1: 3 T;
- 1, 0, 0: 3.5 T;
- 1, 0, 1: 4 T;
- 1, 1, 0: Reserved;
- 1, 1, 1: Reserved.
- Bit 3: Early miss cycle:
- 0: Disabled;
- 1: Enabled.
*/
break;
case 0x03:
/*
- Bit 6: CAS pulse for read cycle:
- 0: 1 T;
- 1: 1.5 T or 2 T.
I can not get the 2.5 T or 3 T setting to apply so
I have no idea what bit governs that.
- Bits 5, 4: CAS pulse for write cycle:
- 0, 0: 0.5 T or 1 T;
- 0, 1: 1.5 T or 2 T;
- 1, 0: 2.5 T or 3 T;
- 1, 1: Reserved.
- Bit 3: CAS active for read cycle:
- 0: Disabled;
- 1: Enabled.
- Bit 2: CAS active for write cycle:
- 0: Disabled;
- 1: Enabled.
*/
break;
case 0x06:
/*
- Bits 6-4: Clock divider:
- 0, 0, 0: / 2;
- 0, 0, 1: / 4;
- 0, 1, 0: / 8;
- 0, 1, 1: Reserved;
- 1, 0, 0: / 3;
- 1, 0, 1: / 6;
- 1, 1, 0: / 5;
- 1, 1, 1: / 10.
*/
switch ((val >> 4) & 7) {
default:
case 3: /* Reserved */
cpu_set_isa_speed(7159091);
break;
case 0xb:
switch ((val >> 4) & 3) {
case 0:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 2:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
case 0:
cpu_set_isa_speed(cpu_busspeed / 2);
break;
case 1:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 2:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 4:
cpu_set_isa_speed(cpu_busspeed / 3);
break;
case 5:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 6:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 7:
cpu_set_isa_speed(cpu_busspeed / 10);
break;
}
break;
case 0x08 ... 0x0b:
ali1409_shadow_recalc(dev);
break;
case 0x0c:
/*
This appears to be turbo in bit 4 (1 = on, 0 = off),
and bus speed in the rest of the bits.
*/
break;
case 0x0d:
cpu_cache_ext_enabled = !!(val & 0x08);
cpu_update_waitstates();
break;
}
} else
dev->index = val;
}
}
} else
dev->index = val;
}
static uint8_t
ali1409_read(uint16_t addr, void *priv)
{
ali1409_log ("reading at %02X\n",addr);
const ali1409_t *dev = (ali1409_t *) priv;
uint8_t ret = 0xff;
if (dev->cfg_locked)
ret = 0xff;
if (addr & 1) {
if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix)
ret = 0xff;
else if (addr & 0x0001) {
if (dev->index < 0x44)
ret = dev->regs[dev->index];
} else
ret = dev->index;
} else
ret = dev->index;
ali1409_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
return ret;
}
@@ -166,17 +313,16 @@ ali1409_init(UNUSED(const device_t *info))
dev->cfg_locked = 1;
/* M1409 Ports:
22h Index Port
23h Data Port
*/
ali1409_log ("Bus speed: %i", cpu_busspeed);
ali1409_log("Bus speed: %i\n", cpu_busspeed);
io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
dev->regs[0x0f] = 0x08;
cpu_set_isa_speed(7159091);
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
return dev;
}

289
src/chipset/cs8220.c Normal file
View File

@@ -0,0 +1,289 @@
/*
* 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.
*
* Emulation of C&T CS8220 ("PC/AT") chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/chipset.h>
typedef struct {
uint32_t virt;
uint32_t phys;
uint32_t size;
mem_mapping_t mapping;
} ram_bank_t;
typedef struct {
uint8_t regs[3];
ram_bank_t ram_banks[3];
} cs8220_t;
static uint8_t
cs8220_mem_read(uint32_t addr, void *priv)
{
ram_bank_t *dev = (ram_bank_t *) priv;
uint8_t ret = 0xff;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ret = ram[addr];
return ret;
}
static uint16_t
cs8220_mem_readw(uint32_t addr, void *priv)
{
ram_bank_t *dev = (ram_bank_t *) priv;
uint16_t ret = 0xffff;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ret = *(uint16_t *) &(ram[addr]);
return ret;
}
static void
cs8220_mem_write(uint32_t addr, uint8_t val, void *priv)
{
ram_bank_t *dev = (ram_bank_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ram[addr] = val;
}
static void
cs8220_mem_writew(uint32_t addr, uint16_t val, void *priv)
{
ram_bank_t *dev = (ram_bank_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
*(uint16_t *) &(ram[addr]) = val;
}
static uint8_t
cs8220_in(uint16_t port, void *priv) {
cs8220_t *dev = (cs8220_t *) priv;
uint8_t ret = 0xff;
switch (port) {
case 0x00a4 ... 0x00a5:
ret = dev->regs[port & 0x0001];
break;
case 0x00ab:
ret = dev->regs[2];
break;
}
return ret;
}
static void
cs8220_out(uint16_t port, uint8_t val, void *priv) {
cs8220_t *dev = (cs8220_t *) priv;
switch (port) {
case 0x00a4:
dev->regs[0] = val;
mem_a20_alt = val & 0x40;
mem_a20_recalc();
break;
case 0x00a5:
dev->regs[1] = val;
if (val & 0x01) {
mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, 0x000040000);
mem_mapping_disable(&dev->ram_banks[1].mapping);
mem_mapping_disable(&dev->ram_banks[2].mapping);
} else {
mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, dev->ram_banks[0].size);
mem_mapping_enable(&dev->ram_banks[1].mapping);
mem_mapping_enable(&dev->ram_banks[2].mapping);
}
break;
case 0x00ab:
dev->regs[2] = val;
break;
}
}
static void
cs8220_close(void *priv)
{
cs8220_t *dev = (cs8220_t *) priv;
free(dev);
}
static void *
cs8220_init(UNUSED(const device_t *info))
{
cs8220_t *dev = (cs8220_t *) calloc(1, sizeof(cs8220_t));
mem_mapping_disable(&ram_low_mapping);
mem_mapping_disable(&ram_mid_mapping);
mem_mapping_disable(&ram_high_mapping);
/*
Dell System 200: 640 kB soldered on-board, any other RAM is expansion.
*/
if (!strcmp(machine_get_internal_name(), "dells200")) switch (mem_size) {
default:
dev->ram_banks[2].virt = 0x00100000;
dev->ram_banks[2].phys = 0x000a0000;
dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000;
fallthrough;
case 640:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
dev->ram_banks[1].virt = 0x00080000;
dev->ram_banks[1].phys = 0x00080000;
dev->ram_banks[1].size = 0x00020000;
break;
/*
We are limited to steps of equal size, so we have to simulate some
memory expansions to work around the chipset's limits.
*/
} else switch (mem_size) {
case 256:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00020000;
dev->ram_banks[1].virt = 0x00020000;
dev->ram_banks[1].phys = 0x00020000;
dev->ram_banks[1].size = 0x00020000;
break;
case 384:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00020000;
/* Pretend there's a 128k expansion. */
dev->ram_banks[2].virt = 0x00020000;
dev->ram_banks[2].phys = 0x00020000;
dev->ram_banks[2].size = 0x00040000;
break;
case 512:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
break;
default:
dev->ram_banks[2].virt = 0x00100000;
dev->ram_banks[2].phys = 0x000a0000;
dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000;
fallthrough;
case 640:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
dev->ram_banks[1].virt = 0x00080000;
dev->ram_banks[1].phys = 0x00080000;
dev->ram_banks[1].size = 0x00020000;
break;
case 768:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
dev->ram_banks[1].virt = 0x00080000;
dev->ram_banks[1].phys = 0x00080000;
dev->ram_banks[1].size = 0x00020000;
/* Pretend there's a 128k expansion. */
dev->ram_banks[2].virt = 0x00100000;
dev->ram_banks[2].phys = 0x00080000;
dev->ram_banks[2].size = 0x00020000;
break;
case 896:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
dev->ram_banks[1].virt = 0x00080000;
dev->ram_banks[1].phys = 0x00080000;
dev->ram_banks[1].size = 0x00020000;
/* Pretend there's a 256k expansion. */
dev->ram_banks[2].virt = 0x00100000;
dev->ram_banks[2].phys = 0x00080000;
dev->ram_banks[2].size = 0x00040000;
break;
case 1024:
dev->ram_banks[0].virt = 0x00000000;
dev->ram_banks[0].phys = 0x00000000;
dev->ram_banks[0].size = 0x00080000;
dev->ram_banks[1].virt = 0x00100000;
dev->ram_banks[1].phys = 0x00080000;
dev->ram_banks[1].size = 0x00080000;
break;
}
if (dev->ram_banks[0].size > 0x00000000)
mem_mapping_add(&dev->ram_banks[0].mapping, dev->ram_banks[0].virt, dev->ram_banks[0].size,
cs8220_mem_read, cs8220_mem_readw, NULL,
cs8220_mem_write, cs8220_mem_writew, NULL,
ram + dev->ram_banks[0].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[0]));
if (dev->ram_banks[1].size > 0x00000000)
mem_mapping_add(&dev->ram_banks[1].mapping, dev->ram_banks[1].virt, dev->ram_banks[1].size,
cs8220_mem_read, cs8220_mem_readw, NULL,
cs8220_mem_write, cs8220_mem_writew, NULL,
ram + dev->ram_banks[1].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[1]));
if (dev->ram_banks[2].size > 0x00000000)
mem_mapping_add(&dev->ram_banks[2].mapping, dev->ram_banks[2].virt, dev->ram_banks[2].size,
cs8220_mem_read, cs8220_mem_readw, NULL,
cs8220_mem_write, cs8220_mem_writew, NULL,
ram + dev->ram_banks[2].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[2]));
io_sethandler(0x00a4, 0x0002,
cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev);
io_sethandler(0x00ab, 0x0001,
cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev);
return dev;
}
const device_t cs8220_device = {
.name = "C&T CS8220 (PC/AT)",
.internal_name = "cs8220",
.flags = 0,
.local = 0,
.init = cs8220_init,
.close = cs8220_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1013,7 +1013,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430TX:
if (!dev->smram_locked) {
i4x0_smram_handler_phase0(dev);
regs[0x71] = (regs[0x71] & 0x20) | (val & 0xdf);
regs[0x71] = (regs[0x71] & 0x60) | (val & 0x9f);
regs[0x71] &= (val & 0x40);
i4x0_smram_handler_phase1(dev);
}
break;
@@ -1041,9 +1042,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x72] = (val & 0x7f);
else
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
regs[0x72] &= 0xbf;
if (val & 0x08) {
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
regs[0x72] &= 0xbf;
}
}
} else {
if (dev->smram_locked)
@@ -1577,6 +1580,8 @@ i4x0_reset(void *priv)
dev->regs[0x68 + i] = 0x00;
}
dev->smram_locked = 0;
if (dev->type >= INTEL_430FX) {
dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */
i4x0_write(0, 0x72, 0x02, priv);

View File

@@ -73,26 +73,24 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0x069:
dev->reg_069 = val;
/*
* Unfortunately, if triggered, the BIOS remapping function fails causing
* a fatal error. Therefore, this code section is currently commented.
*/
#if 0
if (val & 1) {
mem_remap_top(0);
if (val == 0x01) {
/*
* Set the register to 7 or above for the BIOS to trigger the
* memory remapping function if shadowing is active.
*/
dev->reg_069 = 0x7;
dev->reg_069 = 0x07;
}
if (val & 8) {
if (val & 0x08) {
/*
* Activate shadowing for region e0000-fffff
*/
mem_remap_top(256);
mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
mem_remap_top(384);
mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
#endif
break;
default:
break;
@@ -143,7 +141,7 @@ olivetti_eva_init(UNUSED(const device_t *info))
dev->reg_067 = 0x00;
/* RAM enable registers */
dev->reg_069 = 0x0;
dev->reg_069 = 0x00;
io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
@@ -152,13 +150,6 @@ olivetti_eva_init(UNUSED(const device_t *info))
/* When shadowing is not enabled in BIOS, all upper memory is available as XMS */
mem_remap_top(384);
/*
* Default settings when NVRAM is cleared activate shadowing.
* Thus, to avoid boot errors, remap only 256k from UMB to XMS.
* Remove this block once BIOS memory remapping works.
*/
mem_remap_top(256);
return dev;
}

View File

@@ -1177,7 +1177,7 @@ scamp_init(UNUSED(const device_t *info))
dev->mem_flags[i] = MEM_FLAG_READ | MEM_FLAG_WRITE;
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_RW);
if (i >= 60)
if (i >= 56)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
}
}

View File

@@ -270,6 +270,8 @@ hb4_smram(hb4_t *dev)
}
umc_smram_recalc(dev->smram_base >> 12, 1);
flushmmucache();
}
static void
@@ -398,55 +400,6 @@ hb4_close(void *priv)
free(dev);
}
static void
ims8848_write(uint16_t addr, uint8_t val, void *priv)
{
hb4_t *dev = (hb4_t *) priv;
switch (addr) {
case 0x22:
dev->idx = val;
break;
case 0x23:
if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0)))
dev->access_data = 1;
break;
case 0x24:
if (dev->access_data)
dev->access_data = 0;
break;
default:
break;
}
}
static uint8_t
ims8848_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
hb4_t *dev = (hb4_t *) priv;
switch (addr) {
case 0x22:
ret = dev->idx;
break;
case 0x23:
ret = (dev->idx >> 4) | (dev->idx << 4);
break;
case 0x24:
if (dev->access_data) {
ret = dev->pci_conf[dev->idx];
dev->access_data = 0;
}
break;
default:
break;
}
return ret;
}
static void *
hb4_init(UNUSED(const device_t *info))
{
@@ -463,8 +416,6 @@ hb4_init(UNUSED(const device_t *info))
dev->smram_base = 0x000a0000;
hb4_reset(dev);
io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev);
return dev;
}

View File

@@ -4264,7 +4264,7 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
cyrix_addr = val;
else if (addr < 0xf1) switch (cyrix_addr) {
default:
if (cyrix_addr >= 0xc0)
if ((cyrix_addr >= 0xc0) && (cyrix_addr != 0xff))
fatal("Writing unimplemented Cyrix register %02X\n", cyrix_addr);
break;

View File

@@ -830,7 +830,9 @@ write_p2(atkbc_t *dev, uint8_t val)
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw"))
if ((kbc_ven == KBC_VEN_ALI) ||
!strcmp(machine_get_internal_name(), "spc7700plw") ||
!strcmp(machine_get_internal_name(), "pl4600c"))
smbase = 0x00030000;
/* Yes, this is a hack, but until someone gets ahold of the real PCD-2L
@@ -1077,7 +1079,14 @@ write_cmd_generic(void *priv, uint8_t val)
/* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */
if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN))
fixed_bits |= 0x40;
if (kbc_ven == KBC_VEN_IBM_PS1) {
if (!strcmp(machine_get_internal_name(), "dells333sl")) {
/*
Dell System 333s/L:
- Bit 5: Stuck in reboot loop if clear.
*/
uint8_t p1 = 0x20 | (video_is_mda() ? 0x40 : 0x00);
kbc_delay_to_ob(dev, p1, 0, 0x00);
} else if (kbc_ven == KBC_VEN_IBM_PS1) {
current_drive = fdc_get_current_drive();
/* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */
kbc_delay_to_ob(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00),
@@ -1112,7 +1121,7 @@ write_cmd_generic(void *priv, uint8_t val)
Dell 466/NP:
- Bit 2: Keyboard fuse (must be set);
- Bit 4: Password disable jumper (must be clear);
- Bit 5: Manufacturing jumper (must be set);
- Bit 5: Manufacturing jumper (must be set).
*/
uint8_t p1 = 0x24;
kbc_delay_to_ob(dev, p1, 0, 0x00);
@@ -1121,7 +1130,7 @@ write_cmd_generic(void *priv, uint8_t val)
Dell OptiPlex GXL/GXM:
- Bit 3: Password disable jumper (must be clear);
- Bit 4: Keyboard fuse (must be set);
- Bit 5: Manufacturing jumper (must be set);
- Bit 5: Manufacturing jumper (must be set).
*/
uint8_t p1 = 0x30;
kbc_delay_to_ob(dev, p1, 0, 0x00);

View File

@@ -87,6 +87,14 @@ pci_bridge_set_ctl(void *priv, uint8_t ctl)
dev->ctl = ctl;
}
uint8_t
pci_bridge_get_bus_index(void *priv)
{
pci_bridge_t *dev = (pci_bridge_t *) priv;
return dev->bus_index;
}
static void
pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
@@ -513,11 +521,9 @@ static void *
pci_bridge_init(const device_t *info)
{
uint8_t interrupts[4];
uint8_t interrupt_count;
uint8_t interrupt_mask;
uint8_t add_type;
uint8_t slot_count;
uint8_t dell_slots[3] = { 0x09, 0x0a, 0x0b };
uint8_t dell_interrupts[3][4] = { { 1, 2, 3, 4 }, { 4, 2, 1, 3 }, { 1, 3, 4, 2 } };
pci_bridge_t *dev = (pci_bridge_t *) calloc(1, sizeof(pci_bridge_t));
@@ -527,40 +533,35 @@ pci_bridge_init(const device_t *info)
pci_bridge_reset(dev);
if (info->local == PCI_BRIDGE_DEC_21152)
pci_add_card(PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev, &dev->slot);
else
pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot);
interrupt_count = sizeof(interrupts);
interrupt_mask = interrupt_count - 1;
interrupt_mask = sizeof(interrupts) - 1;
if (dev->slot < 32) {
for (uint8_t i = 0; i < interrupt_count; i++)
for (uint8_t i = 0; i <= interrupt_mask; i++)
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
}
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n",
dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0],
interrupts[1], interrupts[2], interrupts[3]);
if (info->local == PCI_BRIDGE_DEC_21150)
if (info->local == PCI_BRIDGE_DEC_21150) {
slot_count = 9; /* 9 bus masters */
else if (info->local == PCI_BRIDGE_DEC_21152)
slot_count = 3; /* 3 bus masters */
else
add_type = PCI_ADD_NORMAL;
} else if (info->local == PCI_BRIDGE_DEC_21152) {
slot_count = 0; /* 4 bus masters, but slots are added by the Dell machines */
add_type = PCI_ADD_BRIDGE;
} else {
slot_count = 1; /* AGP bridges always have 1 slot */
add_type = PCI_ADD_AGPBRIDGE;
}
pci_add_bridge(add_type, pci_bridge_read, pci_bridge_write, dev, &dev->slot);
for (uint8_t i = 0; i < slot_count; i++) {
uint8_t slot = i;
if (info->local == PCI_BRIDGE_DEC_21152) {
slot = dell_slots[i];
memcpy(interrupts, dell_interrupts[i], 4);
}
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n",
dev->bus_index, slot, interrupts[i & interrupt_mask],
dev->bus_index, i, interrupts[i & interrupt_mask],
interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask],
interrupts[(i + 3) & interrupt_mask]);
pci_register_bus_slot(dev->bus_index, slot, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
interrupts[i & interrupt_mask],
interrupts[(i + 1) & interrupt_mask],
interrupts[(i + 2) & interrupt_mask],

View File

@@ -36,6 +36,7 @@ static uint16_t postcard_port;
static uint8_t postcard_written[POSTCARDS_NUM];
static uint8_t postcard_ports_num = 1;
static uint8_t postcard_prev_codes[POSTCARDS_NUM];
static uint8_t postcard_dell_mode = 0;
static char postcard_prev_diags[5] = { 0 };
#define UISTR_LEN 32
static char postcard_str[UISTR_LEN]; /* UI output string */
@@ -99,30 +100,23 @@ postcard_setui(void)
ps[1][0], ps[1][1], ps[1][2], ps[1][3]);
break;
}
} else if (strstr(machines[machine].name, " Dell ") &&
(machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX)) {
char dell_diags[10] = { 0 };
if (!postcard_written[1])
snprintf(dell_diags, sizeof(dell_diags), "---- ----");
else if (postcard_written[1] == 1)
snprintf(dell_diags, sizeof(dell_diags), "%s ----", postcard_diags);
else
snprintf(dell_diags, sizeof(dell_diags), "%s %s", postcard_diags, postcard_prev_diags);
if (!postcard_written[0])
snprintf(postcard_str, sizeof(postcard_str), "POST: -- -- %s", dell_diags);
else if (postcard_written[0] == 1)
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X -- %s", postcard_codes[0], dell_diags);
else
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X %s", postcard_codes[0], postcard_prev_codes[0], dell_diags);
} else {
char dell_diags[11] = { 0 };
if (postcard_dell_mode) {
if (!postcard_written[1])
snprintf(dell_diags, sizeof(dell_diags), " ---- ----");
else if (postcard_written[1] == 1)
snprintf(dell_diags, sizeof(dell_diags), " %s ----", postcard_diags);
else
snprintf(dell_diags, sizeof(dell_diags), " %s %s", postcard_diags, postcard_prev_diags);
}
if (!postcard_written[0])
snprintf(postcard_str, sizeof(postcard_str), "POST: -- --");
snprintf(postcard_str, sizeof(postcard_str), "POST: -- --%s", dell_diags);
else if (postcard_written[0] == 1)
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --", postcard_codes[0]);
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --%s", postcard_codes[0], dell_diags);
else
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X", postcard_codes[0], postcard_prev_codes[0]);
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X%s", postcard_codes[0], postcard_prev_codes[0], dell_diags);
}
ui_sb_bugui(postcard_str);
@@ -224,9 +218,10 @@ postcard_init(UNUSED(const device_t *info))
io_sethandler(postcard_port, postcard_ports_num,
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
if (strstr(machines[machine].name, " Dell ") &&
(machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX))
io_sethandler(0x00e0, 0x0001,
postcard_dell_mode = strstr(machines[machine].name, " Dell ") &&
(machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX);
if (postcard_dell_mode)
io_sethandler(is486 ? 0x00e0 : 0x00e4, 0x0001,
NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL);
return postcard_write;

View File

@@ -55,6 +55,7 @@ extern const device_t neat_sx_device;
extern const device_t scat_device;
extern const device_t scat_4_device;
extern const device_t scat_sx_device;
extern const device_t cs8220_device;
extern const device_t cs8230_device;
extern const device_t cs4031_device;
@@ -112,6 +113,9 @@ extern const device_t slc90e66_device;
extern const device_t ioapic_device;
/* Olivetti */
extern const device_t olivetti_eva_device;
/* OPTi */
extern const device_t opti283_device;
extern const device_t opti291_device;
@@ -203,8 +207,4 @@ extern const device_t nec_mate_unk_device;
extern const device_t phoenix_486_jumper_device;
extern const device_t phoenix_486_jumper_pci_device;
#ifdef USE_OLIVETTI
extern const device_t olivetti_eva_device;
#endif /* USE_OLIVETTI */
#endif /*EMU_CHIPSET_H*/

View File

@@ -211,6 +211,7 @@ enum {
MACHINE_CHIPSET_SCAT_SX,
MACHINE_CHIPSET_NEAT,
MACHINE_CHIPSET_NEAT_SX,
MACHINE_CHIPSET_CT_AT,
MACHINE_CHIPSET_CT_386,
MACHINE_CHIPSET_CT_CS4031,
MACHINE_CHIPSET_CONTAQ_82C596,
@@ -447,9 +448,6 @@ extern int machine_at_pb286_init(const machine_t *);
extern int machine_at_siemens_init(const machine_t *); // Siemens PCD-2L. N82330 discrete machine. It segfaults in some places
extern int machine_at_wellamerastar_init(const machine_t *); // Wells American A*Star with custom award BIOS
#ifdef USE_OPEN_AT
extern int machine_at_openat_init(const machine_t *);
#endif /* USE_OPEN_AT */
/* m_at_286_386sx.c */
extern int machine_at_tg286m_init(const machine_t *);
@@ -475,19 +473,19 @@ extern int machine_at_spc4216p_init(const machine_t *);
extern int machine_at_spc4620p_init(const machine_t *);
extern int machine_at_kmxc02_init(const machine_t *);
extern int machine_at_deskmaster286_init(const machine_t *);
extern int machine_at_dells200_init(const machine_t *);
extern int machine_at_pc8_init(const machine_t *);
extern int machine_at_3302_init(const machine_t *);
#ifdef USE_OLIVETTI
extern int machine_at_m290_init(const machine_t *);
#endif /* USE_OLIVETTI */
extern int machine_at_shuttle386sx_init(const machine_t *);
extern int machine_at_adi386sx_init(const machine_t *);
extern int machine_at_cmdsl386sx16_init(const machine_t *);
extern int machine_at_cmdsl386sx25_init(const machine_t *);
extern int machine_at_dataexpert386sx_init(const machine_t *);
extern int machine_at_dells333sl_init(const machine_t *);
extern int machine_at_if386sx_init(const machine_t *);
extern int machine_at_spc6033p_init(const machine_t *);
extern int machine_at_wd76c10_init(const machine_t *);
@@ -515,7 +513,7 @@ extern int machine_at_ga486l_init(const machine_t *);
extern int machine_at_cougar_init(const machine_t *);
extern int machine_at_acc386_init(const machine_t *);
extern int machine_at_asus386_3364k_init(const machine_t *);
extern int machine_at_asus3863364k_init(const machine_t *);
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 *);
@@ -673,7 +671,7 @@ extern int machine_at_tek932_init(const machine_t *);
extern int machine_at_acerv30_init(const machine_t *);
extern int machine_at_apollo_init(const machine_t *);
extern int machine_at_optiplex_gxl_init(const machine_t *);
extern int machine_at_optiplexgxl_init(const machine_t *);
extern int machine_at_zappa_init(const machine_t *);
extern int machine_at_powermatev_init(const machine_t *);
extern int machine_at_hawk_init(const machine_t *);
@@ -724,6 +722,8 @@ extern int machine_at_vectra54_init(const machine_t *);
extern int machine_at_5sbm2_init(const machine_t *);
/* m_at_socket7.c */
extern void machine_at_optiplex_21152_init(void);
extern int machine_at_acerv35n_init(const machine_t *);
extern int machine_at_p55t2p4_init(const machine_t *);
extern int machine_at_m7shi_init(const machine_t *);
@@ -753,12 +753,10 @@ extern int machine_at_gw2kte_init(const machine_t *);
extern int machine_at_ma23c_init(const machine_t *);
extern int machine_at_nupro592_init(const machine_t *);
extern int machine_at_tx97_init(const machine_t *);
extern int machine_at_optiplex_gn_init(const machine_t *);
#ifdef USE_AN430TX
extern int machine_at_an430tx_init(const machine_t *);
#endif /* USE_AN430TX */
extern int machine_at_optiplexgn_init(const machine_t *);
extern int machine_at_ym430tx_init(const machine_t *);
extern int machine_at_thunderbolt_init(const machine_t *);
extern int machine_at_an430tx_init(const machine_t *);
extern int machine_at_mb540n_init(const machine_t *);
extern int machine_at_56a5_init(const machine_t *);
extern int machine_at_p5mms98_init(const machine_t *);
@@ -824,7 +822,7 @@ extern int machine_at_p65up5_cpknd_init(const machine_t *);
extern int machine_at_kn97_init(const machine_t *);
extern int machine_at_lx6_init(const machine_t *);
extern int machine_at_optiplex_gxa_init(const machine_t *);
extern int machine_at_optiplexgxa_init(const machine_t *);
extern int machine_at_spitfire_init(const machine_t *);
extern int machine_at_ma30d_init(const machine_t *);

View File

@@ -283,6 +283,7 @@ extern void pci_init(int flags);
/* PCI bridge stuff. */
extern void pci_bridge_set_ctl(void *priv, uint8_t ctl);
extern uint8_t pci_bridge_get_bus_index(void *priv);
#ifdef EMU_DEVICE_H
extern const device_t dec21150_device;

View File

@@ -0,0 +1,42 @@
/*
* 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.
*
* Mindscape Music Board emulation.
*
* Authors: Roy Baer, <https://pcem-emulator.co.uk/>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2025 Roy Baer.
* Copyright 2025 Jasmine Iwanek.
*/
#ifndef _SOUND_SND_MMB_H_
#define _SOUND_SND_MMB_H_
#define MMB_FREQ FREQ_48000
/* NOTE:
* The constant clock rate is a deviation from the real hardware which has
* the design flaw that the clock rate is always half the ISA bus clock.
*/
#define MMB_CLOCK 2386364
typedef struct ay_3_891x_s {
uint8_t index;
uint8_t regs[16];
struct ayumi chip;
} ay_3_891x_t;
typedef struct mmb_s {
ay_3_891x_t first;
ay_3_891x_t second;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
} mmb_t;
#endif /* _SOUND_SND_MMB_H_ */

View File

@@ -197,6 +197,7 @@ extern const device_t ct5880_onboard_device;
/* Gravis UltraSound and UltraSound Max */
extern const device_t gus_device;
extern const device_t gus_max_device;
/* IBM PS/1 Audio Card */
extern const device_t ps1snd_device;
@@ -205,6 +206,9 @@ extern const device_t ps1snd_device;
extern const device_t ssi2001_device;
extern const device_t entertainer_device;
/* Mindscape Music Board */
extern const device_t mmb_device;
/* Pro Audio Spectrum Plus, 16, and 16D */
extern const device_t pasplus_device;
extern const device_t pas16_device;

View File

@@ -36,6 +36,10 @@ using atomic_int = std::atomic_int;
#define getcolg(color) (((color) >> 8) & 0xFF)
#define getcolb(color) ((color) & 0xFF)
#ifdef __cplusplus
extern "C" {
#endif
enum {
VID_NONE = 0,
VID_INTERNAL
@@ -49,10 +53,6 @@ enum {
FULLSCR_SCALE_INT43
};
#ifdef __cplusplus
extern "C" {
#endif
enum {
VIDEO_ISA = 0,
VIDEO_MCA,
@@ -71,6 +71,11 @@ enum {
#define VIDEO_FLAG_TYPE_SECONDARY VIDEO_FLAG_TYPE_SPECIAL
#define FONT_IBM_MDA_437_PATH "roms/video/mda/mda.rom"
#define FONT_IBM_MDA_437_NORDIC_PATH "roms/video/mda/4733197.bin"
#define FONT_KAM_PATH "roms/video/mda/kam.bin"
#define FONT_KAMCL16_PATH "roms/video/mda/kamcl16.bin"
typedef struct video_timings_t {
int type;
int write_b;
@@ -189,15 +194,15 @@ extern uint32_t pal_lookup[256];
#endif
extern int video_fullscreen;
extern int video_fullscreen_scale;
extern uint8_t fontdat[2048][8];
extern uint8_t fontdatm[2048][16];
extern uint8_t fontdat2[2048][8];
extern uint8_t fontdatm2[2048][16];
extern uint8_t fontdatw[512][32];
extern uint8_t fontdat8x12[256][16];
extern uint8_t fontdat12x18[256][36];
extern dbcs_font_t *fontdatksc5601;
extern dbcs_font_t *fontdatksc5601_user;
extern uint8_t fontdat[2048][8]; /* IBM CGA font */
extern uint8_t fontdatm[2048][16]; /* IBM MDA font */
extern uint8_t fontdat2[2048][8]; /* IBM CGA 2nd instance font */
extern uint8_t fontdatm2[2048][16]; /* IBM MDA 2nd instance font */
extern uint8_t fontdatw[512][32]; /* Wyse700 font */
extern uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
extern uint8_t fontdat12x18[256][36]; /* IM1024 font */
extern dbcs_font_t *fontdatksc5601; /* Korean KSC-5601 font */
extern dbcs_font_t *fontdatksc5601_user; /* Korean KSC-5601 user defined font */
extern uint32_t *video_6to8;
extern uint32_t *video_8togs;
extern uint32_t *video_8to32;
@@ -277,8 +282,8 @@ extern uint8_t video_force_resize_get_monitor(int monitor_index);
extern void video_force_resize_set_monitor(uint8_t res, int monitor_index);
extern void video_update_timing(void);
extern void loadfont_ex(char *s, int format, int offset);
extern void loadfont(char *s, int format);
extern void loadfont_ex(char *fn, int format, int offset);
extern void loadfont(char *fn, int format);
extern int get_actual_size_x(void);
extern int get_actual_size_y(void);
@@ -351,6 +356,7 @@ extern const device_t gd5401_isa_device;
extern const device_t gd5402_isa_device;
extern const device_t gd5402_onboard_device;
extern const device_t gd5420_isa_device;
extern const device_t gd5420_onboard_device;
extern const device_t gd5422_isa_device;
extern const device_t gd5424_vlb_device;
extern const device_t gd5426_isa_device;

View File

@@ -56,19 +56,3 @@ add_library(mch OBJECT
m_at_socket370.c
m_at_misc.c
)
if(AN430TX)
target_compile_definitions(mch PRIVATE USE_AN430TX)
endif()
if(DESKPRO386)
target_compile_definitions(mch PRIVATE USE_DESKPRO386)
endif()
if(OLIVETTI)
target_compile_definitions(mch PRIVATE USE_OLIVETTI)
endif()
if(OPEN_AT)
target_compile_definitions(mch PRIVATE USE_OPEN_AT)
endif()

View File

@@ -2936,7 +2936,7 @@ machine_amstrad_init(const machine_t *model, int type)
break;
case AMS_PC1640:
loadfont("roms/video/mda/mda.rom", 0);
loadfont(FONT_IBM_MDA_437_PATH, 0);
device_context(&vid_1640_device);
ams->language = device_get_config_int("language");
vid_init_1640(ams);

View File

@@ -388,21 +388,3 @@ machine_at_wellamerastar_init(const machine_t *model)
return ret;
}
#ifdef USE_OPEN_AT
int
machine_at_openat_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/openat/bios.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_ibm_common_init(model);
return ret;
}
#endif /* USE_OPEN_AT */

View File

@@ -37,6 +37,7 @@
#include <86box/hdc.h>
#include <86box/nvr.h>
#include <86box/port_6x.h>
#define USE_SIO_DETECT
#include <86box/sio.h>
#include <86box/serial.h>
#include <86box/video.h>
@@ -261,6 +262,30 @@ machine_at_px286_init(const machine_t *model)
return ret;
}
int
machine_at_dells200_init(const machine_t *model)
{
int ret;
ret = bios_load_interleaved("roms/machines/dells200/dellL200256_LO_@DIP28.BIN",
"roms/machines/dells200/Dell200256_HI_@DIP28.BIN",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&cs8220_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&keyboard_at_phoenix_device);
return ret;
}
int
machine_at_micronics386_init(const machine_t *model)
{
@@ -736,6 +761,75 @@ machine_at_cmdsl386sx25_init(const machine_t *model)
return ret;
}
static const device_config_t dells333sl_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "dells333sl",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "J01 (Jostens Learning Corporation OEM)", .internal_name = "dells333sl_j01", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/dells333sl/DELL386.BIN", "" } },
{ .name = "A02", .internal_name = "dells333sl", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/dells333sl/Dell_386SX_30807_UBIOS_B400_VLSI_VL82C311_Cirrus_Logic_GD5420.bin", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t dells333sl_device = {
.name = "Dell System 333s/L",
.internal_name = "dells333sl_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = dells333sl_config
};
int
machine_at_dells333sl_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);
ret = bios_load_linear(fn, 0x000e0000, 262144, 0);
memcpy(rom, &(rom[0x00020000]), 131072);
mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000);
mem_mapping_set_exec(&bios_mapping, rom);
device_context_restore();
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
machine_at_common_init_ex(model, 2);
device_add(&ide_isa_device);
device_add(&pc87311_device);
device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */
device_add(&vlsi_scamp_device);
return ret;
}
int
machine_at_dataexpert386sx_init(const machine_t *model)
{
@@ -1045,7 +1139,6 @@ machine_at_pc916sx_init(const machine_t *model)
return ret;
}
#ifdef USE_OLIVETTI
int
machine_at_m290_init(const machine_t *model)
{
@@ -1057,15 +1150,16 @@ machine_at_m290_init(const machine_t *model)
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 4);
device_add(&keyboard_at_olivetti_device);
machine_at_common_init_ex(model, 6);
device_add(&amstrad_megapc_nvr_device);
device_add(&olivetti_eva_device);
device_add(&port_6x_olivetti_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&olivetti_eva_device);
device_add(&keyboard_at_olivetti_device);
return ret;
}
#endif /* USE_OLIVETTI */

View File

@@ -73,11 +73,11 @@ machine_at_acc386_init(const machine_t *model)
}
int
machine_at_asus386_3364k_init(const machine_t *model)
machine_at_asus3863364k_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/asus386_3364k/am27c512dip28-64b53c26be3d8160533563.bin",
ret = bios_load_linear("roms/machines/asus3863364k/am27c512dip28-64b53c26be3d8160533563.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)

View File

@@ -151,11 +151,11 @@ machine_at_lx6_init(const machine_t *model)
}
int
machine_at_optiplex_gxa_init(const machine_t *model)
machine_at_optiplexgxa_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/optiplex_gxa/DELL.ROM",
ret = bios_load_linear("roms/machines/optiplexgxa/DELL.ROM",
0x000c0000, 262144, 0);
if (bios_only || !ret)
@@ -170,14 +170,14 @@ machine_at_optiplex_gxa_init(const machine_t *model)
pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0);
pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4);
pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4);
pci_register_slot(0x0F, PCI_CARD_BRIDGE, 0, 0, 0, 0);
if (sound_card_current[0] == SOUND_INTERNAL)
device_add(machine_get_snd_device(machine));
device_add(&i440lx_device);
device_add(&piix4_device);
device_add(&dec21152_device);
machine_at_optiplex_21152_init();
device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307));
device_add(&intel_flash_bxt_device);
spd_register(SPD_TYPE_SDRAM, 0x7, 256);

View File

@@ -238,11 +238,11 @@ machine_at_apollo_init(const machine_t *model)
}
int
machine_at_optiplex_gxl_init(const machine_t *model)
machine_at_optiplexgxl_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/optiplex_gxl/DELL.ROM",
ret = bios_load_linear("roms/machines/optiplexgxl/DELL.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)

View File

@@ -46,6 +46,15 @@
#include <86box/network.h>
#include <86box/pci.h>
void
machine_at_optiplex_21152_init(void)
{
uint8_t bus_index = pci_bridge_get_bus_index(device_add(&dec21152_device));
pci_register_bus_slot(bus_index, 0x09, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_bus_slot(bus_index, 0x0a, PCI_CARD_NORMAL, 4, 2, 1, 3);
pci_register_bus_slot(bus_index, 0x0b, PCI_CARD_NORMAL, 1, 3, 4, 2);
}
int
machine_at_acerv35n_init(const machine_t *model)
{
@@ -970,11 +979,11 @@ machine_at_tx97_init(const machine_t *model)
}
int
machine_at_optiplex_gn_init(const machine_t *model)
machine_at_optiplexgn_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/optiplex_gn/DELL.ROM",
ret = bios_load_linear("roms/machines/optiplexgn/DELL.ROM",
0x000c0000, 262144, 0);
if (bios_only || !ret)
@@ -989,7 +998,7 @@ machine_at_optiplex_gn_init(const machine_t *model)
pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */
pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4);
pci_register_slot(0x0F, PCI_CARD_BRIDGE, 1, 2, 3, 4);
pci_register_slot(0x0F, PCI_CARD_BRIDGE, 0, 0, 0, 0);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
@@ -999,7 +1008,7 @@ machine_at_optiplex_gn_init(const machine_t *model)
device_add(&i430tx_device);
device_add(&piix4_device);
device_add(&dec21152_device);
machine_at_optiplex_21152_init();
device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307));
device_add(&intel_flash_bxt_device);
spd_register(SPD_TYPE_SDRAM, 0x3, 128);
@@ -1007,27 +1016,17 @@ machine_at_optiplex_gn_init(const machine_t *model)
return ret;
}
#ifdef USE_AN430TX
int
machine_at_an430tx_init(const machine_t *model)
{
int ret;
# if 1
ret = bios_load_linear_combined2("roms/machines/an430tx/P10-0095.BIO",
"roms/machines/an430tx/P10-0095.BI1",
"roms/machines/an430tx/P10-0095.BI2",
"roms/machines/an430tx/P10-0095.BI3",
"roms/machines/an430tx/P10-0095.RCV",
ret = bios_load_linear_combined2("roms/machines/an430tx/ANP0911A.BIO",
"roms/machines/an430tx/ANP0911A.BI1",
"roms/machines/an430tx/ANP0911A.BI2",
"roms/machines/an430tx/ANP0911A.BI3",
"roms/machines/an430tx/ANP0911A.RCV",
0x3a000, 160);
# else
ret = bios_load_linear_combined2("roms/machines/an430tx/P06-0062.BIO",
"roms/machines/an430tx/P06-0062.BI1",
"roms/machines/an430tx/P06-0062.BI2",
"roms/machines/an430tx/P06-0062.BI3",
"roms/machines/an430tx/P10-0095.RCV",
0x3a000, 160);
# endif
if (bios_only || !ret)
return ret;
@@ -1036,21 +1035,25 @@ machine_at_an430tx_init(const machine_t *model)
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */
// pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0);
device_add(&i430tx_device);
device_add(&piix4_device);
#ifdef FOLLOW_THE_SPECIFICATION
device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42I | PCX7307_PC97307));
#else
/* The technical specification says Phoenix, a real machnine HWINFO dump says AMI '5'. */
device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC97307));
#endif
device_add(&intel_flash_bxt_ami_device);
spd_register(SPD_TYPE_SDRAM, 0x3, 128);
return ret;
}
#endif /* USE_AN430TX */
int
machine_at_ym430tx_init(const machine_t *model)

View File

@@ -1541,7 +1541,7 @@ machine_pcjr_init(UNUSED(const machine_t *model))
/* Initialize the video controller. */
video_reset(gfxcard[0]);
loadfont("roms/video/mda/mda.rom", 0);
loadfont(FONT_IBM_MDA_437_PATH, 0);
device_context(&pcjr_device);
pcjr_vid_init(pcjr);
device_context_restore();

View File

@@ -8,17 +8,12 @@
*
* Handling of the emulated machines.
*
* NOTES: OpenAT wip for 286-class machine with open BIOS.
* PS2_M80-486 wip, pending receipt of TRM's for machine.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2016-2025 Miran Grca.
* Copyright 2017-2025 Fred N. van Kempen.
* Copyright 2025 Jasmine Iwanek.
*/
#include <stdio.h>
@@ -71,6 +66,7 @@ extern const device_t vendex_device;
extern const device_t c5sbm2_device;
extern const device_t sb486pv_device;
extern const device_t ap5s_device;
extern const device_t dells333sl_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -117,11 +113,12 @@ const machine_filter_t machine_chipsets[] = {
{ "ALi ALADDiN IV+", MACHINE_CHIPSET_ALI_ALADDIN_IV_PLUS },
{ "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V },
{ "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II },
{ "C&T PC/AT", MACHINE_CHIPSET_CT_AT },
{ "C&T 386/AT", MACHINE_CHIPSET_CT_386 },
{ "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT },
{ "C&T 82C236 SCATsx", MACHINE_CHIPSET_SCAT_SX },
{ "C&T CS8221 NEAT", MACHINE_CHIPSET_NEAT },
{ "C&T CS8281 NEATsx", MACHINE_CHIPSET_NEAT_SX },
{ "C&T 386", MACHINE_CHIPSET_CT_386 },
{ "C&T CS4031", MACHINE_CHIPSET_CT_CS4031 },
{ "Contaq 82C596", MACHINE_CHIPSET_CONTAQ_82C596 },
{ "Contaq 82C597", MACHINE_CHIPSET_CONTAQ_82C597 },
@@ -3095,7 +3092,6 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
#ifdef USE_OLIVETTI
/* Has Olivetti KBC firmware. */
{
.name = "[ISA] Olivetti M290",
@@ -3136,49 +3132,6 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
#endif /* USE_OLIVETTI */
#ifdef USE_OPEN_AT
/* Has IBM AT KBC firmware. */
{
.name = "[ISA] OpenAT",
.internal_name = "openat",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_DISCRETE,
.init = machine_at_openat_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.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_FLAGS_NONE,
.ram = {
.min = 256,
.max = 15872,
.step = 128
},
.nvrmask = 63,
.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
},
#endif /* USE_OPEN_AT */
/* Has IBM AT KBC firmware. */
{
.name = "[ISA] Phoenix IBM AT",
@@ -3419,6 +3372,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC
firmware. */
{
.name = "[C&T PC/AT] Dell System 200",
.internal_name = "dells200",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_CT_AT,
.init = machine_at_dells200_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.block = CPU_BLOCK_NONE,
.min_bus = 6000000,
.max_bus = 12000000,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 640,
.max = 16384,
.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 Quadtel KBC firmware. */
{
.name = "[GC103] Quadtel 286 clone",
@@ -4463,7 +4457,7 @@ const machine_t machines[] = {
.net_device = NULL
},
{
.name = "[ALI M1409] Acer 100T",
.name = "[ALi M1409] Acer 100T",
.internal_name = "acer100t",
.type = MACHINE_TYPE_386SX,
.chipset = MACHINE_CHIPSET_ALI_M1409,
@@ -4949,6 +4943,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC
firmware. */
{
.name = "[SCAMP] Dell System 333s/L",
.internal_name = "dells333sl",
.type = MACHINE_TYPE_386SX,
.chipset = MACHINE_CHIPSET_VLSI_SCAMP,
.init = machine_at_dells333sl_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386SX,
.block = CPU_BLOCK_NONE,
.min_bus = 10000000,
.max_bus = 33333333,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2,
.flags = MACHINE_IDE | MACHINE_VIDEO,
.ram = {
.min = 1024,
.max = 16384,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = &dells333sl_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5420_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/2 Type 1 KBC firmware. */
{
.name = "[SCAMP] Samsung SPC-6033P",
@@ -5239,7 +5274,7 @@ const machine_t machines[] = {
},
/* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */
{
.name = "[C&T 386] ECS 386/32",
.name = "[C&T 386/AT] ECS 386/32",
.internal_name = "ecs386",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_CT_386,
@@ -5279,7 +5314,7 @@ const machine_t machines[] = {
},
/* Has IBM AT KBC firmware. */
{
.name = "[C&T 386] Samsung SPC-6000A",
.name = "[C&T 386/AT] Samsung SPC-6000A",
.internal_name = "spc6000a",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_CT_386,
@@ -5678,10 +5713,10 @@ const machine_t machines[] = {
/* Has Award KBC firmware. */
{
.name = "[SiS 310] ASUS 386/33-64K",
.internal_name = "asus386_3364k",
.internal_name = "asus3863364k",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_SIS_310,
.init = machine_at_asus386_3364k_init,
.init = machine_at_asus3863364k_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
@@ -9429,7 +9464,7 @@ const machine_t machines[] = {
.max_multi = 2.0
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM, /* Machine has internal video: ST STPC Atlas */
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL, /* Machine has internal video: ST STPC Atlas */
.ram = {
.min = 32768,
.max = 163840,
@@ -9470,7 +9505,7 @@ const machine_t machines[] = {
.max_multi = 2.0
},
.bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */
.ram = {
.min = 32768,
.max = 163840,
@@ -9511,7 +9546,7 @@ const machine_t machines[] = {
.max_multi = 2.0
},
.bus_flags = MACHINE_PS2,
.flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */
.flags = MACHINE_IDE | MACHINE_APM | MACHINE_PCI_INTERNAL, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */
.ram = {
.min = 32768,
.max = 131072,
@@ -9552,7 +9587,7 @@ const machine_t machines[] = {
.max_multi = 2.0
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL,
.ram = {
.min = 32768,
.max = 98304,
@@ -9593,7 +9628,7 @@ const machine_t machines[] = {
.max_multi = 2.0
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_PCI_INTERNAL,
.ram = {
.min = 32768,
.max = 131072,
@@ -10556,10 +10591,10 @@ const machine_t machines[] = {
/* Has a National Semiconductor PC87332VLJ Super I/O with AMIKey 'F' KBC firmware. */
{
.name = "[i430FX] Dell OptiPlex GXL/GXM",
.internal_name = "optiplex_gxl",
.internal_name = "optiplexgxl",
.type = MACHINE_TYPE_SOCKET5,
.chipset = MACHINE_CHIPSET_INTEL_430FX,
.init = machine_at_optiplex_gxl_init,
.init = machine_at_optiplexgxl_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
@@ -13154,10 +13189,10 @@ const machine_t machines[] = {
*/
{
.name = "[i430TX] Dell OptiPlex GN+",
.internal_name = "optiplex_gn",
.internal_name = "optiplexgn",
.type = MACHINE_TYPE_SOCKET7,
.chipset = MACHINE_CHIPSET_INTEL_430TX,
.init = machine_at_optiplex_gn_init,
.init = machine_at_optiplexgn_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
@@ -13233,49 +13268,6 @@ const machine_t machines[] = {
.snd_device = &cs4236b_device,
.net_device = &pcnet_am79c973_onboard_device
},
#ifdef USE_AN430TX
/* This has the Phoenix MultiKey KBC firmware. */
{
.name = "[i430TX] Intel AN430TX (Anchorage)",
.internal_name = "an430tx",
.type = MACHINE_TYPE_SOCKET7,
.chipset = MACHINE_CHIPSET_INTEL_430TX,
.init = machine_at_an430tx_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET5_7,
.block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P,
CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L),
.min_bus = 60000000,
.max_bus = 66666667,
.min_voltage = 2800,
.max_voltage = 3520,
.min_multi = 1.5,
.max_multi = 3.5
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI,
.ram = {
.min = 8192,
.max = 262144,
.step = 8192
},
.nvrmask = 255,
.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
},
#endif /* USE_AN430TX */
/* This has the AMIKey KBC firmware, which is an updated 'F' type. */
{
.name = "[i430TX] Intel YM430TX (Yamamoto)",
@@ -13317,9 +13309,13 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* PhoenixBIOS 4.0 Rel 6.0 for 430TX, has onboard Yamaha YMF701 which is not emulated yet. */
/* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix
MultiKey/42 (version 1.38) KBC firmware. */
/*
PhoenixBIOS 4.0 Rel 6.0 for 430TX, has onboard Yamaha YMF701 which
is not emulated yet.
Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix
MultiKey/42 (version 1.38) KBC firmware.
*/
{
.name = "[i430TX] Micronics Thunderbolt",
.internal_name = "thunderbolt",
@@ -13341,7 +13337,8 @@ const machine_t machines[] = {
.max_multi = 3.5
},
.bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Yamaha YMF701-S */
/* Machine has internal sound: Yamaha YMF701-S */
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB,
.ram = {
.min = 8192,
.max = 262144,
@@ -13400,6 +13397,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* This has the Phoenix MultiKey KBC firmware. */
{
.name = "[i430TX] Packard Bell PB790",
.internal_name = "an430tx",
.type = MACHINE_TYPE_SOCKET7,
.chipset = MACHINE_CHIPSET_INTEL_430TX,
.init = machine_at_an430tx_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET5_7,
.block = CPU_BLOCK(CPU_K5, CPU_5K86, CPU_K6, CPU_K6_2, CPU_K6_2C, CPU_K6_3, CPU_K6_2P,
CPU_K6_3P, CPU_Cx6x86, CPU_Cx6x86MX, CPU_Cx6x86L),
.min_bus = 60000000,
.max_bus = 66666667,
.min_voltage = 2800,
.max_voltage = 3520,
.min_multi = 1.5,
.max_multi = 3.5
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI,
.ram = {
.min = 8192,
.max = 262144,
.step = 8192
},
.nvrmask = 255,
.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 BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior.
A picture shows a VIA VT82C42N KBC though, so it could be a case of that KBC with AMI firmware. */
{
@@ -14424,7 +14462,7 @@ const machine_t machines[] = {
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = &cs4235_device,
.snd_device = &cs4235_onboard_device,
.net_device = NULL
},
@@ -15214,10 +15252,10 @@ const machine_t machines[] = {
firmwares: AMI '5' MegaKey, Phoenix MultiKey/42 1.37, or Phoenix MultiKey/42i 4.16. */
{
.name = "[i440LX] Dell OptiPlex GXa",
.internal_name = "optiplex_gxa",
.internal_name = "optiplexgxa",
.type = MACHINE_TYPE_SLOT1,
.chipset = MACHINE_CHIPSET_INTEL_440LX,
.init = machine_at_optiplex_gxa_init,
.init = machine_at_optiplexgxa_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,

View File

@@ -2994,10 +2994,12 @@ mem_init(void)
}
static void
umc_page_recalc(uint32_t c, int set)
umc_page_recalc(uint32_t c, uint32_t phys, int set)
{
uint32_t target = set ? phys : c;
if (set) {
pages[c].mem = &ram[(c & 0xff) << 12];
pages[c].mem = &ram[(target & 0xff) << 12];
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
@@ -3010,8 +3012,8 @@ umc_page_recalc(uint32_t c, int set)
#ifdef USE_NEW_DYNAREC
pages[c].evict_prev = EVICT_NOT_IN_LIST;
pages[c].byte_dirty_mask = &byte_dirty_mask[(c & 0xff) * 64];
pages[c].byte_code_present_mask = &byte_code_present_mask[(c & 0xff) * 64];
pages[c].byte_dirty_mask = &byte_dirty_mask[(target & 0xff) * 64];
pages[c].byte_code_present_mask = &byte_code_present_mask[(target & 0xff) * 64];
#endif
}
@@ -3019,7 +3021,7 @@ void
umc_smram_recalc(uint32_t start, int set)
{
for (uint32_t c = start; c < (start + 0x0020); c++)
umc_page_recalc(c, set);
umc_page_recalc(c, c - start + 0x000a0000, set);
}
static void

View File

@@ -59,9 +59,12 @@ smram_read(uint32_t addr, void *priv)
const smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
if (new_addr >= (1 << 30))
return mem_read_ram_2gb(new_addr, priv);
else if (!use_separate_smram || (new_addr >= 0xa0000))
else
#endif
if (!use_separate_smram || (new_addr >= 0xa0000))
return mem_read_ram(new_addr, priv);
else
return dev->mapping.exec[addr - dev->host_base];
@@ -73,9 +76,12 @@ smram_readw(uint32_t addr, void *priv)
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
if (new_addr >= (1 << 30))
return mem_read_ram_2gbw(new_addr, priv);
else if (!use_separate_smram || (new_addr >= 0xa0000))
else
#endif
if (!use_separate_smram || (new_addr >= 0xa0000))
return mem_read_ramw(new_addr, priv);
else
return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]);
@@ -87,9 +93,12 @@ smram_readl(uint32_t addr, void *priv)
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
if (new_addr >= (1 << 30))
return mem_read_ram_2gbl(new_addr, priv);
else if (!use_separate_smram || (new_addr >= 0xa0000))
else
#endif
if (!use_separate_smram || (new_addr >= 0xa0000))
return mem_read_raml(new_addr, priv);
else
return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]);

View File

@@ -855,10 +855,10 @@ pci_register_card(int pci_card)
/* Add an instance of the PCI bridge. */
void
pci_add_bridge(uint8_t agp, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot)
pci_add_bridge(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot)
{
pci_card_t *card;
uint8_t bridge_slot = agp ? pci_find_slot(PCI_ADD_AGPBRIDGE, 0xff) : last_normal_pci_card_id;
uint8_t bridge_slot = (add_type == PCI_ADD_NORMAL) ? last_normal_pci_card_id : pci_find_slot(add_type, 0xff);
if (bridge_slot != PCI_CARD_INVALID) {
card = &pci_cards[bridge_slot];

View File

@@ -199,7 +199,7 @@ HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index)
* than a tenth of a percent change in size.
*/
static void
adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry)
adjust_86box_geometry_for_vhd(_86BoxGeom *_86box_geometry, MVHDGeom *vhd_geometry)
{
if (_86box_geometry->cyl <= 65535) {
vhd_geometry->cyl = _86box_geometry->cyl;
@@ -226,10 +226,10 @@ adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry)
}
static HarddiskDialog *callbackPtr = nullptr;
static MVHDGeom
create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt)
static _86BoxGeom
create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint32_t cyl, uint32_t heads, uint32_t spt)
{
MVHDGeom _86box_geometry = {
_86BoxGeom _86box_geometry = {
.cyl = cyl,
.heads = heads,
.spt = spt
@@ -256,10 +256,10 @@ create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl,
return _86box_geometry;
}
static MVHDGeom
create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize)
static _86BoxGeom
create_drive_vhd_dynamic(const QString &fileName, uint32_t cyl, uint32_t heads, uint32_t spt, int blocksize)
{
MVHDGeom _86box_geometry = {
_86BoxGeom _86box_geometry = {
.cyl = cyl,
.heads = heads,
.spt = spt
@@ -287,7 +287,7 @@ create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, u
return _86box_geometry;
}
static MVHDGeom
static _86BoxGeom
create_drive_vhd_diff(const QString &fileName, const QString &parentFileName, int blocksize)
{
int vhd_error = 0;
@@ -299,25 +299,31 @@ create_drive_vhd_diff(const QString &fileName, const QString &parentFileName, in
options.parent_path = parentFilenameBytes.data();
options.type = MVHD_TYPE_DIFF;
MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
MVHDGeom vhd_geometry;
MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
MVHDGeom vhd_geometry;
_86BoxGeom _86box_geometry;
if (vhd == NULL) {
vhd_geometry.cyl = 0;
vhd_geometry.heads = 0;
vhd_geometry.spt = 0;
_86box_geometry.cyl = 0;
_86box_geometry.heads = 0;
_86box_geometry.spt = 0;
} else {
vhd_geometry = mvhd_get_geometry(vhd);
if (vhd_geometry.spt > 63) {
vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63);
vhd_geometry.heads = 16;
vhd_geometry.spt = 63;
_86box_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63);
_86box_geometry.heads = 16;
_86box_geometry.spt = 63;
} else {
_86box_geometry.cyl = vhd_geometry.cyl;
_86box_geometry.heads = vhd_geometry.heads;
_86box_geometry.spt = vhd_geometry.spt;
}
mvhd_close(vhd);
}
return vhd_geometry;
return _86box_geometry;
}
void
@@ -409,7 +415,7 @@ HarddiskDialog::onCreateNewFile()
} else if (img_format >= IMG_FMT_VHD_FIXED) { /* VHD file */
file.close();
MVHDGeom _86box_geometry {};
_86BoxGeom _86box_geometry {};
int block_size = ui->comboBoxBlockSize->currentIndex() == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL;
switch (img_format) {
case IMG_FMT_VHD_FIXED:
@@ -493,10 +499,14 @@ HarddiskDialog::onCreateNewFile()
}
static void
adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry)
adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry, _86BoxGeom *_86box_geometry)
{
if (vhd_geometry->spt <= 63)
if (vhd_geometry->spt <= 63) {
_86box_geometry->cyl = vhd_geometry->cyl;
_86box_geometry->heads = vhd_geometry->heads;
_86box_geometry->spt = vhd_geometry->spt;
return;
}
int desired_sectors = vhd_geometry->cyl * vhd_geometry->heads * vhd_geometry->spt;
if (desired_sectors > 267321600)
@@ -506,9 +516,9 @@ adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry)
if (remainder > 0)
desired_sectors -= remainder;
vhd_geometry->cyl = desired_sectors / (16 * 63);
vhd_geometry->heads = 16;
vhd_geometry->spt = 63;
_86box_geometry->cyl = desired_sectors / (16 * 63);
_86box_geometry->heads = 16;
_86box_geometry->spt = 63;
}
void
@@ -602,11 +612,12 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck)
}
}
MVHDGeom vhd_geom = mvhd_get_geometry(vhd);
adjust_vhd_geometry_for_86box(&vhd_geom);
cylinders = vhd_geom.cyl;
heads = vhd_geom.heads;
sectors = vhd_geom.spt;
MVHDGeom vhd_geom = mvhd_get_geometry(vhd);
_86BoxGeom _86box_geom;
adjust_vhd_geometry_for_86box(&vhd_geom, &_86box_geom);
cylinders = _86box_geom.cyl;
heads = _86box_geom.heads;
sectors = _86box_geom.spt;
size = static_cast<uint64_t>(cylinders * heads * sectors * 512);
mvhd_close(vhd);
} else {

View File

@@ -64,4 +64,10 @@ private:
void recalcSelection();
};
typedef struct _86BoxGeom {
uint32_t cyl;
uint32_t heads;
uint32_t spt;
} _86BoxGeom;
#endif // QT_HARDDISKDIALOG_HPP

View File

@@ -47,11 +47,12 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv)
static uint8_t
sio_detect_read(uint16_t port, void *priv)
{
const sio_detect_t *dev = (sio_detect_t *) priv;
/*const sio_detect_t *dev = (sio_detect_t *) priv*/;
uint8_t ret = 0xff /*dev->regs[port & 1]*/;
pclog("sio_detect_read : port=%04x = %02X\n", port, dev->regs[port & 1]);
pclog("sio_detect_read : port=%04x = %02X\n", port, ret);
return 0xff /*dev->regs[port & 1]*/;
return ret;
}
static void

View File

@@ -41,6 +41,7 @@ add_library(snd OBJECT
snd_sb.c
snd_sb_dsp.c
snd_emu8k.c
snd_mmb.c
snd_mpu401.c
snd_pas16.c
snd_sn76489.c
@@ -48,8 +49,6 @@ add_library(snd OBJECT
snd_wss.c
snd_ym7128.c
snd_optimc.c
esfmu/esfm.c
esfmu/esfm_registers.c
snd_opl_esfm.c
)
@@ -177,20 +176,22 @@ if(MUNT)
endif()
endif()
add_subdirectory(ayumi)
target_link_libraries(86Box ayumi)
add_subdirectory(esfmu)
target_link_libraries(86Box esfmu)
add_subdirectory(ymfm)
target_link_libraries(86Box ymfm)
if(GUSMAX)
target_compile_definitions(snd PRIVATE USE_GUSMAX)
endif()
if(OPL4ML)
target_compile_definitions(snd PRIVATE USE_OPL4ML)
target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c)
endif()
find_package(PkgConfig )
pkg_check_modules(SERIALPORT libserialport)
find_package(PkgConfig)
pkg_check_modules(SERIALPORT libserialport)
if(SERIALPORT_FOUND OR DEFINED LIBSERIALPORT_ROOT)
add_compile_definitions(USE_LIBSERIALPORT=1)

View File

@@ -0,0 +1,14 @@
#
# 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.
#
# CMake build script.
#
add_library(ayumi STATIC
ayumi.c
)

21
src/sound/ayumi/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) Peter Sovietov, http://sovietov.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

338
src/sound/ayumi/ayumi.c Normal file
View File

@@ -0,0 +1,338 @@
/* Author: Peter Sovietov */
#include <string.h>
#include <math.h>
#include "ayumi.h"
static const double AY_dac_table[] = {
0.0, 0.0,
0.00999465934234, 0.00999465934234,
0.0144502937362, 0.0144502937362,
0.0210574502174, 0.0210574502174,
0.0307011520562, 0.0307011520562,
0.0455481803616, 0.0455481803616,
0.0644998855573, 0.0644998855573,
0.107362478065, 0.107362478065,
0.126588845655, 0.126588845655,
0.20498970016, 0.20498970016,
0.292210269322, 0.292210269322,
0.372838941024, 0.372838941024,
0.492530708782, 0.492530708782,
0.635324635691, 0.635324635691,
0.805584802014, 0.805584802014,
1.0, 1.0
};
static const double YM_dac_table[] = {
0.0, 0.0,
0.00465400167849, 0.00772106507973,
0.0109559777218, 0.0139620050355,
0.0169985503929, 0.0200198367285,
0.024368657969, 0.029694056611,
0.0350652323186, 0.0403906309606,
0.0485389486534, 0.0583352407111,
0.0680552376593, 0.0777752346075,
0.0925154497597, 0.111085679408,
0.129747463188, 0.148485542077,
0.17666895552, 0.211551079576,
0.246387426566, 0.281101701381,
0.333730067903, 0.400427252613,
0.467383840696, 0.53443198291,
0.635172045472, 0.75800717174,
0.879926756695, 1.0
};
static void reset_segment(struct ayumi* ay);
static int update_tone(struct ayumi* ay, int index) {
struct tone_channel* ch = &ay->channels[index];
ch->tone_counter += 1;
if (ch->tone_counter >= ch->tone_period) {
ch->tone_counter = 0;
ch->tone ^= 1;
}
return ch->tone;
}
static int update_noise(struct ayumi* ay) {
int bit0x3;
ay->noise_counter += 1;
if (ay->noise_counter >= (ay->noise_period << 1)) {
ay->noise_counter = 0;
bit0x3 = ((ay->noise ^ (ay->noise >> 3)) & 1);
ay->noise = (ay->noise >> 1) | (bit0x3 << 16);
}
return ay->noise & 1;
}
static void slide_up(struct ayumi* ay) {
ay->envelope += 1;
if (ay->envelope > 31) {
ay->envelope_segment ^= 1;
reset_segment(ay);
}
}
static void slide_down(struct ayumi* ay) {
ay->envelope -= 1;
if (ay->envelope < 0) {
ay->envelope_segment ^= 1;
reset_segment(ay);
}
}
static void hold_top(struct ayumi* ay) {
(void) ay;
}
static void hold_bottom(struct ayumi* ay) {
(void) ay;
}
static void (* const Envelopes[][2])(struct ayumi*) = {
{slide_down, hold_bottom},
{slide_down, hold_bottom},
{slide_down, hold_bottom},
{slide_down, hold_bottom},
{slide_up, hold_bottom},
{slide_up, hold_bottom},
{slide_up, hold_bottom},
{slide_up, hold_bottom},
{slide_down, slide_down},
{slide_down, hold_bottom},
{slide_down, slide_up},
{slide_down, hold_top},
{slide_up, slide_up},
{slide_up, hold_top},
{slide_up, slide_down},
{slide_up, hold_bottom}
};
static void reset_segment(struct ayumi* ay) {
if (Envelopes[ay->envelope_shape][ay->envelope_segment] == slide_down
|| Envelopes[ay->envelope_shape][ay->envelope_segment] == hold_top) {
ay->envelope = 31;
return;
}
ay->envelope = 0;
}
int update_envelope(struct ayumi* ay) {
ay->envelope_counter += 1;
if (ay->envelope_counter >= ay->envelope_period) {
ay->envelope_counter = 0;
Envelopes[ay->envelope_shape][ay->envelope_segment](ay);
}
return ay->envelope;
}
static void update_mixer(struct ayumi* ay) {
int i;
int out;
int noise = update_noise(ay);
int envelope = update_envelope(ay);
ay->left = 0;
ay->right = 0;
for (i = 0; i < TONE_CHANNELS; i += 1) {
out = (update_tone(ay, i) | ay->channels[i].t_off) & (noise | ay->channels[i].n_off);
out *= ay->channels[i].e_on ? envelope : ay->channels[i].volume * 2 + 1;
ay->left += ay->dac_table[out] * ay->channels[i].pan_left;
ay->right += ay->dac_table[out] * ay->channels[i].pan_right;
}
}
int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr) {
int i;
memset(ay, 0, sizeof(struct ayumi));
ay->step = clock_rate / (sr * 8 * DECIMATE_FACTOR);
ay->dac_table = is_ym ? YM_dac_table : AY_dac_table;
ay->noise = 1;
ayumi_set_envelope(ay, 1);
for (i = 0; i < TONE_CHANNELS; i += 1) {
ayumi_set_tone(ay, i, 1);
}
return ay->step < 1;
}
void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp) {
if (is_eqp) {
ay->channels[index].pan_left = sqrt(1 - pan);
ay->channels[index].pan_right = sqrt(pan);
} else {
ay->channels[index].pan_left = 1 - pan;
ay->channels[index].pan_right = pan;
}
}
void ayumi_set_tone(struct ayumi* ay, int index, int period) {
period &= 0xfff;
ay->channels[index].tone_period = (period == 0) | period;
}
void ayumi_set_noise(struct ayumi* ay, int period) {
period &= 0x1f;
ay->noise_period = (period == 0) | period;
}
void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on) {
ay->channels[index].t_off = t_off & 1;
ay->channels[index].n_off = n_off & 1;
ay->channels[index].e_on = e_on;
}
void ayumi_set_volume(struct ayumi* ay, int index, int volume) {
ay->channels[index].volume = volume & 0xf;
}
void ayumi_set_envelope(struct ayumi* ay, int period) {
period &= 0xffff;
ay->envelope_period = (period == 0) | period;
}
void ayumi_set_envelope_shape(struct ayumi* ay, int shape) {
ay->envelope_shape = shape & 0xf;
ay->envelope_counter = 0;
ay->envelope_segment = 0;
reset_segment(ay);
}
static double decimate(double* x) {
double y = -0.0000046183113992051936 * (x[1] + x[191]) +
-0.00001117761640887225 * (x[2] + x[190]) +
-0.000018610264502005432 * (x[3] + x[189]) +
-0.000025134586135631012 * (x[4] + x[188]) +
-0.000028494281690666197 * (x[5] + x[187]) +
-0.000026396828793275159 * (x[6] + x[186]) +
-0.000017094212558802156 * (x[7] + x[185]) +
0.000023798193576966866 * (x[9] + x[183]) +
0.000051281160242202183 * (x[10] + x[182]) +
0.00007762197826243427 * (x[11] + x[181]) +
0.000096759426664120416 * (x[12] + x[180]) +
0.00010240229300393402 * (x[13] + x[179]) +
0.000089344614218077106 * (x[14] + x[178]) +
0.000054875700118949183 * (x[15] + x[177]) +
-0.000069839082210680165 * (x[17] + x[175]) +
-0.0001447966132360757 * (x[18] + x[174]) +
-0.00021158452917708308 * (x[19] + x[173]) +
-0.00025535069106550544 * (x[20] + x[172]) +
-0.00026228714374322104 * (x[21] + x[171]) +
-0.00022258805927027799 * (x[22] + x[170]) +
-0.00013323230495695704 * (x[23] + x[169]) +
0.00016182578767055206 * (x[25] + x[167]) +
0.00032846175385096581 * (x[26] + x[166]) +
0.00047045611576184863 * (x[27] + x[165]) +
0.00055713851457530944 * (x[28] + x[164]) +
0.00056212565121518726 * (x[29] + x[163]) +
0.00046901918553962478 * (x[30] + x[162]) +
0.00027624866838952986 * (x[31] + x[161]) +
-0.00032564179486838622 * (x[33] + x[159]) +
-0.00065182310286710388 * (x[34] + x[158]) +
-0.00092127787309319298 * (x[35] + x[157]) +
-0.0010772534348943575 * (x[36] + x[156]) +
-0.0010737727700273478 * (x[37] + x[155]) +
-0.00088556645390392634 * (x[38] + x[154]) +
-0.00051581896090765534 * (x[39] + x[153]) +
0.00059548767193795277 * (x[41] + x[151]) +
0.0011803558710661009 * (x[42] + x[150]) +
0.0016527320270369871 * (x[43] + x[149]) +
0.0019152679330965555 * (x[44] + x[148]) +
0.0018927324805381538 * (x[45] + x[147]) +
0.0015481870327877937 * (x[46] + x[146]) +
0.00089470695834941306 * (x[47] + x[145]) +
-0.0010178225878206125 * (x[49] + x[143]) +
-0.0020037400552054292 * (x[50] + x[142]) +
-0.0027874356824117317 * (x[51] + x[141]) +
-0.003210329988021943 * (x[52] + x[140]) +
-0.0031540624117984395 * (x[53] + x[139]) +
-0.0025657163651900345 * (x[54] + x[138]) +
-0.0014750752642111449 * (x[55] + x[137]) +
0.0016624165446378462 * (x[57] + x[135]) +
0.0032591192839069179 * (x[58] + x[134]) +
0.0045165685815867747 * (x[59] + x[133]) +
0.0051838984346123896 * (x[60] + x[132]) +
0.0050774264697459933 * (x[61] + x[131]) +
0.0041192521414141585 * (x[62] + x[130]) +
0.0023628575417966491 * (x[63] + x[129]) +
-0.0026543507866759182 * (x[65] + x[127]) +
-0.0051990251084333425 * (x[66] + x[126]) +
-0.0072020238234656924 * (x[67] + x[125]) +
-0.0082672928192007358 * (x[68] + x[124]) +
-0.0081033739572956287 * (x[69] + x[123]) +
-0.006583111539570221 * (x[70] + x[122]) +
-0.0037839040415292386 * (x[71] + x[121]) +
0.0042781252851152507 * (x[73] + x[119]) +
0.0084176358598320178 * (x[74] + x[118]) +
0.01172566057463055 * (x[75] + x[117]) +
0.013550476647788672 * (x[76] + x[116]) +
0.013388189369997496 * (x[77] + x[115]) +
0.010979501242341259 * (x[78] + x[114]) +
0.006381274941685413 * (x[79] + x[113]) +
-0.007421229604153888 * (x[81] + x[111]) +
-0.01486456304340213 * (x[82] + x[110]) +
-0.021143584622178104 * (x[83] + x[109]) +
-0.02504275058758609 * (x[84] + x[108]) +
-0.025473530942547201 * (x[85] + x[107]) +
-0.021627310017882196 * (x[86] + x[106]) +
-0.013104323383225543 * (x[87] + x[105]) +
0.017065133989980476 * (x[89] + x[103]) +
0.036978919264451952 * (x[90] + x[102]) +
0.05823318062093958 * (x[91] + x[101]) +
0.079072012081405949 * (x[92] + x[100]) +
0.097675998716952317 * (x[93] + x[99]) +
0.11236045936950932 * (x[94] + x[98]) +
0.12176343577287731 * (x[95] + x[97]) +
0.125 * x[96];
memcpy(&x[FIR_SIZE - DECIMATE_FACTOR], x, DECIMATE_FACTOR * sizeof(double));
return y;
}
void ayumi_process(struct ayumi* ay) {
int i;
double y1;
double* c_left = ay->interpolator_left.c;
double* y_left = ay->interpolator_left.y;
double* c_right = ay->interpolator_right.c;
double* y_right = ay->interpolator_right.y;
double* fir_left = &ay->fir_left[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
double* fir_right = &ay->fir_right[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
ay->fir_index = (ay->fir_index + 1) % (FIR_SIZE / DECIMATE_FACTOR - 1);
for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) {
ay->x += ay->step;
if (ay->x >= 1) {
ay->x -= 1;
y_left[0] = y_left[1];
y_left[1] = y_left[2];
y_left[2] = y_left[3];
y_right[0] = y_right[1];
y_right[1] = y_right[2];
y_right[2] = y_right[3];
update_mixer(ay);
y_left[3] = ay->left;
y_right[3] = ay->right;
y1 = y_left[2] - y_left[0];
c_left[0] = 0.5 * y_left[1] + 0.25 * (y_left[0] + y_left[2]);
c_left[1] = 0.5 * y1;
c_left[2] = 0.25 * (y_left[3] - y_left[1] - y1);
y1 = y_right[2] - y_right[0];
c_right[0] = 0.5 * y_right[1] + 0.25 * (y_right[0] + y_right[2]);
c_right[1] = 0.5 * y1;
c_right[2] = 0.25 * (y_right[3] - y_right[1] - y1);
}
fir_left[i] = (c_left[2] * ay->x + c_left[1]) * ay->x + c_left[0];
fir_right[i] = (c_right[2] * ay->x + c_right[1]) * ay->x + c_right[0];
}
ay->left = decimate(fir_left);
ay->right = decimate(fir_right);
}
static double dc_filter(struct dc_filter* dc, int index, double x) {
dc->sum += -dc->delay[index] + x;
dc->delay[index] = x;
return x - dc->sum / DC_FILTER_SIZE;
}
void ayumi_remove_dc(struct ayumi* ay) {
ay->left = dc_filter(&ay->dc_left, ay->dc_index, ay->left);
ay->right = dc_filter(&ay->dc_right, ay->dc_index, ay->right);
ay->dc_index = (ay->dc_index + 1) & (DC_FILTER_SIZE - 1);
}

71
src/sound/ayumi/ayumi.h Normal file
View File

@@ -0,0 +1,71 @@
/* Author: Peter Sovietov */
#ifndef AYUMI_H
#define AYUMI_H
enum {
TONE_CHANNELS = 3,
DECIMATE_FACTOR = 8,
FIR_SIZE = 192,
DC_FILTER_SIZE = 1024
};
struct tone_channel {
int tone_period;
int tone_counter;
int tone;
int t_off;
int n_off;
int e_on;
int volume;
double pan_left;
double pan_right;
};
struct interpolator {
double c[4];
double y[4];
};
struct dc_filter {
double sum;
double delay[DC_FILTER_SIZE];
};
struct ayumi {
struct tone_channel channels[TONE_CHANNELS];
int noise_period;
int noise_counter;
int noise;
int envelope_counter;
int envelope_period;
int envelope_shape;
int envelope_segment;
int envelope;
const double* dac_table;
double step;
double x;
struct interpolator interpolator_left;
struct interpolator interpolator_right;
double fir_left[FIR_SIZE * 2];
double fir_right[FIR_SIZE * 2];
int fir_index;
struct dc_filter dc_left;
struct dc_filter dc_right;
int dc_index;
double left;
double right;
};
int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr);
void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp);
void ayumi_set_tone(struct ayumi* ay, int index, int period);
void ayumi_set_noise(struct ayumi* ay, int period);
void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on);
void ayumi_set_volume(struct ayumi* ay, int index, int volume);
void ayumi_set_envelope(struct ayumi* ay, int period);
void ayumi_set_envelope_shape(struct ayumi* ay, int shape);
void ayumi_process(struct ayumi* ay);
void ayumi_remove_dc(struct ayumi* ay);
#endif

View File

@@ -0,0 +1,15 @@
#
# 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.
#
# CMake build script.
#
add_library(esfmu STATIC
esfm.c
esfm_registers.c
)

View File

@@ -650,15 +650,7 @@ cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig)
isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], dev->pnp_size);
/* Disable PnP key if the PKD bit is set, or if it was disabled by command 0x55. */
/* But wait! The TriGem Delhi-III BIOS sends command 0x55, and its behavior doesn't
line up with real hardware (still listed in the POST summary and seen by software).
Disable the PnP key disabling mechanism until someone figures something out. */
#if 0
isapnp_enable_card(dev->pnp_card, ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable) ? ISAPNP_CARD_NO_KEY : ISAPNP_CARD_ENABLE);
#else
if ((dev->ram_data[0x4002] & 0x20) || !dev->pnp_enable)
pclog("CS423x: Attempted to disable PnP key\n");
#endif
}
/* Update some register bits based on the config data in RAM if requested. */

View File

@@ -17,9 +17,7 @@
#include <86box/sound.h>
#include "cpu.h"
#include <86box/timer.h>
#ifdef USE_GUSMAX
# include <86box/snd_ad1848.h>
#endif /*USE_GUSMAX */
#include <86box/snd_ad1848.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
@@ -145,11 +143,9 @@ typedef struct gus_t {
uint8_t usrr;
#ifdef USE_GUSMAX
uint8_t max_ctrl;
ad1848_t ad1848;
#endif /*USE_GUSMAX */
} gus_t;
static int gus_gf1_irqs[8] = { -1, 2, 5, 3, 7, 11, 12, 15 };
@@ -257,9 +253,7 @@ writegus(uint16_t addr, uint8_t val, void *priv)
int d;
int old;
uint16_t port;
#ifdef USE_GUSMAX
uint16_t csioport;
#endif /*USE_GUSMAX */
if ((addr == 0x388) || (addr == 0x389))
port = addr;
@@ -607,10 +601,9 @@ writegus(uint16_t addr, uint8_t val, void *priv)
gus->irq_midi = gus->irq;
} else
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX)
ad1848_setirq(&gus->ad1848, gus->irq);
#endif /*USE_GUSMAX */
gus->sb_nmi = val & 0x80;
} else {
@@ -623,10 +616,9 @@ writegus(uint16_t addr, uint8_t val, void *priv)
gus->dma2 = gus->dma;
} else
gus->dma2 = gus_dmas[(val >> 3) & 7];
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX)
ad1848_setdma(&gus->ad1848, gus->dma2);
#endif /*USE_GUSMAX */
}
break;
case 1:
@@ -684,7 +676,6 @@ writegus(uint16_t addr, uint8_t val, void *priv)
break;
case 0x306:
case 0x706:
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX) {
if (gus->dma >= 4)
val |= 0x10;
@@ -704,7 +695,6 @@ writegus(uint16_t addr, uint8_t val, void *priv)
}
}
}
#endif /*USE_GUSMAX */
break;
default:
@@ -756,11 +746,9 @@ readgus(uint16_t addr, void *priv)
return val;
case 0x20F:
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX)
val = 0x02;
else
#endif /*USE_GUSMAX */
val = 0x00;
break;
@@ -879,11 +867,9 @@ readgus(uint16_t addr, void *priv)
break;
case 0x306:
case 0x706:
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX)
val = 0x0a; /* GUS MAX */
else
#endif /*USE_GUSMAX */
val = 0xff; /*Pre 3.7 - no mixer*/
break;
@@ -1183,24 +1169,20 @@ gus_get_buffer(int32_t *buffer, int len, void *priv)
{
gus_t *gus = (gus_t *) priv;
#ifdef USE_GUSMAX
if ((gus->type == GUS_MAX) && (gus->max_ctrl))
ad1848_update(&gus->ad1848);
#endif /*USE_GUSMAX */
gus_update(gus);
for (int c = 0; c < len * 2; c++) {
#ifdef USE_GUSMAX
if ((gus->type == GUS_MAX) && (gus->max_ctrl))
buffer[c] += (int32_t) (gus->ad1848.buffer[c] / 2);
#endif /*USE_GUSMAX */
buffer[c] += (int32_t) gus->buffer[c & 1][c >> 1];
}
#ifdef USE_GUSMAX
if ((gus->type == GUS_MAX) && (gus->max_ctrl))
gus->ad1848.pos = 0;
#endif /*USE_GUSMAX */
gus->pos = 0;
}
@@ -1333,9 +1315,7 @@ gus_reset(void *priv)
gus->usrr = 0;
#ifdef USE_GUSMAX
gus->max_ctrl = 0;
#endif /*USE_GUSMAX */
gus->irq_state = 0;
gus->midi_irq_state = 0;
@@ -1373,7 +1353,7 @@ gus_init(UNUSED(const device_t *info))
gus->uart_out = 1;
gus->type = device_get_config_int("type");
gus->type = info->local;
gus->base = device_get_config_hex16("base");
@@ -1382,7 +1362,6 @@ gus_init(UNUSED(const device_t *info))
io_sethandler(0x0506 + gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
#ifdef USE_GUSMAX
if (gus->type == GUS_MAX) {
ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231);
ad1848_setirq(&gus->ad1848, 5);
@@ -1390,7 +1369,6 @@ gus_init(UNUSED(const device_t *info))
io_sethandler(0x10C + gus->base, 4,
ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &gus->ad1848);
}
#endif /*USE_GUSMAX */
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
@@ -1423,31 +1401,12 @@ gus_speed_changed(void *priv)
else
gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
#ifdef USE_GUSMAX
if ((gus->type == GUS_MAX) && (gus->max_ctrl))
ad1848_speed_changed(&gus->ad1848);
#endif /*USE_GUSMAX */
}
static const device_config_t gus_config[] = {
// clang-format off
{
.name = "type",
.description = "GUS type",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Classic", .value = GUS_CLASSIC },
#ifdef USE_GUSMAX
{ .description = "MAX", .value = GUS_MAX },
#endif /*USE_GUSMAX */
{ NULL }
},
.bios = { { 0 } }
},
{
.name = "base",
.description = "Address",
@@ -1502,7 +1461,21 @@ const device_t gus_device = {
.name = "Gravis UltraSound",
.internal_name = "gus",
.flags = DEVICE_ISA16,
.local = 0,
.local = GUS_CLASSIC,
.init = gus_init,
.close = gus_close,
.reset = gus_reset,
.available = NULL,
.speed_changed = gus_speed_changed,
.force_redraw = NULL,
.config = gus_config
};
const device_t gus_max_device = {
.name = "Gravis UltraSound MAX",
.internal_name = "gus",
.flags = DEVICE_ISA16,
.local = GUS_MAX,
.init = gus_init,
.close = gus_close,
.reset = gus_reset,

339
src/sound/snd_mmb.c Normal file
View File

@@ -0,0 +1,339 @@
/*
* 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.
*
* Mindscape Music Board emulation.
*
* Authors: Roy Baer, <https://pcem-emulator.co.uk/>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2025 Roy Baer.
* Copyright 2025 Jasmine Iwanek.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/sound.h>
//#i nclude "cpu.h"
#include "ayumi/ayumi.h"
#include <86box/snd_mmb.h>
#include <86box/plat_unused.h>
#ifdef ENABLE_MMB_LOG
int mmb_do_log = ENABLE_MMB_LOG;
static void
mmb_log(const char *fmt, ...)
{
va_list ap;
if (mmb_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define mmb_log(fmt, ...)
#endif
void
mmb_update(mmb_t *mmb)
{
for (; mmb->pos < sound_pos_global; mmb->pos++) {
ayumi_process(&mmb->first.chip);
ayumi_process(&mmb->second.chip);
ayumi_remove_dc(&mmb->first.chip);
ayumi_remove_dc(&mmb->second.chip);
mmb->buffer[mmb->pos << 1] = (mmb->first.chip.left + mmb->second.chip.left) * 16000;
mmb->buffer[(mmb->pos << 1) + 1] = (mmb->first.chip.right + mmb->second.chip.right) * 16000;
}
}
void
mmb_get_buffer(int32_t *buffer, int len, void *priv)
{
mmb_t *mmb = (mmb_t *) priv;
mmb_update(mmb);
for (int c = 0; c < len * 2; c++)
buffer[c] += mmb->buffer[c];
mmb->pos = 0;
}
void
mmb_write(uint16_t addr, uint8_t val, void *priv)
{
mmb_t *mmb = (mmb_t *) priv;
mmb_update(mmb);
mmb_log("mmb_write(%04X): activity now: %02X\n", addr, val);
switch (addr & 3) {
case 0:
mmb->first.index = val;
break;
case 2:
mmb->second.index = val;
break;
case 1:
case 3:
{
ay_3_891x_t *ay = ((addr & 2) == 0) ? &mmb->first : &mmb->second;
switch (ay->index) {
case 0:
ay->regs[0] = val;
ayumi_set_tone(&ay->chip, 0, (ay->regs[1] << 8) | ay->regs[0]);
break;
case 1:
ay->regs[1] = val & 0xf;
ayumi_set_tone(&ay->chip, 0, (ay->regs[1] << 8) | ay->regs[0]);
break;
case 2:
ay->regs[2] = val;
ayumi_set_tone(&ay->chip, 1, (ay->regs[3] << 8) | ay->regs[2]);
break;
case 3:
ay->regs[3] = val & 0xf;
ayumi_set_tone(&ay->chip, 1, (ay->regs[3] << 8) | ay->regs[2]);
break;
case 4:
ay->regs[4] = val;
ayumi_set_tone(&ay->chip, 2, (ay->regs[5] << 8) | ay->regs[4]);
break;
case 5:
ay->regs[5] = val & 0xf;
ayumi_set_tone(&ay->chip, 2, (ay->regs[5] << 8) | ay->regs[4]);
break;
case 6:
ay->regs[6] = val & 0x1f;
ayumi_set_noise(&ay->chip, ay->regs[6]);
break;
case 7:
ay->regs[7] = val;
ayumi_set_mixer(&ay->chip, 0, val & 1, (val >> 3) & 1, (ay->regs[8] >> 4) & 1);
ayumi_set_mixer(&ay->chip, 1, (val >> 1) & 1, (val >> 4) & 1, (ay->regs[9] >> 4) & 1);
ayumi_set_mixer(&ay->chip, 2, (val >> 2) & 1, (val >> 5) & 1, (ay->regs[10] >> 4) & 1);
break;
case 8:
ay->regs[8] = val;
ayumi_set_volume(&ay->chip, 0, val & 0xf);
ayumi_set_mixer(&ay->chip, 0, ay->regs[7] & 1, (ay->regs[7] >> 3) & 1, (val >> 4) & 1);
break;
case 9:
ay->regs[9] = val;
ayumi_set_volume(&ay->chip, 1, val & 0xf);
ayumi_set_mixer(&ay->chip, 1, (ay->regs[7] >> 1) & 1, (ay->regs[7] >> 4) & 1, (val >> 4) & 1);
break;
case 10:
ay->regs[10] = val;
ayumi_set_volume(&ay->chip, 2, val & 0xf);
ayumi_set_mixer(&ay->chip, 2, (ay->regs[7] >> 2) & 1, (ay->regs[7] >> 5) & 1, (val >> 4) & 1);
break;
case 11:
ay->regs[11] = val;
ayumi_set_envelope(&ay->chip, (ay->regs[12] >> 8) | ay->regs[11]);
break;
case 12:
ay->regs[12] = val;
ayumi_set_envelope(&ay->chip, (ay->regs[12] >> 8) | ay->regs[11]);
break;
case 13:
ay->regs[13] = val;
ayumi_set_envelope_shape(&ay->chip, val & 0xf);
break;
case 14:
ay->regs[14] = val;
break;
case 15:
ay->regs[15] = val;
break;
default:
break;
}
break;
}
default:
break;
}
}
uint8_t
mmb_read(uint16_t addr, void *priv)
{
mmb_t *mmb = (mmb_t *) priv;
ay_3_891x_t *ay = ((addr & 2) == 0) ? &mmb->first : &mmb->second;
uint8_t ret = 0;
switch (ay->index) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
ret = ay->regs[ay->index];
break;
case 14:
if (ay->regs[7] & 0x40)
ret = ay->regs[14];
break;
case 15:
if (ay->regs[7] & 0x80)
ret = ay->regs[15];
break;
default:
break;
}
mmb_log("mmb_read(%04X): activity now: %02X\n", addr, ret);
return ret;
}
void *
mmb_init(UNUSED(const device_t *info))
{
mmb_t *mmb = calloc(1, sizeof(mmb_t));
# if 0
uint16_t addr = (device_get_config_int("addr96") << 6) | (device_get_config_int("addr52") << 2);
#else
uint16_t addr = 0x300;
#endif
sound_add_handler(mmb_get_buffer, mmb);
ayumi_configure(&mmb->first.chip, 0, MMB_CLOCK, MMB_FREQ);
ayumi_configure(&mmb->second.chip, 0, MMB_CLOCK, MMB_FREQ);
for (uint8_t i = 0; i < 3; i++) {
ayumi_set_pan(&mmb->first.chip, i, 0.5, 1);
ayumi_set_pan(&mmb->second.chip, i, 0.5, 1);
}
io_sethandler(addr, 0x0004,
mmb_read, NULL, NULL,
mmb_write, NULL, NULL,
mmb);
return mmb;
}
void
mmb_close(void *priv)
{
mmb_t *mmb = (mmb_t *) priv;
free(mmb);
}
// clang-format off
#if 0
static device_config_t mmb_config[] = {
{
.name = "addr96",
.description = "Base address A9...A6",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 12,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "0000", .value = 0 },
{ .description = "0001", .value = 1 },
{ .description = "0010", .value = 2 },
{ .description = "0011", .value = 3 },
{ .description = "0100", .value = 4 },
{ .description = "0101", .value = 5 },
{ .description = "0110", .value = 6 },
{ .description = "0111", .value = 7 },
{ .description = "1000", .value = 8 },
{ .description = "1001", .value = 9 },
{ .description = "1010", .value = 10 },
{ .description = "1011", .value = 11 },
{ .description = "1100", .value = 12 },
{ .description = "1101", .value = 13 },
{ .description = "1110", .value = 14 },
{ .description = "1111", .value = 15 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "addr52",
.description = "Base address A5...A2",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "0000", .value = 0 },
{ .description = "0001", .value = 1 },
{ .description = "0010", .value = 2 },
{ .description = "0011", .value = 3 },
{ .description = "0100", .value = 4 },
{ .description = "0101", .value = 5 },
{ .description = "0110", .value = 6 },
{ .description = "0111", .value = 7 },
{ .description = "1000", .value = 8 },
{ .description = "1001", .value = 9 },
{ .description = "1010", .value = 10 },
{ .description = "1011", .value = 11 },
{ .description = "1100", .value = 12 },
{ .description = "1101", .value = 13 },
{ .description = "1110", .value = 14 },
{ .description = "1111", .value = 15 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .type = CONFIG_END }
};
#endif
// clang-format on
const device_t mmb_device = {
.name = "Mindscape Music Board",
.internal_name = "mmb",
.flags = DEVICE_ISA,
.local = 0,
.init = mmb_init,
.close = mmb_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
#if 0
.config = mmb_config
#else
.config = NULL
#endif
};

View File

@@ -115,6 +115,7 @@ static const SOUND_CARD sound_cards[] = {
{ &ess_ess0102_pnp_device },
{ &ess_ess0968_pnp_device },
{ &gus_device },
{ &gus_max_device },
{ &sb_1_device },
{ &sb_15_device },
{ &sb_2_device },
@@ -137,6 +138,7 @@ static const SOUND_CARD sound_cards[] = {
{ &sb_vibra16xv_device },
{ &ssi2001_device },
{ &entertainer_device },
{ &mmb_device },
{ &pasplus_device },
{ &pas16_device },
{ &pas16d_device },

View File

@@ -4247,7 +4247,10 @@ gd54xx_init(const device_t *info)
break;
case CIRRUS_ID_CLGD5420:
romfn = BIOS_GD5420_PATH;
if (info->local & 0x200)
romfn = NULL;
else
romfn = BIOS_GD5420_PATH;
break;
case CIRRUS_ID_CLGD5422:
@@ -4978,6 +4981,20 @@ const device_t gd5420_isa_device = {
.config = gd542x_config,
};
const device_t gd5420_onboard_device = {
.name = "Cirrus Logic GD5420 (ISA)",
.internal_name = "cl_gd5420_isa",
.flags = DEVICE_ISA16,
.local = CIRRUS_ID_CLGD5420 | 0x200,
.init = gd54xx_init,
.close = gd54xx_close,
.reset = gd54xx_reset,
.available = NULL,
.speed_changed = gd54xx_speed_changed,
.force_redraw = gd54xx_force_redraw,
.config = gd542x_config,
};
const device_t gd5422_isa_device = {
.name = "Cirrus Logic GD5422 (ISA)",
.internal_name = "cl_gd5422_isa",

View File

@@ -543,14 +543,33 @@ hercules_init(UNUSED(const device_t *info))
dev->vram = (uint8_t *) malloc(0x10000);
switch(device_get_config_int("font")) {
case 0:
loadfont(FONT_IBM_MDA_437_PATH, 0);
break;
case 1:
loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0);
break;
case 2:
loadfont(FONT_KAM_PATH, 0);
break;
case 3:
loadfont(FONT_KAMCL16_PATH, 0);
break;
}
timer_add(&dev->timer, hercules_poll, dev, 1);
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
hercules_read, NULL, NULL, hercules_write, NULL, NULL,
NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev);
hercules_read, NULL, NULL,
hercules_write, NULL, NULL,
NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL,
dev);
io_sethandler(0x03b0, 16,
hercules_in, NULL, NULL, hercules_out, NULL, NULL, dev);
io_sethandler(0x03b0, 0x0010,
hercules_in, NULL, NULL,
hercules_out, NULL, NULL,
dev);
for (uint16_t c = 0; c < 256; c++) {
dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16;
@@ -642,6 +661,23 @@ static const device_config_t hercules_config[] = {
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "font",
.description = "Font",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "US (CP 437)", .value = 0 },
{ .description = "IBM Nordic (CP 437-Nordic)", .value = 1 },
{ .description = "Czech Kamenicky (CP 895) #1", .value = 2 },
{ .description = "Czech Kamenicky (CP 895) #2", .value = 3 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};

View File

@@ -317,8 +317,32 @@ mda_standalone_init(UNUSED(const device_t *info))
mda->vram = malloc(0x1000);
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
switch(device_get_config_int("font")) {
case 0:
loadfont(FONT_IBM_MDA_437_PATH, 0);
break;
case 1:
loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0);
break;
case 2:
loadfont(FONT_KAM_PATH, 0);
break;
case 3:
loadfont(FONT_KAMCL16_PATH, 0);
break;
}
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000,
mda_read, NULL, NULL,
mda_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL,
mda);
io_sethandler(0x03b0, 0x0010,
mda_in, NULL, NULL,
mda_out, NULL, NULL,
mda);
mda_init(mda);
@@ -369,6 +393,23 @@ static const device_config_t mda_config[] = {
},
.bios = { { 0 } }
},
{
.name = "font",
.description = "Font",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "US (CP 437)", .value = 0 },
{ .description = "IBM Nordic (CP 437-Nordic)", .value = 1 },
{ .description = "Czech Kamenicky (CP 895) #1", .value = 2 },
{ .description = "Czech Kamenicky (CP 895) #2", .value = 3 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};

View File

@@ -332,7 +332,7 @@ video_reset(int card)
card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0);
monitor_index_global = 0;
loadfont("roms/video/mda/mda.rom", 0);
loadfont(FONT_IBM_MDA_437_PATH, 0);
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
if ((card != VID_NONE) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY) &&

View File

@@ -1006,76 +1006,73 @@ video_force_resize_set_monitor(uint8_t res, int monitor_index)
}
void
loadfont_common(FILE *f, int format)
loadfont_common(FILE *fp, int format)
{
int c;
int d;
switch (format) {
case 0: /* MDA */
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdatm[c][d] = fgetc(f) & 0xff;
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdatm[c][d + 8] = fgetc(f) & 0xff;
(void) fseek(f, 4096 + 2048, SEEK_SET);
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x8 cell (lines 0-7) */
for (uint8_t d = 0; d < 8; d++)
fontdatm[c][d] = fgetc(fp) & 0xff;
for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x8 cell (lines 8-13 + padding lines) */
for (uint8_t d = 0; d < 8; d++)
fontdatm[c][d + 8] = fgetc(fp) & 0xff;
(void) fseek(fp, 4096 + 2048, SEEK_SET);
for (uint16_t c = 0; c < 256; c++)
for (uint8_t d = 0; d < 8; d++) /* 8x8 CGA (thick, primary) */
fontdat[c][d] = fgetc(fp) & 0xff;
break;
case 1: /* PC200 */
for (d = 0; d < 4; d++) {
for (uint8_t d = 0; d < 4; d++) {
/* There are 4 fonts in the ROM */
for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */
(void) !fread(&fontdatm[256 * d + c][0], 1, 16, f);
for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
(void) !fread(&fontdat[256 * d + c][0], 1, 8, f);
fseek(f, 8, SEEK_CUR);
for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */
(void) !fread(&fontdatm[256 * d + c][0], 1, 16, fp);
for (uint16_t c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
(void) !fread(&fontdat[256 * d + c][0], 1, 8, fp);
fseek(fp, 8, SEEK_CUR);
}
}
break;
default:
case 2: /* CGA */
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
for (uint16_t c = 0; c < 256; c++)
for (uint8_t d = 0; d < 8; d++)
fontdat[c][d] = fgetc(fp) & 0xff;
break;
case 3: /* Wyse 700 */
for (c = 0; c < 512; c++)
for (d = 0; d < 32; d++)
fontdatw[c][d] = fgetc(f) & 0xff;
for (uint16_t c = 0; c < 512; c++)
for (uint8_t d = 0; d < 32; d++)
fontdatw[c][d] = fgetc(fp) & 0xff;
break;
case 4: /* MDSI Genius */
for (c = 0; c < 256; c++)
for (d = 0; d < 16; d++)
fontdat8x12[c][d] = fgetc(f) & 0xff;
for (uint16_t c = 0; c < 256; c++)
for (uint8_t d = 0; d < 16; d++)
fontdat8x12[c][d] = fgetc(fp) & 0xff;
break;
case 5: /* Toshiba 3100e */
for (d = 0; d < 2048; d += 512) { /* Four languages... */
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, f);
case 5: /* Toshiba 3100e */
for (uint16_t d = 0; d < 2048; d += 512) { /* Four languages... */
for (uint16_t c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, fp);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, f);
for (uint16_t c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, fp);
}
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, f);
for (uint16_t c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, fp);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, f);
for (uint16_t c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, fp);
}
fseek(f, 4096, SEEK_CUR); /* Skip blank section */
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdat[c][0], 1, 8, f);
fseek(fp, 4096, SEEK_CUR); /* Skip blank section */
for (uint16_t c = d; c < d + 256; c++) {
(void) !fread(&fontdat[c][0], 1, 8, fp);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdat[c][0], 1, 8, f);
for (uint16_t c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdat[c][0], 1, 8, fp);
}
}
break;
@@ -1087,65 +1084,64 @@ loadfont_common(FILE *f, int format)
if (!fontdatksc5601_user)
fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t));
for (c = 0; c < 16384; c++) {
for (d = 0; d < 32; d++)
fontdatksc5601[c].chr[d] = fgetc(f) & 0xff;
for (uint32_t c = 0; c < 16384; c++) {
for (uint8_t d = 0; d < 32; d++)
fontdatksc5601[c].chr[d] = fgetc(fp) & 0xff;
}
break;
case 7: /* Sigma Color 400 */
/* The first 4k of the character ROM holds an 8x8 font */
for (c = 0; c < 256; c++) {
(void) !fread(&fontdat[c][0], 1, 8, f);
fseek(f, 8, SEEK_CUR);
for (uint16_t c = 0; c < 256; c++) {
(void) !fread(&fontdat[c][0], 1, 8, fp);
fseek(fp, 8, SEEK_CUR);
}
/* The second 4k holds an 8x16 font */
for (c = 0; c < 256; c++) {
if (fread(&fontdatm[c][0], 1, 16, f) != 16)
for (uint16_t c = 0; c < 256; c++) {
if (fread(&fontdatm[c][0], 1, 16, fp) != 16)
fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c);
}
break;
case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */
for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */
for (uint16_t c = 0; c < 2048; c++) /* Allow up to 2048 chars */
for (uint8_t d = 0; d < 8; d++)
fontdat[c][d] = fgetc(fp) & 0xff;
break;
case 9: /* Image Manager 1024 native font */
for (c = 0; c < 256; c++)
(void) !fread(&fontdat12x18[c][0], 1, 36, f);
for (uint16_t c = 0; c < 256; c++)
(void) !fread(&fontdat12x18[c][0], 1, 36, fp);
break;
case 10: /* Pravetz */
for (c = 0; c < 1024; c++) /* Allow up to 1024 chars */
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
case 10: /* Pravetz */
for (uint16_t c = 0; c < 1024; c++) /* Allow up to 1024 chars */
for (uint8_t d = 0; d < 8; d++)
fontdat[c][d] = fgetc(fp) & 0xff;
break;
case 11: /* PC200 */
for (d = 0; d < 4; d++) {
for (uint8_t d = 0; d < 4; d++) {
/* There are 4 fonts in the ROM */
for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */
(void) !fread(&fontdatm2[256 * d + c][0], 1, 16, f);
for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
(void) !fread(&fontdat2[256 * d + c][0], 1, 8, f);
fseek(f, 8, SEEK_CUR);
for (uint16_t c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */
(void) !fread(&fontdatm2[256 * d + c][0], 1, 16, fp);
for (uint16_t c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
(void) !fread(&fontdat2[256 * d + c][0], 1, 8, fp);
fseek(fp, 8, SEEK_CUR);
}
}
break;
}
(void) fclose(f);
(void) fclose(fp);
}
void
loadfont_ex(char *s, int format, int offset)
loadfont_ex(char *fn, int format, int offset)
{
FILE *fp;
fp = rom_fopen(s, "rb");
fp = rom_fopen(fn, "rb");
if (fp == NULL)
return;
@@ -1154,9 +1150,9 @@ loadfont_ex(char *s, int format, int offset)
}
void
loadfont(char *s, int format)
loadfont(char *fn, int format)
{
loadfont_ex(s, format, 0);
loadfont_ex(fn, format, 0);
}
uint32_t