This commit is contained in:
MaxwellS04
2025-06-30 00:44:17 +07:00
255 changed files with 12167 additions and 1852 deletions

View File

@@ -69,7 +69,6 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
sdl2
rtmidi
openal-soft
@@ -162,12 +161,12 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
sdl2
rtmidi
openal-soft
fluidsynth
libslirp
vde
libserialport
${{ matrix.ui.packages }}

View File

@@ -3,9 +3,7 @@ name: CodeQL Analysis (Linux)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -16,6 +14,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
@@ -26,6 +25,9 @@ on:
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-linux:

View File

@@ -3,9 +3,7 @@ name: CodeQL Analysis (macos)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -16,6 +14,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
@@ -26,6 +25,9 @@ on:
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-macos13-x86_64:

View File

@@ -3,9 +3,7 @@ name: CodeQL Analysis (Windows, msys2)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -16,6 +14,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -26,6 +25,9 @@ on:
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-msys2:

View File

@@ -137,6 +137,7 @@ option(GDBSTUB "Enable GDB stub server for debugging"
option(DEV_BRANCH "Development branch" OFF)
option(DISCORD "Discord Rich Presence support" ON)
option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF)
option(LIBASAN "Enable compilation with the addresss sanitizer" OFF)
if((ARCH STREQUAL "arm64") OR (ARCH STREQUAL "arm"))
set(NEW_DYNAREC ON)
@@ -223,4 +224,10 @@ if(NOT EMU_COPYRIGHT_YEAR)
set(EMU_COPYRIGHT_YEAR 2024)
endif()
# Libasan
if(LIBASAN)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
add_subdirectory(src)

View File

