Category : Pascal Source Code
Archive   : PIBT41S2.ZIP
Filename : PIB4010A.MOD

 
Output of file : PIB4010A.MOD contained in archive : PIBT41S2.ZIP
PROCEDURE Emulate_TEK4010;

(*----------------------------------------------------------------------*)
(* Emulate_TEK4010 --- Emulate TekTronix 4010 terminal *)
(*----------------------------------------------------------------------*)
(* *)
(* Author: Philip R. Burns *)
(* Date: April, 1986 (Version 1.0) *)
(* January, 1988 (Version 4.1 -- add EGA support) *)
(* *)
(* Systems: For MS-DOS on IBM PCs and close compatibles only. *)
(* *)
(* History: Original with me. *)
(* *)
(* This emulator uses the high-resolution graphics mode *)
(* (640x200) of the standard IBM color graphics adapter, *)
(* or the high-resolution mode of the EGA (640x350). *)
(* Only graphics output is emulated, not graphics input. *)
(* On the CGA, the display consists of 33 rather than 35 *)
(* lines of text, while on the EGA 35 lines are displayed. *)
(* *)
(* Suggestions for improvements or corrections are welcome. *)
(* Please leave messages on Gene Plantz's BBS (312) 882 4145 *)
(* or Ron Fox's BBS (312) 940 6496. *)
(* *)
(* IF you use this code in your own programs, please be nice *)
(* and give proper credit. *)
(* *)
(*----------------------------------------------------------------------*)

TYPE
Graphics_State = ( Text_Plot, Vector_Plot_Start, Vector_Plot,
Point_Plot_Start, Point_Plot, Graphics_Input );

VAR
Done : BOOLEAN (* TRUE to exit terminal emulation mode *);
Ch : CHAR (* Character read/written *);
B : BOOLEAN (* Boolean flag *);
Regs : Registers (* For MS DOS interfacing *);
FlagG : Graphics_State (* Current graphics state *);
CursorX : INTEGER (* X position of cursor *);
CursorY : INTEGER (* Y position of cursor *);
Reset_T : BOOLEAN (* Dummy for reset of terminal *);
EGA_On : BOOLEAN (* TRUE if EGA installed *);
XFactor : REAL (* Horizontal scaling factor *);
YFactor : REAL (* Vertical scaling factor *);
YMax : INTEGER (* Maximum Y value ==> 199, 349 *);
YMaxM1 : INTEGER (* Maximum Y value - 1 ==> 198, 348 *);
YInc : INTEGER (* Increment in Y for characters *);
GMode : INTEGER (* Graphics mode type *);
ClrScr_Req : BOOLEAN (* TRUE if clear screen request typed *);
Save_SUpper: BOOLEAN (* Save send_upper_case_only flag *);

CONST
Prev_Ch : CHAR = ^@;
Hx : INTEGER = 0;
Hy : INTEGER = 0;
Lx : INTEGER = 0;
Ly : INTEGER = 0;
Old : INTEGER = 0;
LeftH : BOOLEAN = TRUE;
LastX : INTEGER = 0;
LastY : INTEGER = 0;
YDist : INTEGER = 6;

CONST
Ch_FF = #12 (* Form Feed *);
Ch_CR = #13 (* Carriage Return *);
Ch_SO = #14 (* Start grahics *);
Ch_SI = #15 (* End graphics *);
Ch_SUB = #26 (* EOF Character *);
Ch_ESC = #27 (* Escape *);
Ch_FS = #28 (* Graphics start *);
Ch_GS = #29 (* Graphics start *);
Ch_RS = #30 (* Inc. plot start *);
Ch_US = #31 (* Graphics end *);

(*----------------------------------------------------------------------*)
(* Plot_Point --- Plot one point in graphics display *)
(*----------------------------------------------------------------------*)

PROCEDURE Plot_Point( X , Y: INTEGER );

(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Plot_Point *)
(* *)
(* Purpose: Plots one pixel in high-resolution graphics screen. *)
(* *)
(* Calling Sequence: *)
(* *)
(* Plot_Point( X , Y : INTEGER ); *)
(* *)
(* X --- Horizontal coordinate (0--639) *)
(* Y --- Vertical coordinate (0--349) *)
(* *)
(*----------------------------------------------------------------------*)

BEGIN (* Plot_Point *)

INLINE(
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
$F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ { TEST Byte [>Write_Graphics_Screen],1 ;Check if direct scren writes}
$74/$30/ { JZ Bios ;No -- use BIOS}
{;}
{; Write pixel directly to screen memory}
{;}
$8B/$96/>Y/ { MOV DX,[BP+>Y] ; Get Y}
$8D/$1E/>SCAN_LINE_TABLE/ { LEA BX,[>Scan_Line_Table] ; Get scan line table address}
$D1/$E2/ { SHL DX,1 ; Y * 2 for integer offset}
$01/$D3/ { ADD BX,DX ; Get offset of entry for Y}
$8B/$1F/ { MOV BX,[BX] ; Get offset for Y}
{;}
$8B/$96/>X/ { MOV DX,[BP+>X] ; Get X}
$89/$D0/ { MOV AX,DX}
$B1/$03/ { MOV CL,3 ;}
$D3/$EA/ { SHR DX,CL ; X DIV 8 = Byte offset within row}
$01/$D3/ { ADD BX,DX ; Byte location in screen memory}
$25/$07/$00/ { AND AX,7 ; X MOD 8}
$BA/$80/$00/ { MOV DX,$80 ; 1 bit in leftmost position}
$89/$C1/ { MOV CX,AX ; shift count}
$D3/$EA/ { SHR DX,CL ; 1 bit in proper position}
$C4/$3E/>GRAPHICS_SCREEN/ { LES DI,[>Graphics_Screen] ; Get screen address}
$01/$DF/ { ADD DI,BX ; Get byte address}
$26/$08/$15/ { ES: OR BYTE PTR [DI],DL ; Get byte to alter}
$E9/$13/$00/ { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
$55/ {Bios: PUSH BP ; Save BP in case BIOS zaps it}
$1E/ { PUSH DS}
$B8/$01/$0C/ { MOV AX,$0C01 ; Plot pixel function}
$8B/$8E/>X/ { MOV CX,[BP+>X] ; Get horizontal position}
$8B/$96/>Y/ { MOV DX,[BP+>Y] ; Get vertical position}
$B7/$00/ { MOV BH,0 ; Always page 0}
$CD/$10/ { INT $10 ; Plot the pixel via BIOS}
$1F/ { POP DS}
$5D); { POP BP ; Restore BP}
{;}
{Exit:}

END (* Plot_Point *);

(*----------------------------------------------------------------------*)
(* XOR_Plot_Point --- Plot one point in graphics display using XOR *)
(*----------------------------------------------------------------------*)

PROCEDURE XOR_Plot_Point( X , Y: INTEGER );

(*----------------------------------------------------------------------*)
(* *)
(* Procedure: XOR_Plot_Point *)
(* *)
(* Purpose: Plots one pixel in high-res graphics using XOR. *)
(* *)
(* Calling Sequence: *)
(* *)
(* XOR_Plot_Point( X , Y : INTEGER ); *)
(* *)
(* X --- Horizontal coordinate (0--639) *)
(* Y --- Vertical coordinate (0--199) *)
(* *)
(*----------------------------------------------------------------------*)

BEGIN (* XOR_Plot_Point *)

INLINE(
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
$F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ { TEST Byte [>Write_Graphics_Screen],1 ;Check if direct scren writes}
$74/$30/ { JZ Bios ;No -- use BIOS}
{;}
{; Write pixel directly to screen memory}
{;}
$8B/$96/>Y/ { MOV DX,[BP+>Y] ; Get Y}
$8D/$1E/>SCAN_LINE_TABLE/ { LEA BX,[>Scan_Line_Table] ; Get scan line table address}
$D1/$E2/ { SHL DX,1 ; Y * 2 for integer offset}
$01/$D3/ { ADD BX,DX ; Get offset of entry for Y}
$8B/$1F/ { MOV BX,[BX] ; Get offset for Y}
{;}
$8B/$96/>X/ { MOV DX,[BP+>X] ; Get X}
$89/$D0/ { MOV AX,DX}
$B1/$03/ { MOV CL,3 ;}
$D3/$EA/ { SHR DX,CL ; X DIV 8 = Byte offset within row}
$01/$D3/ { ADD BX,DX ; Byte location in screen memory}
$25/$07/$00/ { AND AX,7 ; X MOD 8}
$BA/$80/$00/ { MOV DX,$80 ; 1 bit in leftmost position}
$89/$C1/ { MOV CX,AX ; shift count}
$D3/$EA/ { SHR DX,CL ; 1 bit in proper position}
$C4/$3E/>GRAPHICS_SCREEN/ { LES DI,[>Graphics_Screen] ; Get screen address}
$01/$DF/ { ADD DI,BX ; Get byte address}
$26/$08/$15/ { ES: OR BYTE PTR [DI],DL ; Get byte to alter}
$E9/$13/$00/ { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
$55/ {Bios: PUSH BP ; Save BP in case BIOS zaps it}
$1E/ { PUSH DS}
$B8/$81/$0C/ { MOV AX,$0C81 ; Plot pixel function}
$8B/$8E/>X/ { MOV CX,[BP+>X] ; Get horizontal position}
$8B/$96/>Y/ { MOV DX,[BP+>Y] ; Get vertical position}
$B7/$00/ { MOV BH,0 ; Always page 0}
$CD/$10/ { INT $10 ; Plot the pixel via BIOS}
$1F/ { POP DS}
$5D); { POP BP ; Restore BP}
{;}
{Exit:}

END (* XOR_Plot_Point *);

(*----------------------------------------------------------------------*)
(* Clear_Graphics_Screen --- Clear screen and home cursor *)
(*----------------------------------------------------------------------*)

PROCEDURE Clear_Graphics_Screen;

BEGIN (* Clear_Graphics_Screen *)

Set_Graphics_Colors( EGA_On,
GMode,
Graphics_Foreground_Color,
Graphics_BackGround_Color );

(* Move cursor to upper left-hand *)
(* cursor. *)
Graphics_XPos := 0;
Graphics_YPos := 5;

CursorX := 0;
CursorY := 5;

LeftH := TRUE;
Prev_Ch := CHR( 0 );

END (* Clear_Graphics_Screen *);

(*--------------------------------------------------------------------------*)
(* Draw_Line -- Draw line between two points, low res. mode *)
(*--------------------------------------------------------------------------*)

PROCEDURE Draw_Line( X1, Y1, X2, Y2: INTEGER );

(*--------------------------------------------------------------------------*)
(* *)
(* Procedure: Draw_Line *)
(* *)
(* Purpose: Draws line between two points in hi-res. graphics mode *)
(* *)
(* Calling Sequence: *)
(* *)
(* Draw_Line( X1 , Y1 , X2, Y2, LineCol : INTEGER ); *)
(* *)
(* X1 -- Horizontal postion (0 through 639), 1st point *)
(* Y1 -- Vertical position (0 through 119), 1st point *)
(* X2 -- Horizontal postion (0 through 639), 2nd point *)
(* Y2 -- Vertical position (0 through 119), 2nd point *)
(* *)
(* Calls: TurnOnTimeSharing *)
(* TurnOffTimeSharing *)
(* Get_Screen_Address *)
(* *)
(* Remarks: An incremental plotter algorithm is used. *)
(* *)
(*--------------------------------------------------------------------------*)

VAR
LongDelta : INTEGER;
LongStep : INTEGER;
ShortStep : INTEGER;
LineStart : INTEGER;
LineStop : INTEGER;

BEGIN (* Draw_Line *)
(* Turn off timesharing while drawing *)

IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;

INLINE(
$C7/$86/>LONGSTEP/$01/$00/ { MOV WORD PTR >LongStep[BP],1 ; assume motion down or right}
$8B/$B6/>X2/ { MOV SI,>X2[BP]}
$2B/$B6/>X1/ { SUB SI,>X1[BP] ; get BP := LongDelta}
$7D/$06/ { JGE PL1 ; if X1 <= X2 then no change}
$F7/$9E/>LONGSTEP/ { NEG WORD PTR >LongStep[BP] ; ELSE LongStep := -1 (go up or left)}
$F7/$DE/ { NEG SI ; LongDelta = abs(LongDelta)}
{PL1:}
$C7/$86/>SHORTSTEP/$01/$00/ { MOV WORD PTR >ShortStep[BP],1 ; assume motion down or right}
$8B/$86/>Y2/ { MOV AX,>Y2[BP]}
$2B/$86/>Y1/ { SUB AX,>Y1[BP] ; get AX := shortdelta}
$7D/$06/ { JGE PL2 ; if y1 <= y2 then no change}
$F7/$9E/>SHORTSTEP/ { NEG WORD PTR >ShortStep[BP] ; else, ShortStep = -1 (go up or left)}
$F7/$D8/ { NEG AX ; shortdelta = abs(shortdelta)}
{PL2:}
$C7/$86/>LINESTART/$00/$00/ { MOV WORD PTR >LineStart[BP],0 ; assume no skip length}
$8B/$8E/>X1/ { MOV CX,>X1[BP] ; x coordinate in CX}
$8B/$96/>Y1/ { MOV DX,>Y1[BP] ; y coordinate in DX}
$39/$F0/ { CMP AX,SI ; is shortdelta > LongDelta?}
$77/$40/ { JA AltCode ; yes, use alternate draw code}
{;}
{; Do following when line has slope between 0 and 1}
{;}
$89/$B6/>LINESTOP/ { MOV >LineStop[BP],SI ; assume length = LongDelta}
$89/$F7/ { MOV DI,SI ; set up the cycle pointer}
$D1/$EF/ { SHR DI,1 ; cycle := LongDelta/2}
$89/$B6/>LONGDELTA/ { MOV >LongDelta[BP],SI}
$BE/$00/$00/ { MOV SI,0 ; initialize loop counter}
{NormLoop:}
$3B/$B6/>LINESTART/ { CMP SI,>LineStart[BP] ; start to plot yet???}
$7C/$0D/ { JL PL5 ; no, skip}
{;}
$50/ { PUSH AX ;Save registers}
$53/ { PUSH BX}
$51/ { PUSH CX}
$52/ { PUSH DX}
$57/ { PUSH DI}
{;}
$E8/$6E/$00/ { CALL PlotDot ;Plot pixel}
{;}
$5F/ { POP DI ;Restore registers}
$5A/ { POP DX}
$59/ { POP CX}
$5B/ { POP BX}
$58/ { POP AX}
{;}
{PL5:}
$03/$8E/>LONGSTEP/ { ADD CX,>LongStep[BP] ; always move along the X AXis}
$01/$C7/ { ADD DI,AX ; cycle = cycle + shortdelta}
$3B/$BE/>LONGDELTA/ { CMP DI,>LongDelta[BP] ; is cycle >= LongDelta?}
$7C/$08/ { JL PL6 ; no skip (don't go along y yet}
$2B/$BE/>LONGDELTA/ { SUB DI,>LongDelta[BP] ; yes, reset cycle pointer}
$03/$96/>SHORTSTEP/ { ADD DX,>ShortStep[BP] ; and bump the y coord}
{PL6:}
$46/ { INC SI ; bump dot counter}
$3B/$B6/>LINESTOP/ { CMP SI,>LineStop[BP] ; done??}
$76/$D2/ { JBE NormLoop ; no, plot next dot}
$E9/$A1/$00/ { JMP PLExit ; yes, go to commom exit code}
{;}
{; Do following when slope has absolute value > 1}
{;}
{AltCode:}
$96/ { XCHG AX,SI ; swap LongDelta, shortdelta}
$8B/$BE/>LONGSTEP/ { MOV DI,>LongStep[BP] ;}
$87/$BE/>SHORTSTEP/ { XCHG >ShortStep[BP],DI}
$89/$BE/>LONGSTEP/ { MOV >LongStep[BP],DI ; swap LongStep, ShortStep}
$89/$B6/>LINESTOP/ { MOV >LineStop[BP],SI ; assume length = LongDelta}
$89/$F7/ { MOV DI,SI ; set up cycle pointer}
$D1/$EF/ { SHR DI,1 ; cycle := LongDelta/2}
$89/$B6/>LONGDELTA/ { MOV >LongDelta[BP],SI}
$BE/$00/$00/ { MOV SI,0 ; initialize loop counter}
{AltLoop:}
$3B/$B6/>LINESTART/ { CMP SI,>LineStart[BP] ; start to plot yet?}
$7C/$0B/ { JL PL8 ; no, skip}
{;}
$50/ { PUSH AX ;Save registers}
$51/ { PUSH CX}
$52/ { PUSH DX}
$57/ { PUSH DI}
{;}
$E8/$22/$00/ { CALL PlotDot ;Plot pixel}
{;}
$5F/ { POP DI ;Restore registers}
$5A/ { POP DX}
$59/ { POP CX}
$58/ { POP AX}
{;}
{PL8:}
$03/$96/>LONGSTEP/ { ADD DX,>LongStep[BP] ; always move along Y AXis}
$01/$C7/ { ADD DI,AX ; cycle := cycle + shortdelta}
$3B/$BE/>LONGDELTA/ { CMP DI,>LongDelta[BP] ; is cycle >= long delta???}
$7C/$08/ { JL PL9 ; no, skip (don't move along x yet)}
$2B/$BE/>LONGDELTA/ { SUB DI,>LongDelta[BP] ; yes, reset cycle pointer}
$03/$8E/>SHORTSTEP/ { ADD CX,>ShortStep[BP] ; and bump x coordinate}
{PL9:}
$46/ { INC SI ; bump dot counter}
$3B/$B6/>LINESTOP/ { CMP SI,>LineStop[BP] ; done???}
$76/$D4/ { JBE AltLoop ; no, plot next dot}
$E9/$56/$00/ { JMP PLExit ; yes, go to common exit}
{;}
{PlotDot: ;PROC Near}
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
$F6/$06/>WRITE_GRAPHICS_SCREEN/$01/ { TEST Byte [>Write_Graphics_Screen],1 ;Check if direct screen writes}
$74/$43/ { JZ Bios ;No -- use BIOS}
{;}
{; Write pixel directly to screen memory.}
{; Determine if EGA or CGA and get Y offset.}
{;}
$F6/$06/>EGA_USE/$01/ { TEST Byte [>Ega_Use],1 ;Check if EGA used}
$74/$12/ { JZ CGA ;No -- go figure CGA offset}
{;}
$89/$C8/ { MOV AX,CX ;Save X}
$B1/$06/ { MOV CL,6 ;Shift count}
$89/$D3/ { MOV BX,DX ;Copy Y}
$D3/$E2/ { SHL DX,CL ;Y * 64}
$B1/$04/ { MOV CL,4 ;Shift count}
$D3/$E3/ { SHL BX,CL ;Y * 16}
$01/$D3/ { ADD BX,DX ;Y * 80 = offset for Y}
$89/$C1/ { MOV CX,AX ;Restore X}
$EB/$0A/ { JMP Short Both}
{;}
$8D/$1E/>SCAN_LINE_TABLE/ {CGA: LEA BX,[>Scan_Line_Table] ; Get scan line table address}
$D1/$E2/ { SHL DX,1 ; Y * 2 for integer offset}
$01/$D3/ { ADD BX,DX ; Get offset of entry for Y}
$8B/$1F/ { MOV BX,[BX] ; Get offset for Y}
{;}
$89/$CA/ {Both: MOV DX,CX ; Get X}
$89/$C8/ { MOV AX,CX}
$B1/$03/ { MOV CL,3 ;}
$D3/$EA/ { SHR DX,CL ; X DIV 8 = Byte offset in row}
$01/$D3/ { ADD BX,DX ; Byte pos in screen memory}
$25/$07/$00/ { AND AX,7 ; X MOD 8}
$BA/$80/$00/ { MOV DX,$80 ; 1 bit in leftmost position}
$89/$C1/ { MOV CX,AX ; shift count}
$D3/$EA/ { SHR DX,CL ; 1 bit in proper position}
$C4/$3E/>GRAPHICS_SCREEN/ { LES DI,[>Graphics_Screen] ; Get screen address}
$01/$DF/ { ADD DI,BX ; Get byte address}
$26/$08/$15/ { ES: OR BYTE PTR [DI],DL ; Get byte to alter}
$E9/$0B/$00/ { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
$55/ {Bios: PUSH BP ; Save BP in case BIOS zaps it}
$53/ { PUSH BX ; Save BX}
$B7/$00/ { MOV BH,0 ; Page 0 always}
$B8/$01/$0C/ { MOV AX,$0C01 ; Plot pixel function}
$CD/$10/ { INT $10 ; Plot the pixel via BIOS}
$5B/ { POP BX ; Restore BX}
$5D/ { POP BP ; Restore BP}
{;}
{Exit:}
$C3); { RET}
{;}
{PLExit:}

(* Restore timesharing mode *)

IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;

END (* Draw_Line *);

(*----------------------------------------------------------------------*)
(* Plot_Char --- Interpret current char as text to display *)
(*----------------------------------------------------------------------*)

PROCEDURE Plot_Char( Ch: CHAR; X: INTEGER; Y: INTEGER );

VAR
I : INTEGER;
K1 : INTEGER;
K2 : INTEGER;
XB : INTEGER;
XO : INTEGER;
XO1 : INTEGER;
XS : INTEGER;
XSL : INTEGER;
Do_XOR : BOOLEAN;
(* Holds point plot routine offset *)
(* STRUCTURED *) CONST
Plot_Pixel_Function : WORD = 0;

(* Shape table for characters *)
(* STRUCTURED *) CONST
Char_Bits_Table: ARRAY[0..581] OF BYTE =
( 0, 0, 0, 0, 0, 0,
0, 96, 0, 96, 96, 96,
0, 0, 0, 0, 216, 216,
0, 80, 248, 80, 248, 80,
0, 240, 40, 112, 160, 120,
0, 152, 88, 32, 208, 200,
0, 16, 120, 144, 144, 112,
0, 0, 0, 32, 48, 48,
0, 32, 64, 64, 64, 32,
0, 64, 32, 32, 32, 64,
0, 136, 80, 248, 80, 136,
0, 32, 32, 248, 32, 32,
0, 64, 96, 0, 0, 0,
0, 0, 0, 240, 0, 0,
0, 24, 24, 0, 0, 0,
0, 128, 64, 32, 16, 8,
0, 112, 136, 168, 136, 112,
0, 112, 32, 32, 96, 32,
0, 248, 96, 16, 136, 112,
0, 112, 136, 48, 136, 112,
0, 16, 248, 144, 80, 32,
0, 240, 8, 240, 128, 248,
0, 112, 136, 240, 128, 112,
0, 64, 32, 16, 8, 120,
0, 112, 136, 112, 136, 112,
0, 112, 8, 120, 136, 112,
0, 96, 96, 0, 96, 96,
0, 64, 96, 0, 96, 96,
0, 16, 32, 64, 32, 16,
0, 0, 240, 0, 240, 0,
0, 64, 32, 16, 32, 64,
0, 32, 32, 48, 136, 112,
0, 112, 128, 176, 136, 112,
0, 136, 248, 136, 80, 32,
0, 240, 136, 240, 136, 240,
0, 120, 128, 128, 128, 120,
0, 240, 136, 136, 136, 240,
0, 248, 128, 240, 128, 248,
0, 128, 128, 240, 128, 248,
0, 120, 136, 184, 128, 120,
0, 136, 136, 248, 136, 136,
0, 112, 32, 32, 32, 112,
0, 112, 136, 8, 8, 8,
0, 136, 144, 224, 144, 136,
0, 248, 128, 128, 128, 128,
0, 136, 136, 168, 216, 136,
0, 136, 152, 168, 200, 136,
0, 112, 136, 136, 136, 112,
0, 128, 128, 240, 136, 240,
0, 104, 152, 168, 136, 112,
0, 152, 144, 240, 136, 240,
0, 240, 8, 112, 128, 120,
0, 32, 32, 32, 32, 248,
0, 112, 136, 136, 136, 136,
0, 32, 112, 136, 136, 136,
0, 136, 216, 168, 136, 136,
0, 136, 80, 32, 80, 136,
0, 32, 32, 32, 80, 136,
0, 248, 64, 32, 16, 248,
0, 120, 96, 96, 96, 120,
0, 8, 16, 32, 64, 128,
0, 120, 24, 24, 24, 120,
0, 0, 0, 136, 80, 32,
0, 0, 248, 0, 0, 0,
0, 0, 0, 32, 96, 96,
0, 136, 248, 136, 80, 32,
0, 240, 136, 240, 136, 240,
0, 120, 128, 128, 128, 120,
0, 240, 136, 136, 136, 240,
0, 248, 128, 240, 128, 248,
0, 128, 128, 240, 128, 248,
0, 120, 136, 184, 128, 120,
0, 136, 136, 248, 136, 136,
0, 112, 32, 32, 32, 112,
0, 112, 136, 8, 8, 8,
0, 136, 144, 224, 144, 136,
0, 248, 128, 128, 128, 128,
0, 136, 136, 168, 216, 136,
0, 136, 152, 168, 200, 136,
0, 112, 136, 136, 136, 112,
0, 128, 128, 240, 136, 240,
0, 104, 152, 168, 136, 112,
0, 152, 144, 240, 136, 240,
0, 240, 8, 112, 128, 120,
0, 32, 32, 32, 32, 248,
0, 112, 136, 136, 136, 136,
0, 32, 112, 136, 136, 136,
0, 136, 216, 168, 136, 136,
0, 136, 80, 32, 80, 136,
0, 32, 32, 32, 80, 136,
0, 248, 64, 32, 16, 248,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 124, 124, 124, 124, 124 );

BEGIN (* Plot_Char *)
(* Use XOR rather than OR for *)
(* the cursor. *)
Do_XOR := ( ORD( Ch ) = 128 );

IF Write_Graphics_Screen THEN
BEGIN
(* Turn off timesharing while drawing *)

IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;
(* Get byte offset in row *)
XB := SUCC( X SHR 3 );
(* Get bit offset within byte *)
XS := X AND 7;
XSL := 8 - XS;
(* Get offset of character bit *)
(* pattern. *)

K1 := ( ORD( Ch ) - 32 ) * 6;
K2 := K1 + 5;

(* OR/XOR in bits of new character. *)
(* If X is even byte address, then *)
(* simply loop over rows in the *)
(* character. If X is not even *)
(* byte address, we need to store *)
(* part of pattern in two success- *)
(* ive bytes. *)

IF ( XS = 0 ) THEN
WITH Graphics_Screen^ DO
FOR I := K1 TO K2 DO
BEGIN
CASE EGA_Use OF
FALSE: XO := Scan_Line_Table[ Y ] + XB;
TRUE : XO := ( Y * 80 ) + XB;
END (* CASE *);
IF Do_XOR THEN
Screen_Image[ XO ] := Screen_Image[ XO ] XOR
Char_Bits_Table[ I ]
ELSE
Screen_Image[ XO ] := Screen_Image[ XO ] OR
Char_Bits_Table[ I ];
Y := PRED( Y );
END
ELSE
WITH Graphics_Screen^ DO
FOR I := K1 TO K2 DO
BEGIN
CASE EGA_Use OF
FALSE: XO := Scan_Line_Table[ Y ] + XB;
TRUE : XO := ( Y * 80 ) + XB;
END (* CASE *);
XO1 := SUCC( XO );
IF Do_XOR THEN
BEGIN
Screen_Image[ XO ] := Screen_Image[ XO ] XOR
( Char_Bits_Table[ I ] SHR XS );
Screen_Image[ XO1 ] := Screen_Image[ XO1 ] XOR
( Char_Bits_Table[ I ] SHL XSL );
END
ELSE
BEGIN
Screen_Image[ XO ] := Screen_Image[ XO ] OR
( Char_Bits_Table[ I ] SHR XS );
Screen_Image[ XO1 ] := Screen_Image[ XO1 ] OR
( Char_Bits_Table[ I ] SHL XSL );
END;
Y := PRED( Y );
END;

(* Restore timesharing mode *)

IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;

END
ELSE
BEGIN (* Plot through BIOS the hard way *)

IF Do_XOR THEN
Plot_Pixel_Function := $0C81
ELSE
Plot_Pixel_Function := $0C01;

INLINE(
$8B/$86/>X/ { MOV AX,[BP+>X] ;Get X position}
$48/ { DEC AX ;Decrement for 0 offset later}
$89/$C6/ { MOV SI,AX ;Save X position}
{;}
$8B/$86/>Y/ { MOV AX,[BP+>Y] ;Get Y position}
$89/$C7/ { MOV DI,AX ;Save Y position}
{;}
$31/$C0/ { XOR AX,AX ;Clear AX}
$8A/$46/ $2D/$20/$00/ { SUB AX,32 ;Convert to 0 offset}
$89/$C3/ { MOV BX,AX}
$D1/$E0/ { SHL AX,1 ;Offset * 2}
$D1/$E0/ { SHL AX,1 ;Offset * 4}
$01/$D8/ { ADD AX,BX ;Offset * 5}
$01/$C3/ { ADD BX,AX ;Offset * 6 = offset into shape table}
$8D/$06/>CHAR_BITS_TABLE/ { LEA AX,[ $01/$C3/ { ADD BX,AX ;Get starting address this character}
{;}
$B9/$06/$00/ { MOV CX,6 ;Loop over rows in character}
{;}
$51/ {Char1: PUSH CX ;Save loop counter for rows}
$53/ { PUSH BX ;Save table offset}
{;}
$8A/$07/ { MOV AL,[BX] ;Get bit pattern for this row}
$08/$C0/ { OR AL,AL ;Check if any bits on in this row}
$74/$22/ { JZ Char4 ;No -- skip display this row}
{;}
$B9/$08/$00/ { MOV CX,8 ;Loop over bits this row}
{;}
$51/ {Char2: PUSH CX ;Save loop counter for bits}
{;}
$A8/$01/ { TEST AL,1 ;See if "this" bit is turned on}
$74/$15/ { JZ Char3 ;No -- skip to next bit}
{;}
$50/ { PUSH AX ;Save bit mask}
$56/ { PUSH SI ;Save X}
$57/ { PUSH DI ;Save Y}
{;}
$89/$F0/ { MOV AX,SI ;Get X}
$01/$C1/ { ADD CX,AX ;Add offset}
$A1/>PLOT_PIXEL_FUNCTION/ { MOV AX,[>Plot_Pixel_Function] ;Plot pixel function}
$89/$FA/ { MOV DX,DI ;Get vertical position}
$B7/$00/ { MOV BH,0 ;Always page 0}
$55/ { PUSH BP ;Save BP in case BIOS clobbers it}
$CD/$10/ { INT $10 ;Plot the pixel via BIOS}
$5D/ { POP BP ;Restore BP}
{;}
$5F/ { POP DI ;Restore Y}
$5E/ { POP SI ;Restore X}
$58/ { POP AX ;Restore bit mask}
{;}
$D0/$E8/ {Char3: SHR AL,1 ;Shift bit mask to next bit}
$59/ { POP CX ;Retrieve bits counter}
$E2/$E1/ { LOOP Char2 ;and try next bit}
{;}
$5B/ {Char4: POP BX ;Retrieve table offset}
$43/ { INC BX ;Point to next shape table byte}
$89/$F8/ { MOV AX,DI ;Decrement Y}
$48/ { DEC AX ; ...}
$89/$C7/ { MOV DI,AX ; ...}
$59/ { POP CX ;Retrieve rows counter}
$E2/$CC); { LOOP Char1 ;and try next row}

END;

END (* Plot_Char *);

(*----------------------------------------------------------------------*)
(* Display_Cursor --- Display block cursor *)
(*----------------------------------------------------------------------*)

PROCEDURE Display_Cursor( X, Y: INTEGER );

BEGIN (* Display_Cursor *)
(* Don't display cursor while plotting *)

IF ( FlagG = Text_Plot ) THEN
Plot_Char( CHR( 128 ) , X , Y );

END (* Display_Cursor *);

(*----------------------------------------------------------------------*)
(* Display_Graphics --- show character received from port *)
(*----------------------------------------------------------------------*)

PROCEDURE Display_Graphics( VAR Ch : CHAR );

(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_Graphics *)
(* *)
(* Purpose: Displays character received from comm. port on *)
(* screen/printer/capture file. *)
(* *)
(* Calling Sequence: *)
(* *)
(* Display_Graphics( Ch : CHAR ); *)
(* *)
(* Ch --- Character received from Comm. port. *)
(* *)
(* Calls: Async_Receive *)
(* Min *)
(* Update_Review_Pointers *)
(* TimeOfDay *)
(* TimeDiff *)
(* *)
(* Remarks: *)
(* *)
(* This routine strips out certain characters which *)
(* should not be displayed, implements the XON/XOFF protocol *)
(* in a simple-minded manner, performs output wrap, and saves *)
(* output line in the review the review buffer. *)
(* *)
(*----------------------------------------------------------------------*)


(* STRUCTURED *) CONST
CR_Ch : CHAR = ^M;
LF_Ch : CHAR = ^J;
BL_Ch : CHAR = ' ';

VAR
I : INTEGER;
L : INTEGER;
Xpos : INTEGER;
Ypos : INTEGER;
C : INTEGER;
KeyC : CHAR;
TT : Transfer_Type;

(*----------------------------------------------------------------------*)
(* Do_Graphics --- Interpret current char as graphics command *)
(*----------------------------------------------------------------------*)

PROCEDURE Do_Graphics;

BEGIN (* Do_Graphics *)
(* Get previous character and *)
(* save current character *)
Old := ORD( Prev_Ch );
Prev_Ch := Ch;
(* Set first X corrdinate *)

IF ( C > 31 ) AND ( C < 64 ) AND ( Old > 95 ) AND ( Old < 128 ) THEN
BEGIN
Hx := C;
EXIT;
END;
(* Set first Y coordinate *)

IF ( C > 31 ) AND ( C < 64 ) THEN
BEGIN
Hy := C;
EXIT;
END;
(* Set second Y coordinate *)

IF ( C > 95 ) AND ( C < 128 ) THEN
BEGIN
Ly := C;
EXIT;
END;
(* Set second X coordinate, and *)
(* plot point if necessary. *)

IF ( C > 63 ) AND ( C < 96 ) THEN
BEGIN

Lx := C;
(* Get PC screen position of point *)

XPos := TRUNC( XFactor * ( ( Hx - 32 ) * 32 + Lx - 64 ));
YPos := YMax - TRUNC( YFactor * ( ( Hy - 32 ) * 32 + Ly - 96 ));

(* Turn off timesharing while drawing *)

IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;
(* First coordinate -- just move *)
(* to it *)

CASE FlagG OF
Vector_Plot : Draw_Line( Graphics_XPos, Graphics_YPos,
XPos, YPos );
Vector_Plot_Start: FlagG := Vector_Plot;
Point_Plot : Plot_Point( XPos, YPos );
Point_Plot_Start : FlagG := Point_Plot;
ELSE;
END (* CASE *);

(* Restore timesharing mode *)

IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;
(* Update graphics position *)
Graphics_XPos := XPos;
Graphics_YPos := YPos;

END;

END (* Do_Graphics *);



  3 Responses to “Category : Pascal Source Code
Archive   : PIBT41S2.ZIP
Filename : PIB4010A.MOD

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/