Metropoli BBS
VIEWER: pport.asm MODE: TEXT (ASCII)
;--pport.asm--------------------------------------------------------------
;
;Dumps the screen to a remote machine over an 11 wire null printer cable
; using the 3-bit IRQ method with this program running on both ends.
;
;Public Domain from James Vahn - July 2,1996 - (jvahn@short.circuit.com) 
;
;IRQ7 hooks INT 0Fh
;IRQ5 hooks INT 0Dh
;
;Generally LPT1 is on port 378/IRQ7, and LPT2 is port 278/IRQ5
;Port 3BC does not work well for this, apparently a broken IRQ line.
;
;  Standard null-printer cable wiring (machine1 - machine2):
;  2-15, 3-13, 4-12, 5-10, 6-11, 15-2, 13-3, 12-4, 10-5, 11-6, 25-25
;
;
;Data flows 3 bits at a time:
;                    sender            receiver
;       (send first set)   IRQ1->
;                                   <-ACK1
;      (send second set)   IRQ2->
;                                   <-ACK2
;       (send third set)   IRQ3->
;                                   <-ACK3
;
;No error checking, no BUSY.

Hook    EQU     0Dh             ;IRQ5
Port    EQU     278h            ;
Screen  EQU     0B000h          ;Monochrome 0B000h  Color 0B800h

timer   EQU     1               ;Timing loop value. Increase if needed.

.286                            ;Uses 286 opcodes.
cseg segment
assume cs:cseg, ds:cseg
org 100h                        ;COM format.

Begin:
        call    Setup           ;Initialize ports.

  getkey:
        mov     ah,0            ;Use BIOS to get a
        int     16h             ; key from the keyboard.
        cmp     al,27           ;Is escape key?
        jne     main
        jmp     alldone         ; yes, so we quit.

    main:
        mov     ax,Screen       ;Do a screen dump.
        mov     ds,ax
        xor     si,si
        mov     cx,2000

  s:    lodsb
        inc     si              ;Skip screen attribute.
        call    Send
        loop    s

        jmp     getkey

;********************************************************************
Setup proc near
        mov     dx,offset Msg   ;Prints the hello message.
        mov     ah,09h
        int     21h

        mov     ah,35h          ;Get old vector and store it.
        mov     al,Hook
        int     21h
        mov     word ptr [Old_Int],bx
        mov     word ptr [Old_Int+2],es

        mov     al,Hook         ;Change the target vector.
        mov     dx,offset New_ISR
        mov     ah,25h
        int     21h

        mov     dx,Port
        mov     al,00000000b    ;Clear IRQ.
        out     dx,al
        mov     dx,Port+2       ;Control register.
        mov     al,00011100b    ;Initialize (IRQ on).
        out     dx,al

        in      al,21h          ;Enable IRQ's 5 and 7.
        and     al,01011111b    ;Doing both, don't need to.
        out     21h,al
        ret
endp

;****************************************************************
; Sends a byte over the parallel port.
; Registers unchanged.
;
Send proc near
        pusha
        push    ds
        push    es

        push    cs
        pop     ds
        mov     ah,al           ;Save it.

;Send 1st
        mov     dx,Port
        mov     al,00000000b    ;Bring IRQ line low.
        out     dx,al
        call    delay
        mov     al,ah           ;Load data from AH.
        and     al,00000111b    ;Only lower three bits.
        or      al,00001000b    ;Set IRQ line high.
        out     dx,al           ;Ship it.

        mov     bl,1
        call    listen          ;ACK'd?
        jc      nobody

;Send 2nd
;
        mov     dx,Port
        mov     al,00000000b    ;Bring IRQ line low.
        out     dx,al
        call    delay
        mov     al,ah           ;Load data from AH.
        shr     al,3            ;Move second set into position.
        and     al,00000111b    ;Only those three bits.
        or      al,00001000b    ;Set IRQ line high.
        out     dx,al           ;Ship it.

        mov     bl,2
        call    listen          ;ACK'd?
        jc      nobody

;Send 3rd
;
        mov     dx,Port
        mov     al,00000000b    ;Bring IRQ line low.
        out     dx,al
        call    delay
        mov     al,ah           ;Load data from AH.
        shr     al,6            ;Move third set into position.
        and     al,00000111b    ;Only those bits. (Really 2 bits)
        or      al,00001000b    ;Set IRQ line high.
        out     dx,al           ;Ship it.

        mov     bl,3
        call    listen          ;ACK'd?
        jc      nobody

        pop     es
        pop     ds
        popa
        ret
