Merge branch 'master' into pc98x1

This commit is contained in:
TC1995
2025-01-14 13:56:01 +01:00
86 changed files with 2904 additions and 1300 deletions

View File

@@ -32,6 +32,7 @@ It is also recommended to use a manager application with 86Box for easier handli
* [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only)
* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia)
* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux)
* [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python)
* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested)
* [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only)

View File

@@ -103,6 +103,7 @@
#include <86box/machine_status.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/nv/vid_nv_rivatimer.h>
// Disable c99-designator to avoid the warnings about int ng
#ifdef __clang__
@@ -252,12 +253,36 @@ static volatile atomic_int do_pause_ack = 0;
static volatile atomic_int pause_ack = 0;
#ifndef RELEASE_BUILD
static char buff[1024];
static int seen = 0;
#define LOG_SIZE_BUFFER 1024 /* Log size buffer */
static char buff[LOG_SIZE_BUFFER];
static int seen = 0;
static int suppr_seen = 1;
// Functions only used in this translation unit
void pclog_ensure_stdlog_open(void);
#endif
/*
Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic
*/
void pclog_ensure_stdlog_open(void)
{
#ifndef RELEASE_BUILD
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
#endif
}
/*
* Log something to the logfile or stdout.
*
@@ -269,19 +294,12 @@ void
pclog_ex(const char *fmt, va_list ap)
{
#ifndef RELEASE_BUILD
char temp[1024];
char temp[LOG_SIZE_BUFFER];
if (strcmp(fmt, "") == 0)
return;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
pclog_ensure_stdlog_open();
vsprintf(temp, fmt, ap);
if (suppr_seen && !strcmp(buff, temp))
@@ -298,6 +316,8 @@ pclog_ex(const char *fmt, va_list ap)
#endif
}
void
pclog_toggle_suppr(void)
{
@@ -1427,6 +1447,9 @@ pc_run(void)
pc_reset_hard_init();
}
/* Update the guest-CPU independent timer for devices with independent clock speed */
rivatimer_update_all();
/* Run a block of code. */
startblit();
cpu_exec((int32_t) cpu_s->rspeed / 100);

View File

@@ -156,9 +156,9 @@ mitsumi_cdrom_is_ready(const cdrom_t *dev)
static void
mitsumi_cdrom_reset(mcd_t *dev)
{
cdrom_t cdrom;
dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | STAT_CHANGE) : 0;
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | STAT_CHANGE) : 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 0;
dev->buf_count = 0;
@@ -176,12 +176,12 @@ mitsumi_cdrom_reset(mcd_t *dev)
static int
mitsumi_cdrom_read_sector(mcd_t *dev, int first)
{
cdrom_t cdrom;
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
uint8_t status;
int ret;
int ret = 0;
if (dev->drvmode == DRV_MODE_CDDA) {
status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount);
status = cdrom_mitsumi_audio_play(cdrom, dev->readmsf, dev->readcount);
if (status == 1)
return status;
else
@@ -195,15 +195,15 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first)
dev->data = 0;
return 0;
}
cdrom_stop(&cdrom);
ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
cdrom_stop(cdrom);
ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (ret <= 0)
return 0;
if (dev->mode & 0x40) {
dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff);
dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff);
}
dev->readmsf = cdrom_lba_to_msf_accurate(cdrom.seek_pos + 1);
dev->readmsf = cdrom_lba_to_msf_accurate(cdrom->seek_pos + 1);
dev->buf_count = dev->dmalen + 1;
dev->buf_idx = 0;
dev->data = 1;
@@ -224,7 +224,7 @@ static uint8_t
mitsumi_cdrom_in(uint16_t port, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
uint8_t ret;
uint8_t ret = 0xff;
pclog("Mitsumi CD-ROM IN=%03x\n", port);
switch (port & 1) {
@@ -259,14 +259,14 @@ mitsumi_cdrom_in(uint16_t port, void *priv)
break;
}
return 0xff;
return ret;
}
static void
mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
cdrom_t cdrom;
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val);
switch (port & 1) {
@@ -348,19 +348,19 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
}
if (!dev->cmdrd_count)
dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
return;
}
dev->cmd = val;
dev->cmdbuf_idx = 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->cmdbuf[0] = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->data = 0;
switch (val) {
case CMD_GET_INFO:
if (mitsumi_cdrom_is_ready(&cdrom)) {
cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1]));
if (mitsumi_cdrom_is_ready(cdrom)) {
cdrom_get_track_buffer(cdrom, &(dev->cmdbuf[1]));
dev->cmdbuf_count = 10;
dev->readcount = 0;
} else {
@@ -369,8 +369,8 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
}
break;
case CMD_GET_Q:
if (mitsumi_cdrom_is_ready(&cdrom)) {
cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
if (mitsumi_cdrom_is_ready(cdrom)) {
cdrom_get_q(cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
dev->cmdbuf_count = 11;
dev->readcount = 0;
} else {
@@ -386,7 +386,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_STOPCDDA:
case CMD_STOP:
cdrom_stop(&cdrom);
cdrom_stop(cdrom);
dev->drvmode = DRV_MODE_STOP;
dev->cur_toc_track = 0;
break;
@@ -395,7 +395,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_READ1X:
case CMD_READ2X:
if (mitsumi_cdrom_is_ready(&cdrom)) {
if (mitsumi_cdrom_is_ready(cdrom)) {
dev->readcount = 0;
dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ;
dev->cmdrd_count = 6;
@@ -411,7 +411,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
dev->cmdbuf_count = 3;
break;
case CMD_EJECT:
cdrom_stop(&cdrom);
cdrom_stop(cdrom);
cdrom_eject(0);
dev->readcount = 0;
break;
@@ -440,10 +440,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
static void *
mitsumi_cdrom_init(UNUSED(const device_t *info))
{
mcd_t *dev;
dev = malloc(sizeof(mcd_t));
memset(dev, 0x00, sizeof(mcd_t));
mcd_t *dev = calloc(1, sizeof(mcd_t));
dev->irq = MCD_DEFAULT_IRQ;
dev->dma = MCD_DEFAULT_DMA;

View File

@@ -225,12 +225,8 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
ali1531_shadow_recalc(val, dev);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x54:
case 0x55:
case 0x56:
case 0x50 ... 0x52:
case 0x54 ... 0x56:
dev->pci_conf[addr] = val;
break;
@@ -247,8 +243,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x86;
break;
case 0x59:
case 0x5a:
case 0x59 ... 0x5a:
case 0x5c:
dev->pci_conf[addr] = val;
break;
@@ -270,8 +265,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70:
case 0x71:
case 0x70 ... 0x71:
dev->pci_conf[addr] = val;
break;
@@ -283,8 +277,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x76:
case 0x77:
case 0x76 ... 0x77:
dev->pci_conf[addr] = val;
break;

View File

@@ -37,6 +37,9 @@
#define EMS_MAXPAGE 4
#define EMS_PGSIZE 16384
#define EMS_PGMASK 16383
#define REG_MASK 0x0f
/* CS8221 82C211 controller registers. */
#define REG_RA0 0x60 /* PROCCLK selector */
@@ -194,37 +197,47 @@
#define RB10_P0EXT 0xc0 /* page 0 extension */
#define RB10_P0EXT_SH 6
#define REG_RB11 0x6f /* Miscellaneous */
#define RB11_MASK 0xe6 /* 111R R11R */
#define RB11_GA20 0x02 /* gate for A20 */
#define RB11_RASTMO 0x04 /* enable RAS timeout counter */
#define RB11_EMSLEN 0xe0 /* EMS memory chunk size */
#define RB11_EMSLEN_SH 5
#define REG_RB12 0x6f /* Miscellaneous */
#define RB12_MASK 0xe6 /* 111R R11R */
#define RB12_GA20 0x02 /* gate for A20 */
#define RB12_RASTMO 0x04 /* enable RAS timeout counter */
#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */
#define RB12_EMSLEN_SH 5
typedef struct emspage_t {
int8_t enabled; /* 1=ENABLED */
#define RAM_FLAG_EMS 0x08
#define RAM_FLAG_ROMCS 0x04
#define RAM_FLAG_SHREAD 0x02
#define RAM_FLAG_SHWRITE 0x01
#define RAM_FMASK_EMS 0x08
#define RAM_FMASK_SHADOW 0x07
typedef struct ram_page_t {
int8_t enabled; /* 1=ENABLED */
char pad;
uint16_t page; /* selected page in EMS block */
uint32_t start; /* start of EMS in RAM */
uint8_t *addr; /* start addr in EMS RAM */
mem_mapping_t mapping; /* mapping entry for page */
} emspage_t;
uint32_t phys_base;
uint32_t virt_base;
mem_mapping_t mapping; /* mapping entry for page */
} ram_page_t;
typedef struct neat_t {
uint8_t regs[128]; /* all the CS8221 registers */
uint8_t indx; /* programmed index into registers */
uint8_t ram_flags[32];
uint8_t regs[128]; /* all the CS8221 registers */
uint8_t indx; /* programmed index into registers */
char pad;
char pad;
uint16_t ems_base; /* configured base address */
uint16_t ems_oldbase;
uint32_t ems_frame; /* configured frame address */
uint32_t ems_oldframe;
uint16_t ems_size; /* EMS size in KB */
uint16_t ems_pages; /* EMS size in pages */
emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */
uint16_t ems_base; /* configured base address */
uint32_t ems_frame; /* configured frame address */
uint16_t ems_size; /* EMS size in KB */
uint16_t ems_pages; /* EMS size in pages */
ram_page_t ems[EMS_MAXPAGE]; /* EMS page registers */
ram_page_t shadow[32]; /* Shadow RAM pages */
} neat_t;
static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00,
0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 };
#ifdef ENABLE_NEAT_LOG
int neat_do_log = ENABLE_NEAT_LOG;
@@ -247,11 +260,11 @@ neat_log(const char *fmt, ...)
static uint8_t
ems_readb(uint32_t addr, void *priv)
{
neat_t *dev = (neat_t *) priv;
uint8_t ret = 0xff;
ram_page_t *dev = (ram_page_t *) priv;
uint8_t ret = 0xff;
/* Grab the data. */
ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff));
ret = *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]);
return ret;
}
@@ -260,11 +273,11 @@ ems_readb(uint32_t addr, void *priv)
static uint16_t
ems_readw(uint32_t addr, void *priv)
{
neat_t *dev = (neat_t *) priv;
uint16_t ret = 0xffff;
ram_page_t *dev = (ram_page_t *) priv;
uint16_t ret = 0xffff;
/* Grab the data. */
ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff));
ret = *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]);
return ret;
}
@@ -273,40 +286,113 @@ ems_readw(uint32_t addr, void *priv)
static void
ems_writeb(uint32_t addr, uint8_t val, void *priv)
{
neat_t *dev = (neat_t *) priv;
ram_page_t *dev = (ram_page_t *) priv;
/* Write the data. */
*(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val;
*(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val;
}
/* Write one word to paged RAM. */
static void
ems_writew(uint32_t addr, uint16_t val, void *priv)
{
neat_t *dev = (neat_t *) priv;
ram_page_t *dev = (ram_page_t *) priv;
/* Write the data. */
*(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val;
*(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val;
}
static void
neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask)
{
if ((addr >= 0x00080000) && (addr < 0x00100000) &&
((new_flags ^ dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) {
dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask;
dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags;
new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE];
neat_log("neat_mem_update_state(): %08X-%08X: %02X\n", addr, addr + size - 1, new_flags);
if (new_flags & RAM_FLAG_EMS)
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else if (new_flags & RAM_FLAG_ROMCS)
mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS);
else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
}
flushmmucache_nopc();
}
static void
shadow_recalc(neat_t *dev)
{
for (uint8_t i = 8; i < 32; i++) {
int romcs = 0;
int write = 1;
int shadow_reg = REG_RB3 + ((i - 8) >> 3);
int shadow_bit = i & 7;
int ram_flags;
int read;
if (i > 16) {
int rb1_romcs_bit = 7 - (i >> 2);
int rb1_write_bit = rb1_romcs_bit + 4;
romcs = !(dev->regs[REG_RB1] & (1 << rb1_romcs_bit));
write = !(dev->regs[REG_RB1] & (1 << rb1_write_bit));
} else if (i <= 8)
shadow_bit ^= 4;
read = dev->regs[shadow_reg] & (1 << shadow_bit);
write = write && read;
ram_flags = romcs ? RAM_FLAG_ROMCS : 0x00;
ram_flags |= read ? RAM_FLAG_SHREAD : 0x00;
ram_flags |= write ? RAM_FLAG_SHWRITE : 0x00;
if ((ram_flags > 0x00) && !(ram_flags & RAM_FLAG_ROMCS))
mem_mapping_set_addr(&(dev->shadow[i].mapping), dev->shadow[i].virt_base, EMS_PGSIZE);
else
mem_mapping_disable(&(dev->shadow[i].mapping));
neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, ram_flags, RAM_FMASK_SHADOW);
}
}
/* Re-calculate the active-page physical address. */
static void
ems_recalc(neat_t *dev, emspage_t *ems)
ems_recalc(neat_t *dev, ram_page_t *ems)
{
if (ems->page >= dev->ems_pages) {
/* That page does not exist. */
ems->enabled = 0;
}
uint32_t page = ems->phys_base / EMS_PGSIZE;
/* Pre-calculate the page address in EMS RAM. */
ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE);
if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled &&
(page >= 0x40) && (page < (0x40 + dev->ems_pages))) {
neat_log("ems_recalc(): %08X-%08X -> %08X-%08X\n",
ems->virt_base, ems->virt_base + EMS_PGSIZE - 1,
ems->phys_base, ems->phys_base + EMS_PGSIZE - 1);
mem_mapping_set_addr(&ems->mapping, ems->virt_base, EMS_PGSIZE);
if (ems->enabled) {
/* Update the EMS RAM address for this page. */
mem_mapping_set_exec(&ems->mapping, ems->addr);
mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base);
/* Enable this page. */
mem_mapping_enable(&ems->mapping);
if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000))
neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS);
#if NEAT_DEBUG > 1
neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n",
@@ -315,15 +401,18 @@ ems_recalc(neat_t *dev, emspage_t *ems)
} else {
/* Disable this page. */
mem_mapping_disable(&ems->mapping);
if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000))
neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS);
}
}
static void
ems_write(uint16_t port, uint8_t val, void *priv)
{
neat_t *dev = (neat_t *) priv;
emspage_t *ems;
int vpage;
neat_t *dev = (neat_t *) priv;
ram_page_t *ems;
int vpage;
#if NEAT_DEBUG > 1
neat_log("NEAT: ems_write(%04x, %02x)\n", port, val);
@@ -337,8 +426,7 @@ ems_write(uint16_t port, uint8_t val, void *priv)
case 0x0008:
case 0x0009:
ems->enabled = !!(val & 0x80);
ems->page &= 0x0180; /* clear lower bits */
ems->page |= (val & 0x7f); /* add new bits */
ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE);
ems_recalc(dev, ems);
break;
default:
@@ -358,7 +446,7 @@ ems_read(uint16_t port, void *priv)
switch (port & 0x000f) {
case 0x0008: /* page number register */
ret = dev->ems[vpage].page & 0x7f;
ret = (dev->ems[vpage].phys_base / EMS_PGSIZE) & 0x7f;
if (dev->ems[vpage].enabled)
ret |= 0x80;
break;
@@ -373,68 +461,21 @@ ems_read(uint16_t port, void *priv)
return ret;
}
/* Initialize the EMS module. */
static void
ems_init(neat_t *dev, int en)
ems_update(neat_t *dev, int en)
{
uint8_t j;
/* Remove if needed. */
if (!en) {
if (dev->ems_base > 0)
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
/* Disable for now. */
mem_mapping_disable(&dev->ems[i].mapping);
/* Remove I/O handler. */
io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2,
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
}
#ifdef ENABLE_NEAT_LOG
neat_log("NEAT: EMS disabled\n");
#endif
return;
}
/* Get configured I/O address. */
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
dev->ems_base = 0x0208 + (0x10 * j);
/* Get configured frame address. */
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
dev->ems_frame = 0xC0000 + (EMS_PGSIZE * j);
/*
* For each supported page (we can have a maximum of 4),
* create, initialize and disable the mappings, and set
* up the I/O control handler.
*/
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
/* Create and initialize a page mapping. */
mem_mapping_add(&dev->ems[i].mapping,
dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE,
ems_readb, ems_readw, NULL,
ems_writeb, ems_writew, NULL,
ram, MEM_MAPPING_EXTERNAL,
dev);
/* Disable for now. */
mem_mapping_disable(&dev->ems[i].mapping);
/* Set up an I/O port handler. */
io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2,
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
io_handler(en, dev->ems_base + (i * EMS_PGSIZE), 2,
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
/*
* TODO: update the 'high_mem' mapping to reflect that we now
* have NN MB less extended memory available..
*/
if (en)
dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE);
ems_recalc(dev, &(dev->ems[i]));
}
neat_log("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n",
dev->ems_base, dev->ems_frame);
flushmmucache_nopc();
}
static void
@@ -442,6 +483,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
{
neat_t *dev = (neat_t *) priv;
uint8_t xval;
uint8_t j;
uint8_t *reg;
int i;
@@ -493,6 +535,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB1:
val &= RB1_MASK;
*reg = (*reg & ~RB1_MASK) | val;
shadow_recalc(dev);
#if NEAT_DEBUG > 1
neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg);
#endif
@@ -501,6 +544,10 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB2:
val &= RB2_MASK;
*reg = (*reg & ~RB2_MASK) | val;
if (val & RB2_TOP128)
neat_mem_update_state(dev, 0x00080000, 0x00020000, RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE, RAM_FMASK_SHADOW);
else
neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, RAM_FMASK_SHADOW);
#if NEAT_DEBUG > 1
neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg);
#endif
@@ -509,6 +556,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB3:
val &= RB3_MASK;
*reg = (*reg & ~RB3_MASK) | val;
shadow_recalc(dev);
#if NEAT_DEBUG > 1
neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg);
#endif
@@ -517,6 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB4:
val &= RB4_MASK;
*reg = (*reg & ~RB4_MASK) | val;
shadow_recalc(dev);
#if NEAT_DEBUG > 1
neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg);
#endif
@@ -525,6 +574,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB5:
val &= RB5_MASK;
*reg = (*reg & ~RB5_MASK) | val;
shadow_recalc(dev);
#if NEAT_DEBUG > 1
neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg);
#endif
@@ -544,10 +594,9 @@ neat_write(uint16_t port, uint8_t val, void *priv)
#if NEAT_DEBUG > 1
neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg);
#endif
if (val & RB7_EMSEN)
ems_init(dev, 1);
else if (xval & RB7_EMSEN)
ems_init(dev, 0);
if (xval & RB7_EMSEN)
ems_update(dev, !!(val & RB7_EMSEN));
if (xval & RB7_UMAREL) {
if (val & RB7_UMAREL)
@@ -571,10 +620,19 @@ neat_write(uint16_t port, uint8_t val, void *priv)
#if NEAT_DEBUG > 1
neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg);
#endif
if (dev->regs[REG_RB7] & RB7_EMSEN) {
ems_init(dev, 0);
ems_init(dev, 1);
}
ems_update(dev, 0);
/* Get configured I/O address. */
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
dev->ems_base = 0x0208 + (0x10 * j);
/* Get configured frame address. */
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j);
if (dev->regs[REG_RB7] & RB7_EMSEN)
ems_update(dev, 1);
break;
case REG_RB10:
@@ -584,23 +642,29 @@ neat_write(uint16_t port, uint8_t val, void *priv)
neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg);
#endif
dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21;
dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21;
dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21;
dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21;
for (i = 0; i < EMS_MAXPAGE; i++)
ems_recalc(dev, &dev->ems[i]);
dev->ems[3].phys_base = (dev->ems[3].phys_base & 0x001fffff) |
(((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21);
dev->ems[2].phys_base = (dev->ems[2].phys_base & 0x001fffff) |
(((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21);
dev->ems[1].phys_base = (dev->ems[1].phys_base & 0x001fffff) |
(((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21);
dev->ems[0].phys_base = (dev->ems[0].phys_base & 0x001fffff) |
(((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21);
if (dev->regs[REG_RB7] & RB7_EMSEN)
for (i = 0; i < EMS_MAXPAGE; i++)
ems_recalc(dev, &dev->ems[i]);
break;
case REG_RB11:
val &= RB11_MASK;
*reg = (*reg & ~RB11_MASK) | val;
case REG_RB12:
val &= RB12_MASK;
*reg = (*reg & ~RB12_MASK) | val;
#if NEAT_DEBUG > 1
neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg);
neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg);
#endif
i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH;
i = (val & RB12_EMSLEN) >> RB12_EMSLEN_SH;
switch (i) {
case 0: /* "less than 2MB" */
case 0: /* "less than 1MB" */
dev->ems_size = 512;
break;
@@ -617,10 +681,18 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
}
dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE;
if (dev->regs[REG_RB7] & RB7_EMSEN)
for (i = 0; i < EMS_MAXPAGE; i++)
ems_recalc(dev, &dev->ems[i]);
if (dev->regs[REG_RB7] & RB7_EMSEN) {
neat_log("NEAT: EMS %iKB (%i pages)\n",
dev->ems_size, dev->ems_pages);
}
mem_a20_key = val & RB12_GA20;
mem_a20_recalc();
break;
default:
@@ -629,6 +701,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
}
break;
default:
break;
}
@@ -646,8 +719,10 @@ neat_read(uint16_t port, void *priv)
break;
case 0x23:
if ((dev->indx >= 0x60) && (dev->indx <= 0x6f))
if ((dev->indx >= 0x60) && (dev->indx <= 0x6e))
ret = dev->regs[dev->indx];
else if (dev->indx == 0x6f)
ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2);
break;
default:
@@ -674,16 +749,50 @@ neat_init(UNUSED(const device_t *info))
{
neat_t *dev;
uint8_t dram_mode = 0;
uint8_t i;
uint8_t j;
/* Create an instance. */
dev = (neat_t *) malloc(sizeof(neat_t));
memset(dev, 0x00, sizeof(neat_t));
/* Get configured I/O address. */
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
dev->ems_base = 0x0208 + (0x10 * j);
/* Get configured frame address. */
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j);
mem_mapping_disable(&ram_mid_mapping);
/*
* For each supported page (we can have a maximum of 4),
* create, initialize and disable the mappings, and set
* up the I/O control handler.
*/
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
/* Create and initialize a page mapping. */
mem_mapping_add(&dev->ems[i].mapping,
dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE,
ems_readb, ems_readw, NULL,
ems_writeb, ems_writew, NULL,
ram, MEM_MAPPING_INTERNAL,
&(dev->ems[i]));
/* Disable for now. */
mem_mapping_disable(&dev->ems[i].mapping);
}
for (uint8_t i = 0; i < 32; i++) {
dev->shadow[i].virt_base = dev->shadow[i].phys_base =
(i * EMS_PGSIZE) + 0x00080000;
dev->shadow[i].enabled = 1;
}
/* Initialize some of the registers to specific defaults. */
for (i = REG_RA0; i <= REG_RB11; i++) {
for (uint8_t i = REG_RA0; i <= REG_RB12; i++) {
dev->indx = i;
neat_write(0x0023, 0x00, dev);
neat_write(0x0023, defaults[i & REG_MASK], dev);
}
/*

View File

@@ -101,6 +101,8 @@ typedef struct scamp_t {
int ram_interleaved[2];
int ibank_shift[2];
int ram_flags[24];
port_92_t *port_92;
} scamp_t;
@@ -593,6 +595,35 @@ scamp_ems_write(uint32_t addr, uint8_t val, void *priv)
ram[addr] = val;
}
static void
scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size)
{
uint8_t flags;
if ((addr >= 0x000a0000) && (addr < 0x00100000)) {
flags = dev->ram_flags[(addr - 0x000a0000) >> 14];
if (flags & 4)
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else switch (flags & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
}
}
static void
recalc_ems(scamp_t *dev)
{
@@ -630,34 +661,48 @@ recalc_ems(scamp_t *dev)
if (new_mappings[segment] < (mem_size * 1024)) {
mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]);
mem_mapping_enable(&dev->ems_mappings[segment]);
} else
dev->ram_flags[segment] |= 0x04;
} else {
mem_mapping_disable(&dev->ems_mappings[segment]);
dev->ram_flags[segment] &= 0xfb;
}
scamp_mem_update_state(dev, 0xa0000 + segment * 0x4000, 0x4000);
}
}
flushmmucache_nopc();
}
static void
shadow_control(uint32_t addr, uint32_t size, int state, int ems_enable)
shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state)
{
if (ems_enable)
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
switch (state) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
dev->ram_flags[(addr - 0x000a0000) >> 14] &= 0xfc;
dev->ram_flags[(addr - 0x000a0000) >> 14] |= state;
if (size == 0x8000) {
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc;
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state;
}
switch (state) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
scamp_mem_update_state(dev, addr, size);
flushmmucache_nopc();
}
@@ -669,47 +714,38 @@ shadow_recalc(scamp_t *dev)
uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS];
uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS];
uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS];
uint32_t ems_enable;
if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB) {
if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP) /*Axxx/Bxxx/Dxxx*/
ems_enable = (dev->cfg_regs[CFG_EMSEN2] & 0xf) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 4) | ((dev->cfg_regs[CFG_EMSEN2] & 0xf0) << 8);
else /*Cxxx/Dxxx/Exxx*/
ems_enable = (dev->cfg_regs[CFG_EMSEN2] << 8) | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 16);
} else
ems_enable = 0;
/*Enabling remapping will disable all shadowing*/
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)
mem_remap_top(384);
shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00001);
shadow_control(0xa0000, 0x4000, abaxs & 3, ems_enable & 0x00002);
shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00004);
shadow_control(0xa8000, 0x4000, (abaxs >> 2) & 3, ems_enable & 0x00008);
shadow_control(dev, 0xa0000, 0x4000, abaxs & 3);
shadow_control(dev, 0xa0000, 0x4000, abaxs & 3);
shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3);
shadow_control(dev, 0xa8000, 0x4000, (abaxs >> 2) & 3);
shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00010);
shadow_control(0xb0000, 0x4000, (abaxs >> 4) & 3, ems_enable & 0x00020);
shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00040);
shadow_control(0xb8000, 0x4000, (abaxs >> 6) & 3, ems_enable & 0x00080);
shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3);
shadow_control(dev, 0xb0000, 0x4000, (abaxs >> 4) & 3);
shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3);
shadow_control(dev, 0xb8000, 0x4000, (abaxs >> 6) & 3);
shadow_control(0xc0000, 0x4000, caxs & 3, ems_enable & 0x00100);
shadow_control(0xc4000, 0x4000, (caxs >> 2) & 3, ems_enable & 0x00200);
shadow_control(0xc8000, 0x4000, (caxs >> 4) & 3, ems_enable & 0x00400);
shadow_control(0xcc000, 0x4000, (caxs >> 6) & 3, ems_enable & 0x00800);
shadow_control(dev, 0xc0000, 0x4000, caxs & 3);
shadow_control(dev, 0xc4000, 0x4000, (caxs >> 2) & 3);
shadow_control(dev, 0xc8000, 0x4000, (caxs >> 4) & 3);
shadow_control(dev, 0xcc000, 0x4000, (caxs >> 6) & 3);
shadow_control(0xd0000, 0x4000, daxs & 3, ems_enable & 0x01000);
shadow_control(0xd4000, 0x4000, (daxs >> 2) & 3, ems_enable & 0x02000);
shadow_control(0xd8000, 0x4000, (daxs >> 4) & 3, ems_enable & 0x04000);
shadow_control(0xdc000, 0x4000, (daxs >> 6) & 3, ems_enable & 0x08000);
shadow_control(dev, 0xd0000, 0x4000, daxs & 3);
shadow_control(dev, 0xd4000, 0x4000, (daxs >> 2) & 3);
shadow_control(dev, 0xd8000, 0x4000, (daxs >> 4) & 3);
shadow_control(dev, 0xdc000, 0x4000, (daxs >> 6) & 3);
shadow_control(0xe0000, 0x4000, feaxs & 3, ems_enable & 0x10000);
shadow_control(0xe4000, 0x4000, feaxs & 3, ems_enable & 0x20000);
shadow_control(0xe8000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x40000);
shadow_control(0xec000, 0x4000, (feaxs >> 2) & 3, ems_enable & 0x80000);
shadow_control(dev, 0xe0000, 0x4000, feaxs & 3);
shadow_control(dev, 0xe4000, 0x4000, feaxs & 3);
shadow_control(dev, 0xe8000, 0x4000, (feaxs >> 2) & 3);
shadow_control(dev, 0xec000, 0x4000, (feaxs >> 2) & 3);
shadow_control(0xf0000, 0x8000, (feaxs >> 4) & 3, 0);
shadow_control(0xf8000, 0x8000, (feaxs >> 6) & 3, 0);
shadow_control(dev, 0xf0000, 0x8000, (feaxs >> 4) & 3);
shadow_control(dev, 0xf8000, 0x8000, (feaxs >> 6) & 3);
}
static void