@@ -253,6 +253,8 @@ struct accelKey def_acc_keys[NUM_ACCELS] = {
.seq="Ctrl+Alt+M" }
};
char vmm_path[1024] = { '\0'}; /* TEMPORARY - VM manager path to scan for VMs */
int vmm_enabled = 0;
/* Statistics. */
extern int mmuflush;
@@ -600,8 +602,8 @@ pc_show_usage(char *s)
#ifdef _WIN32
"-D or --debug\t\t\t- force debug output logging\n"
#endif
#if 0
"-E or --nographic\t\t- forces the old behavior\n"
#if 1
"-E or --vmmpath\t\t- vm manager path\n"
#endif
"-F or --fullscreen\t\t- start in fullscreen mode\n"
"-G or --lang langid\t\t- start with specified language\n"
@@ -637,7 +639,7 @@ pc_show_usage(char *s)
ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p);
#else
if (s == NULL)
pclog(p);
pclog("%s", p);
else
ui_msgbox(MBX_ANSI | MBX_WARNING, p);
#endif
@@ -734,13 +736,18 @@ usage:
} else if (!strcasecmp(argv[c], "--debug") || !strcasecmp(argv[c], "-D")) {
force_debug = 1;
#endif
#ifdef ENABLE_NG
} else if (!strcasecmp(argv[c], "--nographic") || !strcasecmp(argv[c], "-E")) {
/* Currently does nothing, but if/when we implement a built-in manager,
it's going to force the manager not to run, allowing the old usage
without parameter. */
ng = 1;
#endif
//#ifdef ENABLE_NG
} else if (!strcasecmp(argv[c], "--vmmpath") ||
!strcasecmp(argv[c], "-E")) {
/* Using this variable for vm manager path
Temporary solution!*/
if ((c+1) == argc) goto usage;
char *vp = argv[++c];
if ((strlen(vp) + 1) >= sizeof(vmm_path))
memcpy(vmm_path, vp, sizeof(vmm_path));
else
memcpy(vmm_path, vp, strlen(vp) + 1);
//#endif
} else if (!strcasecmp(argv[c], "--fullscreen") || !strcasecmp(argv[c], "-F")) {
start_in_fullscreen = 1;
} else if (!strcasecmp(argv[c], "--logfile") || !strcasecmp(argv[c], "-L")) {
@@ -775,7 +782,11 @@ usage:
goto usage;
temp2 = (char *) calloc(2048, 1);
sscanf(argv[++c], "%c:%s", &drive, temp2);
if (sscanf(argv[++c], "%c:%2047s", &drive, temp2) != 2) {
fprintf(stderr, "Invalid input format for --image option.\n");
free(temp2);
goto usage;
}
if (drive > 0x40)
drive = (drive & 0x1f) - 1;
else
@@ -1014,9 +1025,21 @@ usage:
* This is where we start outputting to the log file,
* if there is one. Create a little info header first.
*/
struct tm time_buf;
(void) time(&now);
info = localtime(&now);
strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info);
#ifdef _WIN32
if (localtime_s(&time_buf, &now) == 0)
info = &time_buf;
#else
info = localtime_r(&now, &time_buf);
#endif
if (info)
strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info);
else
strcpy(temp, "unknown");
pclog("#\n# %ls v%ls logfile, created %s\n#\n",
EMU_NAME_W, EMU_VERSION_FULL_W, temp);
pclog("# VM: %s\n#\n", vm_name);
@@ -1027,6 +1050,10 @@ usage:
}
pclog("# Configuration file: %s\n#\n\n", cfg_path);
if (strlen(vmm_path) != 0) {
vmm_enabled = 1;
pclog("# VM Manager enabled. Path: %s\n", vmm_path);
}
/*
* We are about to read the configuration file, which MAY
* put data into global variables (the hard- and floppy
@@ -1645,6 +1672,10 @@ pc_close(UNUSED(thread_t *ptr))
scsi_disk_close();
gdbstub_close();
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
mem_free();
#endif
}
#ifdef __APPLE__

View File

@@ -446,24 +446,36 @@ static int
viso_fill_time(uint8_t *data, time_t time, int format, int longform)
{
uint8_t *p = data;
struct tm *time_s = localtime(&time);
if (!time_s) {
/* localtime will return NULL if the time_t is negative (Windows)
or way too far into 64-bit space (Linux). Fall back to epoch. */
time_t epoch = 0;
time_s = localtime(&epoch);
if (UNLIKELY(!time_s))
fatal("VISO: localtime(0) = NULL\n");
struct tm time_s_buf;
struct tm *time_s = NULL;
time_t epoch = 0;
/* Force year clamping if the timestamp is known to be outside the supported ranges. */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &time) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&time, &time_s_buf);
#endif
if (!time_s) {
/* localtime may return NULL if time is negative or out of range */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &epoch) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&epoch, &time_s_buf);
#endif
if (!time_s)
fatal("VISO: localtime fallback to epoch failed\n");
/* Force year clamping for out-of-range times */
if (time < (longform ? -62135596800LL : -2208988800LL)) /* 0001-01-01 00:00:00 : 1900-01-01 00:00:00 */
time_s->tm_year = -1901;
else if (time > (longform ? 253402300799LL : 5869583999LL)) /* 9999-12-31 23:59:59 : 2155-12-31 23:59:59 */
time_s->tm_year = 8100;
}
/* Clamp year to the supported ranges, and assume the
OS returns valid numbers in the other struct fields. */
/* Clamp year within supported ranges */
if (time_s->tm_year < (longform ? -1900 : 0)) {
time_s->tm_year = longform ? -1900 : 0;
time_s->tm_mon = time_s->tm_hour = time_s->tm_min = time_s->tm_sec = 0;
@@ -476,18 +488,18 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
time_s->tm_min = time_s->tm_sec = 59;
}
/* Convert timestamp. */
/* Convert timestamp */
if (longform) {
p += sprintf((char *) p, "%04u%02u%02u%02u%02u%02u00",
1900 + time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
p += sprintf((char *)p, "%04u%02u%02u%02u%02u%02u00",
1900 + (unsigned)time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
time_s->tm_hour, time_s->tm_min, time_s->tm_sec);
} else {
*p++ = time_s->tm_year; /* year since 1900 */
*p++ = 1 + time_s->tm_mon; /* month */
*p++ = time_s->tm_mday; /* day */
*p++ = time_s->tm_hour; /* hour */
*p++ = time_s->tm_min; /* minute */
*p++ = time_s->tm_sec; /* second */
*p++ = (uint8_t)time_s->tm_year; /* year since 1900 */
*p++ = (uint8_t)(1 + time_s->tm_mon); /* month */
*p++ = (uint8_t)time_s->tm_mday; /* day */
*p++ = (uint8_t)time_s->tm_hour; /* hour */
*p++ = (uint8_t)time_s->tm_min; /* minute */
*p++ = (uint8_t)time_s->tm_sec; /* second */
}
if (format & VISO_FORMAT_ISO)
*p++ = tz_offset; /* timezone (ISO only) */
@@ -1034,8 +1046,15 @@ next_dir:
the timezone offset for descriptors and file times to use. */
tzset();
time_t now = time(NULL);
if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
struct tm now_tm;
if (viso->format & VISO_FORMAT_ISO) { /* timezones are ISO only */
#ifdef _WIN32
gmtime_s(&now_tm, &now); // Windows: output first param, input second
#else
gmtime_r(&now, &now_tm); // POSIX: input first param, output second
#endif
tz_offset = (now - mktime(&now_tm)) / (3600 / 4);
}
/* Get root directory basename for the volume ID. */
const char *basename = path_get_filename(viso->root_dir->path);

View File

@@ -17,6 +17,7 @@
add_library(chipset OBJECT
82c100.c
acc2036.c
acc2168.c
cs8220.c
cs8230.c
@@ -48,6 +49,7 @@ add_library(chipset OBJECT
opti291.c
opti391.c
opti495.c
opti498.c
opti499.c
opti602.c
opti822.c

346
src/chipset/acc2036.c Normal file
View File

@@ -0,0 +1,346 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the ACC 2036 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/port_92.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/chipset.h>
typedef struct {
uint32_t virt;
uint32_t phys;
mem_mapping_t mapping;
} ram_page_t;
typedef struct {
uint8_t reg;
uint8_t regs[32];
ram_page_t ram_mid_pages[24];
ram_page_t ems_pages[4];
} acc2036_t;
static uint8_t
acc2036_mem_read(uint32_t addr, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
uint8_t ret = 0xff;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ret = ram[addr];
return ret;
}
static uint16_t
acc2036_mem_readw(uint32_t addr, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
uint16_t ret = 0xffff;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ret = *(uint16_t *) &(ram[addr]);
return ret;
}
static void
acc2036_mem_write(uint32_t addr, uint8_t val, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ram[addr] = val;
}
static void
acc2036_mem_writew(uint32_t addr, uint16_t val, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
*(uint16_t *) &(ram[addr]) = val;
}
static void
acc2036_recalc(acc2036_t *dev)
{
uint32_t ems_bases[4] = { 0x000c0000, 0x000c8000, 0x000d0000, 0x000e0000 };
int start_i = (ems_bases[dev->regs[0x0c] & 0x03] - 0x000a0000) >> 14;
int end_i = start_i + 3;
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
mem_mapping_disable(&rp->mapping);
}
for (int i = 0; i < 4; i++) {
ram_page_t *ep = &dev->ems_pages[i];
mem_mapping_disable(&ep->mapping);
}
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
if ((dev->regs[0x03] & 0x08) && (i >= start_i) && (i <= end_i)) {
/* EMS */
ram_page_t *ep = &dev->ems_pages[i - start_i];
mem_mapping_disable(&rp->mapping);
mem_mapping_set_addr(&ep->mapping, ep->virt, 0x000040000);
mem_mapping_set_exec(&ep->mapping, ram + ep->phys);
mem_set_mem_state_both(ep->virt, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
int master_write;
int master_read;
int bit;
int ew_flag;
int er_flag;
int flags;
uint8_t val;
mem_mapping_set_addr(&rp->mapping, rp->virt, 0x000040000);
mem_mapping_set_exec(&rp->mapping, ram + rp->phys);
if ((i >= 8) && (i <= 15)) {
/* 0C0000-0DFFFF */
master_write = dev->regs[0x02] & 0x08;
master_read = dev->regs[0x02] & 0x04;
bit = ((i - 8) >> 1);
val = dev->regs[0x0d] & (1 << bit);
if (i >= 12) {
ew_flag = (dev->regs[0x07] & 0x80) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x07] & 0x80) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
} else {
ew_flag = (dev->regs[0x07] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x07] & 0x40) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
}
flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag;
flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag;
mem_set_mem_state_both(rp->virt, 0x00004000, flags);
} else if (i > 15) {
/* 0E0000-0FFFFF */
master_write = dev->regs[0x02] & 0x02;
master_read = dev->regs[0x02] & 0x01;
bit = ((i - 8) >> 2);
val = dev->regs[0x0c] & (1 << bit);
if (i >= 20) {
ew_flag = MEM_WRITE_EXTANY;
er_flag = MEM_READ_EXTANY;
} else {
ew_flag = (dev->regs[0x0c] & 0x10) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x0c] & 0x10) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
}
flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag;
flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag;
mem_set_mem_state_both(rp->virt, 0x00004000, flags);
}
}
}
if (dev->regs[0x00] & 0x40)
mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
for (int i = 0x01; i <= 0x06; i++) {
uint32_t base = 0x00fe0000 - (i * 0x00010000);
if (dev->regs[i] & 0x40)
mem_set_mem_state_both(base, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(base, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
if (dev->regs[i] & 0x80)
mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
mem_remap_top(0);
if (dev->regs[0x03] & 0x10) {
if (dev->regs[0x02] & 0x0c)
mem_remap_top(128);
else if (dev->regs[0x02] & 0x03)
mem_remap_top(256);
else
mem_remap_top(384);
}
flushmmucache_nopc();
}
static uint8_t
acc2036_in(uint16_t port, void *priv) {
acc2036_t *dev = (acc2036_t *) priv;
uint8_t reg = dev->reg - 0x20;
uint8_t ret = 0xff;
if (port & 0x0001) switch (dev->reg) {
default:
break;
case 0x20 ... 0x2e:
case 0x31 ... 0x3f:
ret = dev->regs[reg];
break;
} else
ret = dev->reg;
return ret;
}
static void
acc2036_out(uint16_t port, uint8_t val, void *priv) {
acc2036_t *dev = (acc2036_t *) priv;
uint8_t reg = dev->reg - 0x20;
if (port & 0x0001) switch (dev->reg) {
default:
break;
case 0x20 ... 0x23:
dev->regs[reg] = val;
acc2036_recalc(dev);
break;
case 0x24 ... 0x2b:
dev->regs[reg] = val;
dev->ems_pages[(reg - 0x04) >> 1].phys = ((dev->regs[reg & 0xfe] & 0x1f) << 19) |
((dev->regs[reg | 0x01] & 0x1f) << 14);
acc2036_recalc(dev);
break;
case 0x2c: case 0x2d:
dev->regs[reg] = val;
acc2036_recalc(dev);
break;
case 0x2e:
dev->regs[reg] = val | 0x10;
break;
case 0x31:
dev->regs[reg] = val;
mem_a20_alt = (val & 0x01);
mem_a20_recalc();
flushmmucache();
if (val & 0x02) {
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
}
break;
case 0x32 ... 0x3f:
dev->regs[reg] = val;
break;
} else
dev->reg = val;
}
static void
acc2036_close(void *priv)
{
acc2036_t *dev = (acc2036_t *) priv;
free(dev);
}
static void *
acc2036_init(UNUSED(const device_t *info))
{
acc2036_t *dev = (acc2036_t *) calloc(1, sizeof(acc2036_t));
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
rp->virt = 0x000a0000 + (i << 14);
rp->phys = 0x000a0000 + (i << 14);
mem_mapping_add(&rp->mapping, rp->virt, 0x00004000,
acc2036_mem_read, acc2036_mem_readw, NULL,
acc2036_mem_write, acc2036_mem_writew, NULL,
ram + rp->phys, MEM_MAPPING_INTERNAL, rp);
}
for (int i = 0; i < 4; i++) {
ram_page_t *ep = &dev->ems_pages[i];
ep->virt = 0x000d0000 + (i << 14);
ep->phys = 0x00000000 + (i << 14);
mem_mapping_add(&ep->mapping, ep->virt, 0x00004000,
acc2036_mem_read, acc2036_mem_readw, NULL,
acc2036_mem_write, acc2036_mem_writew, NULL,
ram + ep->phys, MEM_MAPPING_INTERNAL, ep);
mem_mapping_disable(&ep->mapping);
}
mem_mapping_disable(&ram_mid_mapping);
dev->regs[0x00] = 0x02;
dev->regs[0x0e] = 0x10;
dev->regs[0x11] = 0x01;
dev->regs[0x13] = 0x40;
dev->regs[0x15] = 0x40;
dev->regs[0x17] = 0x40;
dev->regs[0x19] = 0x40;
dev->regs[0x1b] = 0x40;
dev->regs[0x1c] = 0x22;
dev->regs[0x1d] = 0xc4;
dev->regs[0x1f] = 0x30;
acc2036_recalc(dev);
mem_a20_alt = 0x01;
mem_a20_recalc();
flushmmucache();
io_sethandler(0x00f2, 0x0002,
acc2036_in, NULL, NULL, acc2036_out, NULL, NULL, dev);
device_add(&port_92_device);
return dev;
}
const device_t acc2036_device = {
.name = "ACC 2036",
.internal_name = "acc2036",
.flags = 0,
.local = 0,
.init = acc2036_init,
.close = acc2036_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -16,6 +16,7 @@
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -158,7 +159,20 @@ opti283_shadow_recalc(opti283_t *dev)
rom = dev->regs[0x11] & (1 << ((i >> 2) + 4));
opti283_log("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4)));
if (sh_enable && rom) {
if (sh_copy) {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else if (sh_enable && rom) {
if (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
@@ -171,13 +185,8 @@ opti283_shadow_recalc(opti283_t *dev)
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (sh_copy) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_EXTERNAL\n", base, base + 0x3fff);
}
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else {
if (base >= 0xe0000) {
@@ -239,9 +248,21 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
dev->regs[dev->index] = (dev->regs[dev->index] & 0x80) | (val & 0x7f);
break;
case 0x14:
case 0x14: {
double bus_clk;
switch (val & 0x01) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !!(val & 0x40);
fallthrough;
}
case 0x11:
case 0x12:
case 0x13:
@@ -310,6 +331,8 @@ opti283_init(UNUSED(const device_t *info))
opti283_shadow_recalc(dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
device_add(&port_92_device);
return dev;

View File

@@ -8,14 +8,13 @@
*
* Implementation of the OPTi 82C493/82C495 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -28,6 +27,7 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
@@ -166,6 +166,27 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
case 0x26:
opti495_recalc(dev);
break;
case 0x25: {
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 4.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 3.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * 2.0) / 5.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
}
}
@@ -259,6 +280,8 @@ opti495_init(const device_t *info)
io_sethandler(0x00e1, 0x0002, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
return dev;
}
@@ -276,11 +299,25 @@ const device_t opti493_device = {
.config = NULL
};
const device_t opti495_device = {
const device_t opti495slc_device = {
.name = "OPTi 82C495",
.internal_name = "opti495",
.internal_name = "opti495slc",
.flags = 0,
.local = OPTI495XLC,
.local = OPTI495SLC,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti495sx_device = {
.name = "OPTi 82C495SX",
.internal_name = "opti495sx",
.flags = 0,
.local = OPTI495SX,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,

360
src/chipset/opti498.c Normal file
View File

@@ -0,0 +1,360 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the OPTi 82C498 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI498_LOG
int opti498_do_log = ENABLE_OPTI498_LOG;
static void
opti498_log(const char *fmt, ...)
{
va_list ap;
if (opti498_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define opti498_log(fmt, ...)
#endif
typedef struct mem_remapping_t {
uint32_t phys;
uint32_t virt;
} mem_remapping_t;
typedef struct opti498_t {
uint8_t index;
/* 0x30 for 496/497, 0x70 for 498. */
uint8_t reg_base;
uint8_t shadow_high;
uint8_t regs[256];
mem_remapping_t mem_remappings[2];
mem_mapping_t mem_mappings[2];
} opti498_t;
static uint8_t
opti498_read_remapped_ram(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ram((addr - dev->virt) + dev->phys, priv);
}
static uint16_t
opti498_read_remapped_ramw(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ramw((addr - dev->virt) + dev->phys, priv);
}
static uint32_t
opti498_read_remapped_raml(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_raml((addr - dev->virt) + dev->phys, priv);
}
static void
opti498_write_remapped_ram(uint32_t addr, uint8_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ram((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ramw((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_write_remapped_raml(uint32_t addr, uint32_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_raml((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_shadow_recalc(opti498_t *dev)
{
uint32_t base;
uint32_t rbase;
uint8_t sh_enable;
uint8_t sh_mode;
uint8_t rom;
uint8_t sh_copy;
shadowbios = shadowbios_write = 0;
dev->shadow_high = 0;
opti498_log("OPTI 498: %02X %02X %02X %02X\n", dev->regs[0x02], dev->regs[0x03], dev->regs[0x04], dev->regs[0x05]);
if (dev->regs[0x02] & 0x80) {
if (dev->regs[0x04] & 0x02) {
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_EXTANY\n");
} else {
shadowbios_write = 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n");
}
} else {
shadowbios = 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: F0000-FFFFF READ_INTERNAL, WRITE_DISABLED\n");
}
sh_copy = dev->regs[0x02] & 0x08;
for (uint8_t i = 0; i < 12; i++) {
base = 0xc0000 + (i << 14);
if (i >= 4)
sh_enable = dev->regs[0x03] & (1 << (i - 4));
else
sh_enable = dev->regs[0x04] & (1 << (i + 4));
sh_mode = dev->regs[0x02] & (1 << (i >> 2));
rom = dev->regs[0x02] & (1 << ((i >> 2) + 4));
opti498_log("OPTI 498: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4)));
if (sh_copy) {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else if (sh_enable && rom) {
if (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (sh_mode) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
if (base >= 0x000e0000)
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else {
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
}
}
}
rbase = ((uint32_t) (dev->regs[0x05] & 0x3f)) << 20;
if (rbase > 0) {
dev->mem_remappings[0].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000);
if (!dev->shadow_high) {
rbase += 0x00020000;
dev->mem_remappings[1].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[1], rbase, 0x00020000);
} else
mem_mapping_disable(&dev->mem_mappings[1]);
} else {
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_disable(&dev->mem_mappings[1]);
}
flushmmucache_nopc();
}
static void
opti498_write(uint16_t addr, uint8_t val, void *priv)
{
opti498_t *dev = (opti498_t *) priv;
uint8_t reg = dev->index - dev->reg_base;
switch (addr) {
default:
break;
case 0x22:
dev->index = val;
break;
case 0x24:
opti498_log("OPTi 498: dev->regs[%02x] = %02x\n", dev->index, val);
if ((reg >= 0x00) && (reg <= 0x0b)) switch (reg) {
default:
break;
case 0x00:
dev->regs[reg] = (dev->regs[reg] & 0xc0) | (val & 0x3f);
break;
case 0x01:
case 0x07 ... 0x0b:
dev->regs[reg] = val;
break;
case 0x02:
case 0x03:
case 0x04:
case 0x05:
dev->regs[reg] = val;
opti498_shadow_recalc(dev);
break;
case 0x06: {
double bus_clk;
dev->regs[reg] = val;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 8.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 5.0;
break;
case 0x03:
bus_clk = cpu_busspeed / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !!(val & 0x40);
break;
}
}
dev->index = 0xff;
break;
}
}
static uint8_t
opti498_read(uint16_t addr, void *priv)
{
opti498_t *dev = (opti498_t *) priv;
uint8_t reg = dev->index - dev->reg_base;
uint8_t ret = 0xff;
if (addr == 0x24) {
if ((reg >= 0x00) && (reg <= 0x0b))
ret = dev->regs[reg];
dev->index = 0xff;
}
return ret;
}
static void
opti498_close(void *priv)
{
opti498_t *dev = (opti498_t *) priv;
free(dev);
}
static void *
opti498_init(UNUSED(const device_t *info))
{
opti498_t *dev = (opti498_t *) calloc(1, sizeof(opti498_t));
dev->reg_base = info->local & 0xff;
io_sethandler(0x0022, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev);
dev->regs[0x00] = 0x1f;
dev->regs[0x01] = 0x8f;
dev->regs[0x02] = 0xf0;
dev->regs[0x07] = 0x70;
dev->regs[0x09] = 0x70;
dev->mem_remappings[0].phys = 0x000a0000;
dev->mem_remappings[1].phys = 0x000d0000;
mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000,
opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml,
opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml,
&ram[dev->mem_remappings[0].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[0]);
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_add(&dev->mem_mappings[1], 0, 0x00020000,
opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml,
opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml,
&ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]);
mem_mapping_disable(&dev->mem_mappings[1]);
opti498_shadow_recalc(dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 8.0));
device_add(&port_92_device);
return dev;
}
const device_t opti498_device = {
.name = "OPTi 82C498",
.internal_name = "opti498",
.flags = 0,
.local = 0x70,
.init = opti498_init,
.close = opti498_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -16,6 +16,7 @@
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -148,9 +149,28 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
default:
break;
case 0x20:
case 0x20: {
double coeff = (val & 0x10) ? 1.0 : 2.0;
double bus_clk;
switch (dev->regs[0x25] & 0x03) {
default:
case 0x00:
bus_clk = (cpu_busspeed * coeff) / 6.0;
break;
case 0x01:
bus_clk = (cpu_busspeed * coeff) / 5.0;
break;
case 0x02:
bus_clk = (cpu_busspeed * coeff) / 4.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * coeff) / 3.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !(val & 0x02);
break;
}
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
@@ -163,6 +183,28 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
case 0x2d:
opti499_recalc(dev);
break;
case 0x25: {
double coeff = (dev->regs[0x20] & 0x10) ? 1.0 : 2.0;
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = (cpu_busspeed * coeff) / 8.0;
break;
case 0x01:
bus_clk = (cpu_busspeed * coeff) / 6.0;
break;
case 0x02:
bus_clk = (cpu_busspeed * coeff) / 5.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * coeff) / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
}
}
@@ -229,6 +271,8 @@ opti499_reset(void *priv)
cpu_update_waitstates();
opti499_recalc(dev);
cpu_set_isa_speed((int) round((cpu_busspeed * 2.0) / 6.0));
}
static void

View File

@@ -16,6 +16,7 @@
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -182,6 +183,27 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
smram_state_change(dev->smram, 0, !!(val & 0x80));
break;
case 0x25: {
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 5.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 4.0;
break;
case 0x03:
bus_clk = cpu_busspeed / 3.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
case 0xe0:
if (!(val & 0x01))
dev->forced_green = 0;
@@ -294,6 +316,8 @@ opti895_init(const device_t *info)
smram_enable(dev->smram, 0x00030000, 0x000b0000, 0x00010000, 0, 1);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
return dev;
}

View File

@@ -786,7 +786,7 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
codegen_addquad(block, (uintptr_t) p);
codegen_addbyte3(block, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/
} else {
fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram);
fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIXPTR ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram);
codegen_alloc_bytes(block, 6);
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));

View File

@@ -660,6 +660,8 @@ load_network(void)
nc->net_type = NET_TYPE_SLIRP;
else if (!strcmp(p, "vde") || !strcmp(p, "2"))
nc->net_type = NET_TYPE_VDE;
else if (!strcmp(p, "tap") || !strcmp(p, "3"))
nc->net_type = NET_TYPE_TAP;
else
nc->net_type = NET_TYPE_NONE;
} else
@@ -706,11 +708,12 @@ load_network(void)
nc->net_type = NET_TYPE_SLIRP;
else if (!strcmp(p, "vde") || !strcmp(p, "2"))
nc->net_type = NET_TYPE_VDE;
else if (!strcmp(p, "tap") || !strcmp(p, "3"))
nc->net_type = NET_TYPE_TAP;
else
nc->net_type = NET_TYPE_NONE;
} else
nc->net_type = NET_TYPE_NONE;
sprintf(temp, "net_%02i_host_device", c + 1);
p = ini_section_get_string(cat, temp, NULL);
if (p != NULL) {
@@ -2433,7 +2436,9 @@ save_network(void)
case NET_TYPE_VDE:
ini_section_set_string(cat, temp, "vde");
break;
case NET_TYPE_TAP:
ini_section_set_string(cat, temp, "tap");
break;
default:
break;
}

View File

@@ -264,6 +264,7 @@ opVPCEXT(uint32_t fetchdat)
uint8_t b2;
uint16_t cent;
time_t now;
struct tm tm_buf;
struct tm *tm = NULL;
if (!is_vpc) /* only emulate this on Virtual PC machines */
@@ -282,7 +283,16 @@ opVPCEXT(uint32_t fetchdat)
/* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */
if (b1 == 0x03) {
(void) time(&now);
tm = localtime(&now);
#ifdef _WIN32
if (localtime_s(&tm_buf, &now) == 0)
tm = &tm_buf;
#else
tm = localtime_r(&now, &tm_buf);
#endif
if (!tm)
fatal("localtime() failed for host clock\n");
}
if ((b1 == 0x07) && (b2 == 0x0b)) {

View File

@@ -381,7 +381,7 @@ typedef struct {
MMX_REG MM[8];
#ifdef USE_NEW_DYNAREC
# if defined(__APPLE__) && defined(__aarch64__)
# if (defined(__APPLE__) && defined(__aarch64__)) || defined(__aarch64__)
uint64_t old_fp_control;
uint64_t new_fp_control;
# else

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stddef.h>
#include <stdint.h>
#include "primitiveTypes.h"
@@ -64,7 +65,7 @@ void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *
{
uint64_t wordJam;
uint32_t wordDist;
uint64_t *ptr;
uint64_t *ptr = NULL;
uint8_t i, innerDist;
wordJam = 0;
@@ -89,7 +90,7 @@ void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *
aPtr,
innerDist,
zPtr + indexMultiwordLoBut(4, wordDist)
);
);
if (! wordDist) goto wordJam;
} else {
aPtr += indexWordLo(4 - wordDist);

View File

@@ -41,7 +41,7 @@ add_library(dev OBJECT
keyboard.c
keyboard_at.c
keyboard_xt.c
../lpt.c
lpt.c
mouse.c
mouse_bus.c
mouse_microtouch_touchscreen.c

View File

@@ -27,6 +27,7 @@
#include <stdarg.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/lpt.h>
#include <86box/device.h>
@@ -334,13 +335,16 @@ hasp_close(void *priv)
}
const lpt_device_t lpt_hasp_savquest_device = {
.name = "Protection Dongle for Savage Quest",
.internal_name = "dongle_savquest",
.init = hasp_init_savquest,
.close = hasp_close,
.write_data = hasp_write_data,
.write_ctrl = NULL,
.read_data = NULL,
.read_status = hasp_read_status,
.read_ctrl = NULL
.name = "Protection Dongle for Savage Quest",
.internal_name = "dongle_savquest",
.init = hasp_init_savquest,
.close = hasp_close,
.write_data = hasp_write_data,
.write_ctrl = NULL,
.autofeed = NULL,
.strobe = NULL,
.read_status = hasp_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -156,7 +156,7 @@ isarom_init(const device_t *info)
snprintf(dev->socket[i].nvr_path, sizeof(dev->socket[i].nvr_path), "isarom_%i_%i.nvr", dev->inst, i + 1);
FILE *fp = nvr_fopen(dev->socket[i].nvr_path, "rb");
if (fp != NULL) {
fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp);
(void) !fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp);
fclose(fp);
isarom_log("isarom[%u]: loaded %zu bytes from %s\n", dev->inst, read_bytes, dev->socket[i].nvr_path);
} else

View File

@@ -1817,8 +1817,6 @@ read_p1(atkbc_t *dev)
Compaq: Reserved;
NCR: DMA mode.
*/
kbc_at_log("ATkbc: read P1\n");
fixed_bits = 4;
/* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */
@@ -2108,7 +2106,7 @@ kbc_at_process_cmd(void *priv)
break;
case 0xc0: /* read P1 */
kbc_at_log("ATkbc: read P2\n");
kbc_at_log("ATkbc: read P1\n");
kbc_delay_to_ob(dev, read_p1(dev), 0, 0x00);
break;

View File

@@ -69,6 +69,7 @@ enum {
KBD_TYPE_ZENITH,
KBD_TYPE_PRAVETZ,
KBD_TYPE_HYUNDAI,
KBD_TYPE_FE2010,
KBD_TYPE_XTCLONE
};
@@ -80,6 +81,7 @@ typedef struct xtkbd_t {
uint8_t pa;
uint8_t pb;
uint8_t pd;
uint8_t cfg;
uint8_t clock;
uint8_t key_waiting;
uint8_t type;
@@ -832,12 +834,26 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF");
#endif
break;
#ifdef ENABLE_KEYBOARD_XT_LOG
case 0x62: /* Switch Register (aka Port C) */
#ifdef ENABLE_KEYBOARD_XT_LOG
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ))
kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10));
break;
#endif
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Switch register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->pd = (kbd->pd & 0x30) | (val & 0xcf);
}
break;
case 0x63:
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Configuration register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->cfg = val;
}
break;
case 0xc0 ... 0xcf: /* Pravetz Flags */
kbd_log("XTkbd: Port %02X out: %02X\n", port, val);
@@ -912,7 +928,12 @@ kbd_read(uint16_t port, void *priv)
break;
case 0x62: /* Switch Register (aka Port C) */
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
if (kbd->type == KBD_TYPE_FE2010) {
if (kbd->pb & 0x04) /* PB2 */
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
else
ret = kbd->pd >> 4;
} else if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) {
if (kbd->pb & 0x04) /* PB2 */
switch (mem_size + isa_mem_size) {
@@ -1037,7 +1058,7 @@ kbd_init(const device_t *info)
(kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) ||
(kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH)) {
(kbd->type == KBD_TYPE_VTECH) || (kbd->type == KBD_TYPE_FE2010)) {
/* DIP switch readout: bit set = OFF, clear = ON. */
if (kbd->type == KBD_TYPE_OLIVETTI)
/* Olivetti M19
@@ -1057,7 +1078,7 @@ kbd_init(const device_t *info)
/* Switches 3, 4 - memory size. */
if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA)) {
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_FE2010)) {
switch (mem_size) {
case 256:
kbd->pd |= 0x00;
@@ -1356,7 +1377,7 @@ const device_t keyboard_xt_zenith_device = {
const device_t keyboard_xt_hyundai_device = {
.name = "Hyundai XT Keyboard",
.internal_name = "keyboard_x_hyundai",
.internal_name = "keyboard_xt_hyundai",
.flags = 0,
.local = KBD_TYPE_HYUNDAI,
.init = kbd_init,
@@ -1368,6 +1389,20 @@ const device_t keyboard_xt_hyundai_device = {
.config = NULL
};
const device_t keyboard_xt_fe2010_device = {
.name = "Faraday FE2010 XT Keyboard",
.internal_name = "keyboard_xt_fe2010",
.flags = 0,
.local = KBD_TYPE_FE2010,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xtclone_device = {
.name = "XT (Clone) Keyboard",
.internal_name = "keyboard_xtclone",

839
src/device/lpt.c Normal file
View File

@@ -0,0 +1,839 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/fifo.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/lpt.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/prt_devs.h>
#include <86box/thread.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/network.h>
lpt_port_t lpt_ports[PARALLEL_MAX];
const lpt_device_t lpt_none_device = {
.name = "None",
.internal_name = "none",
.init = NULL,
.close = NULL,
.write_data = NULL,
.write_ctrl = NULL,
.read_status = NULL,
.read_ctrl = NULL
};
static const struct {
const char *internal_name;
const lpt_device_t *device;
} lpt_devices[] = {
// clang-format off
{"none", &lpt_none_device },
{"dss", &dss_device },
{"lpt_dac", &lpt_dac_device },
{"lpt_dac_stereo", &lpt_dac_stereo_device },
{"text_prt", &lpt_prt_text_device },
{"dot_matrix", &lpt_prt_escp_device },
{"postscript", &lpt_prt_ps_device },
#ifdef USE_PCL
{"pcl", &lpt_prt_pcl_device },
#endif
{"plip", &lpt_plip_device },
{"dongle_savquest", &lpt_hasp_savquest_device },
{"", NULL }
// clang-format on
};
#ifdef ENABLE_LPT_LOG
int lpt_do_log = ENABLE_LPT_LOG;
static void
lpt_log(const char *fmt, ...)
{
va_list ap;
if (lpt_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define lpt_log(fmt, ...)
#endif
const char *
lpt_device_get_name(const int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
if (lpt_devices[id].device == NULL)
return "None";
return lpt_devices[id].device->name;
}
const char *
lpt_device_get_internal_name(const int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
return lpt_devices[id].internal_name;
}
int
lpt_device_get_from_internal_name(const char *s)
{
int c = 0;
while (strlen(lpt_devices[c].internal_name) != 0) {
if (strcmp(lpt_devices[c].internal_name, s) == 0)
return c;
c++;
}
return 0;
}
void
lpt_devices_init(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device;
if (lpt_ports[i].dt && lpt_ports[i].dt->init)
lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]);
}
}
void
lpt_devices_close(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_port_t *dev = &lpt_ports[i];
if (lpt_ports[i].dt && lpt_ports[i].dt->close)
dev->dt->close(dev->priv);
dev->dt = NULL;
}
}
static uint8_t
lpt_get_ctrl_raw(const lpt_port_t *dev)
{
uint8_t ret;
if (dev->dt && dev->dt->read_ctrl && dev->priv)
ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq;
else
ret = 0xc0 | dev->ctrl | dev->enable_irq;
return ret & 0xdf;
}
static uint8_t
lpt_is_epp(const lpt_port_t *dev)
{
return (dev->epp || ((dev->ecp) && ((dev->ecr & 0xe0) == 0x80)));
}
static uint8_t
lpt_get_ctrl(const lpt_port_t *dev)
{
uint8_t ret = lpt_get_ctrl_raw(dev);
if (!dev->ecp && !dev->epp)
ret |= 0x20;
return ret;
}
static void
lpt_write_fifo(lpt_port_t *dev, const uint8_t val, const uint8_t tag)
{
if (!fifo_get_full(dev->fifo)) {
fifo_write_evt_tagged(tag, val, dev->fifo);
if (!timer_is_enabled(&dev->fifo_out_timer))
timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
}
}
static void
lpt_ecp_update_irq(lpt_port_t *dev)
{
if (!(dev->ecr & 0x04) && ((dev->fifo_stat | dev->dma_stat) & 0x04))
picintlevel(1 << dev->irq, &dev->irq_state);
else
picintclevel(1 << dev->irq, &dev->irq_state);
}
static void
lpt_autofeed(lpt_port_t *dev, const uint8_t val)
{
if (dev->dt && dev->dt->autofeed && dev->priv)
dev->dt->autofeed(val, dev->priv);
dev->autofeed = val;
}
static void
lpt_strobe(lpt_port_t *dev, const uint8_t val)
{
if (dev->dt && dev->dt->strobe && dev->priv)
dev->dt->strobe(dev->strobe, val, dev->priv);
dev->strobe = val;
}
static void
lpt_fifo_out_callback(void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
switch (dev->state) {
default:
break;
case LPT_STATE_READ_DMA:
;
int ret = 0xff;
if (dev->dma == 0xff)
ret = DMA_NODATA;
else
ret = dma_channel_read(dev->dma);
lpt_log("DMA %02X: %08X\n", dev->dma, ret);
if (ret != DMA_NODATA) {
fifo_write_evt_tagged(0x01, (uint8_t) (ret & 0xff), dev->fifo);
if (ret & DMA_OVER)
/* Internal flag to indicate we have finished the DMA reads. */
dev->dma_stat = 0x08;
}
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
if (dev->dma_stat || fifo_get_full(dev->fifo))
dev->state = LPT_STATE_WRITE_FIFO;
break;
case LPT_STATE_WRITE_FIFO:
if (!fifo_get_empty(dev->fifo)) {
uint8_t tag = 0x00;
const uint8_t val = fifo_read_evt_tagged(&tag, dev->fifo);
lpt_log("FIFO: %02X, TAG = %02X\n", val, tag);
/* We do not currently support sending commands. */
if (tag == 0x01) {
if (dev->dt && dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
lpt_strobe(dev, 1);
lpt_strobe(dev, 0);
}
}
if (dev->ecr & 0x08) {
if (fifo_get_empty(dev->fifo)) {
if (dev->dma_stat) {
/* Now actually set the external flag. */
dev->dma_stat = 0x04;
dev->state = LPT_STATE_IDLE;
lpt_ecp_update_irq(dev);
lpt_autofeed(dev, 0);
} else {
dev->state = LPT_STATE_READ_DMA;
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
}
} else
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
} else if (!fifo_get_empty(dev->fifo))
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
else
lpt_autofeed(dev, 0);
break;
}
}
void
lpt_write(const uint16_t port, const uint8_t val, void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
uint16_t mask = 0x0407;
lpt_log("[W] %04X = %02X\n", port, val);
/* This is needed so the parallel port at 3BC works. */
if (dev->addr & 0x0004)
mask = 0x0403;
switch (port & mask) {
case 0x0000:
if (dev->ecp) {
if ((dev->ecr & 0xe0) == 0x60)
/* AFIFO */
lpt_write_fifo(dev, val, 0x00);
else if (!(dev->ecr & 0xc0) && (!(dev->ecr & 0x20) || !(lpt_get_ctrl_raw(dev) & 0x20)) &&
dev->dt && dev->dt->write_data && dev->priv)
/* DATAR */
dev->dt->write_data(val, dev->priv);
dev->dat = val;
} else {
/* DTR */
if ((!dev->ext || !(lpt_get_ctrl_raw(dev) & 0x20)) && dev->dt &&
dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
dev->dat = val;
}
break;
case 0x0001:
break;
case 0x0002:
if (dev->dt && dev->dt->write_ctrl && dev->priv) {
if (dev->ecp)
dev->dt->write_ctrl((val & 0xfc) | dev->autofeed | dev->strobe, dev->priv);
else
dev->dt->write_ctrl(val, dev->priv);
}
dev->ctrl = val;
dev->enable_irq = val & 0x10;
if (!(val & 0x10) && (dev->irq != 0xff))
picintc(1 << dev->irq);
dev->irq_state = 0;
break;
case 0x0003:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_write_data && dev->priv)
dev->dt->epp_write_data(1, val, dev->priv);
}
break;
case 0x0004 ... 0x0007:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_write_data && dev->priv)
dev->dt->epp_write_data(0, val, dev->priv);
}
break;
case 0x0400: case 0x0404:
switch (dev->ecr >> 5) {
default:
break;
case 2:
lpt_write_fifo(dev, val, 0x01);
break;
case 3:
if (!(lpt_get_ctrl_raw(dev) & 0x20))
lpt_write_fifo(dev, val, 0x01);
break;
case 6:
/* TFIFO */
if (!fifo_get_full(dev->fifo))
fifo_write_evt(val, dev->fifo);
break;
}
break;
case 0x0402: case 0x0406:
if (!(val & 0x0c))
lpt_autofeed(dev, 0x00);
else
lpt_autofeed(dev, 0x02);
if ((dev->ecr & 0x04) && !(val & 0x04)) {
dev->dma_stat = 0x00;
fifo_reset(dev->fifo);
if (val & 0x08) {
dev->state = LPT_STATE_READ_DMA;
dev->fifo_stat = 0x00;
if (!timer_is_enabled(&dev->fifo_out_timer))
timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
} else {
dev->state = LPT_STATE_WRITE_FIFO;
if (lpt_get_ctrl_raw(dev) & 0x20)
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00;
else
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04;
}
} else if ((val & 0x04) && !(dev->ecr & 0x04)) {
if (timer_is_enabled(&dev->fifo_out_timer))
timer_disable(&dev->fifo_out_timer);
dev->state = LPT_STATE_IDLE;
}
dev->ecr = val;
lpt_ecp_update_irq(dev);
break;
default:
break;
}
}
static void
lpt_fifo_d_ready_evt(void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (!(dev->ecr & 0x08)) {
if (lpt_get_ctrl_raw(dev) & 0x20)
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00;
else
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04;
}
lpt_ecp_update_irq(dev);
}
void
lpt_write_to_fifo(void *priv, const uint8_t val)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->ecp) {
if (((dev->ecr & 0xe0) == 0x20) && (lpt_get_ctrl_raw(dev) & 0x20))
dev->dat = val;
else if (((dev->ecr & 0xe0) == 0x60) && (lpt_get_ctrl_raw(dev) & 0x20) &&
!fifo_get_full(dev->fifo))
fifo_write_evt_tagged(0x01, val, dev->fifo);
if (((dev->ecr & 0x0c) == 0x08) && (dev->dma != 0xff)) {
const int ret = dma_channel_write(dev->dma, val);
if (ret & DMA_OVER)
dev->dma_stat |= 0x04;
}
} else {
if (dev->ext && (lpt_get_ctrl_raw(dev) & 0x20))
dev->dat = val;
}
}
void
lpt_write_to_dat(void *priv, const uint8_t val)
{
lpt_port_t *dev = (lpt_port_t *) priv;
dev->dat = val;
}
static uint8_t
lpt_read_fifo(const lpt_port_t *dev)
{
uint8_t ret = 0xff;
if (!fifo_get_empty(dev->fifo))
ret = fifo_read(dev->fifo);
return ret;
}
uint8_t
lpt_read_status(const int port)
{
lpt_port_t *dev = &lpt_ports[port];
uint8_t low_bits = 0x07;
uint8_t ret;
if (dev->ext) {
low_bits = 0x03 | (dev->irq_state ? 0x00 : 0x04);
if (dev->irq != 0xff)
picintclevel(1 << dev->irq, &dev->irq_state);
dev->irq_state = 0;
}
if (dev->epp || dev->ecp) {
low_bits = lpt_is_epp(dev) ? 0x02 : 0x03;
if (lpt_get_ctrl_raw(dev) & 0x10)
low_bits |= (dev->irq_state ? 0x00 : 0x04);
else
low_bits |= 0x04;
}
if (dev->dt && dev->dt->read_status && dev->priv)
ret = (dev->dt->read_status(dev->priv) & 0xf8) | low_bits;
else
ret = 0xd8 | low_bits;
return ret;
}
uint8_t
lpt_read(const uint16_t port, void *priv)
{
const lpt_port_t *dev = (lpt_port_t *) priv;
uint16_t mask = 0x0407;
uint8_t ret = 0xff;
/* This is needed so the parallel port at 3BC works. */
if (dev->addr & 0x0004)
mask = 0x0403;
switch (port & mask) {
case 0x0000:
if (dev->ecp) {
if (!(dev->ecr & 0xc0))
ret = dev->dat;
} else {
/* DTR */
ret = dev->dat;
}
break;
case 0x0001:
ret = lpt_read_status(dev->id);
break;
case 0x0002:
ret = lpt_get_ctrl(dev);
if (dev->ecp)
ret = (ret & 0xfc) | (dev->ctrl & 0x03);
break;
case 0x0003:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_request_read && dev->priv)
dev->dt->epp_request_read(1, dev->priv);
ret = dev->dat;
}
break;
case 0x0004 ... 0x0007:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_request_read && dev->priv)
dev->dt->epp_request_read(0, dev->priv);
ret = dev->dat;
}
break;
case 0x0400: case 0x0404:
switch (dev->ecr >> 5) {
default:
break;
case 3:
if (lpt_get_ctrl_raw(dev) & 0x20)
ret = lpt_read_fifo(dev);
break;
case 6:
/* TFIFO */
if (!fifo_get_empty(dev->fifo))
ret = fifo_read_evt(dev->fifo);
break;
case 7:
/* CNFGA */
ret = 0x14;
break;
}
break;
case 0x0401: case 0x0405:
if ((dev->ecr & 0xe0) == 0xe0) {
/* CNFGB */
ret = 0x08;
ret |= (dev->irq_state ? 0x40 : 0x00);
ret |= ((dev->irq == 0x05) ? 0x30 : 0x00);
if ((dev->dma >= 1) && (dev->dma <= 3))
ret |= dev->dma;
}
break;
case 0x0402: case 0x0406:
ret = dev->ecr | dev->fifo_stat | (dev->dma_stat & 0x04);
ret |= (fifo_get_full(dev->fifo) ? 0x02 : 0x00);
ret |= (fifo_get_empty(dev->fifo) ? 0x01 : 0x00);
break;
default:
break;
}
lpt_log("[R] %04X = %02X\n", port, ret);
return ret;
}
uint8_t
lpt_read_port(const int port, const uint16_t reg)
{
lpt_port_t *dev = &(lpt_ports[port]);
return lpt_read(reg, dev);
}
void
lpt_irq(void *priv, const int raise)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->enable_irq) {
if (dev->irq != 0xff) {
if (dev->ext) {
if (raise)
picintlevel(1 << dev->irq, &dev->irq_state);
else
picintclevel(1 << dev->irq, &dev->irq_state);
} else {
if (raise)
picint(1 << dev->irq);
else
picintc(1 << dev->irq);
}
}
if (!dev->ext || (dev->irq == 0xff))
dev->irq_state = raise;
} else {
if (dev->irq != 0xff) {
if (dev->ext)
picintclevel(1 << dev->irq, &dev->irq_state);
else
picintc(1 << dev->irq);
}
dev->irq_state = 0;
}
}
void
lpt_set_ext(const int port, const uint8_t ext)
{
if (lpt_ports[port].enabled)
lpt_ports[port].ext = ext;
}
void
lpt_set_ecp(const int port, const uint8_t ecp)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].ecp = ecp;
lpt_port_setup(port, addr);
}
}
void
lpt_set_epp(const int port, const uint8_t epp)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].epp = epp;
lpt_port_setup(port, addr);
}
}
void
lpt_set_lv2(const int port, const uint8_t lv2)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].lv2 = lv2;
lpt_port_setup(port, addr);
}
}
void
lpt_close(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
if (lpt_ports[i].enabled) {
fifo_close(lpt_ports[i].fifo);
lpt_ports[i].fifo = NULL;
timer_disable(&lpt_ports[i].fifo_out_timer);
}
}
}
void
lpt_port_zero(lpt_port_t *dev)
{
lpt_port_t temp = { 0 };
temp.irq = dev->irq;
temp.id = dev->id;
temp.device = dev->device;
temp.dt = dev->dt;
temp.priv = dev->priv;
temp.enabled = dev->enabled;
temp.fifo = dev->fifo;
temp.fifo_out_timer = dev->fifo_out_timer;
if (dev->enabled)
lpt_port_remove(dev->id);
memset(dev, 0x00, sizeof(lpt_port_t));
dev->addr = 0xffff;
dev->irq = temp.irq;
dev->id = temp.id;
dev->device = temp.device;
dev->dt = temp.dt;
dev->priv = temp.priv;
dev->enabled = temp.enabled;
dev->fifo = temp.fifo;
dev->fifo_out_timer = temp.fifo_out_timer;
if (machine_has_bus(machine, MACHINE_BUS_MCA))
dev->ext = 1;
}
void
lpt_reset(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
if (lpt_ports[i].enabled)
if (timer_is_enabled(&lpt_ports[i].fifo_out_timer))
timer_disable(&lpt_ports[i].fifo_out_timer);
lpt_port_zero(&(lpt_ports[i]));
if (lpt_ports[i].enabled) {
if (lpt_ports[i].irq_state) {
if (lpt_ports[i].irq == 0xff)
lpt_ports[i].irq_state = 0x00;
else {
picintclevel(lpt_ports[i].irq, &lpt_ports[i].irq_state);
picintc(lpt_ports[i].irq);
}
}
lpt_ports[i].enable_irq = 0x00;
lpt_ports[i].ext = !!(machine_has_bus(machine, MACHINE_BUS_MCA));
lpt_ports[i].epp = 0;
lpt_ports[i].ecp = 0;
lpt_ports[i].ecr = 0x15;
lpt_ports[i].dat = 0xff;
lpt_ports[i].fifo_stat = 0x00;
lpt_ports[i].dma_stat = 0x00;
}
}
}
void
lpt_init(void)
{
const uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR };
const uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ };
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].id = i;
lpt_ports[i].dt = NULL;
lpt_ports[i].priv = NULL;
lpt_ports[i].fifo = NULL;
memset(&lpt_ports[i].fifo_out_timer, 0x00, sizeof(pc_timer_t));
lpt_port_zero(&(lpt_ports[i]));
lpt_ports[i].addr = 0xffff;
lpt_ports[i].irq = 0xff;
lpt_ports[i].dma = 0xff;
lpt_ports[i].enable_irq = 0x00;
lpt_ports[i].ext = 0;
lpt_ports[i].epp = 0;
lpt_ports[i].ecp = 0;
lpt_ports[i].ecr = 0x15;
if (lpt_ports[i].enabled) {
lpt_port_setup(i, default_ports[i]);
lpt_port_irq(i, default_irqs[i]);
lpt_ports[i].fifo = fifo16_init();
fifo_set_trigger_len(lpt_ports[i].fifo, 8);
fifo_set_d_ready_evt(lpt_ports[i].fifo, lpt_fifo_d_ready_evt);
fifo_set_priv(lpt_ports[i].fifo, &lpt_ports[i]);
timer_add(&lpt_ports[i].fifo_out_timer, lpt_fifo_out_callback, &lpt_ports[i], 0);
}
}
}
void
lpt_port_setup(const int i, const uint16_t port)
{
if (lpt_ports[i].enabled) {
if (lpt_ports[i].addr != 0xffff) {
io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
}
if (port != 0xffff) {
lpt_log("Set handler: %04X-%04X\n", port, port + 0x0003);
io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].epp)
io_sethandler(lpt_ports[i].addr + 0x0003, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].ecp || lpt_ports[i].lv2) {
io_sethandler(port + 0x0400, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].epp)
io_sethandler(lpt_ports[i].addr + 0x0403, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
}
}
lpt_ports[i].addr = port;
} else
lpt_ports[i].addr = 0xffff;
}
void
lpt_port_irq(const int i, const uint8_t irq)
{
if (lpt_ports[i].enabled)
lpt_ports[i].irq = irq;
else
lpt_ports[i].irq = 0xff;
lpt_log("Port %i IRQ = %02X\n", i, irq);
}
void
lpt_port_dma(const int i, const uint8_t dma)
{
if (lpt_ports[i].enabled)
lpt_ports[i].dma = dma;
else
lpt_ports[i].dma = 0xff;
lpt_log("Port %i DMA = %02X\n", i, dma);
}
void
lpt_port_remove(const int i)
{
if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) {
io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = 0xffff;
}
}
void
lpt1_remove_ams(void)
{
if (lpt_ports[0].enabled)
io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]);
}

