From 7612b42d9543e4ce9bdbb93a362d91d1d2f13bbc Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 23 Jul 2016 15:34:06 +0200 Subject: [PATCH] Added dummy BT485 emulation for logging purposes, proper BT485 implementation to come. --- src/vid_bt485_ramdac.c | 167 +++++++++++++++++++++++++++++++++++++++++ src/vid_bt485_ramdac.h | 15 ++++ src/vid_s3.c | 31 ++++++-- 3 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 src/vid_bt485_ramdac.c create mode 100644 src/vid_bt485_ramdac.h diff --git a/src/vid_bt485_ramdac.c b/src/vid_bt485_ramdac.c new file mode 100644 index 000000000..a18ef2915 --- /dev/null +++ b/src/vid_bt485_ramdac.c @@ -0,0 +1,167 @@ +/*Brooktree BT485 true colour RAMDAC emulation*/ +/*Currently only a dummy for logging*/ +#include "ibm.h" +#include "mem.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_bt485_ramdac.h" + +int bt485_get_clock_divider(bt485_ramdac_t *ramdac) +{ + return 1; +} + +void bt485_set_rs2(uint8_t rs2, bt485_ramdac_t *ramda) +{ + ramdac->rs2 = rs2 ? 1 : 0; +} + +void bt485_set_rs3(uint8_t rs3, bt485_ramdac_t *ramda) +{ + ramdac->rs3 = rs3 ? 1 : 0; +} + +void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga) +{ +// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); + uint8_t reg = addr & 3; + reg | = (ramdac->rs2 ? 4 : 0); + reg | = (ramdac->rs3 ? 8 : 0); + pclog("BT485 RAMDAC: Writing %02X to register %02\n", val, reg); + return; + + switch (addr) + { + case 0x3C6: + if (val == 0xff) + { + ramdac->rs2 = 0; + ramdac->magic_count = 0; + break; + } + if (ramdac->magic_count < 4) break; + if (ramdac->magic_count == 4) + { + ramdac->command = val; +// pclog("RAMDAC command reg now %02X\n", val); + switch (val >> 4) + { + case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; + case 0x4: case 0xe: svga->bpp = 24; break; + case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; + case 0x7: svga->bpp = 32; break; + + case 0: case 1: default: svga->bpp = 8; break; + } + svga_recalctimings(svga); + } + //ramdac->magic_count = 0; + break; + + case 0x3C7: + ramdac->magic_count = 0; + if (ramdac->rs2) + ramdac->rindex = val; + break; + case 0x3C8: + ramdac->magic_count = 0; + if (ramdac->rs2) + ramdac->windex = val; + break; + case 0x3C9: + ramdac->magic_count = 0; + if (ramdac->rs2) + { + if (!ramdac->reg_ff) ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0xff00) | val; + else ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0x00ff) | (val << 8); + ramdac->reg_ff = !ramdac->reg_ff; +// pclog("RAMDAC reg %02X now %04X\n", ramdac->windex, ramdac->regs[ramdac->windex]); + if (!ramdac->reg_ff) ramdac->windex++; + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga) +{ + uint8_t temp; +// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, ramdac->rs2); + uint8_t reg = addr & 3; + reg | = (ramdac->rs2 ? 4 : 0); + reg | = (ramdac->rs3 ? 8 : 0); + pclog("BT485 RAMDAC: Reading register %02\n", reg); + return; + + switch (addr) + { + case 0x3C6: + ramdac->reg_ff = 0; + if (ramdac->magic_count < 5) + ramdac->magic_count++; + if (ramdac->magic_count == 4) + { + temp = 0x70; /*SDAC ID*/ + ramdac->rs2 = 1; + } + if (ramdac->magic_count == 5) + { + temp = ramdac->command; + ramdac->magic_count = 0; + } + return temp; + case 0x3C7: +// if (ramdac->magic_count < 4) +// { + ramdac->magic_count=0; +// break; +// } + if (ramdac->rs2) return ramdac->rindex; + break; + case 0x3C8: +// if (ramdac->magic_count < 4) +// { + ramdac->magic_count=0; +// break; +// } + if (ramdac->rs2) return ramdac->windex; + break; + case 0x3C9: +// if (ramdac->magic_count < 4) +// { + ramdac->magic_count=0; +// break; +// } + if (ramdac->rs2) + { + if (!ramdac->reg_ff) temp = ramdac->regs[ramdac->rindex] & 0xff; + else temp = ramdac->regs[ramdac->rindex] >> 8; + ramdac->reg_ff = !ramdac->reg_ff; + if (!ramdac->reg_ff) + { + ramdac->rindex++; + ramdac->magic_count = 0; + } + return temp; + } + break; + } + return svga_in(addr, svga); +} + +float bt485_getclock(int clock, void *p) +{ + bt485_ramdac_t *ramdac = (bt485_ramdac_t *)p; + float t; + int m, n1, n2; +// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]); + if (clock == 0) return 25175000.0; + if (clock == 1) return 28322000.0; + clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ + m = (ramdac->regs[clock] & 0x7f) + 2; + n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; + n2 = ((ramdac->regs[clock] >> 13) & 0x07); + t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); +// pclog("BT485 clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2); + return t; +} diff --git a/src/vid_bt485_ramdac.h b/src/vid_bt485_ramdac.h new file mode 100644 index 000000000..ca6f1762e --- /dev/null +++ b/src/vid_bt485_ramdac.h @@ -0,0 +1,15 @@ +typedef struct bt485_ramdac_t +{ + int magic_count; + uint8_t command; + int windex, rindex; + uint16_t regs[256]; + int reg_ff; + int rs2; + int rs3; +} bt485_ramdac_t; + +void bt485_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga); +uint8_t bt485_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga); + +float bt485_getclock(int clock, void *p); diff --git a/src/vid_s3.c b/src/vid_s3.c index e93befd33..3ebed6b8f 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -11,11 +11,13 @@ #include "vid_s3.h" #include "vid_svga.h" #include "vid_svga_render.h" +#include "vid_bt485_ramdac.h" #include "vid_sdac_ramdac.h" enum { S3_VISION864, + S3_VISION964, S3_TRIO32, S3_TRIO64 }; @@ -66,6 +68,7 @@ typedef struct s3_t svga_t svga; sdac_ramdac_t ramdac; + bt485_ramdac_t bt485_ramdac; uint8_t bank; uint8_t ma_ext; @@ -849,7 +852,21 @@ void s3_out(uint16_t addr, uint8_t val, void *p) } } break; - //case 0x55: case 0x43: + case 0x55: case 0x43: + if (s3->chip == S3_VISION964) + { + if (svga->crtc[0x55] & 3) + { + bt485_set_rs2(svga->crtc[0x55] & 1, &s3->bt485_ramdac); + bt485_set_rs3(svga->crtc[0x55] & 2, &s3->bt485_ramdac); + } + else + { + bt485_set_rs2(svga->crtc[0x43] & 2, &s3->bt485_ramdac); + } + pclog("RS2 is now %i, RS3 is now %i\n", s3->bt485_ramdac.rs2, s3->bt485_ramdac.rs3); + } + break; // pclog("Write CRTC R%02X %02X\n", crtcreg, val); } if (old != val) @@ -2269,21 +2286,21 @@ int s3_phoenix_trio64_available() void *s3_miro_vision964_init() { - s3_t *s3 = s3_init("roms/VISION864P.BIN", S3_VISION864); + s3_t *s3 = s3_init("roms/mirocrystal.VBI", S3_VISION964); - s3->id = 0xc1; /*Vision864P*/ - s3->id_ext = s3->id_ext_pci = 0xc1; + s3->id = 0xd1; /*Vision964P*/ + s3->id_ext = s3->id_ext_pci = 0xd1; s3->packed_mmio = 1; - s3->getclock = sdac_getclock; - s3->getclock_p = &s3->ramdac; + s3->getclock = bt485_getclock; + s3->getclock_p = &s3->bt485_ramdac; return s3; } int s3_miro_vision964_available() { - return rom_present("roms/VISION864P.BIN"); + return rom_present("roms/mirocrystal.VBI"); } void s3_close(void *p)