View File

@@ -106,7 +106,7 @@ sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev)
{
memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs));
if (dev->rev == 0b0) {
if (dev->rev == 0xb0) {
dev->apc_regs[0x03] = 0x80;
dev->apc_regs[0x04] = 0x38;
dev->apc_regs[0x07] = 0x01;

View File

@@ -475,8 +475,6 @@ load_input_devices(void)
{
ini_section_t cat = ini_find_section(config, "Input devices");
char temp[512];
int c;
int d;
char *p;
p = ini_section_get_string(cat, "mouse_type", NULL);
@@ -495,8 +493,8 @@ load_input_devices(void)
/* Workaround for ini_section_get_int returning 0 on non-integer data */
joystick_type = joystick_get_from_internal_name("2axis_2button");
else {
c = ini_section_get_int(cat, "joystick_type", 8);
switch (c) {
int js = ini_section_get_int(cat, "joystick_type", 8);
switch (js) {
case JS_TYPE_2AXIS_4BUTTON:
joystick_type = joystick_get_from_internal_name("2axis_4button");
break;
@@ -527,25 +525,25 @@ load_input_devices(void)
} else
joystick_type = JS_TYPE_NONE;
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) {
sprintf(temp, "joystick_%i_nr", c);
joystick_state[c].plat_joystick_nr = ini_section_get_int(cat, temp, 0);
for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) {
sprintf(temp, "joystick_%i_nr", js);
joystick_state[js].plat_joystick_nr = ini_section_get_int(cat, temp, 0);
if (joystick_state[c].plat_joystick_nr) {
for (d = 0; d < joystick_get_axis_count(joystick_type); d++) {
sprintf(temp, "joystick_%i_axis_%i", c, d);
joystick_state[c].axis_mapping[d] = ini_section_get_int(cat, temp, d);
if (joystick_state[js].plat_joystick_nr) {
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) {
sprintf(temp, "joystick_%i_axis_%i", js, axis_nr);
joystick_state[js].axis_mapping[axis_nr] = ini_section_get_int(cat, temp, axis_nr);
}
for (d = 0; d < joystick_get_button_count(joystick_type); d++) {
sprintf(temp, "joystick_%i_button_%i", c, d);
joystick_state[c].button_mapping[d] = ini_section_get_int(cat, temp, d);
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) {
sprintf(temp, "joystick_%i_button_%i", js, button_nr);
joystick_state[js].button_mapping[button_nr] = ini_section_get_int(cat, temp, button_nr);
}
for (d = 0; d < joystick_get_pov_count(joystick_type); d++) {
sprintf(temp, "joystick_%i_pov_%i", c, d);
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) {
sprintf(temp, "joystick_%i_pov_%i", js, pov_nr);
p = ini_section_get_string(cat, temp, "0, 0");
joystick_state[c].pov_mapping[d][0] = joystick_state[c].pov_mapping[d][1] = 0;
sscanf(p, "%i, %i", &joystick_state[c].pov_mapping[d][0],
&joystick_state[c].pov_mapping[d][1]);
joystick_state[js].pov_mapping[pov_nr][0] = joystick_state[js].pov_mapping[pov_nr][1] = 0;
sscanf(p, "%i, %i", &joystick_state[js].pov_mapping[pov_nr][0],
&joystick_state[js].pov_mapping[pov_nr][1]);
}
}
}
@@ -743,11 +741,9 @@ load_ports(void)
ini_section_t cat = ini_find_section(config, "Ports (COM & LPT)");
char *p;
char temp[512];
int c;
memset(temp, 0, sizeof(temp));
for (c = 0; c < SERIAL_MAX; c++) {
for (int c = 0; c < SERIAL_MAX; c++) {
sprintf(temp, "serial%d_enabled", c + 1);
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
@@ -758,7 +754,7 @@ load_ports(void)
config_log("Serial Port %d: passthrough enabled.\n\n", c + 1);
}
for (c = 0; c < PARALLEL_MAX; c++) {
for (int c = 0; c < PARALLEL_MAX; c++) {
sprintf(temp, "lpt%d_enabled", c + 1);
lpt_ports[c].enabled = !!ini_section_get_int(cat, temp, (c == 0) ? 1 : 0);
@@ -776,11 +772,10 @@ load_storage_controllers(void)
ini_section_t migration_cat;
char *p;
char temp[512];
int c;
int min = 0;
int free_p = 0;
for (c = min; c < SCSI_CARD_MAX; c++) {
for (int c = min; c < SCSI_CARD_MAX; c++) {
sprintf(temp, "scsicard_%d", c + 1);
p = ini_section_get_string(cat, temp, NULL);
@@ -932,7 +927,7 @@ load_storage_controllers(void)
ini_section_delete_var(cat, "cassette_ui_writeprot");
}
for (c = 0; c < 2; c++) {
for (int c = 0; c < 2; c++) {
sprintf(temp, "cartridge_%02i_fn", c + 1);
p = ini_section_get_string(cat, temp, "");
@@ -2140,50 +2135,49 @@ save_input_devices(void)
ini_section_t cat = ini_find_or_create_section(config, "Input devices");
char temp[512];
char tmp2[512];
int c;
int d;
ini_section_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type));
if (!joystick_type) {
ini_section_delete_var(cat, "joystick_type");
for (c = 0; c < 16; c++) {
sprintf(tmp2, "joystick_%i_nr", c);
for (int js = 0; js < MAX_PLAT_JOYSTICKS; js++) {
sprintf(tmp2, "joystick_%i_nr", js);
ini_section_delete_var(cat, tmp2);
for (d = 0; d < 16; d++) {
sprintf(tmp2, "joystick_%i_axis_%i", c, d);
for (int axis_nr = 0; axis_nr < MAX_JOY_AXES; axis_nr++) {
sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr);
ini_section_delete_var(cat, tmp2);
}
for (d = 0; d < 16; d++) {
sprintf(tmp2, "joystick_%i_button_%i", c, d);
for (int button_nr = 0; button_nr < MAX_JOY_BUTTONS; button_nr++) {
sprintf(tmp2, "joystick_%i_button_%i", js, button_nr);
ini_section_delete_var(cat, tmp2);
}
for (d = 0; d < 16; d++) {
sprintf(tmp2, "joystick_%i_pov_%i", c, d);
for (int pov_nr = 0; pov_nr < MAX_JOY_POVS; pov_nr++) {
sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr);
ini_section_delete_var(cat, tmp2);
}
}
} else {
ini_section_set_string(cat, "joystick_type", joystick_get_internal_name(joystick_type));
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) {
sprintf(tmp2, "joystick_%i_nr", c);
ini_section_set_int(cat, tmp2, joystick_state[c].plat_joystick_nr);
for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) {
sprintf(tmp2, "joystick_%i_nr", js);
ini_section_set_int(cat, tmp2, joystick_state[js].plat_joystick_nr);
if (joystick_state[c].plat_joystick_nr) {
for (d = 0; d < joystick_get_axis_count(joystick_type); d++) {
sprintf(tmp2, "joystick_%i_axis_%i", c, d);
ini_section_set_int(cat, tmp2, joystick_state[c].axis_mapping[d]);
if (joystick_state[js].plat_joystick_nr) {
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++) {
sprintf(tmp2, "joystick_%i_axis_%i", js, axis_nr);
ini_section_set_int(cat, tmp2, joystick_state[js].axis_mapping[axis_nr]);
}
for (d = 0; d < joystick_get_button_count(joystick_type); d++) {
sprintf(tmp2, "joystick_%i_button_%i", c, d);
ini_section_set_int(cat, tmp2, joystick_state[c].button_mapping[d]);
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++) {
sprintf(tmp2, "joystick_%i_button_%i", js, button_nr);
ini_section_set_int(cat, tmp2, joystick_state[js].button_mapping[button_nr]);
}
for (d = 0; d < joystick_get_pov_count(joystick_type); d++) {
sprintf(tmp2, "joystick_%i_pov_%i", c, d);
sprintf(temp, "%i, %i", joystick_state[c].pov_mapping[d][0], joystick_state[c].pov_mapping[d][1]);
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) {
sprintf(tmp2, "joystick_%i_pov_%i", js, pov_nr);
sprintf(temp, "%i, %i", joystick_state[js].pov_mapping[pov_nr][0],
joystick_state[js].pov_mapping[pov_nr][1]);
ini_section_set_string(cat, tmp2, temp);
}
}
@@ -2341,10 +2335,8 @@ save_ports(void)
{
ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)");
char temp[512];
int c;
int d;
for (c = 0; c < SERIAL_MAX; c++) {
for (int c = 0; c < SERIAL_MAX; c++) {
sprintf(temp, "serial%d_enabled", c + 1);
if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled))
ini_section_delete_var(cat, temp);
@@ -2358,9 +2350,9 @@ save_ports(void)
ini_section_delete_var(cat, temp);
}
for (c = 0; c < PARALLEL_MAX; c++) {
for (int c = 0; c < PARALLEL_MAX; c++) {
sprintf(temp, "lpt%d_enabled", c + 1);
d = (c == 0) ? 1 : 0;
int d = (c == 0) ? 1 : 0;
if (lpt_ports[c].enabled == d)
ini_section_delete_var(cat, temp);
else

View File

@@ -1634,28 +1634,75 @@ cpu_data_opff_rm(void)
}
}
uint8_t
cpu_inb(uint16_t port)
{
int old_cycles = cycles;
uint8_t ret;
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
ret = inb(port);
resub_cycles(old_cycles);
return ret;
}
uint16_t
cpu_inw(uint16_t port)
{
int old_cycles = cycles;
uint16_t ret;
wait(is_mazovia ? 5 : 4, 1);
if (is8086 && !(port & 1)) {
wait(4, 0);
old_cycles = cycles;
ret = inw(port);
} else {
wait(8, 0);
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
ret = inb(port++);
ret |= (inb(port) << 8);
}
return inw(port);
resub_cycles(old_cycles);
return ret;
}
void
cpu_outb(uint16_t port, uint16_t val)
{
int old_cycles = cycles;
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
outb(port, val);
resub_cycles(old_cycles);
}
void
cpu_outw(uint16_t port, uint16_t val)
{
int old_cycles = cycles;
wait(is_mazovia ? 5 : 4, 1);
if (is8086 && !(port & 1)) {
wait(4, 0);
old_cycles = cycles;
outw(port, val);
} else {
wait(8, 0);
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
outb(port++, val);
outb(port, val >> 8);
}
return outw(port, val);
resub_cycles(old_cycles);
}
/* Executes instructions up to the specified number of cycles. */
@@ -1804,8 +1851,7 @@ execx86(int cycs)
writememw(es, DI, cpu_inw(DX));
DI += (cpu_state.flags & D_FLAG) ? -2 : 2;
} else {
wait(4, 0);
writememb(es, DI, inb(DX));
writememb(es, DI, cpu_inb(DX));
DI += (cpu_state.flags & D_FLAG) ? -1 : 1;
}
@@ -1833,8 +1879,7 @@ execx86(int cycs)
cpu_outw(DX, readmemw(dest_seg, SI));
SI += (cpu_state.flags & D_FLAG) ? -2 : 2;
} else {
wait(4, 0);
outb(DX, readmemb(dest_seg + SI));
cpu_outb(DX, readmemb(dest_seg + SI));
SI += (cpu_state.flags & D_FLAG) ? -1 : 1;
}
if (in_rep == 0)

View File

@@ -22,12 +22,8 @@ opSYSCALL(uint32_t fetchdat)
ret = syscall_op(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -41,12 +37,8 @@ opSYSRET(uint32_t fetchdat)
ret = sysret(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}

View File

@@ -18,12 +18,8 @@ opSYSENTER(uint32_t fetchdat)
{
int ret = sysenter(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -33,12 +29,8 @@ opSYSEXIT(uint32_t fetchdat)
{
int ret = sysexit(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -118,7 +110,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
}
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
CLOCK_CYCLES(1);
} else {
/* FXSAVE */
writememw(easeg, cpu_state.eaaddr, i387_get_control_word());
@@ -163,7 +156,7 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp);
}
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
CLOCK_CYCLES(1);
}
return cpu_state.abrt;
@@ -327,7 +320,8 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
}
}
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
CLOCK_CYCLES(1);
} else {
/* FXSAVE */
if ((twd & 0x0003) != 0x0003)
@@ -372,7 +366,7 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
cpu_state.eaaddr = old_eaaddr;
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
CLOCK_CYCLES(1);
}
return cpu_state.abrt;
@@ -400,8 +394,7 @@ static int
opHINT_NOP_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
CLOCK_CYCLES((is486) ? 1 : 3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
CLOCK_CYCLES(1);
return 0;
}
@@ -409,7 +402,6 @@ static int
opHINT_NOP_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
CLOCK_CYCLES((is486) ? 1 : 3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
CLOCK_CYCLES(1);
return 0;
}

View File

@@ -19,7 +19,7 @@
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -89,38 +89,38 @@ device_init(void)
}
void
device_set_context(device_context_t *c, const device_t *dev, int inst)
device_set_context(device_context_t *ctx, const device_t *dev, int inst)
{
memset(c, 0, sizeof(device_context_t));
c->dev = dev;
c->instance = inst;
memset(ctx, 0, sizeof(device_context_t));
ctx->dev = dev;
ctx->instance = inst;
if (inst) {
sprintf(c->name, "%s #%i", dev->name, inst);
sprintf(ctx->name, "%s #%i", dev->name, inst);
/* If a numbered section is not present, but a non-numbered of the same name
is, rename the non-numbered section to numbered. */
const void *sec = config_find_section(c->name);
const void *sec = config_find_section(ctx->name);
void * single_sec = config_find_section((char *) dev->name);
if ((sec == NULL) && (single_sec != NULL))
config_rename_section(single_sec, c->name);
config_rename_section(single_sec, ctx->name);
} else if (!strcmp(dev->name, "PS/2 Mouse")) {
sprintf(c->name, "%s", dev->name);
sprintf(ctx->name, "%s", dev->name);
/* Migrate the old "Standard PS/2 Mouse" section */
const void *sec = config_find_section(c->name);
const void *sec = config_find_section(ctx->name);
void * old_sec = config_find_section("Standard PS/2 Mouse");
if ((sec == NULL) && (old_sec != NULL))
config_rename_section(old_sec, c->name);
config_rename_section(old_sec, ctx->name);
} else if (!strcmp(dev->name, "Microsoft RAMCard")) {
sprintf(c->name, "%s", dev->name);
sprintf(ctx->name, "%s", dev->name);
/* Migrate the old "Standard PS/2 Mouse" section */
const void *sec = config_find_section(c->name);
/* Migrate the old "Microsoft RAMCard for IBM PC" section */
const void *sec = config_find_section(ctx->name);
void * old_sec = config_find_section("Microsoft RAMCard for IBM PC");
if ((sec == NULL) && (old_sec != NULL))
config_rename_section(old_sec, c->name);
config_rename_section(old_sec, ctx->name);
} else
sprintf(c->name, "%s", dev->name);
sprintf(ctx->name, "%s", dev->name);
}
static void
@@ -153,7 +153,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst)
{
device_t *init_dev = NULL;
void *priv = NULL;
int c;
int16_t c;
if (params != NULL) {
init_dev = calloc(1, sizeof(device_t));
@@ -162,7 +162,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst)
} else
init_dev = (device_t *) dev;
for (c = 0; c < 256; c++) {
for (c = 0; c < DEVICE_MAX; c++) {
if (!inst && (devices[c] == dev)) {
device_log("DEVICE: device already exists!\n");
return (NULL);
@@ -244,6 +244,7 @@ void *
device_add_linked(const device_t *dev, void *priv)
{
void *ret;
device_common_priv = priv;
ret = device_add_common(dev, NULL, NULL, 0);
device_common_priv = NULL;
@@ -311,7 +312,8 @@ device_close_all(void)
#endif
if (devices[c]->close != NULL)
devices[c]->close(device_priv[c]);
devices[c] = device_priv[c] = NULL;
devices[c] = NULL;
device_priv[c] = NULL;
}
}
}
@@ -372,7 +374,7 @@ device_available(const device_t *dev)
if (dev != NULL) {
config = dev->config;
if (config != NULL) {
while (config->type != -1) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
int roms_present = 0;
@@ -414,7 +416,7 @@ device_get_bios_file(const device_t *dev, const char *internal_name, int file_no
if (dev != NULL) {
config = dev->config;
if (config != NULL) {
while (config->type != -1) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
bios = config->bios;
@@ -452,7 +454,7 @@ device_has_config(const device_t *dev)
config = dev->config;
while (config->type != -1) {
while (config->type != CONFIG_END) {
c++;
config++;
}
@@ -543,8 +545,7 @@ device_get_name(const device_t *dev, int bus, char *name)
strcat(pbus, ")");
/* Allocate the temporary device name string and set it to all zeroes. */
tname = (char *) malloc(strlen(dev->name) + 1);
memset(tname, 0x00, strlen(dev->name) + 1);
tname = (char *) calloc(1, strlen(dev->name) + 1);
/* First strip the bus string with parentheses. */
fbus = strstr(dev->name, pbus);
@@ -612,256 +613,256 @@ device_get_instance(void)
}
const char *
device_get_config_string(const char *s)
device_get_config_string(const char *str)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_string((char *) device_current.name, (char *) str, (char *) cfg->default_string));
c++;
cfg++;
}
return (NULL);
}
int
device_get_config_int(const char *s)
device_get_config_int(const char *str)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_int((char *) device_current.name, (char *) s, c->default_int));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int));
c++;
cfg++;
}
return 0;
}
int
device_get_config_int_ex(const char *s, int def)
device_get_config_int_ex(const char *str, int def)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_int((char *) device_current.name, (char *) s, def));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, def));
c++;
cfg++;
}
return def;
}
int
device_get_config_hex16(const char *s)
device_get_config_hex16(const char *str)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_hex16((char *) device_current.name, (char *) s, c->default_int));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int));
c++;
cfg++;
}
return 0;
}
int
device_get_config_hex20(const char *s)
device_get_config_hex20(const char *str)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_hex20((char *) device_current.name, (char *) s, c->default_int));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int));
c++;
cfg++;
}
return 0;
}
int
device_get_config_mac(const char *s, int def)
device_get_config_mac(const char *str, int def)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_mac((char *) device_current.name, (char *) s, def));
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_mac((char *) device_current.name, (char *) str, def));
c++;
cfg++;
}
return def;
}
void
device_set_config_int(const char *s, int val)
device_set_config_int(const char *str, int val)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name)) {
config_set_int((char *) device_current.name, (char *) s, val);
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_int((char *) device_current.name, (char *) str, val);
break;
}
c++;
cfg++;
}
}
void
device_set_config_hex16(const char *s, int val)
device_set_config_hex16(const char *str, int val)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name)) {
config_set_hex16((char *) device_current.name, (char *) s, val);
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_hex16((char *) device_current.name, (char *) str, val);
break;
}
c++;
cfg++;
}
}
void
device_set_config_hex20(const char *s, int val)
device_set_config_hex20(const char *str, int val)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name)) {
config_set_hex20((char *) device_current.name, (char *) s, val);
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_hex20((char *) device_current.name, (char *) str, val);
break;
}
c++;
cfg++;
}
}
void
device_set_config_mac(const char *s, int val)
device_set_config_mac(const char *str, int val)
{
const device_config_t *c = device_current.dev->config;
const device_config_t *cfg = device_current.dev->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name)) {
config_set_mac((char *) device_current.name, (char *) s, val);
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_mac((char *) device_current.name, (char *) str, val);
break;
}
c++;
cfg++;
}
}
int
device_is_valid(const device_t *device, int m)
device_is_valid(const device_t *device, int mch)
{
if (device == NULL)
return 1;
if ((device->flags & DEVICE_PCJR) && !machine_has_bus(m, MACHINE_BUS_PCJR))
if ((device->flags & DEVICE_PCJR) && !machine_has_bus(mch, MACHINE_BUS_PCJR))
return 0;
if ((device->flags & DEVICE_XTKBC) && machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC))
if ((device->flags & DEVICE_XTKBC) && machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC))
return 0;
if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16))
if ((device->flags & DEVICE_AT) && !machine_has_bus(mch, MACHINE_BUS_ISA16))
return 0;
if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC))
if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC))
return 0;
if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2_PORTS))
if ((device->flags & DEVICE_PS2) && !machine_has_bus(mch, MACHINE_BUS_PS2_PORTS))
return 0;
if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA))
if ((device->flags & DEVICE_ISA) && !machine_has_bus(mch, MACHINE_BUS_ISA))
return 0;
if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS))
if ((device->flags & DEVICE_CBUS) && !machine_has_bus(mch, MACHINE_BUS_CBUS))
return 0;
if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_ISA))
if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_ISA))
return 0;
if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA))
if ((device->flags & DEVICE_MCA) && !machine_has_bus(mch, MACHINE_BUS_MCA))
return 0;
if ((device->flags & DEVICE_HIL) && !machine_has_bus(m, MACHINE_BUS_HIL))
if ((device->flags & DEVICE_HIL) && !machine_has_bus(mch, MACHINE_BUS_HIL))
return 0;
if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA))
if ((device->flags & DEVICE_EISA) && !machine_has_bus(mch, MACHINE_BUS_EISA))
return 0;
if ((device->flags & DEVICE_AT32) && !machine_has_bus(m, MACHINE_BUS_AT32))
if ((device->flags & DEVICE_AT32) && !machine_has_bus(mch, MACHINE_BUS_AT32))
return 0;
if ((device->flags & DEVICE_OLB) && !machine_has_bus(m, MACHINE_BUS_OLB))
if ((device->flags & DEVICE_OLB) && !machine_has_bus(mch, MACHINE_BUS_OLB))
return 0;
if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB))
if ((device->flags & DEVICE_VLB) && !machine_has_bus(mch, MACHINE_BUS_VLB))
return 0;
if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI))
if ((device->flags & DEVICE_PCI) && !machine_has_bus(mch, MACHINE_BUS_PCI))
return 0;
if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_PCI))
if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_PCI))
return 0;
if ((device->flags & DEVICE_USB) && !machine_has_bus(m, MACHINE_BUS_USB))
if ((device->flags & DEVICE_USB) && !machine_has_bus(mch, MACHINE_BUS_USB))
return 0;
if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP))
if ((device->flags & DEVICE_AGP) && !machine_has_bus(mch, MACHINE_BUS_AGP))
return 0;
if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97))
if ((device->flags & DEVICE_AC97) && !machine_has_bus(mch, MACHINE_BUS_AC97))
return 0;
return 1;
}
int
machine_get_config_int(char *s)
machine_get_config_int(char *str)
{
const device_t *d = machine_get_device(machine);
const device_config_t *c;
const device_t *dev = machine_get_device(machine);
const device_config_t *cfg;
if (d == NULL)
if (dev == NULL)
return 0;
c = d->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_int((char *) d->name, s, c->default_int));
cfg = dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) dev->name, str, cfg->default_int));
c++;
cfg++;
}
return 0;
}
char *
machine_get_config_string(char *s)
machine_get_config_string(char *str)
{
const device_t *d = machine_get_device(machine);
const device_config_t *c;
const device_t *dev = machine_get_device(machine);
const device_config_t *cfg;
if (d == NULL)
if (dev == NULL)
return 0;
c = d->config;
while (c && c->type != -1) {
if (!strcmp(s, c->name))
return (config_get_string((char *) d->name, s, (char *) c->default_string));
cfg = dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_string((char *) dev->name, str, (char *) cfg->default_string));
c++;
cfg++;
}
return NULL;
@@ -881,7 +882,7 @@ const device_t device_none = {
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -895,7 +896,7 @@ const device_t device_internal = {
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -57,7 +57,7 @@ add_library(dev OBJECT
mouse_microtouch_touchscreen.c
)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
target_link_libraries(86Box atomic)
endif()

View File

@@ -2127,6 +2127,13 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
pulse_output(dev, val & 0x0f);
dev->state = STATE_MAIN_IBF;
return;
} else if (val == 0xae) {
/* Fast track it because of the LG MultiNet. */
kbc_at_log("ATkbc: enable keyboard\n");
set_enable_kbd(dev, 1);
dev->state = STATE_MAIN_IBF;
return;
}

View File

@@ -1961,18 +1961,24 @@ keyboard_at_write(void *priv)
}
} else {
if (dev->flags & FLAG_CTRLDAT) {
/* Special case - another command during another command that wants input - proceed
/*
Special case - another command during another command that wants input - proceed
as normal but do not cancel the command (so keep waiting for input), unless the
command in progress is ED (Set/reset LEDs). */
if (val == 0xed) {
keyboard_scan = 1;
command in progress is ED (Set/reset LEDs).
It appears to also apply to command EE (Echo), F4 (Enable), F5 (Diable and Set
Default), and F6 (SetDefault).
*/
if ((val == 0xed) || (val == 0xee) || (val == 0xf4) || (val == 0xf5) || (val == 0xf6))
dev->flags &= ~FLAG_CTRLDAT;
} else
else
dev->state = DEV_STATE_MAIN_WANT_IN;
}
switch (val) {
case 0xed: /* set/reset LEDs */
if ((dev->flags & FLAG_CTRLDAT) && (dev->command == 0xed))
keyboard_scan = 1;
dev->command = val;
keyboard_at_log("%s: set/reset LEDs\n", dev->name);
dev->flags |= FLAG_CTRLDAT;

View File

@@ -282,8 +282,8 @@ static const device_config_t serial_passthrough_config[] = {
.type = CONFIG_SERPORT,
.default_string = "",
.file_filter = NULL,
.spinner = {},
.selection = {}
.spinner = { 0 },
.selection = { { 0 } }
},
#ifdef _WIN32
{
@@ -292,8 +292,8 @@ static const device_config_t serial_passthrough_config[] = {
.type = CONFIG_STRING,
.default_string = "\\\\.\\pipe\\86Box\\test",
.file_filter = NULL,
.spinner = {},
.selection = {}
.spinner = { 0 },
.selection = { { 0 } }
},
#endif
{

View File

@@ -104,8 +104,8 @@ struct unittester_state {
/* 0x04: Exit */
uint8_t exit_code;
};
static struct unittester_state unittester;
static const struct unittester_state unittester_defaults = {
static struct unittester_state unittester;
static struct unittester_state unittester_defaults = {
.trigger_port = 0x0080,
.iobase_port = 0xFFFF,
.fsm1 = UT_FSM1_WAIT_8,
@@ -589,7 +589,7 @@ unittester_trigger_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv))
static void *
unittester_init(UNUSED(const device_t *info))
{
unittester = (struct unittester_state) unittester_defaults;
unittester = unittester_defaults;
unittester_exit_enabled = !!device_get_config_int("exit_enabled");

View File

@@ -1114,7 +1114,7 @@ static const device_config_t wdxt150_config[] = {
.default_string = "",
.default_int = 0x0320,
.file_filter = "",
.spinner = { 0 }, /*W2*/
.spinner = { 0 },
.selection = {
{ .description = "320H", .value = 0x0320 },
{ .description = "324H", .value = 0x0324 },
@@ -1128,7 +1128,7 @@ static const device_config_t wdxt150_config[] = {
.default_string = "",
.default_int = 5,
.file_filter = "",
.spinner = { 0 }, /*W3*/
.spinner = { 0 },
.selection = {
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 4", .value = 4 },
@@ -1142,7 +1142,7 @@ static const device_config_t wdxt150_config[] = {
.default_string = "",
.default_int = 0xc8000,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.selection = {
{ .description = "C800H", .value = 0xc8000 },
{ .description = "CA00H", .value = 0xca000 },
@@ -1156,7 +1156,7 @@ static const device_config_t wdxt150_config[] = {
.default_string = "rev_1",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Revision 1.0", .internal_name = "rev_1", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { WD_REV_1_BIOS_FILE, "" } },

View File

@@ -238,7 +238,7 @@ static const device_config_t xtide_config[] = {
.default_string = "xt",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } },
@@ -260,7 +260,7 @@ static const device_config_t xtide_at_config[] = {
.default_string = "at",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } },

View File

@@ -448,9 +448,13 @@ static hdd_preset_t hdd_speed_presets[] = {
{ .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball TM1080AT", .internal_name = "TM10A462", .model = "QUANTUM FIREBALL TM1.0A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball TM1.2AT", .internal_name = "TM12A012", .model = "QUANTUM FIREBALL TM1.2A", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX5.1AT", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Samsung PLS-31274A", .internal_name = "PLS31274A", .model = "SAMSUNG PLS-31274A", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 45, .track_seek_ms = 4.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 },
{ .name = "[ATA-2] Samsung Winner-1", .internal_name = "WNR31601A", .model = "SAMSUNG WNR-31601A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Seagate Medalist (ST3780A)", .internal_name = "ST3780A", .model = "ST3780A", .zones = 8, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 },

View File

@@ -18,6 +18,7 @@
add_library(fdd OBJECT
fdd.c
fdc.c
fdc_compaticard.c
fdc_magitronic.c
fdc_monster.c
fdc_pii15xb.c

View File

@@ -103,15 +103,18 @@ typedef const struct {
static fdc_cards_t fdc_cards[] = {
// clang-format off
{ &device_none },
{ &device_internal },
{ &fdc_xt_device },
{ &fdc_at_device },
{ &fdc_b215_device },
{ &fdc_pii151b_device },
{ &fdc_pii158b_device },
{ &fdc_monster_device },
{ NULL }
{ &device_none },
{ &device_internal },
{ &fdc_b215_device },
{ &fdc_pii151b_device },
{ &fdc_pii158b_device },
{ &fdc_compaticard_i_device },
{ &fdc_compaticard_ii_device },
#if 0
{ &fdc_compaticard_iv_device },
#endif
{ &fdc_monster_device },
{ NULL }
// clang-format on
};

View File

@@ -0,0 +1,355 @@
/*
* 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 Micro Solutions CompatiCard I/II/IV.
*
* Authors: Jasmine Iwanek, <jasmine@iwanek.co.uk>
*
* Copyright 2022-2025 Jasmine Iwanek.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/timer.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#define DEVICE_COMPATICARD_I 0
#define DEVICE_COMPATICARD_II 1
#define DEVICE_COMPATICARD_IV 2
#define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff)
#define ROM_COMPATICARD_IV "roms/floppy/compaticard/ccivbios1.05.bin"
#define CR_2_MASK 0x2f /* 00101111b */
typedef struct compaticard_s {
rom_t bios_rom;
fdc_t *fdc;
/*
* 7 - Reserved - Set to 0
* 6 - Reserved - Set to 0
* 5 - Programmable Pin 2 Logic I sets Pin 2 low (TODO)
* 4 - Reserved - Set to 0
* 3-0 - Data Transfer Rate Select (TODO)
* 0000---250 Kbps
* 0001-300 Kbps
* 1111-500 Kbps
*/
uint8_t cr_2;
} compaticard_t;
static void
compaticard_out(uint16_t port, uint8_t val, void *priv)
{
compaticard_t *dev = (compaticard_t *) priv;
dev->cr_2 = (val & CR_2_MASK);
}
static uint8_t
compaticard_in(uint16_t port, void *priv)
{
compaticard_t *dev = (compaticard_t *) priv;
uint8_t ret = (dev->cr_2 &CR_2_MASK);
return ret;
}
static void
compaticard_close(void *priv)
{
compaticard_t *dev = (compaticard_t *) priv;
free(dev);
}
static void *
compaticard_init(const device_t *info)
{
compaticard_t *dev = calloc(1, sizeof(compaticard_t));
uint16_t base_addr = device_get_config_hex16("base");
uint8_t irq = 6;
uint8_t dma = 2;
uint16_t cr2_addr = 0x7f2; // Control Register 2
// CompatiCard II & IV have configurable IRQ and DMA
if (info->local >= DEVICE_COMPATICARD_II) {
irq = device_get_config_int("irq");
dma = device_get_config_int("dma");
}
// Only on CompatiCard IV
if ((info->local == DEVICE_COMPATICARD_IV) && (BIOS_ADDR != 0))
rom_init(&dev->bios_rom, ROM_COMPATICARD_IV, BIOS_ADDR, 0x2000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL);
// TODO: Make this neater
switch (base_addr) {
case FDC_SECONDARY_ADDR:
cr2_addr = 0x772;
if (info->local == DEVICE_COMPATICARD_IV)
dev->fdc = device_add(&fdc_at_sec_device);
else
dev->fdc = device_add(&fdc_xt_sec_device);
break;
case FDC_TERTIARY_ADDR:
cr2_addr = 0x762;
if (info->local == DEVICE_COMPATICARD_IV)
dev->fdc = device_add(&fdc_at_ter_device);
else
dev->fdc = device_add(&fdc_xt_ter_device);
break;
case FDC_QUATERNARY_ADDR:
cr2_addr = 0x7e2;
if (info->local == DEVICE_COMPATICARD_IV)
dev->fdc = device_add(&fdc_at_qua_device);
else
dev->fdc = device_add(&fdc_xt_qua_device);
break;
default:
if (info->local == DEVICE_COMPATICARD_IV)
dev->fdc = device_add(&fdc_at_device);
else
dev->fdc = device_add(&fdc_xt_device);
break;
}
fdc_set_irq(dev->fdc, irq);
fdc_set_dma_ch(dev->fdc, dma);
io_sethandler(cr2_addr, 0x0001,
compaticard_in, NULL, NULL,
compaticard_out, NULL, NULL,
dev);
return dev;
}
static int compaticard_iv_available(void)
{
return rom_present(ROM_COMPATICARD_IV);
}
static const device_config_t compaticard_i_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = "",
.default_int = 0x3f0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "0x3f0", .value = 0x3f0 },
{ .description = "0x370", .value = 0x370 },
{ .description = "0x360", .value = 0x360 },
{ .description = "0x3e0", .value = 0x3e0 },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_config_t compaticard_ii_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = "",
.default_int = 0x3f0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "0x3f0", .value = 0x3f0 },
{ .description = "0x370", .value = 0x370 },
{ .description = "0x360", .value = 0x360 },
{ .description = "0x3e0", .value = 0x3e0 },
{ .description = "" }
}
},
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 6,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "IRQ 2", .value = 2 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 4", .value = 4 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 6", .value = 6 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "" }
}
},
{
.name = "dma",
.description = "DMA channel",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 2,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "DMA 1", .value = 1 },
{ .description = "DMA 2", .value = 2 },
{ .description = "DMA 3", .value = 3 },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_config_t compaticard_iv_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = "",
.default_int = 0x3f0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "0x3f0", .value = 0x3f0 },
{ .description = "0x370", .value = 0x370 },
{ .description = "0x360", .value = 0x360 },
{ .description = "0x3e0", .value = 0x3e0 },
{ .description = "" }
}
},
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 6,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "IRQ 2", .value = 2 },
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 4", .value = 4 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 6", .value = 6 },
{ .description = "IRQ 7", .value = 7 },
{ .description = "" }
}
},
{
.name = "dma",
.description = "DMA channel",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 2,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "DMA 1", .value = 1 },
{ .description = "DMA 2", .value = 2 },
{ .description = "DMA 3", .value = 3 },
{ .description = "" }
}
},
{
.name = "bios_addr",
.description = "BIOS Address:",
.type = CONFIG_HEX20,
.default_string = "",
.default_int = 0xce000,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0 },
{ .description = "CC00H", .value = 0xcc000 },
{ .description = "CE00H", .value = 0xce000 },
{ .description = "D000H", .value = 0xd0000 },
{ .description = "D800H", .value = 0xd8000 },
{ .description = "DE00H", .value = 0xde000 },
{ .description = "E000H", .value = 0xe0000 },
{ .description = "E800H", .value = 0xe8000 },
{ .description = "EE00H", .value = 0xee000 },
{ .description = "" }
}
},
#if 0
{
.name = "autoboot_enabled",
.description = "Enable Autoboot",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
#endif
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t fdc_compaticard_i_device = {
.name = "Micro Solutions CompatiCard I",
.internal_name = "compaticard_i",
.flags = DEVICE_ISA,
.local = 0,
.init = compaticard_init,
.close = compaticard_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = compaticard_i_config
};
const device_t fdc_compaticard_ii_device = {
.name = "Micro Solutions CompatiCard II",
.internal_name = "compaticard_ii",
.flags = DEVICE_ISA,
.local = 1,
.init = compaticard_init,
.close = compaticard_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = compaticard_ii_config
};
const device_t fdc_compaticard_iv_device = {
.name = "Micro Solutions CompatiCard IV",
.internal_name = "compaticard_iv",
.flags = DEVICE_ISA,
.local = 2,
.init = compaticard_init,
.close = compaticard_close,
.reset = NULL,
.available = compaticard_iv_available,
.speed_changed = NULL,
.force_redraw = NULL,
.config = compaticard_iv_config
};

View File

@@ -20,7 +20,11 @@
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>

View File

@@ -62,17 +62,13 @@ joystick_standard_read(UNUSED(void *priv))
{
uint8_t ret = 0xf0;
if (JOYSTICK_PRESENT(0)) {
if (joystick_state[0].button[0])
ret &= ~0x10;
if (joystick_state[0].button[1])
ret &= ~0x20;
}
if (JOYSTICK_PRESENT(1)) {
if (joystick_state[1].button[0])
ret &= ~0x40;
if (joystick_state[1].button[1])
ret &= ~0x80;
for (int js = 0; js < 2; js++) {
if (JOYSTICK_PRESENT(js)) {
if (joystick_state[js].button[0])
ret &= ~0x10;
if (joystick_state[js].button[1])
ret &= ~0x20;
}
}
return ret;
@@ -140,9 +136,7 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis)
case 1:
return joystick_state[0].axis[1];
case 2:
return 0;
case 3:
return 0;
default:
return 0;
}
@@ -162,7 +156,6 @@ joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis)
case 2:
return joystick_state[0].axis[2];
case 3:
return 0;
default:
return 0;
}