View File

@@ -13,7 +13,7 @@
* Jasmine Iwanek <jasmine@iwanek.co.uk>
*
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#include <stdarg.h>
@@ -222,10 +222,15 @@ serial_passthrough_dev_init(const device_t *info)
}
const char *serpt_mode_names[SERPT_MODES_MAX] = {
[SERPT_MODE_VCON] = "vcon",
[SERPT_MODE_TCPSRV] = "tcpsrv",
[SERPT_MODE_TCPCLNT] = "tcpclnt",
[SERPT_MODE_HOSTSER] = "hostser",
#ifdef _WIN32
[SERPT_MODE_NPIPE_SRV] = "npipesrv",
[SERPT_MODE_NPIPE_CLNT] = "npipeclnt",
#else
[SERPT_MODE_VCON] = "vcon",
#endif
[SERPT_MODE_TCP_SRV] = "tcpsrv",
[SERPT_MODE_TCP_CLNT] = "tcpclnt",
[SERPT_MODE_HOSTSER] = "hostser",
};
// clang-format off
@@ -240,19 +245,17 @@ static const device_config_t serial_passthrough_config[] = {
.spinner = { 0 },
.selection = {
#ifdef _WIN32
{ .description = "Named Pipe (Server)", .value = SERPT_MODE_VCON },
#if 0 /* TODO */
{ .description = "Named Pipe (Client)", .value = SERPT_MODE_VCON },
#endif
{ .description = "Named Pipe (Server)", .value = SERPT_MODE_NPIPE_SRV },
{ .description = "Named Pipe (Client)", .value = SERPT_MODE_NPIPE_CLNT },
#else /* _WIN32 */
{ .description = "Pseudo Terminal/Virtual Console", .value = SERPT_MODE_VCON },
{ .description = "Pseudo Terminal/Virtual Console", .value = SERPT_MODE_VCON },
#endif /* _WIN32 */
#if 0 /* TODO */
{ .description = "TCP Server", .value = SERPT_MODE_TCPSRV },
{ .description = "TCP Client", .value = SERPT_MODE_TCPCLNT },
{ .description = "TCP Server", .value = SERPT_MODE_TCP_SRV },
{ .description = "TCP Client", .value = SERPT_MODE_TCP_CLNT },
#endif
{ .description = "Host Serial Passthrough", .value = SERPT_MODE_HOSTSER },
{ .description = "" }
{ .description = "Host Serial Passthrough", .value = SERPT_MODE_HOSTSER },
{ .description = "" }
},
.bios = { { 0 } }
},

