void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) { VGACommonState *s = opaque; int index; /* check port range access depending on color/monochrome mode */ if (vga_ioport_invalid(s, addr)) { return; } #ifdef DEBUG_VGA printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); #endif switch(addr) { case VGA_ATT_W: if (s->ar_flip_flop == 0) { val &= 0x3f; s->ar_index = val; } else { index = s->ar_index & 0x1f; switch(index) { case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF: s->ar[index] = val & 0x3f; break; case VGA_ATC_MODE: s->ar[index] = val & ~0x10; break; case VGA_ATC_OVERSCAN: s->ar[index] = val; break; case VGA_ATC_PLANE_ENABLE: s->ar[index] = val & ~0xc0; break; case VGA_ATC_PEL: s->ar[index] = val & ~0xf0; break; case VGA_ATC_COLOR_PAGE: s->ar[index] = val & ~0xf0; break; default: break; } } s->ar_flip_flop ^= 1; break; case VGA_MIS_W: s->msr = val & ~0x10; s->update_retrace_info(s); break; case VGA_SEQ_I: s->sr_index = val & 7; break; case VGA_SEQ_D: #ifdef DEBUG_VGA_REG printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); #endif s->sr[s->sr_index] = val & sr_mask[s->sr_index]; if (s->sr_index == VGA_SEQ_CLOCK_MODE) { s->update_retrace_info(s); } vga_update_memory_access(s); break; case VGA_PEL_IR: s->dac_read_index = val; s->dac_sub_index = 0; s->dac_state = 3; break; case VGA_PEL_IW: s->dac_write_index = val; s->dac_sub_index = 0; s->dac_state = 0; break; case VGA_PEL_D: s->dac_cache[s->dac_sub_index] = val; if (++s->dac_sub_index == 3) { memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); s->dac_sub_index = 0; s->dac_write_index++; } break; case VGA_GFX_I: s->gr_index = val & 0x0f; break; case VGA_GFX_D: #ifdef DEBUG_VGA_REG printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); #endif s->gr[s->gr_index] = val & gr_mask[s->gr_index]; vga_update_memory_access(s); break; case VGA_CRT_IM: case VGA_CRT_IC: s->cr_index = val; break; case VGA_CRT_DM: case VGA_CRT_DC: #ifdef DEBUG_VGA_REG printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); #endif /* handle CR0-7 protection */ if (s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) { if (s->cr_index <= VGA_CRTC_OVERFLOW) { /* can always write bit 4 of CR7 */ if (s->cr_index == VGA_CRTC_OVERFLOW) { s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | (val & 0x10); } return; } else if ((vga_cga_hacks & VGA_CGA_HACK_FONT_HEIGHT) && !(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { /* extra CGA compatibility hacks (not in standard VGA) */ if (s->cr_index == VGA_CRTC_MAX_SCAN && val == 7 && (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { return; } else if (s->cr_index == VGA_CRTC_CURSOR_START && val == 6 && (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { val = 0xd; } else if (s->cr_index == VGA_CRTC_CURSOR_END && val == 7 && (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { val = 0xe; } } } s->cr[s->cr_index] = val; switch(s->cr_index) { case VGA_CRTC_H_TOTAL: case VGA_CRTC_H_SYNC_START: case VGA_CRTC_H_SYNC_END: case VGA_CRTC_V_TOTAL: case VGA_CRTC_OVERFLOW: case VGA_CRTC_V_SYNC_END: case VGA_CRTC_MODE: s->update_retrace_info(s); break; } break; case VGA_IS1_RM: case VGA_IS1_RC: s->fcr = val & 0x10; break; } }