View File

@@ -119,8 +119,7 @@ sw_parity(uint16_t data)
static void *
sw_init(void)
{
sw_data *sw = (sw_data *) malloc(sizeof(sw_data));
memset(sw, 0, sizeof(sw_data));
sw_data *sw = (sw_data *) calloc(1, sizeof(sw_data));
timer_add(&sw->poll_timer, sw_timer_over, sw, 0);
timer_add(&sw->trigger_timer, sw_trigger_timer_over, sw, 0);
@@ -191,24 +190,24 @@ sw_write(void *priv)
sw->poll_data = 1;
}
for (uint8_t c = 0; c < 4; c++) {
for (uint8_t js = 0; js < 4; js++) {
uint16_t data = 0x3fff;
if (!JOYSTICK_PRESENT(c))
if (!JOYSTICK_PRESENT(js))
break;
if (joystick_state[c].axis[1] < -16383)
if (joystick_state[js].axis[1] < -16383)
data &= ~1;
if (joystick_state[c].axis[1] > 16383)
if (joystick_state[js].axis[1] > 16383)
data &= ~2;
if (joystick_state[c].axis[0] > 16383)
if (joystick_state[js].axis[0] > 16383)
data &= ~4;
if (joystick_state[c].axis[0] < -16383)
if (joystick_state[js].axis[0] < -16383)
data &= ~8;
for (uint8_t b = 0; b < 10; b++) {
if (joystick_state[c].button[b])
data &= ~(1 << (b + 4));
for (uint8_t button_nr = 0; button_nr < 10; button_nr++) {
if (joystick_state[js].button[button_nr])
data &= ~(1 << (button_nr + 4));
}
if (sw_parity(data))
@@ -216,10 +215,10 @@ sw_write(void *priv)
if (sw->poll_mode) {
sw->poll_left += 5;
sw->poll_data |= (data << (c * 15 + 3));
sw->poll_data |= (data << (js * 15 + 3));
} else {
sw->poll_left += 15;
sw->poll_data |= (data << (c * 15 + 1));
sw->poll_data |= (data << (js * 15 + 1));
}
}
}

View File

@@ -187,12 +187,17 @@ extern int config_changed; /* config has changed */
/* Function prototypes. */
#ifdef HAVE_STDARG_H
extern void pclog_ex(const char *fmt, va_list);
extern void fatal_ex(const char *fmt, va_list);
extern void pclog_ex(const char *fmt, va_list ap);
extern void fatal_ex(const char *fmt, va_list ap);
#endif
extern void pclog_toggle_suppr(void);
#ifdef _MSC_VER
extern void pclog(const char *fmt, ...);
extern void fatal(const char *fmt, ...);
#else
extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
#endif
extern void set_screen_size(int x, int y);
extern void set_screen_size_monitor(int x, int y, int monitor_index);
extern void reset_screen_size(void);

View File

@@ -18,7 +18,7 @@
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -197,12 +197,12 @@ extern "C" {
#endif
extern void device_init(void);
extern void device_set_context(device_context_t *c, const device_t *dev, int inst);
extern void device_set_context(device_context_t *ctx, const device_t *dev, int inst);
extern void device_context(const device_t *dev);
extern void device_context_inst(const device_t *dev, int inst);
extern void device_context_restore(void);
extern void *device_add(const device_t *d);
extern void *device_add_linked(const device_t *d, void *priv);
extern void *device_add(const device_t *dev);
extern void *device_add_linked(const device_t *dev, void *priv);
extern void *device_add_params(const device_t *dev, void *params);
extern void device_add_ex(const device_t *dev, void *priv);
extern void device_add_ex_params(const device_t *dev, void *priv, void *params);
@@ -223,27 +223,27 @@ extern void device_get_name(const device_t *dev, int bus, char *name);
extern int device_has_config(const device_t *dev);
extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no);
extern int device_is_valid(const device_t *, int m);
extern int device_is_valid(const device_t *, int mch);
extern const device_t* device_context_get_device(void);
extern int device_get_config_int(const char *name);
extern int device_get_config_int_ex(const char *s, int dflt_int);
extern int device_get_config_int_ex(const char *str, int def);
extern int device_get_config_hex16(const char *name);
extern int device_get_config_hex20(const char *name);
extern int device_get_config_mac(const char *name, int dflt_int);
extern void device_set_config_int(const char *s, int val);
extern void device_set_config_hex16(const char *s, int val);
extern void device_set_config_hex20(const char *s, int val);
extern void device_set_config_mac(const char *s, int val);
extern int device_get_config_mac(const char *name, int def);
extern void device_set_config_int(const char *str, int val);
extern void device_set_config_hex16(const char *str, int val);
extern void device_set_config_hex20(const char *str, int val);
extern void device_set_config_mac(const char *str, int val);
extern const char *device_get_config_string(const char *name);
extern int device_get_instance(void);
#define device_get_config_bios device_get_config_string
extern const char *device_get_internal_name(const device_t *dev);
extern int machine_get_config_int(char *s);
extern char *machine_get_config_string(char *s);
extern int machine_get_config_int(char *str);
extern char *machine_get_config_string(char *str);
extern const device_t device_none;
extern const device_t device_internal;

View File

@@ -34,6 +34,10 @@ extern const device_t fdc_b215_device;
extern const device_t fdc_pii151b_device;
extern const device_t fdc_pii158b_device;
extern const device_t fdc_compaticard_i_device;
extern const device_t fdc_compaticard_ii_device;
extern const device_t fdc_compaticard_iv_device;
extern const device_t fdc_monster_device;
extern void fdc_card_init(void);

View File

@@ -12,9 +12,11 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Connor Hyde <mario64crashed@gmail.com, nomorestarfrost@gmail.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
* Copyright 2025 Connor Hyde.
*/
#ifndef EMU_LOG_H
@@ -26,11 +28,16 @@
extern "C" {
# endif
#define LOG_SIZE_BUFFER 1024 /* Log size buffer */
#define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */
#define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */
/* Function prototypes. */
extern void log_set_suppr_seen(void *priv, int suppr_seen);
extern void log_set_dev_name(void *priv, char *dev_name);
# ifdef HAVE_STDARG_H
extern void log_out(void *priv, const char *fmt, va_list);
extern void log_out_cyclic(void* priv, const char *fmt, va_list);
extern void log_fatal(void *priv, const char *fmt, ...);
# endif
extern void *log_open(char *dev_name);

View File

@@ -817,6 +817,7 @@ extern int machine_at_p2bls_init(const machine_t *);
extern int machine_at_lgibmx7g_init(const machine_t *);
extern int machine_at_p3bf_init(const machine_t *);
extern int machine_at_bf6_init(const machine_t *);
extern int machine_at_bx6_init(const machine_t *);
extern int machine_at_ax6bc_init(const machine_t *);
extern int machine_at_atc6310bxii_init(const machine_t *);
extern int machine_at_686bx_init(const machine_t *);

View File

@@ -0,0 +1,84 @@
/*
* 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.
*
* Fast, high-frequency, guest CPU-independent timer for Riva emulation.
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
*
* Copyright 2024-2025 starfrost
*/
/*
RivaTimer
This is a fast, high-frequency, guest CPU-independent timer.
The main 86box timer is dependent on the TSC (time-stamp counter) register of the emulated CPU core.
This is fine for most purposes and has advantages in the fields of synchronisation and integrates neatly with
the clock dividers of the PC architecture, but in the case of the RIVA 128 it does not particularly suffice
(although it can be made to work with various techniques) since the clock source on the RIVA 128 is on the board itself
and the GPU has several different clocks that control different parts of the GPU (e.g., PTIMER runs on the memory clock but the core gpu is using the pixel clock).
As faster graphics cards that offload more and more of the 3D graphics pipeline are emulated in the future, more and more work needs to be done by the emulator and
issues of synchronisation with a host CPU will simply make that work harder. Some features that are required for
Architecture Brand Name 3D Features
NV1 (1995) NV1 Some weird URBS rectangle crap but feature set generally similar to nv3 but a bit worse
NV3 (1997) RIVA 128 (ZX) Triangle setup, edge-slope calculations, edge interpolation, span-slope calculations, span interpolation (Color-buffer, z-buffer, texture mapping, filtering)
NV4 (1998) RIVA TNT NV3 + 2x1 pixel pipelines + 32-bit colour + larger textures + trilinear + more ram (16mb)
NV5 (1999) RIVA TNT2 NV4 + higher clock speed
NV10 (1999) GeForce 256 NV5 + initial geometry transformation + lighting (8x lights) + MPEG-2 motion compensation + 4x1 pixel pipelines
NV15 (2000) GeForce 2 NV10 + First attempt at programmability + 4x2 pixel pipelines
NV20 (2001) GeForce 3 Programmable shaders!
As you can see, the performance basically exponentially increases over a period of only 4 years.
So I decided to create this timer that is completely separate from the CPU Core.
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <86box/86box.h>
#ifdef _WIN32
#include <Windows.h>
// Linux & MacOS should have the same API since OSX 10.12
#else
#include <time.h>
#endif
typedef struct rivatimer_s
{
struct rivatimer_s* prev; // Previous Rivatimer
double period; // Period in uS before firing
double value; // The current value of the rivatimer
bool running; // Is this RivaTimer running?
struct rivatimer_s* next; // Next RivaTimer
void (*callback)(double real_time); // Callback to call on fire
#ifdef _WIN32
LARGE_INTEGER starting_time; // Starting time.
#else
struct timespec starting_time; // Starting time.
#endif
double time; // Accumulated time in uS.
} rivatimer_t;
void rivatimer_init(void); // Initialise the Rivatimer.
rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time));
void rivatimer_destroy(rivatimer_t* rivatimer_ptr);
void rivatimer_update_all(void);
void rivatimer_start(rivatimer_t* rivatimer_ptr);
void rivatimer_stop(rivatimer_t* rivatimer_ptr);
double rivatimer_get_time(rivatimer_t* rivatimer_ptr);
void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time));
void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period);

View File

@@ -104,6 +104,7 @@ typedef struct ncr_t {
int state;
int clear_req;
int wait_data;
int wait_data_back;
int wait_complete;
int command_pos;
int data_pos;

View File

@@ -29,15 +29,19 @@
enum {
SADLIB = 1, /* No DSP */
SB1, /* DSP v1.05 */
SB15, /* DSP v2.00 */
SB2, /* DSP v2.01 - needed for high-speed DMA */
SBPRO, /* DSP v3.00 */
SBPRO2, /* DSP v3.02 + OPL3 */
SB16, /* DSP v4.05 + OPL3 */
SBAWE32, /* DSP v4.12 + OPL3 */
SBAWE32PNP, /* DSP v4.13 + OPL3 */
SBAWE64 /* DSP v4.16 + OPL3 */
SB_DSP_105, /* DSP v1.05, Original CT1320 (Also known as CT1310) */
SB_DSP_200, /* DSP v2.00 */
SB_DSP_201, /* DSP v2.01 - needed for high-speed DMA, Seen on CT1350B with CT1336 */
SB_DSP_202, /* DSP v2.02 - Seen on CT1350B with CT1336A */
SBPRO_DSP_300, /* DSP v3.00 */
SBPRO2_DSP_302, /* DSP v3.02 + OPL3 */
SB16_DSP_404, /* DSP v4.05 + OPL3 */
SB16_DSP_405, /* DSP v4.05 + OPL3 */
SB16_DSP_406, /* DSP v4.06 + OPL3 */
SB16_DSP_411, /* DSP v4.11 + OPL3 */
SBAWE32_DSP_412, /* DSP v4.12 + OPL3 */
SBAWE32_DSP_413, /* DSP v4.13 + OPL3 */
SBAWE64_DSP_416 /* DSP v4.16 + OPL3 */
};
/* SB 2.0 CD version */

View File

@@ -138,6 +138,7 @@ typedef struct ibm8514_t {
int output2;
int ssv_len;
int ssv_len_back;
uint8_t ssv_dir;
uint8_t ssv_draw;
int odd_in;

167
src/log.c
View File

@@ -12,12 +12,15 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Connor Hyde <mario64crashed@gmail.com, nomorestarfrost@gmail.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
* Copyright 2025 Connor Hyde.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -36,13 +39,31 @@
#ifndef RELEASE_BUILD
typedef struct log_t {
char buff[1024];
char *dev_name;
int seen;
int suppr_seen;
char buff[1024];
char *dev_name;
int seen;
int suppr_seen;
char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; // Cyclical log buffer. This is 32kb, might calloc?
int32_t cyclic_last_line;
int32_t log_cycles;
} log_t;
extern FILE *stdlog; /* file to log output to */
// Functions only used in this translation unit
void log_ensure_stdlog_open(void);
void
log_ensure_stdlog_open(void)
{
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
}
void
log_set_suppr_seen(void *priv, int suppr_seen)
@@ -91,14 +112,7 @@ log_out(void *priv, const char *fmt, va_list ap)
if (strcmp(fmt, "") == 0)
return;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
log_ensure_stdlog_open();
vsprintf(temp, fmt, ap);
if (log->suppr_seen && !strcmp(log->buff, temp))
@@ -117,6 +131,131 @@ log_out(void *priv, const char *fmt, va_list ap)
fflush(stdlog);
}
/*
Starfrost, 7-8 January 2025:
For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found.
Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
*/
void
log_out_cyclic(void* priv, const char* fmt, va_list ap)
{
#ifndef RELEASE_BUILD
// get our new logging system instance.
log_t* log = (log_t*)priv;
// does the log actually exist?
if (!log)
return;
// is the string empty?
if (fmt[0] == '\0')
return;
// ensure stdlog is open
log_ensure_stdlog_open();
char temp[LOG_SIZE_BUFFER] = {0};
log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES;
vsprintf(temp, fmt, ap);
log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, LOG_SIZE_BUFFER);
uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0};
// Random numbers
uint32_t base = 257;
uint32_t mod = 1000000007;
uint32_t repeat_order = 0;
bool is_cycle = false;
// compute the set of hashes for the current log buffer
for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++)
{
if (log->cyclic_buff[log_line][0] == '\0')
continue; // skip
for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++)
{
hashes[log_line] = hashes[log_line] * base + log->cyclic_buff[log_line][log_line_char] % mod;
}
}
// Now see if there are real cycles...
// We implement a minimum repeat size.
for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++)
{
//TODO: Log what we need for cycle 1.
//TODO: Command line option that lets us turn off this behaviour.
for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++)
{
if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES])
{
repeat_order = check_size;
break;
}
}
is_cycle = (repeat_order != 0);
// if there still is a cycle..
if (is_cycle)
break;
}
if (is_cycle)
{
if (log->cyclic_last_line % repeat_order == 0)
{
log->log_cycles++;
if (log->log_cycles == 1)
{
// 'Replay' the last few log entries so they actually show up
// Todo: is this right?
for (uint32_t index = log->cyclic_last_line - 1; index > (log->cyclic_last_line - repeat_order); index--)
{
// *very important* to prevent out of bounds index
uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES;
log_copy(log, temp, log->cyclic_buff[real_index], LOG_SIZE_BUFFER);
fprintf(stdlog, "%s", log->cyclic_buff[real_index]);
}
// restore the original line
log_copy(log, temp, log->cyclic_buff[log->cyclic_last_line], LOG_SIZE_BUFFER);
fprintf(stdlog, "%s", temp); // allow normal logging
}
if (log->log_cycles > 1 && log->log_cycles < 100)
fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log->log_cycles);
else if (log->log_cycles == 100)
fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n");
}
}
else
{
log->log_cycles = 0;
fprintf(stdlog, "%s", temp);
}
log->cyclic_last_line++;
#endif
}
void
log_fatal(void *priv, const char *fmt, ...)
{
@@ -145,6 +284,8 @@ log_open(char *dev_name)
log->dev_name = dev_name;
log->suppr_seen = 1;
log->cyclic_last_line = 0;
log->log_cycles = 0;
return (void *) log;
}