View File

@@ -56,35 +56,40 @@ static const struct {
// clang-format off
{ &device_none },
{ &device_internal },
{ &st506_xt_xebec_device },
{ &st506_xt_wdxt_gen_device },
/* ISA */
{ &xtide_acculogic_device },
{ &st506_xt_dtc5150x_device },
{ &st506_xt_xebec_device },
{ &xtide_device },
{ &st506_xt_st11_m_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_xt_wd1004a_wx1_device },
{ &st506_at_wd1003_device },
{ &st506_xt_st11_r_device },
{ &st506_xt_victor_v86p_device },
{ &st506_xt_wd1002a_27x_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_xt_wd1004_27x_device },
{ &st506_xt_wd1004a_27x_device },
{ &st506_xt_victor_v86p_device },
{ &esdi_at_wd1007vse1_device },
{ &st506_xt_wd1004a_wx1_device },
{ &xta_wdxt150_device },
{ &st506_xt_wdxt_gen_device },
/* ISA16 */
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_2ch_device },
{ &xtide_at_ps2_device },
{ &xtide_at_ps2_2ch_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },
{ &st506_at_wd1003_device },
{ &esdi_at_wd1007vse1_device },
/* MCA */
{ &esdi_ps2_device },
{ &esdi_integrated_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ &mcide_device },
/* VLB */
{ &ide_vlb_device },
{ &ide_vlb_2ch_device },
{ &mcide_device },
/* PCI */
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ NULL }
// clang-format on
};

View File

@@ -154,7 +154,7 @@ xtide_init(const device_t *info)
sprintf(xtide->nvr_path, "xtide_%i.nvr", device_get_instance());
FILE *fp = nvr_fopen(xtide->nvr_path, "rb");
if (fp != NULL) {
fread(xtide->bios_rom.rom, 1, 0x2000, fp);
(void) !fread(xtide->bios_rom.rom, 1, 0x2000, fp);
fclose(fp);
}
}

View File

@@ -56,7 +56,9 @@ typedef struct hdd_image_t {
hdd_image_t hdd_images[HDD_NUM];
static char empty_sector[512];
#ifndef __unix__
static char *empty_sector_1mb;
#endif
#ifdef ENABLE_HDD_IMAGE_LOG
int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG;

View File

@@ -191,7 +191,7 @@ fdc_ctrl_reset(void *priv)
fdc->step = 0;
fdc->power_down = 0;
if (!fdc->lock) {
if (!fdc->lock && !fdc->fifointest) {
fdc->fifo = 0;
fdc->tfifo = 1;
@@ -808,6 +808,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->tfifo = 1;
fdc->fifointest = 0;
}
fifo_reset(fdc->fifo_p);
fifo_set_len(fdc->fifo_p, fdc->tfifo + 1);
fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1);
}
return;
case 4: /* DSR */

View File

@@ -177,6 +177,8 @@ extern char usr_path[1024]; /* path (dir) of user data */
extern char cfg_path[1024]; /* full path of config file */
extern int open_dir_usr_path; /* default file open dialog directory of usr_path */
extern char uuid[MAX_UUID_LEN]; /* UUID or machine identifier */
extern char vmm_path[1024]; /* VM Manager path to scan (temporary) */
extern int vmm_enabled;
#ifndef USE_NEW_DYNAREC
extern FILE *stdlog; /* file to log output to */
#endif

View File

@@ -18,6 +18,7 @@
#define EMU_CHIPSET_H
/* ACC */
extern const device_t acc2036_device;
extern const device_t acc2168_device;
/* ALi */
@@ -123,7 +124,9 @@ extern const device_t opti381_device;
extern const device_t opti391_device;
extern const device_t opti481_device;
extern const device_t opti493_device;
extern const device_t opti495_device;
extern const device_t opti495slc_device;
extern const device_t opti495sx_device;
extern const device_t opti498_device;
extern const device_t opti499_device;
extern const device_t opti601_device;
extern const device_t opti602_device;

View File

@@ -20,6 +20,7 @@
#ifndef EMU_FLASH_H
#define EMU_FLASH_H
extern const device_t amd_am28f010_flash_device;
extern const device_t catalyst_flash_device;
extern const device_t intel_flash_bxt_ami_device;

View File

@@ -228,6 +228,7 @@ extern const device_t keyboard_xt_lxt3_device;
extern const device_t keyboard_xt_olivetti_device;
extern const device_t keyboard_xt_zenith_device;
extern const device_t keyboard_xt_hyundai_device;
extern const device_t keyboard_xt_fe2010_device;
extern const device_t keyboard_xtclone_device;
extern const device_t keyboard_at_device;
extern const device_t keyboard_at_ami_device;

View File

@@ -25,14 +25,24 @@ typedef struct lpt_device_t {
void (*close)(void *priv);
void (*write_data)(uint8_t val, void *priv);
void (*write_ctrl)(uint8_t val, void *priv);
uint8_t (*read_data)(void *priv);
void (*autofeed)(uint8_t val,void *priv);
void (*strobe)(uint8_t old, uint8_t val,void *priv);
uint8_t (*read_status)(void *priv);
uint8_t (*read_ctrl)(void *priv);
void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv);
void (*epp_request_read)(uint8_t is_addr, void *priv);
} lpt_device_t;
extern void lpt_set_ext(int port, uint8_t ext);
extern void lpt_set_ecp(int port, uint8_t ecp);
extern void lpt_set_epp(int port, uint8_t epp);
extern void lpt_set_lv2(int port, uint8_t lv2);
extern void lpt_reset(void);
extern void lpt_close(void);
extern void lpt_init(void);
extern void lpt_port_setup(int i, uint16_t port);
extern void lpt_port_irq(int i, uint8_t irq);
extern void lpt_port_dma(int i, uint8_t dma);
extern void lpt_port_remove(int i);
extern void lpt1_remove_ams(void);
@@ -68,31 +78,62 @@ void lpt_devices_close(void);
typedef struct lpt_port_t {
uint8_t enabled;
uint8_t irq;
uint8_t irq_state;
uint8_t dma;
uint8_t dat;
uint8_t ctrl;
uint8_t ext;
uint8_t epp;
uint8_t ecp;
uint8_t ecr;
uint8_t in_dat;
uint8_t fifo_stat;
uint8_t dma_stat;
uint8_t state;
uint8_t autofeed;
uint8_t strobe;
uint8_t lv2;
uint8_t pad[7];
uint16_t addr;
uint16_t pad0;
uint16_t id;
uint16_t pad0[2];
int device;
int enable_irq;
lpt_device_t *dt;
#ifdef FIFO_H
fifo16_t *fifo;
#else
void *fifo;
#endif
void *priv;
pc_timer_t fifo_out_timer;
} lpt_port_t;
typedef enum {
LPT_STATE_IDLE = 0,
LPT_STATE_READ_DMA,
LPT_STATE_WRITE_FIFO
} lpt_state_t;
extern lpt_port_t lpt_ports[PARALLEL_MAX];
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t lpt_read(uint16_t port, void *priv);
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t lpt_read_port(int port, uint16_t reg);
extern void lpt_write_to_fifo(void *priv, uint8_t val);
extern uint8_t lpt_read_status(int port);
extern void lpt_irq(void *priv, int raise);
extern uint8_t lpt_read(uint16_t port, void *priv);
extern uint8_t lpt_read_port(int port, uint16_t reg);
extern uint8_t lpt_read_status(int port);
extern void lpt_irq(void *priv, int raise);
extern int lpt_device_get_from_internal_name(const char *s);
extern const char *lpt_device_get_name(int id);
extern const char *lpt_device_get_internal_name(int id);
extern int lpt_device_get_from_internal_name(char *s);
extern const lpt_device_t lpt_dac_device;
extern const lpt_device_t lpt_dac_stereo_device;

