From ed5b69e26b3ba218b2d216e631b94000a61913c9 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Fri, 7 Oct 2016 09:09:09 -0500 Subject: [PATCH] Cirrus Logic core from QEMU. Code from TC1995, Rebased by MoochMcGee --- src/Makefile.am | 2 +- src/Makefile.mingw | 2 +- src/Makefile.mingw64 | 2 +- src/vid_cl5429.c | 915 ------------------------------- src/vid_cl_gd.c | 1113 ++++++++++++++++++++++++++++++++++++++ src/vid_cl_gd.h | 219 ++++++++ src/vid_cl_gd_blit.c | 821 ++++++++++++++++++++++++++++ src/vid_cl_gd_blit.h | 10 + src/vid_cl_gd_vga_rop.h | 207 +++++++ src/vid_cl_gd_vga_rop2.h | 281 ++++++++++ src/vid_cl_ramdac.c | 100 ++++ src/vid_cl_ramdac.h | 8 + src/video.c | 3 +- 13 files changed, 2764 insertions(+), 919 deletions(-) delete mode 100644 src/vid_cl5429.c create mode 100644 src/vid_cl_gd.c create mode 100644 src/vid_cl_gd.h create mode 100644 src/vid_cl_gd_blit.c create mode 100644 src/vid_cl_gd_blit.h create mode 100644 src/vid_cl_gd_vga_rop.h create mode 100644 src/vid_cl_gd_vga_rop2.h create mode 100644 src/vid_cl_ramdac.c create mode 100644 src/vid_cl_ramdac.h diff --git a/src/Makefile.am b/src/Makefile.am index 7cbcf1363..62307ee6f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,7 +27,7 @@ sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_cms.c sound_emu8k.c sound_g sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c thread-pthread.c \ timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \ -vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_hercules.c \ +vid_ati68860_ramdac.c vid_cga.c vid_cl_gd.c vid_cl_gd_blit.c vid_cl_ramdac.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_hercules.c \ vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_nv_riva128.c vid_nv_rivatnt.c vid_olivetti_m24.c vid_oti067.c vid_paradise.c vid_pc200.c \ vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c \ vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \ diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 8251ce1c8..10f2ad513 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -14,7 +14,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429 sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ - vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \ + vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_ega.o vid_et4000.o \ vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_nv_riva128.o vid_nv_rivatnt.o \ vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index b0559a9cb..536a7d400 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -14,7 +14,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429 sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ - vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \ + vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_ega.o vid_et4000.o \ vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_nv_riva128.o vid_nv_rivatnt.o \ vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c deleted file mode 100644 index cce6f3966..000000000 --- a/src/vid_cl5429.c +++ /dev/null @@ -1,915 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/*Cirrus Logic CL-GD5429 emulation*/ -#include -#include "ibm.h" -#include "device.h" -#include "io.h" -#include "mem.h" -#include "rom.h" -#include "video.h" -#include "vid_cl5429.h" -#include "vid_svga.h" -#include "vid_svga_render.h" -#include "vid_unk_ramdac.h" - -typedef struct gd5429_t -{ - mem_mapping_t mmio_mapping; - - svga_t svga; - - rom_t bios_rom; - - uint32_t bank[2]; - uint32_t mask; - - struct - { - uint16_t bg_col, fg_col; - uint16_t width, height; - uint16_t dst_pitch, src_pitch; - uint32_t dst_addr, src_addr; - uint8_t mask, mode, rop; - - uint32_t dst_addr_backup, src_addr_backup; - uint16_t width_backup, height_internal; - int x_count; - } blt; - -} gd5429_t; - -void gd5429_write(uint32_t addr, uint8_t val, void *p); -uint8_t gd5429_read(uint32_t addr, void *p); - -void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p); -uint8_t gd5429_mmio_read(uint32_t addr, void *p); - -void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p); -void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p); - -void gd5429_recalc_banking(gd5429_t *gd5429); -void gd5429_recalc_mapping(gd5429_t *gd5429); - -void gd5429_out(uint16_t addr, uint8_t val, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; - uint8_t old; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - -// pclog("gd5429 out %04X %02X\n", addr, val); - - switch (addr) - { - case 0x3c4: - svga->seqaddr = val; - break; - case 0x3c5: - if (svga->seqaddr > 5) - { - svga->seqregs[svga->seqaddr & 0x1f] = val; - switch (svga->seqaddr & 0x1f) - { - case 0x10: case 0x30: case 0x50: case 0x70: - case 0x90: case 0xb0: case 0xd0: case 0xf0: - svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7); - pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x); - break; - case 0x11: case 0x31: case 0x51: case 0x71: - case 0x91: case 0xb1: case 0xd1: case 0xf1: - svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7); - pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y); - break; - case 0x12: - svga->hwcursor.ena = val & 1; - pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena); - break; - case 0x13: - svga->hwcursor.addr = 0x1fc000 + ((val & 0x3f) * 256); - pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr); - break; - - case 0x17: - gd5429_recalc_mapping(gd5429); - break; - } - return; - } - break; - - case 0x3cf: - if (svga->gdcaddr == 5) - { - svga->gdcreg[5] = val; - if (svga->gdcreg[0xb] & 0x04) - svga->writemode = svga->gdcreg[5] & 7; - else - svga->writemode = svga->gdcreg[5] & 3; - svga->readmode = val & 8; -// pclog("writemode = %i\n", svga->writemode); - return; - } - if (svga->gdcaddr == 6) - { - if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) - { - svga->gdcreg[6] = val; - gd5429_recalc_mapping(gd5429); - } - svga->gdcreg[6] = val; - return; - } - if (svga->gdcaddr > 8) - { - svga->gdcreg[svga->gdcaddr & 0x3f] = val; - switch (svga->gdcaddr) - { - case 0x09: case 0x0a: case 0x0b: - gd5429_recalc_banking(gd5429); - if (svga->gdcreg[0xb] & 0x04) - svga->writemode = svga->gdcreg[5] & 7; - else - svga->writemode = svga->gdcreg[5] & 3; - break; - } - return; - } - break; - - case 0x3D4: - svga->crtcreg = val & 0x3f; - return; - case 0x3D5: - if (svga->crtcreg <= 0x18) - val &= mask_crtc[svga->crtcreg]; - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - svga_out(addr, val, svga); -} - -uint8_t gd5429_in(uint16_t addr, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - -// if (addr != 0x3da) pclog("IN gd5429 %04X\n", addr); - - switch (addr) - { - case 0x3c5: - if (svga->seqaddr > 5) - { - switch (svga->seqaddr) - { - case 6: - return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; - } - return svga->seqregs[svga->seqaddr & 0x3f]; - } - break; - - case 0x3cf: - if (svga->gdcaddr > 8) - { - return svga->gdcreg[svga->gdcaddr & 0x3f]; - } - break; - - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - switch (svga->crtcreg) - { - case 0x27: /*ID*/ - return 0x9c; /*GD5429*/ - } - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); -} - -void gd5429_recalc_banking(gd5429_t *gd5429) -{ - svga_t *svga = &gd5429->svga; - - if (svga->gdcreg[0xb] & 0x20) - gd5429->bank[0] = (svga->gdcreg[0x09] & 0x7f) << 14; - else - gd5429->bank[0] = svga->gdcreg[0x09] << 12; - - if (svga->gdcreg[0xb] & 0x01) - { - if (svga->gdcreg[0xb] & 0x20) - gd5429->bank[1] = (svga->gdcreg[0x0a] & 0x7f) << 14; - else - gd5429->bank[1] = svga->gdcreg[0x0a] << 12; - } - else - gd5429->bank[1] = gd5429->bank[0] + 0x8000; -} - -void gd5429_recalc_mapping(gd5429_t *gd5429) -{ - svga_t *svga = &gd5429->svga; - - pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04); - switch (svga->gdcreg[6] & 0x0C) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - if (svga->seqregs[0x17] & 0x04) - mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0x7fff; - break; - } -} - -void gd5429_recalctimings(svga_t *svga) -{ - gd5429_t *gd5429 = (gd5429_t *)svga->p; - - if (svga->seqregs[7] & 0x01) - { - svga->render = svga_render_8bpp_highres; - } - - svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); - pclog("MA now %05X %02X\n", svga->ma_latch, svga->crtc[0x1b]); -} - -void gd5429_hwcursor_draw(svga_t *svga, int displine) -{ - int x; - uint8_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - - pclog("HWcursor %i %i %i %i %x %02X %02X\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, offset, displine, svga->hwcursor_latch.addr, vram[svga->hwcursor_latch.addr], vram[svga->hwcursor_latch.addr + 0x80]); - for (x = 0; x < 32; x += 8) - { - dat[0] = svga->vram[svga->hwcursor_latch.addr]; - dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80]; - for (xx = 0; xx < 8; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (dat[1] & 0x80) - ((uint32_t *)buffer32->line[displine])[offset + 32] = 0; - if (dat[0] & 0x80) - ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr++; - } -} - - -void gd5429_write_linear(uint32_t addr, uint8_t val, void *p); - -void gd5429_write(uint32_t addr, uint8_t val, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; -// pclog("gd5429_write : %05X %02X ", addr, val); - addr &= svga->banked_mask; - addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; -// pclog("%08X\n", addr); - gd5429_write_linear(addr, val, p); -} - -uint8_t gd5429_read(uint32_t addr, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; - uint8_t ret; -// pclog("gd5429_read : %05X ", addr); - addr &= svga->banked_mask; - addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - ret = svga_read_linear(addr, &gd5429->svga); -// pclog("%08X %02X\n", addr, ret); - return ret; -} - -void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - uint32_t raddr = addr; - int plane, mask; - - cycles -= video_timing_b; - cycles_lost += video_timing_b; - - egawrites++; - -// if (svga_output) pclog("Write LFB %08X %02X ", addr, val); - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) - { - writemask2 = 1 << (addr & 3); - addr &= ~3; - } - else if (svga->chain2_write) - { - if ((svga->gdcreg[6] & 0xC) == 0x4) - { - writemask2 &= (svga->oddeven_page ? ~0xe : ~0xb); - } - else - { - writemask2 &= ~0xa; - } - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } - else - { - addr <<= 2; - } - addr &= 0x7fffff; - if (addr >= svga->vram_limit) - return; -// if (svga_output) pclog("%08X\n", addr); - svga->changedvram[addr >> 12] = changeframecount; - - switch (svga->writemode) - { - case 4: - pclog("Writemode 4 : %X ", addr); - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; - pclog("%X %X\n", addr, val); - if (val & 0x80) - svga->vram[addr + 0] = svga->gdcreg[1]; - if (val & 0x40) - svga->vram[addr + 1] = svga->gdcreg[1]; - if (val & 0x20) - svga->vram[addr + 2] = svga->gdcreg[1]; - if (val & 0x10) - svga->vram[addr + 3] = svga->gdcreg[1]; - if (val & 0x08) - svga->vram[addr + 4] = svga->gdcreg[1]; - if (val & 0x04) - svga->vram[addr + 5] = svga->gdcreg[1]; - if (val & 0x02) - svga->vram[addr + 6] = svga->gdcreg[1]; - if (val & 0x01) - svga->vram[addr + 7] = svga->gdcreg[1]; - break; - - case 5: - pclog("Writemode 5 : %X ", addr); - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; - pclog("%X %X\n", addr, val); - svga->vram[addr + 0] = (val & 0x80) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 1] = (val & 0x40) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 2] = (val & 0x20) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 3] = (val & 0x10) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 4] = (val & 0x08) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 5] = (val & 0x04) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 6] = (val & 0x02) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + 7] = (val & 0x01) ? svga->gdcreg[1] : svga->gdcreg[0]; - break; - - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) - { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } - else - { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } -// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) - { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; - } -} - -void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - svga_t *svga = &gd5429->svga; - - pclog("gd5429_start_blit %i\n", count); - if (count == -1) - { - gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr; - gd5429->blt.src_addr_backup = gd5429->blt.src_addr; - gd5429->blt.width_backup = gd5429->blt.width; - gd5429->blt.height_internal = gd5429->blt.height; - gd5429->blt.x_count = gd5429->blt.mask & 7; - pclog("gd5429_start_blit : size %i, %i\n", gd5429->blt.width, gd5429->blt.height); - - if (gd5429->blt.mode & 0x04) - { -// pclog("blt.mode & 0x04\n"); - mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l); - mem_mapping_set_p(&svga->mapping, gd5429); - return; - } - else - { - mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); - mem_mapping_set_p(&gd5429->svga.mapping, gd5429); - gd5429_recalc_mapping(gd5429); - } - } - - while (count) - { - uint8_t src, dst; - int mask; - - if (gd5429->blt.mode & 0x04) - { - if (gd5429->blt.mode & 0x80) - { - src = (cpu_dat & 0x80) ? gd5429->blt.fg_col : gd5429->blt.bg_col; - mask = cpu_dat & 0x80; - cpu_dat <<= 1; - count--; - } - else - { - src = cpu_dat & 0xff; - cpu_dat >>= 8; - count -= 8; - mask = 1; - } - } - else - { - switch (gd5429->blt.mode & 0xc0) - { - case 0x00: - src = svga->vram[gd5429->blt.src_addr & svga->vrammask]; - gd5429->blt.src_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1); - mask = 1; - break; - case 0x40: - src = svga->vram[(gd5429->blt.src_addr & (svga->vrammask & ~7)) | (gd5429->blt.dst_addr & 7)]; - mask = 1; - break; - case 0x80: - mask = svga->vram[gd5429->blt.src_addr & svga->vrammask] & (0x80 >> gd5429->blt.x_count); - src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col; - gd5429->blt.x_count++; - if (gd5429->blt.x_count == 8) - { - gd5429->blt.x_count = 0; - gd5429->blt.src_addr++; - } - break; - case 0xc0: - mask = svga->vram[gd5429->blt.src_addr & svga->vrammask] & (0x80 >> (gd5429->blt.dst_addr & 7)); - src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col; - break; - } - count--; - } - dst = svga->vram[gd5429->blt.dst_addr & svga->vrammask]; - svga->changedvram[(gd5429->blt.dst_addr & svga->vrammask) >> 12] = changeframecount; - - pclog("Blit %i,%i %06X %06X %06X %02X %02X %02X %02X ", gd5429->blt.width, gd5429->blt.height_internal, gd5429->blt.src_addr, gd5429->blt.dst_addr, gd5429->blt.src_addr & svga->vrammask, svga->vram[gd5429->blt.src_addr & svga->vrammask], 0x80 >> (gd5429->blt.dst_addr & 7), src, dst); - switch (gd5429->blt.rop) - { - case 0x00: dst = 0; break; - case 0x05: dst = src & dst; break; - case 0x06: dst = dst; break; - case 0x09: dst = src & ~dst; break; - case 0x0b: dst = ~ dst; break; - case 0x0d: dst = src; break; - case 0x0e: dst = 0xff; break; - case 0x50: dst = ~ src & dst; break; - case 0x59: dst = src ^ dst; break; - case 0x6d: dst = src | dst; break; - case 0x90: dst = ~(src | dst); break; - case 0x95: dst = ~(src ^ dst); break; - case 0xad: dst = src | ~dst; break; - case 0xd0: dst = ~src; break; - case 0xd6: dst = ~src | dst; break; - case 0xda: dst = ~(src & dst); break; - } - pclog("%02X %02X\n", dst, mask); - - if ((gd5429->blt.width_backup - gd5429->blt.width) >= (gd5429->blt.mask & 7) && - !((gd5429->blt.mode & 0x08) && !mask)) - svga->vram[gd5429->blt.dst_addr & svga->vrammask] = dst; - - gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1); - - gd5429->blt.width--; - - if (gd5429->blt.width == 0xffff) - { - gd5429->blt.width = gd5429->blt.width_backup; - - gd5429->blt.dst_addr = gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.dst_pitch : gd5429->blt.dst_pitch); - - switch (gd5429->blt.mode & 0xc0) - { - case 0x00: - gd5429->blt.src_addr = gd5429->blt.src_addr_backup = gd5429->blt.src_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.src_pitch : gd5429->blt.src_pitch); - break; - case 0x40: - gd5429->blt.src_addr = ((gd5429->blt.src_addr + ((gd5429->blt.mode & 0x01) ? -8 : 8)) & 0x38) | (gd5429->blt.src_addr & ~0x38); - break; - case 0x80: - if (gd5429->blt.x_count != 0) - { - gd5429->blt.x_count = 0; - gd5429->blt.src_addr++; - } - break; - case 0xc0: - gd5429->blt.src_addr = ((gd5429->blt.src_addr + ((gd5429->blt.mode & 0x01) ? -1 : 1)) & 7) | (gd5429->blt.src_addr & ~7); - break; - } - - gd5429->blt.height_internal--; - if (gd5429->blt.height_internal == 0xffff) - { - if (gd5429->blt.mode & 0x04) - { - mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); - mem_mapping_set_p(&gd5429->svga.mapping, gd5429); - gd5429_recalc_mapping(gd5429); - } - return; - } - - if (gd5429->blt.mode & 0x04) - return; - } - } -} - -void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - pclog("MMIO write %08X %02X\n", addr, val); - switch (addr & 0xff) - { - case 0x00: - gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xff00) | val; - break; - case 0x01: - gd5429->blt.bg_col = (gd5429->blt.bg_col & 0x00ff) | (val << 8); - break; - - case 0x04: - gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xff00) | val; - break; - case 0x05: - gd5429->blt.fg_col = (gd5429->blt.fg_col & 0x00ff) | (val << 8); - break; - - case 0x08: - gd5429->blt.width = (gd5429->blt.width & 0xff00) | val; - break; - case 0x09: - gd5429->blt.width = (gd5429->blt.width & 0x00ff) | (val << 8); - break; - case 0x0a: - gd5429->blt.height = (gd5429->blt.height & 0xff00) | val; - break; - case 0x0b: - gd5429->blt.height = (gd5429->blt.height & 0x00ff) | (val << 8); - break; - case 0x0c: - gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0xff00) | val; - break; - case 0x0d: - gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0x00ff) | (val << 8); - break; - case 0x0e: - gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0xff00) | val; - break; - case 0x0f: - gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0x00ff) | (val << 8); - break; - - case 0x10: - gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xffff00) | val; - break; - case 0x11: - gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xff00ff) | (val << 8); - break; - case 0x12: - gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0x00ffff) | (val << 16); - break; - - case 0x14: - gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xffff00) | val; - break; - case 0x15: - gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xff00ff) | (val << 8); - break; - case 0x16: - gd5429->blt.src_addr = (gd5429->blt.src_addr & 0x00ffff) | (val << 16); - break; - - case 0x17: - gd5429->blt.mask = val; - break; - case 0x18: - gd5429->blt.mode = val; - break; - - case 0x1a: - gd5429->blt.rop = val; - break; - - case 0x40: - if (val & 0x02) - gd5429_start_blit(0, -1, gd5429); - break; - } -} - -uint8_t gd5429_mmio_read(uint32_t addr, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - pclog("MMIO read %08X\n", addr); - switch (addr & 0xff) - { - case 0x40: /*BLT status*/ - return 0; - } - return 0xff; /*All other registers read-only*/ -} - -void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p) -{ - pclog("gd5429_blt_write_w %08X %08X\n", addr, val); - gd5429_start_blit(val, 16, p); -} - -void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - pclog("gd5429_blt_write_l %08X %08X %04X %04X\n", addr, val, ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00), ((val >> 24) & 0x00ff) | ((val >> 8) & 0xff00)); - if ((gd5429->blt.mode & 0x84) == 0x84) - { - gd5429_start_blit( val & 0xff, 8, p); - gd5429_start_blit((val >> 8) & 0xff, 8, p); - gd5429_start_blit((val >> 16) & 0xff, 8, p); - gd5429_start_blit((val >> 24) & 0xff, 8, p); - } - else - gd5429_start_blit(val, 32, p); -} - -void *gd5429_init() -{ - gd5429_t *gd5429 = malloc(sizeof(gd5429_t)); - svga_t *svga = &gd5429->svga; - memset(gd5429, 0, sizeof(gd5429_t)); - - rom_init(&gd5429->bios_rom, "roms/5429.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - svga_init(&gd5429->svga, gd5429, 1 << 21, /*2mb*/ - gd5429_recalctimings, - gd5429_in, gd5429_out, - gd5429_hwcursor_draw, - NULL); - - mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); - mem_mapping_set_p(&gd5429->svga.mapping, gd5429); - - mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, NULL, NULL, gd5429_mmio_write, NULL, NULL, NULL, 0, gd5429); - - io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); - - svga->hwcursor.yoff = 32; - svga->hwcursor.xoff = 0; - - gd5429->bank[1] = 0x8000; - - return gd5429; -} - -static int gd5429_available() -{ - return rom_present("roms/5429.vbi"); -} - -void gd5429_close(void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - svga_close(&gd5429->svga); - - free(gd5429); -} - -void gd5429_speed_changed(void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - svga_recalctimings(&gd5429->svga); -} - -void gd5429_force_redraw(void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - gd5429->svga.fullchange = changeframecount; -} - -void gd5429_add_status_info(char *s, int max_len, void *p) -{ - gd5429_t *gd5429 = (gd5429_t *)p; - - svga_add_status_info(s, max_len, &gd5429->svga); -} - -device_t gd5429_device = -{ - "Cirrus Logic GD5429", - DEVICE_NOT_WORKING, - gd5429_init, - gd5429_close, - gd5429_available, - gd5429_speed_changed, - gd5429_force_redraw, - gd5429_add_status_info -}; diff --git a/src/vid_cl_gd.c b/src/vid_cl_gd.c new file mode 100644 index 000000000..4038e94af --- /dev/null +++ b/src/vid_cl_gd.c @@ -0,0 +1,1113 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "io.h" +#include "mem.h" +#include "rom.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_svga_render.h" +#include "vid_cl_ramdac.h" +#include "vid_cl_gd.h" +#include "vid_cl_gd_blit.h" + +void cirrus_update_bank_ptr(clgd_t *clgd, uint8_t bank_index); +void clgd_recalctimings(svga_t *svga); + +void svga_write_cirrus(uint32_t addr, uint8_t val, void *p); +void svga_write_cirrus_linear(uint32_t addr, uint8_t val, void *p); +void svga_write_cirrus_linear_bitblt(uint32_t addr, uint8_t val, void *p); +uint8_t svga_read_cirrus(uint32_t addr, void *p); +uint8_t svga_read_cirrus_linear(uint32_t addr, void *p); +uint8_t svga_read_cirrus_linear_bitblt(uint32_t addr, void *p); + +void clgd_out(uint16_t addr, uint8_t val, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + // pclog("clgd out %04X %02X\n", addr, val); + + switch (addr) + { + case 0x3c4: + svga->seqaddr = val; + break; + case 0x3c5: + if (svga->seqaddr > 5) + { + old = svga->seqregs[svga->seqaddr & 0x1f]; + switch (svga->seqaddr & 0x1f) + { + case 0x06: + val &= 0x17; + if (val == 0x12) + { + svga->seqregs[svga->seqaddr & 0x1f] = 0x12; + } + else + { + svga->seqregs[svga->seqaddr & 0x1f] = 0xf; + } + break; + + case 0x10: case 0x30: case 0x50: case 0x70: + case 0x90: case 0xb0: case 0xd0: case 0xf0: + svga->seqregs[0x10] = val; + svga->hwcursor.x = (val << 3) | (svga->seqaddr >> 5); + // pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x); + break; + + case 0x11: case 0x31: case 0x51: case 0x71: + case 0x91: case 0xb1: case 0xd1: case 0xf1: + svga->seqregs[0x11] = val; + svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5); + // pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y); + break; + + case 0x07: + cirrus_update_memory_access(clgd); + clgd_recalctimings(svga); + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x14: case 0x15: case 0x16: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + svga->seqregs[svga->seqaddr & 0x1f] = val; + break; + + case 0x13: + svga->seqregs[svga->seqaddr & 0x1f] = val; + svga->hwcursor.addr = 0x1fc000 + ((val & 0x3f) * 256); + // pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr); + break; + + case 0x12: + svga->seqregs[svga->seqaddr & 0x1f] = val; + svga->hwcursor.ena = val & 1; + // pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena); + break; + + case 0x17: + old = svga->seqregs[svga->seqaddr & 0x1f]; + svga->seqregs[svga->seqaddr & 0x1f] = (svga->seqregs[svga->seqaddr & 0x1f] & 0x38) | (val & 0xc7); + cirrus_update_memory_access(clgd); + break; + } + return; + } + break; + + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: + // pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc); + cl_ramdac_out(addr, val, &clgd->ramdac, clgd, svga); + return; + + case 0x3cf: + if (svga->gdcaddr == 5) + { + svga->gdcreg[5] = val & 0x7f; + if (svga->gdcreg[0xb] & 0x04) + svga->writemode = svga->gdcreg[5] & 7; + else + svga->writemode = svga->gdcreg[5] & 3; + cirrus_update_memory_access(clgd); + svga_out(addr, val, svga); + return; + } + if (svga->gdcaddr == 6) + { + if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) + { + svga->gdcreg[6] = val; + cirrus_update_memory_access(clgd); + } + svga->gdcreg[6] = val; + return; + } + if (svga->gdcaddr > 8) + { + switch (svga->gdcaddr) + { + case 0x09: case 0x0A: case 0x0B: + svga->gdcreg[svga->gdcaddr & 0x3f] = val; + cirrus_update_bank_ptr(clgd, 0); + cirrus_update_bank_ptr(clgd, 1); + if (svga->gdcreg[0xb] & 0x04) + svga->writemode = svga->gdcreg[5] & 7; + else + svga->writemode = svga->gdcreg[5] & 3; + cirrus_update_memory_access(clgd); + break; + + case 0x21: case 0x23: case 0x25: case 0x27: + svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x1f; + break; + + case 0x2a: + svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x3f; + /* if auto start mode, starts bit blt now */ + if (svga->gdcreg[0x31] & CIRRUS_BLT_AUTOSTART) cirrus_bitblt_start(clgd, svga); + break; + + case 0x2e: + svga->gdcreg[svga->gdcaddr & 0x3f] = val & 0x3f; + break; + + case 0x31: + cirrus_write_bitblt(clgd, svga, val); + break; + + default: + svga->gdcreg[svga->gdcaddr & 0x3f] = val; + break; + } + return; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (svga->crtcreg <= 0x18) + val &= mask_crtc[svga->crtcreg]; + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + if ((svga->crtcreg != 0x22) && (svga->crtcreg != 0x24) && (svga->crtcreg != 0x26) && (svga->crtcreg != 0x27)) svga->crtc[svga->crtcreg] = val; + if ((svga->crtcreg == 0x22) || (svga->crtcreg == 0x24) || (svga->crtcreg == 0x26) || (svga->crtcreg == 0x27)) return; + + if (old != val) + { + if (svga->crtcreg == 0x1b) + { + svga->vrammask = (val & 2) ? (clgd->vram_size - 1) : 0x3ffff; + clgd->linear_mmio_mask = (val & 2) ? (clgd->vram_size - 256) : (0x40000 - 256); + } + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t clgd_in(uint16_t addr, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1)) + addr ^= 0x60; + + // if (addr != 0x3da) pclog("IN clgd %04X\n", addr); + + switch (addr) + { + case 0x3c5: + if (svga->seqaddr > 5) + { + switch (svga->seqaddr) + { + case 0x06: + return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; + + case 0x10: case 0x30: case 0x50: case 0x70: + case 0x90: case 0xb0: case 0xd0: case 0xf0: + return svga->seqregs[0x10]; + + case 0x11: case 0x31: case 0x51: case 0x71: + case 0x91: case 0xb1: case 0xd1: case 0xf1: + return svga->seqregs[0x11]; + + case 0x15: + return clgd->vram_code; + + case 0x05: case 0x07: case 0x08: case 0x09: + case 0x0a: case 0x0b: case 0x0c: case 0x0d: + case 0x0e: case 0x0f: case 0x12: case 0x13: + case 0x14: case 0x16: case 0x17: case 0x18: + case 0x19: case 0x1a: case 0x1b: case 0x1c: + case 0x1d: case 0x1e: case 0x1f: + return svga->seqregs[svga->seqaddr]; + } + return svga->seqregs[svga->seqaddr & 0x3f]; + } + break; + + case 0x3cf: + if (svga->gdcaddr >= 0x3a) + { + return 0xff; + } + if (svga->gdcaddr > 8) + { + return svga->gdcreg[svga->gdcaddr & 0x3f]; + } + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: +// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc); + return cl_ramdac_in(addr, &clgd->ramdac, clgd, svga); + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + switch (svga->crtcreg) + { + case 0x24: /*Attribute controller toggle readback (R)*/ + return svga->attrff << 7; + case 0x26: /*Attribute controller index readback (R)*/ + return svga->attraddr & 0x3f; + } + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); +} + +/*************************************** + * + * bank memory + * + ***************************************/ +void cirrus_update_bank_ptr(clgd_t *clgd, uint8_t bank_index) +{ + svga_t *svga = &clgd->svga; + + uint32_t offset; + uint32_t limit; + + if ((svga->gdcreg[0x0b] & 0x01) != 0) /* dual bank */ + offset = svga->gdcreg[0x09 + bank_index]; + else /* single bank */ + offset = svga->gdcreg[0x09]; + + if ((svga->gdcreg[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + if (clgd->vram_size <= offset) + limit = 0; + else + limit = clgd->vram_size - offset; + + if (((svga->gdcreg[0x0b] & 0x01) == 0) && (bank_index != 0)) { + if (limit > 0x8000) { + offset += 0x8000; + limit -= 0x8000; + } else { + limit = 0; + } + } + + if (limit > 0) { + clgd->bank[bank_index] = offset; + clgd->limit[bank_index] = limit; + } else { + clgd->bank[bank_index] = 0; + clgd->limit[bank_index] = 0; + } +} + +void clgd_recalctimings(svga_t *svga) +{ + clgd_t *clgd = (clgd_t *)svga->p; + + uint32_t iWidth, iHeight; + uint8_t iDispBpp; + + svga->ma_latch = (svga->crtc[0x0c] << 8) + + svga->crtc[0x0d] + + ((svga->crtc[0x1b] & 0x01) << 16) + + ((svga->crtc[0x1b] & 0x0c) << 15) + + ((svga->crtc[0x1d] & 0x80) << 12); + svga->ma_latch <<= 2; + + iHeight = 1 + svga->crtc[0x12] + + ((svga->crtc[0x07] & 0x02) << 7) + + ((svga->crtc[0x07] & 0x40) << 3); + + if ((svga->crtc[0x1a] & 0x01) > 0) { + iHeight <<= 1; + svga->vtotal *= 2; + svga->dispend *= 2; + svga->vblankstart *= 2; + svga->vsyncstart *= 2; + svga->split *= 2; + } + + iWidth = (svga->crtc[0x01] + 1) * 8; + iDispBpp = 4; + + if ((svga->seqregs[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA) + { + pclog("Cirrus SVGA extended sequencer mode %x\n", svga->seqregs[0x07]); + switch (svga->seqregs[0x07] & CIRRUS_SR7_BPP_MASK) + { + case CIRRUS_SR7_BPP_8: + iDispBpp = 8; + svga->render = svga_render_8bpp_highres; + break; + + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + case CIRRUS_SR7_BPP_16: + case 0x7: + if (clgd->ramdac.ctrl & 0x1) + { + iDispBpp = 16; + svga->render = svga_render_16bpp_highres; + } + else + { + iDispBpp = 15; + svga->render = svga_render_15bpp_highres; + } + break; + + case 0x3: + case CIRRUS_SR7_BPP_24: + case 0x5: + case 0xe: + iDispBpp = 24; + svga->render = svga_render_24bpp_highres; + break; + + case CIRRUS_SR7_BPP_32: + iDispBpp = 32; + svga->render = svga_render_32bpp_highres; + break; + } + } + + if ((iWidth != svga->video_res_x) || (iHeight != svga->video_res_y) + || (iDispBpp != svga->bpp)) { + pclog("Cirrus switched to %u x %u x %u\n", iWidth, iHeight, iDispBpp); + } + + svga->video_res_x = iWidth; + svga->video_res_y = iHeight; + svga->bpp = iDispBpp; + // pclog("MA now %05X %02X\n", svga->ma_latch, svga->crtc[0x1b]); +} + +void clgd_hwcursor_draw(svga_t *svga, int displine) +{ + int x; + uint8_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int largecur = (svga->seqregs[0x12] & 4); + int cursize = (largecur) ? 64 : 32; + int y_add = enable_overscan ? 16 : 0; + int x_add = enable_overscan ? 8 : 0; + + for (x = 0; x < cursize; x += 8) + { + dat[0] = svga->vram[svga->hwcursor_latch.addr]; + dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80]; + for (xx = 0; xx < 8; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (dat[1] & 0x80) + ((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] = 0; + if (dat[0] & 0x80) + ((uint32_t *)buffer32->line[displine + y_add])[offset + cursize + x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr++; + } +} + +void cirrus_update_memory_access(clgd_t *clgd) +{ + svga_t *svga = &clgd->svga; + + if ((svga->seqregs[0x17] & 0x44) == 0x44) + { + goto generic_io; + } + else if (clgd->src_ptr != clgd->src_ptr_end) + { + goto generic_io; + } + else + { + if ((svga->gdcreg[0x0B] & 0x14) == 0x14) + { + goto generic_io; + } + else if (svga->gdcreg[0x0B] & 0x02) + { + goto generic_io; + } + + svga->writemode = svga->gdcreg[0x05] & 7; + if (svga->writemode < 4 || svga->writemode > 5 || ((svga->gdcreg[0x0B] & 0x4) == 0)) + { + //pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04); + switch (svga->gdcreg[6] & 0x0C) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&clgd->mmio_mapping); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + if (svga->seqregs[0x17] & 0x04) + mem_mapping_set_addr(&clgd->mmio_mapping, 0xb8000, 0x00100); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_disable(&clgd->mmio_mapping); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_disable(&clgd->mmio_mapping); + svga->banked_mask = 0x7fff; + break; + } + } + else + { +generic_io: + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&clgd->mmio_mapping); + } + } +} + +void svga_write_mode45_8bpp(clgd_t *clgd, uint8_t mode, uint32_t offset, uint8_t mem_value) +{ + int x; + uint8_t val = mem_value; + uint8_t *dst; + svga_t *svga = &clgd->svga; + + dst = svga->vram + (offset &= svga->vrammask); + + svga->changedvram[(offset &= svga->vrammask) >> 12] = changeframecount; + + for (x = 0; x < 8; x++) + { + if (val & 0x80) + { + *dst = clgd->blt.fg_col; + } + else + { + *dst = clgd->blt.bg_col; + } + val <<= 1; + dst++; + } +} + +void svga_write_mode45_16bpp(clgd_t *clgd, unsigned mode, unsigned offset, uint32_t mem_value) +{ + int x; + unsigned val = mem_value; + uint8_t *dst; + svga_t *svga = &clgd->svga; + + dst = svga->vram + (offset &= svga->vrammask); + + svga->changedvram[(offset &= svga->vrammask) >> 12] = changeframecount; + + for (x = 0; x < 8; x++) + { + if (val & 0x80) + { + *dst = clgd->blt.fg_col; + *(dst + 1) = svga->gdcreg[0x11]; + } + else + { + *dst = clgd->blt.bg_col; + *(dst + 1) = svga->gdcreg[0x10]; + } + val <<= 1; + dst += 2; + } +} + +uint8_t cirrus_mmio_blt_read(uint32_t address, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + uint8_t value; + + switch(address & 0xff) + { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + value = svga->gdcreg[0x00]; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + value = svga->gdcreg[0x10]; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + value = svga->gdcreg[0x12]; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + value = svga->gdcreg[0x14]; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + value = svga->gdcreg[0x01]; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + value = svga->gdcreg[0x11]; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + value = svga->gdcreg[0x13]; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + value = svga->gdcreg[0x15]; + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + value = svga->gdcreg[0x20]; + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + value = svga->gdcreg[0x21]; + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + value = svga->gdcreg[0x22]; + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + value = svga->gdcreg[0x23]; + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + value = svga->gdcreg[0x24]; + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + value = svga->gdcreg[0x25]; + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + value = svga->gdcreg[0x26]; + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + value = svga->gdcreg[0x27]; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + value = svga->gdcreg[0x28]; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + value = svga->gdcreg[0x29]; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + value = svga->gdcreg[0x2a]; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + value = svga->gdcreg[0x2c]; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + value = svga->gdcreg[0x2d]; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + value = svga->gdcreg[0x2e]; + break; + case (CIRRUS_MMIO_BLTWRITEMASK): + value = svga->gdcreg[0x2f]; + break; + case (CIRRUS_MMIO_BLTMODE): + value = svga->gdcreg[0x30]; + break; + case (CIRRUS_MMIO_BLTROP): + value = svga->gdcreg[0x32]; + break; + case (CIRRUS_MMIO_BLTMODEEXT): + value = svga->gdcreg[0x33]; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + value = svga->gdcreg[0x34]; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + value = svga->gdcreg[0x35]; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + value = svga->gdcreg[0x38]; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + value = svga->gdcreg[0x39]; + break; + } + + return value; +} + +void cirrus_mmio_blt_write(uint32_t address, uint8_t value, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + + switch(address & 0xff) + { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + svga->gdcreg[0x00] = value; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + svga->gdcreg[0x10] = value; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + svga->gdcreg[0x12] = value; + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + svga->gdcreg[0x14] = value; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + svga->gdcreg[0x01] = value; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + svga->gdcreg[0x11] = value; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + svga->gdcreg[0x13] = value; + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + svga->gdcreg[0x15] = value; + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + svga->gdcreg[0x20] = value; + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + svga->gdcreg[0x21] = value; + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + svga->gdcreg[0x22] = value; + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + svga->gdcreg[0x23] = value; + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + svga->gdcreg[0x24] = value; + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + svga->gdcreg[0x25] = value; + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + svga->gdcreg[0x26] = value; + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + svga->gdcreg[0x27] = value; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + svga->gdcreg[0x28] = value; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + svga->gdcreg[0x29] = value; + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + svga->gdcreg[0x2a] = value; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + svga->gdcreg[0x2c] = value; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + svga->gdcreg[0x2d] = value; + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + svga->gdcreg[0x2e] = value; + break; + case (CIRRUS_MMIO_BLTWRITEMASK): + svga->gdcreg[0x2f] = value; + break; + case (CIRRUS_MMIO_BLTMODE): + svga->gdcreg[0x30] = value; + break; + case (CIRRUS_MMIO_BLTROP): + svga->gdcreg[0x32] = value; + break; + case (CIRRUS_MMIO_BLTMODEEXT): + svga->gdcreg[0x33] = value; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + svga->gdcreg[0x34] = value; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + svga->gdcreg[0x35] = value; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + svga->gdcreg[0x38] = value; + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + svga->gdcreg[0x39] = value; + break; + } +} + +void cirrus_write(uint32_t addr, uint8_t val, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + +// pclog("gd5429_write : %05X %02X ", addr, val); + if (clgd->src_ptr != clgd->src_ptr_end) + { + /* bitblt */ + *clgd->src_ptr++ = (uint8_t) val; + if (clgd->src_ptr >= clgd->src_ptr_end) + { + cirrus_bitblt_cputovideo_next(clgd, svga); + } + } + + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + clgd->bank[(addr >> 15) & 1]; +// pclog("%08X\n", addr); +// svga_write_linear(addr, val, &clgd->svga); + svga->writemode = svga->gdcreg[0x05] & 0x7; + if (svga->writemode < 4 || svga->writemode > 5 || ((svga->gdcreg[0x0B] & 0x4) == 0)) { + svga_write_linear(addr, val, &clgd->svga); + } else { + if ((svga->gdcreg[0x0B] & 0x14) != 0x14) { + svga_write_mode45_8bpp(clgd, svga->writemode, + addr, + val); + } else { + svga_write_mode45_16bpp(clgd, svga->writemode, + addr, + val); + } + } +} + +uint8_t cirrus_read(uint32_t addr, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + svga_t *svga = &clgd->svga; + uint8_t ret; + +// pclog("gd5429_read : %05X ", addr); + addr &= svga->banked_mask; + addr = (addr & 0x7fff) + clgd->bank[(addr >> 15) & 1]; + ret = svga_read_linear(addr, &clgd->svga); +// pclog("%08X %02X\n", addr, ret); + return ret; +} + +void *clgd_common_init(char *romfn, uint8_t id) +{ + clgd = malloc(sizeof(clgd_t)); + svga_t *svga = &clgd->svga; + memset(clgd, 0, sizeof(clgd_t)); + + rom_init(&clgd->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + svga_init(&clgd->svga, clgd, 1 << 21, /*2mb*/ + clgd_recalctimings, + clgd_in, clgd_out, + clgd_hwcursor_draw, + NULL); + + mem_mapping_set_handler(&svga->mapping, cirrus_read, NULL, NULL, cirrus_write, NULL, NULL); + mem_mapping_set_p(&svga->mapping, clgd); + + mem_mapping_add(&clgd->mmio_mapping, 0, 0, cirrus_mmio_blt_read, NULL, NULL, cirrus_mmio_blt_write, NULL, NULL, NULL, 0, clgd); + + io_sethandler(0x03c0, 0x0020, clgd_in, NULL, NULL, clgd_out, NULL, NULL, clgd); + + if (id < CIRRUS_ID_CLGD5428) + { + /* 1 MB */ + clgd->vram_size = (1 << 20); + clgd->vram_code = 2; + + svga->seqregs[0xf] = 0x18; + svga->seqregs[0x1f] = 0x22; + } + else if ((id >= CIRRUS_ID_CLGD5428) && (id <= CIRRUS_ID_CLGD5430)) + { + /* 2 MB */ + clgd->vram_size = (1 << 21); + clgd->vram_code = 3; + + svga->seqregs[0xf] = 0x18; + svga->seqregs[0x1f] = 0x22; + } + else if (id >= CIRRUS_ID_CLGD5434) + { + /* 4 MB */ + clgd->vram_size = (1 << 22); + clgd->vram_code = 4; + + svga->seqregs[0xf] = 0x98; + svga->seqregs[0x1f] = 0x2d; + svga->seqregs[0x17] = 0x20; + svga->gdcreg[0x18] = 0xf; + } + + // Seems the 5436 and 5446 BIOS'es never turn on that bit until it's actually needed, + // therefore they also don't turn it back off on 640x480x4bpp, + // therefore, we need to make sure the VRAM mask is correct at start. + svga->vrammask = (svga->crtc[0x1b] & 2) ? (clgd->vram_size - 1) : 0x3ffff; + clgd->linear_mmio_mask = (svga->crtc[0x1b] & 2) ? (clgd->vram_size - 256) : (0x40000 - 256); + + svga->seqregs[0x15] = clgd->vram_code; + if ((id >= CIRRUS_ID_CLGD5422) && (id <= CIRRUS_ID_CLGD5429)) svga->seqregs[0xa] = (clgd->vram_code << 3); + + svga->crtc[0x27] = id; + + // clgd_recalc_mapping(clgd); + /* force refresh */ + // cirrus_update_bank_ptr(s, 0); + // cirrus_update_bank_ptr(s, 1); + + init_rops(); + + return clgd; +} + +void *gd6235_init() +{ + return clgd_common_init("roms/vga6235.rom", CIRRUS_ID_CLGD6235); +} + +void *gd5422_init() +{ + return clgd_common_init("roms/CL5422.ROM", CIRRUS_ID_CLGD5422); +} + +void *gd5429_init() +{ + return clgd_common_init("roms/5429.vbi", CIRRUS_ID_CLGD5429); +} + +void *gd5430_init() +{ + return clgd_common_init("roms/pci.BIN", CIRRUS_ID_CLGD5430); +} + +void *dia5430_init() +{ + return clgd_common_init("roms/diamondvlbus.BIN", CIRRUS_ID_CLGD5430); +} + +void *gd5434_init() +{ + return clgd_common_init("roms/japan.BIN", CIRRUS_ID_CLGD5434); +} + +void *gd5436_init() +{ + return clgd_common_init("roms/5436.VBI", CIRRUS_ID_CLGD5436); +} + +void *gd5440_init() +{ + return clgd_common_init("roms/5440BIOS.BIN", CIRRUS_ID_CLGD5440); +} + +void *gd5446_init() +{ + return clgd_common_init("roms/5446BV.VBI", CIRRUS_ID_CLGD5446); +} + +static int gd5422_available() +{ + return rom_present("roms/CL5422.ROM"); +} + +static int gd5429_available() +{ + return rom_present("roms/5429.vbi"); +} + +static int gd5430_available() +{ + return rom_present("roms/pci.BIN"); +} + +static int dia5430_available() +{ + return rom_present("roms/diamondvlbus.BIN"); +} + +static int gd5434_available() +{ + return rom_present("roms/japan.BIN"); +} + +static int gd5436_available() +{ + return rom_present("roms/5436.VBI"); +} + +static int gd5440_available() +{ + return rom_present("roms/5440BIOS.BIN"); +} + +static int gd5446_available() +{ + return rom_present("roms/5446BV.VBI"); +} + +static int gd6235_available() +{ + return rom_present("roms/vga6235.rom"); +} + +void clgd_close(void *p) +{ + clgd_t *clgd = (clgd_t *)p; + + svga_close(&clgd->svga); + + free(clgd); +} + +void clgd_speed_changed(void *p) +{ + clgd_t *clgd = (clgd_t *)p; + + svga_recalctimings(&clgd->svga); +} + +void clgd_force_redraw(void *p) +{ + clgd_t *clgd = (clgd_t *)p; + + clgd->svga.fullchange = changeframecount; +} + +void clgd_add_status_info(char *s, int max_len, void *p) +{ + clgd_t *clgd = (clgd_t *)p; + + svga_add_status_info(s, max_len, &clgd->svga); +} + +device_t gd5422_device = +{ + "Cirrus Logic GD5422", + // DEVICE_NOT_WORKING, + 0, + gd5422_init, + clgd_close, + gd5422_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5429_device = +{ + "Cirrus Logic GD5429", + // DEVICE_NOT_WORKING, + 0, + gd5429_init, + clgd_close, + gd5429_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5430_device = +{ + "Cirrus Logic GD5430", + // DEVICE_NOT_WORKING, + 0, + gd5430_init, + clgd_close, + gd5430_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t dia5430_device = +{ + "Diamond CL-GD5430", + // DEVICE_NOT_WORKING, + 0, + dia5430_init, + clgd_close, + dia5430_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5434_device = +{ + "Cirrus Logic GD5434", + // DEVICE_NOT_WORKING, + 0, + gd5434_init, + clgd_close, + gd5434_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5436_device = +{ + "Cirrus Logic GD5436", + // DEVICE_NOT_WORKING, + 0, + gd5436_init, + clgd_close, + gd5436_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5440_device = +{ + "Cirrus Logic GD5440", + // DEVICE_NOT_WORKING, + 0, + gd5440_init, + clgd_close, + gd5440_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd5446_device = +{ + "Cirrus Logic GD5446", + // DEVICE_NOT_WORKING, + 0, + gd5446_init, + clgd_close, + gd5446_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; + +device_t gd6235_device = +{ + "Cirrus Logic GD6235", + // DEVICE_NOT_WORKING, + 0, + gd6235_init, + clgd_close, + gd6235_available, + clgd_speed_changed, + clgd_force_redraw, + clgd_add_status_info +}; \ No newline at end of file diff --git a/src/vid_cl_gd.h b/src/vid_cl_gd.h new file mode 100644 index 000000000..6e0123cf4 --- /dev/null +++ b/src/vid_cl_gd.h @@ -0,0 +1,219 @@ +// ID +#define CIRRUS_ID_CLGD6225 (0x02<<2) +#define CIRRUS_ID_CLGD5402 (0x06<<2) /* Also Acumos AVGA2 */ +#define CIRRUS_ID_CLGD7542 (0x0B<<2) /* Nordic */ +#define CIRRUS_ID_CLGD7543 (0x0C<<2) /* Viking - guess */ +#define CIRRUS_ID_CLGD7541 (0x0D<<2) /* Nordic Lite */ +#define CIRRUS_ID_CLGD6215 (0x12<<2) +#define CIRRUS_ID_CLGD6235 (0x22<<2) /* Also 5402 */ +#define CIRRUS_ID_CLGD5422 (0x23<<2) +#define CIRRUS_ID_CLGD5426 (0x24<<2) +#define CIRRUS_ID_CLGD5424 (0x25<<2) /* Also 5422-80 */ +#define CIRRUS_ID_CLGD5428 (0x26<<2) +#define CIRRUS_ID_CLGD5429 (0x27<<2) +#define CIRRUS_ID_CLGD5430 (0x28<<2) +#define CIRRUS_ID_CLGD5432 0xA2 +#define CIRRUS_ID_CLGD5434O (0x29<<2) /* O = obsolete, never used? */ +#define CIRRUS_ID_CLGD5434 (0x2A<<2) +#define CIRRUS_ID_CLGD5436 (0x2B<<2) +#define CIRRUS_ID_CLGD5436U (0x3A<<2) +#define CIRRUS_ID_CLGD5440 (0x2C<<2) +#define CIRRUS_ID_CLGD5442 (0x2D<<2) +#define CIRRUS_ID_CLGD5446 (0x2E<<2) +#define CIRRUS_ID_CLGD5455 (0x2F<<2) /* Laguna 3D */ +#define CIRRUS_ID_CLGD6205 (0x32<<2) /* Laguna 3D */ +#define CIRRUS_ID_CLGD5462 (0x34<<2) /* Laguna */ +#define CIRRUS_ID_CLGD5464 (0xD5) /* Laguna BD */ +#define CIRRUS_ID_CLGD5465 (0xD6) /* Laguna 3D */ + +// sequencer 0x07 +#define CIRRUS_SR7_BPP_VGA 0x00 +#define CIRRUS_SR7_BPP_SVGA 0x01 +#define CIRRUS_SR7_BPP_MASK 0x0e +#define CIRRUS_SR7_BPP_8 0x00 +#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 +#define CIRRUS_SR7_BPP_24 0x04 +#define CIRRUS_SR7_BPP_16 0x06 +#define CIRRUS_SR7_BPP_32 0x08 +#define CIRRUS_SR7_ISAADDR_MASK 0xe0 + +// sequencer 0x0f +#define CIRRUS_MEMSIZE_512k 0x08 +#define CIRRUS_MEMSIZE_1M 0x10 +#define CIRRUS_MEMSIZE_2M 0x18 +#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. + +// sequencer 0x12 +#define CIRRUS_CURSOR_SHOW 0x01 +#define CIRRUS_CURSOR_HIDDENPEL 0x02 +#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear + +// sequencer 0x17 +#define CIRRUS_BUSTYPE_VLBFAST 0x10 +#define CIRRUS_BUSTYPE_PCI 0x20 +#define CIRRUS_BUSTYPE_VLBSLOW 0x30 +#define CIRRUS_BUSTYPE_ISA 0x38 +#define CIRRUS_MMIO_ENABLE 0x04 +#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. +#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 + +// control 0x0b +#define CIRRUS_BANKING_DUAL 0x01 +#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k + +// control 0x30 +#define CIRRUS_BLTMODE_BACKWARDS 0x01 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 + +// control 0x31 +#define CIRRUS_BLT_BUSY 0x01 +#define CIRRUS_BLT_START 0x02 +#define CIRRUS_BLT_RESET 0x04 +#define CIRRUS_BLT_FIFOUSED 0x10 +#define CIRRUS_BLT_AUTOSTART 0x80 + +// control 0x32 +#define CIRRUS_ROP_0 0x00 +#define CIRRUS_ROP_SRC_AND_DST 0x05 +#define CIRRUS_ROP_NOP 0x06 +#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 +#define CIRRUS_ROP_NOTDST 0x0b +#define CIRRUS_ROP_SRC 0x0d +#define CIRRUS_ROP_1 0x0e +#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 +#define CIRRUS_ROP_SRC_XOR_DST 0x59 +#define CIRRUS_ROP_SRC_OR_DST 0x6d +#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 +#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 +#define CIRRUS_ROP_SRC_OR_NOTDST 0xad +#define CIRRUS_ROP_NOTSRC 0xd0 +#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 +#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda + +#define CIRRUS_ROP_NOP_INDEX 2 +#define CIRRUS_ROP_SRC_INDEX 5 + +// control 0x33 +#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 +#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 +#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 + +// memory-mapped IO +#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword +#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword +#define CIRRUS_MMIO_BLTWIDTH 0x08 // word +#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word +#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word +#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word +#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword +#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword +#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte +#define CIRRUS_MMIO_BLTMODE 0x18 // byte +#define CIRRUS_MMIO_BLTROP 0x1a // byte +#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte +#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? +#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? +#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word +#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word +#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word +#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte +#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word +#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word +#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word +#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word +#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte +#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte +#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte + +#define CIRRUS_PNPMMIO_SIZE 0x1000 + +#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ + +typedef struct clgd_t +{ + mem_mapping_t mmio_mapping; + + svga_t svga; + cl_ramdac_t ramdac; + + rom_t bios_rom; + + PALETTE hiddenpal; + + uint32_t vram_size; + uint8_t vram_code; + + uint32_t linear_mmio_mask; + + uint32_t bank[2]; + uint32_t limit[2]; + + uint32_t ramptr; + int src_counter; + uint8_t *src_ptr; + uint8_t *src_ptr_end; + + struct + { + uint8_t bpp; + uint32_t bg_col, fg_col; + uint16_t width, height; + uint16_t dst_pitch, src_pitch; + int32_t dst_addr, src_addr; + uint8_t mask, mode, rop, modeext; + uint32_t blttc, blttcmask; + uint16_t ld_start_x, ld_start_y, ld_end_x, ld_end_y; + uint8_t ld_ls_inc, ld_ls_ro, ld_ls_mask, ld_ls_ac; + uint16_t bres_k1, bres_k3, bres_err, bres_dm; + uint8_t bres_dir, ld_mode, blt_status; + + uint32_t dst_addr_backup, src_addr_backup; + uint16_t width_backup, height_internal; + int x_count; + uint8_t buf[CIRRUS_BLTBUFSIZE]; + + uint16_t pixel_width, pixel_height; + } blt; +} clgd_t; + +typedef void (*cirrus_bitblt_rop_t) (clgd_t *clgd, svga_t *svga, + uint8_t * dst, const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight); + +typedef void (*cirrus_fill_t)(clgd_t *clgd, svga_t *svga, + uint8_t *dst, int dst_pitch, int width, int height); + +cirrus_bitblt_rop_t cirrus_rop; + +extern device_t gd5422_device; +extern device_t gd5429_device; +extern device_t gd5430_device; +extern device_t dia5430_device; +extern device_t gd5434_device; +extern device_t gd5436_device; +extern device_t gd5440_device; +extern device_t gd5446_device; +extern device_t gd6235_device; + +clgd_t *clgd; + +void clgd_recalctimings(svga_t *svga); + +void cirrus_update_memory_access(clgd_t *clgd); + +void cirrus_write(uint32_t addr, uint8_t val, void *p); +uint8_t cirrus_read(uint32_t addr, void *p); \ No newline at end of file diff --git a/src/vid_cl_gd_blit.c b/src/vid_cl_gd_blit.c new file mode 100644 index 000000000..0a5348629 --- /dev/null +++ b/src/vid_cl_gd_blit.c @@ -0,0 +1,821 @@ +/*This is the CL-GD 5446 blitter, directly from QEMU*/ +#include +#include "ibm.h" +#include "device.h" +#include "io.h" +#include "mem.h" +#include "rom.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_svga_render.h" +#include "vid_cl_ramdac.h" +#include "vid_cl_gd.h" +#include "vid_cl_gd_blit.h" + +// Same for all the svga->vrammask which are -s>cirrus_addr_mask in the original. + +// Eventually this needs to be configurable +#define clgd_vram_size clgd->vram_size + +#define true 1 +#define false 0 +#define bool int + +#define glue(a,b) glue_hidden(a,b) +#define glue_hidden(a,b) a ## b + +int cl_gd_ABS(int sval) +{ + if (sval < 0) + { + return -sval; + } + else + { + return sval; + } +} + +bool blit_region_is_unsafe(clgd_t *clgd, svga_t *svga, int32_t pitch, int32_t addr) +{ + if (pitch < 0) + { + int64_t min = addr + ((int64_t)clgd->blt.height-1) * pitch; + int32_t max = addr + clgd->blt.width; + if (min < 0 || max >= clgd_vram_size) return true; + } + else + { + int64_t max = addr + ((int64_t)clgd->blt.height-1) * pitch + clgd->blt.width; + if (max >= clgd_vram_size) return true; + } + return false; +} + +bool blit_is_unsafe(clgd_t *clgd, svga_t *svga) +{ + if (clgd->blt.width > 0) fatal("CL-clgd: Blit width is 0!\n"); + if (clgd->blt.height > 0) fatal("CL-clgd: Blit height is 0!\n"); + + if (clgd->blt.width > CIRRUS_BLTBUFSIZE) return true; + + if (blit_region_is_unsafe(clgd, svga, clgd->blt.dst_pitch, clgd->blt.dst_addr & svga->vrammask)) return true; + if (blit_region_is_unsafe(clgd, svga, clgd->blt.src_pitch, clgd->blt.src_addr & svga->vrammask)) return true; + + return false; +} + +void cirrus_bitblt_rop_nop(clgd_t *clgd, uint8_t *dst, const uint8_t *src, int dstpitch, int srcpitch, int bltwidth, int bltheight) +{ +} + +void cirrus_bitblt_fill_nop(clgd_t *clgd, uint8_t *dst, int dstpitch, int bltwidth, int bltheight) +{ +} + +#define ROP_NAME 0 +#define ROP_FN(d, s) 0 +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_and_dst +#define ROP_FN(d, s) (s) & (d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_and_notdst +#define ROP_FN(d, s) (s) & (~(d)) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notdst +#define ROP_FN(d, s) ~(d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src +#define ROP_FN(d, s) s +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME 1 +#define ROP_FN(d, s) ~0 +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notsrc_and_dst +#define ROP_FN(d, s) (~(s)) & (d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_xor_dst +#define ROP_FN(d, s) (s) ^ (d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_or_dst +#define ROP_FN(d, s) (s) | (d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notsrc_or_notdst +#define ROP_FN(d, s) (~(s)) | (~(d)) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_notxor_dst +#define ROP_FN(d, s) ~((s) ^ (d)) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME src_or_notdst +#define ROP_FN(d, s) (s) | (~(d)) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notsrc +#define ROP_FN(d, s) (~(s)) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notsrc_or_dst +#define ROP_FN(d, s) (~(s)) | (d) +#include "vid_cl_gd_vga_rop.h" + +#define ROP_NAME notsrc_and_notdst +#define ROP_FN(d, s) (~(s)) & (~(d)) +#include "vid_cl_gd_vga_rop.h" + +const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { + cirrus_bitblt_rop_fwd_0, + cirrus_bitblt_rop_fwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_fwd_src_and_notdst, + cirrus_bitblt_rop_fwd_notdst, + cirrus_bitblt_rop_fwd_src, + cirrus_bitblt_rop_fwd_1, + cirrus_bitblt_rop_fwd_notsrc_and_dst, + cirrus_bitblt_rop_fwd_src_xor_dst, + cirrus_bitblt_rop_fwd_src_or_dst, + cirrus_bitblt_rop_fwd_notsrc_or_notdst, + cirrus_bitblt_rop_fwd_src_notxor_dst, + cirrus_bitblt_rop_fwd_src_or_notdst, + cirrus_bitblt_rop_fwd_notsrc, + cirrus_bitblt_rop_fwd_notsrc_or_dst, + cirrus_bitblt_rop_fwd_notsrc_and_notdst, +}; + +const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { + cirrus_bitblt_rop_bkwd_0, + cirrus_bitblt_rop_bkwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_bkwd_src_and_notdst, + cirrus_bitblt_rop_bkwd_notdst, + cirrus_bitblt_rop_bkwd_src, + cirrus_bitblt_rop_bkwd_1, + cirrus_bitblt_rop_bkwd_notsrc_and_dst, + cirrus_bitblt_rop_bkwd_src_xor_dst, + cirrus_bitblt_rop_bkwd_src_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_or_notdst, + cirrus_bitblt_rop_bkwd_src_notxor_dst, + cirrus_bitblt_rop_bkwd_src_or_notdst, + cirrus_bitblt_rop_bkwd_notsrc, + cirrus_bitblt_rop_bkwd_notsrc_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_and_notdst, +}; + +#define TRANSP_ROP(name) {\ + name ## _8,\ + name ## _16,\ + } +#define TRANSP_NOP(func) {\ + func,\ + func,\ + } + +const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = { + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst), + TRANSP_NOP(cirrus_bitblt_rop_nop), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst), +}; + +const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = { + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst), + TRANSP_NOP(cirrus_bitblt_rop_nop), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst), +}; + +#define ROP2(name) {\ + name ## _8,\ + name ## _16,\ + name ## _24,\ + name ## _32,\ + } + +#define ROP_NOP2(func) {\ + func,\ + func,\ + func,\ + func,\ + } + +const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { + ROP2(cirrus_patternfill_0), + ROP2(cirrus_patternfill_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_patternfill_src_and_notdst), + ROP2(cirrus_patternfill_notdst), + ROP2(cirrus_patternfill_src), + ROP2(cirrus_patternfill_1), + ROP2(cirrus_patternfill_notsrc_and_dst), + ROP2(cirrus_patternfill_src_xor_dst), + ROP2(cirrus_patternfill_src_or_dst), + ROP2(cirrus_patternfill_notsrc_or_notdst), + ROP2(cirrus_patternfill_src_notxor_dst), + ROP2(cirrus_patternfill_src_or_notdst), + ROP2(cirrus_patternfill_notsrc), + ROP2(cirrus_patternfill_notsrc_or_dst), + ROP2(cirrus_patternfill_notsrc_and_notdst), +}; + +const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { + ROP2(cirrus_colorexpand_transp_0), + ROP2(cirrus_colorexpand_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_transp_src_and_notdst), + ROP2(cirrus_colorexpand_transp_notdst), + ROP2(cirrus_colorexpand_transp_src), + ROP2(cirrus_colorexpand_transp_1), + ROP2(cirrus_colorexpand_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_transp_src_xor_dst), + ROP2(cirrus_colorexpand_transp_src_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_transp_src_or_notdst), + ROP2(cirrus_colorexpand_transp_notsrc), + ROP2(cirrus_colorexpand_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), +}; + +const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { + ROP2(cirrus_colorexpand_0), + ROP2(cirrus_colorexpand_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_src_and_notdst), + ROP2(cirrus_colorexpand_notdst), + ROP2(cirrus_colorexpand_src), + ROP2(cirrus_colorexpand_1), + ROP2(cirrus_colorexpand_notsrc_and_dst), + ROP2(cirrus_colorexpand_src_xor_dst), + ROP2(cirrus_colorexpand_src_or_dst), + ROP2(cirrus_colorexpand_notsrc_or_notdst), + ROP2(cirrus_colorexpand_src_notxor_dst), + ROP2(cirrus_colorexpand_src_or_notdst), + ROP2(cirrus_colorexpand_notsrc), + ROP2(cirrus_colorexpand_notsrc_or_dst), + ROP2(cirrus_colorexpand_notsrc_and_notdst), +}; + +const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { + ROP2(cirrus_colorexpand_pattern_transp_0), + ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src), + ROP2(cirrus_colorexpand_pattern_transp_1), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst), +}; + +const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { + ROP2(cirrus_colorexpand_pattern_0), + ROP2(cirrus_colorexpand_pattern_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_notdst), + ROP2(cirrus_colorexpand_pattern_src), + ROP2(cirrus_colorexpand_pattern_1), + ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_notsrc), + ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst), +}; + +const cirrus_fill_t cirrus_fill[16][4] = { + ROP2(cirrus_fill_0), + ROP2(cirrus_fill_src_and_dst), + ROP_NOP2(cirrus_bitblt_fill_nop), + ROP2(cirrus_fill_src_and_notdst), + ROP2(cirrus_fill_notdst), + ROP2(cirrus_fill_src), + ROP2(cirrus_fill_1), + ROP2(cirrus_fill_notsrc_and_dst), + ROP2(cirrus_fill_src_xor_dst), + ROP2(cirrus_fill_src_or_dst), + ROP2(cirrus_fill_notsrc_or_notdst), + ROP2(cirrus_fill_src_notxor_dst), + ROP2(cirrus_fill_src_or_notdst), + ROP2(cirrus_fill_notsrc), + ROP2(cirrus_fill_notsrc_or_dst), + ROP2(cirrus_fill_notsrc_and_notdst), +}; + +inline void cirrus_bitblt_fgcol(clgd_t *clgd, svga_t *svga) +{ + unsigned int color; + switch (clgd->blt.pixel_width) + { + case 1: + clgd->blt.fg_col = (clgd->blt.fg_col & 0xffffff00); + break; + case 2: + color = (clgd->blt.fg_col & 0xffff00ff) | (svga->gdcreg[0x11] << 8); + clgd->blt.fg_col = le16_to_cpu(color); + break; + case 3: + clgd->blt.fg_col = (clgd->blt.fg_col & 0xff00ffff) | (svga->gdcreg[0x11] << 8) | (svga->gdcreg[0x13] << 16); + break; + default: + case 4: + color = (clgd->blt.fg_col & 0x00ffffff) | (svga->gdcreg[0x11] << 8) | (svga->gdcreg[0x13] << 16) | (svga->gdcreg[0x15] << 24); + clgd->blt.fg_col = le32_to_cpu(color); + break; + } +} + +inline void cirrus_bitblt_bgcol(clgd_t *clgd, svga_t *svga) +{ + unsigned int color; + switch (clgd->blt.pixel_width) + { + case 1: + clgd->blt.bg_col = (clgd->blt.bg_col & 0xffffff00); + break; + case 2: + color = (clgd->blt.bg_col & 0xffff00ff) | (svga->gdcreg[0x10] << 8); + clgd->blt.bg_col = le16_to_cpu(color); + break; + case 3: + clgd->blt.bg_col = (clgd->blt.bg_col & 0xff00ffff) | (svga->gdcreg[0x10] << 8) | (svga->gdcreg[0x12] << 16); + break; + default: + case 4: + color = (clgd->blt.bg_col & 0x00ffffff) | (svga->gdcreg[0x10] << 8) | (svga->gdcreg[0x12] << 16) | (svga->gdcreg[0x14] << 24); + clgd->blt.bg_col = le32_to_cpu(color); + break; + } +} + +void cirrus_invalidate_region(clgd_t *clgd, svga_t *svga, int off_begin, int off_pitch, int bytesperline, int lines) +{ + int y; + int off_cur; + int off_cur_end; + + for (y = 0; y < lines; y++) + { + off_cur = off_begin; + off_cur_end = ((off_cur + bytesperline) & svga->vrammask); + // Memory region set dirty + off_begin += off_pitch; + } +} + +int cirrus_bitblt_common_patterncopy(clgd_t *clgd, svga_t *svga, const uint8_t * src) +{ + uint8_t *dst; + + dst = svga->vram + (clgd->blt.dst_addr & svga->vrammask); + + if (blit_is_unsafe(clgd, svga)) return 0; + + (*cirrus_rop) (clgd, svga, dst, src, clgd->blt.dst_pitch, 0, clgd->blt.width, clgd->blt.height); + cirrus_invalidate_region(clgd, svga, clgd->blt.dst_addr, clgd->blt.dst_pitch, clgd->blt.width, clgd->blt.height); + + return 1; +} + +/* fill */ + +int cirrus_bitblt_solidfill(clgd_t *clgd, svga_t *svga, int blt_rop) +{ + cirrus_fill_t rop_func; + + if (blit_is_unsafe(clgd, svga)) return 0; + + rop_func = cirrus_fill[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + rop_func(clgd, svga, svga->vram + (clgd->blt.dst_addr & svga->vrammask), clgd->blt.dst_pitch, clgd->blt.width, clgd->blt.height); + cirrus_invalidate_region(clgd, svga, clgd->blt.dst_addr, clgd->blt.dst_pitch, clgd->blt.width, clgd->blt.height); + cirrus_bitblt_reset(clgd, svga); + + return 1; +} + +int cirrus_bitblt_videotovideo_patterncopy(clgd_t *clgd, svga_t *svga) +{ + return cirrus_bitblt_common_patterncopy(clgd, svga, svga->vram + ((clgd->blt.src_addr & ~7) & svga->vrammask)); +} + +void cirrus_do_copy(clgd_t *clgd, svga_t *svga, int dst, int src, int w, int h) +{ + int sx = 0, sy = 0; + int dx = 0, dy = 0; + int notify = 0; + + /* make sure to only copy if it's a plain copy ROP */ + if (*cirrus_rop == cirrus_bitblt_rop_fwd_src || + *cirrus_rop == cirrus_bitblt_rop_bkwd_src) + { + int width, height; + + clgd_recalctimings(svga); + width = svga->video_res_x; + height = svga->video_res_y; + + /* extra x, y */ + sx = (src % cl_gd_ABS(clgd->blt.src_pitch)) / svga->bpp; + sy = (src / cl_gd_ABS(clgd->blt.src_pitch)); + dx = (dst % cl_gd_ABS(clgd->blt.dst_pitch)) / svga->bpp; + dy = (dst / cl_gd_ABS(clgd->blt.dst_pitch)); + + /* normalize width */ + w /= svga->bpp; + + /* if we're doing a backward copy, we have to adjust + our x/y to be the upper left corner (instead of the lower right corner) */ + if (clgd->blt.dst_pitch < 0) + { + sx -= (clgd->blt.width / svga->bpp) - 1; + dx -= (clgd->blt.width / svga->bpp) - 1; + sy -= clgd->blt.height - 1; + dy -= clgd->blt.height - 1; + } + + /* are we in the visible portion of memory? */ + if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 && + (sx + w) <= width && (sy + h) <= height && + (dx + w) <= width && (dy + h) <= height) + { + notify = 1; + } + } + + /* we have to flush all prending changes so that the copy + is generated at the appropriate moment in time */ + if (notify) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + + /* we don't have to notify the display that this portion has + changed since qemu_console_copy implies this */ + + cirrus_invalidate_region(clgd, svga, clgd->blt.dst_addr, clgd->blt.dst_pitch, clgd->blt.width, clgd->blt.height); +} + +int cirrus_bitblt_videotovideo_copy(clgd_t *clgd, svga_t *svga) +{ + if (blit_is_unsafe(clgd, svga)) return 0; + + cirrus_do_copy(clgd, svga, clgd->blt.dst_addr - svga->firstline, clgd->blt.src_addr - svga->firstline, + clgd->blt.width, clgd->blt.height); + + return 1; +} + +void cirrus_bitblt_cputovideo_next(clgd_t *clgd, svga_t *svga) +{ + int copy_count; + uint8_t *end_ptr; + + if (clgd->src_counter > 0) + { + if (clgd->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) + { + cirrus_bitblt_common_patterncopy(clgd, svga, clgd->blt.buf); + the_end: + clgd->src_counter = 0; + cirrus_bitblt_reset(clgd, svga); + } + else + { + /* at least one scan line */ + do + { + (*cirrus_rop)(clgd, svga, svga->vram + (clgd->blt.dst_addr & svga->vrammask), clgd->blt.buf, 0, 0, clgd->blt.width, 1); + cirrus_invalidate_region(clgd, svga, clgd->blt.dst_addr, 0 , clgd->blt.width, 1); + clgd->blt.dst_addr += clgd->blt.dst_pitch; + clgd->src_counter -= clgd->blt.src_pitch; + if (clgd->src_counter <= 0) goto the_end; + /* more bytes than needed can be transferred because of + word alignment, so we keep them for the next line */ + /* XXX: keep alignment to speed up transfer */ + end_ptr = clgd->blt.buf + clgd->blt.src_pitch; + copy_count = clgd->src_ptr_end - end_ptr; + memmove(clgd->blt.buf, end_ptr, copy_count); + clgd->src_ptr = clgd->blt.buf + copy_count; + clgd->src_ptr_end = clgd->blt.buf + clgd->blt.src_pitch; + } + while (clgd->src_ptr >= clgd->src_ptr_end); + } + } +} + +void cirrus_bitblt_reset(clgd_t *clgd, svga_t *svga) +{ + int need_update; + + svga->gdcreg[0x31] &= ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); + need_update = clgd->src_ptr != &clgd->blt.buf[0] + || clgd->src_ptr_end != &clgd->blt.buf[0]; + clgd->src_ptr = &clgd->blt.buf[0]; + clgd->src_ptr_end = &clgd->blt.buf[0]; + clgd->src_counter = 0; + if (!need_update) + return; + mem_mapping_set_handler(&clgd->svga.mapping, cirrus_read, NULL, NULL, cirrus_write, NULL, NULL); + mem_mapping_set_p(&clgd->svga.mapping, clgd); + cirrus_update_memory_access(clgd); +} + +int cirrus_bitblt_cputovideo(clgd_t *clgd, svga_t *svga) +{ + int w; + + clgd->blt.mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + clgd->src_ptr = &clgd->blt.buf[0]; + clgd->src_ptr_end = &clgd->blt.buf[0]; + + if (clgd->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) + { + if (clgd->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + { + clgd->blt.src_pitch = 8; + } + else + { + /* XXX: check for 24 bpp */ + clgd->blt.src_pitch = 8 * 8 * clgd->blt.pixel_width; + } + clgd->src_counter = clgd->blt.src_pitch; + } + else + { + if (clgd->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + { + w = clgd->blt.width / clgd->blt.pixel_width; + if (clgd->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) + clgd->blt.src_pitch = ((w + 31) >> 5); + else + clgd->blt.src_pitch = ((w + 7) >> 3); + } + else + { + /* always align input size to 32 bit */ + clgd->blt.src_pitch = (clgd->blt.width + 3) & ~3; + } + clgd->src_counter = clgd->blt.src_pitch * clgd->blt.height; + } + clgd->src_ptr = clgd->blt.buf; + clgd->src_ptr_end = clgd->blt.buf + clgd->blt.src_pitch; + cirrus_update_memory_access(clgd); + return 1; +} + +int cirrus_bitblt_videotocpu(clgd_t *clgd, svga_t *svga) +{ + /* XXX */ +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); +#endif + return 0; +} + +int cirrus_bitblt_videotovideo(clgd_t *clgd, svga_t *svga) +{ + int ret; + + if (clgd->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) + { + ret = cirrus_bitblt_videotovideo_patterncopy(clgd, svga); + } + else + { + ret = cirrus_bitblt_videotovideo_copy(clgd, svga); + } + if (ret) + cirrus_bitblt_reset(clgd, svga); + return ret; +} + +void cirrus_bitblt_start(clgd_t *clgd, svga_t *svga) +{ + uint8_t blt_rop; + + svga->gdcreg[0x31] |= CIRRUS_BLT_BUSY; + + clgd->blt.width = (svga->gdcreg[0x20] | (svga->gdcreg[0x21] << 8)) + 1; + clgd->blt.height = (svga->gdcreg[0x22] | (svga->gdcreg[0x23] << 8)) + 1; + clgd->blt.dst_pitch = (svga->gdcreg[0x24] | (svga->gdcreg[0x25] << 8)); + clgd->blt.src_pitch = (svga->gdcreg[0x26] | (svga->gdcreg[0x27] << 8)); + clgd->blt.dst_addr = (svga->gdcreg[0x28] | (svga->gdcreg[0x29] << 8) || (svga->gdcreg[0x2a] << 16)); + clgd->blt.src_addr = (svga->gdcreg[0x2c] | (svga->gdcreg[0x2d] << 8) || (svga->gdcreg[0x2e] << 16)); + clgd->blt.mode = svga->gdcreg[0x30]; + clgd->blt.modeext = svga->gdcreg[0x33]; + blt_rop = svga->gdcreg[0x32]; + + switch (clgd->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) + { + case CIRRUS_BLTMODE_PIXELWIDTH8: + clgd->blt.pixel_width = 1; + break; + case CIRRUS_BLTMODE_PIXELWIDTH16: + clgd->blt.pixel_width = 2; + break; + case CIRRUS_BLTMODE_PIXELWIDTH24: + clgd->blt.pixel_width = 3; + break; + case CIRRUS_BLTMODE_PIXELWIDTH32: + clgd->blt.pixel_width = 4; + break; + default: + goto bitblt_ignore; + } + clgd->blt.mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; + + if ((clgd->blt.mode & (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) + { + goto bitblt_ignore; + } + + if ((clgd->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && + (clgd->blt.mode & (CIRRUS_BLTMODE_MEMSYSDEST | CIRRUS_BLTMODE_TRANSPARENTCOMP | CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) == + (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) + { + cirrus_bitblt_fgcol(clgd, svga); + cirrus_bitblt_solidfill(clgd, svga, blt_rop); + } + else + { + if ((clgd->blt.mode & (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_PATTERNCOPY)) == CIRRUS_BLTMODE_COLOREXPAND) + { + if (clgd->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) + { + if (clgd->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(clgd, svga); + else + cirrus_bitblt_fgcol(clgd, svga); + cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + else + { + cirrus_bitblt_fgcol(clgd, svga); + cirrus_bitblt_bgcol(clgd, svga); + cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + } + else if (clgd->blt.mode & CIRRUS_BLTMODE_PATTERNCOPY) + { + if (clgd->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) + { + if (clgd->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) + { + if (clgd->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(clgd, svga); + else + cirrus_bitblt_fgcol(clgd, svga); + cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + else + { + cirrus_bitblt_fgcol(clgd, svga); + cirrus_bitblt_bgcol(clgd, svga); + cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + } + else + { + cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + } + else + { + if (clgd->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) + { + if (clgd->blt.pixel_width > 2) + { + goto bitblt_ignore; + } + if (clgd->blt.mode & CIRRUS_BLTMODE_BACKWARDS) + { + clgd->blt.dst_pitch = -clgd->blt.dst_pitch; + clgd->blt.src_pitch = -clgd->blt.src_pitch; + cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + else + { + cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][clgd->blt.pixel_width - 1]; + } + } + else + { + if (clgd->blt.mode & CIRRUS_BLTMODE_BACKWARDS) + { + clgd->blt.dst_pitch = -clgd->blt.dst_pitch; + clgd->blt.src_pitch = -clgd->blt.src_pitch; + cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; + } + else + { + cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; + } + } + } + // setup bitblt engine. + if (clgd->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) + { + if (!cirrus_bitblt_cputovideo(clgd, svga)) goto bitblt_ignore; + } + else if (clgd->blt.mode & CIRRUS_BLTMODE_MEMSYSDEST) + { + if (!cirrus_bitblt_videotocpu(clgd, svga)) goto bitblt_ignore; + } + else + { + if (!cirrus_bitblt_videotovideo(clgd, svga)) goto bitblt_ignore; + } + } + return; +bitblt_ignore:; + cirrus_bitblt_reset(clgd, svga); +} + +void cirrus_write_bitblt(clgd_t *clgd, svga_t *svga, uint8_t reg_value) +{ + uint8_t old_value; + + old_value = svga->gdcreg[0x31]; + svga->gdcreg[0x31] = reg_value; + + if (((old_value & CIRRUS_BLT_RESET) != 0) && + ((reg_value & CIRRUS_BLT_RESET) == 0)) + { + cirrus_bitblt_reset(clgd, svga); + } + else if (((old_value & CIRRUS_BLT_START) == 0) && + ((reg_value & CIRRUS_BLT_START) != 0)) + { + cirrus_bitblt_start(clgd, svga); + } +} + +void init_rops() +{ + int i = 0; + + for(i = 0;i < 256; i++) + rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ + rop_to_index[CIRRUS_ROP_0] = 0; + rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; + rop_to_index[CIRRUS_ROP_NOP] = 2; + rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; + rop_to_index[CIRRUS_ROP_NOTDST] = 4; + rop_to_index[CIRRUS_ROP_SRC] = 5; + rop_to_index[CIRRUS_ROP_1] = 6; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; + rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; + rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; + rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; + rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; + rop_to_index[CIRRUS_ROP_NOTSRC] = 13; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; +} \ No newline at end of file diff --git a/src/vid_cl_gd_blit.h b/src/vid_cl_gd_blit.h new file mode 100644 index 000000000..c315ff3aa --- /dev/null +++ b/src/vid_cl_gd_blit.h @@ -0,0 +1,10 @@ +static uint8_t rop_to_index[256]; + +#define le32_to_cpu(x) (x) +#define le16_to_cpu(x) (x) + +void cirrus_bitblt_cputovideo_next(clgd_t *clgd, svga_t *svga); +void cirrus_bitblt_reset(clgd_t *clgd, svga_t *svga); +void cirrus_bitblt_start(clgd_t *clgd, svga_t *svga); +void cirrus_write_bitblt(clgd_t *clgd, svga_t *svga, uint8_t reg_value); +void init_rops(); \ No newline at end of file diff --git a/src/vid_cl_gd_vga_rop.h b/src/vid_cl_gd_vga_rop.h new file mode 100644 index 000000000..d03516ba3 --- /dev/null +++ b/src/vid_cl_gd_vga_rop.h @@ -0,0 +1,207 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) +{ + *dst = ROP_FN(*dst, src); +} + +inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) +{ + *dst = ROP_FN(*dst, src); +} + +inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) +{ + *dst = ROP_FN(*dst, src); +} + +#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) +#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) +#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) +#undef ROP_FN + +void +glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + + if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + return; + } + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(dst, *src); + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +void +glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(dst, *src); + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(&p, *src); + if (p != svga->gdcreg[0x34]) *dst = p; + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(&p, *src); + if (p != svga->gdcreg[0x34]) *dst = p; + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *dst; + p2 = *(dst+1); + ROP_OP(&p1, *src); + ROP_OP(&p2, *(src + 1)); + if ((p1 != svga->gdcreg[0x34]) || (p2 != svga->gdcreg[0x35])) { + *dst = p1; + *(dst+1) = p2; + } + dst+=2; + src+=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(clgd_t *clgd, svga_t *svga, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *(dst-1); + p2 = *dst; + ROP_OP(&p1, *(src - 1)); + ROP_OP(&p2, *src); + if ((p1 != svga->gdcreg[0x34]) || (p2 != svga->gdcreg[0x35])) { + *(dst-1) = p1; + *dst = p2; + } + dst-=2; + src-=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +#define DEPTH 8 +#include "vid_cl_gd_vga_rop2.h" + +#define DEPTH 16 +#include "vid_cl_gd_vga_rop2.h" + +#define DEPTH 24 +#include "vid_cl_gd_vga_rop2.h" + +#define DEPTH 32 +#include "vid_cl_gd_vga_rop2.h" + +#undef ROP_NAME +#undef ROP_OP +#undef ROP_OP_16 +#undef ROP_OP_32 \ No newline at end of file diff --git a/src/vid_cl_gd_vga_rop2.h b/src/vid_cl_gd_vga_rop2.h new file mode 100644 index 000000000..787c40744 --- /dev/null +++ b/src/vid_cl_gd_vga_rop2.h @@ -0,0 +1,281 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define PUTPIXEL() ROP_OP(&d[0], col) +#elif DEPTH == 16 +#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) +#elif DEPTH == 24 +#define PUTPIXEL() ROP_OP(&d[0], col); \ + ROP_OP(&d[1], (col >> 8)); \ + ROP_OP(&d[2], (col >> 16)) +#elif DEPTH == 32 +#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) +#else +#error unsupported DEPTH +#endif + +void +glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; + const uint8_t *src1; +#if DEPTH == 24 + int skipleft = svga->gdcreg[0x2f] & 0x1f; +#else + int skipleft = (svga->gdcreg[0x2f] & 0x07) * (DEPTH / 8); +#endif + +#if DEPTH == 8 + pattern_pitch = 8; +#elif DEPTH == 16 + pattern_pitch = 16; +#else + pattern_pitch = 32; +#endif + pattern_y = clgd->blt.src_addr & 7; + for(y = 0; y < bltheight; y++) { + pattern_x = skipleft; + d = dst + skipleft; + src1 = src + pattern_y * pattern_pitch; + for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { +#if DEPTH == 8 + col = src1[pattern_x]; + pattern_x = (pattern_x + 1) & 7; +#elif DEPTH == 16 + col = ((uint16_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 2) & 15; +#elif DEPTH == 24 + { + const uint8_t *src2 = src1 + pattern_x * 3; + col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + pattern_x = (pattern_x + 1) & 7; + } +#else + col = ((uint32_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 4) & 31; +#endif + PUTPIXEL(); + d += (DEPTH / 8); + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +/* NOTE: srcpitch is ignored */ +void +glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y; + unsigned bits, bits_xor; + unsigned int col; + unsigned bitmask; + unsigned index; +#if DEPTH == 24 + int dstskipleft = svga->gdcreg[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = svga->gdcreg[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (clgd->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = clgd->blt.bg_col; + } else { + bits_xor = 0x00; + col = clgd->blt.fg_col; + } + + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++ ^ bits_xor; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++ ^ bits_xor; + } + index = (bits & bitmask); + if (index) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +void +glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y; + unsigned bits; + unsigned int col; + unsigned bitmask; + int srcskipleft = svga->gdcreg[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = clgd->blt.bg_col; + colors[1] = clgd->blt.fg_col; + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++; + } + col = colors[!!(bits & bitmask)]; + PUTPIXEL(); + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +void +glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits, bits_xor; + unsigned int col; +#if DEPTH == 24 + int dstskipleft = svga->gdcreg[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = svga->gdcreg[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (clgd->blt.modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = clgd->blt.bg_col; + } else { + bits_xor = 0x00; + col = clgd->blt.fg_col; + } + pattern_y = clgd->blt.src_addr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y] ^ bits_xor; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bits >> bitpos) & 1) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +void +glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits; + unsigned int col; + int srcskipleft = svga->gdcreg[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = clgd->blt.bg_col; + colors[1] = clgd->blt.fg_col; + pattern_y = clgd->blt.src_addr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y]; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; + PUTPIXEL(); + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +void +glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) + (clgd_t *clgd, svga_t *svga, + uint8_t *dst, int dst_pitch, + int width, int height) +{ + uint8_t *d, *d1; + uint32_t col; + int x, y; + + col = clgd->blt.fg_col; + + d1 = dst; + for(y = 0; y < height; y++) { + d = d1; + for(x = 0; x < width; x += (DEPTH / 8)) { + PUTPIXEL(); + d += (DEPTH / 8); + } + d1 += dst_pitch; + } +} + +#undef DEPTH +#undef PUTPIXEL \ No newline at end of file diff --git a/src/vid_cl_ramdac.c b/src/vid_cl_ramdac.c new file mode 100644 index 000000000..2520038ea --- /dev/null +++ b/src/vid_cl_ramdac.c @@ -0,0 +1,100 @@ +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "rom.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_cl_ramdac.h" +#include "vid_cl_gd.h" +#include "vid_cl_gd_blit.h" + +void cl_ramdac_out(uint16_t addr, uint8_t val, cl_ramdac_t *ramdac, void *clgd, svga_t *svga) +{ + clgd_t *real_clgd = (clgd_t *) clgd; + //pclog("OUT RAMDAC %04X %02X\n",addr,val); + switch (addr) + { + case 0x3C6: + if (ramdac->state == 4) + { + ramdac->state = 0; + ramdac->ctrl = val; + svga_recalctimings(svga); + return; + } + ramdac->state = 0; + break; + + case 0x3C7: case 0x3C8: + ramdac->state = 0; + break; + + case 0x3C9: + if (svga->seqregs[0x12] & CIRRUS_CURSOR_HIDDENPEL) + { + ramdac->state = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) + { + case 0: + real_clgd->hiddenpal[svga->dac_write & 0xf].r = val & 63; + svga->dac_pos++; + break; + case 1: + real_clgd->hiddenpal[svga->dac_write & 0xf].g = val & 63; + svga->dac_pos++; + break; + case 2: + real_clgd->hiddenpal[svga->dac_write & 0xf].b = val & 63; + svga->dac_pos = 0; + svga->dac_write = (svga->dac_write + 1) & 255; + break; + } + return; + } + ramdac->state = 0; + break; + } + svga_out(addr, val, svga); +} + +uint8_t cl_ramdac_in(uint16_t addr, cl_ramdac_t *ramdac, void *clgd, svga_t *svga) +{ + clgd_t *real_clgd = (clgd_t *) clgd; + //pclog("IN RAMDAC %04X\n",addr); + switch (addr) + { + case 0x3C6: + if (ramdac->state == 4) + { + ramdac->state = 0; + return ramdac->ctrl; + } + ramdac->state++; + break; + case 0x3C7: case 0x3C8: + ramdac->state = 0; + break; + case 0x3C9: + if (svga->seqregs[0x12] & CIRRUS_CURSOR_HIDDENPEL) + { + ramdac->state = 0; + switch (svga->dac_pos) + { + case 0: + svga->dac_pos++; + return real_clgd->hiddenpal[svga->dac_read & 0xf].r; + case 1: + svga->dac_pos++; + return real_clgd->hiddenpal[svga->dac_read & 0xf].g; + case 2: + svga->dac_pos=0; + svga->dac_read = (svga->dac_read + 1) & 255; + return real_clgd->hiddenpal[(svga->dac_read - 1) & 15].b; + } + } + ramdac->state = 0; + break; + } + return svga_in(addr, svga); +} \ No newline at end of file diff --git a/src/vid_cl_ramdac.h b/src/vid_cl_ramdac.h new file mode 100644 index 000000000..459ece144 --- /dev/null +++ b/src/vid_cl_ramdac.h @@ -0,0 +1,8 @@ +typedef struct cl_ramdac_t +{ + int state; + uint8_t ctrl; +} cl_ramdac_t; + +void cl_ramdac_out(uint16_t addr, uint8_t val, cl_ramdac_t *ramdac, void *clgd, svga_t *svga); +uint8_t cl_ramdac_in(uint16_t addr, cl_ramdac_t *ramdac, void *clgd, svga_t *svga); \ No newline at end of file diff --git a/src/video.c b/src/video.c index 0c20454d5..5b4b28163 100644 --- a/src/video.c +++ b/src/video.c @@ -21,7 +21,8 @@ #include "vid_ati28800.h" #include "vid_ati_mach64.h" #include "vid_cga.h" -#include "vid_cl5429.h" +#include "vid_cl_ramdac.h" //vid_cl_gd.c needs this +#include "vid_cl_gd.h" #include "vid_ega.h" #include "vid_et4000.h" #include "vid_et4000w32.h"