View File

@@ -13,10 +13,12 @@
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2025 Jasmine Iwanek.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,7 +38,6 @@
* Boston, MA 02111-1307
* USA.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -53,6 +54,7 @@
#include <86box/fdc_ext.h>
#include <86box/nvr.h>
#include <86box/gameport.h>
#include <86box/ibm_5161.h>
#include <86box/keyboard.h>
#include <86box/lpt.h>
#include <86box/rom.h>
@@ -149,10 +151,41 @@ machine_at_ps2_ide_init(const machine_t *model)
device_add(&ide_isa_device);
}
static const device_config_t ibmat_config[] = {
// clang-format off
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 0
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmat_device = {
.name = " IBM AT Devices",
.internal_name = "ibmat_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmat_config
};
int
machine_at_ibm_init(const machine_t *model)
{
int ret;
int ret;
uint8_t enable_5161;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
device_context_restore();
ret = bios_load_interleaved("roms/machines/ibmat/62x0820.u27",
"roms/machines/ibmat/62x0821.u47",
@@ -163,6 +196,9 @@ machine_at_ibm_init(const machine_t *model)
machine_at_ibm_common_init(model);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}
@@ -218,10 +254,41 @@ machine_at_ibmatpx_init(const machine_t *model)
return ret;
}
static const device_config_t ibmxt286_config[] = {
// clang-format off
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 0
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmxt286_device = {
.name = "IBM XT Model 286 Devices",
.internal_name = "ibmxt286_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmxt286_config
};
int
machine_at_ibmxt286_init(const machine_t *model)
{
int ret;
int ret;
uint8_t enable_5161;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
device_context_restore();
ret = bios_load_interleaved("roms/machines/ibmxt286/bios_5162_21apr86_u34_78x7460_27256.bin",
"roms/machines/ibmxt286/bios_5162_21apr86_u35_78x7461_27256.bin",
@@ -232,6 +299,9 @@ machine_at_ibmxt286_init(const machine_t *model)
machine_at_ibm_common_init(model);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}

View File

@@ -214,7 +214,7 @@ machine_at_neat_ami_init(const machine_t *model)
// TODO
// Onboard Paradise PVGA1A-JK VGA Graphics
// Data Technology Corporation DTC7187 RLL Controller
// Data Technology Corporation DTC7187 RLL Controller (Optional)
int
machine_at_ataripc4_init(const machine_t *model)
{
@@ -222,10 +222,6 @@ machine_at_ataripc4_init(const machine_t *model)
ret = bios_load_interleaved("roms/machines/ataripc4/AMI_PC4X_1.7_EVEN.BIN",
"roms/machines/ataripc4/AMI_PC4X_1.7_ODD.BIN",
#if 0
ret = bios_load_interleaved("roms/machines/ataripc4/ami_pc4x_1.7_even.bin",
"roms/machines/ataripc4/ami_pc4x_1.7_odd.bin",
#endif
0x000f0000, 65536, 0);
if (bios_only || !ret)

View File

@@ -684,14 +684,57 @@ machine_at_403tg_d_mr_init(const machine_t *model)
return ret;
}
static const device_config_t pb450_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "pci10a",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "PCI 1.0A", .internal_name = "pci10a", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/OPTI802.bin", "" } },
{ .name = "PNP 1.1A", .internal_name = "pnp11a", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/PNP11A.bin", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t pb450_device = {
.name = "Packard Bell PB450 Devices",
.internal_name = "pb450_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = pb450_config
};
int
machine_at_pb450_init(const machine_t *model)
{
int ret;
int ret = 0;
const char* fn;
ret = bios_load_linear("roms/machines/pb450/OPTI802.bin",
0x000e0000, 131072, 0);
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
if (bios_only || !ret)
return ret;

View File

@@ -359,6 +359,37 @@ machine_at_bf6_init(const machine_t *model)
return ret;
}
int
machine_at_bx6_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/bx6/BX6_EG.BIN",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
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);
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&i440bx_device);
device_add(&piix4e_device);
device_add(&keyboard_ps2_pci_device);
device_add(&w83977f_device);
device_add(&sst_flash_29ee010_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 256);
return ret;
}
int
machine_at_ax6bc_init(const machine_t *model)
{

View File

@@ -58,10 +58,6 @@ machine_at_acerv35n_init(const machine_t *model)
return ret;
machine_at_common_init_ex(model, 2);
/* Yes, it's called amstrad_mega_pc_nvr_device, but it's basically the
standard AT NVR, just initialized to 0x00's (perhaps that should be the
default behavior?). */
device_add(&amstrad_megapc_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);

View File

@@ -252,7 +252,7 @@ static const device_config_t ps1_2011_config[] = {
.default_string = "english_us",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } },

View File

@@ -1,3 +1,25 @@
/*
* 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.
*
* Standard PC/AT implementation.
*
*
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2025 Jasmine Iwanek.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -37,22 +59,94 @@ machine_xt_common_init(const machine_t *model, int fixed_floppy)
standalone_gameport_type = &gameport_device;
}
static const device_config_t ibmpc_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5150_5700671",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "5700671 (10/19/81)", .internal_name = "ibm5150_5700671", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_19OCT81_5700671_U33.BIN", "" } },
{ .name = "5700051 (04/24/81)", .internal_name = "ibm5150_5700051", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_24APR81_5700051_U33.BIN", "" } },
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "enable_basic",
.description = "IBM Cassette Basic",
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmpc_device = {
.name = "IBM PC (1981) Device",
.internal_name = "ibmpc_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmpc_config
};
int
machine_pc_init(const machine_t *model)
{
int ret;
int ret = 0;
int ret2;
uint8_t enable_5161;
uint8_t enable_basic;
const char *fn;
ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN",
0x000fe000, 40960, 0);
if (ret) {
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin",
0x000f6000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin",
0x000f8000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin",
0x000fa000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin",
0x000fc000, 8192, 0);
/* No ROMs available. */
if (!device_available(model->device))
return ret;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
enable_basic = machine_get_config_int("enable_basic");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 40960, 0);
device_context_restore();
if (enable_basic && ret) {
ret2 = bios_load_aux_linear("roms/machines/ibmpc/ibm-basic-1.00.rom",
0x000f6000, 32768, 0);
if (!ret2) {
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin",
0x000f6000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin",
0x000f8000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin",
0x000fa000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin",
0x000fc000, 8192, 0);
}
}
if (bios_only || !ret)
@@ -62,28 +156,98 @@ machine_pc_init(const machine_t *model)
machine_xt_common_init(model, 0);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}
static const device_config_t ibmpc82_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5150_1501476",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1501476 (10/27/82)", .internal_name = "ibm5150_1501476", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_27OCT82_1501476_U33.BIN", "" } },
{ .name = "5000024 (08/16/82)", .internal_name = "ibm5150_5000024", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_16AUG82_5000024_U33.BIN", "" } },
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "enable_basic",
.description = "IBM Cassette Basic",
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmpc82_device = {
.name = "IBM PC (1982) Devices",
.internal_name = "ibmpc82_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmpc82_config
};
int
machine_pc82_init(const machine_t *model)
{
int ret;
int ret2;
int ret = 0;
int ret2;
uint8_t enable_5161;
uint8_t enable_basic;
const char *fn;
ret = bios_load_linear("roms/machines/ibmpc82/pc102782.bin",
0x000fe000, 40960, 0);
if (ret) {
/* No ROMs available. */
if (!device_available(model->device))
return ret;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
enable_basic = machine_get_config_int("enable_basic");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 40960, 0);
device_context_restore();
if (enable_basic && ret) {
ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom",
0x000f6000, 32768, 0);
if (!ret2) {
bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6",
bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U29 - 5000019.bin",
0x000f6000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8",
bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U30 - 5000021.bin",
0x000f8000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa",
bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U31 - 5000022.bin",
0x000fa000, 8192, 0);
bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc",
bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U32 - 5000023.bin",
0x000fc000, 8192, 0);
}
}
@@ -92,40 +256,110 @@ machine_pc82_init(const machine_t *model)
return ret;
device_add(&keyboard_pc82_device);
device_add(&ibm_5161_device);
machine_xt_common_init(model, 0);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}
static const device_config_t ibmxt_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5160_1501512_5000027",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } },
{ .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } },
{ .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } },
#if 0
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
#endif
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "enable_basic",
.description = "IBM Cassette Basic",
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmxt_device = {
.name = "IBM XT (1982) Device",
.internal_name = "ibmxt_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmxt_config
};
int
machine_xt_init(const machine_t *model)
{
int ret;
int ret = 0;
uint8_t enable_5161;
uint8_t enable_basic;
const char *fn;
ret = bios_load_linear("roms/machines/ibmxt/xt.rom",
0x000f0000, 65536, 0);
if (!ret) {
ret = bios_load_linear("roms/machines/ibmxt/1501512.u18",
0x000fe000, 65536, 0x6000);
if (ret) {
bios_load_aux_linear("roms/machines/ibmxt/1501512.u18",
0x000f8000, 24576, 0);
bios_load_aux_linear("roms/machines/ibmxt/5000027.u19",
0x000f0000, 32768, 0);
}
/* No ROMs available. */
if (!device_available(model->device))
return ret;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
enable_basic = machine_get_config_int("enable_basic");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000);
if (enable_basic && ret) {
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1);
(void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0);
}
device_context_restore();
if (bios_only || !ret)
return ret;
device_add(&keyboard_xt_device);
device_add(&ibm_5161_device);
machine_xt_common_init(model, 0);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}
@@ -147,28 +381,93 @@ machine_genxt_init(const machine_t *model)
return ret;
}
static const device_config_t ibmxt86_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5160_050986",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } },
{ .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } },
{ .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } },
#if 0
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
#endif
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ibmxt86_device = {
.name = "IBM XT (1986) Device",
.internal_name = "ibmxt86_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ibmxt86_config
};
int
machine_xt86_init(const machine_t *model)
{
int ret;
int ret = 0;
uint8_t enable_5161;
const char *fn;
/* No ROMs available. */
if (!device_available(model->device))
return ret;
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000);
ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN",
0x000fe000, 65536, 0x6000);
if (ret) {
(void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN",
0x000f8000, 24576, 0);
(void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN",
0x000f0000, 32768, 0);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1);
(void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0);
}
device_context_restore();
if (bios_only || !ret)
return ret;
device_add(&keyboard_xt86_device);
device_add(&ibm_5161_device);
machine_xt_common_init(model, 0);
if (enable_5161)
device_add(&ibm_5161_device);
return ret;
}
@@ -214,6 +513,7 @@ machine_xt_amixt_init(const machine_t *model)
// TODO
// Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions)
// RTC
// Adaptec ACB-2072 RLL Controller Card (Optional)
// Atari PCM1 Mouse Support
int

View File

