12 // SC_INDEX is expected to stay at SC_MAPMASK for proper operation
\r
16 unsigned displayofs,pelpan;
\r
18 unsigned screenseg=SCREENSEG; // set to 0xa000 for asm convenience
\r
21 unsigned ylookup[MAXSCANLINES];
\r
23 boolean screenfaded;
\r
24 unsigned bordercolor;
\r
26 boolean fastpalette; // if true, use outsb to set
\r
28 byte far palette1[256][3],far palette2[256][3];
\r
30 //===========================================================================
\r
34 int VL_VideoID (void);
\r
35 void VL_SetCRTC (int crtc);
\r
36 void VL_SetScreen (int crtc, int pelpan);
\r
37 void VL_WaitVBL (int vbls);
\r
39 //===========================================================================
\r
43 =======================
\r
47 =======================
\r
51 void VL_Startup (void)
\r
53 if ( !MS_CheckParm ("HIDDENCARD") && VL_VideoID () != 5)
\r
54 MS_Quit ("You need a VGA graphics card to run this!");
\r
56 asm cld; // all string instructions assume forward
\r
62 =======================
\r
64 = VL_Startup // WOLFENSTEIN HACK
\r
66 =======================
\r
69 static char *ParmStrings[] = {"HIDDENCARD",""};
\r
71 void VL_Startup (void)
\r
77 videocard = VL_VideoID ();
\r
78 for (i = 1;i < _argc;i++)
\r
79 if (US_CheckParm(_argv[i],ParmStrings) == 0)
\r
86 Quit ("Improper video card! If you really have a VGA card that I am not \n"
\r
87 "detecting, use the -HIDDENCARD command line parameter!");
\r
94 =======================
\r
98 =======================
\r
101 void VL_Shutdown (void)
\r
108 =======================
\r
110 = VL_SetVGAPlaneMode
\r
112 =======================
\r
115 void VL_SetVGAPlaneMode (void)
\r
121 VL_SetLineWidth (40);
\r
126 =======================
\r
130 =======================
\r
133 void VL_SetTextMode (void)
\r
139 //===========================================================================
\r
146 = Fill the entire video buffer with a given color
\r
151 void VL_ClearVideo (byte color)
\r
153 asm mov dx,GC_INDEX
\r
158 asm and al,0xfc // write mode 0 to store directly to video
\r
161 asm mov dx,SC_INDEX
\r
162 asm mov ax,SC_MAPMASK+15*256
\r
163 asm out dx,ax // write through all four planes
\r
165 asm mov ax,SCREENSEG
\r
169 asm mov cx,0x8000 // 0x8000 words, clearing 8 video bytes/word
\r
176 =============================================================================
\r
178 VGA REGISTER MANAGEMENT ROUTINES
\r
180 =============================================================================
\r
192 void VL_DePlaneVGA (void)
\r
196 // change CPU addressing to non linear mode
\r
200 // turn off chain 4 and odd/even
\r
202 outportb (SC_INDEX,SC_MEMMODE);
\r
203 outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);
\r
205 outportb (SC_INDEX,SC_MAPMASK); // leave this set throughought
\r
208 // turn off odd/even and set write mode 0
\r
210 outportb (GC_INDEX,GC_MODE);
\r
211 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);
\r
216 outportb (GC_INDEX,GC_MISCELLANEOUS);
\r
217 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);
\r
220 // clear the entire buffer space, because int 10h only did 16 k / plane
\r
225 // change CRTC scanning from doubleword to byte mode, allowing >64k scans
\r
227 outportb (CRTC_INDEX,CRTC_UNDERLINE);
\r
228 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);
\r
230 outportb (CRTC_INDEX,CRTC_MODE);
\r
231 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);
\r
234 //===========================================================================
\r
237 ====================
\r
241 = Line witdh is in WORDS, 40 words is normal width for vgaplanegr
\r
243 ====================
\r
246 void VL_SetLineWidth (unsigned width)
\r
251 // set wide virtual screen
\r
253 outport (CRTC_INDEX,CRTC_OFFSET+width*256);
\r
256 // set up lookup tables
\r
258 linewidth = width*2;
\r
262 for (i=0;i<MAXSCANLINES;i++)
\r
265 offset += linewidth;
\r
270 ====================
\r
272 = VL_SetSplitScreen
\r
274 ====================
\r
277 void VL_SetSplitScreen (int linenum)
\r
280 linenum=linenum*2-1;
\r
281 outportb (CRTC_INDEX,CRTC_LINECOMPARE);
\r
282 outportb (CRTC_INDEX+1,linenum % 256);
\r
283 outportb (CRTC_INDEX,CRTC_OVERFLOW);
\r
284 outportb (CRTC_INDEX+1, 1+16*(linenum/256));
\r
285 outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
\r
286 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
\r
291 =============================================================================
\r
295 To avoid snow, do a WaitVBL BEFORE calling these
\r
297 =============================================================================
\r
309 void VL_FillPalette (int red, int green, int blue)
\r
313 outportb (PEL_WRITE_ADR,0);
\r
314 for (i=0;i<256;i++)
\r
316 outportb (PEL_DATA,red);
\r
317 outportb (PEL_DATA,green);
\r
318 outportb (PEL_DATA,blue);
\r
322 //===========================================================================
\r
332 void VL_SetColor (int color, int red, int green, int blue)
\r
334 outportb (PEL_WRITE_ADR,color);
\r
335 outportb (PEL_DATA,red);
\r
336 outportb (PEL_DATA,green);
\r
337 outportb (PEL_DATA,blue);
\r
340 //===========================================================================
\r
350 void VL_GetColor (int color, int *red, int *green, int *blue)
\r
352 outportb (PEL_READ_ADR,color);
\r
353 *red = inportb (PEL_DATA);
\r
354 *green = inportb (PEL_DATA);
\r
355 *blue = inportb (PEL_DATA);
\r
358 //===========================================================================
\r
365 = If fast palette setting has been tested for, it is used
\r
366 = (some cards don't like outsb palette setting)
\r
371 void VL_SetPalette (byte far *palette)
\r
375 // outportb (PEL_WRITE_ADR,0);
\r
376 // for (i=0;i<768;i++)
\r
377 // outportb(PEL_DATA,*palette++);
\r
379 asm mov dx,PEL_WRITE_ADR
\r
382 asm mov dx,PEL_DATA
\r
383 asm lds si,[palette]
\r
385 asm test [ss:fastpalette],1
\r
388 // set palette fast for cards that can take it
\r
395 // set palette slowly for some video cards
\r
415 //===========================================================================
\r
422 = This does not use the port string instructions,
\r
423 = due to some incompatabilities
\r
428 void VL_GetPalette (byte far *palette)
\r
432 outportb (PEL_READ_ADR,0);
\r
433 for (i=0;i<768;i++)
\r
434 *palette++ = inportb(PEL_DATA);
\r
438 //===========================================================================
\r
445 = Fades the current palette to the given color in the given number of steps
\r
450 void VL_FadeOut (int start, int end, int red, int green, int blue, int steps)
\r
452 int i,j,orig,delta;
\r
453 byte far *origptr, far *newptr;
\r
456 VL_GetPalette (&palette1[0][0]);
\r
457 _fmemcpy (palette2,palette1,768);
\r
460 // fade through intermediate frames
\r
462 for (i=0;i<steps;i++)
\r
464 origptr = &palette1[start][0];
\r
465 newptr = &palette2[start][0];
\r
466 for (j=start;j<=end;j++)
\r
470 *newptr++ = orig + delta * i / steps;
\r
472 delta = green-orig;
\r
473 *newptr++ = orig + delta * i / steps;
\r
476 *newptr++ = orig + delta * i / steps;
\r
480 VL_SetPalette (&palette2[0][0]);
\r
486 VL_FillPalette (red,green,blue);
\r
488 screenfaded = true;
\r
500 void VL_FadeIn (int start, int end, byte far *palette, int steps)
\r
505 VL_GetPalette (&palette1[0][0]);
\r
506 _fmemcpy (&palette2[0][0],&palette1[0][0],sizeof(palette1));
\r
512 // fade through intermediate frames
\r
514 for (i=0;i<steps;i++)
\r
516 for (j=start;j<=end;j++)
\r
518 delta = palette[j]-palette1[0][j];
\r
519 palette2[0][j] = palette1[0][j] + delta * i / steps;
\r
523 VL_SetPalette (&palette2[0][0]);
\r
529 VL_SetPalette (palette);
\r
530 screenfaded = false;
\r
538 = VL_TestPaletteSet
\r
540 = Sets the palette with outsb, then reads it in and compares
\r
541 = If it compares ok, fastpalette is set to true.
\r
546 void VL_TestPaletteSet (void)
\r
550 for (i=0;i<768;i++)
\r
551 palette1[0][i] = i;
\r
553 fastpalette = true;
\r
554 VL_SetPalette (&palette1[0][0]);
\r
555 VL_GetPalette (&palette2[0][0]);
\r
556 if (_fmemcmp (&palette1[0][0],&palette2[0][0],768))
\r
557 fastpalette = false;
\r
569 void VL_ColorBorder (int color)
\r
574 geninterrupt (0x10);
\r
575 bordercolor = color;
\r
581 =============================================================================
\r
585 =============================================================================
\r
588 byte pixmasks[4] = {1,2,4,8};
\r
589 byte leftmasks[4] = {15,14,12,8};
\r
590 byte rightmasks[4] = {1,3,7,15};
\r
601 void VL_Plot (int x, int y, int color)
\r
605 mask = pixmasks[x&3];
\r
607 *(byte far *)MK_FP(SCREENSEG,bufferofs+(ylookup[y]+(x>>2))) = color;
\r
620 void VL_Hlin (unsigned x, unsigned y, unsigned width, unsigned color)
\r
624 byte leftmask,rightmask;
\r
628 leftmask = leftmasks[x&3];
\r
629 rightmask = rightmasks[(x+width-1)&3];
\r
630 midbytes = ((x+width+3)>>2) - xbyte - 2;
\r
632 dest = MK_FP(SCREENSEG,bufferofs+ylookup[y]+xbyte);
\r
637 VGAMAPMASK(leftmask&rightmask);
\r
643 VGAMAPMASK(leftmask);
\r
647 _fmemset (dest,color,midbytes);
\r
650 VGAMAPMASK(rightmask);
\r
665 void VL_Vlin (int x, int y, int height, int color)
\r
667 byte far *dest,mask;
\r
669 mask = pixmasks[x&3];
\r
672 dest = MK_FP(SCREENSEG,bufferofs+ylookup[y]+(x>>2));
\r
692 void VL_Bar (int x, int y, int width, int height, int color)
\r
695 byte leftmask,rightmask;
\r
696 int midbytes,linedelta;
\r
698 leftmask = leftmasks[x&3];
\r
699 rightmask = rightmasks[(x+width-1)&3];
\r
700 midbytes = ((x+width+3)>>2) - (x>>2) - 2;
\r
701 linedelta = linewidth-(midbytes+1);
\r
703 dest = MK_FP(SCREENSEG,bufferofs+ylookup[y]+(x>>2));
\r
708 VGAMAPMASK(leftmask&rightmask);
\r
720 VGAMAPMASK(leftmask);
\r
724 _fmemset (dest,color,midbytes);
\r
727 VGAMAPMASK(rightmask);
\r
737 ============================================================================
\r
741 ============================================================================
\r
752 void VL_MemToLatch (byte far *source, int width, int height, unsigned dest)
\r
757 count = ((width+3)/4)*height;
\r
759 for (plane = 0; plane<4 ; plane++)
\r
765 asm mov ax,SCREENSEG
\r
768 asm lds si,[source]
\r
778 //===========================================================================
\r
786 = Draws a block of data to the screen.
\r
791 void VL_MemToScreen (byte far *source, int width, int height, int x, int y)
\r
793 byte far *screen,far *dest,mask;
\r
797 dest = MK_FP(SCREENSEG,bufferofs+ylookup[y]+(x>>2) );
\r
800 for (plane = 0; plane<4; plane++)
\r
808 for (y=0;y<height;y++,screen+=linewidth,source+=width)
\r
809 _fmemcpy (screen,source,width);
\r
813 //==========================================================================
\r
819 = VL_MaskedToScreen
\r
821 = Masks a block of main memory to the screen.
\r
826 void VL_MaskedToScreen (byte far *source, int width, int height, int x, int y)
\r
828 byte far *screen,far *dest,mask;
\r
833 dest = MK_FP(SCREENSEG,bufferofs+ylookup[y]+(x>>2) );
\r
834 // mask = 1 << (x&3);
\r
836 // maskptr = source;
\r
838 for (plane = 0; plane<4; plane++)
\r
846 for (y=0;y<height;y++,screen+=linewidth,source+=width)
\r
847 _fmemcpy (screen,source,width);
\r
851 //==========================================================================
\r
861 void VL_LatchToScreen (unsigned source, int width, int height, int x, int y)
\r
866 asm mov di,[y] // dest = bufferofs+ylookup[y]+(x>>2)
\r
868 asm mov di,[WORD PTR ylookup+di]
\r
869 asm add di,[bufferofs]
\r
875 asm mov si,[source]
\r
877 asm mov bx,[linewidth]
\r
879 asm mov dx,[height]
\r
880 asm mov cx,SCREENSEG
\r
898 //===========================================================================
\r
905 = VL_ScreenToScreen
\r
910 void VL_ScreenToScreen (unsigned source, unsigned dest,int width, int height)
\r
915 asm mov si,[source]
\r
918 asm mov bx,[linewidth]
\r
920 asm mov dx,[height]
\r
921 asm mov cx,SCREENSEG
\r
943 =============================================================================
\r
945 STRING OUTPUT ROUTINES
\r
947 =============================================================================
\r
954 ===================
\r
956 = VL_DrawTile8String
\r
958 ===================
\r
961 void VL_DrawTile8String (char *str, char far *tile8ptr, int printx, int printy)
\r
964 unsigned far *dest,far *screen,far *src;
\r
966 dest = MK_FP(SCREENSEG,bufferofs+ylookup[printy]+(printx>>2));
\r
970 src = (unsigned far *)(tile8ptr + (*str<<6));
\r
971 // each character is 64 bytes
\r
975 for (i=0;i<8;i++,screen+=linewidth)
\r
979 for (i=0;i<8;i++,screen+=linewidth)
\r
983 for (i=0;i<8;i++,screen+=linewidth)
\r
987 for (i=0;i<8;i++,screen+=linewidth)
\r
999 ===================
\r
1001 = VL_DrawLatch8String
\r
1003 ===================
\r
1006 void VL_DrawLatch8String (char *str, unsigned tile8ptr, int printx, int printy)
\r
1009 unsigned src,dest;
\r
1011 dest = bufferofs+ylookup[printy]+(printx>>2);
\r
1018 src = tile8ptr + (*str<<4); // each character is 16 latch bytes
\r
1022 asm mov dx,[linewidth]
\r
1024 asm mov ax,SCREENSEG
\r
1065 ===================
\r
1067 = VL_SizeTile8String
\r
1069 ===================
\r
1072 void VL_SizeTile8String (char *str, int *width, int *height)
\r
1075 *width = 8*strlen(str);
\r