View File

@@ -17,8 +17,10 @@
#pragma once
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
#define PCJR_RGB_NO_BROWN 4
#define PCJR_RGB_IBM_5153 5
typedef struct pcjr_s
{

View File

@@ -197,6 +197,7 @@ enum {
MACHINE_CHIPSET_GC100A,
MACHINE_CHIPSET_GC103,
MACHINE_CHIPSET_HT18,
MACHINE_CHIPSET_ACC_2036,
MACHINE_CHIPSET_ACC_2168,
MACHINE_CHIPSET_ALI_M1217,
MACHINE_CHIPSET_ALI_M6117,
@@ -240,7 +241,9 @@ enum {
MACHINE_CHIPSET_OPTI_391,
MACHINE_CHIPSET_OPTI_481,
MACHINE_CHIPSET_OPTI_493,
MACHINE_CHIPSET_OPTI_495,
MACHINE_CHIPSET_OPTI_495SLC,
MACHINE_CHIPSET_OPTI_495SX,
MACHINE_CHIPSET_OPTI_498,
MACHINE_CHIPSET_OPTI_499,
MACHINE_CHIPSET_OPTI_895_802G,
MACHINE_CHIPSET_OPTI_547_597,
@@ -456,6 +459,7 @@ extern int machine_at_px286_init(const machine_t *);
extern int machine_at_quadt286_init(const machine_t *);
extern int machine_at_mr286_init(const machine_t *);
extern int machine_at_pbl300sx_init(const machine_t *);
extern int machine_at_neat_init(const machine_t *);
extern int machine_at_neat_ami_init(const machine_t *);
extern int machine_at_ataripc4_init(const machine_t *);
@@ -465,6 +469,7 @@ extern int machine_at_quadt386sx_init(const machine_t *);
extern int machine_at_award286_init(const machine_t *);
extern int machine_at_gdc212m_init(const machine_t *);
extern int machine_at_gw286ct_init(const machine_t *);
extern int machine_at_drsm35286_init(const machine_t *);
extern int machine_at_senor_scat286_init(const machine_t *);
extern int machine_at_super286c_init(const machine_t *);
extern int machine_at_super286tr_init(const machine_t *);
@@ -475,6 +480,7 @@ extern int machine_at_kmxc02_init(const machine_t *);
extern int machine_at_deskmaster286_init(const machine_t *);
extern int machine_at_dells200_init(const machine_t *);
extern int machine_at_at122_init(const machine_t *);
extern int machine_at_tuliptc7_init(const machine_t *);
extern int machine_at_pc8_init(const machine_t *);
@@ -512,6 +518,7 @@ extern int machine_at_dataexpert386wb_init(const machine_t *);
extern int machine_at_isa486c_init(const machine_t *);
extern int machine_at_genoa486_init(const machine_t *);
extern int machine_at_ga486l_init(const machine_t *);
extern int machine_at_cobalt_init(const machine_t *);
extern int machine_at_cougar_init(const machine_t *);
extern int machine_at_acc386_init(const machine_t *);
@@ -544,6 +551,7 @@ extern int machine_at_winbios1429_init(const machine_t *);
extern int machine_at_opti495_init(const machine_t *);
extern int machine_at_opti495_ami_init(const machine_t *);
extern int machine_at_opti495_mr_init(const machine_t *);
extern int machine_at_c747_init(const machine_t *);
extern int machine_at_exp4349_init(const machine_t *);
extern int machine_at_vect486vl_init(const machine_t *);
@@ -564,6 +572,7 @@ extern int machine_at_dtk461_init(const machine_t *);
extern int machine_at_sis401_init(const machine_t *);
extern int machine_at_isa486_init(const machine_t *);
extern int machine_at_av4_init(const machine_t *);
extern int machine_at_advantage40xxd_init(const machine_t *);
extern int machine_at_valuepoint433_init(const machine_t *);
extern int machine_at_vli486sv2g_init(const machine_t *);
@@ -646,6 +655,7 @@ extern void machine_at_award_common_init(const machine_t *);
extern void machine_at_sp4_common_init(const machine_t *model);
extern int machine_at_v12p_init(const machine_t *);
extern int machine_at_excaliburpci_init(const machine_t *);
extern int machine_at_p5mp3_init(const machine_t *);
extern int machine_at_dellxp60_init(const machine_t *);
@@ -973,6 +983,7 @@ extern int machine_xt_kaypropc_init(const machine_t *);
extern int machine_xt_sansx16_init(const machine_t *);
extern int machine_xt_bw230_init(const machine_t *);
extern int machine_xt_pb8810_init(const machine_t *);
extern int machine_xt_tuliptc8_init(const machine_t *);
extern int machine_xt_v20xt_init(const machine_t *);

View File

@@ -265,12 +265,16 @@ extern uint32_t biosmask;
extern uint32_t biosaddr;
extern int readlookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern uintptr_t *readlookup2;
#endif
extern uintptr_t old_rl2;
extern uint8_t uncached;
extern int readlnext;
extern int writelookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern uintptr_t *writelookup2;
#endif
extern int writelnext;
extern uint32_t ram_mapped_addr[64];
extern uint8_t page_ff[4096];
@@ -288,7 +292,16 @@ extern mem_mapping_t bios_high_mapping;
extern uint32_t mem_logical_addr;
extern page_t *pages;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern page_t **page_lookup;
#endif
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
/* The lookup tables. */
extern page_t *page_lookup[1048576];
extern uintptr_t readlookup2[1048576];
extern uintptr_t writelookup2[1048576];
#endif
extern uint32_t get_phys_virt;
extern uint32_t get_phys_phys;
@@ -457,6 +470,9 @@ extern void mem_a20_init(void);
extern void mem_a20_recalc(void);
extern void mem_init(void);
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern void mem_free(void);
#endif
extern void mem_close(void);
extern void mem_zero(void);
extern void mem_reset(void);

View File

@@ -52,6 +52,7 @@
#define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */
#define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */
#define NET_TYPE_VDE 3 /* use the VDE plug API */
#define NET_TYPE_TAP 4 /* use a linux TAP device */
#define NET_MAX_FRAME 1518
/* Queue size must be a power of 2 */
@@ -126,6 +127,7 @@ typedef struct netdrv_t {
extern const netdrv_t net_pcap_drv;
extern const netdrv_t net_slirp_drv;
extern const netdrv_t net_vde_drv;
extern const netdrv_t net_tap_drv;
extern const netdrv_t net_null_drv;
struct _netcard_t {
@@ -155,10 +157,11 @@ typedef struct {
int has_slirp;
int has_pcap;
int has_vde;
int has_tap;
} network_devmap_t;
#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde)
#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde || x.has_tap)
#ifdef __cplusplus
extern "C" {

View File

@@ -0,0 +1,40 @@
/*
* 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.
*
* definitions for renderers
*
* Authors: Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2025 Jasmine Iwanek.
*/
#ifndef EMU_RENDERDEFS_H
#define EMU_RENDERDEFS_H
#define RENDERER_NAME_DEFAULT "default"
#define RENDERER_NAME_SYSTEM "system"
#define RENDERER_NAME_QT_SOFTWARE "qt_software"
#define RENDERER_NAME_QT_OPENGL "qt_opengl"
#define RENDERER_NAME_QT_OPENGLES "qt_opengles"
#define RENDERER_NAME_QT_OPENGL3 "qt_opengl3"
#define RENDERER_NAME_QT_VULKAN "qt_vulkan"
#define RENDERER_NAME_VNC "vnc"
#define RENDERER_SOFTWARE 0
#define RENDERER_OPENGL3 1
#define RENDERER_VULKAN 2
#define RENDERER_VNC 3
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /*EMU_RENDERDEFS_H*/

View File

@@ -13,7 +13,7 @@
* Jasmine Iwanek <jasmine@iwanek.co.uk>
*
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#ifndef SERIAL_PASSTHROUGH_H
@@ -28,10 +28,15 @@
#include <86box/serial.h>
enum serial_passthrough_mode {
SERPT_MODE_VCON, /*Named Pipe (Server) / Pseudo Terminal/Virtual Console */
SERPT_MODE_TCPSRV, /* TCP Server (TODO) */
SERPT_MODE_TCPCLNT, /* TCP Client (TODO) */
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
#ifdef _WIN32
SERPT_MODE_NPIPE_SRV, /* Named Pipe (Server) */
SERPT_MODE_NPIPE_CLNT, /* Named Pipe (Client) */
#else
SERPT_MODE_VCON, /* Pseudo Terminal/Virtual Console */
#endif
SERPT_MODE_TCP_SRV, /* TCP Server (TODO) */
SERPT_MODE_TCP_CLNT, /* TCP Client (TODO) */
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
SERPT_MODES_MAX,
};

View File

@@ -20,8 +20,6 @@
extern const device_t acc3221_device;
/* Acer / ALi */
extern const device_t ali5105_device;
extern const device_t ali5123_device;
/* Chips & Technologies */
@@ -79,10 +77,13 @@ extern const device_t i82091aa_398_device;
extern const device_t i82091aa_ide_pri_device;
extern const device_t i82091aa_ide_device;
/* National Semiconductors */
extern const device_t pc87310_device;
extern const device_t pc87310_ide_device;
/* National Semiconductors PC87310 / ALi M5105 */
#define PC87310_IDE 0x0001
#define PC87310_ALI 0x0002
extern const device_t pc87310_device;
/* National Semiconductors */
extern const device_t pc87306_device;
extern const device_t pc87311_device;
extern const device_t pc87311_ide_device;
@@ -92,6 +93,7 @@ extern const device_t pc87332_398_ide_device;
extern const device_t pc87332_398_ide_sec_device;
extern const device_t pc87332_398_ide_fdcon_device;
/* National Semiconductors PC87307 / PC87309 */
#define PCX7307_PC87307 0x00c0
#define PCX7307_PC97307 0x00cf
@@ -125,6 +127,10 @@ extern const device_t sio_detect_device;
#endif /* USE_SIO_DETECT */
/* UMC */
extern const device_t um82c862f_device;
extern const device_t um82c862f_ide_device;
extern const device_t um82c863f_device;
extern const device_t um82c863f_ide_device;
extern const device_t um8663af_device;
extern const device_t um8663af_ide_device;
extern const device_t um8663af_sec_device;

View File

@@ -4,7 +4,7 @@
#ifdef __cplusplus
extern "C" {
#endif
void *sid_init(uint8_t type);
void *sid_init(uint8_t type, double range);
void sid_close(void *priv);
void sid_reset(void *priv);
uint8_t sid_read(uint16_t addr, void *priv);

View File

@@ -37,6 +37,13 @@ typedef enum {
EXTENSIONS_MAX
} ibm8514_extensions_t;
typedef enum {
VGA_MODE = 0,
IBM_MODE,
ATI_MODE,
MODE_MAX
} ibm8514_mode_t;
typedef struct hwcursor8514_t {
int ena;
int x;
@@ -202,6 +209,7 @@ typedef struct ibm8514_t {
int split;
int h_disp;
int h_total;
int h_sync_start;
int h_sync_width;
int h_disp_time;
int rowoffset;
@@ -260,6 +268,7 @@ typedef struct ibm8514_t {
int ext_pitch;
int ext_crt_pitch;
ibm8514_extensions_t extensions;
ibm8514_mode_t mode;
int onboard;
int linear;
uint32_t vram_amount;

View File

@@ -18,6 +18,12 @@
#ifndef VIDEO_ATI_MACH8_H
#define VIDEO_ATI_MACH8_H
typedef enum {
ATI_68875 = 0,
ATI_68860,
RAMDAC_MAX
} mach_ramdac_type;
typedef struct mach_t {
ati_eeprom_t eeprom;
svga_t svga;
@@ -39,7 +45,7 @@ typedef struct mach_t {
uint8_t irq_state;
int index;
int ramdac_type;
mach_ramdac_type ramdac_type;
int old_mode;
uint16_t config1;

View File

@@ -136,6 +136,7 @@ typedef struct svga_t {
int packed_4bpp;
int ps_bit_bug;
int ati_4color;
int vblankend;
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
0MB-1MB - VRAM
@@ -281,6 +282,10 @@ typedef struct svga_t {
you should set this flag when entering that mode*/
int disable_blink;
/*Force special shifter bypass logic for 8-bpp lowres modes.
Needed if the screen is squished on certain S3 cards.*/
int force_shifter_bypass;
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
@@ -404,15 +409,15 @@ uint32_t svga_lookup_lut_ram(svga_t* svga, uint32_t val);
/* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and
possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga);
extern void ati68860_set_ramdac_type(void *priv, int type);
extern void ati68860_ramdac_set_render(void *priv, svga_t *svga);
extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col);
extern void ati68860_hwcursor_draw(svga_t *svga, int displine);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga);
extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);

View File

@@ -58,10 +58,6 @@ extern void svga_render_8bpp_highres(svga_t *svga);
extern void svga_render_8bpp_clone_highres(svga_t *svga);
extern void svga_render_8bpp_tseng_lowres(svga_t *svga);
extern void svga_render_8bpp_tseng_highres(svga_t *svga);
extern void svga_render_8bpp_gs_lowres(svga_t *svga);
extern void svga_render_8bpp_gs_highres(svga_t *svga);
extern void svga_render_8bpp_rgb_lowres(svga_t *svga);
extern void svga_render_8bpp_rgb_highres(svga_t *svga);
extern void svga_render_15bpp_lowres(svga_t *svga);
extern void svga_render_15bpp_highres(svga_t *svga);
extern void svga_render_15bpp_mix_lowres(svga_t *svga);

View File

@@ -75,6 +75,7 @@ enum {
#define FONT_IBM_MDA_437_NORDIC_PATH "roms/video/mda/4733197.bin"
#define FONT_KAM_PATH "roms/video/mda/kam.bin"
#define FONT_KAMCL16_PATH "roms/video/mda/kamcl16.bin"
#define FONT_TULIP_DGA_PATH "roms/video/mda/tulip-dga-bios.bin"
typedef struct video_timings_t {
int type;
@@ -357,12 +358,14 @@ extern const device_t chips_69000_onboard_device;
/* Cirrus Logic GD54xx */
extern const device_t gd5401_isa_device;
extern const device_t gd5401_onboard_device;
extern const device_t gd5402_isa_device;
extern const device_t gd5402_onboard_device;
extern const device_t gd5420_isa_device;
extern const device_t gd5420_onboard_device;
extern const device_t gd5422_isa_device;
extern const device_t gd5424_vlb_device;
extern const device_t gd5424_onboard_device;
extern const device_t gd5426_isa_device;
extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device;
extern const device_t gd5426_vlb_device;
@@ -472,6 +475,7 @@ extern const device_t if386jega_device;
/* Oak OTI-0x7 */
extern const device_t oti037c_device;
extern const device_t oti037_pbl300sx_device;
extern const device_t oti067_device;
extern const device_t oti067_acer386_device;
extern const device_t oti067_ama932j_device;

264
src/lpt.c
View File

@@ -1,264 +0,0 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/lpt.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/prt_devs.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/network.h>
lpt_port_t lpt_ports[PARALLEL_MAX];
const lpt_device_t lpt_none_device = {
.name = "None",
.internal_name = "none",
.init = NULL,
.close = NULL,
.write_data = NULL,
.write_ctrl = NULL,
.read_data = NULL,
.read_status = NULL,
.read_ctrl = NULL
};
static const struct {
const char *internal_name;
const lpt_device_t *device;
} lpt_devices[] = {
// clang-format off
{"none", &lpt_none_device },
{"dss", &dss_device },
{"lpt_dac", &lpt_dac_device },
{"lpt_dac_stereo", &lpt_dac_stereo_device },
{"text_prt", &lpt_prt_text_device },
{"dot_matrix", &lpt_prt_escp_device },
{"postscript", &lpt_prt_ps_device },
#ifdef USE_PCL
{"pcl", &lpt_prt_pcl_device },
#endif
{"plip", &lpt_plip_device },
{"dongle_savquest", &lpt_hasp_savquest_device },
{"", NULL }
// clang-format on
};
const char *
lpt_device_get_name(int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
if (!lpt_devices[id].device)
return "None";
return lpt_devices[id].device->name;
}
const char *
lpt_device_get_internal_name(int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
return lpt_devices[id].internal_name;
}
int
lpt_device_get_from_internal_name(char *s)
{
int c = 0;
while (strlen(lpt_devices[c].internal_name) != 0) {
if (strcmp(lpt_devices[c].internal_name, s) == 0)
return c;
c++;
}
return 0;
}
void
lpt_devices_init(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device;
if (lpt_ports[i].dt && lpt_ports[i].dt->init)
lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]);
}
}
void
lpt_devices_close(void)
{
lpt_port_t *dev;
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
dev = &lpt_ports[i];
if (lpt_ports[i].dt && lpt_ports[i].dt->close)
dev->dt->close(dev->priv);
dev->dt = NULL;
}
}
void
lpt_write(uint16_t port, uint8_t val, void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
switch (port & 3) {
case 0:
if (dev->dt && dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
dev->dat = val;
break;
case 1:
break;
case 2:
if (dev->dt && dev->dt->write_ctrl && dev->priv)
dev->dt->write_ctrl(val, dev->priv);
dev->ctrl = val;
dev->enable_irq = val & 0x10;
break;
default:
break;
}
}
uint8_t
lpt_read(uint16_t port, void *priv)
{
uint8_t ret = 0xff;
lpt_port_t *dev = (lpt_port_t *) priv;
switch (port & 3) {
case 0:
if (dev->dt && dev->dt->read_data && dev->priv)
ret = dev->dt->read_data(dev->priv);
else
ret = dev->dat;
break;
case 1:
if (dev->dt && dev->dt->read_status && dev->priv)
ret = dev->dt->read_status(dev->priv) | 0x07;
else
ret = 0xdf;
break;
case 2:
if (dev->dt && dev->dt->read_ctrl && dev->priv)
ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq;
else
ret = 0xe0 | dev->ctrl | dev->enable_irq;
break;
default:
break;
}
return ret;
}
uint8_t
lpt_read_port(int port, uint16_t reg)
{
lpt_port_t *dev = &(lpt_ports[port]);
uint8_t ret = lpt_read(reg, dev);
return ret;
}
uint8_t
lpt_read_status(int port)
{
lpt_port_t *dev = &(lpt_ports[port]);
uint8_t ret = 0xff;
if (dev->dt && dev->dt->read_status && dev->priv)
ret = dev->dt->read_status(dev->priv) | 0x07;
else
ret = 0xdf;
return ret;
}
void
lpt_irq(void *priv, int raise)
{
const lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->enable_irq && (dev->irq != 0xff)) {
if (raise)
picint(1 << dev->irq);
else
picintc(1 << dev->irq);
}
}
void
lpt_init(void)
{
uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR };
uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ };
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].addr = 0xffff;
lpt_ports[i].irq = 0xff;
lpt_ports[i].enable_irq = 0x10;
if (lpt_ports[i].enabled) {
lpt_port_setup(i, default_ports[i]);
lpt_port_irq(i, default_irqs[i]);
}
}
}
void
lpt_port_setup(int i, uint16_t port)
{
if (lpt_ports[i].enabled) {
if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000))
io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if ((port != 0xffff) && (port != 0x0000))
io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = port;
} else
lpt_ports[i].addr = 0xffff;
}
void
lpt_port_irq(int i, uint8_t irq)
{
if (lpt_ports[i].enabled)
lpt_ports[i].irq = irq;
else
lpt_ports[i].irq = 0xff;
}
void
lpt_port_remove(int i)
{
if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) {
io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = 0xffff;
}
}
void
lpt1_remove_ams(void)
{
if (lpt_ports[0].enabled)
io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]);
}

View File

@@ -118,7 +118,7 @@ machine_at_ama932j_init(const machine_t *model)
machine_at_headland_common_init(model, 2);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
return ret;
}
@@ -169,6 +169,72 @@ machine_at_quadt386sx_init(const machine_t *model)
return ret;
}
static const device_config_t pbl300sx_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "pbl300sx",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1991", .internal_name = "pbl300sx_1991", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pbl300sx/V1.10_1113_910723.bin", "" } },
{ .name = "1992", .internal_name = "pbl300sx", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pbl300sx/pb_l300sx_1992.bin", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t pbl300sx_device = {
.name = "Packard Bell Legend 300SX",
.internal_name = "pbl300sx_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = pbl300sx_config
};
int
machine_at_pbl300sx_init(const machine_t *model)
{
int ret = 0;
const char* fn;
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&acc2036_device);
device_add(&keyboard_ps2_phoenix_device);
device_add(&um82c862f_ide_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
return ret;
}
int
machine_at_neat_init(const machine_t *model)
{
@@ -292,6 +358,22 @@ machine_at_dells200_init(const machine_t *model)
return ret;
}
int
machine_at_at122_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/at122/FINAL.BIN",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_ctat_common_init(model);
return ret;
}
int
machine_at_tuliptc7_init(const machine_t *model)
{
@@ -447,6 +529,28 @@ machine_at_gw286ct_init(const machine_t *model)
return ret;
}
int
machine_at_drsm35286_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/drsm35286/syab04-665821fb81363428830424.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
device_add(&ide_isa_device);
device_add(&fdc37c651_ide_device);
machine_at_scat_init(model, 1, 0);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
return ret;
}
int
machine_at_senor_scat286_init(const machine_t *model)
{
@@ -776,7 +880,7 @@ machine_at_cmdsl386sx25_init(const machine_t *model)
device_add(&ide_isa_device);
device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */
device_add(&vlsi_scamp_device);
@@ -926,7 +1030,7 @@ machine_at_acer100t_init(const machine_t *model)
if (gfxcard[0] == VID_INTERNAL)
device_add(&oti077_acer100t_device);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
return ret;
}