@@ -15,9 +15,11 @@
*
* 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 2025 Jasmine Iwanek.
*/
#include <stdio.h>
#include <stdint.h>
@@ -55,6 +57,13 @@ extern const device_t vid_device_sl;
extern const device_t t1200_video_device;
extern const device_t compaq_plasma_device;
extern const device_t ps1_2011_device;
extern const device_t ibmpc_device;
extern const device_t ibmpc82_device;
extern const device_t ibmxt_device;
extern const device_t ibmxt86_device;
extern const device_t ibmat_device;
extern const device_t ibmxt286_device;
extern const device_t pb450_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -243,7 +252,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmpc_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -282,7 +291,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmpc82_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -360,7 +369,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmxt_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -399,7 +408,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmxt86_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -2673,7 +2682,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmat_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -2793,7 +2802,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ibmxt286_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
@@ -6880,7 +6889,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &pb450_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5428_vlb_onboard_device,
@@ -14623,6 +14632,47 @@ const machine_t machines[] = {
},
/* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC
firmware. */
{
.name = "[i440BX] ABIT BX6",
.internal_name = "bx6",
.type = MACHINE_TYPE_SLOT1,
.chipset = MACHINE_CHIPSET_INTEL_440BX,
.init = machine_at_bx6_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SLOT1,
.block = CPU_BLOCK_NONE,
.min_bus = 66666667,
.max_bus = 133333333,
.min_voltage = 1500,
.max_voltage = 3500,
.min_multi = 2.0,
.max_multi = 5.5
},
.bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB,
.ram = {
.min = 8192,
.max = 524288,
.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
},
{
.name = "[i440BX] ABIT BF6",
.internal_name = "bf6",

View File

@@ -41,7 +41,10 @@ pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp)
target_link_libraries(86Box PkgConfig::SLIRP)
if(WIN32)
target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi iconv)
target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi)
if (NOT MSVC)
target_link_libraries(PkgConfig::SLIRP INTERFACE iconv)
endif()
if(STATIC_BUILD)
add_compile_definitions(LIBSLIRP_STATIC)
endif()

View File

@@ -28,6 +28,9 @@
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#ifdef _MVC_VER
#include <stddef.h>
#endif
#include <time.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
@@ -531,14 +534,14 @@ rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
if (size > wrapped) {
dma_bm_write(s->RxBuf + s->RxBufAddr,
buf, size - wrapped, 1);
(uint8_t *) buf, size - wrapped, 1);
}
/* reset buffer pointer */
s->RxBufAddr = 0;
dma_bm_write(s->RxBuf + s->RxBufAddr,
buf + (size - wrapped), wrapped, 1);
(uint8_t *) buf + (size - wrapped), wrapped, 1);
s->RxBufAddr = wrapped;

View File

@@ -54,7 +54,9 @@
#include <stdlib.h>
#include <wchar.h>
#include <time.h>
#ifndef _MSC_VER
#include <sys/time.h>
#endif
#include <stdbool.h>
#define HAVE_STDARG_H
#include <86box/86box.h>

View File

@@ -17,6 +17,7 @@
* Copyright 2015-2020 Andrew Jenner.
* Copyright 2016-2020 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -522,7 +523,7 @@ pic_read(uint16_t addr, void *priv)
simply read whatever is currently on the data bus. */
}
pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus);
pic_log("pic_read(%04X) = %02X\n", addr, dev->data_bus);
return dev->data_bus;
}

View File

@@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local)
}
int
plat_cdrom_ext_medium_changed(void *local)
plat_cdrom_ext_medium_changed(UNUSED(void *local))
{
#if 0
dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local;
plat_cdrom_read_toc(ioctl);
#endif
int ret = 0;
dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret);

View File

@@ -230,7 +230,11 @@ static HarddiskDialog *callbackPtr = nullptr;
static MVHDGeom
create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl, uint8_t heads, uint8_t spt)
{
MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt };
MVHDGeom _86box_geometry = {
.cyl = cyl,
.heads = heads,
.spt = spt
};
MVHDGeom vhd_geometry;
adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry);
@@ -256,7 +260,11 @@ create_drive_vhd_fixed(const QString &fileName, HarddiskDialog *p, uint16_t cyl,
static MVHDGeom
create_drive_vhd_dynamic(const QString &fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize)
{
MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt };
MVHDGeom _86box_geometry = {
.cyl = cyl,
.heads = heads,
.spt = spt
};
MVHDGeom vhd_geometry;
adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry);
int vhd_error = 0;

View File

@@ -178,15 +178,17 @@ updateJoystickConfig(int type, int joystick_nr, QWidget *parent)
joystick_state[joystick_nr].plat_joystick_nr = jc.selectedDevice();
if (joystick_state[joystick_nr].plat_joystick_nr) {
for (int c = 0; c < joystick_get_axis_count(type); c++) {
joystick_state[joystick_nr].axis_mapping[c] = get_axis(jc, c, joystick_nr);
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(type); axis_nr++) {
joystick_state[joystick_nr].axis_mapping[axis_nr] = get_axis(jc, axis_nr, joystick_nr);
}
for (int c = 0; c < joystick_get_button_count(type); c++) {
joystick_state[joystick_nr].button_mapping[c] = jc.selectedButton(c);
for (int button_nr = 0; button_nr < joystick_get_button_count(type); button_nr++) {
joystick_state[joystick_nr].button_mapping[button_nr] = jc.selectedButton(button_nr);
}
for (int c = 0; c < joystick_get_pov_count(type) * 2; c += 2) {
joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(jc, c, joystick_nr);
joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(jc, c + 1, joystick_nr);
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(type) * 2; pov_nr += 2) {
joystick_state[joystick_nr].pov_mapping[pov_nr][0] = get_pov(jc, pov_nr, joystick_nr);
joystick_state[joystick_nr].pov_mapping[pov_nr][1] = get_pov(jc, pov_nr + 1, joystick_nr);
}
}
}

View File

@@ -160,6 +160,7 @@ SettingsPorts::on_pushButtonSerialPassThru4_clicked()
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast<Settings *>(Settings::settings));
}
#if 0
void
SettingsPorts::on_pushButtonSerialPassThru5_clicked()
{
@@ -177,6 +178,7 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked()
{
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast<Settings *>(Settings::settings));
}
#endif
void
SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked)
@@ -220,4 +222,4 @@ SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked)
{
ui->pushButtonSerialPassThru7->setEnabled(checked);
}
#endif
#endif

View File

@@ -19,45 +19,23 @@ public:
#if 0
private slots:
void on_checkBoxSerialPassThru7_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru6_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru5_clicked(bool checked);
#endif
private slots:
void on_checkBoxSerialPassThru4_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru3_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru2_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru1_clicked(bool checked);
private slots:
#if 0
void on_pushButtonSerialPassThru7_clicked();
private slots:
void on_pushButtonSerialPassThru6_clicked();
private slots:
void on_pushButtonSerialPassThru5_clicked();
private slots:
#endif
void on_pushButtonSerialPassThru4_clicked();
private slots:
void on_pushButtonSerialPassThru3_clicked();
private slots:
void on_pushButtonSerialPassThru2_clicked();
private slots:
void on_pushButtonSerialPassThru1_clicked();
private slots:

View File

@@ -30,10 +30,11 @@
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
****************************************************************************/
#include "qt_vulkanrenderer.hpp"
#include <QCoreApplication>
#include <QFile>
#include "qt_vulkanrenderer.hpp"
#if QT_CONFIG(vulkan)
# include <QVulkanFunctions>
@@ -676,7 +677,7 @@ VulkanRenderer2::initResources()
v_texcoord = texcoord;
gl_Position = ubuf.mvp * position;
}
#endif
#endif /* 0 */
VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv"));
#if 0
#version 440
@@ -691,7 +692,7 @@ VulkanRenderer2::initResources()
{
fragColor = texture(tex, v_texcoord);
}
#endif
#endif /* 0 */
VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv"));
// Graphics pipeline
@@ -1009,4 +1010,4 @@ VulkanRenderer2::startNextFrame()
m_window->frameReady();
m_window->requestUpdate(); // render continuously, throttled by the presentation rate
}
#endif
#endif /* QT_CONFIG(vulkan) */

View File

@@ -31,6 +31,8 @@
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
****************************************************************************/
#ifndef VULKANRENDERER_HPP
#define VULKANRENDERER_HPP
#include <QVulkanWindow>
#include <QImage>
@@ -90,4 +92,6 @@ private:
QMatrix4x4 m_proj;
};
#endif
#endif // QT_CONFIG(vulkan)
#endif // VULKANRENDERER_HPP

View File

@@ -1,3 +1,35 @@
/****************************************************************************
**
** Copyright (C) 2022 Cacodemon345
** Copyright (C) 2017 The Qt Company Ltd.
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
****************************************************************************/
#include "qt_vulkanwindowrenderer.hpp"
#include <QMessageBox>
@@ -697,7 +729,7 @@ public:
# if VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162
case VK_ERROR_INCOMPATIBLE_VERSION_KHR:
return "VK_ERROR_INCOMPATIBLE_VERSION_KHR";
# endif
# endif /* VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162 */
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
case VK_ERROR_NOT_PERMITTED_EXT:
@@ -788,7 +820,7 @@ public:
m_devFuncs->vkDeviceWaitIdle(m_window->device());
}
};
# endif
# endif /* 0*/
VulkanWindowRenderer::VulkanWindowRenderer(QWidget *parent)
: QVulkanWindow(parent->windowHandle())
@@ -851,4 +883,4 @@ VulkanWindowRenderer::getBuffers()
{
return std::vector { std::make_tuple((uint8_t *) renderer->mappedPtr, &this->buf_usage[0]) };
}
#endif
#endif /* QT_CONFIG(vulkan) */

View File

@@ -35,6 +35,6 @@ private:
VulkanRenderer2 *renderer;
};
#endif
#endif // QT_CONFIG(vulkan)
#endif // VULKANWINDOWRENDERER_HPP

View File

@@ -56,14 +56,18 @@ std::unique_ptr<WindowsRawInputFilter>
WindowsRawInputFilter::Register(MainWindow *window)
{
RAWINPUTDEVICE rid[2] = {
{.usUsagePage = 0x01,
.usUsage = 0x06,
.dwFlags = RIDEV_NOHOTKEYS,
.hwndTarget = nullptr},
{ .usUsagePage = 0x01,
.usUsage = 0x02,
.dwFlags = 0,
.hwndTarget = nullptr}
{
.usUsagePage = 0x01,
.usUsage = 0x06,
.dwFlags = RIDEV_NOHOTKEYS,
.hwndTarget = nullptr
},
{
.usUsagePage = 0x01,
.usUsage = 0x02,
.dwFlags = 0,
.hwndTarget = nullptr
}
};
if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE))
@@ -89,14 +93,18 @@ WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window)
WindowsRawInputFilter::~WindowsRawInputFilter()
{
RAWINPUTDEVICE rid[2] = {
{.usUsagePage = 0x01,
.usUsage = 0x06,
.dwFlags = RIDEV_REMOVE,
.hwndTarget = NULL},
{ .usUsagePage = 0x01,
.usUsage = 0x02,
.dwFlags = RIDEV_REMOVE,
.hwndTarget = NULL}
{
.usUsagePage = 0x01,
.usUsage = 0x06,
.dwFlags = RIDEV_REMOVE,
.hwndTarget = NULL
},
{
.usUsagePage = 0x01,
.usUsage = 0x02,
.dwFlags = RIDEV_REMOVE,
.hwndTarget = NULL
}
};
if (hook_enabled)

View File

@@ -54,28 +54,26 @@ joystick_init(void)
joysticks_present = SDL_NumJoysticks();
memset(sdl_joy, 0, sizeof(sdl_joy));
for (int c = 0; c < joysticks_present; c++) {
sdl_joy[c] = SDL_JoystickOpen(c);
for (int js = 0; js < joysticks_present; js++) {
sdl_joy[js] = SDL_JoystickOpen(js);
if (sdl_joy[c]) {
int d;
if (sdl_joy[js]) {
strncpy(plat_joystick_state[js].name, SDL_JoystickNameForIndex(js), 64);
plat_joystick_state[js].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[js]), MAX_JOY_AXES);
plat_joystick_state[js].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[js]), MAX_JOY_BUTTONS);
plat_joystick_state[js].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[js]), MAX_JOY_POVS);
strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64);
plat_joystick_state[c].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES);
plat_joystick_state[c].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS);
plat_joystick_state[c].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS);
for (d = 0; d < plat_joystick_state[c].nr_axes; d++) {
snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d);
plat_joystick_state[c].axis[d].id = d;
for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++) {
snprintf(plat_joystick_state[js].axis[axis_nr].name, sizeof(plat_joystick_state[js].axis[axis_nr].name), "Axis %i", axis_nr);
plat_joystick_state[js].axis[axis_nr].id = axis_nr;
}
for (d = 0; d < plat_joystick_state[c].nr_buttons; d++) {
snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d);
plat_joystick_state[c].button[d].id = d;
for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++) {
snprintf(plat_joystick_state[js].button[button_nr].name, sizeof(plat_joystick_state[js].button[button_nr].name), "Button %i", button_nr);
plat_joystick_state[js].button[button_nr].id = button_nr;
}
for (d = 0; d < plat_joystick_state[c].nr_povs; d++) {
snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d);
plat_joystick_state[c].pov[d].id = d;
for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++) {
snprintf(plat_joystick_state[js].pov[pov_nr].name, sizeof(plat_joystick_state[js].pov[pov_nr].name), "POV %i", pov_nr);
plat_joystick_state[js].pov[pov_nr].id = pov_nr;
}
}
}
@@ -84,11 +82,9 @@ joystick_init(void)
void
joystick_close(void)
{
int c;
for (c = 0; c < joysticks_present; c++) {
if (sdl_joy[c])
SDL_JoystickClose(sdl_joy[c]);
for (int js = 0; js < joysticks_present; js++) {
if (sdl_joy[js])
SDL_JoystickClose(sdl_joy[js]);
}
}
@@ -132,57 +128,60 @@ joystick_get_axis(int joystick_nr, int mapping)
void
joystick_process(void)
{
int c;
int d;
if (!joystick_type)
return;
SDL_JoystickUpdate();
for (c = 0; c < joysticks_present; c++) {
int b;
for (int js = 0; js < joysticks_present; js++) {
for (int axis_nr = 0; axis_nr < plat_joystick_state[js].nr_axes; axis_nr++)
plat_joystick_state[js].a[axis_nr] = SDL_JoystickGetAxis(sdl_joy[js], axis_nr);
for (b = 0; b < plat_joystick_state[c].nr_axes; b++)
plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b);
for (int button_nr = 0; button_nr < plat_joystick_state[js].nr_buttons; button_nr++)
plat_joystick_state[js].b[button_nr] = SDL_JoystickGetButton(sdl_joy[js], button_nr);
for (b = 0; b < plat_joystick_state[c].nr_buttons; b++)
plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b);
for (int pov_nr = 0; pov_nr < plat_joystick_state[js].nr_povs; pov_nr++)
plat_joystick_state[js].p[pov_nr] = SDL_JoystickGetHat(sdl_joy[js], pov_nr);
for (b = 0; b < plat_joystick_state[c].nr_povs; b++)
plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b);
// pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present);
#if 0
pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", js,
joystick_state[js].x,
joystick_state[js].y,
joystick_state[js].b[0],
joystick_state[js].b[1],
joysticks_present);
#endif
}
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) {
if (joystick_state[c].plat_joystick_nr) {
int joystick_nr = joystick_state[c].plat_joystick_nr - 1;
for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) {
if (joystick_state[js].plat_joystick_nr) {
int joystick_nr = joystick_state[js].plat_joystick_nr - 1;
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]);
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]];
for (d = 0; d < joystick_get_pov_count(joystick_type); d++) {
int x, y;
double angle, magnitude;
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++)
joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]);
x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]);
y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]);
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++)
joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]];
angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI);
magnitude = sqrt((double) x * (double) x + (double) y * (double) y);
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) {
int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]);
int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]);
double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI);
double magnitude = sqrt((double) x * (double) x + (double) y * (double) y);
if (magnitude < 16384)
joystick_state[c].pov[d] = -1;
joystick_state[js].pov[pov_nr] = -1;
else
joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360;
joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360;
}
} else {
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = 0;
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = 0;
for (d = 0; d < joystick_get_pov_count(joystick_type); d++)
joystick_state[c].pov[d] = -1;
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++)
joystick_state[js].axis[axis_nr] = 0;
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++)
joystick_state[js].button[button_nr] = 0;
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++)
joystick_state[js].pov[pov_nr] = -1;
}
}
}

View File

@@ -412,7 +412,7 @@ win_joystick_handle(PRAWINPUT raw)
/* Read buttons */
USAGE usage_list[128] = { 0 };
ULONG usage_length = plat_joystick_state[j].nr_buttons;
memset(plat_joystick_state[j].b, 0, 32 * sizeof(int));
memset(plat_joystick_state[j].b, 0, MAX_JOY_BUTTONS * sizeof(int));
r = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usage_list, &usage_length,
raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid);
@@ -425,8 +425,8 @@ win_joystick_handle(PRAWINPUT raw)
}
/* Read axes */
for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) {
const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a];
for (int axis_nr = 0; axis_nr < plat_joystick_state[j].nr_axes; axis_nr++) {
const struct raw_axis_t *axis = &raw_joystick_state[j].axis[axis_nr];
ULONG uvalue = 0;
LONG value = 0;
LONG center = (axis->max - axis->min + 1) / 2;
@@ -453,15 +453,15 @@ win_joystick_handle(PRAWINPUT raw)
value = value * 32768 / center;
}
plat_joystick_state[j].a[a] = value;
plat_joystick_state[j].a[axis_nr] = value;
#if 0
joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]);
joystick_log("%s %-06d ", plat_joystick_state[j].axis[axis_nr].name, plat_joystick_state[j].a[axis_nr]);
#endif
}
/* read povs */
for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) {
const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p];
for (int pov_nr = 0; pov_nr < plat_joystick_state[j].nr_povs; pov_nr++) {
const struct raw_pov_t *pov = &raw_joystick_state[j].pov[pov_nr];
ULONG uvalue = 0;
LONG value = -1;
@@ -474,10 +474,10 @@ win_joystick_handle(PRAWINPUT raw)
value %= 36000;
}
plat_joystick_state[j].p[p] = value;
plat_joystick_state[j].p[pov_nr] = value;
#if 0
joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]);
joystick_log("%s %-3d ", plat_joystick_state[j].pov[pov_nr].name, plat_joystick_state[j].p[pov_nr]);
#endif
}
#if 0
@@ -508,44 +508,39 @@ joystick_get_axis(int joystick_nr, int mapping)
void
joystick_process(void)
{
int d;
if (joystick_type == JS_TYPE_NONE)
return;
for (int c = 0; c < joystick_get_max_joysticks(joystick_type); c++) {
if (joystick_state[c].plat_joystick_nr) {
int joystick_nr = joystick_state[c].plat_joystick_nr - 1;
for (int js = 0; js < joystick_get_max_joysticks(joystick_type); js++) {
if (joystick_state[js].plat_joystick_nr) {
int joystick_nr = joystick_state[js].plat_joystick_nr - 1;
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]);
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]];
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++)
joystick_state[js].axis[axis_nr] = joystick_get_axis(joystick_nr, joystick_state[js].axis_mapping[axis_nr]);
for (d = 0; d < joystick_get_pov_count(joystick_type); d++) {
int x;
int y;
double angle;
double magnitude;
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++)
joystick_state[js].button[button_nr] = plat_joystick_state[joystick_nr].b[joystick_state[js].button_mapping[button_nr]];
x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]);
y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]);
angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI);
magnitude = sqrt((double) x * (double) x + (double) y * (double) y);
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++) {
int x = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][0]);
int y = joystick_get_axis(joystick_nr, joystick_state[js].pov_mapping[pov_nr][1]);
double angle = (atan2((double) y, (double) x) * 360.0) / (2 * M_PI);
double magnitude = sqrt((double) x * (double) x + (double) y * (double) y);
if (magnitude < 16384)
joystick_state[c].pov[d] = -1;
joystick_state[js].pov[pov_nr] = -1;
else
joystick_state[c].pov[d] = ((int) angle + 90 + 360) % 360;
joystick_state[js].pov[pov_nr] = ((int) angle + 90 + 360) % 360;
}
} else {
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = 0;
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = 0;
for (d = 0; d < joystick_get_pov_count(joystick_type); d++)
joystick_state[c].pov[d] = -1;
for (int axis_nr = 0; axis_nr < joystick_get_axis_count(joystick_type); axis_nr++)
joystick_state[js].axis[axis_nr] = 0;
for (int button_nr = 0; button_nr < joystick_get_button_count(joystick_type); button_nr++)
joystick_state[js].button[button_nr] = 0;
for (int pov_nr = 0; pov_nr < joystick_get_pov_count(joystick_type); pov_nr++)
joystick_state[js].pov[pov_nr] = -1;
}
}
}

View File

@@ -88,7 +88,7 @@ plat_serpt_set_params(void *priv)
const serial_passthrough_t *dev = (serial_passthrough_t *) priv;
if (dev->mode == SERPT_MODE_HOSTSER) {
DCB serialattr = {};
DCB serialattr = { 0 };
GetCommState((HANDLE) dev->master_fd, &serialattr);
#define BAUDRATE_RANGE(baud_rate, min, max) \
if (baud_rate >= min && baud_rate < max) { \

View File

@@ -1421,7 +1421,7 @@ static const device_config_t aha_154xcp_config[] = {
.default_string = "v1_02_en",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Version 1.02 (English)", .internal_name = "v1_02_en", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp102.bin",

View File

@@ -197,20 +197,30 @@ ncr5380_bus_read(ncr_t *ncr)
phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN);
if (phase == SCSI_PHASE_DATA_IN) {
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->state = STATE_DATAIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) {
ncr5380_log("Phase Data In.\n");
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->state = STATE_DATAIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
}
} else if (phase == SCSI_PHASE_DATA_OUT) {
if (ncr->new_phase & BUS_IDLE) {
ncr->state = STATE_IDLE;
ncr->cur_bus &= ~BUS_BSY;
} else
ncr->state = STATE_DATAOUT;
} else {
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1))
ncr->state = STATE_DATAOUT;
}
} else if (phase == SCSI_PHASE_STATUS) {
ncr5380_log("Phase Status.\n");
ncr->wait_data_back = 0;
ncr->cur_bus |= BUS_REQ;
ncr->state = STATE_STATUS;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_IN) {
ncr5380_log("Phase Message In.\n");
ncr->state = STATE_MESSAGEIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_OUT) {
@@ -335,19 +345,22 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
ncr5380_log("CMD Phase1 DataIn.\n");
scsi_device_command_phase1(dev);
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle in\n");
ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos);
ncr->timer(ncr->priv, ncr->period);
} else {
ncr5380_log("DMA mode IN.\n");
ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos);
ncr->clear_req = 3;
}
@@ -359,7 +372,8 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
case STATE_DATAOUT:
dev = &scsi_devices[ncr->bus][ncr->target_id];
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
@@ -439,12 +453,12 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
switch (port & 7) {
case 0: /* Output data register */
ncr5380_log("Write: Output data register, val = %02x\n", val);
ncr5380_log("[%04X:%08X]: Write: Output data register, val=%02x\n", CS, cpu_state.pc, val);
ncr->output_data = val;
break;
case 1: /* Initiator Command Register */
ncr5380_log("Write: Initiator command register\n");
ncr5380_log("[%04X:%08X]: Write: Initiator command register, val=%02x.\n", CS, cpu_state.pc, val);
if ((val & 0x80) && !(ncr->icr & 0x80)) {
ncr5380_log("Resetting the 5380\n");
ncr5380_reset(ncr);
@@ -465,7 +479,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 3: /* Target Command Register */
ncr5380_log("Write: Target Command register\n");
ncr5380_log("Write: Target Command register, val=%02x.\n", val);
ncr->tcr = val;
break;
@@ -482,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 7: /* start DMA Initiator Receive */
ncr5380_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA);
ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA);
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
if (ncr->dma_initiator_receive_ext)
@@ -510,13 +524,13 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
ncr5380_log("Read: Current SCSI data register\n");
if (ncr->icr & ICR_DBP) {
/*Return the data from the output register if on data bus phase from ICR*/
ncr5380_log("Data Bus Phase, ret = %02x\n", ncr->output_data);
ret = ncr->output_data;
ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data);
} else {
/*Return the data from the SCSI bus*/
ncr5380_bus_read(ncr);
ncr5380_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus));
ret = BUS_GETDATA(ncr->cur_bus);
ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret);
}
break;
@@ -595,7 +609,9 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
break;
case 6:
ret = ncr->tx_data;
ncr5380_log("Read: Input Data.\n");
ncr5380_bus_read(ncr);
ret = BUS_GETDATA(ncr->cur_bus);
break;
case 7: /* reset Parity/Interrupt */

