home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / mspdmp.asm < prev    next >
Assembly Source File  |  2020-01-01  |  15KB  |  527 lines

  1.      page  60,132
  2.      title Graphics Module for Print Screen with the EGA
  3. Dmp200     segment para public 'code'
  4.      assume cs:Dmp200,ds:Dmp200,es:Dmp200
  5.  
  6. Comment #
  7.  
  8. This routine was written by Dr. R.Brooks Van Horn, Jr. to fill a void
  9. left by Big Blue when their support for the EGA never arrived.    This
  10. routine will perform the Shift Print Screen function for a Radio Shack
  11. DMP200 printer. I also have an Epson (IBM Printer) version and an EGA
  12. Mode 16 driver to supplement EGA BIOS versions that like IBM's do not
  13. support a read/write mode 16 (10H) interupt.
  14.  
  15. #
  16.  
  17.      org 100h 
  18.      jmp   Setup
  19.  
  20. Mlen     db    'EGA Print Screen Version 2.0'
  21. Cmp_Str     dw    $-mlen
  22.  
  23. ;     normal int 5 entry point
  24.  
  25. Begin:     pushf             ; enable further interrupts
  26.      push  ax
  27.      push  bx
  28.      push  bp
  29.      push  di
  30.      push  si
  31.      push  ds
  32.      xor   ax,ax
  33.      mov   ds,ax
  34.      mov   al,Byte Ptr ds:[449h] ; get the video mode
  35.      pop   ds         ; restore data set register
  36.      and   al,07fh         ; mask off any unwanted data
  37.      mov   cs:[Mode],ax  ; and save it for future use
  38.      cmp   al,7         ; is this a mono card?
  39.      jz    Outz         ; yes, exit - when in text mode
  40.      cmp   al,3         ; see if we are in the graphics mode?
  41.      jg    cont         ; yes, go around using dos
  42. Outz:     pop   si         ; restore the registers saved
  43.      pop   di
  44.      pop   bp
  45.      pop   bx
  46.      pop   ax
  47.      popf
  48. ;-----     jump far to Dos
  49.      db    0EAh         ; jump far segment to Print
  50. dos     dw    0         ; offset of jump
  51. dos2     dw    0         ; segment of jump
  52.  
  53. Cont:     push  cx         ; and save all the registers
  54.      push  dx
  55.      push  ds
  56.      push  es
  57.      push  cs         ; now put code seg register into
  58.      pop   es         ; the extra segment register
  59.      xor   ax,ax
  60.      mov   ds,ax
  61.      inc   al         ; see if we are already being done
  62.      mov   al,Byte Ptr ds:[500h] ; get the current printer status
  63.      or    al,al
  64.      jnz   Getout         ; if 500h was not zero then exit
  65.      push  cs
  66.      pop   ds
  67.      xchg  al,Byte Ptr cs:switch
  68.      or    al,al
  69.      jnz   GetOut
  70.      sti
  71.      mov   cs:[sp_save],sp
  72.      jmp   Process
  73.  
  74. Return:     mov   si,Offset Restore
  75.      mov   cl,cs:[si]    ; get number of bytes to print
  76.      xor   ch,ch
  77.      inc   si
  78.      call  Tabptr         ; restore printer to original state
  79. Exit:     mov   sp,cs:[sp_save]
  80.      xor   ax,ax
  81.      mov   Byte Ptr cs:switch,al ; set value to zero
  82. Getout:     pop   es         ; restore registers and exit
  83.      pop   ds
  84.      pop   dx
  85.      pop   cx
  86.      pop   si
  87.      pop   di
  88.      pop   bp
  89.      pop   bx
  90.      pop   ax
  91.      popf
  92.      sti
  93.      iret             ; bye...............
  94.  
  95. ;--------------------------------------------------------------------
  96. ;           Radio Shack DMP-200 Printer with PC or AT
  97. ;--------------------------------------------------------------------
  98.  
  99. ;  set graphics mode, condensed, 8 CRs, and tab to pos 45 to print
  100. Line_Sp     db    11,27,20,18,10,10,10,10,10,10,10,10,27,16,0,45
  101. NofByte     dw    0          ; total number of columns required
  102. Restore     db    6,30,27,18,27,31,12
  103. Line_Buf db    800 dup (?)      ; line buffer
  104. Col_2_Do dw    0          ; column being printed
  105. Eight     dw    7
  106. Four     dw    4
  107. Switch     db    0
  108. Sp_Save     dw    0
  109. Temp     db    0,0
  110. save_bp     dw    0
  111.  
  112. ;      Modes =     4   5     6   7     8   9     A   B     C   D     E   F    10  11    12  13
  113. Col_Mode dw    320,320,640,  0,     0,320,640,  0,720,320,640,640,640,640,640,350
  114. Row_Mode dw    200,200,200,  0,     0,200,200,  0,348,200,200,350,350,480,480,320
  115.  
  116. Mode     dw    0         ; Current Video Mode
  117. Rows     dw    0         ; Number of rows for this mode
  118. Cols     dw    0         ; Number of columns for this mode
  119.  
  120. ;--------------------------------------------------------------------
  121. ;
  122. ;     Print a Table of Control Values
  123. ;     ===============================
  124. ;
  125. Tabptr:     mov   al,cs:[si]
  126.      call  Printer
  127.      inc   si
  128.      loop  Tabptr
  129.      nop
  130.      ret
  131. ;
  132. ;     Send an alarm bell sound
  133. ;     ========================
  134. ;
  135. Bell:     mov   al,7
  136.      mov   ah,14
  137.      int   10h
  138.      ret
  139.  
  140. ;     Send the character in AL to the printer
  141. ;     =======================================
  142. ;
  143. Printer: push  dx
  144.      sub   dx,dx
  145.      xor   ah,ah
  146.      int   17h
  147.      pop   dx
  148.      test  ah,25h
  149.      jnz   Error
  150.      ret      
  151. ;
  152. ;     Error returns on printer commands
  153. ;     =================================
  154. Error:     call  Bell
  155.      call  Bell
  156.      jmp   Exit        
  157. ;
  158. ;     Send a form feed to the Printer
  159. ;     ===============================
  160. ;
  161. Cr_Lf:     push  dx
  162.      sub   dx,dx
  163.      mov   ax,0dh
  164.      int   17h
  165.      mov   ax,0ah
  166.      int   17h
  167.      pop   dx
  168.      test  ah,25h
  169.      jnz   Error
  170.      ret
  171.  
  172. ;---------------------------------------------------------------------
  173. ;                                     l
  174. ;           Graphics Processing Section                 l
  175. ;                                     l
  176. ;---------------------------------------------------------------------
  177.  
  178. Process: mov   bp,cs:[Mode]
  179.      sub   bp,4
  180.      sal   bp,1
  181.  
  182.      mov   ax,cs:Row_Mode[bp]   ; save rows-1 and cols-1
  183.      dec   ax
  184.      mov   cs:Rows,ax
  185.      mov   ax,cs:Col_Mode[bp]
  186.      dec   ax
  187.      mov   cs:Cols,ax
  188.  
  189.      mov   ah,1        ; initialize the printer
  190.      xor   dx,dx
  191.      int   17h
  192.  
  193.      mov   si,Offset cs:Line_Sp ; setup for correct interline spacing
  194.      mov   cl,cs:[si]    ; get length
  195.      xor   ch,ch
  196.      inc   si
  197.      call  TabPtr
  198.      
  199.      mov   ax,cs:[Cols]    ; decide to do graphics by row or column mode
  200.      cmp   ax,320
  201.      jg    By_Rows
  202.      jmp   By_Cols
  203.  
  204. ;--------------------------------------------------------------------
  205. ;      for By_Rows calls we have usually 640 x 200 type, so do 200
  206. ;      across and 640 down the page.     This means that we can only 
  207. ;      single dot to get lines to connect on the printer paper.
  208. ;--------------------------------------------------------------------
  209.  
  210. By_Rows: mov   cx,0         ; start the column index at zero
  211.  
  212. Br_Strt: push  cx         ; save the current column index
  213.      mov   dx,cs:[Rows]  ; initialize the row count to max
  214.      mov   bh,Byte Ptr cs:[Eight]
  215.      xor   si,si         ; max characters to print
  216.      mov   cs:[Col_2_Do],si
  217.      mov   di,Offset Line_Buf
  218.      xor   bl,bl
  219.  
  220. ;     do for a count of 'Eight'
  221.  
  222. Br_Cont: call  Read         ; read the next dot at (row,col)
  223.      and   al,07fh         ; check if any thing is there
  224.      jz    Br_Fill         ; and skip if nothing there
  225.      mov   al,40h         ; else fill the byte 
  226. Br_Fill: shr   bl,1         ; move reg left one bit 
  227.      or    bl,al         ; and or in the next value
  228.      inc   cx         ; increment the column count
  229.      dec   bh         ; and the loop index
  230.      jnz   Br_Cont         ; continue loop for 8 times
  231.  
  232. ;     undo
  233.  
  234.      add   si,2         ; add two to the column counter
  235.      or    bl,80h         ; turn on the high order bit
  236.      mov   Byte Ptr cs:[di],bl ; save filled byte
  237.      mov   Byte Ptr cs:[di+1],bl ; twice for filling
  238.      cmp   cs:[Rows],199
  239.      jg    Br_Two
  240.      mov   Byte Ptr cs:[di+2],bl
  241.      inc   di
  242.      inc   si
  243. Br_Two:     add   di,2         ; up the buffer ptr
  244.      and   bl,7fh
  245.      jz    Br_Skp
  246.  
  247.      mov   Word Ptr cs:[Col_2_Do],si ; save index
  248.  
  249. Br_Skp:     mov   bh,Byte Ptr cs:[Eight] ; set loop for 8 more cols per row
  250.      dec   dx         ; delete one from the row index
  251.      pop   cx         ; restore the column count
  252.      push  cx         ; and save it again for this row
  253.      xor   bl,bl
  254.      cmp   dx,0         ; and test to see if we are finished
  255.      jge   Br_Cont         ; loop
  256.  
  257.      mov   si,Offset Line_Buf ; get print line pointer
  258.      mov   cx,cs:[Col_2_Do] ; get the number of bytes to print
  259.      or    cx,cx
  260.      jz    Br_NoP         ; skip if didn't get anything
  261.      call  TabPtr         ; print the line
  262. Br_NoP:     call  Cr_Lf
  263.  
  264.      pop   cx
  265.      add   cx,cs:[Eight] ; add 8 to column count
  266.      cmp   cx,cs:[Cols]  ; compare to max to do
  267.      jg    Br_Ret
  268.      jmp   Br_Strt         ; continue until fini
  269.  
  270. Br_Ret:     jmp   Return         ; restore printer and exit
  271.  
  272. ;--------------------------------------------------------------------
  273. ;      for By_Cols calls we have usually 320 x 200 type, so do 320
  274. ;      across and 200 down the page.     This means that we must double
  275. ;      dot to get lines to connect on the printer paper.
  276. ;--------------------------------------------------------------------
  277.  
  278. By_Cols: mov   dx,0         ; start the row index at zero
  279.      mov   cx,799         ; clear the buffer
  280.      mov   di,Offset cs:Line_Buf
  281.      cld
  282.      mov   ax,0
  283.      mov   Word Ptr cs:[Temp],ax
  284.      push  cs
  285.      pop   es
  286.      rep   stosb
  287.  
  288. ;     for each row do all the columns
  289. Bc_Strt: push  dx         ; save the current row index
  290.      mov   cx,0         ; initialize the col count to start
  291.      mov   bh,Byte Ptr cs:[Four]
  292.      mov   cs:[Temp],bh
  293.      xor   si,si         ; max characters to print
  294.      mov   cs:[Col_2_Do],si
  295.      mov   di,Offset Line_Buf
  296.  
  297. ;     for each column in the row, do
  298. Bc_Pick: mov   bl,cs:[di]    ; get the last value
  299.      mov   al,cs:[Temp]  ; and see if this is a four or three count
  300.      shr   al,1
  301.      shl   al,1
  302.      cmp   al,cs:[Temp]  ; if even then use four
  303.      je    Bc_Cont
  304.      dec   bh         ; otherwise use three
  305.      mov   cs:[Temp],bh        
  306.  
  307. Bc_Cont: call  Read         ; read the next dot at (row,col)
  308.      and   al,07fh         ; check if any thing is there
  309.      jz    Bc_Fill         ; and skip if nothing there
  310.      mov   al,60h         ; else fill the byte 
  311. Bc_Fill: shr   bl,1         ; move reg left one bit 
  312.      shr   bl,1         ; and repeat
  313.      or    bl,al         ; and or in the next value
  314.      inc   dx         ; increment the row count
  315.      dec   bh         ; and the loop index
  316.      jnz   Bc_Cont         ; continue loop for 4 times
  317.  
  318.      add   si,2         ; add two to the column counter
  319.      or    bl,80h         ; turn on the high order bit
  320.      mov   Byte Ptr cs:[di],bl ; save filled byte
  321.      mov   Byte Ptr cs:[di+1],bl ; twice for filling
  322.      add   di,2         ; up the buffer ptr
  323.      and   bl,7fh
  324.      jz    Bc_Skp
  325.  
  326.      mov   Word Ptr cs:[Col_2_Do],si ; save index
  327.  
  328. Bc_Skp:     mov   bh,cs:[Temp] ; set loop for 8 more cols per row
  329.      mov   bl,cs:[di]    ; get the last value
  330.      inc   cx         ; add one to the col index
  331.      pop   dx         ; restore the row count
  332.      push  dx         ; and save it again for this row
  333.      cmp   cx,cs:[Cols]  ; and test to see if we are finished
  334.      jle   Bc_Pick         ; loop
  335.  
  336.      mov   bp,Word Ptr cs:[Temp] ; save the current Temp setting
  337.      xor   Byte Ptr cs:[Temp],7
  338.      mov   si,Offset Line_Buf ; get print line pointer
  339.      mov   cx,cs:[Col_2_Do] ; get the number of bytes to print
  340.      or    cx,cx
  341.      jz    Bc_NoP         ; skip if didn't get anything
  342.      call  TabPtr         ; print the line
  343. Bc_NoP:     call  Cr_Lf
  344.  
  345.      pop   dx
  346.      add   dx,bp         ; add to column count
  347.      cmp   dx,cs:[Rows]  ; compare to max to do
  348.  
  349.      jg    Bc_Ret         ; if fini then exit
  350.      jmp   Bc_Strt         ; else go do next row
  351. Bc_Ret:     jmp   Return         ; restore printer and exit
  352.  
  353. ;--------------------------------------------------------------------
  354. ;
  355. ;     Read Dot Routine Using DOS/BIOS or VDI interface for int 10h
  356. ;
  357. ;-------------------------------------------------------------------
  358. Read:      xor  al,al
  359.       cmp    dx,0          ; see if all is ok
  360.       jl    Read_Ret
  361.       cmp    cx,cs:[Cols]  ; also check on overdoing it
  362.       jg    Read_Ret
  363.       cmp    cs:[Mode],6
  364.       jg    Read_Dot
  365.       mov    ah,13
  366.       push    bx
  367.       push    cx
  368.       push    dx
  369.       mov    cs:[save_bp],bp
  370.       int    10h          ; let BIOS read the dots
  371.       mov    bp,cs:[save_bp]
  372.       pop    dx
  373.       pop    cx
  374.       pop    bx
  375.       xor    ah,ah          ; clear the high byte for testing
  376. Read_Ret: ret
  377.  
  378. Read_Dot: push bx
  379.      push  cx
  380.      push  dx
  381.      mov   ax,dx         ; save column value
  382.      mov   bx,cx         ; and row value
  383.      mov   dx,0a000h     ; Video ram address
  384.      mov   ds,dx         ; into segment register
  385.      mov   dx,80
  386.      mul   dx         ; column * 80
  387.      shr   bx,1
  388.      shr   bx,1
  389.      shr   bx,1         ; row / 8
  390.      add   bx,ax         ; actual data byte address
  391.      and   cl,7         ; row mod 8
  392.      xor   cl,7         ; bit mask 7 - (row mod 8)
  393.      mov   ch,1
  394.      shl   ch,cl         ; 2^mask
  395.      mov   ah,3         ; initialize bit plane number
  396. Plane_Loop:
  397.      mov   dx,03CEh         ; EGA Controller
  398.      mov   al,4         ; map select register
  399.      out   dx,al
  400.      mov   dx,03CFh         ; data register
  401.      mov   al,ah         ; select bit planes 3,2,1,0
  402.      out   dx,al
  403.      mov   al,ds:[bx]    ; read bit plane
  404.      shl   cl,1
  405.      and   al,ch
  406.      jz    Not_On
  407.      or    cl,1
  408. Not_On:     dec   ah
  409.      jge   Plane_Loop
  410.      and   cl,0fh
  411.      mov   al,cl
  412.      pop   dx
  413.      pop   cx
  414.      pop   bx
  415.      ret
  416.  
  417.      dw    -1         ; fense
  418.      
  419. ;--------------------------------------------------------------------
  420. ;
  421. ;     Initialization Routine for Graphics.Com
  422. ;
  423. ;--------------------------------------------------------------------
  424. Setup:     xor   ax,ax
  425.      mov   es,ax          ; setup to address segment zero
  426.      mov   cx,es:[0016h]      ; get current segment
  427.      mov   bx,es:[0014h]      ; and offset
  428.      mov   ds,cx          ; make that the data segment
  429.      mov   cx,cs:[Cmp_Str]      ; setup to check bytes for same
  430.      mov   si,Offset cs:mlen  ; data field "Graphic..."
  431.      mov   bx,si  
  432.  
  433. Check:     mov   ax,cs:[si]      ; get a byte in accum
  434.      cmp   ax,ds:[bx]      ; is it the same
  435.      jne   Ok          ; no, then we are ok
  436.      inc   si          ; otherwise, increment pointers
  437.      inc   bx          ; to both fields
  438.      loop  Check          ; and loop for 7 checks
  439.  
  440. ;     Bad news, it is already resident
  441.  
  442.      push  cs          ; now setup to display a message
  443.      pop   ds   
  444.      mov   ax,es:[0016h]      ; get current segment address
  445.      mov   di,Offset Field3
  446.      call  Convert
  447.      add   di,5          ; increase pointer to next field
  448.      mov   ax,es:[0014h]      ; and the offset address
  449.      call  Convert 
  450.      mov   ax,cs
  451.      mov   ds,ax
  452.      mov   ah,09h
  453.      mov   dx,Offset Message1 ; setup to display message
  454.      int   21h
  455.      int   20h          ; if same then dont overlay but exit
  456.  
  457. ;     Good News, make DMP200 resident and display location message
  458.  
  459. Ok:     mov   bx,es:[0014h]      ; get the current offset in int vector
  460.      mov   ax,cs          ; now setup to display a message
  461.      mov   ds,ax
  462.      mov   Word Ptr dos,bx      ; and save it locally
  463.      mov   bx,es:[0016h]      ; get the segment location of item too
  464.      mov   Word Ptr dos2,bx      ; and save it also
  465.      mov   ax,cs          ; save our entry at int vector
  466.      mov   es:[0016h],ax      ; segment
  467.      mov   bx,Offset cs:Begin ; define entry point to routine
  468.      mov   es:[0014h],bx      ; offset
  469.      mov   di,Offset Field1
  470.      call  Convert          ; convert starting address
  471.      mov   di,Offset Field2
  472.      mov   bx,Offset Setup
  473.      add   bx,15          ; convert to next paragraph addr
  474.      mov   cl,4
  475.      shr   bx,cl
  476.      add   ax,bx
  477.      call  Convert          ; and the new ending address
  478.      mov   ah,09h          ; now do our message
  479.      mov   dx,Offset Message2
  480.      int   21h
  481.      mov   dx,Offset cs:Setup
  482.      int   27h          ; terminate but stay resident
  483.  
  484. Convert     proc  near
  485. ;
  486. ;     ax = number to be converted 
  487. ;     di = address of field in which to put the hex characters 
  488. ;
  489.      push  ax
  490.      push  bx
  491.      push  cx
  492.      push  dx
  493.      lea   bx,Ascii
  494.      mov   cl,4
  495.      mov   dx,ax
  496.      mov   al,ah
  497.      shr   al,cl
  498.      xlat  Ascii
  499.      mov   Byte Ptr cs:[di],al
  500.      mov   al,dh
  501.      and   al,0fh
  502.      xlat  Ascii
  503.      mov   Byte Ptr cs:[di+1],al
  504.      mov   al,dl
  505.      shr   al,cl
  506.      xlat  Ascii
  507.      mov   Byte Ptr cs:[di+2],al
  508.      mov   al,dl
  509.      and   al,0fh
  510.      xlat  Ascii
  511.      mov   Byte Ptr cs:[di+3],al
  512.      pop   dx
  513.      pop   cx
  514.      pop   bx
  515.      pop   ax
  516.      ret
  517. Convert     endp
  518. Message1 db    'DMP200 Graphics routine is already resident ('
  519. Field3     db    '0000-0000)',13,10,'$'
  520. Message2 db    'DMP200 Graphics routine is now resident ('
  521. Field1     db    '0000-'
  522. Field2     db    '0000)',13,10,'$'
  523. Ascii     db    '0123456789abcdef'
  524. Dmp200     ends
  525.      end
  526.