⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tl_vga.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** thinlib (c) 2000 Matthew Conte (matt@conte.com)****** This program is free software; you can redistribute it and/or** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation.**** 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 ** Library General Public License for more details.  To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**** Any permitted reproduction of these routines, in whole or in part,** must bear this legend.****** tl_vga.c**** VGA-related thinlib functions** $Id: tl_vga.c,v 1.9 2001/03/12 06:06:55 matt Exp $*/#include <stdio.h>#include <string.h>#include <dpmi.h>#include <dos.h>#include "tl_types.h"#include "tl_bmp.h"#include "tl_vga.h"#include "tl_djgpp.h"#define  DEFAULT_OVERSCAN        0#define  MODE_TEXT               0x03#define  MODE_13H                0x13/* VGA card register addresses */#define  VGA_ATTR                0x3C0 /* Attribute reg */#define  VGA_MISC                0x3C2 /* Misc. output register */#define  VGA_SEQ_ADDR            0x3C4 /* Base port of sequencer */#define  VGA_SEQ_DATA            0x3C5 /* Data port of sequencer */#define  VGA_CRTC_ADDR           0x3D4 /* Base port of CRT controller */#define  VGA_CRTC_DATA           0x3D5 /* Data port of CRT controller */#define  VGA_STATUS              0x3DA /* Input status #1 register */#define  VGA_PAL_READ            0x3C7 /* Palette read address */#define  VGA_PAL_WRITE           0x3C8 /* Palette write address */#define  VGA_PAL_DATA            0x3C9 /* Palette data register *//* generic VGA CRTC register indexes */#define  HZ_DISPLAY_TOTAL        0x00#define  HZ_DISPLAY_END          0x01#define  CRTC_OVERFLOW           0x07#define  VT_DISPLAY_END          0x12#define  MEM_OFFSET              0x13/* indices into our register array */#define  CLOCK_INDEX             0#define  H_TOTAL_INDEX           1#define  H_DISPLAY_INDEX         2#define  H_BLANKING_START_INDEX  3#define  H_BLANKING_END_INDEX    4#define  H_RETRACE_START_INDEX   5#define  H_RETRACE_END_INDEX     6#define  V_TOTAL_INDEX           7#define  OVERFLOW_INDEX          8#define  MAXIMUM_SCANLINE_INDEX  10#define  V_RETRACE_START_INDEX   11#define  V_RETRACE_END_INDEX     12#define  V_END_INDEX             13#define  MEM_OFFSET_INDEX        14#define  UNDERLINE_LOC_INDEX     15#define  V_BLANKING_START_INDEX  16#define  V_BLANKING_END_INDEX    17#define  MODE_CONTROL_INDEX      18#define  MEMORY_MODE_INDEX       20typedef struct vgareg_s{   int port;   int index;   uint8 value;} vgareg_t;typedef struct vgamode_s{   int width;   int height;   char *name;   vgareg_t *regs;} vgamode_t;/* 60 Hz */static vgareg_t mode_256x224[] ={   { 0x3C2, 0x00, 0xE3 }, { 0x3D4, 0x00, 0x5F }, { 0x3D4, 0x01, 0x3F },   { 0x3D4, 0x02, 0x40 }, { 0x3D4, 0x03, 0x82 }, { 0x3D4, 0x04, 0x4A },   { 0x3D4, 0x05, 0x9A }, { 0x3D4, 0x06, 0x0B }, { 0x3D4, 0x07, 0xB2 },   { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x61 }, { 0x3d4, 0x10, 0x00 },   { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xBF }, { 0x3D4, 0x13, 0x20 },   { 0x3D4, 0x14, 0x40 }, { 0x3D4, 0x15, 0x01 }, { 0x3D4, 0x16, 0x0A },   { 0x3D4, 0x17, 0xA3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x04, 0x0E },   { 0, 0, 0 }};static vgareg_t mode_256x240[] ={   { 0x3c2, 0x00, 0xe3},{ 0x3d4, 0x00, 0x55},{ 0x3d4, 0x01, 0x3f},   { 0x3d4, 0x02, 0x80},{ 0x3d4, 0x03, 0x90},{ 0x3d4, 0x04, 0x49},   { 0x3d4, 0x05, 0x80},{ 0x3D4, 0x06, 0x43},{ 0x3d4, 0x07, 0xb2},   { 0x3d4, 0x08, 0x00},{ 0x3D4, 0x09, 0x61},{ 0x3d4, 0x10, 0x04},   { 0x3d4, 0x11, 0xac},{ 0x3D4, 0x12, 0xdf},{ 0x3d4, 0x13, 0x20},   { 0x3d4, 0x14, 0x40},{ 0x3d4, 0x15, 0x07},{ 0x3D4, 0x16, 0x11},   { 0x3d4, 0x17, 0xa3},{ 0x3c4, 0x01, 0x01},{ 0x3c4, 0x04, 0x0e},   { 0, 0, 0 }};static vgareg_t mode_256x256[] ={   { 0x3C2, 0x00, 0xE3 }, { 0x3D4, 0x00, 0x5F }, { 0x3D4, 0x01, 0x3F },   { 0x3D4, 0x02, 0x40 }, { 0x3D4, 0x03, 0x82 }, { 0x3D4, 0x04, 0x4A },   { 0x3D4, 0x05, 0x9A }, { 0x3D4, 0x06, 0x23 }, { 0x3D4, 0x07, 0xB2 },   { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x61 }, { 0x3D4, 0x10, 0x0A },   { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xFF }, { 0x3D4, 0x13, 0x20 },   { 0x3D4, 0x14, 0x40 }, { 0x3D4, 0x15, 0x07 }, { 0x3D4, 0x16, 0x1A },   { 0x3D4, 0x17, 0xA3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x04, 0x0E },   { 0, 0, 0 }};/* 60 Hz */static vgareg_t mode_256x256wide[] ={   { 0x3C2, 0x00, 0xE3 }, { 0x3D4, 0x00, 0x52 }, { 0x3D4, 0x01, 0x3F },   { 0x3D4, 0x02, 0x80 }, { 0x3D4, 0x03, 0x90 }, { 0x3D4, 0x04, 0x49 },   { 0x3D4, 0x05, 0x80 }, { 0x3D4, 0x06, 0x55 }, { 0x3D4, 0x07, 0xB2 },   { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x61 }, { 0x3D4, 0x10, 0x20 },   { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xFF }, { 0x3D4, 0x13, 0x20 },   { 0x3D4, 0x14, 0x40 }, { 0x3D4, 0x15, 0x07 }, { 0x3D4, 0x16, 0x1A },   { 0x3D4, 0x17, 0xA3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x04, 0x0E },   { 0, 0, 0 }};/* 60 Hz */static vgareg_t mode_288x224[] ={   { 0x3C2, 0x00, 0xE3 }, { 0x3D4, 0x00, 0x5F }, { 0x3D4, 0x01, 0x47 },   { 0x3D4, 0x02, 0x50 }, { 0x3D4, 0x03, 0x82 }, { 0x3D4, 0x04, 0x50 },   { 0x3D4, 0x05, 0x80 }, { 0x3D4, 0x06, 0x08 }, { 0x3D4, 0x07, 0x3E },   { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x41 }, { 0x3D4, 0x10, 0xDA },   { 0x3D4, 0x11, 0x9C }, { 0x3D4, 0x12, 0xBF }, { 0x3D4, 0x13, 0x24 },   { 0x3D4, 0x14, 0x40 }, { 0x3D4, 0x15, 0xC7 }, { 0x3D4, 0x16, 0x04 },   { 0x3D4, 0x17, 0xA3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x04, 0x0E },   { 0, 0, 0 }};static vgareg_t mode_320x200[] ={   { 0, 0, 0 }};static vgamode_t vidmodes[] ={   { 288, 224, "288x224", mode_288x224 },   { 256, 224, "256x224", mode_256x224 },   { 256, 240, "256x240", mode_256x240 },   { 256, 256, "256x256 (wide)", mode_256x256wide },   { 256, 256, "256x256", mode_256x256 },   { 320, 200, "320x200", mode_320x200 },   { 0, 0, NULL, 0 }};static bitmap_t *screen = NULL;static bitmap_t *hardware = NULL;/* current VGA mode */static vgamode_t *vga_mode = NULL;/* eek */static int center_x, center_y;static vgareg_t *tweak_addscanlines(vgareg_t *inreg, int entries){   static vgareg_t outreg[32];   int maxscan,maxscanout;   int overflow,overflowout;   int ytotalin,ytotalout;   int ydispin,ydispout;   int vrsin,vrsout,vreout,vblksout,vblkeout;   /* first - check's it not already a 'non doubled' line mode */   maxscan = inreg[MAXIMUM_SCANLINE_INDEX].value;   if ((maxscan & 1) == 0)   /* it is, so just return the array as is */      return inreg;   /* copy across our standard display array */   memcpy (&outreg, inreg, entries * sizeof(vgareg_t));   /* keep hold of the overflow register - as we'll need to refer to it a lot */   overflow = inreg[OVERFLOW_INDEX].value;   /* set a large line compare value  - as we won't be doing any split window scrolling etc.*/   maxscanout = 0x40;   /* half all the y values */   /* total */   ytotalin = inreg[V_TOTAL_INDEX].value;   ytotalin |= ((overflow & 1)<<0x08) | ((overflow & 0x20)<<0x04);   ytotalout = ytotalin >> 1;   /* display enable end */   ydispin = inreg[13].value | ((overflow & 0x02)<< 0x07) | ((overflow & 0x040) << 0x03);   ydispin ++;   ydispout = ydispin >> 1;   ydispout --;   overflowout = ((ydispout & 0x100) >> 0x07) | ((ydispout && 0x200) >> 0x03);   outreg[V_END_INDEX].value = (ydispout & 0xff);   /* avoid top over scan */   if ((ytotalin - ydispin) < 40 && !center_y)   {      vrsout = ydispout;      /* give ourselves a scanline cushion */      ytotalout += 2;   }   else   {      /* vertical retrace start */      vrsin = inreg[V_RETRACE_START_INDEX].value | ((overflow & 0x04)<<0x06) | ((overflow & 0x80)<<0x02);      vrsout = vrsin >> 1;   }   /* check it's legal */   if (vrsout < ydispout)      vrsout = ydispout;   /* update our output overflow */   overflowout |= (((vrsout & 0x100) >> 0x06) | ((vrsout & 0x200) >> 0x02));   outreg[V_RETRACE_START_INDEX].value = (vrsout & 0xff);   /* vertical retrace end */   vreout = vrsout + 2;   /* make sure the retrace fits into our adjusted display size */   if (vreout > (ytotalout - 9))      ytotalout = vreout + 9;   /* write out the vertical retrace end */   outreg[V_RETRACE_END_INDEX].value &= ~0x0f;   outreg[V_RETRACE_END_INDEX].value |= (vreout & 0x0f);   /* vertical blanking start */   vblksout = ydispout + 1;   /* check it's legal */   if(vblksout > vreout)      vblksout = vreout;   /* save the overflow value */   overflowout |= ((vblksout & 0x100) >> 0x05);   maxscanout |= ((vblksout & 0x200) >> 0x04);   /* write the v blank value out */   outreg[V_BLANKING_START_INDEX].value = (vblksout & 0xff);   /* vertical blanking end */   vblkeout = vreout + 1;   /* make sure the blanking fits into our adjusted display size */   if (vblkeout > (ytotalout - 9))      ytotalout = vblkeout + 9;   /* write out the vertical blanking total */   outreg[V_BLANKING_END_INDEX].value = (vblkeout & 0xff);   /* update our output overflow */   overflowout |= ((ytotalout & 0x100) >> 0x08) | ((ytotalout & 0x200) >> 0x04);   /* write out the new vertical total */   outreg[V_TOTAL_INDEX].value = (ytotalout & 0xff);   /* write out our over flows */   outreg[OVERFLOW_INDEX].value = overflowout;   /* finally the max scan line */   outreg[MAXIMUM_SCANLINE_INDEX].value = maxscanout;   /* and we're done */   return outreg;}static void tweak_centermode(vgareg_t *pReg){   int center;   int hrt_start, hrt_end, hrt, hblnk_start, hblnk_end;   int vrt_start, vrt_end, vert_total, vert_display, vblnk_start, vrt, vblnk_end;   if (!pReg)      return;   /* vertical retrace width */   vrt = 2;   /* check the clock speed, to work out the retrace width */   if (pReg[CLOCK_INDEX].value == 0xe7)      hrt = 11;   else      hrt = 10;   /* our center x tweak value */   center = center_x;   /* check for double width scanline rather than half clock (15.75kHz modes) */   if( pReg[H_TOTAL_INDEX].value > 0x96)   {      center<<=1;      hrt<<=1;   }   /* set the hz retrace */   hrt_start = pReg[H_RETRACE_START_INDEX].value;   hrt_start += center;   /* make sure it's legal */   if (hrt_start <= pReg[H_DISPLAY_INDEX].value)      hrt_start = pReg[H_DISPLAY_INDEX].value + 1;   pReg[H_RETRACE_START_INDEX].value = hrt_start;   /* set hz retrace end */   hrt_end = hrt_start + hrt;   /* make sure it's legal */   if( hrt_end > pReg[H_TOTAL_INDEX].value)      hrt_end = pReg[H_TOTAL_INDEX].value;   /* set the hz blanking */   hblnk_start = pReg[H_DISPLAY_INDEX].value + 1;   /* make sure it's legal */   if (hblnk_start > hrt_start)      hblnk_start = pReg[H_RETRACE_START_INDEX].value;   pReg[H_BLANKING_START_INDEX].value = hblnk_start;   /* the horizontal blanking end */   hblnk_end = hrt_end + 2;   /* make sure it's legal */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -