static void write_crtc_data_other(Bitu port,Bitu val,Bitu iolen) { switch (vga.other.index) { case 0x00: //Horizontal total if (vga.other.htotal ^ val) VGA_StartResize(); vga.other.htotal=val; break; case 0x01: //Horizontal displayed chars if (vga.other.hdend ^ val) VGA_StartResize(); vga.other.hdend=val; break; case 0x02: //Horizontal sync position vga.other.hsyncp=val; break; case 0x03: //Horizontal sync width vga.other.hsyncw=val; break; case 0x04: //Vertical total if (vga.other.vtotal ^ val) VGA_StartResize(); vga.other.vtotal=val; break; case 0x05: //Vertical display adjust if (vga.other.vadjust ^ val) VGA_StartResize(); vga.other.vadjust=val; break; case 0x06: //Vertical rows if (vga.other.vdend ^ val) VGA_StartResize(); vga.other.vdend=val; break; case 0x07: //Vertical sync position vga.other.vsyncp=val; break; case 0x09: //Max scanline if (vga.other.max_scanline ^ val) VGA_StartResize(); vga.other.max_scanline=val; break; case 0x0A: /* Cursor Start Register */ vga.draw.cursor.sline = val&0x1f; vga.draw.cursor.enabled = ((val & 0x60) != 0x20); break; case 0x0B: /* Cursor End Register */ vga.draw.cursor.eline = val&0x1f; break; case 0x0C: /* Start Address High Register */ vga.config.display_start=(vga.config.display_start & 0x00FF) | (val << 8); break; case 0x0D: /* Start Address Low Register */ vga.config.display_start=(vga.config.display_start & 0xFF00) | val; break; case 0x0E: /*Cursor Location High Register */ vga.config.cursor_start&=0x00ff; vga.config.cursor_start|=val << 8; break; case 0x0F: /* Cursor Location Low Register */ vga.config.cursor_start&=0xff00; vga.config.cursor_start|=val; break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Write %X to illegal index %x",val,vga.other.index); } }
void write_p3c0(Bitu port,Bitu val,Bitu iolen) { if (!vga.internal.attrindex) { attr(index)=val & 0x1F; vga.internal.attrindex=true; attr(enabled)=val & 0x20; /* 0-4 Address of data register to write to port 3C0h or read from port 3C1h 5 If set screen output is enabled and the palette can not be modified, if clear screen output is disabled and the palette can be modified. */ return; } else { vga.internal.attrindex=false; switch (attr(index)) { /* Palette */ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: if (!attr(enabled)) VGA_ATTR_SetPalette(attr(index),val); /* 0-5 Index into the 256 color DAC table. May be modified by 3C0h index 10h and 14h. */ break; case 0x10: /* Mode Control Register */ if (!IS_VGA_ARCH) val&=0x1f; // not really correct, but should do it if ((attr(mode_control) ^ val) & 0x80) { attr(mode_control)^=0x80; for (Bitu i=0;i<0x10;i++) { VGA_ATTR_SetPalette(i,vga.attr.palette[i]); } } if ((attr(mode_control) ^ val) & 0x08) { VGA_SetBlinking(val & 0x8); } if ((attr(mode_control) ^ val) & 0x04) { attr(mode_control)=val; VGA_DetermineMode(); if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) VGA_StartResize(); } else { attr(mode_control)=val; VGA_DetermineMode(); } /* 0 Graphics mode if set, Alphanumeric mode else. 1 Monochrome mode if set, color mode else. 2 9-bit wide characters if set. The 9th bit of characters C0h-DFh will be the same as the 8th bit. Otherwise it will be the background color. 3 If set Attribute bit 7 is blinking, else high intensity. 5 If set the PEL panning register (3C0h index 13h) is temporarily set to 0 from when the line compare causes a wrap around until the next vertical retrace when the register is automatically reloaded with the old value, else the PEL panning register ignores line compares. 6 If set pixels are 8 bits wide. Used in 256 color modes. 7 If set bit 4-5 of the index into the DAC table are taken from port 3C0h index 14h bit 0-1, else the bits in the palette register are used. */ break; case 0x11: /* Overscan Color Register */ attr(overscan_color)=val; /* 0-5 Color of screen border. Color is defined as in the palette registers. */ break; case 0x12: /* Color Plane Enable Register */ /* Why disable colour planes? */ attr(color_plane_enable)=val; /* 0 Bit plane 0 is enabled if set. 1 Bit plane 1 is enabled if set. 2 Bit plane 2 is enabled if set. 3 Bit plane 3 is enabled if set. 4-5 Video Status MUX. Diagnostics use only. Two attribute bits appear on bits 4 and 5 of the Input Status Register 1 (3dAh). 0: Bit 2/0, 1: Bit 5/4, 2: bit 3/1, 3: bit 7/6 */ break; case 0x13: /* Horizontal PEL Panning Register */ attr(horizontal_pel_panning)=val & 0xF; switch (vga.mode) { case M_TEXT: if ((val==0x7) && (svgaCard==SVGA_None)) vga.config.pel_panning=7; if (val>0x7) vga.config.pel_panning=0; else vga.config.pel_panning=val+1; break; case M_VGA: case M_LIN8: vga.config.pel_panning=(val & 0x7)/2; break; case M_LIN16: default: vga.config.pel_panning=(val & 0x7); } /* 0-3 Indicates number of pixels to shift the display left Value 9bit textmode 256color mode Other modes 0 1 0 0 1 2 n/a 1 2 3 1 2 3 4 n/a 3 4 5 2 4 5 6 n/a 5 6 7 3 6 7 8 n/a 7 8 0 n/a n/a */ break; case 0x14: /* Color Select Register */ if (!IS_VGA_ARCH) { attr(color_select)=0; break; } if (attr(color_select) ^ val) { attr(color_select)=val; for (Bitu i=0;i<0x10;i++) { VGA_ATTR_SetPalette(i,vga.attr.palette[i]); } } /* 0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of the index into the DAC table. 2-3 These 2 bits are used as bit 6-7 of the index into the DAC table except in 256 color mode. Note: this register does not affect 256 color modes. */ break; default: if (svga.write_p3c0) { svga.write_p3c0(attr(index), val, iolen); break; } LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Write to unkown Index %2X",attr(index)); break; } } }
static void write_crtc_data_other(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { switch (vga.other.index) { case 0x00: //Horizontal total if (vga.other.htotal ^ val) VGA_StartResize(); vga.other.htotal=(Bit8u)val; break; case 0x01: //Horizontal displayed chars if (vga.other.hdend ^ val) VGA_StartResize(); vga.other.hdend=(Bit8u)val; break; case 0x02: //Horizontal sync position vga.other.hsyncp=(Bit8u)val; break; case 0x03: //Horizontal sync width if (machine==MCH_TANDY) vga.other.vsyncw=(Bit8u)(val >> 4); else vga.other.vsyncw = 16; // The MC6845 has a fixed v-sync width of 16 lines vga.other.hsyncw=(Bit8u)(val & 0xf); break; case 0x04: //Vertical total if (vga.other.vtotal ^ val) VGA_StartResize(); vga.other.vtotal=(Bit8u)val; break; case 0x05: //Vertical display adjust if (vga.other.vadjust ^ val) VGA_StartResize(); vga.other.vadjust=(Bit8u)val; break; case 0x06: //Vertical rows if (vga.other.vdend ^ val) VGA_StartResize(); vga.other.vdend=(Bit8u)val; break; case 0x07: //Vertical sync position vga.other.vsyncp=(Bit8u)val; break; case 0x09: //Max scanline val &= 0x1f; // VGADOC says bit 0-3 but the MC6845 datasheet says bit 0-4 if (vga.other.max_scanline ^ val) VGA_StartResize(); vga.other.max_scanline=(Bit8u)val; break; case 0x0A: /* Cursor Start Register */ vga.other.cursor_start = (Bit8u)(val & 0x3f); vga.draw.cursor.sline = (Bit8u)(val&0x1f); vga.draw.cursor.enabled = ((val & 0x60) != 0x20); break; case 0x0B: /* Cursor End Register */ vga.other.cursor_end = (Bit8u)(val&0x1f); vga.draw.cursor.eline = (Bit8u)(val&0x1f); break; case 0x0C: /* Start Address High Register */ vga.config.display_start=(vga.config.display_start & 0x00FF) | (val << 8); break; case 0x0D: /* Start Address Low Register */ vga.config.display_start=(vga.config.display_start & 0xFF00) | val; break; case 0x0E: /*Cursor Location High Register */ vga.config.cursor_start&=0x00ff; vga.config.cursor_start|=((Bit8u)val) << 8; break; case 0x0F: /* Cursor Location Low Register */ vga.config.cursor_start&=0xff00; vga.config.cursor_start|=(Bit8u)val; break; case 0x10: /* Light Pen High */ vga.other.lightpen &= 0xff; vga.other.lightpen |= (val & 0x3f)<<8; // only 6 bits break; case 0x11: /* Light Pen Low */ vga.other.lightpen &= 0xff00; vga.other.lightpen |= (Bit8u)val; break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Write %X to illegal index %x",val,vga.other.index); }
void SetClock_PVGA1A(Bitu which,Bitu target) { if (which < 4) { pvga1a.clockFreq[which]=1000*target; VGA_StartResize(); } }
void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) { // if((crtc(index)!=0xe)&&(crtc(index)!=0xf)) // LOG_MSG("CRTC w #%2x val %2x",crtc(index),val); switch(crtc(index)) { case 0x00: /* Horizontal Total Register */ if (crtc(read_only)) break; crtc(horizontal_total)=val; /* 0-7 Horizontal Total Character Clocks-5 */ break; case 0x01: /* Horizontal Display End Register */ if (crtc(read_only)) break; if (val != crtc(horizontal_display_end)) { crtc(horizontal_display_end)=val; VGA_StartResize(); } /* 0-7 Number of Character Clocks Displayed -1 */ break; case 0x02: /* Start Horizontal Blanking Register */ if (crtc(read_only)) break; crtc(start_horizontal_blanking)=val; /* 0-7 The count at which Horizontal Blanking starts */ break; case 0x03: /* End Horizontal Blanking Register */ if (crtc(read_only)) break; crtc(end_horizontal_blanking)=val; /* 0-4 Horizontal Blanking ends when the last 6 bits of the character counter equals this field. Bit 5 is at 3d4h index 5 bit 7. 5-6 Number of character clocks to delay start of display after Horizontal Total has been reached. 7 Access to Vertical Retrace registers if set. If clear reads to 3d4h index 10h and 11h access the Lightpen read back registers ?? */ break; case 0x04: /* Start Horizontal Retrace Register */ if (crtc(read_only)) break; crtc(start_horizontal_retrace)=val; /* 0-7 Horizontal Retrace starts when the Character Counter reaches this value. */ break; case 0x05: /* End Horizontal Retrace Register */ if (crtc(read_only)) break; crtc(end_horizontal_retrace)=val; /* 0-4 Horizontal Retrace ends when the last 5 bits of the character counter equals this value. 5-6 Number of character clocks to delay start of display after Horizontal Retrace. 7 bit 5 of the End Horizontal Blanking count (See 3d4h index 3 bit 0-4) */ break; case 0x06: /* Vertical Total Register */ if (crtc(read_only)) break; if (val != crtc(vertical_total)) { crtc(vertical_total)=val; VGA_StartResize(); } /* 0-7 Lower 8 bits of the Vertical Total. Bit 8 is found in 3d4h index 7 bit 0. Bit 9 is found in 3d4h index 7 bit 5. Note: For the VGA this value is the number of scan lines in the display -2. */ break; case 0x07: /* Overflow Register */ //Line compare bit ignores read only */ vga.config.line_compare=(vga.config.line_compare & 0x6ff) | (val & 0x10) << 4; if (crtc(read_only)) break; if ((vga.crtc.overflow ^ val) & 0xd6) { crtc(overflow)=val; VGA_StartResize(); } else crtc(overflow)=val; /* 0 Bit 8 of Vertical Total (3d4h index 6) 1 Bit 8 of Vertical Display End (3d4h index 12h) 2 Bit 8 of Vertical Retrace Start (3d4h index 10h) 3 Bit 8 of Start Vertical Blanking (3d4h index 15h) 4 Bit 8 of Line Compare Register (3d4h index 18h) 5 Bit 9 of Vertical Total (3d4h index 6) 6 Bit 9 of Vertical Display End (3d4h index 12h) 7 Bit 9 of Vertical Retrace Start (3d4h index 10h) */ break; case 0x08: /* Preset Row Scan Register */ crtc(preset_row_scan)=val; vga.config.hlines_skip=val&31; if (IS_VGA_ARCH) vga.config.bytes_skip=(val>>5)&3; else vga.config.bytes_skip=0; // LOG_DEBUG("Skip lines %d bytes %d",vga.config.hlines_skip,vga.config.bytes_skip); /* 0-4 Number of lines we have scrolled down in the first character row. Provides Smooth Vertical Scrolling.b 5-6 Number of bytes to skip at the start of scanline. Provides Smooth Horizontal Scrolling together with the Horizontal Panning Register (3C0h index 13h). */ break; case 0x09: /* Maximum Scan Line Register */ { if (IS_VGA_ARCH) { vga.config.line_compare &= 0x5ff; vga.config.line_compare |= (val&0x40)<<3; } else if(machine==MCH_EGA) { val &= 0x7f; // EGA ignores the doublescan bit } Bit8u old = crtc(maximum_scan_line); crtc(maximum_scan_line) = val; if(!vga.draw.doublescan_merging) { if ((old ^ val) & 0x20) VGA_StartResize(); vga.draw.address_line_total = (val &0x1F) + 1; if (val&0x80) vga.draw.address_line_total*=2; } else if ((old ^ val) & 0xbf) VGA_StartResize(); /* 0-4 Number of scan lines in a character row -1. In graphics modes this is the number of times (-1) the line is displayed before passing on to the next line (0: normal, 1: double, 2: triple...). This is independent of bit 7, except in CGA modes which seems to require this field to be 1 and bit 7 to be set to work. 5 Bit 9 of Start Vertical Blanking 6 Bit 9 of Line Compare Register 7 Doubles each scan line if set. I.e. displays 200 lines on a 400 display. */ break; } case 0x0A: /* Cursor Start Register */ crtc(cursor_start)=val; vga.draw.cursor.sline=val&0x1f; if (IS_VGA_ARCH) vga.draw.cursor.enabled=!(val&0x20); else vga.draw.cursor.enabled=true; /* 0-4 First scanline of cursor within character. 5 Turns Cursor off if set */ break; case 0x0B: /* Cursor End Register */ crtc(cursor_end)=val; vga.draw.cursor.eline=val&0x1f; vga.draw.cursor.delay=(val>>5)&0x3; /* 0-4 Last scanline of cursor within character 5-6 Delay of cursor data in character clocks. */ break; case 0x0C: /* Start Address High Register */ crtc(start_address_high)=val; vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8); /* 0-7 Upper 8 bits of the start address of the display buffer */ page_flip_debug_notify(); break; case 0x0D: /* Start Address Low Register */ crtc(start_address_low)=val; vga.config.display_start=(vga.config.display_start & 0xFFFF00)| val; /* 0-7 Lower 8 bits of the start address of the display buffer */ page_flip_debug_notify(); break; case 0x0E: /*Cursor Location High Register */ crtc(cursor_location_high)=val; vga.config.cursor_start&=0xff00ff; vga.config.cursor_start|=val << 8; /* 0-7 Upper 8 bits of the address of the cursor */ break; case 0x0F: /* Cursor Location Low Register */ //TODO update cursor on screen crtc(cursor_location_low)=val; vga.config.cursor_start&=0xffff00; vga.config.cursor_start|=val; /* 0-7 Lower 8 bits of the address of the cursor */ break; case 0x10: /* Vertical Retrace Start Register */ crtc(vertical_retrace_start)=val; /* 0-7 Lower 8 bits of Vertical Retrace Start. Vertical Retrace starts when the line counter reaches this value. Bit 8 is found in 3d4h index 7 bit 2. Bit 9 is found in 3d4h index 7 bit 7. */ break; case 0x11: /* Vertical Retrace End Register */ crtc(vertical_retrace_end)=val; if (IS_EGAVGA_ARCH && !(val & 0x10)) { vga.draw.vret_triggered=false; if (GCC_UNLIKELY(machine==MCH_EGA)) PIC_DeActivateIRQ(9); } if (IS_VGA_ARCH) crtc(read_only)=(val & 128)>0; else crtc(read_only)=false; /* 0-3 Vertical Retrace ends when the last 4 bits of the line counter equals this value. 4 if clear Clears pending Vertical Interrupts. 5 Vertical Interrupts (IRQ 2) disabled if set. Can usually be left disabled, but some systems (including PS/2) require it to be enabled. 6 If set selects 5 refresh cycles per scanline rather than 3. 7 Disables writing to registers 0-7 if set 3d4h index 7 bit 4 is not affected by this bit. */ break; case 0x12: /* Vertical Display End Register */ if (val!=crtc(vertical_display_end)) { if (abs((Bits)val-(Bits)crtc(vertical_display_end))<3) { // delay small vde changes a bit to avoid screen resizing // if they are reverted in a short timeframe PIC_RemoveEvents(VGA_SetupDrawing); vga.draw.resizing=false; crtc(vertical_display_end)=val; VGA_StartResize(150); } else { crtc(vertical_display_end)=val; VGA_StartResize(); } } /* 0-7 Lower 8 bits of Vertical Display End. The display ends when the line counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1. Bit 9 is found in 3d4h index 7 bit 6. */ break; case 0x13: /* Offset register */ crtc(offset)=val; vga.config.scan_len&=0x300; vga.config.scan_len|=val; VGA_CheckScanLength(); /* 0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for word mode and 8 for Double Word mode. */ break; case 0x14: /* Underline Location Register */ crtc(underline_location)=val; if (IS_VGA_ARCH) { //Byte,word,dword mode if ( crtc(underline_location) & 0x40 ) vga.config.addr_shift = 2; else if ( crtc( mode_control) & 0x40 ) vga.config.addr_shift = 0; else vga.config.addr_shift = 1; } else { vga.config.addr_shift = 1; } VGA_CheckScanLength(); /* 0-4 Position of underline within Character cell. 5 If set memory address is only changed every fourth character clock. 6 Double Word mode addressing if set */ break; case 0x15: /* Start Vertical Blank Register */ if (val!=crtc(start_vertical_blanking)) { crtc(start_vertical_blanking)=val; VGA_StartResize(); } /* 0-7 Lower 8 bits of Vertical Blank Start. Vertical blanking starts when the line counter reaches this value. Bit 8 is found in 3d4h index 7 bit 3. */ break; case 0x16: /* End Vertical Blank Register */ if (val!=crtc(end_vertical_blanking)) { crtc(end_vertical_blanking)=val; VGA_StartResize(); } /* 0-6 Vertical blanking stops when the lower 7 bits of the line counter equals this field. Some SVGA chips uses all 8 bits! IBM actually says bits 0-7. */ break; case 0x17: /* Mode Control Register */ crtc(mode_control)=val; vga.tandy.line_mask = (~val) & 3; //Byte,word,dword mode if ( crtc(underline_location) & 0x40 ) vga.config.addr_shift = 2; else if ( crtc( mode_control) & 0x40 ) vga.config.addr_shift = 0; else vga.config.addr_shift = 1; if ( vga.tandy.line_mask ) { vga.tandy.line_shift = 13; vga.tandy.addr_mask = (1 << 13) - 1; } else { vga.tandy.addr_mask = ~0; vga.tandy.line_shift = 0; } VGA_CheckScanLength(); //Should we really need to do a determinemode here? // VGA_DetermineMode(); /* 0 If clear use CGA compatible memory addressing system by substituting character row scan counter bit 0 for address bit 13, thus creating 2 banks for even and odd scan lines. 1 If clear use Hercules compatible memory addressing system by substituting character row scan counter bit 1 for address bit 14, thus creating 4 banks. 2 If set increase scan line counter only every second line. 3 If set increase memory address counter only every other character clock. 5 When in Word Mode bit 15 is rotated to bit 0 if this bit is set else bit 13 is rotated into bit 0. 6 If clear system is in word mode. Addresses are rotated 1 position up bringing either bit 13 or 15 into bit 0. 7 Clearing this bit will reset the display system until the bit is set again. */ break; case 0x18: /* Line Compare Register */ crtc(line_compare)=val; vga.config.line_compare=(vga.config.line_compare & 0x700) | val; /* 0-7 Lower 8 bits of the Line Compare. When the Line counter reaches this value, the display address wraps to 0. Provides Split Screen facilities. Bit 8 is found in 3d4h index 7 bit 4. Bit 9 is found in 3d4h index 9 bit 6. */ break; default: if (svga.write_p3d5) { svga.write_p3d5(crtc(index), val, iolen); } else { LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Write to unknown index %X",crtc(index)); } break; }