Merge pull request #1676 from 86Box/master
Bring the branch up to par with master.
This commit is contained in:
352
src/chipset/82c100.c
Normal file
352
src/chipset/82c100.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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 Chips&Technology's 82C100 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int enabled;
|
||||
uint32_t virt, phys;
|
||||
} ems_page_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t index, access;
|
||||
uint16_t ems_io_base;
|
||||
uint32_t ems_window_base;
|
||||
uint8_t ems_page_regs[4],
|
||||
regs[256];
|
||||
ems_page_t ems_pages[4];
|
||||
mem_mapping_t ems_mappings[4];
|
||||
} ct_82c100_t;
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_ems_pages_recalc(ct_82c100_t *dev)
|
||||
{
|
||||
int i;
|
||||
uint32_t page_base;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
page_base = dev->ems_window_base + (i << 14);
|
||||
if (dev->ems_page_regs[i] & 0x80) {
|
||||
dev->ems_pages[i].virt = page_base;
|
||||
dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14);
|
||||
mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000);
|
||||
mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys]));
|
||||
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
} else {
|
||||
mem_mapping_disable(&(dev->ems_mappings[i]));
|
||||
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
|
||||
dev->ems_page_regs[port >> 14] = val;
|
||||
ct_82c100_ems_pages_recalc(dev);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ct_82c100_ems_in(uint16_t port, void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
ret = dev->ems_page_regs[port >> 14];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_ems_update(ct_82c100_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
io_handler(0, dev->ems_io_base + (i << 14), 1,
|
||||
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
io_handler(1, dev->ems_io_base + (i << 14), 1,
|
||||
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14);
|
||||
|
||||
ct_82c100_ems_pages_recalc(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_reset(void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
|
||||
memset(dev->regs, 0x00, sizeof(dev->regs));
|
||||
memset(dev->ems_page_regs, 0x00, sizeof(dev->ems_page_regs));
|
||||
|
||||
dev->index = dev->access = 0x00;
|
||||
|
||||
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
|
||||
dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */
|
||||
dev->regs[0x43] = 0x30;
|
||||
dev->regs[0x48] = 0x01;
|
||||
|
||||
use_custom_nmi_vector = 0;
|
||||
ct_82c100_ems_update(dev);
|
||||
|
||||
/* ADDITIONAL I/O REGISTERS */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
|
||||
if (port == 0x0022) {
|
||||
dev->index = val;
|
||||
dev->access = 1;
|
||||
} else if (port == 0x0023) {
|
||||
if (dev->access) {
|
||||
switch (dev->index) {
|
||||
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
|
||||
case 0x40:
|
||||
dev->regs[0x40] = val & 0xc7;
|
||||
/* TODO: Clock stuff - needs CPU speed change functionality that's
|
||||
going to be implemented in 86box v4.0.
|
||||
Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */
|
||||
break;
|
||||
case 0x41:
|
||||
dev->regs[0x41] = val & 0xed;
|
||||
/* TODO: Where is the Software Reset Function that's enabled by
|
||||
setting bit 6 to 1? */
|
||||
break;
|
||||
case 0x42:
|
||||
dev->regs[0x42] = val & 0x01;
|
||||
break;
|
||||
case 0x43:
|
||||
dev->regs[0x43] = val;
|
||||
break;
|
||||
case 0x44:
|
||||
dev->regs[0x44] = val;
|
||||
custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val);
|
||||
break;
|
||||
case 0x45:
|
||||
dev->regs[0x45] = val;
|
||||
custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8);
|
||||
break;
|
||||
case 0x46:
|
||||
dev->regs[0x46] = val;
|
||||
custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16);
|
||||
break;
|
||||
case 0x47:
|
||||
dev->regs[0x47] = val;
|
||||
custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24);
|
||||
break;
|
||||
case 0x48: case 0x49:
|
||||
dev->regs[dev->index] = val;
|
||||
break;
|
||||
case 0x4b:
|
||||
dev->regs[0x4b] = val;
|
||||
use_custom_nmi_vector = !!(val & 0x40);
|
||||
break;
|
||||
case 0x4c:
|
||||
dev->regs[0x4c] = val;
|
||||
ct_82c100_ems_update(dev);
|
||||
break;
|
||||
}
|
||||
dev->access = 0;
|
||||
}
|
||||
} else if (port == 0x72)
|
||||
dev->regs[0x72] = val & 0x7e;
|
||||
else if (port == 0x7e)
|
||||
dev->regs[0x7e] = val;
|
||||
else if (port == 0x7f) {
|
||||
/* Bit 3 is Software Controlled Reset, asserted if set. Will be
|
||||
done in the feature/machine_and_kb branch using hardresetx86(). */
|
||||
dev->regs[0x7f] = val;
|
||||
if ((dev->regs[0x41] & 0x40) && (val & 0x08)) {
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
ct_82c100_reset(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ct_82c100_in(uint16_t port, void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (port == 0x0022)
|
||||
ret = dev->index;
|
||||
else if (port == 0x0023) {
|
||||
if (dev->access) {
|
||||
switch (dev->index) {
|
||||
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
|
||||
case 0x40 ... 0x49:
|
||||
case 0x4b: case 0x4c:
|
||||
ret = dev->regs[dev->index];
|
||||
break;
|
||||
}
|
||||
dev->access = 0;
|
||||
}
|
||||
} else if (port == 0x72)
|
||||
ret = dev->regs[0x72];
|
||||
else if (port == 0x7e)
|
||||
ret = dev->regs[0x7e];
|
||||
else if (port == 0x7f)
|
||||
ret = dev->regs[0x7f];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
mem_read_emsb(uint32_t addr, void *priv)
|
||||
{
|
||||
ems_page_t *page = (ems_page_t *)priv;
|
||||
uint8_t val = 0xff;
|
||||
|
||||
addr = addr - page->virt + page->phys;
|
||||
|
||||
if (addr < ((uint32_t)mem_size << 10))
|
||||
val = ram[addr];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
mem_read_emsw(uint32_t addr, void *priv)
|
||||
{
|
||||
ems_page_t *page = (ems_page_t *)priv;
|
||||
uint16_t val = 0xffff;
|
||||
|
||||
addr = addr - page->virt + page->phys;
|
||||
|
||||
if (addr < ((uint32_t)mem_size << 10))
|
||||
val = *(uint16_t *)&ram[addr];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mem_write_emsb(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ems_page_t *page = (ems_page_t *)priv;
|
||||
|
||||
addr = addr - page->virt + page->phys;
|
||||
|
||||
if (addr < ((uint32_t)mem_size << 10))
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mem_write_emsw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
ems_page_t *page = (ems_page_t *)priv;
|
||||
|
||||
addr = addr - page->virt + page->phys;
|
||||
|
||||
if (addr < ((uint32_t)mem_size << 10))
|
||||
*(uint16_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ct_82c100_close(void *priv)
|
||||
{
|
||||
ct_82c100_t *dev = (ct_82c100_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ct_82c100_init(const device_t *info)
|
||||
{
|
||||
ct_82c100_t *dev;
|
||||
uint32_t i;
|
||||
|
||||
dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t));
|
||||
memset(dev, 0x00, sizeof(ct_82c100_t));
|
||||
|
||||
ct_82c100_reset(dev);
|
||||
|
||||
io_sethandler(0x0022, 2,
|
||||
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
|
||||
io_sethandler(0x0072, 1,
|
||||
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
|
||||
io_sethandler(0x007e, 2,
|
||||
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000,
|
||||
mem_read_emsb, mem_read_emsw, NULL,
|
||||
mem_write_emsb, mem_write_emsw, NULL,
|
||||
ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]);
|
||||
mem_mapping_disable(&(dev->ems_mappings[i]));
|
||||
}
|
||||
|
||||
mem_mapping_disable(&ram_mid_mapping);
|
||||
|
||||
device_add(&port_92_device);
|
||||
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
const device_t ct_82c100_device = {
|
||||
"C&T 82C100",
|
||||
0,
|
||||
0,
|
||||
ct_82c100_init, ct_82c100_close, ct_82c100_reset,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
@@ -38,6 +38,10 @@
|
||||
/* Is the CPU 8088 or 8086. */
|
||||
int is8086 = 0;
|
||||
|
||||
uint8_t use_custom_nmi_vector = 0;
|
||||
uint32_t custom_nmi_vector = 0x00000000;
|
||||
|
||||
|
||||
/* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */
|
||||
static uint8_t pfq[6];
|
||||
|
||||
@@ -578,6 +582,9 @@ reset_808x(int hard)
|
||||
|
||||
prefetching = 1;
|
||||
cpu_alu_op = 0;
|
||||
|
||||
use_custom_nmi_vector = 0x00;
|
||||
custom_nmi_vector = 0x00000000;
|
||||
}
|
||||
|
||||
|
||||
@@ -943,6 +950,41 @@ interrupt(uint16_t addr)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
custom_nmi(void)
|
||||
{
|
||||
uint16_t old_cs, old_ip;
|
||||
uint16_t new_cs, new_ip;
|
||||
uint16_t tempf;
|
||||
|
||||
cpu_state.eaaddr = 0x0002;
|
||||
old_cs = CS;
|
||||
access(5, 16);
|
||||
(void) readmemw(0, cpu_state.eaaddr);
|
||||
new_ip = custom_nmi_vector & 0xffff;
|
||||
wait(1, 0);
|
||||
cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff;
|
||||
access(6, 16);
|
||||
(void) readmemw(0, cpu_state.eaaddr);
|
||||
new_cs = custom_nmi_vector >> 16;
|
||||
prefetching = 0;
|
||||
pfq_clear();
|
||||
ovr_seg = NULL;
|
||||
access(39, 16);
|
||||
tempf = cpu_state.flags & 0x0fd7;
|
||||
push(&tempf);
|
||||
cpu_state.flags &= ~(I_FLAG | T_FLAG);
|
||||
access(40, 16);
|
||||
push(&old_cs);
|
||||
old_ip = cpu_state.pc;
|
||||
load_cs(new_cs);
|
||||
access(68, 16);
|
||||
set_ip(new_ip);
|
||||
access(41, 16);
|
||||
push(&old_ip);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
irq_pending(void)
|
||||
{
|
||||
@@ -967,7 +1009,10 @@ check_interrupts(void)
|
||||
}
|
||||
if (nmi && nmi_enable && nmi_mask) {
|
||||
nmi_enable = 0;
|
||||
interrupt(2);
|
||||
if (use_custom_nmi_vector)
|
||||
custom_nmi();
|
||||
else
|
||||
interrupt(2);
|
||||
#ifndef OLD_NMI_BEHAVIOR
|
||||
nmi = 0;
|
||||
#endif
|
||||
|
@@ -715,6 +715,9 @@ extern int reset_on_hlt, hlt_reset_pending;
|
||||
|
||||
extern cyrix_t cyrix;
|
||||
|
||||
extern uint8_t use_custom_nmi_vector;
|
||||
extern uint32_t custom_nmi_vector;
|
||||
|
||||
extern void (*cpu_exec)(int cycs);
|
||||
extern uint8_t do_translate, do_translate2;
|
||||
|
||||
|
@@ -128,7 +128,7 @@ serial_update_ints(serial_t *dev)
|
||||
dev->iir = 0;
|
||||
}
|
||||
|
||||
if (stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) {
|
||||
if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) {
|
||||
if (dev->type >= SERIAL_NS16450)
|
||||
picintlevel(1 << dev->irq);
|
||||
else
|
||||
@@ -615,7 +615,7 @@ serial_remove(serial_t *dev)
|
||||
|
||||
|
||||
void
|
||||
serial_setup(serial_t *dev, uint16_t addr, int irq)
|
||||
serial_setup(serial_t *dev, uint16_t addr, uint8_t irq)
|
||||
{
|
||||
serial_log("Adding serial port %i at %04X...\n", dev->inst, addr);
|
||||
|
||||
|
@@ -41,6 +41,7 @@ extern const device_t contaq_82c596a_device;
|
||||
extern const device_t contaq_82c597_device;
|
||||
|
||||
/* C&T */
|
||||
extern const device_t ct_82c100_device;
|
||||
extern const device_t neat_device;
|
||||
extern const device_t scat_device;
|
||||
extern const device_t scat_4_device;
|
||||
@@ -67,6 +68,7 @@ extern const device_t i420zx_device;
|
||||
extern const device_t i430lx_device;
|
||||
extern const device_t i430nx_device;
|
||||
extern const device_t i430fx_device;
|
||||
extern const device_t i430fx_old_device;
|
||||
extern const device_t i430fx_rev02_device;
|
||||
extern const device_t i430hx_device;
|
||||
extern const device_t i430vx_device;
|
||||
@@ -86,6 +88,7 @@ extern const device_t sio_device;
|
||||
extern const device_t sio_zb_device;
|
||||
|
||||
extern const device_t piix_device;
|
||||
extern const device_t piix_old_device;
|
||||
extern const device_t piix_rev02_device;
|
||||
extern const device_t piix3_device;
|
||||
extern const device_t piix4_device;
|
||||
|
@@ -661,6 +661,9 @@ extern int machine_tandy_init(const machine_t *);
|
||||
extern int machine_tandy1000hx_init(const machine_t *);
|
||||
extern int machine_tandy1000sl2_init(const machine_t *);
|
||||
|
||||
/* m_v86p.c */
|
||||
extern int machine_v86p_init(const machine_t *);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *tandy1k_get_device(void);
|
||||
extern const device_t *tandy1k_hx_get_device(void);
|
||||
|
@@ -121,6 +121,7 @@ extern void nvr_wp_set(int set, int h, nvr_t *nvr);
|
||||
extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr);
|
||||
extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr);
|
||||
extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr);
|
||||
extern void nvr_irq_set(int irq, nvr_t *nvr);
|
||||
|
||||
|
||||
#endif /*EMU_NVR_H*/
|
||||
|
@@ -36,7 +36,7 @@ extern int stricmp(const char* s1, const char* s2);
|
||||
extern int strnicmp(const char* s1, const char* s2, size_t n);
|
||||
#endif
|
||||
|
||||
#if defined(UNIX) && defined(FREEBSD) || defined(__APPLE__)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__)
|
||||
/* FreeBSD has largefile by default. */
|
||||
# define fopen64 fopen
|
||||
# define fseeko64 fseeko
|
||||
|
@@ -77,7 +77,7 @@ extern serial_t * serial_attach(int port,
|
||||
void *priv);
|
||||
extern void serial_remove(serial_t *dev);
|
||||
extern void serial_set_type(serial_t *dev, int type);
|
||||
extern void serial_setup(serial_t *dev, uint16_t addr, int irq);
|
||||
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
|
||||
extern void serial_clear_fifo(serial_t *dev);
|
||||
extern void serial_write_fifo(serial_t *dev, uint8_t dat);
|
||||
extern void serial_set_next_inst(int ni);
|
||||
|
@@ -20,6 +20,7 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv);
|
||||
|
||||
extern const device_t acc3221_device;
|
||||
extern const device_t f82c710_device;
|
||||
extern const device_t f82c606_device;
|
||||
extern const device_t fdc37c651_device;
|
||||
extern const device_t fdc37c651_ide_device;
|
||||
extern const device_t fdc37c661_device;
|
||||
|
@@ -156,6 +156,7 @@ typedef struct svga_t
|
||||
|
||||
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
|
||||
int force_dword_mode;
|
||||
int force_byte_mode;
|
||||
|
||||
int remap_required;
|
||||
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
|
||||
|
@@ -101,7 +101,7 @@ void svga_recalc_remap_func(svga_t *svga)
|
||||
{
|
||||
int func_nr;
|
||||
|
||||
if (svga->fb_only)
|
||||
if (svga->fb_only || svga->force_byte_mode)
|
||||
func_nr = 0;
|
||||
else {
|
||||
if (svga->force_dword_mode)
|
||||
|
@@ -250,6 +250,9 @@ extern const device_t compaq_cga_2_device;
|
||||
extern const device_t ogc_device;
|
||||
extern const device_t ogc_m24_device;
|
||||
|
||||
/* Chips & Technologies 82C425 */
|
||||
extern const device_t f82c425_video_device;
|
||||
|
||||
/* NCR NGA */
|
||||
extern const device_t nga_device;
|
||||
|
||||
|
@@ -16,7 +16,8 @@
|
||||
add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.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
|
||||
m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c
|
||||
m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.c
|
||||
m_at.c m_at_commodore.c
|
||||
m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c
|
||||
m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c
|
||||
m_at_socket4.c m_at_socket5.c m_at_socket7_3v.c m_at_socket7.c
|
||||
|
97
src/machine/m_v86p.c
Normal file
97
src/machine/m_v86p.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Victor V86P portable computer emulation.
|
||||
*
|
||||
* Author: Lubomir Rintel, <lkundrak@v3.sk>
|
||||
*
|
||||
* Copyright 2021 Lubomir Rintel.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/video.h>
|
||||
|
||||
int
|
||||
machine_v86p_init(const machine_t *model)
|
||||
{
|
||||
int ret, rom = 0;
|
||||
|
||||
ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom",
|
||||
"roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom",
|
||||
0x000f8000, 65536, 0);
|
||||
|
||||
if (!ret) {
|
||||
/* Try an older version of the BIOS. */
|
||||
rom = 1;
|
||||
ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom",
|
||||
"roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom",
|
||||
0x000f8000, 65536, 0);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
/* Try JVERNET's BIOS. */
|
||||
rom = 2;
|
||||
ret = bios_load_linear("roms/machines/v86p/V86P.ROM",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
}
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
if (rom == 2)
|
||||
loadfont("roms/machines/v86p/V86P.FON", 8);
|
||||
else
|
||||
loadfont("roms/machines/v86p/v86pfont.rom", 8);
|
||||
|
||||
machine_common_init(model);
|
||||
|
||||
device_add(&ct_82c100_device);
|
||||
device_add(&f82c606_device);
|
||||
|
||||
device_add(&keyboard_xt_device);
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
device_add(&fdc_xt_device);
|
||||
|
||||
if (gfxcard == VID_INTERNAL)
|
||||
device_add(&f82c425_video_device);
|
||||
|
||||
return ret;
|
||||
}
|
@@ -152,6 +152,7 @@ const machine_t machines[] = {
|
||||
{ "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL },
|
||||
{ "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL },
|
||||
{ "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device },
|
||||
{ "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 512, 128, 127, machine_v86p_init, NULL },
|
||||
{ "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device },
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
|
@@ -20,6 +20,6 @@ void nmi_write(uint16_t port, uint8_t val, void *p)
|
||||
|
||||
void nmi_init(void)
|
||||
{
|
||||
io_sethandler(0x00a0, 0x0001, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL);
|
||||
nmi_mask = 0;
|
||||
}
|
||||
|
@@ -931,6 +931,13 @@ nvr_lock_set(int base, int size, int lock, nvr_t *nvr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nvr_irq_set(int irq, nvr_t *nvr)
|
||||
{
|
||||
nvr->irq = irq;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nvr_at_reset(void *priv)
|
||||
{
|
||||
|
@@ -6,13 +6,23 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Chips & Technologies F82C710 Universal Peripheral Controller (UPC).
|
||||
* Implementation of the Chips & Technologies F82C710 Universal Peripheral
|
||||
* Controller (UPC) and 82C606 CHIPSpak Multifunction Controller.
|
||||
*
|
||||
* Relevant literature:
|
||||
*
|
||||
* [1] Chips and Technologies, Inc.,
|
||||
* 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS,
|
||||
* PRELIMINARY Data Sheet, Revision 1, May 1987.
|
||||
* <https://archive.org/download/82C606/82C606.pdf>
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Eluan Costa Miranda <eluancm@gmail.com>
|
||||
* Lubomir Rintel <lkundrak@v3.sk>
|
||||
*
|
||||
* Copyright 2020 Sarah Walker.
|
||||
* Copyright 2020 Eluan Costa Miranda.
|
||||
* Copyright 2021 Lubomir Rintel.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -25,14 +35,17 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/sio.h>
|
||||
|
||||
typedef struct upc_t
|
||||
{
|
||||
uint32_t local;
|
||||
int configuration_state; /* state of algorithm to enter configuration mode */
|
||||
int configuration_mode;
|
||||
uint16_t cri_addr; /* cri = configuration index register, addr is even */
|
||||
@@ -42,6 +55,8 @@ typedef struct upc_t
|
||||
/* these regs are not affected by reset */
|
||||
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
|
||||
fdc_t *fdc;
|
||||
nvr_t *nvr;
|
||||
void *gameport;
|
||||
serial_t *uart[2];
|
||||
} upc_t;
|
||||
|
||||
@@ -87,6 +102,66 @@ f82c710_update_ports(upc_t *upc)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
f82c606_update_ports(upc_t *upc)
|
||||
{
|
||||
uint8_t uart1_int = 0xff;
|
||||
uint8_t uart2_int = 0xff;
|
||||
uint8_t lpt1_int = 0xff;
|
||||
int nvr_int = -1;
|
||||
|
||||
serial_remove(upc->uart[0]);
|
||||
serial_remove(upc->uart[1]);
|
||||
lpt1_remove();
|
||||
lpt2_remove();
|
||||
|
||||
nvr_at_handler(0, upc->regs[3] * 4, upc->nvr);
|
||||
nvr_at_handler(0, 0x70, upc->nvr);
|
||||
|
||||
switch (upc->regs[8] & 0xc0) {
|
||||
case 0x40: nvr_int = 4; break;
|
||||
case 0x80: uart1_int = 4; break;
|
||||
case 0xc0: uart2_int = 4; break;
|
||||
}
|
||||
|
||||
switch (upc->regs[8] & 0x30) {
|
||||
case 0x10: nvr_int = 3; break;
|
||||
case 0x20: uart1_int = 3; break;
|
||||
case 0x30: uart2_int = 3; break;
|
||||
}
|
||||
|
||||
switch (upc->regs[8] & 0x0c) {
|
||||
case 0x04: nvr_int = 5; break;
|
||||
case 0x08: uart1_int = 5; break;
|
||||
case 0x0c: lpt1_int = 5; break;
|
||||
}
|
||||
|
||||
switch (upc->regs[8] & 0x03) {
|
||||
case 0x01: nvr_int = 7; break;
|
||||
case 0x02: uart2_int = 7; break;
|
||||
case 0x03: lpt1_int = 7; break;
|
||||
}
|
||||
|
||||
if (upc->regs[0] & 1)
|
||||
gameport_remap(upc->gameport, upc->regs[7] * 4);
|
||||
else
|
||||
gameport_remap(upc->gameport, 0);
|
||||
|
||||
if (upc->regs[0] & 2)
|
||||
serial_setup(upc->uart[0], upc->regs[4] * 4, uart1_int);
|
||||
|
||||
if (upc->regs[0] & 4)
|
||||
serial_setup(upc->uart[1], upc->regs[5] * 4, uart2_int);
|
||||
|
||||
if (upc->regs[0] & 8) {
|
||||
lpt1_init(upc->regs[6] * 4);
|
||||
lpt1_irq(lpt1_int);
|
||||
}
|
||||
|
||||
nvr_at_handler(1, upc->regs[3] * 4, upc->nvr);
|
||||
nvr_irq_set(nvr_int, upc->nvr);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
f82c710_config_read(uint16_t port, void *priv)
|
||||
{
|
||||
@@ -151,7 +226,11 @@ f82c710_config_write(uint16_t port, uint8_t val, void *priv)
|
||||
if (upc->cri == 0xf) {
|
||||
upc->configuration_mode = 0;
|
||||
io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
||||
f82c710_update_ports(upc); /* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
||||
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
||||
if (upc->local == 710)
|
||||
f82c710_update_ports(upc);
|
||||
if (upc->local == 606)
|
||||
f82c606_update_ports(upc);
|
||||
} else {
|
||||
upc->regs[upc->cri] = val;
|
||||
}
|
||||
@@ -179,7 +258,8 @@ f82c710_reset(upc_t *upc)
|
||||
lpt1_init(0x378);
|
||||
lpt1_irq(7);
|
||||
|
||||
fdc_reset(upc->fdc);
|
||||
if (upc->local == 710)
|
||||
fdc_reset(upc->fdc);
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -187,8 +267,43 @@ f82c710_init(const device_t *info)
|
||||
{
|
||||
upc_t *upc = (upc_t *) malloc(sizeof(upc_t));
|
||||
memset(upc, 0, sizeof(upc_t));
|
||||
upc->local = info->local;
|
||||
|
||||
upc->fdc = device_add(&fdc_at_device);
|
||||
if (upc->local == 710) {
|
||||
upc->regs[0] = 0x0c;
|
||||
upc->regs[1] = 0x00;
|
||||
upc->regs[2] = 0x00;
|
||||
upc->regs[3] = 0x00;
|
||||
upc->regs[4] = 0xfe;
|
||||
upc->regs[5] = 0x00;
|
||||
upc->regs[6] = 0x9e;
|
||||
upc->regs[7] = 0x00;
|
||||
upc->regs[8] = 0x00;
|
||||
upc->regs[9] = 0xb0;
|
||||
upc->regs[10] = 0x00;
|
||||
upc->regs[11] = 0x00;
|
||||
upc->regs[12] = 0xa0;
|
||||
upc->regs[13] = 0x00;
|
||||
upc->regs[14] = 0x00;
|
||||
|
||||
upc->fdc = device_add(&fdc_at_device);
|
||||
}
|
||||
|
||||
if (upc->local == 606) {
|
||||
/* Set power-on defaults. */
|
||||
upc->regs[0] = 0x00; /* Enable */
|
||||
upc->regs[1] = 0x00; /* Configuration Register */
|
||||
upc->regs[2] = 0x00; /* Ext Baud Rate Select */
|
||||
upc->regs[3] = 0xb0; /* RTC Base */
|
||||
upc->regs[4] = 0xfe; /* UART1 Base */
|
||||
upc->regs[5] = 0xbe; /* UART2 Base */
|
||||
upc->regs[6] = 0x9e; /* Parallel Base */
|
||||
upc->regs[7] = 0x80; /* Game Base */
|
||||
upc->regs[8] = 0xec; /* Interrupt Select */
|
||||
|
||||
upc->nvr = device_add(&at_nvr_old_device);
|
||||
upc->gameport = gameport_add(&gameport_sio_device);
|
||||
}
|
||||
|
||||
upc->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||
upc->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||
@@ -196,25 +311,12 @@ f82c710_init(const device_t *info)
|
||||
io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
||||
io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
||||
|
||||
upc->regs[0] = 0x0c;
|
||||
upc->regs[1] = 0x00;
|
||||
upc->regs[2] = 0x00;
|
||||
upc->regs[3] = 0x00;
|
||||
upc->regs[4] = 0xfe;
|
||||
upc->regs[5] = 0x00;
|
||||
upc->regs[6] = 0x9e;
|
||||
upc->regs[7] = 0x00;
|
||||
upc->regs[8] = 0x00;
|
||||
upc->regs[9] = 0xb0;
|
||||
upc->regs[10] = 0x00;
|
||||
upc->regs[11] = 0x00;
|
||||
upc->regs[12] = 0xa0;
|
||||
upc->regs[13] = 0x00;
|
||||
upc->regs[14] = 0x00;
|
||||
|
||||
f82c710_reset(upc);
|
||||
|
||||
f82c710_update_ports(upc);
|
||||
if (upc->local == 710)
|
||||
f82c710_update_ports(upc);
|
||||
if (upc->local == 606)
|
||||
f82c606_update_ports(upc);
|
||||
|
||||
return upc;
|
||||
}
|
||||
@@ -227,10 +329,19 @@ f82c710_close(void *priv)
|
||||
free(upc);
|
||||
}
|
||||
|
||||
const device_t f82c710_device = {
|
||||
"F82C710 UPC Super I/O",
|
||||
0,
|
||||
const device_t f82c606_device = {
|
||||
"82C606 CHIPSpak Multifunction Controller",
|
||||
0,
|
||||
606,
|
||||
f82c710_init, f82c710_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t f82c710_device = {
|
||||
"F82C710 UPC Super I/O",
|
||||
0,
|
||||
710,
|
||||
f82c710_init, f82c710_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
|
@@ -298,14 +298,17 @@ void plat_midi_input_init(void)
|
||||
|
||||
void plat_midi_input_close(void)
|
||||
{
|
||||
thread_wait_mutex(midiinmtx);
|
||||
if (midiinmtx) thread_wait_mutex(midiinmtx);
|
||||
if (midiin != NULL)
|
||||
{
|
||||
snd_rawmidi_close(midiin);
|
||||
midiin = NULL;
|
||||
}
|
||||
thread_release_mutex(midiinmtx);
|
||||
thread_close_mutex(midiinmtx);
|
||||
if (midiinmtx)
|
||||
{
|
||||
thread_release_mutex(midiinmtx);
|
||||
thread_close_mutex(midiinmtx);
|
||||
}
|
||||
midiinmtx = NULL;
|
||||
}
|
||||
|
||||
|
@@ -154,7 +154,11 @@ static const uint16_t sdl_to_xt[0x200] =
|
||||
[SDL_SCANCODE_KP_2] = 0x50,
|
||||
[SDL_SCANCODE_KP_1] = 0x4F,
|
||||
[SDL_SCANCODE_KP_0] = 0x52,
|
||||
[SDL_SCANCODE_KP_PERIOD] = 0x53
|
||||
[SDL_SCANCODE_KP_PERIOD] = 0x53,
|
||||
|
||||
[SDL_SCANCODE_LGUI] = 0x15B,
|
||||
[SDL_SCANCODE_RGUI] = 0x15C,
|
||||
[SDL_SCANCODE_APPLICATION] = 0x15D
|
||||
};
|
||||
|
||||
typedef struct sdl_blit_params
|
||||
@@ -755,6 +759,7 @@ void monitor_thread(void* param)
|
||||
xargv[cmdargc++] = local_strsep(&linecpy, " ");
|
||||
if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break;
|
||||
}
|
||||
cmdargc--;
|
||||
if (strncasecmp(xargv[0], "exit", 4) == 0)
|
||||
{
|
||||
exit_event = 1;
|
||||
|
668
src/video/vid_f82c425.c
Normal file
668
src/video/vid_f82c425.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Chips & Technologies 82C425 display controller emulation,
|
||||
* with support for 640x200 LCD and SMARTMAP text contrast
|
||||
* enhancement.
|
||||
*
|
||||
* Relevant literature:
|
||||
*
|
||||
* [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller,
|
||||
* Data Sheet, Revision No. 2.2, September 1991.
|
||||
* <https://archive.org/download/82C425/82C425.pdf>
|
||||
*
|
||||
* [2] Pleva et al., COLOR TO MONOCHROME CONVERSION,
|
||||
* U.S. Patent 4,977,398, Dec. 11, 1990.
|
||||
* <https://pimg-fpiw.uspto.gov/fdd/98/773/049/0.pdf>
|
||||
*
|
||||
* Based on Toshiba T1000 plasma display emulation code.
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
* Lubomir Rintel, <lkundrak@v3.sk>
|
||||
*
|
||||
* Copyright 2018,2019 Fred N. van Kempen.
|
||||
* Copyright 2018,2019 Miran Grca.
|
||||
* Copyright 2018,2019 Sarah Walker.
|
||||
* Copyright 2021 Lubomir Rintel.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_cga.h>
|
||||
|
||||
#define F82C425_XSIZE 640
|
||||
#define F82C425_YSIZE 200
|
||||
|
||||
/* Mapping of attributes to colours */
|
||||
static uint32_t smartmap[256][2];
|
||||
static uint32_t colormap[4];
|
||||
|
||||
static video_timings_t timing_f82c425 = {VIDEO_ISA, 8,16,32, 8,16,32};
|
||||
|
||||
static uint8_t st_video_options;
|
||||
static uint8_t st_enabled = 1;
|
||||
static int8_t st_display_internal = -1;
|
||||
|
||||
void f82c425_video_options_set(uint8_t options)
|
||||
{
|
||||
st_video_options = options;
|
||||
}
|
||||
|
||||
void f82c425_video_enable(uint8_t enabled)
|
||||
{
|
||||
st_enabled = enabled;
|
||||
}
|
||||
|
||||
void f82c425_display_set(uint8_t internal)
|
||||
{
|
||||
st_display_internal = (int8_t)internal;
|
||||
}
|
||||
|
||||
uint8_t f82c425_display_get()
|
||||
{
|
||||
return (uint8_t)st_display_internal;
|
||||
}
|
||||
|
||||
|
||||
typedef struct f82c425_t
|
||||
{
|
||||
mem_mapping_t mapping;
|
||||
cga_t cga;
|
||||
uint8_t crtcreg;
|
||||
|
||||
uint64_t dispontime, dispofftime;
|
||||
|
||||
int linepos, displine;
|
||||
int dispon;
|
||||
uint8_t video_options;
|
||||
|
||||
uint8_t *vram;
|
||||
|
||||
/* Registers specific to 82C425. */
|
||||
uint8_t ac_limit;
|
||||
uint8_t threshold;
|
||||
uint8_t shift;
|
||||
uint8_t hsync;
|
||||
uint8_t vsync_blink;
|
||||
uint8_t timing;
|
||||
uint8_t function;
|
||||
} f82c425_t;
|
||||
|
||||
|
||||
/* Convert IRGB representation to RGBI,
|
||||
* useful in SMARTMAP calculations. */
|
||||
static inline uint8_t f82c425_rgbi(uint8_t irgb)
|
||||
{
|
||||
return ((irgb & 0x7) << 1) | (irgb >> 3);
|
||||
}
|
||||
|
||||
/* Convert IRGB SMARTMAP output to a RGB representation of one of 4/8 grey
|
||||
* shades we'd see on an actual V86P display: with some bias toward lighter
|
||||
* shades and a backlight with yellow/green-ish tint. */
|
||||
static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
gs4 = 1 + !!gs4;
|
||||
if (!inv)
|
||||
{
|
||||
rgbi = 15 - rgbi;
|
||||
}
|
||||
c = 0x10 * gs4 * ((rgbi >> gs4) + 2);
|
||||
|
||||
return makecol(c, c + 0x08, c - 0x20);
|
||||
}
|
||||
|
||||
/* Saturating/non-saturating addition for SMARTMAP(see below). */
|
||||
static inline int f82c425_smartmap_add(int a, int b, int sat)
|
||||
{
|
||||
int c = a + b;
|
||||
|
||||
/* (SATURATING OR NON SATURATING) */
|
||||
if (sat)
|
||||
{
|
||||
if (c < 0)
|
||||
c = 0;
|
||||
else if (c > 15)
|
||||
c = 15;
|
||||
}
|
||||
|
||||
return c & 0xf;
|
||||
}
|
||||
|
||||
/* Calculate and cache mapping of CGA text color attribute to a
|
||||
* shade of gray enhanced via the SMARTMAP algorithm.
|
||||
*
|
||||
* This is a straightforward implementation of the algorithm as described
|
||||
* in U.S. Patent 4,977,398 [2]. The comments in capitals refer to portions
|
||||
* of a figure on page 4. */
|
||||
static void f82c425_smartmap(f82c425_t *f82c425)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
uint8_t bg = f82c425_rgbi(i >> 4);
|
||||
uint8_t fg = f82c425_rgbi(i & 0xf);
|
||||
|
||||
/* FIG._4. */
|
||||
if (abs(bg - fg) <= (f82c425->threshold & 0x0f))
|
||||
{
|
||||
/* FOREGROUND=BACKGROUND */
|
||||
if (bg == fg)
|
||||
{
|
||||
/* SPECIAL CASE */
|
||||
if (f82c425->shift == 0xff)
|
||||
{
|
||||
/* CHECK MOST SIGNIFICANT BIT */
|
||||
if (fg & 0x8)
|
||||
{
|
||||
/* FULL WHITE */
|
||||
fg = bg = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FULL BLACK */
|
||||
fg = bg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t sat = f82c425->threshold & 0x10;
|
||||
|
||||
/* DETERMINE WHICH IS LIGHT */
|
||||
if (fg > bg)
|
||||
{
|
||||
fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat);
|
||||
bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat);
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat);
|
||||
bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80);
|
||||
smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate mapping of 320x200 graphical mode colors. */
|
||||
static void f82c425_colormap(f82c425_t *f82c425)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80);
|
||||
}
|
||||
|
||||
static void f82c425_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
if (addr == 0x3d4)
|
||||
f82c425->crtcreg = val;
|
||||
|
||||
if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5)))
|
||||
return;
|
||||
|
||||
if (addr != 0x3d5 || f82c425->crtcreg <= 31)
|
||||
{
|
||||
cga_out(addr, val, &f82c425->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (f82c425->crtcreg)
|
||||
{
|
||||
case 0xd9:
|
||||
f82c425->ac_limit = val;
|
||||
break;
|
||||
case 0xda:
|
||||
f82c425->threshold = val;
|
||||
f82c425_smartmap(f82c425);
|
||||
break;
|
||||
case 0xdb:
|
||||
f82c425->shift = val;
|
||||
f82c425_smartmap(f82c425);
|
||||
break;
|
||||
case 0xdc:
|
||||
f82c425->hsync = val;
|
||||
break;
|
||||
case 0xdd:
|
||||
f82c425->vsync_blink = val;
|
||||
break;
|
||||
case 0xde:
|
||||
f82c425->timing = val;
|
||||
break;
|
||||
case 0xdf:
|
||||
f82c425->function = val;
|
||||
f82c425_smartmap(f82c425);
|
||||
f82c425_colormap(f82c425);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t f82c425_in(uint16_t addr, void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
if ((f82c425->function & 0x01) == 0)
|
||||
return 0xff;
|
||||
|
||||
if (addr == 0x3d4)
|
||||
return f82c425->crtcreg;
|
||||
|
||||
if (addr != 0x3d5 || f82c425->crtcreg <= 31)
|
||||
return cga_in(addr, &f82c425->cga);
|
||||
|
||||
switch (f82c425->crtcreg)
|
||||
{
|
||||
case 0xd9:
|
||||
return f82c425->ac_limit;
|
||||
case 0xda:
|
||||
return f82c425->threshold;
|
||||
case 0xdb:
|
||||
return f82c425->shift;
|
||||
case 0xdc:
|
||||
return f82c425->hsync;
|
||||
case 0xdd:
|
||||
return f82c425->vsync_blink;
|
||||
case 0xde:
|
||||
return f82c425->timing;
|
||||
case 0xdf:
|
||||
return f82c425->function;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static void f82c425_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
f82c425->vram[addr & 0x3fff] = val;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
static uint8_t f82c425_read(uint32_t addr, void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
cycles -= 4;
|
||||
|
||||
return f82c425->vram[addr & 0x3fff];
|
||||
}
|
||||
|
||||
static void f82c425_recalctimings(f82c425_t *f82c425)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime, _dispofftime;
|
||||
|
||||
if (f82c425->function & 0x08)
|
||||
{
|
||||
cga_recalctimings(&f82c425->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
disptime = 651;
|
||||
_dispontime = 640;
|
||||
_dispofftime = disptime - _dispontime;
|
||||
f82c425->dispontime = (uint64_t)(_dispontime * xt_cpu_multi);
|
||||
f82c425->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi);
|
||||
}
|
||||
|
||||
/* Draw a row of text. */
|
||||
static void f82c425_text_row(f82c425_t *f82c425)
|
||||
{
|
||||
uint32_t colors[2];
|
||||
int x, c;
|
||||
uint8_t chr, attr;
|
||||
int drawcursor;
|
||||
int cursorline;
|
||||
int blink;
|
||||
uint16_t addr;
|
||||
uint8_t sc;
|
||||
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
|
||||
uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff;
|
||||
uint8_t sl = f82c425->cga.crtc[9] + 1;
|
||||
int columns = f82c425->cga.crtc[1];
|
||||
|
||||
sc = (f82c425->displine) & 7;
|
||||
addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2;
|
||||
ma += (f82c425->displine >> 3) * columns;
|
||||
|
||||
if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20)
|
||||
{
|
||||
cursorline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) &&
|
||||
((f82c425->cga.crtc[0x0b] & 0x0F) >= sc);
|
||||
}
|
||||
|
||||
for (x = 0; x < columns; x++)
|
||||
{
|
||||
chr = f82c425->vram[(addr + 2 * x) & 0x3FFF];
|
||||
attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF];
|
||||
drawcursor = ((ma == ca) && cursorline &&
|
||||
(f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10));
|
||||
|
||||
blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) &&
|
||||
(attr & 0x80) && !drawcursor);
|
||||
|
||||
if (drawcursor)
|
||||
{
|
||||
colors[0] = smartmap[~attr & 0xff][0];
|
||||
colors[1] = smartmap[~attr & 0xff][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
colors[0] = smartmap[attr][0];
|
||||
colors[1] = smartmap[attr][1];
|
||||
}
|
||||
|
||||
if (blink)
|
||||
colors[1] = colors[0];
|
||||
|
||||
if (f82c425->cga.cgamode & 0x01)
|
||||
{
|
||||
/* High resolution (80 cols) */
|
||||
for (c = 0; c < sl; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[(x << 3) + c] =
|
||||
colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Low resolution (40 columns, stretch pixels horizontally) */
|
||||
for (c = 0; c < sl; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2] =
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2+1] =
|
||||
colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0];
|
||||
}
|
||||
}
|
||||
|
||||
++ma;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a line in CGA 640x200 mode */
|
||||
static void f82c425_cgaline6(f82c425_t *f82c425)
|
||||
{
|
||||
int x, c;
|
||||
uint8_t dat;
|
||||
uint16_t addr;
|
||||
|
||||
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
|
||||
|
||||
addr = ((f82c425->displine) & 1) * 0x2000 +
|
||||
(f82c425->displine >> 1) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
dat = f82c425->vram[addr & 0x3FFF];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[x*8+c] =
|
||||
colormap[dat & 0x80 ? 3 : 0];
|
||||
|
||||
dat = dat << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a line in CGA 320x200 mode. */
|
||||
static void f82c425_cgaline4(f82c425_t *f82c425)
|
||||
{
|
||||
int x, c;
|
||||
uint8_t dat, pattern;
|
||||
uint16_t addr;
|
||||
|
||||
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
|
||||
addr = ((f82c425->displine) & 1) * 0x2000 +
|
||||
(f82c425->displine >> 1) * 80 +
|
||||
((ma & ~1) << 1);
|
||||
|
||||
for (x = 0; x < 80; x++)
|
||||
{
|
||||
dat = f82c425->vram[addr & 0x3FFF];
|
||||
addr++;
|
||||
|
||||
for (c = 0; c < 4; c++)
|
||||
{
|
||||
pattern = (dat & 0xC0) >> 6;
|
||||
if (!(f82c425->cga.cgamode & 0x08)) pattern = 0;
|
||||
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c] =
|
||||
((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c+1] =
|
||||
colormap[pattern & 3];
|
||||
|
||||
dat = dat << 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void f82c425_poll(void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
if (f82c425->video_options != st_video_options ||
|
||||
!!(f82c425->function & 1) != st_enabled)
|
||||
{
|
||||
f82c425->video_options = st_video_options;
|
||||
f82c425->function &= ~1;
|
||||
f82c425->function |= st_enabled ? 1 : 0;
|
||||
|
||||
if (f82c425->function & 0x01)
|
||||
mem_mapping_enable(&f82c425->mapping);
|
||||
else
|
||||
mem_mapping_disable(&f82c425->mapping);
|
||||
}
|
||||
/* Switch between internal LCD and external CRT display. */
|
||||
if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08))
|
||||
{
|
||||
if (st_display_internal)
|
||||
{
|
||||
f82c425->function &= ~0x08;
|
||||
f82c425->timing &= ~0x20;
|
||||
}
|
||||
else
|
||||
{
|
||||
f82c425->function |= 0x08;
|
||||
f82c425->timing |= 0x20;
|
||||
}
|
||||
f82c425_recalctimings(f82c425);
|
||||
}
|
||||
|
||||
if (f82c425->function & 0x08)
|
||||
{
|
||||
cga_poll(&f82c425->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!f82c425->linepos)
|
||||
{
|
||||
timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime);
|
||||
f82c425->cga.cgastat |= 1;
|
||||
f82c425->linepos = 1;
|
||||
if (f82c425->dispon)
|
||||
{
|
||||
if (f82c425->displine == 0)
|
||||
{
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
|
||||
switch (f82c425->cga.cgamode & 0x13)
|
||||
{
|
||||
case 0x12:
|
||||
f82c425_cgaline6(f82c425);
|
||||
break;
|
||||
case 0x02:
|
||||
f82c425_cgaline4(f82c425);
|
||||
break;
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
f82c425_text_row(f82c425);
|
||||
break;
|
||||
}
|
||||
}
|
||||
f82c425->displine++;
|
||||
|
||||
/* Hardcode a fixed refresh rate and VSYNC timing */
|
||||
if (f82c425->displine >= 216)
|
||||
{
|
||||
/* End of VSYNC */
|
||||
f82c425->displine = 0;
|
||||
f82c425->cga.cgastat &= ~8;
|
||||
f82c425->dispon = 1;
|
||||
}
|
||||
else
|
||||
if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6])
|
||||
{
|
||||
/* Start of VSYNC */
|
||||
f82c425->cga.cgastat |= 8;
|
||||
f82c425->dispon = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f82c425->dispon)
|
||||
f82c425->cga.cgastat &= ~1;
|
||||
timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime);
|
||||
f82c425->linepos = 0;
|
||||
|
||||
if (f82c425->displine == 200)
|
||||
{
|
||||
/* Hardcode 640x200 window size */
|
||||
if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get())
|
||||
{
|
||||
xsize = F82C425_XSIZE;
|
||||
ysize = F82C425_YSIZE;
|
||||
set_screen_size(xsize, ysize);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
}
|
||||
video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
|
||||
frames++;
|
||||
|
||||
/* Fixed 640x200 resolution */
|
||||
video_res_x = F82C425_XSIZE;
|
||||
video_res_y = F82C425_YSIZE;
|
||||
|
||||
switch (f82c425->cga.cgamode & 0x12)
|
||||
{
|
||||
case 0x12:
|
||||
video_bpp = 1;
|
||||
break;
|
||||
case 0x02:
|
||||
video_bpp = 2;
|
||||
break;
|
||||
default:
|
||||
video_bpp = 0;
|
||||
}
|
||||
|
||||
f82c425->cga.cgablink++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *f82c425_init(const device_t *info)
|
||||
{
|
||||
f82c425_t *f82c425 = malloc(sizeof(f82c425_t));
|
||||
memset(f82c425, 0, sizeof(f82c425_t));
|
||||
cga_init(&f82c425->cga);
|
||||
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425);
|
||||
|
||||
/* Initialize registers that don't default to zero. */
|
||||
f82c425->hsync = 0x40;
|
||||
f82c425->vsync_blink = 0x72;
|
||||
|
||||
/* 16k video RAM */
|
||||
f82c425->vram = malloc(0x4000);
|
||||
|
||||
timer_set_callback(&f82c425->cga.timer, f82c425_poll);
|
||||
timer_set_p(&f82c425->cga.timer, f82c425);
|
||||
|
||||
/* Occupy memory between 0xB8000 and 0xBFFFF */
|
||||
mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425);
|
||||
/* Respond to CGA I/O ports */
|
||||
io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425);
|
||||
|
||||
/* Initialize color maps for text & graphic modes */
|
||||
f82c425_smartmap(f82c425);
|
||||
f82c425_colormap(f82c425);
|
||||
|
||||
/* Start off in 80x25 text mode */
|
||||
f82c425->cga.cgastat = 0xF4;
|
||||
f82c425->cga.vram = f82c425->vram;
|
||||
f82c425->video_options = 0x01;
|
||||
|
||||
return f82c425;
|
||||
}
|
||||
|
||||
static void f82c425_close(void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
free(f82c425->vram);
|
||||
free(f82c425);
|
||||
}
|
||||
|
||||
static void f82c425_speed_changed(void *p)
|
||||
{
|
||||
f82c425_t *f82c425 = (f82c425_t *)p;
|
||||
|
||||
f82c425_recalctimings(f82c425);
|
||||
}
|
||||
|
||||
const device_t f82c425_video_device = {
|
||||
"82C425 CGA LCD/CRT Controller",
|
||||
0, 0,
|
||||
f82c425_init, f82c425_close, NULL,
|
||||
{ NULL },
|
||||
f82c425_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
@@ -279,11 +279,17 @@ static void
|
||||
hercules_render_overscan_left(hercules_t *dev)
|
||||
{
|
||||
int i;
|
||||
uint32_t width;
|
||||
|
||||
if (dev->ctrl & 0x02)
|
||||
width = (((uint32_t) dev->crtc[1]) << 4);
|
||||
else
|
||||
width = (((uint32_t) dev->crtc[1]) * 9);
|
||||
|
||||
if ((dev->displine + 14) < 0)
|
||||
return;
|
||||
|
||||
if ((((uint32_t) dev->crtc[1]) * 9) == 0)
|
||||
if (width == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
@@ -295,15 +301,21 @@ static void
|
||||
hercules_render_overscan_right(hercules_t *dev)
|
||||
{
|
||||
int i;
|
||||
uint32_t width;
|
||||
|
||||
if (dev->ctrl & 0x02)
|
||||
width = (((uint32_t) dev->crtc[1]) << 4);
|
||||
else
|
||||
width = (((uint32_t) dev->crtc[1]) * 9);
|
||||
|
||||
if ((dev->displine + 14) < 0)
|
||||
return;
|
||||
|
||||
if ((((uint32_t) dev->crtc[1]) * 9) == 0)
|
||||
if (width == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
buffer32->line[dev->displine + 14][8 + (((uint32_t) dev->crtc[1]) * 9) + i] = 0x00000000;
|
||||
buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -649,7 +649,9 @@ ht216_recalctimings(svga_t *svga)
|
||||
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
|
||||
svga->rowoffset <<= 1;
|
||||
if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/
|
||||
svga->crtc[0x17] |= 0x40;
|
||||
svga->force_byte_mode = 1;
|
||||
else
|
||||
svga->force_byte_mode = 0;
|
||||
}
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
}
|
||||
|
@@ -491,26 +491,45 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(8, 1, val | (val << 16), 0, s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
|
||||
break;
|
||||
case 0x400:
|
||||
if (svga->crtc[0x53] & 0x08) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(32, 1, val | (val << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(32, 1, val | (val << 16), 0, s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
|
||||
} else {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(16, 1, val | (val << 16), 0, s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3);
|
||||
}
|
||||
@@ -518,10 +537,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
case 0x600:
|
||||
if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = (val >> 8) | (val << 8);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -536,21 +557,31 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(8, 1, val, 0, s3);
|
||||
s3_accel_start(8, 1, val >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(8, 1, val, 0, s3);
|
||||
s3_accel_start(8, 1, val >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(1, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(16, 1, val, 0, s3);
|
||||
s3_accel_start(16, 1, val >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
|
||||
s3_accel_start(16, 1, val, 0, s3);
|
||||
s3_accel_start(16, 1, val >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
|
||||
@@ -558,21 +589,26 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val)
|
||||
break;
|
||||
case 0x400:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(32, 1, val, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(32, 1, val, 0, s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val, s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, val, s3);
|
||||
break;
|
||||
case 0x600:
|
||||
if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)))
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
|
||||
s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
|
||||
s3_accel_start(8, 1, val & 0xff, 0, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1024,7 +1060,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
if (s3->accel.cmd & 0x100) {
|
||||
if (!(s3->accel.cmd & 0x600)) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
|
||||
}
|
||||
@@ -1039,59 +1078,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
/*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/
|
||||
if (s3->accel.cmd & 0x1000) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
|
||||
else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
}
|
||||
} else {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x400:
|
||||
if (svga->crtc[0x53] & 0x08) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else
|
||||
s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
break;
|
||||
case 0x600:
|
||||
if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1111,59 +1142,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
/*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/
|
||||
if (s3->accel.cmd & 0x1000) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3);
|
||||
else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3);
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3);
|
||||
}
|
||||
} else {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
}
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x400:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
} else
|
||||
s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
break;
|
||||
case 0x600:
|
||||
if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1353,14 +1376,20 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
|
||||
if (s3->accel.cmd & 0x100) {
|
||||
if ((s3->accel.cmd & 0x600) == 0x200) {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, val, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
|
||||
} else {
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, val, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, val, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2720,8 +2749,14 @@ static void s3_recalctimings(svga_t *svga)
|
||||
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
|
||||
|
||||
if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) {
|
||||
if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08))
|
||||
svga->crtc[0x17] |= 0x40;
|
||||
pclog("CRTC14 bit 6 byte mode = %02x, CRTC17 bit 6 byte mode = %02x, CRTC17 bit 5 word mode ma15 = %02x, CRTC31 bit 3 dword mode = %02x\n",
|
||||
svga->crtc[0x14] & 0x40, svga->crtc[0x17] & 0x40, svga->crtc[0x17] & 0x20, svga->crtc[0x31] & 0x08);
|
||||
|
||||
if (svga->crtc[0x31] & 0x08) /*This would typically force dword mode, but we are encountering accel bugs with it, so force byte mode instead*/
|
||||
svga->force_byte_mode = 1;
|
||||
else
|
||||
svga->force_byte_mode = 0;
|
||||
|
||||
switch (svga->bpp) {
|
||||
case 8:
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
@@ -2880,8 +2915,6 @@ static void s3_trio64v_recalctimings(svga_t *svga)
|
||||
|
||||
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
|
||||
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
|
||||
if (((svga->crtc[0x17] & 0x60) == 0x20) && (svga->crtc[0x31] & 0x08))
|
||||
svga->crtc[0x17] |= 0x40;
|
||||
switch (svga->bpp) {
|
||||
case 8:
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
@@ -3507,7 +3540,10 @@ s3_accel_in(uint16_t port, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
break;
|
||||
@@ -3532,13 +3568,19 @@ s3_accel_in(uint16_t port, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
break;
|
||||
@@ -3560,13 +3602,19 @@ s3_accel_in(uint16_t port, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
break;
|
||||
@@ -3603,13 +3651,19 @@ s3_accel_in_w(uint16_t port, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
break;
|
||||
@@ -3635,8 +3689,13 @@ s3_accel_in_l(uint16_t port, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, temp, 0, s3);
|
||||
s3_accel_start(8, 1, temp >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(8, 1, temp, 0, s3);
|
||||
s3_accel_start(8, 1, temp >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(1, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(1, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
|
||||
@@ -3644,8 +3703,13 @@ s3_accel_in_l(uint16_t port, void *p)
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, temp, 0, s3);
|
||||
s3_accel_start(16, 1, temp >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(16, 1, temp, 0, s3);
|
||||
s3_accel_start(16, 1, temp >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
|
||||
@@ -3757,15 +3821,21 @@ s3_accel_read(uint32_t addr, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, temp, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, temp, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3802,13 +3872,19 @@ s3_accel_read_w(uint32_t addr, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
} else
|
||||
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
|
||||
s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
} else
|
||||
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
|
||||
break;
|
||||
@@ -3954,8 +4030,13 @@ s3_accel_read_l(uint32_t addr, void *p)
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(8, 1, temp, 0, s3);
|
||||
s3_accel_start(8, 1, temp >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(8, 1, temp, 0, s3);
|
||||
s3_accel_start(8, 1, temp >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(1, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(1, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3);
|
||||
@@ -3963,8 +4044,13 @@ s3_accel_read_l(uint32_t addr, void *p)
|
||||
break;
|
||||
case 0x200:
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
s3_accel_start(16, 1, temp, 0, s3);
|
||||
s3_accel_start(16, 1, temp >> 16, 0, s3);
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
s3_accel_start(16, 1, temp, 0, s3);
|
||||
s3_accel_start(16, 1, temp >> 16, 0, s3);
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
|
||||
}
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, temp, s3);
|
||||
s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3);
|
||||
@@ -4757,32 +4843,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
|
||||
if (!cpu_input)
|
||||
s3->accel.dat_count = 0;
|
||||
|
||||
/*If the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/
|
||||
if (cpu_input) {
|
||||
if (mix_dat & mix_mask) {
|
||||
if ((s3->accel.cmd & 0x600) != 0x600) {
|
||||
if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
|
||||
cpu_dat = mix_dat;
|
||||
count >>= 3;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cmd == 3) {
|
||||
if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
|
||||
cpu_dat = mix_dat;
|
||||
count >>= 3;
|
||||
}
|
||||
} else {
|
||||
if ((s3->accel.cmd & 0x600) != 0x600) {
|
||||
if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) {
|
||||
cpu_dat = mix_dat;
|
||||
count >>= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) {
|
||||
if ((s3->bpp == 3) && count == 2) {
|
||||
@@ -4806,6 +4866,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
else if (s3->bpp == 1)
|
||||
rd_mask &= 0xffff;
|
||||
|
||||
if (s3->bpp == 0) compare &= 0xff;
|
||||
if (s3->bpp == 1) compare &= 0xffff;
|
||||
|
||||
switch (s3->accel.cmd & 0x600)
|
||||
{
|
||||
case 0x000: mix_mask = 0x80; break;
|
||||
@@ -4814,9 +4877,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break;
|
||||
}
|
||||
|
||||
if (s3->bpp == 0) compare &= 0xff;
|
||||
if (s3->bpp == 1) compare &= 0xffff;
|
||||
|
||||
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
|
||||
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
|
||||
the NOP command)*/
|
||||
|
@@ -613,7 +613,7 @@ MCHOBJ := machine.o machine_table.o \
|
||||
m_xt_xi8088.o m_xt_zenith.o \
|
||||
m_pcjr.o \
|
||||
m_amstrad.o m_europc.o \
|
||||
m_xt_olivetti.o m_tandy.o \
|
||||
m_xt_olivetti.o m_tandy.o m_v86p.o \
|
||||
m_at.o m_at_commodore.o \
|
||||
m_at_t3100e.o m_at_t3100e_vid.o \
|
||||
m_ps1.o m_ps1_hdc.o \
|
||||
@@ -765,6 +765,7 @@ VIDOBJ := video.o \
|
||||
vid_paradise.o \
|
||||
vid_rtg310x.o \
|
||||
vid_ti_cf62011.o \
|
||||
vid_f82c425.o \
|
||||
vid_tvga.o \
|
||||
vid_tgui9440.o vid_tkd8001_ramdac.o \
|
||||
vid_att20c49x_ramdac.o \
|
||||
|
Reference in New Issue
Block a user