"Fossies" - the Fresh Open Source Software Archive

Member "pcemu/vga.c" (22 Jan 2001, 18517 Bytes) of package /linux/privat/old/pcemu-1.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "vga.c" see the Fossies "Dox" file reference documentation.

    1 /****************************************************************************
    2 *                                                                           *
    3 *                            Third Year Project                             *
    4 *                                                                           *
    5 *                            An IBM PC Emulator                             *
    6 *                          For Unix and X Windows                           *
    7 *                                                                           *
    8 *                             By David Hedley                               *
    9 *                                                                           *
   10 *                                                                           *
   11 * This program is Copyrighted.  Consult the file COPYRIGHT for more details *
   12 *                                                                           *
   13 ****************************************************************************/
   14 
   15 /* This is VGA.C It contains stuff about the VGA BIOS */
   16 
   17 #include "global.h"
   18 
   19 #include <stdio.h>
   20 
   21 #include "vga.h"
   22 #include "bios.h"
   23 #include "cpu.h"
   24 #include "vgahard.h"
   25 #include "video.h"
   26 #include "hardware.h"
   27 
   28 #define MAXPAGES 8
   29 
   30 #define VIDEOFUNCTIONALITY 0x2000
   31 
   32 static BYTE *data_segment;   /* pointer to 0040:0000 */
   33 static BYTE *screen_mem;     /* pointer to screen memory */
   34 
   35 #define MAXMODE (sizeof defaults/sizeof defaults[0])
   36 
   37 static struct
   38 {
   39     int cs, ce;
   40     int sx, sy;
   41     int colours;
   42     int pages;
   43     int base;
   44     int text;
   45 } defaults[] = 
   46 {
   47     { 6, 7, 40, 25, 16, 8, 0xb800, TRUE },   /* Mode 0x00 */
   48     { 6, 7, 40, 25, 16, 8, 0xb800, TRUE },   /* Mode 0x01 */
   49     { 6, 7, 80, 25, 16, 8, 0xb800, TRUE },   /* Mode 0x02 */
   50     { 6, 7, 80, 25, 16, 8, 0xb800, TRUE },   /* Mode 0x03 */
   51     { 0, 0, 320, 200, 4, 4, 0xb800, FALSE }, /* Mode 0x04 */
   52     { 0, 0, 320, 200, 4, 4, 0xb800, FALSE }, /* Mode 0x05 */
   53     { 0, 0, 640, 200, 2, 4, 0xb800, FALSE }, /* Mode 0x06 */
   54     { 11, 12, 80, 25, 2, 8, 0xb000, TRUE },  /* Mode 0x07 */
   55     { 0, 0, 0, 0, 0, 0, 0, FALSE },          /* Mode 0x08 */
   56     { 0, 0, 0, 0, 0, 0, 0, FALSE },          /* Mode 0x09 */
   57     { 0, 0, 0, 0, 0, 0, 0, FALSE },          /* Mode 0x0a */
   58     { 0, 0, 0, 0, 0, 0, 0, FALSE },          /* Mode 0x0b */
   59     { 0, 0, 0, 0, 0, 0, 0, FALSE },          /* Mode 0x0c */
   60     { 0, 0, 320, 200, 16, 8, 0xa000, FALSE },/* Mode 0x0d */
   61     { 0, 0, 640, 200, 16, 4, 0xa000, FALSE },/* Mode 0x0e */
   62     { 0, 0, 640, 350, 2, 2, 0xa000, FALSE }, /* Mode 0x0f */
   63     { 0, 0, 640, 350, 16, 2, 0xa000, FALSE },/* Mode 0x10 */
   64     { 0, 0, 640, 480, 2, 1, 0xa000, FALSE }, /* Mode 0x11 */
   65     { 0, 0, 640, 480, 16, 1, 0xa000, FALSE },/* Mode 0x12 */
   66     { 0, 0, 320, 200, 256, 1, 0xa000, FALSE },/* Mode 0x13 */
   67 };
   68 
   69 int mono;                    /* TRUE if on monochrome screen */
   70 
   71 /* Remember: screen height is stored one less than actual!!! */
   72 
   73 #define SetMode(m)      PutMemB(data_segment, 0x49, m)
   74 #define GetMode()       GetMemB(data_segment, 0x49)
   75 #define SetWidth(w)     PutMemW(data_segment, 0x4a, w)
   76 #define GetWidth()      GetMemW(data_segment, 0x4a)
   77 #define SetHeight(h)    PutMemB(data_segment, 0x84, h)
   78 #define GetHeight()     GetMemB(data_segment, 0x84)
   79 #define SetSize(s)      PutMemW(data_segment, 0x4c, s)
   80 #define GetSize()       GetMemW(data_segment, 0x4c)
   81 #define SetOffset(o)    PutMemW(data_segment, 0x4e, o)
   82 #define GetOffset()     GetMemW(data_segment, 0x4e)
   83 #define SetCx(page,cx)  PutMemB(data_segment, 0x50+(page << 1), cx)
   84 #define GetCx(page)     GetMemB(data_segment, 0x50+(page << 1))
   85 #define SetCy(page,cy)  PutMemB(data_segment, 0x51+(page << 1), cy)
   86 #define GetCy(page)     GetMemB(data_segment, 0x51+(page << 1))
   87 #define SetCs(s)        PutMemB(data_segment, 0x61, s)
   88 #define GetCs()         GetMemB(data_segment, 0x61)
   89 #define SetCe(s)        PutMemB(data_segment, 0x60, s)
   90 #define GetCe()         GetMemB(data_segment, 0x60)
   91 #define SetCp(cp)       PutMemB(data_segment, 0x62, cp)
   92 #define GetCp()         GetMemB(data_segment, 0x62)
   93 #define GetCRT()        GetMemW(data_segment, 0x63)
   94 #define SetCRT(c)       PutMemW(data_segment, 0x63, c)
   95 #define SetCharHeight(c) PutMemW(data_segment, 0x85, c)
   96 #define GetCharHeight() GetMemW(data_segment, 0x85)
   97 
   98 static int cur_emulate = TRUE;
   99 static int pages;            /* Maximum number of pages */
  100 
  101 #define page_start(page) &screen_mem[GetSize()*(page)]
  102 
  103 
  104 static BYTE functionality[] = 
  105 {
  106     0xff,               /* Modes 0->7 supported */
  107     0x00,               /* Modes 8->0x0f not supported yet */
  108     0x00,               /* Modes 0x10->0x13 not supported yet */
  109     0,0,0,0,            /* Reserved bytes */
  110     0x04,               /* Only 400 scan lines supported at the moment */
  111     0x01,               /* Character blocks */
  112     0x01,               /* Number of active character blocks */
  113     0x04+0x08+0x16,     /* Various functions */
  114     0x04+0x08,          /* ditto */
  115     0,0,                /* Reserved */
  116     0x00,               /* Various saved things */
  117     0x00,               /* Reserved */
  118 };
  119 
  120 
  121 static BYTE *get_offset(int page)
  122 {
  123     return &screen_mem[(GetSize() * page) + (2 * (GetCx(page) +
  124                                                   GetCy(page)*GetWidth()))];
  125 }
  126 
  127 
  128 static void clearscr(int x1,int y1,int x2,int y2,int attr)
  129 {
  130     BYTE *scr = &screen_mem[GetOffset()];
  131     int x,y;
  132     unsigned width = GetWidth();
  133 
  134     for (y = y1; y <= y2; y++)
  135     {
  136         for (x = x1; x <= x2; x++)
  137         {
  138             scr[2*(x+y*width)] = ' ';
  139             scr[2*(x+y*width)+1] = (BYTE)attr;
  140         }
  141     }
  142     update_display();
  143 }
  144 
  145 
  146 static void scroll(int x1, int y1, int x2, int y2, int num, int attr)
  147 {
  148     int x,y;
  149     unsigned width = GetWidth();
  150     BYTE *scr;
  151 
  152     if (x1 > x2 || y1 > y2)
  153         return;
  154 
  155     scr = &screen_mem[GetOffset()];
  156 
  157     if (num == 0 || y2-y1 < abs(num))
  158     {
  159         clearscr(x1,y1,x2,y2, attr);
  160         return;
  161     }
  162 
  163     if (num > 0)
  164     {
  165         disable();    /* To prevent occasional screen glitch */
  166         for (y = y1; y <= y2-num; y++)
  167             for (x = x1; x <= x2; x++)
  168             {
  169                 scr[2*(x+y*width)] = scr[2*(x+(y+num)*width)];
  170                 scr[2*(x+y*width)+1] = scr[2*(x+(y+num)*width)+1];
  171             }
  172         y = y2-num+1;
  173         copy_text(x1,y1+num,x2,y2,x1,y1);
  174         enable();
  175     }
  176     else
  177     {
  178         num = -num;
  179         disable();    /* To prevent occasional screen glitch */
  180         for (y = y2-num; y >= y1; y--)
  181             for (x = x1; x <= x2; x++)
  182             {
  183                 scr[2*(x+(y+num)*width)] = scr[2*(x+y*width)];
  184                 scr[2*(x+(y+num)*width)+1] = scr[2*(x+y*width)+1];
  185             }
  186         y = y1;
  187         copy_text(x1,y1,x2,y2-num,x1,y1+num);
  188         enable();     
  189     }
  190     clearscr(x1,y,x2,y+num-1,attr);
  191 }
  192 
  193 
  194 void set_cursor_type(unsigned start, unsigned end)
  195 {
  196     if (start == 0x20)
  197         set_cursor_height(0, -1);
  198     else
  199     {
  200         start &= 0x1f;
  201         end &= 0x1f;
  202 
  203         SetCs(start);
  204         SetCe(end);
  205         if (cur_emulate && GetMode() <= 3 && start <= 8 && end <= 8)
  206         {
  207             start = (GetCharHeight()*start)/8;
  208             end = (GetCharHeight()*end)/8;
  209         }
  210         set_cursor_height(start, end);
  211     }
  212 }
  213 
  214 
  215 static void set_mode(int mode)
  216 {
  217     if (mode < MAXMODE)
  218     {
  219         if (!mono || (defaults[mode].colours <= 2 && mono))
  220         {
  221             int i;
  222 
  223             if (!defaults[mode].text)
  224                 return;
  225             SetMode(mode);
  226             SetWidth(defaults[mode].sx);
  227             SetHeight(defaults[mode].sy-1);
  228             SetSize(defaults[mode].sx * defaults[mode].sy * 2);
  229             SetCp(0);
  230             SetOffset(0);
  231             if (mode == 0x7)
  232                 SetCRT(0x3b4);
  233             else
  234                 SetCRT(0x3d4);
  235             pages = defaults[mode].pages;
  236             for (i = 0; i < pages; i++)
  237             {
  238                 SetCx(i,0);
  239                 SetCy(i,0);
  240             }
  241             SetCharHeight(16);
  242             set_cursor_type(defaults[mode].cs,defaults[mode].ce);
  243             move_cursor(0, 0);
  244             screen_mem = &memory[defaults[mode].base << 4];
  245             new_screen(GetWidth(), GetHeight()+1, screen_mem);
  246         }
  247     }
  248 }
  249 
  250 
  251 static void display_message(void)
  252 {
  253     static char message1[] =
  254         "PC Emulator v1.01alpha (C) 1994 University of Bristol";
  255     static char message2[] =
  256         "Please report comments, bugs etc to hedley@cs.bris.ac.uk";
  257     BYTE *mem = get_offset(0);
  258     int i;
  259 
  260     disable();
  261 
  262     for (i = 0; i < sizeof message1-1; i++)
  263         mem[i<<1] = message1[i];
  264 
  265     for (i = 0; i < sizeof message2-1; i++)
  266         mem[(i+80)<<1] = message2[i];
  267 
  268     SetCx(0, 0);
  269     SetCy(0, 4);
  270     move_cursor(GetCx(0),GetCy(0));
  271     enable();
  272 
  273 }
  274 
  275 
  276 static void fill_in_functionality(void)
  277 {
  278     WORD tmp = ChangeE(wregs[DI]);
  279     PutMemW(c_es, tmp, VIDEOFUNCTIONALITY);
  280     tmp += 2;
  281     PutMemW(c_es, tmp, 0xf000);
  282     tmp += 2;
  283     PutMemB(c_es, tmp, GetMode());
  284     tmp++;
  285     PutMemW(c_es, tmp, GetWidth());
  286     tmp += 2;
  287     PutMemW(c_es, tmp, GetSize());
  288     tmp += 2;
  289     PutMemW(c_es, tmp, GetSize() * GetCp());
  290     tmp += 2;
  291     
  292     PutMemB(c_es, tmp, GetCy(0));
  293     tmp++;
  294     PutMemB(c_es, tmp, GetCx(0));
  295     tmp++;
  296     PutMemB(c_es, tmp, GetCy(1));
  297     tmp++;
  298     PutMemB(c_es, tmp, GetCx(1));
  299     tmp++;
  300     PutMemB(c_es, tmp, GetCy(2));
  301     tmp++;
  302     PutMemB(c_es, tmp, GetCx(2));
  303     tmp++;
  304     PutMemB(c_es, tmp, GetCy(3));
  305     tmp++;
  306     PutMemB(c_es, tmp, GetCx(3));
  307     tmp++;
  308     PutMemB(c_es, tmp, GetCy(4));
  309     tmp++;
  310     PutMemB(c_es, tmp, GetCx(4));
  311     tmp++;
  312     PutMemB(c_es, tmp, GetCy(5));
  313     tmp++;
  314     PutMemB(c_es, tmp, GetCx(5));
  315     tmp++;
  316     PutMemB(c_es, tmp, GetCy(6));
  317     tmp++;
  318     PutMemB(c_es, tmp, GetCx(6));
  319     tmp++;
  320     PutMemB(c_es, tmp, GetCy(7));
  321     tmp++;
  322     PutMemB(c_es, tmp, GetCx(7));
  323     tmp++;
  324     
  325     PutMemB(c_es, tmp, GetCs());
  326     tmp++;
  327     PutMemB(c_es, tmp, GetCe());
  328     tmp++;
  329     PutMemB(c_es, tmp, GetCp());
  330     tmp++;
  331     
  332     PutMemW(c_es, tmp, GetCRT());
  333     tmp += 2;
  334     
  335     PutMemB(c_es, tmp, 0);
  336     tmp++;
  337     PutMemB(c_es, tmp, 0);
  338     tmp++;
  339  
  340     PutMemB(c_es, tmp, GetHeight()+1);
  341     tmp++;
  342     PutMemW(c_es, tmp, GetCharHeight());
  343     tmp += 2;
  344     PutMemB(c_es, tmp, mono ? 7 : 8);
  345     tmp++;
  346     PutMemB(c_es, tmp, 0);
  347     tmp++;
  348     PutMemW(c_es, tmp, mono ? 0 : 256);
  349     tmp += 2;
  350     PutMemB(c_es, tmp, defaults[GetMode()].pages);
  351     tmp++;
  352     PutMemB(c_es, tmp, 0x02);
  353     tmp++;
  354     PutMemB(c_es, tmp, 0);
  355     tmp++;
  356     PutMemB(c_es, tmp, 0);
  357     tmp++;
  358     PutMemB(c_es, tmp, mono ? 4 : 0);
  359     tmp++;
  360     PutMemW(c_es, tmp, 0);
  361     tmp += 2;
  362     PutMemB(c_es, tmp, 0);
  363     tmp++;
  364     PutMemB(c_es, tmp, 3);
  365     tmp++;
  366     PutMemB(c_es, tmp, 1);
  367 }
  368 
  369 
  370 void int_video(void)
  371 {
  372     unsigned page, al;
  373     unsigned height, width;
  374     
  375     D(printf("In Video. Function = %02X\n", *bregs[AH]););
  376 
  377     CalcAll();
  378     page = *bregs[BH];
  379     al = *bregs[AL];
  380     height = GetHeight();
  381     width = GetWidth()-1;
  382 
  383     switch(*bregs[AH])
  384     {
  385     case 0:     /* Set mode */
  386         set_mode(al & 0x7f);
  387         if ((al & 0x80) == 0)
  388             clearscr(0,0,width, height, 0x07);
  389         break;
  390     case 1:     /* Set cursor type */
  391         set_cursor_type(*bregs[CH], *bregs[CL]);
  392         break;
  393     case 2:     /* Move cursor position */
  394         if (page < pages)
  395         {
  396             SetCx(page, *bregs[DL]);
  397             SetCy(page, *bregs[DH]);
  398             move_cursor(GetCx(page),GetCy(page));
  399         }
  400         break;
  401     case 3:     /* Get cursor position */
  402         if (page < pages)
  403         {
  404             *bregs[CH] = GetCs();
  405             *bregs[CL] = GetCe();
  406             *bregs[DL] = GetCx(page);
  407             *bregs[DH] = GetCy(page);
  408         }
  409         break;
  410     case 4:     /* Light pen (!) */
  411         *bregs[AH] = 0;
  412         wregs[BX] = wregs[CX] = wregs[DX] = 0;
  413         break;
  414     case 5:     /* Set display page */
  415         if (al < pages)
  416         {
  417             SetCp(al);
  418             SetOffset(al*GetSize());
  419             new_screen(width+1, height+1, page_start(al));
  420             update_display();
  421         }
  422         break;
  423     case 6:     /* Scroll down/clear window */
  424         scroll(*bregs[CL], *bregs[CH], *bregs[DL], *bregs[DH], al, *bregs[BH]);
  425         break;
  426     case 7:     /* Scroll up/clear window */
  427         scroll(*bregs[CL], *bregs[CH], *bregs[DL], *bregs[DH], -al,*bregs[BH]);
  428         break;
  429     case 8:     /* Read character and attribute at cursor */
  430         if (page < pages)
  431         {
  432             BYTE *pos = get_offset(page);
  433             
  434             *bregs[AL] = *pos++;
  435             *bregs[AH] = *pos;
  436         }
  437         break;
  438     case 9:     /* Write character(s) and attribute(s) at cursor */
  439         if (page < pages)
  440         {
  441             BYTE *pos = get_offset(page);
  442             unsigned i, count;
  443             
  444             count = ChangeE(wregs[CX]);
  445             for (i = count; i > 0; i--)
  446             {
  447                 *pos++ = al;
  448                 *pos++ = *bregs[BL];
  449             }
  450             if (count > 1)
  451                 update_display();
  452             else
  453                 if (count == 1)
  454                     displaychar();
  455         }
  456         break;
  457     case 0x0a:  /* Write character at cursor */
  458         if (page < pages)
  459         {
  460             BYTE *pos = get_offset(page);
  461             unsigned i, count;
  462 
  463             count = ChangeE(wregs[CX]);
  464             for (i = count; i > 0; i--)
  465                 *pos++ = al;
  466 
  467             if (count > 1)
  468                 update_display();
  469             else
  470                 if (count == 1)
  471                     displaychar();
  472         }
  473         break;
  474 
  475     case 0x0b:  /* Set palette/background/border */
  476         break;
  477     case 0x0e:  /* Write character in teletype mode */
  478         if (page < pages)
  479         {
  480             BYTE *pos = get_offset(page);
  481             int x,y;
  482 
  483             x = GetCx(page);
  484             y = GetCy(page);
  485             switch(al)
  486             {
  487             case 0x0a:  /* Line feed */
  488                 y++;
  489                 break;
  490             case 0x0d:  /* Return */
  491                 x = 0;
  492                 break;
  493             case 0x8:   /* Backspace */
  494                 x--;
  495                 break;
  496             case 0x7:   /* Bell */
  497                 fprintf(stderr,"\a");
  498                 fflush(stderr);
  499                 break;
  500             default:
  501                 *pos = al;
  502                 x++;
  503                 displaychar();
  504             }
  505             if (x > width)
  506             {
  507                 x = 0;
  508                 y++;
  509             }
  510             if (x < 0)
  511             {
  512                 x = width;
  513                 y--;
  514             }
  515             if (y > height)
  516             {
  517                 BYTE attr;
  518                 y = height;
  519                 attr = screen_mem[GetSize()*(page+1) -1];
  520                 scroll(0,0,width,y,1,attr);
  521             }
  522             if (y < 0)
  523             {
  524                 y = 0;
  525                 scroll(0,0,width,height,-1,7);
  526             }
  527             SetCx(page,x);
  528             SetCy(page,y);
  529             move_cursor(x,y);
  530         }
  531         break;
  532     case 0x0f:  /* Return information */
  533         *bregs[AL] = GetMode();
  534         *bregs[AH] = width+1;
  535         *bregs[BH] = GetCp();
  536         break;
  537     case 0x10:  /* Colour/palette stuff... */
  538         break;
  539     case 0x11:  /* Font stuff... */
  540         switch(*bregs[AL])
  541         {
  542         case 0x02:      /* Load rom 8x8 font (set 50/42 lines) */
  543         case 0x12:
  544             height = 49;
  545             SetHeight(height);
  546             SetSize((width+1) * (height+1) * 2);
  547             new_screen(width+1, height+1, screen_mem);
  548             clearscr(0,0,width, height, 0x07);
  549             break;
  550         case 0x30:      /* Get font information */
  551             switch(*bregs[BH])
  552             {
  553             default:
  554                 wregs[CX] = ChangeE(16);
  555                 *bregs[DL] = height;
  556                 sregs[ES] = 0xf000;
  557                 c_es = SegToMemPtr(ES);
  558                 wregs[BP] = ChangeE(0);
  559             }
  560             break;
  561         default:
  562             printf("Unimplemented int 0x10 function 0x11 sub-function %02X\n",*bregs[AL]);
  563 #ifdef DEBUG
  564             loc();
  565             exit_emu();
  566 #endif
  567             break;
  568         }
  569         break;
  570     case 0x12:  /* Display information */
  571         switch(*bregs[BL])
  572         {
  573         case 0x10:      /* Get config info */
  574             *bregs[BH] = mono;
  575             *bregs[BL] = 3;
  576             wregs[CX] = ChangeE(0);
  577             break;
  578         case 0x30:      /* Set scan lines */
  579             *bregs[AL] = 0x12;
  580             break;
  581         case 0x34:      /* Enable/disable cursor emulation */
  582             cur_emulate = *bregs[AL] == 0;
  583             *bregs[AL] = 0x12;
  584             break;
  585         default:
  586             printf("Unimplemented int 10 function 0x12 sub-function 0x%02X\n",*bregs[BL]);
  587 #ifdef DEBUG
  588             loc();
  589             exit_emu();
  590 #endif
  591             break;
  592         }
  593         break;
  594     case 0x1a:  /* Get/Set display combination */
  595         if (*bregs[AL] == 0)
  596         {
  597             *bregs[BL] = mono ? 7 : 8; 
  598             *bregs[BH] = 0;
  599             *bregs[AL] = 0x1a;
  600         }
  601         break;
  602     case 0x1b:  /* Get functionality/state information etc */
  603         fill_in_functionality();
  604         *bregs[AL] = 0x1b;
  605         break;
  606     case 0x30:  /* ??? Called by MSD.EXE */
  607     case 0x4f:  /* VESA functions... */
  608     case 0x6f:  /* ??? Called by borland C  */
  609     case 0xcc:  /* ??? Called by Norton's disk edit */
  610     case 0xef:  /* ??? Called by QBASIC.EXE */
  611     case 0xfa:  /* ??? Called by MSD.EXE (Microsoft Diagonstics) */
  612     case 0xfe:  /* ??? - but several programs call it. Appears to do nothing */
  613     case 0xff:  /* ??? Called by WordPerfect 5.1 */
  614         break;
  615     default:
  616         printf("Unimplemented int 10 function: %02X. AL = %02X  BL = %02X\n",
  617                *bregs[AH], *bregs[AL], *bregs[BL]);
  618 #ifdef DEBUG
  619         loc();
  620         exit_emu();
  621 #endif
  622         break;
  623     }
  624 }
  625 
  626 void init_vga(void)
  627 {
  628     int mode = mono ? 7 : 3;
  629     static BYTE afterint[] =
  630     {
  631         0xfb, 0xca, 0x02, 0x00
  632     };
  633 
  634     init_hardware();
  635 
  636     screen_mem = &memory[defaults[mode].base << 4];
  637     data_segment = &memory[0x00400];
  638 
  639     memcpy(&memory[0xf0000+VIDEOFUNCTIONALITY], &functionality, sizeof functionality);
  640 
  641     set_mode(mode);
  642     clearscr(0,0,GetWidth()-1, GetHeight(), 0x07);
  643     set_int(0x10, NULL, 0, int_video, afterint, sizeof afterint);
  644     display_message();
  645 }
  646 
  647 void vga_off(void)
  648 {
  649     finish_hardware();
  650 }