View File

@@ -148,6 +148,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
ncr400->busy = 1;
if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0)))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
break;
@@ -181,13 +187,15 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
memset(ncr400->buffer, 0, MIN(128, dev->buffer_length));
if (ncr->mode & MODE_MONITOR_BUSY)
timer_on_auto(&ncr400->timer, ncr->period);
timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0);
else if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 40.0);
else
timer_on_auto(&ncr400->timer, ncr->period);
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
ncr->wait_data_back = ncr->wait_data;
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n",
ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
}
break;
@@ -244,6 +252,12 @@ ncr53c400_read(uint32_t addr, void *priv)
ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl);
if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
break;
@@ -397,16 +411,20 @@ t130b_in(uint16_t port, void *priv)
}
static void
ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv))
ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
{
ncr_t *ncr = (ncr_t *) priv;
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
if (!(ncr->mode & MODE_DMA)) {
ncr53c400_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded);
if (!ncr400->block_count_loaded) {
if (!(ncr->mode & MODE_DMA)) {
ncr53c400_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
}
}
}
@@ -474,6 +492,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -527,6 +546,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
@@ -544,6 +564,7 @@ ncr53c400_callback(void *priv)
break;
}
ncr53c400_log("Bus Read.\n");
ncr5380_bus_read(ncr);
if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {
@@ -841,7 +862,7 @@ static const device_config_t rt1000b_config[] = {
.default_string = "v8_10r",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Version 8.10R", .internal_name = "v8_10r", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_810R_ROM, "" } },

View File

@@ -630,6 +630,7 @@ esp_hard_reset(esp_t *dev)
fifo8_reset(&dev->fifo);
fifo8_reset(&dev->cmdfifo);
dev->dma = 0;
dev->tchi_written = 0;
dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7;
esp_log("ESP Reset\n");
@@ -1346,7 +1347,7 @@ esp_reg_read(esp_t *dev, uint32_t saddr)
if (dev->mca) {
ret = dev->rregs[ESP_TCHI];
} else {
if (dev->rregs[ESP_CFG2] & 0x40)
if (!dev->tchi_written)
ret = TCHI_AM53C974;
else
ret = dev->rregs[ESP_TCHI];
@@ -1369,6 +1370,8 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val)
esp_log("Write reg %02x = %02x\n", saddr, val);
switch (saddr) {
case ESP_TCHI:
dev->tchi_written = 1;
fallthrough;
case ESP_TCLO:
case ESP_TCMID:
esp_log("ESP TCW reg%02x = %02x.\n", saddr, val);

View File

@@ -71,7 +71,7 @@ typedef struct
const device_t *device;
} MIDI_OUT_DEVICE, MIDI_IN_DEVICE;
static const MIDI_OUT_DEVICE devices[] = {
static const MIDI_OUT_DEVICE midi_out_devices[] = {
// clang-format off
{ &device_none },
#ifdef USE_FLUIDSYNTH
@@ -106,8 +106,8 @@ static const MIDI_IN_DEVICE midi_in_devices[] = {
int
midi_out_device_available(int card)
{
if (devices[card].device)
return device_available(devices[card].device);
if (midi_out_devices[card].device)
return device_available(midi_out_devices[card].device);
return 1;
}
@@ -115,21 +115,21 @@ midi_out_device_available(int card)
const device_t *
midi_out_device_getdevice(int card)
{
return devices[card].device;
return midi_out_devices[card].device;
}
int
midi_out_device_has_config(int card)
{
if (!devices[card].device)
if (!midi_out_devices[card].device)
return 0;
return devices[card].device->config ? 1 : 0;
return midi_out_devices[card].device->config ? 1 : 0;
}
const char *
midi_out_device_get_internal_name(int card)
{
return device_get_internal_name(devices[card].device);
return device_get_internal_name(midi_out_devices[card].device);
}
int
@@ -137,8 +137,8 @@ midi_out_device_get_from_internal_name(char *s)
{
int c = 0;
while (devices[c].device != NULL) {
if (!strcmp(devices[c].device->internal_name, s))
while (midi_out_devices[c].device != NULL) {
if (!strcmp(midi_out_devices[c].device->internal_name, s))
return c;
c++;
}
@@ -149,8 +149,8 @@ midi_out_device_get_from_internal_name(char *s)
void
midi_out_device_init(void)
{
if ((midi_output_device_current > 0) && devices[midi_output_device_current].device)
device_add(devices[midi_output_device_current].device);
if ((midi_output_device_current > 0) && midi_out_devices[midi_output_device_current].device)
device_add(midi_out_devices[midi_output_device_current].device);
midi_output_device_last = midi_output_device_current;
}

View File

@@ -330,8 +330,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "output_gain",
.description = "Output Gain",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 100
},
@@ -347,8 +346,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "chorus_voices",
.description = "Chorus Voices",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 99
},
@@ -358,8 +356,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "chorus_level",
.description = "Chorus Level",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 100
},
@@ -369,8 +366,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "chorus_speed",
.description = "Chorus Speed",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 10,
.max = 500
},
@@ -380,8 +376,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "chorus_depth",
.description = "Chorus Depth",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 2560
},
@@ -391,8 +386,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "chorus_waveform",
.description = "Chorus Waveform",
.type = CONFIG_SELECTION,
.selection =
{
.selection = {
{
.description = "Sine",
.value = 0
@@ -414,8 +408,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "reverb_room_size",
.description = "Reverb Room Size",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 100
},
@@ -425,8 +418,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "reverb_damping",
.description = "Reverb Damping",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 100
},
@@ -436,8 +428,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "reverb_width",
.description = "Reverb Width",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 1000
},
@@ -447,8 +438,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "reverb_level",
.description = "Reverb Level",
.type = CONFIG_SPINNER,
.spinner =
{
.spinner = {
.min = 0,
.max = 100
},
@@ -458,8 +448,7 @@ static const device_config_t fluidsynth_config[] = {
.name = "interpolation",
.description = "Interpolation Method",
.type = CONFIG_SELECTION,
.selection =
{
.selection = {
{
.description = "None",
.value = 0

View File

@@ -24,7 +24,11 @@
#define RESID_BRANCH_HINTS true
// Compiler specifics.
#ifndef _MSC_VER
#define HAVE_BUILTIN_EXPECT true
#else
#define HAVE_BUILTIN_EXPECT false
#endif
// Branch prediction macros, lifted off the Linux kernel.
#if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT

View File

@@ -1238,7 +1238,7 @@ azt_init(const device_t *info)
fm_driver_get(FM_YMF262, &azt2316a->sb->opl);
sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1);
sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a);
sb_dsp_init(&azt2316a->sb->dsp, SBPRO2_DSP_302, azt2316a->type, azt2316a);
sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr);
sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq);
sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma);

View File

@@ -497,7 +497,7 @@ cmi8x38_sb_mixer_write(uint16_t addr, uint8_t val, void *priv)
/* Set TDMA channels if auto-detection is enabled. */
if ((dev->io_regs[0x27] & 0x01) && (mixer->index == 0x81)) {
dev->tdma_8 = dev->sb->dsp.sb_8_dmanum;
if (dev->sb->dsp.sb_type >= SB16)
if (dev->sb->dsp.sb_type >= SB16_DSP_404)
dev->tdma_16 = dev->sb->dsp.sb_16_dmanum;
}
} else {
@@ -879,7 +879,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
dev->sb->dsp.sbleftright_default = !!(val & 0x02);
/* Enable or disable SB16 mode. */
dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2 : SB16;
dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2_DSP_302 : SB16_DSP_405;
break;
case 0x22:

View File

@@ -173,8 +173,8 @@ static const device_config_t opl2board_config[] = {
.type = CONFIG_SERPORT,
.default_string = "",
.file_filter = NULL,
.spinner = {},
.selection = {}
.spinner = { 0 },
.selection = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};

View File

@@ -394,7 +394,7 @@ optimc_init(const device_t *info)
optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262;
sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B);
sb_dsp_init(&optimc->sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, optimc);
sb_dsp_init(&optimc->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, optimc);
sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr);
sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq);
sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma);

View File

@@ -86,6 +86,7 @@
* Copyright 2008-2024 Sarah Walker.
* Copyright 2024 Miran Grca.
*/
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
@@ -2314,7 +2315,7 @@ pas16_init(const device_t *info)
pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f);
fm_driver_get(FM_YMF262, &pas16->opl);
sb_dsp_set_real_opl(&pas16->dsp, 1);
sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16);
pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(pas16->mpu, 0, sizeof(mpu_t));
mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));

View File

