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
This commit is contained in:
parent
2c95419294
commit
e0d88e1d11
17 changed files with 1512 additions and 226 deletions
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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 <string.h>
|
||||
#include <math.h>
|
||||
|
@ -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();
|
||||
|
|
|
@ -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<Bit32u>(gfx(index)),port);
|
||||
break;
|
||||
}
|
||||
return 0; /* Compiler happy */
|
||||
}
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -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<true>(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<true>(addr+0,(Bit8u)(val >> 0));
|
||||
writeHandler<true>(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<true>(addr+0,(Bit8u)(val >> 0));
|
||||
writeHandler<true>(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<Bit8u>( addr );
|
||||
}
|
||||
Bitu readw(PhysPt addr ) {
|
||||
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
|
||||
addr += vga.svga.bank_read_full;
|
||||
if (GCC_UNLIKELY(addr & 1))
|
||||
return
|
||||
(readHandler<Bit8u>( 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<Bit8u>( 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<Bit8u>( addr, val );
|
||||
writeCache<Bit8u>( 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<Bit8u>( &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<Bit16u>( &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<Bit32u>( &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<Bit8u>( &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<Bit16u>( &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<Bit32u>( &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<false>(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<false>(addr+0,(Bit8u)(val >> 0));
|
||||
writeHandler<false>(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<false>(addr+0,(Bit8u)(val >> 0));
|
||||
|
@ -503,19 +521,19 @@ public:
|
|||
writeHandler<false>(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 */
|
||||
|
|
223
src/hardware/vga_paradise.cpp
Normal file
223
src/hardware/vga_paradise.cpp
Normal file
|
@ -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!
|
||||
}
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
785
src/hardware/vga_tseng.cpp
Normal file
785
src/hardware/vga_tseng.cpp
Normal file
|
@ -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,' ');
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue