diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 8b80ce2..61558bd 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -17,7 +17,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \ vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_s3.o \ vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \ - vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ + vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ vid_voodoo.o video.o wd76c10.o win.o win-d3d.o win-ddraw.o win-keyboard.o win-midi.o \ win-mouse.o win-timer.o win-video.o x86seg.o x87.o xtide.o pc.res FMOBJ = fmopl.o ymf262.o diff --git a/src/vid_ati18800.c b/src/vid_ati18800.c index 9feb110..37137e4 100644 --- a/src/vid_ati18800.c +++ b/src/vid_ati18800.c @@ -160,6 +160,13 @@ void ati18800_force_redraw(void *p) ati18800->svga.fullchange = changeframecount; } +int ati18800_add_status_info(char *s, int max_len, void *p) +{ + ati18800_t *ati18800 = (ati18800_t *)p; + + return svga_add_status_info(s, max_len, &ati18800->svga); +} + device_t ati18800_device = { "ATI-18800", @@ -168,6 +175,6 @@ device_t ati18800_device = NULL, ati18800_speed_changed, ati18800_force_redraw, - svga_add_status_info + ati18800_add_status_info }; diff --git a/src/vid_ati28800.c b/src/vid_ati28800.c index 7c85bc5..c3cb8c1 100644 --- a/src/vid_ati28800.c +++ b/src/vid_ati28800.c @@ -181,6 +181,13 @@ void ati28800_force_redraw(void *p) ati28800->svga.fullchange = changeframecount; } +int ati28800_add_status_info(char *s, int max_len, void *p) +{ + ati28800_t *ati28800 = (ati28800_t *)p; + + return svga_add_status_info(s, max_len, &ati28800->svga); +} + device_t ati28800_device = { "ATI-28800", @@ -189,5 +196,5 @@ device_t ati28800_device = NULL, ati28800_speed_changed, ati28800_force_redraw, - svga_add_status_info + ati28800_add_status_info }; diff --git a/src/vid_ati_mach64.c b/src/vid_ati_mach64.c index 3e211e0..e75c7d3 100644 --- a/src/vid_ati_mach64.c +++ b/src/vid_ati_mach64.c @@ -336,21 +336,25 @@ void mach64_updatemapping(mach64_t *mach64) mem_mapping_set_p(&mach64->svga.mapping, mach64); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); mem_mapping_enable(&mach64->mmio_mapping); + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, NULL, NULL, mach64_write, NULL, NULL); mem_mapping_set_p(&mach64->svga.mapping, mach64); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_mapping_set_p(&mach64->svga.mapping, svga); mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_mapping_set_p(&mach64->svga.mapping, svga); mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; break; } if (mach64->linear_base) @@ -2081,6 +2085,13 @@ void mach64_force_redraw(void *p) mach64->svga.fullchange = changeframecount; } +int mach64_add_status_info(char *s, int max_len, void *p) +{ + mach64_t *mach64 = (mach64_t *)p; + + return svga_add_status_info(s, max_len, &mach64->svga); +} + device_t mach64gx_device = { "ATI Mach64GX", @@ -2089,5 +2100,5 @@ device_t mach64gx_device = NULL, mach64_speed_changed, mach64_force_redraw, - svga_add_status_info + mach64_add_status_info }; diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index 38a816b..e9e5399 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -17,6 +17,7 @@ typedef struct gd5429_t svga_t svga; uint32_t bank[2]; + uint32_t mask; struct { @@ -228,19 +229,23 @@ void gd5429_recalc_mapping(gd5429_t *gd5429) 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; } } @@ -294,7 +299,9 @@ 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); @@ -303,8 +310,10 @@ void gd5429_write(uint32_t addr, uint8_t val, void *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); @@ -850,6 +859,13 @@ void gd5429_force_redraw(void *p) gd5429->svga.fullchange = changeframecount; } +int gd5429_add_status_info(char *s, int max_len, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + + return svga_add_status_info(s, max_len, &gd5429->svga); +} + device_t gd5429_device = { "Cirrus Logic GD5429", @@ -858,5 +874,5 @@ device_t gd5429_device = NULL, gd5429_speed_changed, gd5429_force_redraw, - svga_add_status_info + gd5429_add_status_info }; diff --git a/src/vid_et4000.c b/src/vid_et4000.c index ea43290..1902f6e 100644 --- a/src/vid_et4000.c +++ b/src/vid_et4000.c @@ -113,7 +113,16 @@ void et4000_recalctimings(svga_t *svga) case 5: svga->clock = cpuclock / 65000000.0; break; default: svga->clock = cpuclock / 36000000.0; break; } - + + switch (svga->bpp) + { + case 15: case 16: + svga->hdisp /= 2; + break; + case 24: + svga->hdisp /= 3; + break; + } } void *et4000_init() @@ -154,6 +163,13 @@ void et4000_force_redraw(void *p) et4000->svga.fullchange = changeframecount; } +int et4000_add_status_info(char *s, int max_len, void *p) +{ + et4000_t *et4000 = (et4000_t *)p; + + return svga_add_status_info(s, max_len, &et4000->svga); +} + device_t et4000_device = { "Tseng Labs ET4000AX", @@ -162,5 +178,5 @@ device_t et4000_device = NULL, et4000_speed_changed, et4000_force_redraw, - svga_add_status_info + et4000_add_status_info }; diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c index a5c083e..cce7f6b 100644 --- a/src/vid_et4000w32.c +++ b/src/vid_et4000w32.c @@ -251,7 +251,7 @@ void et4000w32p_recalctimings(svga_t *svga) svga->hdisp >>= 1; break; case 24: - svga->hdisp /= 8; + svga->hdisp /= 3; break; } } @@ -277,30 +277,37 @@ void et4000w32p_recalcmapping(et4000w32p_t *et4000) case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0xffff; break; case 0x1: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0xffff; break; case 0x2: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; break; case 0x3: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); mem_mapping_disable(&et4000->mmu_mapping); + svga->banked_mask = 0x7fff; break; case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); + svga->banked_mask = 0xffff; break; case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + svga->banked_mask = 0x7fff; break; } @@ -983,6 +990,13 @@ void et4000w32p_force_redraw(void *p) et4000w32p->svga.fullchange = changeframecount; } +int et4000w32p_add_status_info(char *s, int max_len, void *p) +{ + et4000w32p_t *et4000w32p = (et4000w32p_t *)p; + + return svga_add_status_info(s, max_len, &et4000w32p->svga); +} + device_t et4000w32p_device = { "Tseng Labs ET4000/w32p", @@ -991,5 +1005,5 @@ device_t et4000w32p_device = NULL, et4000w32p_speed_changed, et4000w32p_force_redraw, - svga_add_status_info + et4000w32p_add_status_info }; diff --git a/src/vid_oti067.c b/src/vid_oti067.c index 1fb0990..a20301e 100644 --- a/src/vid_oti067.c +++ b/src/vid_oti067.c @@ -149,6 +149,13 @@ void oti067_force_redraw(void *p) oti067->svga.fullchange = changeframecount; } +int oti067_add_status_info(char *s, int max_len, void *p) +{ + oti067_t *oti067 = (oti067_t *)p; + + return svga_add_status_info(s, max_len, &oti067->svga); +} + device_t oti067_device = { "Oak OTI-067", @@ -157,5 +164,5 @@ device_t oti067_device = NULL, oti067_speed_changed, oti067_force_redraw, - svga_add_status_info + oti067_add_status_info }; diff --git a/src/vid_paradise.c b/src/vid_paradise.c index 9af6dfe..3578052 100644 --- a/src/vid_paradise.c +++ b/src/vid_paradise.c @@ -70,15 +70,19 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; break; } } @@ -331,6 +335,13 @@ void paradise_force_redraw(void *p) paradise->svga.fullchange = changeframecount; } +int paradise_add_status_info(char *s, int max_len, void *p) +{ + paradise_t *paradise = (paradise_t *)p; + + return svga_add_status_info(s, max_len, ¶dise->svga); +} + device_t paradise_pvga1a_device = { "Paradise PVGA1A", @@ -339,7 +350,7 @@ device_t paradise_pvga1a_device = NULL, paradise_speed_changed, paradise_force_redraw, - svga_add_status_info + paradise_add_status_info }; device_t paradise_wd90c11_device = { @@ -349,5 +360,5 @@ device_t paradise_wd90c11_device = NULL, paradise_speed_changed, paradise_force_redraw, - svga_add_status_info + paradise_add_status_info }; diff --git a/src/vid_s3.c b/src/vid_s3.c index 10fb8f8..46b525b 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -28,6 +28,9 @@ typedef struct s3_t uint32_t linear_base, linear_size; + float (*getclock)(int clock, void *p); + void *getclock_p; + struct { uint8_t subsys_cntl; @@ -85,6 +88,16 @@ void s3_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) + { + case 0x12: case 0x13: + svga_recalctimings(svga); + return; + } + } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { if (val & 8) svga->write_bank = svga->read_bank = s3->bank << 16; @@ -213,6 +226,11 @@ uint8_t s3_in(uint16_t addr, void *p) // if (addr != 0x3da) pclog("S3 in %04X\n", addr); switch (addr) { + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + return svga->seqregs[svga->seqaddr]; + break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: // pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc); return sdac_ramdac_in(addr, &s3->ramdac, svga); @@ -260,9 +278,14 @@ void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = cpuclock / sdac_getclock((svga->miscout >> 2) & 3, &s3->ramdac); -// pclog("SVGA_CLOCK = %f %02X %f\n", svga_clock, svga_miscout, cpuclock); - if (svga->bpp > 8) svga->clock /= 2; + svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + + switch (svga->crtc[0x67] >> 4) + { + case 3: case 5: case 7: + svga->clock /= 2; + break; + } svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) @@ -274,23 +297,23 @@ void s3_recalctimings(svga_t *svga) break; case 15: svga->render = svga_render_15bpp_highres; + svga->hdisp /= 2; break; case 16: svga->render = svga_render_16bpp_highres; + svga->hdisp /= 2; break; case 24: svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; break; case 32: svga->render = svga_render_32bpp_highres; - if (gfxcard == GFX_N9_9FX) /*Trio64*/ - svga->hdisp *= 4; + if (gfxcard != GFX_N9_9FX) /*Trio64*/ + svga->hdisp /= 4; break; } } - - // if (svga->bpp == 32) svga->hdisp *= 3; -// pclog("svga->hdisp %i %02X %i\n", svga->hdisp, svga->crtc[0x5d], svga->hdisp_time); } void s3_updatemapping(s3_t *s3) @@ -305,15 +328,19 @@ void s3_updatemapping(s3_t *s3) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; break; } @@ -345,6 +372,7 @@ void s3_updatemapping(s3_t *s3) { mem_mapping_disable(&s3->linear_mapping); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; // mem_mapping_set_addr(&s3->linear_mapping, 0xa0000, 0x10000); } else @@ -360,6 +388,23 @@ void s3_updatemapping(s3_t *s3) mem_mapping_disable(&s3->mmio_mapping); } +static float s3_trio64_getclock(int clock, void *p) +{ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + float t; + int m, n1, n2; +// pclog("Trio64_getclock %i %02X %02X\n", clock, svga->seqregs[0x13], svga->seqregs[0x12]); + if (clock == 0) return 25175000.0; + if (clock == 1) return 28322000.0; + m = svga->seqregs[0x13] + 2; + n1 = (svga->seqregs[0x12] & 0x1f) + 2; + n2 = ((svga->seqregs[0x12] >> 5) & 0x07); + t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); +// pclog("TRIO64 clock %i %i %i %f %f %i\n", m, n1, n2, t, 14318184.0 * ((float)m / (float)n1), 1 << n2); + return t; +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); @@ -1591,7 +1636,10 @@ void *s3_bahamas64_init() s3->id = 0xc1; /*Vision864P*/ s3->id_ext = 0xc1; /*Trio64*/ - + + s3->getclock = sdac_getclock; + s3->getclock_p = &s3->ramdac; + return s3; } @@ -1601,7 +1649,10 @@ void *s3_9fx_init() s3->id = 0xe1; s3->id_ext = 0x11; /*Trio64*/ - + + s3->getclock = s3_trio64_getclock; + s3->getclock_p = s3; + return s3; } @@ -1628,6 +1679,13 @@ void s3_force_redraw(void *p) s3->svga.fullchange = changeframecount; } +int s3_add_status_info(char *s, int max_len, void *p) +{ + s3_t *s3 = (s3_t *)p; + + return svga_add_status_info(s, max_len, &s3->svga); +} + device_t s3_bahamas64_device = { "Paradise Bahamas 64 (S3 Vision864)", @@ -1636,7 +1694,7 @@ device_t s3_bahamas64_device = NULL, s3_speed_changed, s3_force_redraw, - svga_add_status_info + s3_add_status_info }; device_t s3_9fx_device = @@ -1647,5 +1705,5 @@ device_t s3_9fx_device = NULL, s3_speed_changed, s3_force_redraw, - svga_add_status_info + s3_add_status_info }; diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c index 8f43355..e02575a 100644 --- a/src/vid_s3_virge.c +++ b/src/vid_s3_virge.c @@ -271,15 +271,19 @@ void s3_virge_updatemapping(virge_t *virge) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; break; } @@ -503,6 +507,13 @@ void s3_virge_force_redraw(void *p) virge->svga.fullchange = changeframecount; } +int s3_virge_add_status_info(char *s, int max_len, void *p) +{ + virge_t *virge = (virge_t *)p; + + return svga_add_status_info(s, max_len, &virge->svga); +} + device_t s3_virge_device = { "Diamond Stealth 3D 2000 (S3 VIRGE)", @@ -511,5 +522,5 @@ device_t s3_virge_device = NULL, s3_virge_speed_changed, s3_virge_force_redraw, - svga_add_status_info + s3_virge_add_status_info }; diff --git a/src/vid_sdac_ramdac.c b/src/vid_sdac_ramdac.c index 196c70a..0098d60 100644 --- a/src/vid_sdac_ramdac.c +++ b/src/vid_sdac_ramdac.c @@ -121,8 +121,9 @@ uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga) return svga_in(addr, svga); } -float sdac_getclock(int clock, sdac_ramdac_t *ramdac) +float sdac_getclock(int clock, void *p) { + sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p; float t; int m, n1, n2; // pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]); diff --git a/src/vid_sdac_ramdac.h b/src/vid_sdac_ramdac.h index 35c95db..3029d12 100644 --- a/src/vid_sdac_ramdac.h +++ b/src/vid_sdac_ramdac.h @@ -11,4 +11,4 @@ typedef struct sdac_ramdac_t void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga); uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga); -float sdac_getclock(int clock, sdac_ramdac_t *ramdac); +float sdac_getclock(int clock, void *p); diff --git a/src/vid_svga.c b/src/vid_svga.c index 739cbfe..741cc9d 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -136,23 +136,27 @@ void svga_out(uint16_t addr, uint8_t val, void *p) case 4: svga->readplane=val&3; break; case 5: svga->writemode=val&3; svga->readmode=val&8; break; case 6: - pclog("svga_out recalcmapping %p\n", svga); +// pclog("svga_out recalcmapping %p\n", svga); if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { - pclog("Write mapping %02X\n", val); +// pclog("Write mapping %02X\n", val); switch (val&0xC) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; break; } } @@ -309,49 +313,31 @@ void svga_recalctimings(svga_t *svga) if (svga->lowres) svga->render = svga_render_8bpp_lowres; else - { svga->render = svga_render_8bpp_highres; -// svga_hdisp <<= 1; - } break; case 15: if (svga->lowres) svga->render = svga_render_15bpp_lowres; else - { svga->render = svga_render_15bpp_highres; - svga->hdisp <<= 1; - } break; case 16: if (svga->lowres) svga->render = svga_render_16bpp_lowres; else - { svga->render = svga_render_16bpp_highres; - svga->hdisp <<= 1; - } break; case 24: if (svga->lowres) - { svga->render = svga_render_24bpp_lowres; - svga->hdisp = ((svga->hdisp << 3) / 3); - } else - { svga->render = svga_render_24bpp_highres; - svga->hdisp = ((svga->hdisp << 3) / 3); - } break; case 32: if (svga->lowres) svga->render = svga_render_32bpp_lowres; else - { svga->render = svga_render_32bpp_highres; - svga->hdisp <<= 1; - } break; } break; @@ -516,15 +502,12 @@ void svga_poll(void *p) svga->cgastat |= 8; x = svga->hdisp; - if (svga->bpp == 16 || svga->bpp == 15) x /= 2; - if (svga->bpp == 32) x /= 4; if (svga->interlace && !svga->oddeven) svga->lastline++; if (svga->interlace && svga->oddeven) svga->firstline--; wx = x; wy = svga->lastline - svga->firstline; - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); readflash = 0; @@ -548,7 +531,6 @@ void svga_poll(void *p) svga->maback <<= 2; svga->ca <<= 2; - svga->video_res_x = wx; svga->video_res_y = wy + 1; // pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres); @@ -668,13 +650,8 @@ void svga_write(uint32_t addr, uint8_t val, void *p) cycles_lost += video_timing_b; if (svga_output) pclog("Writeega %06X ",addr); - if (addr>=0xB0000) addr&=0x7FFF; - else - { - //if (gdcreg[6]&8) return; - addr &= 0xFFFF; - addr += svga->write_bank; - } + addr &= svga->banked_mask; + addr += svga->write_bank; if (!(svga->gdcreg[6] & 1)) svga->fullchange=2; if (svga->chain4) @@ -848,12 +825,9 @@ uint8_t svga_read(uint32_t addr, void *p) egareads++; // pclog("Readega %06X ",addr); - if (addr>=0xB0000) addr&=0x7FFF; - else - { - addr &= 0xFFFF; - addr += svga->read_bank; - } + addr &= svga->banked_mask; + addr += svga->read_bank; + // pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode); // pclog("%i\n", svga->readmode); if (svga->chain4) @@ -1120,6 +1094,7 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) // pclog("svga_doblit start\n"); svga->frames++; // pclog("doblit %i %i\n", y1, y2); +// pclog("svga_doblit %i %i\n", wx, svga->hdisp); if (y1 > y2) { video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize); @@ -1163,7 +1138,7 @@ void svga_writew(uint32_t addr, uint16_t val, void *p) cycles_lost += video_timing_w; if (svga_output) pclog("svga_writew: %05X ", addr); - addr = (addr & 0xffff) + svga->write_bank; + addr = (addr & svga->banked_mask) + svga->write_bank; addr &= 0x7FFFFF; if (addr >= svga->vram_limit) return; @@ -1191,7 +1166,7 @@ void svga_writel(uint32_t addr, uint32_t val, void *p) cycles_lost += video_timing_l; if (svga_output) pclog("svga_writel: %05X ", addr); - addr = (addr & 0xffff) + svga->write_bank; + addr = (addr & svga->banked_mask) + svga->write_bank; addr &= 0x7FFFFF; if (addr >= svga->vram_limit) return; @@ -1214,7 +1189,7 @@ uint16_t svga_readw(uint32_t addr, void *p) cycles_lost += video_timing_w; // pclog("Readw %05X ", addr); - addr = (addr & 0xffff) + svga->read_bank; + addr = (addr & svga->banked_mask) + svga->read_bank; addr &= 0x7FFFFF; // pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]); if (addr >= svga->vram_limit) return 0xffff; @@ -1235,7 +1210,7 @@ uint32_t svga_readl(uint32_t addr, void *p) cycles_lost += video_timing_l; // pclog("Readl %05X ", addr); - addr = (addr & 0xffff) + svga->read_bank; + addr = (addr & svga->banked_mask) + svga->read_bank; addr &= 0x7FFFFF; // pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]); if (addr >= svga->vram_limit) return 0xffffffff; diff --git a/src/vid_svga.h b/src/vid_svga.h index 30a79e9..630dfa9 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -64,6 +64,7 @@ typedef struct svga_t uint8_t *vram; uint8_t *changedvram; int vrammask; + uint32_t banked_mask; uint32_t write_bank, read_bank; diff --git a/src/vid_tgui9440.c b/src/vid_tgui9440.c new file mode 100644 index 0000000..63cfe06 --- /dev/null +++ b/src/vid_tgui9440.c @@ -0,0 +1,1133 @@ +/*Trident TGUI9440 emulation*/ +#include +#include "ibm.h" +#include "device.h" +#include "io.h" +#include "mem.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_svga_render.h" +#include "vid_tkd8001_ramdac.h" +#include "vid_tgui9440.h" + +typedef struct tgui_t +{ + mem_mapping_t linear_mapping; + mem_mapping_t accel_mapping; + + svga_t svga; + + struct + { + uint16_t src_x, src_y; + uint16_t dst_x, dst_y; + uint16_t size_x, size_y; + uint16_t fg_col, bg_col; + uint8_t rop; + uint16_t flags; + uint8_t pattern[0x80]; + int command; + int offset; + uint8_t ger22; + + int x, y; + uint32_t src, dst, src_old, dst_old; + int pat_x, pat_y; + int use_src; + + int pitch, bpp; + + uint16_t tgui_pattern[8][8]; + } accel; + + uint8_t tgui_3d8, tgui_3d9; + int oldmode; + uint8_t oldctrl2,newctrl2; + + uint32_t linear_base, linear_size; + + int ramdac_state; + uint8_t ramdac_ctrl; + + int clock_m, clock_n, clock_k; +} tgui_t; + +void tgui_recalcmapping(tgui_t *tgui); + + +uint8_t tgui_accel_read(uint32_t addr, void *priv); +uint16_t tgui_accel_read_w(uint32_t addr, void *priv); +uint32_t tgui_accel_read_l(uint32_t addr, void *priv); + +void tgui_accel_write(uint32_t addr, uint8_t val, void *priv); +void tgui_accel_write_w(uint32_t addr, uint16_t val, void *priv); +void tgui_accel_write_l(uint32_t addr, uint32_t val, void *priv); + + +void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); + +void tgui_out(uint16_t addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + + uint8_t old; + +// pclog("tgui_out : %04X %02X %04X:%04X %i\n", addr, val, CS,pc, svga->bpp); + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) + { + case 0x3C5: + switch (svga->seqaddr & 0xf) + { + case 0xB: + tgui->oldmode=1; + break; + case 0xC: + if (svga->seqregs[0xe] & 0x80) + svga->seqregs[0xc] = val; + break; + case 0xd: + if (tgui->oldmode) + tgui->oldctrl2 = val; + else + tgui->newctrl2=val; + break; + case 0xE: + svga->seqregs[0xe] = val ^ 2; + svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + if (!(svga->gdcreg[0xf] & 1)) + svga->read_bank = svga->write_bank; + return; + } + break; + + case 0x3C6: + if (tgui->ramdac_state == 4) + { + tgui->ramdac_state = 0; + tgui->ramdac_ctrl = val; + switch (tgui->ramdac_ctrl & 0xf0) + { + case 0x10: + svga->bpp = 15; + break; + case 0x30: + svga->bpp = 16; + break; + case 0xd0: + svga->bpp = 24; + break; + default: + svga->bpp = 8; + break; + } + return; + } + case 0x3C7: case 0x3C8: case 0x3C9: + tgui->ramdac_state = 0; + break; + + case 0x3CF: + switch (svga->gdcaddr & 15) + { + case 0x6: + if (svga->gdcreg[6] != val) + { + svga->gdcreg[6] = val; + tgui_recalcmapping(tgui); + } + return; + + case 0xE: + svga->gdcreg[0xe] = val ^ 2; + if ((svga->gdcreg[0xf] & 1) == 1) + svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536; + break; + case 0xF: + if (val & 1) svga->read_bank = (svga->gdcreg[0xe] & 0xf) *65536; + else svga->read_bank = (svga->seqregs[0xe] & 0xf) *65536; + svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + break; + } + break; + case 0x3D4: + svga->crtcreg = val & 0x7f; + return; + case 0x3D5: + if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return; + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; +// if (svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X\n", svga->crtcreg, val); + if (old != val) + { + if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + switch (svga->crtcreg) + { + case 0x21: + if (old != val) + { + if (!PCI) + { + tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; + tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; + } + tgui_recalcmapping(tgui); + } + break; + + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; + svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; + svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x7) << 18) | (svga->hwcursor.yoff * 8); + break; + + case 0x50: + svga->hwcursor.ena = val & 0x80; + break; + } + return; + case 0x3D8: + tgui->tgui_3d8 = val; + if (svga->gdcreg[0xf] & 4) + { + svga->write_bank = (val & 0x1f) * 65536; +// pclog("SVGAWBANK 3D8 %08X %04X:%04X\n",svgawbank,CS,pc); + if (!(svga->gdcreg[0xf] & 1)) + { + svga->read_bank = (val & 0x1f) * 65536; +// pclog("SVGARBANK 3D8 %08X %04X:%04X\n",svgarbank,CS,pc); + } + } + return; + case 0x3D9: + tgui->tgui_3d9 = val; + if ((svga->gdcreg[0xf] & 5) == 5) + { + svga->read_bank = (val & 0x1F) * 65536; +// pclog("SVGARBANK 3D9 %08X %04X:%04X\n",svgarbank,CS,pc); + } + return; + + case 0x43c8: + tgui->clock_n = val & 0x7f; + tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); + break; + case 0x43c9: + tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e); + tgui->clock_k = (val & 0x10) >> 4; + break; + } + svga_out(addr, val, svga); +} + +uint8_t tgui_in(uint16_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + +// if (addr != 0x3da) pclog("tgui_in : %04X %04X:%04X\n", addr, CS,pc); + + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) + { + case 0x3C5: + if ((svga->seqaddr & 0xf) == 0xb) + { +// printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); + tgui->oldmode = 0; + return 0xe3; /*TGUI9440AGi*/ + } + if ((svga->seqaddr & 0xf) == 0xc) + { +// printf("Read Trident Power Up 1 %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); +// return 0x20; /*2 DRAM banks*/ + } + if ((svga->seqaddr & 0xf) == 0xd) + { + if (tgui->oldmode) return tgui->oldctrl2; + return tgui->newctrl2; + } + break; + case 0x3C6: + if (tgui->ramdac_state == 4) + return tgui->ramdac_ctrl; + tgui->ramdac_state++; + break; + case 0x3C7: case 0x3C8: case 0x3C9: + tgui->ramdac_state = 0; + break; + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + return svga->crtc[svga->crtcreg]; + case 0x3d8: + return tgui->tgui_3d8; + case 0x3d9: + return tgui->tgui_3d9; + } + return svga_in(addr, svga); +} + +void tgui_recalctimings(svga_t *svga) +{ + tgui_t *tgui = (tgui_t *)svga->p; + + if (svga->crtc[0x29] & 0x10) + svga->rowoffset += 0x100; + + if (svga->bpp == 24) + svga->hdisp = (svga->crtc[1] + 1) * 8; + + if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; + if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000; + if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000; + + if (tgui->oldctrl2 & 0x10) + { + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + if (tgui->oldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ + svga->lowres=0; + + svga->lowres = !(svga->crtc[0x2a] & 0x40); + + svga->interlace = svga->crtc[0x1e] & 4; + + if (svga->miscout & 8) + svga->clock = cpuclock / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); + + if (svga->gdcreg[0xf] & 0x08) + svga->clock *= 2; + else if (svga->gdcreg[0xf] & 0x40) + svga->clock *= 3; + + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) + { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + break; + case 16: + svga->render = svga_render_16bpp_highres; + break; + case 24: + svga->render = svga_render_24bpp_highres; + break; + } + } +} + +void tgui_recalcmapping(tgui_t *tgui) +{ + svga_t *svga = &tgui->svga; + +// pclog("tgui_recalcmapping : %02X %02X\n", svga->crtc[0x21], svga->gdcreg[6]); + + if (svga->crtc[0x21] & 0x20) + { + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); +// pclog("Trident linear framebuffer at %08X - size %06X\n", tgui->linear_base, tgui->linear_size); + mem_mapping_enable(&tgui->accel_mapping); + } + else + { +// pclog("Write mapping %02X\n", val); + mem_mapping_disable(&tgui->linear_mapping); + mem_mapping_disable(&tgui->accel_mapping); + switch (svga->gdcreg[6] & 0xC) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_enable(&tgui->accel_mapping); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } +} + +void tgui_hwcursor_draw(svga_t *svga, int displine) +{ + uint32_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; + for (xx = 0; xx < 32; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (!(dat[0] & 0x80000000)) + ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; + else if (dat[1] & 0x80000000) + ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; +// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]); + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr += 8; +} + +uint8_t tgui_pci_read(int func, int addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + +// pclog("Trident PCI read %08X\n", addr); + + switch (addr) + { + case 0x00: return 0x23; /*Trident*/ + case 0x01: return 0x10; + + case 0x02: return 0x40; /*TGUI9440 (9682)*/ + case 0x03: return 0x94; + + case 0x04: return 0x03; /*Respond to IO and memory accesses*/ + + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return tgui->linear_base >> 16; + case 0x13: return tgui->linear_base >> 24; + + case 0x30: return 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return 0x0C; + case 0x33: return 0x00; + } + return 0; +} + +void tgui_pci_write(int func, int addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + +// pclog("Trident PCI write %08X %02X\n", addr, val); + + switch (addr) + { + case 0x12: + tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); + tgui->linear_size = 2 << 20; + svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4); + tgui_recalcmapping(tgui); + break; + case 0x13: + tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); + tgui->linear_size = 2 << 20; + svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6); + tgui_recalcmapping(tgui); + break; + } +} + +void *tgui8900d_init() +{ + tgui_t *tgui = malloc(sizeof(tgui_t)); + memset(tgui, 0, sizeof(tgui_t)); + + svga_init(&tgui->svga, tgui, 1 << 20, /*1mb - chip supports 2mb, but drivers are buggy*/ + tgui_recalctimings, + tgui_in, tgui_out, + NULL); + + mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tgui->svga); + mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, tgui); + mem_mapping_disable(&tgui->linear_mapping); + mem_mapping_disable(&tgui->accel_mapping); + + io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + + return tgui; +} +void *tgui9440_init() +{ + tgui_t *tgui = malloc(sizeof(tgui_t)); + memset(tgui, 0, sizeof(tgui_t)); + + svga_init(&tgui->svga, tgui, 1 << 21, /*2mb*/ + tgui_recalctimings, + tgui_in, tgui_out, + tgui_hwcursor_draw); + + mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tgui->svga); + mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, tgui); + mem_mapping_disable(&tgui->accel_mapping); + + io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + + pci_add(tgui_pci_read, tgui_pci_write, tgui); + + return tgui; +} + +void tgui_close(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + svga_close(&tgui->svga); + + free(tgui); +} + +void tgui_speed_changed(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + svga_recalctimings(&tgui->svga); +} + +void tgui_force_redraw(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + tgui->svga.fullchange = changeframecount; +} + +enum +{ + TGUI_BITBLT = 1 +}; + +enum +{ + TGUI_SRCCPU = 0, + + TGUI_SRCDISP = 0x04, /*Source is from display*/ + TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ + TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ + TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ + TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ + TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/ +}; + +#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \ + else dat = vram_w[addr & 0xfffff]; + +#define MIX() do \ + { \ + out = 0; \ + for (c=0;c<16;c++) \ + { \ + d=(dst_dat & (1<accel.rop & (1<accel.bpp == 0) \ + { \ + svga->vram[addr & 0x1fffff] = dat; \ + svga->changedvram[((addr) & 0x1fffff) >> 10] = changeframecount; \ + } \ + else \ + { \ + vram_w[addr & 0xfffff] = dat; \ + svga->changedvram[((addr) & 0xfffff) >> 9] = changeframecount; \ + } + +void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); +void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); + +void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) +{ + svga_t *svga = &tgui->svga; + int x, y; + int c, d; + uint16_t src_dat, dst_dat, pat_dat; + uint16_t out; + int xdir = (tgui->accel.flags & 0x200) ? -1 : 1; + int ydir = (tgui->accel.flags & 0x100) ? -1 : 1; + uint16_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; + uint16_t *vram_w = (uint16_t *)svga->vram; + + if (tgui->accel.bpp == 0) + trans_col &= 0xff; + + if (count != -1 && !tgui->accel.x) + { + count -= tgui->accel.offset; + cpu_dat <<= tgui->accel.offset; + } + if (count == -1) + { + tgui->accel.x = tgui->accel.y = 0; + } + if (tgui->accel.flags & TGUI_SOLIDFILL) + { +// pclog("SOLIDFILL\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.fg_col; + } + } + } + else if (tgui->accel.flags & TGUI_PATMONO) + { +// pclog("PATMONO\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col; + } + } + } + else + { + if (tgui->accel.bpp == 0) + { +// pclog("OTHER 8-bit\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x + y*8]; + } + } + } + else + { +// pclog("OTHER 16-bit\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x*2 + y*16] | (tgui->accel.pattern[x*2 + y*16 + 1] << 8); + } + } + } + } +/* for (y = 0; y < 8; y++) + { + if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tgui->accel.tgui_pattern[y][0], tgui->accel.tgui_pattern[y][1], tgui->accel.tgui_pattern[y][2], tgui->accel.tgui_pattern[y][3], tgui->accel.tgui_pattern[y][4], tgui->accel.tgui_pattern[y][5], tgui->accel.tgui_pattern[y][6], tgui->accel.tgui_pattern[y][7]); + }*/ +// if (count == -1) pclog("Command %i %i %p\n", tgui->accel.command, TGUI_BITBLT, tgui); + switch (tgui->accel.command) + { + case TGUI_BITBLT: +// if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tgui->accel.src_x, tgui->accel.src_y, tgui->accel.dst_x, tgui->accel.dst_y, tgui->accel.size_x, tgui->accel.size_y, tgui->accel.flags); + if (count == -1) + { + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y = tgui->accel.dst_y; + } + + switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) + { + case TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start TGUI_SRCCPU\n"); + if (svga->crtc[0x21] & 0x20) + mem_mapping_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l); + + if (tgui->accel.use_src) + return; + } + else + count >>= 3; +// pclog("TGUI_SRCCPU\n"); + while (count) + { + if (tgui->accel.bpp == 0) + { + src_dat = cpu_dat >> 24; + cpu_dat <<= 8; + } + else + { + src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); + cpu_dat <<= 16; + count--; + } + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } + +// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + { + if (svga->crtc[0x21] & 0x20) + { +// pclog("Blit end\n"); + mem_mapping_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); + } + return; + } + if (tgui->accel.use_src) + return; + } + count--; + } + break; + + case TGUI_SRCMONO | TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start TGUI_SRCMONO | TGUI_SRCCPU\n"); + if (svga->crtc[0x21] & 0x20) + mem_mapping_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l); + +// pclog(" %i\n", tgui->accel.command); + if (tgui->accel.use_src) + return; + } +// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n"); + while (count) + { + src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); + if (tgui->accel.bpp == 0) + src_dat &= 0xff; + + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X %i\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out, (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)); + cpu_dat <<= 1; + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + { + if (svga->crtc[0x21] & 0x20) + { +// pclog("Blit end\n"); + mem_mapping_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); + } + return; + } + if (tgui->accel.use_src) + return; + } + count--; + } + break; + + default: + while (count) + { + READ(tgui->accel.src, src_dat); + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + return; + } + count--; + } + break; + } + break; + } +} + +void tgui_accel_write(uint32_t addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode); + if ((addr & ~0xff) != 0xbff00) + return; + switch (addr & 0xff) + { + case 0x22: + tgui->accel.ger22 = val; + tgui->accel.pitch = 512 << ((val >> 2) & 3); + tgui->accel.bpp = (val & 3) ? 1 : 0; + tgui->accel.pitch >>= tgui->accel.bpp; + break; + + case 0x24: /*Command*/ + tgui->accel.command = val; + tgui_accel_command(-1, 0, tgui); + break; + + case 0x27: /*ROP*/ + tgui->accel.rop = val; + tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); +// pclog("Write ROP %02X %i\n", val, tgui->accel.use_src); + break; + + case 0x28: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xff00) | val; + break; + case 0x29: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xff) | (val << 8); + break; + + case 0x2b: + tgui->accel.offset = val & 7; + break; + + case 0x2c: /*Foreground colour*/ + tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00) | val; + break; + case 0x2d: /*Foreground colour*/ + tgui->accel.fg_col = (tgui->accel.fg_col & 0xff) | (val << 8); + break; + + case 0x30: /*Background colour*/ + tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00) | val; + break; + case 0x31: /*Background colour*/ + tgui->accel.bg_col = (tgui->accel.bg_col & 0xff) | (val << 8); + break; + + case 0x38: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; + break; + case 0x39: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); + break; + case 0x3a: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; + break; + case 0x3b: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); + break; + + case 0x3c: /*Src X*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; + break; + case 0x3d: /*Src X*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); + break; + case 0x3e: /*Src Y*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; + break; + case 0x3f: /*Src Y*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); + break; + + case 0x40: /*Size X*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; + break; + case 0x41: /*Size X*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); + break; + case 0x42: /*Size Y*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; + break; + case 0x43: /*Size Y*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); + break; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + tgui->accel.pattern[addr & 0x7f] = val; + break; + } +} + +void tgui_accel_write_w(uint32_t addr, uint16_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write_w %08X %04X\n", addr, val); + tgui_accel_write(addr, val, tgui); + tgui_accel_write(addr + 1, val >> 8, tgui); +} + +void tgui_accel_write_l(uint32_t addr, uint32_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write_l %08X %08X\n", addr, val); + tgui_accel_write(addr, val, tgui); + tgui_accel_write(addr + 1, val >> 8, tgui); + tgui_accel_write(addr + 2, val >> 16, tgui); + tgui_accel_write(addr + 3, val >> 24, tgui); +} + +uint8_t tgui_accel_read(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read : %08X\n", addr); + if ((addr & ~0xff) != 0xbff00) + return 0xff; + switch (addr & 0xff) + { + case 0x20: /*Status*/ + return 0; + + case 0x27: /*ROP*/ + return tgui->accel.rop; + + case 0x28: /*Flags*/ + return tgui->accel.flags & 0xff; + case 0x29: /*Flags*/ + return tgui->accel.flags >> 8; + + case 0x2b: + return tgui->accel.offset; + + case 0x2c: /*Background colour*/ + return tgui->accel.bg_col & 0xff; + case 0x2d: /*Background colour*/ + return tgui->accel.bg_col >> 8; + + case 0x30: /*Foreground colour*/ + return tgui->accel.fg_col & 0xff; + case 0x31: /*Foreground colour*/ + return tgui->accel.fg_col >> 8; + + case 0x38: /*Dest X*/ + return tgui->accel.dst_x & 0xff; + case 0x39: /*Dest X*/ + return tgui->accel.dst_x >> 8; + case 0x3a: /*Dest Y*/ + return tgui->accel.dst_y & 0xff; + case 0x3b: /*Dest Y*/ + return tgui->accel.dst_y >> 8; + + case 0x3c: /*Src X*/ + return tgui->accel.src_x & 0xff; + case 0x3d: /*Src X*/ + return tgui->accel.src_x >> 8; + case 0x3e: /*Src Y*/ + return tgui->accel.src_y & 0xff; + case 0x3f: /*Src Y*/ + return tgui->accel.src_y >> 8; + + case 0x40: /*Size X*/ + return tgui->accel.size_x & 0xff; + case 0x41: /*Size X*/ + return tgui->accel.size_x >> 8; + case 0x42: /*Size Y*/ + return tgui->accel.size_y & 0xff; + case 0x43: /*Size Y*/ + return tgui->accel.size_y >> 8; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return tgui->accel.pattern[addr & 0x7f]; + } + return 0xff; +} + +uint16_t tgui_accel_read_w(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read_w %08X\n", addr); + return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8); +} + +uint32_t tgui_accel_read_l(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read_l %08X\n", addr); + return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16); +} + +void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; +// pclog("tgui_accel_write_fb_b %08X %02X\n", addr, val); + tgui_accel_command(8, val << 24, tgui); +} + +void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; +// pclog("tgui_accel_write_fb_w %08X %04X\n", addr, val); + tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui); +} + +void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; +// pclog("tgui_accel_write_fb_l %08X %08X\n", addr, val); + tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui); +} + +int tgui_add_status_info(char *s, int max_len, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + return svga_add_status_info(s, max_len, &tgui->svga); +} + +device_t tgui9440_device = +{ + "Trident TGUI 9440", + tgui9440_init, + tgui_close, + NULL, + tgui_speed_changed, + tgui_force_redraw, + tgui_add_status_info +}; diff --git a/src/vid_tgui9440.h b/src/vid_tgui9440.h new file mode 100644 index 0000000..828562d --- /dev/null +++ b/src/vid_tgui9440.h @@ -0,0 +1 @@ +extern device_t tgui9440_device; diff --git a/src/vid_tvga.c b/src/vid_tvga.c index d0a35ad..2934999 100644 --- a/src/vid_tvga.c +++ b/src/vid_tvga.c @@ -18,50 +18,12 @@ typedef struct tvga_t svga_t svga; tkd8001_ramdac_t ramdac; - struct - { - uint16_t src_x, src_y; - uint16_t dst_x, dst_y; - uint16_t size_x, size_y; - uint16_t fg_col, bg_col; - uint8_t rop; - uint16_t flags; - uint8_t pattern[0x80]; - int command; - int offset; - uint8_t ger22; - - int x, y; - uint32_t src, dst, src_old, dst_old; - int pat_x, pat_y; - int use_src; - - int pitch, bpp; - - uint16_t tvga_pattern[8][8]; - } accel; - uint8_t tvga_3d8, tvga_3d9; int oldmode; - uint8_t oldctrl2,newctrl2; - - uint32_t linear_base, linear_size; + uint8_t oldctrl1; + uint8_t oldctrl2, newctrl2; } tvga_t; -void tvga_recalcmapping(tvga_t *tvga); - - -uint8_t tvga_accel_read(uint32_t addr, void *priv); -uint16_t tvga_accel_read_w(uint32_t addr, void *priv); -uint32_t tvga_accel_read_l(uint32_t addr, void *priv); - -void tvga_accel_write(uint32_t addr, uint8_t val, void *priv); -void tvga_accel_write_w(uint32_t addr, uint16_t val, void *priv); -void tvga_accel_write_l(uint32_t addr, uint32_t val, void *priv); - - -void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); - void tvga_out(uint16_t addr, uint8_t val, void *p) { tvga_t *tvga = (tvga_t *)p; @@ -88,36 +50,29 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) if (tvga->oldmode) tvga->oldctrl2 = val; else - tvga->newctrl2=val; + tvga->newctrl2 = val; break; case 0xE: - svga->seqregs[0xe] = val ^ 2; - svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; - if (!(svga->gdcreg[0xf] & 1)) - svga->read_bank = svga->write_bank; + if (tvga->oldmode) + tvga->oldctrl1 = val; + else + { + svga->seqregs[0xe] = val ^ 2; + svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + if (!(svga->gdcreg[0xf] & 1)) + svga->read_bank = svga->write_bank; + } return; } break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (gfxcard != GFX_TGUI9440) - { - tkd8001_ramdac_out(addr, val, &tvga->ramdac, svga); - return; - } - break; + tkd8001_ramdac_out(addr, val, &tvga->ramdac, svga); + return; case 0x3CF: switch (svga->gdcaddr & 15) { - case 0x6: - if (svga->gdcreg[6] != val) - { - svga->gdcreg[6] = val; - tvga_recalcmapping(tvga); - } - return; - case 0xE: svga->gdcreg[0xe] = val ^ 2; if ((svga->gdcreg[0xf] & 1) == 1) @@ -131,8 +86,7 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) } break; case 0x3D4: - if (gfxcard == GFX_TGUI9440) svga->crtcreg = val & 0x7f; - else svga->crtcreg = val & 0x3f; + svga->crtcreg = val & 0x3f; return; case 0x3D5: if (svga->crtcreg <= 7 && svga->crtc[0x11] & 0x80) return; @@ -147,44 +101,6 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) svga_recalctimings(svga); } } - switch (svga->crtcreg) - { - case 0x21: - if (old != val) - { - if (!PCI) - { - tvga->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; - tvga->linear_size = (val & 0x10) ? 0x200000 : 0x100000; - } - tvga_recalcmapping(tvga); - } - break; - - - case 0x38: /*Pixel bus register*/ -// pclog("Pixel bus register %02X\n", val); - if (gfxcard != GFX_TGUI9440) - break; - - if ((val & 0xc) == 4) svga->bpp = 16; - else if (!(val & 0xc)) svga->bpp = 8; - else svga->bpp = 24; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; - svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; - svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; - svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x7) << 18) | (svga->hwcursor.yoff * 8); - break; - - case 0x50: - svga->hwcursor.ena = val & 0x80; - break; - } return; case 0x3D8: tvga->tvga_3d8 = val; @@ -227,8 +143,7 @@ uint8_t tvga_in(uint16_t addr, void *p) { // printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); tvga->oldmode = 0; - if (gfxcard == GFX_TVGA) return 0x33; /*TVGA8900D*/ - else return 0xe3; /*TGUI9440AGi*/ + return 0x33; /*TVGA8900D*/ } if ((svga->seqaddr & 0xf) == 0xc) { @@ -242,9 +157,7 @@ uint8_t tvga_in(uint16_t addr, void *p) } break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (gfxcard != GFX_TGUI9440) - return tkd8001_ramdac_in(addr, &tvga->ramdac, svga); - break; + return tkd8001_ramdac_in(addr, &tvga->ramdac, svga); case 0x3D4: return svga->crtcreg; case 0x3D5: @@ -266,7 +179,7 @@ void tvga_recalctimings(svga_t *svga) if (svga->crtc[0x29] & 0x10) svga->rowoffset += 0x100; - if (gfxcard == GFX_TGUI9440 && svga->bpp == 24) + if (svga->bpp == 24) svga->hdisp = (svga->crtc[1] + 1) * 8; if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; @@ -278,19 +191,16 @@ void tvga_recalctimings(svga_t *svga) svga->rowoffset <<= 1; svga->ma_latch <<= 1; } - if (tvga->oldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ - svga->lowres=0; - if (gfxcard == GFX_TGUI9440) - svga->lowres = !(svga->crtc[0x2a] & 0x40); - - if (svga->gdcreg[0xf] & 8) + if (svga->gdcreg[0xf] & 0x08) { - svga->htotal <<= 1; - svga->hdisp <<= 1; + svga->htotal *= 2; + svga->hdisp *= 2; + svga->hdisp_time *= 2; } + svga->interlace = svga->crtc[0x1e] & 4; if (svga->interlace) - svga->rowoffset >>= 1; + svga->rowoffset >>= 1; switch (((svga->miscout >> 2) & 3) | ((tvga->newctrl2 << 2) & 4)) { @@ -302,7 +212,7 @@ void tvga_recalctimings(svga_t *svga) case 7: svga->clock = cpuclock/40000000.0; break; } - if ((tvga->oldctrl2 & 0x10) || (gfxcard == GFX_TGUI9440 && (svga->crtc[0x2a] & 0x40))) + if (tvga->oldctrl2 & 0x10) { switch (svga->bpp) { @@ -311,142 +221,18 @@ void tvga_recalctimings(svga_t *svga) break; case 15: svga->render = svga_render_15bpp_highres; + svga->hdisp /= 2; break; case 16: svga->render = svga_render_16bpp_highres; + svga->hdisp /= 2; break; case 24: - svga->render = svga_render_24bpp_highres; - break; - case 32: - svga->render = svga_render_32bpp_highres; + svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; break; } - } -} - -void tvga_recalcmapping(tvga_t *tvga) -{ - svga_t *svga = &tvga->svga; - -// pclog("tvga_recalcmapping : %02X %02X\n", svga->crtc[0x21], svga->gdcreg[6]); - - if (svga->crtc[0x21] & 0x20) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&tvga->linear_mapping, tvga->linear_base, tvga->linear_size); -// pclog("Trident linear framebuffer at %08X - size %06X\n", tvga->linear_base, tvga->linear_size); - mem_mapping_enable(&tvga->accel_mapping); - } - else - { -// pclog("Write mapping %02X\n", val); - mem_mapping_disable(&tvga->linear_mapping); - mem_mapping_disable(&tvga->accel_mapping); - switch (svga->gdcreg[6] & 0xC) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_enable(&tvga->accel_mapping); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - break; - } - } -} - -void tvga_hwcursor_draw(svga_t *svga, int displine) -{ - uint32_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; - for (xx = 0; xx < 32; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; - else if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; -// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]); - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr += 8; -} - -uint8_t tvga_pci_read(int func, int addr, void *p) -{ - tvga_t *tvga = (tvga_t *)p; - svga_t *svga = &tvga->svga; - -// pclog("Trident PCI read %08X\n", addr); - - switch (addr) - { - case 0x00: return 0x23; /*Trident*/ - case 0x01: return 0x10; - - case 0x02: return 0x40; /*TGUI9440 (9682)*/ - case 0x03: return 0x94; - - case 0x04: return 0x03; /*Respond to IO and memory accesses*/ - - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return tvga->linear_base >> 16; - case 0x13: return tvga->linear_base >> 24; - - case 0x30: return 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; - } - return 0; -} - -void tvga_pci_write(int func, int addr, uint8_t val, void *p) -{ - tvga_t *tvga = (tvga_t *)p; - svga_t *svga = &tvga->svga; - -// pclog("Trident PCI write %08X %02X\n", addr, val); - - switch (addr) - { - case 0x12: - tvga->linear_base = (tvga->linear_base & 0xff000000) | ((val & 0xe0) << 16); - tvga->linear_size = 2 << 20; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4); - tvga_recalcmapping(tvga); - break; - case 0x13: - tvga->linear_base = (tvga->linear_base & 0xe00000) | (val << 24); - tvga->linear_size = 2 << 20; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6); - tvga_recalcmapping(tvga); - break; + svga->lowres = 0; } } @@ -459,41 +245,16 @@ void *tvga8900d_init() tvga_recalctimings, tvga_in, tvga_out, NULL); - - mem_mapping_add(&tvga->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tvga->svga); - mem_mapping_add(&tvga->accel_mapping, 0xbc000, 0x4000, tvga_accel_read, tvga_accel_read_w, tvga_accel_read_l, tvga_accel_write, tvga_accel_write_w, tvga_accel_write_l, tvga); - mem_mapping_disable(&tvga->linear_mapping); - mem_mapping_disable(&tvga->accel_mapping); - + io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); return tvga; } -void *tgui9440_init() -{ - tvga_t *tvga = malloc(sizeof(tvga_t)); - memset(tvga, 0, sizeof(tvga_t)); - - svga_init(&tvga->svga, tvga, 1 << 21, /*2mb*/ - tvga_recalctimings, - tvga_in, tvga_out, - tvga_hwcursor_draw); - - mem_mapping_add(&tvga->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, &tvga->svga); - mem_mapping_add(&tvga->accel_mapping, 0xbc000, 0x4000, tvga_accel_read, tvga_accel_read_w, tvga_accel_read_l, tvga_accel_write, tvga_accel_write_w, tvga_accel_write_l, tvga); - mem_mapping_disable(&tvga->accel_mapping); - - io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); - - pci_add(tvga_pci_read, tvga_pci_write, tvga); - - return tvga; -} void tvga_close(void *p) { tvga_t *tvga = (tvga_t *)p; - + svga_close(&tvga->svga); free(tvga); @@ -513,592 +274,11 @@ void tvga_force_redraw(void *p) tvga->svga.fullchange = changeframecount; } -enum +int tvga_add_status_info(char *s, int max_len, void *p) { - TGUI_BITBLT = 1 -}; - -enum -{ - TGUI_SRCCPU = 0, + tvga_t *tvga = (tvga_t *)p; - TGUI_SRCDISP = 0x04, /*Source is from display*/ - TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ - TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ - TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ - TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ - TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/ -}; - -#define READ(addr, dat) if (tvga->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \ - else dat = vram_w[addr & 0xfffff]; - -#define MIX() do \ - { \ - out = 0; \ - for (c=0;c<16;c++) \ - { \ - d=(dst_dat & (1<accel.rop & (1<accel.bpp == 0) \ - { \ - svga->vram[addr & 0x1fffff] = dat; \ - svga->changedvram[((addr) & 0x1fffff) >> 10] = changeframecount; \ - } \ - else \ - { \ - vram_w[addr & 0xfffff] = dat; \ - svga->changedvram[((addr) & 0xfffff) >> 9] = changeframecount; \ - } - -void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); -void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); - -void tvga_accel_command(int count, uint32_t cpu_dat, tvga_t *tvga) -{ - svga_t *svga = &tvga->svga; - int x, y; - int c, d; - uint16_t src_dat, dst_dat, pat_dat; - uint16_t out; - int xdir = (tvga->accel.flags & 0x200) ? -1 : 1; - int ydir = (tvga->accel.flags & 0x100) ? -1 : 1; - uint16_t trans_col = (tvga->accel.flags & TGUI_TRANSREV) ? tvga->accel.fg_col : tvga->accel.bg_col; - uint16_t *vram_w = (uint16_t *)svga->vram; - - if (tvga->accel.bpp == 0) - trans_col &= 0xff; - - if (count != -1 && !tvga->accel.x) - { - count -= tvga->accel.offset; - cpu_dat <<= tvga->accel.offset; - } - if (count == -1) - { - tvga->accel.x = tvga->accel.y = 0; - } - if (tvga->accel.flags & TGUI_SOLIDFILL) - { -// pclog("SOLIDFILL\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tvga->accel.tvga_pattern[y][x] = tvga->accel.fg_col; - } - } - } - else if (tvga->accel.flags & TGUI_PATMONO) - { -// pclog("PATMONO\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tvga->accel.tvga_pattern[y][x] = (tvga->accel.pattern[y] & (1 << x)) ? tvga->accel.fg_col : tvga->accel.bg_col; - } - } - } - else - { - if (tvga->accel.bpp == 0) - { -// pclog("OTHER 8-bit\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tvga->accel.tvga_pattern[y][x] = tvga->accel.pattern[x + y*8]; - } - } - } - else - { -// pclog("OTHER 16-bit\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tvga->accel.tvga_pattern[y][x] = tvga->accel.pattern[x*2 + y*16] | (tvga->accel.pattern[x*2 + y*16 + 1] << 8); - } - } - } - } -/* for (y = 0; y < 8; y++) - { - if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tvga->accel.tvga_pattern[y][0], tvga->accel.tvga_pattern[y][1], tvga->accel.tvga_pattern[y][2], tvga->accel.tvga_pattern[y][3], tvga->accel.tvga_pattern[y][4], tvga->accel.tvga_pattern[y][5], tvga->accel.tvga_pattern[y][6], tvga->accel.tvga_pattern[y][7]); - }*/ -// if (count == -1) pclog("Command %i %i %p\n", tvga->accel.command, TGUI_BITBLT, tvga); - switch (tvga->accel.command) - { - case TGUI_BITBLT: -// if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tvga->accel.src_x, tvga->accel.src_y, tvga->accel.dst_x, tvga->accel.dst_y, tvga->accel.size_x, tvga->accel.size_y, tvga->accel.flags); - if (count == -1) - { - tvga->accel.src = tvga->accel.src_old = tvga->accel.src_x + (tvga->accel.src_y * tvga->accel.pitch); - tvga->accel.dst = tvga->accel.dst_old = tvga->accel.dst_x + (tvga->accel.dst_y * tvga->accel.pitch); - tvga->accel.pat_x = tvga->accel.dst_x; - tvga->accel.pat_y = tvga->accel.dst_y; - } - - switch (tvga->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) - { - case TGUI_SRCCPU: - if (count == -1) - { -// pclog("Blit start TGUI_SRCCPU\n"); - if (svga->crtc[0x21] & 0x20) - mem_mapping_set_handler(&tvga->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l); - - if (tvga->accel.use_src) - return; - } - else - count >>= 3; -// pclog("TGUI_SRCCPU\n"); - while (count) - { - if (tvga->accel.bpp == 0) - { - src_dat = cpu_dat >> 24; - cpu_dat <<= 8; - } - else - { - src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); - cpu_dat <<= 16; - count--; - } - READ(tvga->accel.dst, dst_dat); - pat_dat = tvga->accel.tvga_pattern[tvga->accel.pat_y & 7][tvga->accel.pat_x & 7]; - - if (!(tvga->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tvga->accel.dst, out); - } - -// pclog(" %i,%i %02X %02X %02X %02X\n", tvga->accel.x, tvga->accel.y, src_dat,dst_dat,pat_dat, out); - - tvga->accel.src += xdir; - tvga->accel.dst += xdir; - tvga->accel.pat_x += xdir; - - tvga->accel.x++; - if (tvga->accel.x > tvga->accel.size_x) - { - tvga->accel.x = 0; - tvga->accel.y++; - - tvga->accel.pat_x = tvga->accel.dst_x; - - tvga->accel.src = tvga->accel.src_old = tvga->accel.src_old + (ydir * tvga->accel.pitch); - tvga->accel.dst = tvga->accel.dst_old = tvga->accel.dst_old + (ydir * tvga->accel.pitch); - tvga->accel.pat_y += ydir; - - if (tvga->accel.y > tvga->accel.size_y) - { - if (svga->crtc[0x21] & 0x20) - { -// pclog("Blit end\n"); - mem_mapping_set_handler(&tvga->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); - } - return; - } - if (tvga->accel.use_src) - return; - } - count--; - } - break; - - case TGUI_SRCMONO | TGUI_SRCCPU: - if (count == -1) - { -// pclog("Blit start TGUI_SRCMONO | TGUI_SRCCPU\n"); - if (svga->crtc[0x21] & 0x20) - mem_mapping_set_handler(&tvga->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tvga_accel_write_fb_b, tvga_accel_write_fb_w, tvga_accel_write_fb_l); - -// pclog(" %i\n", tvga->accel.command); - if (tvga->accel.use_src) - return; - } -// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n"); - while (count) - { - src_dat = ((cpu_dat >> 31) ? tvga->accel.fg_col : tvga->accel.bg_col); - if (tvga->accel.bpp == 0) - src_dat &= 0xff; - - READ(tvga->accel.dst, dst_dat); - pat_dat = tvga->accel.tvga_pattern[tvga->accel.pat_y & 7][tvga->accel.pat_x & 7]; - - if (!(tvga->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tvga->accel.dst, out); - } -// pclog(" %i,%i %02X %02X %02X %02X %i\n", tvga->accel.x, tvga->accel.y, src_dat,dst_dat,pat_dat, out, (!(tvga->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)); - cpu_dat <<= 1; - tvga->accel.src += xdir; - tvga->accel.dst += xdir; - tvga->accel.pat_x += xdir; - - tvga->accel.x++; - if (tvga->accel.x > tvga->accel.size_x) - { - tvga->accel.x = 0; - tvga->accel.y++; - - tvga->accel.pat_x = tvga->accel.dst_x; - - tvga->accel.src = tvga->accel.src_old = tvga->accel.src_old + (ydir * tvga->accel.pitch); - tvga->accel.dst = tvga->accel.dst_old = tvga->accel.dst_old + (ydir * tvga->accel.pitch); - tvga->accel.pat_y += ydir; - - if (tvga->accel.y > tvga->accel.size_y) - { - if (svga->crtc[0x21] & 0x20) - { -// pclog("Blit end\n"); - mem_mapping_set_handler(&tvga->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); - } - return; - } - if (tvga->accel.use_src) - return; - } - count--; - } - break; - - default: - while (count) - { - READ(tvga->accel.src, src_dat); - READ(tvga->accel.dst, dst_dat); - pat_dat = tvga->accel.tvga_pattern[tvga->accel.pat_y & 7][tvga->accel.pat_x & 7]; - - if (!(tvga->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tvga->accel.dst, out); - } -// pclog(" %i,%i %02X %02X %02X %02X\n", tvga->accel.x, tvga->accel.y, src_dat,dst_dat,pat_dat, out); - - tvga->accel.src += xdir; - tvga->accel.dst += xdir; - tvga->accel.pat_x += xdir; - - tvga->accel.x++; - if (tvga->accel.x > tvga->accel.size_x) - { - tvga->accel.x = 0; - tvga->accel.y++; - - tvga->accel.pat_x = tvga->accel.dst_x; - - tvga->accel.src = tvga->accel.src_old = tvga->accel.src_old + (ydir * tvga->accel.pitch); - tvga->accel.dst = tvga->accel.dst_old = tvga->accel.dst_old + (ydir * tvga->accel.pitch); - tvga->accel.pat_y += ydir; - - if (tvga->accel.y > tvga->accel.size_y) - return; - } - count--; - } - break; - } - break; - } -} - -void tvga_accel_write(uint32_t addr, uint8_t val, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode); - if ((addr & ~0xff) != 0xbff00) - return; - switch (addr & 0xff) - { - case 0x22: - tvga->accel.ger22 = val; - tvga->accel.pitch = 512 << ((val >> 2) & 3); - tvga->accel.bpp = (val & 3) ? 1 : 0; - tvga->accel.pitch >>= tvga->accel.bpp; - break; - - case 0x24: /*Command*/ - tvga->accel.command = val; - tvga_accel_command(-1, 0, tvga); - break; - - case 0x27: /*ROP*/ - tvga->accel.rop = val; - tvga->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); -// pclog("Write ROP %02X %i\n", val, tvga->accel.use_src); - break; - - case 0x28: /*Flags*/ - tvga->accel.flags = (tvga->accel.flags & 0xff00) | val; - break; - case 0x29: /*Flags*/ - tvga->accel.flags = (tvga->accel.flags & 0xff) | (val << 8); - break; - - case 0x2b: - tvga->accel.offset = val & 7; - break; - - case 0x2c: /*Foreground colour*/ - tvga->accel.fg_col = (tvga->accel.fg_col & 0xff00) | val; - break; - case 0x2d: /*Foreground colour*/ - tvga->accel.fg_col = (tvga->accel.fg_col & 0xff) | (val << 8); - break; - - case 0x30: /*Background colour*/ - tvga->accel.bg_col = (tvga->accel.bg_col & 0xff00) | val; - break; - case 0x31: /*Background colour*/ - tvga->accel.bg_col = (tvga->accel.bg_col & 0xff) | (val << 8); - break; - - case 0x38: /*Dest X*/ - tvga->accel.dst_x = (tvga->accel.dst_x & 0xff00) | val; - break; - case 0x39: /*Dest X*/ - tvga->accel.dst_x = (tvga->accel.dst_x & 0xff) | (val << 8); - break; - case 0x3a: /*Dest Y*/ - tvga->accel.dst_y = (tvga->accel.dst_y & 0xff00) | val; - break; - case 0x3b: /*Dest Y*/ - tvga->accel.dst_y = (tvga->accel.dst_y & 0xff) | (val << 8); - break; - - case 0x3c: /*Src X*/ - tvga->accel.src_x = (tvga->accel.src_x & 0xff00) | val; - break; - case 0x3d: /*Src X*/ - tvga->accel.src_x = (tvga->accel.src_x & 0xff) | (val << 8); - break; - case 0x3e: /*Src Y*/ - tvga->accel.src_y = (tvga->accel.src_y & 0xff00) | val; - break; - case 0x3f: /*Src Y*/ - tvga->accel.src_y = (tvga->accel.src_y & 0xff) | (val << 8); - break; - - case 0x40: /*Size X*/ - tvga->accel.size_x = (tvga->accel.size_x & 0xff00) | val; - break; - case 0x41: /*Size X*/ - tvga->accel.size_x = (tvga->accel.size_x & 0xff) | (val << 8); - break; - case 0x42: /*Size Y*/ - tvga->accel.size_y = (tvga->accel.size_y & 0xff00) | val; - break; - case 0x43: /*Size Y*/ - tvga->accel.size_y = (tvga->accel.size_y & 0xff) | (val << 8); - break; - - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - tvga->accel.pattern[addr & 0x7f] = val; - break; - } -} - -void tvga_accel_write_w(uint32_t addr, uint16_t val, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_write_w %08X %04X\n", addr, val); - tvga_accel_write(addr, val, tvga); - tvga_accel_write(addr + 1, val >> 8, tvga); -} - -void tvga_accel_write_l(uint32_t addr, uint32_t val, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_write_l %08X %08X\n", addr, val); - tvga_accel_write(addr, val, tvga); - tvga_accel_write(addr + 1, val >> 8, tvga); - tvga_accel_write(addr + 2, val >> 16, tvga); - tvga_accel_write(addr + 3, val >> 24, tvga); -} - -uint8_t tvga_accel_read(uint32_t addr, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_read : %08X\n", addr); - if ((addr & ~0xff) != 0xbff00) - return 0xff; - switch (addr & 0xff) - { - case 0x20: /*Status*/ - return 0; - - case 0x27: /*ROP*/ - return tvga->accel.rop; - - case 0x28: /*Flags*/ - return tvga->accel.flags & 0xff; - case 0x29: /*Flags*/ - return tvga->accel.flags >> 8; - - case 0x2b: - return tvga->accel.offset; - - case 0x2c: /*Background colour*/ - return tvga->accel.bg_col & 0xff; - case 0x2d: /*Background colour*/ - return tvga->accel.bg_col >> 8; - - case 0x30: /*Foreground colour*/ - return tvga->accel.fg_col & 0xff; - case 0x31: /*Foreground colour*/ - return tvga->accel.fg_col >> 8; - - case 0x38: /*Dest X*/ - return tvga->accel.dst_x & 0xff; - case 0x39: /*Dest X*/ - return tvga->accel.dst_x >> 8; - case 0x3a: /*Dest Y*/ - return tvga->accel.dst_y & 0xff; - case 0x3b: /*Dest Y*/ - return tvga->accel.dst_y >> 8; - - case 0x3c: /*Src X*/ - return tvga->accel.src_x & 0xff; - case 0x3d: /*Src X*/ - return tvga->accel.src_x >> 8; - case 0x3e: /*Src Y*/ - return tvga->accel.src_y & 0xff; - case 0x3f: /*Src Y*/ - return tvga->accel.src_y >> 8; - - case 0x40: /*Size X*/ - return tvga->accel.size_x & 0xff; - case 0x41: /*Size X*/ - return tvga->accel.size_x >> 8; - case 0x42: /*Size Y*/ - return tvga->accel.size_y & 0xff; - case 0x43: /*Size Y*/ - return tvga->accel.size_y >> 8; - - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - return tvga->accel.pattern[addr & 0x7f]; - } - return 0xff; -} - -uint16_t tvga_accel_read_w(uint32_t addr, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_read_w %08X\n", addr); - return tvga_accel_read(addr, tvga) | (tvga_accel_read(addr + 1, tvga) << 8); -} - -uint32_t tvga_accel_read_l(uint32_t addr, void *p) -{ - tvga_t *tvga = (tvga_t *)p; -// pclog("tvga_accel_read_l %08X\n", addr); - return tvga_accel_read_w(addr, tvga) | (tvga_accel_read_w(addr + 2, tvga) << 16); -} - -void tvga_accel_write_fb_b(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tvga_t *tvga = (tvga_t *)svga->p; -// pclog("tvga_accel_write_fb_b %08X %02X\n", addr, val); - tvga_accel_command(8, val << 24, tvga); -} - -void tvga_accel_write_fb_w(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tvga_t *tvga = (tvga_t *)svga->p; -// pclog("tvga_accel_write_fb_w %08X %04X\n", addr, val); - tvga_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tvga); -} - -void tvga_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tvga_t *tvga = (tvga_t *)svga->p; -// pclog("tvga_accel_write_fb_l %08X %08X\n", addr, val); - tvga_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tvga); + return svga_add_status_info(s, max_len, &tvga->svga); } device_t tvga8900d_device = @@ -1109,16 +289,5 @@ device_t tvga8900d_device = NULL, tvga_speed_changed, tvga_force_redraw, - svga_add_status_info -}; - -device_t tgui9440_device = -{ - "Trident TGUI 9440", - tgui9440_init, - tvga_close, - NULL, - tvga_speed_changed, - tvga_force_redraw, - svga_add_status_info + tvga_add_status_info }; diff --git a/src/vid_tvga.h b/src/vid_tvga.h index ced63d3..d55ff65 100644 --- a/src/vid_tvga.h +++ b/src/vid_tvga.h @@ -1,2 +1 @@ extern device_t tvga8900d_device; -extern device_t tgui9440_device; diff --git a/src/vid_vga.c b/src/vid_vga.c index 3f6fdde..cab5b53 100644 --- a/src/vid_vga.c +++ b/src/vid_vga.c @@ -114,6 +114,13 @@ void vga_force_redraw(void *p) vga->svga.fullchange = changeframecount; } +int vga_add_status_info(char *s, int max_len, void *p) +{ + vga_t *vga = (vga_t *)p; + + return svga_add_status_info(s, max_len, &vga->svga); +} + device_t vga_device = { "VGA", @@ -122,5 +129,5 @@ device_t vga_device = NULL, vga_speed_changed, vga_force_redraw, - svga_add_status_info + vga_add_status_info }; diff --git a/src/video.c b/src/video.c index 775de27..052bedb 100644 --- a/src/video.c +++ b/src/video.c @@ -29,6 +29,7 @@ #include "vid_s3.h" #include "vid_s3_virge.h" #include "vid_tandy.h" +#include "vid_tgui9440.h" #include "vid_tvga.h" #include "vid_vga.h"