;Autor: Claudio Eduardo Storti Lago <edulago@mandic.com.br> - 1999
;Distribui‡Æo livre, desde que seja mantida a integridade do arquivo fonte
;(modifica‡äes nÆo sÆo permitidas sem a autoriza‡Æo do autor).

        TITLE   ** Serial Chat v1.0 **

        memoria_video   equ     0b800h
        serial_cfg      equ     11100011b               ;9600 bps
                                                        ;s/ paridade
                                                        ;2 sb
                                                        ;8 bits
        att_linha       equ     01110000b
        att_transmi     equ     00010111b
        att_receive     equ     00100000b

        codigo  segment byte
        assume  cs:codigo,ds:codigo,es:codigo,ss:codigo

        org     100h

inicio: jmp     main

        presents        db      'Serial Chat v1.0',10,13
                        db      'por Claudio Eduardo Storti Lago'
                        db      13,10,13,10
                        db      'Qual o porto serial que vocˆ deseja usar?'
                        db      13,10,'COM(1)',13,10,'COM(2)',13,10,'$'
        porta           dw      ?
        porta_num       dw      ?           
        porta_con       dw      ?           
        menu            db      ' Serial Chat v1.0 - Tecle Crtl+Q para sair$'

        posicao_trans   dw      0000h
        posicao_receb   dw      0C00h

        copyright       db      'Copyright Claudio Eduardo Lago - 1999'

        old_cursor      dw      ?

        main    proc near
                                                        
        mov     ah,3                                           
        int     10h

        mov     [old_cursor],cx                         ;Salva o cursor

        mov     ah,1                                    ;Tira o cursor
        mov     ch,32
        int     10h

        call    clrscr

        lea     dx,presents
        mov     ah,9
        int     21h

le_outro:
        mov     ah,8                                    ;Utiliza a fun‡Æo
        int     21h                                     ;8 da INT21h para
        cmp     al,'1'                                  ;ler qual o porto
        je      com1                                    ;a ser utilizado
        cmp     al,'2'
        jne     le_outro
        mov     [porta],1                               ;0=com1
        mov     [porta_num],02f8h                       
        mov     [porta_con],02fdh                       
        jmp     fim_setup                               ;1=com2
com1:   mov     [porta],2
        mov     [porta_num],03f8h
        mov     [porta_con],03fdh
fim_setup:

        call    clrscr                                  ;Limpa a Tela

        call    monta_tela                              ;Faz a divisÆo de
                                                        ;cores
                     
        mov     ax,01800h                               ;Coloca a posi‡Æo
        push    ax                                      ;inicial na pilha
                                                        ;linha coluna

        call    gotoxy                                  ;Posiciona na Tela

        lea     dx,menu                                 ;Escreve o menu
        mov     ah,9
        int     21h

        xor     ax,ax                                   ;Posiciona o cursor
        push    ax

        call    gotoxy                                  ;Posiciona na Tela

        mov     dx,[porta]                              ;Configura a serial
        mov     ah,0
        mov     al,serial_cfg
        int     14h
main_loop:                                              ;Loop Principal
        mov     ah,0bh                                  ;Verifica se h  uma
        int     21h                                     ;tecla para ser 
        cmp     al,0ffh                                 ;transmitida
        je      trans_link
        jmp     pula_link
trans_link: jmp     transmite_tecla                     ;Caso tenha envia
pula_link: mov     dx,[porta_con]                       ;Verifica o controle
        in      al,dx                                   ;Caso nÆo tenha 
        and     al,1                                    ;recebindo nenhuma,
        cmp     al,1                                    ;volta ao in¡cio do
        jne     main_loop                               ;loop

        mov     dx,[porta_num]                          ;Lˆ o byte recebido
        in      al,dx                                   
        cmp     al,13                                   ;Verifica RETURN
        jne     t_1                                     ;Se nÆo for pula
        mov     dx,[posicao_receb]                      ;tratamento
        shr     dx,8
        sub     dx,11
        cmp     dx,12
        je      rola_receive                            ;Caso esteja
        add     [posicao_receb],0100h                   ;lotato rotaciona
        and     [posicao_receb],0ff00h                  ;senÆo apenas 
        jmp     t_1                                     ;incrementa
