home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / screen / herc_eps.pas < prev    next >
Pascal/Delphi Source File  |  1994-03-05  |  8KB  |  208 lines

  1. Date: Wed, 6 Jan 88 12:59 EST
  2. From: P150BK19@VB.CC.CMU.EDU
  3. Subject: Hercules-to-Epson Turbo Pascal code
  4. To: hicks@WALKER-EMH.ARPA
  5.  
  6. Procedure HGCopy;
  7.  
  8. (* This procedure produces a hard copy of a Hercules screen on an
  9. Epson-compatible printer (mode 1) using inline code, which is considerably
  10. faster than the HardCopy procedure provided with the Turbo Graphix ToolBox.
  11. On a Panasonic XK-P1080i, which can print 8-bit double-density graphics (mode
  12. 1) at 6 inches per second, this routine essentially keeps the printer fully
  13. occupied.  About half of the speedup over the ToolBox version comes from
  14. using inline code to map the graphics bits to a print row, and the other half
  15. comes from using inline code to print the row itself (instead of a "write"
  16. call for each and every byte of dots).  While the procedure uses variables
  17. which are defined from the Graphix ToolBox, owning the ToolBox is not
  18. strictly necessary (of course you must then supply your own drivers).  The
  19. key variables are:
  20.  
  21.      GrafBase : segment address of active screen
  22.                 (hardware screen is $B000);
  23.      XScreenMaxGlb : width of screen (in pixels) - 1;
  24.      XMaxGlb : (XScreenMaxGlb - 7) / 8; width of screen in bytes - 1;
  25.  
  26. The screen is mapped to a print row which is 8 bits high, corresponding to 8
  27. scan lines.  The Hercules scan lines are stored in 4 sectors, the low address
  28. of which are separated by $2000.  Each print row thus contains two successive
  29. scan lines from each sector.  It is also assumed that the screen has 352 scan
  30. lines (as is used in the ToolBox, in spite of the Hercules specification of
  31. 348), corresponding to exactly 44 8-bit print rows. This can also be changed
  32. directly in the main portion of the procedure.  *)
  33.  
  34.  
  35. type
  36.  
  37.   LineType = array [0..XScreenMaxGlb] of Byte;
  38.  
  39. var
  40.   PrintLine : LineType;
  41.   PrntChrPtr,LinePtr,SectorPtr,ScanPtr,
  42.     PrtLineNum, ByteNum : integer;
  43.   WorkByte : Byte;
  44.  
  45. Procedure MapLine(LinePtr, XMaxLoc, XScreenMaxLoc : integer;
  46.   var PrintLine : LineType);
  47.      {inline procedure to map a single print line }
  48.  
  49. var
  50.   ScanBitLoc : integer;
  51.  
  52. begin {MapLine}
  53.  
  54.   XMaxLoc := XMaxGlb; {get Local variable versions for inline code}
  55.   XScreenMaxLoc := XScreenMaxGlb; {which utilizes stack segment}
  56.  
  57. Inline(
  58.   $C4/$9E/>PrintLine/    {     LES     BX,>PrintLine[BP] }
  59.                          { set print line to zero }
  60.   $89/$D9/               {     MOV     CX,BX }
  61.   $03/$8E/>XScreenMaxLoc/ {     ADD     CX,>XScreenMaxLoc[BP] }
  62.   $31/$C0/               {     XOR     AX,AX }
  63.                          { ZeroStringLoop: }
  64.   $26/                   {     ES:     ; PrintLine in extra segment! }
  65.   $88/$07/               {     MOV     [BX],AL }
  66.   $43/                   {     INC     BX }
  67.   $39/$CB/               {     CMP     BX,CX }
  68.   $7E/$F8/               {     JLE     ZeroStringLoop }
  69.                          {     SectorPtr := LinePtr }
  70.   $8B/$BE/>LinePtr/      {     MOV     DI,>LinePtr[BP] ; SectorPtr }
  71.                          {     for SectorBitLoc := 7 downto 4 do }
  72.                          {     4 Sectors in memory }
  73.   $B9/$07/$00/           {     MOV     CX,7 }
  74.                          { SectorLoop: }
  75.                          {     ScanBitLoc := SectorBitLoc }
  76.   $89/$8E/>ScanBitLoc/   {     MOV     >ScanBitLoc[BP],CX }
  77.                          {     ScanPtr := SectorPtr }
  78.   $57/                   {     PUSH    DI }
  79.   $51/                   {     PUSH    CX }
  80.   $31/$C9/               {     XOR     CX,CX }
  81.                          {     for ScanNum := 0 to 1 do }
  82.                          {     2 Scan Lines per Sector }
  83.                          { ScanLineLoop: }
  84.   $C4/$9E/>PrintLine/    {     LES     BX,>PrintLine[BP] ; PrntChrPtr }
  85.   $51/                   {     PUSH    CX }
  86.   $31/$C9/               {     XOR     CX,CX }
  87.                          {     for ByteNum := 0 to XMaxLoc do }
  88.                          {     90 Bytes/Scan Line }
  89.                          { ByteScanLoop: }
  90.                          {     WorkByte := mem[GrafBase:ScanPtr] }
  91.   $06/                   {     PUSH    ES }
  92.   $A1/>GrafBase/         {     MOV     AX,[>GrafBase] }
  93.   $8E/$C0/               {     MOV     ES,AX }
  94.   $26/                   {     ES: }
  95.   $8A/$05/               {     MOV     AL,[DI] }
  96.   $07/                   {     POP     ES }
  97.   $51/                   {     PUSH    CX }
  98.   $BA/$07/$00/           {     MOV     DX,7 }
  99.                          {     for BitNum := 7 downto 0 do } 
  100.                          {     Scan single Byte }
  101.                          { BitScanLoop: }
  102.                          {     mem[PrntSeg:PrntChrPtr]
  103.                                := mem[PrntSeg:PrntChrPtr] or
  104.                          ( ( (WorkByte shr BitNum) and 1 ) shl ScanBitLoc ) }
  105.   $88/$C4/               {     MOV     AH,AL }
  106.   $89/$D1/               {     MOV     CX,DX }
  107.   $D2/$EC/               {     SHR     AH,CL }
  108.   $80/$E4/$01/           {     AND     AH,1 }
  109.   $8B/$8E/>ScanBitLoc/   {     MOV     CX,>ScanBitLoc[BP] }
  110.   $D2/$E4/               {     SHL     AH,CL }
  111.   $26/                   {     ES: }
  112.                          {     PrintLine in extra segment }
  113.   $08/$27/               {     OR     [BX],AH }
  114.                          {     PrntChrPtr := PrntChrPtr + 1 }
  115.   $43/                   {     INC     BX }
  116.   $4A/                   {     DEC     DX }
  117.   $81/$FA/$00/$00/       {     CMP     DX,0 }
  118.   $7D/$E6/               {     JGE     BitScanLoop }
  119.   $59/                   {     POP     CX }
  120.                          {     ScanPtr := ScanPtr + 1 }
  121.   $47/                   {     INC     DI }
  122.   $41/                   {     INC     CX }
  123.   $3B/$8E/>XMaxLoc/      {     CMP     CX,>XMaxLoc[BP] }
  124.   $7E/$CF/               {     JLE     ByteScanLoop }
  125.   $59/                   {     POP     CX }
  126.                          {     ScanBitLoc := ScanBitLoc - 4 }
  127.   $8B/$9E/>ScanBitLoc/   {     MOV     BX,>ScanBitLoc[BP] }
  128.   $81/$EB/$04/$00/       {     SUB     BX,4 }
  129.   $89/$9E/>ScanBitLoc/   {     MOV     >ScanBitLoc[BP],BX }
  130.   $41/                   {     INC     CX }
  131.   $81/$F9/$01/$00/       {     CMP     CX,1 }
  132.   $7E/$B4/               {     JLE     ScanLineLoop }
  133.   $59/                   {     POP     CX }
  134.                          {     SectorPtr := SectorPtr + $2000 }
  135.   $5F/                   {     POP     DI }
  136.   $81/$C7/$00/$20/       {     ADD     DI,$2000 }
  137.   $49/                   {     DEC     CX }
  138.   $81/$F9/$04/$00/       {     CMP     CX,4 }
  139.   $7D/$9F);              {     JGE     SectorLoop }
  140.  
  141. end; {MapLine}
  142.  
  143. Procedure PrintByte (OneByte : Byte);
  144.  
  145. begin {PrintByte}
  146. Inline(
  147.   $31/$D2/               {     XOR     DX,DX }
  148.   $B4/$00/               {     MOV     AH,0 }
  149.   $8A/$86/>OneByte/      {     MOV     AL,>OneByte[BP] }
  150.   $CD/$17);              {     INT     $17 }
  151. end; {PrintByte}
  152.  
  153.  
  154. Procedure PrintRow (XScreenMaxLoc : integer; var PrintLine : LineType);
  155.  
  156. begin {PrintRow}
  157.  
  158. Inline(
  159.   $C4/$9E/>PrintLine/    {     LES     BX,>PrintLine[BP] }
  160.   $89/$D9/               {     MOV     CX,BX }
  161.   $03/$8E/>XscreenMaxLoc/ {    ADD     CX,>XScreenMaxLoc[BP] }
  162.                          {     for ByteNum := 0 to XScreenMaxGlb do }
  163.                          {PrintLoop: }
  164.                          {    Write(Lst, Chr( PrintLine[ByteNum]) ) }
  165.   $31/$D2/               {     XOR     DX,DX }
  166.   $B4/$00/               {     MOV     AH,0 }
  167.   $26/                   {     ES: }
  168.   $8A/$07/               {     MOV     AL,[BX] }
  169.   $CD/$17/               {     INT     $17 }
  170.   $43/                   {     INC     BX }
  171.   $39/$CB/               {     CMP     BX,CX }
  172.   $7E/$F2);              {     JLE     PrintLoop }
  173.  
  174. end; {PrintRow}
  175.  
  176.  
  177. begin { HGCopy }
  178.  
  179.   PrintByte(27); {set Line spacing to 9/inch}
  180.   PrintByte(Byte('3'));
  181.   PrintByte(24);
  182.  
  183.   LinePtr := 0;  {start with 0 offset from GrafBase}
  184.   for PrtLineNum := 1 to 44 do  {44 total print Lines}
  185.   begin
  186.  
  187.     MapLine(LinePtr, XMaxGlb, XScreenMaxGlb, PrintLine);
  188.     {map the Bits with an inLine procedure}
  189.  
  190.     {now print the Line}
  191.  
  192.     PrintByte(27);  {force EPSON mode 1 for now}
  193.     PrintByte(Byte('L'));
  194.     PrintByte(Lo(XScreenMaxGlb + 1));
  195.     PrintByte(Hi(XScreenMaxGlb + 1));
  196.  
  197.     PrintRow(XScreenMaxGlb, PrintLine); {print row of Bytes}
  198.  
  199.     PrintByte(10);
  200.     LinePtr := LinePtr + 2 * (XMaxGlb + 1); {jump 2 scan lines / print row}
  201.  
  202.   end; {print Line Loop}
  203.  
  204.   PrintByte(27); {reset printer}
  205.   PrintByte(Byte('2'));
  206.  
  207. end; {HGCopy}
  208.