From 95638bd90a1ca1aa92c2ae3cdfc8cbeb1c4d4204 Mon Sep 17 00:00:00 2001 From: Korneliusz Osmenda Date: Tue, 10 May 2022 17:29:32 +0200 Subject: [PATCH 01/13] Buildable with ENABLE_DP8390_LOG --- src/network/net_dp8390.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 819412454..13145244f 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -42,11 +42,11 @@ dp8390_log(const char *fmt, ...) { va_list ap; - if (dp8390_do_log >= lvl) { +// if (dp8390_do_log >= lvl) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); - } +// } } #else #define dp8390_log(lvl, fmt, ...) @@ -97,8 +97,8 @@ dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len) uint32_t retval = 0; #ifdef ENABLE_DP8390_LOG - if ((len > 1) && (addr & (len - 1)) - dp3890_log("DP8390: unaligned chipmem word read\n"); + if ((len > 1) && (addr & (len - 1))) + dp8390_log("DP8390: unaligned chipmem word read\n"); #endif dp8390_log("DP8390: Chipmem Read Address=%04x\n", addr); @@ -126,7 +126,7 @@ dp8390_chipmem_write(dp8390_t *dev, uint32_t addr, uint32_t val, unsigned len) int i; #ifdef ENABLE_DP8390_LOG - if ((len > 1) && (addr & (len - 1)) + if ((len > 1) && (addr & (len - 1))) dp8390_log("DP8390: unaligned chipmem word write\n"); #endif @@ -199,7 +199,7 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) dev->remote_start = dev->remote_dma = dev->bound_ptr * 256; dev->remote_bytes = (uint16_t) dp8390_chipmem_read(dev, dev->bound_ptr * 256 + 2, 2); dp8390_log("DP8390: sending buffer #x%x length %d\n", - dev->dp8390.remote_start, dev->dp8390.remote_bytes); + dev->remote_start, dev->remote_bytes); } /* Check for start-tx */ @@ -283,7 +283,7 @@ dp8390_rx_common(void *priv, uint8_t *buf, int io_len) int endbytes; if (io_len != 60) - dp8390_log("%s: rx_frame with length %d\n", dev->name, io_len); + dp8390_log("rx_frame with length %d\n", io_len); if ((dev->CR.stop != 0) || (dev->page_start == 0)) return 0; @@ -801,9 +801,9 @@ dp8390_page1_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len) dev->physaddr[off - 1] = val; if (off == 6) dp8390_log("DP8390: Physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->dp8390->physaddr[0], dev->dp8390.physaddr[1], - dev->dp8390->physaddr[2], dev->dp8390.physaddr[3], - dev->dp8390->physaddr[4], dev->dp8390.physaddr[5]); + dev->physaddr[0], dev->physaddr[1], + dev->physaddr[2], dev->physaddr[3], + dev->physaddr[4], dev->physaddr[5]); break; case 0x07: /* CURR */ From e15eade178cbee54df234e21773f55aa621dbf7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Thu, 12 May 2022 14:37:32 +0200 Subject: [PATCH 02/13] Update net_dp8390.c Fixed the DCR FIFO size. --- src/network/net_dp8390.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 819412454..b36d5e1c9 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -706,7 +706,7 @@ dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, unsigned len) dev->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ dev->DCR.loop = ((val & 0x08) == 0x08); dev->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ - dev->DCR.fifo_size = (val & 0x50) >> 5; + dev->DCR.fifo_size = (val & 0x60) >> 5; break; case 0x0f: /* IMR */ From 340e891d98832180462764bb899c2d3ab36f57c7 Mon Sep 17 00:00:00 2001 From: Jester Date: Sat, 14 May 2022 16:21:00 +0200 Subject: [PATCH 03/13] change m24 BIOS rom to newer 1.44 version https://forum.vcfed.org/index.php?threads/olivetti-m21-m24-with-bios-version-1-44.72815/ --- src/machine/m_xt_olivetti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index a8743cfc5..8541fa2c3 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -752,8 +752,8 @@ machine_xt_m24_init(const machine_t *model) int ret; m24_kbd_t *m24_kbd; - ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_version_1.43_low.bin", - "roms/machines/m24/olivetti_m24_version_1.43_high.bin", + ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_bios_version_1.44_low_even.bin", + "roms/machines/m24/olivetti_m24_bios_version_1.44_high_odd.bin", 0x000fc000, 16384, 0); if (bios_only || !ret) From d0335e967950c2453b1fc0d284542b290848290a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 14 May 2022 18:55:00 +0200 Subject: [PATCH 04/13] Initial emulation of the IBM 8514/A coprocessor for both the MCA and ISA buses. Currently the GUI option is on the QT frontend. --- src/86box.c | 1 + src/config.c | 6 + src/include/86box/86box.h | 3 +- src/include/86box/vid_8514a.h | 109 ++ src/include/86box/vid_svga.h | 10 + src/include/86box/video.h | 3 + src/machine/machine.c | 6 + src/qt/qt_settingsdisplay.cpp | 8 + src/qt/qt_settingsdisplay.ui | 7 + src/video/CMakeLists.txt | 2 +- src/video/vid_8514a.c | 3207 +++++++++++++++++++++++++++++++++ 11 files changed, 3360 insertions(+), 2 deletions(-) create mode 100644 src/include/86box/vid_8514a.h create mode 100644 src/video/vid_8514a.c diff --git a/src/86box.c b/src/86box.c index 0ebc603d3..7dce1d111 100644 --- a/src/86box.c +++ b/src/86box.c @@ -171,6 +171,7 @@ int GAMEBLASTER = 0; /* (C) sound option */ int GUS = 0; /* (C) sound option */ int SSI2001 = 0; /* (C) sound option */ int voodoo_enabled = 0; /* (C) video option */ +int ibm8514_enabled = 0; /* (C) video option */ uint32_t mem_size = 0; /* (C) memory size (Installed on system board)*/ uint32_t isa_mem_size = 0; /* (C) memory size (ISA Memory Cards) */ int cpu_use_dynarec = 0; /* (C) cpu uses/needs Dyna */ diff --git a/src/config.c b/src/config.c index 556a13b09..6f923b28a 100644 --- a/src/config.c +++ b/src/config.c @@ -924,6 +924,7 @@ load_video(void) } voodoo_enabled = !!config_get_int(cat, "voodoo", 0); + ibm8514_enabled = !!config_get_int(cat, "8514a", 0); } @@ -2457,6 +2458,11 @@ save_video(void) else config_set_int(cat, "voodoo", voodoo_enabled); + if (ibm8514_enabled == 0) + config_delete_var(cat, "8514a"); + else + config_set_int(cat, "8514a", ibm8514_enabled); + delete_section_if_empty(cat); } diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 8b84100fd..220d120fa 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -111,7 +111,8 @@ extern int sound_is_float, /* (C) sound uses FP values */ GAMEBLASTER, /* (C) sound option */ GUS, GUSMAX, /* (C) sound option */ SSI2001, /* (C) sound option */ - voodoo_enabled; /* (C) video option */ + voodoo_enabled, /* (C) video option */ + ibm8514_enabled; /* (C) video option */ extern uint32_t mem_size; /* (C) memory size (Installed on system board) */ extern uint32_t isa_mem_size; /* (C) memory size (ISA Memory Cards) */ extern int cpu, /* (C) cpu type */ diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h new file mode 100644 index 000000000..1b071ef29 --- /dev/null +++ b/src/include/86box/vid_8514a.h @@ -0,0 +1,109 @@ +/* + * 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 8514/A card from IBM for the MCA bus and + * generic ISA bus clones without vendor extensions. + * + * + * + * Authors: TheCollector1995 + * + * Copyright 2022 TheCollector1995. + */ + +#ifndef VIDEO_8514A_H +# define VIDEO_8514A_H + +typedef struct ibm8514_t +{ + uint8_t pos_regs[8]; + + int force_old_addr; + int type; + + uint32_t vram_size; + uint32_t vram_mask; + + PALETTE vgapal; + uint8_t dac_mask, dac_status; + uint32_t *map8; + int dac_addr, dac_pos, dac_r, dac_g; + + struct { + uint16_t subsys_cntl; + uint16_t setup_md; + uint8_t advfunc_cntl, ext_advfunc_cntl; + uint16_t cur_y, cur_y_bitres; + uint16_t cur_x, cur_x_bitres; + int16_t desty_axstp; + int16_t destx_distp; + int16_t err_term; + int16_t maj_axis_pcnt; + uint16_t cmd, cmd_back; + uint16_t short_stroke; + uint16_t bkgd_color; + uint16_t frgd_color; + uint16_t wrt_mask; + uint16_t rd_mask; + uint16_t color_cmp; + uint16_t bkgd_mix; + uint16_t frgd_mix; + uint16_t multifunc_cntl; + uint16_t multifunc[16]; + uint8_t pix_trans[2]; + int poly_draw; + int ssv_state; + int x1, x2, y1, y2; + int sys_cnt, sys_cnt2; + int temp_cnt; + int cx, cy; + int sx, sy; + int dx, dy; + uint32_t src, dest; + uint32_t newsrc_blt, newdest_blt; + uint32_t newdest_in, newdest_out; + uint8_t *writemono, *nibbleset; + int x_count, y_count; + int input, output; + + uint16_t cur_x_bit12, cur_y_bit12; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; + int odd_in, odd_out; + + uint16_t scratch; + } accel; + + uint16_t test; + + int v_total, dispend, v_syncstart, split, + h_disp, h_disp_old, h_total, h_disp_time, rowoffset, + dispon, hdisp_on, linecountff, + vc, linepos, oddeven, cursoron, blink, scrollcache, + firstline, lastline, firstline_draw, lastline_draw, + displine, fullchange, x_add, y_add; + uint32_t ma, maback; + + uint8_t *vram, *changedvram, linedbl; + + uint8_t data_available, data_available2; + uint8_t scanmodulos, rowcount; + int htotal, hdisp, vtadj, vdadj, vsadj, sc, + vtb, vdb, vsb, vsyncstart, vsyncwidth; + int vtotal, vdisp; + int disp_cntl, interlace; + uint8_t subsys_cntl, subsys_stat; + + volatile int force_busy, force_busy2; + + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; +} ibm8514_t; +#endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 5109207d0..9881725ff 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -17,6 +17,9 @@ * Copyright 2016-2020 Miran Grca. */ +#include <86box/thread.h> +#include <86box/vid_8514a.h> + #ifndef VIDEO_SVGA_H # define VIDEO_SVGA_H @@ -45,6 +48,7 @@ typedef union { typedef struct svga_t { + ibm8514_t dev8514; mem_mapping_t mapping; uint8_t fast, chain4, chain2_write, chain2_read, @@ -161,12 +165,18 @@ typedef struct svga_t int force_old_addr; + int vga_on; + int remap_required; uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); void *ramdac, *clock_gen; } svga_t; +extern svga_t *svga_8514; + +extern void ibm8514_poll(ibm8514_t *dev, svga_t *svga); +extern void ibm8514_recalctimings(svga_t *svga); extern int svga_init(const device_t *info, svga_t *svga, void *p, int memsize, void (*recalctimings_ex)(struct svga_t *svga), diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 44bf94a08..7253e1049 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -200,6 +200,9 @@ extern void agpgart_set_gart(void *handle, uint32_t base); #ifdef EMU_DEVICE_H +/* IBM 8514/A and generic clones*/ +extern void ibm8514_device_add(void); + /* ATi Mach64 */ extern const device_t mach64gx_isa_device; extern const device_t mach64gx_vlb_device; diff --git a/src/machine/machine.c b/src/machine/machine.c index 5813c1d1a..8bd83b6ba 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -114,6 +114,12 @@ machine_init_ex(int m) if (bios_only || !ret) return ret; + if (gfxcard != VID_NONE) { + if (ibm8514_enabled) { + ibm8514_device_add(); + } + } + /* Reset the graphics card (or do nothing if it was already done by the machine's init function). */ video_reset(gfxcard); diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 394033a47..089232a94 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -46,6 +46,7 @@ SettingsDisplay::~SettingsDisplay() void SettingsDisplay::save() { gfxcard = ui->comboBoxVideo->currentData().toInt(); voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; + ibm8514_enabled = ui->checkBox8514->isChecked() ? 1 : 0; } void SettingsDisplay::onCurrentMachineChanged(int machineId) { @@ -113,6 +114,13 @@ void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) { ui->checkBoxVoodoo->setChecked(voodoo_enabled); } ui->pushButtonConfigureVoodoo->setEnabled(machineHasPci && ui->checkBoxVoodoo->isChecked()); + + bool hasIsa16 = machine_has_bus(machineId, MACHINE_BUS_ISA | MACHINE_AT) > 0; + bool has_MCA = machine_has_bus(machineId, MACHINE_BUS_MCA) > 0; + ui->checkBox8514->setEnabled(hasIsa16 || has_MCA); + if (hasIsa16 || has_MCA) { + ui->checkBox8514->setChecked(ibm8514_enabled > 0); + } } void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) { diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index 2ed153a21..dd637801c 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -63,6 +63,13 @@ + + + + 8514/A + + + diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 3e1ffcc71..ca455ba72 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_compaq_cga.c vid_mda.c vid_hercules.c vid_herculesplus.c vid_incolor.c vid_colorplus.c vid_genius.c vid_pgc.c vid_im1024.c - vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c + vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c vid_8514a.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c new file mode 100644 index 000000000..fbf0264da --- /dev/null +++ b/src/video/vid_8514a.c @@ -0,0 +1,3207 @@ +/* + * 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 8514/A card from IBM for the MCA bus and + * generic ISA bus clones without vendor extensions. + * + * + * + * Authors: TheCollector1995 + * + * Copyright 2022 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/mca.h> +#include <86box/rom.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/vid_8514a.h> +#include "cpu.h" + +#define INT_VSY (1 << 0) +#define INT_GE_BSY (1 << 1) +#define INT_FIFO_OVR (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_MASK 0xf + +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) + +#define FIFO_ENTRIES_8514 (dev->fifo_write_idx - dev->fifo_read_idx) +#define FIFO_FULL_8514 ((dev->fifo_write_idx - dev->fifo_read_idx) >= FIFO_SIZE) +#define FIFO_EMPTY_8514 (dev->fifo_read_idx == dev->fifo_write_idx) + +#define FIFO_TYPE_8514 0xff000000 +#define FIFO_ADDR_8514 0x00ffffff + +static void ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len); +static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *p); +static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *p); +static uint8_t ibm8514_accel_inb(uint16_t port, void *p); +static uint16_t ibm8514_accel_inw(uint16_t port, void *p); + +static void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, uint8_t ssv, int len); +static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len); + +#define READ_PIXTRANS_WORD(cx, n) \ + if (cmd == 1) { \ + temp = dev->vram[((dev->accel.cy * 1024) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.cy * 1024) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } else { \ + temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } + +#define READ(addr, dat) \ + dat = dev->vram[(addr) & (dev->vram_mask)]; + +#define MIX(mixmode, dest_dat, src_dat) { \ + switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + case 0x00: dest_dat = ~dest_dat; break; \ + case 0x01: dest_dat = 0; break; \ + case 0x02: dest_dat = ~0; break; \ + case 0x03: dest_dat = dest_dat; break; \ + case 0x04: dest_dat = ~src_dat; break; \ + case 0x05: dest_dat = src_dat ^ dest_dat; break; \ + case 0x06: dest_dat = ~(src_dat ^ dest_dat); break; \ + case 0x07: dest_dat = src_dat; break; \ + case 0x08: dest_dat = ~(src_dat & dest_dat); break; \ + case 0x09: dest_dat = ~src_dat | dest_dat; break; \ + case 0x0a: dest_dat = src_dat | ~dest_dat; break; \ + case 0x0b: dest_dat = src_dat | dest_dat; break; \ + case 0x0c: dest_dat = src_dat & dest_dat; break; \ + case 0x0d: dest_dat = src_dat & ~dest_dat; break; \ + case 0x0e: dest_dat = ~src_dat & dest_dat; break; \ + case 0x0f: dest_dat = ~(src_dat | dest_dat); break; \ + case 0x10: dest_dat = MIN(src_dat, dest_dat); break; \ + case 0x11: dest_dat = dest_dat - src_dat; break; \ + case 0x12: dest_dat = src_dat - dest_dat; break; \ + case 0x13: dest_dat = src_dat + dest_dat; break; \ + case 0x14: dest_dat = MAX(src_dat, dest_dat); break; \ + case 0x15: dest_dat = (dest_dat - src_dat) / 2; break; \ + case 0x16: dest_dat = (src_dat - dest_dat) / 2; break; \ + case 0x17: dest_dat = (dest_dat + src_dat) / 2; break; \ + case 0x18: dest_dat = MAX(0, (dest_dat - src_dat)); break; \ + case 0x19: dest_dat = MAX(0, (dest_dat - src_dat)); break; \ + case 0x1a: dest_dat = MAX(0, (src_dat - dest_dat)); break; \ + case 0x1b: dest_dat = MIN(0xff, (dest_dat + src_dat)); break; \ + case 0x1c: dest_dat = MAX(0, (dest_dat - src_dat)) / 2; break; \ + case 0x1d: dest_dat = MAX(0, (dest_dat - src_dat)) / 2; break; \ + case 0x1e: dest_dat = MAX(0, (src_dat - dest_dat)) / 2; break; \ + case 0x1f: dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); break; \ + } \ + } + +#define WRITE(addr, dat) \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; + + +static int +ibm8514_cpu_src(ibm8514_t *dev) +{ + if (!(dev->accel.cmd & 0x100)) + return 0; + + if (dev->accel.cmd & 1) + return 1; + + return 0; +} + +static int +ibm8514_cpu_dest(ibm8514_t *dev) +{ + if (!(dev->accel.cmd & 0x100)) + return 0; + + if (dev->accel.cmd & 1) + return 0; + + return 1; +} + + +static void +ibm8514_accel_out_pixtrans(ibm8514_t *dev, uint16_t port, uint16_t val, int len) +{ + uint8_t nibble = 0; + uint32_t pixelxfer = 0, monoxfer = 0xffffffff; + int pixcnt = 0; + int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; + int frgd_mix = (dev->accel.frgd_mix >> 5) & 3; + int bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + int cmd = dev->accel.cmd >> 13; + int and3 = dev->accel.cur_x & 3; + + if (dev->accel.cmd & 0x100) { + if (len != 1) { + /*Bus size*/ + if (dev->accel.cmd & 0x200) /*16-bit*/ + pixcnt = 16; + else /*8-bit*/ + pixcnt = 8; + + /*Pixel transfer data mode, can't be the same as Foreground/Background CPU data*/ + if (pixcntl == 2) { + if ((frgd_mix == 2) || (bkgd_mix == 2)) { + pixelxfer = val; + } else { + if (dev->accel.cmd & 2) { + if (pixcnt == 16) { + if ((cmd != 1) && (dev->accel.cmd & 0x1000)) + val = (val >> 8) | (val << 8); + } + if (and3 == 3) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x10; + if (val & 0x04) + nibble |= 0x08; + if (val & 0x08) + nibble |= 0x04; + if (val & 0x10) + nibble |= 0x02; + if (val & 0x200) + nibble |= 0x01; + if (val & 0x400) + nibble |= 0x80; + if (val & 0x800) + nibble |= 0x40; + if (val & 0x1000) + nibble |= 0x20; + } else if (and3 == 2) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x20; + if (val & 0x04) + nibble |= 0x10; + if (val & 0x08) + nibble |= 0x08; + if (val & 0x10) + nibble |= 0x04; + if (val & 0x200) + nibble |= 0x02; + if (val & 0x400) + nibble |= 0x01; + if (val & 0x800) + nibble |= 0x80; + if (val & 0x1000) + nibble |= 0x40; + } else if (and3 == 1) { + if (dev->accel.cmd & 0x1000) + goto regular_nibble; + if (val & 0x02) + nibble |= 0x40; + if (val & 0x04) + nibble |= 0x20; + if (val & 0x08) + nibble |= 0x10; + if (val & 0x10) + nibble |= 0x08; + if (val & 0x200) + nibble |= 0x04; + if (val & 0x400) + nibble |= 0x02; + if (val & 0x800) + nibble |= 0x01; + if (val & 0x1000) + nibble |= 0x80; + } else { +regular_nibble: + if (val & 0x02) + nibble |= 0x80; + if (val & 0x04) + nibble |= 0x40; + if (val & 0x08) + nibble |= 0x20; + if (val & 0x10) + nibble |= 0x10; + if (val & 0x200) + nibble |= 0x08; + if (val & 0x400) + nibble |= 0x04; + if (val & 0x800) + nibble |= 0x02; + if (val & 0x1000) + nibble |= 0x01; + } + + if ((and3 == 0) || (dev->accel.cmd & 0x1000)) { + monoxfer = nibble; + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, dev, len); + if (dev->accel.nibbleset != NULL) { + free(dev->accel.nibbleset); + dev->accel.nibbleset = NULL; + } + if (dev->accel.writemono != NULL) { + free(dev->accel.writemono); + dev->accel.writemono = NULL; + } + return; + } + + dev->accel.writemono[dev->accel.x_count] = nibble; + if (val & 0x1c00) { + if (and3 == 1) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } else if (and3 == 2) { + if (val & 0x1000) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x40; + } else if (val & 0x800) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } else if (and3 == 3) { + if (val & 0x1000) { + if (val & 0x800) { + if (val & 0x400) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x60; + } else if (val & 0x400) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xa0; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x20; + } else if (val & 0x800) { + if (val & 0x400) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + } else if (val & 0x1000) { + if (val & 0x400) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0x60; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x40; + } else if (val & 0x400) { + if (val & 0x800) { + if (val & 0x1000) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xc0; + } else if (val & 0x1000) { + if (val & 0x800) + dev->accel.nibbleset[dev->accel.x_count] = 0xe0; + else + dev->accel.nibbleset[dev->accel.x_count] = 0xa0; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0x80; + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + } + } else + dev->accel.nibbleset[dev->accel.x_count] = 0; + + dev->accel.x_count++; + if (dev->accel.x_count == dev->accel.sys_cnt) { + for (int i = 0; i < dev->accel.x_count; i++) { + dev->accel.writemono[i] &= ~dev->accel.nibbleset[i]; + dev->accel.writemono[i] |= dev->accel.nibbleset[i + 1]; + ibm8514_accel_start(pixcnt, 1, dev->accel.writemono[i], pixelxfer, dev, len); + } + + dev->accel.x_count = 0; + if (dev->accel.nibbleset != NULL) { + free(dev->accel.nibbleset); + dev->accel.nibbleset = NULL; + } + if (dev->accel.writemono != NULL) { + free(dev->accel.writemono); + dev->accel.writemono = NULL; + } + } + return; + } + monoxfer = val; + } + } else { + pixelxfer = val; + } + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, dev, len); + } + } +} + +static void +ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) +{ + + switch (port) { + case 0x82e8: + case 0xc2e8: + if (len == 1) { + dev->accel.cur_y_bitres = (dev->accel.cur_y_bitres & 0xff00) | val; + dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; + } else { + dev->accel.cur_y_bitres = val; + dev->accel.cur_y = val & 0x7ff; + dev->accel.cur_y_bit12 = (val & 0x1000) >> 8; + } + break; + case 0x82e9: + case 0xc2e9: + if (len == 1) { + dev->accel.cur_y_bitres = (dev->accel.cur_y_bitres & 0xff) | (val << 8); + dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); + dev->accel.cur_y_bit12 = val & 0x10; + } + break; + + case 0x86e8: + case 0xc6e8: + if (len == 1) { + dev->accel.cur_x_bitres = (dev->accel.cur_x_bitres & 0xff00) | val; + dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; + } else { + dev->accel.cur_x_bitres = val; + dev->accel.cur_x = val & 0x7ff; + dev->accel.cur_x_bit12 = (val & 0x1000) >> 8; + } + break; + case 0x86e9: + case 0xc6e9: + if (len == 1) { + dev->accel.cur_x_bitres = (dev->accel.cur_x_bitres & 0xff) | (val << 8); + dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); + dev->accel.cur_x_bit12 = val & 0x10; + } + break; + + case 0x8ae8: + case 0xcae8: + if (len == 1) + dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; + else { + dev->accel.desty_axstp = val & 0x3fff; + if (val & 0x2000) + dev->accel.desty_axstp |= ~0x1fff; + } + break; + case 0x8ae9: + case 0xcae9: + if (len == 1) { + dev->accel.desty_axstp = (dev->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.desty_axstp |= ~0x1fff; + } + break; + + case 0x8ee8: + case 0xcee8: + if (len == 1) + dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; + else { + dev->accel.destx_distp = val & 0x3fff; + if (val & 0x2000) + dev->accel.destx_distp |= ~0x1fff; + } + break; + case 0x8ee9: + case 0xcee9: + if (len == 1) { + dev->accel.destx_distp = (dev->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.destx_distp |= ~0x1fff; + } + break; + + case 0x92e8: + if (len != 1) + dev->test = val; + case 0xd2e8: + if (len == 1) + dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; + else { + dev->accel.err_term = val & 0x3fff; + if (val & 0x2000) + dev->accel.err_term |= ~0x1fff; + } + break; + case 0x92e9: + case 0xd2e9: + if (len == 1) { + dev->accel.err_term = (dev->accel.err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.err_term |= ~0x1fff; + } + break; + + case 0x96e8: + case 0xd6e8: + if (len == 1) + dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0x700) | val; + else { + dev->accel.maj_axis_pcnt = val & 0x7ff; + } + break; + case 0x96e9: + case 0xd6e9: + if (len == 1) { + dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0xff) | ((val & 0x07) << 8); + } + break; + + case 0x9ae8: + case 0xdae8: + dev->accel.ssv_state = 0; + if (len == 1) + dev->accel.cmd = (dev->accel.cmd & 0xff00) | val; + else { + dev->data_available = 0; + dev->data_available2 = 0; + dev->accel.cmd = val; + if (dev->accel.cmd & 0x100) + dev->accel.cmd_back = 0; + ibm8514_accel_start(-1, 0, -1, 0, dev, len); + } + break; + case 0x9ae9: + case 0xdae9: + if (len == 1) { + dev->data_available = 0; + dev->data_available2 = 0; + dev->accel.cmd = (dev->accel.cmd & 0xff) | (val << 8); + if (port == 0xdae9) { + if (dev->accel.cmd & 0x100) + dev->accel.cmd_back = 0; + } + ibm8514_accel_start(-1, 0, -1, 0, dev, len); + } + break; + + case 0x9ee8: + case 0xdee8: + dev->accel.ssv_state = 1; + if (len == 1) + dev->accel.short_stroke = (dev->accel.short_stroke & 0xff00) | val; + else { + dev->accel.short_stroke = val; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_y & 0x400) + dev->accel.cy |= ~0x3ff; + if (dev->accel.cmd & 0x1000) { + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + } else { + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + } + } + break; + case 0x9ee9: + case 0xdee9: + if (len == 1) { + dev->accel.short_stroke = (dev->accel.short_stroke & 0xff) | (val << 8); + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_y & 0x400) + dev->accel.cy |= ~0x3ff; + + if (dev->accel.cmd & 0x1000) { + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + } else { + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + } + } + break; + + case 0xa2e8: + case 0xe2e8: + if (port == 0xe2e8) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0x00ff) | val; + else + dev->accel.bkgd_color = val; + } else { + if (ibm8514_cpu_dest(dev)) + break; + ibm8514_accel_out_pixtrans(dev, port, val, len); + } + } else { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0x00ff) | val; + else + dev->accel.bkgd_color = val; + } + break; + case 0xa2e9: + case 0xe2e9: + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0xff00) | (val << 8); + break; + + case 0xa6e8: + case 0xe6e8: + if (port == 0xe6e8) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0x00ff) | val; + else + dev->accel.frgd_color = val; + } else { + if (ibm8514_cpu_dest(dev)) + break; + ibm8514_accel_out_pixtrans(dev, port, val, len); + } + } else { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0x00ff) | val; + else + dev->accel.frgd_color = val; + } + break; + case 0xa6e9: + case 0xe6e9: + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0xff00) | (val << 8); + break; + + case 0xaae8: + case 0xeae8: + if (len == 1) + dev->accel.wrt_mask = (dev->accel.wrt_mask & 0x00ff) | val; + else + dev->accel.wrt_mask = val; + break; + case 0xaae9: + case 0xeae9: + if (len == 1) + dev->accel.wrt_mask = (dev->accel.wrt_mask & 0xff00) | (val << 8); + break; + + case 0xaee8: + case 0xeee8: + if (len == 1) + dev->accel.rd_mask = (dev->accel.rd_mask & 0x00ff) | val; + else + dev->accel.rd_mask = val; + break; + case 0xaee9: + case 0xeee9: + if (len == 1) + dev->accel.rd_mask = (dev->accel.rd_mask & 0xff00) | (val << 8); + break; + + case 0xb2e8: + case 0xf2e8: + if (len == 1) + dev->accel.color_cmp = (dev->accel.color_cmp & 0x00ff) | val; + else + dev->accel.color_cmp = val; + break; + case 0xb2e9: + case 0xf2e9: + if (len == 1) + dev->accel.color_cmp = (dev->accel.color_cmp & 0xff00) | (val << 8); + break; + + case 0xb6e8: + case 0xf6e8: + dev->accel.bkgd_mix = val & 0xff; + break; + + case 0xbae8: + case 0xfae8: + dev->accel.frgd_mix = val & 0xff; + break; + + case 0xbee8: + case 0xfee8: + if (len == 1) + dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff00) | val; + else { + dev->accel.multifunc_cntl = val; + dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if (port == 0xfee8) + dev->accel.cmd_back = 1; + else + dev->accel.cmd_back = 0; + } + break; + case 0xbee9: + case 0xfee9: + if (len == 1) { + dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); + dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if (port == 0xfee9) + dev->accel.cmd_back = 1; + else + dev->accel.cmd_back = 0; + } + break; + } +} + +static void +ibm8514_ramdac_out(uint16_t port, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + uint8_t index; + + switch (port) { + case 0x2ea: + svga_out(0x3c6, val, svga); + break; + case 0x2eb: + svga_out(0x3c7, val, svga); + break; + case 0x2ec: + svga_out(0x3c8, val, svga); + break; + case 0x2ed: + svga_out(0x3c9, val, svga); + break; + } +} + +static uint8_t +ibm8514_ramdac_in(uint16_t port, void *p) +{ + svga_t *svga = (svga_t *)p; + uint8_t ret = 0xff; + uint8_t index; + + switch (port) { + case 0x2ea: + ret = svga_in(0x3c6, svga); + break; + case 0x2eb: + ret = svga_in(0x3c7, svga); + break; + case 0x2ec: + ret = svga_in(0x3c8, svga); + break; + case 0x2ed: + ret = svga_in(0x3c9, svga); + break; + + } + return ret; +} + +static void +ibm8514_io_remove(svga_t *svga) +{ + io_removehandler(0x2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x2ea, 0x0004, ibm8514_ramdac_in, NULL, NULL, ibm8514_ramdac_out, NULL, NULL, svga); + io_removehandler(0x6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x12e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x16e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x1ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x1ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x22e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x26e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x2ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x42e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x4ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x52e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x56e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x5ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x5ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x82e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x86e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x8ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x8ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x92e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x96e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x9ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0x9ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xa2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xa6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xaae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xaee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xb2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xb6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xbae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xbee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xe2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + + io_removehandler(0xc2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xc6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xcae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xcee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xd2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xd6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xdae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xdee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xe6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xeae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xeee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xf2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xf6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xfae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_removehandler(0xfee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); +} + +static void +ibm8514_io_set(svga_t *svga) +{ + io_sethandler(0x2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x2ea, 0x0004, ibm8514_ramdac_in, NULL, NULL, ibm8514_ramdac_out, NULL, NULL, svga); + io_sethandler(0x6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x12e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x16e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x1ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x1ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x22e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x26e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x2ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x42e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x4ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x52e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x56e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x5ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x5ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x82e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x86e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x8ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x8ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x92e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x96e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x9ae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0x9ee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xa2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xa6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xaae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xaee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xb2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xb6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xbae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xbee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xe2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + + io_sethandler(0xc2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xc6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xcae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xcee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xd2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xd6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xdae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xdee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xe6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xeae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xeee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xf2e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xf6e8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xfae8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); + io_sethandler(0xfee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); +} + +static void +ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) +{ + ibm8514_t *dev = &svga->dev8514; + + if (port & 0x8000) { + ibm8514_accel_out_fifo(dev, port, val, len); + } else { + switch (port) { + case 0x2e8: + if (len == 1) + dev->htotal = (dev->htotal & 0xff00) | val; + else { + dev->htotal = val; + svga_recalctimings(svga); + } + break; + case 0x2e9: + if (len != 1) { + dev->htotal = (dev->htotal & 0xff) | (val << 8); + //pclog("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); + svga_recalctimings(svga); + } + break; + + case 0x6e8: + dev->hdisp = val; + //pclog("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + svga_recalctimings(svga); + break; + + case 0xae8: + //pclog("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + svga_recalctimings(svga); + break; + + case 0xee8: + //pclog("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); + svga_recalctimings(svga); + break; + + case 0x12e8: + if (len == 1) + dev->vtotal = (dev->vtotal & 0x1f00) | val; + else { + dev->vtotal = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x12e9: + if (len == 1) { + dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8); + //pclog("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); + svga_recalctimings(svga); + } + break; + + case 0x16e8: + if (len == 1) + dev->vdisp = (dev->vdisp & 0x1f00) | val; + else { + dev->vdisp = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x16e9: + if (len == 1) { + dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8); + //pclog("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); + svga_recalctimings(svga); + } + break; + + case 0x1ae8: + if (len == 1) + dev->vsyncstart = (dev->vsyncstart & 0x1f00) | val; + else { + dev->vsyncstart = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x1ae9: + if (len == 1) { + dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8); + //pclog("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); + svga_recalctimings(svga); + } + break; + + case 0x1ee8: + dev->vsyncwidth = val; + svga_recalctimings(svga); + break; + + case 0x22e8: + dev->disp_cntl = val & 0x7e; + dev->interlace = !!(val & 0x10); + //pclog("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + svga_recalctimings(svga); + break; + + case 0x42e8: + if (len == 1) { + dev->subsys_stat &= ~val; + } else { + dev->subsys_stat &= ~(val & 0xff); + dev->subsys_cntl = (val >> 8); + } + break; + case 0x42e9: + if (len == 1) { + dev->subsys_cntl = val; + } + break; + + case 0x4ae8: + dev->accel.advfunc_cntl = val & 7; + svga->vga_on = ((dev->accel.advfunc_cntl & 1) == 0) ? 1 : 0; + //pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", svga->vga_on, val); + svga_recalctimings(svga); + break; + } + } +} + +static void +ibm8514_accel_outb(uint16_t port, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + ibm8514_accel_out(port, val, svga, 1); +} + +static void +ibm8514_accel_outw(uint16_t port, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + ibm8514_accel_out(port, val, svga, 2); +} + +static uint32_t +ibm8514_accel_in(uint16_t port, svga_t *svga, int len) +{ + ibm8514_t *dev = &svga->dev8514; + uint32_t temp = 0; + int cmd; + + switch (port) { + case 0x6e8: + temp = dev->hdisp; + break; + + case 0x22e8: + temp = dev->disp_cntl; + break; + + case 0x26e8: + if (len == 1) + temp = dev->htotal & 0xff; + else + temp = dev->htotal; + break; + case 0x26e9: + if (len == 1) + temp = dev->htotal >> 8; + break; + + case 0x2ee8: + temp = dev->subsys_cntl; + break; + + case 0x42e8: + if (len != 1) + temp = dev->subsys_stat | 0xa0 | 0x8000; + else + temp = dev->subsys_stat | 0xa0; + break; + + case 0x42e9: + if (len == 1) + temp |= 0x80; + break; + + case 0x92e8: + if (len != 1) { + temp = dev->test; + } + break; + + case 0x9ae8: + case 0xdae8: + temp = 0; + if (len != 1) { + if (dev->force_busy) + temp |= 0x200; /*Hardware busy*/ + dev->force_busy = 0; + if (dev->data_available) { + temp |= 0x100; /*Read Data available*/ + dev->data_available = 0; + } + } + break; + case 0x9ae9: + case 0xdae9: + temp = 0; + if (len == 1) { + if (dev->force_busy2) + temp |= 2; /*Hardware busy*/ + dev->force_busy2 = 0; + if (dev->data_available2) { + temp |= 1; /*Read Data available*/ + dev->data_available2 = 0; + } + } + break; + + case 0xe2e8: + case 0xe6e8: + if (ibm8514_cpu_dest(dev)) { + if (len == 1) { + ;//READ_PIXTRANS_BYTE_IO(0) + } else { + cmd = (dev->accel.cmd >> 13); + READ_PIXTRANS_WORD(dev->accel.cx, 0) + if (dev->accel.input && !dev->accel.odd_in && !dev->accel.sx) { + temp &= ~0xff00; + temp |= (dev->vram[(dev->accel.newdest_in + dev->accel.cur_x) & dev->vram_mask] << 8); + } + } + ibm8514_accel_out_pixtrans(dev, port, temp, len); + } + break; + case 0xe2e9: + case 0xe6e9: + if (ibm8514_cpu_dest(dev)) { + if (len == 1) { + ;//READ_PIXTRANS_BYTE_IO(1) + ibm8514_accel_out_pixtrans(dev, port, temp, len); + } + } + break; + } + return temp; +} + + +static uint8_t +ibm8514_accel_inb(uint16_t port, void *p) +{ + svga_t *svga = (svga_t *)p; + return ibm8514_accel_in(port, svga, 1); +} + +static uint16_t +ibm8514_accel_inw(uint16_t port, void *p) +{ + svga_t *svga = (svga_t *)p; + return ibm8514_accel_in(port, svga, 2); +} + + +static void +ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, uint8_t ssv, int len) +{ + if (!cpu_input) { + dev->accel.ssv_len = ssv & 0x0f; + dev->accel.ssv_dir = ssv & 0xe0; + dev->accel.ssv_draw = ssv & 0x10; + + if (ibm8514_cpu_src(dev)) { + return; /*Wait for data from CPU*/ + } + } + + ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, dev, len); +} + +static void +ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len) +{ + uint8_t src_dat = 0, dest_dat, old_dest_dat; + int frgd_mix, bkgd_mix; + int16_t clip_t = dev->accel.multifunc[1] & 0x3ff; + int16_t clip_l = dev->accel.multifunc[2] & 0x3ff; + uint16_t clip_b = dev->accel.multifunc[3] & 0x7ff; + uint16_t clip_r = dev->accel.multifunc[4] & 0x7ff; + int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; + uint8_t mix_mask = 0x80; + uint8_t compare = dev->accel.color_cmp & 0xff; + int compare_mode = dev->accel.multifunc[0x0a] & 0x38; + int cmd = dev->accel.cmd >> 13; + uint8_t wrt_mask = dev->accel.wrt_mask & 0xff; + uint8_t rd_mask = ((dev->accel.rd_mask & 0x01) << 7) | ((dev->accel.rd_mask & 0xfe) >> 1); + uint8_t frgd_color = dev->accel.frgd_color; + uint8_t bkgd_color = dev->accel.bkgd_color; + uint32_t old_mix_dat; + + if (dev->accel.cmd & 0x100) { + dev->force_busy = 1; + dev->force_busy2 = 1; + } + + frgd_mix = (dev->accel.frgd_mix >> 5) & 3; + bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; + + if (cpu_input) { + if ((dev->accel.cmd & 2) || (pixcntl == 2)) { + if ((frgd_mix == 2) || (bkgd_mix == 2)) { + count >>= 3; + } else if (pixcntl == 2) { + if (dev->accel.cmd & 2) { + count >>= 1; + } else + count >>= 3; + } + } else { + count >>= 3; + } + } + + if (pixcntl == 1) { + mix_dat = 0; + if ((dev->accel.cur_x & 3) == 3) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x20; + } + if ((dev->accel.cur_x & 3) == 2) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x04; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x40; + } + if ((dev->accel.cur_x & 3) == 1) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x40; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x04; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; + } + if ((dev->accel.cur_x & 3) == 0) { + if (dev->accel.multifunc[8] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x40; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; + } + } + + old_mix_dat = mix_dat; + + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. + When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on + the NOP command)*/ + switch (cmd) { + case 0: /*NOP (Short Stroke Vectors)*/ + if (dev->accel.ssv_state == 0) + break; + + if (dev->accel.cmd & 8) { + while (count-- && dev->accel.ssv_len >= 0) { + if (dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + + if (dev->accel.ssv_draw) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (!dev->accel.ssv_len) + break; + + switch (dev->accel.ssv_dir & 0xe0) { + case 0x00: dev->accel.cx++; break; + case 0x20: dev->accel.cx++; dev->accel.cy--; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cx--; dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx--; dev->accel.cy++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cx++; dev->accel.cy++; break; + } + + dev->accel.ssv_len--; + } + + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } + break; + + case 1: /*Draw line*/ + case 5: /*Draw Polygon Boundary Line*/ + if (!cpu_input) { + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_y & 0x400) + dev->accel.cy |= ~0x3ff; + + dev->accel.sy = dev->accel.maj_axis_pcnt; + + if (ibm8514_cpu_src(dev)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(dev)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + + if (dev->accel.cmd & 8) { /*Vector Line*/ + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * 1024) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + switch (dev->accel.cmd & 0xe0) + { + case 0x00: dev->accel.cx++; break; + case 0x20: dev->accel.cx++; dev->accel.cy--; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cx--; dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx--; dev->accel.cy++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cx++; dev->accel.cy++; break; + } + + dev->accel.sy--; + + if (cmd == 5) + break; + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } else { /*Bresenham*/ + if (pixcntl == 1) { + dev->accel.temp_cnt = 8; + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + } else switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cy--; break; + case 0x20: dev->accel.cy--; break; + case 0x40: dev->accel.cx--; break; + case 0x60: dev->accel.cx++; break; + case 0x80: dev->accel.cy++; break; + case 0xa0: dev->accel.cy++; break; + case 0xc0: dev->accel.cx--; break; + case 0xe0: dev->accel.cx++; break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cx--; break; + case 0x20: dev->accel.cx++; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cy++; break; + } + + dev->accel.sy--; + + if (cmd == 5) + break; + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * 1024) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cy--; break; + case 0x20: dev->accel.cy--; break; + case 0x40: dev->accel.cx--; break; + case 0x60: dev->accel.cx++; break; + case 0x80: dev->accel.cy++; break; + case 0xa0: dev->accel.cy++; break; + case 0xc0: dev->accel.cx--; break; + case 0xe0: dev->accel.cx++; break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cx--; break; + case 0x20: dev->accel.cx++; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cy++; break; + } + + dev->accel.sy--; + + if (cmd == 5) + break; + } + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } + break; + + case 2: /*Rectangle fill (X direction)*/ + case 3: /*Rectangle fill (Y direction)*/ + case 4: /*Rectangle fill (Y direction using nibbles)*/ + if (!cpu_input) { + dev->accel.x_count = 0; + dev->accel.odd_out = 0; + dev->accel.odd_in = 0; + dev->accel.input = 0; + dev->accel.output = 0; + dev->accel.newdest_out = 0; + dev->accel.newdest_in = 0; + + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; + + dev->accel.cx = dev->accel.cur_x & 0x3ff; + dev->accel.cy = dev->accel.cur_y & 0x3ff; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_y & 0x400) + dev->accel.cy |= ~0x3ff; + + dev->accel.dest = dev->accel.cy * 1024; + + if (cmd == 4) + dev->accel.cmd |= 2; + else if (cmd == 3) + dev->accel.cmd &= ~2; + + if (ibm8514_cpu_src(dev)) { + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) { + dev->accel.sx += (dev->accel.cur_x & 3); + if (dev->accel.sx) { + dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } + } + } else { + if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { + if (!(dev->accel.sx & 1)) { + dev->accel.output = 1; + dev->accel.newdest_out = (dev->accel.cy + 1) * 1024; + } + } + } + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(dev)) { + if (!(dev->accel.cmd & 2) && (frgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { + if (!(dev->accel.sx & 1)) { + dev->accel.input = 1; + dev->accel.newdest_in = (dev->accel.cy + 1) * 1024; + } + } + dev->data_available = 1; + dev->data_available2 = 1; + return; /*Wait for data from CPU*/ + } + } + + if (dev->accel.cmd & 2) { + if (cpu_input) { +rect_fill_pix: + if (count < 8) { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = 1; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else { + switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + mix_dat >>= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 0x1000) { + dev->accel.cx = dev->accel.cur_x & 0x3ff; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + } + } + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } + } else { + goto rect_fill; + } + } else { + if (cpu_input) { + if (pixcntl == 2) { + goto rect_fill_pix; + } else { + if (dev->accel.input && !dev->accel.output) { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + if (!dev->accel.odd_in && !dev->accel.sx) { + READ(dev->accel.newdest_in + dev->accel.cur_x, src_dat); + READ(dev->accel.newdest_in + dev->accel.cur_x, dest_dat); + } else { + READ(dev->accel.dest + dev->accel.cx, src_dat); + READ(dev->accel.dest + dev->accel.cx, dest_dat); + } + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (!dev->accel.odd_in && !dev->accel.sx) { + WRITE(dev->accel.newdest_in + dev->accel.cur_x, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.odd_in) { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_in = 0; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.newdest_in = (dev->accel.cy + 1) * 1024; + dev->accel.sy--; + return; + } + } else { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sx--; + dev->accel.cx = dev->accel.cur_x; + dev->accel.odd_in = 1; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.newdest_in = (dev->accel.cy + 1) * 1024; + dev->accel.sy--; + return; + } + } + } + } else if (dev->accel.output && !dev->accel.input) { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + src_dat = cpu_dat; + if (!dev->accel.odd_out && !dev->accel.sx) { + READ(dev->accel.newdest_out + dev->accel.cur_x, dest_dat); + } else { + READ(dev->accel.dest + dev->accel.cx, dest_dat); + } + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (!dev->accel.odd_out && !dev->accel.sx) { + WRITE(dev->accel.newdest_out + dev->accel.cur_x, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.odd_out) { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_out = 0; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.newdest_out = (dev->accel.cy + 1) * 1024; + dev->accel.sy--; + return; + } + } else { + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.odd_out = 1; + dev->accel.sx--; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.newdest_out = (dev->accel.cy + 1) * 1024; + dev->accel.sy--; + return; + } + } + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + if (ibm8514_cpu_dest(dev)) { + if (pixcntl == 3) { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + } + } else { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + } + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } + } + } else { +rect_fill: + if (pixcntl == 1) { + if (dev->accel.cmd & 0x40) { + count = dev->accel.maj_axis_pcnt + 1; + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + mix_dat >>= 8; + dev->accel.temp_cnt = 8; + } + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + if (dev->accel.temp_cnt > 0) { + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } else { + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } + } + } else { + while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && + dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } + } + } + } + } + } + break; + + case 6: /*BitBlt*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + dev->accel.x_count = 0; + dev->accel.output = 0; + + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; + + dev->accel.dx = dev->accel.destx_distp & 0x3ff; + dev->accel.dy = dev->accel.desty_axstp & 0x3ff; + + if (dev->accel.destx_distp & 0x400) + dev->accel.dx |= ~0x3ff; + if (dev->accel.desty_axstp & 0x400) + dev->accel.dy |= ~0x3ff; + + dev->accel.cx = dev->accel.cur_x & 0x3ff; + dev->accel.cy = dev->accel.cur_y & 0x3ff; + + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_y & 0x400) + dev->accel.cy |= ~0x3ff; + + dev->accel.src = dev->accel.cy * 1024; + dev->accel.dest = dev->accel.dy * 1024; + + if (ibm8514_cpu_src(dev)) { + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) { + dev->accel.sx += (dev->accel.cur_x & 3); + if (dev->accel.sx) { + dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } + } + } + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(dev)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; /*Wait for data from CPU*/ + } + } + + if (dev->accel.cmd & 2) { + if (cpu_input) { +bitblt_pix: + if (count < 8) { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if (pixcntl == 3) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if (pixcntl == 3) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? 1 : 0; + } + } + switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + } + + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + mix_dat >>= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 2) { + if (!(dev->accel.cmd & 0x1000)) + dev->accel.sx += (dev->accel.cur_x & 3); + } + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 2) { + if (dev->accel.cmd & 0x1000) { + dev->accel.cx = dev->accel.cur_x & 0x3ff; + if (dev->accel.cur_x & 0x400) + dev->accel.cx |= ~0x3ff; + dev->accel.dx = dev->accel.destx_distp & 0x3ff; + if (dev->accel.destx_distp & 0x400) + dev->accel.dx |= ~0x3ff; + } + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * 1024; + dev->accel.src = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } + } else { + goto bitblt; + } + } else { + if (cpu_input) { + if (pixcntl == 2) { + goto bitblt_pix; + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if (pixcntl == 3) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + } + + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * 1024; + dev->accel.src = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } + } else { +bitblt: + if (pixcntl == 1) { + if (dev->accel.cmd & 0x40) { + count = dev->accel.maj_axis_pcnt + 1; + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + mix_dat >>= 8; + dev->accel.temp_cnt = 8; + } + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + break; + } + + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + if (dev->accel.temp_cnt > 0) { + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * 1024; + dev->accel.src = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + } else { + dev->accel.temp_cnt = 8; + while (count-- && dev->accel.sy >= 0) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + break; + } + + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * 1024; + dev->accel.src = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + return; + } + } + } + } + } else { + while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && + dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if (pixcntl == 3) { + if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } else if (dev->accel.cmd & 0x10) { + READ(dev->accel.src + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) { + src_dat = ((src_dat & rd_mask) == rd_mask); + } + } + break; + } + + READ(dev->accel.dest + dev->accel.dx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; + dev->accel.cx--; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; + dev->accel.cx -= (dev->accel.sx) + 1; + } else { + dev->accel.dx += (dev->accel.sx) + 1; + dev->accel.cx += (dev->accel.sx) + 1; + } + + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; + dev->accel.cy++; + } else { + dev->accel.dy--; + dev->accel.cy--; + } + + dev->accel.dest = dev->accel.dy * 1024; + dev->accel.src = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + return; + } + } + } + } + } + } + break; + } +} + +static void +ibm8514_render_8bpp(svga_t *svga) +{ + ibm8514_t *dev = &svga->dev8514; + int x; + uint32_t *p; + uint32_t dat; + + if ((svga->displine + svga->y_add) < 0) { + return; + } + + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= dev->h_disp; x += 8) { + dat = *(uint32_t *)(&dev->vram[dev->ma & dev->vram_mask]); + p[0] = dev->map8[dat & 0xff]; + p[1] = dev->map8[(dat >> 8) & 0xff]; + p[2] = dev->map8[(dat >> 16) & 0xff]; + p[3] = dev->map8[(dat >> 24) & 0xff]; + + dat = *(uint32_t *)(&dev->vram[(dev->ma + 4) & dev->vram_mask]); + p[4] = dev->map8[dat & 0xff]; + p[5] = dev->map8[(dat >> 8) & 0xff]; + p[6] = dev->map8[(dat >> 16) & 0xff]; + p[7] = dev->map8[(dat >> 24) & 0xff]; + + dev->ma += 8; + p += 8; + } + dev->ma &= dev->vram_mask; + } +} + +static void +ibm8514_render_overscan_left(ibm8514_t *dev, svga_t *svga) +{ + int i; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->scrblank || (dev->h_disp == 0)) + return; + + for (i = 0; i < svga->x_add; i++) + buffer32->line[svga->displine + svga->y_add][i] = svga->overscan_color; +} + + +static void +ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) +{ + int i, right; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->scrblank || (dev->h_disp == 0)) + return; + + right = (overscan_x >> 1); + for (i = 0; i < right; i++) + buffer32->line[svga->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; +} + +static void +ibm8514_doblit(int wx, int wy, ibm8514_t *dev, svga_t *svga) +{ + int y_add, x_add, y_start, x_start, bottom; + uint32_t *p; + int i, j; + int xs_temp, ys_temp; + + y_add = (enable_overscan) ? overscan_y : 0; + x_add = (enable_overscan) ? overscan_x : 0; + y_start = (enable_overscan) ? 0 : (overscan_y >> 1); + x_start = (enable_overscan) ? 0 : (overscan_x >> 1); + bottom = (overscan_y >> 1) + (svga->crtc[8] & 0x1f); + + if ((wx <= 0) || (wy <= 0)) + return; + + xs_temp = wx; + ys_temp = wy + 1; + if (xs_temp < 64) + xs_temp = 640; + if (ys_temp < 32) + ys_temp = 200; + + if ((svga->crtc[0x17] & 0x80) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + /* Screen res has changed.. fix up, and let them know. */ + xsize = xs_temp; + ysize = ys_temp; + + if ((xsize > 1984) || (ysize > 2016)) { + /* 2048x2048 is the biggest safe render texture, to account for overscan, + we suppress overscan starting from x 1984 and y 2016. */ + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; + + /* Block resolution changes while in DPMS mode to avoid getting a bogus + screen width (320). We're already rendering a blank screen anyway. */ + set_screen_size(xsize + x_add, ysize + y_add); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if ((wx >= 160) && ((wy + 1) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top and bottom. */ + for (i = 0; i < svga->y_add; i++) { + p = &buffer32->line[i & 0x7ff][0]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + + for (i = 0; i < bottom; i++) { + p = &buffer32->line[(ysize + svga->y_add + i) & 0x7ff][0]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + } + + video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); +} + +void +ibm8514_poll(ibm8514_t *dev, svga_t *svga) +{ + uint32_t x; + int wx, wy; + int old_ma, blink_delay; + + if (!dev->linepos) { + timer_advance_u64(&svga->timer, svga->dispofftime); + dev->linepos = 1; + + if (dev->dispon) { + dev->hdisp_on = 1; + + dev->ma &= dev->vram_mask; + + if (svga->firstline == 2000) { + svga->firstline = svga->displine; + video_wait_for_buffer(); + } + + svga->render(svga); + + svga->x_add = (overscan_x >> 1); + ibm8514_render_overscan_left(dev, svga); + ibm8514_render_overscan_right(dev, svga); + svga->x_add = (overscan_x >> 1); + + if (svga->lastline < svga->displine) + svga->lastline = svga->displine; + } + + svga->displine++; + if (dev->interlace) + svga->displine++; + if (svga->displine > 1500) + svga->displine = 0; + } else { + timer_advance_u64(&svga->timer, svga->dispontime); + dev->hdisp_on = 0; + + dev->linepos = 0; + if (dev->dispon) { + if (svga->linedbl && !dev->linecountff) { + dev->linecountff = 1; + dev->ma = dev->maback; + } else if (dev->sc == dev->rowcount) { + dev->linecountff = 0; + dev->sc = 0; + + dev->maback += (dev->rowoffset << 3); + if (dev->interlace) + dev->maback += (dev->rowoffset << 3); + dev->maback &= dev->vram_mask; + dev->ma = dev->maback; + } else { + dev->linecountff = 0; + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + } + + dev->vc++; + dev->vc &= 2047; + + if (dev->vc == dev->split) { + if (dev->interlace && dev->oddeven) + dev->ma = dev->maback = (dev->rowoffset << 1) + 0; + else + dev->ma = dev->maback = 0; + dev->ma = (dev->ma << 2); + dev->maback = (dev->maback << 2); + + dev->sc = 0; + } + if (dev->vc == dev->dispend) { + dev->dispon = 0; + + for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { + if (dev->changedvram[x]) + dev->changedvram[x]--; + } + + if (svga->fullchange) + svga->fullchange--; + } + if (dev->vc == dev->v_syncstart) { + dev->dispon = 0; + x = dev->h_disp; + + if (dev->interlace && !dev->oddeven) + svga->lastline++; + if (dev->interlace && dev->oddeven) + svga->firstline--; + + wx = x; + + wy = svga->lastline - svga->firstline; + ibm8514_doblit(wx, wy, dev, svga); + + svga->firstline = 2000; + svga->lastline = 0; + + svga->firstline_draw = 2000; + svga->lastline_draw = 0; + + dev->oddeven ^= 1; + + changeframecount = dev->interlace ? 3 : 2; + + if (dev->interlace && dev->oddeven) + dev->ma = dev->maback = 0 + (dev->rowoffset << 1); + else + dev->ma = dev->maback = 0; + + dev->ma = (dev->ma << 2); + dev->maback = (dev->maback << 2); + } + if (dev->vc == dev->v_total) { + dev->vc = 0; + dev->sc = 0; + dev->dispon = 1; + svga->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + dev->linecountff = 0; + } + } +} + +void +ibm8514_recalctimings(svga_t *svga) +{ + ibm8514_t *dev = &svga->dev8514; + + dev->h_disp_time = dev->h_disp = (dev->hdisp + 1) << 3; + dev->rowoffset = (dev->hdisp + 1); + dev->h_total = (dev->htotal + 1); + dev->v_total = (dev->vtotal + 1); + dev->v_syncstart = (dev->vsyncstart + 1); + dev->rowcount = !!(dev->disp_cntl & 0x08); + + if (dev->accel.advfunc_cntl & 4) { + if (dev->h_disp == 8) + dev->h_disp = 1024; + if (dev->rowoffset == 1) + dev->rowoffset = 128; + if (dev->v_total == 1) + dev->v_total = 1632; + if (dev->v_syncstart == 1) + dev->vsyncstart = 1536; + if (dev->interlace) { + dev->dispend = 384; /*Interlaced*/ + dev->v_total >>= 2; + dev->v_syncstart >>= 2; + } else { + dev->dispend = 768; + dev->v_total >>= 1; + dev->v_syncstart >>= 1; + } + //pclog("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); + svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; + } else { + //pclog("640x480 clock mode\n"); + dev->dispend = 480; + dev->v_total >>= 1; + dev->v_syncstart >>= 1; + svga->clock = (cpuclock * (double)(1ull << 32)) / 25175000.0; + } + dev->split = 0xffffff; + svga->render = ibm8514_render_8bpp; + //pclog("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vblankstart=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vblankstart, dev->vsyncstart, dev->split); +} + +static uint8_t +ibm8514_mca_read(int port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + ibm8514_t *dev = &svga->dev8514; + + return(dev->pos_regs[port & 7]); +} + + +static void +ibm8514_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + ibm8514_t *dev = &svga->dev8514; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 7] = val; +} + + +static uint8_t +ibm8514_mca_feedb(void *priv) +{ + return 1; +} + + +static void +*ibm8514_init(const device_t *info) +{ + svga_t *svga = svga_8514; + ibm8514_t *dev = &svga->dev8514; + + dev->vram_size = 1024 << 10; + dev->vram = calloc(dev->vram_size, 1); + dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->vram_mask = dev->vram_size - 1; + dev->map8 = svga->pallook; + + dev->type = info->flags; + + ibm8514_io_remove(svga); + ibm8514_io_set(svga); + + if (info->flags & DEVICE_MCA) { + dev->pos_regs[0] = 0x7f; + dev->pos_regs[1] = 0xef; + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, NULL, svga); + } + + return svga; +} + +static void +ibm8514_close(void *p) +{ + svga_t *svga = (svga_t *)p; + ibm8514_t *dev = &svga->dev8514; + + if (dev) { + free(dev->vram); + free(dev->changedvram); + } +} + +static void +ibm8514_speed_changed(void *p) +{ + svga_t *svga = (svga_t *)p; + ibm8514_t *dev = &svga->dev8514; + + svga_recalctimings(svga); +} + +static void +ibm8514_force_redraw(void *p) +{ + svga_t *svga = (svga_t *)p; + ibm8514_t *dev = &svga->dev8514; + + dev->fullchange = changeframecount; +} + +// clang-format off +const device_t gen8514_isa_device = { + .name = "Generic 8514/A clone (ISA)", + .internal_name = "8514_isa", + .flags = DEVICE_AT | DEVICE_ISA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ibm8514_speed_changed, + .force_redraw = ibm8514_force_redraw, + .config = NULL +}; + +const device_t ibm8514_mca_device = { + .name = "IBM 8514/A (MCA)", + .internal_name = "8514_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = ibm8514_init, + .close = ibm8514_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = ibm8514_speed_changed, + .force_redraw = ibm8514_force_redraw, + .config = NULL +}; + + +void +ibm8514_device_add(void) +{ + if (!ibm8514_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ibm8514_mca_device); + else + device_add(&gen8514_isa_device); +} From d2ab74b79c018ae31c2281eff78852c8911975c5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 14 May 2022 19:08:30 +0200 Subject: [PATCH 05/13] Fixed win32 makefile (was missing the 8514a file on it). --- src/win/Makefile.mingw | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d956b4586..028dc34a7 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -689,6 +689,7 @@ VIDOBJ := agpgart.o video.o \ vid_wy700.o \ vid_ega.o vid_ega_render.o \ vid_svga.o vid_svga_render.o \ + vid_8514a.o \ vid_ddc.o \ vid_vga.o \ vid_ati_eeprom.o \ From 4af6b1dcad765cd5ec2199a5323d68c902b82c9b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 14 May 2022 19:26:41 +0200 Subject: [PATCH 06/13] Compile fix (I didn't commit the svga changes, oops). --- src/video/vid_svga.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 20c4d6dd6..4cc66899c 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -43,6 +43,8 @@ void svga_doblit(int wx, int wy, svga_t *svga); +svga_t *svga_8514; + extern int cyc_total; extern uint8_t edatlookup[4][4]; @@ -552,8 +554,13 @@ svga_recalctimings(svga_t *svga) } else overscan_x = 16; - if (svga->recalctimings_ex) - svga->recalctimings_ex(svga); + if (svga->vga_on) { + if (svga->recalctimings_ex) { + svga->recalctimings_ex(svga); + } + } else { + ibm8514_recalctimings(svga); + } svga->y_add = (overscan_y >> 1) - (svga->crtc[8] & 0x1f); svga->x_add = (overscan_x >> 1); @@ -650,6 +657,11 @@ svga_poll(void *p) int wx, wy; int ret, old_ma; + if (!svga->vga_on) { + ibm8514_poll(&svga->dev8514, svga); + return; + } + if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { svga->hwcursor_on = svga->hwcursor.ysize - svga->hwcursor_latch.yoff; @@ -956,6 +968,8 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->translate_address = NULL; svga->ksc5601_english_font_type = 0; + svga->vga_on = 1; + if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, @@ -977,6 +991,11 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga_pri = svga; + if (ibm8514_enabled) + svga_8514 = svga; + else + svga_8514 = NULL; + svga->ramdac_type = RAMDAC_6BIT; svga->map8 = svga->pallook; From dbb4d35d8ece78b212b705d190e7564b08981aea Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Tue, 17 May 2022 02:07:51 +0500 Subject: [PATCH 07/13] Fix the position of the 8514/A checkbox on the Display settings page --- src/qt/qt_settingsdisplay.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index dd637801c..275af9fd3 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -63,14 +63,14 @@ - + 8514/A - + Qt::Vertical From 5fb1ce2bec4dbc4921605486605dc5ded0dcc4c3 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 19 May 2022 00:15:03 +0200 Subject: [PATCH 08/13] 8514/A changes: Reduced the number of variables that depend on the main SVGA handler. Re-implemented accel command 5 (Polygon Boundary Line) right. Implemented Polygon fill type A and B (latter not tested yet) on accel command 2 per manual. Fixed crashes when starting Win2.1x using the built-in 8514/A driver. Some wip cleanups. --- src/include/86box/vid_8514a.h | 6 +- src/video/vid_8514a.c | 933 +++++++++++++++++++++++++++------- 2 files changed, 753 insertions(+), 186 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 1b071ef29..af46b166d 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -55,20 +55,21 @@ typedef struct ibm8514_t uint16_t frgd_mix; uint16_t multifunc_cntl; uint16_t multifunc[16]; + int16_t clip_left, clip_top; uint8_t pix_trans[2]; int poly_draw; int ssv_state; int x1, x2, y1, y2; int sys_cnt, sys_cnt2; int temp_cnt; - int cx, cy; + int16_t cx, cy; int sx, sy; int dx, dy; uint32_t src, dest; uint32_t newsrc_blt, newdest_blt; uint32_t newdest_in, newdest_out; uint8_t *writemono, *nibbleset; - int x_count, y_count; + int x_count, xx_count, y_count; int input, output; uint16_t cur_x_bit12, cur_y_bit12; @@ -78,6 +79,7 @@ typedef struct ibm8514_t int odd_in, odd_out; uint16_t scratch; + int fill_state, fill_drop; } accel; uint16_t test; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index fbf0264da..af3d9968d 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -11,9 +11,11 @@ * * * - * Authors: TheCollector1995 + * Authors: Sarah Walker, + * Miran Grca, * - * Copyright 2022 TheCollector1995. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -64,7 +66,7 @@ static void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_da static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len); #define READ_PIXTRANS_WORD(cx, n) \ - if (cmd == 1) { \ + if (cmd <= 1) { \ temp = dev->vram[((dev->accel.cy * 1024) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((dev->accel.cy * 1024) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } else { \ @@ -169,7 +171,7 @@ ibm8514_accel_out_pixtrans(ibm8514_t *dev, uint16_t port, uint16_t val, int len) } else { if (dev->accel.cmd & 2) { if (pixcnt == 16) { - if ((cmd != 1) && (dev->accel.cmd & 0x1000)) + if ((cmd >= 2) && (dev->accel.cmd & 0x1000)) val = (val >> 8) | (val << 8); } if (and3 == 3) { @@ -249,8 +251,11 @@ regular_nibble: nibble |= 0x01; } - if ((and3 == 0) || (dev->accel.cmd & 0x1000)) { - monoxfer = nibble; + if ((and3 == 0) || (dev->accel.cmd & 0x1000) || (dev->accel.cmd & 8)) { + if (dev->accel.cmd & 8) { + monoxfer = val; + } else + monoxfer = nibble; ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, dev, len); if (dev->accel.nibbleset != NULL) { free(dev->accel.nibbleset); @@ -362,45 +367,40 @@ regular_nibble: static void ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) { - switch (port) { case 0x82e8: case 0xc2e8: if (len == 1) { - dev->accel.cur_y_bitres = (dev->accel.cur_y_bitres & 0xff00) | val; + dev->accel.cur_y_bit12 = (dev->accel.cur_y_bit12 & 0xf00) | val; dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; } else { - dev->accel.cur_y_bitres = val; + dev->accel.cur_y_bit12 = val & 0xfff; dev->accel.cur_y = val & 0x7ff; - dev->accel.cur_y_bit12 = (val & 0x1000) >> 8; } break; case 0x82e9: case 0xc2e9: if (len == 1) { - dev->accel.cur_y_bitres = (dev->accel.cur_y_bitres & 0xff) | (val << 8); + dev->accel.cur_y_bit12 = (dev->accel.cur_y_bit12 & 0xff) | ((val & 0x0f) << 8); dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - dev->accel.cur_y_bit12 = val & 0x10; } break; case 0x86e8: case 0xc6e8: if (len == 1) { - dev->accel.cur_x_bitres = (dev->accel.cur_x_bitres & 0xff00) | val; + dev->accel.cur_x_bit12 = (dev->accel.cur_x_bit12 & 0xf00) | val; dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; } else { - dev->accel.cur_x_bitres = val; + dev->accel.cur_x_bit12 = val & 0xfff; dev->accel.cur_x = val & 0x7ff; - dev->accel.cur_x_bit12 = (val & 0x1000) >> 8; } break; case 0x86e9: case 0xc6e9: if (len == 1) { - dev->accel.cur_x_bitres = (dev->accel.cur_x_bitres & 0xff) | (val << 8); + dev->accel.cur_x_bit12 = (dev->accel.cur_x_bit12 & 0xff) | ((val & 0x0f) << 8); dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); - dev->accel.cur_x_bit12 = val & 0x10; } break; @@ -451,7 +451,7 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) else { dev->accel.err_term = val & 0x3fff; if (val & 0x2000) - dev->accel.err_term |= ~0x1fff; + dev->accel.err_term |= ~0x3fff; } break; case 0x92e9: @@ -459,7 +459,7 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) if (len == 1) { dev->accel.err_term = (dev->accel.err_term & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - dev->accel.err_term |= ~0x1fff; + dev->accel.err_term |= ~0x3fff; } break; @@ -655,6 +655,12 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) else { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if ((dev->accel.multifunc_cntl >> 12) == 1) { + dev->accel.clip_top = val & 0x3ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 2) { + dev->accel.clip_left = val & 0x3ff; + } if (port == 0xfee8) dev->accel.cmd_back = 1; else @@ -925,6 +931,7 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x1ee8: dev->vsyncwidth = val; + //pclog("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); svga_recalctimings(svga); break; @@ -1005,9 +1012,9 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) break; case 0x42e8: - if (len != 1) + if (len != 1) { temp = dev->subsys_stat | 0xa0 | 0x8000; - else + } else temp = dev->subsys_stat | 0xa0; break; @@ -1115,8 +1122,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat { uint8_t src_dat = 0, dest_dat, old_dest_dat; int frgd_mix, bkgd_mix; - int16_t clip_t = dev->accel.multifunc[1] & 0x3ff; - int16_t clip_l = dev->accel.multifunc[2] & 0x3ff; uint16_t clip_b = dev->accel.multifunc[3] & 0x7ff; uint16_t clip_r = dev->accel.multifunc[4] & 0x7ff; int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; @@ -1126,9 +1131,12 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat int cmd = dev->accel.cmd >> 13; uint8_t wrt_mask = dev->accel.wrt_mask & 0xff; uint8_t rd_mask = ((dev->accel.rd_mask & 0x01) << 7) | ((dev->accel.rd_mask & 0xfe) >> 1); + uint8_t rd_mask_polygon = dev->accel.rd_mask & 0xff; uint8_t frgd_color = dev->accel.frgd_color; uint8_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; + int and3 = dev->accel.cur_x & 3; + uint8_t poly_src = 0; if (dev->accel.cmd & 0x100) { dev->force_busy = 1; @@ -1155,7 +1163,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (pixcntl == 1) { mix_dat = 0; - if ((dev->accel.cur_x & 3) == 3) { + if (and3 == 3) { if (dev->accel.multifunc[8] & 0x02) mix_dat |= 0x10; if (dev->accel.multifunc[8] & 0x04) @@ -1173,7 +1181,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x20; } - if ((dev->accel.cur_x & 3) == 2) { + if (and3 == 2) { if (dev->accel.multifunc[8] & 0x02) mix_dat |= 0x20; if (dev->accel.multifunc[8] & 0x04) @@ -1191,7 +1199,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x40; } - if ((dev->accel.cur_x & 3) == 1) { + if (and3 == 1) { if (dev->accel.multifunc[8] & 0x02) mix_dat |= 0x40; if (dev->accel.multifunc[8] & 0x04) @@ -1209,7 +1217,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x80; } - if ((dev->accel.cur_x & 3) == 0) { + if (and3 == 0) { if (dev->accel.multifunc[8] & 0x02) mix_dat |= 0x80; if (dev->accel.multifunc[8] & 0x04) @@ -1234,15 +1242,15 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ - switch (cmd) { + switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (dev->accel.ssv_state == 0) break; if (dev->accel.cmd & 8) { while (count-- && dev->accel.ssv_len >= 0) { - if (dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b) { + if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; case 1: src_dat = frgd_color; break; @@ -1293,16 +1301,18 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; case 1: /*Draw line*/ - case 5: /*Draw Polygon Boundary Line*/ if (!cpu_input) { dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - if (dev->accel.cur_y & 0x400) - dev->accel.cy |= ~0x3ff; - dev->accel.sy = dev->accel.maj_axis_pcnt; + if (dev->accel.cur_x & 0x400) { + dev->accel.cx |= ~0x3ff; + } + if (dev->accel.cur_y & 0x400) { + dev->accel.cy |= ~0x3ff; + } + + dev->accel.sy = dev->accel.maj_axis_pcnt; if (ibm8514_cpu_src(dev)) { dev->data_available = 0; @@ -1317,8 +1327,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cmd & 8) { /*Vector Line*/ while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -1351,8 +1361,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - - WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } } } @@ -1364,8 +1377,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - switch (dev->accel.cmd & 0xe0) - { + switch (dev->accel.cmd & 0xe0) { case 0x00: dev->accel.cx++; break; case 0x20: dev->accel.cx++; dev->accel.cy--; break; case 0x40: dev->accel.cy--; break; @@ -1377,9 +1389,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } dev->accel.sy--; - - if (cmd == 5) - break; } dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1391,8 +1400,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { if (ibm8514_cpu_dest(dev)) { READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); } else switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { @@ -1414,7 +1423,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_dest_dat = dest_dat; MIX(mix_dat & 1, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } } } @@ -1455,14 +1468,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } dev->accel.sy--; - - if (cmd == 5) - break; } } else { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if (((dev->accel.cx) >= dev->accel.clip_left && (dev->accel.cx) <= clip_r && + (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -1495,8 +1505,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - - WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } } } @@ -1537,9 +1550,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } dev->accel.sy--; - - if (cmd == 5) - break; } } dev->accel.cur_x = dev->accel.cx; @@ -1552,6 +1562,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat case 4: /*Rectangle fill (Y direction using nibbles)*/ if (!cpu_input) { dev->accel.x_count = 0; + dev->accel.xx_count = 0; dev->accel.odd_out = 0; dev->accel.odd_in = 0; dev->accel.input = 0; @@ -1564,11 +1575,13 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.cx = dev->accel.cur_x & 0x3ff; dev->accel.cy = dev->accel.cur_y & 0x3ff; + if (dev->accel.cur_x & 0x400) dev->accel.cx |= ~0x3ff; if (dev->accel.cur_y & 0x400) dev->accel.cy |= ~0x3ff; + dev->accel.fill_state = 0; dev->accel.dest = dev->accel.cy * 1024; if (cmd == 4) @@ -1579,11 +1592,69 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (ibm8514_cpu_src(dev)) { if (dev->accel.cmd & 2) { if (!(dev->accel.cmd & 0x1000)) { - dev->accel.sx += (dev->accel.cur_x & 3); - if (dev->accel.sx) { + if (!(dev->accel.cmd & 8)) { + dev->accel.sx += and3; dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; + } else { + if (and3 == 1) { + dev->accel.sx += 4; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx -= 4; + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx += 4; + break; + } + } else if (and3 == 2) { + dev->accel.sx += 5; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx -= 5; + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx += 5; + break; + } + } else if (and3 == 3) { + dev->accel.sx += 6; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx -= 6; + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx += 6; + break; + } + } else { + dev->accel.sx += 3; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx -= 3; + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx += 3; + break; + } + } } } } else { @@ -1613,10 +1684,170 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cmd & 2) { if (cpu_input) { rect_fill_pix: + if (dev->accel.cmd & 8) { + dev->accel.xx_count++; + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_dat; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ(dev->accel.dest + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ(dev->accel.dest + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (and3 == 1) { + if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 2) { + if (dev->accel.xx_count == 2) { + if (count <= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (and3 == 3) { + if (dev->accel.xx_count == 2) { + if (count <= 1) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 3) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else { + if (dev->accel.xx_count == 1) { + if (!count) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } else if (dev->accel.xx_count >= 2) { + if ((dev->accel.cmd & 4) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx++; + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx--; + break; + } + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + if (and3 == 1) { + dev->accel.sx += 4; + } else if (and3 == 2) { + dev->accel.sx += 5; + } else if (and3 == 3) { + dev->accel.sx += 6; + } else { + dev->accel.sx += 3; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + case 0x20: + case 0xe0: + dev->accel.cx -= (dev->accel.sx + 1); + break; + case 0x60: + case 0x80: + case 0xa0: + dev->accel.cx += (dev->accel.sx + 1); + break; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x20: + case 0x40: + case 0x60: + dev->accel.cy--; + break; + case 0xa0: + case 0xc0: + case 0xe0: + dev->accel.cy++; + break; + } + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + return; + } + } + break; + } if (count < 8) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -1687,8 +1918,8 @@ rect_fill_pix: } } else { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = 1; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -1777,8 +2008,8 @@ rect_fill_pix: } else { if (dev->accel.input && !dev->accel.output) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ if (!dev->accel.odd_in && !dev->accel.sx) { READ(dev->accel.newdest_in + dev->accel.cur_x, src_dat); @@ -1854,8 +2085,8 @@ rect_fill_pix: } } else if (dev->accel.output && !dev->accel.input) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { src_dat = cpu_dat; if (!dev->accel.odd_out && !dev->accel.sx) { READ(dev->accel.newdest_out + dev->accel.cur_x, dest_dat); @@ -1930,8 +2161,8 @@ rect_fill_pix: } } else { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { @@ -2016,8 +2247,8 @@ rect_fill: mix_dat >>= 8; dev->accel.temp_cnt = 8; } - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; case 1: src_dat = frgd_color; break; @@ -2082,8 +2313,8 @@ rect_fill: dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; case 1: src_dat = frgd_color; break; @@ -2142,60 +2373,135 @@ rect_fill: } } } else { - while (count-- && dev->accel.sy >= 0) { - if ((dev->accel.cx >= clip_l && dev->accel.cx <= clip_r && - dev->accel.cy >= clip_t && dev->accel.cy <= clip_b)) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: src_dat = bkgd_color; break; - case 1: src_dat = frgd_color; break; - case 2: src_dat = 0; break; - case 3: src_dat = 0; break; + if (dev->accel.multifunc[0x0a] & 4) { + while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: src_dat = 0; break; + } + + READ(dev->accel.dest + dev->accel.cx, poly_src); + if (dev->accel.multifunc[0x0a] & 2) { + poly_src = ((poly_src & wrt_mask) == wrt_mask); + } else { + poly_src = ((poly_src & rd_mask_polygon) == rd_mask_polygon); + } + + if (poly_src) + dev->accel.fill_state = !dev->accel.fill_state; + + if (dev->accel.fill_state) { + READ(dev->accel.dest + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } } - READ(dev->accel.dest + dev->accel.cx, dest_dat); + mix_dat <<= 1; + mix_dat |= 1; - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.fill_state = 0; + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } } } - mix_dat <<= 1; - mix_dat |= 1; + } else { + while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = 0; break; + case 3: src_dat = 0; break; + } - if (dev->accel.cmd & 0x20) - dev->accel.cx++; - else - dev->accel.cx--; + READ(dev->accel.dest + dev->accel.cx, dest_dat); - dev->accel.sx--; - if (dev->accel.sx < 0) { - dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } - if (dev->accel.cmd & 0x20) { - dev->accel.cx -= (dev->accel.sx) + 1; - } else - dev->accel.cx += (dev->accel.sx) + 1; + mix_dat <<= 1; + mix_dat |= 1; - if (dev->accel.cmd & 0x80) - dev->accel.cy++; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; else - dev->accel.cy--; + dev->accel.cx--; - dev->accel.dest = dev->accel.cy * 1024; - dev->accel.sy--; + dev->accel.sx--; + if (dev->accel.sx < 0) { + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.sy < 0) { - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; - return; + if (dev->accel.cmd & 0x20) { + dev->accel.cx -= (dev->accel.sx) + 1; + } else + dev->accel.cx += (dev->accel.sx) + 1; + + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + + dev->accel.dest = dev->accel.cy * 1024; + dev->accel.sy--; + + if (dev->accel.sy < 0) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + return; + } } } } @@ -2204,6 +2510,278 @@ rect_fill: } break; + case 5: /*Draw Polygon Boundary Line*/ + if (!cpu_input) { + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + + if (dev->accel.cur_x & 0x400) { + if (dev->accel.cx >= 1024) { + dev->accel.cx = 0; + } else + dev->accel.cx |= ~0x3ff; + } + + if (dev->accel.cur_y & 0x400) { + if (dev->accel.cy >= 1024) + dev->accel.cy = 1; + else + dev->accel.cy |= ~0x3ff; + } + + dev->accel.sy = dev->accel.maj_axis_pcnt; + + if (ibm8514_cpu_src(dev)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; /*Wait for data from CPU*/ + } else if (ibm8514_cpu_dest(dev)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + + if (dev->accel.cmd & 8) { /*Vector Line*/ + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * 1024) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cx++; break; + case 0x20: dev->accel.cx++; dev->accel.cy--; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cx--; dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx--; dev->accel.cy++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cx++; dev->accel.cy++; break; + } + + dev->accel.sy--; + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } else { /*Bresenham*/ + if (pixcntl == 1) { + dev->accel.temp_cnt = 8; + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat = old_mix_dat; + } + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + } else switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & 1, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + } + + dev->accel.temp_cnt--; + mix_dat >>= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cy--; break; + case 0x20: dev->accel.cy--; break; + case 0x40: dev->accel.cx--; break; + case 0x60: dev->accel.cx++; break; + case 0x80: dev->accel.cy++; break; + case 0xa0: dev->accel.cy++; break; + case 0xc0: dev->accel.cx--; break; + case 0xe0: dev->accel.cx++; break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cx--; break; + case 0x20: dev->accel.cx++; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cy++; break; + } + + dev->accel.sy--; + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.cur_x >= 1024) { + dev->accel.cx = 0; + } + if (dev->accel.cur_y >= 1024) { + dev->accel.cy = 1; + } + + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && + dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + /* Mix data = current video memory value. */ + READ((dev->accel.cy * 1024) + dev->accel.cx, mix_dat); + mix_dat = ((mix_dat & rd_mask) == rd_mask); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (ibm8514_cpu_dest(dev)) { + READ((dev->accel.cy * 1024) + dev->accel.cx, src_dat); + if (pixcntl == 3) + src_dat = ((src_dat & rd_mask) == rd_mask); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } + + READ((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((dev->accel.cmd & 4) && dev->accel.sy) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * 1024) + dev->accel.cx, dest_dat); + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; + + if (dev->accel.sy == 0) { + break; + } + + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cy--; break; + case 0x20: dev->accel.cy--; break; + case 0x40: dev->accel.cx--; break; + case 0x60: dev->accel.cx++; break; + case 0x80: dev->accel.cy++; break; + case 0xa0: dev->accel.cy++; break; + case 0xc0: dev->accel.cx--; break; + case 0xe0: dev->accel.cx++; break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: dev->accel.cx--; break; + case 0x20: dev->accel.cx++; break; + case 0x40: dev->accel.cy--; break; + case 0x60: dev->accel.cy--; break; + case 0x80: dev->accel.cx--; break; + case 0xa0: dev->accel.cx++; break; + case 0xc0: dev->accel.cy++; break; + case 0xe0: dev->accel.cy++; break; + } + + dev->accel.sy--; + } + } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } + break; + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { @@ -2236,11 +2814,9 @@ rect_fill: if (dev->accel.cmd & 2) { if (!(dev->accel.cmd & 0x1000)) { dev->accel.sx += (dev->accel.cur_x & 3); - if (dev->accel.sx) { - dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); - dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); - dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; - } + dev->accel.nibbleset = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.writemono = (uint8_t *)calloc(1, (dev->accel.sx >> 3) + 1); + dev->accel.sys_cnt = (dev->accel.sx >> 3) + 1; } } dev->data_available = 0; @@ -2258,8 +2834,8 @@ rect_fill: bitblt_pix: if (count < 8) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2334,8 +2910,8 @@ bitblt_pix: } } else { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2438,8 +3014,8 @@ bitblt_pix: goto bitblt_pix; } else { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2530,8 +3106,8 @@ bitblt: mix_dat >>= 8; dev->accel.temp_cnt = 8; } - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; case 1: src_dat = frgd_color; break; @@ -2604,8 +3180,8 @@ bitblt: dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; case 1: src_dat = frgd_color; break; @@ -2674,8 +3250,8 @@ bitblt: } } else { while (count-- && dev->accel.sy >= 0) { - if ((dev->accel.dx >= clip_l && dev->accel.dx <= clip_r && - dev->accel.dy >= clip_t && dev->accel.dy <= clip_b)) { + if ((dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && + dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2772,16 +3348,16 @@ ibm8514_render_8bpp(svga_t *svga) uint32_t *p; uint32_t dat; - if ((svga->displine + svga->y_add) < 0) { + if ((dev->displine + svga->y_add) < 0) { return; } if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; for (x = 0; x <= dev->h_disp; x += 8) { dat = *(uint32_t *)(&dev->vram[dev->ma & dev->vram_mask]); @@ -2808,14 +3384,14 @@ ibm8514_render_overscan_left(ibm8514_t *dev, svga_t *svga) { int i; - if ((svga->displine + svga->y_add) < 0) + if ((dev->displine + svga->y_add) < 0) return; if (svga->scrblank || (dev->h_disp == 0)) return; for (i = 0; i < svga->x_add; i++) - buffer32->line[svga->displine + svga->y_add][i] = svga->overscan_color; + buffer32->line[dev->displine + svga->y_add][i] = svga->overscan_color; } @@ -2824,7 +3400,7 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) { int i, right; - if ((svga->displine + svga->y_add) < 0) + if ((dev->displine + svga->y_add) < 0) return; if (svga->scrblank || (dev->h_disp == 0)) @@ -2832,7 +3408,7 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) right = (overscan_x >> 1); for (i = 0; i < right; i++) - buffer32->line[svga->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; + buffer32->line[dev->displine + svga->y_add][svga->x_add + dev->h_disp + i] = svga->overscan_color; } static void @@ -2897,7 +3473,6 @@ ibm8514_doblit(int wx, int wy, ibm8514_t *dev, svga_t *svga) p[j] = svga->overscan_color; } } - video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); } @@ -2906,7 +3481,6 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) { uint32_t x; int wx, wy; - int old_ma, blink_delay; if (!dev->linepos) { timer_advance_u64(&svga->timer, svga->dispofftime); @@ -2917,37 +3491,34 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) dev->ma &= dev->vram_mask; - if (svga->firstline == 2000) { - svga->firstline = svga->displine; + if (dev->firstline == 2000) { + dev->firstline = dev->displine; video_wait_for_buffer(); } - svga->render(svga); + ibm8514_render_8bpp(svga); svga->x_add = (overscan_x >> 1); ibm8514_render_overscan_left(dev, svga); ibm8514_render_overscan_right(dev, svga); svga->x_add = (overscan_x >> 1); - if (svga->lastline < svga->displine) - svga->lastline = svga->displine; + if (dev->lastline < dev->displine) + dev->lastline = dev->displine; } - svga->displine++; + dev->displine++; if (dev->interlace) - svga->displine++; - if (svga->displine > 1500) - svga->displine = 0; + dev->displine++; + if (dev->displine > 1500) + dev->displine = 0; } else { timer_advance_u64(&svga->timer, svga->dispontime); dev->hdisp_on = 0; dev->linepos = 0; if (dev->dispon) { - if (svga->linedbl && !dev->linecountff) { - dev->linecountff = 1; - dev->ma = dev->maback; - } else if (dev->sc == dev->rowcount) { + if (dev->sc == dev->rowcount) { dev->linecountff = 0; dev->sc = 0; @@ -2967,16 +3538,6 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) dev->vc++; dev->vc &= 2047; - if (dev->vc == dev->split) { - if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1) + 0; - else - dev->ma = dev->maback = 0; - dev->ma = (dev->ma << 2); - dev->maback = (dev->maback << 2); - - dev->sc = 0; - } if (dev->vc == dev->dispend) { dev->dispon = 0; @@ -2993,20 +3554,20 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) x = dev->h_disp; if (dev->interlace && !dev->oddeven) - svga->lastline++; + dev->lastline++; if (dev->interlace && dev->oddeven) - svga->firstline--; + dev->firstline--; wx = x; - wy = svga->lastline - svga->firstline; + wy = dev->lastline - dev->firstline; ibm8514_doblit(wx, wy, dev, svga); - svga->firstline = 2000; - svga->lastline = 0; + dev->firstline = 2000; + dev->lastline = 0; - svga->firstline_draw = 2000; - svga->lastline_draw = 0; + dev->firstline_draw = 2000; + dev->lastline_draw = 0; dev->oddeven ^= 1; @@ -3024,7 +3585,7 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) dev->vc = 0; dev->sc = 0; dev->dispon = 1; - svga->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; svga->x_add = (overscan_x >> 1); @@ -3045,15 +3606,21 @@ ibm8514_recalctimings(svga_t *svga) dev->v_syncstart = (dev->vsyncstart + 1); dev->rowcount = !!(dev->disp_cntl & 0x08); + if (((dev->disp_cntl & 0x60) == 0) || ((dev->disp_cntl == 0x60) >= 0x40)) + return; + if (dev->accel.advfunc_cntl & 4) { - if (dev->h_disp == 8) - dev->h_disp = 1024; - if (dev->rowoffset == 1) + if (dev->hdisp == 0) { dev->rowoffset = 128; - if (dev->v_total == 1) + dev->h_disp = 1024; + } + + if (dev->vtotal == 0) dev->v_total = 1632; - if (dev->v_syncstart == 1) - dev->vsyncstart = 1536; + + if (dev->vsyncstart == 0) + dev->v_syncstart = 1536; + if (dev->interlace) { dev->dispend = 384; /*Interlaced*/ dev->v_total >>= 2; @@ -3072,9 +3639,7 @@ ibm8514_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; svga->clock = (cpuclock * (double)(1ull << 32)) / 25175000.0; } - dev->split = 0xffffff; - svga->render = ibm8514_render_8bpp; - //pclog("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vblankstart=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vblankstart, dev->vsyncstart, dev->split); + //pclog("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); } static uint8_t From 1ac46d792f21d41f7d4342fa6563be662b25e849 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 19 May 2022 20:07:06 +0200 Subject: [PATCH 09/13] Fixed the 8514/A to VGA soft reset and made the vga_on variable a global one to make sure it's used by the soft reset. Updated copyright holder that was accidentally reverted while committing the IBM 8514/A source files. --- src/cpu/x86.c | 5 +++++ src/include/86box/vid_svga.h | 3 +-- src/video/vid_8514a.c | 4 ++-- src/video/vid_svga.c | 8 ++++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 60bc33b9b..77dd3b139 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -36,6 +36,8 @@ #include <86box/pci.h> #include <86box/ppi.h> #include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> /* The opcode of the instruction currently being executed. */ uint8_t opcode; @@ -341,6 +343,9 @@ softresetx86(void) if (soft_reset_mask) return; + if (ibm8514_enabled) + vga_on = 1; + reset_common(0); } diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 9881725ff..30d66f436 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -165,8 +165,6 @@ typedef struct svga_t int force_old_addr; - int vga_on; - int remap_required; uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); @@ -174,6 +172,7 @@ typedef struct svga_t } svga_t; extern svga_t *svga_8514; +extern int vga_on; extern void ibm8514_poll(ibm8514_t *dev, svga_t *svga); extern void ibm8514_recalctimings(svga_t *svga); diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index af3d9968d..af18727c5 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -958,8 +958,8 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x4ae8: dev->accel.advfunc_cntl = val & 7; - svga->vga_on = ((dev->accel.advfunc_cntl & 1) == 0) ? 1 : 0; - //pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", svga->vga_on, val); + vga_on = ((dev->accel.advfunc_cntl & 1) == 0) ? 1 : 0; + //pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); svga_recalctimings(svga); break; } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 4cc66899c..dde271df9 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -53,7 +53,7 @@ uint8_t svga_rotate[8][256]; /*Primary SVGA device. As multiple video cards are not yet supported this is the only SVGA device.*/ static svga_t *svga_pri; - +int vga_on; svga_t *svga_get_pri() @@ -554,7 +554,7 @@ svga_recalctimings(svga_t *svga) } else overscan_x = 16; - if (svga->vga_on) { + if (vga_on) { if (svga->recalctimings_ex) { svga->recalctimings_ex(svga); } @@ -657,7 +657,7 @@ svga_poll(void *p) int wx, wy; int ret, old_ma; - if (!svga->vga_on) { + if (!vga_on) { ibm8514_poll(&svga->dev8514, svga); return; } @@ -968,7 +968,7 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->translate_address = NULL; svga->ksc5601_english_font_type = 0; - svga->vga_on = 1; + vga_on = 1; if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, From fb2658bfecd3ab8b08e454f6b17a00a003439dbe Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 May 2022 01:35:32 +0200 Subject: [PATCH 10/13] Fixed the Samsung SPC-6000A. --- src/include/86box/keyboard.h | 1 + src/machine/m_at_386dx_486.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index b87f2552a..ff588c3b4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -73,6 +73,7 @@ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; +extern const device_t keyboard_at_samsung_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_at_olivetti_device; extern const device_t keyboard_at_ncr_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 6fe53e5e2..5944132e5 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -236,7 +236,7 @@ machine_at_spc6000a_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - device_add(&keyboard_at_ami_device); + device_add(&keyboard_at_samsung_device); return ret; } From 1e29e24b661ac34cd56ad8bc459cec64b2b1136f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Fri, 20 May 2022 19:04:53 +0200 Subject: [PATCH 11/13] [8514a] fix typo --- src/video/vid_8514a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index af18727c5..cfed45bfd 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -3606,7 +3606,7 @@ ibm8514_recalctimings(svga_t *svga) dev->v_syncstart = (dev->vsyncstart + 1); dev->rowcount = !!(dev->disp_cntl & 0x08); - if (((dev->disp_cntl & 0x60) == 0) || ((dev->disp_cntl == 0x60) >= 0x40)) + if (((dev->disp_cntl & 0x60) == 0) || ((dev->disp_cntl & 0x60) >= 0x40)) return; if (dev->accel.advfunc_cntl & 4) { From a3db023f19815d07ce89321cb45d6ccbdc6afe1c Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Sat, 21 May 2022 11:23:14 +0200 Subject: [PATCH 12/13] Fix building on macOS without Qt --- src/unix/unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/unix.c b/src/unix/unix.c index a7ef1abe7..3ab5d46e6 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -806,7 +806,7 @@ plat_init_rom_paths() #else char default_rom_path[1024] = { '\0 '}; getDefaultROMPath(default_rom_path); - rom_path_add(default_rom_path); + rom_add_path(default_rom_path); #endif } From 825141621f63470259a729345201ce7b7b7f39fe Mon Sep 17 00:00:00 2001 From: richardg867 Date: Sun, 22 May 2022 22:39:27 -0300 Subject: [PATCH 13/13] Improve App Translocation error message (moving also works) --- src/86box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index 7dce1d111..34cd3891c 100644 --- a/src/86box.c +++ b/src/86box.c @@ -428,7 +428,7 @@ pc_init(int argc, char *argv[]) *p = '\0'; } if (!strncmp(exe_path, "/private/var/folders/", 21)) { - ui_msgbox_header(MBX_FATAL, L"App Translocation", EMU_NAME_W L" cannot determine the emulated machine's location due to a macOS security feature. Please make a copy of the " EMU_NAME_W L" app and open that copy instead."); + ui_msgbox_header(MBX_FATAL, L"App Translocation", EMU_NAME_W L" cannot determine the emulated machine's location due to a macOS security feature. Please move the " EMU_NAME_W L" app to another folder (not /Applications), or make a copy of it and open that copy instead."); return(0); } #elif !defined(_WIN32)