rola_receive:
        call    rola_receiver                           ;Rola a tela
t_1:    cmp     al,8                                    ;Verifica BS
        jne     t_2                                     ;se nÆo pula trat.
        mov     dx,[posicao_receb]                      ;Verifica o n£mero
        and     dx,00ffh                                ;de colunas
        cmp     dx,0                                    ;Se zero nÆo DEC
        je      t_2_1
        dec     [posicao_receb]                         ;DEC
t_2_1:  mov     dx,[posicao_receb]                      ;Localiza a posi‡Æo
        push    dx                                      ;na tela
        call    gotoxy

        mov     ah,2                                    ;Limpa EOL
        mov     dl,' '                                  ;(fim da linha)
        int     21h
        mov     dx,[posicao_receb]
        push    dx
        call    gotoxy

        jmp     pula_linha_fim_2
t_2:    cmp     al,13                                   ;Caso seja RETURN
        je      pula_linha_fim_2                        ;nÆo mostra
        mov     dx,[posicao_receb]                      ;Localiza a posi‡Æo
        push    dx                                      ;na tela
        call    gotoxy
                         
        mov     ah,2                                    ;Escreve o caracter
        mov     dl,al                                   ;lido
        int     21h
        inc     [posicao_receb]                         ;INC a posi‡Æo
        mov     dx,[posicao_receb]                      ;Verifica se nÆo
        and     dx,0ffh                                 ;passou da tela
        cmp     dx,80
        jne     pula_linha_fim_2                        ;Caso nÆo pula
        mov     dx,[posicao_receb]                      ;Tratamento
        shr     dx,8
        sub     dx,11                                   ;Ajusta a tela
        cmp     dx,12                                   
        je      rola_receive_2                          ;Pula para a rolagem
        add     [posicao_receb],0100h
        and     [posicao_receb],0ff00h
        jmp     pula_linha_fim_2
rola_receive_2:
        call    rola_receiver                           ;Rola a tela (REC)
        
pula_linha_fim_2: jmp     main_loop                     ;Volta ao loop

transmite_tecla:                                        ;Transmite a tecla
        mov     ah,8                                    ;pega o byte do
        int     21h                                     ;teclado
        cmp     al,17                                   ;Compara com Crtl+Q
        je      termina_loop_min                        ;Se = salta
        jmp     pula_min                                
termina_loop_min:
        jmp     termina_loop
pula_min: cmp     al,8                                  ;Compara com o BS
        je      remove                                  ;se for remove
        cmp     al,13                                   ;Compara com RETURN
        jne     continua                                ;Se nÆo for pula
        mov     dx,[posicao_trans]                      ;Verifica tela cheia
        shr     dx,8
        cmp     dx,11
        je      pula_linha                              ;Se cheia Rola a tela
        add     [posicao_trans],100h                    ;Pula a linha
        and     [posicao_trans],0ff00h
        jmp     continua
remove: mov     dx,[posicao_trans]                      ;Remove o caractere
        and     dx,0ffh
        cmp     dx,0
        je      continua
        dec     [posicao_trans]                         ;DEC
        jmp     continua
pula_linha:
        call    rola_transmitter                        ;Rola a tela
continua: push    ax                                    ;Päe AX na pilha
espera: mov     dx,[porta_con]                          ;Lˆ o controle
        in      al,dx                                   ;Verifica se o
        and     al,00100000b                            ;buffer est  
        cmp     al,00100000b                            ;dispon¡vel
        jne      espera

        mov     dx,[posicao_trans]                      ;Posiciona  na tela
        push    dx

        call    gotoxy

        pop     ax                                      ;Restaura ax
        mov     dx,[porta_num]                          ;Transmite a tecla
        out     dx,al

        cmp     al,13                                   ;Compara com RETURN
        je      main_loop_min                           ;se for nÆo mostra
        jmp     pula_min_2
