
;
FALSE   EQU     0H
TRUE    EQU     NOT FALSE
;
BASE    EQU     0
;
EXITCHR EQU     '\'-40H ; CTL-\ TO EXIT TERM MODE TO MS-DOS
ESC     EQU     06H     ; CTL-F TO EXIT TERM MODE TO FILE RECEIVE
;
FASTCLK EQU     TRUE
;
;
; MODEM DEFINITIONS
MODCTLP EQU     042H
MODCTL2 EQU     002H
MODSNDB EQU     4
MODSNDR EQU     4
MODRCVB EQU     1
MODRCVR EQU     1
MODDATP EQU     040H
BAUDRP  EQU     006H
;
;
ERRLIM  EQU     10
;
SOH     EQU     1
EOT     EQU     4
ACK     EQU     6
NAK     EQU     015H
CAN     EQU     018H
LF      EQU     10
CR      EQU     13
;
FCB     EQU     BASE+5CH
;
;
STACK   SEGMENT PARA STACK 'STACK'
        DW      100 DUP(?)      ; INITIALIZE STACK TO ALL ZEROS.
STK     EQU     THIS WORD
STACK   ENDS
;
;
MAIN    SEGMENT PARA PUBLIC 'MAIN'
        ASSUME CS:MAIN,DS:DATAS,SS:STACK,ES:NOTHING
;
START   PROC    FAR
        PUSH    DS              ; SAVE SYSTEM DATA AREA
        XOR     AX,AX
        PUSH    AX              ; PUT ZERO RETURN ADDR ON STACK
        MOV     AX,DATAS        ; INITIALIZE DS
        MOV     DS,AX
        XOR     AX,AX
        MOV     OLDSTK,SP       ; SAVE STACK POINTER
        CLD
; MOVE THE FCB INTO OUR AREA
        MOV     BX,OFFSET OURFCB
        MOV     DI,FCB
        MOV     CX,0CH
FCBMOV: MOV     AL,ES: BYTE PTR [DI]
        MOV     DS: BYTE PTR [BX],AL
        INC     DI
        INC     BX
        LOOPNE  FCBMOV
; Start processing
        CALL    INITADR
        CALL    ILPRT
        DB      'MBOOT/MS-D0S as of 9/4/83',CR,LF,0
        MOV     AL,OURFCB+1
        CMP     AL,' '
        JNZ     TERMI
        CALL    ILPRT
        DB      '++No filename specified++',CR,LF,0
        JMP     EXIT
;
TERMI:  CALL    INITMOD
        IN      AL,MODDATP
        IN      AL,MODDATP
        CALL    ILPRT
        DB      CR,LF,'Terminal mode',CR,LF
        DB      'CTL-\ exits to MS-DOS, CTL-F starts file transfer.'
        DB      CR,LF,0
;
TERM:   CALL    KEYIN
        JZ      TERML
        CMP     AL,EXITCHR
        JNZ     TERM01
        JMP     EXIT
TERM01: CMP     AL,ESC
        JZ      RCVFIL
        PUSH    AX
TERM02: IN      AL,MODCTLP
        AND     AL,MODSNDB
        CMP     AL,MODSNDR
        JNZ     TERM02
        POP     AX
        OUT     MODDATP,AL
TERML:  IN      AL,MODCTLP
        AND     AL,MODRCVB
        CMP     AL,MODRCVR
        JNZ     TERM
        IN      AL,MODDATP
        AND     AL,7FH
        CALL    TIPE
        JMP     TERM
;
RCVFIL: CALL    ERASFIL
        CALL    MAKEFIL
        CALL    ILPRT



        DB      'File open, ready to receive.',CR,LF,0
;
RCVLP:  CALL    RCVSECT
        JC      RCVEOT
        CALL    WRSECT
        CALL    INCRSNO
        CALL    SENDACK
        JMP     RCVLP
;
RCVEOT: CALL    WRBLOCK
        CALL    SENDACK
        CALL    CLOSFIL
        CALL    ERXIT
        DB      CR,LF,'Transfer complete$'
;
EXIT:   MOV     SP,OLDSTK
        RET
START   ENDP
;
RCVSECT:
        MOV     ERRCT,0
;
RCVRPT: MOV     CH,10
        CALL    RECV
        JC      RCVSERR
        CMP     AL,SOH
        JZ      RCVSOH
        OR      AL,AL
        JZ      RCVRPT
        CMP     AL,EOT
        STC
        JNZ     RCVSERR
        RET
