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 + -
显示快捷键?