This commit is contained in:
starfrost013
2025-06-24 11:51:53 +01:00
252 changed files with 14200 additions and 4529 deletions

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")) {
@@ -1027,6 +1034,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

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) + 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

@@ -212,7 +212,7 @@ isarom_init(const device_t *info)
static const device_config_t isarom_config[] = {
{
.name = "bios_fn",
.description = "BIOS File",
.description = "BIOS file",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -234,7 +234,7 @@ static const device_config_t isarom_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size:",
.description = "BIOS size",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -260,7 +260,7 @@ static const device_config_t isarom_config[] = {
static const device_config_t isarom_dual_config[] = {
{
.name = "bios_fn",
.description = "BIOS File (ROM #1)",
.description = "BIOS file (ROM #1)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -271,7 +271,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address (ROM #1)",
.description = "BIOS address (ROM #1)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -282,7 +282,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size (ROM #1):",
.description = "BIOS size (ROM #1)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -304,7 +304,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_fn2",
.description = "BIOS File (ROM #2)",
.description = "BIOS file (ROM #2)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -315,7 +315,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_addr2",
.description = "BIOS Address (ROM #2)",
.description = "BIOS address (ROM #2)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -326,7 +326,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_size2",
.description = "BIOS Size (ROM #2):",
.description = "BIOS size (ROM #2)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -352,7 +352,7 @@ static const device_config_t isarom_dual_config[] = {
static const device_config_t isarom_quad_config[] = {
{
.name = "bios_fn",
.description = "BIOS File (ROM #1)",
.description = "BIOS file (ROM #1)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -363,7 +363,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address (ROM #1)",
.description = "BIOS address (ROM #1)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -374,7 +374,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size (ROM #1):",
.description = "BIOS size (ROM #1)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -396,7 +396,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn2",
.description = "BIOS File (ROM #2)",
.description = "BIOS file (ROM #2)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -407,7 +407,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr2",
.description = "BIOS Address (ROM #2)",
.description = "BIOS address (ROM #2)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -418,7 +418,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size2",
.description = "BIOS Size (ROM #2):",
.description = "BIOS size (ROM #2)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -440,7 +440,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn3",
.description = "BIOS File (ROM #3)",
.description = "BIOS file (ROM #3)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -451,7 +451,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr3",
.description = "BIOS Address (ROM #3)",
.description = "BIOS address (ROM #3)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -462,7 +462,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size3",
.description = "BIOS Size (ROM #3):",
.description = "BIOS size (ROM #3)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -484,7 +484,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn4",
.description = "BIOS File (ROM #4)",
.description = "BIOS file (ROM #4)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -495,7 +495,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr4",
.description = "BIOS Address (ROM #4)",
.description = "BIOS address (ROM #4)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -506,7 +506,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size4",
.description = "BIOS Size (ROM #4):",
.description = "BIOS size (ROM #4)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,

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",

View File

@@ -109,7 +109,7 @@ static const device_config_t keycard_config[] = {
};
const device_t novell_keycard_device = {
.name = "Novell Netware 2.x Key Card",
.name = "Novell NetWare 2.x Key Card",
.internal_name = "mssystems",
.flags = DEVICE_ISA,
.local = 0,

View File

@@ -183,7 +183,7 @@ static const device_config_t monster_fdc_config[] = {
#if 0
{
.name = "bios_size",
.description = "BIOS Size:",
.description = "BIOS size",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 32,

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

@@ -0,0 +1,74 @@
/*
* 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.
*
* Header files for the PCjr keyboard and video subsystems.
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2025 starfrost
*/
#pragma once
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
#define PCJR_RGB_NO_BROWN 4
#define PCJR_RGB_IBM_5153 5
typedef struct pcjr_s
{
/* Video Controller stuff. */
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[32];
int array_ff;
int memctrl;
uint8_t status;
int addr_mode;
uint8_t *vram;
uint8_t *b8000;
int linepos;
int displine;
int scanline;
int vc;
int dispon;
int cursorvisible; // Is the cursor visible on the current scanline?
int cursoron;
int blink;
int vsynctime;
int fullchange;
int vadj;
uint16_t memaddr;
uint16_t memaddr_backup;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
int apply_hd;
/* Keyboard Controller stuff. */
int latched;
int data;
int serial_data[44];
int serial_pos;
uint8_t pa;
uint8_t pb;
pc_timer_t send_delay_timer;
} pcjr_t;
void pcjr_recalc_timings(pcjr_t *pcjr);
// Note: This is a temporary solution until the pcjr video is made its own gfx card
void pcjr_vid_init(pcjr_t *pcjr);

View File

@@ -0,0 +1,95 @@
/*
* 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.
*
* Header files for the Tandy keyboard and video subsystems.
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2025 starfrost
*/
typedef struct t1kvid_t {
mem_mapping_t mapping;
mem_mapping_t vram_mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[256];
int memctrl;
uint8_t mode;
uint8_t col;
uint8_t status;
uint8_t *vram;
uint8_t *b8000;
uint32_t b8000_mask;
uint32_t b8000_limit;
uint8_t planar_ctrl;
uint8_t lp_strobe;
int linepos;
int displine;
int scanline;
int vc;
int dispon;
int cursorvisible;
int cursoron;
int blink;
int fullchange;
int vsynctime;
int vadj;
uint16_t memaddr;
uint16_t memaddr_backup;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
} t1kvid_t;
typedef struct t1keep_t {
char *path;
int state;
int count;
int addr;
int clk;
uint16_t data;
uint16_t store[64];
} t1keep_t;
typedef struct tandy_t {
mem_mapping_t ram_mapping;
mem_mapping_t rom_mapping; /* SL2 */
uint8_t *rom; /* SL2 */
uint8_t ram_bank;
uint8_t rom_bank; /* SL2 */
int rom_offset; /* SL2 */
uint32_t base;
uint32_t mask;
int is_hx;
int is_sl2;
t1kvid_t *vid;
} tandy_t;
void tandy_vid_init(tandy_t* dev);
uint8_t tandy_vid_in(uint16_t addr, void* priv);
void tandy_vid_out(uint16_t addr, uint8_t val, void *priv);
void tandy_vid_close(void* priv);
void tandy_recalc_address_sl(tandy_t* dev); //this function is needed by both m_ and vid_tandy.c

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 *);
@@ -475,6 +479,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 *);
@@ -544,6 +549,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 +570,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 *);
@@ -973,6 +980,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

@@ -125,6 +125,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

@@ -80,7 +80,7 @@ typedef struct ibm8514_t {
uint32_t vram_mask;
uint32_t pallook[512];
uint32_t bios_addr;
uint32_t ma_latch;
uint32_t memaddr_latch;
PALETTE vgapal;
uint8_t hwcursor_oddeven;
@@ -220,8 +220,8 @@ typedef struct ibm8514_t {
int lastline_draw;
int displine;
int fullchange;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint8_t *vram;
uint8_t *changedvram;
@@ -236,7 +236,7 @@ typedef struct ibm8514_t {
int hdisp;
int hdisp2;
int hdisped;
int sc;
int scanline;
int vsyncstart;
int vsyncwidth;
int vtotal;

View File

@@ -137,6 +137,7 @@ typedef struct mach_t {
int16_t dx_end;
int16_t dy;
int16_t dy_end;
int16_t dx_first_row_start;
int16_t dx_start;
int16_t dy_start;
int16_t cy;

View File

@@ -11,7 +11,8 @@
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Miran Grca, <mgrca8@gmail.com>,
* Connor Hyde / starfrost, <mario64crashed@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
@@ -56,6 +57,7 @@ typedef enum cga_crtc_registers_e
CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, // Light pen address low 8 bits (not currently supported)
} cga_crtc_registers;
// Registers for the CGA
typedef enum cga_registers_e
{
CGA_REGISTER_CRTC_INDEX = 0x3D4,
@@ -85,16 +87,16 @@ typedef struct cga_t {
int fontbase;
int linepos;
int displine;
int sc;
int scanline;
int vc;
int cgadispon;
int con;
int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE.
int cursoron;
int cgablink;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int oddeven;
uint64_t dispontime;

View File

@@ -39,7 +39,7 @@ typedef struct ega_t {
uint8_t lb;
uint8_t lc;
uint8_t ld;
uint8_t stat;
uint8_t status;
uint8_t colourcompare;
uint8_t colournocare;
uint8_t scrblank;
@@ -68,12 +68,12 @@ typedef struct ega_t {
int chain4;
int chain2_read;
int chain2_write;
int con;
int cursorvisible;
int oddeven_page;
int oddeven_chain;
int vc;
int real_vc;
int sc;
int scanline;
int dispon;
int hdisp_on;
int cursoron;
@@ -115,14 +115,14 @@ typedef struct ega_t {
int chipset;
int mono_display;
int mdacols[256][2][2];
int mda_attr_to_color_table[256][2][2];
uint32_t charseta;
uint32_t charsetb;
uint32_t ma_latch;
uint32_t ma;
uint32_t maback;
uint32_t ca;
uint32_t memaddr_latch;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t cursoraddr;
uint32_t vram_limit;
uint32_t overscan_color;
uint32_t cca;
@@ -189,11 +189,11 @@ extern void ega_set_type(void *priv, uint32_t local);
extern int firstline_draw;
extern int lastline_draw;
extern int displine;
extern int sc;
extern int scanline;
extern uint32_t ma;
extern uint32_t ca;
extern int con;
extern uint32_t memaddr;
extern uint32_t cursoraddr;
extern int cursorvisible;
extern int cursoron;
extern int cgablink;

View File

@@ -33,9 +33,9 @@
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); \
out_addr = (out_addr & ~0x8000) | ((ega->scanline & 1) ? 0x8000 : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); \
out_addr = (out_addr & ~0x10000) | ((ega->scanline & 2) ? 0x10000 : 0); \
\
return out_addr; \
}

View File

@@ -13,10 +13,12 @@
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Connor Hyde / starfrost, <mario64crashed@gmail.com
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2021 Jasmine Iwanek.
* Copyright 2025 starfrost
*/
#ifndef VIDEO_HERCULES_H
@@ -31,7 +33,7 @@ typedef struct {
uint8_t ctrl;
uint8_t ctrl2;
uint8_t stat;
uint8_t status;
uint64_t dispontime;
uint64_t dispofftime;
@@ -43,20 +45,20 @@ typedef struct {
int linepos;
int displine;
int vc;
int sc;
uint16_t ma;
uint16_t maback;
int con;
int scanline;
uint16_t memaddr;
uint16_t memaddr_backup;
int cursorvisible;
int cursoron;
int dispon;
int blink;
int vsynctime;
int vadj;
int lp_ff;
int fullchange;
int lp_ff;
int fullchange;
int cols[256][2][2];
int cols[256][2][2];
uint8_t *vram;
int monitor_index;

View File

@@ -1,41 +1,123 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the IBM Monochrome Display and Printer card.
*
* Authors: Sarah Walker, starfrost
*
* Copyright 2007-2024 Sarah Walker
* Copyright 2025 Connor Hyde / starfrost, <mario64crashed@gmail.com>
*/
#ifndef VIDEO_MDA_H
#define VIDEO_MDA_H
// Defines
#define MDA_CRTC_NUM_REGISTERS 32
// Enums & structures
typedef enum mda_registers_e
{
MDA_REGISTER_START = 0x3B0,
MDA_REGISTER_CRTC_INDEX = 0x3B4,
MDA_REGISTER_CRTC_DATA = 0x3B5,
MDA_REGISTER_MODE_CONTROL = 0x3B8,
MDA_REGISTER_CRT_STATUS = 0x3BA,
MDA_REGISTER_PARALLEL_DATA = 0x3BC,
MDA_REGISTER_PRINTER_STATUS = 0x3BD,
MDA_REGISTER_PRINTER_CONTROL = 0x3BE,
MDA_REGISTER_END = 0x3BF,
} mda_registers;
// Motorola MC6845 CRTC registers (without light pen for some reason)
typedef enum mda_crtc_registers_e
{
MDA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync)
MDA_CRTC_HDISP = 0x1, // Horizontal display
MDA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc
MDA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync
MDA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync)
MDA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value
MDA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline)
MDA_CRTC_VSYNC = 0x7, // Vertical sync scanline number
MDA_CRTC_INTERLACE = 0x8, // Interlacing mode
MDA_CRTC_MAX_SCANLINE_ADDR = 0x9, // Maximum scanline address
MDA_CRTC_CURSOR_START = 0xA, // Cursor start scanline
MDA_CRTC_CURSOR_END = 0xB, // Cursor end scanline
MDA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits
MDA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits
MDA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits
MDA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor address low 8 bits
} mda_crtc_registers;
typedef enum mda_mode_flags_e
{
MDA_MODE_HIGHRES = 1 << 0, // MUST be enabled for sane operation
MDA_MODE_BW = 1 << 1, // UNUSED in most cases. Not present on Hercules
MDA_MODE_VIDEO_ENABLE = 1 << 3,
MDA_MODE_BLINK = 1 << 5,
} mda_mode_flags;
typedef enum mda_colors_e
{
MDA_COLOR_BLACK = 0,
MDA_COLOR_BLUE = 1,
MDA_COLOR_GREEN = 2,
MDA_COLOR_CYAN = 3,
MDA_COLOR_RED = 4,
MDA_COLOR_MAGENTA = 5,
MDA_COLOR_BROWN = 6,
MDA_COLOR_WHITE = 7,
MDA_COLOR_GREY = 8,
MDA_COLOR_BRIGHT_BLUE = 9,
MDA_COLOR_BRIGHT_GREEN = 10,
MDA_COLOR_BRIGHT_CYAN = 11,
MDA_COLOR_BRIGHT_RED = 12,
MDA_COLOR_BRIGHT_MAGENTA = 13,
MDA_COLOR_BRIGHT_YELLOW = 14,
MDA_COLOR_BRIGHT_WHITE = 15,
} mda_colors;
typedef struct mda_t {
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
uint8_t crtc[MDA_CRTC_NUM_REGISTERS];
int32_t crtcreg;
uint8_t ctrl;
uint8_t stat;
uint8_t mode;
uint8_t status;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int32_t firstline;
int32_t lastline;
int fontbase;
int linepos;
int displine;
int vc;
int sc;
uint16_t ma;
uint16_t maback;
int con;
int cursoron;
int dispon;
int blink;
int vsynctime;
int vadj;
int monitor_index;
int prev_monitor_index;
int32_t fontbase;
int32_t linepos;
int32_t displine;
int32_t vc;
int32_t scanline;
uint16_t memaddr;
uint16_t memaddr_backup;
int32_t cursorvisible;
int32_t cursoron;
int32_t dispon;
int32_t blink;
int32_t vsynctime;
int32_t vadj;
int32_t monitor_index;
int32_t prev_monitor_index;
int32_t monitor_type; // Used for MDA Colour support (REV0 u64)
uint8_t *vram;
} mda_t;

View File

@@ -115,13 +115,13 @@ typedef struct pgc {
int displine;
int vc;
int cgadispon;
int con;
int cursorvisible;
int cursoron;
int cgablink;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int oddeven;
uint64_t dispontime;

View File

@@ -100,12 +100,12 @@ typedef struct svga_t {
int dispon;
int hdisp_on;
int vc;
int sc;
int scanline;
int linepos;
int vslines;
int linecountff;
int oddeven;
int con;
int cursorvisible;
int cursoron;
int blink;
int scrollcache;
@@ -152,15 +152,15 @@ typedef struct svga_t {
uint32_t charseta;
uint32_t charsetb;
uint32_t adv_flags;
uint32_t ma_latch;
uint32_t memaddr_latch;
uint32_t ca_adj;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t write_bank;
uint32_t read_bank;
uint32_t extra_banks[2];
uint32_t banked_mask;
uint32_t ca;
uint32_t cursoraddr;
uint32_t overscan_color;
uint32_t *map8;
uint32_t pallook[512];

View File

@@ -23,11 +23,11 @@
extern int firstline_draw;
extern int lastline_draw;
extern int displine;
extern int sc;
extern int scanline;
extern uint32_t ma;
extern uint32_t ca;
extern int con;
extern uint32_t memaddr;
extern uint32_t cursoraddr;
extern int cursorvisible;
extern int cursoron;
extern int cgablink;

View File

@@ -47,9 +47,9 @@
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); \
out_addr = (out_addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); \
out_addr = (out_addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); \
\
return out_addr; \
}

View File

@@ -127,7 +127,7 @@ typedef struct xga_t {
int dispon;
int h_disp_on;
int vc;
int sc;
int scanline;
int linepos;
int oddeven;
int firstline;
@@ -160,12 +160,12 @@ typedef struct xga_t {
uint32_t hwc_color0;
uint32_t hwc_color1;
uint32_t disp_start_addr;
uint32_t ma_latch;
uint32_t memaddr_latch;
uint32_t vram_size;
uint32_t vram_mask;
uint32_t rom_addr;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t read_bank;
uint32_t write_bank;
uint32_t px_map_base;

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;
@@ -187,6 +188,10 @@ extern bitmap_t *buffer32;
#define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y)
#define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x)
#define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y)
#define CGAPAL_CGA_START 16 // Where the 16-color cga text/composite starts
extern PALETTE cgapal;
extern PALETTE cgapal_mono[6];
#if 0
@@ -359,6 +364,7 @@ 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;
@@ -395,6 +401,7 @@ extern const device_t gd5480_pci_device;
/* Compaq CGA */
extern const device_t compaq_cga_device;
extern const device_t compaq_cga_2_device;
extern const device_t compaq_plasma_device;
/* Olivetti OGC */
extern const device_t ogc_device;
@@ -467,6 +474,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;
@@ -613,6 +621,11 @@ extern const device_t nv3t_device_agp;
/* Wyse 700 */
extern const device_t wy700_device;
/* Tandy */
extern const device_t tandy_1000_video_device;
extern const device_t tandy_1000hx_video_device;
extern const device_t tandy_1000sl_video_device;
#endif
#endif /*EMU_VIDEO_H*/

View File

@@ -23,7 +23,6 @@ add_library(mch OBJECT
m_xt_laserxt.c
m_xt_philips.c
m_xt_t1000.c
m_xt_t1000_vid.c
m_xt_xi8088.c
m_xt_zenith.c
m_pcjr.c
@@ -37,7 +36,6 @@ add_library(mch OBJECT
m_at_commodore.c
m_at_grid.c
m_at_t3100e.c
m_at_t3100e_vid.c
m_ps1.c
m_ps1_hdc.c
m_ps2_isa.c

View File

@@ -105,7 +105,7 @@ typedef struct amsvid_t {
int cga_enabled; /* 1640 */
uint8_t cgacol;
uint8_t cgamode;
uint8_t stat;
uint8_t status;
uint8_t plane_write; /* 1512/200 */
uint8_t plane_read; /* 1512/200 */
uint8_t border; /* 1512/200 */
@@ -113,17 +113,17 @@ typedef struct amsvid_t {
int fontbase; /* 1512/200 */
int linepos;
int displine;
int sc;
int scanline;
int vc;
int cgadispon;
int con;
int cursorvisible;
int cursoron;
int cgablink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int dispon;
int blink;
uint64_t dispontime; /* 1512/1640 */
@@ -290,7 +290,7 @@ vid_in_1512(uint16_t addr, void *priv)
break;
case 0x03da:
ret = vid->stat;
ret = vid->status;
break;
default:
@@ -339,7 +339,7 @@ static void
vid_poll_1512(void *priv)
{
amsvid_t *vid = (amsvid_t *) priv;
uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
@@ -353,13 +353,13 @@ vid_poll_1512(void *priv)
uint16_t dat4;
int cols[4];
int col;
int oldsc;
int scanline_old;
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
vid->stat |= 1;
vid->status |= 1;
vid->linepos = 1;
oldsc = vid->sc;
scanline_old = vid->scanline;
if (vid->dispon) {
if (vid->displine < vid->firstline) {
vid->firstline = vid->displine;
@@ -369,26 +369,26 @@ vid_poll_1512(void *priv)
for (c = 0; c < 8; c++) {
if ((vid->cgamode & 0x12) == 0x12) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16;
}
}
}
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < 80; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
chr = vid->vram[(vid->memaddr<< 1) & 0x3fff];
attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff];
drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron);
if (vid->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
@@ -399,21 +399,23 @@ vid_poll_1512(void *priv)
}
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
vid->ma++;
vid->memaddr++;
}
} else if (!(vid->cgamode & 2)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < 40; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
chr = vid->vram[(vid->memaddr<< 1) & 0x3fff];
attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff];
drawcursor = ((vid->memaddr == cursoraddr)
&& vid->cursorvisible && vid->cursoron);
if (vid->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80))
@@ -422,21 +424,21 @@ vid_poll_1512(void *priv)
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
vid->ma++;
vid->memaddr++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else if (!(vid->cgamode & 16)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
cols[0] = (vid->cgacol & 15) | 16;
col = (vid->cgacol & 16) ? 24 : 16;
if (vid->cgamode & 4) {
if (vid->cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
@@ -450,8 +452,8 @@ vid_poll_1512(void *priv)
cols[3] = col | 6;
}
for (x = 0; x < 40; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
dat = (vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) | vid->vram[((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1];
vid->memaddr++;
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
@@ -459,13 +461,13 @@ vid_poll_1512(void *priv)
}
} else {
for (x = 0; x < 40; x++) {
ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000);
dat = (vid->vram[ca] << 8) | vid->vram[ca + 1];
dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001];
dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001];
dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001];
cursoraddr = ((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000);
dat = (vid->vram[cursoraddr] << 8) | vid->vram[cursoraddr + 1];
dat2 = (vid->vram[cursoraddr + 0x4000] << 8) | vid->vram[cursoraddr + 0x4001];
dat3 = (vid->vram[cursoraddr + 0x8000] << 8) | vid->vram[cursoraddr + 0x8001];
dat4 = (vid->vram[cursoraddr + 0xc000] << 8) | vid->vram[cursoraddr + 0xc001];
vid->ma++;
vid->memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16;
dat <<= 1;
@@ -477,7 +479,7 @@ vid_poll_1512(void *priv)
}
} else {
cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]);
} else {
@@ -486,7 +488,7 @@ vid_poll_1512(void *priv)
}
}
if (vid->cgamode & 1)
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
@@ -494,9 +496,9 @@ vid_poll_1512(void *priv)
video_process_8(x, vid->displine << 1);
video_process_8(x, (vid->displine << 1) + 1);
vid->sc = oldsc;
vid->scanline = scanline_old;
if (vid->vsynctime)
vid->stat |= 8;
vid->status |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
@@ -505,29 +507,29 @@ vid_poll_1512(void *priv)
if ((vid->lastline - vid->firstline) == 199)
vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
if (vid->dispon)
vid->stat &= ~1;
vid->status &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (!vid->vsynctime)
vid->stat &= ~8;
vid->status &= ~8;
}
if (vid->sc == (vid->crtc[11] & 31)) {
vid->con = 0;
if (vid->scanline == (vid->crtc[11] & 31)) {
vid->cursorvisible = 0;
}
if (vid->vadj) {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->scanline++;
vid->scanline &= 31;
vid->memaddr= vid->memaddr_backup;
vid->vadj--;
if (!vid->vadj) {
vid->dispon = 1;
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->sc = 0;
vid->memaddr= vid->memaddr_backup = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->scanline = 0;
}
} else if (vid->sc == vid->crtc[9]) {
vid->maback = vid->ma;
vid->sc = 0;
} else if (vid->scanline == vid->crtc[9]) {
vid->memaddr_backup = vid->memaddr;
vid->scanline = 0;
vid->vc++;
vid->vc &= 127;
@@ -545,7 +547,7 @@ vid_poll_1512(void *priv)
vid->displine = 0;
vid->vsynctime = 46;
if (vid->cgamode & 1)
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
@@ -582,15 +584,15 @@ vid_poll_1512(void *priv)
video_res_x = xsize;
video_res_y = ysize;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->cgamode & 2)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->cgamode & 16)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else {
@@ -602,12 +604,12 @@ vid_poll_1512(void *priv)
vid->blink++;
}
} else {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->scanline++;
vid->scanline &= 31;
vid->memaddr= vid->memaddr_backup;
}
if (vid->sc == (vid->crtc[10] & 31))
vid->con = 1;
if (vid->scanline == (vid->crtc[10] & 31))
vid->cursorvisible = 1;
}
}
@@ -1044,7 +1046,7 @@ vid_in_200(uint16_t addr, void *priv)
switch (addr) {
case 0x03b8:
return (mda->ctrl);
return (mda->mode);
case 0x03d8:
return (cga->cgamode);
@@ -1106,9 +1108,9 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
}
return;
case 0x3b8:
old = mda->ctrl;
mda->ctrl = val;
if ((mda->ctrl ^ old) & 3)
old = mda->mode;
mda->mode = val;
if ((mda->mode ^ old) & 3)
mda_recalctimings(mda);
vid->crtc_index &= 0x1F;
vid->crtc_index |= 0x80;
@@ -1210,11 +1212,11 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
static void
lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
uint8_t attr, int drawcursor, int blink, int sc,
uint8_t attr, int drawcursor, int blink, int scanline,
int mode160, uint8_t control)
{
int c;
uint8_t bits = fontdat[chr + vid->cga.fontbase][sc];
uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline];
uint8_t bright = 0;
uint16_t mask;
@@ -1245,10 +1247,10 @@ lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
static void
lcd_draw_char_40(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
uint8_t attr, int drawcursor, int blink, int sc,
uint8_t attr, int drawcursor, int blink, int scanline,
uint8_t control)
{
uint8_t bits = fontdat[chr + vid->cga.fontbase][sc];
uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline];
uint8_t mask = 0x80;
if (attr & 8) /* bright */
@@ -1269,91 +1271,91 @@ static void
lcdm_poll(amsvid_t *vid)
{
mda_t *mda = &vid->mda;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int oldvc;
uint8_t chr;
uint8_t attr;
int oldsc;
int scanline_old;
int blink;
if (!mda->linepos) {
timer_advance_u64(&vid->timer, mda->dispofftime);
mda->stat |= 1;
mda->status |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
scanline_old = mda->scanline;
if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3)
mda->scanline = (mda->scanline << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline)
mda->firstline = mda->displine;
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
chr = mda->vram[(mda->ma << 1) & 0xfff];
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) {
chr = mda->vram[(mda->memaddr<< 1) & 0xfff];
attr = mda->vram[((mda->memaddr<< 1) + 1) & 0xfff];
drawcursor = ((mda->memaddr== cursoraddr) && mda->cursorvisible && mda->cursoron);
blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl);
mda->ma++;
lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->scanline, 0, mda->mode);
mda->memaddr++;
}
}
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc)
mda->stat |= 8;
mda->scanline = scanline_old;
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline)
mda->status |= 8;
mda->displine++;
if (mda->displine >= 500)
mda->displine = 0;
} else {
timer_advance_u64(&vid->timer, mda->dispontime);
if (mda->dispon)
mda->stat &= ~1;
mda->status &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
if (!mda->vsynctime)
mda->stat &= ~8;
mda->status &= ~8;
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
mda->con = 0;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) {
mda->cursorvisible = 0;
}
if (mda->vadj) {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr= mda->memaddr_backup;
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
mda->scanline = 0;
}
} else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) {
mda->maback = mda->ma;
mda->sc = 0;
} else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
mda->memaddr_backup = mda->memaddr;
mda->scanline = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
if (mda->vc == mda->crtc[MDA_CRTC_VDISP])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20)
mda->cursoron = 0;
else
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 8;
if (mda->crtc[MDA_CRTC_VSYNC]) {
x = mda->crtc[MDA_CRTC_HDISP] * 8;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
@@ -1369,8 +1371,8 @@ lcdm_poll(amsvid_t *vid)
}
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_res_x = mda->crtc[MDA_CRTC_HDISP];
video_res_y = mda->crtc[MDA_CRTC_VDISP];
video_bpp = 0;
}
mda->firstline = 1000;
@@ -1378,12 +1380,12 @@ lcdm_poll(amsvid_t *vid)
mda->blink++;
}
} else {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr= mda->memaddr_backup;
}
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))
mda->con = 1;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1)))
mda->cursorvisible = 1;
}
}
@@ -1399,19 +1401,19 @@ lcdc_poll(amsvid_t *vid)
uint8_t chr;
uint8_t attr;
uint16_t dat;
int oldsc;
uint16_t ca;
int scanline_old;
uint16_t cursoraddr;
int blink;
ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
if (!cga->linepos) {
timer_advance_u64(&vid->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
scanline_old = cga->scanline;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
cga->scanline = ((cga->scanline << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
@@ -1419,30 +1421,30 @@ lcdc_poll(amsvid_t *vid)
}
cga->lastline = cga->displine;
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode);
lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode);
cga->ma++;
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode);
lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode);
cga->memaddr++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
chr = cga->vram[(cga->ma << 1) & 0x3fff];
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode);
lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode);
cga->ma++;
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
chr = cga->vram[(cga->memaddr << 1) & 0x3fff];
attr = cga->vram[((cga->memaddr << 1) + 1) & 0x3fff];
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode);
lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode);
cga->memaddr++;
}
} else { /* Graphics mode */
for (x = 0; x < cga->crtc[1]; x++) {
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
cga->ma++;
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) | cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1];
cga->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[cga->displine << 1][(x << 4) + c] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c] = (dat & 0x8000) ? blue : green;
dat <<= 1;
@@ -1450,22 +1452,22 @@ lcdc_poll(amsvid_t *vid)
}
}
} else {
if (cga->cgamode & 1) {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 3), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 3), green);
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 3), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 3), green);
} else {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 4), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 4), green);
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 4), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 4), green);
}
}
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3);
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3);
else
x = (cga->crtc[1] << 4);
x = (cga->crtc[CGA_CRTC_HDISP] << 4);
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->scanline = scanline_old;
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->scanline)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
@@ -1478,53 +1480,53 @@ lcdc_poll(amsvid_t *vid)
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
cga->cursorvisible = 0;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
cga->memaddr_backup = cga->memaddr;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
cga->scanline = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
} else if (cga->scanline == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
cga->memaddr_backup = cga->memaddr;
cga->scanline = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (cga->vc == cga->crtc[6])
if (cga->vc == cga->crtc[CGA_CRTC_VDISP])
cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) {
if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!cga->vadj)
cga->cgadispon = 1;
if (!cga->vadj)
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
if ((cga->crtc[10] & 0x60) == 0x20)
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
cga->cursoron = 0;
else
cga->cursoron = cga->cgablink & 8;
}
if (cga->vc == cga->crtc[7]) {
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3);
if (cga->crtc[CGA_CRTC_VSYNC]) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3);
else
x = (cga->crtc[1] << 4);
x = (cga->crtc[CGA_CRTC_HDISP] << 4);
cga->lastline++;
xs_temp = x;
@@ -1536,7 +1538,7 @@ lcdc_poll(amsvid_t *vid)
if (ys_temp < 32)
ys_temp = 400;
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize);
@@ -1553,15 +1555,15 @@ lcdc_poll(amsvid_t *vid)
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else
@@ -1573,17 +1575,17 @@ lcdc_poll(amsvid_t *vid)
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff];
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
cga->cursorvisible = 1;
if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->memaddr << 1) + x) & 0x3fff];
}
}
}

