From 0d8071ff77dc75e2fec28c3989f47ed382697905 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 21 Jul 2023 01:27:19 +0600 Subject: [PATCH 01/52] C&T 69000 (broken) --- src/include/86box/video.h | 3 + src/machine/m_at_socket370.c | 4 + src/machine/machine_table.c | 2 +- src/video/CMakeLists.txt | 3 +- src/video/vid_c&t_69000.c | 1353 ++++++++++++++++++++++++++++++++++ src/video/vid_table.c | 1 + 6 files changed, 1364 insertions(+), 2 deletions(-) create mode 100644 src/video/vid_c&t_69000.c diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 418423ea9..4c94fabfd 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -537,6 +537,9 @@ extern const device_t velocity_200_agp_device; /* Wyse 700 */ extern const device_t wy700_device; +/* Chips & Technologies */ +extern const device_t chips_69000_device; + #endif #endif /*EMU_VIDEO_H*/ diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index b8cc437a1..5e60885f3 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -312,6 +312,10 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); + if (gfxcard[0] == VID_INTERNAL) { + extern const device_t chips_69000_onboard_device; + device_add(&chips_69000_onboard_device); + } spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e73b74736..ea5d06a70 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -12478,7 +12478,7 @@ const machine_t machines[] = { .max_multi = 8.0 /* limits assumed */ }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO, .ram = { .min = 8192, .max = 524288, diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index b37e81134..70ef72b7a 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -25,7 +25,8 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c - vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c) + vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c + vid_c&t_69000.c) if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c new file mode 100644 index 000000000..fe22985e0 --- /dev/null +++ b/src/video/vid_c&t_69000.c @@ -0,0 +1,1353 @@ +/* + * 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. + * + * C&T 69000 emulation. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/pci.h> +#include <86box/thread.h> +#include + +typedef struct chips_69000_t { + svga_t svga; + uint8_t pci_conf_status; + uint8_t pci_line_interrupt; + uint8_t pci_rom_enable; + uint8_t read_write_bank; + atomic_bool engine_active; + atomic_bool quit; + thread_t *accel_thread; + event_t *fifo_event, *fifo_data_event; + pc_timer_t decrement_timer; + uint16_t rom_addr; + mem_mapping_t linear_mapping; + uint8_t on_board; + + rgb_t cursor_palette[8]; + uint32_t cursor_pallook[8]; + + uint8_t mm_regs[256], mm_index; + uint8_t flat_panel_regs[256], flat_panel_index; + uint8_t ext_regs[256], ext_index; + + union { + uint32_t mem_regs[4]; + uint16_t mem_regs_w[4 * 2]; + uint8_t mem_regs_b[4 * 4]; + }; + union { + uint32_t bitblt_regs[16]; + uint16_t bitblt_regs_w[16 * 2]; + uint8_t bitblt_regs_b[16 * 4]; + }; + + union { + uint16_t subsys_vid; + uint8_t subsys_vid_b[2]; + }; + + union { + uint16_t subsys_pid; + uint8_t subsys_pid_b[2]; + }; + + rom_t bios_rom; +} chips_69000_t; + +static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; + +void +chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_15bpp(uint16_t *dst, uint16_t src, uint8_t rop) +{ + uint16_t orig_dst = *dst & 0x8000; + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = ~0; + break; + } + *dst &= 0x7FFF; + *dst |= orig_dst; +} + +void +chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) +{ + uint32_t orig_dst = *dst & 0xFF000000; + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } + *dst &= 0xFFFFFF; + *dst |= orig_dst; +} + +void +chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~src; + break; + case 0x0A: + *dst &= ~src; + break; + case 0x0F: + *dst = ~src; + break; + case 0x50: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= src; + break; + case 0x5F: + *dst = ~src | ~(*dst); + break; + case 0xB8: + *dst = (((src ^ *dst) & nonpattern_src) ^ src); + break; + case 0xA0: + *dst &= src; + break; + case 0xA5: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xAF: + *dst |= ~src; + break; + case 0xF0: + *dst = src; + break; + case 0xF5: + *dst = src | ~(*dst); + break; + case 0xFA: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_15bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) +{ + uint16_t orig_dst = *dst & 0x8000; + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~src; + break; + case 0x0A: + *dst &= ~src; + break; + case 0x0F: + *dst = ~src; + break; + case 0x50: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= src; + break; + case 0x5F: + *dst = ~src | ~(*dst); + break; + case 0xB8: + *dst = (((src ^ *dst) & nonpattern_src) ^ src); + break; + case 0xA0: + *dst &= src; + break; + case 0xA5: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xAF: + *dst |= ~src; + break; + case 0xF0: + *dst = src; + break; + case 0xF5: + *dst = src | ~(*dst); + break; + case 0xFA: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } + *dst &= 0x7FFF; + *dst |= orig_dst; +} + +void +chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~src; + break; + case 0x0A: + *dst &= ~src; + break; + case 0x0F: + *dst = ~src; + break; + case 0x50: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= src; + break; + case 0x5F: + *dst = ~src | ~(*dst); + break; + case 0xB8: + *dst = (((src ^ *dst) & nonpattern_src) ^ src); + break; + case 0xA0: + *dst &= src; + break; + case 0xA5: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xAF: + *dst |= ~src; + break; + case 0xF0: + *dst = src; + break; + case 0xF5: + *dst = src | ~(*dst); + break; + case 0xFA: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpattern_src, uint8_t rop) +{ + uint32_t orig_dst = *dst & 0xFF000000; + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~src; + break; + case 0x0A: + *dst &= ~src; + break; + case 0x0F: + *dst = ~src; + break; + case 0x50: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= src; + break; + case 0x5F: + *dst = ~src | ~(*dst); + break; + case 0xB8: + *dst = (((src ^ *dst) & nonpattern_src) ^ src); + break; + case 0xA0: + *dst &= src; + break; + case 0xA5: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xAF: + *dst |= ~src; + break; + case 0xF0: + *dst = src; + break; + case 0xF5: + *dst = src | ~(*dst); + break; + case 0xFA: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } + *dst &= 0xFFFFFF; + *dst |= orig_dst; +} + +void +chips_69000_recalctimings(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (chips->ext_regs[0x81] & 0x10) { + svga->htotal -= 5; + } + + if (chips->ext_regs[0x09] & 0x1) { + svga->vtotal -= 2; + svga->vtotal &= 0xFF; + svga->vtotal |= (svga->crtc[0x30] & 0xF) << 8; + svga->vtotal += 2; + + svga->dispend--; + svga->dispend &= 0xFF; + svga->dispend |= (svga->crtc[0x31] & 0xF) << 8; + svga->dispend++; + + svga->vsyncstart--; + svga->vsyncstart &= 0xFF; + svga->vsyncstart |= (svga->crtc[0x32] & 0xF) << 8; + svga->vsyncstart++; + + svga->vblankstart--; + svga->vblankstart &= 0xFF; + svga->vblankstart |= (svga->crtc[0x33] & 0xF) << 8; + svga->vblankstart++; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal -= 5; + + svga->htotal |= (svga->crtc[0x38] & 0x1) << 8; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal += 5; + + /* Let's care about horizontal blanking end later when it matters. */ + + svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; + svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 16; + } + + svga->interlace = !!(svga->crtc[0x70] & 0x80); + + switch (chips->ext_regs[0x81] & 0xF) { + case 0b0010: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + svga->rowoffset <<= 2; + break; + + case 0b0100: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + svga->rowoffset <<= 2; + break; + case 0b0101: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + svga->rowoffset <<= 2; + break; + case 0b0110: + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + svga->rowoffset <<= 2; + break; + case 0b0111: + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + svga->rowoffset <<= 2; + break; + } +} + +void +chips_69000_decrement_timer(void* p) +{ + chips_69000_t *chips = (chips_69000_t*)p; + + chips->ext_regs[0xD2]--; + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); +} + +void +chips_69000_recalc_banking(chips_69000_t *chips) +{ + svga_t* svga = &chips->svga; + chips->svga.read_bank = chips->svga.write_bank = 0; + + svga->chain2_write = !(svga->seqregs[0x4] & 4); + svga->chain4 = (svga->seqregs[0x4] & 8) || (chips->ext_regs[0xA] & 0x4); + svga->packed_chain4 = !!(chips->ext_regs[0xA] & 0x4); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); + + if (chips->ext_regs[0xA] & 1) { + chips->svga.read_bank = chips->svga.write_bank = 0x10000 * (chips->ext_regs[0xE] & 0x7f); + } + + /*if (chips->ext_regs[0x40] & 2) { + svga->decode_mask = (1 << 18) - 1; + } else { + svga->decode_mask = (1 << 21) - 1; + }*/ +} + +uint8_t +chips_69000_read_ext_reg(chips_69000_t* chips) +{ + uint8_t index = chips->ext_index; + switch (index) { + case 0x00: + return 0x2C; + case 0x01: + return 0x10; + case 0x02: + return 0xC0; + case 0x03: + return 0x00; + case 0x04: + return 0x62; + case 0x05: + case 0x06: + return 0x00; + case 0x08: + return 0x02; + case 0x0A: + return chips->ext_regs[index] & 0x37; + case 0x63: + return 0xFF; + case 0x70: + return 0x3; + case 0x71: + return 0x0; + } + return chips->ext_regs[index]; +} + +void +chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) +{ + switch (chips->ext_index) { + case 0xA: + chips->ext_regs[chips->ext_index] = val & 0x37; + chips_69000_recalc_banking(chips); + break; + case 0xB: + chips->ext_regs[chips->ext_index] = val & 0xD; + break; + case 0xE: + chips->ext_regs[chips->ext_index] = val & 0x7f; + chips_69000_recalc_banking(chips); + break; + case 0x9: + chips->ext_regs[chips->ext_index] = val & 0x3; + svga_recalctimings(&chips->svga); + break; + case 0x40: + chips->ext_regs[chips->ext_index] = val & 0x3; + chips_69000_recalc_banking(chips); + break; + case 0x60: + chips->ext_regs[chips->ext_index] = val & 0x43; + break; + case 0x20: + chips->ext_regs[chips->ext_index] = val & 0x3f; + break; + case 0x61: + chips->ext_regs[chips->ext_index] = val & 0x7f; + break; + case 0x62: + chips->ext_regs[chips->ext_index] = val & 0x9C; + break; + case 0x67: + chips->ext_regs[chips->ext_index] = val & 0x2; + break; + case 0x80: + chips->ext_regs[chips->ext_index] = val & 0xBF; + chips->svga.ramdac_type = (val & 0x80) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + case 0x81: + chips->ext_regs[chips->ext_index] = val & 0x1f; + svga_recalctimings(&chips->svga); + break; + default: + chips->ext_regs[chips->ext_index] = val; + break; + } +} + +void +chips_69000_out(uint16_t addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t old, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + // if (!(addr == 0x3CC || addr == 0x3C9)) pclog("SiS SVGA out: 0x%X, 0x%X\n", addr, val); + switch (addr) { + case 0x3c0: + if (!(chips->ext_regs[0x09] & 0x02)) + break; + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + return; + case 0x3c1: + if ((chips->ext_regs[0x09] & 0x02)) + { + svga->attrff = 1; + svga_out(addr, val, svga); + svga->attrff = 0; + return; + } + break; + case 0x3c9: + if (!(chips->ext_regs[0x09] & 0x01)) + break; + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + val <<= 2; + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 2: + index = svga->dac_addr & 7; + chips->cursor_palette[index].r = svga->dac_r; + chips->cursor_palette[index].g = svga->dac_g; + chips->cursor_palette[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + chips->cursor_pallook[index] = makecol32(chips->cursor_palette[index].r, chips->cursor_palette[index].g, chips->cursor_palette[index].b); + else + chips->cursor_pallook[index] = makecol32(video_6to8[chips->cursor_palette[index].r & 0x3f], video_6to8[chips->cursor_palette[index].g & 0x3f], video_6to8[chips->cursor_palette[index].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + } + return; + case 0x3c5: + svga_out(addr, val, svga); + chips_69000_recalc_banking(chips); + return; + case 0x3D4: + svga->crtcreg = val & 0xff; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + if (old != val) { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { + svga->fullchange = 3; + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + case 0x3D6: + chips->ext_index = val; + return; + case 0x3D7: + return chips_69000_write_ext_reg(chips, val); + + } + svga_out(addr, val, svga); +} + +uint8_t +chips_69000_in(uint16_t addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t temp, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + // if (!(addr == 0x3CC || addr == 0x3C9)) pclog("SiS SVGA in: 0x%X\n", addr); + switch (addr) { + case 0x3C5: + return svga->seqregs[svga->seqaddr]; + case 0x3c9: + if (!(chips->ext_regs[0x09] & 0x01)) { + temp = svga_in(addr, svga); + break; + } + index = (svga->dac_addr - 1) & 7; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].r; + else + temp = chips->cursor_palette[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].g; + else + temp = chips->cursor_palette[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].b; + else + temp = chips->cursor_palette[index].b & 0x3f; + break; + } + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + temp >>= 2; + break; + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; + break; + case 0x3D6: + temp = chips->ext_index; + break; + case 0x3D7: + temp = chips_69000_read_ext_reg(chips); + break; + default: + temp = svga_in(addr, svga); + break; + } + return temp; +} + +static uint8_t +chips_69000_pci_read(int func, int addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x00: + case 0x01: + return (0x102C >> ((addr & 1) * 8)) & 0xFF; + case 0x02: + case 0x03: + return (0x00C0 >> ((addr & 1) * 8)) & 0xFF; + case 0x04: + return chips->pci_conf_status; + case 0x07: + return 0x02; + case 0x08: + case 0x09: + case 0x0a: + return 0x00; + case 0x0b: + return 0x03; + case 0x13: + return chips->linear_mapping.base >> 24; + case 0x30: + return chips->pci_rom_enable & 0x1; + case 0x31: + return 0x0; + case 0x32: + return chips->rom_addr & 0xFF; + case 0x33: + return (chips->rom_addr & 0xFF00) >> 8; + case 0x3c: + return chips->pci_line_interrupt; + case 0x3d: + return 0x01; + case 0x2C: + case 0x2D: + case 0x6C: + case 0x6D: + return (chips->subsys_vid >> ((addr & 1) * 8)) & 0xFF; + case 0x2E: + case 0x2F: + case 0x6E: + case 0x6F: + return (chips->subsys_pid >> ((addr & 1) * 8)) & 0xFF; + default: + return 0x00; + } + } +} + +static void +chips_69000_pci_write(int func, int addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x04: + { + chips->pci_conf_status = val; + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + mem_mapping_disable(&chips->bios_rom.mapping); + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (chips->pci_conf_status & PCI_COMMAND_IO) { + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + } + if (chips->pci_conf_status & PCI_COMMAND_MEM) { + if (!chips->on_board) mem_mapping_enable(&chips->bios_rom.mapping); + mem_mapping_enable(&chips->svga.mapping); + if (chips->linear_mapping.base) + mem_mapping_enable(&chips->linear_mapping); + } + break; + } + case 0x13: + { + mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24) - 1); + break; + } + case 0x3c: + chips->pci_line_interrupt = val; + break; + case 0x30: + if (chips->on_board) break; + chips->pci_rom_enable = val & 0x1; + mem_mapping_disable(&chips->bios_rom.mapping); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x40000); + } + break; + case 0x32: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF; + chips->rom_addr |= val & 0xFC; + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x40000); + } + break; + case 0x33: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF00; + chips->rom_addr |= (val << 8); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x40000); + } + break; + case 0x6C: + case 0x6D: + chips->subsys_vid_b[addr & 1] = val; + break; + case 0x6E: + case 0x6F: + chips->subsys_pid_b[addr & 1] = val; + break; + } + } +} + +uint8_t +chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + case 0x00 ... 0x28: + return chips->bitblt_regs_b[addr & 0xFF]; + case 0x600 ... 0x60F: + return chips->mem_regs_b[addr & 0xF]; + case 0x768: + return chips_69000_in(0x3b4, chips); + case 0x769: + return chips_69000_in(0x3b5, chips); + case 0x774: + return chips_69000_in(0x3ba, chips); + case 0x780: + return chips_69000_in(0x3c0, chips); + case 0x781: + return chips_69000_in(0x3c1, chips); + case 0x784: + return chips_69000_in(0x3c2, chips); + case 0x788: + return chips_69000_in(0x3c4, chips); + case 0x789: + return chips_69000_in(0x3c5, chips); + case 0x78C: + return chips_69000_in(0x3c6, chips); + case 0x78D: + return chips_69000_in(0x3c7, chips); + case 0x790: + return chips_69000_in(0x3c8, chips); + case 0x791: + return chips_69000_in(0x3c9, chips); + case 0x794: + return chips_69000_in(0x3ca, chips); + case 0x798: + return chips_69000_in(0x3cc, chips); + case 0x79C: + return chips_69000_in(0x3ce, chips); + case 0x79D: + return chips_69000_in(0x3cf, chips); + case 0x7A0: + return chips_69000_in(0x3d0, chips); + case 0x7A1: + return chips_69000_in(0x3d1, chips); + case 0x7A4: + return chips_69000_in(0x3d2, chips); + case 0x7A5: + return chips_69000_in(0x3d3, chips); + case 0x7A8: + return chips_69000_in(0x3d4, chips); + case 0x7A9: + return chips_69000_in(0x3d5, chips); + case 0x7AC: + return chips_69000_in(0x3d6, chips); + case 0x7AD: + return chips_69000_in(0x3d7, chips); + case 0x7B4: + return chips_69000_in(0x3da, chips); + } + return 0xFF; +} + +uint16_t +chips_69000_readw_mmio(uint32_t addr, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + default: + return chips_69000_readb_mmio(addr, chips) | (chips_69000_readb_mmio(addr + 1, chips) << 8); + } + return 0xFFFF; +} + +uint32_t +chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + default: + return chips_69000_readw_mmio(addr, chips) | (chips_69000_readw_mmio(addr + 2, chips) << 16); + } + return 0xFFFFFFFF; +} + +void +chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + case 0x00 ... 0x28: + chips->bitblt_regs_b[addr & 0xFF] = val; + break; + case 0x600 ... 0x60F: + chips->mem_regs_b[addr & 0xF] = val; + break; + case 0x768: + chips_69000_out(0x3b4, val, chips); break; + case 0x769: + chips_69000_out(0x3b5, val, chips); break; + case 0x774: + chips_69000_out(0x3ba, val, chips); break; + case 0x780: + chips_69000_out(0x3c0, val, chips); break; + case 0x781: + chips_69000_out(0x3c1, val, chips); break; + case 0x784: + chips_69000_out(0x3c2, val, chips); break; + case 0x788: + chips_69000_out(0x3c4, val, chips); break; + case 0x789: + chips_69000_out(0x3c5, val, chips); break; + case 0x78C: + chips_69000_out(0x3c6, val, chips); break; + case 0x78D: + chips_69000_out(0x3c7, val, chips); break; + case 0x790: + chips_69000_out(0x3c8, val, chips); break; + case 0x791: + chips_69000_out(0x3c9, val, chips); break; + case 0x794: + chips_69000_out(0x3ca, val, chips); break; + case 0x798: + chips_69000_out(0x3cc, val, chips); break; + case 0x79C: + chips_69000_out(0x3ce, val, chips); break; + case 0x79D: + chips_69000_out(0x3cf, val, chips); break; + case 0x7A0: + chips_69000_out(0x3d0, val, chips); break; + case 0x7A1: + chips_69000_out(0x3d1, val, chips); break; + case 0x7A4: + chips_69000_out(0x3d2, val, chips); break; + case 0x7A5: + chips_69000_out(0x3d3, val, chips); break; + case 0x7A8: + chips_69000_out(0x3d4, val, chips); break; + case 0x7A9: + chips_69000_out(0x3d5, val, chips); break; + case 0x7AC: + chips_69000_out(0x3d6, val, chips); break; + case 0x7AD: + chips_69000_out(0x3d7, val, chips); break; + case 0x7B4: + chips_69000_out(0x3da, val, chips); break; + } +} + +void +chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + default: + chips_69000_writeb_mmio(addr, val, chips); + chips_69000_writeb_mmio(addr + 1, val >> 8, chips); + break; + } +} + +void +chips_69000_writel_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) +{ + switch (addr & 0xFFF) { + default: + chips_69000_writew_mmio(addr, val, chips); + chips_69000_writew_mmio(addr + 2, val >> 16, chips); + break; + } +} + +uint8_t +chips_69000_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_readb_mmio(addr, chips); + + return svga_readb_linear(addr & 0x1FFFFF, p); +} + +uint16_t +chips_69000_readw_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_readw_mmio(addr, chips); + + return svga_readw_linear(addr & 0x1FFFFF, p); +} + +uint32_t +chips_69000_readl_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_readl_mmio(addr, chips); + + return svga_readl_linear(addr & 0x1FFFFF, p); +} + +void +chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_writeb_mmio(addr, val, chips); + + svga_writeb_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_writew_mmio(addr, val, chips); + + svga_writew_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->p; + + if (addr & 0x400000) + return chips_69000_writel_mmio(addr, val, chips); + + svga_writel_linear(addr & 0x1FFFFF, val, p); +} + +static void * +chips_69000_init(const device_t *info) +{ + chips_69000_t *chips = malloc(sizeof(chips_69000_t)); + memset(chips, 0, sizeof(chips_69000_t)); + + /* Appears to have an odd VBIOS size. */ + if (!info->local) { + rom_init(&chips->bios_rom, "roms/video/chips/69000.ROM", 0xc0000, 0x40000, 0x3ffff, 0x0000, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&chips->bios_rom.mapping); + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_sis); + + svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ + NULL, + chips_69000_in, chips_69000_out, + NULL, + NULL); + + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + + pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips); + + chips->svga.bpp = 8; + chips->svga.miscout = 1; + chips->svga.recalctimings_ex = chips_69000_recalctimings; + + mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); + + chips->quit = 0; + chips->engine_active = 0; + chips->on_board = !!(info->local); + + timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); + + return chips; +} + +static int +chips_69000_available(void) +{ + return rom_present("roms/video/chips/69000.ROM"); +} + +void +chips_69000_close(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->quit = 1; +// thread_set_event(chips->fifo_event); + // thread_wait(chips->accel_thread); + svga_close(&chips->svga); + + free(chips); +} + +void +chips_69000_speed_changed(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + svga_recalctimings(&chips->svga); +} + +void +chips_69000_force_redraw(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->svga.fullchange = changeframecount; +} + +const device_t chips_69000_device = { + .name = "Chips & Technologies 69000", + .internal_name = "c&t_69000", + .flags = DEVICE_PCI, + .local = 0, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; + +const device_t chips_69000_onboard_device = { + .name = "Chips & Technologies 69000 (onboard)", + .internal_name = "c&t_69000_onboard", + .flags = DEVICE_PCI, + .local = 1, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a2cead1ec..d4915a056 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -198,6 +198,7 @@ video_cards[] = { { &s3_virge_357_pci_device }, { &s3_diamond_stealth_4000_pci_device }, { &s3_trio3d2x_pci_device }, + { &chips_69000_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) { &millennium_device, VIDEO_FLAG_TYPE_SPECIAL }, { &mystique_device }, From 91da7aab511f4187650b6f24d64456488647a1ca Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 29 Jan 2024 15:53:26 +0600 Subject: [PATCH 02/52] Merge prep --- src/machine/m_at_socket370.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 5e60885f3..b8cc437a1 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -312,10 +312,6 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); - if (gfxcard[0] == VID_INTERNAL) { - extern const device_t chips_69000_onboard_device; - device_add(&chips_69000_onboard_device); - } spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; From 00a5017f5549284529fa8055058dc628e4b962bd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 29 Jan 2024 15:57:09 +0600 Subject: [PATCH 03/52] Re-add it again --- src/machine/m_at_socket370.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 2b2615422..4920f3d27 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -351,6 +351,10 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); + if (gfxcard[0] == VID_INTERNAL) { + extern const device_t chips_69000_onboard_device; + device_add(&chips_69000_onboard_device); + } spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; From c95a0ac599524f756eeaa95e62e82eb0db082084 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 29 Jan 2024 16:23:23 +0600 Subject: [PATCH 04/52] Update vid_c&t_69000.c --- src/video/vid_c&t_69000.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index fe22985e0..4856aff33 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -42,6 +42,7 @@ typedef struct chips_69000_t { uint8_t pci_line_interrupt; uint8_t pci_rom_enable; uint8_t read_write_bank; + uint8_t slot; atomic_bool engine_active; atomic_bool quit; thread_t *accel_thread; @@ -1193,7 +1194,7 @@ uint16_t chips_69000_readw_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readw_mmio(addr, chips); @@ -1205,7 +1206,7 @@ uint32_t chips_69000_readl_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readl_mmio(addr, chips); @@ -1217,7 +1218,7 @@ void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writeb_mmio(addr, val, chips); @@ -1229,7 +1230,7 @@ void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writew_mmio(addr, val, chips); @@ -1241,7 +1242,7 @@ void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writel_mmio(addr, val, chips); @@ -1271,7 +1272,7 @@ chips_69000_init(const device_t *info) io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); - pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips); + pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); chips->svga.bpp = 8; chips->svga.miscout = 1; From 8724f30320b1b09e32a3ab317126e0cf0ad73e9f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 29 Jan 2024 16:31:35 +0600 Subject: [PATCH 05/52] Update vid_c&t_69000.c --- src/video/vid_c&t_69000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 4856aff33..c994e8e54 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1182,7 +1182,7 @@ uint8_t chips_69000_readb_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readb_mmio(addr, chips); @@ -1268,7 +1268,7 @@ chips_69000_init(const device_t *info) NULL, chips_69000_in, chips_69000_out, NULL, - NULL); + chips_69000_recalctimings); io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); From f313e420d3887db891009cd3121668fd996d30b7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 29 Jan 2024 16:35:10 +0600 Subject: [PATCH 06/52] Ok fixed for real --- src/video/vid_c&t_69000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index c994e8e54..a06246538 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -544,7 +544,7 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpatte void chips_69000_recalctimings(svga_t *svga) { - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (chips->ext_regs[0x81] & 0x10) { svga->htotal -= 5; @@ -1265,10 +1265,10 @@ chips_69000_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_sis); svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ - NULL, + chips_69000_recalctimings, chips_69000_in, chips_69000_out, NULL, - chips_69000_recalctimings); + NULL); io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); From 0d427c813838db3a3e1d35aae420d30dd24a1356 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 30 Jan 2024 13:41:35 +0600 Subject: [PATCH 07/52] Fix video modes for real --- src/video/vid_c&t_69000.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index fe22985e0..6c9abd742 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -39,6 +39,7 @@ typedef struct chips_69000_t { svga_t svga; uint8_t pci_conf_status; + uint8_t slot; uint8_t pci_line_interrupt; uint8_t pci_rom_enable; uint8_t read_write_bank; @@ -543,7 +544,7 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpatte void chips_69000_recalctimings(svga_t *svga) { - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (chips->ext_regs[0x81] & 0x10) { svga->htotal -= 5; @@ -581,7 +582,7 @@ chips_69000_recalctimings(svga_t *svga) /* Let's care about horizontal blanking end later when it matters. */ svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; - svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 16; + svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; } svga->interlace = !!(svga->crtc[0x70] & 0x80); @@ -614,6 +615,11 @@ chips_69000_recalctimings(svga_t *svga) svga->rowoffset <<= 2; break; } + + if (chips->ext_regs[0x40] & 1) { + svga->force_dword_mode = chips->ext_regs[0x40] & 1; + svga->rowoffset >>= 2; + } } void @@ -701,6 +707,7 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0x40: chips->ext_regs[chips->ext_index] = val & 0x3; chips_69000_recalc_banking(chips); + svga_recalctimings(&chips->svga); break; case 0x60: chips->ext_regs[chips->ext_index] = val & 0x43; @@ -1181,7 +1188,7 @@ uint8_t chips_69000_readb_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readb_mmio(addr, chips); @@ -1193,7 +1200,7 @@ uint16_t chips_69000_readw_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readw_mmio(addr, chips); @@ -1205,7 +1212,7 @@ uint32_t chips_69000_readl_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_readl_mmio(addr, chips); @@ -1217,7 +1224,7 @@ void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writeb_mmio(addr, val, chips); @@ -1229,7 +1236,7 @@ void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writew_mmio(addr, val, chips); @@ -1241,7 +1248,7 @@ void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) { svga_t *svga = (svga_t *) p; - chips_69000_t *chips = (chips_69000_t *) svga->p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; if (addr & 0x400000) return chips_69000_writel_mmio(addr, val, chips); @@ -1271,7 +1278,7 @@ chips_69000_init(const device_t *info) io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); - pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips); + pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); chips->svga.bpp = 8; chips->svga.miscout = 1; From 82e95cf59cb43465d278d9aee5a72f0b4c11686f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 30 Jan 2024 16:56:08 +0600 Subject: [PATCH 08/52] More C&T 69000 fixes --- src/video/vid_c&t_69000.c | 70 +++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 92de759f9..5b1384b17 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -43,7 +43,6 @@ typedef struct chips_69000_t { uint8_t pci_line_interrupt; uint8_t pci_rom_enable; uint8_t read_write_bank; - uint8_t slot; atomic_bool engine_active; atomic_bool quit; thread_t *accel_thread; @@ -580,46 +579,45 @@ chips_69000_recalctimings(svga_t *svga) if (!(chips->ext_regs[0x81] & 0x10)) svga->htotal += 5; - /* Let's care about horizontal blanking end later when it matters. */ + svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000); + svga->hblank_end_len = 0x100; svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; - } - - svga->interlace = !!(svga->crtc[0x70] & 0x80); - switch (chips->ext_regs[0x81] & 0xF) { - case 0b0010: - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - svga->rowoffset <<= 2; - break; + svga->interlace = !!(svga->crtc[0x70] & 0x80); - case 0b0100: - svga->bpp = 15; - svga->render = svga_render_15bpp_highres; - svga->rowoffset <<= 2; - break; - case 0b0101: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - svga->rowoffset <<= 2; - break; - case 0b0110: - svga->bpp = 24; - svga->render = svga_render_24bpp_highres; - svga->rowoffset <<= 2; - break; - case 0b0111: - svga->bpp = 32; - svga->render = svga_render_32bpp_highres; - svga->rowoffset <<= 2; - break; - } + switch (chips->ext_regs[0x81] & 0xF) { + case 0b0010: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + break; - if (chips->ext_regs[0x40] & 1) { - svga->force_dword_mode = chips->ext_regs[0x40] & 1; - svga->rowoffset >>= 2; + case 0b0100: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + break; + case 0b0101: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + case 0b0110: + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + break; + case 0b0111: + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + break; + } + + if (chips->ext_regs[0x40] & 1) { + svga->force_dword_mode = chips->ext_regs[0x40] & 1; + } else { + svga->force_dword_mode = 0; + } + } else { + svga->force_dword_mode = 0; } } @@ -976,7 +974,7 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) } case 0x13: { - mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24) - 1); + mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24)); break; } case 0x3c: From 844e6e8579d8a213ccc71dfcf7fb6de566c87af7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 30 Jan 2024 21:18:55 +0600 Subject: [PATCH 09/52] Fix 8bpp modes --- src/video/vid_c&t_69000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 5b1384b17..aa42b61d6 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -725,7 +725,7 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) break; case 0x80: chips->ext_regs[chips->ext_index] = val & 0xBF; - chips->svga.ramdac_type = (val & 0x80) ? RAMDAC_8BIT : RAMDAC_6BIT; + svga_set_ramdac_type(&chips->svga, (val & 0x80) ? RAMDAC_8BIT : RAMDAC_6BIT); break; case 0x81: chips->ext_regs[chips->ext_index] = val & 0x1f; @@ -769,7 +769,7 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) } break; case 0x3c9: - if (!(chips->ext_regs[0x09] & 0x01)) + if (!(chips->ext_regs[0x80] & 0x01)) break; if (svga->adv_flags & FLAG_RAMDAC_SHIFT) val <<= 2; @@ -840,7 +840,7 @@ chips_69000_in(uint16_t addr, void *p) case 0x3C5: return svga->seqregs[svga->seqaddr]; case 0x3c9: - if (!(chips->ext_regs[0x09] & 0x01)) { + if (!(chips->ext_regs[0x80] & 0x01)) { temp = svga_in(addr, svga); break; } From 439c1152fb4d2fe0a2d4c487a2667d683c286096 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 30 Jan 2024 22:00:12 +0600 Subject: [PATCH 10/52] C&T_69000: All modes are working --- src/video/vid_c&t_69000.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index aa42b61d6..e351f51af 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -610,14 +610,6 @@ chips_69000_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } - - if (chips->ext_regs[0x40] & 1) { - svga->force_dword_mode = chips->ext_regs[0x40] & 1; - } else { - svga->force_dword_mode = 0; - } - } else { - svga->force_dword_mode = 0; } } @@ -638,7 +630,6 @@ chips_69000_recalc_banking(chips_69000_t *chips) svga->chain2_write = !(svga->seqregs[0x4] & 4); svga->chain4 = (svga->seqregs[0x4] & 8) || (chips->ext_regs[0xA] & 0x4); - svga->packed_chain4 = !!(chips->ext_regs[0xA] & 0x4); svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); if (chips->ext_regs[0xA] & 1) { @@ -1288,6 +1279,8 @@ chips_69000_init(const device_t *info) chips->quit = 0; chips->engine_active = 0; chips->on_board = !!(info->local); + + chips->svga.packed_chain4 = 1; timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); From 2ee97bf1e190d8a00bbacf9ae3e0969a249560cd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 30 Jan 2024 23:33:55 +0600 Subject: [PATCH 11/52] DDC work --- src/video/vid_c&t_69000.c | 44 ++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index e351f51af..5037cb1c2 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -10,11 +10,9 @@ * * * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Cacodemon345 * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2023-2024 Cacodemon345 */ #include #include @@ -34,6 +32,8 @@ #include <86box/vid_svga_render.h> #include <86box/pci.h> #include <86box/thread.h> +#include <86box/i2c.h> +#include <86box/vid_ddc.h> #include typedef struct chips_69000_t { @@ -81,6 +81,8 @@ typedef struct chips_69000_t { }; rom_t bios_rom; + + void* i2c_ddc, *ddc; } chips_69000_t; static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; @@ -666,7 +668,16 @@ chips_69000_read_ext_reg(chips_69000_t* chips) case 0x0A: return chips->ext_regs[index] & 0x37; case 0x63: - return 0xFF; + { + uint8_t val = chips->ext_regs[index]; + if (!(chips->ext_regs[0x62] & 0x8)) + val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c_ddc) << 3); + + if (!(chips->ext_regs[0x62] & 0x4)) + val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c_ddc) << 2); + + return val; + } case 0x70: return 0x3; case 0x71: @@ -711,6 +722,24 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0x62: chips->ext_regs[chips->ext_index] = val & 0x9C; break; + case 0x63: + { + uint8_t scl = 0, sda = 0; + if (chips->ext_regs[0x62] & 0x8) + scl = !!(val & 8); + else + scl = i2c_gpio_get_scl(chips->i2c_ddc); + + if (chips->ext_regs[0x62] & 0x4) + sda = !!(val & 4); + else + scl = i2c_gpio_get_sda(chips->i2c_ddc); + + i2c_gpio_set(chips->i2c_ddc, scl, sda); + + chips->ext_regs[chips->ext_index] = val & 0x9F; + break; + } case 0x67: chips->ext_regs[chips->ext_index] = val & 0x2; break; @@ -1285,6 +1314,9 @@ chips_69000_init(const device_t *info) timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); + chips->i2c_ddc = i2c_gpio_init("c&t_69000_mga"); + chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c_ddc)); + return chips; } @@ -1302,6 +1334,8 @@ chips_69000_close(void *p) chips->quit = 1; // thread_set_event(chips->fifo_event); // thread_wait(chips->accel_thread); + ddc_close(chips->ddc); + i2c_gpio_close(chips->i2c_ddc); svga_close(&chips->svga); free(chips); From f018ef27889c40e54153d9d8933dc5245acdf3d5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 31 Jan 2024 00:59:37 +0600 Subject: [PATCH 12/52] More changes --- src/video/vid_c&t_69000.c | 108 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 5037cb1c2..5e23c0710 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -83,10 +83,68 @@ typedef struct chips_69000_t { rom_t bios_rom; void* i2c_ddc, *ddc; + + uint8_t st01; } chips_69000_t; static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +/* Multimedia handling. */ +uint8_t +chips_69000_read_multimedia(chips_69000_t* chips) +{ + switch (chips->mm_index) { + case 0: + /* Report no playback/capture capability. */ + return 0; + default: + return chips->mm_regs[chips->mm_index]; + } + return chips->mm_regs[chips->mm_index]; +} + +/* Multimedia (write) handling. */ +void +chips_69000_write_multimedia(chips_69000_t* chips, uint8_t val) +{ + switch (chips->mm_index) { + case 0: + return; + default: + chips->mm_regs[chips->mm_index] = val; + break; + } + chips->mm_regs[chips->mm_index] = val; +} + +/* Flat panel handling. */ +uint8_t +chips_69000_read_flat_panel(chips_69000_t* chips) +{ + switch (chips->flat_panel_index) { + case 0: + /* Report no presence of flat panel module. */ + return 0; + default: + return chips->flat_panel_regs[chips->flat_panel_index]; + } + return chips->flat_panel_regs[chips->flat_panel_index]; +} + +/* Flat panel (write) handling. */ +void +chips_69000_write_flat_panel(chips_69000_t* chips, uint8_t val) +{ + switch (chips->flat_panel_index) { + case 0: + return; + default: + chips->flat_panel_regs[chips->flat_panel_index] = val; + break; + } + chips->flat_panel_regs[chips->flat_panel_index] = val; +} + void chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) { @@ -813,6 +871,18 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); chips_69000_recalc_banking(chips); return; +#if 1 + case 0x3D0: + chips->flat_panel_index = val; + return; + case 0x3D1: + return chips_69000_write_flat_panel(chips, val); + case 0x3D2: + chips->mm_index = val; + return; + case 0x3D3: + return chips_69000_write_multimedia(chips, val); +#endif case 0x3D4: svga->crtcreg = val & 0xff; return; @@ -850,7 +920,7 @@ chips_69000_in(uint16_t addr, void *p) { chips_69000_t *chips = (chips_69000_t *) p; svga_t *svga = &chips->svga; - uint8_t temp, index; + uint8_t temp = 0, index; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -892,6 +962,16 @@ chips_69000_in(uint16_t addr, void *p) if (svga->adv_flags & FLAG_RAMDAC_SHIFT) temp >>= 2; break; +#if 1 + case 0x3D0: + return chips->flat_panel_index; + case 0x3D1: + return chips_69000_read_flat_panel(chips); + case 0x3D2: + return chips->mm_index; + case 0x3D3: + return chips_69000_read_multimedia(chips); +#endif case 0x3D4: temp = svga->crtcreg; break; @@ -1124,6 +1204,8 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) switch (addr & 0xFFF) { case 0x00 ... 0x28: chips->bitblt_regs_b[addr & 0xFF] = val; + if ((addr & 0xFFF) == 0x023) + pclog("BitBLT/Draw operation\n"); break; case 0x600 ... 0x60F: chips->mem_regs_b[addr & 0xF] = val; @@ -1275,11 +1357,25 @@ chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) svga_writel_linear(addr & 0x1FFFFF, val, p); } +void +chips_69000_vsync_start(svga_t *svga) +{ + /* TODO: PCI interrupts for this. */ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + +} + +void +chips_69000_vblank_start(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + /* Needed? */ +} + static void * chips_69000_init(const device_t *info) { - chips_69000_t *chips = malloc(sizeof(chips_69000_t)); - memset(chips, 0, sizeof(chips_69000_t)); + chips_69000_t *chips = calloc(1, sizeof(chips_69000_t)); /* Appears to have an odd VBIOS size. */ if (!info->local) { @@ -1302,6 +1398,8 @@ chips_69000_init(const device_t *info) chips->svga.bpp = 8; chips->svga.miscout = 1; chips->svga.recalctimings_ex = chips_69000_recalctimings; + chips->svga.vsync_callback = chips_69000_vsync_start; + chips->svga.vblank_start = chips_69000_vblank_start; mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); @@ -1316,6 +1414,10 @@ chips_69000_init(const device_t *info) chips->i2c_ddc = i2c_gpio_init("c&t_69000_mga"); chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c_ddc)); + + chips->flat_panel_regs[0x01] = 1; + + sizeof(chips->bitblt_regs); return chips; } From 2b0a494eded5f493240c7cdccc00709dcabfc97f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 31 Jan 2024 13:24:51 +0600 Subject: [PATCH 13/52] Report linear mapping properly --- src/video/vid_c&t_69000.c | 57 ++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 5e23c0710..9ce7f89b5 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -707,46 +707,65 @@ uint8_t chips_69000_read_ext_reg(chips_69000_t* chips) { uint8_t index = chips->ext_index; + uint8_t val = chips->ext_regs[index]; switch (index) { case 0x00: - return 0x2C; + val = 0x2C; + break; case 0x01: - return 0x10; + val = 0x10; + break; case 0x02: - return 0xC0; + val = 0xC0; + break; case 0x03: - return 0x00; + val = 0x00; + break; case 0x04: - return 0x62; + val = 0x62; + break; case 0x05: + val = 0x00; + break; case 0x06: - return 0x00; + val = chips->linear_mapping.base >> 24; + break; case 0x08: - return 0x02; + val = 0x02; + break; case 0x0A: - return chips->ext_regs[index] & 0x37; + val = chips->ext_regs[index] & 0x37; + break; case 0x63: { - uint8_t val = chips->ext_regs[index]; + val = chips->ext_regs[index]; if (!(chips->ext_regs[0x62] & 0x8)) val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c_ddc) << 3); if (!(chips->ext_regs[0x62] & 0x4)) val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c_ddc) << 2); - return val; + break; } case 0x70: - return 0x3; + val = 0x3; + break; case 0x71: - return 0x0; + val = 0x0; + break; } - return chips->ext_regs[index]; + //if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + // pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); + return val; } void chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) { + //if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + //&& (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + // pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); switch (chips->ext_index) { case 0xA: chips->ext_regs[chips->ext_index] = val & 0x37; @@ -809,6 +828,8 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) chips->ext_regs[chips->ext_index] = val & 0x1f; svga_recalctimings(&chips->svga); break; + case 0xD2: + break; default: chips->ext_regs[chips->ext_index] = val; break; @@ -1002,11 +1023,13 @@ chips_69000_pci_read(int func, int addr, void *p) { switch (addr) { case 0x00: + return 0x2C; case 0x01: - return (0x102C >> ((addr & 1) * 8)) & 0xFF; + return 0x10; case 0x02: + return 0xC0; case 0x03: - return (0x00C0 >> ((addr & 1) * 8)) & 0xFF; + return 0x00; case 0x04: return chips->pci_conf_status; case 0x07: @@ -1074,6 +1097,10 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) } case 0x13: { + if (!(chips->pci_conf_status & PCI_COMMAND_MEM)) { + chips->linear_mapping.base = val << 24; + break; + } mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24)); break; } From a9b3fdd945dd6aa9be691bff9aa7ebfa815f2eb6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 31 Jan 2024 16:34:34 +0600 Subject: [PATCH 14/52] BitBLT work --- src/video/vid_c&t_69000.c | 274 +++++++++++++++++++------------------- 1 file changed, 138 insertions(+), 136 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 9ce7f89b5..cab0f0f21 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -36,10 +36,55 @@ #include <86box/vid_ddc.h> #include +#pragma pack(push, 1) +typedef struct chips_69000_bitblt_t +{ + /* BR00 - Source and Destination Span Register. */ + uint16_t source_span; + uint16_t destination_span; + + /* BR01 - Pattern/Source Expansion Background Color & Transparency Key Register. */ + uint32_t pattern_source_key_bg; + + /* BR02 - Pattern/Source Expansion Foreground Color Register. */ + uint32_t pattern_source_key_fg; + + /* BR03 - Monochrome Source Control Register. */ + uint8_t monochrome_source_left_clip; + uint8_t monochrome_source_right_clip; + uint8_t monochrome_source_initial_discard; + uint8_t monochrome_source_alignment : 3; + uint8_t monochrome_source_expansion_color_reg_select : 1; + uint8_t dummy_8 : 4; + + /* BR04 - BitBLT Control Register. */ + uint32_t bitblt_control; + + /* BR05 - Pattern Address Register. */ + uint32_t pat_addr; + + /* BR06 - Source Address Register. */ + uint32_t source_addr; + + /* BR07 - Destination Address Register. */ + uint32_t destination_addr; + + /* BR08 - Destination Width & Height Register. */ + uint16_t destination_width; + uint16_t destination_height; + + /* BR09 - Source Expansion Background Color & Transparency Key Register. */ + uint32_t source_key_bg; + + /* BR0A - Source Expansion Foreground Color Register. */ + uint32_t source_key_fg; +}; +#pragma pack(pop) + typedef struct chips_69000_t { svga_t svga; uint8_t pci_conf_status; - uint8_t slot; + uint8_t slot, irq_state; uint8_t pci_line_interrupt; uint8_t pci_rom_enable; uint8_t read_write_bank; @@ -65,11 +110,21 @@ typedef struct chips_69000_t { uint8_t mem_regs_b[4 * 4]; }; union { - uint32_t bitblt_regs[16]; - uint16_t bitblt_regs_w[16 * 2]; - uint8_t bitblt_regs_b[16 * 4]; + uint32_t bitblt_regs[11]; + uint16_t bitblt_regs_w[11 * 2]; + uint8_t bitblt_regs_b[11 * 4]; + struct chips_69000_bitblt_t bitblt; }; + struct + { + struct chips_69000_bitblt_t bitblt; + + uint32_t actual_source_height; + uint32_t actual_destination_height; + uint8_t bytes_per_pixel; + } bitblt_running; + union { uint16_t subsys_vid; uint8_t subsys_vid_b[2]; @@ -145,6 +200,20 @@ chips_69000_write_flat_panel(chips_69000_t* chips, uint8_t val) chips->flat_panel_regs[chips->flat_panel_index] = val; } +void +chips_69000_interrupt(chips_69000_t* chips) +{ + pci_irq(chips->slot, PCI_INTA, 0, !!((chips->mem_regs[0] & chips->mem_regs[1]) & 0x80004040), &chips->irq_state); +} + +void +chips_69000_bitblt_interrupt(chips_69000_t* chips) +{ + chips->mem_regs[1] |= 1 << 31; + + chips_69000_interrupt(chips); +} + void chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) { @@ -199,63 +268,6 @@ chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) } } -void -chips_69000_do_rop_15bpp(uint16_t *dst, uint16_t src, uint8_t rop) -{ - uint16_t orig_dst = *dst & 0x8000; - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = ~0; - break; - } - *dst &= 0x7FFF; - *dst |= orig_dst; -} - void chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) { @@ -424,66 +436,6 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ } } -void -chips_69000_do_rop_15bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) -{ - uint16_t orig_dst = *dst & 0x8000; - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~src; - break; - case 0x0A: - *dst &= ~src; - break; - case 0x0F: - *dst = ~src; - break; - case 0x50: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= src; - break; - case 0x5F: - *dst = ~src | ~(*dst); - break; - case 0xB8: - *dst = (((src ^ *dst) & nonpattern_src) ^ src); - break; - case 0xA0: - *dst &= src; - break; - case 0xA5: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xAF: - *dst |= ~src; - break; - case 0xF0: - *dst = src; - break; - case 0xF5: - *dst = src | ~(*dst); - break; - case 0xFA: - *dst |= src; - break; - case 0xFF: - *dst = 0xFF; - break; - } - *dst &= 0x7FFF; - *dst |= orig_dst; -} - void chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) { @@ -703,6 +655,24 @@ chips_69000_recalc_banking(chips_69000_t *chips) }*/ } +void +chips_69000_setup_bitblt(chips_69000_t* chips) +{ + chips->engine_active = 1; + chips->bitblt_running.bitblt = chips->bitblt; + chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; + chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; + + if (!chips->bitblt_running.actual_destination_height) { + chips->bitblt_running.actual_destination_height = 1; + } + + + /*Stubbed!*/ + chips->engine_active = 0; + chips_69000_bitblt_interrupt(chips); +} + uint8_t chips_69000_read_ext_reg(chips_69000_t* chips) { @@ -736,6 +706,11 @@ chips_69000_read_ext_reg(chips_69000_t* chips) case 0x0A: val = chips->ext_regs[index] & 0x37; break; + case 0x20: + val &= ~1; + val |= !!(chips->bitblt.bitblt_control & (1 << 31)); + /* TODO: Handle BitBLT reset, if required. */ + break; case 0x63: { val = chips->ext_regs[index]; @@ -983,7 +958,6 @@ chips_69000_in(uint16_t addr, void *p) if (svga->adv_flags & FLAG_RAMDAC_SHIFT) temp >>= 2; break; -#if 1 case 0x3D0: return chips->flat_panel_index; case 0x3D1: @@ -992,7 +966,6 @@ chips_69000_in(uint16_t addr, void *p) return chips->mm_index; case 0x3D3: return chips_69000_read_multimedia(chips); -#endif case 0x3D4: temp = svga->crtcreg; break; @@ -1146,6 +1119,7 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) uint8_t chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: return chips->bitblt_regs_b[addr & 0xFF]; @@ -1208,6 +1182,7 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) uint16_t chips_69000_readw_mmio(uint32_t addr, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { default: return chips_69000_readb_mmio(addr, chips) | (chips_69000_readb_mmio(addr + 1, chips) << 8); @@ -1218,6 +1193,7 @@ chips_69000_readw_mmio(uint32_t addr, chips_69000_t* chips) uint32_t chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { default: return chips_69000_readw_mmio(addr, chips) | (chips_69000_readw_mmio(addr + 2, chips) << 16); @@ -1228,13 +1204,44 @@ chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) void chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: chips->bitblt_regs_b[addr & 0xFF] = val; - if ((addr & 0xFFF) == 0x023) - pclog("BitBLT/Draw operation\n"); + if ((addr & 0xFFF) == 0x023) { + uint8_t cntr = 0; + pclog("BitBLT/Draw operation %hd\n", (uint8_t)cntr++); + chips_69000_setup_bitblt(chips); + } break; case 0x600 ... 0x60F: + switch (addr & 0xFFF) + { + case 0x600 ... 0x603: + { + chips->mem_regs_b[addr & 0xF] = val; + chips->mem_regs[addr >> 2] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x604 ... 0x607: + { + chips->mem_regs_b[addr & 0xF] &= ~val; + chips->mem_regs[addr >> 2] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x60c ... 0x60f: + { + chips->mem_regs_b[addr & 0xF] = val; + break; + } + + } chips->mem_regs_b[addr & 0xF] = val; break; case 0x768: @@ -1293,6 +1300,7 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) void chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { default: chips_69000_writeb_mmio(addr, val, chips); @@ -1304,6 +1312,7 @@ chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) void chips_69000_writel_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) { + addr &= 0xFFF; switch (addr & 0xFFF) { default: chips_69000_writew_mmio(addr, val, chips); @@ -1384,19 +1393,13 @@ chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) svga_writel_linear(addr & 0x1FFFFF, val, p); } -void -chips_69000_vsync_start(svga_t *svga) -{ - /* TODO: PCI interrupts for this. */ - chips_69000_t *chips = (chips_69000_t *) svga->priv; - -} - void chips_69000_vblank_start(svga_t *svga) { chips_69000_t *chips = (chips_69000_t *) svga->priv; - /* Needed? */ + chips->mem_regs[1] |= 1 << 14; + + chips_69000_interrupt(chips); } static void * @@ -1425,7 +1428,6 @@ chips_69000_init(const device_t *info) chips->svga.bpp = 8; chips->svga.miscout = 1; chips->svga.recalctimings_ex = chips_69000_recalctimings; - chips->svga.vsync_callback = chips_69000_vsync_start; chips->svga.vblank_start = chips_69000_vblank_start; mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); @@ -1444,7 +1446,7 @@ chips_69000_init(const device_t *info) chips->flat_panel_regs[0x01] = 1; - sizeof(chips->bitblt_regs); + sizeof(struct chips_69000_bitblt_t); return chips; } From 2b6cf4846c4ba36c41e9b14198043366ef881c25 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 1 Feb 2024 01:53:17 +0600 Subject: [PATCH 15/52] No more nonsense getting DWORD-written --- src/video/vid_c&t_69000.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index cab0f0f21..bc660283e 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -729,18 +729,18 @@ chips_69000_read_ext_reg(chips_69000_t* chips) val = 0x0; break; } - //if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - // pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); + if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); return val; } void chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) { - //if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - //&& (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - // pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); + if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); switch (chips->ext_index) { case 0xA: chips->ext_regs[chips->ext_index] = val & 0x37; @@ -1119,6 +1119,7 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) uint8_t chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) { + pclog("C&T Read 0x%X\n", addr); addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: @@ -1204,6 +1205,7 @@ chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) void chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) { + pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: @@ -1310,7 +1312,7 @@ chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) } void -chips_69000_writel_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) +chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { addr &= 0xFFF; switch (addr & 0xFFF) { From 10de00c984d32f544f33e25c66c1b751aa416746 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 1 Feb 2024 15:19:23 +0600 Subject: [PATCH 16/52] BitBlt works, but improperly --- src/video/vid_c&t_69000.c | 232 +++++++++++++++++++++++++++++++++++--- 1 file changed, 216 insertions(+), 16 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index bc660283e..fde218ed8 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -78,7 +78,7 @@ typedef struct chips_69000_bitblt_t /* BR0A - Source Expansion Foreground Color Register. */ uint32_t source_key_fg; -}; +} chips_69000_bitblt_t; #pragma pack(pop) typedef struct chips_69000_t { @@ -122,6 +122,13 @@ typedef struct chips_69000_t { uint32_t actual_source_height; uint32_t actual_destination_height; + + uint32_t actual_destination_width; + + uint32_t count_x, count_y; + uint32_t x, y; + int x_dir, y_dir; + uint8_t bytes_per_pixel; } bitblt_running; @@ -144,6 +151,13 @@ typedef struct chips_69000_t { static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +uint8_t chips_69000_readb_linear(uint32_t addr, void *p); +uint16_t chips_69000_readw_linear(uint32_t addr, void *p); +uint32_t chips_69000_readl_linear(uint32_t addr, void *p); +void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p); +void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p); +void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p); + /* Multimedia handling. */ uint8_t chips_69000_read_multimedia(chips_69000_t* chips) @@ -209,6 +223,7 @@ chips_69000_interrupt(chips_69000_t* chips) void chips_69000_bitblt_interrupt(chips_69000_t* chips) { + chips->engine_active = 0; chips->mem_regs[1] |= 1 << 31; chips_69000_interrupt(chips); @@ -382,6 +397,10 @@ chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) void chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_src, uint8_t rop) { + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_8bpp(dst, nonpattern_src, rop); + } + switch (rop) { case 0x00: *dst = 0; @@ -439,6 +458,10 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ void chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) { + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_16bpp(dst, nonpattern_src, rop); + } + switch (rop) { case 0x00: *dst = 0; @@ -497,6 +520,11 @@ void chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpattern_src, uint8_t rop) { uint32_t orig_dst = *dst & 0xFF000000; + + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_24bpp(dst, nonpattern_src, rop); + } + switch (rop) { case 0x00: *dst = 0; @@ -655,6 +683,99 @@ chips_69000_recalc_banking(chips_69000_t *chips) }*/ } +void +chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) +{ + uint32_t pattern_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t pattern_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + uint8_t pattern_data = 0; + uint8_t pattern_data_8bpp[8][8]; + uint16_t pattern_data_16bpp[8][8]; + uint32_t pattern_pixel = 0; + uint32_t dest_pixel = 0; + uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + uint8_t vert_pat_alignment = (chips->bitblt_running.bitblt.bitblt_control >> 20) & 7; + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16; + break; + } + } + + /* TODO: Find out from where it actually pulls the exact pattern x and y values. */ + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) { + uint8_t is_true = 0; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) + pattern_data = 0; + else + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + (vert_pat_alignment + chips->bitblt_running.count_y), chips); + + is_true = !!(pattern_data & (1 << (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.count_x) & 7))); + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 17))) { + return; + } + + pattern_pixel = is_true ? pattern_fg : pattern_bg; + + pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_do_rop_8bpp_patterned((uint8_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_do_rop_16bpp_patterned((uint16_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_do_rop_24bpp_patterned((uint32_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips); + break; + } + } +} + void chips_69000_setup_bitblt(chips_69000_t* chips) { @@ -662,14 +783,90 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt = chips->bitblt; chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; + chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; - if (!chips->bitblt_running.actual_destination_height) { - chips->bitblt_running.actual_destination_height = 1; + if (chips->bitblt.bitblt_control & (1 << 23)) { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); + } else { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->ext_regs[0x20] >> 4) & 3); } - - /*Stubbed!*/ - chips->engine_active = 0; + chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel; + + switch ((chips->bitblt.bitblt_control >> 8) & 3) { + case 0: + chips->bitblt_running.x = 0; + chips->bitblt_running.y = 0; + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = 1; + break; + case 1: + chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; + chips->bitblt_running.y = 0; + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = 1; + break; + case 2: + chips->bitblt_running.x = 0; + chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1; + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = -1; + break; + case 3: + chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; + chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1; + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = -1; + break; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + return; + } + + /* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */ + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) { + chips_69000_bitblt_interrupt(chips); + return; + } + + do { + do { + uint32_t pixel = 0; + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.y * chips->bitblt.source_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16; + break; + } + } + + chips_69000_process_pixel(chips, pixel); + + chips->bitblt_running.x += chips->bitblt_running.x_dir; + } while ((chips->bitblt_running.count_x++) < chips->bitblt_running.actual_destination_width); + + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_x = 0; + } while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height); + chips_69000_bitblt_interrupt(chips); } @@ -708,7 +905,7 @@ chips_69000_read_ext_reg(chips_69000_t* chips) break; case 0x20: val &= ~1; - val |= !!(chips->bitblt.bitblt_control & (1 << 31)); + val |= !!chips->engine_active; /* TODO: Handle BitBLT reset, if required. */ break; case 0x63: @@ -729,18 +926,18 @@ chips_69000_read_ext_reg(chips_69000_t* chips) val = 0x0; break; } - if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); + // if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + // pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); return val; } void chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) { - if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); + // if (chips->ext_index != 0x4E && chips->ext_index != 0x4F + // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) + // pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); switch (chips->ext_index) { case 0xA: chips->ext_regs[chips->ext_index] = val & 0x37; @@ -1119,10 +1316,13 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) uint8_t chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) { - pclog("C&T Read 0x%X\n", addr); + //pclog("C&T Read 0x%X\n", addr); addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: + if (addr == 0x10) { + return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); + } return chips->bitblt_regs_b[addr & 0xFF]; case 0x600 ... 0x60F: return chips->mem_regs_b[addr & 0xF]; @@ -1205,12 +1405,12 @@ chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) void chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) { - pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); + //pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: chips->bitblt_regs_b[addr & 0xFF] = val; - if ((addr & 0xFFF) == 0x023) { + if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { uint8_t cntr = 0; pclog("BitBLT/Draw operation %hd\n", (uint8_t)cntr++); chips_69000_setup_bitblt(chips); From 2dba92221fdc2ffc4997dda1f52397c745efa6c5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 1 Feb 2024 19:48:09 +0600 Subject: [PATCH 17/52] Try fixing overdrawing --- src/video/vid_c&t_69000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index fde218ed8..75848a7f5 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -861,11 +861,11 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips_69000_process_pixel(chips, pixel); chips->bitblt_running.x += chips->bitblt_running.x_dir; - } while ((chips->bitblt_running.count_x++) < chips->bitblt_running.actual_destination_width); + } while ((++chips->bitblt_running.count_x) < chips->bitblt_running.actual_destination_width); chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_x = 0; - } while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height); + } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); chips_69000_bitblt_interrupt(chips); } From e0503e6381b4e3562b15e51612167bee7a1cde12 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 2 Feb 2024 01:44:51 +0600 Subject: [PATCH 18/52] Patterns now are blitted correctly --- src/video/vid_c&t_69000.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 75848a7f5..05c549d2f 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -130,6 +130,9 @@ typedef struct chips_69000_t { int x_dir, y_dir; uint8_t bytes_per_pixel; + + /* Byte counter for BitBLT port writes. */ + uint8_t bytes_written; } bitblt_running; union { @@ -693,7 +696,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) uint16_t pattern_data_16bpp[8][8]; uint32_t pattern_pixel = 0; uint32_t dest_pixel = 0; - uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt_running.bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); uint8_t vert_pat_alignment = (chips->bitblt_running.bitblt.bitblt_control >> 20) & 7; switch (chips->bitblt_running.bytes_per_pixel) { @@ -723,7 +726,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) pattern_data = 0; else - pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + (vert_pat_alignment + chips->bitblt_running.count_y), chips); + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + chips->bitblt_running.count_y) & 7), chips); is_true = !!(pattern_data & (1 << (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.count_x) & 7))); @@ -793,7 +796,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel; - switch ((chips->bitblt.bitblt_control >> 8) & 3) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 8) & 3) { case 0: chips->bitblt_running.x = 0; chips->bitblt_running.y = 0; @@ -808,13 +811,13 @@ chips_69000_setup_bitblt(chips_69000_t* chips) break; case 2: chips->bitblt_running.x = 0; - chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1; + chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height; chips->bitblt_running.x_dir = 1; chips->bitblt_running.y_dir = -1; break; case 3: chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1; + chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height; chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = -1; break; @@ -865,7 +868,11 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_x = 0; - } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { + chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; + } else + chips->bitblt_running.x = 0; + } while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height); chips_69000_bitblt_interrupt(chips); } From 2690132bc37b1785740adb179ca1c8843b6bb1d8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 2 Feb 2024 02:28:32 +0600 Subject: [PATCH 19/52] WIP BitBLT port work --- src/video/vid_c&t_69000.c | 66 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 05c549d2f..c3912fa77 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -133,6 +133,7 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; + uint8_t bytes_port[4]; } bitblt_running; union { @@ -721,14 +722,15 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) } /* TODO: Find out from where it actually pulls the exact pattern x and y values. */ + /* Also: is horizontal pattern alignment a requirement? */ if (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) { uint8_t is_true = 0; if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) pattern_data = 0; else - pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + chips->bitblt_running.count_y) & 7), chips); + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + chips->bitblt_running.y) & 7), chips); - is_true = !!(pattern_data & (1 << (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.count_x) & 7))); + is_true = !!(pattern_data & (1 << (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7))); if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 17))) { return; @@ -737,6 +739,12 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) pattern_pixel = is_true ? pattern_fg : pattern_bg; pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + } else { + if (chips->bitblt_running.bytes_per_pixel == 1) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); + } } switch (chips->bitblt_running.bytes_per_pixel) { @@ -787,6 +795,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; + chips->bitblt_running.bytes_written = 0; if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); @@ -877,6 +886,43 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips_69000_bitblt_interrupt(chips); } +void +chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { + + if (!chips->engine_active) + return; + + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { + uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + if (chips->bitblt_running.bytes_per_pixel == 1) + source_pixel = (chips->bitblt_running.bytes_port[1] << 8); + if (chips->bitblt_running.bytes_per_pixel == 2) + source_pixel = (chips->bitblt_running.bytes_port[2] << 16); + + chips_69000_process_pixel(chips, source_pixel); + chips->bitblt_running.x += chips->bitblt_running.x_dir; + chips->bitblt_running.count_x++; + + if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_y++; + + chips->bitblt_running.count_x = 0; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { + chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; + } else + chips->bitblt_running.x = 0; + + if (chips->bitblt_running.count_y > chips->bitblt_running.actual_destination_height) { + chips_69000_bitblt_interrupt(chips); + return; + } + } + } +} + uint8_t chips_69000_read_ext_reg(chips_69000_t* chips) { @@ -1413,6 +1459,10 @@ void chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) { //pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); + if (addr & 0x10000) { + chips_69000_bitblt_write(chips, val); + return; + } addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: @@ -1509,6 +1559,11 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) void chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) { + if (addr & 0x10000) { + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + return; + } addr &= 0xFFF; switch (addr & 0xFFF) { default: @@ -1521,6 +1576,13 @@ chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) void chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { + if (addr & 0x10000) { + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 24) & 0xFF); + return; + } addr &= 0xFFF; switch (addr & 0xFFF) { default: From 08660004af780143a2a15dfa97f1bf2d7daa4c56 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 2 Feb 2024 12:32:13 +0600 Subject: [PATCH 20/52] Fix BitBLT status read --- src/video/vid_c&t_69000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index c3912fa77..786a28778 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1373,7 +1373,7 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: - if (addr == 0x10) { + if (addr == 0x13) { return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); } return chips->bitblt_regs_b[addr & 0xFF]; From 08d784fe07fd655b9d1cb6e17b2a8093bb1e7abb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 2 Feb 2024 13:20:24 +0600 Subject: [PATCH 21/52] Working (but with pitch troubles) BitBLT emulation --- src/video/vid_c&t_69000.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 786a28778..e35f28227 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -460,7 +460,7 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ } void -chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop) +chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpattern_src, uint8_t rop) { if ((rop & 0xF) == ((rop >> 4) & 0xF)) { return chips_69000_do_rop_16bpp(dst, nonpattern_src, rop); @@ -521,7 +521,7 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpatte } void -chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpattern_src, uint8_t rop) +chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpattern_src, uint8_t rop) { uint32_t orig_dst = *dst & 0xFF000000; @@ -832,10 +832,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) break; } - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { - return; - } - /* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */ if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17)) && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) @@ -844,6 +840,10 @@ chips_69000_setup_bitblt(chips_69000_t* chips) return; } + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + return; + } + do { do { uint32_t pixel = 0; @@ -896,16 +896,15 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; - if (chips->bitblt_running.bytes_per_pixel == 1) - source_pixel = (chips->bitblt_running.bytes_port[1] << 8); if (chips->bitblt_running.bytes_per_pixel == 2) - source_pixel = (chips->bitblt_running.bytes_port[2] << 16); + source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); + if (chips->bitblt_running.bytes_per_pixel == 3) + source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); chips_69000_process_pixel(chips, source_pixel); chips->bitblt_running.x += chips->bitblt_running.x_dir; - chips->bitblt_running.count_x++; - if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + if (++chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width - 1) { chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_y++; From 33cba9ef5095c3c9575ee452b518fe0ebc4692fa Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 2 Feb 2024 15:31:42 +0600 Subject: [PATCH 22/52] More ROP codes --- src/video/vid_c&t_69000.c | 114 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index e35f28227..b2cd62f07 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -133,6 +133,7 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; + uint32_t bytes_counter; uint8_t bytes_port[4]; } bitblt_running; @@ -418,6 +419,18 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ case 0x0F: *dst = ~src; break; + case 0x1A: + *dst = src ^ (*dst | (src & nonpattern_src)); + break; + case 0x2A: + *dst = *dst & (~(nonpattern_src & src)); + break; + case 0x3A: + *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + break; + case 0x4A: + *dst = *dst ^ (src & (nonpattern_src | *dst)); + break; case 0x50: *dst = src & ~(*dst); break; @@ -430,6 +443,18 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ case 0x5F: *dst = ~src | ~(*dst); break; + case 0x6A: + *dst = *dst ^ (src & nonpattern_src); + break; + case 0x7A: + *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (nonpattern_src | (~src)); + break; + case 0x9A: + *dst = *dst ^ (src & (~nonpattern_src)); + break; case 0xB8: *dst = (((src ^ *dst) & nonpattern_src) ^ src); break; @@ -444,6 +469,18 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ case 0xAF: *dst |= ~src; break; + case 0xBA: + *dst |= (src & ~nonpattern_src); + break; + case 0xCA: + *dst ^= (src & (nonpattern_src ^ *dst)); + break; + case 0xDA: + *dst ^= src & (~(nonpattern_src & *dst)); + break; + case 0xEA: + *dst |= src & nonpattern_src; + break; case 0xF0: *dst = src; break; @@ -479,6 +516,18 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpatt case 0x0F: *dst = ~src; break; + case 0x1A: + *dst = src ^ (*dst | (src & nonpattern_src)); + break; + case 0x2A: + *dst = *dst & (~(nonpattern_src & src)); + break; + case 0x3A: + *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + break; + case 0x4A: + *dst = *dst ^ (src & (nonpattern_src | *dst)); + break; case 0x50: *dst = src & ~(*dst); break; @@ -491,6 +540,18 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpatt case 0x5F: *dst = ~src | ~(*dst); break; + case 0x6A: + *dst = *dst ^ (src & nonpattern_src); + break; + case 0x7A: + *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (nonpattern_src | (~src)); + break; + case 0x9A: + *dst = *dst ^ (src & (~nonpattern_src)); + break; case 0xB8: *dst = (((src ^ *dst) & nonpattern_src) ^ src); break; @@ -505,6 +566,18 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpatt case 0xAF: *dst |= ~src; break; + case 0xBA: + *dst |= (src & ~nonpattern_src); + break; + case 0xCA: + *dst ^= (src & (nonpattern_src ^ *dst)); + break; + case 0xDA: + *dst ^= src & (~(nonpattern_src & *dst)); + break; + case 0xEA: + *dst |= src & nonpattern_src; + break; case 0xF0: *dst = src; break; @@ -542,6 +615,18 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpatt case 0x0F: *dst = ~src; break; + case 0x1A: + *dst = src ^ (*dst | (src & nonpattern_src)); + break; + case 0x2A: + *dst = *dst & (~(nonpattern_src & src)); + break; + case 0x3A: + *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + break; + case 0x4A: + *dst = *dst ^ (src & (nonpattern_src | *dst)); + break; case 0x50: *dst = src & ~(*dst); break; @@ -554,6 +639,18 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpatt case 0x5F: *dst = ~src | ~(*dst); break; + case 0x6A: + *dst = *dst ^ (src & nonpattern_src); + break; + case 0x7A: + *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (nonpattern_src | (~src)); + break; + case 0x9A: + *dst = *dst ^ (src & (~nonpattern_src)); + break; case 0xB8: *dst = (((src ^ *dst) & nonpattern_src) ^ src); break; @@ -568,6 +665,18 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpatt case 0xAF: *dst |= ~src; break; + case 0xBA: + *dst |= (src & ~nonpattern_src); + break; + case 0xCA: + *dst ^= (src & (nonpattern_src ^ *dst)); + break; + case 0xDA: + *dst ^= src & (~(nonpattern_src & *dst)); + break; + case 0xEA: + *dst |= src & nonpattern_src; + break; case 0xF0: *dst = src; break; @@ -796,6 +905,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; chips->bitblt_running.bytes_written = 0; + chips->bitblt_running.bytes_counter = 0; if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); @@ -892,6 +1002,10 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (!chips->engine_active) return; + + chips->bitblt_running.bytes_counter++; + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) + return; chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; From 323c179cee8096efd3fc5c0f735f40b10dbd18d7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 3 Feb 2024 15:02:49 +0600 Subject: [PATCH 23/52] Force quadword alignment --- src/video/vid_c&t_69000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index b2cd62f07..0f058b592 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1018,7 +1018,9 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips_69000_process_pixel(chips, source_pixel); chips->bitblt_running.x += chips->bitblt_running.x_dir; - if (++chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width - 1) { + if (++chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + if (chips->bitblt_running.bitblt.destination_width & 7) + chips->bitblt_running.bitblt.source_addr = 8 - (chips->bitblt_running.bitblt.destination_width & 7); chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_y++; From 45b9cb1980c1c443e15c076d4c7e18ec3ea7702a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 3 Feb 2024 15:27:46 +0600 Subject: [PATCH 24/52] Part 2 of quadword alignment fixing --- src/video/vid_c&t_69000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 0f058b592..6fb3ad2a5 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1002,7 +1002,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (!chips->engine_active) return; - chips->bitblt_running.bytes_counter++; if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) return; @@ -1021,8 +1020,12 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (++chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { if (chips->bitblt_running.bitblt.destination_width & 7) chips->bitblt_running.bitblt.source_addr = 8 - (chips->bitblt_running.bitblt.destination_width & 7); + else + chips->bitblt_running.bitblt.source_addr = 0; + chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_y++; + chips->bitblt_running.bytes_counter = 0; chips->bitblt_running.count_x = 0; if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { From 0bca52bfe5d08dfd8691c7b1ec3615933db1f290 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 3 Feb 2024 15:45:52 +0600 Subject: [PATCH 25/52] Fix height counting --- src/video/vid_c&t_69000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 6fb3ad2a5..fae8c04bd 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1033,7 +1033,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } else chips->bitblt_running.x = 0; - if (chips->bitblt_running.count_y > chips->bitblt_running.actual_destination_height) { + if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) { chips_69000_bitblt_interrupt(chips); return; } From ac0f7ec9e7f5e1a7d36a5f25db11ba317097f62c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 4 Feb 2024 01:23:26 +0600 Subject: [PATCH 26/52] Implement color transparency and 16/24-bpp color patterns --- src/video/vid_c&t_69000.c | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index fae8c04bd..efa619491 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -854,6 +854,43 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); } + if (chips->bitblt_running.bytes_per_pixel == 2) { + pattern_pixel = chips_69000_readw_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + } + if (chips->bitblt_running.bytes_per_pixel == 3) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; + } + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 1: + case 3: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } } switch (chips->bitblt_running.bytes_per_pixel) { @@ -874,6 +911,25 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) } } + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 0: + case 2: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } + } + switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { From 35cae93fed7f83c17e9c23facf1c9217abd75c2b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 4 Feb 2024 16:25:17 +0600 Subject: [PATCH 27/52] More monochrome source work Mostly correct now. --- src/video/vid_c&t_69000.c | 189 +++++++++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 4 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index efa619491..b34c5c826 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -34,6 +34,7 @@ #include <86box/thread.h> #include <86box/i2c.h> #include <86box/vid_ddc.h> +#include <86box/plat_unused.h> #include #pragma pack(push, 1) @@ -134,7 +135,11 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; uint32_t bytes_counter; - uint8_t bytes_port[4]; + uint8_t bytes_port[8]; + + /* Monochrome sources. */ + uint8_t mono_is_first_quadword; + uint8_t mono_bit_cntr; } bitblt_running; union { @@ -952,6 +957,153 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) } } +void +chips_69000_process_mono_data(UNUSED(chips_69000_t* chips), uint64_t val) +{ + /* Notes: + Reserved value of 0b000 for monochrome source alignment makes it use Destination Scanline Width. + + TODO: + Actually implement this. + + Figure out how alignment works. The example provided is unclear about non-quadword alignment. + (Outside of the one xf86-video-chips already documents). + Maybe it merely advances the source address pointer by alignment after consuming a byte. + + Edit: It actually consumes all 8 bytes of the quadword before incrementing the pitch. + Which begs the next question: Are those 8 bytes for same-scanline drawing or for y-incremented drawing? + And is 4-byte-or-less alignment relevant for our purposes? The Monochrome Source Register only talks about quadwords, nothing else. + */ + + uint64_t i = 0; + uint8_t is_true = 0; + int orig_x = chips->bitblt_running.x; + int orig_y = chips->bitblt_running.y; + uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + + int orig_count_x = chips->bitblt_running.count_x; + int orig_count_y = chips->bitblt_running.count_y; + + chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; + + if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { + source_fg = chips->bitblt_running.bitblt.source_key_fg; + source_bg = chips->bitblt_running.bitblt.source_key_bg; + } + + for (i = 0; i < 64; i++) { + uint32_t pixel = 0x0; + if (chips->bitblt_running.mono_is_first_quadword && (i < chips->bitblt_running.bitblt.monochrome_source_initial_discard)) + goto increment; + + if (i < chips->bitblt_running.bitblt.monochrome_source_left_clip) + goto increment; + + if (i >= (64 - chips->bitblt_running.bitblt.monochrome_source_right_clip)) + goto increment; + + is_true = !!(val & (1 << (i))); + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { + goto increment; + } + + pixel = is_true ? source_fg : source_bg; + pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + chips->bitblt_running.x = orig_x + (chips->bitblt_running.count_x); + chips->bitblt_running.y = orig_y + chips->bitblt_running.count_y; + + if ((orig_count_x + (chips->bitblt_running.count_x)) < chips->bitblt_running.actual_destination_width + && (orig_count_y + chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height) + chips_69000_process_pixel(chips, pixel); + +increment: + chips->bitblt_running.count_x++; + if (chips->bitblt_running.count_x == 8) { + chips->bitblt_running.count_x = 0; + chips->bitblt_running.count_y++; + } + } + chips->bitblt_running.x = orig_x; + chips->bitblt_running.y = orig_y; + chips->bitblt_running.count_x = orig_count_x; + chips->bitblt_running.count_y = orig_count_y; + chips->bitblt_running.x += chips->bitblt_running.x_dir * 8; + chips->bitblt_running.count_x += 8; + chips->bitblt_running.mono_is_first_quadword = 0; + if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + chips->bitblt_running.count_y += 8; + chips->bitblt_running.y += chips->bitblt_running.y_dir * 8; + chips->bitblt_running.count_x = 0; + if (chips->bitblt_running.count_y > chips->bitblt_running.actual_destination_height) + chips_69000_bitblt_interrupt(chips); + } +} + +void +chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t val) +{ + uint64_t i = 0; + uint8_t is_true = 0; + int orig_x = chips->bitblt_running.x; + int orig_y = chips->bitblt_running.y; + uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + + if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { + source_fg = chips->bitblt_running.bitblt.source_key_fg; + source_bg = chips->bitblt_running.bitblt.source_key_bg; + } + + for (i = chips->bitblt_running.mono_bit_cntr; i < (chips->bitblt_running.mono_bit_cntr + 8); i++) { + uint32_t pixel = 0x0; + if (chips->bitblt_running.mono_is_first_quadword && (i < chips->bitblt_running.bitblt.monochrome_source_initial_discard)) + continue; + + if (i < chips->bitblt_running.bitblt.monochrome_source_left_clip) + continue; + + if (i >= (64 - chips->bitblt_running.bitblt.monochrome_source_right_clip)) + continue; + + is_true = !!(val & (1 << (8 - (i & 7)))); + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { + continue; + } + + pixel = is_true ? source_fg : source_bg; + pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + chips->bitblt_running.x = orig_x + (i & 7); + + //if ((chips->bitblt_running.count_x + (i & 7)) < chips->bitblt_running.actual_destination_width) + chips_69000_process_pixel(chips, pixel); + } + chips->bitblt_running.mono_bit_cntr += 8; + chips->bitblt_running.x = orig_x; + chips->bitblt_running.y = orig_y; + chips->bitblt_running.x += chips->bitblt_running.x_dir * 8; + chips->bitblt_running.count_x += 8; + if (chips->bitblt_running.mono_bit_cntr >= 64) { + chips->bitblt_running.mono_is_first_quadword = 0; + chips->bitblt_running.mono_bit_cntr = 0; + } + if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + chips->bitblt_running.count_y += 1; + chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; + chips->bitblt_running.count_x = 0; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { + chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; + } else + chips->bitblt_running.x = 0; + if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) + chips_69000_bitblt_interrupt(chips); + } +} + void chips_69000_setup_bitblt(chips_69000_t* chips) { @@ -962,6 +1114,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; chips->bitblt_running.bytes_written = 0; chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.mono_is_first_quadword = 1; + chips->bitblt_running.mono_bit_cntr = 0; + int orig_cycles = cycles; if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); @@ -1010,6 +1165,10 @@ chips_69000_setup_bitblt(chips_69000_t* chips) return; } + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("C&T: Monochrome blit\n"); + } + do { do { uint32_t pixel = 0; @@ -1048,7 +1207,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } else chips->bitblt_running.x = 0; } while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height); - + cycles = orig_cycles; chips_69000_bitblt_interrupt(chips); } @@ -1058,6 +1217,27 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (!chips->engine_active) return; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 + && chips->bitblt_running.bytes_written == 4) { + chips->bitblt_running.bytes_written = 0; + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + } else if (chips->bitblt_running.bytes_written == 8) { + chips->bitblt_running.bytes_written = 0; + uint64_t mono_data = chips->bitblt_running.bytes_port[0]; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[1] << 8ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[2] << 16ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[3] << 24ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[4] << 32ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[5] << 40ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[6] << 48ull; + mono_data |= (uint64_t)chips->bitblt_running.bytes_port[7] << 56ull; + chips_69000_process_mono_data(chips, mono_data); + } + return; + } + chips->bitblt_running.bytes_counter++; if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) return; @@ -1291,7 +1471,6 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); chips_69000_recalc_banking(chips); return; -#if 1 case 0x3D0: chips->flat_panel_index = val; return; @@ -1302,7 +1481,6 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) return; case 0x3D3: return chips_69000_write_multimedia(chips, val); -#endif case 0x3D4: svga->crtcreg = val & 0xff; return; @@ -1751,6 +1929,9 @@ void chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { if (addr & 0x10000) { + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("BitBLT mono 0x%08X\n", val); + } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); chips_69000_bitblt_write(chips, (val >> 16) & 0xFF); From 485d17e117ee743a9c3da831fccfcdfa9048dd60 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Feb 2024 13:03:34 +0600 Subject: [PATCH 28/52] Fix height overdrawing and BitBlt direction --- src/video/vid_c&t_69000.c | 59 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index b34c5c826..a101232b9 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -127,7 +127,7 @@ typedef struct chips_69000_t { uint32_t actual_destination_width; uint32_t count_x, count_y; - uint32_t x, y; + int x, y; int x_dir, y_dir; uint8_t bytes_per_pixel; @@ -1079,7 +1079,7 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va chips->bitblt_running.x = orig_x + (i & 7); - //if ((chips->bitblt_running.count_x + (i & 7)) < chips->bitblt_running.actual_destination_width) + if ((chips->bitblt_running.count_x + (i & 7)) <= chips->bitblt_running.actual_destination_width) chips_69000_process_pixel(chips, pixel); } chips->bitblt_running.mono_bit_cntr += 8; @@ -1095,10 +1095,7 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va chips->bitblt_running.count_y += 1; chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; chips->bitblt_running.count_x = 0; - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { - chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - } else - chips->bitblt_running.x = 0; + chips->bitblt_running.x = 0; if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) chips_69000_bitblt_interrupt(chips); } @@ -1126,28 +1123,23 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel; + chips->bitblt_running.x = 0; + chips->bitblt_running.y = 0; + switch ((chips->bitblt_running.bitblt.bitblt_control >> 8) & 3) { case 0: - chips->bitblt_running.x = 0; - chips->bitblt_running.y = 0; chips->bitblt_running.x_dir = 1; chips->bitblt_running.y_dir = 1; break; case 1: - chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - chips->bitblt_running.y = 0; chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = 1; break; case 2: - chips->bitblt_running.x = 0; - chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height; chips->bitblt_running.x_dir = 1; chips->bitblt_running.y_dir = -1; break; case 3: - chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height; chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = -1; break; @@ -1161,12 +1153,21 @@ chips_69000_setup_bitblt(chips_69000_t* chips) return; } - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { - return; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " + "monochrome left clip = %d, " + "monochrome right clip = %d, " + "monochrome initial discard = %d, " + "destination_width = %d, destination_height = %d\n", chips->bitblt_running.bitblt.monochrome_source_alignment, + chips->bitblt_running.bitblt.monochrome_source_left_clip, + chips->bitblt_running.bitblt.monochrome_source_right_clip, + chips->bitblt_running.bitblt.monochrome_source_initial_discard, + chips->bitblt_running.bitblt.destination_width, + chips->bitblt_running.bitblt.destination_height); } - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { - pclog("C&T: Monochrome blit\n"); + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + return; } do { @@ -1202,11 +1203,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_x = 0; - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { - chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - } else - chips->bitblt_running.x = 0; - } while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height); + chips->bitblt_running.x = 0; + } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); cycles = orig_cycles; chips_69000_bitblt_interrupt(chips); } @@ -1223,6 +1221,12 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { && chips->bitblt_running.bytes_written == 4) { chips->bitblt_running.bytes_written = 0; chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + if (chips->bitblt_running.actual_destination_width > 8) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); + if (chips->bitblt_running.actual_destination_width > 16) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[2]); + if (chips->bitblt_running.actual_destination_width > 24) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[3]); } else if (chips->bitblt_running.bytes_written == 8) { chips->bitblt_running.bytes_written = 0; uint64_t mono_data = chips->bitblt_running.bytes_port[0]; @@ -1264,10 +1268,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.bytes_counter = 0; chips->bitblt_running.count_x = 0; - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 8)) { - chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1; - } else - chips->bitblt_running.x = 0; + chips->bitblt_running.x = 0; if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) { chips_69000_bitblt_interrupt(chips); @@ -1820,8 +1821,6 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) case 0x00 ... 0x28: chips->bitblt_regs_b[addr & 0xFF] = val; if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { - uint8_t cntr = 0; - pclog("BitBLT/Draw operation %hd\n", (uint8_t)cntr++); chips_69000_setup_bitblt(chips); } break; @@ -1929,7 +1928,7 @@ void chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { if (addr & 0x10000) { - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) && chips->bitblt_running.bitblt.destination_width > 8) { pclog("BitBLT mono 0x%08X\n", val); } chips_69000_bitblt_write(chips, val & 0xFF); From d6e1d6aa322f51edb2e5c9a7faa5de883e8c2b15 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Feb 2024 15:23:36 +0600 Subject: [PATCH 29/52] Monochrome drawing is now finally fixed --- src/video/vid_c&t_69000.c | 196 +++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index a101232b9..afdc748e6 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -405,10 +405,10 @@ chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) } void -chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_src, uint8_t rop) +chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) { if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_8bpp(dst, nonpattern_src, rop); + return chips_69000_do_rop_8bpp(dst, src, rop); } switch (rop) { @@ -416,84 +416,84 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ *dst = 0; break; case 0x05: - *dst = ~(*dst) & ~src; + *dst = ~(*dst) & ~pattern; break; case 0x0A: - *dst &= ~src; + *dst &= ~pattern; break; case 0x0F: - *dst = ~src; + *dst = ~pattern; break; case 0x1A: - *dst = src ^ (*dst | (src & nonpattern_src)); + *dst = pattern ^ (*dst | (pattern & src)); break; case 0x2A: - *dst = *dst & (~(nonpattern_src & src)); + *dst = *dst & (~(src & pattern)); break; case 0x3A: - *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + *dst = src ^ (pattern | (*dst ^ src)); break; case 0x4A: - *dst = *dst ^ (src & (nonpattern_src | *dst)); + *dst = *dst ^ (pattern & (src | *dst)); break; case 0x50: - *dst = src & ~(*dst); + *dst = pattern & ~(*dst); break; case 0x55: *dst = ~*dst; break; case 0x5A: - *dst ^= src; + *dst ^= pattern; break; case 0x5F: - *dst = ~src | ~(*dst); + *dst = ~pattern | ~(*dst); break; case 0x6A: - *dst = *dst ^ (src & nonpattern_src); + *dst = *dst ^ (pattern & src); break; case 0x7A: - *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + *dst = *dst ^ (pattern & (src | (~*dst))); break; case 0x8A: - *dst = *dst & (nonpattern_src | (~src)); + *dst = *dst & (src | (~pattern)); break; case 0x9A: - *dst = *dst ^ (src & (~nonpattern_src)); + *dst = *dst ^ (pattern & (~src)); break; case 0xB8: - *dst = (((src ^ *dst) & nonpattern_src) ^ src); + *dst = (((pattern ^ *dst) & src) ^ pattern); break; case 0xA0: - *dst &= src; + *dst &= pattern; break; case 0xA5: - *dst ^= ~src; + *dst ^= ~pattern; break; case 0xAA: break; /* No-op. */ case 0xAF: - *dst |= ~src; + *dst |= ~pattern; break; case 0xBA: - *dst |= (src & ~nonpattern_src); + *dst |= (pattern & ~src); break; case 0xCA: - *dst ^= (src & (nonpattern_src ^ *dst)); + *dst ^= (pattern & (src ^ *dst)); break; case 0xDA: - *dst ^= src & (~(nonpattern_src & *dst)); + *dst ^= pattern & (~(src & *dst)); break; case 0xEA: - *dst |= src & nonpattern_src; + *dst |= pattern & src; break; case 0xF0: - *dst = src; + *dst = pattern; break; case 0xF5: - *dst = src | ~(*dst); + *dst = pattern | ~(*dst); break; case 0xFA: - *dst |= src; + *dst |= pattern; break; case 0xFF: *dst = 0xFF; @@ -502,10 +502,10 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_ } void -chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpattern_src, uint8_t rop) +chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) { if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_16bpp(dst, nonpattern_src, rop); + return chips_69000_do_rop_16bpp(dst, src, rop); } switch (rop) { @@ -513,84 +513,84 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpatt *dst = 0; break; case 0x05: - *dst = ~(*dst) & ~src; + *dst = ~(*dst) & ~pattern; break; case 0x0A: - *dst &= ~src; + *dst &= ~pattern; break; case 0x0F: - *dst = ~src; + *dst = ~pattern; break; case 0x1A: - *dst = src ^ (*dst | (src & nonpattern_src)); + *dst = pattern ^ (*dst | (pattern & src)); break; case 0x2A: - *dst = *dst & (~(nonpattern_src & src)); + *dst = *dst & (~(src & pattern)); break; case 0x3A: - *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + *dst = src ^ (pattern | (*dst ^ src)); break; case 0x4A: - *dst = *dst ^ (src & (nonpattern_src | *dst)); + *dst = *dst ^ (pattern & (src | *dst)); break; case 0x50: - *dst = src & ~(*dst); + *dst = pattern & ~(*dst); break; case 0x55: *dst = ~*dst; break; case 0x5A: - *dst ^= src; + *dst ^= pattern; break; case 0x5F: - *dst = ~src | ~(*dst); + *dst = ~pattern | ~(*dst); break; case 0x6A: - *dst = *dst ^ (src & nonpattern_src); + *dst = *dst ^ (pattern & src); break; case 0x7A: - *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + *dst = *dst ^ (pattern & (src | (~*dst))); break; case 0x8A: - *dst = *dst & (nonpattern_src | (~src)); + *dst = *dst & (src | (~pattern)); break; case 0x9A: - *dst = *dst ^ (src & (~nonpattern_src)); + *dst = *dst ^ (pattern & (~src)); break; case 0xB8: - *dst = (((src ^ *dst) & nonpattern_src) ^ src); + *dst = (((pattern ^ *dst) & src) ^ pattern); break; case 0xA0: - *dst &= src; + *dst &= pattern; break; case 0xA5: - *dst ^= ~src; + *dst ^= ~pattern; break; case 0xAA: break; /* No-op. */ case 0xAF: - *dst |= ~src; + *dst |= ~pattern; break; case 0xBA: - *dst |= (src & ~nonpattern_src); + *dst |= (pattern & ~src); break; case 0xCA: - *dst ^= (src & (nonpattern_src ^ *dst)); + *dst ^= (pattern & (src ^ *dst)); break; case 0xDA: - *dst ^= src & (~(nonpattern_src & *dst)); + *dst ^= pattern & (~(src & *dst)); break; case 0xEA: - *dst |= src & nonpattern_src; + *dst |= pattern & src; break; case 0xF0: - *dst = src; + *dst = pattern; break; case 0xF5: - *dst = src | ~(*dst); + *dst = pattern | ~(*dst); break; case 0xFA: - *dst |= src; + *dst |= pattern; break; case 0xFF: *dst = 0xFF; @@ -599,12 +599,12 @@ chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint16_t nonpatt } void -chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpattern_src, uint8_t rop) +chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src, uint8_t rop) { uint32_t orig_dst = *dst & 0xFF000000; if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_24bpp(dst, nonpattern_src, rop); + return chips_69000_do_rop_24bpp(dst, src, rop); } switch (rop) { @@ -612,84 +612,84 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint32_t nonpatt *dst = 0; break; case 0x05: - *dst = ~(*dst) & ~src; + *dst = ~(*dst) & ~pattern; break; case 0x0A: - *dst &= ~src; + *dst &= ~pattern; break; case 0x0F: - *dst = ~src; + *dst = ~pattern; break; case 0x1A: - *dst = src ^ (*dst | (src & nonpattern_src)); + *dst = pattern ^ (*dst | (pattern & src)); break; case 0x2A: - *dst = *dst & (~(nonpattern_src & src)); + *dst = *dst & (~(src & pattern)); break; case 0x3A: - *dst = nonpattern_src ^ (src | (*dst ^ nonpattern_src)); + *dst = src ^ (pattern | (*dst ^ src)); break; case 0x4A: - *dst = *dst ^ (src & (nonpattern_src | *dst)); + *dst = *dst ^ (pattern & (src | *dst)); break; case 0x50: - *dst = src & ~(*dst); + *dst = pattern & ~(*dst); break; case 0x55: *dst = ~*dst; break; case 0x5A: - *dst ^= src; + *dst ^= pattern; break; case 0x5F: - *dst = ~src | ~(*dst); + *dst = ~pattern | ~(*dst); break; case 0x6A: - *dst = *dst ^ (src & nonpattern_src); + *dst = *dst ^ (pattern & src); break; case 0x7A: - *dst = *dst ^ (src & (nonpattern_src | (~*dst))); + *dst = *dst ^ (pattern & (src | (~*dst))); break; case 0x8A: - *dst = *dst & (nonpattern_src | (~src)); + *dst = *dst & (src | (~pattern)); break; case 0x9A: - *dst = *dst ^ (src & (~nonpattern_src)); + *dst = *dst ^ (pattern & (~src)); break; case 0xB8: - *dst = (((src ^ *dst) & nonpattern_src) ^ src); + *dst = (((pattern ^ *dst) & src) ^ pattern); break; case 0xA0: - *dst &= src; + *dst &= pattern; break; case 0xA5: - *dst ^= ~src; + *dst ^= ~pattern; break; case 0xAA: break; /* No-op. */ case 0xAF: - *dst |= ~src; + *dst |= ~pattern; break; case 0xBA: - *dst |= (src & ~nonpattern_src); + *dst |= (pattern & ~src); break; case 0xCA: - *dst ^= (src & (nonpattern_src ^ *dst)); + *dst ^= (pattern & (src ^ *dst)); break; case 0xDA: - *dst ^= src & (~(nonpattern_src & *dst)); + *dst ^= pattern & (~(src & *dst)); break; case 0xEA: - *dst |= src & nonpattern_src; + *dst |= pattern & src; break; case 0xF0: - *dst = src; + *dst = pattern; break; case 0xF5: - *dst = src | ~(*dst); + *dst = pattern | ~(*dst); break; case 0xFA: - *dst |= src; + *dst |= pattern; break; case 0xFF: *dst = 0xFF; @@ -1048,7 +1048,6 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va uint64_t i = 0; uint8_t is_true = 0; int orig_x = chips->bitblt_running.x; - int orig_y = chips->bitblt_running.y; uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; @@ -1059,6 +1058,7 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va for (i = chips->bitblt_running.mono_bit_cntr; i < (chips->bitblt_running.mono_bit_cntr + 8); i++) { uint32_t pixel = 0x0; + if (chips->bitblt_running.mono_is_first_quadword && (i < chips->bitblt_running.bitblt.monochrome_source_initial_discard)) continue; @@ -1068,7 +1068,7 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va if (i >= (64 - chips->bitblt_running.bitblt.monochrome_source_right_clip)) continue; - is_true = !!(val & (1 << (8 - (i & 7)))); + is_true = !!(val & (1 << (7 - (i & 7)))); if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { continue; @@ -1077,14 +1077,13 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va pixel = is_true ? source_fg : source_bg; pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - chips->bitblt_running.x = orig_x + (i & 7); + chips->bitblt_running.x = (orig_x + (i & 7) * chips->bitblt_running.x_dir); - if ((chips->bitblt_running.count_x + (i & 7)) <= chips->bitblt_running.actual_destination_width) + if ((chips->bitblt_running.count_x + (i & 7)) < chips->bitblt_running.actual_destination_width) chips_69000_process_pixel(chips, pixel); } chips->bitblt_running.mono_bit_cntr += 8; chips->bitblt_running.x = orig_x; - chips->bitblt_running.y = orig_y; chips->bitblt_running.x += chips->bitblt_running.x_dir * 8; chips->bitblt_running.count_x += 8; if (chips->bitblt_running.mono_bit_cntr >= 64) { @@ -1147,11 +1146,15 @@ chips_69000_setup_bitblt(chips_69000_t* chips) /* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */ if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17)) - && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) - && (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) { - chips_69000_bitblt_interrupt(chips); - return; - } + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) { + chips_69000_bitblt_interrupt(chips); + return; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + return; + } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " @@ -1166,10 +1169,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.destination_height); } - if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { - return; - } - do { do { uint32_t pixel = 0; @@ -1212,8 +1211,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) void chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { - if (!chips->engine_active) + if (!chips->engine_active) { return; + } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; @@ -1928,8 +1928,8 @@ void chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { if (addr & 0x10000) { - if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) && chips->bitblt_running.bitblt.destination_width > 8) { - pclog("BitBLT mono 0x%08X\n", val); + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + //pclog("BitBLT mono 0x%08X\n", val); } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); From 7b05547e5931c5f856875ec3dfba5b59e66322a2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 5 Feb 2024 15:41:10 +0600 Subject: [PATCH 30/52] Use bytes to count image --- src/video/vid_c&t_69000.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index afdc748e6..f47de012d 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -135,6 +135,7 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; uint32_t bytes_counter; + uint32_t bytes_in_line_written; uint8_t bytes_port[8]; /* Monochrome sources. */ @@ -1112,6 +1113,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bytes_counter = 0; chips->bitblt_running.mono_is_first_quadword = 1; chips->bitblt_running.mono_bit_cntr = 0; + chips->bitblt_running.bytes_in_line_written = 0; int orig_cycles = cycles; if (chips->bitblt.bitblt_control & (1 << 23)) { @@ -1153,6 +1155,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + pclog("source_span = %d, dest_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); + } return; } @@ -1253,11 +1258,13 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); if (chips->bitblt_running.bytes_per_pixel == 3) source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); + + chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; chips_69000_process_pixel(chips, source_pixel); chips->bitblt_running.x += chips->bitblt_running.x_dir; - if (++chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { if (chips->bitblt_running.bitblt.destination_width & 7) chips->bitblt_running.bitblt.source_addr = 8 - (chips->bitblt_running.bitblt.destination_width & 7); else @@ -1266,6 +1273,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.y += chips->bitblt_running.y_dir; chips->bitblt_running.count_y++; chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.bytes_in_line_written = 0; chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; From cd03088873117e86aebb58fe2f483803f8a62b27 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Feb 2024 00:51:17 +0600 Subject: [PATCH 31/52] Source offset trouble fixed WIP hardware cursor --- src/video/vid_c&t_69000.c | 115 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 4 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index f47de012d..f3e3132b2 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -134,8 +134,10 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; + uint8_t bytes_skip; uint32_t bytes_counter; uint32_t bytes_in_line_written; + uint32_t bytes_in_line_counter; uint8_t bytes_port[8]; /* Monochrome sources. */ @@ -1114,6 +1116,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.mono_is_first_quadword = 1; chips->bitblt_running.mono_bit_cntr = 0; chips->bitblt_running.bytes_in_line_written = 0; + chips->bitblt_running.bytes_skip = 0; int orig_cycles = cycles; if (chips->bitblt.bitblt_control & (1 << 23)) { @@ -1156,12 +1159,17 @@ chips_69000_setup_bitblt(chips_69000_t* chips) if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { - pclog("source_span = %d, dest_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); + //pclog("source_span = %d, dest_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); + //pclog("destination_width = %d (qword aligned = %d), skip left = %d\n", chips->bitblt_running.bitblt.destination_width, (chips->bitblt_running.bitblt.destination_width + 7) & ~7, chips->bitblt_running.bitblt.source_addr); + chips->bitblt_running.bytes_in_line_counter = (chips->bitblt_running.bitblt.source_addr + chips->bitblt_running.bitblt.destination_width + 7) & ~7; + if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) + chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); } return; } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr; pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " "monochrome left clip = %d, " "monochrome right clip = %d, " @@ -1172,6 +1180,12 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.monochrome_source_initial_discard, chips->bitblt_running.bitblt.destination_width, chips->bitblt_running.bitblt.destination_height); + + while (chips->engine_active) { + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + + source_addr += chips->bitblt_running.x_dir; + } } do { @@ -1248,8 +1262,9 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_counter++; - if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr)) { return; + } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; @@ -1265,8 +1280,11 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.x += chips->bitblt_running.x_dir; if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { - if (chips->bitblt_running.bitblt.destination_width & 7) - chips->bitblt_running.bitblt.source_addr = 8 - (chips->bitblt_running.bitblt.destination_width & 7); + if (chips->bitblt_running.bytes_skip) { + chips->bitblt_running.bitblt.source_addr = chips->bitblt_running.bytes_skip; + } + else if (chips->bitblt_running.bitblt.destination_width & 7) + chips->bitblt_running.bitblt.source_addr = 8 - ((chips->bitblt_running.bitblt.destination_width) & 7); else chips->bitblt_running.bitblt.source_addr = 0; @@ -1416,6 +1434,34 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) chips->ext_regs[chips->ext_index] = val & 0x1f; svga_recalctimings(&chips->svga); break; + case 0xA0: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.ena = ((val & 7) == 0b101) || ((val & 7) == 0b1); + break; + case 0xA2: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = (val << 8) | ((chips->ext_regs[0xA3] & 0x3F) << 16); + break; + case 0xA3: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = ((chips->ext_regs[0xA2]) << 8) | ((val & 0x3F) << 16); + break; + case 0xA4: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = val | (chips->ext_regs[0xA5] & 7) << 8; + break; + case 0xA5: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = chips->ext_regs[0xA4] | (val & 7) << 8; + break; + case 0xA6: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = val | (chips->ext_regs[0xA7] & 7) << 8; + break; + case 0xA7: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; + break; case 0xD2: break; default: @@ -2035,6 +2081,66 @@ chips_69000_vblank_start(svga_t *svga) chips_69000_interrupt(chips); } +static void +chips_69000_hwcursor_draw(svga_t *svga, int displine) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x; + + if ((chips->ext_regs[0xA0] & 7) == 1) { + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + + dat[0] = *(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8]); + svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + + for (uint8_t x = 0; x < 32; x++) { + if (!(dat[1] & (1ULL << 31))) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 31)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); + else if (dat[0] & (1ULL << 31)) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + + return; + } + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += (chips->ext_regs[0xA0] & 7) == 1 ? 8 : 16; + + dat[0] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8]); + svga->hwcursor_latch.addr += 16; + switch (chips->ext_regs[0xa0] & 7) { + case 0b101: + for (uint8_t x = 0; x < 64; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[1]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[0]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + break; + + default: + break; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + static void * chips_69000_init(const device_t *info) { @@ -2062,6 +2168,7 @@ chips_69000_init(const device_t *info) chips->svga.miscout = 1; chips->svga.recalctimings_ex = chips_69000_recalctimings; chips->svga.vblank_start = chips_69000_vblank_start; + chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); From 614241b8b29cf154660544a2e568cc93f1b50de8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Feb 2024 01:25:54 +0600 Subject: [PATCH 32/52] Non-CPU-driven monochrome source blits --- src/video/vid_c&t_69000.c | 76 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index f3e3132b2..d73042552 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -137,7 +137,6 @@ typedef struct chips_69000_t { uint8_t bytes_skip; uint32_t bytes_counter; uint32_t bytes_in_line_written; - uint32_t bytes_in_line_counter; uint8_t bytes_port[8]; /* Monochrome sources. */ @@ -1103,6 +1102,8 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va } } +void chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data); + void chips_69000_setup_bitblt(chips_69000_t* chips) { @@ -1161,7 +1162,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { //pclog("source_span = %d, dest_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); //pclog("destination_width = %d (qword aligned = %d), skip left = %d\n", chips->bitblt_running.bitblt.destination_width, (chips->bitblt_running.bitblt.destination_width + 7) & ~7, chips->bitblt_running.bitblt.source_addr); - chips->bitblt_running.bytes_in_line_counter = (chips->bitblt_running.bitblt.source_addr + chips->bitblt_running.bitblt.destination_width + 7) & ~7; if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); } @@ -1182,9 +1182,49 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.destination_height); while (chips->engine_active) { - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + switch (chips->bitblt_running.bitblt.monochrome_source_alignment) { + case 0: /* Source-span aligned. */ + { + /* TODO: This is handled purely on a best case basis. */ + uint32_t orig_count_y = chips->bitblt_running.count_y; + uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; + while (orig_count_y == chips->bitblt_running.count_y) { + uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); + orig_source_addr++; + chips_69000_bitblt_write(chips, data & 0xFF); + if ((source_addr + chips->bitblt_running.bitblt.source_span) == orig_source_addr) + break; + } - source_addr += chips->bitblt_running.x_dir; + source_addr = chips->bitblt_running.bitblt.source_addr + chips->bitblt_running.bitblt.source_span; + chips->bitblt_running.bitblt.source_addr = source_addr; + break; + } + case 4: /* Doubleword-aligned*/ + { + uint32_t data = chips_69000_readl_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + source_addr += 4; + break; + } + case 5: /* Quadword-aligned*/ + { + uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 32ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 40ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 48ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 56ull) & 0xFF); + source_addr += 8; + break; + } + } } } @@ -1236,7 +1276,16 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; - if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + chips->bitblt_running.bytes_written &= 7; + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 3 + && chips->bitblt_running.bytes_written == 2) { + chips->bitblt_running.bytes_written = 0; + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + if (chips->bitblt_running.actual_destination_width > 8) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 && chips->bitblt_running.bytes_written == 4) { chips->bitblt_running.bytes_written = 0; chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); @@ -1246,6 +1295,23 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[2]); if (chips->bitblt_running.actual_destination_width > 24) chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[3]); + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5 && chips->bitblt_running.bytes_written == 8) { + chips->bitblt_running.bytes_written = 0; + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + if (chips->bitblt_running.actual_destination_width > 8) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); + if (chips->bitblt_running.actual_destination_width > 16) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[2]); + if (chips->bitblt_running.actual_destination_width > 24) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[3]); + if (chips->bitblt_running.actual_destination_width > 32) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[4]); + if (chips->bitblt_running.actual_destination_width > 40) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[5]); + if (chips->bitblt_running.actual_destination_width > 48) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[6]); + if (chips->bitblt_running.actual_destination_width > 52) + chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[7]); } else if (chips->bitblt_running.bytes_written == 8) { chips->bitblt_running.bytes_written = 0; uint64_t mono_data = chips->bitblt_running.bytes_port[0]; From df91185e7505812a52d6508f1504475cc16dc26a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Feb 2024 01:32:46 +0600 Subject: [PATCH 33/52] Minor line fix --- src/video/vid_c&t_69000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index d73042552..b01be7adb 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1278,7 +1278,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); - chips->bitblt_running.bytes_written &= 7; + chips->bitblt_running.bytes_written = 0; } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 3 && chips->bitblt_running.bytes_written == 2) { chips->bitblt_running.bytes_written = 0; From 1808498370edfeba58f03d6d10f48acb61f8272c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 7 Feb 2024 01:40:15 +0600 Subject: [PATCH 34/52] Add note about bytes_skip calculation --- src/video/vid_c&t_69000.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index b01be7adb..ee83ba6a9 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1160,8 +1160,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { - //pclog("source_span = %d, dest_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); - //pclog("destination_width = %d (qword aligned = %d), skip left = %d\n", chips->bitblt_running.bitblt.destination_width, (chips->bitblt_running.bitblt.destination_width + 7) & ~7, chips->bitblt_running.bitblt.source_addr); + /* Yes, the NT 4.0 and Linux drivers will send this many amount of bytes to the video adapter on quadword-boundary-crossing image blits. + This weird calculation is intended and deliberate. + */ if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); } From 5ce8b9e1a1f398314d63d4155daa30c825f8607f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Feb 2024 00:34:29 +0600 Subject: [PATCH 35/52] 24-bpp image blit fixes --- src/video/vid_c&t_69000.c | 130 +++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 38 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index ee83ba6a9..60afb8d65 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -35,6 +35,7 @@ #include <86box/i2c.h> #include <86box/vid_ddc.h> #include <86box/plat_unused.h> +#include <86box/bswap.h> #include #pragma pack(push, 1) @@ -352,7 +353,6 @@ chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) void chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) { - uint32_t orig_dst = *dst & 0xFF000000; switch (rop) { case 0x00: *dst = 0; @@ -402,8 +402,6 @@ chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) *dst = 0xFF; break; } - *dst &= 0xFFFFFF; - *dst |= orig_dst; } void @@ -868,15 +866,15 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) } if (chips->bitblt_running.bytes_per_pixel == 3) { pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (3 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; } } @@ -962,21 +960,6 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) void chips_69000_process_mono_data(UNUSED(chips_69000_t* chips), uint64_t val) { - /* Notes: - Reserved value of 0b000 for monochrome source alignment makes it use Destination Scanline Width. - - TODO: - Actually implement this. - - Figure out how alignment works. The example provided is unclear about non-quadword alignment. - (Outside of the one xf86-video-chips already documents). - Maybe it merely advances the source address pointer by alignment after consuming a byte. - - Edit: It actually consumes all 8 bytes of the quadword before incrementing the pitch. - Which begs the next question: Are those 8 bytes for same-scanline drawing or for y-incremented drawing? - And is 4-byte-or-less alignment relevant for our purposes? The Monochrome Source Register only talks about quadwords, nothing else. - */ - uint64_t i = 0; uint8_t is_true = 0; int orig_x = chips->bitblt_running.x; @@ -1276,6 +1259,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + int orig_cycles = cycles; chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); @@ -1325,6 +1309,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { mono_data |= (uint64_t)chips->bitblt_running.bytes_port[7] << 56ull; chips_69000_process_mono_data(chips, mono_data); } + cycles = orig_cycles; return; } @@ -1334,16 +1319,18 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { + int orig_cycles = cycles; uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; - if (chips->bitblt_running.bytes_per_pixel == 2) + if (chips->bitblt_running.bytes_per_pixel >= 2) source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); - if (chips->bitblt_running.bytes_per_pixel == 3) + if (chips->bitblt_running.bytes_per_pixel >= 3) source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; chips_69000_process_pixel(chips, source_pixel); + cycles = orig_cycles; chips->bitblt_running.x += chips->bitblt_running.x_dir; if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { @@ -1504,6 +1491,7 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0xA0: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.ena = ((val & 7) == 0b101) || ((val & 7) == 0b1); + chips->svga.hwcursor.cur_xsize = chips->svga.hwcursor.cur_ysize = ((val & 7) == 0b1) ? 32 : 64; break; case 0xA2: chips->ext_regs[chips->ext_index] = val; @@ -1529,6 +1517,12 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; break; + case 0xC8: + case 0xC9: + case 0xCB: + chips->ext_regs[chips->ext_index] = val; + svga_recalctimings(&chips->svga); + break; case 0xD2: break; default: @@ -1575,6 +1569,14 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) val <<= 2; svga->fullchange = svga->monitor->mon_changeframecount; switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; case 2: index = svga->dac_addr & 7; chips->cursor_palette[index].r = svga->dac_r; @@ -2153,44 +2155,49 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) { chips_69000_t *chips = (chips_69000_t *) svga->priv; uint64_t dat[2]; - int offset = svga->hwcursor_latch.x; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; +#if 0 if ((chips->ext_regs[0xA0] & 7) == 1) { + uint32_t oddaddr = (displine - svga->hwcursor_latch.y) & 1; + uint32_t dat_32[2]; if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + svga->hwcursor_latch.addr += oddaddr ? 8 : 4; - dat[0] = *(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr]); - dat[1] = *(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8]); - svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + dat_32[1] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat_32[0] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += oddaddr ? 4 : 8; for (uint8_t x = 0; x < 32; x++) { - if (!(dat[1] & (1ULL << 31))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 31)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); - else if (dat[0] & (1ULL << 31)) + if (!(dat_32[1] & (1ULL << 31))) + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat_32[0] & (1ULL << 31)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); + else if (dat_32[0] & (1ULL << 31)) svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; offset++; - dat[0] <<= 1; - dat[1] <<= 1; + dat_32[0] <<= 1; + dat_32[1] <<= 1; } if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += (svga->hwcursor_on & 1) ? 8 : 4; + svga->hwcursor_latch.addr += oddaddr ? 8 : 4; return; } +#endif if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += (chips->ext_regs[0xA0] & 7) == 1 ? 8 : 16; + svga->hwcursor_latch.addr += 16; - dat[0] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr]); - dat[1] = *(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8]); + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); svga->hwcursor_latch.addr += 16; switch (chips->ext_regs[0xa0] & 7) { + case 0b1: case 0b101: for (uint8_t x = 0; x < 64; x++) { if (!(dat[1] & (1ULL << 63))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[1]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[0]); + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); else if (dat[0] & (1ULL << 63)) svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; @@ -2208,6 +2215,51 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += 16; } +static float +chips_69000_getclock(int clock, void *priv) +{ + const chips_69000_t *chips = (chips_69000_t *) priv; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + + int m = chips->ext_regs[0xc8]; + int n = chips->ext_regs[0xc9]; + int pl = (chips->ext_regs[0xcb] >> 4) & 7; + + float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); + if (chips->ext_regs[0xcb] & 4) + fvco *= 4.0; + float fo = fvco / (float)(1 << pl); + + return fo; +} + +uint32_t +chips_69000_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + uint32_t ret = 0x00000000; + + if (svga->lut_map) { + if (bpp == 15) { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 2]); + uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 7]); + ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b); + } else { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 3]); + uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 8]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } + } else + ret = (bpp == 15) ? video_15to32[color] : video_16to32[color]; + + return ret; +} + static void * chips_69000_init(const device_t *info) { @@ -2236,6 +2288,8 @@ chips_69000_init(const device_t *info) chips->svga.recalctimings_ex = chips_69000_recalctimings; chips->svga.vblank_start = chips_69000_vblank_start; chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; + chips->svga.getclock = chips_69000_getclock; + chips->svga.conv_16to32 = chips_69000_conv_16to32; mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); From 395941aa54a30aaba1709f3db42ac67c2f9f2abf Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Feb 2024 02:07:49 +0600 Subject: [PATCH 36/52] HWCursor work --- src/video/vid_c&t_69000.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 60afb8d65..df41e9095 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -207,6 +207,8 @@ chips_69000_read_flat_panel(chips_69000_t* chips) case 0: /* Report no presence of flat panel module. */ return 0; + case 1: + return 1; default: return chips->flat_panel_regs[chips->flat_panel_index]; } @@ -745,6 +747,10 @@ chips_69000_recalctimings(svga_t *svga) svga->interlace = !!(svga->crtc[0x70] & 0x80); + if (svga->dispend == 2002 && svga->hdisp == 1024) { + svga->dispend = 1280; + } + switch (chips->ext_regs[0x81] & 0xF) { case 0b0010: svga->bpp = 8; @@ -1413,6 +1419,9 @@ chips_69000_read_ext_reg(chips_69000_t* chips) case 0x71: val = 0x0; break; + case 0xD0: + val |= 1; + break; } // if (chips->ext_index != 0x4E && chips->ext_index != 0x4F // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) @@ -2189,13 +2198,21 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; - dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); - dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); - svga->hwcursor_latch.addr += 16; + if ((svga->hwcursor_on & 1) && (chips->ext_regs[0xa0] & 7) == 0b1) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr - 16])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[(svga->hwcursor_latch.addr - 16) + 8])); + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } + else { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + } switch (chips->ext_regs[0xa0] & 7) { case 0b1: case 0b101: - for (uint8_t x = 0; x < 64; x++) { + for (uint8_t x = 0; x < (((chips->ext_regs[0xa0] & 7) == 0b1) ? 32 : 64); x++) { if (!(dat[1] & (1ULL << 63))) svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); else if (dat[0] & (1ULL << 63)) From a0078e6d2b6e915afd15edb633f5812904dfb52d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Feb 2024 13:22:01 +0600 Subject: [PATCH 37/52] Fix inverted hardware cursor color --- src/video/vid_c&t_69000.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index df41e9095..8128c8086 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1157,6 +1157,10 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } return; } + + if (chips->bitblt_running.x_dir == -1 && chips->bitblt_running.bytes_per_pixel == 3) { + //chips->bitblt_running.actual_destination_width++; + } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { uint32_t source_addr = chips->bitblt_running.bitblt.source_addr; @@ -2168,14 +2172,12 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) #if 0 if ((chips->ext_regs[0xA0] & 7) == 1) { - uint32_t oddaddr = (displine - svga->hwcursor_latch.y) & 1; + uint32_t evenline = svga->hwcursor_latch.cur_ysize - ((svga->hwcursor_on) & ~1) >> 1; uint32_t dat_32[2]; - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += oddaddr ? 8 : 4; - dat_32[1] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr])); - dat_32[0] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); - svga->hwcursor_latch.addr += oddaddr ? 4 : 8; + dat_32[1] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + (((displine - svga->hwcursor_latch.y) & 1) ? 4 : 0)])); + dat_32[0] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8 + (((displine - svga->hwcursor_latch.y) & 1) ? 4 : 0)])); + svga->hwcursor_latch.addr = svga->hwcursor.addr + (evenline * 16); for (uint8_t x = 0; x < 32; x++) { if (!(dat_32[1] & (1ULL << 31))) @@ -2188,9 +2190,6 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) dat_32[1] <<= 1; } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += oddaddr ? 8 : 4; - return; } #endif @@ -2214,7 +2213,7 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) case 0b101: for (uint8_t x = 0; x < (((chips->ext_regs[0xa0] & 7) == 0b1) ? 32 : 64); x++) { if (!(dat[1] & (1ULL << 63))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); + svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); else if (dat[0] & (1ULL << 63)) svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; From 4a087b81c64f0d5195127367ccf9d620799bcd28 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Feb 2024 15:51:15 +0600 Subject: [PATCH 38/52] Fix RTL BitBlt on 16+ bpp --- src/video/vid_c&t_69000.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 8128c8086..2e11764d9 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1128,6 +1128,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 1: chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = 1; + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); break; case 2: chips->bitblt_running.x_dir = 1; @@ -1136,6 +1138,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 3: chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = -1; + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); break; } @@ -1517,18 +1521,26 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0xA4: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.x = val | (chips->ext_regs[0xA5] & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; break; case 0xA5: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.x = chips->ext_regs[0xA4] | (val & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; break; case 0xA6: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.y = val | (chips->ext_regs[0xA7] & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; break; case 0xA7: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; break; case 0xC8: case 0xC9: @@ -2213,9 +2225,9 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) case 0b101: for (uint8_t x = 0; x < (((chips->ext_regs[0xa0] & 7) == 0b1) ? 32 : 64); x++) { if (!(dat[1] & (1ULL << 63))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); else if (dat[0] & (1ULL << 63)) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; offset++; dat[0] <<= 1; From 3e098b190e25553f4a4491660bcc0fd1a48a51ca Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 8 Feb 2024 16:08:05 +0600 Subject: [PATCH 39/52] HW cursor position fixing --- src/video/vid_c&t_69000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 2e11764d9..4f8254477 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -1533,8 +1533,10 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0xA6: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.y = val | (chips->ext_regs[0xA7] & 7) << 8; - if (chips->ext_regs[0xA7] & 0x80) - chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + if (chips->ext_regs[0xA7] & 0x80) { + chips->svga.hwcursor.yoff = chips->svga.hwcursor.y; + chips->svga.hwcursor.y = 0; + } break; case 0xA7: chips->ext_regs[chips->ext_index] = val; From da3203a6c10c48426d1296a7abaf2a74da3878c2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 Feb 2024 00:20:59 +0600 Subject: [PATCH 40/52] Force interlace to be off at 1280x1024 --- src/video/vid_c&t_69000.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 4f8254477..cbfb7b6d6 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -747,8 +747,8 @@ chips_69000_recalctimings(svga_t *svga) svga->interlace = !!(svga->crtc[0x70] & 0x80); - if (svga->dispend == 2002 && svga->hdisp == 1024) { - svga->dispend = 1280; + if (svga->hdisp == 1280 && svga->dispend == 1024) { + svga->interlace = 0; } switch (chips->ext_regs[0x81] & 0xF) { @@ -1541,8 +1541,10 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) case 0xA7: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; - if (chips->ext_regs[0xA7] & 0x80) - chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + if (chips->ext_regs[0xA7] & 0x80){ + chips->svga.hwcursor.yoff = chips->svga.hwcursor.y; + chips->svga.hwcursor.y = 0; + } break; case 0xC8: case 0xC9: From d646efc2888fdf9aedff7450d33507634b08f616 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 9 Feb 2024 12:44:43 +0600 Subject: [PATCH 41/52] Fix hardware cursor in interlaced modes Report 1280*1024 Dual Scan STN Color Panel for now --- src/video/vid_c&t_69000.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index cbfb7b6d6..9968e5205 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -209,6 +209,8 @@ chips_69000_read_flat_panel(chips_69000_t* chips) return 0; case 1: return 1; + case 0x10: + return 1; default: return chips->flat_panel_regs[chips->flat_panel_index]; } @@ -1425,7 +1427,7 @@ chips_69000_read_ext_reg(chips_69000_t* chips) val = 0x3; break; case 0x71: - val = 0x0; + val = 0b01101000; break; case 0xD0: val |= 1; @@ -2186,29 +2188,26 @@ chips_69000_hwcursor_draw(svga_t *svga, int displine) uint64_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; -#if 0 - if ((chips->ext_regs[0xA0] & 7) == 1) { - uint32_t evenline = svga->hwcursor_latch.cur_ysize - ((svga->hwcursor_on) & ~1) >> 1; - uint32_t dat_32[2]; - - dat_32[1] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + (((displine - svga->hwcursor_latch.y) & 1) ? 4 : 0)])); - dat_32[0] = bswap32(*(uint32_t *) (&svga->vram[svga->hwcursor_latch.addr + 8 + (((displine - svga->hwcursor_latch.y) & 1) ? 4 : 0)])); - svga->hwcursor_latch.addr = svga->hwcursor.addr + (evenline * 16); - + if (svga->interlace && (chips->ext_regs[0xa0] & 7) == 0b1) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + if (svga->hwcursor_oddeven) { + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } for (uint8_t x = 0; x < 32; x++) { - if (!(dat_32[1] & (1ULL << 31))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat_32[0] & (1ULL << 31)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[4]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[5]); - else if (dat_32[0] & (1ULL << 31)) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; offset++; - dat_32[0] <<= 1; - dat_32[1] <<= 1; + dat[0] <<= 1; + dat[1] <<= 1; } - return; } -#endif if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -2339,8 +2338,6 @@ chips_69000_init(const device_t *info) chips->flat_panel_regs[0x01] = 1; - sizeof(struct chips_69000_bitblt_t); - return chips; } From 9b4f98cb044befc1f2831d3c7596d9c590c91662 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 11 Feb 2024 11:07:58 +0600 Subject: [PATCH 42/52] Rewritten monochrome source data handling, partially fixes text drawing under Windows 98 SE --- src/video/vid_c&t_69000.c | 334 ++++++++++++++++++-------------------- 1 file changed, 160 insertions(+), 174 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 9968e5205..2935b7085 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -136,13 +136,12 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; uint8_t bytes_skip; + uint8_t mono_bytes_skip; + uint8_t mono_bits_skip_left; + uint8_t mono_bytes_to_skip; uint32_t bytes_counter; uint32_t bytes_in_line_written; uint8_t bytes_port[8]; - - /* Monochrome sources. */ - uint8_t mono_is_first_quadword; - uint8_t mono_bit_cntr; } bitblt_running; union { @@ -933,6 +932,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) ? chips->bitblt_running.bitblt.source_key_bg : chips->bitblt_running.bitblt.pattern_source_key_bg; color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; @@ -966,81 +966,10 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) } void -chips_69000_process_mono_data(UNUSED(chips_69000_t* chips), uint64_t val) +chips_69000_process_mono_bit(chips_69000_t* chips, uint8_t val) { - uint64_t i = 0; - uint8_t is_true = 0; - int orig_x = chips->bitblt_running.x; - int orig_y = chips->bitblt_running.y; - uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; - uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; - - int orig_count_x = chips->bitblt_running.count_x; - int orig_count_y = chips->bitblt_running.count_y; - - chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; - - if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { - source_fg = chips->bitblt_running.bitblt.source_key_fg; - source_bg = chips->bitblt_running.bitblt.source_key_bg; - } - - for (i = 0; i < 64; i++) { - uint32_t pixel = 0x0; - if (chips->bitblt_running.mono_is_first_quadword && (i < chips->bitblt_running.bitblt.monochrome_source_initial_discard)) - goto increment; - - if (i < chips->bitblt_running.bitblt.monochrome_source_left_clip) - goto increment; - - if (i >= (64 - chips->bitblt_running.bitblt.monochrome_source_right_clip)) - goto increment; - - is_true = !!(val & (1 << (i))); - - if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { - goto increment; - } - - pixel = is_true ? source_fg : source_bg; - pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - - chips->bitblt_running.x = orig_x + (chips->bitblt_running.count_x); - chips->bitblt_running.y = orig_y + chips->bitblt_running.count_y; - - if ((orig_count_x + (chips->bitblt_running.count_x)) < chips->bitblt_running.actual_destination_width - && (orig_count_y + chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height) - chips_69000_process_pixel(chips, pixel); - -increment: - chips->bitblt_running.count_x++; - if (chips->bitblt_running.count_x == 8) { - chips->bitblt_running.count_x = 0; - chips->bitblt_running.count_y++; - } - } - chips->bitblt_running.x = orig_x; - chips->bitblt_running.y = orig_y; - chips->bitblt_running.count_x = orig_count_x; - chips->bitblt_running.count_y = orig_count_y; - chips->bitblt_running.x += chips->bitblt_running.x_dir * 8; - chips->bitblt_running.count_x += 8; - chips->bitblt_running.mono_is_first_quadword = 0; - if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { - chips->bitblt_running.count_y += 8; - chips->bitblt_running.y += chips->bitblt_running.y_dir * 8; - chips->bitblt_running.count_x = 0; - if (chips->bitblt_running.count_y > chips->bitblt_running.actual_destination_height) - chips_69000_bitblt_interrupt(chips); - } -} - -void -chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t val) -{ - uint64_t i = 0; - uint8_t is_true = 0; - int orig_x = chips->bitblt_running.x; + uint32_t pixel = 0x0; + uint8_t is_true = !!val; uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; @@ -1049,46 +978,35 @@ chips_69000_process_mono_data_non_qword(UNUSED(chips_69000_t* chips), uint8_t va source_bg = chips->bitblt_running.bitblt.source_key_bg; } - for (i = chips->bitblt_running.mono_bit_cntr; i < (chips->bitblt_running.mono_bit_cntr + 8); i++) { - uint32_t pixel = 0x0; - - if (chips->bitblt_running.mono_is_first_quadword && (i < chips->bitblt_running.bitblt.monochrome_source_initial_discard)) - continue; - - if (i < chips->bitblt_running.bitblt.monochrome_source_left_clip) - continue; - - if (i >= (64 - chips->bitblt_running.bitblt.monochrome_source_right_clip)) - continue; - - is_true = !!(val & (1 << (7 - (i & 7)))); - - if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { - continue; - } - - pixel = is_true ? source_fg : source_bg; - pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - - chips->bitblt_running.x = (orig_x + (i & 7) * chips->bitblt_running.x_dir); - - if ((chips->bitblt_running.count_x + (i & 7)) < chips->bitblt_running.actual_destination_width) - chips_69000_process_pixel(chips, pixel); + if (chips->bitblt_running.bitblt.monochrome_source_initial_discard) { + chips->bitblt_running.bitblt.monochrome_source_initial_discard--; + return; } - chips->bitblt_running.mono_bit_cntr += 8; - chips->bitblt_running.x = orig_x; - chips->bitblt_running.x += chips->bitblt_running.x_dir * 8; - chips->bitblt_running.count_x += 8; - if (chips->bitblt_running.mono_bit_cntr >= 64) { - chips->bitblt_running.mono_is_first_quadword = 0; - chips->bitblt_running.mono_bit_cntr = 0; + + if (chips->bitblt_running.mono_bits_skip_left) { + chips->bitblt_running.mono_bits_skip_left--; + return; } + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { + goto advance; + } + pixel = is_true ? source_fg : source_bg; + pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + chips_69000_process_pixel(chips, pixel); + +advance: + chips->bitblt_running.x += chips->bitblt_running.x_dir; + chips->bitblt_running.count_x += 1; if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { chips->bitblt_running.count_y += 1; chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; - if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) + chips->bitblt_running.mono_bytes_to_skip = chips->bitblt_running.mono_bytes_skip; + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + if (chips->bitblt_running.count_y >= (chips->bitblt_running.actual_destination_height)) chips_69000_bitblt_interrupt(chips); } } @@ -1099,18 +1017,25 @@ void chips_69000_setup_bitblt(chips_69000_t* chips) { chips->engine_active = 1; + + memset(&chips->bitblt_running, 0, sizeof(chips->bitblt_running)); + chips->bitblt_running.bitblt = chips->bitblt; chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; chips->bitblt_running.bytes_written = 0; chips->bitblt_running.bytes_counter = 0; - chips->bitblt_running.mono_is_first_quadword = 1; - chips->bitblt_running.mono_bit_cntr = 0; chips->bitblt_running.bytes_in_line_written = 0; chips->bitblt_running.bytes_skip = 0; + chips->bitblt_running.mono_bytes_skip = 0; + chips->bitblt_running.mono_bytes_to_skip = 0; + chips->bitblt_running.mono_bits_skip_left = 0; int orig_cycles = cycles; + if (chips->bitblt_running.bitblt.source_span != chips->bitblt_running.bitblt.destination_span) + pclog("source_span = %d, destination_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); + if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); } else { @@ -1152,6 +1077,19 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips_69000_bitblt_interrupt(chips); return; } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " + "monochrome left clip = %d, " + "monochrome right clip = %d, " + "monochrome initial discard = %d, " + "destination_width = %d, destination_height = %d)\n", chips->bitblt_running.bitblt.monochrome_source_alignment, + chips->bitblt_running.bitblt.monochrome_source_left_clip, + chips->bitblt_running.bitblt.monochrome_source_right_clip, + chips->bitblt_running.bitblt.monochrome_source_initial_discard, + chips->bitblt_running.bitblt.destination_width, + chips->bitblt_running.bitblt.destination_height); + } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { @@ -1160,26 +1098,18 @@ chips_69000_setup_bitblt(chips_69000_t* chips) */ if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); + } else { + chips->bitblt_running.mono_bytes_skip = (chips->bitblt_running.actual_destination_width <= 32 + && chips->bitblt_running.bitblt.monochrome_source_alignment == 0 + && chips->bitblt_running.actual_destination_width > 16) ? 4 : 0; + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; } + return; } - - if (chips->bitblt_running.x_dir == -1 && chips->bitblt_running.bytes_per_pixel == 3) { - //chips->bitblt_running.actual_destination_width++; - } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { uint32_t source_addr = chips->bitblt_running.bitblt.source_addr; - pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " - "monochrome left clip = %d, " - "monochrome right clip = %d, " - "monochrome initial discard = %d, " - "destination_width = %d, destination_height = %d\n", chips->bitblt_running.bitblt.monochrome_source_alignment, - chips->bitblt_running.bitblt.monochrome_source_left_clip, - chips->bitblt_running.bitblt.monochrome_source_right_clip, - chips->bitblt_running.bitblt.monochrome_source_initial_discard, - chips->bitblt_running.bitblt.destination_width, - chips->bitblt_running.bitblt.destination_height); while (chips->engine_active) { switch (chips->bitblt_running.bitblt.monochrome_source_alignment) { @@ -1200,6 +1130,13 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.source_addr = source_addr; break; } + case 2: /* Byte-aligned */ + { + uint32_t data = chips_69000_readb_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + source_addr += 1; + break; + } case 4: /* Doubleword-aligned*/ { uint32_t data = chips_69000_readl_linear(source_addr, chips); @@ -1226,6 +1163,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } } } + return; } do { @@ -1276,54 +1214,75 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { int orig_cycles = cycles; + if (chips->bitblt_running.mono_bytes_to_skip) { + chips->bitblt_running.mono_bytes_to_skip--; + return; + } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; - if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint8_t val = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 3 && chips->bitblt_running.bytes_written == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint16_t val = (chips->bitblt_running.bytes_port[1]) | (chips->bitblt_running.bytes_port[0] << 8); chips->bitblt_running.bytes_written = 0; - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); - if (chips->bitblt_running.actual_destination_width > 8) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); + + for (i = 0; i < 16; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (15 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 && chips->bitblt_running.bytes_written == 4) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint32_t val = chips->bitblt_running.bytes_port[3] | (chips->bitblt_running.bytes_port[2] << 8) | (chips->bitblt_running.bytes_port[1] << 16) | (chips->bitblt_running.bytes_port[0] << 24); chips->bitblt_running.bytes_written = 0; - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); - if (chips->bitblt_running.actual_destination_width > 8) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); - if (chips->bitblt_running.actual_destination_width > 16) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[2]); - if (chips->bitblt_running.actual_destination_width > 24) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[3]); + + for (i = 0; i < 32; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (31 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5 && chips->bitblt_running.bytes_written == 8) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint64_t val = 0; + + val |= chips->bitblt_running.bytes_port[7]; + val |= chips->bitblt_running.bytes_port[6] << 8; + val |= chips->bitblt_running.bytes_port[5] << 16; + val |= chips->bitblt_running.bytes_port[4] << 24; + val |= (uint64_t)chips->bitblt_running.bytes_port[3] << 32ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[2] << 40ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[1] << 48ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[0] << 56ULL; + chips->bitblt_running.bytes_written = 0; - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[0]); - if (chips->bitblt_running.actual_destination_width > 8) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[1]); - if (chips->bitblt_running.actual_destination_width > 16) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[2]); - if (chips->bitblt_running.actual_destination_width > 24) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[3]); - if (chips->bitblt_running.actual_destination_width > 32) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[4]); - if (chips->bitblt_running.actual_destination_width > 40) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[5]); - if (chips->bitblt_running.actual_destination_width > 48) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[6]); - if (chips->bitblt_running.actual_destination_width > 52) - chips_69000_process_mono_data_non_qword(chips, chips->bitblt_running.bytes_port[7]); - } else if (chips->bitblt_running.bytes_written == 8) { - chips->bitblt_running.bytes_written = 0; - uint64_t mono_data = chips->bitblt_running.bytes_port[0]; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[1] << 8ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[2] << 16ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[3] << 24ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[4] << 32ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[5] << 40ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[6] << 48ull; - mono_data |= (uint64_t)chips->bitblt_running.bytes_port[7] << 56ull; - chips_69000_process_mono_data(chips, mono_data); + + for (i = 0; i < 64; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (63 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } } cycles = orig_cycles; return; @@ -1433,18 +1392,12 @@ chips_69000_read_ext_reg(chips_69000_t* chips) val |= 1; break; } - // if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - // pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val); return val; } void chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) { - // if (chips->ext_index != 0x4E && chips->ext_index != 0x4F - // && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB)) - // pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val); switch (chips->ext_index) { case 0xA: chips->ext_regs[chips->ext_index] = val & 0x37; @@ -1658,9 +1611,11 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) } } break; + case 0x3B6: case 0x3D6: chips->ext_index = val; return; + case 0x3B7: case 0x3D7: return chips_69000_write_ext_reg(chips, val); @@ -1732,9 +1687,11 @@ chips_69000_in(uint16_t addr, void *p) else temp = svga->crtc[svga->crtcreg]; break; + case 0x3B6: case 0x3D6: temp = chips->ext_index; break; + case 0x3B7: case 0x3D7: temp = chips_69000_read_ext_reg(chips); break; @@ -1876,7 +1833,6 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) uint8_t chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) { - //pclog("C&T Read 0x%X\n", addr); addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x28: @@ -1884,6 +1840,10 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); } return chips->bitblt_regs_b[addr & 0xFF]; + case 0x3b: + return (chips->engine_active ? 0x80 : 0x00); + case 0x38: + return (0xFF - chips->ext_regs[0xD2]); case 0x600 ... 0x60F: return chips->mem_regs_b[addr & 0xF]; case 0x768: @@ -1937,7 +1897,7 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) case 0x7B4: return chips_69000_in(0x3da, chips); } - return 0xFF; + return 0x00; } uint16_t @@ -1978,6 +1938,9 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) chips_69000_setup_bitblt(chips); } break; + default: + pclog("C&T Write (unknown) 0x%X, val = 0x%02X\n", addr, val); + break; case 0x600 ... 0x60F: switch (addr & 0xFFF) { @@ -2065,6 +2028,9 @@ void chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) { if (addr & 0x10000) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + pclog("BitBLT mono 0x%04X\n", val); + } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); return; @@ -2083,7 +2049,7 @@ chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { if (addr & 0x10000) { if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { - //pclog("BitBLT mono 0x%08X\n", val); + pclog("BitBLT mono 0x%08X\n", val); } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); @@ -2118,6 +2084,13 @@ chips_69000_readw_linear(uint32_t addr, void *p) svga_t *svga = (svga_t *) p; chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap16(chips_69000_readw_mmio(addr, chips)); + + return bswap16(svga_readw_linear(addr & 0x1FFFFF, p)); + } + if (addr & 0x400000) return chips_69000_readw_mmio(addr, chips); @@ -2130,6 +2103,13 @@ chips_69000_readl_linear(uint32_t addr, void *p) svga_t *svga = (svga_t *) p; chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap32(chips_69000_readl_mmio(addr, chips)); + + return bswap32(svga_readl_linear(addr & 0x1FFFFF, p)); + } + if (addr & 0x400000) return chips_69000_readl_mmio(addr, chips); @@ -2154,6 +2134,9 @@ chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) svga_t *svga = (svga_t *) p; chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (addr & 0x800000) + val = bswap16(val); + if (addr & 0x400000) return chips_69000_writew_mmio(addr, val, chips); @@ -2166,6 +2149,9 @@ chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) svga_t *svga = (svga_t *) p; chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (addr & 0x800000) + val = bswap32(val); + if (addr & 0x400000) return chips_69000_writel_mmio(addr, val, chips); From 376b704ceab0f2edd8326b18500831b99563fb3e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 12 Feb 2024 01:25:27 +0600 Subject: [PATCH 43/52] Fix 16+ bpp text background drawing --- src/video/vid_c&t_69000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 2935b7085..94b5750ce 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -141,7 +141,7 @@ typedef struct chips_69000_t { uint8_t mono_bytes_to_skip; uint32_t bytes_counter; uint32_t bytes_in_line_written; - uint8_t bytes_port[8]; + uint8_t bytes_port[256]; } bitblt_running; union { @@ -1835,7 +1835,7 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) { addr &= 0xFFF; switch (addr & 0xFFF) { - case 0x00 ... 0x28: + case 0x00 ... 0x2B: if (addr == 0x13) { return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); } @@ -1932,7 +1932,7 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) } addr &= 0xFFF; switch (addr & 0xFFF) { - case 0x00 ... 0x28: + case 0x00 ... 0x2B: chips->bitblt_regs_b[addr & 0xFF] = val; if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { chips_69000_setup_bitblt(chips); From 40d7e626fc94e2b47d362f6a38488a7798fe799f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 01:15:53 +0600 Subject: [PATCH 44/52] Fix monochrome blits for real --- src/video/vid_c&t_69000.c | 62 +++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 94b5750ce..697d7d19b 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -137,6 +137,7 @@ typedef struct chips_69000_t { uint8_t bytes_written; uint8_t bytes_skip; uint8_t mono_bytes_skip; + uint32_t mono_bytes_pitch; uint8_t mono_bits_skip_left; uint8_t mono_bytes_to_skip; uint32_t bytes_counter; @@ -973,6 +974,9 @@ chips_69000_process_mono_bit(chips_69000_t* chips, uint8_t val) uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + if (!chips->engine_active) + return; + if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { source_fg = chips->bitblt_running.bitblt.source_key_fg; source_bg = chips->bitblt_running.bitblt.source_key_bg; @@ -1019,7 +1023,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->engine_active = 1; memset(&chips->bitblt_running, 0, sizeof(chips->bitblt_running)); - chips->bitblt_running.bitblt = chips->bitblt; chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; @@ -1029,13 +1032,11 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bytes_in_line_written = 0; chips->bitblt_running.bytes_skip = 0; chips->bitblt_running.mono_bytes_skip = 0; + chips->bitblt_running.mono_bytes_pitch = 0; chips->bitblt_running.mono_bytes_to_skip = 0; chips->bitblt_running.mono_bits_skip_left = 0; int orig_cycles = cycles; - if (chips->bitblt_running.bitblt.source_span != chips->bitblt_running.bitblt.destination_span) - pclog("source_span = %d, destination_span = %d\n", chips->bitblt_running.bitblt.source_span, chips->bitblt_running.bitblt.destination_span); - if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); } else { @@ -1055,7 +1056,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 1: chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = 1; - chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); break; case 2: @@ -1065,7 +1067,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 3: chips->bitblt_running.x_dir = -1; chips->bitblt_running.y_dir = -1; - chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); break; } @@ -1078,6 +1081,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) return; } +#if 0 if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " "monochrome left clip = %d, " @@ -1090,6 +1094,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.destination_width, chips->bitblt_running.bitblt.destination_height); } +#endif if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { @@ -1099,10 +1104,12 @@ chips_69000_setup_bitblt(chips_69000_t* chips) if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); } else { - chips->bitblt_running.mono_bytes_skip = (chips->bitblt_running.actual_destination_width <= 32 - && chips->bitblt_running.bitblt.monochrome_source_alignment == 0 - && chips->bitblt_running.actual_destination_width > 16) ? 4 : 0; + chips->bitblt_running.mono_bytes_skip = 0; chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + + if (!chips->bitblt_running.mono_bytes_skip && chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { + chips->bitblt_running.mono_bytes_pitch = ((chips->bitblt_running.actual_destination_width + chips->bitblt_running.bitblt.monochrome_source_left_clip + 63) & ~63) / 8; + } } return; @@ -1119,9 +1126,15 @@ chips_69000_setup_bitblt(chips_69000_t* chips) uint32_t orig_count_y = chips->bitblt_running.count_y; uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; while (orig_count_y == chips->bitblt_running.count_y) { + int i = 0; uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); orig_source_addr++; - chips_69000_bitblt_write(chips, data & 0xFF); + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(data & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + break; + } + } if ((source_addr + chips->bitblt_running.bitblt.source_span) == orig_source_addr) break; } @@ -1219,7 +1232,23 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { return; } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; - if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && chips->bitblt_running.mono_bytes_pitch && chips->bitblt_running.mono_bytes_pitch == chips->bitblt_running.bytes_written) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0, j = 0; + uint8_t val = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + + for (j = 0; j < chips->bitblt_running.mono_bytes_pitch; j++) { + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(chips->bitblt_running.bytes_port[j] & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } + } + else if ((chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && !chips->bitblt_running.mono_bytes_pitch) || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { int orig_count_y = chips->bitblt_running.count_y; int i = 0; uint8_t val = chips->bitblt_running.bytes_port[0]; @@ -1289,7 +1318,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_counter++; - if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr)) { + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) { return; } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; @@ -1843,7 +1872,7 @@ chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) case 0x3b: return (chips->engine_active ? 0x80 : 0x00); case 0x38: - return (0xFF - chips->ext_regs[0xD2]); + return 0x7F; case 0x600 ... 0x60F: return chips->mem_regs_b[addr & 0xF]; case 0x768: @@ -1933,6 +1962,9 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) addr &= 0xFFF; switch (addr & 0xFFF) { case 0x00 ... 0x2B: + if (addr <= 0x3) { + //pclog("[%04X:%08X] C&T Write span 0x%X, val = 0x%02X\n", CS, cpu_state.pc, addr, val); + } chips->bitblt_regs_b[addr & 0xFF] = val; if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { chips_69000_setup_bitblt(chips); @@ -2029,7 +2061,7 @@ chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) { if (addr & 0x10000) { if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { - pclog("BitBLT mono 0x%04X\n", val); + //pclog("BitBLT mono 0x%04X\n", val); } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); @@ -2049,7 +2081,7 @@ chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) { if (addr & 0x10000) { if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { - pclog("BitBLT mono 0x%08X\n", val); + //pclog("BitBLT mono 0x%08X\n", val); } chips_69000_bitblt_write(chips, val & 0xFF); chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); From 62135c5c8a4096d1f4feeb93b29094b5576d5560 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 01:28:14 +0600 Subject: [PATCH 45/52] Minor cleanup --- src/video/vid_c&t_69000.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 697d7d19b..973502f55 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -136,10 +136,8 @@ typedef struct chips_69000_t { /* Byte counter for BitBLT port writes. */ uint8_t bytes_written; uint8_t bytes_skip; - uint8_t mono_bytes_skip; uint32_t mono_bytes_pitch; uint8_t mono_bits_skip_left; - uint8_t mono_bytes_to_skip; uint32_t bytes_counter; uint32_t bytes_in_line_written; uint8_t bytes_port[256]; @@ -1008,7 +1006,6 @@ advance: chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; - chips->bitblt_running.mono_bytes_to_skip = chips->bitblt_running.mono_bytes_skip; chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; if (chips->bitblt_running.count_y >= (chips->bitblt_running.actual_destination_height)) chips_69000_bitblt_interrupt(chips); @@ -1031,9 +1028,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bytes_counter = 0; chips->bitblt_running.bytes_in_line_written = 0; chips->bitblt_running.bytes_skip = 0; - chips->bitblt_running.mono_bytes_skip = 0; chips->bitblt_running.mono_bytes_pitch = 0; - chips->bitblt_running.mono_bytes_to_skip = 0; chips->bitblt_running.mono_bits_skip_left = 0; int orig_cycles = cycles; @@ -1104,10 +1099,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); } else { - chips->bitblt_running.mono_bytes_skip = 0; chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; - if (!chips->bitblt_running.mono_bytes_skip && chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { chips->bitblt_running.mono_bytes_pitch = ((chips->bitblt_running.actual_destination_width + chips->bitblt_running.bitblt.monochrome_source_left_clip + 63) & ~63) / 8; } } @@ -1227,10 +1221,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { int orig_cycles = cycles; - if (chips->bitblt_running.mono_bytes_to_skip) { - chips->bitblt_running.mono_bytes_to_skip--; - return; - } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && chips->bitblt_running.mono_bytes_pitch && chips->bitblt_running.mono_bytes_pitch == chips->bitblt_running.bytes_written) { int orig_count_y = chips->bitblt_running.count_y; From 6e35d009420739e2acd29c5f77fa55dd1ef758c4 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 01:49:43 +0600 Subject: [PATCH 46/52] Gamma correction support --- src/video/vid_c&t_69000.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 973502f55..6f41ba2df 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -752,6 +752,9 @@ chips_69000_recalctimings(svga_t *svga) } switch (chips->ext_regs[0x81] & 0xF) { + default: + svga->bpp = 8; + break; case 0b0010: svga->bpp = 8; svga->render = svga_render_8bpp_highres; @@ -1479,6 +1482,10 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) chips->ext_regs[chips->ext_index] = val & 0x1f; svga_recalctimings(&chips->svga); break; + case 0x82: + chips->ext_regs[chips->ext_index] = val & 0xf; + chips->svga.lut_map = !!(val & 0x8); + break; case 0xA0: chips->ext_regs[chips->ext_index] = val; chips->svga.hwcursor.ena = ((val & 7) == 0b101) || ((val & 7) == 0b1); From afa545ca25f164ba6ccffb271306b4791d441288 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 01:57:54 +0600 Subject: [PATCH 47/52] Bit-depth fixes --- src/video/vid_c&t_69000.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 6f41ba2df..273c5de5c 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -777,6 +777,8 @@ chips_69000_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } + } else { + svga->bpp = 8; } } From fd33034915f36824d6d5c7ea60d9dc6c04895077 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 11:42:15 +0600 Subject: [PATCH 48/52] 1600x1200 resolution fixes Fix source address behaviour properly --- src/video/vid_c&t_69000.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 273c5de5c..0118bcd1f 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -15,6 +15,7 @@ * Copyright 2023-2024 Cacodemon345 */ #include +#include #include #include #include @@ -90,8 +91,8 @@ typedef struct chips_69000_t { uint8_t pci_line_interrupt; uint8_t pci_rom_enable; uint8_t read_write_bank; - atomic_bool engine_active; - atomic_bool quit; + bool engine_active; + bool quit; thread_t *accel_thread; event_t *fifo_event, *fifo_data_event; pc_timer_t decrement_timer; @@ -1095,8 +1096,9 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.destination_height); } #endif - + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + chips->bitblt_running.bitblt.source_addr &= 7; if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { /* Yes, the NT 4.0 and Linux drivers will send this many amount of bytes to the video adapter on quadword-boundary-crossing image blits. This weird calculation is intended and deliberate. @@ -1121,6 +1123,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) switch (chips->bitblt_running.bitblt.monochrome_source_alignment) { case 0: /* Source-span aligned. */ { + /* Note: This value means quadword-alignment when BitBLT port is the source. */ /* TODO: This is handled purely on a best case basis. */ uint32_t orig_count_y = chips->bitblt_running.count_y; uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; @@ -1142,6 +1145,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bitblt.source_addr = source_addr; break; } + case 1: /* Bit-aligned */ case 2: /* Byte-aligned */ { uint32_t data = chips_69000_readb_linear(source_addr, chips); @@ -1149,6 +1153,14 @@ chips_69000_setup_bitblt(chips_69000_t* chips) source_addr += 1; break; } + case 3: /* Word-aligned*/ + { + uint32_t data = chips_69000_readw_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + source_addr += 2; + break; + } case 4: /* Doubleword-aligned*/ { uint32_t data = chips_69000_readl_linear(source_addr, chips); @@ -1243,7 +1255,9 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } } } - else if ((chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && !chips->bitblt_running.mono_bytes_pitch) || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { + else if ((chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && !chips->bitblt_running.mono_bytes_pitch) + || chips->bitblt_running.bitblt.monochrome_source_alignment == 2 + || chips->bitblt_running.bitblt.monochrome_source_alignment == 1) { int orig_count_y = chips->bitblt_running.count_y; int i = 0; uint8_t val = chips->bitblt_running.bytes_port[0]; @@ -1251,7 +1265,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); - if (orig_count_y != chips->bitblt_running.count_y) { + if (orig_count_y != chips->bitblt_running.count_y && chips->bitblt_running.bitblt.monochrome_source_alignment != 1) { cycles = orig_cycles; return; } @@ -1313,7 +1327,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_counter++; - if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr & 7)) { + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr)) { return; } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; @@ -2308,6 +2322,16 @@ chips_69000_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) return ret; } +static int +chips_69000_line_compare(svga_t* svga) +{ + /* Line compare glitches out at 1600x1200 and above. Disable it. */ + if (svga->dispend >= 1200) + return 0; + + return 1; +} + static void * chips_69000_init(const device_t *info) { @@ -2338,6 +2362,7 @@ chips_69000_init(const device_t *info) chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; chips->svga.getclock = chips_69000_getclock; chips->svga.conv_16to32 = chips_69000_conv_16to32; + chips->svga.line_compare = chips_69000_line_compare; mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); From b95139033c77702814ae0c3e99c37eed87df3284 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 11:45:28 +0600 Subject: [PATCH 49/52] Timing and name changes --- src/video/vid_c&t_69000.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index 0118bcd1f..bbf1cfb3a 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -161,7 +161,8 @@ typedef struct chips_69000_t { uint8_t st01; } chips_69000_t; -static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; +/* TODO: Probe timings on real hardware. */ +static video_timings_t timing_chips = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; uint8_t chips_69000_readb_linear(uint32_t addr, void *p); uint16_t chips_69000_readw_linear(uint32_t addr, void *p); @@ -1567,7 +1568,6 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - // if (!(addr == 0x3CC || addr == 0x3C9)) pclog("SiS SVGA out: 0x%X, 0x%X\n", addr, val); switch (addr) { case 0x3c0: if (!(chips->ext_regs[0x09] & 0x02)) @@ -1675,7 +1675,6 @@ chips_69000_in(uint16_t addr, void *p) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - // if (!(addr == 0x3CC || addr == 0x3C9)) pclog("SiS SVGA in: 0x%X\n", addr); switch (addr) { case 0x3C5: return svga->seqregs[svga->seqaddr]; @@ -2343,7 +2342,7 @@ chips_69000_init(const device_t *info) mem_mapping_disable(&chips->bios_rom.mapping); } - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_sis); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_chips); svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ chips_69000_recalctimings, @@ -2421,7 +2420,7 @@ chips_69000_force_redraw(void *p) } const device_t chips_69000_device = { - .name = "Chips & Technologies 69000", + .name = "Chips & Technologies B69000", .internal_name = "c&t_69000", .flags = DEVICE_PCI, .local = 0, @@ -2435,7 +2434,7 @@ const device_t chips_69000_device = { }; const device_t chips_69000_onboard_device = { - .name = "Chips & Technologies 69000 (onboard)", + .name = "Chips & Technologies B69000 (onboard)", .internal_name = "c&t_69000_onboard", .flags = DEVICE_PCI, .local = 1, From baac839d892bfd7dea0fa0c14734f00d0f10bdae Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 17:04:53 +0600 Subject: [PATCH 50/52] Unused variables cleanup --- src/video/vid_c&t_69000.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/video/vid_c&t_69000.c b/src/video/vid_c&t_69000.c index bbf1cfb3a..b15546a69 100644 --- a/src/video/vid_c&t_69000.c +++ b/src/video/vid_c&t_69000.c @@ -820,8 +820,6 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) uint32_t pattern_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; uint32_t pattern_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; uint8_t pattern_data = 0; - uint8_t pattern_data_8bpp[8][8]; - uint16_t pattern_data_16bpp[8][8]; uint32_t pattern_pixel = 0; uint32_t dest_pixel = 0; uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt_running.bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); @@ -1243,7 +1241,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && chips->bitblt_running.mono_bytes_pitch && chips->bitblt_running.mono_bytes_pitch == chips->bitblt_running.bytes_written) { int orig_count_y = chips->bitblt_running.count_y; int i = 0, j = 0; - uint8_t val = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; for (j = 0; j < chips->bitblt_running.mono_bytes_pitch; j++) { From 8ed622f67b681fe08b864609c772785e64bdda97 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 17:06:10 +0600 Subject: [PATCH 51/52] Move extern into video.h (part 1) --- src/include/86box/video.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 9e15a5cf9..47d237b10 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -579,6 +579,7 @@ extern const device_t wy700_device; /* Chips & Technologies */ extern const device_t chips_69000_device; +extern const device_t chips_69000_onboard_device; #endif From 49ab582234bb3589c1d3f9fee05547e154bfcc43 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 13 Feb 2024 17:07:19 +0600 Subject: [PATCH 52/52] Move extern into video.h (part 2) --- src/machine/m_at_socket370.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 8344e6b8f..dce0034ff 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -355,7 +355,6 @@ machine_at_awo671r_init(const machine_t *model) device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); if (gfxcard[0] == VID_INTERNAL) { - extern const device_t chips_69000_onboard_device; device_add(&chips_69000_onboard_device); } spd_register(SPD_TYPE_SDRAM, 0x3, 256);