From e29dafa17a56f58c3d91b16ecd23618b88ca2de0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 18 Nov 2021 23:58:04 +0100 Subject: [PATCH] Changes list 5: Added the AT&T 2xc498 Precision RAMDAC. Added 1MB configurations to the Cirrus Logic GD5434 as well as re-organized the memory size options of the other Cirrus cards. Separated the et4000w32/i blitter from the standard et4000w32p blitter and properly implemented the X/Y Count route. Added several Diamond Cirrus cards. Added Number Nine S3 cards (868 and 968-based). Fixed the WD90c30 1MB modes. Re-organized the video card names. --- src/include/86box/vid_svga.h | 3 + src/include/86box/video.h | 10 +- src/video/CMakeLists.txt | 2 +- src/video/vid_att2xc498_ramdac.c | 186 ++++++ src/video/vid_cl54xx.c | 476 +++++++++---- src/video/vid_et4000w32.c | 1063 ++++++++++++++++++++++-------- src/video/vid_paradise.c | 378 +++++++---- src/video/vid_s3.c | 193 ++++-- src/video/vid_table.c | 24 +- src/win/Makefile.mingw | 1 + 10 files changed, 1747 insertions(+), 589 deletions(-) create mode 100644 src/video/vid_att2xc498_ramdac.c diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 9022a4a86..4380e041b 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -226,6 +226,8 @@ extern void ati68860_hwcursor_draw(svga_t *svga, int displine); extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t att498_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); extern float av9194_getclock(int clock, void *p); extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga); @@ -278,6 +280,7 @@ extern const device_t ati68860_ramdac_device; extern const device_t att490_ramdac_device; extern const device_t att491_ramdac_device; extern const device_t att492_ramdac_device; +extern const device_t att498_ramdac_device; extern const device_t av9194_device; extern const device_t bt484_ramdac_device; extern const device_t att20c504_ramdac_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 166770154..3e0c74ce9 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -226,24 +226,28 @@ extern const device_t compaq_ati28800_device; extern const device_t ati28800_wonderxl24_device; #endif -/* Cirrus Logic CL-GD 54xx */ +/* Cirrus Logic GD54xx */ extern const device_t gd5401_isa_device; extern const device_t gd5402_isa_device; extern const device_t gd5402_onboard_device; extern const device_t gd5420_isa_device; extern const device_t gd5422_isa_device; extern const device_t gd5424_vlb_device; +extern const device_t gd5426_isa_device; +extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device; extern const device_t gd5426_vlb_device; extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; extern const device_t gd5428_vlb_device; +extern const device_t gd5428_diamond_speedstar_pro_b1_vlb_device; extern const device_t gd5428_mca_device; extern const device_t gd5428_onboard_device; extern const device_t gd5429_isa_device; extern const device_t gd5429_vlb_device; -extern const device_t gd5430_vlb_device; +extern const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device; extern const device_t gd5430_pci_device; extern const device_t gd5434_isa_device; +extern const device_t gd5434_diamond_speedstar_64_a3_isa_device; extern const device_t gd5434_onboard_pci_device; extern const device_t gd5434_vlb_device; extern const device_t gd5434_pci_device; @@ -369,6 +373,7 @@ extern const device_t s3_mirocrystal_20sv_964_pci_device; extern const device_t s3_mirocrystal_20sd_864_vlb_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; +extern const device_t s3_9fx_531_pci_device; extern const device_t s3_phoenix_vision868_pci_device; extern const device_t s3_phoenix_vision868_vlb_device; extern const device_t s3_diamond_stealth64_pci_device; @@ -376,6 +381,7 @@ extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; extern const device_t s3_mirovideo_40sv_ergo_968_pci_device; +extern const device_t s3_9fx_771_pci_device; extern const device_t s3_phoenix_vision968_pci_device; extern const device_t s3_phoenix_vision968_vlb_device; extern const device_t s3_spea_mercury_p64v_pci_device; diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 0c3befa62..b42bd21cb 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -24,7 +24,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.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_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c) if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) diff --git a/src/video/vid_att2xc498_ramdac.c b/src/video/vid_att2xc498_ramdac.c new file mode 100644 index 000000000..747ffe75c --- /dev/null +++ b/src/video/vid_att2xc498_ramdac.c @@ -0,0 +1,186 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of a AT&T 2xc498 RAMDAC. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> + + +typedef struct +{ + int type; + int state; + int loop; + uint8_t ctrl; +} att498_ramdac_t; + +static void +att498_ramdac_control(uint8_t val, void *p, svga_t *svga) +{ + att498_ramdac_t *ramdac = (att498_ramdac_t *) p; + ramdac->ctrl = val; + + if (val == 0xff) + return; + + switch ((ramdac->ctrl >> 4) & 0x0f) { + default: + svga->bpp = 8; + break; + case 1: + if (ramdac->ctrl & 4) + svga->bpp = 15; + else + svga->bpp = 8; + break; + case 3: + case 6: + svga->bpp = 16; + break; + case 5: + case 7: + svga->bpp = 32; + break; + case 0x0e: + svga->bpp = 24; + break; + } + + svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT); + svga_recalctimings(svga); +} + +void +att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +{ + att498_ramdac_t *ramdac = (att498_ramdac_t *) p; + uint8_t rs = (addr & 0x03); + rs |= ((!!rs2) << 2); + + switch (rs) { + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + svga_out(addr, val, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 4: + att498_ramdac_control(val, ramdac, svga); + break; + default: + svga_out(addr, val, svga); + break; + } + break; + case 0x06: + att498_ramdac_control(val, ramdac, svga); + break; + } +} + + +uint8_t +att498_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +{ + att498_ramdac_t *ramdac = (att498_ramdac_t *) p; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + rs |= ((!!rs2) << 2); + + switch (rs) { + case 0x00: + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x07: + temp = svga_in(addr, svga); + ramdac->state = 0; + break; + case 0x02: + switch (ramdac->state) { + case 4: + temp = ramdac->ctrl; + ramdac->state++; + break; + case 5: + temp = 0x84; + ramdac->state++; + break; + case 6: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + default: + temp = svga_in(addr, svga); + ramdac->state++; + break; + } + break; + case 0x06: + temp = ramdac->ctrl; + ramdac->state = 0; + break; + } + + return temp; +} + + +static void * +att498_ramdac_init(const device_t *info) +{ + att498_ramdac_t *ramdac = (att498_ramdac_t *) malloc(sizeof(att498_ramdac_t)); + memset(ramdac, 0, sizeof(att498_ramdac_t)); + + ramdac->type = info->local; + + return ramdac; +} + + +static void +att498_ramdac_close(void *priv) +{ + att498_ramdac_t *ramdac = (att498_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + + +const device_t att498_ramdac_device = +{ + "AT&T 22c498 RAMDAC", + 0, 0, + att498_ramdac_init, att498_ramdac_close, + NULL, { NULL }, NULL, NULL +}; \ No newline at end of file diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 7ba2efb3c..3055de90a 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -45,13 +45,15 @@ #define BIOS_GD5402_ONBOARD_PATH "roms/machines/cbm_sl386sx25/c000.rom" #define BIOS_GD5420_PATH "roms/video/cirruslogic/5420.vbi" #define BIOS_GD5422_PATH "roms/video/cirruslogic/cl5422.bin" -#define BIOS_GD5426_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" +#define BIOS_GD5426_DIAMOND_A1_ISA_PATH "roms/video/cirruslogic/diamond5426.bin" +#define BIOS_GD5428_DIAMOND_B1_VLB_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" #define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin" #define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM" #define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN" #define BIOS_GD5429_PATH "roms/video/cirruslogic/5429.vbi" -#define BIOS_GD5430_VLB_PATH "roms/video/cirruslogic/diamondvlbus.bin" -#define BIOS_GD5430_PCI_PATH "roms/video/cirruslogic/pci.bin" +#define BIOS_GD5430_DIAMOND_A8_VLB_PATH "roms/video/cirruslogic/diamondvlbus.bin" +#define BIOS_GD5430_PATH "roms/video/cirruslogic/pci.bin" +#define BIOS_GD5434_DIAMOND_A3_ISA_PATH "roms/video/cirruslogic/Diamond Multimedia SpeedStar 64 v2.02 EPROM Backup from ST M27C256B-12F1.BIN" #define BIOS_GD5434_PATH "roms/video/cirruslogic/gd5434.bin" #define BIOS_GD5436_PATH "roms/video/cirruslogic/5436.vbi" #define BIOS_GD5440_PATH "roms/video/cirruslogic/BIOS.BIN" @@ -1209,11 +1211,62 @@ gd54xx_in(uint16_t addr, void *p) ret |= 0x80; } break; + case 0x0a: /*Scratch Pad 1 (Memory size for 5402/542x)*/ + ret = svga->seqregs[0x0a] & ~0x1a; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5402) { + ret |= 0x01; /*512K of memory*/ + } else if (svga->crtc[0x27] > CIRRUS_ID_CLGD5402) { + switch (gd54xx->vram_size >> 10) { + case 512: + ret |= 0x08; + break; + case 1024: + ret |= 0x10; + break; + case 2048: + ret |= 0x18; + break; + } + } + break; case 0x0b: case 0x0c: case 0x0d: case 0x0e: ret = gd54xx->vclk_n[svga->seqaddr-0x0b]; break; + case 0x0f: /*DRAM control*/ + ret = svga->seqregs[0x0f] & ~0x98; + switch (gd54xx->vram_size >> 10) { + case 512: + ret |= 0x08; /*16-bit DRAM data bus width*/ + break; + case 1024: + ret |= 0x10; /*32-bit DRAM data bus width for 1M of memory*/ + break; + case 2048: + ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18; /*32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width for 2M of memory*/ + break; + case 4096: + ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/ + break; + } + break; + case 0x15: /*Scratch Pad 3 (Memory size for 543x)*/ + ret = svga->seqregs[0x15] & ~0x0f; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { + switch (gd54xx->vram_size >> 20) { + case 1: + ret |= 0x02; + break; + case 2: + ret |= 0x03; + break; + case 4: + ret |= 0x04; + break; + } + } + break; case 0x17: - ret = svga->gdcreg[0x17] & ~(7 << 3); + ret = svga->seqregs[0x17] & ~(7 << 3); if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { if (gd54xx->vlb) @@ -3844,17 +3897,29 @@ static void case CIRRUS_ID_CLGD5426: if (info->local & 0x200) romfn = NULL; - else - romfn = BIOS_GD5426_PATH; + else { + if (info->local & 0x100) + romfn = BIOS_GD5426_DIAMOND_A1_ISA_PATH; + else { + if (gd54xx->vlb) + romfn = BIOS_GD5428_PATH; + else + romfn = BIOS_GD5428_ISA_PATH; + } + } break; case CIRRUS_ID_CLGD5428: - if (gd54xx->vlb) - romfn = BIOS_GD5428_PATH; - else if (gd54xx->mca) - romfn = BIOS_GD5428_MCA_PATH; - else - romfn = BIOS_GD5428_ISA_PATH; + if (info->local & 0x100) + romfn = BIOS_GD5428_DIAMOND_B1_VLB_PATH; + else { + if (gd54xx->vlb) + romfn = BIOS_GD5428_PATH; + else if (gd54xx->mca) + romfn = BIOS_GD5428_MCA_PATH; + else + romfn = BIOS_GD5428_ISA_PATH; + } break; case CIRRUS_ID_CLGD5429: @@ -3873,8 +3938,12 @@ static void if (info->local & 0x200) { romfn = NULL; gd54xx->has_bios = 0; - } else - romfn = BIOS_GD5434_PATH; + } else { + if (info->local & 0x100) + romfn = BIOS_GD5434_DIAMOND_A3_ISA_PATH; + else + romfn = BIOS_GD5434_PATH; + } break; case CIRRUS_ID_CLGD5436: @@ -3896,9 +3965,9 @@ static void romfn = NULL; gd54xx->has_bios = 0; } else if (gd54xx->pci) - romfn = BIOS_GD5430_PCI_PATH; + romfn = BIOS_GD5430_PATH; else - romfn = BIOS_GD5430_VLB_PATH; + romfn = BIOS_GD5430_DIAMOND_A8_VLB_PATH; } break; @@ -3915,23 +3984,24 @@ static void } if (info->flags & DEVICE_MCA) { - vram = 1; - gd54xx->vram_size = 1 << 20; + vram = 1024; + gd54xx->vram_size = vram << 10; } else { - if (id >= CIRRUS_ID_CLGD5420) { + if (id <= CIRRUS_ID_CLGD5428) { if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200)) - vram = 1; + vram = 1024; + else if (id == CIRRUS_ID_CLGD5401) + vram = 256; + else if (id == CIRRUS_ID_CLGD5402) + vram = 512; else vram = device_get_config_int("memory"); - } else - vram = 0; - - if (vram) - gd54xx->vram_size = vram << 20; - else - gd54xx->vram_size = 1 << 19; + gd54xx->vram_size = vram << 10; + } else { + vram = device_get_config_int("memory"); + gd54xx->vram_size = vram << 20; + } } - gd54xx->vram_mask = gd54xx->vram_size - 1; if (romfn) @@ -3955,8 +4025,8 @@ static void } svga->vblank_start = gd54xx_vblank_start; svga->ven_write = gd54xx_write_modes45; - if (vram <= 1) - svga->decode_mask = gd54xx->vram_mask; + if ((vram == 1) || (vram >= 256 && vram <= 1024)) + svga->decode_mask = gd54xx->vram_mask; if (gd54xx->bit32) { mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); @@ -4039,6 +4109,7 @@ static void svga->crtc[0x27] = id; svga->seqregs[6] = 0x0f; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) gd54xx->unlocked = 1; @@ -4089,9 +4160,9 @@ gd5422_available(void) } static int -gd5426_available(void) +gd5426_diamond_a1_available(void) { - return rom_present(BIOS_GD5426_PATH); + return rom_present(BIOS_GD5426_DIAMOND_A1_ISA_PATH); } static int @@ -4100,6 +4171,12 @@ gd5428_available(void) return rom_present(BIOS_GD5428_PATH); } +static int +gd5428_diamond_b1_available(void) +{ + return rom_present(BIOS_GD5428_DIAMOND_B1_VLB_PATH); +} + static int gd5428_isa_available(void) { @@ -4119,15 +4196,15 @@ gd5429_available(void) } static int -gd5430_vlb_available(void) +gd5430_diamond_a8_available(void) { - return rom_present(BIOS_GD5430_VLB_PATH); + return rom_present(BIOS_GD5430_DIAMOND_A8_VLB_PATH); } static int -gd5430_pci_available(void) +gd5430_available(void) { - return rom_present(BIOS_GD5430_PCI_PATH); + return rom_present(BIOS_GD5430_PATH); } static int @@ -4136,6 +4213,12 @@ gd5434_available(void) return rom_present(BIOS_GD5434_PATH); } +static int +gd5434_diamond_a3_available(void) +{ + return rom_present(BIOS_GD5434_DIAMOND_A3_ISA_PATH); +} + static int gd5436_available(void) { @@ -4199,28 +4282,96 @@ gd54xx_force_redraw(void *p) gd54xx->svga.fullchange = changeframecount; } -static const device_config_t gd5422_config[] = +static const device_config_t gd542x_config[] = { { - "memory","Memory size",CONFIG_SELECTION,"", 1, "", { 0 }, + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { { - "512 KB", 0 + .description = "512 KB", + .value = 512 }, { - "1 MB", 1 + .description = "1 MB", + .value = 1024 }, { - "" + .description = "" } }, + .default_int = 512 }, { - "", "", -1 + .type = -1 } }; -static const device_config_t gd5428_config[] = +static const device_config_t gd5426_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "" + } + }, + .default_int = 2048 + }, + { + .type = -1 + } +}; + +static const device_config_t gd5428_onboard_config[] = +{ + { + .name = "memory", + .description = "Onboard memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "" + } + }, + .default_int = 2048 + }, + { + .type = -1 + } +}; + +static const device_config_t gd5429_config[] = { { .name = "memory", @@ -4247,38 +4398,11 @@ static const device_config_t gd5428_config[] = } }; -static const device_config_t gd5428_onboard_config[] = -{ - { - .name = "memory", - .description = "Onboard Video RAM size", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - }, - .default_int = 2 - }, - { - .type = -1 - } -}; - static const device_config_t gd5440_onboard_config[] = { { .name = "memory", - .description = "Video memory size", + .description = "Onboard memory size", .type = CONFIG_SELECTION, .selection = { @@ -4302,6 +4426,68 @@ static const device_config_t gd5440_onboard_config[] = }; static const device_config_t gd5434_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 4 + }, + { + .type = -1 + } +}; + +static const device_config_t gd5434_onboard_config[] = +{ + { + .name = "memory", + .description = "Onboard memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "" + } + }, + .default_int = 4 + }, + { + .type = -1 + } +}; + +static const device_config_t gd5480_config[] = { { .name = "memory", @@ -4330,7 +4516,7 @@ static const device_config_t gd5434_config[] = const device_t gd5401_isa_device = { - "Cirrus Logic GD-5401 (ACUMOS AVGA1)", + "Cirrus Logic GD5401 (ISA) (ACUMOS AVGA1)", DEVICE_ISA, CIRRUS_ID_CLGD5401, gd54xx_init, gd54xx_close, @@ -4343,7 +4529,7 @@ const device_t gd5401_isa_device = const device_t gd5402_isa_device = { - "Cirrus Logic GD-5402 (ACUMOS AVGA2)", + "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2)", DEVICE_ISA, CIRRUS_ID_CLGD5402, gd54xx_init, gd54xx_close, @@ -4356,7 +4542,7 @@ const device_t gd5402_isa_device = const device_t gd5402_onboard_device = { - "Cirrus Logic GD-5402 (ACUMOS AVGA2) (On-Board)", + "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5402 | 0x200, gd54xx_init, gd54xx_close, @@ -4369,7 +4555,7 @@ const device_t gd5402_onboard_device = const device_t gd5420_isa_device = { - "Cirrus Logic GD-5420", + "Cirrus Logic GD5420 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5420, gd54xx_init, gd54xx_close, @@ -4377,11 +4563,11 @@ const device_t gd5420_isa_device = { gd5420_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5422_config, + gd542x_config, }; const device_t gd5422_isa_device = { - "Cirrus Logic GD-5422", + "Cirrus Logic GD5422 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5422, gd54xx_init, gd54xx_close, @@ -4389,11 +4575,11 @@ const device_t gd5422_isa_device = { { gd5422_available }, /* Common BIOS between 5422 and 5424 */ gd54xx_speed_changed, gd54xx_force_redraw, - gd5422_config, + gd542x_config, }; const device_t gd5424_vlb_device = { - "Cirrus Logic GD-5424", + "Cirrus Logic GD5424 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5424, gd54xx_init, gd54xx_close, @@ -4401,26 +4587,57 @@ const device_t gd5424_vlb_device = { { gd5422_available }, /* Common BIOS between 5422 and 5424 */ gd54xx_speed_changed, gd54xx_force_redraw, - gd5422_config, + gd542x_config, +}; + +const device_t gd5426_isa_device = +{ + "Cirrus Logic GD5426 (ISA)", + DEVICE_AT | DEVICE_ISA, + CIRRUS_ID_CLGD5426, + gd54xx_init, + gd54xx_close, + gd54xx_reset, + { gd5428_isa_available }, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5426_config +}; + + +/*According to a Diamond bios file listing and vgamuseum*/ +const device_t gd5426_diamond_speedstar_pro_a1_isa_device = +{ + "Cirrus Logic GD5426 (ISA) (Diamond SpeedStar Pro Rev. A1)", + DEVICE_AT | DEVICE_ISA, + CIRRUS_ID_CLGD5426 | 0x100, + gd54xx_init, + gd54xx_close, + gd54xx_reset, + { gd5426_diamond_a1_available }, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5426_config }; const device_t gd5426_vlb_device = { - "Cirrus Logic CL-GD 5426 (VLB)", + "Cirrus Logic GD5426 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5426, gd54xx_init, gd54xx_close, gd54xx_reset, - { gd5426_available }, + { gd5428_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5426_config }; + const device_t gd5426_onboard_device = { - "Cirrus Logic CL-GD 5426 (On-board)", + "Cirrus Logic GD5426 (VLB) (On-Board)", DEVICE_VLB, CIRRUS_ID_CLGD5426 | 0x200, gd54xx_init, @@ -4434,7 +4651,7 @@ const device_t gd5426_onboard_device = const device_t gd5428_isa_device = { - "Cirrus Logic CL-GD 5428 (ISA)", + "Cirrus Logic GD5428 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5428, gd54xx_init, @@ -4443,12 +4660,12 @@ const device_t gd5428_isa_device = { gd5428_isa_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5426_config }; const device_t gd5428_vlb_device = { - "Cirrus Logic CL-GD 5428 (VLB)", + "Cirrus Logic GD5428 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5428, gd54xx_init, @@ -4457,12 +4674,27 @@ const device_t gd5428_vlb_device = { gd5428_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5426_config +}; + +/*According to a Diamond bios file listing and vgamuseum*/ +const device_t gd5428_diamond_speedstar_pro_b1_vlb_device = +{ + "Cirrus Logic GD5428 (VLB) (Diamond SpeedStar Pro Rev. B1)", + DEVICE_VLB, + CIRRUS_ID_CLGD5428 | 0x100, + gd54xx_init, + gd54xx_close, + gd54xx_reset, + { gd5428_diamond_b1_available }, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5426_config }; const device_t gd5428_mca_device = { - "Cirrus Logic CL-GD 5428 (IBM SVGA Adapter/A)", + "Cirrus Logic GD5428 (MCA) (IBM SVGA Adapter/A)", DEVICE_MCA, CIRRUS_ID_CLGD5428, gd54xx_init, @@ -4476,7 +4708,7 @@ const device_t gd5428_mca_device = const device_t gd5428_onboard_device = { - "Cirrus Logic CL-GD 5428 (On-Board)", + "Cirrus Logic GD5428 (ISA) (On-Board)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5428, gd54xx_init, @@ -4490,7 +4722,7 @@ const device_t gd5428_onboard_device = const device_t gd5429_isa_device = { - "Cirrus Logic CL-GD 5429 (ISA)", + "Cirrus Logic GD5429 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5429, gd54xx_init, @@ -4499,12 +4731,12 @@ const device_t gd5429_isa_device = { gd5429_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5429_config }; const device_t gd5429_vlb_device = { - "Cirrus Logic CL-GD 5429 (VLB)", + "Cirrus Logic GD5429 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5429, gd54xx_init, @@ -4513,40 +4745,41 @@ const device_t gd5429_vlb_device = { gd5429_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5429_config }; -const device_t gd5430_vlb_device = +/*According to a Diamond bios file listing and vgamuseum*/ +const device_t gd5430_diamond_speedstar_pro_se_a8_vlb_device = { - "Cirrus Logic CL-GD 5430 (VLB)", + "Cirrus Logic GD5430 (VLB) (Diamond SpeedStar Pro SE Rev. A8)", DEVICE_VLB, CIRRUS_ID_CLGD5430, gd54xx_init, gd54xx_close, gd54xx_reset, - { gd5430_vlb_available }, + { gd5430_diamond_a8_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5429_config }; const device_t gd5430_pci_device = { - "Cirrus Logic CL-GD 5430 (PCI)", + "Cirrus Logic GD5430 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5430, gd54xx_init, gd54xx_close, gd54xx_reset, - { gd5430_pci_available }, + { gd5430_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5429_config }; const device_t gd5434_isa_device = { - "Cirrus Logic CL-GD 5434 (ISA)", + "Cirrus Logic GD5434 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -4558,9 +4791,24 @@ const device_t gd5434_isa_device = gd5434_config }; +/*According to a Diamond bios file listing and vgamuseum*/ +const device_t gd5434_diamond_speedstar_64_a3_isa_device = +{ + "Cirrus Logic GD5434 (ISA) (Diamond SpeedStar 64 Rev. A3)", + DEVICE_AT | DEVICE_ISA, + CIRRUS_ID_CLGD5434 | 0x100, + gd54xx_init, + gd54xx_close, + gd54xx_reset, + { gd5434_diamond_a3_available }, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5429_config +}; + const device_t gd5434_onboard_pci_device = { - "Cirrus Logic CL-GD 5434-4 (On-Board PCI)", + "Cirrus Logic GD5434-4 (PCI) (On-Board)", DEVICE_PCI, CIRRUS_ID_CLGD5434 | 0x200, gd54xx_init, @@ -4569,12 +4817,12 @@ const device_t gd5434_onboard_pci_device = { NULL }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5434_config + gd5434_onboard_config }; const device_t gd5434_vlb_device = { - "Cirrus Logic CL-GD 5434 (VLB)", + "Cirrus Logic GD5434 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -4588,7 +4836,7 @@ const device_t gd5434_vlb_device = const device_t gd5434_pci_device = { - "Cirrus Logic CL-GD 5434 (PCI)", + "Cirrus Logic GD5434 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -4602,7 +4850,7 @@ const device_t gd5434_pci_device = const device_t gd5436_pci_device = { - "Cirrus Logic CL-GD 5436 (PCI)", + "Cirrus Logic GD5436 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5436, gd54xx_init, @@ -4616,7 +4864,7 @@ const device_t gd5436_pci_device = const device_t gd5440_onboard_pci_device = { - "Cirrus Logic CL-GD 5440 (On-Board PCI)", + "Cirrus Logic GD5440 (PCI) (On-Board)", DEVICE_PCI, CIRRUS_ID_CLGD5440 | 0x600, gd54xx_init, @@ -4630,7 +4878,7 @@ const device_t gd5440_onboard_pci_device = const device_t gd5440_pci_device = { - "Cirrus Logic CL-GD 5440 (PCI)", + "Cirrus Logic GD5440 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5440 | 0x400, gd54xx_init, @@ -4639,12 +4887,12 @@ const device_t gd5440_pci_device = { gd5440_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5428_config + gd5429_config }; const device_t gd5446_pci_device = { - "Cirrus Logic CL-GD 5446 (PCI)", + "Cirrus Logic GD5446 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5446, gd54xx_init, @@ -4658,7 +4906,7 @@ const device_t gd5446_pci_device = const device_t gd5446_stb_pci_device = { - "STB Nitro 64V (PCI)", + "Cirrus Logic GD5446 (PCI) (STB Nitro 64V)", DEVICE_PCI, CIRRUS_ID_CLGD5446 | 0x100, gd54xx_init, @@ -4672,7 +4920,7 @@ const device_t gd5446_stb_pci_device = const device_t gd5480_pci_device = { - "Cirrus Logic CL-GD 5480 (PCI)", + "Cirrus Logic GD5480 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5480, gd54xx_init, @@ -4681,5 +4929,5 @@ const device_t gd5480_pci_device = { gd5480_available }, gd54xx_speed_changed, gd54xx_force_redraw, - gd5434_config + gd5480_config }; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 65dced875..1c2ca794e 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -78,9 +78,9 @@ typedef struct et4000w32p_t uint8_t regs[256], pci_regs[256]; int index, vlb, pci, interleaved, - bank, blitter_busy, type; + bank, type; - uint32_t linearbase, linearbase_old; + uint32_t linearbase; uint32_t vram_mask; /* Accelerator */ @@ -97,12 +97,13 @@ typedef struct et4000w32p_t uint32_t pattern_addr, source_addr, dest_addr, mix_addr; } queued, internal; - uint8_t osr; + uint8_t suspend_terminate, osr; uint8_t status; + uint16_t x_count, y_count; int pattern_x, source_x, pattern_x_back, source_x_back, pattern_y, source_y, cpu_dat_pos, pix_pos, - cpu_input_num, queue; + cpu_input_num, fifo_queue; uint32_t pattern_addr, source_addr, dest_addr, mix_addr, pattern_back, source_back, dest_back, mix_back, @@ -115,6 +116,8 @@ typedef struct et4000w32p_t uint32_t base[3]; uint8_t ctrl; } mmu; + + volatile int busy; } et4000w32p_t; @@ -131,12 +134,13 @@ static video_timings_t timing_et4000w32_isa = {VIDEO_ISA, 4, 4, 4, 10, 10, 10 void et4000w32p_recalcmapping(et4000w32p_t *et4000); -uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); -void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); +static uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); +static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); -void et4000w32_blit_start(et4000w32p_t *et4000); -void et4000w32p_blit_start(et4000w32p_t *et4000); -void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); +static void et4000w32_blit_start(et4000w32p_t *et4000); +static void et4000w32p_blit_start(et4000w32p_t *et4000); +static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000); +static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); uint8_t et4000w32p_in(uint16_t addr, void *p); @@ -213,7 +217,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) } break; case 0x3d4: - svga->crtcreg = val & 63; + svga->crtcreg = val & 0x3f; return; case 0x3d5: if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) @@ -333,12 +337,16 @@ et4000w32p_in(uint16_t addr, void *p) case 0x3d4: return svga->crtcreg; case 0x3d5: + if (et4000->type == ET4000W32) { + if (svga->crtcreg == 0x37) + return 0x09; + } return svga->crtc[svga->crtcreg]; case 0x3da: svga->attrff = 0; - /*Bit 1 of the Input Status Register is required by OS/2 ET4000W32/I drivers to be set otherwise + /*Bit 1 of the Input Status Register is required by the OS/2 and NT ET4000W32/I drivers to be set otherwise the guest will loop infinitely upon reaching the GUI*/ if (svga->cgastat & 0x01) svga->cgastat &= ~0x32; @@ -397,6 +405,24 @@ et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + if (et4000->type != ET4000W32P_DIAMOND) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->gdcreg[5] & 0x40) { + switch (svga->bpp) { + case 8: + svga->clock /= 2; + break; + case 15: case 16: + svga->clock /= 3; + break; + case 24: + svga->clock /= 4; + break; + } + } + } + } + if (svga->adv_flags & FLAG_NOSKEW) { /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ @@ -550,6 +576,7 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) map = (svga->gdcreg[6] & 0xc) >> 2; if (svga->crtc[0x36] & 0x20) map |= 4; if (svga->crtc[0x36] & 0x08) map |= 8; + mem_mapping_disable(&et4000->linear_mapping); switch (map) { case 0x0: case 0x4: case 0x8: case 0xc: /* 128k at A0000 */ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -587,12 +614,8 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) svga->banked_mask = 0x7fff; break; } - - mem_mapping_disable(&et4000->linear_mapping); } - et4000->linearbase_old = et4000->linearbase; - if (!et4000->interleaved && (svga->crtc[0x32] & 0x80)) mem_mapping_disable(&svga->mapping); } @@ -601,128 +624,208 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) static void et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) { - switch (addr & 0x7fff) { - case 0x7f80: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFFFF00) | val; break; - case 0x7f81: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFF00FF) | (val << 8); break; - case 0x7f82: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; - case 0x7f84: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFFFF00) | val; break; - case 0x7f85: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFF00FF) | (val << 8); break; - case 0x7f86: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; - case 0x7f88: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xFF00) | val; break; - case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7f8a: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xFF00) | val; break; - case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); et4000->acl.queue++;break; - case 0x7f8c: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xFF00) | val; break; - case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7f8e: - et4000->acl.queue++; - if (et4000->type >= ET4000W32P_REVC) - et4000->acl.queued.pixel_depth = val; - else - et4000->acl.queued.vbus = val; + et4000->acl.fifo_queue++; + switch (addr & 0xff) { + case 0x80: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x3fff00) | val; break; - case 0x7f8f: et4000->acl.queued.xy_dir = val; et4000->acl.queue++; break; - case 0x7f90: et4000->acl.queued.pattern_wrap = val; et4000->acl.queue++; break; - case 0x7f92: et4000->acl.queued.source_wrap = val; et4000->acl.queue++; break; - case 0x7f98: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xFF00) | val; break; - case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7f9a: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xFF00) | val; break; - case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7f9c: et4000->acl.queued.ctrl_routing = val; et4000->acl.queue++; break; - case 0x7f9d: et4000->acl.queued.ctrl_reload = val; et4000->acl.queue++; break; - case 0x7f9e: et4000->acl.queued.rop_bg = val; et4000->acl.queue++; break; - case 0x7f9f: et4000->acl.queued.rop_fg = val; et4000->acl.queue++; break; - case 0x7fa0: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFFFF00) | val; break; - case 0x7fa1: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFF00FF) | (val << 8); break; - case 0x7fa2: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7fa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00FFFFFF) | (val << 24); - et4000->acl.queue++; + case 0x81: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x3f00ff) | (val << 8); + break; + case 0x82: + et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0x84: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x3fff00) | val; + break; + case 0x85: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x3f00ff) | (val << 8); + break; + case 0x86: + et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0x88: + et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x0f00) | val; + break; + case 0x89: + et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00ff) | ((val & 0x0f) << 8); + break; + case 0x8a: + et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x0f00) | val; + break; + case 0x8b: + et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00ff) | ((val & 0x0f) << 8); + break; + case 0x8c: + et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x0f00) | val; + break; + case 0x8d: + et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | ((val & 0x0f) << 8); + break; + case 0x8e: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.pixel_depth = val & 0x30; + else + et4000->acl.queued.vbus = val & 0x03; + break; + case 0x8f: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.xy_dir = val & 0xb7; + else + et4000->acl.queued.xy_dir = val & 0x03; + break; + case 0x90: + et4000->acl.queued.pattern_wrap = val & 0x77; + break; + case 0x92: + et4000->acl.queued.source_wrap = val & 0x77; + break; + case 0x98: + et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x0f00) | val; + break; + case 0x99: + et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00ff) | ((val & 0x0f) << 8); + break; + case 0x9a: + et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x0f00) | val; + break; + case 0x9b: + et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | ((val & 0x0f) << 8); + break; + case 0x9c: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.ctrl_routing = val & 0xdb; + else + et4000->acl.queued.ctrl_routing = val & 0xb7; + break; + case 0x9d: + et4000->acl.queued.ctrl_reload = val & 0x03; + break; + case 0x9e: + et4000->acl.queued.rop_bg = val; + break; + case 0x9f: + et4000->acl.queued.rop_fg = val; + break; + case 0xa0: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x3fff00) | val; + break; + case 0xa1: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x3f00ff) | (val << 8); + break; + case 0xa2: + et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0xa3: et4000->acl.internal = et4000->acl.queued; if (et4000->type >= ET4000W32P_REVC) { - if (et4000->acl.osr & 0x10) { - et4000w32p_blit_start(et4000); - if (!(et4000->acl.queued.ctrl_routing & 0x43)) { - et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); - } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { - et4000w32p_blit(4, ~0, 0, 0, et4000); - } + et4000w32p_blit_start(et4000); + et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); + if (!(et4000->acl.queued.ctrl_routing & 0x43)) { + et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { + et4000w32p_blit(4, ~0, 0, 0, et4000); } } else { et4000w32_blit_start(et4000); et4000->acl.cpu_input_num = 0; - if (!(et4000->acl.queued.ctrl_routing & 0x37)) - et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); + } } break; - case 0x7fa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break; - case 0x7fa5: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); break; - case 0x7fa6: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; - case 0x7fa8: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; break; - case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7faa: et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; break; - case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7fac: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; break; - case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); et4000->acl.queue++; break; - case 0x7fae: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; break; - case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); et4000->acl.queue++; break; + case 0xa4: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; + break; + case 0xa5: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); + break; + case 0xa6: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); + break; + case 0xa7: + et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); + break; + case 0xa8: + et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; + break; + case 0xa9: + et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); + break; + case 0xaa: + et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; + break; + case 0xab: + et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); + break; + case 0xac: + et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; + break; + case 0xad: + et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); + break; + case 0xae: + et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; + break; + case 0xaf: + et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); + break; } } - static void -et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val) +et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { if (et4000->type >= ET4000W32P_REVC) { - if (!(et4000->acl.status & ACL_XYST)) + if (!(et4000->acl.status & ACL_XYST)) { + et4000w32_log("XY MMU block not started\n"); return; + } if (et4000->acl.internal.ctrl_routing & 3) { - et4000->acl.queue++; - if ((et4000->acl.internal.ctrl_routing & 3) == 2) { + et4000->acl.fifo_queue++; + if ((et4000->acl.internal.ctrl_routing & 3) == 2) /*CPU data is Mix data*/ et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); - } - else if ((et4000->acl.internal.ctrl_routing & 3) == 1) { + else if ((et4000->acl.internal.ctrl_routing & 3) == 1) /*CPU data is Source data*/ et4000w32p_blit(1, ~0, val, 2, et4000); - } } } else { if (!(et4000->acl.status & ACL_XYST)) { - et4000->acl.queue++; - et4000->acl.queued.dest_addr = (addr & 0x1FFF) + et4000->mmu.base[et4000->bank]; + et4000->acl.fifo_queue++; + et4000->acl.queued.dest_addr = ((addr & 0x1fff) + et4000->mmu.base[bank]); et4000->acl.internal = et4000->acl.queued; et4000w32_blit_start(et4000); - if (!(et4000->acl.internal.ctrl_routing & 0x37)) - et4000w32p_blit(0xFFFFFF, ~0, 0, 0, et4000); + et4000w32_log("Accelerated MMU aperture = %i and start XY Block (Implicit), xcnt = %i, ycnt = %i\n", bank, et4000->acl.x_count + 1, et4000->acl.y_count + 1); et4000->acl.cpu_input_num = 0; + if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); + } } if (et4000->acl.internal.ctrl_routing & 7) { - et4000->acl.queue++; - et4000->acl.cpu_input = (et4000->acl.cpu_input &~ (0xFF << (et4000->acl.cpu_input_num << 3))) | + et4000->acl.fifo_queue++; + et4000->acl.cpu_input = (et4000->acl.cpu_input & ~(0xff << (et4000->acl.cpu_input_num << 3))) | (val << (et4000->acl.cpu_input_num << 3)); et4000->acl.cpu_input_num++; - if (et4000->acl.cpu_input_num == et4000w32_vbus[et4000->acl.internal.vbus & 3]) { - if ((et4000->acl.internal.ctrl_routing & 7) == 2) - et4000w32p_blit(et4000->acl.cpu_input_num << 3, et4000->acl.cpu_input, 0, 1, et4000); - else if ((et4000->acl.internal.ctrl_routing & 7) == 1) - et4000w32p_blit(et4000->acl.cpu_input_num, ~0, et4000->acl.cpu_input, 2, et4000); - else if ((et4000->acl.internal.ctrl_routing & 7) == 4) - et4000w32p_blit(et4000->acl.cpu_input_num, ~0, et4000->acl.internal.count_x, 2, et4000); - else if ((et4000->acl.internal.ctrl_routing & 7) == 5) - et4000w32p_blit(et4000->acl.cpu_input_num, ~0, et4000->acl.internal.count_y, 2, et4000); + if (et4000->acl.cpu_input_num == et4000w32_vbus[et4000->acl.internal.vbus]) { + if ((et4000->acl.internal.ctrl_routing & 7) == 2) /*CPU data is Mix data*/ + et4000w32_blit(et4000->acl.cpu_input_num << 3, 2, 0, et4000->acl.cpu_input, et4000); + else if ((et4000->acl.internal.ctrl_routing & 7) == 1) /*CPU data is Source data*/ + et4000w32_blit(et4000->acl.cpu_input_num, 1, et4000->acl.cpu_input, 0xffffffff, et4000); et4000->acl.cpu_input_num = 0; } + + if ((et4000->acl.internal.ctrl_routing & 7) == 4) /*CPU data is X Count*/ + et4000w32_blit(val | (et4000->acl.queued.count_x << 8), 0, 0, 0xffffffff, et4000); + if ((et4000->acl.internal.ctrl_routing & 7) == 5) /*CPU data is Y Count*/ + et4000w32_blit(val | (et4000->acl.queued.count_y << 8), 0, 0, 0xffffffff, et4000); } } } - -void +static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -734,7 +837,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) case 0x4000: /* MMU 2 */ et4000->bank = (addr >> 13) & 3; if (et4000->mmu.ctrl & (1 << et4000->bank)) { - et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val); + et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank); } else { if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val; @@ -743,43 +846,65 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) } break; case 0x6000: - if ((addr & 0x7fff) >= 0x7f80) { + if ((addr & 0xff) >= 0x80) { et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); - } else switch (addr & 0x7fff) { - case 0x7f00: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFFFF00) | val; break; - case 0x7f01: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFFFF00FF) | (val << 8); break; - case 0x7f02: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xFF00FFFF) | (val << 16); break; - case 0x7f03: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00FFFFFF) | (val << 24); break; - case 0x7f04: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFFFF00) | val; break; - case 0x7f05: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFFFF00FF) | (val << 8); break; - case 0x7f06: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xFF00FFFF) | (val << 16); break; - case 0x7f07: et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00FFFFFF) | (val << 24); break; - case 0x7f08: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFFFF00) | val; break; - case 0x7f09: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFFFF00FF) | (val << 8); break; - case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break; - case 0x7f0b: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break; - case 0x7f13: et4000->mmu.ctrl = val; break; - case 0x7f31: et4000->acl.osr = val; break; + } else { + switch (addr & 0xff) { + case 0x00: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x3fff00) | val; + break; + case 0x01: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x3f00ff) | (val << 8); + break; + case 0x02: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0x04: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x3fff00) | val; + break; + case 0x05: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x3f00ff) | (val << 8); + break; + case 0x06: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0x08: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x3fff00) | val; + break; + case 0x09: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x3f00ff) | (val << 8); + break; + case 0x0a: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00ffff) | ((val & 0x3f) << 16); + break; + case 0x13: + et4000->mmu.ctrl = val; + break; + case 0x30: + et4000->acl.suspend_terminate = val; + break; + case 0x31: + et4000->acl.osr = val; + break; + } } break; } } - -uint8_t +static uint8_t et4000w32p_mmu_read(uint32_t addr, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; - int bank; uint8_t temp; switch (addr & 0x6000) { case 0x0000: /* MMU 0 */ case 0x2000: /* MMU 1 */ case 0x4000: /* MMU 2 */ - bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << bank)) { + et4000->bank = (addr >> 13) & 3; + if (et4000->mmu.ctrl & (1 << et4000->bank)) { temp = 0xff; if (et4000->acl.cpu_dat_pos) { et4000->acl.cpu_dat_pos--; @@ -793,84 +918,97 @@ et4000w32p_mmu_read(uint32_t addr, void *p) return temp; } - if ((addr&0x1fff) + et4000->mmu.base[bank] >= svga->vram_max) + if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] >= svga->vram_max) return 0xff; - return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]]; + return svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]]; case 0x6000: - switch (addr & 0x7fff) { - case 0x7f00: return et4000->mmu.base[0]; - case 0x7f01: return et4000->mmu.base[0] >> 8; - case 0x7f02: return et4000->mmu.base[0] >> 16; - case 0x7f03: return et4000->mmu.base[0] >> 24; - case 0x7f04: return et4000->mmu.base[1]; - case 0x7f05: return et4000->mmu.base[1] >> 8; - case 0x7f06: return et4000->mmu.base[1] >> 16; - case 0x7f07: return et4000->mmu.base[1] >> 24; - case 0x7f08: return et4000->mmu.base[2]; - case 0x7f09: return et4000->mmu.base[2] >> 8; - case 0x7f0a: return et4000->mmu.base[2] >> 16; - case 0x7f0b: return et4000->mmu.base[2] >> 24; - case 0x7f13: return et4000->mmu.ctrl; + switch (addr & 0xff) { + case 0x00: + return et4000->mmu.base[0] & 0xff; + case 0x01: + return et4000->mmu.base[0] >> 8; + case 0x02: + return et4000->mmu.base[0] >> 16; + case 0x03: + return et4000->mmu.base[0] >> 24; + case 0x04: + return et4000->mmu.base[1] & 0xff; + case 0x05: + return et4000->mmu.base[1] >> 8; + case 0x06: + return et4000->mmu.base[1] >> 16; + case 0x07: + return et4000->mmu.base[1] >> 24; + case 0x08: + return et4000->mmu.base[2] & 0xff; + case 0x09: + return et4000->mmu.base[2] >> 8; + case 0x0a: + return et4000->mmu.base[2] >> 16; + case 0x0b: + return et4000->mmu.base[2] >> 24; + case 0x13: + return et4000->mmu.ctrl; - case 0x7f36: - if (et4000->type >= ET4000W32P_REVC) { - if (et4000->acl.queue) { - et4000->acl.status |= ACL_RDST; - et4000->acl.queue = 0; - } else - et4000->acl.status &= ~ACL_RDST; - - temp = et4000->acl.status; - } else { - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + case 0x36: + if (et4000->acl.fifo_queue) { + et4000->acl.status |= ACL_RDST; + et4000->acl.fifo_queue = 0; + } else + et4000->acl.status &= ~ACL_RDST; + return et4000->acl.status; - if (et4000->acl.queue) { - et4000->acl.status |= ACL_RDST; - et4000->acl.queue = 0; - } else - et4000->acl.status &= ~ACL_RDST; - - temp = et4000->acl.status; - } - return temp; - - case 0x7f80: return et4000->acl.internal.pattern_addr; - case 0x7f81: return et4000->acl.internal.pattern_addr >> 8; - case 0x7f82: return et4000->acl.internal.pattern_addr >> 16; - case 0x7f83: return et4000->acl.internal.pattern_addr >> 24; - case 0x7f84: return et4000->acl.internal.source_addr; - case 0x7f85: return et4000->acl.internal.source_addr >> 8; - case 0x7f86: return et4000->acl.internal.source_addr >> 16; - case 0x7f87: return et4000->acl.internal.source_addr >> 24; - case 0x7f88: return et4000->acl.internal.pattern_off; - case 0x7f89: return et4000->acl.internal.pattern_off >> 8; - case 0x7f8a: return et4000->acl.internal.source_off; - case 0x7f8b: return et4000->acl.internal.source_off >> 8; - case 0x7f8c: return et4000->acl.internal.dest_off; - case 0x7f8d: return et4000->acl.internal.dest_off >> 8; - case 0x7f8e: + case 0x80: + return et4000->acl.internal.pattern_addr & 0xff; + case 0x81: + return et4000->acl.internal.pattern_addr >> 8; + case 0x82: + return et4000->acl.internal.pattern_addr >> 16; + case 0x83: + return et4000->acl.internal.pattern_addr >> 24; + case 0x84: + return et4000->acl.internal.source_addr & 0xff; + case 0x85: + return et4000->acl.internal.source_addr >> 8; + case 0x86: + return et4000->acl.internal.source_addr >> 16; + case 0x87: + return et4000->acl.internal.source_addr >> 24; + case 0x88: + return et4000->acl.internal.pattern_off & 0xff; + case 0x89: + return et4000->acl.internal.pattern_off >> 8; + case 0x8a: + return et4000->acl.internal.source_off & 0xff; + case 0x8b: + return et4000->acl.internal.source_off >> 8; + case 0x8c: + return et4000->acl.internal.dest_off & 0xff; + case 0x8d: + return et4000->acl.internal.dest_off >> 8; + case 0x8e: if (et4000->type >= ET4000W32P_REVC) return et4000->acl.internal.pixel_depth; else return et4000->acl.internal.vbus; break; - case 0x7f8f: return et4000->acl.internal.xy_dir; - case 0x7f90: return et4000->acl.internal.pattern_wrap; - case 0x7f92: return et4000->acl.internal.source_wrap; - case 0x7f98: return et4000->acl.internal.count_x; - case 0x7f99: return et4000->acl.internal.count_x >> 8; - case 0x7f9a: return et4000->acl.internal.count_y; - case 0x7f9b: return et4000->acl.internal.count_y >> 8; - case 0x7f9c: return et4000->acl.internal.ctrl_routing; - case 0x7f9d: return et4000->acl.internal.ctrl_reload; - case 0x7f9e: return et4000->acl.internal.rop_bg; - case 0x7f9f: return et4000->acl.internal.rop_fg; - case 0x7fa0: return et4000->acl.internal.dest_addr; - case 0x7fa1: return et4000->acl.internal.dest_addr >> 8; - case 0x7fa2: return et4000->acl.internal.dest_addr >> 16; - case 0x7fa3: return et4000->acl.internal.dest_addr >> 24; + case 0x8f: return et4000->acl.internal.xy_dir; + case 0x90: return et4000->acl.internal.pattern_wrap; + case 0x92: return et4000->acl.internal.source_wrap; + case 0x98: return et4000->acl.internal.count_x & 0xff; + case 0x99: return et4000->acl.internal.count_x >> 8; + case 0x9a: return et4000->acl.internal.count_y & 0xff; + case 0x9b: return et4000->acl.internal.count_y >> 8; + case 0x9c: return et4000->acl.internal.ctrl_routing; + case 0x9d: return et4000->acl.internal.ctrl_reload; + case 0x9e: return et4000->acl.internal.rop_bg; + case 0x9f: return et4000->acl.internal.rop_fg; + case 0xa0: return et4000->acl.internal.dest_addr & 0xff; + case 0xa1: return et4000->acl.internal.dest_addr >> 8; + case 0xa2: return et4000->acl.internal.dest_addr >> 16; + case 0xa3: return et4000->acl.internal.dest_addr >> 24; } return 0xff; @@ -883,16 +1021,19 @@ et4000w32p_mmu_read(uint32_t addr, void *p) void et4000w32_blit_start(et4000w32p_t *et4000) { - et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; - et4000->acl.source_addr = et4000->acl.internal.source_addr; - et4000->acl.dest_addr = et4000->acl.internal.dest_addr; - et4000->acl.dest_back = et4000->acl.dest_addr; - et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0; - et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; + et4000->acl.x_count = et4000->acl.internal.count_x; + et4000->acl.y_count = et4000->acl.internal.count_y; + + et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; + et4000->acl.source_addr = et4000->acl.internal.source_addr; + et4000->acl.dest_addr = et4000->acl.internal.dest_addr; + et4000->acl.dest_back = et4000->acl.dest_addr; + et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; et4000->acl.status |= ACL_XYST; + et4000->acl.status &= ~ACL_SSO; - if (!(et4000->acl.internal.ctrl_routing & 7)) + if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) et4000->acl.status |= ACL_SSO; if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { @@ -900,10 +1041,11 @@ et4000w32_blit_start(et4000w32p_t *et4000) et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; } et4000->acl.pattern_back = et4000->acl.pattern_addr; + if (!(et4000->acl.internal.pattern_wrap & 0x40)) { - if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) + if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ et4000->acl.pattern_y = (et4000->acl.pattern_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); - else + } else et4000->acl.pattern_y = (et4000->acl.pattern_addr / (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); et4000->acl.pattern_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) - 1); } @@ -913,13 +1055,12 @@ et4000w32_blit_start(et4000w32p_t *et4000) et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; } - et4000->acl.source_back = et4000->acl.source_addr; if (!(et4000->acl.internal.source_wrap & 0x40)) { - if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) + if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ et4000->acl.source_y = (et4000->acl.source_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); - else + } else et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); } @@ -927,9 +1068,12 @@ et4000w32_blit_start(et4000w32p_t *et4000) } -void +static void et4000w32p_blit_start(et4000w32p_t *et4000) { + et4000->acl.x_count = et4000->acl.internal.count_x; + et4000->acl.y_count = et4000->acl.internal.count_y; + if (!(et4000->acl.queued.xy_dir & 0x20)) et4000->acl.internal.error = et4000->acl.internal.dmaj / 2; et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; @@ -941,6 +1085,7 @@ et4000w32p_blit_start(et4000w32p_t *et4000) et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0; et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; et4000->acl.status |= ACL_XYST; + et4000w32_log("ACL status XYST set\n"); if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) et4000->acl.status |= ACL_SSO; @@ -961,13 +1106,14 @@ et4000w32p_blit_start(et4000w32p_t *et4000) et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; } et4000->acl.source_back = et4000->acl.source_addr; + if (!(et4000->acl.internal.source_wrap & 0x40)) { et4000->acl.source_y = (et4000->acl.source_addr / (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); et4000->acl.source_back &= ~(((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) * et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) - 1); } et4000->acl.source_x_back = et4000->acl.source_x; - et4000w32_max_x[2] = ((et4000->acl.internal.pixel_depth & 0x30) == 0x20) ? 3 : 4; + et4000w32_max_x[2] = (et4000->acl.internal.pixel_depth == 0x20) ? 3 : 4; et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3; et4000->acl.cpu_dat_pos = 0; @@ -1040,24 +1186,393 @@ et4000w32_decy(et4000w32p_t *et4000) et4000->acl.source_y--; if (et4000->acl.source_y < 0 && !(et4000->acl.internal.source_wrap & 0x40)) { et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1; - et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] *(et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1));; + et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] *(et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1)); } } -void +#define ROPMIX(R, D, P, S, out) \ + { \ + switch (R) { \ + case 0x00: out = 0; break; \ + case 0x01: out = ~(D | (P | S)); break; \ + case 0x02: out = D & ~(P | S); break; \ + case 0x03: out = ~(P | S); break; \ + case 0x04: out = S & ~(D | P); break; \ + case 0x05: out = ~(D | P); break; \ + case 0x06: out = ~(P | ~(D ^ S)); break; \ + case 0x07: out = ~(P | (D & S)); break; \ + case 0x08: out = S & (D & ~P); break; \ + case 0x09: out = ~(P | (D ^ S)); break; \ + case 0x0a: out = D & ~P; break; \ + case 0x0b: out = ~(P | (S & ~D)); break; \ + case 0x0c: out = S & ~P; break; \ + case 0x0d: out = ~(P | (D & ~S)); break; \ + case 0x0e: out = ~(P | ~(D | S)); break; \ + case 0x0f: out = ~P; break; \ + case 0x10: out = P & ~(D | S); break; \ + case 0x11: out = ~(D | S); break; \ + case 0x12: out = ~(S | ~(D ^ P)); break; \ + case 0x13: out = ~(S | (D & P)); break; \ + case 0x14: out = ~(D | ~(P ^ S)); break; \ + case 0x15: out = ~(D | (P & S)); break; \ + case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ + case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ + case 0x18: out = (S ^ P) & (P ^ D); break; \ + case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ + case 0x1a: out = P ^ (D | (S & P)); break; \ + case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ + case 0x1c: out = P ^ (S | (D & P)); break; \ + case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ + case 0x1e: out = P ^ (D | S); break; \ + case 0x1f: out = ~(P & (D | S)); break; \ + case 0x20: out = D & (P & ~S); break; \ + case 0x21: out = ~(S | (D ^ P)); break; \ + case 0x22: out = D & ~S; break; \ + case 0x23: out = ~(S | (P & ~D)); break; \ + case 0x24: out = (S ^ P) & (D ^ S); break; \ + case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ + case 0x26: out = S ^ (D | (P & S)); break; \ + case 0x27: out = S ^ (D | ~(P ^ S)); break; \ + case 0x28: out = D & (P ^ S); break; \ + case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ + case 0x2a: out = D & ~(P & S); break; \ + case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ + case 0x2c: out = S ^ (P & (D | S)); break; \ + case 0x2d: out = P ^ (S | ~D); break; \ + case 0x2e: out = P ^ (S | (D ^ P)); break; \ + case 0x2f: out = ~(P & (S | ~D)); break; \ + case 0x30: out = P & ~S; break; \ + case 0x31: out = ~(S | (D & ~P)); break; \ + case 0x32: out = S ^ (D | (P | S)); break; \ + case 0x33: out = ~S; break; \ + case 0x34: out = S ^ (P | (D & S)); break; \ + case 0x35: out = S ^ (P | ~(D ^ S)); break; \ + case 0x36: out = S ^ (D | P); break; \ + case 0x37: out = ~(S & (D | P)); break; \ + case 0x38: out = P ^ (S & (D | P)); break; \ + case 0x39: out = S ^ (P | ~D); break; \ + case 0x3a: out = S ^ (P | (D ^ S)); break; \ + case 0x3b: out = ~(S & (P | ~D)); break; \ + case 0x3c: out = P ^ S; break; \ + case 0x3d: out = S ^ (P | ~(D | S)); break; \ + case 0x3e: out = S ^ (P | (D & ~S)); break; \ + case 0x3f: out = ~(P & S); break; \ + case 0x40: out = P & (S & ~D); break; \ + case 0x41: out = ~(D | (P ^ S)); break; \ + case 0x42: out = (S ^ D) & (P ^ D); break; \ + case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ + case 0x44: out = S & ~D; break; \ + case 0x45: out = ~(D | (P & ~S)); break; \ + case 0x46: out = D ^ (S | (P & D)); break; \ + case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ + case 0x48: out = S & (D ^ P); break; \ + case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ + case 0x4a: out = D ^ (P & (S | D)); break; \ + case 0x4b: out = P ^ (D | ~S); break; \ + case 0x4c: out = S & ~(D & P); break; \ + case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ + case 0x4e: out = P ^ (D | (S ^ P)); break; \ + case 0x4f: out = ~(P & (D | ~S)); break; \ + case 0x50: out = P & ~D; break; \ + case 0x51: out = ~(D | (S & ~P)); break; \ + case 0x52: out = D ^ (P | (S & D)); break; \ + case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ + case 0x54: out = ~(D | ~(P | S)); break; \ + case 0x55: out = ~D; break; \ + case 0x56: out = D ^ (P | S); break; \ + case 0x57: out = ~(D & (P | S)); break; \ + case 0x58: out = P ^ (D & (S | P)); break; \ + case 0x59: out = D ^ (P | ~S); break; \ + case 0x5a: out = D ^ P; break; \ + case 0x5b: out = D ^ (P | ~(S | D)); break; \ + case 0x5c: out = D ^ (P | (S ^ D)); break; \ + case 0x5d: out = ~(D & (P | ~S)); break; \ + case 0x5e: out = D ^ (P | (S & ~D)); break; \ + case 0x5f: out = ~(D & P); break; \ + case 0x60: out = P & (D ^ S); break; \ + case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ + case 0x62: out = D ^ (S & (P | D)); break; \ + case 0x63: out = S ^ (D | ~P); break; \ + case 0x64: out = S ^ (D & (P | S)); break; \ + case 0x65: out = D ^ (S | ~P); break; \ + case 0x66: out = D ^ S; break; \ + case 0x67: out = S ^ (D | ~(P | S)); break; \ + case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ + case 0x69: out = ~(P ^ (D ^ S)); break; \ + case 0x6a: out = D ^ (P & S); break; \ + case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ + case 0x6c: out = S ^ (D & P); break; \ + case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ + case 0x6e: out = S ^ (D & (P | ~S)); break; \ + case 0x6f: out = ~(P & ~(D ^ S)); break; \ + case 0x70: out = P & ~(D & S); break; \ + case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ + case 0x72: out = S ^ (D | (P ^ S)); break; \ + case 0x73: out = ~(S & (D | ~P)); break; \ + case 0x74: out = D ^ (S | (P ^ D)); break; \ + case 0x75: out = ~(D & (S | ~P)); break; \ + case 0x76: out = S ^ (D | (P & ~S)); break; \ + case 0x77: out = ~(D & S); break; \ + case 0x78: out = P ^ (D & S); break; \ + case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ + case 0x7a: out = D ^ (P & (S | ~D)); break; \ + case 0x7b: out = ~(S & ~(D ^ P)); break; \ + case 0x7c: out = S ^ (P & (D | ~S)); break; \ + case 0x7d: out = ~(D & ~(P ^ S)); break; \ + case 0x7e: out = (S ^ P) | (D ^ S); break; \ + case 0x7f: out = ~(D & (P & S)); break; \ + case 0x80: out = D & (P & S); break; \ + case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ + case 0x82: out = D & ~(P ^ S); break; \ + case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ + case 0x84: out = S & ~(D ^ P); break; \ + case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ + case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ + case 0x87: out = ~(P ^ (D & S)); break; \ + case 0x88: out = D & S; break; \ + case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ + case 0x8a: out = D & (S | ~P); break; \ + case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ + case 0x8c: out = S & (D | ~P); break; \ + case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ + case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ + case 0x8f: out = ~(P & ~(D & S)); break; \ + case 0x90: out = P & ~(D ^ S); break; \ + case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ + case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ + case 0x93: out = ~(S ^ (P & D)); break; \ + case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ + case 0x95: out = ~(D ^ (P & S)); break; \ + case 0x96: out = D ^ (P ^ S); break; \ + case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ + case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ + case 0x99: out = ~(D ^ S); break; \ + case 0x9a: out = D ^ (P & ~S); break; \ + case 0x9b: out = ~(S ^ (D & (P | S))); break; \ + case 0x9c: out = S ^ (P & ~D); break; \ + case 0x9d: out = ~(D ^ (S & (P | D))); break; \ + case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ + case 0x9f: out = ~(P & (D ^ S)); break; \ + case 0xa0: out = D & P; break; \ + case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ + case 0xa2: out = D & (P | ~S); break; \ + case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ + case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ + case 0xa5: out = ~(P ^ D); break; \ + case 0xa6: out = D ^ (S & ~P); break; \ + case 0xa7: out = ~(P ^ (D & (S | P))); break; \ + case 0xa8: out = D & (P | S); break; \ + case 0xa9: out = ~(D ^ (P | S)); break; \ + case 0xaa: out = D; break; \ + case 0xab: out = D | ~(P | S); break; \ + case 0xac: out = S ^ (P & (D ^ S)); break; \ + case 0xad: out = ~(D ^ (P | (S & D))); break; \ + case 0xae: out = D | (S & ~P); break; \ + case 0xaf: out = D | ~P; break; \ + case 0xb0: out = P & (D | ~S); break; \ + case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ + case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ + case 0xb3: out = ~(S & ~(D & P)); break; \ + case 0xb4: out = P ^ (S & ~D); break; \ + case 0xb5: out = ~(D ^ (P & (S | D))); break; \ + case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ + case 0xb7: out = ~(S & (D ^ P)); break; \ + case 0xb8: out = P ^ (S & (D ^ P)); break; \ + case 0xb9: out = ~(D ^ (S | (P & D))); break; \ + case 0xba: out = D | (P & ~S); break; \ + case 0xbb: out = D | ~S; break; \ + case 0xbc: out = S ^ (P & ~(D & S)); break; \ + case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ + case 0xbe: out = D | (P ^ S); break; \ + case 0xbf: out = D | ~(P & S); break; \ + case 0xc0: out = P & S; break; \ + case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ + case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ + case 0xc3: out = ~(P ^ S); break; \ + case 0xc4: out = S & (P | ~D); break; \ + case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ + case 0xc6: out = S ^ (D & ~P); break; \ + case 0xc7: out = ~(P ^ (S & (D | P))); break; \ + case 0xc8: out = S & (D | P); break; \ + case 0xc9: out = ~(S ^ (P | D)); break; \ + case 0xca: out = D ^ (P & (S ^ D)); break; \ + case 0xcb: out = ~(S ^ (P | (D & S))); break; \ + case 0xcc: out = S; break; \ + case 0xcd: out = S | ~(D | P); break; \ + case 0xce: out = S | (D & ~P); break; \ + case 0xcf: out = S | ~P; break; \ + case 0xd0: out = P & (S | ~D); break; \ + case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ + case 0xd2: out = P ^ (D & ~S); break; \ + case 0xd3: out = ~(S ^ (P & (D | S))); break; \ + case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ + case 0xd5: out = ~(D & ~(P & S)); break; \ + case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ + case 0xd7: out = ~(D & (P ^ S)); break; \ + case 0xd8: out = P ^ (D & (S ^ P)); break; \ + case 0xd9: out = ~(S ^ (D | (P & S))); break; \ + case 0xda: out = D ^ (P & ~(S & D)); break; \ + case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ + case 0xdc: out = S | (P & ~D); break; \ + case 0xdd: out = S | ~D; break; \ + case 0xde: out = S | (D ^ P); break; \ + case 0xdf: out = S | ~(D & P); break; \ + case 0xe0: out = P & (D | S); break; \ + case 0xe1: out = ~(P ^ (D | S)); break; \ + case 0xe2: out = D ^ (S & (P ^ D)); break; \ + case 0xe3: out = ~(P ^ (S | (D & P))); break; \ + case 0xe4: out = S ^ (D & (P ^ S)); break; \ + case 0xe5: out = ~(P ^ (D | (S & P))); break; \ + case 0xe6: out = S ^ (D & ~(P & S)); break; \ + case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ + case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ + case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ + case 0xea: out = D | (P & S); break; \ + case 0xeb: out = D | ~(P ^ S); break; \ + case 0xec: out = S | (D & P); break; \ + case 0xed: out = S | ~(D ^ P); break; \ + case 0xee: out = D | S; break; \ + case 0xef: out = S | (D | ~P); break; \ + case 0xf0: out = P; break; \ + case 0xf1: out = P | ~(D | S); break; \ + case 0xf2: out = P | (D & ~S); break; \ + case 0xf3: out = P | ~S; break; \ + case 0xf4: out = P | (S & ~D); break; \ + case 0xf5: out = P | ~D; break; \ + case 0xf6: out = P | (D ^ S); break; \ + case 0xf7: out = P | ~(D & S); break; \ + case 0xf8: out = P | (D & S); break; \ + case 0xf9: out = P | ~(D ^ S); break; \ + case 0xfa: out = D | P; break; \ + case 0xfb: out = D | (P | ~S); break; \ + case 0xfc: out = P | S; break; \ + case 0xfd: out = P | (S | ~D); break; \ + case 0xfe: out = D | (P | S); break; \ + case 0xff: out = ~0; break; \ + } \ + } + +static void +et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000) +{ + svga_t *svga = &et4000->svga; + uint8_t pattern, source, dest; + uint8_t rop; + int mixmap; + + while (count-- && et4000->acl.y_count >= 0) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + + if (cpu_input == 1) { + source = src_dat & 0xff; + src_dat >>= 8; + } else /*The source data is from the display memory if the Control Routing register is not set to 1*/ + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + mixmap = mix_dat & 1; + + /*Now determine the Raster Operation*/ + rop = mixmap ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; + mix_dat >>= 1; + mix_dat |= 0x80000000; + + ROPMIX(rop, dest, pattern, source, dest); + + /*Write the data*/ + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = dest; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + + if (et4000->acl.internal.xy_dir & 1) { + et4000->acl.dest_addr--; + et4000->acl.pattern_x--; + et4000->acl.source_x--; + if (et4000->acl.pattern_x < 0) + et4000->acl.pattern_x += (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1); + if (et4000->acl.source_x < 0) + et4000->acl.source_x += (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1); + } else { + et4000->acl.dest_addr++; + et4000->acl.pattern_x++; + et4000->acl.source_x++; + if (et4000->acl.pattern_x >= (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1)) + et4000->acl.pattern_x -= (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1); + if (et4000->acl.source_x >= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) + et4000->acl.source_x -= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1); + } + + et4000->acl.x_count--; + if (et4000->acl.x_count == 0xffff) { + et4000->acl.x_count = et4000->acl.internal.count_x; + + if (et4000->acl.internal.xy_dir & 2) { + et4000->acl.pattern_addr -= (et4000->acl.internal.pattern_off + 1); + et4000->acl.source_addr -= (et4000->acl.internal.source_off + 1); + et4000->acl.dest_addr -= (et4000->acl.internal.dest_off + 1); + et4000->acl.pattern_y--; + if ((et4000->acl.pattern_y < 0) && !(et4000->acl.internal.pattern_wrap & 0x40)) { + et4000->acl.pattern_y = et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1; + et4000->acl.pattern_addr = et4000->acl.pattern_back + (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1)); + } + et4000->acl.source_y--; + if ((et4000->acl.source_y < 0) && !(et4000->acl.internal.source_wrap & 0x40)) { + et4000->acl.source_y = et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1; + et4000->acl.source_addr = et4000->acl.source_back + (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] * (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1)); + } + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000->acl.pattern_addr += (et4000->acl.internal.pattern_off + 1); + et4000->acl.source_addr += (et4000->acl.internal.source_off + 1); + et4000->acl.dest_addr += (et4000->acl.internal.dest_off + 1); + et4000->acl.pattern_y++; + if (et4000->acl.pattern_y == et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]) { + et4000->acl.pattern_y = 0; + et4000->acl.pattern_addr = et4000->acl.pattern_back; + } + et4000->acl.source_y++; + if (et4000->acl.source_y == et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7]) { + et4000->acl.source_y = 0; + et4000->acl.source_addr = et4000->acl.source_back; + } + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + (et4000->acl.internal.dest_off + 1); + } + + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + et4000->acl.y_count--; + if (et4000->acl.y_count == 0xffff) { + et4000->acl.status &= ~ACL_XYST; + if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) { + et4000w32_log("W32i: end blit, xcount = %i\n", et4000->acl.x_count); + et4000->acl.status &= ~ACL_SSO; + } + et4000->acl.cpu_input_num = 0; + return; + } + + if (cpu_input) + return; + } + } +} + +static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; - int c, d; uint8_t pattern, source, dest, out; uint8_t rop; int mixdat; - if (!(et4000->acl.status & ACL_XYST) && (et4000->type >= ET4000W32P_REVC)) - return; + if (!(et4000->acl.status & ACL_XYST)) { + et4000w32_log("XY Block not started\n"); + return; + } if (et4000->acl.internal.xy_dir & 0x80) { /* Line draw */ + et4000w32_log("Line draw\n"); while (count--) { et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; @@ -1080,12 +1595,9 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 } et4000->acl.mix_addr++; rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - for (c = 0; c < 8; c++) { - d = (dest & (1 << c)) ? 1 : 0; - if (source & (1 << c)) d |= 2; - if (pattern & (1 << c)) d |= 4; - if (rop & (1 << d)) out |= (1 << c); - } + + ROPMIX(rop, dest, pattern, source, out); + et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & et4000->vram_mask, out); if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; @@ -1157,80 +1669,77 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 } } } else { - while (count--) { - et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); + et4000w32_log("BitBLT: count = %i\n", count); + while (count-- && et4000->acl.y_count >= 0) { + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; - pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; - source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - et4000w32_log("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask, pattern, source); - - if (cpu_input == 2) { - source = sdat & 0xff; - sdat >>= 8; - } - dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; - out = 0; - et4000w32_log("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr); - if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { - mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); - et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask]); - } else { - mixdat = mix & 1; - mix >>= 1; - mix |= 0x80000000; - } - - rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - for (c = 0; c < 8; c++) { - d = (dest & (1 << c)) ? 1 : 0; - if (source & (1 << c)) d |= 2; - if (pattern & (1 << c)) d |= 4; - if (rop & (1 << d)) out |= (1 << c); - } - et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & et4000->vram_mask, out); - if (!(et4000->acl.internal.ctrl_routing & 0x40)) { - svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; - svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; - } else { - et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8)); - et4000->acl.cpu_dat_pos++; - } - - if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000); - else et4000w32_incx(1, et4000); - - et4000->acl.internal.pos_x++; - if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x) { - if (et4000->acl.internal.xy_dir & 2) { - et4000w32_decy(et4000); - et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1); - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + if (cpu_input == 2) { + source = sdat & 0xff; + sdat >>= 8; + } else + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + out = 0; + + if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { + mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); } else { - et4000w32_incy(et4000); - et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1; - et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + mixdat = mix & 1; + mix >>= 1; + mix |= 0x80000000; } - et4000->acl.pattern_x = et4000->acl.pattern_x_back; - et4000->acl.source_x = et4000->acl.source_x_back; + rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - et4000->acl.internal.pos_y++; - et4000->acl.internal.pos_x = 0; - if (et4000->acl.internal.pos_y > et4000->acl.internal.count_y) { - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); - return; + ROPMIX(rop, dest, pattern, source, out); + + if (!(et4000->acl.internal.ctrl_routing & 0x40)) { + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; + svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; + } else { + et4000->acl.cpu_dat |= ((uint64_t)out << (et4000->acl.cpu_dat_pos * 8)); + et4000->acl.cpu_dat_pos++; } - if (cpu_input) - return; + if (et4000->acl.internal.xy_dir & 1) + et4000w32_decx(1, et4000); + else + et4000w32_incx(1, et4000); + + et4000->acl.x_count--; + if (et4000->acl.x_count == 0xffff) { + if (et4000->acl.internal.xy_dir & 2) { + et4000w32_decy(et4000); + et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back - (et4000->acl.internal.mix_off + 1); + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back - (et4000->acl.internal.dest_off + 1); + } else { + et4000w32_incy(et4000); + et4000->acl.mix_back = et4000->acl.mix_addr = et4000->acl.mix_back + et4000->acl.internal.mix_off + 1; + et4000->acl.dest_back = et4000->acl.dest_addr = et4000->acl.dest_back + et4000->acl.internal.dest_off + 1; + } - if (et4000->acl.internal.ctrl_routing & 0x40) { - if (et4000->acl.cpu_dat_pos & 3) - et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3); - return; + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + et4000->acl.y_count--; + et4000->acl.x_count = et4000->acl.internal.count_x; + if (et4000->acl.y_count == 0xffff) { + et4000w32_log("BitBLT end\n"); + et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + return; + } + + if (cpu_input) + return; + + if (et4000->acl.internal.ctrl_routing & 0x40) { + if (et4000->acl.cpu_dat_pos & 3) + et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3); + return; + } } } - } } } diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 107a1773f..d32871c22 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -40,7 +40,7 @@ typedef struct paradise_t rom_t bios_rom; - uint8_t pr0a, pr0b, pr1, pr5, bank_mask; + uint8_t bank_mask; enum { @@ -54,7 +54,7 @@ typedef struct paradise_t uint32_t read_bank[4], write_bank[4]; int interlace; - int check; + int check, check2; struct { uint8_t reg_block_ptr; @@ -81,7 +81,7 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) { paradise_t *paradise = (paradise_t *)p; svga_t *svga = ¶dise->svga; - uint8_t old, o; + uint8_t old; if (paradise->vram_mask <= ((512 << 10) - 1)) paradise->bank_mask = 0x7f; @@ -94,15 +94,14 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c5: - if (svga->seqaddr > 7) - { - if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) - return; - svga->seqregs[svga->seqaddr & 0x1f] = val; - if (svga->seqaddr == 0x11) { - paradise_remap(paradise); - } - return; + if (svga->seqaddr > 7) { + if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) + return; + svga->seqregs[svga->seqaddr & 0x1f] = val; + if (svga->seqaddr == 0x11) { + paradise_remap(paradise); + } + return; } break; @@ -115,53 +114,45 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) case 0x3cf: if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { - if ((paradise->pr5 & 7) != 5) + if ((svga->gdcreg[0x0f] & 7) != 5) return; } + switch (svga->gdcaddr) { case 6: - if (val & 8) - svga->banked_mask = 0x7fff; - else - svga->banked_mask = 0xffff; - if (svga->gdcreg[6] != val) - svga->gdcreg[6] = val; + if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { + switch (val & 0x0c) { + case 0x00: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x04: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x08: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0x0c: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } + svga->gdcreg[6] = val; paradise_remap(paradise); - break; + return; case 9: - paradise->pr0a = val & paradise->bank_mask; - paradise_remap(paradise); - break; case 0x0a: - paradise->pr0b = val & paradise->bank_mask; + svga->gdcreg[svga->gdcaddr] = val & paradise->bank_mask; paradise_remap(paradise); - break; + return; case 0x0b: - paradise->pr1 = val; + svga->gdcreg[0x0b] = val; paradise_remap(paradise); - break; - case 0x0d: - o = svga->gdcreg[0x0d]; - svga->gdcreg[0x0d] = val; - if ((o ^ val) & 0x18) - svga_recalctimings(svga); - break; - case 0x0e: - o = svga->gdcreg[0x0e]; - svga->gdcreg[0x0e] = val; - if ((o ^ val) & 0x01) - svga_recalctimings(svga); - break; - case 0x0c: - svga->gdcreg[0x0c] = val; - break; - case 0x0f: - paradise->pr5 = val; - break; - default: - svga->gdcreg[svga->gdcaddr] = val; - break; + return; } break; @@ -216,10 +207,8 @@ uint8_t paradise_in(uint16_t addr, void *p) { if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) return 0xff; - if (paradise->type < WD90C30) { - if (svga->seqaddr > 0x12) + if (svga->seqaddr > 0x12) return 0xff; - } return svga->seqregs[svga->seqaddr & 0x1f]; } break; @@ -231,36 +220,21 @@ uint8_t paradise_in(uint16_t addr, void *p) case 0x3cf: if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { - if (paradise->pr5 & 0x10) + if (svga->gdcreg[0x0f] & 0x10) return 0xff; } switch (svga->gdcaddr) { - case 9: - return paradise->pr0a; - case 0x0a: - return paradise->pr0b; case 0x0b: - if (paradise->vram_mask == (512 << 10) - 1) { - paradise->pr1 |= 0xc0; - paradise->pr1 &= ~0x40; - } else if (paradise->vram_mask == (1024 << 10) - 1) { - paradise->pr1 |= 0xc0; - /*The following is a horrible tweak, but needed to get around black corruption in 1M mode*/ - if (svga->bpp >= 8 && (svga->gdcreg[0x0e] & 0x01) && paradise->check) - paradise->pr1 &= ~0x40; - else if (!(svga->gdcreg[0x0e] & 0x01) && !(svga->crtc[0x14] & 0x40) && paradise->check) - paradise->check = 0; + if (paradise->type == WD90C30) { + if (paradise->vram_mask == ((512 << 10) - 1)) { + svga->gdcreg[0x0b] |= 0xc0; + svga->gdcreg[0x0b] &= ~0x40; + } } - return paradise->pr1; - case 6: - case 0x0c: - case 0x0d: - case 0x0e: - return svga->gdcreg[svga->gdcaddr]; + return svga->gdcreg[0x0b]; + case 0x0f: - return (paradise->pr5 & 0x17) | 0x80; - default: - return svga->gdcreg[svga->gdcaddr]; + return (svga->gdcreg[0x0f] & 0x17) | 0x80; } break; @@ -278,61 +252,46 @@ uint8_t paradise_in(uint16_t addr, void *p) void paradise_remap(paradise_t *paradise) { - svga_t *svga = ¶dise->svga; + svga_t *svga = ¶dise->svga; + paradise->check = 0; - if (svga->seqregs[0x11] & 0x80) { - paradise->read_bank[0] = (paradise->pr0a) << 12; - paradise->read_bank[1] = paradise->read_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->read_bank[0]; - paradise->read_bank[3] = paradise->read_bank[1]; - paradise->write_bank[0] = (paradise->pr0b) << 12; - paradise->write_bank[1] = paradise->write_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[2] = paradise->write_bank[0]; - paradise->write_bank[3] = paradise->write_bank[1]; - } else if (paradise->pr1 & 8) { - if (svga->gdcreg[6] & 0x0c) { - paradise->read_bank[0] = (paradise->pr0b) << 12; - paradise->read_bank[1] = ((paradise->pr0a) << 12) + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->read_bank[0]; - paradise->read_bank[3] = paradise->read_bank[1]; - paradise->write_bank[0] = (paradise->pr0b) << 12; - paradise->write_bank[1] = ((paradise->pr0a) << 12) + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[2] = paradise->write_bank[0]; - paradise->write_bank[3] = paradise->write_bank[1]; - } else { - paradise->read_bank[0] = (paradise->pr0b) << 12; - paradise->read_bank[1] = paradise->read_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->read_bank[2] = (paradise->pr0a) << 12; - paradise->read_bank[3] = paradise->read_bank[2] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[0] = (paradise->pr0b) << 12; - paradise->write_bank[1] = paradise->write_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[2] = (paradise->pr0a) << 12; - paradise->write_bank[3] = paradise->write_bank[2] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - } - } else { - paradise->read_bank[0] = (paradise->pr0a) << 12; - paradise->write_bank[0] = (paradise->pr0a) << 12; - paradise->read_bank[1] = paradise->read_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[1] = paradise->write_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->read_bank[0]; - paradise->write_bank[2] = paradise->write_bank[0]; - paradise->read_bank[3] = paradise->read_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - paradise->write_bank[3] = paradise->write_bank[0] + ((svga->gdcreg[6] & 8) ? 0 : 0x8000); - } - - if (paradise->bank_mask == 0x7f) { - paradise->read_bank[1] &= 0x7ffff; - paradise->write_bank[1] &= 0x7ffff; + if (svga->seqregs[0x11] & 0x80) { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[0x0a] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } else if (svga->gdcreg[0x0b] & 0x08) { + if (svga->gdcreg[6] & 0x0c) { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } else { + paradise->read_bank[0] = paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->write_bank[1] = (svga->gdcreg[0xa] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->read_bank[2] = paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[3] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); } + } else { + paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); + } + + if ((((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4 && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[6] >> 2) & 3) == 1)) + paradise->check = 1; + + if (paradise->bank_mask == 0x7f) { + paradise->read_bank[1] &= 0x7ffff; + paradise->write_bank[1] &= 0x7ffff; + } } void paradise_recalctimings(svga_t *svga) { paradise_t *paradise = (paradise_t *) svga->p; - if (svga->gdcreg[0x0d] & 0x08) svga->ma_latch |= 0x10000; - if (svga->gdcreg[0x0d] & 0x10) svga->ma_latch |= 0x20000; - svga->lowres = !(svga->gdcreg[0x0e] & 0x01); if (paradise->type == WD90C30) { @@ -355,8 +314,6 @@ void paradise_recalctimings(svga_t *svga) if (paradise->type < WD90C30) { if (svga->bpp >= 8 && !svga->lowres) { - if ((svga->crtc[0x17] == 0xc2) && (svga->crtc[0x14] & 0x40)) - paradise->check = 1; svga->render = svga_render_8bpp_highres; } } else { @@ -368,8 +325,6 @@ void paradise_recalctimings(svga_t *svga) svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; } else { - if ((svga->crtc[0x17] == 0xc2) && (svga->crtc[0x14] & 0x40)) - paradise->check = 1; svga->render = svga_render_8bpp_highres; } } @@ -380,20 +335,94 @@ static void paradise_write(uint32_t addr, uint8_t val, void *p) { paradise_t *paradise = (paradise_t *)p; svga_t *svga = ¶dise->svga; + uint32_t prev_addr, prev_addr2; - addr &= svga->banked_mask; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + svga_write_linear(addr, val, svga); } static void paradise_writew(uint32_t addr, uint16_t val, void *p) { paradise_t *paradise = (paradise_t *)p; svga_t *svga = ¶dise->svga; + uint32_t prev_addr, prev_addr2; - addr &= svga->banked_mask; addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } + svga_writew_linear(addr, val, svga); } @@ -401,9 +430,46 @@ static uint8_t paradise_read(uint32_t addr, void *p) { paradise_t *paradise = (paradise_t *)p; svga_t *svga = ¶dise->svga; - - addr &= svga->banked_mask; + uint32_t prev_addr, prev_addr2; + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } return svga_read_linear(addr, svga); } @@ -411,11 +477,48 @@ static uint16_t paradise_readw(uint32_t addr, void *p) { paradise_t *paradise = (paradise_t *)p; svga_t *svga = ¶dise->svga; - - addr &= svga->banked_mask; + uint32_t prev_addr, prev_addr2; + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + + /*Could be done in a better way but it works.*/ + if (!svga->lowres) { + if (paradise->check) { + prev_addr = addr & 3; + prev_addr2 = addr & 0xfffc; + if ((addr & 3) == 3) { + if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 2) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 1) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x00000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } else if ((addr & 3) == 0) { + if ((addr & 0x30000) == 0x30000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x20000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + else if ((addr & 0x30000) == 0x10000) + addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; + } + } + } - return svga_readw_linear(addr, svga); + return svga_readw_linear(addr, svga); } void *paradise_init(const device_t *info, uint32_t memsize) @@ -653,9 +756,6 @@ static const device_config_t paradise_pvga1a_config[] = { "512 kB", 512 }, - { - "1 MB", 1024 - }, { "" } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7dff04e4a..30c0df216 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -62,9 +62,11 @@ #define ROM_DIAMOND_STEALTH_SE "roms/video/s3/DiamondStealthSE.VBI" #define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" #define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" +#define ROM_NUMBER9_9FX_531 "roms/video/s3/numbernine.BIN" #define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" #define ROM_MIROVIDEO40SV_ERGO_968_PCI "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" #define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" +#define ROM_NUMBER9_9FX_771 "roms/video/s3/no9motionfx771.BIN" #define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" enum @@ -100,7 +102,9 @@ enum S3_MIROCRYSTAL20SV_964, S3_MIROCRYSTAL20SD_864, S3_PHOENIX_VISION968, - S3_MIROCRYSTAL8S_805 + S3_MIROCRYSTAL8S_805, + S3_NUMBER9_9FX_531, + S3_NUMBER9_9FX_771 }; @@ -1140,18 +1144,30 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[0] = val; if (s3->accel.cmd & 0x100) { - if (!(s3->accel.cmd & 0x600)) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } else { - if (s3->color_16bit) - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + if (s3->color_16bit) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3); + } else { + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3); + } + break; } } break; @@ -2442,7 +2458,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || - s3->card_type == S3_PHOENIX_VISION968))) + s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); @@ -2451,7 +2467,9 @@ s3_out(uint16_t addr, uint8_t val, void *p) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip <= S3_86C924) { sc1148x_ramdac_out(addr, rs2, val, svga->ramdac, svga); - } else + } else if (s3->card_type == S3_NUMBER9_9FX_531) + att498_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga); return; @@ -2728,7 +2746,7 @@ s3_in(uint16_t addr, void *p) rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || - s3->card_type == S3_PHOENIX_VISION968))) + s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); @@ -2737,6 +2755,8 @@ s3_in(uint16_t addr, void *p) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, rs2, svga->ramdac, svga); + else if (s3->card_type == S3_NUMBER9_9FX_531) + return att498_ramdac_in(addr, rs2, svga->ramdac, svga); else return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); break; @@ -2839,7 +2859,7 @@ static void s3_recalctimings(svga_t *svga) else ibm_rgb528_recalctimings(svga->ramdac, svga); } else - svga->interlace = svga->crtc[0x42] & 0x20; + svga->interlace = !!(svga->crtc[0x42] & 0x20); if ((((svga->miscout >> 2) & 3) == 3) && s3->chip < S3_TRIO32) clk_sel = svga->crtc[0x42] & 0x0f; @@ -2856,10 +2876,25 @@ static void s3_recalctimings(svga_t *svga) if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || - s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || + s3->card_type == S3_NUMBER9_9FX_531) { + if (!(svga->crtc[0x5e] & 0x04)) + svga->vblankstart = svga->dispend; if (svga->bpp != 32) { if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ s3->width = 2048; + else { + if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (svga->hdisp == 1280 && s3->width == 1024) { + s3->width = 1280; + } + } + } + } else { + if (s3->card_type == S3_NUMBER9_9FX_531) { + if (svga->hdisp == 1600 && s3->width == 1600) + s3->width = 800; + } } } else if (s3->chip == S3_86C928) { if (svga->bpp == 15) { @@ -2889,15 +2924,16 @@ static void s3_recalctimings(svga_t *svga) if (s3->chip != S3_VISION868) { if (s3->chip == S3_86C928) { if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) - svga->hdisp *= 2; + svga->hdisp <<= 1; } else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { if (s3->width == 1280 || s3->width == 1600) - svga->hdisp *= 2; + svga->hdisp <<= 1; } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { if (s3->width == 1280 || s3->width == 1600) - svga->hdisp *= 2; - } + svga->hdisp <<= 1; + } else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { @@ -2948,19 +2984,21 @@ static void s3_recalctimings(svga_t *svga) if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { if (s3->chip == S3_86C928) - svga->hdisp *= 2; + svga->hdisp <<= 1; else if (s3->chip != S3_VISION968) - svga->hdisp /= 2; + svga->hdisp >>= 1; } if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { if (s3->width == 1280 || s3->width == 1600) - svga->hdisp *= 2; + svga->hdisp <<= 1; + else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; } if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp == (1408*2)) - svga->hdisp /= 2; + svga->hdisp >>= 1; else svga->hdisp = s3->width; } @@ -2973,21 +3011,22 @@ static void s3_recalctimings(svga_t *svga) if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { if (s3->chip == S3_86C928) - svga->hdisp *= 2; + svga->hdisp <<= 1; else if (s3->chip != S3_VISION968) - svga->hdisp /= 2; - } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) { - svga->hdisp /= 2; - } + svga->hdisp >>= 1; + } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) + svga->hdisp >>= 1; if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { if (s3->width == 1280 || s3->width == 1600) - svga->hdisp *= 2; + svga->hdisp <<= 1; + else if (s3->card_type == S3_NUMBER9_9FX_771) + svga->hdisp <<= 1; } if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp == (1408*2)) - svga->hdisp /= 2; + svga->hdisp >>= 1; else svga->hdisp = s3->width; } @@ -3013,12 +3052,13 @@ static void s3_recalctimings(svga_t *svga) if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { if (s3->chip == S3_VISION868) - svga->hdisp /= 2; + svga->hdisp >>= 1; else - svga->hdisp /= 4; + svga->hdisp >>= 2; } - if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) - svga->hdisp *= 2; + if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || + s3->card_type == S3_NUMBER9_9FX_771)) + svga->hdisp <<= 1; if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { @@ -3110,11 +3150,11 @@ static void s3_trio64v_recalctimings(svga_t *svga) break; case 15: svga->render = svga_render_15bpp_highres; - svga->hdisp /= 2; + svga->hdisp >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; - svga->hdisp /= 2; + svga->hdisp >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; @@ -6530,6 +6570,7 @@ static void s3_reset(void *priv) case S3_ELSAWIN2KPROX: case S3_SPEA_MERCURY_P64V: case S3_MIROVIDEO40SV_ERGO_968: + case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: if (s3->pci) { svga->crtc[0x53] = 0x18; @@ -6544,6 +6585,7 @@ static void s3_reset(void *priv) } break; + case S3_NUMBER9_9FX_531: case S3_PHOENIX_VISION868: if (s3->pci) { svga->crtc[0x53] = 0x18; @@ -6679,6 +6721,11 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); break; + case S3_NUMBER9_9FX_531: + bios_fn = ROM_NUMBER9_9FX_531; + chip = S3_VISION868; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); + break; case S3_PHOENIX_VISION868: bios_fn = ROM_PHOENIX_VISION868; chip = S3_VISION868; @@ -6710,6 +6757,11 @@ static void *s3_init(const device_t *info) chip = S3_VISION968; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); break; + case S3_NUMBER9_9FX_771: + bios_fn = ROM_NUMBER9_9FX_771; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; case S3_PHOENIX_VISION968: bios_fn = ROM_PHOENIX_VISION968; chip = S3_VISION968; @@ -6887,7 +6939,7 @@ static void *s3_init(const device_t *info) if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && (info->local == S3_ELSAWIN2KPROX || - info->local == S3_PHOENIX_VISION968))) + info->local == S3_PHOENIX_VISION968 || info->local == S3_NUMBER9_9FX_771))) svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; else if (chip == S3_VISION968 && (info->local == S3_SPEA_MERCURY_P64V || info->local == S3_MIROVIDEO40SV_ERGO_968)) svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; @@ -7048,7 +7100,7 @@ static void *s3_init(const device_t *info) case S3_PARADISE_BAHAMAS64: case S3_PHOENIX_VISION864: - case S3_MIROCRYSTAL20SD_864: + case S3_MIROCRYSTAL20SD_864: /*BIOS 3.xx has a SDAC ramdac.*/ svga->decode_mask = (8 << 20) - 1; if (info->local == S3_PARADISE_BAHAMAS64 || info->local == S3_MIROCRYSTAL20SD_864) stepping = 0xc0; /*Vision864*/ @@ -7085,6 +7137,7 @@ static void *s3_init(const device_t *info) case S3_ELSAWIN2KPROX: case S3_SPEA_MERCURY_P64V: case S3_MIROVIDEO40SV_ERGO_968: + case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ @@ -7102,7 +7155,8 @@ static void *s3_init(const device_t *info) svga->crtc[0x5a] = 0x0a; } - if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968) + if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968 || + info->local == S3_NUMBER9_9FX_771) svga->ramdac = device_add(&ibm_rgb528_ramdac_device); else svga->ramdac = device_add(&tvp3026_ramdac_device); @@ -7111,6 +7165,7 @@ static void *s3_init(const device_t *info) svga->getclock = icd2061_getclock; break; + case S3_NUMBER9_9FX_531: case S3_PHOENIX_VISION868: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision868*/ @@ -7128,10 +7183,16 @@ static void *s3_init(const device_t *info) svga->crtc[0x59] = 0x00; svga->crtc[0x5a] = 0x0a; } - - svga->ramdac = device_add(&sdac_ramdac_device); - svga->clock_gen = svga->ramdac; - svga->getclock = sdac_getclock; + + if (info->local == S3_NUMBER9_9FX_531) { + svga->ramdac = device_add(&att498_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + } else { + svga->ramdac = device_add(&sdac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + } break; case S3_PHOENIX_TRIO32: @@ -7261,6 +7322,11 @@ static int s3_phoenix_vision864_available(void) return rom_present(ROM_PHOENIX_VISION864); } +static int s3_9fx_531_available(void) +{ + return rom_present(ROM_NUMBER9_9FX_531); +} + static int s3_phoenix_vision868_available(void) { return rom_present(ROM_PHOENIX_VISION868); @@ -7286,6 +7352,11 @@ static int s3_mirovideo_40sv_ergo_968_pci_available(void) return rom_present(ROM_MIROVIDEO40SV_ERGO_968_PCI); } +static int s3_9fx_771_available(void) +{ + return rom_present(ROM_NUMBER9_9FX_771); +} + static int s3_phoenix_vision968_available(void) { return rom_present(ROM_PHOENIX_VISION968); @@ -7448,7 +7519,7 @@ static const device_config_t s3_phoenix_trio32_config[] = static const device_config_t s3_standard_config[] = { { - "memory", "Video memory size", CONFIG_SELECTION, "", 4, "", { 0 }, + "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, { { "1 MB", 1 @@ -7750,6 +7821,20 @@ const device_t s3_diamond_stealth64_964_pci_device = s3_standard_config }; +const device_t s3_9fx_771_pci_device = +{ + "S3 Vision968 PCI (Number 9 9FX 771)", + DEVICE_PCI, + S3_NUMBER9_9FX_771, + s3_init, + s3_close, + s3_reset, + { s3_9fx_771_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + const device_t s3_phoenix_vision968_pci_device = { "S3 Vision968 PCI (Phoenix)", @@ -7989,6 +8074,20 @@ const device_t s3_phoenix_vision864_pci_device = s3_standard_config }; +const device_t s3_9fx_531_pci_device = +{ + "S3 Vision868 PCI (Number 9 9FX 531)", + DEVICE_PCI, + S3_NUMBER9_9FX_531, + s3_init, + s3_close, + s3_reset, + { s3_9fx_531_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + const device_t s3_phoenix_vision868_vlb_device = { "S3 Vision868 VLB (Phoenix)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 32865df01..f1752d611 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -72,9 +72,12 @@ video_cards[] = { { "cl_gd5402_isa", &gd5402_isa_device }, { "cl_gd5420_isa", &gd5420_isa_device }, { "cl_gd5422_isa", &gd5422_isa_device }, + { "cl_gd5426_isa", &gd5426_isa_device }, + { "cl_gd5426_diamond_a1_isa", &gd5426_diamond_speedstar_pro_a1_isa_device }, { "cl_gd5428_isa", &gd5428_isa_device }, { "cl_gd5429_isa", &gd5429_isa_device }, { "cl_gd5434_isa", &gd5434_isa_device }, + { "cl_gd5434_diamond_a3_isa", &gd5434_diamond_speedstar_64_a3_isa_device }, { "compaq_cga", &compaq_cga_device }, { "compaq_cga_2", &compaq_cga_2_device }, { "compaq_ega", &cpqega_device }, @@ -123,14 +126,15 @@ video_cards[] = { { "radius_mc", &radius_svga_multiview_mca_device }, { "mach64gx_pci", &mach64gx_pci_device }, { "mach64vt2", &mach64vt2_device }, + { "et4000w32p_revc_pci", &et4000w32p_revc_pci_device }, { "et4000w32p_pci", &et4000w32p_cardex_pci_device }, { "et4000w32p_nc_pci", &et4000w32p_noncardex_pci_device }, - { "et4000w32p_revc_pci", &et4000w32p_revc_pci_device }, { "cl_gd5430_pci", &gd5430_pci_device, }, { "cl_gd5434_pci", &gd5434_pci_device }, { "cl_gd5436_pci", &gd5436_pci_device }, { "cl_gd5440_pci", &gd5440_pci_device }, { "cl_gd5446_pci", &gd5446_pci_device }, + { "cl_gd5446_stb_pci", &gd5446_stb_pci_device }, { "cl_gd5480_pci", &gd5480_pci_device }, { "ctl3d_banshee_pci", &creative_voodoo_banshee_device }, { "stealth32_pci", &et4000w32p_pci_device }, @@ -146,8 +150,10 @@ video_cards[] = { { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, { "mirovideo40sv_pci", &s3_mirovideo_40sv_ergo_968_pci_device }, + { "n9_9fx_771_pci", &s3_9fx_771_pci_device }, { "px_vision968_pci", &s3_phoenix_vision968_pci_device }, { "spea_mercury64p_pci", &s3_spea_mercury_p64v_pci_device }, + { "n9_9fx_531_pci", &s3_9fx_531_pci_device }, { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, { "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, @@ -164,7 +170,6 @@ video_cards[] = { { "mystique", &mystique_device }, { "mystique_220", &mystique_220_device }, #endif - { "cl_gd5446_stb_pci", &gd5446_stb_pci_device }, { "tgui9440_pci", &tgui9440_pci_device }, { "tgui9660_pci", &tgui9660_pci_device }, { "tgui9680_pci", &tgui9680_pci_device }, @@ -173,16 +178,17 @@ video_cards[] = { { "voodoo3_3k_pci", &voodoo_3_3000_device }, { "mach64gx_vlb", &mach64gx_vlb_device }, { "et4000w32i_vlb", &et4000w32i_vlb_device }, - { "et4000w32p_vlb", &et4000w32p_cardex_vlb_device }, - { "et4000w32p_nc_vlb", &et4000w32p_noncardex_vlb_device }, { "et4000w32p_revc_vlb", &et4000w32p_revc_vlb_device }, - { "cl_gd5424_vlb", &gd5424_vlb_device }, - { "cl_gd5428_vlb", &gd5428_vlb_device }, - { "cl_gd5429_vlb", &gd5429_vlb_device }, - { "cl_gd5434_vlb", &gd5434_vlb_device }, + { "et4000w32p_vlb", &et4000w32p_cardex_vlb_device }, { "stealth32_vlb", &et4000w32p_vlb_device }, + { "et4000w32p_nc_vlb", &et4000w32p_noncardex_vlb_device }, + { "cl_gd5424_vlb", &gd5424_vlb_device }, { "cl_gd5426_vlb", &gd5426_vlb_device }, - { "cl_gd5430_vlb", &gd5430_vlb_device }, + { "cl_gd5428_vlb", &gd5428_vlb_device }, + { "cl_gd5428_diamond_b1_vlb", &gd5428_diamond_speedstar_pro_b1_vlb_device }, + { "cl_gd5429_vlb", &gd5429_vlb_device }, + { "cl_gd5430_vlb", &gd5430_diamond_speedstar_pro_se_a8_vlb_device }, + { "cl_gd5434_vlb", &gd5434_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "mirocrystal8s_vlb", &s3_mirocrystal_8s_805_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d678e2699..2d2ad272f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -730,6 +730,7 @@ VIDOBJ := agpgart.o video.o \ vid_tvga.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ + vid_att2xc498_ramdac.o \ vid_s3.o vid_s3_virge.o \ vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ vid_ogc.o \