View File

@@ -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)
{
@@ -1128,7 +1210,7 @@ machine_at_3302_init(const machine_t *model)
device_add(&fdc_at_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&paradise_pvga1a_ncr3302_device);
device_add(machine_get_vid_device(machine));
device_add(&keyboard_at_ncr_device);

View File

@@ -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)
{
@@ -2447,7 +2500,7 @@ machine_at_actionpc2600_init(const machine_t *model)
device_add(&keyboard_ps2_tg_ami_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&tgui9440_onboard_pci_device);
device_add(machine_get_vid_device(machine));
return ret;
}
@@ -2479,7 +2532,7 @@ machine_at_actiontower8400_init(const machine_t *model)
device_add(&intel_flash_bxt_device); // The ActionPC 2600 has this so I'm gonna assume this does too.
device_add(&keyboard_ps2_ami_pci_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5430_onboard_pci_device);
device_add(machine_get_vid_device(machine));
return ret;
}

View File

@@ -44,9 +44,6 @@
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
enum {
COMPAQ_PORTABLEII = 0,
COMPAQ_PORTABLEIII,
@@ -55,752 +52,11 @@ enum {
COMPAQ_DESKPRO386_05_1988
};
#define CGA_RGB 0
#define CGA_COMPOSITE 1
/*Very rough estimate*/
#define VID_CLOCK (double) (651 * 416 * 60)
/* Mapping of attributes to colours */
static uint32_t amber;
static uint32_t black;
static uint32_t blinkcols[256][2];
static uint32_t normcols[256][2];
/* Video options set by the motherboard; they will be picked up by the card
* on the next poll.
*
* Bit 3: Disable built-in video (for add-on card)
* Bit 2: Thin font
* Bits 0,1: Font set (not currently implemented)
*/
static int8_t cpq_st_display_internal = -1;
static uint8_t mdaattr[256][2][2];
static void
compaq_plasma_display_set(uint8_t internal)
{
cpq_st_display_internal = internal;
}
typedef struct compaq_plasma_t {
cga_t cga;
mem_mapping_t font_ram_mapping;
uint8_t *font_ram;
uint8_t port_13c6;
uint8_t port_23c6;
uint8_t port_27c6;
uint8_t internal_monitor;
} compaq_plasma_t;
static int compaq_machine_type = 0;
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
static mem_mapping_t ram_mapping;
static void compaq_plasma_recalcattrs(compaq_plasma_t *self);
static void
compaq_plasma_recalctimings(compaq_plasma_t *self)
{
double _dispontime;
double _dispofftime;
double disptime;
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
cga_recalctimings(&self->cga);
return;
}
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
}
static void
compaq_plasma_waitstates(UNUSED(void *priv))
{
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
ws = ws_array[cycles & 0xf];
sub_cycles(ws);
}
static void
compaq_plasma_write(uint32_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
if (self->port_23c6 & 0x08)
self->font_ram[addr & 0x1fff] = val;
else
self->cga.vram[addr & 0x7fff] = val;
compaq_plasma_waitstates(&self->cga);
}
static uint8_t
compaq_plasma_read(uint32_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret;
compaq_plasma_waitstates(&self->cga);
if (self->port_23c6 & 0x08)
ret = (self->font_ram[addr & 0x1fff]);
else
ret = (self->cga.vram[addr & 0x7fff]);
return ret;
}
static void
compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
switch (addr) {
/* Emulated CRTC, register select */
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
cga_out(addr, val, &self->cga);
break;
/* Emulated CRTC, value */
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
cga_out(addr, val, &self->cga);
compaq_plasma_recalctimings(self);
break;
case 0x3d8:
case 0x3d9:
cga_out(addr, val, &self->cga);
break;
case 0x13c6:
self->port_13c6 = val;
compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0);
/*
For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA;
Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA;
This leads me to believe bit 2 is not relevant to the mode.
*/
if ((val & 0x03) == 0x03)
mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000);
else
mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000);
break;
case 0x23c6:
self->port_23c6 = val;
compaq_plasma_recalcattrs(self);
break;
case 0x27c6:
self->port_27c6 = val;
break;
default:
break;
}
}
static uint8_t
compaq_plasma_in(uint16_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d4:
case 0x3da:
case 0x3db:
case 0x3dc:
ret = cga_in(addr, &self->cga);
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = cga_in(addr, &self->cga);
break;
case 0x3d8:
ret = self->cga.cgamode;
break;
case 0x13c6:
ret = self->port_13c6;
#if 0
if ((self->cga.cgamode & 0x28) == 0x00)
ret |= 0x04;
#endif
break;
case 0x17c6:
ret = 0xe6;
break;
case 0x1bc6:
ret = 0x40;
break;
case 0x23c6:
ret = self->port_23c6;
break;
case 0x27c6:
ret = self->port_27c6 & 0x3f;
break;
default:
break;
}
return ret;
}
static void
compaq_plasma_poll(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t chr;
uint8_t attr;
uint8_t sc;
uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff;
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff;
uint16_t addr;
int drawcursor;
int cursorline;
int blink = 0;
int underline = 0;
int c;
int x;
uint32_t ink = 0;
uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black;
uint32_t bg = black;
uint32_t cols[2];
uint8_t dat;
uint8_t pattern;
uint32_t ink0 = 0;
uint32_t ink1 = 0;
/* Switch between internal plasma and external CRT display. */
if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) {
self->internal_monitor = cpq_st_display_internal;
compaq_plasma_recalctimings(self);
}
/* graphic mode and not mode 40h */
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
/* standard cga mode */
cga_poll(&self->cga);
return;
} else {
/* mode 40h or text mode */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
if (self->cga.cgadispon) {
if (self->cga.displine == 0)
video_wait_for_buffer();
/* 80-col */
if (self->cga.cgamode & 0x01) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1;
ma += (self->cga.displine >> 4) * 80;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
/* for each text column */
for (x = 0; x < 80; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black);
} else if ((self->port_23c6 >> 5) == 4) {
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16);
}
}
}
ma++;
}
}
/* 40-col */
else if (!(self->cga.cgamode & 0x02)) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1;
ma += (self->cga.displine >> 4) * 40;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
for (x = 0; x < 40; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1)
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black);
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black);
}
else if ((self->port_23c6 >> 5) == 4)
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16);
}
}
ma++;
}
} else {
if (self->cga.cgamode & 0x10) {
/* 640x400 mode */
if (self->port_23c6 & 0x01) /* 640*400 */ {
addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(self->cga.cgamode & 0x08))
ink = black;
buffer32->line[self->cga.displine][(x << 3) + c] = ink;
dat <<= 1;
}
}
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(self->cga.cgamode & 0x08))
pattern = 0;
switch (pattern & 3) {
case 0:
ink0 = ink1 = black;
break;
case 1:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = black;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 2:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = amber;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 3:
ink0 = ink1 = amber;
break;
default:
break;
}
buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0;
buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1;
dat <<= 2;
}
}
}
}
}
self->cga.displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (self->cga.displine == 400) { /* Start of VSYNC */
self->cga.cgastat |= 8;
self->cga.cgadispon = 0;
}
if (self->cga.displine == 416) { /* End of VSYNC */
self->cga.displine = 0;
self->cga.cgastat &= ~8;
self->cga.cgadispon = 1;
}
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
self->cga.linepos = 0;
if (self->cga.displine == 400) {
xsize = 640;
ysize = 400;
if ((self->cga.cgamode & 0x08) || video_force_resize_get()) {
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
/* Plasma specific */
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */
video_res_x = 640;
video_res_y = 400;
if (self->cga.cgamode & 0x02) {
if (self->cga.cgamode & 0x10)
video_bpp = 1;
else
video_bpp = 2;
} else
video_bpp = 0;
self->cga.cgablink++;
}
}
}
}
static void
compaq_plasma_mdaattr_rebuild(void)
{
for (uint16_t c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
static void
compaq_plasma_recalcattrs(compaq_plasma_t *self)
{
int n;
/* val behaves as follows:
* Bit 0: Attributes 01-06, 08-0E are inverse video
* Bit 1: Attributes 01-06, 08-0E are bold
* Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are inverse video
* Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are bold */
/* Set up colours */
amber = makecol(0xff, 0x7d, 0x00);
black = makecol(0x64, 0x19, 0x00);
/* Initialize the attribute mapping. Start by defaulting everything
* to black on amber, and with bold set by bit 3 */
for (n = 0; n < 256; n++) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
}
/* Colours 0x11-0xFF are controlled by bits 2 and 3 of the
* passed value. Exclude x0 and x8, which are always black on
* amber. */
for (n = 0x11; n <= 0xFF; n++) {
if ((n & 7) == 0)
continue;
if ((self->port_23c6 >> 5) == 1) { /* Inverse */
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
} else { /* Normal */
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
}
}
/* Set up the 01-0E range, controlled by bits 0 and 1 of the
* passed value. When blinking is enabled this also affects 81-8E. */
for (n = 0x01; n <= 0x0E; n++) {
if (n == 7)
continue;
if ((self->port_23c6 >> 5) == 1) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
blinkcols[n + 128][0] = amber;
blinkcols[n + 128][1] = black;
} else {
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
}
/* Colours 07 and 0F are always amber on black. If blinking is
* enabled so are 87 and 8F. */
for (n = 0x07; n <= 0x0F; n += 8) {
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
/* When not blinking, colours 81-8F are always amber on black. */
for (n = 0x81; n <= 0x8F; n++) {
normcols[n][0] = black;
normcols[n][1] = amber;
}
/* Finally do the ones which are solid black. These differ between
* the normal and blinking mappings */
for (n = 0; n <= 0xFF; n += 0x11)
normcols[n][0] = normcols[n][1] = black;
/* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */
for (n = 0; n <= 0x77; n += 0x11) {
blinkcols[n][0] = blinkcols[n][1] = black;
blinkcols[n + 128][0] = blinkcols[n + 128][1] = black;
}
}
static void *
compaq_plasma_init(UNUSED(const device_t *info))
{
compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t));
cga_init(&self->cga);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma);
self->cga.composite = 0;
self->cga.revision = 0;
self->cga.vram = malloc(0x8000);
self->internal_monitor = 1;
self->font_ram = malloc(0x2000);
cga_comp_init(self->cga.revision);
timer_set_callback(&self->cga.timer, compaq_plasma_poll);
timer_set_p(&self->cga.timer, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000,
compaq_plasma_read, NULL, NULL,
compaq_plasma_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, self);
for (int i = 1; i <= 2; i++) {
io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
}
io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
overscan_x = overscan_y = 16;
self->cga.rgb_type = device_get_config_int("rgb_type");
cga_palette = (self->cga.rgb_type << 1);
cgapal_rebuild();
compaq_plasma_mdaattr_rebuild();
return self;
}
static void
compaq_plasma_close(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
free(self->cga.vram);
free(self->font_ram);
free(self);
}
static void
compaq_plasma_speed_changed(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
compaq_plasma_recalctimings(self);
}
const device_config_t compaq_plasma_config[] = {
// clang-format off
{
.name = "rgb_type",
.description = "RGB type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Color", .value = 0 },
{ .description = "Green Monochrome", .value = 1 },
{ .description = "Amber Monochrome", .value = 2 },
{ .description = "Gray Monochrome", .value = 3 },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t compaq_plasma_device = {
.name = "Compaq Plasma",
.internal_name = "compaq_plasma",
.flags = 0,
.local = 0,
.init = compaq_plasma_init,
.close = compaq_plasma_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_plasma_speed_changed,
.force_redraw = NULL,
.config = compaq_plasma_config
};
static uint8_t
read_ram(uint32_t addr, UNUSED(void *priv))

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

@@ -58,13 +58,13 @@ static void
elt_vid_off_poll(void *priv)
{
cga_t *cga = priv;
uint8_t hdisp = cga->crtc[1];
uint8_t hdisp = cga->crtc[CGA_CRTC_HDISP];
/* Don't display anything.
* TODO: Do something less stupid to emulate backlight off. */
cga->crtc[1] = 0;
cga->crtc[CGA_CRTC_HDISP] = 0;
cga_poll(cga);
cga->crtc[1] = hdisp;
cga->crtc[CGA_CRTC_HDISP] = hdisp;
}
static void

View File

@@ -48,11 +48,10 @@
#include <86box/snd_sn76489.h>
#include <86box/video.h>
#include <86box/vid_cga_comp.h>
#include <86box/m_pcjr.h>
#include <86box/machine.h>
#include <86box/plat_unused.h>
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
@@ -63,49 +62,10 @@
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
typedef struct pcjr_t {
/* Video Controller stuff. */
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[32];
int array_ff;
int memctrl;
uint8_t stat;
int addr_mode;
uint8_t *vram;
uint8_t *b8000;
int linepos;
int displine;
int sc;
int vc;
int dispon;
int con;
int cursoron;
int blink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma;
uint16_t maback;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
int apply_hd;
/* Keyboard Controller stuff. */
int latched;
int data;
int serial_data[44];
int serial_pos;
uint8_t pa;
uint8_t pb;
pc_timer_t send_delay_timer;
} pcjr_t;
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
/*PCjr keyboard has no escape scancodes, and no scancodes beyond 54
Map right alt to 54h (FN) */
@@ -626,643 +586,6 @@ const scancode scancode_pcjr[512] = {
// clang-format on
};
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
static void
recalc_address(pcjr_t *pcjr)
{
uint8_t masked_memctrl = pcjr->memctrl;
/* According to the Technical Reference, bits 2 and 5 are
ignored if there is only 64k of RAM and there are only
4 pages. */
if (mem_size < 128)
masked_memctrl &= ~0x24;
if ((pcjr->memctrl & 0xc0) == 0xc0) {
pcjr->vram = &ram[(masked_memctrl & 0x06) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11];
} else {
pcjr->vram = &ram[(masked_memctrl & 0x07) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11];
}
}
static void
recalc_timings(pcjr_t *pcjr)
{
double _dispontime;
double _dispofftime;
double disptime;
if (pcjr->array[0] & 1) {
disptime = pcjr->crtc[0] + 1;
_dispontime = pcjr->crtc[1];
} else {
disptime = (pcjr->crtc[0] + 1) << 1;
_dispontime = pcjr->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
pcjr->dispontime = (uint64_t) (_dispontime);
pcjr->dispofftime = (uint64_t) (_dispofftime);
}
static int
vid_get_h_overscan_size(pcjr_t *pcjr)
{
int ret;
if (pcjr->array[0] & 1)
ret = 128;
else
ret = 256;
return ret;
}
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t old;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
pcjr->crtcreg = val & 0x1f;
return;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
old = pcjr->crtc[pcjr->crtcreg];
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
if (pcjr->crtcreg == 2)
overscan_x = vid_get_h_overscan_size(pcjr);
if (old != val) {
if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) {
pcjr->fullchange = changeframecount;
recalc_timings(pcjr);
}
}
return;
case 0x3da:
if (!pcjr->array_ff)
pcjr->array_index = val & 0x1f;
else {
if (pcjr->array_index & 0x10)
val &= 0x0f;
pcjr->array[pcjr->array_index & 0x1f] = val;
if (!(pcjr->array_index & 0x1f))
update_cga16_color(val);
}
pcjr->array_ff = !pcjr->array_ff;
break;
case 0x3df:
pcjr->memctrl = val;
pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to
then be readable from port 60, others it errors out
with only 64k RAM set (but somehow, still works with
128k or more RAM). */
pcjr->addr_mode = val >> 6;
recalc_address(pcjr);
break;
default:
break;
}
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
ret = pcjr->crtcreg;
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = pcjr->crtc[pcjr->crtcreg];
break;
case 0x3da:
pcjr->array_ff = 0;
pcjr->stat ^= 0x10;
ret = pcjr->stat;
break;
default:
break;
}
return ret;
}
static void
vid_write(uint32_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return;
pcjr->b8000[addr & 0x3fff] = val;
}
static uint8_t
vid_read(uint32_t addr, void *priv)
{
const pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return 0xff;
return (pcjr->b8000[addr & 0x3fff]);
}
static int
vid_get_h_overscan_delta(pcjr_t *pcjr)
{
int def;
int coef;
int ret;
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
def = 0x56;
coef = 8;
break;
case 0x12: /*160x200x16*/
def = 0x2c; /* I'm going to assume a datasheet erratum here. */
coef = 16;
break;
case 0x03: /*640x200x4*/
def = 0x56;
coef = 8;
break;
case 0x01: /*80 column text*/
def = 0x5a;
coef = 8;
break;
case 0x00: /*40 column text*/
default:
def = 0x2c;
coef = 16;
break;
case 0x02: /*320x200x4*/
def = 0x2b;
coef = 16;
break;
case 0x102: /*640x200x2*/
def = 0x2b;
coef = 16;
break;
}
ret = pcjr->crtc[0x02] - def;
if (ret < -8)
ret = -8;
if (ret > 8)
ret = 8;
return ret * coef;
}
static void
vid_blit_h_overscan(pcjr_t *pcjr)
{
int cols = (pcjr->array[2] & 0xf) + 16;;
int y0 = pcjr->firstline << 1;
int y = (pcjr->lastline << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int i;
int x;
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
for (i = 0; i < 16; i++) {
hline(buffer32, 0, y0 + i, x, cols);
hline(buffer32, 0, y + i, x, cols);
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]);
} else {
video_process_8(x, y0 + i);
video_process_8(x, y + i);
}
}
}
static void
vid_poll(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int oldsc;
int l = (pcjr->displine << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2);
if (!pcjr->linepos) {
timer_advance_u64(&pcjr->timer, pcjr->dispofftime);
pcjr->stat &= ~1;
pcjr->linepos = 1;
oldsc = pcjr->sc;
if ((pcjr->crtc[8] & 3) == 3)
pcjr->sc = (pcjr->sc << 1) & 7;
if (pcjr->dispon) {
uint16_t offset = 0;
uint16_t mask = 0x1fff;
if (pcjr->displine < pcjr->firstline) {
pcjr->firstline = pcjr->displine;
video_wait_for_buffer();
}
pcjr->lastline = pcjr->displine;
cols[0] = (pcjr->array[2] & 0xf) + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
switch (pcjr->addr_mode) {
case 0: /*Alpha*/
offset = 0;
mask = 0x3fff;
break;
case 1: /*Low resolution graphics*/
offset = (pcjr->sc & 1) * 0x2000;
break;
case 3: /*High resolution graphics*/
offset = (pcjr->sc & 3) * 0x2000;
break;
default:
break;
}
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x12: /*160x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] =
buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] =
buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] =
buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] =
buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] =
buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] =
buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x03: /*640x200x4*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset];
pcjr->ma++;
for (uint8_t c = 0; c < 8; c++) {
chr = (dat >> 7) & 1;
chr |= ((dat >> 14) & 2);
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16;
dat <<= 1;
}
}
break;
case 0x01: /*80 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
if (pcjr->sc & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] =
cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
pcjr->ma++;
}
break;
case 0x00: /*40 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
pcjr->ma++;
if (pcjr->sc & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] =
cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
}
break;
case 0x02: /*320x200x4*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
cols[2] = pcjr->array[2 + 16] + 16;
cols[3] = pcjr->array[3 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14];
dat <<= 2;
}
}
break;
case 0x102: /*640x200x2*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
cols[dat >> 15];
dat <<= 1;
}
}
break;
default:
break;
}
} else {
if (pcjr->array[3] & 4) {
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
}
} else {
cols[0] = pcjr->array[0 + 16] + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
}
}
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]);
} else {
video_process_8(x, l);
video_process_8(x, l + 1);
}
pcjr->sc = oldsc;
if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) {
pcjr->stat |= 8;
}
pcjr->displine++;
if (pcjr->displine >= 360)
pcjr->displine = 0;
} else {
timer_advance_u64(&pcjr->timer, pcjr->dispontime);
if (pcjr->dispon)
pcjr->stat |= 1;
pcjr->linepos = 0;
if (pcjr->vsynctime) {
pcjr->vsynctime--;
if (!pcjr->vsynctime) {
pcjr->stat &= ~8;
}
}
if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) {
pcjr->con = 0;
}
if (pcjr->vadj) {
pcjr->sc++;
pcjr->sc &= 31;
pcjr->ma = pcjr->maback;
pcjr->vadj--;
if (!pcjr->vadj) {
pcjr->dispon = 1;
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
pcjr->sc = 0;
}
} else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) {
pcjr->maback = pcjr->ma;
pcjr->sc = 0;
oldvc = pcjr->vc;
pcjr->vc++;
pcjr->vc &= 127;
if (pcjr->vc == pcjr->crtc[6])
pcjr->dispon = 0;
if (oldvc == pcjr->crtc[4]) {
pcjr->vc = 0;
pcjr->vadj = pcjr->crtc[5];
if (!pcjr->vadj)
pcjr->dispon = 1;
if (!pcjr->vadj)
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
if ((pcjr->crtc[10] & 0x60) == 0x20)
pcjr->cursoron = 0;
else
pcjr->cursoron = pcjr->blink & 16;
}
if (pcjr->vc == pcjr->crtc[7]) {
pcjr->dispon = 0;
pcjr->displine = 0;
pcjr->vsynctime = 16;
picint(1 << 5);
if (pcjr->crtc[7]) {
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
pcjr->lastline++;
xs_temp = x;
ys_temp = (pcjr->lastline - pcjr->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
int actual_ys = ys_temp;
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= ho_s;
if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
vid_blit_h_overscan(pcjr);
if (enable_overscan) {
video_blit_memtoscreen(0, pcjr->firstline << 1,
xsize, actual_ys + 32);
} else if (pcjr->apply_hd) {
video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
} else {
video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
}
pcjr->firstline = 1000;
pcjr->lastline = 0;
pcjr->blink++;
}
} else {
pcjr->sc++;
pcjr->sc &= 31;
pcjr->ma = pcjr->maback;
}
if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1)))
pcjr->con = 1;
}
}
static void
kbd_write(uint16_t port, uint8_t val, void *priv)
@@ -1433,35 +756,7 @@ speed_changed(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
recalc_timings(pcjr);
}
static void
pcjr_vid_init(pcjr_t *pcjr)
{
int display_type;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
pcjr->memctrl = -1;
if (mem_size < 128)
pcjr->memctrl &= ~0x24;
display_type = device_get_config_int("display_type");
pcjr->composite = (display_type != PCJR_RGB);
pcjr->apply_hd = device_get_config_int("apply_hd");
overscan_x = 256;
overscan_y = 32;
mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL,
vid_write, NULL, NULL, NULL, 0, pcjr);
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr);
timer_add(&pcjr->timer, vid_poll, pcjr, 1);
cga_palette = 0;
cgapal_rebuild();
pcjr_recalc_timings(pcjr);
}
void
@@ -1487,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

@@ -44,12 +44,9 @@
#include <86box/video.h>
#include <86box/vid_cga_comp.h>
#include <86box/machine.h>
#include <86box/m_tandy.h>
#include <86box/plat_unused.h>
enum {
TANDY_RGB = 0,
TANDY_COMPOSITE
};
enum {
TYPE_TANDY = 0,
@@ -65,79 +62,6 @@ enum {
EEPROM_WRITE
};
typedef struct t1kvid_t {
mem_mapping_t mapping;
mem_mapping_t vram_mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[256];
int memctrl;
uint8_t mode;
uint8_t col;
uint8_t stat;
uint8_t *vram;
uint8_t *b8000;
uint32_t b8000_mask;
uint32_t b8000_limit;
uint8_t planar_ctrl;
uint8_t lp_strobe;
int linepos;
int displine;
int sc;
int vc;
int dispon;
int con;
int cursoron;
int blink;
int fullchange;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
} t1kvid_t;
typedef struct t1keep_t {
char *path;
int state;
int count;
int addr;
int clk;
uint16_t data;
uint16_t store[64];
} t1keep_t;
typedef struct tandy_t {
mem_mapping_t ram_mapping;
mem_mapping_t rom_mapping; /* SL2 */
uint8_t *rom; /* SL2 */
uint8_t ram_bank;
uint8_t rom_bank; /* SL2 */
int rom_offset; /* SL2 */
uint32_t base;
uint32_t mask;
int is_hx;
int is_sl2;
t1kvid_t *vid;
} tandy_t;
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
static const scancode scancode_tandy[512] = {
// clang-format off
@@ -655,22 +579,8 @@ static const scancode scancode_tandy[512] = {
{ .mk = { 0 }, .brk = { 0 } } /* 1ff */
// clang-format on
};
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t crtcmask_sl[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static int eep_data_out;
static uint8_t vid_in(uint16_t addr, void *priv);
static void vid_out(uint16_t addr, uint8_t val, void *priv);
static int eep_data_out;
#ifdef ENABLE_TANDY_LOG
int tandy_do_log = ENABLE_TANDY_LOG;
@@ -690,762 +600,7 @@ tandy_log(const char *fmt, ...)
# define tandy_log(fmt, ...)
#endif
static void
recalc_mapping(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
mem_mapping_disable(&vid->mapping);
io_removehandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
if (vid->planar_ctrl & 4) {
mem_mapping_enable(&vid->mapping);
if (vid->array[5] & 1)
mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000);
else
mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000);
io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
}
}
static void
recalc_timings(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
double _dispontime;
double _dispofftime;
double disptime;
if (vid->mode & 1) {
disptime = vid->crtc[0] + 1;
_dispontime = vid->crtc[1];
} else {
disptime = (vid->crtc[0] + 1) << 1;
_dispontime = vid->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
vid->dispontime = (uint64_t) (_dispontime);
vid->dispofftime = (uint64_t) (_dispofftime);
}
static void
recalc_address(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
if ((vid->memctrl & 0xc0) == 0xc0) {
vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base];
vid->b8000_mask = 0x7fff;
} else {
vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base];
vid->b8000_mask = 0x3fff;
}
}
static void
recalc_address_sl(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
vid->b8000_limit = 0x8000;
if (vid->array[5] & 1) {
vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base];
} else if ((vid->memctrl & 0xc0) == 0xc0) {
vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base];
} else {
vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base];
if ((vid->memctrl & 0x38) == 0x38)
vid->b8000_limit = 0x4000;
}
}
static void
vid_update_latch(t1kvid_t *vid)
{
uint32_t lp_latch = vid->displine * vid->crtc[1];
vid->crtc[0x10] = (lp_latch >> 8) & 0x3f;
vid->crtc[0x11] = lp_latch & 0xff;
}
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint8_t old;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x03d4:
vid->crtcreg = val & 0x1f;
break;
case 0x03d5:
old = vid->crtc[vid->crtcreg];
if (dev->is_sl2)
vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg];
else
vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg];
if (old != val) {
if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) {
vid->fullchange = changeframecount;
recalc_timings(dev);
}
}
break;
case 0x03d8:
old = vid->mode;
vid->mode = val;
if ((old ^ val) & 0x01)
recalc_timings(dev);
if (!dev->is_sl2)
update_cga16_color(vid->mode);
break;
case 0x03d9:
vid->col = val;
break;
case 0x03da:
vid->array_index = val & 0x1f;
break;
case 0x3db:
if (!dev->is_sl2 && (vid->lp_strobe == 1))
vid->lp_strobe = 0;
break;
case 0x3dc:
if (!dev->is_sl2 && (vid->lp_strobe == 0)) {
vid->lp_strobe = 1;
vid_update_latch(vid);
}
break;
case 0x03de:
if (vid->array_index & 16)
val &= 0xf;
vid->array[vid->array_index & 0x1f] = val;
if (dev->is_sl2) {
if ((vid->array_index & 0x1f) == 5) {
recalc_mapping(dev);
recalc_address_sl(dev);
}
}
break;
case 0x03df:
vid->memctrl = val;
if (dev->is_sl2)
recalc_address_sl(dev);
else
recalc_address(dev);
break;
case 0x0065:
if (val == 8)
return; /*Hack*/
vid->planar_ctrl = val;
recalc_mapping(dev);
break;
default:
break;
}
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
const tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint8_t ret = 0xff;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x03d4:
ret = vid->crtcreg;
break;
case 0x03d5:
ret = vid->crtc[vid->crtcreg];
break;
case 0x03da:
ret = vid->stat;
break;
case 0x3db:
if (!dev->is_sl2 && (vid->lp_strobe == 1))
vid->lp_strobe = 0;
break;
case 0x3dc:
if (!dev->is_sl2 && (vid->lp_strobe == 0)) {
vid->lp_strobe = 1;
vid_update_latch(vid);
}
break;
default:
break;
}
return ret;
}
static void
vid_write(uint32_t addr, uint8_t val, void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
if (vid->memctrl == -1)
return;
if (dev->is_sl2) {
if (vid->array[5] & 1)
vid->b8000[addr & 0xffff] = val;
else {
if ((addr & 0x7fff) < vid->b8000_limit)
vid->b8000[addr & 0x7fff] = val;
}
} else {
vid->b8000[addr & vid->b8000_mask] = val;
}
}
static uint8_t
vid_read(uint32_t addr, void *priv)
{
const tandy_t *dev = (tandy_t *) priv;
const t1kvid_t *vid = dev->vid;
if (vid->memctrl == -1)
return 0xff;
if (dev->is_sl2) {
if (vid->array[5] & 1)
return (vid->b8000[addr & 0xffff]);
if ((addr & 0x7fff) < vid->b8000_limit)
return (vid->b8000[addr & 0x7fff]);
else
return 0xff;
} else {
return (vid->b8000[addr & vid->b8000_mask]);
}
}
static void
vid_poll(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int col;
int oldsc;
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
vid->stat |= 1;
vid->linepos = 1;
oldsc = vid->sc;
if ((vid->crtc[8] & 3) == 3)
vid->sc = (vid->sc << 1) & 7;
if (vid->dispon) {
if (vid->displine < vid->firstline) {
vid->firstline = vid->displine;
video_wait_for_buffer();
}
vid->lastline = vid->displine;
cols[0] = (vid->array[2] & 0xf) + 16;
for (c = 0; c < 8; c++) {
if (vid->array[3] & 4) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0];
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0];
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0];
}
} else if ((vid->mode & 0x12) == 0x12) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0;
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16;
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16;
}
}
}
if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/
for (x = 0; x < vid->crtc[1] * 2; x++) {
dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff];
vid->ma++;
buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = vid->array[(dat & 0xf) + 16] + 16;
}
} else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
vid->ma++;
buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
}
} else if (vid->array[3] & 0x10) { /*160x200x16*/
for (x = 0; x < vid->crtc[1]; x++) {
if (dev->is_sl2) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
} else {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
}
vid->ma++;
buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
}
} else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 8; c++) {
chr = (dat >> 6) & 2;
chr |= ((dat >> 15) & 1);
buffer32->line[vid->displine << 1][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16;
dat <<= 1;
}
}
} else if (vid->mode & 1) {
for (x = 0; x < vid->crtc[1]; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->mode & 0x20) {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
if (vid->sc & 8) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0];
}
} else {
for (c = 0; c < 8; c++) {
if (vid->sc == 8) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
} else {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] ^= 15;
buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15;
}
}
vid->ma++;
}
} else if (!(vid->mode & 2)) {
for (x = 0; x < vid->crtc[1]; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->mode & 0x20) {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
vid->ma++;
if (vid->sc & 8) {
for (c = 0; c < 8; c++)
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0];
} else {
for (c = 0; c < 8; c++) {
if (vid->sc == 8) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
} else {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
if (drawcursor) {
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] ^= 15;
buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15;
}
}
}
} else if (!(vid->mode & 16)) {
cols[0] = (vid->col & 15);
col = (vid->col & 16) ? 8 : 0;
if (vid->mode & 4) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
} else if (vid->col & 32) {
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
} else {
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16;
cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16;
cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16;
cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16;
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
} else {
cols[0] = 0;
cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16;
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
} else {
if (vid->array[3] & 4) {
if (vid->mode & 1) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16);
} else {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16);
}
} else {
cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16;
if (vid->mode & 1) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]);
} else {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]);
}
}
}
if (vid->mode & 1)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
if (!dev->is_sl2 && vid->composite) {
Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine << 1]);
Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]);
} else {
video_process_8(x, vid->displine << 1);
video_process_8(x, (vid->displine << 1) + 1);
}
vid->sc = oldsc;
if (vid->vc == vid->crtc[7] && !vid->sc)
vid->stat |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
} else {
timer_advance_u64(&vid->timer, vid->dispontime);
if (vid->dispon)
vid->stat &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (!vid->vsynctime)
vid->stat &= ~8;
}
if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) {
vid->con = 0;
}
if (vid->vadj) {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->vadj--;
if (!vid->vadj) {
vid->dispon = 1;
if (dev->is_sl2 && (vid->array[5] & 1))
vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8);
else
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->sc = 0;
}
} else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) {
vid->maback = vid->ma;
vid->sc = 0;
oldvc = vid->vc;
vid->vc++;
if (dev->is_sl2)
vid->vc &= 255;
else
vid->vc &= 127;
if (vid->vc == vid->crtc[6])
vid->dispon = 0;
if (oldvc == vid->crtc[4]) {
vid->vc = 0;
vid->vadj = vid->crtc[5];
if (!vid->vadj)
vid->dispon = 1;
if (!vid->vadj) {
if (dev->is_sl2 && (vid->array[5] & 1))
vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8);
else
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
}
if ((vid->crtc[10] & 0x60) == 0x20)
vid->cursoron = 0;
else
vid->cursoron = vid->blink & 16;
}
if (vid->vc == vid->crtc[7]) {
vid->dispon = 0;
vid->displine = 0;
vid->vsynctime = 16;
picint(1 << 5);
if (vid->crtc[7]) {
if (vid->mode & 1)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
vid->lastline++;
xs_temp = x;
ys_temp = (vid->lastline - vid->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan) {
video_blit_memtoscreen(0, (vid->firstline - 4) << 1,
xsize, ((vid->lastline - vid->firstline) + 8) << 1);
} else {
video_blit_memtoscreen(8, vid->firstline << 1,
xsize, (vid->lastline - vid->firstline) << 1);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/
video_res_x /= 2;
video_bpp = 4;
} else if (vid->array[3] & 0x10) { /*160x200x16*/
video_res_x /= 4;
video_bpp = 4;
} else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/
video_bpp = 2;
} else if (vid->mode & 1) {
video_res_x /= 8;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->mode & 2)) {
video_res_x /= 16;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->mode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else {
video_bpp = 1;
}
}
vid->firstline = 1000;
vid->lastline = 0;
vid->blink++;
}
} else {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
}
if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))
vid->con = 1;
}
}
static void
vid_speed_changed(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
recalc_timings(dev);
}
static void
vid_close(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
free(dev->vid);
dev->vid = NULL;
}
static void
vid_init(tandy_t *dev)
{
int display_type;
t1kvid_t *vid;
vid = calloc(1, sizeof(t1kvid_t));
vid->memctrl = -1;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
display_type = device_get_config_int("display_type");
vid->composite = (display_type != TANDY_RGB);
cga_comp_init(1);
if (dev->is_sl2) {
vid->b8000_limit = 0x8000;
vid->planar_ctrl = 4;
overscan_x = overscan_y = 16;
io_sethandler(0x0065, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
} else
vid->b8000_mask = 0x3fff;
timer_add(&vid->timer, vid_poll, dev, 1);
mem_mapping_add(&vid->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev);
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
dev->vid = vid;
}
const device_config_t vid_config[] = {
// clang-format off
{
.name = "display_type",
.description = "Display type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = TANDY_RGB,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "RGB", .value = TANDY_RGB },
{ .description = "Composite", .value = TANDY_COMPOSITE },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t vid_device = {
.name = "Tandy 1000",
.internal_name = "tandy1000_video",
.flags = 0,
.local = 0,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = vid_config
};
const device_t vid_device_hx = {
.name = "Tandy 1000 HX",
.internal_name = "tandy1000_hx_video",
.flags = 0,
.local = 0,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = vid_config
};
const device_t vid_device_sl = {
.name = "Tandy 1000SL2",
.internal_name = "tandy1000_sl_video",
.flags = 0,
.local = 1,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = NULL
};
static void
eep_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
@@ -1630,12 +785,12 @@ tandy_write(uint16_t addr, uint8_t val, void *priv)
}
if (dev->is_hx) {
io_removehandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev);
if (val & 0x01)
mem_mapping_disable(&dev->vid->mapping);
else {
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev);
mem_mapping_set_addr(&dev->vid->mapping, 0xb8000, 0x8000);
}
} else {
@@ -1654,7 +809,7 @@ tandy_write(uint16_t addr, uint8_t val, void *priv)
mem_mapping_set_addr(&dev->ram_mapping,
((val >> 1) & 7) * 128 * 1024,
0x20000);
recalc_address_sl(dev);
tandy_recalc_address_sl(dev);
dev->ram_bank = val;
break;
@@ -1803,10 +958,10 @@ machine_tandy1k_init(const machine_t *model, int type)
keyboard_set_table(scancode_tandy);
io_sethandler(0x00a0, 1,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device);
vid_init(dev);
device_context(&tandy_1000_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device, dev);
device_add_ex(&tandy_1000_video_device, dev);
device_add((type == TYPE_TANDY1000SX) ? &ncr8496_device : &sn76489_device);
break;
@@ -1815,10 +970,10 @@ machine_tandy1k_init(const machine_t *model, int type)
keyboard_set_table(scancode_tandy);
io_sethandler(0x00a0, 1,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device_hx);
vid_init(dev);
device_context(&tandy_1000hx_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device_hx, dev);
device_add_ex(&tandy_1000hx_video_device, dev);
device_add(&ncr8496_device);
device_add(&eep_1000hx_device);
break;
@@ -1828,10 +983,10 @@ machine_tandy1k_init(const machine_t *model, int type)
init_rom(dev);
io_sethandler(0xffe8, 8,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device_sl);
vid_init(dev);
device_context(&tandy_1000sl_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device_sl, dev);
device_add_ex(&tandy_1000sl_video_device, dev);
device_add(&pssj_device);
device_add(&eep_1000sl2_device);
break;

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

@@ -1918,7 +1918,7 @@ m19_vid_out(uint16_t addr, uint8_t val, void *priv)
/* activating plantronics mode */
if (addr == 0x3dd) {
/* already in graphics mode */
if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2))
if ((val & 0x30) && (vid->ogc.cga.cgamode & CGA_MODE_FLAG_GRAPHICS))
vid->mode = PLANTRONICS_MODE;
else
vid->mode = OLIVETTI_OGC_MODE;