;
RCVSERR:
        MOV     CH,1
        CALL    RECV
        JNC     RCVSERR
        MOV     AL,NAK
        CALL    SEND
        MOV     AL,ERRCT
        INC     AL
        MOV     ERRCT,AL
        CMP     AL,ERRLIM
        JC      RCVRPT
;
RCVSABT:
        CALL    CLOSFIL
        CALL    ERXIT
        DB      '++Unable to receive block'
        DB      CR,LF,'++Aborting++$'
;
RCVSOH:
        MOV     CH,1
        CALL    RECV
        JC      RCVSERR
        MOV     DH,AL
        MOV     CH,1
        CALL    RECV
        JC      RCVSERR
        NOT     AL
        CMP     AL,DH
        JZ      RCVDATA
        JMP     RCVSERR
;
RCVDATA:
        MOV     RCVSNO,DH
        MOV     CL,0
        MOV     BX,OFFSET OURBUF
;
RCVCHR: MOV     CH,1
        CALL    RECV
        JC      RCVSERR
        MOV     DS: BYTE PTR [BX],AL
        INC     BX
        CMP     BX,OFFSET OURBUF+80H
        JNZ     RCVCHR
        MOV     DH,CL
        MOV     CH,1
        CALL    RECV
        JC      RCVSERR
        CMP     DH,AL
        JZ      RCVCHR01
        JMP     RCVSERR
RCVCHR01:
        MOV     CH,RCVSNO
        MOV     AL,SECTNO
        CMP     CH,AL
        JZ      RECVACK
        INC     AL
        CMP     CH,AL
        JNZ     ABORT
        RET
;
RECVACK:
        CALL    SENDACK
        JMP     RCVSECT
;
SENDACK:
        MOV     AL,ACK
;
SEND:   PUSH    AX
        ADD     CL,AL
SENDW:  IN      AL,MODCTLP
        AND     AL,MODSNDB
        CMP     AL,MODSNDR
        JNZ     SENDW
        POP     AX
        OUT     MODDATP,AL
        RET
;
ABORT:
;
ABORTL: MOV     CH,1
        CALL    RECV
        JNC     ABORTL
        MOV     AL,CAN
        CALL    SEND
;
ABORTW: MOV     CH,1
        CALL    RECV
        JNC     ABORTW
        MOV     AL,' '
        CALL    SEND
        CALL    ERXIT
        DB      'MBOOT program cancelled$'
;
INCRSNO:
        INC     SECTNO
        RET
;
ERASFIL:
        MOV     DX,OFFSET OURFCB
        MOV     AH,11H
        CALL    BDOS
        INC     AL
        JNZ     ERAS01
        RET
ERAS01:
        CALL    ILPRT
        DB      '++File exists, type Y to erase:',0
ERAS03: CALL    KEYIN
        JZ      ERAS03
        PUSH    AX
        CALL    TIPE
        CALL    CRLF
        POP     AX
        AND     AL,5FH
        CMP     AL,'Y'
        JZ      ERAS02
        JMP     MXIT
ERAS02:
        MOV     DX,OFFSET OURFCB
        MOV     AH,19
        JMP     BDOS
;
MAKEFIL:
        MOV     DX,OFFSET OURFCB
        MOV     AH,22
        CALL    BDOS
        INC     AL
        JZ      MAKE01
        RET
MAKE01:
        CALL    ERXIT
        DB      "++Error - can't make file", CR,LF
        DB      '++Directory must be full$'
;
CLOSFIL:
        MOV     DX,OFFSET OURFCB
        MOV     AH,16
        CALL    BDOS
        INC     AL
        JZ      CLOS01
        RET
CLOS01:
        CALL    ERXIT
        DB      "++Can't close file$"
;
WRSECT: MOV     BX,SECPTR
        XCHG    BX,DX
        MOV     BX,OFFSET OURBUF
        CALL    MOVE128
        XCHG    BX,DX
        MOV     SECPTR,BX
        MOV     AL,SECINBF
        INC     AL
        MOV     SECINBF,AL
        CMP     AL,16
        JZ      WRBLOCK
        RET
;
WRBLOCK:
        MOV     AL,SECINBF
        OR      AL,AL
        JNZ     WRBL01
        RET
WRBL01:
        MOV     CL,AL
        MOV     DX,OFFSET DBUF
;
DKWRLP: PUSH    BX
        PUSH    DX
        PUSH    CX
        MOV     AH,26
        CALL    BDOS
        MOV     DX,OFFSET OURFCB
        MOV     AH,21
        CALL    BDOS
        POP     CX
        POP     DX
        POP     BX
        OR      AL,AL
        JNZ     WRERR
        MOV     BX,OFFSET 80H
        ADD     BX,DX
        XCHG    BX,DX
        DEC     CL
        JNZ     DKWRLP
        XOR     AL,AL
        MOV     SECINBF,AL
        MOV     BX,OFFSET DBUF
        MOV     SECPTR,BX
