diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 01ea8db6..5fc6957c 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_draw.cpp,v 1.104 2008-12-28 20:22:12 c2woody Exp $ */ +/* $Id: vga_draw.cpp,v 1.105 2009-01-11 18:22:59 c2woody Exp $ */ #include #include @@ -373,6 +373,55 @@ skip_cursor: return TempLine; } +static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) { + Bits font_addr; + Bit32u * draw=(Bit32u *)TempLine; + const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; + + for (Bitu cx=0;cx> 7]; + else { + Bitu font=vga.draw.font_tables[0][chr*32+line]; + mask1=TXT_Font_Table[font>>4] & FontMask[attrib >> 7]; // blinking + mask2=TXT_Font_Table[font&0xf] & FontMask[attrib >> 7]; + } + *draw++=(fg&mask1) | (bg&~mask1); + *draw++=(fg&mask2) | (bg&~mask2); + } + } + if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; + font_addr = (vga.draw.cursor.address-vidstart) >> 1; + if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { + if (linevga.draw.cursor.eline) goto skip_cursor; + draw=(Bit32u *)&TempLine[font_addr*8]; + Bit32u att=TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]; + *draw++=att;*draw++=att; + } +skip_cursor: + return TempLine; +} + static Bit8u * VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) { Bits font_addr; Bit16u * draw=(Bit16u *)TempLine; @@ -987,8 +1036,8 @@ void VGA_SetupDrawing(Bitu /*val*/) { clock=((vga.tandy.mode_control & 1) ? 14318180 : (14318180/2))/8; break; case MCH_HERC: - if (vga.herc.mode_control & 0x2) clock=14318180/16; - else clock=14318180/8; + if (vga.herc.mode_control & 0x2) clock=16000000/16; + else clock=16000000/8; break; default: clock = 14318180; @@ -1245,16 +1294,22 @@ void VGA_SetupDrawing(Bitu /*val*/) { break; case M_TANDY_TEXT: doublewidth=(vga.tandy.mode_control & 0x1)==0; - case M_HERC_TEXT: aspect_ratio=1; - doubleheight=(vga.mode!=M_HERC_TEXT); + doubleheight=true; vga.draw.blocks=width; width<<=3; VGA_DrawLine=VGA_TEXT_Draw_Line; break; + case M_HERC_TEXT: + aspect_ratio=1; + vga.draw.blocks=width; + width<<=3; + VGA_DrawLine=VGA_TEXT_Herc_Draw_Line; + break; default: LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA mode %d while checking for resolution",vga.mode); - }; + break; + } VGA_CheckScanLength(); if (vga.draw.double_scan) { if (IS_VGA_ARCH) height/=2; diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 6e301705..4e68727d 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_misc.cpp,v 1.37 2008-06-03 18:35:32 c2woody Exp $ */ +/* $Id: vga_misc.cpp,v 1.38 2009-01-11 18:22:59 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -39,40 +39,46 @@ Bitu vga_read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; vga.tandy.pcjr_flipflop=false; - switch (machine) { - case MCH_HERC: - { - // 3BAh (R): Status Register - // bit 0 Horizontal sync - // 3 Video signal - // 7 Vertical sync - if(timeInFrame >= vga.draw.delay.vrstart && - timeInFrame <= vga.draw.delay.vrend) - retval |= 0x80; - double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); - if(timeInLine >= vga.draw.delay.hrstart && - timeInLine <= vga.draw.delay.hrend) - retval |= 1; - retval |= 0x10; //Hercules ident - break; - } - default: + if (machine!=MCH_HERC) { // 3DAh (R): Status Register // bit 0 Horizontal or Vertical blanking // 3 Vertical sync - if(timeInFrame >= vga.draw.delay.vrstart && + if (timeInFrame >= vga.draw.delay.vrstart && timeInFrame <= vga.draw.delay.vrend) retval |= 8; - if(timeInFrame >= vga.draw.delay.vdend) + if (timeInFrame >= vga.draw.delay.vdend) { retval |= 1; - else { + } else { double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); - if(timeInLine >= (vga.draw.delay.hblkstart) && - timeInLine <= vga.draw.delay.hblkend){ + if (timeInLine >= vga.draw.delay.hblkstart && + timeInLine <= vga.draw.delay.hblkend) { retval |= 1; } } + } else { + // 3BAh (R): Status Register + // bit 0 Horizontal sync + // 1 Light pen status (only some cards) + // 3 Video signal + // 4-6 000: Hercules + // 001: Hercules Plus + // 101: Hercules InColor + // 111: Unknown clone + // 7 Vertical sync inverted + + retval=0x72; // Hercules ident; from a working card (Winbond W86855AF) + // Another known working card has 0x76 ("KeysoGood", full-length) + if (timeInFrame < vga.draw.delay.vrstart || + timeInFrame > vga.draw.delay.vrend) retval |= 0x80; + + double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); + if (timeInLine >= vga.draw.delay.hrstart && + timeInLine <= vga.draw.delay.hrend) retval |= 0x1; + + // 688 Attack sub checks bit 3 - as a workaround have the bit enabled + // if no sync active (corresponds to a completely white screen) + if ((retval&0x81)==0x80) retval |= 0x8; } return retval; } diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp index 64c1d8ac..800827b0 100644 --- a/src/hardware/vga_other.cpp +++ b/src/hardware/vga_other.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_other.cpp,v 1.23 2008-08-06 18:32:35 c2woody Exp $ */ +/* $Id: vga_other.cpp,v 1.24 2009-01-11 18:22:59 c2woody Exp $ */ #include #include @@ -432,26 +432,40 @@ static void write_pcjr(Bitu port,Bitu val,Bitu iolen) { static void write_hercules(Bitu port,Bitu val,Bitu iolen) { switch (port) { - case 0x3b8: - if (vga.herc.enable_bits & 1 ) { - vga.herc.mode_control&=~0x2; - vga.herc.mode_control|=(val&0x2); - if (val & 0x2) { - VGA_SetMode(M_HERC_GFX); - } else { + case 0x3b8: { + // the protected bits can always be cleared but only be set if the + // protection bits are set + if (vga.herc.mode_control&0x2) { + // already set + if (!(val&0x2)) { + vga.herc.mode_control &= ~0x2; VGA_SetMode(M_HERC_TEXT); } + } else { + // not set, can only set if protection bit is set + if ((val & 0x2) && (vga.herc.enable_bits & 0x1)) { + vga.herc.mode_control |= 0x2; + VGA_SetMode(M_HERC_GFX); + } } - if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) { - vga.herc.mode_control^=0x80; + if (vga.herc.mode_control&0x80) { + if (!(val&0x80)) { + vga.herc.mode_control &= ~0x80; + vga.tandy.draw_base = &vga.mem.linear[0]; + } + } else { + if ((val & 0x80) && (vga.herc.enable_bits & 0x2)) { + vga.herc.mode_control |= 0x80; + vga.tandy.draw_base = &vga.mem.linear[32*1024]; + } } - vga.tandy.draw_base = &vga.mem.linear[(vga.herc.mode_control & 0x80 ) ? 32*1024 : 0]; + vga.draw.blinking = (val&0x20)!=0; + vga.herc.mode_control &= 0x82; + vga.herc.mode_control |= val & ~0x82; break; - case 0x3bf: - if ( vga.herc.enable_bits ^ val) { - vga.herc.enable_bits=val; - VGA_SetupHandlers(); } + case 0x3bf: + vga.herc.enable_bits=val; break; } } @@ -488,12 +502,6 @@ void VGA_SetupOther(void) { MAPPER_AddHandler(IncreaseHue,MK_f11,MMOD2,"inchue","Inc Hue"); MAPPER_AddHandler(DecreaseHue,MK_f11,0,"dechue","Dec Hue"); } - if (machine==MCH_HERC) { - vga.herc.enable_bits=0; - vga.herc.mode_control=0x8; - IO_RegisterWriteHandler(0x3b8,write_hercules,IO_MB); - IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); - } if (machine==MCH_TANDY) { write_tandy( 0x3df, 0x0, 0 ); IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB); @@ -509,6 +517,22 @@ void VGA_SetupOther(void) { IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); } + if (machine==MCH_HERC) { + Bitu base=0x3b0; + for (Bitu i = 0; i < 4; i++) { + // The registers are repeated as the address is not decoded properly; + // The official ports are 3b4, 3b5 + IO_RegisterWriteHandler(base+i*2,write_crtc_index_other,IO_MB); + IO_RegisterWriteHandler(base+i*2+1,write_crtc_data_other,IO_MB); + IO_RegisterReadHandler(base+i*2,read_crtc_index_other,IO_MB); + IO_RegisterReadHandler(base+i*2+1,read_crtc_data_other,IO_MB); + } + vga.herc.enable_bits=0; + vga.herc.mode_control=0xa; // first mode written will be text mode + vga.crtc.underline_location = 13; + IO_RegisterWriteHandler(0x3b8,write_hercules,IO_MB); + IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); + } if (machine==MCH_CGA) { Bitu base=0x3d0; for (Bitu port_ct=0; port_ct<4; port_ct++) { @@ -518,8 +542,8 @@ void VGA_SetupOther(void) { IO_RegisterReadHandler(base+port_ct*2+1,read_crtc_data_other,IO_MB); } } - if (machine==MCH_HERC || IS_TANDY_ARCH) { - Bitu base=machine==MCH_HERC ? 0x3b4 : 0x3d4; + if (IS_TANDY_ARCH) { + Bitu base=0x3d4; IO_RegisterWriteHandler(base,write_crtc_index_other,IO_MB); IO_RegisterWriteHandler(base+1,write_crtc_data_other,IO_MB); IO_RegisterReadHandler(base,read_crtc_index_other,IO_MB); diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index f86abf2f..9c32e424 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_modes.cpp,v 1.83 2009-01-02 19:30:53 c2woody Exp $ */ +/* $Id: int10_modes.cpp,v 1.84 2009-01-11 18:22:59 c2woody Exp $ */ #include @@ -368,13 +368,11 @@ static void FinishSetMode(bool clearmem) { real_writew( 0xb800,i*2,0x0000); } break; - case M_TEXT: - if (CurMode->mode==7) for (i=0;i<16*1024;i++) { - real_writew(0xb000,i*2,0x0120); - } else for (i=0;i<16*1024;i++) { - real_writew(0xb800,i*2,0x0720); - } + case M_TEXT: { + Bit16u seg = (CurMode->mode==7)?0xb000:0xb800; + for (i=0;i<16*1024;i++) real_writew(seg,i*2,0x0720); break; + } case M_EGA: case M_VGA: case M_LIN8: @@ -436,8 +434,7 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { case MCH_HERC: if (mode!=7) { //Just the text memory, most games seem to use any random mode to clear the screen - for (i=0;i<16*1024;i++) - real_writew(0xb000,i*2,0x0120); + for (i=0;i<16*1024;i++) real_writew(0xb000,i*2,0x0720); return false; } CurMode=&Hercules_Mode; @@ -504,12 +501,14 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { Bit8u mode_control,color_select; switch (machine) { case MCH_HERC: - IO_WriteB(0x3bf,0x3); //Enable changing all bits - IO_WriteB(0x3b8,0x8); //TEXT mode and non-blinking characters - IO_WriteB(0x3bf,0x0); + IO_WriteB(0x3b8,0x28); // TEXT mode and blinking characters + VGA_DAC_CombineColor(0,0); - for ( i = 1; i < 15;i++) - VGA_DAC_CombineColor(i,0xf); + VGA_DAC_CombineColor(8,0); + for ( i = 1; i < 8;i++) { + VGA_DAC_CombineColor(i,0x7); + VGA_DAC_CombineColor(i+8,0xf); + } break; case MCH_CGA: mode_control=mode_control_list[CurMode->mode]; diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 8a8fb976..395fdcac 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.cpp,v 1.95 2008-09-20 14:51:53 c2woody Exp $ */ +/* $Id: shell.cpp,v 1.96 2009-01-11 18:22:59 c2woody Exp $ */ #include #include @@ -297,14 +297,12 @@ void DOS_Shell::Run(void) { return; } /* Start a normal shell and check for a first command init */ - if(machine != MCH_HERC) { //Hide it for hercules as that looks too weird - WriteOut(MSG_Get("SHELL_STARTUP_BEGIN"),VERSION); + WriteOut(MSG_Get("SHELL_STARTUP_BEGIN"),VERSION); #if C_DEBUG - WriteOut(MSG_Get("SHELL_STARTUP_DEBUG")); + WriteOut(MSG_Get("SHELL_STARTUP_DEBUG")); #endif - if(machine == MCH_CGA) WriteOut(MSG_Get("SHELL_STARTUP_CGA")); - WriteOut(MSG_Get("SHELL_STARTUP_END")); - } + if (machine == MCH_CGA) WriteOut(MSG_Get("SHELL_STARTUP_CGA")); + WriteOut(MSG_Get("SHELL_STARTUP_END")); if (cmd->FindString("/INIT",line,true)) { strcpy(input_line,line.c_str()); diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 6842b258..1c659c38 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 The DOSBox Team + * Copyright (C) 2002-2009 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_cmds.cpp,v 1.84 2008-09-07 10:55:16 c2woody Exp $ */ +/* $Id: shell_cmds.cpp,v 1.85 2009-01-11 18:22:59 c2woody Exp $ */ #include "dosbox.h" #include "shell.h" @@ -167,7 +167,9 @@ void DOS_Shell::DoCommand(char * line) { void DOS_Shell::CMD_CLS(char * args) { HELP("CLS"); - reg_ax=0x0003; + // 3 is not good for hercules as it 'forgets' to reset the cursor position + if (machine==MCH_HERC) reg_ax=0x0007; + else reg_ax=0x0003; CALLBACK_RunRealInt(0x10); }