From e0d88e1d11f94c14872886fbe8648cc62231870f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Wed, 9 Jan 2008 20:34:51 +0000 Subject: [PATCH] additional svga chipset emulation (tseng, paradise) and small fixes for s3, vasyl Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3075 --- include/dosbox.h | 8 +- include/vga.h | 88 ++-- src/dosbox.cpp | 19 +- src/hardware/Makefile.am | 2 +- src/hardware/vga.cpp | 35 +- src/hardware/vga_attr.cpp | 10 +- src/hardware/vga_crtc.cpp | 21 +- src/hardware/vga_draw.cpp | 43 +- src/hardware/vga_gfx.cpp | 19 +- src/hardware/vga_memory.cpp | 66 ++- src/hardware/vga_paradise.cpp | 223 ++++++++++ src/hardware/vga_s3.cpp | 56 ++- src/hardware/vga_seq.cpp | 21 +- src/hardware/vga_tseng.cpp | 785 ++++++++++++++++++++++++++++++++++ src/ints/int10.cpp | 6 +- src/ints/int10_modes.cpp | 330 +++++++++----- visualc_net/dosbox.vcproj | 6 + 17 files changed, 1512 insertions(+), 226 deletions(-) create mode 100644 src/hardware/vga_paradise.cpp create mode 100644 src/hardware/vga_tseng.cpp diff --git a/include/dosbox.h b/include/dosbox.h index 19bde530..4f80bc87 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: dosbox.h,v 1.31 2008-01-09 20:34:21 c2woody Exp $ */ + #ifndef DOSBOX_DOSBOX_H #define DOSBOX_DOSBOX_H @@ -51,7 +53,9 @@ enum MachineType { enum SVGACards { SVGA_None, SVGA_S3Trio, - SVGA_TsengET4K + SVGA_TsengET4K, + SVGA_TsengET3K, + SVGA_ParadisePVGA1A }; extern SVGACards svgaCard; diff --git a/include/vga.h b/include/vga.h index 1d8faf84..a497b33a 100644 --- a/include/vga.h +++ b/include/vga.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: vga.h,v 1.37 2008-01-09 20:34:21 c2woody Exp $ */ + #ifndef DOSBOX_VGA_H #define DOSBOX_VGA_H @@ -157,23 +159,7 @@ typedef struct { Bit8u mc[64][64]; } VGA_HWCURSOR; -typedef union { - Bit32u fullbank; -#ifndef WORDS_BIGENDIAN - struct { - Bit16u lowerbank; - Bit16u bank; - } b; -#else - struct { - Bit16u bank; - Bit16u lowerbank; - } b; -#endif -} VGA_S3_BANK; - typedef struct { - VGA_S3_BANK svga_bank; Bit8u reg_lock1; Bit8u reg_lock2; Bit8u reg_31; @@ -330,6 +316,11 @@ typedef struct { typedef struct { Bitu readStart, writeStart; Bitu bankMask; + Bitu bank_read_full; + Bitu bank_write_full; + Bit8u bank_read; + Bit8u bank_write; + Bitu bank_size; } VGA_SVGA; typedef union { @@ -423,15 +414,64 @@ void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3); void VGA_ActivateHardwareCursor(void); void VGA_KillDrawing(void); -/* S3 Functions */ -Bitu SVGA_S3_GetClock(void); -void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen); -Bitu SVGA_S3_ReadCRTC(Bitu reg,Bitu iolen); -void SVGA_S3_WriteSEQ(Bitu reg,Bitu val,Bitu iolen); -Bitu SVGA_S3_ReadSEQ(Bitu reg,Bitu iolen); - extern VGA_Type vga; +/* Support for modular SVGA implementation */ +/* Video mode extra data to be passed to FinishSetMode_SVGA(). + This structure will be in flux until all drivers (including S3) + are properly separated. Right now it contains only three overflow + fields in S3 format and relies on drivers re-interpreting those. + For reference: + ver_overflow:X|line_comp10|X|vretrace10|X|vbstart10|vdispend10|vtotal10 + hor_overflow:X|X|X|hretrace8|X|hblank8|hdispend8|htotal8 + offset is not currently used by drivers (useful only for S3 itself) + It also contains basic int10 mode data - number, vtotal, htotal + */ +typedef struct { + Bit8u ver_overflow; + Bit8u hor_overflow; + Bitu offset; + Bitu modeNo; + Bitu htotal; + Bitu vtotal; +} VGA_ModeExtraData; + +// Vector function prototypes +typedef void (*tWritePort)(Bitu reg,Bitu val,Bitu iolen); +typedef Bitu (*tReadPort)(Bitu reg,Bitu iolen); +typedef void (*tFinishSetMode)(Bitu crtc_base, VGA_ModeExtraData* modeData); +typedef void (*tDetermineMode)(); +typedef void (*tSetClock)(Bitu which,Bitu target); +typedef Bitu (*tGetClock)(); +typedef bool (*tHWCursorActive)(); +typedef bool (*tAcceptsMode)(Bitu modeNo); + +struct SVGA_Driver { + tWritePort write_p3d5; + tReadPort read_p3d5; + tWritePort write_p3c5; + tReadPort read_p3c5; + tWritePort write_p3c0; + tReadPort read_p3c1; + tWritePort write_p3cf; + tReadPort read_p3cf; + + tFinishSetMode set_video_mode; + tDetermineMode determine_mode; + tSetClock set_clock; + tGetClock get_clock; + tHWCursorActive hardware_cursor_active; + tAcceptsMode accepts_mode; +}; + +extern SVGA_Driver svga; + +void SVGA_Setup_S3Trio(void); +void SVGA_Setup_TsengET4K(void); +void SVGA_Setup_TsengET3K(void); +void SVGA_Setup_ParadisePVGA1A(void); +void SVGA_Setup_Driver(void); + extern Bit32u ExpandTable[256]; extern Bit32u FillTable[16]; extern Bit32u CGA_2_Table[16]; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 1291e113..3c5cd29c 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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: dosbox.cpp,v 1.124 2007-12-13 12:38:13 qbix79 Exp $ */ +/* $Id: dosbox.cpp,v 1.125 2008-01-09 20:34:21 c2woody Exp $ */ #include #include @@ -269,13 +269,22 @@ static void DOSBOX_RealInit(Section * sec) { (strcasecmp(mtype,"svga")==0) || (strcasecmp(mtype,"svga_s3")==0)) { machine=MCH_VGA; svgaCard=SVGA_S3Trio; -/* } else if ((strcasecmp(mtype,"vga_et4000")==0) || (strcasecmp(mtype,"svga_et4000")==0)) { + } else if ((strcasecmp(mtype,"vga_et4000")==0) || (strcasecmp(mtype,"svga_et4000")==0)) { machine=MCH_VGA; - svgaCard=SVGA_TsengET4K; */ + svgaCard=SVGA_TsengET4K; + } else if ((strcasecmp(mtype,"vga_et3000")==0) || (strcasecmp(mtype,"svga_et3000")==0)) { + machine=MCH_VGA; + svgaCard=SVGA_TsengET3K; + } else if ((strcasecmp(mtype,"vga_pvga1a")==0) || (strcasecmp(mtype,"svga_pvga1a")==0) || + (strcasecmp(mtype,"svga_paradise")==0)) { + machine=MCH_VGA; + svgaCard=SVGA_ParadisePVGA1A; } else if (strcasecmp(mtype,"vgaonly")==0) { machine=MCH_VGA; svgaCard=SVGA_None; - } else LOG_MSG("DOSBOX:Unknown machine type %s",mtype); + } else { + LOG_MSG("DOSBOX:Unknown machine type %s",mtype); + } } diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index c733621c..7a9f7bf6 100644 --- a/src/hardware/Makefile.am +++ b/src/hardware/Makefile.am @@ -9,7 +9,7 @@ noinst_LIBRARIES = libhardware.a libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \ - vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp \ + vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \ cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index b60cece0..5a52b026 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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.cpp,v 1.31 2007-12-10 22:11:13 c2woody Exp $ */ +/* $Id: vga.cpp,v 1.32 2008-01-09 20:34:51 c2woody Exp $ */ #include "dosbox.h" //#include "setup.h" @@ -24,7 +24,10 @@ #include "pic.h" #include "vga.h" +#include + VGA_Type vga; +SVGA_Driver svga; Bit32u CGA_2_Table[16]; Bit32u CGA_4_Table[256]; @@ -48,6 +51,10 @@ void VGA_SetMode(VGAModes mode) { } void VGA_DetermineMode(void) { + if (svga.determine_mode) { + svga.determine_mode(); + return; + } /* Test for VGA output active or direct color modes */ switch (vga.s3.misc_control_2 >> 4) { case 0: @@ -84,6 +91,10 @@ void VGA_StartResize(void) { } void VGA_SetClock(Bitu which,Bitu target) { + if (svga.set_clock) { + svga.set_clock(which, target); + return; + } struct{ Bitu n,m; Bits err; @@ -158,6 +169,7 @@ void VGA_Init(Section* sec) { vga.screenflip = 0; vga.draw.resizing=false; vga.mode=M_ERROR; //For first init + SVGA_Setup_Driver(); VGA_SetupMemory(); VGA_SetupMisc(); VGA_SetupDAC(); @@ -220,3 +232,22 @@ void VGA_Init(Section* sec) { } } } + +void SVGA_Setup_Driver(void) { + memset(&svga, 0, sizeof(SVGA_Driver)); + + switch(svgaCard) { + case SVGA_S3Trio: + SVGA_Setup_S3Trio(); + break; + case SVGA_TsengET4K: + SVGA_Setup_TsengET4K(); + break; + case SVGA_TsengET3K: + SVGA_Setup_TsengET3K(); + break; + case SVGA_ParadisePVGA1A: + SVGA_Setup_ParadisePVGA1A(); + break; + } +} diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index 95c3c810..622d39a5 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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_attr.cpp,v 1.27 2007-12-23 16:00:53 c2woody Exp $ */ +/* $Id: vga_attr.cpp,v 1.28 2008-01-09 20:34:51 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -177,6 +177,10 @@ void write_p3c0(Bitu port,Bitu val,Bitu iolen) { */ 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; } @@ -203,6 +207,8 @@ Bitu read_p3c1(Bitu port,Bitu iolen) { case 0x14: /* Color Select Register */ return attr(color_select); default: + if (svga.read_p3c1) + return svga.read_p3c1(attr(index), iolen); LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Read from unkown Index %2X",attr(index)); } return 0; diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index c2e3e1b0..c35c2fe0 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: vga_crtc.cpp,v 1.30 2008-01-09 20:34:51 c2woody Exp $ */ + #include #include "dosbox.h" #include "inout.h" @@ -330,12 +332,10 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) { */ break; default: - switch (svgaCard) { - case SVGA_S3Trio: - SVGA_S3_WriteCRTC( crtc(index), val, iolen); - break; - default: - break; + 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; } @@ -395,10 +395,9 @@ Bitu vga_read_p3d5(Bitu port,Bitu iolen) { case 0x18: /* Line Compare Register */ return crtc(line_compare); default: - switch (svgaCard) { - case SVGA_S3Trio: - return SVGA_S3_ReadCRTC( crtc(index), iolen ); - default: + if (svga.read_p3d5) { + return svga.read_p3d5(crtc(index), iolen); + } else { LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Read from unknown index %X",crtc(index)); return 0x0; } diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 07106670..ed9b5de1 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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.90 2007-12-19 21:12:22 c2woody Exp $ */ +/* $Id: vga_draw.cpp,v 1.91 2008-01-09 20:34:51 c2woody Exp $ */ #include #include @@ -206,7 +206,11 @@ static Bit8u * VGA_Draw_Chain_Line(Bitu vidstart, Bitu line) { } static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu line) { - if(vga.s3.hgc.curmode & 0x1) { + bool hwcursor_active=false; + if (svga.hardware_cursor_active) { + if (svga.hardware_cursor_active()) hwcursor_active=true; + } + if (hwcursor_active) { Bitu lineat = (vidstart-(vga.config.real_start<<2)) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; @@ -266,7 +270,11 @@ static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu line) { } static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu line) { - if(vga.s3.hgc.curmode & 0x1) { + bool hwcursor_active=false; + if (svga.hardware_cursor_active) { + if (svga.hardware_cursor_active()) hwcursor_active=true; + } + if (hwcursor_active) { Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 1) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; @@ -329,7 +337,11 @@ static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu line) { } static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu line) { - if(vga.s3.hgc.curmode & 0x1) { + bool hwcursor_active=false; + if (svga.hardware_cursor_active) { + if (svga.hardware_cursor_active()) hwcursor_active=true; + } + if (hwcursor_active) { Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 2) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; @@ -881,7 +893,11 @@ void VGA_CheckScanLength(void) { } void VGA_ActivateHardwareCursor(void) { - if(vga.s3.hgc.curmode & 0x1) { + bool hwcursor_active=false; + if (svga.hardware_cursor_active) { + if (svga.hardware_cursor_active()) hwcursor_active=true; + } + if (hwcursor_active) { switch(vga.mode) { case M_LIN32: VGA_DrawLine=VGA_Draw_LIN32_Line_HWMouse; @@ -963,11 +979,9 @@ void VGA_SetupDrawing(Bitu val) { if ( !vbend) vbend = vbstart + 0x3f + 1; else vbend = vbstart + vbend; - switch (svgaCard) { - case SVGA_S3Trio: - clock = SVGA_S3_GetClock(); - break; - default: + if (svga.get_clock) { + clock = svga.get_clock(); + } else { switch ((vga.misc_output >> 2) & 3) { case 0: clock = 25175000; @@ -976,7 +990,6 @@ void VGA_SetupDrawing(Bitu val) { clock = 28322000; break; } - break; } /* Check for 8 for 9 character clock mode */ @@ -986,8 +999,6 @@ void VGA_SetupDrawing(Bitu val) { htotal*=2; } vga.draw.address_line_total=(vga.crtc.maximum_scan_line&0xf)+1; - /* Check for dual transfer whatever thing,master clock/2 */ - if (vga.s3.pll.cmd & 0x10) clock/=2; if (IS_VGA_ARCH) vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0; else vga.draw.double_scan=(vtotal==262); @@ -1150,7 +1161,7 @@ void VGA_SetupDrawing(Bitu val) { case M_LIN8: if (vga.crtc.mode_control & 0x8) width >>=1; - else if(!(vga.s3.reg_3a&0x10)) { + else if(svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) { doublewidth=true; width >>=1; } @@ -1166,7 +1177,7 @@ void VGA_SetupDrawing(Bitu val) { case M_LIN16: // 15/16 bpp modes double the horizontal values width<<=2; - if ((vga.crtc.mode_control & 0x8) || (vga.s3.pll.cmd & 0x10)) + if ((vga.crtc.mode_control & 0x8) || (svgaCard == SVGA_S3Trio && (vga.s3.pll.cmd & 0x10))) doublewidth = true; /* Use HW mouse cursor drawer if enabled */ VGA_ActivateHardwareCursor(); diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index 81d61f56..53055266 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: vga_gfx.cpp,v 1.18 2008-01-09 20:34:51 c2woody Exp $ */ + #include "dosbox.h" #include "inout.h" #include "vga.h" @@ -174,14 +176,16 @@ static void write_p3cf(Bitu port,Bitu val,Bitu iolen) { display memory. */ break; - case 9: /* Unknown */ - /* Crystal Dreams seems to like to write tothis register very weird */ - if (!index9warned) { + default: + if (svga.write_p3cf) { + svga.write_p3cf(gfx(index), val, iolen); + break; + } + if (gfx(index) == 9 && !index9warned) { LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index 9",val); index9warned=true; + break; } - break; - default: LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); break; } @@ -208,7 +212,10 @@ static Bitu read_p3cf(Bitu port,Bitu iolen) { case 8: /* Bit Mask Register */ return gfx(bit_mask); default: + if (svga.read_p3cf) + return svga.read_p3cf(gfx(index), iolen); LOG(LOG_VGAMISC,LOG_NORMAL)("Reading from illegal index %2X in port %4X",static_cast(gfx(index)),port); + break; } return 0; /* Compiler happy */ } diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 00f9fe98..fd9ab374 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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_memory.cpp,v 1.45 2007-12-10 22:11:13 c2woody Exp $ */ +/* $Id: vga_memory.cpp,v 1.46 2008-01-09 20:34:51 c2woody Exp $ */ #include #include @@ -132,16 +132,19 @@ public: public: Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return readHandler(addr); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -187,17 +190,20 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -206,16 +212,19 @@ public: } Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return readHandler(addr); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -263,17 +272,20 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -307,10 +319,12 @@ public: } Bitu readb(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; return readHandler( addr ); } Bitu readw(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; if (GCC_UNLIKELY(addr & 1)) return (readHandler( addr+0 ) << 0 ) | @@ -320,6 +334,7 @@ public: } Bitu readd(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_read_full; if (GCC_UNLIKELY(addr & 3)) return (readHandler( addr+0 ) << 0 ) | @@ -331,12 +346,14 @@ public: } void writeb(PhysPt addr, Bitu val ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); writeHandler( addr, val ); writeCache( addr, val ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); // MEM_CHANGED( addr + 1); if (GCC_UNLIKELY(addr & 1)) { @@ -349,6 +366,7 @@ public: } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); // MEM_CHANGED( addr + 3); if (GCC_UNLIKELY(addr & 3)) { @@ -381,20 +399,20 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 2 ); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -427,11 +445,11 @@ public: } HostPt GetHostReadPt(Bitu phys_page) { phys_page-=vgapages.base; - return &vga.mem.linear[vga.s3.svga_bank.fullbank+phys_page*4096]; + return &vga.mem.linear[vga.svga.bank_read_full+phys_page*4096]; } HostPt GetHostWritePt(Bitu phys_page) { phys_page-=vgapages.base; - return &vga.mem.linear[vga.s3.svga_bank.fullbank+phys_page*4096]; + return &vga.mem.linear[vga.svga.bank_write_full+phys_page*4096]; } }; @@ -442,34 +460,34 @@ public: } Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_read_full; return hostRead( &vga.mem.linear[addr] ); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_read_full; return hostRead( &vga.mem.linear[addr] ); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_read_full; return hostRead( &vga.mem.linear[addr] ); } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - addr += vga.s3.svga_bank.fullbank; + addr += vga.svga.bank_write_full; MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } @@ -481,20 +499,20 @@ public: flags=PFLAG_NOCODE; } void writeb(PhysPt addr,Bitu val) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); @@ -503,19 +521,19 @@ public: writeHandler(addr+3,(Bit8u)(val >> 24)); } Bitu readb(PhysPt addr) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); return readHandler(addr); } Bitu readw(PhysPt addr) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); } Bitu readd(PhysPt addr) { - addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); + addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); addr &= (128*1024-1); return (readHandler(addr+0) << 0) | @@ -687,6 +705,9 @@ void VGA_ChangedBank(void) { } void VGA_SetupHandlers(void) { + vga.svga.bank_read_full = vga.svga.bank_read*vga.svga.bank_size; + vga.svga.bank_write_full = vga.svga.bank_write*vga.svga.bank_size; + PageHandler *newHandler; switch (machine) { case MCH_CGA: @@ -803,7 +824,7 @@ void VGA_SetupHandlers(void) { MEM_ResetPageHandler( VGA_PAGE_B0, 8 ); break; } - if(vga.s3.ext_mem_ctrl & 0x10) + if(svgaCard == SVGA_S3Trio && (vga.s3.ext_mem_ctrl & 0x10)) MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); range_done: PAGING_ClearTLB(); @@ -828,7 +849,10 @@ void VGA_SetupMemory() { #ifdef VGA_KEEP_CHANGES memset( &vga.changes, 0, sizeof( vga.changes )); #endif - vga.s3.svga_bank.fullbank=0; + vga.svga.bank_read = vga.svga.bank_write = 0; + vga.svga.bank_read_full = vga.svga.bank_write_full = 0; + vga.svga.bank_size = 0x10000; /* most common bank size is 64K */ + if (machine==MCH_PCJR) { /* PCJr does not have dedicated graphics memory but uses conventional memory below 128k */ diff --git a/src/hardware/vga_paradise.cpp b/src/hardware/vga_paradise.cpp new file mode 100644 index 00000000..8a10c76e --- /dev/null +++ b/src/hardware/vga_paradise.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2002-2008 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: vga_paradise.cpp,v 1.1 2008-01-09 20:34:51 c2woody Exp $ */ + +#include "dosbox.h" +#include "setup.h" +#include "vga.h" +#include "inout.h" +#include "mem.h" + +typedef struct { + Bitu PR0A; + Bitu PR0B; + Bitu PR1; + Bitu PR2; + Bitu PR3; + Bitu PR4; + Bitu PR5; + + inline bool locked() { return (PR5&7)!=5; } + + Bitu clockFreq[4]; + Bitu biosMode; +} SVGA_PVGA1A_DATA; + +static SVGA_PVGA1A_DATA pvga1a = { 0, 0, 0, 0, 0, 0, 0 }; + + +static void bank_setup_pvga1a() { +// Note: There is some inconsistency in available documentation. Most sources tell that PVGA1A used +// only 7 bits of bank index (VGADOC and Ferraro agree on that) but also point that there are +// implementations with 1M of RAM which is simply not possible with 7-bit banks. This implementation +// assumes that the eighth bit was actually wired and could be used. This does not conflict with +// anything and actually works in WHATVGA just fine. + if (pvga1a.PR1 & 0x08) { + // TODO: Dual bank function is not supported yet + // TODO: Requirements are not compatible with vga_memory implementation. + } else { + // Single bank config is straightforward + vga.svga.bank_read = vga.svga.bank_write = pvga1a.PR0A; + vga.svga.bank_size = 4*1024; + VGA_SetupHandlers(); + } +} + +void write_p3cf_pvga1a(Bitu reg,Bitu val,Bitu iolen) { + if (pvga1a.locked() && reg >= 0x09 && reg <= 0x0e) + return; + + switch (reg) { + case 0x09: + // Bank A, 4K granularity, not using bit 7 + // Maps to A800h-AFFFh if PR1 bit 3 set and 64k config B000h-BFFFh if 128k config. A000h-AFFFh otherwise. + pvga1a.PR0A = val; + bank_setup_pvga1a(); + break; + case 0x0a: + // Bank B, 4K granularity, not using bit 7 + // Maps to A000h-A7FFh if PR1 bit 3 set and 64k config, A000h-AFFFh if 128k + pvga1a.PR0B = val; + bank_setup_pvga1a(); + break; + case 0x0b: + // Memory size. We only allow to mess with bit 3 here (enable bank B) - this may break some detection schemes + pvga1a.PR1 = (pvga1a.PR1 & ~0x08) | (val & 0x08); + bank_setup_pvga1a(); + break; + case 0x0c: + // Video configuration + // TODO: Figure out if there is anything worth implementing here. + pvga1a.PR2 = val; + break; + case 0x0d: + // CRT control. Bits 3-4 contain bits 16-17 of CRT start. + // TODO: Implement bit 2 (CRT address doubling - this mechanism is present in other chipsets as well, + // but not implemented in DosBox core) + pvga1a.PR3 = val; + vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x18)<<13); + vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x18)<<13); + break; + case 0x0e: + // Video control + // TODO: Figure out if there is anything worth implementing here. + pvga1a.PR4 = val; + break; + case 0x0f: + // Enable extended registers + pvga1a.PR5 = val; + break; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:GFX:PVGA1A:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3cf_pvga1a(Bitu reg,Bitu iolen) { + if (pvga1a.locked() && reg >= 0x09 && reg <= 0x0e) + return 0x0; + + switch (reg) { + case 0x09: + return pvga1a.PR0A; + case 0x0a: + return pvga1a.PR0B; + case 0x0b: + return pvga1a.PR1; + case 0x0c: + return pvga1a.PR2; + case 0x0d: + return pvga1a.PR3; + case 0x0e: + return pvga1a.PR4; + case 0x0f: + return pvga1a.PR5; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:GFX:PVGA1A:Read from illegal index %2X", reg); + break; + } + + return 0x0; +} + +void FinishSetMode_PVGA1A(Bitu /*crtc_base*/, VGA_ModeExtraData* modeData) { + pvga1a.biosMode = modeData->modeNo; + +// Reset to single bank and set it to 0. May need to unlock first (DPaint locks on exit) + IO_Write(0x3ce, 0x0f); + Bitu oldlock = IO_Read(0x3cf); + IO_Write(0x3cf, 0x05); + IO_Write(0x3ce, 0x09); + IO_Write(0x3cf, 0x00); + IO_Write(0x3ce, 0x0a); + IO_Write(0x3cf, 0x00); + IO_Write(0x3ce, 0x0b); + Bit8u val = IO_Read(0x3cf); + IO_Write(0x3cf, val & ~0x08); + IO_Write(0x3ce, 0x0c); + IO_Write(0x3cf, 0x00); + IO_Write(0x3ce, 0x0d); + IO_Write(0x3cf, 0x00); + IO_Write(0x3ce, 0x0e); + IO_Write(0x3cf, 0x00); + IO_Write(0x3ce, 0x0f); + IO_Write(0x3cf, oldlock); + + if (svga.determine_mode) + svga.determine_mode(); + + if (vga.mode != M_VGA) + vga.config.compatible_chain4 = false; // in process of verification + else + vga.config.compatible_chain4 = true; + + VGA_SetupHandlers(); +} + +void DetermineMode_PVGA1A() { + // Close replica from the base implementation. It will stay here + // until I figure a way to either distinguish M_VGA and M_LIN8 or + // merge them. + if (vga.attr.mode_control & 1) { + if (vga.gfx.mode & 0x40) VGA_SetMode((pvga1a.biosMode<=0x13)?M_VGA:M_LIN8); + else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); + else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); + else VGA_SetMode((pvga1a.biosMode<=0x13)?M_EGA:M_LIN4); + } else { + VGA_SetMode(M_TEXT); + } +} + +void SetClock_PVGA1A(Bitu which,Bitu target) { + if (which < 4) { + pvga1a.clockFreq[which]=1000*target; + VGA_StartResize(); + } +} + +Bitu GetClock_PVGA1A() { + return pvga1a.clockFreq[(vga.misc_output >> 2) & 3]; +} + +void SVGA_Setup_ParadisePVGA1A(void) { + svga.write_p3cf = &write_p3cf_pvga1a; + svga.read_p3cf = &read_p3cf_pvga1a; + + svga.set_video_mode = &FinishSetMode_PVGA1A; + svga.determine_mode = &DetermineMode_PVGA1A; + svga.set_clock = &SetClock_PVGA1A; + svga.get_clock = &GetClock_PVGA1A; + + VGA_SetClock(0,CLK_25); + VGA_SetClock(1,CLK_28); + VGA_SetClock(2,32400); // could not find documentation + VGA_SetClock(3,35900); + + // Set memory size at 512K (standard for PVGA1A) + pvga1a.PR1 = 2<<6; + + // Paradise ROM signature + PhysPt rom_base=PhysMake(0xc000,0); + phys_writeb(rom_base+0x007d,'V'); + phys_writeb(rom_base+0x007e,'G'); + phys_writeb(rom_base+0x007f,'A'); + phys_writeb(rom_base+0x0080,'='); + + IO_Write(0x3cf, 0x05); // Enable! +} diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp index 9bf965ed..2f5484e6 100644 --- a/src/hardware/vga_s3.cpp +++ b/src/hardware/vga_s3.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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_s3.cpp,v 1.10 2007-12-27 10:57:51 c2woody Exp $ */ +/* $Id: vga_s3.cpp,v 1.11 2008-01-09 20:34:51 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -28,6 +28,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { //TODO Base address vga.s3.reg_31 = val; vga.config.compatible_chain4 = !(val&0x08); + vga.config.display_start = (vga.config.display_start&~0x30000)|((val&0x30)<<12); VGA_DetermineMode(); VGA_SetupHandlers(); break; @@ -48,9 +49,10 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { case 0x35: /* CR35 CRT Register Lock */ if (vga.s3.reg_lock1 != 0x48) return; //Needed for uvconfig detection vga.s3.reg_35=val & 0xf0; - if ((vga.s3.svga_bank.b.bank & 0xf) ^ (val & 0xf)) { - vga.s3.svga_bank.b.bank&=0xf0; - vga.s3.svga_bank.b.bank|=val & 0xf; + if ((vga.svga.bank_read & 0xf) ^ (val & 0xf)) { + vga.svga.bank_read&=0xf0; + vga.svga.bank_read|=val & 0xf; + vga.svga.bank_write = vga.svga.bank_read; VGA_SetupHandlers(); } break; @@ -138,12 +140,12 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { break; case 0x51: /* Extended System Control 2 */ vga.s3.reg_51=val & 0xc0; //Only store bits 6,7 - //TODO Display start - vga.config.display_start&=0xFCFFFF; - vga.config.display_start|=(val & 3) << 16; - if ((vga.s3.svga_bank.b.bank&0xcf) ^ ((val&0xc)<<2)) { - vga.s3.svga_bank.b.bank&=0xcf; - vga.s3.svga_bank.b.bank|=(val&0xc)<<2; + vga.config.display_start&=0xF3FFFF; + vga.config.display_start|=(val & 3) << 18; + if ((vga.svga.bank_read&0x30) ^ ((val&0xc)<<2)) { + vga.svga.bank_read&=0xcf; + vga.svga.bank_read|=(val&0xc)<<2; + vga.svga.bank_write = vga.svga.bank_read; VGA_SetupHandlers(); } if (((val & 0x30) ^ (vga.config.scan_len >> 4)) & 0x30) { @@ -310,7 +312,8 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { } break; case 0x6a: /* Extended System Control 4 */ - vga.s3.svga_bank.b.bank=val & 0x3f; + vga.svga.bank_read=val & 0x3f; + vga.svga.bank_write = vga.svga.bank_read; VGA_SetupHandlers(); break; case 0x6b: // BIOS scratchpad: LFB adress @@ -340,7 +343,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { //TODO mix in bits from baseaddress; return vga.s3.reg_31; case 0x35: /* CR35 CRT Register Lock */ - return vga.s3.reg_35|(vga.s3.svga_bank.b.bank & 0xf); + return vga.s3.reg_35|(vga.svga.bank_read & 0xf); case 0x36: /* CR36 Reset State Read 1 */ return 0x92; /* PCI version */ //2 Mb PCI and some bios settings @@ -349,7 +352,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { case 0x38: /* CR38 Register Lock 1 */ return vga.s3.reg_lock1; case 0x39: /* CR39 Register Lock 2 */ - return vga.s3.reg_lock2; + return vga.s3.reg_lock2; case 0x3a: return vga.s3.reg_3a; case 0x40: /* CR40 system config */ @@ -376,7 +379,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { return vga.s3.reg_50; case 0x51: /* Extended System Control 2 */ return ((vga.config.display_start >> 16) & 3 ) | - ((vga.s3.svga_bank.b.bank & 0x30) >> 2) | + ((vga.svga.bank_read & 0x30) >> 2) | ((vga.config.scan_len & 0x300) >> 4) | vga.s3.reg_51; case 0x52: // CR52 Extended BIOS flags 1 @@ -400,7 +403,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { case 0x69: /* Extended System Control 3 */ return (Bit8u)((vga.config.display_start & 0x1f0000)>>16); case 0x6a: /* Extended System Control 4 */ - return (Bit8u)(vga.s3.svga_bank.b.bank & 0x3f); + return (Bit8u)(vga.svga.bank_read & 0x3f); case 0x6b: // BIOS scatchpad: LFB address return vga.s3.reg_6b; default: @@ -471,6 +474,27 @@ Bitu SVGA_S3_GetClock(void) { clock = 28322000; else clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); + /* Check for dual transfer, master clock/2 */ + if (vga.s3.pll.cmd & 0x10) clock/=2; return clock; } +bool SVGA_S3_HWCursorActive(void) { + return (vga.s3.hgc.curmode & 0x1) != 0; +} + +void SVGA_Setup_S3Trio(void) { + svga.write_p3d5 = &SVGA_S3_WriteCRTC; + svga.read_p3d5 = &SVGA_S3_ReadCRTC; + svga.write_p3c5 = &SVGA_S3_WriteSEQ; + svga.read_p3c5 = &SVGA_S3_ReadSEQ; + svga.write_p3c0 = 0; /* no S3-specific functionality */ + svga.read_p3c1 = 0; /* no S3-specific functionality */ + + svga.set_video_mode = 0; /* implemented in core */ + svga.determine_mode = 0; /* implemented in core */ + svga.set_clock = 0; /* implemented in core */ + svga.get_clock = &SVGA_S3_GetClock; + svga.hardware_cursor_active = &SVGA_S3_HWCursorActive; + svga.accepts_mode = 0; /* don't filter modes */ +} diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 8e979ede..130025c4 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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_seq.cpp,v 1.21 2007-12-23 16:00:53 c2woody Exp $ */ +/* $Id: vga_seq.cpp,v 1.22 2008-01-09 20:34:51 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -109,13 +109,12 @@ void write_p3c5(Bitu port,Bitu val,Bitu iolen) { } break; default: - switch (svgaCard) { - case SVGA_S3Trio: - SVGA_S3_WriteSEQ( seq(index), val, iolen ); - break; - default: + if (svga.write_p3c5) { + svga.write_p3c5(seq(index), val, iolen); + } else { LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Write to illegal index %2X",seq(index)); } + break; } } @@ -137,11 +136,11 @@ Bitu read_p3c5(Bitu port,Bitu iolen) { break; case 4: /* Memory Mode */ return seq(memory_mode); + break; default: - switch (svgaCard) { - case SVGA_S3Trio: - return SVGA_S3_ReadSEQ( seq(index), iolen ); - } + if (svga.read_p3c5) + return svga.read_p3c5(seq(index), iolen); + break; } return 0; } diff --git a/src/hardware/vga_tseng.cpp b/src/hardware/vga_tseng.cpp new file mode 100644 index 00000000..3dadc70f --- /dev/null +++ b/src/hardware/vga_tseng.cpp @@ -0,0 +1,785 @@ +/* + * Copyright (C) 2002-2008 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: vga_tseng.cpp,v 1.1 2008-01-09 20:34:51 c2woody Exp $ */ + +#include "dosbox.h" +#include "setup.h" +#include "vga.h" +#include "inout.h" +#include "mem.h" + +// Tseng ET4K data +typedef struct { + Bit8u extensionsEnabled; + +// Stored exact values of some registers. Documentation only specifies some bits but hardware checks may +// expect other bits to be preserved. + Bitu store_3d4_31; + Bitu store_3d4_32; + Bitu store_3d4_33; + Bitu store_3d4_34; + Bitu store_3d4_35; + Bitu store_3d4_36; + Bitu store_3d4_37; + Bitu store_3d4_3f; + + Bitu store_3c0_16; + Bitu store_3c0_17; + + Bitu store_3c4_06; + Bitu store_3c4_07; + + Bitu clockFreq[16]; + Bitu biosMode; +} SVGA_ET4K_DATA; + +static SVGA_ET4K_DATA et4k = { 1, 0, /* the rest are 0s */ }; + +#define STORE_ET4K(port, index) \ + case 0x##index: \ + et4k.store_##port##_##index = val; \ + break; + +#define RESTORE_ET4K(port, index) \ + case 0x##index: \ + return et4k.store_##port##_##index; + +// Tseng ET4K implementation +void write_p3d5_et4k(Bitu reg,Bitu val,Bitu iolen) { + if(!et4k.extensionsEnabled && reg!=0x33) + return; + + switch(reg) { + /* + 3d4h index 31h (R/W): General Purpose + bit 0-3 Scratch pad + 6-7 Clock Select bits 3-4. Bits 0-1 are in 3C2h/3CCh bits 2-3. + */ + STORE_ET4K(3d4, 31); + + // 3d4h index 32h - RAS/CAS Configuration (R/W) + // No effect on emulation. Should not be written by software. + STORE_ET4K(3d4, 32); + + case 0x33: + // 3d4 index 33h (R/W): Extended start Address + // 0-1 Display Start Address bits 16-17 + // 2-3 Cursor start address bits 16-17 + // Used by standard Tseng ID scheme + et4k.store_3d4_33 = val; + vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x03)<<16); + vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x0c)<<14); + break; + + /* + 3d4h index 34h (R/W): 6845 Compatibility Control Register + bit 0 Enable CS0 (alternate clock timing) + 1 Clock Select bit 2. Bits 0-1 in 3C2h bits 2-3, bits 3-4 are in 3d4h + index 31h bits 6-7 + 2 Tristate ET4000 bus and color outputs if set + 3 Video Subsystem Enable Register at 46E8h if set, at 3C3h if clear. + 4 Enable Translation ROM for reading CRTC and MISCOUT if set + 5 Enable Translation ROM for writing CRTC and MISCOUT if set + 6 Enable double scan in AT&T compatibility mode if set + 7 Enable 6845 compatibility if set + */ + // TODO: Bit 6 may have effect on emulation + STORE_ET4K(3d4, 34); + + case 0x35: + /* + 3d4h index 35h (R/W): Overflow High + bit 0 Vertical Blank Start Bit 10 (3d4h index 15h). + 1 Vertical Total Bit 10 (3d4h index 6). + 2 Vertical Display End Bit 10 (3d4h index 12h). + 3 Vertical Sync Start Bit 10 (3d4h index 10h). + 4 Line Compare Bit 10 (3d4h index 18h). + 5 Gen-Lock Enabled if set (External sync) + 6 (4000) Read/Modify/Write Enabled if set. Currently not implemented. + 7 Vertical interlace if set. The Vertical timing registers are + programmed as if the mode was non-interlaced!! + */ + et4k.store_3d4_35 = val; + vga.config.line_compare = (vga.config.line_compare & 0x3ff) | ((val&0x10)<<6); + // Abusing s3 ex_ver_overflow field. This is to be cleaned up later. + { + Bit8u s3val = + ((val & 0x01) << 2) | // vbstart + ((val & 0x02) >> 1) | // vtotal + ((val & 0x04) >> 1) | // vdispend + ((val & 0x08) << 1) | // vsyncstart (?) + ((val & 0x10) << 2); // linecomp + if ((s3val ^ vga.s3.ex_ver_overflow) & 0x3) { + vga.s3.ex_ver_overflow=s3val; + VGA_StartResize(); + } else vga.s3.ex_ver_overflow=s3val; + } + break; + + // 3d4h index 36h - Video System Configuration 1 (R/W) + // VGADOC provides a lot of info on this register, Ferraro has significantly less detail. + // This is unlikely to be used by any games. Bit 4 switches chipset into linear mode - + // that may be useful in some cases if there is any software actually using it. + // TODO (not near future): support linear addressing + STORE_ET4K(3d4, 36); + + // 3d4h index 37 - Video System Configuration 2 (R/W) + // Bits 0,1, and 3 provides information about memory size: + // 0-1 Bus width (1: 8 bit, 2: 16 bit, 3: 32 bit) + // 3 Size of RAM chips (0: 64Kx, 1: 256Kx) + // Other bits have no effect on emulation. + case 0x37: + if (val != et4k.store_3d4_37) { + et4k.store_3d4_37 = val; + VGA_SetupHandlers(); + } + break; + + case 0x3f: + /* + 3d4h index 3Fh (R/W): + bit 0 Bit 8 of the Horizontal Total (3d4h index 0) + 2 Bit 8 of the Horizontal Blank Start (3d4h index 3) + 4 Bit 8 of the Horizontal Retrace Start (3d4h index 4) + 7 Bit 8 of the CRTC offset register (3d4h index 13h). + */ + // The only unimplemented one is bit 7 + et4k.store_3d4_3f = val; + // Abusing s3 ex_hor_overflow field which very similar. This is + // to be cleaned up later + if ((val ^ vga.s3.ex_hor_overflow) & 3) { + vga.s3.ex_hor_overflow=(val&0x15); + VGA_StartResize(); + } else vga.s3.ex_hor_overflow=(val&0x15); + break; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET4K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3d5_et4k(Bitu reg,Bitu iolen) { + if (!et4k.extensionsEnabled && reg!=0x33) + return 0x0; + switch(reg) { + RESTORE_ET4K(3d4, 31); + RESTORE_ET4K(3d4, 32); + RESTORE_ET4K(3d4, 33); + RESTORE_ET4K(3d4, 34); + RESTORE_ET4K(3d4, 35); + RESTORE_ET4K(3d4, 36); + RESTORE_ET4K(3d4, 37); + RESTORE_ET4K(3d4, 3f); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET4K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +void write_p3c5_et4k(Bitu reg,Bitu val,Bitu iolen) { + switch(reg) { + /* + 3C4h index 6 (R/W): TS State Control + bit 1-2 Font Width Select in dots/character + If 3C4h index 4 bit 0 clear: + 0: 9 dots, 1: 10 dots, 2: 12 dots, 3: 6 dots + If 3C4h index 5 bit 0 set: + 0: 8 dots, 1: 11 dots, 2: 7 dots, 3: 16 dots + Only valid if 3d4h index 34h bit 3 set. + */ + // TODO: Figure out if this has any practical use + STORE_ET4K(3c4, 06); + // 3C4h index 7 (R/W): TS Auxiliary Mode + // Unlikely to be used by games (things like ROM enable/disable and emulation of VGA vs EGA) + STORE_ET4K(3c4, 07); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET4K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3c5_et4k(Bitu reg,Bitu iolen) { + switch(reg) { + RESTORE_ET4K(3c4, 06); + RESTORE_ET4K(3c4, 07); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET4K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +/* +3CDh (R/W): Segment Select +bit 0-3 64k Write bank number (0..15) + 4-7 64k Read bank number (0..15) +*/ +void write_p3cd_et4k(Bitu port,Bitu val,Bitu iolen) { + vga.svga.bank_write = val & 0x0f; + vga.svga.bank_read = (val>>4) & 0x0f; + VGA_SetupHandlers(); +} + +Bitu read_p3cd_et4k(Bitu port,Bitu iolen) { + return (vga.svga.bank_read<<4)|vga.svga.bank_write; +} + +void write_p3c0_et4k(Bitu reg,Bitu val,Bitu iolen) { + switch(reg) { + // 3c0 index 16h: ATC Miscellaneous + // VGADOC provides a lot of information, Ferarro documents only two bits + // and even those incompletely. The register is used as part of identification + // scheme. + // Unlikely to be used by any games but double timing may be useful. + // TODO: Figure out if this has any practical use + STORE_ET4K(3c0, 16); + /* + 3C0h index 17h (R/W): Miscellaneous 1 + bit 7 If set protects the internal palette ram and redefines the attribute + bits as follows: + Monochrome: + bit 0-2 Select font 0-7 + 3 If set selects blinking + 4 If set selects underline + 5 If set prevents the character from being displayed + 6 If set displays the character at half intensity + 7 If set selects reverse video + Color: + bit 0-1 Selects font 0-3 + 2 Foreground Blue + 3 Foreground Green + 4 Foreground Red + 5 Background Blue + 6 Background Green + 7 Background Red + */ + // TODO: Figure out if this has any practical use + STORE_ET4K(3c0, 17); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET4K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3c1_et4k(Bitu reg,Bitu iolen) { + switch(reg) { + RESTORE_ET4K(3c0, 16); + RESTORE_ET4K(3c0, 17); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET4K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +/* +These ports are used but have little if any effect on emulation: + 3BFh (R/W): Hercules Compatibility Mode + 3CBh (R/W): PEL Address/Data Wd + 3CEh index 0Dh (R/W): Microsequencer Mode + 3CEh index 0Eh (R/W): Microsequencer Reset + 3d8h (R/W): Display Mode Control + 3DEh (W); AT&T Mode Control Register +*/ + +static Bitu get_clock_index_et4k() { + // Ignoring bit 4, using "only" 16 frequencies. Looks like most implementations had only that + return ((vga.misc_output>>2)&3) | ((et4k.store_3d4_34<<1)&4) | ((et4k.store_3d4_31>>3)&8); +} + +static void set_clock_index_et4k(Bitu index) { + // Shortwiring register reads/writes for simplicity + IO_Write(0x3c2, (vga.misc_output&~0x0c)|((index&3)<<2)); + et4k.store_3d4_34 = (et4k.store_3d4_34&~0x02)|((index&4)>>1); + et4k.store_3d4_31 = (et4k.store_3d4_31&~0xc0)|((index&8)<<3); // (index&0x18) if 32 clock frequencies are to be supported +} + +void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) { + et4k.biosMode = modeData->modeNo; + + IO_Write(0x3cd, 0x00); // both banks to 0 + + // Reinterpret hor_overflow. Curiously, three bits out of four are + // in the same places. Input has hdispend (not supported), output + // has CRTC offset (also not supported) + Bit8u et4k_hor_overflow = + (modeData->hor_overflow & 0x01) | + (modeData->hor_overflow & 0x04) | + (modeData->hor_overflow & 0x10); + IO_Write(crtc_base,0x3f);IO_Write(crtc_base+1,et4k_hor_overflow); + + // Reinterpret ver_overflow + Bit8u et4k_ver_overflow = + ((modeData->ver_overflow & 0x01) << 1) | // vtotal10 + ((modeData->ver_overflow & 0x02) << 1) | // vdispend10 + ((modeData->ver_overflow & 0x04) >> 2) | // vbstart10 + ((modeData->ver_overflow & 0x10) >> 1) | // vretrace10 (tseng has vsync start?) + ((modeData->ver_overflow & 0x40) >> 2); // line_compare + IO_Write(crtc_base,0x35);IO_Write(crtc_base+1,et4k_ver_overflow); + + // Clear remaining ext CRTC registers + IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x32);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x33);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x34);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x36);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0f); // 1M video ram (0x0e for 512K, 0x0d for 256K) + // Clear ext SEQ + IO_Write(0x3c4,0x06);IO_Write(0x3c5,0); + IO_Write(0x3c4,0x07);IO_Write(0x3c5,0); + // Clear ext ATTR + IO_Write(0x3c0,0x16);IO_Write(0x3c0,0); + IO_Write(0x3c0,0x17);IO_Write(0x3c0,0); + + // Select SVGA clock to get close to 60Hz (not particularly clean implementation) + if (modeData->modeNo > 0x13) { + Bitu target = modeData->vtotal*8*modeData->htotal*60; + Bitu best = 1; + Bits dist = 100000000; + for (Bitu i=0; i<16; i++) { + if (abs(target-et4k.clockFreq[i]) < dist) { + best = i; + dist = abs(target-et4k.clockFreq[i]); + } + } + set_clock_index_et4k(best); + } + + if(svga.determine_mode) + svga.determine_mode(); + + // Verified (on real hardware and in a few games): Tseng ET4000 used chain4 implementation + // different from standard VGA. It was also not limited to 64K in regular mode 13h. + vga.config.compatible_chain4 = false; + + VGA_SetupHandlers(); +} + +void DetermineMode_ET4K() { + // Close replica from the base implementation. It will stay here + // until I figure a way to either distinguish M_VGA and M_LIN8 or + // merge them. + if (vga.attr.mode_control & 1) { + if (vga.gfx.mode & 0x40) VGA_SetMode((et4k.biosMode<=0x13)?M_VGA:M_LIN8); // Ugly... + else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); + else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); + else VGA_SetMode((et4k.biosMode<=0x13)?M_EGA:M_LIN4); + } else { + VGA_SetMode(M_TEXT); + } +} + +void SetClock_ET4K(Bitu which,Bitu target) { + et4k.clockFreq[which]=1000*target; + VGA_StartResize(); +} + +Bitu GetClock_ET4K() { + return et4k.clockFreq[get_clock_index_et4k()]; +} + +bool AcceptsMode_ET4K(Bitu mode) { + return mode != 0x3d; +} + +void SVGA_Setup_TsengET4K(void) { + svga.write_p3d5 = &write_p3d5_et4k; + svga.read_p3d5 = &read_p3d5_et4k; + svga.write_p3c5 = &write_p3c5_et4k; + svga.read_p3c5 = &read_p3c5_et4k; + svga.write_p3c0 = &write_p3c0_et4k; + svga.read_p3c1 = &read_p3c1_et4k; + + svga.set_video_mode = &FinishSetMode_ET4K; + svga.determine_mode = &DetermineMode_ET4K; + svga.set_clock = &SetClock_ET4K; + svga.get_clock = &GetClock_ET4K; + svga.accepts_mode = &AcceptsMode_ET4K; + + // From the depths of X86Config, probably inexact + VGA_SetClock(0,CLK_25); + VGA_SetClock(1,CLK_28); + VGA_SetClock(2,32400); + VGA_SetClock(3,35900); + VGA_SetClock(4,39900); + VGA_SetClock(5,44700); + VGA_SetClock(6,31400); + VGA_SetClock(7,37500); + VGA_SetClock(8,50000); + VGA_SetClock(9,56500); + VGA_SetClock(10,64900); + VGA_SetClock(11,71900); + VGA_SetClock(12,79900); + VGA_SetClock(13,89600); + VGA_SetClock(14,62800); + VGA_SetClock(15,74800); + + IO_RegisterReadHandler(0x3cd,read_p3cd_et4k,IO_MB); + IO_RegisterWriteHandler(0x3cd,write_p3cd_et4k,IO_MB); + + // Tseng ROM signature + PhysPt rom_base=PhysMake(0xc000,0); + phys_writeb(rom_base+0x0075,' '); + phys_writeb(rom_base+0x0076,'T'); + phys_writeb(rom_base+0x0077,'s'); + phys_writeb(rom_base+0x0078,'e'); + phys_writeb(rom_base+0x0079,'n'); + phys_writeb(rom_base+0x007a,'g'); + phys_writeb(rom_base+0x007b,' '); +} + + +// Tseng ET3K implementation +typedef struct { +// Stored exact values of some registers. Documentation only specifies some bits but hardware checks may +// expect other bits to be preserved. + Bitu store_3d4_1b; + Bitu store_3d4_1c; + Bitu store_3d4_1d; + Bitu store_3d4_1e; + Bitu store_3d4_1f; + Bitu store_3d4_20; + Bitu store_3d4_21; + Bitu store_3d4_23; // note that 22 is missing + Bitu store_3d4_24; + Bitu store_3d4_25; + + Bitu store_3c0_16; + Bitu store_3c0_17; + + Bitu store_3c4_06; + Bitu store_3c4_07; + + Bitu clockFreq[8]; + Bitu biosMode; +} SVGA_ET3K_DATA; + +static SVGA_ET3K_DATA et3k = { 0 /* and the rest are 0s as well */ }; + +#define STORE_ET3K(port, index) \ + case 0x##index: \ + et3k.store_##port##_##index = val; \ + break; + +#define RESTORE_ET3K(port, index) \ + case 0x##index: \ + return et3k.store_##port##_##index; + + +void write_p3d5_et3k(Bitu reg,Bitu val,Bitu iolen) { + switch(reg) { + // 3d4 index 1bh-21h: Hardware zoom control registers + // I am not sure if there was a piece of software that used these. + // Not implemented and will probably stay this way. + STORE_ET3K(3d4, 1b); + STORE_ET3K(3d4, 1c); + STORE_ET3K(3d4, 1d); + STORE_ET3K(3d4, 1e); + STORE_ET3K(3d4, 1f); + STORE_ET3K(3d4, 20); + STORE_ET3K(3d4, 21); + + case 0x23: + /* + 3d4h index 23h (R/W): Extended start ET3000 + bit 0 Cursor start address bit 16 + 1 Display start address bit 16 + 2 Zoom start address bit 16 + 7 If set memory address 8 is output on the MBSL pin (allowing access to + 1MB), if clear the blanking signal is output. + */ + // Only bits 1 and 2 are supported. Bit 2 is related to hardware zoom, bit 7 is too obscure to be useful + et3k.store_3d4_23 = val; + vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x02)<<15); + vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x01)<<16); + break; + + + /* + 3d4h index 24h (R/W): Compatibility Control + bit 0 Enable Clock Translate if set + 1 Clock Select bit 2. Bits 0-1 are in 3C2h/3CCh. + 2 Enable tri-state for all output pins if set + 3 Enable input A8 of 1MB DRAMs from the INTL output if set + 4 Reserved + 5 Enable external ROM CRTC translation if set + 6 Enable Double Scan and Underline Attribute if set + 7 Enable 6845 compatibility if set. + */ + // TODO: Some of these may be worth implementing. + STORE_ET3K(3d4, 24); + + + case 0x25: + /* + 3d4h index 25h (R/W): Overflow High + bit 0 Vertical Blank Start bit 10 + 1 Vertical Total Start bit 10 + 2 Vertical Display End bit 10 + 3 Vertical Sync Start bit 10 + 4 Line Compare bit 10 + 5-6 Reserved + 7 Vertical Interlace if set + */ + et3k.store_3d4_25 = val; + vga.config.line_compare = (vga.config.line_compare & 0x3ff) | ((val&0x10)<<6); + // Abusing s3 ex_ver_overflow field. This is to be cleaned up later. + { + Bit8u s3val = + ((val & 0x01) << 2) | // vbstart + ((val & 0x02) >> 1) | // vtotal + ((val & 0x04) >> 1) | // vdispend + ((val & 0x08) << 1) | // vsyncstart (?) + ((val & 0x10) << 2); // linecomp + if ((s3val ^ vga.s3.ex_ver_overflow) & 0x3) { + vga.s3.ex_ver_overflow=s3val; + VGA_StartResize(); + } else vga.s3.ex_ver_overflow=s3val; + } + break; + + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET3K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3d5_et3k(Bitu reg,Bitu iolen) { + switch(reg) { + RESTORE_ET3K(3d4, 1b); + RESTORE_ET3K(3d4, 1c); + RESTORE_ET3K(3d4, 1d); + RESTORE_ET3K(3d4, 1e); + RESTORE_ET3K(3d4, 1f); + RESTORE_ET3K(3d4, 20); + RESTORE_ET3K(3d4, 21); + RESTORE_ET3K(3d4, 23); + RESTORE_ET3K(3d4, 24); + RESTORE_ET3K(3d4, 25); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET3K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +void write_p3c5_et3k(Bitu reg,Bitu val,Bitu iolen) { + switch(reg) { + // Both registers deal mostly with hardware zoom which is not implemented. Other bits + // seem to be useless for emulation with the exception of index 7 bit 4 (font select) + STORE_ET3K(3c4, 06); + STORE_ET3K(3c4, 07); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET3K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3c5_et3k(Bitu reg,Bitu iolen) { + switch(reg) { + RESTORE_ET3K(3c4, 06); + RESTORE_ET3K(3c4, 07); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET3K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +/* +3CDh (R/W): Segment Select +bit 0-2 64k Write bank number + 3-5 64k Read bank number + 6-7 Segment Configuration. + 0 128K segments + 1 64K segments + 2 1M linear memory +NOTES: 1M linear memory is not supported +*/ +void write_p3cd_et3k(Bitu port,Bitu val,Bitu iolen) { + vga.svga.bank_write = val & 0x07; + vga.svga.bank_read = (val>>3) & 0x07; + vga.svga.bank_size = (val&0x40)?64*1024:128*1024; + VGA_SetupHandlers(); +} + +Bitu read_p3cd_et3k(Bitu port,Bitu iolen) { + return (vga.svga.bank_read<<3)|vga.svga.bank_write|((vga.svga.bank_size==128*1024)?0:0x40); +} + +void write_p3c0_et3k(Bitu reg,Bitu val,Bitu iolen) { +// See ET4K notes. + switch(reg) { + STORE_ET3K(3c0, 16); + STORE_ET3K(3c0, 17); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET3K:Write to illegal index %2X", reg); + break; + } +} + +Bitu read_p3c1_et3k(Bitu reg,Bitu iolen) { + switch(reg) { + RESTORE_ET3K(3c0, 16); + RESTORE_ET3K(3c0, 17); + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET3K:Read from illegal index %2X", reg); + break; + } + return 0x0; +} + +/* +These ports are used but have little if any effect on emulation: + 3B8h (W): Display Mode Control Register + 3BFh (R/W): Hercules Compatibility Mode + 3CBh (R/W): PEL Address/Data Wd + 3CEh index 0Dh (R/W): Microsequencer Mode + 3CEh index 0Eh (R/W): Microsequencer Reset + 3d8h (R/W): Display Mode Control + 3D9h (W): Color Select Register + 3dAh (W): Feature Control Register + 3DEh (W); AT&T Mode Control Register +*/ + +static Bitu get_clock_index_et3k() { + return ((vga.misc_output>>2)&3) | ((et3k.store_3d4_24<<1)&4); +} + +static void set_clock_index_et3k(Bitu index) { + // Shortwiring register reads/writes for simplicity + IO_Write(0x3c2, (vga.misc_output&~0x0c)|((index&3)<<2)); + et3k.store_3d4_24 = (et3k.store_3d4_24&~0x02)|((index&4)>>1); +} + +void FinishSetMode_ET3K(Bitu crtc_base, VGA_ModeExtraData* modeData) { + et3k.biosMode = modeData->modeNo; + + IO_Write(0x3cd, 0x40); // both banks to 0, 64K bank size + + // Tseng ET3K does not have horizontal overflow bits + // Reinterpret ver_overflow + Bit8u et4k_ver_overflow = + ((modeData->ver_overflow & 0x01) << 1) | // vtotal10 + ((modeData->ver_overflow & 0x02) << 1) | // vdispend10 + ((modeData->ver_overflow & 0x04) >> 2) | // vbstart10 + ((modeData->ver_overflow & 0x10) >> 1) | // vretrace10 (tseng has vsync start?) + ((modeData->ver_overflow & 0x40) >> 2); // line_compare + IO_Write(crtc_base,0x25);IO_Write(crtc_base+1,et4k_ver_overflow); + + // Clear remaining ext CRTC registers + for (Bitu i=0x16; i<=0x21; i++) + IO_Write(crtc_base,i);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x23);IO_Write(crtc_base+1,0); + IO_Write(crtc_base,0x24);IO_Write(crtc_base+1,0); + // Clear ext SEQ + IO_Write(0x3c4,0x06);IO_Write(0x3c5,0); + IO_Write(0x3c4,0x07);IO_Write(0x3c5,0x40); // 0 in this register breaks WHATVGA + // Clear ext ATTR + IO_Write(0x3c0,0x16);IO_Write(0x3c0,0); + IO_Write(0x3c0,0x17);IO_Write(0x3c0,0); + + // Select SVGA clock to get close to 60Hz (not particularly clean implementation) + if (modeData->modeNo > 0x13) { + Bitu target = modeData->vtotal*8*modeData->htotal*60; + Bitu best = 1; + Bits dist = 100000000; + for (Bitu i=0; i<8; i++) { + if (abs(target-et3k.clockFreq[i]) < dist) { + best = i; + dist = abs(target-et3k.clockFreq[i]); + } + } + set_clock_index_et3k(best); + } + + if (svga.determine_mode) + svga.determine_mode(); + + // Verified on functioning (at last!) hardware: Tseng ET3000 is the same as ET4000 when + // it comes to chain4 architecture + vga.config.compatible_chain4 = false; + + VGA_SetupHandlers(); +} + +void DetermineMode_ET3K() { + // Close replica from the base implementation. It will stay here + // until I figure a way to either distinguish M_VGA and M_LIN8 or + // merge them. + if (vga.attr.mode_control & 1) { + if (vga.gfx.mode & 0x40) VGA_SetMode((et3k.biosMode<=0x13)?M_VGA:M_LIN8); // Ugly... + else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); + else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); + else VGA_SetMode((et3k.biosMode<=0x13)?M_EGA:M_LIN4); + } else { + VGA_SetMode(M_TEXT); + } +} + +void SetClock_ET3K(Bitu which,Bitu target) { + et3k.clockFreq[which]=1000*target; + VGA_StartResize(); +} + +Bitu GetClock_ET3K() { + return et3k.clockFreq[get_clock_index_et3k()]; +} + +bool AcceptsMode_ET3K(Bitu mode) { + return mode <= 0x37 && mode != 0x2f; +} + +void SVGA_Setup_TsengET3K(void) { + svga.write_p3d5 = &write_p3d5_et3k; + svga.read_p3d5 = &read_p3d5_et3k; + svga.write_p3c5 = &write_p3c5_et3k; + svga.read_p3c5 = &read_p3c5_et3k; + svga.write_p3c0 = &write_p3c0_et3k; + svga.read_p3c1 = &read_p3c1_et3k; + + svga.set_video_mode = &FinishSetMode_ET3K; + svga.determine_mode = &DetermineMode_ET3K; + svga.set_clock = &SetClock_ET3K; + svga.get_clock = &GetClock_ET3K; + svga.accepts_mode = &AcceptsMode_ET3K; + + VGA_SetClock(0,CLK_25); + VGA_SetClock(1,CLK_28); + VGA_SetClock(2,32400); + VGA_SetClock(3,35900); + VGA_SetClock(4,39900); + VGA_SetClock(5,44700); + VGA_SetClock(6,31400); + VGA_SetClock(7,37500); + + IO_RegisterReadHandler(0x3cd,read_p3cd_et3k,IO_MB); + IO_RegisterWriteHandler(0x3cd,write_p3cd_et3k,IO_MB); + + // Tseng ROM signature + PhysPt rom_base=PhysMake(0xc000,0); + phys_writeb(rom_base+0x0075,' '); + phys_writeb(rom_base+0x0076,'T'); + phys_writeb(rom_base+0x0077,'s'); + phys_writeb(rom_base+0x0078,'e'); + phys_writeb(rom_base+0x0079,'n'); + phys_writeb(rom_base+0x007a,'g'); + phys_writeb(rom_base+0x007b,' '); +} diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 96af9e9b..3effb153 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: int10.cpp,v 1.48 2008-01-09 20:34:51 c2woody Exp $ */ + #include "dosbox.h" #include "mem.h" #include "callback.h" @@ -480,7 +482,7 @@ graphics_chars: } break; case 0x4f: /* VESA Calls */ - if ((!IS_VGA_ARCH) || (svgaCard==SVGA_None)) break; + if ((!IS_VGA_ARCH) || (svgaCard!=SVGA_S3Trio)) break; switch (reg_al) { case 0x00: /* Get SVGA Information */ reg_al=0x4f; diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index c64f2714..a3b3cb92 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 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.73 2007-12-27 10:57:51 c2woody Exp $ */ +/* $Id: int10_modes.cpp,v 1.74 2008-01-09 20:34:51 c2woody Exp $ */ #include @@ -124,6 +124,79 @@ VideoModeBlock ModeList_VGA[]={ {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, }; +VideoModeBlock ModeList_VGA_Tseng[]={ +/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ +{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, + +{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, +{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, +{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/ +{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, +{ 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ +{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, +{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 }, + +{ 0x018 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB0000 ,0x4000, 192, 800, 132, 704, 0 }, +{ 0x019 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 400, 0 }, +{ 0x01A ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 448, 0 }, +{ 0x022 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB8000 ,0x4000, 192, 800, 132, 704, 0 }, +{ 0x023 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 400, 0 }, +{ 0x024 ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 448, 0 }, +{ 0x025 ,M_LIN4 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 , 0 }, +{ 0x029 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 }, +{ 0x02D ,M_LIN8 ,640 ,350 ,80 ,21 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 , 0 }, +{ 0x02E ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 }, +{ 0x02F ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },/* ET4000 only */ +{ 0x030 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 , 0 }, +{ 0x036 ,M_LIN4 ,960 , 720,120,45 ,8 ,16 ,1 ,0xA0000 ,0xA000, 120 ,800 ,120,720 , 0 },/* STB only */ +{ 0x037 ,M_LIN4 ,1024, 768,128,48 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,800 ,128,768 , 0 }, +{ 0x038 ,M_LIN8 ,1024 ,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,800 ,128,768 , 0 },/* ET4000 only */ +{ 0x03D ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1152,160,1024, 0 },/* newer ET4000 */ +{ 0x03E ,M_LIN4 ,1280, 960,160,60 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1024,160,960 , 0 },/* Definicon only */ +{ 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */ + +{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, +}; + +VideoModeBlock ModeList_VGA_Paradise[]={ +/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ +{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, + +{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, +{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, +{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/ +{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, +{ 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ +{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, +{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 }, + +{ 0x054 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 }, +{ 0x055 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 }, +{ 0x056 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 }, +{ 0x057 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 }, +{ 0x058 ,M_LIN4 ,800 , 600, 100,37, 8, 16,1, 0xA0000, 0xA000, 128 ,663 ,100,600, 0 }, +{ 0x05D ,M_LIN4 ,1024, 768, 128,48 ,8, 16,1, 0xA0000, 0x10000,128 ,800 ,128,768 ,0 }, // documented only on C00 upwards +{ 0x05E ,M_LIN8 ,640 , 400, 80 ,25, 8, 16,1, 0xA0000, 0x10000,100 ,449 ,80 ,400, 0 }, +{ 0x05F ,M_LIN8 ,640 , 480, 80 ,30, 8, 16,1, 0xA0000, 0x10000,100 ,525 ,80 ,480, 0 }, + +{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, +}; + + VideoModeBlock ModeList_EGA[]={ /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ { 0x000 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,366 ,40 ,350 ,_EGA_HALF_CLOCK }, @@ -510,9 +583,29 @@ bool INT10_SetVideoMode(Bitu mode) { Bit8u modeset_ctl,video_ctl,vga_switches; if (IS_VGA_ARCH) { - if (!SetCurMode(ModeList_VGA,mode)){ - LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); - return false; + if (svga.accepts_mode) { + if (!svga.accepts_mode(mode)) return false; + } + + switch(svgaCard) { + case SVGA_TsengET4K: + case SVGA_TsengET3K: + if (!SetCurMode(ModeList_VGA_Tseng,mode)){ + LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); + return false; + } + break; + case SVGA_ParadisePVGA1A: + if (!SetCurMode(ModeList_VGA_Paradise,mode)){ + LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); + return false; + } + break; + default: + if (!SetCurMode(ModeList_VGA,mode)){ + LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); + return false; + } } } else { if (!SetCurMode(ModeList_EGA,mode)){ @@ -534,7 +627,7 @@ bool INT10_SetVideoMode(Bitu mode) { else crtc_base=0x3d4; // Disable MMIO here so we can read / write memory - if (IS_VGA_ARCH) IO_Write(crtc_base,0x53);IO_Write(crtc_base+1,0x0); + if (IS_VGA_ARCH && svgaCard == SVGA_S3Trio) IO_Write(crtc_base,0x53);IO_Write(crtc_base+1,0x0); /* Setup MISC Output Register */ Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); @@ -744,10 +837,14 @@ bool INT10_SetVideoMode(Bitu mode) { /* OverFlow */ IO_Write(crtc_base,0x07);IO_Write(crtc_base+1,overflow); - /* Extended Horizontal Overflow */ - IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow); - /* Extended Vertical Overflow */ - IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); + + if (svgaCard == SVGA_S3Trio) { + /* Extended Horizontal Overflow */ + IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow); + /* Extended Vertical Overflow */ + IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); + } + /* Offset Register */ Bitu offset; switch (CurMode->type) { @@ -766,15 +863,18 @@ bool INT10_SetVideoMode(Bitu mode) { } IO_Write(crtc_base,0x13); IO_Write(crtc_base + 1,offset & 0xff); - /* Extended System Control 2 Register */ - /* This register actually has more bits but only use the extended offset ones */ - IO_Write(crtc_base,0x51); - IO_Write(crtc_base + 1,(offset & 0x300) >> 4); - /* Clear remaining bits of the display start */ - IO_Write(crtc_base,0x69); - IO_Write(crtc_base + 1,0); - /* Extended Vertical Overflow */ - IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); + + if (svgaCard == SVGA_S3Trio) { + /* Extended System Control 2 Register */ + /* This register actually has more bits but only use the extended offset ones */ + IO_Write(crtc_base,0x51); + IO_Write(crtc_base + 1,(offset & 0x300) >> 4); + /* Clear remaining bits of the display start */ + IO_Write(crtc_base,0x69); + IO_Write(crtc_base + 1,0); + /* Extended Vertical Overflow */ + IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); + } /* Mode Control */ Bit8u mode_control=0; @@ -815,32 +915,36 @@ bool INT10_SetVideoMode(Bitu mode) { /* Renable write protection */ IO_Write(crtc_base,0x11); IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80); - /* Setup the correct clock */ - if (CurMode->mode>=0x100) { - misc_output|=0xef; //Select clock 3 - Bitu clock=CurMode->vtotal*8*CurMode->htotal*70; - VGA_SetClock(3,clock/1000); + + if (svgaCard == SVGA_S3Trio) { + /* Setup the correct clock */ + if (CurMode->mode>=0x100) { + misc_output|=0xef; //Select clock 3 + Bitu clock=CurMode->vtotal*8*CurMode->htotal*70; + VGA_SetClock(3,clock/1000); + } + Bit8u misc_control_2; + /* Setup Pixel format */ + switch (CurMode->type) { + case M_LIN8: + misc_control_2=0x00; + break; + case M_LIN15: + misc_control_2=0x30; + break; + case M_LIN16: + misc_control_2=0x50; + break; + case M_LIN32: + misc_control_2=0xd0; + break; + default: + misc_control_2=0x0; + break; + } + IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1,misc_control_2); } - Bit8u misc_control_2; - /* Setup Pixel format */ - switch (CurMode->type) { - case M_LIN8: - misc_control_2=0x00; - break; - case M_LIN15: - misc_control_2=0x30; - break; - case M_LIN16: - misc_control_2=0x50; - break; - case M_LIN32: - misc_control_2=0xd0; - break; - default: - misc_control_2=0x0; - break; - } - IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1,misc_control_2); + /* Write Misc Output */ IO_Write(0x3c2,misc_output); /* Program Graphics controller */ @@ -1073,78 +1177,90 @@ dac_text16: } // disabled, has to be set in bios.cpp exclusively // real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature); - /* Setup the CPU Window */ - IO_Write(crtc_base,0x6a); - IO_Write(crtc_base+1,0); - /* Setup the linear frame buffer */ - IO_Write(crtc_base,0x59); - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); - IO_Write(crtc_base,0x5a); - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16)); - IO_Write(crtc_base,0x6b); // BIOS scratchpad - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); - - /* Setup some remaining S3 registers */ - IO_Write(crtc_base,0x41); // BIOS scratchpad - IO_Write(crtc_base+1,0x88); - IO_Write(crtc_base,0x52); // extended BIOS scratchpad - IO_Write(crtc_base+1,0x80); - IO_Write(0x3c4,0x15); - IO_Write(0x3c5,0x03); + if (svgaCard == SVGA_S3Trio) { + /* Setup the CPU Window */ + IO_Write(crtc_base,0x6a); + IO_Write(crtc_base+1,0); + /* Setup the linear frame buffer */ + IO_Write(crtc_base,0x59); + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); + IO_Write(crtc_base,0x5a); + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16)); + IO_Write(crtc_base,0x6b); // BIOS scratchpad + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); + + /* Setup some remaining S3 registers */ + IO_Write(crtc_base,0x41); // BIOS scratchpad + IO_Write(crtc_base+1,0x88); + IO_Write(crtc_base,0x52); // extended BIOS scratchpad + IO_Write(crtc_base+1,0x80); - // Accellerator setup - Bitu reg_50=0; - switch (CurMode->type) { - case M_LIN15: - case M_LIN16: reg_50|=0x10; break; - case M_LIN32: reg_50|=0x30; break; - } - switch(CurMode->swidth) - { - case 640: reg_50|=0x40; break; - case 800: reg_50|=0x80; break; - case 1024: break; - case 1152: reg_50|=0x01; break; - case 1280: reg_50|=0xc1; break; - } - IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1,reg_50); + IO_Write(0x3c4,0x15); + IO_Write(0x3c5,0x03); - Bitu reg_31, reg_3a; - switch (CurMode->type) { + // Accellerator setup + Bitu reg_50=0; + switch (CurMode->type) { + case M_LIN15: + case M_LIN16: reg_50|=0x10; break; + case M_LIN32: reg_50|=0x30; break; + } + switch(CurMode->swidth) { + case 640: reg_50|=0x40; break; + case 800: reg_50|=0x80; break; + case 1024: break; + case 1152: reg_50|=0x01; break; + case 1280: reg_50|=0xc1; break; + } + IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1,reg_50); + + Bitu reg_31, reg_3a; + switch (CurMode->type) { + case M_LIN15: + case M_LIN16: + case M_LIN32: + reg_3a=0x15; + break; + case M_LIN8: + // S3VBE20 does it this way. The other double pixel bit does not + // seem to have an effect on the Trio64. + if(CurMode->special&_VGA_PIXEL_DOUBLE) reg_3a=0x5; + else reg_3a=0x15; + break; + default: + reg_3a=5; + break; + }; + + switch (CurMode->type) { + case M_LIN4: // <- Theres a discrepance with real hardware on this + case M_LIN8: case M_LIN15: case M_LIN16: case M_LIN32: - reg_3a=0x15; - break; - case M_LIN8: - // S3VBE20 does it this way. The other double pixel bit does not - // seem to have an effect on the Trio64. - if(CurMode->special&_VGA_PIXEL_DOUBLE) reg_3a=0x5; - else reg_3a=0x15; + reg_31 = 9; break; default: - reg_3a=5; - }; - - switch (CurMode->type) { - case M_LIN4: // <- Theres a discrepance with real hardware on this - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - reg_31 = 9; - break; - default: - reg_31 = 5; - break; - } - IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1,reg_3a); - IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access - IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing + reg_31 = 5; + break; + } + IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1,reg_3a); + IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access + IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing - IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 - IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 + IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 + IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 + } else if (svga.set_video_mode) { + VGA_ModeExtraData modeData; + modeData.ver_overflow = ver_overflow; + modeData.hor_overflow = hor_overflow; + modeData.offset = offset; + modeData.modeNo = CurMode->mode; + modeData.htotal = CurMode->htotal; + modeData.vtotal = CurMode->vtotal; + svga.set_video_mode(crtc_base, &modeData); + } FinishSetMode(clearmem); /* Load text mode font */ diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj index a98b5210..f2257ce0 100644 --- a/visualc_net/dosbox.vcproj +++ b/visualc_net/dosbox.vcproj @@ -513,12 +513,18 @@ + + + +