endp

;***********************************************************************
; Listen on port for ACK in BL. Carry set on failure.
;
listen proc near
        mov     cx,0FFFFh
listen1:
        call    delay
        mov     dx,Port+1       ;Read data waiting.
        in      al,dx
        shr     al,3            ;Move bits into position.
        and     al,00000111b    ;Mask upper nibble away.
        cmp     al,bl           ;Is it our ACK in BL?
        loopne  listen1         ; nope, loop.
        stc                     ;Carry set on error.
        jcxz    listen2         ;If CX=0 then we have timed out.
        clc                     ;Okay, clear carry.
        ret
 listen2:
        ret
endp
;***********************************************************************
; Miscellaneous routines.
;
  delay:
        push    cx
        mov     cx,timer
    d1: out     0BDh,al         ;Simple I/O delay.
        loop    d1
        pop     cx
        ret

 nobody:
        mov     dx,offset Msg2
        mov     ah,9
        int     21h             ;Print 'nobody home' message
                                ; and fall through...
 alldone:
        in      al,21h          ;Disable IRQ's 5 and 7.
        or      al,10100000b
        out     21h,al

        mov     ax,word ptr cs:[Old_Int +2]
        mov     dx,word ptr cs:[Old_Int]
        mov     ds,ax
        mov     al,Hook         ;Restore old ISR.
        mov     ah,25h
        int     21h
        int     20h             ;Exit to DOS.

;***********************************************************************
; Data storage area.

Msg      db 13,10
         db 'Parallel port Screen dump, demonstrating data transfer.',13,10
         db 'Press any key to dump screen, ESC to terminate.',13,10
         db 13,10,36
Msg2     db 13,10,"There's nobody listening..",13,10,36
Old_Int  dd  ?                  ;Storage- points to the old ISR.
tmp      db  ?
ack      db  1

;***********************************************************************
; This ISR prints the data received to the screen.
;
;  Note: Receiving 00001000b appears as 11000111b on the input port.
;                      ^^^^              ^^^^
;     Input port bits:  7       6       5     4     3     2    1    0
;              Useage: BUSY, IRQ/DATA, DATA, DATA, DATA, N/C, N/C, N/C
;
New_ISR proc near
        pusha                   ;Save the registers
        push    ds
        push    es
        push    cs
        pop     ds

        mov     al,ack          ;Determine which set.
        cmp     al,1
        je      _1st
        cmp     al,2
        je      _2nd
        cmp     al,3
        je      _3rd
        jmp     exit
 _1st:
        mov     dx,Port+1       ;Get from input port
        in      al,dx
        shr     al,3            ;Move into position.
        and     al,00000111b    ;Just those three bits.
        mov     tmp,al          ;Store them.
        mov     al,1
        mov     ack,al          ;Return ACK1
        jmp     ackd

 _2nd:
        mov     dx,Port+1       ;Get from input port
        in      al,dx
        and     al,00111000b    ;Bits already in position.
        or      tmp,al          ;Store them.
        mov     al,2
        mov     ack,al          ;Return ACK2
        jmp     ackd

 _3rd:
        mov     dx,Port+1       ;Get from input port
        in      al,dx
        shl     al,3            ;Move into position.
        and     al,11000000b    ;Just those two bits.
        or      tmp,al          ;Store them.
        mov     al,tmp
        int     29h             ;Print to screen. A cheat, potential bug.
        mov     al,3
        mov     ack,al          ;Return ACK3
        jmp     ackd
 ackd:

        mov     dx,Port
        mov     al,ack
        and     al,00000111b    ;Send ACK, no IRQ.
        out     dx,al

        inc     ack             ;Increment data counter
        cmp     ack,4           ; for next set. 1, 2, 3
        jb      reset
        mov     al,1
        mov     ack,al

 reset:
        mov     al,20h          ;Ready for more interrupts.
        out     20h,al

 exit:
        pop     es              ;Restore registers
        pop     ds
        popa                    ;End of ISR- exit
        jmp     cs:[Old_Int]    ; to old vector.
endp
;***********************************************************************

cseg ends
end Begin
[ RETURN TO DIRECTORY ]