View File

@@ -535,7 +535,7 @@ machine_at_acera1g_init(const machine_t *model)
device_add(&keyboard_ps2_acer_pci_device);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&ide_ali5213_device);
return ret;
@@ -682,7 +682,7 @@ machine_at_opti495_init(const machine_t *model)
machine_at_common_init(model);
device_add(&opti495_device);
device_add(&opti495slc_device);
device_add(&keyboard_at_device);
@@ -697,7 +697,7 @@ machine_at_opti495_ami_common_init(const machine_t *model)
{
machine_at_common_init(model);
device_add(&opti495_device);
device_add(&opti495sx_device);
device_add(&keyboard_at_ami_device);
@@ -737,6 +737,32 @@ machine_at_opti495_mr_init(const machine_t *model)
return ret;
}
int
machine_at_c747_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/c747/486-C747 Tandon.BIN",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
/* The EFAR chipset is a rebrand of the OPTi 495SX. */
device_add(&opti495sx_device);
/*
No idea what KBC it actually has but this produces the
desired behavior: command A9 does absolutely nothing.
*/
device_add(&keyboard_at_siemens_device);
device_add(&um82c862f_ide_device);
return ret;
}
int
machine_at_exp4349_init(const machine_t *model)
{
@@ -822,6 +848,7 @@ machine_at_403tg_d_mr_init(const machine_t *model)
return ret;
}
static const device_config_t pb450_config[] = {
// clang-format off
{
@@ -974,7 +1001,8 @@ machine_at_mvi486_init(const machine_t *model)
machine_at_common_init(model);
device_add(&opti495_device);
device_add(&opti498_device);
device_add(&keyboard_at_device);
device_add(&pc87311_ide_device);
@@ -1009,6 +1037,31 @@ machine_at_ami471_init(const machine_t *model)
return ret;
}
int
machine_at_advantage40xxd_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/advantage40xxd/AST101.09A",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&sis_85c471_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
device_add(&keyboard_ps2_phoenix_device);
device_add(&um82c863f_ide_device);
device_add(&intel_flash_bxt_device);
return ret;
}
int
machine_at_vli486sv2g_init(const machine_t *model)
{
@@ -2816,6 +2869,32 @@ machine_at_ga486l_init(const machine_t *model)
return ret;
}
int
machine_at_cobalt_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/cobalt/Cobalt_2.3.BIN",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&opti499_device);
device_add(&ide_opti611_vlb_device);
device_add(&ide_isa_sec_device);
device_add(&fdc37c665_device);
device_add(&keyboard_ps2_ami_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
return ret;
}
int
machine_at_cougar_init(const machine_t *model)
{

View File

@@ -41,6 +41,79 @@
#include <86box/video.h>
#include <86box/machine.h>
int
machine_at_v12p_init(const machine_t *model)
{
int ret = 0;
const char* fn;
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0);
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init(model);
device_add(&ide_isa_device);
pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SCSI, 1, 4, 3, 2);
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 2, 1, 4, 3);
pci_register_slot(0x03, PCI_CARD_NORMAL, 3, 2, 1, 4);
pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 0, 0, 0);
pci_register_slot(0x05, PCI_CARD_NORMAL, 0, 0, 0, 0);
device_add(&i430lx_device);
device_add(&keyboard_ps2_acer_pci_device);
device_add(&sio_zb_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&amd_am28f010_flash_device);
return ret;
}
static const device_config_t v12p_config[] = {
// clang-format off
{
.name = "bios_versions",
.description = "BIOS Versions",
.type = CONFIG_BIOS,
.default_string = "v12p_14",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "Core Version 1.2 Version R1.4", .internal_name = "v12p_14", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_14.bin", "" } },
{ .name = "Core Version 1.2 Version R1.6", .internal_name = "v12p_16", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_16.bin", "" } },
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t v12p_device = {
.name = "Acer V12P",
.internal_name = "v12p",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = &v12p_config[0]
};
void
machine_at_premiere_common_init(const machine_t *model, int pci_switch)
{

View File

@@ -96,21 +96,21 @@ machine_at_d842_init(const machine_t *model)
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init(model);
machine_at_common_init(model);
device_add(&ide_pci_2ch_device);
pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */
pci_register_slot(0x03, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Onboard */
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */
pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */
pci_register_slot(0x03, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Onboard */
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); /* Slot 01 */
pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); /* Slot 02 */
device_add(&keyboard_ps2_pci_device);
device_add(&i430nx_device);
device_add(&sio_zb_device);
device_add(&fdc37c665_device);
device_add(&intel_flash_bxt_device);
device_add(&intel_flash_bxt_device);
return ret;
}
@@ -127,18 +127,17 @@ static const device_config_t d842_config[] = {
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "Version 1.03 Revision 1.03.842 (11/24/1994)", .internal_name = "d842", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842.bin", "" } },
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842.BIN", "" } },
{ .name = "Version 4.04 Revision 1.05.842 (03/15/1996)", .internal_name = "d842_mar96", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_mar96.bin", "" } },
{ .name = "Version 4.04 Revision 1.06.842 (04/03/1998)", .internal_name = "d842_apr98", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_apr98.bin", "" } },
{ .name = "Version 4.04 Revision 1.07.842 (06/02/1998)", .internal_name = "d842_jun98", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.bin", "" } },
{ .name = "Version 1.03 Revision 1.09.842 (07/08/1996)", .internal_name = "d842_jul96", .bios_type = BIOS_NORMAL,
{ .name = "Version 4.04 Revision 1.07.842 (06/02/1998)", .internal_name = "d842_jun98", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.BIN", "" } },
{ .name = "Version 1.03 Revision 1.09.842 (07/08/1996)", .internal_name = "d842_jul96", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jul96.bin", "" } },
{ .name = "Version 1.03 Revision 1.10.842 (06/04/1998)", .internal_name = "d842_jun98_1", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } },
{ .name = "Version 1.03 Revision 1.10.842 (06/04/1998)", .internal_name = "d842_jun98_1", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } },
},
},
{ .name = "", .description = "", .type = CONFIG_END }
@@ -155,7 +154,7 @@ const device_t d842_device = {
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = &d842_config[0]

View File

@@ -628,25 +628,24 @@ machine_at_d943_init(const machine_t *model)
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init_ex(model, 2);
device_add(&amstrad_megapc_nvr_device);
machine_at_common_init_ex(model, 2);
device_add(&amstrad_megapc_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0);
pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 2, 4, 1);
pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 1, 3, 4);
pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 3, 2, 4);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0);
pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 2, 4, 1);
pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 1, 3, 4);
pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 3, 2, 4);
device_add(&i430hx_device);
device_add(&piix3_device);
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c665_device);
device_add(&intel_flash_bxt_device);
spd_register(SPD_TYPE_EDO, 0x7, 256);
if (gfxcard[0] == VID_INTERNAL)
spd_register(SPD_TYPE_EDO, 0x7, 256);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
if (sound_card_current[0] == SOUND_INTERNAL)
@@ -670,11 +669,10 @@ static const device_config_t d943_config[] = {
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct96.bin", "" } },
{ .name = "Version 4.05 Revision 1.03.943 (12/12/1996)", .internal_name = "d943_dec96", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_dec96.bin", "" } },
{ .name = "Version 4.05 Revision 1.05.943 (09/04/1997)", .internal_name = "d943_sept97", .bios_type = BIOS_NORMAL,
{ .name = "Version 4.05 Revision 1.05.943 (09/04/1997)", .internal_name = "d943_sept97", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_sept97.bin", "" } },
{ .name = "Version 4.05 Revision 1.06.943 (10/29/1997)", .internal_name = "d943_oct97", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct97.bin", "" } },
},
},
{ .name = "", .description = "", .type = CONFIG_END }
@@ -691,7 +689,7 @@ const device_t d943_device = {
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = &d943_config[0]

View File

@@ -782,9 +782,11 @@ static const device_config_t pcjr_config[] = {
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "RGB", .value = PCJR_RGB },
{ .description = "Composite", .value = PCJR_COMPOSITE },
{ .description = "" }
{ .description = "RGB", .value = PCJR_RGB },
{ .description = "Composite", .value = PCJR_COMPOSITE },
{ .description = "RGB (no brown)", .value = PCJR_RGB_NO_BROWN },
{ .description = "RGB (IBM 5153)", .value = PCJR_RGB_IBM_5153 },
{ .description = "" }
}
},
{

View File

@@ -39,6 +39,7 @@
#include <86box/keyboard.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/nvr.h>
#include <86box/chipset.h>
#include <86box/port_6x.h>
#include <86box/video.h>
@@ -668,6 +669,34 @@ machine_xt_amixt_init(const machine_t *model)
return ret;
}
int
machine_xt_tuliptc8_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/tuliptc8/tulip-bios_xt_compact_2.bin",
0x000fc000, 16384, 0);
if (bios_only || !ret)
return ret;
device_add(&keyboard_xt_fe2010_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
machine_common_init(model);
pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt);
nmi_init();
standalone_gameport_type = &gameport_device;
device_add(&amstrad_megapc_nvr_device);
return ret;
}
// TODO
// Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions)
// RTC

View File