main_loop_min: jmp     main_loop
pula_min_2: cmp     al,8                                ;Compara com BS
        je      ceol                                    ;se for limpa EOL
        mov     ah,2
        mov     dl,al
        int     21h

        inc     [posicao_trans]                         ;INC posicao
        mov     dx,[posicao_trans]
        and     dx,0ffh
        cmp     dx,80                                   ;Compara linha cheia
        jne     pula_linha_fim
        mov     dx,[posicao_trans]
        shr     dx,8
        cmp     dx,11
        je      pula_linha_2
        add     [posicao_trans],100h                    ;Caso cheia
        and     [posicao_trans],0ff00h                  ;Pula linha
        jmp     pula_linha_fim
pula_linha_2:
        call    rola_transmitter                        ;Caso tela cheia
                                                        ;Rotaciona
        
pula_linha_fim: jmp     main_loop

ceol:   mov     ah,2                                    ;Limpa EOL
        mov     dl,' '
        int     21h
        mov     dx,[posicao_trans]
        push    dx
        call    gotoxy
        jmp     main_loop                               ;Retorna ao LOOP
termina_loop:                                           ;Fim do la‡o

        call    clrscr                                  ;Limpa a tela
                                                        
        xor     ax,ax                                   ;Posiciona no canto
        push    ax                                      ;superior esquerdo

        call    gotoxy

        mov     ah,1                                    ;Coloca o cursor
        mov     cx,[old_cursor]
        int     10h

        ret                                             ;Retorna

        main    endp

        clrscr  proc near                               ;Apaga a tela
        mov     ah,6                                    ;Utiliza fun‡Æo
        mov     bh,7                                    ;BIOS para apagar
        xor     cx,cx                                   ;a tela INT 10h
        mov     dx,184fh
        mov     al,cl
        int     10h
        ret
        clrscr  endp

        gotoxy  proc near
        pop     cx                                      ;POP IP return
        pop     dx                                      ;POP dx (linha coluna)
        push    cx                                      ;PUSH IP return
        mov     ah,2
        mov     bh,0
        int     10h
        ret
        gotoxy  endp

        monta_tela proc near                            ;Monta todas as cores
        push    ax                                      ;da tela principal
        push    es
        mov     ax,memoria_video                        ;es cont‚m o valor
        mov     es,ax                                   ;da mem¢ria de video
        xor     di,di                                   ;Coloca todos os 
        mov     ah,att_transmi                          ;atributos diretamente
        mov     al,0
        mov     cx,960
        rep     stosw
        mov     ah,att_receive
        mov     al,0
        mov     cx,960
        rep     stosw
        mov     ah,att_linha
        mov     al,0
        mov     cx,80
        rep     stosw
        pop     es
        pop     ax
        ret
        monta_tela endp

        rola_transmitter proc near                      ;Rola a tela do
        push    ax                                      ;transmissor
        push    cx                                      ;Salva os
        push    es                                      ;registradores para
        push    ds                                      ;evitar perda de
        mov     cx,880                                  ;dados
        mov     ax,memoria_video
        mov     ds,ax                                   ;Copia a mem¢ria para
        mov     es,ax                                   ;a primeira posicao
        mov     di,0                                    ;da tela do
        mov     si,160                                  ;transmissor com
        rep     movsw                                   ;delta de 160 bytes
        mov     ah,att_transmi
        mov     al,' '
        mov     cx,80
        mov     di,1760
        rep     stosw
        pop     ds
        pop     es
        pop     cx
        pop     ax
        and     [posicao_trans],0ff00h
        ret
        rola_transmitter endp

        rola_receiver proc near                         ;Rola a tela do
        push    ax                                      ;receptor
        push    cx
        push    es                                      ;Salva os
        push    ds                                      ;registradores para
        mov     cx,880                                  ;evitar perda de
        mov     ax,memoria_video                        ;dados
        mov     ds,ax
        mov     es,ax                                   ;Copia a mem¢ria para
        mov     di,1920                                 ;a primeira posicao
        mov     si,2080                                 ;da tela do receptor
        rep     movsw                                   ;com delta de 160
        mov     ah,att_receive                          ;bytes
        mov     al,' '
        mov     cx,80
        mov     di,3680
        rep     stosw
        pop     ds
        pop     es
        pop     cx
        pop     ax
        and     [posicao_receb],0ff00h
        ret
        rola_receiver endp

        ends

        end     inicio
