From 283908df11cbc328b136995b62a263108eec9c01 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 25 Mar 2021 02:17:39 +0100 Subject: [PATCH 1/3] Fixed warnings in vid_s3.c. --- src/video/vid_s3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 02008c13b..c80a3cddf 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -4153,8 +4153,8 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) svga_t *svga = &s3->svga; int idf, odf, host; int is_yuv; - uint32_t src, dest; - uint8_t r, g, b, r2, g2, b2; + uint32_t src, dest = 0x00000000; + uint8_t r = 0x00, g = 0x00, b = 0x00, r2 = 0x00, g2 = 0x00, b2 = 0x00; uint16_t *vram_w = (uint16_t *)svga->vram; uint32_t *vram_l = (uint32_t *)svga->vram; uint32_t k2 = 0, dda = 0, diff = 0; From 22bf154153062993b8938fb3594dfe20371a1493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Thu, 25 Mar 2021 03:43:02 +0100 Subject: [PATCH 2/3] Update machine_table.c Fixed the Machine table entry for the Commodore SL386SX-25, fixes #1324. --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 1972bfcc0..dbecf22c3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -167,7 +167,7 @@ const machine_t machines[] = { { "[OPTi 283] Olivetti M300-08", "m30008", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_08_init, at_m300_08_get_device }, { "[OPTi 283] Olivetti M300-15", "m30015", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_15_init, NULL }, { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, - { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device }, + { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device }, { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, From 7b22fa60d1313b762b6e0fb2087620624b436048 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 25 Mar 2021 06:32:10 +0100 Subject: [PATCH 3/3] Cleaned up the ET4000/W32, fixed the ICS 53xx/GENDAC/SDAC RAMDAC's, and readded the Cardex ET4000/W32p Rev. C with ICS 5341 RAMDAC. --- src/include/86box/video.h | 2 + src/video/vid_et4000w32.c | 2980 ++++++++++++++++++----------------- src/video/vid_sdac_ramdac.c | 70 +- src/video/vid_table.c | 10 +- 4 files changed, 1560 insertions(+), 1502 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 71786bd09..e51021098 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -261,6 +261,8 @@ extern const device_t et4000_mca_device; extern const device_t et4000w32_device; extern const device_t et4000w32i_isa_device; extern const device_t et4000w32i_vlb_device; +extern const device_t et4000w32p_revc_vlb_device; +extern const device_t et4000w32p_revc_pci_device; extern const device_t et4000w32p_vlb_device; extern const device_t et4000w32p_pci_device; extern const device_t et4000w32p_noncardex_vlb_device; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c25d4705d..050e5cbc3 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -40,125 +40,137 @@ #define BIOS_ROM_PATH_DIAMOND L"roms/video/et4000w32/et4000w32.bin" #define BIOS_ROM_PATH_CARDEX L"roms/video/et4000w32/cardex.vbi" -#define BIOS_ROM_PATH_W32 L"roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" +#define BIOS_ROM_PATH_W32 L"roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" #define BIOS_ROM_PATH_W32I_ISA L"roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB L"roms/video/et4000w32/tseng.u41.bin" -#define BIOS_ROM_PATH_W32P L"roms/video/et4000w32/ET4K_W32.BIN" +#define BIOS_ROM_PATH_W32P L"roms/video/et4000w32/ET4K_W32.BIN" +#define BIOS_ROM_PATH_W32P_REVC L"roms/video/et4000w32/et4000w32pcardex.BIN" -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) -#define FIFO_ENTRIES (et4000->fifo_write_idx - et4000->fifo_read_idx) -#define FIFO_FULL ((et4000->fifo_write_idx - et4000->fifo_read_idx) >= (FIFO_SIZE-1)) -#define FIFO_EMPTY (et4000->fifo_read_idx == et4000->fifo_write_idx) +#define FIFO_ENTRIES (et4000->fifo_write_idx - et4000->fifo_read_idx) +#define FIFO_FULL ((et4000->fifo_write_idx - et4000->fifo_read_idx) >= (FIFO_SIZE-1)) +#define FIFO_EMPTY (et4000->fifo_read_idx == et4000->fifo_write_idx) -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +#define ACL_WRST 1 +#define ACL_RDST 2 +#define ACL_XYST 4 +#define ACL_SSO 8 -#define ET4000W32 0 -#define ET4000W32I 1 -#define ET4000W32P 2 -#define ET4000W32_CARDEX 3 -#define ET4000W32_DIAMOND 4 enum { - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_MMU = (0x02 << 24) + ET4000W32, + ET4000W32I, + ET4000W32P_REVC, + ET4000W32P, + ET4000W32P_CARDEX, + ET4000W32P_DIAMOND }; +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_MMU = (0x02 << 24) +}; + + typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; + typedef struct et4000w32p_t { - mem_mapping_t linear_mapping; - mem_mapping_t mmu_mapping; - - rom_t bios_rom; - - svga_t svga; + mem_mapping_t linear_mapping; + mem_mapping_t mmu_mapping; - int index; - int pci; - int isa; - uint8_t regs[256]; - uint32_t linearbase, linearbase_old; - uint32_t vram_mask; + rom_t bios_rom; - uint8_t banking, banking2; - uint8_t adjust_cursor; + svga_t svga; - uint8_t pci_regs[256]; - - int interleaved; - int bank; + uint8_t banking, banking2, adjust_cursor, rev; - /*Accelerator*/ - struct - { - struct - { - uint32_t pattern_addr,source_addr,dest_addr,mix_addr; - uint16_t pattern_off,source_off,dest_off,mix_off; - uint8_t vbus, pixel_depth,xy_dir; - uint8_t pattern_wrap,source_wrap; - uint16_t count_x,count_y; - uint8_t ctrl_routing,ctrl_reload; - uint8_t rop_fg,rop_bg; - uint16_t pos_x,pos_y; - uint16_t error; - uint16_t dmin,dmaj; - } queued,internal; - uint32_t pattern_addr,source_addr,dest_addr,mix_addr; - uint32_t pattern_back,source_back,dest_back,mix_back; - int pattern_x,source_x; - int pattern_x_back,source_x_back; - int pattern_y,source_y; - uint8_t status; - uint64_t cpu_dat; - int cpu_dat_pos; - int pix_pos; - uint32_t cpu_input; - int cpu_input_num; - } acl; + uint8_t regs[256], pci_regs[256]; - struct - { - uint32_t base[3]; - uint8_t ctrl; - } mmu; + int index, vlb, pci, interleaved, + bank, blitter_busy, type; - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; + uint32_t linearbase, linearbase_old; + uint32_t vram_mask; - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - int type; + /* Accelerator */ + struct { + struct { + uint8_t vbus, pixel_depth, xy_dir, pattern_wrap, + source_wrap, ctrl_routing, ctrl_reload, rop_fg, + rop_bg; + + uint16_t pattern_off, source_off, dest_off, mix_off, + count_x,count_y, pos_x, pos_y, + error, dmin, dmaj; + + uint32_t pattern_addr, source_addr, dest_addr, mix_addr; + } queued, internal; + + uint8_t status; + + int pattern_x, source_x, pattern_x_back, source_x_back, + pattern_y, source_y, cpu_dat_pos, pix_pos, + cpu_input_num; + + uint32_t pattern_addr, source_addr, dest_addr, mix_addr, + pattern_back, source_back, dest_back, mix_back, + cpu_input; + + uint64_t cpu_dat; + } acl; + + struct { + uint32_t base[3]; + uint8_t ctrl; + } mmu; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t * fifo_thread; + event_t * wake_fifo_thread; + event_t * fifo_not_full_event; + + uint64_t blitter_time, status_time; } et4000w32p_t; -static video_timings_t timing_et4000w32_vlb = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; -static video_timings_t timing_et4000w32_pci = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; -static video_timings_t timing_et4000w32_isa = {VIDEO_ISA, 4, 4, 4, 10, 10, 10}; -void et4000w32p_recalcmapping(et4000w32p_t *et4000); +static int et4000w32_vbus[4] = {1, 2, 4, 4}; -uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); -void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); +static int et4000w32_max_x[8] = {0, 0, 4, 8, 16, 32, 64, 0x70000000}; +static int et4000w32_wrap_x[8] = {0, 0, 3, 7, 15, 31, 63, 0xffffffff}; +static int et4000w32_wrap_y[8] = {1, 2, 4, 8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; + +static video_timings_t timing_et4000w32_vlb = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; +static video_timings_t timing_et4000w32_pci = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; +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); + +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); +uint8_t et4000w32p_in(uint16_t addr, 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); #ifdef ENABLE_ET4000W32_LOG int et4000w32_do_log = ENABLE_ET4000W32_LOG; @@ -180,187 +192,161 @@ et4000w32_log(const char *fmt, ...) #endif -uint8_t et4000w32p_in(uint16_t addr, void *p); - -static int et4000w32_vbus[4]={1,2,4,4}; - -void et4000w32p_out(uint16_t addr, uint8_t val, void *p) +void +et4000w32p_out(uint16_t addr, uint8_t val, void *p) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; - uint8_t old; - uint32_t add2addr; + et4000w32p_t *et4000 = (et4000w32p_t *)p; + svga_t *svga = &et4000->svga; + uint8_t old; + uint32_t add2addr; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c2: - if (et4000->type == ET4000W32_DIAMOND) - icd2061_write(svga->clock_gen, (val >> 2) & 3); - break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (et4000->type <= ET4000W32I) - sdac_ramdac_out(addr, 1, val, svga->ramdac, svga); - else - stg_ramdac_out(addr, val, svga->ramdac, svga); - return; - - case 0x3CB: /*Banking extension*/ - if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); - svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); - } - et4000->banking2 = val; - return; - case 0x3CD: /*Banking*/ - if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536); - svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536); - } - et4000->banking = val; - return; - case 0x3CF: - switch (svga->gdcaddr & 15) - { - case 6: - if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { - svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); - svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); - } else - svga->write_bank = svga->read_bank = 0; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - svga->gdcreg[svga->gdcaddr & 15] = val; - et4000w32p_recalcmapping(et4000); - return; - } - break; - case 0x3D4: - svga->crtcreg = val & 63; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 0x35) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; + switch (addr) { + case 0x3c2: + if (et4000->type == ET4000W32P_DIAMOND) + icd2061_write(svga->clock_gen, (val >> 2) & 3); + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (et4000->type <= ET4000W32I) + sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + stg_ramdac_out(addr, val, svga->ramdac, svga); + return; + + case 0x3cb: /* Banking extension */ + if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); + svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); + } + et4000->banking2 = val; + return; + case 0x3cd: /* Banking */ + if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { + svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536); + svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536); + } + et4000->banking = val; + return; + case 0x3cf: + switch (svga->gdcaddr & 15) { + case 6: + if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { + svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); + svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); + } else + svga->write_bank = svga->read_bank = 0; + + svga->gdcreg[svga->gdcaddr & 15] = val; + et4000w32p_recalcmapping(et4000); + return; + } + break; + case 0x3d4: + svga->crtcreg = val & 63; + return; + case 0x3d5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 0x35) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; if (svga->crtcreg == 0x36) { if (!(val & 0x10) && !(svga->gdcreg[6] & 0x08)) { - svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); - svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); + svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); + svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); } else svga->write_bank = svga->read_bank = 0; } - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - if (svga->crtcreg == 0x30) - { - if (et4000->pci) - { - et4000->linearbase &= 0xc0000000; - et4000->linearbase |= (val & 0xfc) << 22; - } - else - { - et4000->linearbase = val << 22; - } - et4000w32p_recalcmapping(et4000); - } - if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) - et4000w32p_recalcmapping(et4000); - break; + if (old != val) { + if ((svga->crtcreg < 0xe) || (svga->crtcreg > 0x10)) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + if (svga->crtcreg == 0x30) { + if (et4000->pci) + et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22); + else + et4000->linearbase = val << 22; + et4000w32p_recalcmapping(et4000); + } + if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) + et4000w32p_recalcmapping(et4000); + break; - case 0x210A: case 0x211A: case 0x212A: case 0x213A: - case 0x214A: case 0x215A: case 0x216A: case 0x217A: - et4000->index=val; - return; - case 0x210B: case 0x211B: case 0x212B: case 0x213B: - case 0x214B: case 0x215B: case 0x216B: case 0x217B: - et4000->regs[et4000->index] = val; - svga->hwcursor.xsize = svga->hwcursor.ysize = (et4000->regs[0xEF] & 4) ? 128 : 64; - svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8); - svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8); - svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80); - if (svga->hwcursor.xsize == 128) { - svga->hwcursor.xoff = et4000->regs[0xE2] & 0x7f; - svga->hwcursor.yoff = et4000->regs[0xE6] & 0x7f; - } else { - svga->hwcursor.xoff = et4000->regs[0xE2] & 0x3f; - svga->hwcursor.yoff = et4000->regs[0xE6] & 0x3f; - } - svga->hwcursor.addr = (et4000->regs[0xE8] | (et4000->regs[0xE9] << 8) | ((et4000->regs[0xEA] & 7) << 16)) << 2; - add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16); - svga->hwcursor.addr += add2addr; + case 0x210a: case 0x211a: case 0x212a: case 0x213a: + case 0x214a: case 0x215a: case 0x216a: case 0x217a: + et4000->index = val; + return; + case 0x210b: case 0x211b: case 0x212b: case 0x213b: + case 0x214b: case 0x215b: case 0x216b: case 0x217b: + et4000->regs[et4000->index] = val; + svga->hwcursor.xsize = svga->hwcursor.ysize = (et4000->regs[0xEF] & 4) ? 128 : 64; + svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8); + svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8); + svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80); + if (svga->hwcursor.xsize == 128) { + svga->hwcursor.xoff = et4000->regs[0xE2] & 0x7f; + svga->hwcursor.yoff = et4000->regs[0xE6] & 0x7f; + } else { + svga->hwcursor.xoff = et4000->regs[0xE2] & 0x3f; + svga->hwcursor.yoff = et4000->regs[0xE6] & 0x3f; + } + svga->hwcursor.addr = (et4000->regs[0xe8] | (et4000->regs[0xe9] << 8) | ((et4000->regs[0xea] & 7) << 16)) << 2; + add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16); + svga->hwcursor.addr += add2addr; + return; + } - if (et4000->type <= ET4000W32I) { - if (svga->bpp == 15 || svga->bpp == 16) - svga->hwcursor.x >>= 1; - else if (svga->bpp == 24) - svga->hwcursor.x /= 3; - } - return; - - } - svga_out(addr, val, svga); + svga_out(addr, val, svga); } -uint8_t et4000w32p_in(uint16_t addr, void *p) + +uint8_t +et4000w32p_in(uint16_t addr, void *p) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; + et4000w32p_t *et4000 = (et4000w32p_t *)p; + svga_t *svga = &et4000->svga; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c5: - if ((svga->seqaddr & 0xf) == 7) - return svga->seqregs[svga->seqaddr & 0xf] | 4; - break; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (et4000->type <= ET4000W32I) - return sdac_ramdac_in(addr, 1, svga->ramdac, svga); - else - return stg_ramdac_in(addr, svga->ramdac, svga); - break; + switch (addr) { + case 0x3c5: + if ((svga->seqaddr & 0xf) == 7) + return svga->seqregs[svga->seqaddr & 0xf] | 4; + break; - case 0x3CB: - return et4000->banking2; - case 0x3CD: - return et4000->banking; - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - return svga->crtc[svga->crtcreg]; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (et4000->type <= ET4000W32I) + return sdac_ramdac_in(addr, 0, svga->ramdac, svga); + else + return stg_ramdac_in(addr, svga->ramdac, svga); + break; - case 0x210A: case 0x211A: case 0x212A: case 0x213A: - case 0x214A: case 0x215A: case 0x216A: case 0x217A: - return et4000->index; - case 0x210B: case 0x211B: case 0x212B: case 0x213B: - case 0x214B: case 0x215B: case 0x216B: case 0x217B: - if (et4000->index==0xec) { - if (et4000->type == ET4000W32I) - return (et4000->regs[0xec] & 0xf) | 0x30; /*ET4000/W32i rev B*/ - else if (et4000->type == ET4000W32) - return (et4000->regs[0xec] & 0xf); /*ET4000/W32*/ - else - return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/ - } - if (et4000->index == 0xee) /*Preliminary implementation*/ - { + case 0x3cb: + return et4000->banking2; + case 0x3cd: + return et4000->banking; + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + return svga->crtc[svga->crtcreg]; + + case 0x210a: case 0x211a: case 0x212a: case 0x213a: + case 0x214a: case 0x215a: case 0x216a: case 0x217a: + return et4000->index; + case 0x210B: case 0x211B: case 0x212B: case 0x213B: + case 0x214B: case 0x215B: case 0x216B: case 0x217B: + if (et4000->index == 0xec) + return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4); + if (et4000->index == 0xee) { /* Preliminary implementation */ if (svga->bpp == 8) return 3; else if (svga->bpp == 16) @@ -368,1314 +354,1323 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) else break; } - if (et4000->index == 0xef) - { - if (et4000->type == ET4000W32I) { - if (et4000->isa) - return et4000->regs[0xef] | 0x30; /*ET4000/W32i rev B (ISA)*/ - else - return et4000->regs[0xef] | 0x70; /*ET4000/W32i rev B (VLB)*/ - } else if (et4000->type == ET4000W32) - return et4000->regs[0xef]; /*ET4000/W32*/ - else { - if (et4000->pci) - return et4000->regs[0xef] | 0xe0; /*ET4000/W32p rev D (PCI) */ - else - return et4000->regs[0xef] | 0x60; /*ET4000/W32p rev D (VLB) */ - } - } - return et4000->regs[et4000->index]; - } - return svga_in(addr, svga); + if (et4000->index == 0xef) { + if (et4000->type >= ET4000W32P_REVC) + return (et4000->regs[0xef] & 0x0f) | (et4000->rev << 4) | et4000->pci; + else + return (et4000->regs[0xef] & 0x8f) | (et4000->rev << 4) | et4000->vlb; + } + return et4000->regs[et4000->index]; + } + + return svga_in(addr, svga); } -void et4000w32p_recalctimings(svga_t *svga) + +void +et4000w32p_recalctimings(svga_t *svga) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - - svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; - if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; - if (svga->crtc[0x35] & 0x02) svga->vtotal += 0x400; - if (svga->crtc[0x35] & 0x04) svga->dispend += 0x400; - if (svga->crtc[0x35] & 0x08) svga->vsyncstart += 0x400; - if (svga->crtc[0x35] & 0x10) svga->split += 0x400; - if (svga->crtc[0x3F] & 0x80) svga->rowoffset += 0x100; - if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; - - svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - 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*/ - svga->ma_latch--; + svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; + if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; + if (svga->crtc[0x35] & 0x02) svga->vtotal += 0x400; + if (svga->crtc[0x35] & 0x04) svga->dispend += 0x400; + if (svga->crtc[0x35] & 0x08) svga->vsyncstart += 0x400; + if (svga->crtc[0x35] & 0x10) svga->split += 0x400; + if (svga->crtc[0x3F] & 0x80) svga->rowoffset += 0x100; + if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; + if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; - if ((svga->seqregs[1] & 8)) /*40 column*/ - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + + 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 */ + svga->ma_latch--; + + if ((svga->seqregs[1] & 8)) /*40 column*/ + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + } else { + /* Also adjust the graphics mode clocks in some cases. */ + if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) { + if ((svga->bpp == 15) || (svga->bpp == 16)) + svga->hdisp += 16; else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else { - switch (svga->gdcreg[5] & 0x60) { - case 0x40: case 0x60: /*256+ colours*/ - switch (svga->bpp) { - case 8: - case 24: - svga->hdisp += 8; - break; - case 15: - case 16: - svga->hdisp += 16; - break; - case 32: - break; - } - break; - } + svga->hdisp += 8; } } + } - et4000->adjust_cursor = 0; + et4000->adjust_cursor = 0; - switch (svga->bpp) - { - case 15: case 16: - svga->hdisp >>= 1; + switch (svga->bpp) { + case 15: case 16: + svga->hdisp >>= 1; if (et4000->type <= ET4000W32I) et4000->adjust_cursor = 1; - break; - case 24: - svga->hdisp /= 3; + break; + case 24: + svga->hdisp /= 3; if (et4000->type <= ET4000W32I) et4000->adjust_cursor = 2; - break; - } + break; + } - svga->render = svga_render_blank; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ - svga->render = svga_render_text_40; - else - svga->render = svga_render_text_80; + svga->render = svga_render_blank; + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ + if (svga->seqregs[1] & 8) /* 40 column */ + svga->render = svga_render_text_40; + else + svga->render = svga_render_text_80; + } else { + if (svga->adv_flags & FLAG_NOSKEW) + svga->ma_latch--; + + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /* Low res (320) */ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /* 4 colours */ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /* 256+ colours */ + if (et4000->type <= ET4000W32I) + svga->clock /= 2; + + switch (svga->bpp) { + case 8: + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + case 15: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 17: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_mix_highres; + break; + case 24: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + } + break; + } + } + } +} + + +void +et4000w32p_recalcmapping(et4000w32p_t *et4000) +{ + svga_t *svga = &et4000->svga; + int map; + + if (et4000->pci && !(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&et4000->linear_mapping); + mem_mapping_disable(&et4000->mmu_mapping); + return; + } + + if (svga->crtc[0x36] & 0x10) { /* Linear frame buffer */ + mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&et4000->mmu_mapping); + } else { + map = (svga->gdcreg[6] & 0xc) >> 2; + if (svga->crtc[0x36] & 0x20) map |= 4; + if (svga->crtc[0x36] & 0x08) map |= 8; + switch (map) { + case 0x0: case 0x4: case 0x8: case 0xc: /* 128k at A0000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x1ffff; + break; + case 0x1: /* 64k at A0000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0xffff; + break; + case 0x2: /* 32k at B0000 */ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; + break; + case 0x3: /* 32k at B8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; + break; + case 0x5: case 0x9: case 0xd: /* 64k at A0000, MMU at B8000 */ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); + svga->banked_mask = 0xffff; + break; + case 0x6: case 0xa: case 0xe: /* 32k at B0000, MMU at A8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0x7: case 0xb: case 0xf: /* 32k at B8000, MMU at A8000 */ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + 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); +} + + +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); 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); 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); 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); 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); break; + case 0x7f8e: + if (et4000->type >= ET4000W32P_REVC) + et4000->acl.queued.pixel_depth = val; + else + et4000->acl.queued.vbus = val; + break; + case 0x7f8f: et4000->acl.queued.xy_dir = val; break; + case 0x7f90: et4000->acl.queued.pattern_wrap = val; break; + case 0x7f92: et4000->acl.queued.source_wrap = val; 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); 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); break; + case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break; + case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break; + case 0x7f9e: et4000->acl.queued.rop_bg = val; break; + case 0x7f9f: et4000->acl.queued.rop_fg = val; 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.internal = et4000->acl.queued; + if (et4000->type >= ET4000W32P_REVC) { + 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); } else { - if (svga->adv_flags & FLAG_NOSKEW) - svga->ma_latch--; - - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; + et4000w32_blit_start(et4000); + et4000->acl.cpu_input_num = 0; + if (!(et4000->acl.queued.ctrl_routing & 0x37)) + et4000w32p_blit(0xffffff, ~0, 0, 0, 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); 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); 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); 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); 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); break; + } +} + + +static void +et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val) +{ + if (et4000->type >= ET4000W32P_REVC) { + if (!(et4000->acl.status & ACL_XYST)) + return; + if (et4000->acl.internal.ctrl_routing & 3) { + if ((et4000->acl.internal.ctrl_routing & 3) == 2) { + if (et4000->acl.mix_addr & 7) + et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); + else + et4000w32p_blit(8, val, 0, 1, et4000); + } + else if ((et4000->acl.internal.ctrl_routing & 3) == 1) + et4000w32p_blit(1, ~0, val, 2, et4000); + } + } else { + if (!(et4000->acl.status & ACL_XYST)) { + et4000->acl.queued.dest_addr = (addr & 0x1FFF) + et4000->mmu.base[et4000->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); + et4000->acl.cpu_input_num = 0; + } + + if (et4000->acl.internal.ctrl_routing & 7) { + 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); + + et4000->acl.cpu_input_num = 0; + } + } + } +} + + +static void +fifo_thread(void *param) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)param; + + uint64_t start_time = 0; + uint64_t end_time = 0; + + fifo_entry_t *fifo; + + while (1) { + thread_set_event(et4000->fifo_not_full_event); + thread_wait_event(et4000->wake_fifo_thread, -1); + thread_reset_event(et4000->wake_fifo_thread); + et4000->blitter_busy = 1; + while (!FIFO_EMPTY) { + start_time = plat_timer_read(); + fifo = &et4000->fifo[et4000->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_BYTE: + et4000w32p_accel_write_fifo(et4000, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_MMU: + et4000w32p_accel_write_mmu(et4000, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + } + + et4000->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(et4000->fifo_not_full_event); + + end_time = plat_timer_read(); + et4000->blitter_time += end_time - start_time; + } + et4000->blitter_busy = 0; + } +} + + +static __inline void +wake_fifo_thread(et4000w32p_t *et4000) +{ + thread_set_event(et4000->wake_fifo_thread); /* Wake up FIFO thread if moving from idle */ +} + + +static void +et4000w32p_wait_fifo_idle(et4000w32p_t *et4000) +{ + while (!FIFO_EMPTY) { + wake_fifo_thread(et4000); + thread_wait_event(et4000->fifo_not_full_event, 1); + } +} + + +static void +et4000w32p_queue(et4000w32p_t *et4000, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &et4000->fifo[et4000->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) { + thread_reset_event(et4000->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(et4000->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + et4000->fifo_write_idx++; + + if ((FIFO_ENTRIES > 0xe000) || (FIFO_ENTRIES < 8)) + wake_fifo_thread(et4000); +} + + +void +et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)p; + svga_t *svga = &et4000->svga; + + switch (addr & 0x6000) { + case 0x0000: /* MMU 0 */ + case 0x2000: /* MMU 1 */ + case 0x4000: /* MMU 2 */ + et4000->bank = (addr >> 13) & 3; + if (et4000->mmu.ctrl & (1 << et4000->bank)) { + if (et4000->type >= ET4000W32P_REVC) + et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_MMU); + else + et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val); + } else { + if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { + svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val; + svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) >> 12] = changeframecount; + } + } + break; + case 0x6000: + if ((addr & 0x7fff) >= 0x7f80) { + if (et4000->type >= ET4000W32P_REVC) + et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_BYTE); + else + 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; + } + break; + } +} + + +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)) { + if (et4000->type >= ET4000W32P_REVC) + et4000w32p_wait_fifo_idle(et4000); + + temp = 0xff; + if (et4000->acl.cpu_dat_pos) { + et4000->acl.cpu_dat_pos--; + temp = et4000->acl.cpu_dat & 0xff; + et4000->acl.cpu_dat >>= 8; + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) + et4000w32p_blit(4, ~0, 0, 0, et4000); + + /* ???? */ + return temp; + } + + if ((addr&0x1fff) + et4000->mmu.base[bank] >= svga->vram_max) + return 0xff; + + return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]]; + + case 0x6000: + if ((addr & 0x7fff) >= 0x7f80) { + if (et4000->type >= ET4000W32P_REVC) + et4000w32p_wait_fifo_idle(et4000); + } + 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; + + case 0x7f36: + if (et4000->type >= ET4000W32P_REVC) { + temp = et4000->acl.status; + temp &= ~(ACL_RDST | ACL_WRST); + if (!FIFO_EMPTY) + temp |= ACL_RDST; + if (FIFO_FULL) + temp |= ACL_WRST; + if (temp == ACL_XYST && (et4000->acl.internal.ctrl_routing & 3)) + temp |= ACL_RDST; + } else { + et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + 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: + 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; + } + + return 0xff; + } + + return 0xff; +} + + +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.status |= ACL_XYST; + + if (!(et4000->acl.internal.ctrl_routing & 7)) + et4000->acl.status |= ACL_SSO; + + if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { + et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + 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)) { + 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); + } + et4000->acl.pattern_x_back = et4000->acl.pattern_x; + + if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { + 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)) { + 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; +} + + +void +et4000w32p_blit_start(et4000w32p_t *et4000) +{ + 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; + et4000->acl.source_addr = et4000->acl.internal.source_addr; + et4000->acl.mix_addr = et4000->acl.internal.mix_addr; + et4000->acl.mix_back = et4000->acl.mix_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.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; + + if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { + et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; + 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)) { + 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); + } + et4000->acl.pattern_x_back = et4000->acl.pattern_x; + + if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { + 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)) { + 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; + + et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3; + et4000->acl.cpu_dat_pos = 0; + et4000->acl.cpu_dat = 0; + + et4000->acl.pix_pos = 0; +} + + +void +et4000w32_incx(int c, et4000w32p_t *et4000) +{ + et4000->acl.dest_addr += c; + et4000->acl.pattern_x += c; + et4000->acl.source_x += c; + et4000->acl.mix_addr += c; + if (et4000->acl.pattern_x >= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]) + et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; + if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]) + et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; +} + + +void +et4000w32_decx(int c, et4000w32p_t *et4000) +{ + et4000->acl.dest_addr -= c; + et4000->acl.pattern_x -= c; + et4000->acl.source_x -= c; + et4000->acl.mix_addr -= c; + if (et4000->acl.pattern_x < 0) + et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; + if (et4000->acl.source_x < 0) + et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; +} + + +void +et4000w32_incy(et4000w32p_t *et4000) +{ + et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1; + et4000->acl.source_addr += et4000->acl.internal.source_off + 1; + et4000->acl.mix_addr += et4000->acl.internal.mix_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; + } +} + + +void +et4000w32_decy(et4000w32p_t *et4000) +{ + et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1; + et4000->acl.source_addr -= et4000->acl.internal.source_off + 1; + et4000->acl.mix_addr -= et4000->acl.internal.mix_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));; + } +} + + +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.internal.xy_dir & 0x80){ /* Line draw */ + 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]; + source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask); + if (cpu_input == 2) { + source = sdat & 0xff; + sdat >>= 8; + } + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; + out = 0; + et4000w32_log("%06X ", et4000->acl.dest_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; + } + 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); + } + 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++; + } + + et4000->acl.pix_pos++; + et4000->acl.internal.pos_x++; + if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3)) { + if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000); + else et4000w32_incx(1, et4000); + } else { + if (et4000->acl.internal.xy_dir & 1) + et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); + else + et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); + et4000->acl.pix_pos = 0; + + /*Next pixel*/ + switch (et4000->acl.internal.xy_dir & 7) { + case 0: case 1: /* Y+ */ + et4000w32_incy(et4000); + et4000->acl.internal.pos_y++; + et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; + case 2: case 3: /* Y- */ + et4000w32_decy(et4000); + et4000->acl.internal.pos_y++; + et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; break; - case 0x40: case 0x60: /*256+ colours*/ - if (et4000->type <= ET4000W32I) - svga->clock /= 2; - - switch (svga->bpp) { - case 8: - svga->map8 = svga->pallook; - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; - case 15: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 24: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } + case 4: case 6: /* X+ */ + et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); break; + case 5: case 7: /* X- */ + et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + break; + } + et4000->acl.internal.error += et4000->acl.internal.dmin; + if (et4000->acl.internal.error > et4000->acl.internal.dmaj) { + et4000->acl.internal.error -= et4000->acl.internal.dmaj; + switch (et4000->acl.internal.xy_dir & 7) { + case 0: case 2: /* X+ */ + et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + et4000->acl.internal.pos_x++; + break; + case 1: case 3: /* X- */ + et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); + et4000->acl.internal.pos_x++; + break; + case 4: case 5: /* Y+ */ + et4000w32_incy(et4000); + et4000->acl.internal.pos_y++; + break; + case 6: case 7: /* Y- */ + et4000w32_decy(et4000); + et4000->acl.internal.pos_y++; + break; + } + } + if ((et4000->acl.internal.pos_x > et4000->acl.internal.count_x) || + (et4000->acl.internal.pos_y > et4000->acl.internal.count_y)) { + et4000w32_log("ACL status linedraw 0\n"); + et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + return; } } } -} + } else { + while (count--) { + et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); -void et4000w32p_recalcmapping(et4000w32p_t *et4000) -{ - svga_t *svga = &et4000->svga; - - if (et4000->pci && !(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->linear_mapping); - mem_mapping_disable(&et4000->mmu_mapping); - return; - } + 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 (svga->crtc[0x36] & 0x10) /*Linear frame buffer*/ - { - mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->mmu_mapping); - } - else - { - int map = (svga->gdcreg[6] & 0xc) >> 2; - if (svga->crtc[0x36] & 0x20) map |= 4; - if (svga->crtc[0x36] & 0x08) map |= 8; - switch (map) - { - case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x1ffff; - break; - case 0x1: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0xffff; - break; - case 0x2: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x7fff; - break; - case 0x3: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); - svga->banked_mask = 0x7fff; - break; - case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); - svga->banked_mask = 0xffff; - break; - case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); - 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); -} - -#define ACL_WRST 1 -#define ACL_RDST 2 -#define ACL_XYST 4 -#define ACL_SSO 8 - -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); 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); 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); 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); 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); break; - case 0x7f8e: - if (et4000->type >= ET4000W32P) - et4000->acl.queued.pixel_depth = val; - else - et4000->acl.queued.vbus = val; - break; - case 0x7f8f: et4000->acl.queued.xy_dir = val; break; - case 0x7f90: et4000->acl.queued.pattern_wrap = val; break; - case 0x7f92: et4000->acl.queued.source_wrap = val; 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); 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); break; - case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break; - case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break; - case 0x7f9e: et4000->acl.queued.rop_bg = val; break; - case 0x7f9f: et4000->acl.queued.rop_fg = val; 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.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P) { - 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); - } - } 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); - } - } - 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); 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); 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); 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); 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); break; - } -} - -static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val) -{ - if (et4000->type >= ET4000W32P) { - if (!(et4000->acl.status & ACL_XYST)) return; - if (et4000->acl.internal.ctrl_routing & 3) - { - if ((et4000->acl.internal.ctrl_routing & 3) == 2) - { - if (et4000->acl.mix_addr & 7) - et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); - else - et4000w32p_blit(8, val, 0, 1, et4000); - } - else if ((et4000->acl.internal.ctrl_routing & 3) == 1) - et4000w32p_blit(1, ~0, val, 2, et4000); - } + 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 { - if (!(et4000->acl.status & ACL_XYST)) { - et4000->acl.queued.dest_addr = (addr & 0x1FFF) + et4000->mmu.base[et4000->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); - et4000->acl.cpu_input_num = 0; - } - - if (et4000->acl.internal.ctrl_routing & 7) { - 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); - - et4000->acl.cpu_input_num = 0; - } + 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); + } 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; + } + + et4000->acl.pattern_x = et4000->acl.pattern_x_back; + et4000->acl.source_x = et4000->acl.source_x_back; + + 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; + } + + 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; } } -} - -static void fifo_thread(void *param) -{ - et4000w32p_t *et4000 = (et4000w32p_t *)param; - - uint64_t start_time = 0; - uint64_t end_time = 0; - - fifo_entry_t *fifo; - - while (1) - { - thread_set_event(et4000->fifo_not_full_event); - thread_wait_event(et4000->wake_fifo_thread, -1); - thread_reset_event(et4000->wake_fifo_thread); - et4000->blitter_busy = 1; - while (!FIFO_EMPTY) - { - start_time = plat_timer_read(); - fifo = &et4000->fifo[et4000->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - et4000w32p_accel_write_fifo(et4000, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_MMU: - et4000w32p_accel_write_mmu(et4000, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - et4000->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(et4000->fifo_not_full_event); - - end_time = plat_timer_read(); - et4000->blitter_time += end_time - start_time; - } - et4000->blitter_busy = 0; - } -} - -static __inline void wake_fifo_thread(et4000w32p_t *et4000) -{ - thread_set_event(et4000->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void et4000w32p_wait_fifo_idle(et4000w32p_t *et4000) -{ - while (!FIFO_EMPTY) - { - wake_fifo_thread(et4000); - thread_wait_event(et4000->fifo_not_full_event, 1); - } -} - -static void et4000w32p_queue(et4000w32p_t *et4000, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &et4000->fifo[et4000->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(et4000->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(et4000->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - et4000->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(et4000); -} - -void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) -{ - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; - - switch (addr & 0x6000) - { - case 0x0000: /*MMU 0*/ - case 0x2000: /*MMU 1*/ - case 0x4000: /*MMU 2*/ - et4000->bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << et4000->bank)) - { - if (et4000->type >= ET4000W32P) { - et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_MMU); - } else { - et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val); - } - } - else - { - if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] < svga->vram_max) - { - svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val; - svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) >> 12] = changeframecount; - } - } - break; - case 0x6000: - if ((addr & 0x7fff) >= 0x7f80) - { - if (et4000->type >= ET4000W32P) - et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_BYTE); - else - 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; - } - break; - } -} - -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)) - { - if (et4000->type >= ET4000W32P) - et4000w32p_wait_fifo_idle(et4000); - - temp = 0xff; - if (et4000->acl.cpu_dat_pos) - { - et4000->acl.cpu_dat_pos--; - temp = et4000->acl.cpu_dat & 0xff; - et4000->acl.cpu_dat >>= 8; - } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) - et4000w32p_blit(4, ~0, 0, 0, et4000); - /*???*/ - return temp; - } - if ((addr&0x1fff) + et4000->mmu.base[bank] >= svga->vram_max) - return 0xff; - return svga->vram[(addr&0x1fff) + et4000->mmu.base[bank]]; - - case 0x6000: - if ((addr & 0x7fff) >= 0x7f80) { - if (et4000->type >= ET4000W32P) - et4000w32p_wait_fifo_idle(et4000); - } - 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; - - case 0x7f36: - if (et4000->type >= ET4000W32P) { - temp = et4000->acl.status; - temp &= ~(ACL_RDST | ACL_WRST); - if (!FIFO_EMPTY) - temp |= ACL_RDST; - if (FIFO_FULL) - temp |= ACL_WRST; - if (temp == ACL_XYST && (et4000->acl.internal.ctrl_routing & 3)) - temp |= ACL_RDST; - } else { - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); - 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: - if (et4000->type >= ET4000W32P) - 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; - } - return 0xff; - } - return 0xff; -} - -static int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000}; -static int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF}; -static int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; - -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.status |= ACL_XYST; - if (!(et4000->acl.internal.ctrl_routing & 7)) - et4000->acl.status |= ACL_SSO; - - if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) - { - et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; - 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)) - { - 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); - } - et4000->acl.pattern_x_back = et4000->acl.pattern_x; - - if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) - { - 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)) - { - 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; -} - -void et4000w32p_blit_start(et4000w32p_t *et4000) -{ - 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; - et4000->acl.source_addr = et4000->acl.internal.source_addr; - et4000->acl.mix_addr = et4000->acl.internal.mix_addr; - et4000->acl.mix_back = et4000->acl.mix_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.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; - - if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) - { - et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; - 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)) - { - 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); - } - et4000->acl.pattern_x_back = et4000->acl.pattern_x; - - if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) - { - 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)) - { - 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; - - et4000->acl.internal.count_x += (et4000->acl.internal.pixel_depth >> 4) & 3; - et4000->acl.cpu_dat_pos = 0; - et4000->acl.cpu_dat = 0; - - et4000->acl.pix_pos = 0; -} - -void et4000w32_incx(int c, et4000w32p_t *et4000) -{ - et4000->acl.dest_addr += c; - et4000->acl.pattern_x += c; - et4000->acl.source_x += c; - et4000->acl.mix_addr += c; - if (et4000->acl.pattern_x >= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]) - et4000->acl.pattern_x -= et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; - if (et4000->acl.source_x >= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]) - et4000->acl.source_x -= et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; -} -void et4000w32_decx(int c, et4000w32p_t *et4000) -{ - et4000->acl.dest_addr -= c; - et4000->acl.pattern_x -= c; - et4000->acl.source_x -= c; - et4000->acl.mix_addr -= c; - if (et4000->acl.pattern_x < 0) - et4000->acl.pattern_x += et4000w32_max_x[et4000->acl.internal.pattern_wrap & 7]; - if (et4000->acl.source_x < 0) - et4000->acl.source_x += et4000w32_max_x[et4000->acl.internal.source_wrap & 7]; -} -void et4000w32_incy(et4000w32p_t *et4000) -{ - et4000->acl.pattern_addr += et4000->acl.internal.pattern_off + 1; - et4000->acl.source_addr += et4000->acl.internal.source_off + 1; - et4000->acl.mix_addr += et4000->acl.internal.mix_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; - } -} -void et4000w32_decy(et4000w32p_t *et4000) -{ - et4000->acl.pattern_addr -= et4000->acl.internal.pattern_off + 1; - et4000->acl.source_addr -= et4000->acl.internal.source_off + 1; - et4000->acl.mix_addr -= et4000->acl.internal.mix_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));; - } -} - -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)) return; - if (et4000->acl.internal.xy_dir & 0x80) /*Line draw*/ - { - 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]; - source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask, (et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask); - if (cpu_input == 2) - { - source = sdat & 0xff; - sdat >>= 8; - } - dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; - out = 0; - et4000w32_log("%06X ", et4000->acl.dest_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; - } - 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); - } - 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++; - } - - et4000->acl.pix_pos++; - et4000->acl.internal.pos_x++; - if (et4000->acl.pix_pos <= ((et4000->acl.internal.pixel_depth >> 4) & 3)) - { - if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000); - else et4000w32_incx(1, et4000); - } - else - { - if (et4000->acl.internal.xy_dir & 1) - et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); - else - et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); - et4000->acl.pix_pos = 0; - /*Next pixel*/ - switch (et4000->acl.internal.xy_dir & 7) - { - case 0: case 1: /*Y+*/ - et4000w32_incy(et4000); - et4000->acl.internal.pos_y++; - et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; - break; - case 2: case 3: /*Y-*/ - et4000w32_decy(et4000); - et4000->acl.internal.pos_y++; - et4000->acl.internal.pos_x -= ((et4000->acl.internal.pixel_depth >> 4) & 3) + 1; - break; - case 4: case 6: /*X+*/ - et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - break; - case 5: case 7: /*X-*/ - et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - break; - } - et4000->acl.internal.error += et4000->acl.internal.dmin; - if (et4000->acl.internal.error > et4000->acl.internal.dmaj) - { - et4000->acl.internal.error -= et4000->acl.internal.dmaj; - switch (et4000->acl.internal.xy_dir & 7) - { - case 0: case 2: /*X+*/ - et4000w32_incx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - et4000->acl.internal.pos_x++; - break; - case 1: case 3: /*X-*/ - et4000w32_decx(((et4000->acl.internal.pixel_depth >> 4) & 3) + 1, et4000); - et4000->acl.internal.pos_x++; - break; - case 4: case 5: /*Y+*/ - et4000w32_incy(et4000); - et4000->acl.internal.pos_y++; - break; - case 6: case 7: /*Y-*/ - et4000w32_decy(et4000); - et4000->acl.internal.pos_y++; - break; - } - } - if (et4000->acl.internal.pos_x > et4000->acl.internal.count_x || - et4000->acl.internal.pos_y > et4000->acl.internal.count_y) - { - et4000w32_log("ACL status linedraw 0\n"); - et4000->acl.status &= ~(ACL_XYST | ACL_SSO); - return; - } - } - } - } - else - { - 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]; - 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); - } - 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; - } - - et4000->acl.pattern_x = et4000->acl.pattern_x_back; - et4000->acl.source_x = et4000->acl.source_x_back; - - 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; - } - 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; - } - } - } - } + } + } } -void et4000w32p_hwcursor_draw(svga_t *svga, int displine) +void +et4000w32p_hwcursor_draw(svga_t *svga, int displine) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - int x, offset; - int xx, shift = (et4000->adjust_cursor + 1); - int xx2, width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff); - int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16; - uint8_t dat; - offset = svga->hwcursor_latch.xoff; + et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; + int x, offset, xx, xx2; + int shift = (et4000->adjust_cursor + 1); + int width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff); + int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16; + uint8_t dat; + offset = svga->hwcursor_latch.xoff; - for (x = 0; x < width; x += 4) { - dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; + for (x = 0; x < width; x += 4) { + dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; - xx = svga->hwcursor_latch.x + svga->x_add + x; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; - xx++; - if (!(xx % shift)) { - xx2 = xx / shift; - if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; - else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; - } - dat >>= 2; + xx = svga->hwcursor_latch.x + svga->x_add + x; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; + xx++; + if (!(xx % shift)) { + xx2 = xx / shift; + if (!(dat & 2)) buffer32->line[displine][xx2] = (dat & 1) ? 0xFFFFFF : 0; + else if ((dat & 3) == 3) buffer32->line[displine][xx2] ^= 0xFFFFFF; + } + dat >>= 2; - offset += 4; - } + offset += 4; + } - svga->hwcursor_latch.addr += pitch; + svga->hwcursor_latch.addr += pitch; } -static void et4000w32p_io_remove(et4000w32p_t *et4000) -{ - io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_removehandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); +static void +et4000w32p_io_remove(et4000w32p_t *et4000) +{ + io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + + io_removehandler(0x210a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x211a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x212a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x213a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x214a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x215a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x216a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_removehandler(0x217a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); } -static void et4000w32p_io_set(et4000w32p_t *et4000) -{ - et4000w32p_io_remove(et4000); - - io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); - io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); +static void +et4000w32p_io_set(et4000w32p_t *et4000) +{ + et4000w32p_io_remove(et4000); + + io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + + io_sethandler(0x210a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x211a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x212a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x213a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x214a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x215a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x216a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + io_sethandler(0x217a, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); } -uint8_t et4000w32p_pci_read(int func, int addr, void *p) + +uint8_t +et4000w32p_pci_read(int func, int addr, void *p) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; + et4000w32p_t *et4000 = (et4000w32p_t *)p; - addr &= 0xff; + addr &= 0xff; - switch (addr) - { - case 0x00: return 0x0c; /*Tseng Labs*/ - case 0x01: return 0x10; - - case 0x02: return 0x06; /*ET4000W32p Rev D*/ - case 0x03: return 0x32; - - case PCI_REG_COMMAND: - return et4000->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + switch (addr) { + case 0x00: return 0x0c; /* Tseng Labs */ + case 0x01: return 0x10; - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0x06; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x00; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; /* This has to be done in order to make this card work with the two 486 PCI machines. */ - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return 0x00; - case 0x13: return (et4000->linearbase >> 24); + case 0x02: return (et4000->rev); + case 0x03: return 0x32; - case 0x30: return et4000->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return 0x00; - case 0x33: return et4000->pci_regs[0x33] & 0xf0; + case PCI_REG_COMMAND: + return et4000->pci_regs[PCI_REG_COMMAND] | 0x80; /* Respond to IO and memory accesses */ - } - return 0; + case 0x07: return 1 << 1; /* Medium DEVSEL timing */ + + case 0x08: return 0x06; /* Revision ID */ + case 0x09: return 0; /* Programming interface */ + + case 0x0a: return 0x00; /* Supports VGA interface, XGA compatible */ + case 0x0b: return 0x03; /* This has to be done in order to make this card work with the two 486 PCI machines. */ + + case 0x10: return 0x00; /* Linear frame buffer address */ + case 0x11: return 0x00; + case 0x12: return 0x00; + case 0x13: return (et4000->linearbase >> 24); + + case 0x30: return et4000->pci_regs[0x30] & 0x01; /* BIOS ROM address */ + case 0x31: return 0x00; + case 0x32: return 0x00; + case 0x33: return et4000->pci_regs[0x33] & 0xf0; + } + + return 0; } -void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) + +void +et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - svga_t *svga = &et4000->svga; + et4000w32p_t *et4000 = (et4000w32p_t *)p; + svga_t *svga = &et4000->svga; - addr &= 0xff; + addr &= 0xff; - switch (addr) - { - case PCI_REG_COMMAND: - et4000->pci_regs[PCI_REG_COMMAND] = (val & 0x23) | 0x80; - if (val & PCI_COMMAND_IO) - et4000w32p_io_set(et4000); - else - et4000w32p_io_remove(et4000); - et4000w32p_recalcmapping(et4000); - break; + switch (addr) { + case PCI_REG_COMMAND: + et4000->pci_regs[PCI_REG_COMMAND] = (val & 0x23) | 0x80; + if (val & PCI_COMMAND_IO) + et4000w32p_io_set(et4000); + else + et4000w32p_io_remove(et4000); + et4000w32p_recalcmapping(et4000); + break; - case 0x13: + case 0x13: et4000->linearbase &= 0x00c00000; - et4000->linearbase |= (et4000->pci_regs[0x13] << 24); + et4000->linearbase |= (et4000->pci_regs[0x13] << 24); svga->crtc[0x30] &= 3; svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); - et4000w32p_recalcmapping(et4000); - break; + et4000w32p_recalcmapping(et4000); + break; - case 0x30: case 0x31: case 0x32: case 0x33: - et4000->pci_regs[addr] = val; + case 0x30: case 0x31: case 0x32: case 0x33: + et4000->pci_regs[addr] = val; et4000->pci_regs[0x30] = 1; et4000->pci_regs[0x31] = 0; et4000->pci_regs[0x32] = 0; et4000->pci_regs[0x33] &= 0xf0; - if (et4000->pci_regs[0x30] & 0x01) - { - uint32_t addr = (et4000->pci_regs[0x33] << 24); + if (et4000->pci_regs[0x30] & 0x01) { + uint32_t addr = (et4000->pci_regs[0x33] << 24); if (!addr) - { - addr = 0xC0000; - } - et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr); - mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); - } - else - { - et4000w32_log("ET4000 bios_rom disabled\n"); - mem_mapping_disable(&et4000->bios_rom.mapping); - } - return; - } -} - -void *et4000w32p_init(const device_t *info) -{ - int vram_size; - et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); - memset(et4000, 0, sizeof(et4000w32p_t)); - - vram_size = device_get_config_int("memory"); - et4000->interleaved = (vram_size == 2 && (info->local >= ET4000W32I)) ? 1 : 0; - - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci); - else if (info->flags & DEVICE_VLB) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_vlb); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa); - - svga_init(info, &et4000->svga, et4000, vram_size << 20, - et4000w32p_recalctimings, - et4000w32p_in, et4000w32p_out, - et4000w32p_hwcursor_draw, - NULL); - - et4000->vram_mask = (vram_size << 20) - 1; - - et4000->type = info->local; - - switch(et4000->type) { - case ET4000W32: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; - - case ET4000W32I: - if (et4000->isa) - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - else - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; - - case ET4000W32P: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; - break; - - case ET4000W32_CARDEX: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; - break; - - case ET4000W32_DIAMOND: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = device_add(&icd2061_device); - et4000->svga.getclock = icd2061_getclock; - break; - } - et4000->pci = !!(info->flags & DEVICE_PCI); - et4000->isa = !!(info->flags & (DEVICE_ISA | DEVICE_AT)); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&et4000->bios_rom.mapping); - - mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); - mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); - - et4000w32p_io_set(et4000); - - if (info->flags & DEVICE_PCI) - pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); - - /* Hardwired bits: 00000000 1xx0x0xx */ - /* R/W bits: xx xxxx */ - /* PCem bits: 111 */ - et4000->pci_regs[0x04] = 0x83; - - et4000->pci_regs[0x10] = 0x00; - et4000->pci_regs[0x11] = 0x00; - et4000->pci_regs[0x12] = 0xff; - et4000->pci_regs[0x13] = 0xff; - - et4000->pci_regs[0x30] = 0x00; - et4000->pci_regs[0x31] = 0x00; - et4000->pci_regs[0x32] = 0x00; - et4000->pci_regs[0x33] = 0xf0; - - if (et4000->type >= ET4000W32P) { - et4000w32_log("Thread started\n"); - et4000->wake_fifo_thread = thread_create_event(); - et4000->fifo_not_full_event = thread_create_event(); - et4000->fifo_thread = thread_create(fifo_thread, et4000); + addr = 0xc0000; + et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); + } else { + et4000w32_log("ET4000 bios_rom disabled\n"); + mem_mapping_disable(&et4000->bios_rom.mapping); } - - return et4000; + return; + } } -int et4000w32_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32); -} -int et4000w32i_isa_available(void) +void * +et4000w32p_init(const device_t *info) { - return rom_present(BIOS_ROM_PATH_W32I_ISA); -} + int vram_size; + et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); + memset(et4000, 0, sizeof(et4000w32p_t)); -int et4000w32i_vlb_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32I_VLB); -} + vram_size = device_get_config_int("memory"); + et4000->interleaved = (vram_size == 2 && (info->local >= ET4000W32I)) ? 1 : 0; -int et4000w32p_noncardex_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P); -} + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_pci); + else if (info->flags & DEVICE_VLB) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_vlb); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa); -int et4000w32p_available(void) -{ - return rom_present(BIOS_ROM_PATH_DIAMOND); -} + svga_init(info, &et4000->svga, et4000, vram_size << 20, + et4000w32p_recalctimings, + et4000w32p_in, et4000w32p_out, + et4000w32p_hwcursor_draw, + NULL); -int et4000w32p_cardex_available(void) -{ - return rom_present(BIOS_ROM_PATH_CARDEX); -} + et4000->vram_mask = (vram_size << 20) - 1; -void et4000w32p_close(void *p) -{ - et4000w32p_t *et4000 = (et4000w32p_t *)p; + et4000->type = info->local; - svga_close(&et4000->svga); - - if (et4000->type >= ET4000W32P) { - thread_kill(et4000->fifo_thread); - thread_destroy_event(et4000->wake_fifo_thread); - thread_destroy_event(et4000->fifo_not_full_event); + switch(et4000->type) { + case ET4000W32: + /* ET4000/W32 */ + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; + + case ET4000W32I: + /* ET4000/W32i rev B */ + et4000->rev = 3; + + if (et4000->vlb) { + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + } else { + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); } - free(et4000); + et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; + + case ET4000W32P_REVC: + /* ET4000/W32p rev C */ + et4000->rev = 7; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; + + case ET4000W32P: + /* ET4000/W32p rev D */ + et4000->rev = 6; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; + + case ET4000W32P_CARDEX: + /* ET4000/W32p rev D */ + et4000->rev = 6; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; + + case ET4000W32P_DIAMOND: + /* ET4000/W32p rev D */ + et4000->rev = 6; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = device_add(&icd2061_device); + et4000->svga.getclock = icd2061_getclock; + break; + } + et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00; + et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00; + if (info->flags & DEVICE_PCI) + mem_mapping_disable(&et4000->bios_rom.mapping); + + mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); + mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); + + et4000w32p_io_set(et4000); + + if (info->flags & DEVICE_PCI) + pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); + + /* Hardwired bits: 00000000 1xx0x0xx */ + /* R/W bits: xx xxxx */ + /* PCem bits: 111 */ + et4000->pci_regs[0x04] = 0x83; + + et4000->pci_regs[0x10] = 0x00; + et4000->pci_regs[0x11] = 0x00; + et4000->pci_regs[0x12] = 0xff; + et4000->pci_regs[0x13] = 0xff; + + et4000->pci_regs[0x30] = 0x00; + et4000->pci_regs[0x31] = 0x00; + et4000->pci_regs[0x32] = 0x00; + et4000->pci_regs[0x33] = 0xf0; + + if (et4000->type >= ET4000W32P_REVC) { + et4000w32_log("Thread started\n"); + et4000->wake_fifo_thread = thread_create_event(); + et4000->fifo_not_full_event = thread_create_event(); + et4000->fifo_thread = thread_create(fifo_thread, et4000); + } + + return et4000; } -void et4000w32p_speed_changed(void *p) + +int +et4000w32_available(void) { - et4000w32p_t *et4000 = (et4000w32p_t *)p; - - svga_recalctimings(&et4000->svga); + return rom_present(BIOS_ROM_PATH_W32); } -void et4000w32p_force_redraw(void *p) + +int +et4000w32i_isa_available(void) { - et4000w32p_t *et4000w32p = (et4000w32p_t *)p; - - et4000w32p->svga.fullchange = changeframecount; + return rom_present(BIOS_ROM_PATH_W32I_ISA); } + +int +et4000w32i_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32I_VLB); +} + + +int +et4000w32p_revc_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_REVC); +} + + +int +et4000w32p_noncardex_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P); +} + + +int +et4000w32p_available(void) +{ + return rom_present(BIOS_ROM_PATH_DIAMOND); +} + + +int +et4000w32p_cardex_available(void) +{ + return rom_present(BIOS_ROM_PATH_CARDEX); +} + + +void +et4000w32p_close(void *p) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)p; + + svga_close(&et4000->svga); + + if (et4000->type >= ET4000W32P_REVC) { + thread_kill(et4000->fifo_thread); + thread_destroy_event(et4000->wake_fifo_thread); + thread_destroy_event(et4000->fifo_not_full_event); + } + + free(et4000); +} + + +void +et4000w32p_speed_changed(void *p) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)p; + + svga_recalctimings(&et4000->svga); +} + + +void +et4000w32p_force_redraw(void *p) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)p; + + et4000->svga.fullchange = changeframecount; +} + + static const device_config_t et4000w32p_config[] = { { @@ -1697,6 +1692,7 @@ static const device_config_t et4000w32p_config[] = } }; + const device_t et4000w32_device = { "Tseng Labs ET4000/w32", @@ -1730,6 +1726,28 @@ const device_t et4000w32i_vlb_device = et4000w32p_config }; +const device_t et4000w32p_revc_vlb_device = +{ + "Tseng Labs ET4000/w32p Rev. C VLB (Cardex)", + DEVICE_VLB, ET4000W32P_REVC, + et4000w32p_init, et4000w32p_close, NULL, + { et4000w32p_revc_available }, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_config +}; + +const device_t et4000w32p_revc_pci_device = +{ + "Tseng Labs ET4000/w32p Rev. C PCI (Cardex)", + DEVICE_PCI, ET4000W32P_REVC, + et4000w32p_init, et4000w32p_close, NULL, + { et4000w32p_revc_available }, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_config +}; + const device_t et4000w32p_noncardex_vlb_device = { "Tseng Labs ET4000/w32p VLB", @@ -1755,7 +1773,7 @@ const device_t et4000w32p_noncardex_pci_device = const device_t et4000w32p_cardex_vlb_device = { "Tseng Labs ET4000/w32p VLB (Cardex)", - DEVICE_VLB, ET4000W32_CARDEX, + DEVICE_VLB, ET4000W32P_CARDEX, et4000w32p_init, et4000w32p_close, NULL, { et4000w32p_cardex_available }, et4000w32p_speed_changed, @@ -1766,7 +1784,7 @@ const device_t et4000w32p_cardex_vlb_device = const device_t et4000w32p_cardex_pci_device = { "Tseng Labs ET4000/w32p PCI (Cardex)", - DEVICE_PCI, ET4000W32_CARDEX, + DEVICE_PCI, ET4000W32P_CARDEX, et4000w32p_init, et4000w32p_close, NULL, { et4000w32p_cardex_available }, et4000w32p_speed_changed, @@ -1777,7 +1795,7 @@ const device_t et4000w32p_cardex_pci_device = const device_t et4000w32p_vlb_device = { "Tseng Labs ET4000/w32p VLB (Diamond)", - DEVICE_VLB, ET4000W32_DIAMOND, + DEVICE_VLB, ET4000W32P_DIAMOND, et4000w32p_init, et4000w32p_close, NULL, { et4000w32p_available }, et4000w32p_speed_changed, @@ -1788,7 +1806,7 @@ const device_t et4000w32p_vlb_device = const device_t et4000w32p_pci_device = { "Tseng Labs ET4000/w32p PCI (Diamond)", - DEVICE_PCI, ET4000W32_DIAMOND, + DEVICE_PCI, ET4000W32P_DIAMOND, et4000w32p_init, et4000w32p_close, NULL, { et4000w32p_available }, et4000w32p_speed_changed, diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index 5bc62ea5a..fa6ab4990 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -39,6 +39,13 @@ enum }; +#define ICS_S3_MASK 7 +#define ICS_S3 8 + +#define S3_86C708 (ICS_5300 | ICS_S3) +#define S3_86C716 (ICS_5342 | ICS_S3) + + typedef struct sdac_ramdac_t { uint16_t regs[256]; @@ -54,7 +61,7 @@ sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val) { ramdac->command = val; - switch (ramdac->type) { + switch (ramdac->type & ICS_S3_MASK) { case ICS_5300: case ICS_5301: switch (val >> 5) { @@ -150,17 +157,31 @@ sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) { sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; uint8_t rs = (addr & 0x03); - rs |= (!!rs2 << 8); + rs |= ((!!rs2) << 2); + + if (rs != 0x02) + ramdac->magic_count = 0; switch (rs) { case 0x02: - if (ramdac->magic_count == 4) - sdac_control_write(ramdac, svga, val); - /* Fall through. */ + switch (ramdac->magic_count) { + case 4: + sdac_control_write(ramdac, svga, val); + if (!(ramdac->type & ICS_S3)) + ramdac->magic_count = 0; + break; + case 5: + ramdac->magic_count = 0; + break; + default: + svga_out(addr, val, svga); + break; + } + break; case 0x00: case 0x01: case 0x03: - ramdac->magic_count = 0; + svga_out(addr, val, svga); break; case 0x04: ramdac->windex = val; @@ -177,8 +198,6 @@ sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) ramdac->reg_ff = 0; break; } - - svga_out(addr, val, svga); } @@ -188,24 +207,41 @@ sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; uint8_t temp = 0xff; uint8_t rs = (addr & 0x03); - rs |= (!!rs2 << 8); + rs |= ((!!rs2) << 2); + + if (rs != 0x02) + ramdac->magic_count = 0; switch (rs) { case 0x02: - if (ramdac->magic_count < 5) + switch (ramdac->magic_count) { + case 1: + case 2: case 3: + temp = 0x00; ramdac->magic_count++; - if ((ramdac->magic_count == 4) && (ramdac->type != 1) && (ramdac->type != 2)) - temp = 0x70; /*SDAC ID*/ - else if (ramdac->magic_count == 5) { + break; + case 4: + if (ramdac->type & ICS_S3) { + temp = 0x70; /* SDAC ID */ + ramdac->magic_count++; + } else { + temp = ramdac->command; + ramdac->magic_count = 0; + } + break; + case 5: temp = ramdac->command; ramdac->magic_count = 0; - } else + break; + default: temp = svga_in(addr, svga); + ramdac->magic_count++; + break; + } break; case 0x00: case 0x01: case 0x03: - ramdac->magic_count = 0; temp = svga_in(addr, svga); break; case 0x04: @@ -281,7 +317,7 @@ sdac_ramdac_close(void *priv) const device_t gendac_ramdac_device = { "S3 GENDAC 86c708 RAMDAC", - 0, ICS_5300, + 0, S3_86C708, sdac_ramdac_init, sdac_ramdac_close, NULL, { NULL }, NULL, NULL }; @@ -305,7 +341,7 @@ const device_t tseng_ics5341_ramdac_device = const device_t sdac_ramdac_device = { "S3 SDAC 86c716 RAMDAC", - 0, ICS_5342, + 0, S3_86C716, sdac_ramdac_init, sdac_ramdac_close, NULL, { NULL }, NULL, NULL }; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index cd8d20ffa..2f9b9c4ff 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -91,7 +91,7 @@ video_cards[] = { { "mda", &mda_device }, { "genius", &genius_device }, { "metheus928_isa", &s3_metheus_86c928_isa_device }, - { "nga", &nga_device }, + { "nga", &nga_device }, { "ogc", &ogc_device }, { "oti037c", &oti037c_device }, { "oti067", &oti067_device }, @@ -120,7 +120,8 @@ video_cards[] = { { "mach64gx_pci", &mach64gx_pci_device }, { "mach64vt2", &mach64vt2_device }, { "et4000w32p_pci", &et4000w32p_cardex_pci_device }, - { "et4000w32p_nc_pci", &et4000w32p_noncardex_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 }, @@ -160,9 +161,10 @@ video_cards[] = { { "voodoo3_2k_pci", &voodoo_3_2000_device }, { "voodoo3_3k_pci", &voodoo_3_3000_device }, { "mach64gx_vlb", &mach64gx_vlb_device }, - { "et4000w32i_vlb", &et4000w32i_vlb_device }, + { "et4000w32i_vlb", &et4000w32i_vlb_device }, { "et4000w32p_vlb", &et4000w32p_cardex_vlb_device }, - { "et4000w32p_nc_vlb", &et4000w32p_noncardex_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 },