/* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * * This file is part of the 86Box distribution. * * The below is (with some removals) a reasonable emulation * of the ET4000/W32i blitter. Unfortunately the Diamond * Stealth 32 is actually an ET4000/W32p! Which has a different * blitter. If only I'd dug out and looked at the card before * trying to emulate it. * * This might be of use for an attempt at an ET4000/W32i. * * Version: @(#)vid_et4000w32i.c 1.0.2 2017/11/04 * * Author: Sarah Walker, * * Copyright 2008-2017 Sarah Walker. */ #if 0 #include #include #include #include #include "../86box.h" int et4k_b8000; struct { struct { uint32_t pattern_addr,source_addr,dest_addr; uint16_t pattern_off,source_off,dest_off; uint8_t vbus,xy_dir; uint8_t pattern_wrap,source_wrap; uint16_t count_x,count_y; uint8_t ctrl_routing,ctrl_reload; uint8_t rop_fg,rop_bg; uint16_t pos_x,pos_y; } queued,internal; uint32_t pattern_addr,source_addr,dest_addr; uint32_t pattern_back,dest_back; int pattern_x,source_x; int pattern_x_back; int pattern_y,source_y; uint8_t status; uint32_t cpu_input; int cpu_input_num; } acl; #define ACL_WRST 1 #define ACL_RDST 2 #define ACL_XYST 4 #define ACL_SSO 8 struct { uint32_t base[3]; uint8_t ctrl; } mmu; void et4000w32_reset() { acl.status=0; acl.cpu_input_num=0; } void et4000w32_blit_start(); void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input); int et4000w32_vbus[4]={1,2,4,4}; void et4000w32_mmu_write(uint32_t addr, uint8_t val) { int bank; pclog("ET4K write %08X %02X %i %02X %02X %04X(%08X):%08X %04X %04X %02X %08X\n",addr,val,acl.cpu_input_num,acl.status,acl.internal.ctrl_routing,CS,cs,pc,CS,DI,mmu.ctrl,mmu.base[2]); switch (addr&0x6000) { case 0x0000: /*MMU 0*/ case 0x2000: /*MMU 1*/ case 0x4000: /*MMU 2*/ bank=(addr>>13)&3; if (mmu.ctrl&(1<>12]=changeframecount; } break; case 0x6000: switch (addr&0x7FFF) { case 0x7F00: mmu.base[0]=(mmu.base[0]&0xFFFFFF00)|val; break; case 0x7F01: mmu.base[0]=(mmu.base[0]&0xFFFF00FF)|(val<<8); break; case 0x7F02: mmu.base[0]=(mmu.base[0]&0xFF00FFFF)|(val<<16); break; case 0x7F03: mmu.base[0]=(mmu.base[0]&0x00FFFFFF)|(val<<24); break; case 0x7F04: mmu.base[1]=(mmu.base[1]&0xFFFFFF00)|val; break; case 0x7F05: mmu.base[1]=(mmu.base[1]&0xFFFF00FF)|(val<<8); break; case 0x7F06: mmu.base[1]=(mmu.base[1]&0xFF00FFFF)|(val<<16); break; case 0x7F07: mmu.base[1]=(mmu.base[1]&0x00FFFFFF)|(val<<24); break; case 0x7F08: mmu.base[2]=(mmu.base[2]&0xFFFFFF00)|val; break; case 0x7F09: mmu.base[2]=(mmu.base[2]&0xFFFF00FF)|(val<<8); break; case 0x7F0A: mmu.base[2]=(mmu.base[2]&0xFF00FFFF)|(val<<16); break; case 0x7F0B: mmu.base[2]=(mmu.base[2]&0x00FFFFFF)|(val<<24); break; case 0x7F13: mmu.ctrl=val; break; case 0x7F80: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFFFF00)|val; break; case 0x7F81: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFF00FF)|(val<<8); break; case 0x7F82: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFF00FFFF)|(val<<16); break; case 0x7F83: acl.queued.pattern_addr=(acl.queued.pattern_addr&0x00FFFFFF)|(val<<24); break; case 0x7F84: acl.queued.source_addr =(acl.queued.source_addr &0xFFFFFF00)|val; break; case 0x7F85: acl.queued.source_addr =(acl.queued.source_addr &0xFFFF00FF)|(val<<8); break; case 0x7F86: acl.queued.source_addr =(acl.queued.source_addr &0xFF00FFFF)|(val<<16); break; case 0x7F87: acl.queued.source_addr =(acl.queued.source_addr &0x00FFFFFF)|(val<<24); break; case 0x7F88: acl.queued.pattern_off=(acl.queued.pattern_off&0xFF00)|val; break; case 0x7F89: acl.queued.pattern_off=(acl.queued.pattern_off&0x00FF)|(val<<8); break; case 0x7F8A: acl.queued.source_off =(acl.queued.source_off &0xFF00)|val; break; case 0x7F8B: acl.queued.source_off =(acl.queued.source_off &0x00FF)|(val<<8); break; case 0x7F8C: acl.queued.dest_off =(acl.queued.dest_off &0xFF00)|val; break; case 0x7F8D: acl.queued.dest_off =(acl.queued.dest_off &0x00FF)|(val<<8); break; case 0x7F8E: acl.queued.vbus=val; break; case 0x7F8F: acl.queued.xy_dir=val; break; case 0x7F90: acl.queued.pattern_wrap=val; break; case 0x7F92: acl.queued.source_wrap=val; break; case 0x7F98: acl.queued.count_x =(acl.queued.count_x &0xFF00)|val; break; case 0x7F99: acl.queued.count_x =(acl.queued.count_x &0x00FF)|(val<<8); break; case 0x7F9A: acl.queued.count_y =(acl.queued.count_y &0xFF00)|val; break; case 0x7F9B: acl.queued.count_y =(acl.queued.count_y &0x00FF)|(val<<8); break; case 0x7F9C: acl.queued.ctrl_routing=val; break; case 0x7F9D: acl.queued.ctrl_reload =val; break; case 0x7F9E: acl.queued.rop_bg =val; break; case 0x7F9F: acl.queued.rop_fg =val; break; case 0x7FA0: acl.queued.dest_addr =(acl.queued.dest_addr &0xFFFFFF00)|val; break; case 0x7FA1: acl.queued.dest_addr =(acl.queued.dest_addr &0xFFFF00FF)|(val<<8); break; case 0x7FA2: acl.queued.dest_addr =(acl.queued.dest_addr &0xFF00FFFF)|(val<<16); break; case 0x7FA3: acl.queued.dest_addr =(acl.queued.dest_addr &0x00FFFFFF)|(val<<24); acl.internal=acl.queued; et4000w32_blit_start(); acl.cpu_input_num=0; if (!(acl.queued.ctrl_routing&0x37)) { et4000w32_blit(0xFFFFFF, ~0, 0, 0); } break; } break; } } uint8_t et4000w32_mmu_read(uint32_t addr) { int bank; pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc); switch (addr&0x6000) { case 0x0000: /*MMU 0*/ case 0x2000: /*MMU 1*/ case 0x4000: /*MMU 2*/ bank=(addr>>13)&3; if (mmu.ctrl&(1<>8; case 0x7F02: return mmu.base[0]>>16; case 0x7F03: return mmu.base[0]>>24; case 0x7F04: return mmu.base[1]; case 0x7F05: return mmu.base[1]>>8; case 0x7F06: return mmu.base[1]>>16; case 0x7F07: return mmu.base[1]>>24; case 0x7F08: return mmu.base[2]; case 0x7F09: return mmu.base[2]>>8; case 0x7F0A: return mmu.base[2]>>16; case 0x7F0B: return mmu.base[2]>>24; case 0x7F13: return mmu.ctrl; case 0x7F36: // if (acl.internal.pos_x!=acl.internal.count_x || acl.internal.pos_y!=acl.internal.count_y) return acl.status | ACL_XYST; return acl.status & ~(ACL_XYST | ACL_SSO); case 0x7F80: return acl.internal.pattern_addr; case 0x7F81: return acl.internal.pattern_addr>>8; case 0x7F82: return acl.internal.pattern_addr>>16; case 0x7F83: return acl.internal.pattern_addr>>24; case 0x7F84: return acl.internal.source_addr; case 0x7F85: return acl.internal.source_addr>>8; case 0x7F86: return acl.internal.source_addr>>16; case 0x7F87: return acl.internal.source_addr>>24; case 0x7F88: return acl.internal.pattern_off; case 0x7F89: return acl.internal.pattern_off>>8; case 0x7F8A: return acl.internal.source_off; case 0x7F8B: return acl.internal.source_off>>8; case 0x7F8C: return acl.internal.dest_off; case 0x7F8D: return acl.internal.dest_off>>8; case 0x7F8E: return acl.internal.vbus; case 0x7F8F: return acl.internal.xy_dir; case 0x7F90: return acl.internal.pattern_wrap; case 0x7F92: return acl.internal.source_wrap; case 0x7F98: return acl.internal.count_x; case 0x7F99: return acl.internal.count_x>>8; case 0x7F9A: return acl.internal.count_y; case 0x7F9B: return acl.internal.count_y>>8; case 0x7F9C: return acl.internal.ctrl_routing; case 0x7F9D: return acl.internal.ctrl_reload; case 0x7F9E: return acl.internal.rop_bg; case 0x7F9F: return acl.internal.rop_fg; case 0x7FA0: return acl.internal.dest_addr; case 0x7FA1: return acl.internal.dest_addr>>8; case 0x7FA2: return acl.internal.dest_addr>>16; case 0x7FA3: return acl.internal.dest_addr>>24; } return 0xFF; } } int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF}; int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; void et4000w32_blit_start() { pclog("Blit - %08X %08X %08X (%i,%i) %i %i %i %02X %02X %02X\n",acl.internal.pattern_addr,acl.internal.source_addr,acl.internal.dest_addr,acl.internal.dest_addr%640,acl.internal.dest_addr/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing); acl.pattern_addr=acl.internal.pattern_addr; acl.source_addr =acl.internal.source_addr; acl.dest_addr =acl.internal.dest_addr; acl.dest_back =acl.dest_addr; acl.internal.pos_x=acl.internal.pos_y=0; acl.pattern_x=acl.source_x=acl.pattern_y=acl.source_y=0; acl.status = ACL_XYST; if (!(acl.internal.ctrl_routing&7) || (acl.internal.ctrl_routing&4)) acl.status |= ACL_SSO; if (et4000w32_wrap_x[acl.internal.pattern_wrap&7]) { acl.pattern_x=acl.pattern_addr&et4000w32_wrap_x[acl.internal.pattern_wrap&7]; acl.pattern_addr&=~et4000w32_wrap_x[acl.internal.pattern_wrap&7]; } if (!(acl.internal.pattern_wrap&0x80)) { acl.pattern_y=(acl.pattern_addr/(et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1))&(et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1); acl.pattern_addr&=~(((et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1)*et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])-1); } acl.pattern_x_back=acl.pattern_x; acl.pattern_back=acl.pattern_addr; } void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input) { int c,d; uint8_t pattern,source,dest,out; uint8_t rop; // if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr); // pclog("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y); while (count--) { pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y); if (acl.internal.xy_dir&1) { pattern=vram[(acl.pattern_addr-acl.pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr -acl.source_x) &0x1FFFFF]; pclog("%06X %06X ",(acl.pattern_addr-acl.pattern_x)&0x1FFFFF,(acl.source_addr -acl.source_x) &0x1FFFFF); } else { pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF]; pclog("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF); } if (cpu_input==2) { source=sdat&0xFF; sdat>>=8; } dest=vram[acl.dest_addr &0x1FFFFF]; out=0; pclog("%06X %i %08X ",acl.dest_addr,mix&1,mix); rop = (mix & 1) ? acl.internal.rop_fg:acl.internal.rop_bg; mix>>=1; mix|=0x80000000; for (c=0;c<8;c++) { d=(dest & (1<>12]=changeframecount; acl.pattern_x++; acl.pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7]; acl.source_x++; acl.source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7]; if (acl.internal.xy_dir&1) acl.dest_addr--; else acl.dest_addr++; acl.internal.pos_x++; if (acl.internal.pos_x>acl.internal.count_x) { if (acl.internal.xy_dir&2) { acl.pattern_addr-=(acl.internal.pattern_off+1); acl.source_addr -=(acl.internal.source_off +1); acl.dest_back=acl.dest_addr=acl.dest_back-(acl.internal.dest_off+1); } else { acl.pattern_addr+=acl.internal.pattern_off+1; acl.source_addr +=acl.internal.source_off +1; acl.dest_back=acl.dest_addr=acl.dest_back+acl.internal.dest_off+1; } acl.pattern_x = acl.pattern_x_back; acl.source_x = 0; acl.pattern_y++; if (acl.pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]) { acl.pattern_y=0; acl.pattern_addr=acl.pattern_back; } acl.source_y++; if (acl.source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7]) { acl.source_y=0; acl.source_addr=acl.internal.source_addr; } acl.internal.pos_y++; if (acl.internal.pos_y>acl.internal.count_y) { acl.status = 0; return; } acl.internal.pos_x=0; if (cpu_input) return; } } } /* for (y=0;y<=acl.internal.count_y;y++) { dest_back=acl.dest_addr; for (x=0;x<=acl.internal.count_x;x++) { if (acl.internal.xy_dir&1) { pattern=vram[(acl.pattern_addr-pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr -source_x) &0x1FFFFF]; } else { pattern=vram[(acl.pattern_addr+pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr +source_x) &0x1FFFFF]; } dest=vram[acl.dest_addr &0x1FFFFF]; out=0; for (c=0;c<8;c++) { d=(dest&(1<>12]=changeframecount; pattern_x++; pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7]; source_x++; source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7]; if (acl.internal.xy_dir&1) acl.dest_addr--; else acl.dest_addr++; } acl.pattern_addr+=acl.internal.pattern_off+1; acl.source_addr +=acl.internal.source_off+1; acl.dest_addr=dest_back+acl.internal.dest_off+1; pattern_y++; if (pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]) { pattern_y=0; acl.pattern_addr=acl.internal.pattern_addr; } source_y++; if (source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7]) { source_y=0; acl.source_addr=acl.internal.source_addr; } }*/ #endif