home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 December / simtel1292_SIMTEL_1292_Walnut_Creek.iso / msdos / pibterm / pibt41s2.arc / PIB4010A.MOD < prev    next >
Text File  |  1988-02-21  |  52KB  |  865 lines

  1. PROCEDURE Emulate_TEK4010;
  2.  
  3. (*----------------------------------------------------------------------*)
  4. (*             Emulate_TEK4010 --- Emulate TekTronix 4010 terminal      *)
  5. (*----------------------------------------------------------------------*)
  6. (*                                                                      *)
  7. (*  Author:  Philip R. Burns                                            *)
  8. (*  Date:    April, 1986        (Version 1.0)                           *)
  9. (*           January, 1988      (Version 4.1 -- add EGA support)        *)
  10. (*                                                                      *)
  11. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  12. (*                                                                      *)
  13. (*  History: Original with me.                                          *)
  14. (*                                                                      *)
  15. (*           This emulator uses the high-resolution graphics mode       *)
  16. (*           (640x200) of the standard IBM color graphics adapter,      *)
  17. (*           or the high-resolution mode of the EGA (640x350).          *)
  18. (*           Only graphics output is emulated, not graphics input.      *)
  19. (*           On the CGA, the display consists of 33 rather than 35      *)
  20. (*           lines of text, while on the EGA 35 lines are displayed.    *)
  21. (*                                                                      *)
  22. (*           Suggestions for improvements or corrections are welcome.   *)
  23. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  24. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  25. (*                                                                      *)
  26. (*           IF you use this code in your own programs, please be nice  *)
  27. (*           and give proper credit.                                    *)
  28. (*                                                                      *)
  29. (*----------------------------------------------------------------------*)
  30.  
  31. TYPE
  32.    Graphics_State = ( Text_Plot, Vector_Plot_Start, Vector_Plot,
  33.                       Point_Plot_Start, Point_Plot, Graphics_Input );
  34.  
  35. VAR
  36.    Done       : BOOLEAN            (* TRUE to exit terminal emulation mode *);
  37.    Ch         : CHAR               (* Character read/written               *);
  38.    B          : BOOLEAN            (* Boolean flag                         *);
  39.    Regs       : Registers          (* For MS DOS interfacing               *);
  40.    FlagG      : Graphics_State     (* Current graphics state               *);
  41.    CursorX    : INTEGER            (* X position of cursor                 *);
  42.    CursorY    : INTEGER            (* Y position of cursor                 *);
  43.    Reset_T    : BOOLEAN            (* Dummy for reset of terminal          *);
  44.    EGA_On     : BOOLEAN            (* TRUE if EGA installed                *);
  45.    XFactor    : REAL               (* Horizontal scaling factor            *);
  46.    YFactor    : REAL               (* Vertical scaling factor              *);
  47.    YMax       : INTEGER            (* Maximum Y value ==> 199, 349         *);
  48.    YMaxM1     : INTEGER            (* Maximum Y value - 1 ==> 198, 348     *);
  49.    YInc       : INTEGER            (* Increment in Y for characters        *);
  50.    GMode      : INTEGER            (* Graphics mode type                   *);
  51.    ClrScr_Req : BOOLEAN            (* TRUE if clear screen request typed   *);
  52.    Save_SUpper: BOOLEAN            (* Save send_upper_case_only flag       *);
  53.  
  54. CONST
  55.    Prev_Ch : CHAR = ^@;
  56.    Hx      : INTEGER = 0;
  57.    Hy      : INTEGER = 0;
  58.    Lx      : INTEGER = 0;
  59.    Ly      : INTEGER = 0;
  60.    Old     : INTEGER = 0;
  61.    LeftH   : BOOLEAN = TRUE;
  62.    LastX   : INTEGER = 0;
  63.    LastY   : INTEGER = 0;
  64.    YDist   : INTEGER = 6;
  65.  
  66. CONST
  67.    Ch_FF   = #12                   (* Form Feed       *);
  68.    Ch_CR   = #13                   (* Carriage Return *);
  69.    Ch_SO   = #14                   (* Start grahics   *);
  70.    Ch_SI   = #15                   (* End graphics    *);
  71.    Ch_SUB  = #26                   (* EOF Character   *);
  72.    Ch_ESC  = #27                   (* Escape          *);
  73.    Ch_FS   = #28                   (* Graphics start  *);
  74.    Ch_GS   = #29                   (* Graphics start  *);
  75.    Ch_RS   = #30                   (* Inc. plot start *);
  76.    Ch_US   = #31                   (* Graphics end    *);
  77.  
  78. (*----------------------------------------------------------------------*)
  79. (*         Plot_Point --- Plot one point in graphics display            *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. PROCEDURE Plot_Point( X , Y: INTEGER );
  83.  
  84. (*----------------------------------------------------------------------*)
  85. (*                                                                      *)
  86. (*     Procedure:  Plot_Point                                           *)
  87. (*                                                                      *)
  88. (*     Purpose:    Plots one pixel in high-resolution graphics screen.  *)
  89. (*                                                                      *)
  90. (*     Calling Sequence:                                                *)
  91. (*                                                                      *)
  92. (*        Plot_Point( X , Y : INTEGER );                                *)
  93. (*                                                                      *)
  94. (*           X --- Horizontal coordinate (0--639)                       *)
  95. (*           Y --- Vertical coordinate   (0--349)                       *)
  96. (*                                                                      *)
  97. (*----------------------------------------------------------------------*)
  98.  
  99. BEGIN (* Plot_Point *)
  100.  
  101. INLINE(
  102.                                       {;}
  103.                                       {;  Check if we are to use BIOS to plot pixel}
  104.                                       {;}
  105.   $F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ {         TEST    Byte [>Write_Graphics_Screen],1 ;Check if direct scren writes}
  106.   $74/$30/                            {         JZ      Bios                            ;No -- use BIOS}
  107.                                       {;}
  108.                                       {;  Write pixel directly to screen memory}
  109.                                       {;}
  110.   $8B/$96/>Y/                         {         MOV     DX,[BP+>Y]            ; Get Y}
  111.   $8D/$1E/>SCAN_LINE_TABLE/           {         LEA     BX,[>Scan_Line_Table] ; Get scan line table address}
  112.   $D1/$E2/                            {         SHL     DX,1                  ; Y * 2 for integer offset}
  113.   $01/$D3/                            {         ADD     BX,DX                 ; Get offset of entry for Y}
  114.   $8B/$1F/                            {         MOV     BX,[BX]               ; Get offset for Y}
  115.                                       {;}
  116.   $8B/$96/>X/                         {         MOV     DX,[BP+>X]            ; Get X}
  117.   $89/$D0/                            {         MOV     AX,DX}
  118.   $B1/$03/                            {         MOV     CL,3                  ;}
  119.   $D3/$EA/                            {         SHR     DX,CL                 ; X DIV 8 = Byte offset within row}
  120.   $01/$D3/                            {         ADD     BX,DX                 ; Byte location in screen memory}
  121.   $25/$07/$00/                        {         AND     AX,7                  ; X MOD 8}
  122.   $BA/$80/$00/                        {         MOV     DX,$80                ; 1 bit in leftmost position}
  123.   $89/$C1/                            {         MOV     CX,AX                 ; shift count}
  124.   $D3/$EA/                            {         SHR     DX,CL                 ; 1 bit in proper position}
  125.   $C4/$3E/>GRAPHICS_SCREEN/           {         LES     DI,[>Graphics_Screen] ; Get screen address}
  126.   $01/$DF/                            {         ADD     DI,BX                 ; Get byte address}
  127.   $26/$08/$15/                        {     ES: OR      BYTE PTR [DI],DL      ; Get byte to alter}
  128.   $E9/$13/$00/                        {         JMP     Exit                  ; Return to caller}
  129.                                       {;}
  130.                                       {;  Plot pixel using BIOS}
  131.                                       {;}
  132.   $55/                                {Bios:    PUSH    BP                    ; Save BP in case BIOS zaps it}
  133.   $1E/                                {         PUSH    DS}
  134.   $B8/$01/$0C/                        {         MOV     AX,$0C01              ; Plot pixel function}
  135.   $8B/$8E/>X/                         {         MOV     CX,[BP+>X]            ; Get horizontal position}
  136.   $8B/$96/>Y/                         {         MOV     DX,[BP+>Y]            ; Get vertical position}
  137.   $B7/$00/                            {         MOV     BH,0                  ; Always page 0}
  138.   $CD/$10/                            {         INT     $10                   ; Plot the pixel via BIOS}
  139.   $1F/                                {         POP     DS}
  140.   $5D);                               {         POP     BP                    ; Restore BP}
  141.                                       {;}
  142.                                       {Exit:}
  143.  
  144. END   (* Plot_Point *);
  145.  
  146. (*----------------------------------------------------------------------*)
  147. (*  XOR_Plot_Point --- Plot one point in graphics display using XOR     *)
  148. (*----------------------------------------------------------------------*)
  149.  
  150. PROCEDURE XOR_Plot_Point( X , Y: INTEGER );
  151.  
  152. (*----------------------------------------------------------------------*)
  153. (*                                                                      *)
  154. (*     Procedure:  XOR_Plot_Point                                       *)
  155. (*                                                                      *)
  156. (*     Purpose:    Plots one pixel in high-res graphics using XOR.      *)
  157. (*                                                                      *)
  158. (*     Calling Sequence:                                                *)
  159. (*                                                                      *)
  160. (*        XOR_Plot_Point( X , Y : INTEGER );                            *)
  161. (*                                                                      *)
  162. (*           X --- Horizontal coordinate (0--639)                       *)
  163. (*           Y --- Vertical coordinate   (0--199)                       *)
  164. (*                                                                      *)
  165. (*----------------------------------------------------------------------*)
  166.  
  167. BEGIN (* XOR_Plot_Point *)
  168.  
  169. INLINE(
  170.                                       {;}
  171.                                       {;  Check if we are to use BIOS to plot pixel}
  172.                                       {;}
  173.   $F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ {         TEST    Byte [>Write_Graphics_Screen],1 ;Check if direct scren writes}
  174.   $74/$30/                            {         JZ      Bios                            ;No -- use BIOS}
  175.                                       {;}
  176.                                       {;  Write pixel directly to screen memory}
  177.                                       {;}
  178.   $8B/$96/>Y/                         {         MOV     DX,[BP+>Y]            ; Get Y}
  179.   $8D/$1E/>SCAN_LINE_TABLE/           {         LEA     BX,[>Scan_Line_Table] ; Get scan line table address}
  180.   $D1/$E2/                            {         SHL     DX,1                  ; Y * 2 for integer offset}
  181.   $01/$D3/                            {         ADD     BX,DX                 ; Get offset of entry for Y}
  182.   $8B/$1F/                            {         MOV     BX,[BX]               ; Get offset for Y}
  183.                                       {;}
  184.   $8B/$96/>X/                         {         MOV     DX,[BP+>X]            ; Get X}
  185.   $89/$D0/                            {         MOV     AX,DX}
  186.   $B1/$03/                            {         MOV     CL,3                  ;}
  187.   $D3/$EA/                            {         SHR     DX,CL                 ; X DIV 8 = Byte offset within row}
  188.   $01/$D3/                            {         ADD     BX,DX                 ; Byte location in screen memory}
  189.   $25/$07/$00/                        {         AND     AX,7                  ; X MOD 8}
  190.   $BA/$80/$00/                        {         MOV     DX,$80                ; 1 bit in leftmost position}
  191.   $89/$C1/                            {         MOV     CX,AX                 ; shift count}
  192.   $D3/$EA/                            {         SHR     DX,CL                 ; 1 bit in proper position}
  193.   $C4/$3E/>GRAPHICS_SCREEN/           {         LES     DI,[>Graphics_Screen] ; Get screen address}
  194.   $01/$DF/                            {         ADD     DI,BX                 ; Get byte address}
  195.   $26/$08/$15/                        {     ES: OR      BYTE PTR [DI],DL      ; Get byte to alter}
  196.   $E9/$13/$00/                        {         JMP     Exit                  ; Return to caller}
  197.                                       {;}
  198.                                       {;  Plot pixel using BIOS}
  199.                                       {;}
  200.   $55/                                {Bios:    PUSH    BP                    ; Save BP in case BIOS zaps it}
  201.   $1E/                                {         PUSH    DS}
  202.   $B8/$81/$0C/                        {         MOV     AX,$0C81              ; Plot pixel function}
  203.   $8B/$8E/>X/                         {         MOV     CX,[BP+>X]            ; Get horizontal position}
  204.   $8B/$96/>Y/                         {         MOV     DX,[BP+>Y]            ; Get vertical position}
  205.   $B7/$00/                            {         MOV     BH,0                  ; Always page 0}
  206.   $CD/$10/                            {         INT     $10                   ; Plot the pixel via BIOS}
  207.   $1F/                                {         POP     DS}
  208.   $5D);                               {         POP     BP                    ; Restore BP}
  209.                                       {;}
  210.                                       {Exit:}
  211.  
  212. END   (* XOR_Plot_Point *);
  213.  
  214. (*----------------------------------------------------------------------*)
  215. (*          Clear_Graphics_Screen --- Clear screen and home cursor      *)
  216. (*----------------------------------------------------------------------*)
  217.  
  218. PROCEDURE Clear_Graphics_Screen;
  219.  
  220. BEGIN (* Clear_Graphics_Screen *)
  221.  
  222.    Set_Graphics_Colors( EGA_On,
  223.                         GMode,
  224.                         Graphics_Foreground_Color,
  225.                         Graphics_BackGround_Color  );
  226.  
  227.                                    (* Move cursor to upper left-hand *)
  228.                                    (* cursor.                        *)
  229.    Graphics_XPos := 0;
  230.    Graphics_YPos := 5;
  231.  
  232.    CursorX       := 0;
  233.    CursorY       := 5;
  234.  
  235.    LeftH         := TRUE;
  236.    Prev_Ch       := CHR( 0 );
  237.  
  238. END   (* Clear_Graphics_Screen *);
  239.  
  240. (*--------------------------------------------------------------------------*)
  241. (*           Draw_Line -- Draw line between two points, low res. mode      *)
  242. (*--------------------------------------------------------------------------*)
  243.  
  244. PROCEDURE Draw_Line( X1, Y1, X2, Y2: INTEGER );
  245.  
  246. (*--------------------------------------------------------------------------*)
  247. (*                                                                          *)
  248. (*    Procedure:  Draw_Line                                                 *)
  249. (*                                                                          *)
  250. (*    Purpose:    Draws line between two points in hi-res. graphics mode    *)
  251. (*                                                                          *)
  252. (*    Calling Sequence:                                                     *)
  253. (*                                                                          *)
  254. (*       Draw_Line( X1 , Y1 , X2, Y2, LineCol : INTEGER );                  *)
  255. (*                                                                          *)
  256. (*           X1      -- Horizontal postion (0 through 639), 1st point       *)
  257. (*           Y1      -- Vertical position (0 through 119), 1st point        *)
  258. (*           X2      -- Horizontal postion (0 through 639), 2nd point       *)
  259. (*           Y2      -- Vertical position (0 through 119), 2nd point        *)
  260. (*                                                                          *)
  261. (*    Calls:  TurnOnTimeSharing                                             *)
  262. (*            TurnOffTimeSharing                                            *)
  263. (*            Get_Screen_Address                                            *)
  264. (*                                                                          *)
  265. (*    Remarks: An incremental plotter algorithm is used.                    *)
  266. (*                                                                          *)
  267. (*--------------------------------------------------------------------------*)
  268.  
  269. VAR
  270.    LongDelta : INTEGER;
  271.    LongStep  : INTEGER;
  272.    ShortStep : INTEGER;
  273.    LineStart : INTEGER;
  274.    LineStop  : INTEGER;
  275.  
  276. BEGIN (* Draw_Line *)
  277.                                    (* Turn off timesharing while drawing *)
  278.  
  279.    IF ( MultiTasker = DoubleDos ) THEN
  280.       BEGIN
  281.          TurnOffTimeSharing;
  282.          Get_Screen_Address( Graphics_Screen );
  283.       END;
  284.  
  285. INLINE(
  286.   $C7/$86/>LONGSTEP/$01/$00/          {          MOV    WORD PTR >LongStep[BP],1       ; assume motion down or right}
  287.   $8B/$B6/>X2/                        {          MOV    SI,>X2[BP]}
  288.   $2B/$B6/>X1/                        {          SUB    SI,>X1[BP]                     ; get BP := LongDelta}
  289.   $7D/$06/                            {          JGE    PL1                            ; if X1 <= X2 then no change}
  290.   $F7/$9E/>LONGSTEP/                  {          NEG    WORD PTR >LongStep[BP]         ; ELSE LongStep := -1 (go up or left)}
  291.   $F7/$DE/                            {          NEG    SI                             ;       LongDelta = abs(LongDelta)}
  292.                                       {PL1:}
  293.   $C7/$86/>SHORTSTEP/$01/$00/         {          MOV    WORD PTR >ShortStep[BP],1      ; assume motion down or right}
  294.   $8B/$86/>Y2/                        {          MOV    AX,>Y2[BP]}
  295.   $2B/$86/>Y1/                        {          SUB    AX,>Y1[BP]                     ; get AX := shortdelta}
  296.   $7D/$06/                            {          JGE    PL2                            ; if y1 <= y2 then no change}
  297.   $F7/$9E/>SHORTSTEP/                 {          NEG    WORD PTR >ShortStep[BP]        ; else, ShortStep = -1 (go up or left)}
  298.   $F7/$D8/                            {          NEG    AX                             ;       shortdelta = abs(shortdelta)}
  299.                                       {PL2:}
  300.   $C7/$86/>LINESTART/$00/$00/         {          MOV    WORD PTR >LineStart[BP],0      ; assume no skip length}
  301.   $8B/$8E/>X1/                        {          MOV    CX,>X1[BP]                     ; x coordinate in CX}
  302.   $8B/$96/>Y1/                        {          MOV    DX,>Y1[BP]                     ; y coordinate in DX}
  303.   $39/$F0/                            {          CMP    AX,SI                          ; is shortdelta > LongDelta?}
  304.   $77/$40/                            {          JA     AltCode                        ; yes, use alternate draw code}
  305.                                       {;}
  306.                                       {;         Do following when line has slope between 0 and 1}
  307.                                       {;}
  308.   $89/$B6/>LINESTOP/                  {          MOV    >LineStop[BP],SI               ; assume length = LongDelta}
  309.   $89/$F7/                            {          MOV    DI,SI                          ; set up the cycle pointer}
  310.   $D1/$EF/                            {          SHR    DI,1                           ; cycle := LongDelta/2}
  311.   $89/$B6/>LONGDELTA/                 {          MOV    >LongDelta[BP],SI}
  312.   $BE/$00/$00/                        {          MOV    SI,0                           ; initialize loop counter}
  313.                                       {NormLoop:}
  314.   $3B/$B6/>LINESTART/                 {          CMP    SI,>LineStart[BP]              ; start to plot yet???}
  315.   $7C/$0D/                            {          JL     PL5                            ; no, skip}
  316.                                       {;}
  317.   $50/                                {          PUSH   AX                             ;Save registers}
  318.   $53/                                {          PUSH   BX}
  319.   $51/                                {          PUSH   CX}
  320.   $52/                                {          PUSH   DX}
  321.   $57/                                {          PUSH   DI}
  322.                                       {;}
  323.   $E8/$6E/$00/                        {          CALL   PlotDot                        ;Plot pixel}
  324.                                       {;}
  325.   $5F/                                {          POP    DI                             ;Restore registers}
  326.   $5A/                                {          POP    DX}
  327.   $59/                                {          POP    CX}
  328.   $5B/                                {          POP    BX}
  329.   $58/                                {          POP    AX}
  330.                                       {;}
  331.                                       {PL5:}
  332.   $03/$8E/>LONGSTEP/                  {          ADD    CX,>LongStep[BP]               ; always move along the X AXis}
  333.   $01/$C7/                            {          ADD    DI,AX                          ; cycle = cycle + shortdelta}
  334.   $3B/$BE/>LONGDELTA/                 {          CMP    DI,>LongDelta[BP]              ; is cycle >= LongDelta?}
  335.   $7C/$08/                            {          JL     PL6                            ; no skip (don't go along y yet}
  336.   $2B/$BE/>LONGDELTA/                 {          SUB    DI,>LongDelta[BP]              ; yes, reset cycle pointer}
  337.   $03/$96/>SHORTSTEP/                 {          ADD    DX,>ShortStep[BP]              ;       and bump the y coord}
  338.                                       {PL6:}
  339.   $46/                                {          INC    SI                             ; bump dot counter}
  340.   $3B/$B6/>LINESTOP/                  {          CMP    SI,>LineStop[BP]               ; done??}
  341.   $76/$D2/                            {          JBE    NormLoop                       ; no, plot next dot}
  342.   $E9/$A1/$00/                        {          JMP    PLExit                         ; yes, go to commom exit code}
  343.                                       {;}
  344.                                       {;         Do following when slope has absolute value > 1}
  345.                                       {;}
  346.                                       {AltCode:}
  347.   $96/                                {          XCHG   AX,SI                          ; swap LongDelta, shortdelta}
  348.   $8B/$BE/>LONGSTEP/                  {          MOV    DI,>LongStep[BP]               ;}
  349.   $87/$BE/>SHORTSTEP/                 {          XCHG   >ShortStep[BP],DI}
  350.   $89/$BE/>LONGSTEP/                  {          MOV    >LongStep[BP],DI               ; swap LongStep, ShortStep}
  351.   $89/$B6/>LINESTOP/                  {          MOV    >LineStop[BP],SI               ; assume length = LongDelta}
  352.   $89/$F7/                            {          MOV    DI,SI                          ; set up cycle pointer}
  353.   $D1/$EF/                            {          SHR    DI,1                           ; cycle := LongDelta/2}
  354.   $89/$B6/>LONGDELTA/                 {          MOV    >LongDelta[BP],SI}
  355.   $BE/$00/$00/                        {          MOV    SI,0                           ; initialize loop counter}
  356.                                       {AltLoop:}
  357.   $3B/$B6/>LINESTART/                 {          CMP    SI,>LineStart[BP]              ; start to plot yet?}
  358.   $7C/$0B/                            {          JL     PL8                            ; no, skip}
  359.                                       {;}
  360.   $50/                                {          PUSH   AX                             ;Save registers}
  361.   $51/                                {          PUSH   CX}
  362.   $52/                                {          PUSH   DX}
  363.   $57/                                {          PUSH   DI}
  364.                                       {;}
  365.   $E8/$22/$00/                        {          CALL   PlotDot                        ;Plot pixel}
  366.                                       {;}
  367.   $5F/                                {          POP    DI                             ;Restore registers}
  368.   $5A/                                {          POP    DX}
  369.   $59/                                {          POP    CX}
  370.   $58/                                {          POP    AX}
  371.                                       {;}
  372.                                       {PL8:}
  373.   $03/$96/>LONGSTEP/                  {          ADD    DX,>LongStep[BP]               ; always move along Y AXis}
  374.   $01/$C7/                            {          ADD    DI,AX                          ; cycle := cycle + shortdelta}
  375.   $3B/$BE/>LONGDELTA/                 {          CMP    DI,>LongDelta[BP]              ; is cycle >= long delta???}
  376.   $7C/$08/                            {          JL     PL9                            ; no, skip (don't move along x yet)}
  377.   $2B/$BE/>LONGDELTA/                 {          SUB    DI,>LongDelta[BP]              ; yes, reset cycle pointer}
  378.   $03/$8E/>SHORTSTEP/                 {          ADD    CX,>ShortStep[BP]              ;        and bump x coordinate}
  379.                                       {PL9:}
  380.   $46/                                {          INC    SI                             ; bump dot counter}
  381.   $3B/$B6/>LINESTOP/                  {          CMP    SI,>LineStop[BP]               ; done???}
  382.   $76/$D4/                            {          JBE    AltLoop                        ; no, plot next dot}
  383.   $E9/$56/$00/                        {          JMP    PLExit                         ; yes, go to common exit}
  384.                                       {;}
  385.                                       {PlotDot:  ;PROC   Near}
  386.                                       {;}
  387.                                       {;  Check if we are to use BIOS to plot pixel}
  388.                                       {;}
  389.   $F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ {         TEST    Byte [>Write_Graphics_Screen],1 ;Check if direct screen writes}
  390.   $74/$43/                            {         JZ      Bios                            ;No -- use BIOS}
  391.                                       {;}
  392.                                       {;  Write pixel directly to screen memory.}
  393.                                       {;  Determine if EGA or CGA and get Y offset.}
  394.                                       {;}
  395.   $F6/$06/>EGA_USE/$01/               {         TEST    Byte [>Ega_Use],1      ;Check if EGA used}
  396.   $74/$12/                            {         JZ      CGA                    ;No -- go figure CGA offset}
  397.                                       {;}
  398.   $89/$C8/                            {         MOV     AX,CX                  ;Save X}
  399.   $B1/$06/                            {         MOV     CL,6                   ;Shift count}
  400.   $89/$D3/                            {         MOV     BX,DX                  ;Copy Y}
  401.   $D3/$E2/                            {         SHL     DX,CL                  ;Y * 64}
  402.   $B1/$04/                            {         MOV     CL,4                   ;Shift count}
  403.   $D3/$E3/                            {         SHL     BX,CL                  ;Y * 16}
  404.   $01/$D3/                            {         ADD     BX,DX                  ;Y * 80 = offset for Y}
  405.   $89/$C1/                            {         MOV     CX,AX                  ;Restore X}
  406.   $EB/$0A/                            {         JMP     Short Both}
  407.                                       {;}
  408.   $8D/$1E/>SCAN_LINE_TABLE/           {CGA:     LEA     BX,[>Scan_Line_Table]          ; Get scan line table address}
  409.   $D1/$E2/                            {         SHL     DX,1                           ; Y * 2 for integer offset}
  410.   $01/$D3/                            {         ADD     BX,DX                          ; Get offset of entry for Y}
  411.   $8B/$1F/                            {         MOV     BX,[BX]                        ; Get offset for Y}
  412.                                       {;}
  413.   $89/$CA/                            {Both:    MOV     DX,CX                          ; Get X}
  414.   $89/$C8/                            {         MOV     AX,CX}
  415.   $B1/$03/                            {         MOV     CL,3                           ;}
  416.   $D3/$EA/                            {         SHR     DX,CL                          ; X DIV 8 = Byte offset in row}
  417.   $01/$D3/                            {         ADD     BX,DX                          ; Byte pos in screen memory}
  418.   $25/$07/$00/                        {         AND     AX,7                           ; X MOD 8}
  419.   $BA/$80/$00/                        {         MOV     DX,$80                         ; 1 bit in leftmost position}
  420.   $89/$C1/                            {         MOV     CX,AX                          ; shift count}
  421.   $D3/$EA/                            {         SHR     DX,CL                          ; 1 bit in proper position}
  422.   $C4/$3E/>GRAPHICS_SCREEN/           {         LES     DI,[>Graphics_Screen]          ; Get screen address}
  423.   $01/$DF/                            {         ADD     DI,BX                          ; Get byte address}
  424.   $26/$08/$15/                        {     ES: OR      BYTE PTR [DI],DL               ; Get byte to alter}
  425.   $E9/$0B/$00/                        {         JMP     Exit                           ; Return to caller}
  426.                                       {;}
  427.                                       {;  Plot pixel using BIOS}
  428.                                       {;}
  429.   $55/                                {Bios:    PUSH    BP                             ; Save BP in case BIOS zaps it}
  430.   $53/                                {         PUSH    BX                             ; Save BX}
  431.   $B7/$00/                            {         MOV     BH,0                           ; Page 0 always}
  432.   $B8/$01/$0C/                        {         MOV     AX,$0C01                       ; Plot pixel function}
  433.   $CD/$10/                            {         INT     $10                            ; Plot the pixel via BIOS}
  434.   $5B/                                {         POP     BX                             ; Restore BX}
  435.   $5D/                                {         POP     BP                             ; Restore BP}
  436.                                       {;}
  437.                                       {Exit:}
  438.   $C3);                               {         RET}
  439.                                       {;}
  440.                                       {PLExit:}
  441.  
  442.                                    (* Restore timesharing mode *)
  443.  
  444.    IF ( MultiTasker = DoubleDos ) THEN
  445.       TurnOnTimeSharing;
  446.  
  447. END   (* Draw_Line *);
  448.  
  449. (*----------------------------------------------------------------------*)
  450. (*          Plot_Char --- Interpret current char as text to display     *)
  451. (*----------------------------------------------------------------------*)
  452.  
  453. PROCEDURE Plot_Char( Ch: CHAR; X: INTEGER; Y: INTEGER );
  454.  
  455. VAR
  456.    I         : INTEGER;
  457.    K1        : INTEGER;
  458.    K2        : INTEGER;
  459.    XB        : INTEGER;
  460.    XO        : INTEGER;
  461.    XO1       : INTEGER;
  462.    XS        : INTEGER;
  463.    XSL       : INTEGER;
  464.    Do_XOR    : BOOLEAN;
  465.                                    (* Holds point plot routine offset *)
  466. (* STRUCTURED *) CONST
  467.    Plot_Pixel_Function : WORD = 0;
  468.  
  469.                                    (* Shape table for characters *)
  470. (* STRUCTURED *) CONST
  471.    Char_Bits_Table: ARRAY[0..581] OF BYTE =
  472.                     (     0,   0,   0,   0,   0,   0,
  473.                           0,  96,   0,  96,  96,  96,
  474.                           0,   0,   0,   0, 216, 216,
  475.                           0,  80, 248,  80, 248,  80,
  476.                           0, 240,  40, 112, 160, 120,
  477.                           0, 152,  88,  32, 208, 200,
  478.                           0,  16, 120, 144, 144, 112,
  479.                           0,   0,   0,  32,  48,  48,
  480.                           0,  32,  64,  64,  64,  32,
  481.                           0,  64,  32,  32,  32,  64,
  482.                           0, 136,  80, 248,  80, 136,
  483.                           0,  32,  32, 248,  32,  32,
  484.                           0,  64,  96,   0,   0,   0,
  485.                           0,   0,   0, 240,   0,   0,
  486.                           0,  24,  24,   0,   0,   0,
  487.                           0, 128,  64,  32,  16,   8,
  488.                           0, 112, 136, 168, 136, 112,
  489.                           0, 112,  32,  32,  96,  32,
  490.                           0, 248,  96,  16, 136, 112,
  491.                           0, 112, 136,  48, 136, 112,
  492.                           0,  16, 248, 144,  80,  32,
  493.                           0, 240,   8, 240, 128, 248,
  494.                           0, 112, 136, 240, 128, 112,
  495.                           0,  64,  32,  16,   8, 120,
  496.                           0, 112, 136, 112, 136, 112,
  497.                           0, 112,   8, 120, 136, 112,
  498.                           0,  96,  96,   0,  96,  96,
  499.                           0,  64,  96,   0,  96,  96,
  500.                           0,  16,  32,  64,  32,  16,
  501.                           0,   0, 240,   0, 240,   0,
  502.                           0,  64,  32,  16,  32,  64,
  503.                           0,  32,  32,  48, 136, 112,
  504.                           0, 112, 128, 176, 136, 112,
  505.                           0, 136, 248, 136,  80,  32,
  506.                           0, 240, 136, 240, 136, 240,
  507.                           0, 120, 128, 128, 128, 120,
  508.                           0, 240, 136, 136, 136, 240,
  509.                           0, 248, 128, 240, 128, 248,
  510.                           0, 128, 128, 240, 128, 248,
  511.                           0, 120, 136, 184, 128, 120,
  512.                           0, 136, 136, 248, 136, 136,
  513.                           0, 112,  32,  32,  32, 112,
  514.                           0, 112, 136,   8,   8,   8,
  515.                           0, 136, 144, 224, 144, 136,
  516.                           0, 248, 128, 128, 128, 128,
  517.                           0, 136, 136, 168, 216, 136,
  518.                           0, 136, 152, 168, 200, 136,
  519.                           0, 112, 136, 136, 136, 112,
  520.                           0, 128, 128, 240, 136, 240,
  521.                           0, 104, 152, 168, 136, 112,
  522.                           0, 152, 144, 240, 136, 240,
  523.                           0, 240,   8, 112, 128, 120,
  524.                           0,  32,  32,  32,  32, 248,
  525.                           0, 112, 136, 136, 136, 136,
  526.                           0,  32, 112, 136, 136, 136,
  527.                           0, 136, 216, 168, 136, 136,
  528.                           0, 136,  80,  32,  80, 136,
  529.                           0,  32,  32,  32,  80, 136,
  530.                           0, 248,  64,  32,  16, 248,
  531.                           0, 120,  96,  96,  96, 120,
  532.                           0,   8,  16,  32,  64, 128,
  533.                           0, 120,  24,  24,  24, 120,
  534.                           0,   0,   0, 136,  80,  32,
  535.                           0,   0, 248,   0,   0,   0,
  536.                           0,   0,   0,  32,  96,  96,
  537.                           0, 136, 248, 136,  80,  32,
  538.                           0, 240, 136, 240, 136, 240,
  539.                           0, 120, 128, 128, 128, 120,
  540.                           0, 240, 136, 136, 136, 240,
  541.                           0, 248, 128, 240, 128, 248,
  542.                           0, 128, 128, 240, 128, 248,
  543.                           0, 120, 136, 184, 128, 120,
  544.                           0, 136, 136, 248, 136, 136,
  545.                           0, 112,  32,  32,  32, 112,
  546.                           0, 112, 136,   8,   8,   8,
  547.                           0, 136, 144, 224, 144, 136,
  548.                           0, 248, 128, 128, 128, 128,
  549.                           0, 136, 136, 168, 216, 136,
  550.                           0, 136, 152, 168, 200, 136,
  551.                           0, 112, 136, 136, 136, 112,
  552.                           0, 128, 128, 240, 136, 240,
  553.                           0, 104, 152, 168, 136, 112,
  554.                           0, 152, 144, 240, 136, 240,
  555.                           0, 240,   8, 112, 128, 120,
  556.                           0,  32,  32,  32,  32, 248,
  557.                           0, 112, 136, 136, 136, 136,
  558.                           0,  32, 112, 136, 136, 136,
  559.                           0, 136, 216, 168, 136, 136,
  560.                           0, 136,  80,  32,  80, 136,
  561.                           0,  32,  32,  32,  80, 136,
  562.                           0, 248,  64,  32,  16, 248,
  563.                           0,   0,   0,   0,   0,   0,
  564.                           0,   0,   0,   0,   0,   0,
  565.                           0,   0,   0,   0,   0,   0,
  566.                           0,   0,   0,   0,   0,   0,
  567.                           0,   0,   0,   0,   0,   0,
  568.                           0, 124, 124, 124, 124, 124 );
  569.  
  570. BEGIN (* Plot_Char *)
  571.                                    (* Use XOR rather than OR for *)
  572.                                    (* the cursor.                *)
  573.    Do_XOR := ( ORD( Ch ) = 128 );
  574.  
  575.    IF Write_Graphics_Screen THEN
  576.       BEGIN
  577.                                    (* Turn off timesharing while drawing *)
  578.  
  579.          IF ( MultiTasker = DoubleDos ) THEN
  580.             BEGIN
  581.                TurnOffTimeSharing;
  582.                Get_Screen_Address( Graphics_Screen );
  583.             END;
  584.                                    (* Get byte offset in row *)
  585.          XB  := SUCC( X SHR 3 );
  586.                                    (* Get bit offset within byte *)
  587.          XS  := X AND 7;
  588.          XSL := 8 - XS;
  589.                                    (* Get offset of character bit *)
  590.                                    (* pattern.                    *)
  591.  
  592.          K1  := ( ORD( Ch ) - 32 ) * 6;
  593.          K2  := K1 + 5;
  594.  
  595.                                    (* OR/XOR in bits of new character. *)
  596.                                    (* If X is even byte address, then  *)
  597.                                    (* simply loop over rows in the     *)
  598.                                    (* character.  If X is not even     *)
  599.                                    (* byte address, we need to store   *)
  600.                                    (* part of pattern in two success-  *)
  601.                                    (* ive bytes.                       *)
  602.  
  603.          IF ( XS = 0 ) THEN
  604.             WITH Graphics_Screen^ DO
  605.                FOR I := K1 TO K2 DO
  606.                   BEGIN
  607.                      CASE EGA_Use OF
  608.                         FALSE: XO := Scan_Line_Table[ Y ] + XB;
  609.                         TRUE : XO := ( Y * 80 ) + XB;
  610.                      END (* CASE *);
  611.                      IF Do_XOR THEN
  612.                         Screen_Image[ XO ] := Screen_Image[ XO ] XOR
  613.                                               Char_Bits_Table[ I ]
  614.                      ELSE
  615.                         Screen_Image[ XO ] := Screen_Image[ XO ] OR
  616.                                               Char_Bits_Table[ I ];
  617.                      Y := PRED( Y );
  618.                   END
  619.          ELSE
  620.             WITH Graphics_Screen^ DO
  621.                FOR I := K1 TO K2 DO
  622.                   BEGIN
  623.                      CASE EGA_Use OF
  624.                         FALSE: XO := Scan_Line_Table[ Y ] + XB;
  625.                         TRUE : XO := ( Y * 80 ) + XB;
  626.                      END (* CASE *);
  627.                      XO1 := SUCC( XO );
  628.                      IF Do_XOR THEN
  629.                         BEGIN
  630.                            Screen_Image[ XO  ] := Screen_Image[ XO  ] XOR
  631.                                                   ( Char_Bits_Table[ I ] SHR XS );
  632.                            Screen_Image[ XO1 ] := Screen_Image[ XO1 ] XOR
  633.                                                   ( Char_Bits_Table[ I ] SHL XSL );
  634.                         END
  635.                      ELSE
  636.                         BEGIN
  637.                            Screen_Image[ XO  ] := Screen_Image[ XO  ] OR
  638.                                                   ( Char_Bits_Table[ I ] SHR XS );
  639.                            Screen_Image[ XO1 ] := Screen_Image[ XO1 ] OR
  640.                                                   ( Char_Bits_Table[ I ] SHL XSL );
  641.                         END;
  642.                      Y := PRED( Y );
  643.                   END;
  644.  
  645.                                    (* Restore timesharing mode *)
  646.  
  647.          IF ( MultiTasker = DoubleDos ) THEN
  648.             TurnOnTimeSharing;
  649.  
  650.       END
  651.    ELSE
  652.       BEGIN (* Plot through BIOS the hard way *)
  653.  
  654.          IF Do_XOR THEN
  655.             Plot_Pixel_Function := $0C81
  656.          ELSE
  657.             Plot_Pixel_Function := $0C01;
  658.  
  659. INLINE(
  660.   $8B/$86/>X/               {         MOV     AX,[BP+>X]                 ;Get X position}
  661.   $48/                      {         DEC     AX                         ;Decrement for 0 offset later}
  662.   $89/$C6/                  {         MOV     SI,AX                      ;Save X position}
  663.                             {;}
  664.   $8B/$86/>Y/               {         MOV     AX,[BP+>Y]                 ;Get Y position}
  665.   $89/$C7/                  {         MOV     DI,AX                      ;Save Y position}
  666.                             {;}
  667.   $31/$C0/                  {         XOR     AX,AX                      ;Clear AX}
  668.   $8A/$46/<CH/              {         MOV     AL,[BP+<Ch]                ;Pick up character to display}
  669.   $2D/$20/$00/              {         SUB     AX,32                      ;Convert to 0 offset}
  670.   $89/$C3/                  {         MOV     BX,AX}
  671.   $D1/$E0/                  {         SHL     AX,1                       ;Offset * 2}
  672.   $D1/$E0/                  {         SHL     AX,1                       ;Offset * 4}
  673.   $01/$D8/                  {         ADD     AX,BX                      ;Offset * 5}
  674.   $01/$C3/                  {         ADD     BX,AX                      ;Offset * 6 = offset into shape table}
  675.   $8D/$06/>CHAR_BITS_TABLE/ {         LEA     AX,[<Char_Bits_Table]      ;Get address of shape table}
  676.   $01/$C3/                  {         ADD     BX,AX                      ;Get starting address this character}
  677.                             {;}
  678.   $B9/$06/$00/              {         MOV     CX,6                       ;Loop over rows in character}
  679.                             {;}
  680.   $51/                      {Char1:   PUSH    CX                         ;Save loop counter for rows}
  681.   $53/                      {         PUSH    BX                         ;Save table offset}
  682.                             {;}
  683.   $8A/$07/                  {         MOV     AL,[BX]                    ;Get bit pattern for this row}
  684.   $08/$C0/                  {         OR      AL,AL                      ;Check if any bits on in this row}
  685.   $74/$22/                  {         JZ      Char4                      ;No -- skip display this row}
  686.                             {;}
  687.   $B9/$08/$00/              {         MOV     CX,8                       ;Loop over bits this row}
  688.                             {;}
  689.   $51/                      {Char2:   PUSH    CX                         ;Save loop counter for bits}
  690.                             {;}
  691.   $A8/$01/                  {         TEST    AL,1                       ;See if "this" bit is turned on}
  692.   $74/$15/                  {         JZ      Char3                      ;No -- skip to next bit}
  693.                             {;}
  694.   $50/                      {         PUSH    AX                         ;Save bit mask}
  695.   $56/                      {         PUSH    SI                         ;Save X}
  696.   $57/                      {         PUSH    DI                         ;Save Y}
  697.                             {;}
  698.   $89/$F0/                  {         MOV     AX,SI                      ;Get X}
  699.   $01/$C1/                  {         ADD     CX,AX                      ;Add offset}
  700.   $A1/>PLOT_PIXEL_FUNCTION/ {         MOV     AX,[>Plot_Pixel_Function]  ;Plot pixel function}
  701.   $89/$FA/                  {         MOV     DX,DI                      ;Get vertical position}
  702.   $B7/$00/                  {         MOV     BH,0                       ;Always page 0}
  703.   $55/                      {         PUSH    BP                         ;Save BP in case BIOS clobbers it}
  704.   $CD/$10/                  {         INT     $10                        ;Plot the pixel via BIOS}
  705.   $5D/                      {         POP     BP                         ;Restore BP}
  706.                             {;}
  707.   $5F/                      {         POP     DI                         ;Restore Y}
  708.   $5E/                      {         POP     SI                         ;Restore X}
  709.   $58/                      {         POP     AX                         ;Restore bit mask}
  710.                             {;}
  711.   $D0/$E8/                  {Char3:   SHR     AL,1                       ;Shift bit mask to next bit}
  712.   $59/                      {         POP     CX                         ;Retrieve bits counter}
  713.   $E2/$E1/                  {         LOOP    Char2                      ;and try next bit}
  714.                             {;}
  715.   $5B/                      {Char4:   POP     BX                         ;Retrieve table offset}
  716.   $43/                      {         INC     BX                         ;Point to next shape table byte}
  717.   $89/$F8/                  {         MOV     AX,DI                      ;Decrement Y}
  718.   $48/                      {         DEC     AX                         ;  ...}
  719.   $89/$C7/                  {         MOV     DI,AX                      ;  ...}
  720.   $59/                      {         POP     CX                         ;Retrieve rows counter}
  721.   $E2/$CC);                 {         LOOP    Char1                      ;and try next row}
  722.  
  723.       END;
  724.  
  725. END   (* Plot_Char *);
  726.  
  727. (*----------------------------------------------------------------------*)
  728. (*               Display_Cursor  --- Display block cursor               *)
  729. (*----------------------------------------------------------------------*)
  730.  
  731. PROCEDURE Display_Cursor( X, Y: INTEGER );
  732.  
  733. BEGIN (* Display_Cursor *)
  734.                                    (* Don't display cursor while plotting *)
  735.  
  736.    IF ( FlagG = Text_Plot ) THEN
  737.       Plot_Char( CHR( 128 ) , X , Y );
  738.  
  739. END   (* Display_Cursor *);
  740.  
  741. (*----------------------------------------------------------------------*)
  742. (*           Display_Graphics --- show character received from port     *)
  743. (*----------------------------------------------------------------------*)
  744.  
  745. PROCEDURE Display_Graphics( VAR Ch : CHAR );
  746.  
  747. (*----------------------------------------------------------------------*)
  748. (*                                                                      *)
  749. (*     Procedure:  Display_Graphics                                     *)
  750. (*                                                                      *)
  751. (*     Purpose:    Displays character received from comm. port on       *)
  752. (*                 screen/printer/capture file.                         *)
  753. (*                                                                      *)
  754. (*     Calling Sequence:                                                *)
  755. (*                                                                      *)
  756. (*        Display_Graphics( Ch : CHAR );                                *)
  757. (*                                                                      *)
  758. (*           Ch         --- Character received from Comm. port.         *)
  759. (*                                                                      *)
  760. (*      Calls:   Async_Receive                                          *)
  761. (*               Min                                                    *)
  762. (*               Update_Review_Pointers                                 *)
  763. (*               TimeOfDay                                              *)
  764. (*               TimeDiff                                               *)
  765. (*                                                                      *)
  766. (*      Remarks:                                                        *)
  767. (*                                                                      *)
  768. (*         This routine strips out certain characters which             *)
  769. (*         should not be displayed, implements the XON/XOFF protocol    *)
  770. (*         in a simple-minded manner, performs output wrap, and saves   *)
  771. (*         output line in the review the review buffer.                 *)
  772. (*                                                                      *)
  773. (*----------------------------------------------------------------------*)
  774.  
  775.  
  776. (* STRUCTURED *) CONST
  777.    CR_Ch   : CHAR = ^M;
  778.    LF_Ch   : CHAR = ^J;
  779.    BL_Ch   : CHAR = ' ';
  780.  
  781. VAR
  782.    I    : INTEGER;
  783.    L    : INTEGER;
  784.    Xpos : INTEGER;
  785.    Ypos : INTEGER;
  786.    C    : INTEGER;
  787.    KeyC : CHAR;
  788.    TT   : Transfer_Type;
  789.  
  790. (*----------------------------------------------------------------------*)
  791. (*          Do_Graphics --- Interpret current char as graphics command  *)
  792. (*----------------------------------------------------------------------*)
  793.  
  794. PROCEDURE Do_Graphics;
  795.  
  796. BEGIN (* Do_Graphics *)
  797.                                    (* Get previous character and *)
  798.                                    (* save current character     *)
  799.    Old     := ORD( Prev_Ch );
  800.    Prev_Ch := Ch;
  801.                                    (* Set first X corrdinate     *)
  802.  
  803.    IF ( C > 31 ) AND ( C < 64 ) AND ( Old > 95 ) AND ( Old < 128 ) THEN
  804.       BEGIN
  805.          Hx      := C;
  806.          EXIT;
  807.       END;
  808.                                    (* Set first Y coordinate     *)
  809.  
  810.    IF ( C > 31 ) AND ( C < 64 ) THEN
  811.       BEGIN
  812.          Hy      := C;
  813.          EXIT;
  814.       END;
  815.                                    (* Set second Y coordinate    *)
  816.  
  817.    IF ( C > 95 ) AND ( C < 128 ) THEN
  818.       BEGIN
  819.          Ly      := C;
  820.          EXIT;
  821.       END;
  822.                                    (* Set second X coordinate, and *)
  823.                                    (* plot point if necessary.     *)
  824.  
  825.    IF ( C > 63 ) AND ( C < 96 ) THEN
  826.       BEGIN
  827.  
  828.          Lx      := C;
  829.                                    (* Get PC screen position of point *)
  830.  
  831.          XPos    := TRUNC( XFactor * ( ( Hx - 32 ) * 32 + Lx - 64 ));
  832.          YPos    := YMax - TRUNC( YFactor * ( ( Hy - 32 ) * 32 + Ly - 96 ));
  833.  
  834.                                    (* Turn off timesharing while drawing *)
  835.  
  836.          IF ( MultiTasker = DoubleDos ) THEN
  837.             BEGIN
  838.                TurnOffTimeSharing;
  839.                Get_Screen_Address( Graphics_Screen );
  840.             END;
  841.                                    (* First coordinate -- just move *)
  842.                                    (* to it                         *)
  843.  
  844.          CASE FlagG OF
  845.             Vector_Plot      : Draw_Line( Graphics_XPos, Graphics_YPos,
  846.                                           XPos, YPos );
  847.             Vector_Plot_Start: FlagG   := Vector_Plot;
  848.             Point_Plot       : Plot_Point( XPos, YPos );
  849.             Point_Plot_Start : FlagG   := Point_Plot;
  850.             ELSE;
  851.          END (* CASE *);
  852.  
  853.                                    (* Restore timesharing mode *)
  854.  
  855.          IF ( MultiTasker = DoubleDos ) THEN
  856.             TurnOnTimeSharing;
  857.                                    (* Update graphics position *)
  858.          Graphics_XPos := XPos;
  859.          Graphics_YPos := YPos;
  860.  
  861.       END;
  862.  
  863. END   (* Do_Graphics *);
  864.  
  865.