RSDMA:
        MOV     DX,OFFSET 80H
        MOV     AH,26
        JMP     BDOS
;
WRERR:  CALL    RSDMA
        CALL    ILPRT
        DB      '++Error writing file',CR,LF,0
        JMP     ABORT
;
RECV:   PUSH    DX
;
        IF      FASTCLK
        MOV     AL,CH
        ADD     AL,AL
        MOV     CH,AL
        ENDIF
;
MSEC:   MOV     DX,15000
;
MWTI:
        IN      AL,MODCTLP
        AND     AL,MODRCVB
        CMP     AL,MODRCVR
        JZ      MCHAR
        DEC     DL
        JNZ     MWTI
        DEC     DH
        JNZ     MWTI
        DEC     CH
        JNZ     MSEC
        POP     DX
        STC
        RET
;
MCHAR:  IN      AL,MODDATP
        POP     DX
        ADD     CL,AL
        OR      AL,AL
        RET

INITADR:
        RET
;
;
INITMOD:
;
        MOV     AL,24
        OUT     MODCTLP,AL
        MOV     AL,4
        OUT     MODCTLP,AL
        MOV     AL,68
        OUT     MODCTLP,AL
        MOV     AL,1
        OUT     MODCTLP,AL
        MOV     AL,0
        OUT     MODCTLP,AL
        MOV     AL,3
        OUT     MODCTLP,AL
        MOV     AL,193
        OUT     MODCTLP,AL
        MOV     AL,5
        OUT     MODCTLP,AL
        MOV     AL,234
        OUT     MODCTLP,AL
        MOV     AL,0
        OUT     MODCTLP,AL
        MOV     AL,00           ; CLEAR BITS TO SET DTR
        OUT     MODCTL2,AL      ; OUT TO COMM CONTROL REGISTER
        RET
;
;
BDOS:   PUSH    ES      ; PRESERVE ES
        INT     DOS     ; MS-DOS CALL
        POP     ES
        RET
;
CRLF:   MOV     AL,CR
        CALL    TIPE
        MOV     AL,LF
;
TIPE:   PUSH    CX
        PUSH    DX
        PUSH    BX
        PUSH    SI
        AND     AL,07FH
        MOV     DL,AL
        MOV     AH,DCONIO
        CALL    BDOS
        POP     SI
        POP     BX
        POP     DX
        POP     CX
        RET
;
; KEYBOARD INPUT
;
KEYIN:  MOV     AH,DCONIO
        MOV     DL,0FFH
        CALL    BDOS
        OR      AL,AL
        RET
;
ILPRT:  POP     SI
        XCHG    BX,SI
        PUSH    SI
;
ILPLP:  MOV     AL,CS: BYTE PTR [BX]
        OR      AL,AL
        JZ      ILPRET
        CALL    TIPE
        INC     BX
        JMP     ILPLP
;
ILPRET: INC     BX
        POP     SI
        XCHG    BX,SI
        PUSH    SI
        RET
;
ERXIT:  POP     DX
        PUSH    DS
        MOV     AX,CS
        MOV     DS,AX
        MOV     AH,9
        CALL    BDOS
        POP     DS
;
MXIT:   CALL    ILPRT
        DB      CR,LF,"Don't forget to disconnect modem"
        DB      CR,LF,0
        JMP     EXIT
;
MOVE128:
        MOV     CH,128
;
MOVE:   MOV     AL,DS: BYTE PTR [BX]
        XCHG    BX,DX
        MOV     DS: BYTE PTR [BX],AL
        XCHG    BX,DX
        INC     BX
        INC     DX
        DEC     CH
        JNZ     MOVE
        RET
MAIN    ENDS
;
DATAS   SEGMENT PARA    PUBLIC 'DATAS'
;
;
        ORG     100H
OLDSTK  DW      ?
OURFCB  DB      25H DUP(0)
RCVSNO  DB      0
OURBUF  DB      80H DUP(?)
SECTNO  DB      0
ERRCT   DB      0
EOFLG   DB      0
SECPTR  DW      DBUF
SECINBF DB      0
DBUF    DB      16*128 DUP(?)
FAKE    DB      0
;
; BDOS EQUATES
DCONIO  EQU     06H
CONSTAT EQU     0BH
CONST   EQU     11
DOS     EQU     21H

DATAS   ENDS
        END     START

