Merge pull request #27 from MoochMcGee/cirrus
Cirrus Logic core from QEMU. Code from TC1995, Rebased by MoochMcGee
This commit is contained in:
@@ -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 \
|
||||
|
@@ -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 \
|
||||
|
@@ -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 \
|
||||
|
915
src/vid_cl5429.c
915
src/vid_cl5429.c
@@ -1,915 +0,0 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
/*Cirrus Logic CL-GD5429 emulation*/
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
};
|
1113
src/vid_cl_gd.c
Normal file
1113
src/vid_cl_gd.c
Normal file
File diff suppressed because it is too large
Load Diff
219
src/vid_cl_gd.h
Normal file
219
src/vid_cl_gd.h
Normal file
@@ -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);
|
821
src/vid_cl_gd_blit.c
Normal file
821
src/vid_cl_gd_blit.c
Normal file
@@ -0,0 +1,821 @@
|
||||
/*This is the CL-GD 5446 blitter, directly from QEMU*/
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
10
src/vid_cl_gd_blit.h
Normal file
10
src/vid_cl_gd_blit.h
Normal file
@@ -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();
|
207
src/vid_cl_gd_vga_rop.h
Normal file
207
src/vid_cl_gd_vga_rop.h
Normal file
@@ -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
|
281
src/vid_cl_gd_vga_rop2.h
Normal file
281
src/vid_cl_gd_vga_rop2.h
Normal file
@@ -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
|
100
src/vid_cl_ramdac.c
Normal file
100
src/vid_cl_ramdac.c
Normal file
@@ -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);
|
||||
}
|
8
src/vid_cl_ramdac.h
Normal file
8
src/vid_cl_ramdac.h
Normal file
@@ -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);
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user