@@ -43,6 +43,10 @@
#include <86box/snd_sb.h>
#include <86box/plat_unused.h>
#define SB_1 0
#define SB_15 1
#define SB_2 2
#define SB_16_PNP_NOIDE 0
#define SB_16_PNP_IDE 1
@@ -288,7 +292,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv)
if (!sb->opl_enabled)
return;
if (sb->dsp.sb_type == SBPRO) {
if (sb->dsp.sb_type == SBPRO_DSP_300) {
opl_buf = sb->opl.update(sb->opl.priv);
opl2_buf = sb->opl2.update(sb->opl2.priv);
} else
@@ -300,7 +304,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv)
out_l = 0.0;
out_r = 0.0;
if (sb->dsp.sb_type == SBPRO) {
if (sb->dsp.sb_type == SBPRO_DSP_300) {
/* Two chips for LEFT and RIGHT channels.
Each chip stores data into the LEFT channel only (no sample alternating.) */
out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375;
@@ -322,7 +326,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv)
}
sb->opl.reset_buffer(sb->opl.priv);
if (sb->dsp.sb_type == SBPRO)
if (sb->dsp.sb_type == SBPRO_DSP_300)
sb->opl2.reset_buffer(sb->opl2.priv);
}
@@ -415,7 +419,7 @@ sb_get_music_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv)
const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16;
const int dsp_rec_pos = sb->dsp.record_pos_write;
double bass_treble;
const int32_t *opl_buf = NULL;
const int32_t *opl_buf = NULL;
if (sb->opl_enabled)
opl_buf = sb->opl.update(sb->opl.priv);
@@ -1157,7 +1161,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0xff:
if ((sb->dsp.sb_type > SBAWE32) && !sb->dsp.sb_16_dma_supported) {
if ((sb->dsp.sb_type > SBAWE32_DSP_412) && !sb->dsp.sb_16_dma_supported) {
/*
Bit 5: High DMA channel enabled (0 = yes, 1 = no);
Bit 2: ????;
@@ -1341,7 +1345,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
/* http://the.earth.li/~tfm/oldpage/sb_mixer.html - 0x10, 0x20, 0x80. */
const uint8_t temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) |
((sb->dsp.sb_irq401) ? 4 : 0);
if (sb->dsp.sb_type >= SBAWE32)
if (sb->dsp.sb_type >= SBAWE32_DSP_412)
ret = temp | 0x80;
else
ret = temp | 0x40;
@@ -1386,7 +1390,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
- Register FF = FF: Volume playback normal.
- Register FF = Not FF: Volume playback low unless
bit 6 of 82h is set. */
if (sb->dsp.sb_type > SBAWE32)
if (sb->dsp.sb_type > SBAWE32_DSP_412)
ret = mixer->regs[mixer->index];
break;
@@ -1808,8 +1812,8 @@ sb_mcv_read(int port, void *priv)
void
sb_mcv_write(int port, uint8_t val, void *priv)
{
uint16_t addr;
sb_t *sb = (sb_t *) priv;
uint16_t addr = 0;
sb_t *sb = (sb_t *) priv;
if (port < 0x102)
return;
@@ -1872,8 +1876,8 @@ sb_pro_mcv_read(int port, void *priv)
static void
sb_pro_mcv_write(int port, uint8_t val, void *priv)
{
uint16_t addr;
sb_t *sb = (sb_t *) priv;
uint16_t addr = 0;
sb_t *sb = (sb_t *) priv;
if (port < 0x102)
return;
@@ -1943,8 +1947,8 @@ sb_16_reply_mca_read(int port, void *priv)
static void
sb_16_reply_mca_write(const int port, const uint8_t val, void *priv)
{
uint16_t addr;
sb_t *sb = (sb_t *) priv;
uint16_t addr = 0;
sb_t *sb = (sb_t *) priv;
if (port < 0x102)
return;
@@ -2219,7 +2223,7 @@ sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void
break;
case 2: /* Reserved (16) / WaveTable (32+) */
if (sb->dsp.sb_type > SB16)
if (sb->dsp.sb_type >= SBAWE32_DSP_412)
emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0);
break;
@@ -2812,182 +2816,62 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv)
}
void *
sb_1_init(UNUSED(const device_t *info))
sb_init(UNUSED(const device_t *info))
{
/* SB1/2 port mappings, 210h to 260h in 10h steps
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip */
sb_t *sb = malloc(sizeof(sb_t));
const uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YM3812, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
/* DSP I/O handler is activated in sb_dsp_setaddr */
if (sb->opl_enabled) {
io_sethandler(addr + 8, 0x0002,
sb->opl.read, NULL, NULL,
sb->opl.write, NULL, NULL,
sb->opl.priv);
io_sethandler(0x0388, 0x0002,
sb->opl.read, NULL, NULL,
sb->opl.write, NULL, NULL,
sb->opl.priv);
}
sb->cms_enabled = 1;
memset(&sb->cms, 0, sizeof(cms_t));
io_sethandler(addr, 0x0004,
cms_read, NULL, NULL,
cms_write, NULL, NULL,
&sb->cms);
sb->mixer_enabled = 0;
sound_add_handler(sb_get_buffer_sb2, sb);
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sb2, sb);
sound_set_cd_audio_filter(sb2_filter_cd_audio, sb);
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
return sb;
}
void *
sb_15_init(UNUSED(const device_t *info))
{
/* SB1/2 port mappings, 210h to 260h in 10h steps
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip */
sb_t *sb = malloc(sizeof(sb_t));
const uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YM3812, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
/* DSP I/O handler is activated in sb_dsp_setaddr */
if (sb->opl_enabled) {
io_sethandler(addr + 8, 0x0002,
sb->opl.read, NULL, NULL,
sb->opl.write, NULL, NULL,
sb->opl.priv);
io_sethandler(0x0388, 0x0002,
sb->opl.read, NULL, NULL,
sb->opl.write, NULL, NULL,
sb->opl.priv);
}
sb->cms_enabled = device_get_config_int("cms");
if (sb->cms_enabled) {
memset(&sb->cms, 0, sizeof(cms_t));
io_sethandler(addr, 0x0004,
cms_read, NULL, NULL,
cms_write, NULL, NULL,
&sb->cms);
}
sb->mixer_enabled = 0;
sound_add_handler(sb_get_buffer_sb2, sb);
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sb2, sb);
sound_set_cd_audio_filter(sb2_filter_cd_audio, sb);
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
return sb;
}
void *
sb_mcv_init(UNUSED(const device_t *info))
{
/* SB1/2 port mappings, 210h to 260h in 10h steps
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip */
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YM3812, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sb->mixer_enabled = 0;
sound_add_handler(sb_get_buffer_sb2, sb);
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sb2, sb);
sound_set_cd_audio_filter(sb2_filter_cd_audio, sb);
/* I/O handlers activated in sb_mcv_write */
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, NULL, sb);
sb->pos_regs[0] = 0x84;
sb->pos_regs[1] = 0x50;
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
return sb;
}
void *
sb_2_init(UNUSED(const device_t *info))
{
/* SB2 port mappings, 220h or 240h.
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip
"CD version" also uses 250h or 260h for
2x0 to 2x3 -> CDROM interface
2x4 to 2x5 -> Mixer interface */
/* SB1.x port mappings, 210h to 260h in 10h steps:
(SB2 port mappings are 220h or 240h)
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip
SB2 "CD version" also uses 250h or 260h:
2x0 to 2x3 -> CDROM interface
2x4 to 2x5 -> Mixer interface */
/* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the
CMS chips are present.
This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't
exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror
for music to play.*/
sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_hex16("base");
uint16_t mixer_addr = device_get_config_int("mixaddr");
for music to play. */
sb_t *sb = calloc(1, sizeof(sb_t));
const uint16_t addr = device_get_config_hex16("base");
uint16_t mixer_addr = 0x0000;
uint8_t model = 0;
memset(sb, 0, sizeof(sb_t));
switch (info->local) {
default:
case SB_1:
model = SB_DSP_105;
sb->cms_enabled = 1;
break;
case SB_15:
model = SB_DSP_200;
sb->cms_enabled = device_get_config_int("cms");
break;
case SB_2:
model = SB_DSP_201;
sb->cms_enabled = device_get_config_int("cms");
mixer_addr = device_get_config_int("mixaddr");
break;
}
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YM3812, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, model, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
if (mixer_addr > 0x000)
if (mixer_addr > 0x0000)
sb_ct1335_mixer_reset(sb);
sb->cms_enabled = device_get_config_int("cms");
/* DSP I/O handler is activated in sb_dsp_setaddr */
if (sb->opl_enabled) {
if (!sb->cms_enabled) {
// TODO: See if this applies to the SB1.5 as well
if ((!sb->cms_enabled) && ((model == SB_DSP_201) || (model == SB_DSP_202))) {
io_sethandler(addr, 0x0002,
sb->opl.read, NULL, NULL,
sb->opl.write, NULL, NULL,
@@ -3019,6 +2903,7 @@ sb_2_init(UNUSED(const device_t *info))
sb);
} else
sb->mixer_enabled = 0;
sound_add_handler(sb_get_buffer_sb2, sb);
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sb2, sb);
@@ -3030,6 +2915,41 @@ sb_2_init(UNUSED(const device_t *info))
return sb;
}
void *
sb_mcv_init(UNUSED(const device_t *info))
{
/* SB1/2 port mappings, 210h to 260h in 10h steps
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip */
sb_t *sb = calloc(1, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YM3812, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB_DSP_105, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sb->mixer_enabled = 0;
sound_add_handler(sb_get_buffer_sb2, sb);
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sb2, sb);
sound_set_cd_audio_filter(sb2_filter_cd_audio, sb);
/* I/O handlers activated in sb_mcv_write */
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, NULL, sb);
sb->pos_regs[0] = 0x84;
sb->pos_regs[1] = 0x50;
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
return sb;
}
static uint8_t
sb_pro_v1_opl_read(uint16_t port, void *priv)
{
@@ -3059,9 +2979,8 @@ sb_pro_v1_init(UNUSED(const device_t *info))
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices)
2x0+10 to 2x0+13 CDROM interface. */
sb_t *sb = malloc(sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled) {
@@ -3072,7 +2991,7 @@ sb_pro_v1_init(UNUSED(const device_t *info))
}
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SBPRO_DSP_300, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -3122,16 +3041,15 @@ sb_pro_v2_init(UNUSED(const device_t *info))
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices)
2x0+10 to 2x0+13 CDROM interface. */
sb_t *sb = malloc(sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
uint16_t addr = device_get_config_hex16("base");
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -3176,14 +3094,13 @@ sb_pro_mcv_init(UNUSED(const device_t *info))
2x4 to 2x5 -> Mixer interface
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices) */
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
sb->mixer_enabled = 1;
@@ -3205,13 +3122,12 @@ sb_pro_mcv_init(UNUSED(const device_t *info))
static void *
sb_pro_compat_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
sb->mixer_enabled = 1;
@@ -3219,8 +3135,7 @@ sb_pro_compat_init(UNUSED(const device_t *info))
if (sb->opl_enabled)
music_add_handler(sb_get_music_buffer_sbpro, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, 1);
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3230,18 +3145,16 @@ sb_pro_compat_init(UNUSED(const device_t *info))
static void *
sb_16_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
const uint16_t addr = device_get_config_hex16("base");
const uint16_t mpu_addr = device_get_config_hex16("base401");
memset(sb, 0x00, sizeof(sb_t));
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
fm_driver_get((int) (intptr_t) info->local, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32PNP : SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32_DSP_413 : SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -3277,8 +3190,7 @@ sb_16_init(UNUSED(const device_t *info))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
if (mpu_addr) {
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART,
device_get_config_int("receive_input401"));
} else
@@ -3298,14 +3210,13 @@ sb_16_init(UNUSED(const device_t *info))
static void *
sb_16_reply_mca_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0x00, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_dsp_setdma16_enabled(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
@@ -3318,8 +3229,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info))
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3353,15 +3263,14 @@ sb_16_pnp_ide_available(void)
static void *
sb_16_pnp_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0x00, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
sb->pnp = 1;
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
@@ -3373,8 +3282,7 @@ sb_16_pnp_init(UNUSED(const device_t *info))
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3457,8 +3365,7 @@ sb_vibra16xv_available(void)
static void *
sb_vibra16_pnp_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0x00, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
sb->pnp = 1;
@@ -3466,7 +3373,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info))
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb);
/* The ViBRA 16XV does 16-bit DMA through 8-bit DMA. */
sb_dsp_setdma16_supported(&sb->dsp, info->local != SB_VIBRA16XV);
sb_ct1745_mixer_reset(sb);
@@ -3479,8 +3386,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info))
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3558,13 +3464,12 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info))
static void *
sb_16_compat_init(const device_t *info)
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_dsp_setdma16_enabled(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
@@ -3574,7 +3479,7 @@ sb_16_compat_init(const device_t *info)
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
music_add_handler(sb_get_music_buffer_sb16_awe32, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, (int) (intptr_t) info->local);
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3637,7 +3542,7 @@ sb_awe64_gold_available(void)
static void *
sb_awe32_init(UNUSED(const device_t *info))
{
sb_t *sb = malloc(sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
uint16_t addr = device_get_config_hex16("base");
uint16_t mpu_addr = device_get_config_hex16("base401");
uint16_t emu_addr = device_get_config_hex16("emu_base");
@@ -3650,7 +3555,7 @@ sb_awe32_init(UNUSED(const device_t *info))
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_set_real_opl(&sb->dsp, 1);
sb_dsp_init(&sb->dsp, SBAWE32, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, SBAWE32_DSP_412, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -3687,7 +3592,7 @@ sb_awe32_init(UNUSED(const device_t *info))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
if (mpu_addr) {
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART,
device_get_config_int("receive_input401"));
@@ -3710,11 +3615,9 @@ sb_awe32_init(UNUSED(const device_t *info))
static void *
sb_goldfinch_init(const device_t *info)
{
goldfinch_t *goldfinch = malloc(sizeof(goldfinch_t));
goldfinch_t *goldfinch = calloc(1, sizeof(goldfinch_t));
int onboard_ram = device_get_config_int("onboard_ram");
memset(goldfinch, 0x00, sizeof(goldfinch_t));
wavetable_add_handler(sb_get_wavetable_buffer_goldfinch, goldfinch);
emu8k_init(&goldfinch->emu8k, 0, onboard_ram);
@@ -3758,18 +3661,16 @@ sb_goldfinch_init(const device_t *info)
static void *
sb_awe32_pnp_init(const device_t *info)
{
sb_t *sb = malloc(sizeof(sb_t));
sb_t *sb = calloc(1, sizeof(sb_t));
int onboard_ram = device_get_config_int("onboard_ram");
memset(sb, 0x00, sizeof(sb_t));
sb->pnp = 1;
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, (info->local >= SB_AWE64_VALUE) ?
SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb);
SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
@@ -3783,8 +3684,7 @@ sb_awe32_pnp_init(const device_t *info)
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
@@ -3903,7 +3803,7 @@ ess_x688_init(UNUSED(const device_t *info))
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
sb_dsp_set_real_opl(&ess->dsp, 1);
sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_setaddr(&ess->dsp, addr);
sb_dsp_setirq(&ess->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma"));
@@ -4014,7 +3914,7 @@ ess_x688_pnp_init(UNUSED(const device_t *info))
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
sb_dsp_set_real_opl(&ess->dsp, 1);
sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_setdma16_supported(&ess->dsp, 0);
ess_mixer_reset(ess);
@@ -4100,7 +4000,7 @@ ess_x688_mca_init(UNUSED(const device_t *info))
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
sb_dsp_set_real_opl(&ess->dsp, 1);
sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
sb_dsp_setdma16_supported(&ess->dsp, 0);
ess_mixer_reset(ess);
@@ -4211,7 +4111,8 @@ static const device_config_t sb_config[] = {
},
{
.description = "0x260",
.value = 0x260 },
.value = 0x260
},
{ .description = "" }
}
},
@@ -4260,7 +4161,7 @@ static const device_config_t sb_config[] = {
.description = "DMA 3",
.value = 3
},
{ "" }
{ .description = "" }
}
},
{
@@ -4314,8 +4215,7 @@ static const device_config_t sb15_config[] = {
.description = "0x260",
.value = 0x260
},
{
.description = "" }
{ .description = "" }
}
},
{
@@ -4408,10 +4308,6 @@ static const device_config_t sb2_config[] = {
.description = "0x240",
.value = 0x240
},
{
.description = "0x260",
.value = 0x260
},
{ .description = "" }
}
},
@@ -4428,14 +4324,6 @@ static const device_config_t sb2_config[] = {
.description = "Disabled",
.value = 0
},
{
.description = "0x220",
.value = 0x220
},
{
.description = "0x240",
.value = 0x240
},
{
.description = "0x250",
.value = 0x250
@@ -5769,8 +5657,8 @@ const device_t sb_1_device = {
.name = "Sound Blaster v1.0",
.internal_name = "sb",
.flags = DEVICE_ISA,
.local = 0,
.init = sb_1_init,
.local = SB_1,
.init = sb_init,
.close = sb_close,
.reset = NULL,
.available = NULL,
@@ -5783,8 +5671,8 @@ const device_t sb_15_device = {
.name = "Sound Blaster v1.5",
.internal_name = "sb1.5",
.flags = DEVICE_ISA,
.local = 0,
.init = sb_15_init,
.local = SB_15,
.init = sb_init,
.close = sb_close,
.reset = NULL,
.available = NULL,
@@ -5811,8 +5699,8 @@ const device_t sb_2_device = {
.name = "Sound Blaster v2.0",
.internal_name = "sb2.0",
.flags = DEVICE_ISA,
.local = 0,
.init = sb_2_init,
.local = SB_2,
.init = sb_init,
.close = sb_close,
.reset = NULL,
.available = NULL,

View File

@@ -77,13 +77,33 @@ static int sb_commands[256] = {
-1, -1, 0, 0, -1, -1, -1, -1, -1, 1, 2, -1, -1, -1, -1, 0
};
#if 0
// Currently unused, here for reference if ever needed
char sb202_copyright[] = "COPYRIGHT(C) CREATIVE TECHNOLOGY PTE. LTD. (1991) "
#endif
char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40c, 0x40d, 0x410 };
uint16_t sb_dsp_versions[] = {
0, /* Pad */
0, /* SADLIB - No DSP */
0x105, /* SB_DSP_105 - SB1/1.5, DSP v1.05 */
0x200, /* SB_DSP_200 - SB1.5/2, DSP v2.00 */
0x201, /* SB_DSP_201 - SB1.5/2, DSP v2.01 - needed for high-speed DMA */
0x202, /* SB_DSP_202 - SB2, DSP v2.02 */
0x300, /* SB_PRO_DSP_300 - SB Pro, DSP v3.00 */
0x302, /* SBPRO2_DSP_302 - SB Pro 2, DSP v3.02 + OPL3 */
0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */
0x405, /* SB16_405 - DSP v4.05 + OPL3 */
0x406, /* SB16_406 - DSP v4.06 + OPL3 */
0x40b, /* SB16_411 - DSP v4.11 + OPL3 */
0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */
0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */
0x410 /* SBAWE64 - DSP v4.16 + OPL3 */
};
/*These tables were 'borrowed' from DOSBox*/
int8_t scaleMap4[64] = {
0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7,
1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7,
1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30,
4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
};
@@ -525,7 +545,7 @@ sb_doreset(sb_dsp_t *dsp)
sb_commands[8] = 1;
sb_commands[9] = 1;
} else {
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
sb_commands[8] = 1;
else
sb_commands[8] = -1;
@@ -1206,7 +1226,7 @@ sb_exec_command(sb_dsp_t *dsp)
/* Update 8051 ram with the current DSP command.
See https://github.com/joncampbell123/dosbox-x/issues/1044 */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sb_8051_ram[0x20] = dsp->sb_command;
}
@@ -1232,15 +1252,15 @@ sb_exec_command(sb_dsp_t *dsp)
switch (dsp->sb_command) {
case 0x01: /* ???? */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1;
break;
case 0x03: /* ASP status */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
sb_add_data(dsp, 0);
break;
case 0x04: /* ASP set mode register */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sb_asp_mode = dsp->sb_data[0];
if (dsp->sb_asp_mode & 4)
dsp->sb_asp_ram_index = 0;
@@ -1248,7 +1268,7 @@ sb_exec_command(sb_dsp_t *dsp)
} /* else DSP Status (Obsolete) */
break;
case 0x05: /* ASP set codec parameter */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]);
}
break;
@@ -1278,9 +1298,9 @@ sb_exec_command(sb_dsp_t *dsp)
sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */
break;
}
if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */
if (dsp->sb_type == SBAWE64_DSP_416) /* AWE64 has no ASP or a socket for it */
sb_add_data(dsp, 0xFF);
else if (dsp->sb_type >= SB16)
else if (dsp->sb_type >= SB16_DSP_404)
sb_add_data(dsp, 0x18);
break;
case 0x09: /* AZTECH mode set */
@@ -1296,7 +1316,7 @@ sb_exec_command(sb_dsp_t *dsp)
}
break;
case 0x0E: /* ASP set register */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1];
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */
@@ -1315,7 +1335,7 @@ sb_exec_command(sb_dsp_t *dsp)
}
break;
case 0x0F: /* ASP get register */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */
if (dsp->sb_asp_mode & 8)
dsp->sb_asp_ram_index = 0;
@@ -1359,11 +1379,11 @@ sb_exec_command(sb_dsp_t *dsp)
}
break;
case 0x1C: /* 8-bit autoinit DMA output */
if (dsp->sb_type >= SB15)
if (dsp->sb_type >= SB_DSP_200)
sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen);
break;
case 0x1F: /* 2-bit ADPCM autoinit output */
if (dsp->sb_type >= SB15) {
if (dsp->sb_type >= SB_DSP_200) {
sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv);
dsp->sb_8_length--;
@@ -1388,7 +1408,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0x28: /* Direct ADC, 8-bit (Burst) */
break;
case 0x2C: /* 8-bit autoinit DMA input */
if (dsp->sb_type >= SB15)
if (dsp->sb_type >= SB_DSP_200)
sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
break;
case 0x30: /* MIDI Polling mode input */
@@ -1405,7 +1425,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0x33: /* MIDI Read Timestamp Interrupt */
break;
case 0x34: /* MIDI In poll */
if (dsp->sb_type < SB2)
if (dsp->sb_type < SB_DSP_200)
break;
sb_dsp_log("MIDI poll in\n");
dsp->midi_in_poll = 1;
@@ -1413,7 +1433,7 @@ sb_exec_command(sb_dsp_t *dsp)
dsp->uart_irq = 0;
break;
case 0x35: /* MIDI In irq */
if (dsp->sb_type < SB2)
if (dsp->sb_type < SB_DSP_200)
break;
sb_dsp_log("MIDI irq in\n");
dsp->midi_in_poll = 0;
@@ -1432,7 +1452,7 @@ sb_exec_command(sb_dsp_t *dsp)
temp = 256 - dsp->sb_data[0];
temp = 1000000 / temp;
sb_dsp_log("Sample rate - %ihz (%f)\n", temp, dsp->sblatcho);
if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16))
if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16_DSP_404))
recalc_sb16_filter(0, temp);
dsp->sb_freq = temp;
if (IS_ESS(dsp)) {
@@ -1441,7 +1461,7 @@ sb_exec_command(sb_dsp_t *dsp)
break;
case 0x41: /* Set output sampling rate */
case 0x42: /* Set input sampling rate */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sblatcho = (double) ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
sb_dsp_log("Sample rate - %ihz (%f)\n", dsp->sb_data[1] + (dsp->sb_data[0] << 8), dsp->sblatcho);
temp = dsp->sb_freq;
@@ -1459,7 +1479,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0x47: /* Continue Auto-Initialize DMA, 16-bit */
break;
case 0x48: /* Set DSP block transfer size */
dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
if (dsp->sb_type >= SB_DSP_200)
dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
break;
case 0x65: /* 4-bit ESPCM output with reference */
case 0x64: /* 4-bit ESPCM output */
@@ -1534,7 +1555,7 @@ sb_exec_command(sb_dsp_t *dsp)
}
break;
case 0x7D: /* 4-bit ADPCM autoinit output */
if (dsp->sb_type >= SB15) {
if (dsp->sb_type >= SB_DSP_200) {
sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv);
dsp->sb_8_length--;
@@ -1542,7 +1563,7 @@ sb_exec_command(sb_dsp_t *dsp)
}
break;
case 0x7F: /* 2.6-bit ADPCM autoinit output */
if (dsp->sb_type >= SB15) {
if (dsp->sb_type >= SB_DSP_200) {
sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv);
dsp->sb_8_length--;
@@ -1555,24 +1576,24 @@ sb_exec_command(sb_dsp_t *dsp)
timer_set_delay_u64(&dsp->output_timer, (uint64_t) trunc(dsp->sblatcho));
break;
case 0x90: /* High speed 8-bit autoinit DMA output */
if (dsp->sb_type >= SB2)
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated
sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen);
break;
case 0x91: /* High speed 8-bit single cycle DMA output */
if (dsp->sb_type >= SB2)
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated
sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen);
break;
case 0x98: /* High speed 8-bit autoinit DMA input */
if (dsp->sb_type >= SB2)
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated
sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen);
break;
case 0x99: /* High speed 8-bit single cycle DMA input */
if (dsp->sb_type >= SB2)
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated
sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen);
break;
case 0xA0: /* Set input mode to mono */
case 0xA8: /* Set input mode to stereo */
if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2))
if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO2_DSP_302))
break;
/* TODO: Implement. 3.xx-only command. */
break;
@@ -1584,7 +1605,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xB5:
case 0xB6:
case 0xB7: /* 16-bit DMA output */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
@@ -1598,7 +1619,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xBD:
case 0xBE:
case 0xBF: /* 16-bit DMA input */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
@@ -1612,7 +1633,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xC5:
case 0xC6:
case 0xC7: /* 8-bit DMA output */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
@@ -1626,7 +1647,7 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xCD:
case 0xCE:
case 0xCF: /* 8-bit DMA input */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
@@ -1638,20 +1659,20 @@ sb_exec_command(sb_dsp_t *dsp)
break;
case 0xD1: /* Speaker on */
if (IS_NOT_ESS(dsp)) {
if (dsp->sb_type < SB15) {
if (dsp->sb_type < SB_DSP_200) {
dsp->sb_8_pause = 1;
sb_stop_dma(dsp);
} else if (dsp->sb_type < SB16)
} else if (dsp->sb_type < SB16_DSP_404)
dsp->muted = 0;
}
dsp->sb_speaker = 1;
break;
case 0xD3: /* Speaker off */
if (IS_NOT_ESS(dsp)) {
if (dsp->sb_type < SB15) {
if (dsp->sb_type < SB_DSP_201) {
dsp->sb_8_pause = 1;
sb_stop_dma(dsp);
} else if (dsp->sb_type < SB16)
} else if (dsp->sb_type < SB16_DSP_404)
dsp->muted = 1;
}
dsp->sb_speaker = 0;
@@ -1661,26 +1682,28 @@ sb_exec_command(sb_dsp_t *dsp)
sb_resume_dma(dsp, 1);
break;
case 0xD5: /* Pause 16-bit DMA */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sb_16_pause = 1;
sb_stop_dma(dsp);
}
break;
case 0xD6: /* Continue 16-bit DMA */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
dsp->sb_16_pause = 0;
sb_resume_dma(dsp, 1);
}
break;
case 0xD8: /* Get speaker status */
sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0);
if (dsp->sb_type >= SB_DSP_200)
sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0);
break;
case 0xD9: /* Exit 16-bit auto-init mode */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
dsp->sb_16_autoinit = 0;
break;
case 0xDA: /* Exit 8-bit auto-init mode */
dsp->sb_8_autoinit = 0;
if (dsp->sb_type >= SB_DSP_200)
dsp->sb_8_autoinit = 0;
break;
case 0xE0: /* DSP identification */
sb_add_data(dsp, ~dsp->sb_data[0]);
@@ -1721,7 +1744,7 @@ sb_exec_command(sb_dsp_t *dsp)
sb_add_data(dsp, dsp->sbe2);
break;
case 0xE3: /* DSP copyright */
if (dsp->sb_type >= SB16) {
if (dsp->sb_type >= SB16_DSP_404) {
c = 0;
while (sb16_copyright[c])
sb_add_data(dsp, sb16_copyright[c++]);
@@ -1782,15 +1805,15 @@ sb_exec_command(sb_dsp_t *dsp)
timer_set_delay_u64(&dsp->irq16_timer, (10ULL * TIMER_USEC));
break;
case 0xF8:
if (dsp->sb_type < SB16)
if (dsp->sb_type < SB16_DSP_404)
sb_add_data(dsp, 0);
break;
case 0xF9: /* SB16 8051 RAM read */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
sb_add_data(dsp, dsp->sb_8051_ram[dsp->sb_data[0]]);
break;
case 0xFA: /* SB16 8051 RAM write */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1];
break;
case 0xFF: /* No, that's not how you program auto-init DMA */
@@ -1800,11 +1823,24 @@ sb_exec_command(sb_dsp_t *dsp)
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
* http://www.synchrondata.com/pheaven/www/area19.htm
* http://www.dcee.net/Files/Programm/Sound/
* 0E3h DSP Copyright SBPro2???
* 0F0h Sine Generator SB
* 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2
* 0F2h IRQ Request, 8-bit SB
* https://github.com/schlae/sb-firmware/blob/master/sbv202.asm
* 008h Halt (Infinate Loop) SB2???
* 018h DMA playback with auto init DMA. SB2???
* 028h Auto-init direct ADC SB2???
* 036h (Timestamp) SB???
* 037h (Timestamp) SB???
* 050h Stops playback of SRAM samples SB???
* 051h Plays back samples stored in SRAM. SB???
* 058h Load data into SRAM SB???
* 059h Fetches the samples and then immediately plays them back. SB???
* 078h Auto-init DMA ADPCM SB2???
* 07Ah 2.6-bit ADPCM SB???
* 0E3h DSP Copyright SBPro2??? (SBPRO2_DSP_302)
* 0F0h Sine Generator SB (SB_DSP_105, DSP20x)
* 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (DSP20x, SBPRO2_DSP_302)
* 0F2h IRQ Request, 8-bit SB (SB_DSP_105, DSP20x)
* 0F3h IRQ Request, 16-bit SB16
* 0F4h Perform ROM checksum SB (SB_DSP_105, DSP20x)
* 0FBh DSP Status SB16
* 0FCh DSP Auxiliary Status SB16
* 0FDh DSP Command Status SB16
@@ -1817,7 +1853,7 @@ sb_exec_command(sb_dsp_t *dsp)
/* Update 8051 ram with the last DSP command.
See https://github.com/joncampbell123/dosbox-x/issues/1044 */
if (dsp->sb_type >= SB16)
if (dsp->sb_type >= SB16_DSP_404)
dsp->sb_8051_ram[0x30] = dsp->sb_command;
}
@@ -1836,31 +1872,31 @@ sb_do_reset(sb_dsp_t *dsp, const uint8_t v)
}
void
sb_write(uint16_t a, uint8_t v, void *priv)
sb_write(uint16_t addr, uint8_t val, void *priv)
{
sb_dsp_t *dsp = (sb_dsp_t *) priv;
sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, a, v);
sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xE)))
a &= 0xfffe;
if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE)))
addr &= 0xfffe;
switch (a & 0xF) {
switch (addr & 0xF) {
case 6: /* Reset */
sb_do_reset(dsp, v);
sb_do_reset(dsp, val);
if (!(v & 2) && (dsp->espcm_fifo_reset & 2)) {
if (!(val & 2) && (dsp->espcm_fifo_reset & 2)) {
fifo_reset(dsp->espcm_fifo);
}
dsp->espcm_fifo_reset = v;
dsp->espcm_fifo_reset = val;
dsp->uart_midi = 0;
dsp->uart_irq = 0;
dsp->onebyte_midi = 0;
return;
case 0xC: /* Command/data write */
if (dsp->uart_midi || dsp->onebyte_midi) {
midi_raw_out_byte(v);
midi_raw_out_byte(val);
dsp->onebyte_midi = 0;
return;
}
@@ -1873,8 +1909,8 @@ sb_write(uint16_t a, uint8_t v, void *priv)
return;
}
if (dsp->sb_data_stat == -1) {
dsp->sb_command = v;
if (v == 0x01)
dsp->sb_command = val;
if (val == 0x01)
sb_add_data(dsp, 0);
dsp->sb_data_stat++;
if (IS_AZTECH(dsp)) {
@@ -1901,7 +1937,7 @@ sb_write(uint16_t a, uint8_t v, void *priv)
}
}
} else {
dsp->sb_data[dsp->sb_data_stat++] = v;
dsp->sb_data[dsp->sb_data_stat++] = val;
}
if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) {
sb_exec_command(dsp);
@@ -1920,17 +1956,17 @@ sb_write(uint16_t a, uint8_t v, void *priv)
}
uint8_t
sb_read(uint16_t a, void *priv)
sb_read(uint16_t addr, void *priv)
{
sb_dsp_t *dsp = (sb_dsp_t *) priv;
uint8_t ret = 0x00;
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xF)))
if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF)))
/* Exception: ESS AudioDrive does not alias port base+0xf */
a &= 0xfffe;
addr &= 0xfffe;
switch (a & 0xf) {
switch (addr & 0xf) {
case 0x6:
if (IS_ESS(dsp)) {
ret = (dsp->espcm_fifo_reset & 0x03) | 0x08 | (dsp->activity & 0xe0);
@@ -1968,7 +2004,7 @@ sb_read(uint16_t a, void *priv)
if (dsp->state == DSP_S_RESET_WAIT)
dsp->state = DSP_S_NORMAL;
if ((dsp->state == DSP_S_NORMAL) || IS_ESS(dsp)) {
if (dsp->sb_8_enable || dsp->sb_type >= SB16)
if (dsp->sb_8_enable || dsp->sb_type >= SB16_DSP_404)
dsp->busy_count = (dsp->busy_count + 1) & 3;
else
dsp->busy_count = 0;
@@ -1993,7 +2029,7 @@ sb_read(uint16_t a, void *priv)
ret = 0x80;
} else {
sb_dsp_log("SB Write Data Creative read 0xff\n");
if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp))
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp))
ret = 0xaa;
else
ret = 0xff;
@@ -2003,7 +2039,7 @@ sb_read(uint16_t a, void *priv)
ret = 0x00;
} else {
sb_dsp_log("SB Write Data Creative read 0x7f\n");
if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp))
if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp))
ret = 0x2a;
else
ret = 0x7f;
@@ -2027,7 +2063,7 @@ sb_read(uint16_t a, void *priv)
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80;
} else {
sb_dsp_log("SB Read Data Creative read %02X\n", (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff);
if ((dsp->sb_type < SB16) && IS_NOT_ESS(dsp))
if ((dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp))
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x2a : 0xaa;
else
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff;
@@ -2138,11 +2174,11 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
/* Default values. Use sb_dsp_setxxx() methods to change. */
dsp->sb_irqnum = 7;
dsp->sb_8_dmanum = 1;
if (type >= SB16)
if (type >= SB16_DSP_404)
dsp->sb_16_dmanum = 5;
else
dsp->sb_16_dmanum = 0xff;
if ((type >= SB16) || IS_ESS(dsp))
if ((type >= SB16_DSP_404) || IS_ESS(dsp))
dsp->sb_16_8_dmanum = 0x1;
dsp->mpu = NULL;
@@ -2174,7 +2210,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
a set frequency command is sent. */
recalc_sb16_filter(0, 3200 * 2);
}
if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2)) {
if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2_DSP_302)) {
/* OPL3 or dual OPL2 is stereo. */
if (dsp->sb_has_real_opl)
recalc_opl_filter(FREQ_49716 * 2);

View File

@@ -4,6 +4,7 @@
#include <wchar.h>
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/nv/vid_nv_rivatimer.h>
uint64_t TIMER_USEC;
uint32_t timer_target;
@@ -168,6 +169,9 @@ timer_init(void)
timer_target = 0ULL;
tsc = 0;
/* Initialise the CPU-independent timer */
rivatimer_init();
timer_inited = 1;
}

View File

@@ -134,9 +134,14 @@ plat_cdrom_get_last_block(void *local)
}
int
plat_cdrom_ext_medium_changed(void *local)
plat_cdrom_ext_medium_changed(UNUSED(void *local))
{
#if 0
dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local;
plat_cdrom_read_toc(ioctl);
#endif
int ret = 0;
dummy_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret);

View File

@@ -27,7 +27,9 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c
vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c
vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c
vid_bochs_vbe.c)
vid_bochs_vbe.c
nv/nv_rivatimer.c
)
if(G100)
target_compile_definitions(vid PRIVATE USE_G100)

274
src/video/nv/nv_rivatimer.c Normal file
View File