@@ -71,6 +71,8 @@ extern const device_t d842_device;
extern const device_t d943_device;
extern const device_t dells333sl_device;
extern const device_t hot433a_device;
extern const device_t pbl300sx_device;
extern const device_t v12p_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -107,6 +109,7 @@ const machine_filter_t machine_chipsets[] = {
{ "Headland GC100A", MACHINE_CHIPSET_GC100A },
{ "Headland GC103", MACHINE_CHIPSET_GC103 },
{ "Headland HT18", MACHINE_CHIPSET_HT18 },
{ "ACC 2036", MACHINE_CHIPSET_ACC_2036 },
{ "ACC 2168", MACHINE_CHIPSET_ACC_2168 },
{ "ALi M1217", MACHINE_CHIPSET_ALI_M1217 },
{ "ALi M6117", MACHINE_CHIPSET_ALI_M6117 },
@@ -150,7 +153,9 @@ const machine_filter_t machine_chipsets[] = {
{ "OPTi 391", MACHINE_CHIPSET_OPTI_391 },
{ "OPTi 481", MACHINE_CHIPSET_OPTI_481 },
{ "OPTi 493", MACHINE_CHIPSET_OPTI_493 },
{ "OPTi 495", MACHINE_CHIPSET_OPTI_495 },
{ "OPTi 495SLC", MACHINE_CHIPSET_OPTI_495SLC },
{ "OPTi 495SX", MACHINE_CHIPSET_OPTI_495SX },
{ "OPTi 498", MACHINE_CHIPSET_OPTI_498 },
{ "OPTi 499", MACHINE_CHIPSET_OPTI_499 },
{ "OPTi 895/802G", MACHINE_CHIPSET_OPTI_895_802G },
{ "OPTi 547/597", MACHINE_CHIPSET_OPTI_547_597 },
@@ -2026,6 +2031,45 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{
.name = "[V20] Tulip PC Compact 2",
.internal_name = "tuliptc8",
.type = MACHINE_TYPE_8088,
.chipset = MACHINE_CHIPSET_DISCRETE,
.init = machine_xt_tuliptc8_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_8088,
.block = CPU_BLOCK(CPU_8088),
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PC,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 64,
.max = 640,
.step = 64
},
.nvrmask = 63,
.kbc_device = &keyboard_xtclone_device,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* 8086 Machines */
{
@@ -3098,7 +3142,7 @@ const machine_t machines[] = {
},
/* Has Olivetti KBC firmware. */
{
.name = "[ISA] Olivetti M290",
.name = "[ISA] Olivetti M290/AT&T 6286 WGS",
.internal_name = "m290",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_PROPRIETARY,
@@ -3120,7 +3164,7 @@ const machine_t machines[] = {
.bus_flags = MACHINE_AT,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 640,
.min = 1024,
.max = 16384,
.step = 128
},
@@ -3417,6 +3461,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC
firmware. */
{
.name = "[C&T PC/AT] PC's Limited (Dell) 28608L/AT122",
.internal_name = "at122",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_CT_AT,
.init = machine_at_at122_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.block = CPU_BLOCK_NONE,
.min_bus = 6000000,
.max_bus = 12000000,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 640,
.max = 16384,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC
firmware. */
{
@@ -3897,6 +3982,45 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{
.name = "[SCAT] ICL DRS M35/286",
.internal_name = "drsm35286",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_SCAT,
.init = machine_at_drsm35286_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2,
.flags = MACHINE_IDE | MACHINE_VIDEO,
.ram = {
.min = 512,
.max = 5120,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5401_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/2 Type 1 KBC firmware. */
{
.name = "[SCAT] Samsung SPC-4200P",
@@ -4301,6 +4425,46 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Most likely has Phonenix KBC firmware. */
{
.name = "[ACC 2036] Packard Bell Legend 300SX",
.internal_name = "pbl300sx",
.type = MACHINE_TYPE_386SX,
.chipset = MACHINE_CHIPSET_ACC_2036,
.init = machine_at_pbl300sx_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386SX,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2,
.flags = MACHINE_IDE | MACHINE_VIDEO,
.ram = {
.min = 1024,
.max = 16384,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = &pbl300sx_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &oti037_pbl300sx_device,
.snd_device = NULL,
.net_device = NULL
},
/* This has an AMIKey-2, which is an updated version of type 'H'. */
{
.name = "[ALi M1217] Acrosser AR-B1374",
@@ -5717,10 +5881,10 @@ const machine_t machines[] = {
but the BIOS sends commands C9 without a parameter and D5, both of which are
Phoenix MultiKey commands. */
{
.name = "[OPTi 495] U-Board OPTi 495SLC",
.name = "[OPTi 495SLC] U-Board OPTi 495SLC",
.internal_name = "award495",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_OPTI_495,
.chipset = MACHINE_CHIPSET_OPTI_495SLC,
.init = machine_at_opti495_init,
.p1_handler = NULL,
.gpio_handler = NULL,
@@ -5959,12 +6123,52 @@ const machine_t machines[] = {
},
/* 386DX/486 machines */
/* Has AMIKey F KBC firmware. The EFAR chipst is a rebrand of OPTi 495SX. */
{
.name = "[OPTi 495SX] CAF Technology C747",
.internal_name = "c747",
.type = MACHINE_TYPE_386DX_486,
.chipset = MACHINE_CHIPSET_OPTI_495SX,
.init = machine_at_c747_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386DX | CPU_PKG_SOCKET1,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_APM | MACHINE_IDE,
.ram = {
.min = 1024,
.max = 32768,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey F KBC firmware. */
{
.name = "[OPTi 495] DataExpert SX495",
.name = "[OPTi 495SX] DataExpert SX495",
.internal_name = "ami495",
.type = MACHINE_TYPE_386DX_486,
.chipset = MACHINE_CHIPSET_OPTI_495,
.chipset = MACHINE_CHIPSET_OPTI_495SX,
.init = machine_at_opti495_ami_init,
.p1_handler = NULL,
.gpio_handler = NULL,
@@ -6001,10 +6205,10 @@ const machine_t machines[] = {
},
/* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */
{
.name = "[OPTi 495] DataExpert SX495 (MR BIOS)",
.name = "[OPTi 495SX] DataExpert SX495 (MR BIOS)",
.internal_name = "mr495",
.type = MACHINE_TYPE_386DX_486,
.chipset = MACHINE_CHIPSET_OPTI_495,
.chipset = MACHINE_CHIPSET_OPTI_495SX,
.init = machine_at_opti495_mr_init,
.p1_handler = NULL,
.gpio_handler = NULL,
@@ -6326,10 +6530,10 @@ const machine_t machines[] = {
/* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix
copyright. */
{
.name = "[OPTi 495] Mylex MVI486",
.name = "[OPTi 498] Mylex MVI486",
.internal_name = "mvi486",
.type = MACHINE_TYPE_486,
.chipset = MACHINE_CHIPSET_OPTI_495,
.chipset = MACHINE_CHIPSET_OPTI_498,
.init = machine_at_mvi486_init,
.p1_handler = NULL,
.gpio_handler = NULL,
@@ -6485,6 +6689,46 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has Phoenix KBC firmware. */
{
.name = "[SiS 471] AST Advantage! 40xxd",
.internal_name = "advantage40xxd",
.type = MACHINE_TYPE_486,
.chipset = MACHINE_CHIPSET_SIS_471,
.init = machine_at_advantage40xxd_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET1,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 2
},
.bus_flags = MACHINE_PS2_VLB,
.flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM,
.ram = {
.min = 4096,
.max = 36864,
.step = 4096
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5424_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey F KBC firmware. */
{
.name = "[Symphony SL42C460] DTK PKM-0031Y",
@@ -6975,6 +7219,45 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{
.name = "[OPTi 499] Alaris Cobalt LPX",
.internal_name = "cobalt",
.type = MACHINE_TYPE_486_S2,
.chipset = MACHINE_CHIPSET_OPTI_499,
.init = machine_at_cobalt_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET3 | CPU_PKG_486BL,
.block = CPU_BLOCK(CPU_P24T),
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2_VLB,
.flags = MACHINE_APM | MACHINE_VIDEO | MACHINE_IDE_DUAL,
.ram = {
.min = 1024,
.max = 65536,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5428_vlb_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey-2 'H' KBC firmware. */
{
.name = "[OPTi 499] Alaris COUGAR 486BL",
@@ -9775,6 +10058,45 @@ const machine_t machines[] = {
/* Socket 4 machines */
/* 430LX */
{
.name = "[i430LX] Acer V12P",
.internal_name = "v12p",
.type = MACHINE_TYPE_SOCKET4,
.chipset = MACHINE_CHIPSET_INTEL_430LX,
.init = machine_at_v12p_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET4,
.block = CPU_BLOCK_NONE,
.min_bus = 60000000,
.max_bus = 66666667,
.min_voltage = 5000,
.max_voltage = 5000,
.min_multi = MACHINE_MULTIPLIER_FIXED,
.max_multi = MACHINE_MULTIPLIER_FIXED
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE | MACHINE_APM,
.ram = {
.min = 2048,
.max = 196608,
.step = 2048
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = &v12p_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey H KBC firmware (AMIKey-2), per POST screen with BIOS string
shown in the manual. Has PS/2 mouse support with serial-style (DB9)
connector.
@@ -11968,7 +12290,7 @@ const machine_t machines[] = {
.ram = {
.min = 8192,
.max = 131072,
.step = 8192
.step = 4096
},
.nvrmask = 511,
.kbc_device = NULL,

View File

@@ -29,6 +29,7 @@
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/plat.h>
#include <86box/plat_fallthrough.h>
#define FLAG_WORD 4
#define FLAG_BXB 2
@@ -44,21 +45,22 @@ enum {
};
enum {
CMD_SET_READ = 0x00,
CMD_READ_SIGNATURE = 0x90,
CMD_ERASE = 0x20,
CMD_ERASE_CONFIRM = 0x20,
CMD_ERASE_VERIFY = 0xA0,
CMD_PROGRAM = 0x40,
CMD_PROGRAM_VERIFY = 0xC0,
CMD_RESET = 0xFF
CMD_SET_READ = 0x00,
CMD_READ_AUTO_SELECT = 0x80,
CMD_READ_SIGNATURE = 0x90,
CMD_ERASE = 0x20,
CMD_ERASE_CONFIRM = 0x20,
CMD_ERASE_VERIFY = 0xA0,
CMD_PROGRAM = 0x40,
CMD_PROGRAM_VERIFY = 0xC0,
CMD_RESET = 0xFF
};
typedef struct flash_t {
uint8_t command;
uint8_t is_amd;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t *array;
mem_mapping_t mapping;
@@ -83,11 +85,22 @@ flash_read(uint32_t addr, void *priv)
ret = dev->array[addr];
break;
case CMD_READ_AUTO_SELECT:
if (!dev->is_amd)
break;
fallthrough;
case CMD_READ_SIGNATURE:
if (addr == 0x00000)
ret = 0x31; /* CATALYST */
else if (addr == 0x00001)
ret = 0xB4; /* 28F010 */
if (dev->is_amd) {
if (addr == 0x00000)
ret = 0x01; /* AMD */
else if (addr == 0x00001)
ret = 0xa7; /* Am28F010 */
} else {
if (addr == 0x00000)
ret = 0x31; /* CATALYST */
else if (addr == 0x00001)
ret = 0xb4; /* 28F010 */
}
break;
default:
@@ -205,6 +218,7 @@ catalyst_flash_init(UNUSED(const device_t *info))
catalyst_flash_add_mappings(dev);
dev->command = CMD_RESET;
dev->is_amd = info->local;
fp = nvr_fopen(flash_path, "rb");
if (fp) {
@@ -244,3 +258,17 @@ const device_t catalyst_flash_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t amd_am28f010_flash_device = {
.name = "AMD Am28F010-D Flash BIOS",
.internal_name = "amd_am28f010_flash",
.flags = DEVICE_PCI,
.local = 1,
.init = catalyst_flash_init,
.close = catalyst_flash_close,
.reset = catalyst_flash_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -67,7 +67,9 @@ mem_mapping_t bios_mapping;
mem_mapping_t bios_high_mapping;
page_t *pages; /* RAM page table */
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
page_t **page_lookup; /* pagetable lookup */
#endif
uint32_t pages_sz; /* #pages in table */
uint8_t *ram; /* the virtual RAM */
@@ -85,12 +87,23 @@ uint8_t *pccache2;
int readlnext;
int readlookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
uintptr_t *readlookup2;
#endif
uintptr_t old_rl2;
uint8_t uncached = 0;
int writelnext;
int writelookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
uintptr_t *writelookup2;
#endif
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
/* The lookup tables. */
page_t *page_lookup[1048576] = { 0 };
uintptr_t readlookup2[1048576] = { 0 };
uintptr_t writelookup2[1048576] = { 0 };
#endif
uint32_t mem_logical_addr;
@@ -2987,12 +3000,25 @@ mem_init(void)
ram2 = NULL;
pages = NULL;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
/* Allocate the lookup tables. */
page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *));
readlookup2 = malloc((1 << 20) * sizeof(uintptr_t));
writelookup2 = malloc((1 << 20) * sizeof(uintptr_t));
#endif
}
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
void
mem_free(void)
{
free(page_lookup);
free(readlookup2);
free(writelookup2);
}
#endif
static void
umc_page_recalc(uint32_t c, uint32_t phys, int set)
{

View File

@@ -70,5 +70,14 @@ if (UNIX)
endif()
endif()
endif()
if (UNIX AND NOT APPLE) # Support for TAP on Linux and BSD, supposedly.
find_path(HAS_TAP "linux/if_tun.h" PATHS ${TAP_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" )
if(HAS_TAP)
add_compile_definitions(HAS_TAP)
list(APPEND net_sources net_tap.c)
else()
message(WARNING "TAP support not available. Are you on some BSD?")
endif()
endif()
add_library(net OBJECT ${net_sources})

View File

@@ -488,15 +488,18 @@ plip_close(void *priv)
}
const lpt_device_t lpt_plip_device = {
.name = "Parallel Line Internet Protocol",
.internal_name = "plip",
.init = plip_lpt_init,
.close = plip_close,
.write_data = plip_write_data,
.write_ctrl = plip_write_ctrl,
.read_data = NULL,
.read_status = plip_read_status,
.read_ctrl = NULL
.name = "Parallel Line Internet Protocol",
.internal_name = "plip",
.init = plip_lpt_init,
.close = plip_close,
.write_data = plip_write_data,
.write_ctrl = plip_write_ctrl,
.autofeed = NULL,
.strobe = NULL,
.read_status = plip_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
const device_t plip_device = {

353
src/network/net_tap.c Normal file
View File

@@ -0,0 +1,353 @@
/*
* 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.
*
* Linux TAP network interface for 86box.
*
* This file was created by looking at the VDE network backend
* as a reference, credit to jguillaumes.
*
* Authors: Doug Johnson <dougvj@gmail.com>
*
*
* Copyright 2023 Doug Johnson
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef _WIN32
# error TAP networking is only supported on Linux
#endif
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdbool.h>
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_arp.h>
#include <linux/sockios.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/network.h>
#include <86box/net_event.h>
typedef struct net_tap_t {
int fd; // tap device file descriptor
netcard_t *card;
thread_t *poll_tid;
net_evt_t tx_event;
net_evt_t stop_event;
netpkt_t pkt_rx;
netpkt_t pkts_tx[NET_QUEUE_LEN];
} net_tap_t;
#ifdef ENABLE_TAP_LOG
int tap_do_log = ENABLE_TAP_LOG;
static void tap_logv(const char *fmt, va_list ap)
{
if (tap_do_log) {
pclog_ex(fmt, ap);
}
}
static void tap_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (tap_do_log) {
va_start(ap, fmt);
tap_logv(fmt, ap);
va_end(ap);
}
va_end(ap);
}
#else
# define tap_log(...) \
do { \
} while (0)
# define tap_logv(...) \
do { \
} while (0)
#endif
static void net_tap_thread(void *priv) {
enum {
NET_EVENT_STOP = 0,
NET_EVENT_TX,
NET_EVENT_RX,
NET_EVENT_TAP,
NET_EVENT_MAX,
};
net_tap_t *tap = priv;
tap_log("TAP: poll thread started.\n");
struct pollfd pfd[NET_EVENT_MAX];
pfd[NET_EVENT_STOP].fd = net_event_get_fd(&tap->stop_event);
pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TX].fd = net_event_get_fd(&tap->tx_event);
pfd[NET_EVENT_TX].events = POLLIN | POLLPRI;
pfd[NET_EVENT_RX].fd = tap->fd;
pfd[NET_EVENT_RX].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TAP].fd = tap->fd;
pfd[NET_EVENT_TAP].events = POLLERR | POLLHUP | POLLPRI;
fcntl(tap->fd, F_SETFL, O_NONBLOCK);
while(1) {
ssize_t ret = poll(pfd, NET_EVENT_MAX, -1);
if (ret < 0) {
tap_log("TAP: poll error: %s\n", strerror(errno));
net_event_set(&tap->stop_event);
break;
}
if (pfd[NET_EVENT_TAP].revents) {
tap_log("TAP: tap close/error event received.\n");
net_event_set(&tap->stop_event);
}
if (pfd[NET_EVENT_TX].revents & POLLIN) {
net_event_clear(&tap->tx_event);
int packets = network_tx_popv(tap->card, tap->pkts_tx,
NET_QUEUE_LEN);
for(int i = 0; i < packets; i++) {
netpkt_t *pkt = &tap->pkts_tx[i];
ssize_t ret = write(tap->fd, pkt->data, pkt->len);
if (ret < 0) {
tap_log("TAP: write error: %s\n", strerror(errno));
}
}
}
if (pfd[NET_EVENT_RX].revents & POLLIN) {
ssize_t len = read(tap->fd, tap->pkt_rx.data, NET_MAX_FRAME);
if (len < 0) {
tap_log("TAP: read error: %s\n", strerror(errno));
continue;
}
tap->pkt_rx.len = len;
network_rx_put_pkt(tap->card, &tap->pkt_rx);
}
if (pfd[NET_EVENT_STOP].revents & POLLIN) {
net_event_clear(&tap->stop_event);
break;
}
}
}
void net_tap_close(void *priv)
{
if (!priv) {
return;
}
net_tap_t *tap = priv;
tap_log("TAP: closing.\n");
net_event_set(&tap->stop_event);
tap_log("TAP: waiting for poll thread to exit.\n");
thread_wait(tap->poll_tid);
tap_log("TAP: poll thread exited.\n");
for(int i = 0; i < NET_QUEUE_LEN; i++) {
free(tap->pkts_tx[i].data);
}
free(tap->pkt_rx.data);
if (tap->fd >= 0) {
close(tap->fd);
}
free(tap);
}
void net_tap_error(char *errbuf, const char* format, ...)
{
va_list ap;
va_start(ap, format);
vsnprintf(errbuf, NET_DRV_ERRBUF_SIZE, format, ap);
tap_log("TAP: %s", errbuf);
va_end(ap);
}
// Error handling macro for the many ioctl calls we use in net_tap_alloc
#define ioctl_or_fail(fd, request, argp) \
do { \
if ((err = ioctl(fd, request, argp)) < 0) { \
tap_log("TAP: ioctl " #request " error: %s\n", strerror(errno)); \
goto fail; \
} \
} while (0)
// Returns -ERRNO so we can get an idea what's wrong
int net_tap_alloc(const uint8_t *mac_addr, const char* bridge_dev)
{
int fd;
struct ifreq ifr = {0};
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
tap_log("TAP: open error: %s\n", strerror(errno));
return -errno;
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
int err;
if ((err = ioctl(fd, TUNSETIFF, &ifr)) < 0) {
tap_log("TAP: ioctl TUNSETIFF error: %s\n", strerror(errno));
close(fd);
return -errno;
}
// Create a socket for ioctl operations
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
tap_log("TAP: socket error: %s\n", strerror(errno));
close(fd);
return -errno;
}
// Bring the interface up
tap_log("TAP: Bringing interface '%s' up.\n", ifr.ifr_name);
ifr.ifr_flags = IFF_UP;
ioctl_or_fail(sock, SIOCSIFFLAGS, &ifr);
// Add interface to bridge, if specified
if (bridge_dev && bridge_dev[0] != '\0') {
// First see if the bridge exists
struct ifreq ifr_bridge;
//NOTE strncpy does not null terminate if the string is too long, I use
// snprintf or strlcpy instead
//strncpy(ifr_bridge.ifr_name, bridge_dev, IFNAMSIZ);
snprintf(ifr_bridge.ifr_name, IFNAMSIZ, "%s", bridge_dev);
if ((err = ioctl(sock, SIOCGIFINDEX, &ifr_bridge)) < 0) {
if (errno != ENODEV) {
tap_log("TAP: ioctl SIOCGIFINDEX error: %s\n", strerror(errno));
goto fail;
} else {
// Create the bridge
ioctl_or_fail(sock, SIOCBRADDBR, &ifr_bridge);
// Set the bridge up
ifr_bridge.ifr_flags = IFF_UP;
ioctl_or_fail(sock, SIOCSIFFLAGS, &ifr_bridge);
}
}
// Get TAP index
ioctl_or_fail(sock, SIOCGIFINDEX, &ifr);
// Add the tap device to the bridge
ifr_bridge.ifr_ifindex = ifr.ifr_ifindex;
ioctl_or_fail(sock, SIOCBRADDIF, &ifr_bridge);
}
// close the socket we used for ioctl operations
close(sock);
tap_log("Allocated tap device %s\n", ifr.ifr_name);
return fd;
// cleanup point used by ioctl_or_fail macro
fail:
close(sock);
close(fd);
return -errno;
}
void net_tap_in_available(void *priv)
{
net_tap_t *tap = priv;
net_event_set(&tap->tx_event);
}
void *
net_tap_init(
const netcard_t *card,
const uint8_t *mac_addr,
void *priv,
char *netdrv_errbuf)
{
const char *bridge_dev = (void *) priv;
int tap_fd = net_tap_alloc(mac_addr, bridge_dev);
if (tap_fd < 0) {
if (tap_fd == -EPERM) {
net_tap_error(
netdrv_errbuf,
"No permissions to allocate tap device. "
"Try adding NET_CAP_ADMIN,NET_CAP_RAW to 86box ("
"sudo setcap 'CAP_NET_RAW,CAP_NET_ADMIN=eip')");
} else {
net_tap_error(
netdrv_errbuf,
"Unable to allocate TAP device: %s",
strerror(-tap_fd));
}
return NULL;
}
if (bridge_dev && bridge_dev[0] != '\0') {
}
net_tap_t *tap = calloc(1, sizeof(net_tap_t));
if (!tap) {
goto alloc_fail;
}
tap->pkt_rx.data = calloc(1, NET_MAX_FRAME);
if (!tap->pkt_rx.data) {
goto alloc_fail;
}
for(int i = 0; i < NET_QUEUE_LEN; i++) {
tap->pkts_tx[i].data = calloc(1, NET_MAX_FRAME);
if (!tap->pkts_tx[i].data) {
goto alloc_fail;
}
}
tap->fd = tap_fd;
tap->card = (netcard_t *) card;
net_event_init(&tap->tx_event);
net_event_init(&tap->stop_event);
tap->poll_tid = thread_create(net_tap_thread, tap);
return tap;
alloc_fail:
net_tap_error(netdrv_errbuf, "Failed to allocate memory");
close(tap_fd);
free(tap);
return NULL;
}
const netdrv_t net_tap_drv = {
&net_tap_in_available,
&net_tap_init,
&net_tap_close,
NULL
};

View File

@@ -85,36 +85,43 @@ static const NETWORK_CARD net_cards[] = {
// clang-format off
{ &device_none },
{ &device_internal },
/* ISA */
{ &threec501_device },
{ &threec503_device },
{ &pcnet_am79c960_device },
{ &pcnet_am79c961_device },
{ &de220p_device },
{ &ne1000_compat_device },
{ &ne2000_compat_device },
{ &ne2000_compat_8bit_device },
{ &ne1000_device },
{ &ne2000_device },
{ &pcnet_am79c960_eb_device },
{ &rtl8019as_pnp_device },
{ &wd8003e_device },
{ &wd8003eb_device },
{ &wd8013ebt_device },
/* COM */
{ &modem_device },
/* LPT */
{ &plip_device },
/* ISA16 */
{ &pcnet_am79c960_device },
{ &pcnet_am79c961_device },
{ &de220p_device },
{ &ne2000_compat_device },
{ &ne2000_device },
{ &pcnet_am79c960_eb_device },
{ &rtl8019as_pnp_device },
/* MCA */
{ &ethernext_mc_device },
{ &wd8003eta_device },
{ &wd8003ea_device },
{ &wd8013epa_device },
/* VLB */
{ &pcnet_am79c960_vlb_device },
/* PCI */
{ &pcnet_am79c973_device },
{ &pcnet_am79c970a_device },
{ &dec_tulip_21140_device },
{ &dec_tulip_21040_device },
{ &dec_tulip_device },
{ &dec_tulip_21140_vpc_device },
{ &rtl8029as_device },
{ &rtl8139c_plus_device },
{ &dec_tulip_21140_device },
{ &dec_tulip_21140_vpc_device },
{ &dec_tulip_21040_device },
{ &pcnet_am79c960_vlb_device },
{ &modem_device },
{ NULL }
// clang-format on
};
@@ -489,6 +496,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
card->host_drv = net_vde_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error);
break;
#endif
#ifdef HAS_TAP
case NET_TYPE_TAP:
card->host_drv = net_tap_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error);
break;
#endif
default:
card->host_drv.priv = NULL;

View File

@@ -310,18 +310,25 @@ nvr_close(void)
void
nvr_time_sync(void)
{
struct tm *tm;
time_t now;
struct tm tm;
time_t now;
/* Get the current time of day, and convert to local time. */
(void) time(&now);
if (time_sync & TIME_SYNC_UTC)
tm = gmtime(&now);
else
tm = localtime(&now);
/* Set the internal clock. */
nvr_time_set(tm);
#ifdef _WIN32
if (time_sync & TIME_SYNC_UTC)
gmtime_s(&tm, &now);
else
localtime_s(&tm, &now);
#else
if (time_sync & TIME_SYNC_UTC)
gmtime_r(&now, &tm);
else
localtime_r(&now, &tm);
#endif
nvr_time_set(&tm);
}
/* Get current time from internal clock. */

View File

@@ -1881,6 +1881,39 @@ write_data(uint8_t val, void *priv)
dev->data = val;
}
static void
autofeed(uint8_t val, void *priv)
{
escp_t *dev = (escp_t *) priv;
if (dev == NULL)
return;
dev->autofeed = ((val & 0x02) > 0);
}
static void
strobe(uint8_t old, uint8_t val, void *priv)
{
escp_t *dev = (escp_t *) priv;
if (dev == NULL)
return;
/* Data is strobed to the parallel printer on the falling edge of the
strobe bit. */
if (!(val & 0x01) && (old & 0x01)) {
/* Process incoming character. */
handle_char(dev, dev->data);
/* ACK it, will be read on next READ STATUS. */
dev->ack = 1;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
write_ctrl(uint8_t val, void *priv)
{
@@ -1919,14 +1952,6 @@ write_ctrl(uint8_t val, void *priv)
dev->autofeed = ((val & 0x02) > 0);
}
static uint8_t
read_data(void *priv)
{
const escp_t *dev = (escp_t *) priv;
return dev->data;
}
static uint8_t
read_ctrl(void *priv)
{
@@ -2058,13 +2083,16 @@ escp_close(void *priv)
}
const lpt_device_t lpt_prt_escp_device = {
.name = "Generic ESC/P Dot-Matrix Printer",
.internal_name = "dot_matrix",
.init = escp_init,
.close = escp_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.read_data = read_data,
.read_status = read_status,
.read_ctrl = read_ctrl
.name = "Generic ESC/P Dot-Matrix",
.internal_name = "dot_matrix",
.init = escp_init,
.close = escp_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.autofeed = autofeed,
.strobe = strobe,
.read_status = read_status,
.read_ctrl = read_ctrl,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -319,6 +319,35 @@ process_data(ps_t *dev)
dev->buffer[dev->buffer_pos] = 0;
}
static void
ps_autofeed(uint8_t val, void *priv)
{
ps_t *dev = (ps_t *) priv;
if (dev == NULL)
return;
dev->autofeed = val & 0x02 ? true : false;
}
static void
ps_strobe(uint8_t old, uint8_t val, void *priv)
{
ps_t *dev = (ps_t *) priv;
if (dev == NULL)
return;
if (!(val & 0x01) && (old & 0x01)) {
process_data(dev);
dev->ack = true;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
ps_write_ctrl(uint8_t val, void *priv)
{
@@ -479,27 +508,33 @@ ps_close(void *priv)
}
const lpt_device_t lpt_prt_ps_device = {
.name = "Generic PostScript Printer",
.internal_name = "postscript",
.init = ps_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.read_data = NULL,
.read_status = ps_read_status,
.read_ctrl = NULL
.name = "Generic PostScript Printer",
.internal_name = "postscript",
.init = ps_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.autofeed = ps_autofeed,
.strobe = ps_strobe,
.read_status = ps_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
#ifdef USE_PCL
const lpt_device_t lpt_prt_pcl_device = {
.name = "Generic PCL5e Printer",
.internal_name = "pcl",
.init = pcl_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.read_data = NULL,
.read_status = ps_read_status,
.read_ctrl = NULL
.name = "Generic PCL5e Printer",
.internal_name = "pcl",
.init = pcl_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.autofeed = ps_autofeed,
.strobe = ps_strobe,
.read_status = ps_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
#endif

View File

@@ -367,6 +367,38 @@ write_data(uint8_t val, void *priv)
dev->data = val;
}
static void
autofeed(uint8_t val, void *priv)
{
prnt_t *dev = (prnt_t *) priv;
if (dev == NULL)
return;
/* set autofeed value */
dev->autofeed = val & 0x02 ? 1 : 0;
}
static void
strobe(uint8_t old, uint8_t val, void *priv)
{
prnt_t *dev = (prnt_t *) priv;
if (dev == NULL)
return;
if (!(val & 0x01) && (old & 0x01)) { /* STROBE */
/* Process incoming character. */
handle_char(dev);
/* ACK it, will be read on next READ STATUS. */
dev->ack = 1;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
write_ctrl(uint8_t val, void *priv)
{
@@ -465,13 +497,16 @@ prnt_close(void *priv)
}
const lpt_device_t lpt_prt_text_device = {
.name = "Generic Text Printer",
.internal_name = "text_prt",
.init = prnt_init,
.close = prnt_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.read_data = NULL,
.read_status = read_status,
.read_ctrl = NULL
.name = "Generic Text Printer",
.internal_name = "text_prt",
.init = prnt_init,
.close = prnt_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.autofeed = autofeed,
.strobe = strobe,
.read_status = read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -85,8 +85,6 @@ add_library(ui STATIC
qt_renderercommon.hpp
qt_softwarerenderer.cpp
qt_softwarerenderer.hpp
qt_hardwarerenderer.cpp
qt_hardwarerenderer.hpp
qt_openglrenderer.cpp
qt_openglrenderer.hpp
qt_glsl_parser.cpp
@@ -189,6 +187,49 @@ add_library(ui STATIC
qt_mediahistorymanager.cpp
qt_mediahistorymanager.hpp
qt_updatecheck.cpp
qt_updatecheck.hpp
qt_updatecheckdialog.cpp
qt_updatecheckdialog.hpp
qt_updatecheckdialog.ui
qt_updatedetails.cpp
qt_updatedetails.hpp
qt_updatedetails.ui
qt_downloader.cpp
qt_downloader.hpp
qt_vmmanager_clientsocket.cpp
qt_vmmanager_clientsocket.hpp
qt_vmmanager_serversocket.cpp
qt_vmmanager_serversocket.hpp
qt_vmmanager_protocol.cpp
qt_vmmanager_protocol.hpp
qt_vmmanager_details.hpp
qt_vmmanager_details.cpp
qt_vmmanager_details.ui
qt_vmmanager_addmachine.cpp
qt_vmmanager_addmachine.hpp
qt_vmmanager_detailsection.cpp
qt_vmmanager_detailsection.hpp
qt_vmmanager_detailsection.ui
qt_vmmanager_listviewdelegate.hpp
qt_vmmanager_listviewdelegate.cpp
qt_vmmanager_preferences.cpp
qt_vmmanager_preferences.hpp
qt_vmmanager_preferences.ui
qt_vmmanager_main.hpp
qt_vmmanager_main.cpp
qt_vmmanager_main.ui
qt_vmmanager_model.cpp
qt_vmmanager_model.hpp
qt_vmmanager_system.cpp
qt_vmmanager_system.hpp
qt_vmmanager_config.cpp
qt_vmmanager_config.hpp
qt_vmmanager_mainwindow.cpp
qt_vmmanager_mainwindow.hpp
qt_vmmanager_mainwindow.ui
../qt_resources.qrc
./qdarkstyle/dark/darkstyle.qrc

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Some files were not shown because too many files have changed in this diff Show More