home *** CD-ROM | disk | FTP | other *** search
/ Game Hack 1 / GHM01.ZIP / XUNIT.PAS < prev   
Pascal/Delphi Source File  |  1994-03-02  |  12KB  |  372 lines

  1. Unit XUnit;
  2.  
  3. {$F+}
  4.  
  5. Interface
  6.  
  7. Type
  8.   AlphaType=Array [0..6,30..126] of Byte;
  9.   RGB=Record
  10.     Red:Byte;
  11.     Grn:Byte;
  12.     Blu:Byte;
  13.   End;
  14.   PaletteRegType=Array [0..255] of RGB;
  15.  
  16. Var
  17.   Alphafile:File of Byte;
  18.   AlphaChar:^AlphaType;
  19.  
  20. Procedure XSet320x240Mode;
  21. Procedure XSet80x25Mode;
  22. Procedure XPutPix(X,Y,PageBase,Color:Word);
  23. Procedure XFillRect(StartX,StartY,EndX,EndY,PageBase,Color:Word);
  24. Procedure XClrScr(PageBase:Word);
  25. Procedure XGetRGB(PaletteNum:Byte;var RGBVal:RGB);
  26. Procedure XPutRGB(PaletteNum:Byte;RGBVal:RGB);
  27. Procedure XRGB2Buf(var PBuf:PaletteRegType);
  28. Procedure XBuf2RGB(PBuf:PaletteRegType);
  29. Procedure XWriteString(Scale,X,Y:Integer;TheString:String;
  30.   PageBase,Color:Integer);
  31. Procedure XWriteCenter(Scale,Y:Integer;TheString:String;
  32.   PageBase,Color:Integer);
  33. Procedure XWriteDrop(Scale,X,Y:Integer;TheString:String;
  34.   PageBase,ColorFG,ColorDrop:Integer);
  35. Procedure XWriteCenterDrop(Scale,Y:Integer;TheString:String;
  36.   PageBase,ColorFG,ColorDrop:Integer);
  37.  
  38.  
  39. Implementation
  40.  
  41. Uses CRT,DOS;
  42.  
  43. Var
  44.   Reg:Registers;
  45.  
  46. Procedure XSet320x240Mode;
  47. { This procedure performs 2 functions:
  48.  
  49.   1. Sets up the VGA to Mode X 320x240
  50.   2. Since the call to Mode 13h screws up the mouse parameters, these
  51.      are set to default values (full-screen, sensitivity in both X and
  52.      Y equal, and located in the center of the screen)
  53.  
  54.   It is always possible to set mouse parameters here because the mouse
  55. driver has always been set up as part of the initialization routine for
  56. this unit.}
  57.  
  58. Const
  59.   CRTParams:Array[0..9] of Word=($0d06,$3e07,$4109,$ea10,$ac11,$df12,
  60.     $0014,$e715,$0616,$e317);
  61. Begin
  62.   asm
  63.     push bp
  64.     push si
  65.     push di
  66.     mov ax,13h
  67.     int 10h
  68.     mov dx,03c4h     {SC_INDEX}
  69.     mov ax,0604h
  70.     out dx,ax        {Disable Chain4 Mode}
  71.     mov ax,0100h     {Synchronous reset while switching clocks}
  72.     out dx,ax
  73.     mov dx,03c2h     {Misc Output}
  74.     mov al,0e3h
  75.     out dx,al        {28 MHz dot clock/60 Hz scan rate}
  76.     mov dx,03c4h
  77.     mov ax,0300h
  78.     out dx,ax        {Undo reset (restart sequencer)}
  79.     mov dx,03d4h     {CTRC_INDEX}
  80.     mov al,11h       {VSync End reg contains register ...}
  81.     out dx,al        {... write protect bit}
  82.     inc dx
  83.     in al,dx
  84.     and al,7fh
  85.     out dx,al
  86.     dec dx
  87.     cld
  88.     mov si,offset CRTParams
  89.     mov cx,10
  90. @SetCRTParmsLoop:
  91.     lodsw
  92.     out dx,ax
  93.     loop @SetCRTParmsLoop
  94.     mov dx,03c4h
  95.     mov ax,0f02h
  96.     out dx,ax
  97.     mov ax,SegA000  {Get Screen Segment from Pascal}
  98.     mov es,ax
  99.     sub di,di
  100.     sub ax,ax
  101.     mov cx,0FFFFh
  102.     rep stosw
  103.     pop di
  104.     pop si
  105.     pop bp
  106.   End;
  107. End;
  108.  
  109. Procedure XSet80x25Mode;
  110. Begin
  111.   asm
  112.     push bp
  113.     mov ax,3
  114.     int 10h
  115.     pop bp
  116.   end;
  117. End;
  118.  
  119. Procedure XPutPix(X,Y,PageBase,Color:Word);
  120. Begin
  121.   asm
  122.     mov   ax,80
  123.     mul   Y                {offset of pixel's scan line in page}
  124.     mov   bx,X             {X value to bx register}
  125.     mov   cl,bl            {Lower byte to cl, we'll use it later}
  126.     shr   bx,1             {Divide X by 4 ...}
  127.     shr   bx,1             {... X/4 = offset of pixel in scan line}
  128.     add   bx,ax            {offset of pixel in page}
  129.     add   bx,PageBase      {Offset of pixel in display memory}
  130.     mov   ax,SegA000       {Get Screen seg from Pascal}
  131.     mov   es,ax            {point ES:BX to the pixel's address}
  132.     and   cl,011b          {CL = pixel's plane}
  133.     mov   ax,0102h         {AL = index in SC of Map Mask reg}
  134.     shl   ah,cl            {set only the bit for the pixel's plane to 1}
  135.     mov   dx,03C4H         {set the Map Mask to enable only the ...}
  136.     out   dx,ax            { ... pixel's plane}
  137.     mov   al,byte ptr [Color]
  138.     mov   es:[bx],al       {draw the pixel in the desired color}
  139.   end;
  140. End;
  141.  
  142. Procedure XFillRect(StartX,StartY,EndX,EndY,PageBase,Color:Word);
  143. Const
  144.   LMask:Array[0..3] of Byte=($f,$e,$c,$8);
  145.   RMask:Array[0..3] of Byte=($f,$1,$3,$7);
  146. Begin
  147.   asm
  148.     push    bp            {save away regs we'll use here}
  149.     push    si
  150.     cld
  151.     mov     ax,80
  152.     mul     StartY        {offset in page of top rectangle scan line}
  153.     mov     di,StartX
  154.     shr     di,1          {X/4 = offset of first rectangle pixel in ... }
  155.     shr     di,1          {... scan line}
  156.     add     di,ax         {offset of first rectangle pixel in page}
  157.     add     di,PageBase   {offset of first rectangle pixel in disp memory}
  158.     mov     ax,SegA000    {point ES:DI to the first rectangle}
  159.     mov     es,ax         {pixel's address}
  160.     mov     dx,03C4H      {set the Sequence Controller Index to ... }
  161.     mov     al,02H        {...point to the Map Mask register}
  162.     out     dx,al
  163.     inc     dx            {point DX to the SC Data register}
  164.     mov     si,StartX
  165.     and     si,0003h      {look up left edge plane mask}
  166.     mov     bh,byte ptr LMask[si]  {to clip & put in BH}
  167.     mov     si,EndX
  168.     and     si,0003h      {look up right edge plane}
  169.     mov     bl,byte ptr RMask[si]  {mask to clip & put in BL}
  170.     mov     cx,EndX       {calculate # of addresses across rect}
  171.     mov     si,StartX
  172.     cmp     cx,si
  173.     jle     @FillDone     {skip if 0 or negative width}
  174.     dec     cx
  175.     and     si,not 011b
  176.     sub     cx,si
  177.     shr     cx,1
  178.     shr     cx,1          {# of addrs across rectangle to fill - 1}
  179.     jnz     @MasksSet     {there's more than one byte to draw}
  180.     and     bh,bl         {there's only one byte, so combine the left ...
  181.                            ... and right edge clip masks}
  182. @MasksSet:
  183.     mov     si,EndY
  184.     sub     si,StartY     {BX = height of rectangle}
  185.     jle     @FillDone     {skip if 0 or negative height}
  186.     mov     ah,byte ptr [Color] {color with which to fill}
  187.     mov     bp,80         {stack frame isn't needed any more}
  188.     sub     bp,cx         {distance from end of one scan line to start ...}
  189.     dec     bp            {... of next}
  190. @FillRowsLoop:
  191.     push    cx            {remember width in addresses - 1}
  192.     mov     al,bh         {put left-edge clip mask in AL}
  193.     out     dx,al         {set the left-edge plane (clip) mask}
  194.     mov     al,ah         {put color in AL}
  195.     stosb                 {draw the left edge}
  196.     dec     cx            {count off left edge byte}
  197.     js      @FillLoopBottom {that's the only byte}
  198.     jz      @DoRightEdge  {there are only two bytes}
  199.     mov     al,00fh       {middle addresses are drawn 4 pixels at a pop}
  200.     out     dx,al         {set the middle pixel mask to no clip}
  201.     mov     al,ah         {put color in AL}
  202.     rep     stosb         {draw the middle addresses four pixels apiece}
  203. @DoRightEdge:
  204.     mov     al,bl         {put right-edge clip mask in AL}
  205.     out     dx,al         {set the right-edge plane (clip) mask}
  206.     mov     al,ah         {put color in AL}
  207.     stosb                 {draw the right edge}
  208. @FillLoopBottom:
  209.     add     di,bp         {point to the start of the next scan line of ...
  210.                            ... rectangle}
  211.     pop     cx            {retrieve width in addresses - 1}
  212.     dec     si            {count down scan lines}
  213.     jnz     @FillRowsLoop
  214. @FillDone:
  215.     pop     si
  216.     pop     bp            {restore caller's stack frame}
  217.   End;
  218. End;
  219.  
  220. Procedure XClrScr(PageBase:Word);
  221. { Clears screen PageBase. More exactly, fills screen PageBase with palette #
  222.   zero's, which is usually set to black.}
  223. Begin
  224.   XFillRect(0,0,320,240,PageBase,0);
  225. End;
  226.  
  227. Procedure XGetRGB(PaletteNum:Byte;var RGBVal:RGB);
  228. { Return RGB values for PaletteNum into var RGBVal }
  229. Begin
  230.   Reg.AX:=$1015;
  231.   Reg.BL:=PaletteNum;
  232.   Intr($10,Reg);
  233.   RGBVal.Red:=Reg.DH;
  234.   RGBVal.Grn:=Reg.CH;
  235.   RGBVal.Blu:=Reg.CL;
  236. End;
  237.  
  238. Procedure XPutRGB(PaletteNum:Byte;RGBVal:RGB);
  239. { Write RGBVal to PaletteNum }
  240. Begin
  241.   Reg.AX:=$1010;
  242.   Reg.BX:=PaletteNum;
  243.   Reg.DH:=RGBVal.Red;
  244.   Reg.CH:=RGBVal.Grn;
  245.   Reg.CL:=RGBVal.Blu;
  246.   Intr($10,Reg);
  247. End;
  248.  
  249. Procedure XRGB2Buf(var PBuf:PaletteRegType);
  250. { Copy all RGB Palette values to a buffer, PBuf }
  251. Begin
  252.   Reg.AX:=$1017;
  253.   Reg.BX:=$0000;
  254.   Reg.CX:=256;
  255.   Reg.ES:=Seg(PBuf);
  256.   Reg.DX:=Ofs(PBuf);
  257.   Intr($10,Reg);
  258. End;
  259.  
  260. Procedure XBuf2RGB(PBuf:PaletteRegType);
  261. { Copy values from PBuf into RGB Palettes }
  262. Begin
  263.   Reg.AX:=$1012;
  264.   Reg.BX:=$0000;
  265.   Reg.CX:=256;
  266.   Reg.ES:=Seg(PBuf);
  267.   Reg.DX:=Ofs(PBuf);
  268.   Intr($10,Reg);
  269. End;
  270.  
  271. Procedure LoadFonts;
  272. Var
  273.   I,J:Integer;
  274. Begin
  275.   Assign(AlphaFile,'FONT7X7.DAT');
  276.   {$I-}
  277.   Reset(AlphaFile);
  278.   {$I+}
  279.   If IOResult<>0 then
  280.   Begin
  281.     XSet80x25Mode;
  282.     WriteLn('Error: Font file FONT7X7.DAT not found.');
  283.     Halt(0);
  284.   End;
  285.   New(AlphaChar);
  286.   For I:=0 to 6 do For J:=33 to 126 do
  287.     Read(AlphaFile,AlphaChar^[I,J]);
  288.   Close(AlphaFile);
  289. End;
  290.  
  291. Procedure XWriteString(Scale,X,Y:Integer;TheString:String;
  292.   PageBase,Color:Integer);
  293. { This procedure writes a string using the 7x7 font set loaded by the
  294.   LoadFonts procedure. The parameters are:
  295.  
  296.   Scale: An integer. If 1, each font is 7x7 pixels with 1 1-pixel space
  297.     between each character. If 2, each font is 14x14 pixels with a 2-pixel
  298.     space between each letter. I have tried scales up to 4, but it should
  299.     work with any reasonable integer number.
  300.   X,Y: The X,Y pixel coordinates (in real screen coordinates, [0,0] being
  301.     the upper left of the screen, [319,239] being the lower right) of the
  302.     bottom left corner of the text to be written.
  303.   TheString: The string to be written.
  304.   PageBase: Offset into screen memory.
  305.   Color: A number from 0 to 255. This is actually the palette number to use
  306.     for the text, not the color. The actual colors are defined by the PutRGB
  307.     and/or the Buf2RGB procedures. }
  308. Var
  309.   I,CharPos,CharNum,PixNum:Byte;
  310. Begin
  311.   Y:=Y-(7*Scale-1); {Shift Y so that text bottom falls at specified Y}
  312.   For CharPos:=1 to Length(TheString) do  {For each character in the string}
  313.   Begin
  314.     CharNum:=Ord(TheString[CharPos]); {Get ASCII code of that character}
  315.     {Next, if character is lowercase, make it uppercase. This is because
  316.     I have not defined fonts for lowercase letters.}
  317.     If CharNum in [96..123] then CharNum:=CharNum-32;
  318.     {If the character is not a space, then draw it}
  319.     If CharNum<>32 then For I:=0 to (7*Scale-1) do
  320.       For PixNum:=0 to (7*Scale-1) do
  321.     Begin
  322.       {For each bit set to 1 in the font map Alphachar^[Row,Code], light
  323.       up the pixel corresponding to that bit position. If you wish, remove
  324.       the curly-braces from "and (X+PixNum<319)", and then pixels whose X
  325.       coordinates are greater than 319 will be clipped. No checks have been
  326.       made for wrapping in the Y direction.}
  327.       If ((AlphaChar^[(I div Scale),CharNum] Shr (7-(PixNum div Scale)))
  328.         and $01 = $01) {and (X+PixNum<319)} then
  329.         XPutPix(X+PixNum,Y+I,PageBase,Color);
  330.     End;
  331.     X:=X+8*Scale; {Step X to prepare for next letter}
  332.   End;
  333. End;
  334.  
  335. Procedure XWriteCenter(Scale,Y:Integer;TheString:String;
  336.   PageBase,Color:Integer);
  337. { This procedure writes a string using the 7x7 font set loaded by the
  338.   LoadFonts procedure. The text is centered on the screen in the X
  339.   direction, so no X coordinate is passed to this procedure. X is cal-
  340.   culated within this procedure, then a call is made to WriteString,
  341.   the most primitive string writing procedure. For parameter meanings
  342.   see XWriteString procedure}
  343. Begin
  344.   XWriteString(Scale,159-Length(TheString)*4*Scale,Y,TheString,PageBase,
  345.     Color);
  346. End;
  347.  
  348. Procedure XWriteDrop(Scale,X,Y:Integer;TheString:String;
  349.   PageBase,ColorFG,ColorDrop:Integer);
  350. { This is like XWriteString, but writes the string with a drop-shadow one
  351.   pixel below and to the left of the font. ColorFG is the foreground color,
  352.   ColoroDrop is the drop-shadow color. As before, "color" actually refers
  353.   to palette number, not the true color.}
  354. Begin
  355.   XWriteString(Scale,X-1,Y+1,TheString,PageBase,ColorDrop);
  356.   XWriteString(Scale,X,Y,TheString,PageBase,ColorFG);
  357. End;
  358.  
  359. Procedure XWriteCenterDrop(Scale,Y:Integer;TheString:String;
  360.   PageBase,ColorFG,ColorDrop:Integer);
  361. {Write string centered on the screen in X, with drop shadow. See XWrite-
  362. Center procedure.}
  363. Begin
  364.   XWriteString(Scale,158-Length(TheString)*4*Scale,Y+1,TheString,PageBase,
  365.     ColorDrop);
  366.   XWriteCenter(Scale,Y,TheString,PageBase,ColorFG);
  367. End;
  368.  
  369. Begin
  370.   LoadFonts;
  371. End.
  372.