@@ -0,0 +1,274 @@
/*
* 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.
*
* Fast, high-frequency, CPU-independent timer.
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
*
* Copyright 2024-2025 starfrost
*/
/* See vid_nv_rivatimer.h comments for rationale behind not using the regular timer system
Notes applicable to this file:
Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot fail so they are not checked.
*/
#include <86box/nv/vid_nv_rivatimer.h>
#ifdef _WIN32
LARGE_INTEGER performance_frequency;
#endif
rivatimer_t* rivatimer_head; // The head of the rivatimer list.
rivatimer_t* rivatimer_tail; // The tail of the rivatimer list.
/* Functions only used in this translation unit */
bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list.
void rivatimer_init(void)
{
// Destroy all the rivatimers.
rivatimer_t* rivatimer_ptr = rivatimer_head;
if (!rivatimer_ptr)
return;
while (rivatimer_ptr)
{
// since we are destroing it
rivatimer_t* old_next = rivatimer_ptr->next;
rivatimer_destroy(rivatimer_ptr);
rivatimer_ptr = old_next;
}
#ifdef _WIN32
// Query the performance frequency.
QueryPerformanceFrequency(&performance_frequency);
#endif
}
// Creates a rivatimer.
rivatimer_t* rivatimer_create(double period, void (*callback)(double real_time))
{
rivatimer_t* new_rivatimer = NULL;
// See i
if (period <= 0
|| !callback)
{
fatal("Invalid rivatimer_create call: period <= 0 or no callback");
}
// If there are no rivatimers, create one
if (!rivatimer_head)
{
rivatimer_head = calloc(1, sizeof(rivatimer_t));
rivatimer_head->prev = NULL; // indicate this is the first in the list even if we don't strictly need to
rivatimer_tail = rivatimer_head;
new_rivatimer = rivatimer_head;
}
else // Otherwise add a new one to the list
{
rivatimer_tail->next = calloc(1, sizeof(rivatimer_t));
rivatimer_tail = rivatimer_tail->next;
new_rivatimer = rivatimer_tail;
}
// sanity check
if (new_rivatimer)
{
new_rivatimer->running = false;
new_rivatimer->period = period;
new_rivatimer->next = NULL; // indicate this is the last in the list
new_rivatimer->callback = callback;
}
return new_rivatimer;
}
// Determines if a rivatimer really exists.
bool rivatimer_really_exists(rivatimer_t* rivatimer)
{
rivatimer_t* current = rivatimer_head;
if (!current)
return false;
while (current)
{
if (current == rivatimer)
return true;
current = current->next;
}
return false;
}
// Destroy a rivatimer.
void rivatimer_destroy(rivatimer_t* rivatimer_ptr)
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place.");
// Case: We are destroying the head
if (rivatimer_ptr == rivatimer_head)
{
// This is the only rivatimer
if (rivatimer_ptr->next == NULL)
{
rivatimer_head = NULL;
rivatimer_tail = NULL;
}
// This is not the only rivatimer
else
{
rivatimer_head = rivatimer_ptr->next;
rivatimer_head->prev = NULL;
// This is the only rivatimer and now there is only one
if (!rivatimer_head->next)
rivatimer_tail = rivatimer_head;
}
}
// Case: We are destroying the tail
else if (rivatimer_ptr == rivatimer_tail)
{
// We already covered the case where there is only one item above
rivatimer_tail = rivatimer_ptr->prev;
rivatimer_tail->next = NULL;
}
// Case: This is not the first or last rivatimer, so we don't need to set the head or tail
else
{
// Fix the break in the chain that this
if (rivatimer_ptr->next)
rivatimer_ptr->prev->next = rivatimer_ptr->next;
if (rivatimer_ptr->prev)
rivatimer_ptr->next->prev = rivatimer_ptr->prev;
}
free(rivatimer_ptr);
rivatimer_ptr = NULL; //explicitly set to null
}
void rivatimer_update_all(void)
{
rivatimer_t* rivatimer_ptr = rivatimer_head;
if (!rivatimer_ptr)
return;
while (rivatimer_ptr)
{
// if it's not running skip it
if (!rivatimer_ptr->running)
{
rivatimer_ptr = rivatimer_ptr->next;
continue;
}
#ifdef _WIN32
LARGE_INTEGER current_time;
QueryPerformanceCounter(&current_time);
double microseconds = ((double)current_time.QuadPart / 1000000.0) - (rivatimer_ptr->starting_time.QuadPart / 1000000.0);
#else
struct timespec current_time;
clock_gettime(CLOCK_REALTIME, &current_time);
double microseconds = ((double)current_time.tv_sec * 1000000.0) + ((double)current_time.tv_nsec / 1000.0);
#endif
rivatimer_ptr->time += microseconds;
// Reset the current time so we can actually restart
#ifdef _WIN32
QueryPerformanceCounter(&rivatimer_ptr->starting_time);
#else
clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time);
#endif
// Time to fire
if (microseconds > rivatimer_ptr->period)
{
if (!rivatimer_ptr->callback)
{
pclog("Eh? No callback in RivaTimer?");
continue;
}
rivatimer_ptr->callback(microseconds);
}
rivatimer_ptr = rivatimer_ptr->next;
}
}
void rivatimer_start(rivatimer_t* rivatimer_ptr)
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place.");
if (rivatimer_ptr->period <= 0)
fatal("rivatimer_start: Zero period!");
rivatimer_ptr->running = true;
// Start off so rivatimer_update_all can actually update.
#ifdef _WIN32
QueryPerformanceCounter(&rivatimer_ptr->starting_time);
#else
clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time);
#endif
}
void rivatimer_stop(rivatimer_t* rivatimer_ptr)
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place.");
rivatimer_ptr->running = false;
rivatimer_ptr->time = 0;
}
// Get the current time value of a rivatimer
double rivatimer_get_time(rivatimer_t* rivatimer_ptr)
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place.");
return rivatimer_ptr->time;
}
void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)(double real_time))
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place.");
if (!callback)
fatal("rivatimer_set_callback: No callback!");
rivatimer_ptr->callback = callback;
}
void rivatimer_set_period(rivatimer_t* rivatimer_ptr, double period)
{
if (!rivatimer_really_exists(rivatimer_ptr))
fatal("rivatimer_set_period: The timer has been destroyed, or never existed in the first place.");
rivatimer_ptr->period = period;
}

View File

@@ -43,6 +43,11 @@
#include <86box/vid_ati_mach8.h>
#include "cpu.h"
#ifdef CLAMP
# undef CLAMP
#endif
#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_4k.BIN"
static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv);
@@ -68,6 +73,17 @@ ibm8514_log(const char *fmt, ...)
# define ibm8514_log(fmt, ...)
#endif
static int16_t
CLAMP(int16_t in, int16_t min, int16_t max)
{
if (in < min)
return min;
if (in > max)
return max;
return in;
}
#define WRITE8(addr, var, val) \
switch ((addr) & 1) { \
case 0: \
@@ -416,14 +432,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
if (len == 2) {
dev->accel.short_stroke = val;
dev->accel.cx = dev->accel.cur_x;
if (dev->accel.cur_x >= 0x600)
dev->accel.cx |= ~0x5ff;
dev->accel.cy = dev->accel.cur_y;
if (dev->accel.cur_y >= 0x600)
dev->accel.cy |= ~0x5ff;
if (dev->accel.cmd & 0x1000) {
ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len);
ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len);
@@ -969,6 +977,7 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t
dev->accel.ssv_len = ssv & 0x0f;
dev->accel.ssv_dir = ssv & 0xe0;
dev->accel.ssv_draw = ssv & 0x10;
dev->accel.ssv_len_back = dev->accel.ssv_len;
if (ibm8514_cpu_src(svga)) {
dev->data_available = 0;
@@ -1006,6 +1015,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
uint16_t bkgd_color = dev->accel.bkgd_color;
uint32_t old_mix_dat;
int and3 = dev->accel.cur_x & 3;
int poly_src;
if (!dev->bpp) {
compare &= 0xff;
@@ -1121,13 +1131,24 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
old_mix_dat = mix_dat;
if (cmd == 5 || cmd == 1 || (cmd == 2 && (dev->accel.multifunc[0x0a] & 0x06)))
ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06);
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
the NOP command)*/
switch (cmd) {
case 0: /*NOP (Short Stroke Vectors)*/
if (dev->accel.ssv_state == 0)
if (dev->accel.ssv_state == 0) {
dev->accel.cx = dev->accel.cur_x;
if (dev->accel.cur_x >= 0x600)
dev->accel.cx |= ~0x5ff;
dev->accel.cy = dev->accel.cur_y;
if (dev->accel.cur_y >= 0x600)
dev->accel.cy |= ~0x5ff;
break;
}
if (dev->accel.cmd & 0x08) {
while (count-- && dev->accel.ssv_len >= 0) {
@@ -1289,7 +1310,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cy--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.ssv_len_back) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x20)
dev->accel.cx++;
@@ -1303,7 +1324,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cx--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.ssv_len_back) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x80)
dev->accel.cy++;
@@ -1454,6 +1475,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (!dev->accel.sy) {
dev->accel.cmd_back = 1;
if (!cpu_input) {
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
}
break;
}
@@ -1505,8 +1530,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.sy--;
}
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
dev->accel.x_count = 0;
dev->accel.output = 0;
} else { /*Bresenham Line*/
@@ -1580,7 +1603,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cy--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x20)
dev->accel.cx++;
@@ -1594,7 +1617,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cx--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x80)
dev->accel.cy++;
@@ -1673,6 +1696,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (!dev->accel.sy) {
dev->accel.cmd_back = 1;
if (!cpu_input) {
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
}
break;
}
@@ -1682,7 +1709,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cy--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x20)
dev->accel.cx++;
@@ -1696,7 +1723,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
else
dev->accel.cx--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x80)
dev->accel.cy++;
@@ -1709,8 +1736,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
dev->accel.sy--;
}
}
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
}
break;
@@ -2283,35 +2308,62 @@ skip_nibble_rect_write:
}
}
} else if ((dev->accel.multifunc[0x0a] & 0x06) == 0x04) { /*Polygon Draw Type A*/
ibm8514_log("Polygon Draw Type A: Clipping: L=%d, R=%d, T=%d, B=%d, C(%d,%d), sx=%d, sy=%d.\n", clip_l, clip_r, clip_t, clip_b, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy);
while (count-- && (dev->accel.sy >= 0)) {
if ((dev->accel.cx >= clip_l) &&
(dev->accel.cx <= clip_r) &&
(dev->accel.cy >= clip_t) &&
(dev->accel.cy <= clip_b)) {
READ(dev->accel.dest + dev->accel.cx, mix_dat);
if ((mix_dat & rd_mask_polygon) == rd_mask_polygon)
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
case 0:
src_dat = bkgd_color;
break;
case 1:
src_dat = frgd_color;
break;
case 2:
case 3:
src_dat = 0;
break;
default:
break;
}
READ(dev->accel.dest + dev->accel.cx, poly_src);
if ((poly_src & rd_mask_polygon) == rd_mask_polygon)
dev->accel.fill_state ^= 1;
READ(dev->accel.dest + dev->accel.cx, dest_dat);
old_dest_dat = dest_dat;
if (dev->accel.fill_state) {
if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) {
MIX(mix_dat ^ rd_mask_polygon, dest_dat, mix_dat);
ibm8514_log("Filling c(%d,%d) without bit 0 of rdmask=%02x, wrtmask=%02x, mixdat=%02x, dest=%02x, old=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, old_dest_dat);
dest_dat &= ~rd_mask_polygon;
} else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) {
ibm8514_log("Filling c(%d,%d) with bit 0 of rdmask=%02x, wrtmask=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask);
dest_dat &= ~(rd_mask_polygon & wrt_mask);
if (rd_mask_polygon & 0x01) {
if (wrt_mask & 0x01) {
dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State On, Write Mask 1, Read Mask 1.*/
dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask);
}
} else {
if (wrt_mask & 0x01) {
MIX(mix_dat & mix_mask, dest_dat, src_dat);
dest_dat &= ~rd_mask_polygon; /*Fill State On, Write Mask 1, Read Mask 0.*/
dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask);
}
}
} else {
if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01))
dest_dat &= ~rd_mask_polygon;
else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01))
dest_dat &= ~(rd_mask_polygon & wrt_mask);
if (rd_mask_polygon & 0x01) {
if (wrt_mask & 0x01) {
dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State Off, Write Mask 1, Read Mask 1.*/
dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask);
}
} else {
if (wrt_mask & 0x01) {
dest_dat &= ~rd_mask_polygon; /*Fill State Off, Write Mask 1, Read Mask 0.*/
dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask);
}
}
}
dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask);
if ((compare_mode == 0) ||
((compare_mode == 0x10) && (dest_dat >= compare)) ||
((compare_mode == 0x18) && (dest_dat < compare)) ||
@@ -2322,7 +2374,11 @@ skip_nibble_rect_write:
ibm8514_log("Results c(%d,%d):rdmask=%02x, wrtmask=%02x, mix=%02x, destdat=%02x, nowrite=%d.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, dev->accel.cx_back);
WRITE(dev->accel.dest + dev->accel.cx, dest_dat);
}
}
} else
ibm8514_log("Out of bounds DrawA C(%d,%d).\n", dev->accel.cx, dev->accel.cy);
mix_dat <<= 1;
mix_dat |= 1;
if (dev->accel.cmd & 0x20)
dev->accel.cx++;
@@ -2356,6 +2412,8 @@ skip_nibble_rect_write:
if (dev->accel.sy < 0) {
ibm8514_log(".\n");
dev->accel.cmd_back = 1;
dev->accel.cur_x = dev->accel.cx;
dev->accel.cur_y = dev->accel.cy;
return;
}
}
@@ -2468,7 +2526,7 @@ skip_nibble_rect_write:
else
dev->accel.oldcy = dev->accel.cy - 1;
ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.clip_top, clip_b, dev->accel.multifunc[0x0a]);
ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, clip_l, clip_r, clip_t, clip_b, dev->accel.multifunc[0x0a]);
if (ibm8514_cpu_src(svga)) {
dev->data_available = 0;
@@ -2483,8 +2541,7 @@ skip_nibble_rect_write:
if (dev->accel.cmd & 0x08) { /*Vectored Boundary Line*/
while (count-- && (dev->accel.sy >= 0)) {
if (dev->accel.cx < clip_l)
dev->accel.cx = clip_l;
dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r);
if ((dev->accel.cx >= clip_l) &&
(dev->accel.cx <= clip_r) &&
@@ -2591,11 +2648,10 @@ skip_nibble_rect_write:
}
} else { /*Vectored Bresenham*/
while (count-- && (dev->accel.sy >= 0)) {
if (dev->accel.cx < clip_l)
dev->accel.cx = clip_l;
dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r);
if ((dev->accel.cx >= clip_l) &&
(dev->accel.cx <= clip_r) &&
(dev->accel.cx < clip_r) &&
(dev->accel.cy >= clip_t) &&
(dev->accel.cy <= clip_b)) {
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
@@ -2658,7 +2714,7 @@ skip_nibble_rect_write:
else
dev->accel.cy--;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x20)
dev->accel.cx++;
@@ -2673,7 +2729,7 @@ skip_nibble_rect_write:
dev->accel.cx--;
dev->accel.oldcy = dev->accel.cy;
if (dev->accel.err_term >= 0) {
if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) {
dev->accel.err_term += dev->accel.destx_distp;
if (dev->accel.cmd & 0x80)
dev->accel.cy++;

View File

@@ -1361,7 +1361,7 @@ gd54xx_in(uint16_t addr, void *priv)
32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width
for 2M of memory
*/
ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18;
ret |= 0x18;
break;
case 4096:
ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/
@@ -2281,6 +2281,9 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv)
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest &&
!(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY))
val = (val >> 8) | (val << 8);
gd54xx_write(addr, val, gd54xx);
gd54xx_write(addr + 1, val >> 8, gd54xx);
return;
@@ -2308,6 +2311,9 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv)
if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest &&
!(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) {
if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY))
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
gd54xx_write(addr, val, gd54xx);
gd54xx_write(addr + 1, val >> 8, gd54xx);
gd54xx_write(addr + 2, val >> 16, gd54xx);
@@ -3661,9 +3667,6 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count)
mask_shift = 31 - byte_pos;
if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND))
cpu_dat >>= byte_pos;
else if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
cpu_dat = ((cpu_dat & 0xff000000) >> 24) | ((cpu_dat & 0x00ff0000) >> 8) |
((cpu_dat & 0x0000ff00) << 8) | ((cpu_dat & 0x000000ff) << 24);
} else
mask_shift = 7;

View File

@@ -548,17 +548,20 @@ et3000_available(void)
}
static const device_config_t et3000_config[] = {
{ .name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{ .description = "256 KB",
.value = 256 },
{ .description = "512 KB",
.value = 512 },
{ .description = "" } } },
// clang-format off
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{ .description = "256 KB", .value = 256 },
{ .description = "512 KB", .value = 512 },
{ .description = "" }
}
},
{ .type = CONFIG_END }
// clang-format on
};
const device_t et3000_isa_device = {

View File

@@ -972,7 +972,7 @@ static const device_config_t et4000_tc6058af_config[] = {
.default_string = "v1_10",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Version 1.10", .internal_name = "v1_10", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 32768, .files = { TC6058AF_BIOS_ROM_PATH, "" } },
@@ -1019,7 +1019,7 @@ static const device_config_t et4000_bios_config[] = {
.default_string = "v8_01",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.spinner = { 0 },
.bios = {
{ .name = "Version 8.01", .internal_name = "v8_01", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 32768, .files = { BIOS_ROM_PATH, "" } },

View File

@@ -1701,52 +1701,37 @@ ht216_force_redraw(void *priv)
ht216->svga.fullchange = changeframecount;
}
// clang-format off
static const device_config_t v7_vga_1024i_config[] = {
{ .name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{ .description = "256 KB",
.value = 256 },
{ .description = "512 KB",
.value = 512 },
{ .description = "" } } },
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{ .description = "256 KB", .value = 256 },
{ .description = "512 KB", .value = 512 },
{ .description = "" }
}
},
{ .type = CONFIG_END }
};
// clang-format off
static const device_config_t ht216_32_standalone_config[] = {
{
.name = "monitor_type",
.name = "monitor_type",
.description = "Monitor type",
.type = CONFIG_SELECTION,
.type = CONFIG_SELECTION,
.default_int = 0x18,
.selection = {
{
.description = "Mono Interlaced",
.value = 0x00
},
{
.description = "Mono Non-Interlaced",
.value = 0x08
},
{
.description = "Color Interlaced",
.value = 0x10
},
{
.description = "Color Non-Interlaced",
.value = 0x18
},
{
.description = ""
}
.selection = {
{ .description = "Mono Interlaced", .value = 0x00 },
{ .description = "Mono Non-Interlaced", .value = 0x08 },
{ .description = "Color Interlaced", .value = 0x10 },
{ .description = "Color Non-Interlaced", .value = 0x18 },
{ .description = "" }
}
},
{
.type = CONFIG_END
}
{ .type = CONFIG_END }
};
// clang-format on

View File

@@ -6851,8 +6851,7 @@ static const device_config_t mystique_config[] = {
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.selection =
{
.selection = {
{
.description = "2 MB",
.value = 2
@@ -6865,15 +6864,11 @@ static const device_config_t mystique_config[] = {
.description = "8 MB",
.value = 8
},
{
.description = ""
}
{ .description = "" }
},
.default_int = 8
},
{
.type = CONFIG_END
}
{ .type = CONFIG_END }
// clang-format on
};
@@ -6883,8 +6878,7 @@ static const device_config_t millennium_ii_config[] = {
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.selection =
{
.selection = {
{
.description = "4 MB",
.value = 4
@@ -6897,15 +6891,11 @@ static const device_config_t millennium_ii_config[] = {
.description = "16 MB",
.value = 16
},
{
.description = ""
}
{ .description = "" }
},
.default_int = 8
},
{
.type = CONFIG_END
}
{ .type = CONFIG_END }
// clang-format on
};

View File

@@ -273,6 +273,7 @@ typedef struct s3_t {
int dat_count;
int b2e8_pix, temp_cnt;
int ssv_len;
int ssv_len_back;
uint8_t ssv_dir;
uint8_t ssv_draw;
uint8_t dat_buf_16bit;
@@ -511,7 +512,7 @@ s3_update_irqs(s3_t *s3)
}
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv);
void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv);
void s3_short_stroke_start(s3_t *s3, uint8_t ssv);
static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3);
#define WRITE8(addr, var, val) \
@@ -922,15 +923,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8);
s3->accel.ssv_state = 1;
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
if (s3->accel.cmd & 0x1000) {
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
} else {
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
}
break;
@@ -1787,15 +1785,12 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
s3->accel.short_stroke = val;
s3->accel.ssv_state = 1;
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
if (s3->accel.cmd & 0x1000) {
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
} else {
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff);
s3_short_stroke_start(s3, s3->accel.short_stroke >> 8);
s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff);
}
}
}
@@ -7823,19 +7818,16 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3)
}
void
s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv)
s3_short_stroke_start(s3_t *s3, uint8_t ssv)
{
if (!cpu_input) {
s3->accel.ssv_len = ssv & 0x0f;
s3->accel.ssv_dir = ssv & 0xe0;
s3->accel.ssv_draw = ssv & 0x10;
s3->accel.ssv_len = ssv & 0x0f;
s3->accel.ssv_dir = ssv & 0xe0;
s3->accel.ssv_draw = !!(ssv & 0x10);
if (s3_cpu_src(s3)) {
return; /*Wait for data from CPU*/
}
}
if (s3_cpu_src(s3))
return; /*Wait for data from CPU*/
s3->accel_start(count, cpu_input, mix_dat, cpu_dat, s3);
s3->accel_start(-1, 0, -1, 0, s3);
}
void
@@ -7978,11 +7970,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
switch (cmd) {
case 0: /*NOP (Short Stroke Vectors)*/
if (s3->accel.ssv_state == 0)
if (s3->accel.ssv_state == 0) {
s3->accel.cx = s3->accel.cur_x & 0xfff;
s3->accel.cy = s3->accel.cur_y & 0xfff;
break;
}
if (s3->accel.cmd & 0x08) /*Radial*/
{
if (s3->accel.cmd & 0x08) { /*Radial*/
while (count-- && s3->accel.ssv_len >= 0) {
if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) {
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) {
@@ -8036,8 +8030,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
else
cpu_dat >>= 16;
if (!s3->accel.ssv_len)
if (!s3->accel.ssv_len) {
s3->accel.cur_x = s3->accel.cx & 0xfff;
s3->accel.cur_y = s3->accel.cy & 0xfff;
break;
}
switch (s3->accel.ssv_dir & 0xe0) {
case 0x00:
@@ -8077,9 +8074,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
s3->accel.cx &= 0xfff;
s3->accel.cy &= 0xfff;
}
s3->accel.cur_x = s3->accel.cx & 0xfff;
s3->accel.cur_y = s3->accel.cy & 0xfff;
}
break;
@@ -8270,7 +8264,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
else
s3->accel.cy--;
if (s3->accel.err_term >= 0) {
if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) {
s3->accel.err_term += s3->accel.destx_distp;
if (s3->accel.cmd & 0x20)
s3->accel.cx++;
@@ -8284,7 +8278,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
else
s3->accel.cx--;
if (s3->accel.err_term >= 0) {
if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) {
s3->accel.err_term += s3->accel.destx_distp;
if (s3->accel.cmd & 0x80)
s3->accel.cy++;