View File

@@ -39,8 +39,10 @@
// Temporarily here till we move everything out into the right files
extern const device_t pcjr_device;
extern const device_t m19_vid_device;
extern const device_t vid_device;
extern const device_t vid_device_hx;
extern const device_t tandy_1000_video_device;
extern const device_t tandy_1000hx_video_device;
extern const device_t tandy_1000sl_video_device;
extern const device_t t1000_video_device;
extern const device_t xi8088_device;
extern const device_t cga_device;
@@ -50,7 +52,6 @@ extern const device_t vid_pc2086_device;
extern const device_t vid_pc3086_device;
extern const device_t vid_200_device;
extern const device_t vid_ppc512_device;
extern const device_t vid_device_sl;
extern const device_t t1200_video_device;
extern const device_t compaq_plasma_device;
extern const device_t ps1_2011_device;
@@ -70,6 +71,7 @@ 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;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -106,6 +108,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 },
@@ -149,7 +152,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 },
@@ -1591,7 +1596,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device,
.vid_device = &tandy_1000_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -1630,7 +1635,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device_hx,
.vid_device = &tandy_1000hx_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -2025,6 +2030,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 */
{
@@ -2531,7 +2575,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device_sl,
.vid_device = &tandy_1000sl_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -3416,6 +3460,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. */
{
@@ -3692,7 +3777,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &paradise_pvga1a_ncr3302_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -4300,6 +4385,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",
@@ -5716,10 +5841,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,
@@ -5958,12 +6083,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,
@@ -6000,10 +6165,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,
@@ -6325,10 +6490,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,
@@ -6484,6 +6649,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",
@@ -9235,7 +9440,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &tgui9440_onboard_pci_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -9276,7 +9481,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &gd5430_onboard_pci_device,
.snd_device = NULL,
.net_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

@@ -197,6 +197,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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

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