2009-05-03 01:02:35 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2002-2009 The DOSBox Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* 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_s3.cpp,v 1.18 2009/03/15 11:28:35 c2woody Exp $ */
|
|
|
|
|
|
|
|
#include "dosbox.h"
|
|
|
|
#include "inout.h"
|
|
|
|
#include "vga.h"
|
|
|
|
#include "mem.h"
|
|
|
|
|
|
|
|
void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
|
|
|
|
switch (reg) {
|
|
|
|
case 0x31: /* CR31 Memory Configuration */
|
|
|
|
//TODO Base address
|
|
|
|
vga.s3.reg_31 = val;
|
|
|
|
vga.config.compatible_chain4 = !(val&0x08);
|
|
|
|
if (vga.config.compatible_chain4) vga.vmemwrap = 256*1024;
|
|
|
|
else vga.vmemwrap = vga.vmemsize;
|
|
|
|
vga.config.display_start = (vga.config.display_start&~0x30000)|((val&0x30)<<12);
|
|
|
|
VGA_DetermineMode();
|
|
|
|
VGA_SetupHandlers();
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0 Enable Base Address Offset (CPUA BASE). Enables bank operation if
|
|
|
|
set, disables if clear.
|
|
|
|
1 Two Page Screen Image. If set enables 2048 pixel wide screen setup
|
|
|
|
2 VGA 16bit Memory Bus Width. Set for 16bit, clear for 8bit
|
|
|
|
3 Use Enhanced Mode Memory Mapping (ENH MAP). Set to enable access to
|
|
|
|
video memory above 256k.
|
|
|
|
4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index
|
|
|
|
51h, for the 864/964 see index 69h.
|
|
|
|
6 High Speed Text Display Font Fetch Mode. If set enables Page Mode
|
|
|
|
for Alpha Mode Font Access.
|
|
|
|
7 (not 864/964) Extended BIOS ROM Space Mapped out. If clear the area
|
|
|
|
C6800h-C7FFFh is mapped out, if set it is accessible.
|
|
|
|
*/
|
|
|
|
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.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;
|
|
|
|
/*
|
|
|
|
0-3 CPU Base Address. 64k bank number. For the 801/5 and 928 see 3d4h
|
|
|
|
index 51h bits 2-3. For the 864/964 see index 6Ah.
|
|
|
|
4 Lock Vertical Timing Registers (LOCK VTMG). Locks 3d4h index 6, 7
|
|
|
|
(bits 0,2,3,5,7), 9 bit 5, 10h, 11h bits 0-3, 15h, 16h if set
|
|
|
|
5 Lock Horizontal Timing Registers (LOCK HTMG). Locks 3d4h index
|
|
|
|
0,1,2,3,4,5,17h bit 2 if set
|
|
|
|
6 (911/924) Lock VSync Polarity.
|
|
|
|
7 (911/924) Lock HSync Polarity.
|
|
|
|
*/
|
|
|
|
case 0x38: /* CR38 Register Lock 1 */
|
|
|
|
vga.s3.reg_lock1=val;
|
|
|
|
break;
|
|
|
|
case 0x39: /* CR39 Register Lock 2 */
|
|
|
|
vga.s3.reg_lock2=val;
|
|
|
|
break;
|
|
|
|
case 0x3a:
|
|
|
|
vga.s3.reg_3a = val;
|
|
|
|
break;
|
|
|
|
case 0x40: /* CR40 System Config */
|
|
|
|
vga.s3.reg_40 = val;
|
|
|
|
break;
|
|
|
|
case 0x41: /* CR41 BIOS flags */
|
|
|
|
vga.s3.reg_41 = val;
|
|
|
|
break;
|
|
|
|
case 0x43: /* CR43 Extended Mode */
|
|
|
|
vga.s3.reg_43=val & ~0x4;
|
|
|
|
if (((val & 0x4) ^ (vga.config.scan_len >> 6)) & 0x4) {
|
|
|
|
vga.config.scan_len&=0x2ff;
|
|
|
|
vga.config.scan_len|=(val & 0x4) << 6;
|
|
|
|
VGA_CheckScanLength();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
2 Logical Screen Width bit 8. Bit 8 of the Display Offset Register/
|
|
|
|
(3d4h index 13h). (801/5,928) Only active if 3d4h index 51h bits 4-5
|
|
|
|
are 0
|
|
|
|
*/
|
|
|
|
case 0x45: /* Hardware cursor mode */
|
|
|
|
vga.s3.hgc.curmode = val;
|
|
|
|
// Activate hardware cursor code if needed
|
|
|
|
VGA_ActivateHardwareCursor();
|
|
|
|
break;
|
|
|
|
case 0x46:
|
|
|
|
vga.s3.hgc.originx = (vga.s3.hgc.originx & 0x00ff) | (val << 8);
|
|
|
|
break;
|
|
|
|
case 0x47: /* HGC orgX */
|
|
|
|
vga.s3.hgc.originx = (vga.s3.hgc.originx & 0xff00) | val;
|
|
|
|
break;
|
|
|
|
case 0x48:
|
|
|
|
vga.s3.hgc.originy = (vga.s3.hgc.originy & 0x00ff) | (val << 8);
|
|
|
|
break;
|
|
|
|
case 0x49: /* HGC orgY */
|
|
|
|
vga.s3.hgc.originy = (vga.s3.hgc.originy & 0xff00) | val;
|
|
|
|
break;
|
|
|
|
case 0x4A: /* HGC foreground stack */
|
|
|
|
if (vga.s3.hgc.fstackpos > 2) vga.s3.hgc.fstackpos = 0;
|
|
|
|
vga.s3.hgc.forestack[vga.s3.hgc.fstackpos] = val;
|
|
|
|
vga.s3.hgc.fstackpos++;
|
|
|
|
break;
|
|
|
|
case 0x4B: /* HGC background stack */
|
|
|
|
if (vga.s3.hgc.bstackpos > 2) vga.s3.hgc.bstackpos = 0;
|
|
|
|
vga.s3.hgc.backstack[vga.s3.hgc.bstackpos] = val;
|
|
|
|
vga.s3.hgc.bstackpos++;
|
|
|
|
break;
|
|
|
|
case 0x4c: /* HGC start address high byte*/
|
|
|
|
vga.s3.hgc.startaddr &=0xff;
|
|
|
|
vga.s3.hgc.startaddr |= ((val & 0xf) << 8);
|
|
|
|
if ((((Bitu)vga.s3.hgc.startaddr)<<10)+((64*64*2)/8) > vga.vmemsize) {
|
|
|
|
vga.s3.hgc.startaddr &= 0xff; // put it back to some sane area;
|
|
|
|
// if read back of this address is ever implemented this needs to change
|
|
|
|
LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC: HGC pattern address beyond video memory" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x4d: /* HGC start address low byte*/
|
|
|
|
vga.s3.hgc.startaddr &=0xff00;
|
|
|
|
vga.s3.hgc.startaddr |= (val & 0xff);
|
|
|
|
break;
|
|
|
|
case 0x4e: /* HGC pattern start X */
|
|
|
|
vga.s3.hgc.posx = val & 0x3f; // bits 0-5
|
|
|
|
break;
|
|
|
|
case 0x4f: /* HGC pattern start Y */
|
|
|
|
vga.s3.hgc.posy = val & 0x3f; // bits 0-5
|
|
|
|
break;
|
|
|
|
case 0x50: // Extended System Control 1
|
|
|
|
vga.s3.reg_50 = val;
|
|
|
|
switch (val & S3_XGA_CMASK) {
|
|
|
|
case S3_XGA_32BPP: vga.s3.xga_color_mode = M_LIN32; break;
|
|
|
|
case S3_XGA_16BPP: vga.s3.xga_color_mode = M_LIN16; break;
|
|
|
|
case S3_XGA_8BPP: vga.s3.xga_color_mode = M_LIN8; break;
|
|
|
|
}
|
|
|
|
switch (val & S3_XGA_WMASK) {
|
|
|
|
case S3_XGA_1024: vga.s3.xga_screen_width = 1024; break;
|
|
|
|
case S3_XGA_1152: vga.s3.xga_screen_width = 1152; break;
|
|
|
|
case S3_XGA_640: vga.s3.xga_screen_width = 640; break;
|
|
|
|
case S3_XGA_800: vga.s3.xga_screen_width = 800; break;
|
|
|
|
case S3_XGA_1280: vga.s3.xga_screen_width = 1280; break;
|
|
|
|
default: vga.s3.xga_screen_width = 1024; break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x51: /* Extended System Control 2 */
|
|
|
|
vga.s3.reg_51=val & 0xc0; //Only store bits 6,7
|
|
|
|
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) {
|
|
|
|
vga.config.scan_len&=0xff;
|
|
|
|
vga.config.scan_len|=(val & 0x30) << 4;
|
|
|
|
VGA_CheckScanLength();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0 (80x) Display Start Address bit 18
|
|
|
|
0-1 (928 +) Display Start Address bit 18-19
|
|
|
|
Bits 16-17 are in index 31h bits 4-5, Bits 0-15 are in 3d4h index
|
|
|
|
0Ch,0Dh. For the 864/964 see 3d4h index 69h
|
|
|
|
2 (80x) CPU BASE. CPU Base Address Bit 18.
|
|
|
|
2-3 (928 +) Old CPU Base Address Bits 19-18.
|
|
|
|
64K Bank register bits 4-5. Bits 0-3 are in 3d4h index 35h.
|
|
|
|
For the 864/964 see 3d4h index 6Ah
|
|
|
|
4-5 Logical Screen Width Bit [8-9]. Bits 8-9 of the CRTC Offset register
|
|
|
|
(3d4h index 13h). If this field is 0, 3d4h index 43h bit 2 is active
|
|
|
|
6 (928,964) DIS SPXF. Disable Split Transfers if set. Spilt Transfers
|
|
|
|
allows transferring one half of the VRAM shift register data while
|
|
|
|
the other half is being output. For the 964 Split Transfers
|
|
|
|
must be enabled in enhanced modes (4AE8h bit 0 set). Guess: They
|
|
|
|
probably can't time the VRAM load cycle closely enough while the
|
|
|
|
graphics engine is running.
|
|
|
|
7 (not 864/964) Enable EPROM Write. If set enables flash memory write
|
|
|
|
control to the BIOS ROM address
|
|
|
|
*/
|
|
|
|
case 0x52: // Extended System Control 1
|
|
|
|
vga.s3.reg_52 = val;
|
|
|
|
break;
|
|
|
|
case 0x53:
|
|
|
|
// Map or unmap MMIO
|
|
|
|
// bit 4 = MMIO at A0000
|
|
|
|
// bit 3 = MMIO at LFB + 16M (should be fine if its always enabled for now)
|
|
|
|
if(vga.s3.ext_mem_ctrl!=val) {
|
|
|
|
vga.s3.ext_mem_ctrl = val;
|
|
|
|
VGA_SetupHandlers();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x55: /* Extended Video DAC Control */
|
|
|
|
vga.s3.reg_55=val;
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the
|
|
|
|
RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs.
|
|
|
|
If this field is 0, 3d4h index 43h bit 1 is active.
|
|
|
|
2 Enable General Input Port Read. If set DAC reads are disabled and the
|
|
|
|
STRD strobe for reading the General Input Port is enabled for reading
|
|
|
|
while DACRD is active, if clear DAC reads are enabled.
|
|
|
|
3 (928) Enable External SID Operation if set. If set video data is
|
|
|
|
passed directly from the VRAMs to the DAC rather than through the
|
|
|
|
VGA chip
|
|
|
|
4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11
|
|
|
|
mode, if clear in MS-Windows mode
|
|
|
|
5 (80x,928) Hardware Cursor External Operation Mode. If set the two
|
|
|
|
bits of cursor data ,is output on the HC[0-1] pins for the video DAC
|
|
|
|
The SENS pin becomes HC1 and the MID2 pin becomes HC0.
|
|
|
|
6 ??
|
|
|
|
7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated.
|
|
|
|
(864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri
|
|
|
|
-stated if set
|
|
|
|
*/
|
|
|
|
case 0x58: /* Linear Address Window Control */
|
|
|
|
vga.s3.reg_58=val;
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0-1 Linear Address Window Size. Must be less than or equal to video
|
|
|
|
memory size. 0: 64K, 1: 1MB, 2: 2MB, 3: 4MB (928)/8Mb (864/964)
|
|
|
|
2 (not 864/964) Enable Read Ahead Cache if set
|
|
|
|
3 (80x,928) ISA Latch Address. If set latches address during every ISA
|
|
|
|
cycle, unlatches during every ISA cycle if clear.
|
|
|
|
(864/964) LAT DEL. Address Latch Delay Control (VL-Bus only). If set
|
|
|
|
address latching occours in the T1 cycle, if clear in the T2 cycle
|
|
|
|
(I.e. one clock cycle delayed).
|
|
|
|
4 ENB LA. Enable Linear Addressing if set.
|
|
|
|
5 (not 864/964) Limit Entry Depth for Write-Post. If set limits Write
|
|
|
|
-Post Entry Depth to avoid ISA bus timeout due to wait cycle limit.
|
|
|
|
6 (928,964) Serial Access Mode (SAM) 256 Words Control. If set SAM
|
|
|
|
control is 256 words, if clear 512 words.
|
|
|
|
7 (928) RAS 6-MCLK. If set the random read/write cycle time is 6MCLKs,
|
|
|
|
if clear 7MCLKs
|
|
|
|
*/
|
|
|
|
case 0x59: /* Linear Address Window Position High */
|
|
|
|
if ((vga.s3.la_window&0xff00) ^ (val << 8)) {
|
|
|
|
vga.s3.la_window=(vga.s3.la_window&0x00ff) | (val << 8);
|
|
|
|
VGA_StartUpdateLFB();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x5a: /* Linear Address Window Position Low */
|
|
|
|
if ((vga.s3.la_window&0x00ff) ^ val) {
|
|
|
|
vga.s3.la_window=(vga.s3.la_window&0xff00) | val;
|
|
|
|
VGA_StartUpdateLFB();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x5D: /* Extended Horizontal Overflow */
|
|
|
|
if ((val ^ vga.s3.ex_hor_overflow) & 3) {
|
|
|
|
vga.s3.ex_hor_overflow=val;
|
|
|
|
VGA_StartResize();
|
|
|
|
} else vga.s3.ex_hor_overflow=val;
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h
|
|
|
|
index 0)
|
|
|
|
1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End
|
|
|
|
register (3d4h index 1)
|
|
|
|
2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking
|
|
|
|
register (3d4h index 2).
|
|
|
|
3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse
|
|
|
|
is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or
|
|
|
|
does it really extend by 64 ?
|
|
|
|
4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start
|
|
|
|
Retrace register (3d4h index 4).
|
|
|
|
5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse
|
|
|
|
is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or
|
|
|
|
does it really extend by 32 ?
|
|
|
|
6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer
|
|
|
|
Position register (3d4h index 3Bh)
|
|
|
|
7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant
|
|
|
|
Termination register (3d4h index 5Fh).
|
|
|
|
*/
|
|
|
|
case 0x5e: /* Extended Vertical Overflow */
|
|
|
|
vga.config.line_compare=(vga.config.line_compare & 0x3ff) | (val & 0x40) << 4;
|
|
|
|
if ((val ^ vga.s3.ex_ver_overflow) & 0x3) {
|
|
|
|
vga.s3.ex_ver_overflow=val;
|
|
|
|
VGA_StartResize();
|
|
|
|
} else vga.s3.ex_ver_overflow=val;
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h
|
|
|
|
index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5.
|
|
|
|
1 Vertical Display End bit 10. Bit 10 of the Vertical Display End
|
|
|
|
register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1
|
|
|
|
and 6
|
|
|
|
2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking
|
|
|
|
register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9
|
|
|
|
in 3d4h index 9 bit 5
|
|
|
|
4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace
|
|
|
|
register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2
|
|
|
|
and 7.
|
|
|
|
6 Line Compare Position bit 10. Bit 10 of the Line Compare register
|
|
|
|
(3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h
|
|
|
|
index 9 bit 6.
|
|
|
|
*/
|
|
|
|
case 0x67: /* Extended Miscellaneous Control 2 */
|
|
|
|
/*
|
|
|
|
0 VCLK PHS. VCLK Phase With Respect to DCLK. If clear VLKC is inverted
|
|
|
|
DCLK, if set VCLK = DCLK.
|
|
|
|
2-3 (Trio64V+) streams mode
|
|
|
|
00 disable Streams Processor
|
|
|
|
01 overlay secondary stream on VGA-mode background
|
|
|
|
10 reserved
|
|
|
|
11 full Streams Processor operation
|
|
|
|
4-7 Pixel format.
|
|
|
|
0 Mode 0: 8bit (1 pixel/VCLK)
|
|
|
|
1 Mode 8: 8bit (2 pixels/VCLK)
|
|
|
|
3 Mode 9: 15bit (1 pixel/VCLK)
|
|
|
|
5 Mode 10: 16bit (1 pixel/VCLK)
|
|
|
|
7 Mode 11: 24/32bit (2 VCLKs/pixel)
|
|
|
|
13 (732/764) 32bit (1 pixel/VCLK)
|
|
|
|
*/
|
|
|
|
vga.s3.misc_control_2=val;
|
|
|
|
VGA_DetermineMode();
|
|
|
|
break;
|
|
|
|
case 0x69: /* Extended System Control 3 */
|
|
|
|
if (((vga.config.display_start & 0x1f0000)>>16) ^ (val & 0x1f)) {
|
|
|
|
vga.config.display_start&=0xffff;
|
|
|
|
vga.config.display_start|=(val & 0x1f) << 16;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x6a: /* Extended System Control 4 */
|
|
|
|
vga.svga.bank_read=val & 0x7f;
|
|
|
|
vga.svga.bank_write = vga.svga.bank_read;
|
|
|
|
VGA_SetupHandlers();
|
|
|
|
break;
|
|
|
|
case 0x6b: // BIOS scratchpad: LFB adress
|
|
|
|
vga.s3.reg_6b=(Bit8u)val;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC:Write to illegal index %2X", reg );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) {
|
|
|
|
switch (reg) {
|
|
|
|
case 0x24: /* attribute controller index (read only) */
|
|
|
|
case 0x26:
|
|
|
|
return (vga.attr.enabled?0x20:0x00) | (vga.attr.index&0x1f);
|
|
|
|
case 0x2d: /* Extended Chip ID (high byte of PCI device ID) */
|
|
|
|
return 0x88;
|
|
|
|
case 0x2e: /* New Chip ID (low byte of PCI device ID) */
|
|
|
|
return 0x11; // Trio64
|
|
|
|
case 0x2f: /* Revision */
|
|
|
|
return 0x00; // Trio64 (exact value?)
|
|
|
|
// return 0x44; // Trio64 V+
|
|
|
|
case 0x30: /* CR30 Chip ID/REV register */
|
|
|
|
return 0xe1; // Trio+ dual byte
|
|
|
|
case 0x31: /* CR31 Memory Configuration */
|
|
|
|
//TODO mix in bits from baseaddress;
|
|
|
|
return vga.s3.reg_31;
|
|
|
|
case 0x35: /* CR35 CRT Register Lock */
|
|
|
|
return vga.s3.reg_35|(vga.svga.bank_read & 0xf);
|
|
|
|
case 0x36: /* CR36 Reset State Read 1 */
|
|
|
|
return vga.s3.reg_36;
|
|
|
|
case 0x37: /* Reset state read 2 */
|
|
|
|
return 0x2b;
|
|
|
|
case 0x38: /* CR38 Register Lock 1 */
|
|
|
|
return vga.s3.reg_lock1;
|
|
|
|
case 0x39: /* CR39 Register Lock 2 */
|
|
|
|
return vga.s3.reg_lock2;
|
|
|
|
case 0x3a:
|
|
|
|
return vga.s3.reg_3a;
|
|
|
|
case 0x40: /* CR40 system config */
|
|
|
|
return vga.s3.reg_40;
|
|
|
|
case 0x41: /* CR40 system config */
|
|
|
|
return vga.s3.reg_41;
|
|
|
|
case 0x42: // not interlaced
|
|
|
|
return 0x0d;
|
|
|
|
case 0x43: /* CR43 Extended Mode */
|
|
|
|
return vga.s3.reg_43|((vga.config.scan_len>>6)&0x4);
|
|
|
|
case 0x45: /* Hardware cursor mode */
|
|
|
|
vga.s3.hgc.bstackpos = 0;
|
|
|
|
vga.s3.hgc.fstackpos = 0;
|
|
|
|
return vga.s3.hgc.curmode|0xa0;
|
|
|
|
case 0x46:
|
|
|
|
return vga.s3.hgc.originx>>8;
|
|
|
|
case 0x47: /* HGC orgX */
|
|
|
|
return vga.s3.hgc.originx&0xff;
|
|
|
|
case 0x48:
|
|
|
|
return vga.s3.hgc.originy>>8;
|
|
|
|
case 0x49: /* HGC orgY */
|
|
|
|
return vga.s3.hgc.originy&0xff;
|
|
|
|
case 0x4A: /* HGC foreground stack */
|
|
|
|
return vga.s3.hgc.forestack[vga.s3.hgc.fstackpos];
|
|
|
|
case 0x4B: /* HGC background stack */
|
|
|
|
return vga.s3.hgc.backstack[vga.s3.hgc.bstackpos];
|
|
|
|
case 0x50: // CR50 Extended System Control 1
|
|
|
|
return vga.s3.reg_50;
|
|
|
|
case 0x51: /* Extended System Control 2 */
|
|
|
|
return ((vga.config.display_start >> 16) & 3 ) |
|
|
|
|
((vga.svga.bank_read & 0x30) >> 2) |
|
|
|
|
((vga.config.scan_len & 0x300) >> 4) |
|
|
|
|
vga.s3.reg_51;
|
|
|
|
case 0x52: // CR52 Extended BIOS flags 1
|
|
|
|
return vga.s3.reg_52;
|
|
|
|
case 0x53:
|
|
|
|
return vga.s3.ext_mem_ctrl;
|
|
|
|
case 0x55: /* Extended Video DAC Control */
|
|
|
|
return vga.s3.reg_55;
|
|
|
|
case 0x58: /* Linear Address Window Control */
|
|
|
|
return vga.s3.reg_58;
|
|
|
|
case 0x59: /* Linear Address Window Position High */
|
|
|
|
return (vga.s3.la_window >> 8);
|
|
|
|
case 0x5a: /* Linear Address Window Position Low */
|
|
|
|
return (vga.s3.la_window & 0xff);
|
|
|
|
case 0x5D: /* Extended Horizontal Overflow */
|
|
|
|
return vga.s3.ex_hor_overflow;
|
|
|
|
case 0x5e: /* Extended Vertical Overflow */
|
|
|
|
return vga.s3.ex_ver_overflow;
|
|
|
|
case 0x67: /* Extended Miscellaneous Control 2 */
|
|
|
|
return vga.s3.misc_control_2;
|
|
|
|
case 0x69: /* Extended System Control 3 */
|
|
|
|
return (Bit8u)((vga.config.display_start & 0x1f0000)>>16);
|
|
|
|
case 0x6a: /* Extended System Control 4 */
|
|
|
|
return (Bit8u)(vga.svga.bank_read & 0x7f);
|
|
|
|
case 0x6b: // BIOS scatchpad: LFB address
|
|
|
|
return vga.s3.reg_6b;
|
|
|
|
default:
|
|
|
|
return 0x00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVGA_S3_WriteSEQ(Bitu reg,Bitu val,Bitu iolen) {
|
|
|
|
if (reg>0x8 && vga.s3.pll.lock!=0x6) return;
|
|
|
|
switch (reg) {
|
|
|
|
case 0x08:
|
|
|
|
vga.s3.pll.lock=val;
|
|
|
|
break;
|
|
|
|
case 0x10: /* Memory PLL Data Low */
|
|
|
|
vga.s3.mclk.n=val & 0x1f;
|
|
|
|
vga.s3.mclk.r=val >> 5;
|
|
|
|
break;
|
|
|
|
case 0x11: /* Memory PLL Data High */
|
|
|
|
vga.s3.mclk.m=val & 0x7f;
|
|
|
|
break;
|
|
|
|
case 0x12: /* Video PLL Data Low */
|
|
|
|
vga.s3.clk[3].n=val & 0x1f;
|
|
|
|
vga.s3.clk[3].r=val >> 5;
|
|
|
|
break;
|
|
|
|
case 0x13: /* Video PLL Data High */
|
|
|
|
vga.s3.clk[3].m=val & 0x7f;
|
|
|
|
break;
|
|
|
|
case 0x15:
|
|
|
|
vga.s3.pll.cmd=val;
|
|
|
|
VGA_StartResize();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:SEQ:Write to illegal index %2X", reg );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitu SVGA_S3_ReadSEQ(Bitu reg,Bitu iolen) {
|
|
|
|
/* S3 specific group */
|
|
|
|
if (reg>0x8 && vga.s3.pll.lock!=0x6) {
|
|
|
|
if (reg<0x1b) return 0;
|
|
|
|
else return reg;
|
|
|
|
}
|
|
|
|
switch (reg) {
|
|
|
|
case 0x08: /* PLL Unlock */
|
|
|
|
return vga.s3.pll.lock;
|
|
|
|
case 0x10: /* Memory PLL Data Low */
|
|
|
|
return vga.s3.mclk.n || (vga.s3.mclk.r << 5);
|
|
|
|
case 0x11: /* Memory PLL Data High */
|
|
|
|
return vga.s3.mclk.m;
|
|
|
|
case 0x12: /* Video PLL Data Low */
|
|
|
|
return vga.s3.clk[3].n || (vga.s3.clk[3].r << 5);
|
|
|
|
case 0x13: /* Video Data High */
|
|
|
|
return vga.s3.clk[3].m;
|
|
|
|
case 0x15:
|
|
|
|
return vga.s3.pll.cmd;
|
|
|
|
default:
|
|
|
|
LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:SEQ:Read from illegal index %2X", reg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitu SVGA_S3_GetClock(void) {
|
|
|
|
Bitu clock = (vga.misc_output >> 2) & 3;
|
|
|
|
if (clock == 0)
|
|
|
|
clock = 25175000;
|
|
|
|
else if (clock == 1)
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SVGA_S3_AcceptsMode(Bitu mode) {
|
|
|
|
return VideoModeMemSize(mode) < vga.vmemsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 = &SVGA_S3_AcceptsMode;
|
|
|
|
|
|
|
|
if (vga.vmemsize == 0)
|
|
|
|
vga.vmemsize = 2*1024*1024; // the most common S3 configuration
|
|
|
|
|
|
|
|
// Set CRTC 36 to specify amount of VRAM and PCI
|
|
|
|
if (vga.vmemsize < 1024*1024) {
|
|
|
|
vga.vmemsize = 512*1024;
|
|
|
|
vga.s3.reg_36 = 0xfa; // less than 1mb fast page mode
|
|
|
|
} else if (vga.vmemsize < 2048*1024) {
|
|
|
|
vga.vmemsize = 1024*1024;
|
|
|
|
vga.s3.reg_36 = 0xda; // 1mb fast page mode
|
|
|
|
} else if (vga.vmemsize < 3072*1024) {
|
|
|
|
vga.vmemsize = 2048*1024;
|
|
|
|
vga.s3.reg_36 = 0x9a; // 2mb fast page mode
|
|
|
|
} else if (vga.vmemsize < 4096*1024) {
|
|
|
|
vga.vmemsize = 3072*1024;
|
|
|
|
vga.s3.reg_36 = 0x5a; // 3mb fast page mode
|
|
|
|
} else { // Trio64 supported only up to 4M
|
|
|
|
vga.vmemsize = 4096*1024;
|
|
|
|
vga.s3.reg_36 = 0x1a; // 4mb fast page mode
|
|
|
|
}
|
|
|
|
|
|
|
|
// S3 ROM signature
|
|
|
|
PhysPt rom_base=PhysMake(0xc000,0);
|
|
|
|
phys_writeb(rom_base+0x003f,'S');
|
|
|
|
phys_writeb(rom_base+0x0040,'3');
|
|
|
|
phys_writeb(rom_base+0x0041,' ');
|
|
|
|
phys_writeb(rom_base+0x0042,'8');
|
|
|
|
phys_writeb(rom_base+0x0043,'6');
|
|
|
|
phys_writeb(rom_base+0x0044,'C');
|
|
|
|
phys_writeb(rom_base+0x0045,'7');
|
|
|
|
phys_writeb(rom_base+0x0046,'6');
|
|
|
|
phys_writeb(rom_base+0x0047,'4');
|
|
|
|
}
|