diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 083de1f26..a177c69d8 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -48,11 +48,11 @@ typedef struct ht216_t int clk_sel; uint8_t read_bank_reg[2], write_bank_reg[2]; - uint32_t read_bank[2], write_bank[2]; - uint8_t misc, pad; - uint16_t id; + uint16_t id, misc; + uint32_t read_banks[2], write_banks[2]; uint8_t bg_latch[8]; + uint8_t mw_state, mw_cnt, mw_cpu; uint8_t ht_regs[256]; } ht216_t; @@ -60,7 +60,7 @@ typedef struct ht216_t #define HT_MISC_PAGE_SEL (1 << 5) -/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel colour expansion*/ +/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel color expansion*/ #define HT_REG_C8_MOVSB (1 << 0) #define HT_REG_C8_E256 (1 << 4) #define HT_REG_C8_XLAM (1 << 6) @@ -132,11 +132,12 @@ ht216_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: ht216->clk_sel = (ht216->clk_sel & ~3) | ((val & 0x0c) >> 2); - ht216->misc = val; - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0); + /*Bit 17 of the display memory address, only active on odd/even modes, has no effect on graphics modes.*/ + ht216->misc = val; + ht216_log("HT216 misc val = %02x\n", val); ht216_remap(ht216); - svga_recalctimings(&ht216->svga); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; case 0x3c5: @@ -182,49 +183,58 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0xa4: ht216->clk_sel = (val >> 2) & 0xf; svga->miscout = (svga->miscout & ~0xc) | ((ht216->clk_sel & 3) << 2); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; case 0xa5: - svga->hwcursor.ena = val & 0x80; + svga->hwcursor.ena = !!(val & 0x80); break; case 0xc8: - if ((old ^ val) & 0x10) { + if ((old ^ val) & HT_REG_C8_E256) { svga->fullchange = changeframecount; svga_recalctimings(svga); } break; + /*Bank registers*/ case 0xe8: - ht216->read_bank_reg[0] = val; - ht216->write_bank_reg[0] = val; - break; case 0xe9: - ht216->read_bank_reg[1] = val; - ht216->write_bank_reg[1] = val; + ht216_remap(ht216); break; + case 0xf6: svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff; - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0xc0) | ((val & 0xc) << 4); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0xc0) | ((val & 0x3) << 6); + /*Bits 18 and 19 of the display memory address*/ + ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x\n", val & 0x40, svga->vram_display_mask); + ht216_remap(ht216); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; + case 0xf9: - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0); + /*Bit 16 of the display memory address, only active when in chain4 mode and 256 color mode.*/ + ht216_log("HT216 reg 0xf9 write = %02x\n", val & HT_REG_F9_XPSEL); + ht216_remap(ht216); break; + + case 0xfc: + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + case 0xff: svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((val & 0x60) << 11)) << 2; break; } switch (svga->seqaddr & 0xff) { - case 0xa4: case 0xf6: case 0xfc: - svga->fullchange = changeframecount; - svga_recalctimings(&ht216->svga); - break; - } - switch (svga->seqaddr & 0xff) { - case 0xc8: case 0xc9: case 0xcf: - case 0xe0: case 0xe8: case 0xe9: - case 0xf6: case 0xf9: + case 0xc8: case 0xc9: case 0xcf: case 0xe0: + if ((svga->seqaddr & 0xff) == 0xc8) { + svga->adv_flags = 0; + if (val & HT_REG_C8_MOVSB) { + svga->adv_flags = FLAG_ADDR_BY8; + } + } ht216_remap(ht216); break; } @@ -233,12 +243,12 @@ ht216_out(uint16_t addr, uint8_t val, void *p) break; case 0x3cf: - if (svga->gdcaddr == 6) { - if (val & 8) - svga->banked_mask = 0x7fff; - else - svga->banked_mask = 0xffff; - } + if (svga->gdcaddr == 6) { + if (val & 8) + svga->banked_mask = 0x7fff; + else + svga->banked_mask = 0xffff; + } break; case 0x3D4: @@ -263,11 +273,11 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0x46e8: io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_disable(&ht216->svga.mapping); + mem_mapping_disable(&svga->mapping); mem_mapping_disable(&ht216->linear_mapping); if (val & 8) { io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_enable(&ht216->svga.mapping); + mem_mapping_enable(&svga->mapping); ht216_remap(ht216); } break; @@ -335,42 +345,142 @@ void ht216_remap(ht216_t *ht216) { svga_t *svga = &ht216->svga; + uint8_t bank = ht216->ht_regs[0xf6] & 0x0f; mem_mapping_disable(&ht216->linear_mapping); if (ht216->ht_regs[0xc8] & HT_REG_C8_XLAM) { - uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); - - mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000); - /*Linear mapping enabled*/ + uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000); } else { - uint8_t read_bank_reg[2] = {ht216->read_bank_reg[0], ht216->read_bank_reg[1]}; - uint8_t write_bank_reg[2] = {ht216->write_bank_reg[0], ht216->write_bank_reg[1]}; - - if (!svga->chain4 || !(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { - read_bank_reg[0] &= ~0x30; - read_bank_reg[1] &= ~0x30; - write_bank_reg[0] &= ~0x30; - write_bank_reg[1] &= ~0x30; - } - - ht216->read_bank[0] = read_bank_reg[0] << 12; - ht216->write_bank[0] = write_bank_reg[0] << 12; if (ht216->ht_regs[0xe0] & HT_REG_E0_SBAE) { - /*Split bank*/ - ht216->read_bank[1] = read_bank_reg[1] << 12; - ht216->write_bank[1] = write_bank_reg[1] << 12; + /*Split bank: two banks used*/ + /*Windows 3.1 always touches the misc register when split banks are enabled.*/ + if (!(ht216->misc & HT_MISC_PAGE_SEL)) { + //pclog("No page sel\n"); + ht216->read_banks[0] = ht216->ht_regs[0xe8] << 12; + ht216->write_banks[0] = ht216->ht_regs[0xe8] << 12; + ht216->read_banks[1] = ht216->ht_regs[0xe9] << 12; + ht216->write_banks[1] = ht216->ht_regs[0xe9] << 12; + + if (!svga->chain4) { + if (ht216->ht_regs[0xe8] == 0x40) { + ht216->read_banks[0] = 0x10000; + ht216->write_banks[0] = 0x10000; + } + if (ht216->ht_regs[0xe9] == 0x40) { + ht216->read_banks[1] = 0x10000; + ht216->write_banks[1] = 0x10000; + } + + if (ht216->ht_regs[0xe8] == 0x48) { + ht216->read_banks[0] = 0x18000; + ht216->write_banks[0] = 0x18000; + } + if (ht216->ht_regs[0xe9] == 0x48) { + ht216->read_banks[1] = 0x18000; + ht216->write_banks[1] = 0x18000; + } + + if (ht216->ht_regs[0xe8] == 0x80) { + ht216->read_banks[0] = 0x20000; + ht216->write_banks[0] = 0x20000; + } + if (ht216->ht_regs[0xe9] == 0x80) { + ht216->read_banks[1] = 0x20000; + ht216->write_banks[1] = 0x20000; + } + + if (ht216->ht_regs[0xe8] == 0x88) { + ht216->read_banks[0] = 0x28000; + ht216->write_banks[0] = 0x28000; + } + if (ht216->ht_regs[0xe9] == 0x88) { + ht216->read_banks[1] = 0x28000; + ht216->write_banks[1] = 0x28000; + } + + if (ht216->ht_regs[0xe9] == 0xc0) { + ht216->read_banks[1] = 0x30000; + ht216->write_banks[1] = 0x30000; + } + } + } } else { - ht216->read_bank[1] = ht216->read_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); - ht216->write_bank[1] = ht216->write_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); - } + /*One bank used*/ + /*Bit 17 of the video memory address*/ + if (ht216->misc & HT_MISC_PAGE_SEL) { + ht216->read_bank_reg[0] |= 0x20; + ht216->write_bank_reg[0] |= 0x20; + } else { + ht216->read_bank_reg[0] &= ~0x20; + ht216->write_bank_reg[0] &= ~0x20; + } - if (!svga->chain4) { - ht216->read_bank[0] >>= 2; - ht216->read_bank[1] >>= 2; - ht216->write_bank[0] >>= 2; - ht216->write_bank[1] >>= 2; + if (!(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { + if (bank & 2) { + bank &= ~2; + bank |= 1; + } + if (bank & 8) { + bank &= ~8; + bank |= 4; + } + } + + /*Bit 18 and 19 of the video memory address*/ + if (bank & 1) + ht216->write_bank_reg[0] |= 0x40; + else + ht216->write_bank_reg[0] &= ~0x40; + + if (bank & 2) + ht216->write_bank_reg[0] |= 0x80; + else + ht216->write_bank_reg[0] &= ~0x80; + + if (bank & 4) + ht216->read_bank_reg[0] |= 0x40; + else + ht216->read_bank_reg[0] &= ~0x40; + + if (bank & 8) + ht216->read_bank_reg[0] |= 0x80; + else + ht216->read_bank_reg[0] &= ~0x80; + + if (svga->chain4) { + /*Bit 16 of the video memory address*/ + if (ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL) { + ht216->read_bank_reg[0] |= 0x10; + ht216->write_bank_reg[0] |= 0x10; + } else { + ht216->read_bank_reg[0] &= ~0x10; + ht216->write_bank_reg[0] &= ~0x10; + } + } + + if (!svga->chain4) { + /*In linear modes, bits 4 and 5 are ignored*/ + ht216->read_bank_reg[0] &= ~0x30; + ht216->write_bank_reg[0] &= ~0x30; + } + + ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; + ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; + ht216->read_banks[1] = ht216->read_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); + ht216->write_banks[1] = ht216->write_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); + + if (!svga->chain4) { + ht216->read_banks[0] >>= 2; + ht216->read_banks[1] >>= 2; + ht216->write_banks[0] >>= 2; + ht216->write_banks[1] >>= 2; + } } + + ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->banked_mask); } } @@ -386,11 +496,14 @@ ht216_recalctimings(svga_t *svga) case 10: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; } svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256); + svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); + svga->interlace = ht216->ht_regs[0xe0] & 1; - if ((svga->bpp == 8) && !svga->lowres) + if ((svga->bpp == 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; + } } @@ -399,7 +512,7 @@ ht216_hwcursor_draw(svga_t *svga, int displine) { int x; uint32_t dat[2]; - int offset = svga->hwcursor_latch.x + svga->x_add; + int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 4; @@ -415,9 +528,9 @@ ht216_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 32; x++) { if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[offset + x] = 0; + ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] = 0; if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[offset + x] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] ^= 0xffffff; dat[0] <<= 1; dat[1] <<= 1; @@ -461,15 +574,23 @@ static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded) { svga_t *svga = &ht216->svga; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; + int writemask2 = svga->writemask, reset_wm = 0; + latch_t vall; + uint8_t wm = svga->writemask; + uint8_t count, i; uint8_t fg_data[4] = {0, 0, 0, 0}; + if (svga->adv_flags & FLAG_ADDR_BY8) + writemask2 = svga->seqregs[2]; + if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; - if (svga->chain4 || svga->fb_only) { - writemask2=1<<(addr&3); - addr&=~3; + + if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4)) + addr <<= 3; + else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; } else if (svga->chain2_write) { writemask2 &= ~0xa; if (addr & 1) @@ -477,185 +598,168 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u addr &= ~1; addr <<= 2; } else - addr<<=2; + addr <<= 2; + if (addr >= svga->vram_max) return; - svga->changedvram[addr >> 12]=changeframecount; + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + count = 4; switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) { case 0x00: - fg_data[0] = fg_data[1] = fg_data[2] = fg_data[3] = cpu_dat; + for (i = 0; i < count; i++) + fg_data[i] = cpu_dat; break; case 0x04: if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) { if (addr & 4) { - fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) { + fg_data[i] = (cpu_dat_unexpanded & (1 << (((addr + i + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + pclog("FBRC source select = %02x, frgd = %02x, bkgd = %02x\n", (cpu_dat_unexpanded & (1 << (((addr + i + 4) & 7) ^ 7))), ht216->ht_regs[0xf0], ht216->ht_regs[0xf2]); + } } else { - fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) { + fg_data[i] = (cpu_dat_unexpanded & (1 << (((addr + i) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + pclog("FBRC source select = %02x, frgd = %02x, bkgd = %02x\n", (cpu_dat_unexpanded & (1 << (((addr + i) & 7) ^ 7))), ht216->ht_regs[0xf0], ht216->ht_regs[0xf2]); + } } } else { if (addr & 4) { - fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) + fg_data[i] = (ht216->ht_regs[0xf5] & (1 << (((addr + i + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; } else { - fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) + fg_data[i] = (ht216->ht_regs[0xf5] & (1 << (((addr + i) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; } } break; case 0x08: - fg_data[0] = ht216->ht_regs[0xec]; - fg_data[1] = ht216->ht_regs[0xed]; - fg_data[2] = ht216->ht_regs[0xee]; - fg_data[3] = ht216->ht_regs[0xef]; - break; case 0x0c: - fg_data[0] = ht216->ht_regs[0xec]; - fg_data[1] = ht216->ht_regs[0xed]; - fg_data[2] = ht216->ht_regs[0xee]; - fg_data[3] = ht216->ht_regs[0xef]; + for (i = 0; i < count; i++) + fg_data[i] = ht216->ht_regs[0xec + i]; break; } switch (svga->writemode) { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->latch.b[3]; - break; case 0: - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = fg_data[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = fg_data[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = fg_data[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = fg_data[3]; + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = fg_data[i]; + } else { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = fg_data[i]; + } + } + } + return; } else { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = fg_data[0]; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = fg_data[1]; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = fg_data[2]; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = fg_data[3]; - - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = fg_data[i]; } } break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = (((cpu_dat & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((cpu_dat & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((cpu_dat & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((cpu_dat & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - } else { - vala = ((cpu_dat & 1) ? 0xff : 0); - valb = ((cpu_dat & 2) ? 0xff : 0); - valc = ((cpu_dat & 4) ? 0xff : 0); - vald = ((cpu_dat & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + case 1: + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; } } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(cpu_dat & (1 << i)) * 0xff; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + return; + } break; case 3: - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= cpu_dat; + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= cpu_dat; - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + + reset_wm = 1; + break; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } } - svga->gdcreg[8] = wm; break; } + + if (reset_wm) + svga->gdcreg[8] = wm; } @@ -709,6 +813,108 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi svga->changedvram[addr >> 12] = changeframecount; } +static void +ht216_dm_masked_write(ht216_t *ht216, uint32_t addr, uint8_t val, uint8_t bit_mask) +{ + svga_t *svga = &ht216->svga; + int writemask2 = svga->writemask; + uint8_t count, i; + uint8_t mask1 = 0; + uint8_t mask2 = 0; + + if (svga->adv_flags & FLAG_ADDR_BY8) + writemask2 = svga->seqregs[2]; + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4)) + addr <<= 3; + else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + if (addr >= svga->vram_max) + return; + + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + count = 4; + + if (ht216->mw_cnt == 0) { + mask1 = bit_mask; + ht216->mw_cnt = 1; + } else if (ht216->mw_cnt == 1) { + mask2 = bit_mask; + ht216->mw_cnt = 0; + } + + + switch (svga->writemode) { + case 0: + if ((bit_mask == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = val; + } else { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = val; + pclog("BitMask = ff, vram dat = %02x, val = %02x\n", svga->vram[addr | i], val); + } + } + } + return; + } + break; + case 2: + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } + } + return; + } + break; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } else { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + pclog("BitMask = %02x, vram dat = %02x, actual val = %02x, addr = %05x, first = %02x, second = %02x\n", bit_mask, svga->vram[addr | i], val, addr | i, mask1, mask2); + } + } + } + break; + } +} + static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) @@ -727,6 +933,7 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) 1x = (3C4:F5) */ svga_t *svga = &ht216->svga; + int i; uint8_t bit_mask = 0, rop_select = 0; cycles -= video_timing_write_b; @@ -735,7 +942,7 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) addr &= 0xfffff; - val = svga_rotate[svga->gdcreg[3] & 7][val]; + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); if (ht216->ht_regs[0xcd] & HT_REG_CD_EXALU) { /*Extended ALU*/ @@ -761,30 +968,30 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) bit_mask = ht216->ht_regs[0xf5]; break; } - + if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ addr = (addr << 3) & 0xfffff; - ht216_dm_extalu_write(ht216, addr, (val & 0x80) ? 0xff : 0, (bit_mask & 0x80) ? 0xff : 0, val, (rop_select & 0x80) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, (bit_mask & 0x40) ? 0xff : 0, val, (rop_select & 0x40) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, (bit_mask & 0x20) ? 0xff : 0, val, (rop_select & 0x20) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, (bit_mask & 0x10) ? 0xff : 0, val, (rop_select & 0x10) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, (bit_mask & 0x08) ? 0xff : 0, val, (rop_select & 0x08) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, (bit_mask & 0x04) ? 0xff : 0, val, (rop_select & 0x04) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, (bit_mask & 0x02) ? 0xff : 0, val, (rop_select & 0x02) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, (bit_mask & 0x01) ? 0xff : 0, val, (rop_select & 0x01) ? 0xff : 0); - } else + for (i = 0; i < 8; i++) + ht216_dm_extalu_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, (bit_mask & (0x80 >> i)) ? 0xff : 0, val, (rop_select & (0x80 >> i)) ? 0xff : 0); + } else { ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); + } + } else if (ht216->ht_regs[0xf3]) { + if (ht216->ht_regs[0xf3] & 2) { + if (ht216->mw_state == 0) { + ht216->mw_cpu = val; + ht216->mw_state = 1; + } else if (ht216->mw_state == 1) { + ht216_dm_masked_write(ht216, addr, val, ht216->mw_cpu); + ht216->mw_state = 0; + } + } else + ht216_dm_masked_write(ht216, addr, val, ht216->ht_regs[0xf4]); } else { if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ addr = (addr << 3) & 0xfffff; - ht216_dm_write(ht216, addr, (val & 0x80) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, val); + for (i = 0; i < 8; i++) + ht216_dm_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, val); } else ht216_dm_write(ht216, addr, val, val); } @@ -798,10 +1005,10 @@ ht216_write(uint32_t addr, uint8_t val, void *p) svga_t *svga = &ht216->svga; addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_write_linear(addr, val, &ht216->svga); + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + svga_write_linear(addr, val, svga); else ht216_write_common(ht216, addr, val); } @@ -812,11 +1019,12 @@ ht216_writew(uint32_t addr, uint16_t val, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writew_linear(addr, val, &ht216->svga); + svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -831,9 +1039,10 @@ ht216_writel(uint32_t addr, uint32_t val, void *p) svga_t *svga = &ht216->svga; addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writel_linear(addr, val, &ht216->svga); + svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -853,7 +1062,7 @@ ht216_write_linear(uint32_t addr, uint8_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_write_linear(addr, val, &ht216->svga); + svga_write_linear(addr, val, svga); else ht216_write_common(ht216, addr, val); } @@ -869,7 +1078,7 @@ ht216_writew_linear(uint32_t addr, uint16_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writew_linear(addr, val, &ht216->svga); + svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -887,7 +1096,7 @@ ht216_writel_linear(uint32_t addr, uint32_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writel_linear(addr, val, &ht216->svga); + svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -901,37 +1110,39 @@ static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr) { svga_t *svga = &ht216->svga; - uint8_t temp, temp2, temp3, temp4, or; + uint32_t latch_addr = 0; int readplane = svga->readplane; + uint8_t or, count, i; + uint8_t plane, pixel; + uint8_t temp, ret; int offset; - uint32_t latch_addr; - if (ht216->ht_regs[0xc8] & HT_REG_C8_MOVSB) - addr <<= 3; - - addr &= 0xfffff; + if (svga->adv_flags & FLAG_ADDR_BY8) { + readplane = svga->gdcreg[4] & 7; + } cycles -= video_timing_read_b; egareads++; + + addr &= 0xfffff; - if (svga->chain4 || svga->fb_only) { + count = 2; + + latch_addr = (addr << count) & svga->decode_mask; + count = (1 << count); + + if (svga->adv_flags & FLAG_ADDR_BY8) + addr <<= 3; + else if (svga->chain4 || svga->fb_only) { addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; - latch_addr = (addr & svga->vram_mask) & ~7; if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) latch_addr += (svga->gdcreg[3] & 7); - ht216->bg_latch[0] = svga->vram[latch_addr]; - ht216->bg_latch[1] = svga->vram[latch_addr + 1]; - ht216->bg_latch[2] = svga->vram[latch_addr + 2]; - ht216->bg_latch[3] = svga->vram[latch_addr + 3]; - ht216->bg_latch[4] = svga->vram[latch_addr + 4]; - ht216->bg_latch[5] = svga->vram[latch_addr + 5]; - ht216->bg_latch[6] = svga->vram[latch_addr + 6]; - ht216->bg_latch[7] = svga->vram[latch_addr + 7]; - + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | i]; return svga->vram[addr & svga->vram_mask]; } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); @@ -950,45 +1161,34 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) latch_addr = addr & ~7; if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) { offset = addr & 7; - - ht216->bg_latch[0] = svga->vram[latch_addr | offset]; - ht216->bg_latch[1] = svga->vram[latch_addr | ((offset + 1) & 7)]; - ht216->bg_latch[2] = svga->vram[latch_addr | ((offset + 2) & 7)]; - ht216->bg_latch[3] = svga->vram[latch_addr | ((offset + 3) & 7)]; - ht216->bg_latch[4] = svga->vram[latch_addr | ((offset + 4) & 7)]; - ht216->bg_latch[5] = svga->vram[latch_addr | ((offset + 5) & 7)]; - ht216->bg_latch[6] = svga->vram[latch_addr | ((offset + 6) & 7)]; - ht216->bg_latch[7] = svga->vram[latch_addr | ((offset + 7) & 7)]; + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | ((offset + i) & 7)]; } else { - ht216->bg_latch[0] = svga->vram[latch_addr]; - ht216->bg_latch[1] = svga->vram[latch_addr | 1]; - ht216->bg_latch[2] = svga->vram[latch_addr | 2]; - ht216->bg_latch[3] = svga->vram[latch_addr | 3]; - ht216->bg_latch[4] = svga->vram[latch_addr | 4]; - ht216->bg_latch[5] = svga->vram[latch_addr | 5]; - ht216->bg_latch[6] = svga->vram[latch_addr | 6]; - ht216->bg_latch[7] = svga->vram[latch_addr | 7]; + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | i]; } + or = addr & 4; svga->latch.d[0] = ht216->bg_latch[0 | or] | (ht216->bg_latch[1 | or] << 8) | (ht216->bg_latch[2 | or] << 16) | (ht216->bg_latch[3 | or] << 24); if (svga->readmode) { - temp = svga->latch.b[0]; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->latch.b[1]; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->latch.b[2]; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->latch.b[3]; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } + temp = 0xff; + + for (pixel = 0; pixel < 8; pixel++) { + for (plane = 0; plane < 4; plane++) { + if (svga->colournocare & (1 << plane)) { + /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ + if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) + temp &= ~(1 << pixel); + } + } + } - return svga->vram[addr | readplane]; + ret = temp; + } else + ret = svga->vram[addr | readplane]; + + return ret; } @@ -997,14 +1197,13 @@ ht216_read(uint32_t addr, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->read_bank[(addr >> 15) & 1]; - + addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; + return ht216_read_common(ht216, addr); } - static uint8_t ht216_read_linear(uint32_t addr, void *p) { @@ -1040,7 +1239,7 @@ void else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_isa); - svga_init(info, &ht216->svga, ht216, mem_size, + svga_init(info, svga, ht216, mem_size, ht216_recalctimings, ht216_in, ht216_out, ht216_hwcursor_draw, @@ -1050,19 +1249,24 @@ void svga->decode_mask = mem_size - 1; if (info->flags & DEVICE_VLB) { - mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &ht216->svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); } else { - mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, &ht216->svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); } - mem_mapping_set_p(&ht216->svga.mapping, ht216); + mem_mapping_set_p(&svga->mapping, ht216); + mem_mapping_disable(&ht216->linear_mapping); svga->bpp = 8; svga->miscout = 1; - ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ ht216->id = info->local; + + if (ht216->id == 0x7861) + ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ + + svga->adv_flags = 0; return ht216; } @@ -1094,7 +1298,6 @@ ht216_pb410a_init(const device_t *info) return ht216; } - static int g2_gc205_available(void) { @@ -1108,7 +1311,6 @@ v7_vga_1024i_available(void) return rom_present(BIOS_VIDEO7_VGA_1024I_PATH); } - void ht216_close(void *p) { @@ -1159,6 +1361,27 @@ static const device_config_t v7_vga_1024i_config[] = } }; +static const device_config_t ht216_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, + { + { + "512 kB", 512 + }, + { + "1 MB", 1024 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + const device_t g2_gc205_device = { "G2 GC205", @@ -1196,5 +1419,6 @@ const device_t ht216_32_pb410a_device = NULL, { NULL }, ht216_speed_changed, - ht216_force_redraw + ht216_force_redraw, + ht216_config };