grsvga.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 695 行 · 第 1/2 页
C
695 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Setup for SuperVGA and VESA modes.
*
****************************************************************************/
#include <conio.h>
#include "gdefn.h"
#include "gbios.h"
#include "svgadef.h"
#if defined( __386__ )
#include "rmalloc.h"
#endif
extern void pascal _MoveLeft256();
extern void pascal _MoveRight256();
extern void pascal _MoveUp640();
extern void pascal _MoveDown640();
extern void pascal _MoveUp800();
extern void pascal _MoveDown800();
extern void pascal _MoveUp1024();
extern void pascal _MoveDown1024();
extern void _Rep19();
extern void _CoXor();
extern void _And19();
extern void _CoOr();
#if 0 // This mode is untested
extern void _MoveUp1280();
extern void _MoveDown1280();
extern void _MoveLeftWord();
extern void _MoveRightWord();
extern void _RepWord();
extern void _XorWord();
extern void _AndWord();
extern void _OrWord();
extern void _GetDotWord();
extern void _ZapWord();
extern void _FillWord();
extern void _PixCopyWord();
extern void _PixReadWord();
extern void _ScanLeftWord();
extern void _ScanRightWord();
#endif
extern short _GetDot19();
extern void _Zap256();
extern void _Fill256();
extern void _PixCopy256();
extern void _PixRead256();
extern short pascal _ScanLeft256();
extern short pascal _ScanRight256();
extern void _EGASet();
extern void _EGAReset( void );
extern void pascal _EGAMoveLeft();
extern void pascal _EGAMoveRight();
extern void pascal _MoveUp100();
extern void pascal _MoveDown100();
extern void pascal _MoveUp128();
extern void pascal _MoveDown128();
extern void _EGARep();
extern short _EGAGetDot();
extern void _EGAZap();
extern void _EGAFill();
extern void _EGAPixCopy();
extern void _EGAReadRow();
extern short pascal _EGAScanLeft();
extern short pascal _EGAScanRight();
extern void pascal _MoveLeft19();
extern void pascal _MoveRight19();
extern void _Zap19();
extern void _Fill19();
extern void _PixCopy19();
extern void _PixRead19();
extern short pascal _ScanLeft19();
extern short pascal _ScanRight19();
extern void _PageVESA();
extern void _PageVideo7();
extern void _PageParadise();
extern void _PageATI();
extern void _PageTseng3();
extern void _PageTseng4();
extern void _PageOak();
extern void _PageTrident();
extern void _PageChips();
extern void _PageGenoa();
extern void _PageS3();
extern void _PageCirrus();
extern void _PageViper();
/* Use PASCAL pragma to define our convention for
calling the SVGA page number routine. */
#define PAGE_FUNC pascal // make sure page # gets passed in ax
#if defined ( __386__ )
#pragma aux pascal "*" parm caller [eax];
#else
#pragma aux pascal "*" far parm caller [ax];
#endif
static short _SuperVGAModes[ _SV_MAX-2 ][ 6 ] = {
// 100h 101h 102h 103h 104h 105h
// ==== ==== ==== ==== ==== ====
/* _SV_VIDEO7 */ 0x66, 0x67, 0x62, 0x69, 0x65, 0x6a,
/* _SV_PARADISE */ 0x5e, 0x5f, 0x58, 0x5c, 0x5d, 0,
/* _SV_ATI */ 0x61, 0x62, 0x54, 0x63, 0x55, 0x64,
/* _SV_TSENG3000 */ 0, 0x2e, 0x29, 0x30, 0x37, 0,
/* _SV_TSENG4000 */ 0x2f, 0x2e, 0x29, 0x30, 0x37, 0x38,
/* _SV_OAK */ 0, 0x53, 0x52, 0x54, 0x56, 0x59,
/* _SV_TRIDENT */ 0x5c, 0x5d, 0x5b, 0x5e, 0x5f, 0x62,
/* _SV_CHIPS */ 0x78, 0x79, 0x6a, 0x7c, 0x72, 0x7e,
/* _SV_GENOA */ 0x7e, 0x5c, 0x79, 0x5e, 0x5f, 0,
/* _SV_S3 */ 0, 0x101, 0x102, 0x103, 0x104, 0x105,
/* _SV_CIRRUS */ 0, 0x5f, 0x58, 0x5c, 0x5d, 0x60,
/* _SV_VIPER */ 0, 0x101, 0, 0x103, 0, 0x105,
};
// The page setting functions are defined as FARC pointers.
// This is _WCI86FAR for 16-bit, and nothing for 32-bit flat model.
// QNX 32-bit uses small model, and FARC is defined as _WCI86FAR.
// For QNX 32-bit, we still want only near pointers in the table though,
// to avoid segment relocations in the executable.
// The assignment to _SetVGAPage provides the CS value at runtime.
#if defined(__QNX__) && defined(__386__)
#pragma aux cs = "mov ax,cs" value [ax] modify []
extern unsigned short cs(void);
#define INIT_FARC
#define MAKE_VGA_PG_PTR( x ) MK_FP( cs(), x )
#else
#define INIT_FARC _FARC
#define MAKE_VGA_PG_PTR( x ) x
#endif
static void INIT_FARC * _VGAPageFunc[ _SV_MAX-1 ] = {
_PageVESA,
_PageVideo7,
_PageParadise,
_PageATI,
_PageTseng3,
_PageTseng4,
_PageOak,
_PageTrident,
_PageChips,
_PageGenoa,
_PageS3,
_PageCirrus,
_PageViper,
};
static short SuperVGASetMode( short adapter, short mode, short *stride )
//======================================================================
{
short val;
//#if !defined( __QNX__ )
short granule;
unsigned short buf[ 128 ]; // 256 bytes
#if defined( __386__ ) && !defined(__QNX__)
short i;
short far *rbuf;
RM_ALLOC mem;
#endif
//#endif
*stride = 0;
switch( adapter ) {
//#if !defined( __QNX__ )
case _SV_VESA:
#if defined( __386__ ) && !defined(__QNX__)
if( !_RMAlloc( 256, &mem ) ) {
return( FALSE );
}
/*
AH=0x4F is a VESA BIOS call AL=0x01 VESA return SVGA Mode info
CX=desired mode
ES:DI=address of information block
return value AL=0x4F AH=0x00
*/
val = _RMInterrupt( 0x10, 0x4f01, 0, mode, 0, mem.rm_seg, 0 );
if( val == 0x004f ) {
rbuf = mem.pm_ptr;
for( i = 2; i <= 8; ++i ) {
buf[ i ] = rbuf[ i ];
}
}
_RMFree( &mem );
if( val != 0x004f ) {
return( FALSE );
}
#else
if( GetVESAInfo( 0x4f01, mode, &buf ) != 0x004f ) {
return( FALSE );
}
#endif
#if !defined( __QNX__ )
if( buf[ 3 ] != 64 || buf[ 4 ] != 0xa000 ) { // need 64k pages
#else
if( buf[ 3 ] != 64 ) { // need 64k pages
#endif
return( FALSE ); // starting at A000
}
*stride = buf[ 8 ];
/*
AH=0x4F is a VESA BIOS call AL=0x02 VESA set SVGA Display Mode
BX=desired mode
return value AL=0x4F AH=0x00
*/
if( VideoInt( 0x4f02, mode, 0, 0 ) != 0x004f ) { // set mode
return( FALSE );
}
granule = 64 / buf[ 2 ];
_VGAGran = 0;
while( granule > 1 ) {
granule >>= 1;
++_VGAGran;
}
break;
//#endif
case _SV_VIDEO7:
VideoInt( 0x6f05, mode, 0, 0 ); // set mode
if( ( VideoInt( 0x6f04, 0, 0, 0 ) & 0x00ff ) != mode ) { // get mode
return( FALSE );
}
outpw( 0x3c4, 0xea06 ); // enable extended register access
if( mode == 0x66 ) { // enable access to 2nd bank
outp( 0x3c4, 0xff );
val = inp( 0x3c5 );
outp( 0x3c5, val | 0x10 );
}
// different paging mechanism for 16/256 - use VGAGran to distinguish
if( mode == 0x65 ) { // 16 colours
_VGAGran = 16;
} else {
_VGAGran = 256 - 1;
}
break;
case _SV_PARADISE:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
outpw( 0x3ce, 0x050f ); // unlock extended registers
break;
case _SV_ATI:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
outp( 0x1ce, 0xbe ); // ensure we're in single bank mode
val = inp( 0x1ce + 1 );
val &= 0xf7; // clear bit 3 at port 0xBE
outpw( 0x1ce, ( val << 8 ) + 0xbe );
break;
case _SV_TSENG3000:
case _SV_TSENG4000:
case _SV_OAK:
case _SV_GENOA:
case _SV_VIPER:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
break;
case _SV_S3:
if( VideoInt( 0x4f02, mode, 0, 0 ) != 0x004f ) { // set mode
// if 100 range modes don't work, try 200 range
if( VideoInt( 0x4f02, mode + 0x100, 0, 0 ) != 0x004f ) {
return( FALSE );
}
}
// different paging mechanism for 16/256 - use VGAGran to distinguish
if( mode == 0x104 ) { // 16 colours
_VGAGran = 16;
} else {
_VGAGran = 256 - 1;
}
break;
case _SV_TRIDENT:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
outp( 0x3c4, 0x0b ); // enable extended register
inp( 0x3c4+1 );
outp( 0x3ce, 0x06 );
val = inp( 0x3ce+1 );
outp( 0x3ce+1, ( val & 0xf3 ) | 0x04 );
break;
case _SV_CHIPS:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
outp( 0x46e8, 0x18 ); // enable setup
outp( 0x103, 0x80 ); // enable extended registers
outp( 0x46e8, 0x08 ); // disable setup
outp( 0x3d6, 0x0b ); // enable memory beyond 256k
val = inp( 0x3d6+1 );
outp( 0x3d6+1, val | 1 );
if( mode == 0x61 || mode == 0x72 ) { // 16 colours
_VGAGran = 4;
} else {
_VGAGran = 2;
}
case _SV_CIRRUS:
VideoInt( _BIOS_SET_MODE + mode, 0, 0, 0 );
if( GetVideoMode() != mode ) {
return( FALSE );
}
outp( 0x3ce, 0x0b ); // enable single-page mapping
val = inp( 0x3ce+1 );
outp( 0x3ce+1, val & 0xfe );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?