; Received from Kelly Smith's CP/M-NET (tm) ; For publication in Doctor Dobb's Journal ; ; ASSEMBLED, LOADED AND EXECUTED AS SHOWN ; (except for custom equates) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; MBOOT.ASM ver 3.0 ; (revised 5 Nov 80) ; ;MODEM BOOT PROGRAM by Keith Petersen, W8SDZ. ;Thanks to John Taylor for idea of incorporating ;simple terminal routine. Based on MODEM.ASM V2.O, ;by Ward Christensen with enhancements from MODEM527. ; ;CP/M - CP/M file transfer program (receive-only) ; ;This program is intended for use as a way to ;initially transfer MODEM.COM or MODEM.ASM to ;a new user. It may be used with almost any ;modern (see equates). If PMMI or D.C. Hayes modem ;is used, then uses 'ORIGINATE' mode, 300 baud. ; ;A simple terminal routine at start of program allows ;user to communicate with a remote system prior to ;receiving a file to make it possible to down-load ;a file without intervention on the part of the host ;system's operator. ; ;COMMANDS: MBOOT FILENAME.FILETYPE ; or MBOOT A:FILENAME.FILETYPE ; or MBOOT B:FILENAME.FILETYPE ; ;The program will operate as a dumb terminal until ;an 'ESC' key is typed (ctrl-[). It then branches ;to the receive routine. The user may also exit ;to CP/M without opening the receive file by typing ;ctrl-E from the terminal. The values for the escape ;and exit keys may be changed in accordance with the ;needs of the user - some keyboards do not have the ;'ESC' key and/or provision for control characters. ;See equates. ; ;NOTE: Comments for the source code and tabs have been ;removed to make this file easier to transport from one ;System to another. (KBP) ; ;NOTE: NOTE: TABS have been re-expanded for DDJ format ; false equ 0 true equ not false ; stdcpm equ true ; TRUE, IS STANDARD CP/M altcpm equ false ; TRUE, IS ALTERNATE CP/M FOR HB OR TRS80 ; if stdcpm base equ 0 endif ; if altcpm base equ 4200h endif ; exitchr equ 05h ; CTL-E TO EXIT TERM MODE TO CP/M esc equ 1bh ; ESCAPE TO EXIT TERM MODE TO FILE RCVE ; fastclk equ false ; TRUE FOR 4 MHZ CLOCK ; pmmi equ true ; TRUE, IS PMMI MODEM dch equ false ; TRUE, IS D.C. HAYES MODEM ; ;IF YOU ARE USING AN EXTERNAL MODEM (NOT S-1OO PLUG-IN) ;CHANGE THESE EQUATES FOR YOUR MODEM PORT REQUIREMENTS ; initreq equ false ; TRUE, IF MODEM PORT INIT. REQ'D initc1 equ 0aah ; 1ST INIT CHAR TO CTL PORT FOR USART initc2 equ 40h ; 2ND " initc3 equ 4eh ; 3RD " initc4 equ 37h ; 4TH " ; if not pmmi and not dch modctlp equ 02h ; PUT YOUR MODEM CONTROL PORT HERE modsndb equ 80h ; YOUR BIT TO TEST FOR SEND modsndr equ 80h ; YOUR VALUE WHEN READY TO SEND modrcvb equ 40h ; YOUR BIT TO TEST FOR RECEI VE modrcvr equ 40h ; YOUR VALUE WHEN READY TO RECEIVE moddatp equ 03h ; YOUR MODEM DATA PORT endif ; END OF EXTERNAL MODEM EQUATES ; if pmmi modctlp equ 0c0h modsndb equ 1 modsndr equ 1 modrcvb equ 2 modrcvr equ 2 moddatp equ 0c1h baudrp equ 0c2h modctl2 equ 0c3h origmod equ 1dh answmod equ 1eh endif ; if dch modctlp equ 82h modsndb equ 2 modsndr equ 2 modrcvb equ 1 modrcvr equ 1 moddatp equ 80h modctl2 equ 81h origmod equ 87h answmod equ 83h endif ; errlim equ 10 ; soh equ 1 eot equ 4 ack equ 6 nak equ 15h can equ 18h lf equ 10 cr equ 13 ; bdos equ base+5 fcb equ base+5ch ; org base+100h ; ld hl,0 add hl,sp ld (stack),hl ld sp,stack call initadr call ilprt db 'MBOOT as of ' db '11/5/80',cr,lf,0 ld a,(fcb+1) cp ' ' jp nz,termi call ilprt db '++NO FILE NAME SPECIFIED++',cr,lf,0 jp exit ; termi: call initmod in a,(moddatp) in a,(moddatp) call ilprt db cr,lf,'TERMINAL MODE',cr,lf db 'CTL-E exits to CP/M, ESC starts file transfer' db cr,lf,0 ; term: call stat jp z,terml call keyin cp exitchr jp z,exit cp esc jp z,rcvfil out (moddatp),a ; if not dch terml: in a,(modctlp) endif ; if dch terml: in a,(modctl2) endif ; and modrcvb cp modrcvr jp nz,term in a,(moddatp) and 7fh call type jp term ; rcvfil: call erasfil call makefil call ilprt db 'FILE OPEN, READY TO RECEIVE',cr,lf,0 ; rcvlp: call rcvsect jp c,rcveot call wrsect call incrsno call sendack jp rcvlp ; rcveot: call wrblock call sendack call closfil call erxit db cr,lf,'TRANSFER COMPLETE$' ; rcvsect:xor a ld (errct),a ; rcvrpt: ld b,10 call recv jp c,rcvserr cp soh jp z,rcvsoh or a jp z,rcvrpt cp eot scf ret z ; rcvserr:ld b,1 call recv jp nc,rcvserr ld a,nak call send ld a,(errct) inc a ld (errct),a cp errlim jp c,rcvrpt ; rcvsabt:call closfil call erxit db: '++UNABLE TO RECEIVE BLOCK' db: cr,lf,'++ABORTING++$' ; rcvsoh: ld b,1 call recv jp c,rcvserr ld d,a ld b,1 call recv jp c,rcvserr cpl cp d jp z,rcvdata jp rcvserr ; rcvdata:ld a,d ld (rcvsno),a ld c,0 ld hl,base+80h ; rcvchr: ld b,1 call recv jp c,rcvserr ld (hl),a inc l jp nz,rcvchr ld d,c ld b,1 call recv jp c,rcvserr cp d jp nz,rcvserr ld a,(rcvsno) ld b, a ld a,(sectno) cp b jp z,recvack inc a cp b jp nz,abort ret ; recvack:call sendack jp rcvsect ; sendack:ld a,ack ; send: push af add a,c ld c,a ; if not dch sendw: in a,(modctlp) endif ; if dch sendw: in a,(modctl2) endif ; and modsndb cp modsndr jp nz,sendw pop af out (moddatp),a ret ; abort: ld sp,stack ; abortl: ld b,1 call recv jp nc,abortl ld a,can call send ; abortw: ld b,1 call recv jp nc,abortw ld a, ' ' call send call erxit db 'MBOOT PROSRAM CANCELLED$' ; incrsno:ld a,(sectno) inc a ld (sectno),a ret ; erasfil:ld de,fcb ld c,17 call bdos inc a ret z call ilprt db '++FILE EXISTS, TYPE Y TO ERASE:',0 call keyin push af call type call crlf pop af and 5fh cp 'Y' jp nz,mxit ld de,fcb ld c,19 jp bdos ; makefil:ld de,fcb ld c,22 call bdos inc a ret nz call erxit db '++ERROR - CAN''T MAKE FILE',cr,lf db '++DIRECTORY MUST BE FULL$' ; closfil:ld de,fcb ld c,16 call bdos inc a ret nz call erxit db '++CAN"T CLOSE FILE$' ; wrsect: ld hl,(secptr) ex de,hl ld hl,base+80h call move128 ex de,hl ld (secptr),hl ld a,(secinbf) inc a ld (secinbf),a cp 16 ret nz ; wrblock:ld a,(secinbf) or a ret z ld c,a ld de,dbuf ; dkwrlp: push hl push de push bc ld c,26 call bdos ld de,fcb ld c,21 call bdos pop bc pop de pop hl or a jp nz,wrerr ld hl,80h add hl,de ex de,hl dec c jp nz,dkwrlp xor a ld (secinbf),a ld hl,dbuf ld (secptr),hl ; rsdma: ld de,base+80h ld c,26 jp bdos ; wrerr: call rsdma call ilprt db '++ERROR WRITING FILE',cr,lf,0 jp abort ; recv: push de ; if fastclk ld a,b add a,a ld b,a endif ; msec: ld de,50000 ; if not dch mwti: in a,(modctlp) endif ; if dch mwti: in a,(modctl2) endif ; and modrcvb cp modrcvr jp z,mchar dec e jp nz,mwti dec d jp nz,mwti dec b jp nz,msec pop de scf ret ; mchar: in a,(moddatp) pop de push af add a,c ld c,a pop af or a ret ; initadr:ld hl,(base+1) ld de,3 add hl,de ld (vstat+1),hl add hl,de ld (vkeyin+1),hl add hl,de ld (vtype+1),hl ret ; initmod equ $ ; if initreq ld a,initc1 out (modctlp),a nop nop nop nop ndp ld a,initc2 out (modctlp),a nop nop nop nop nop ld a,initc3 out (modctlp),a nop nop nop nop nop ld a,initc4 out (modctlp),a nop nop nop nop nop endif ; if pmmi ld a,52 out (baudrp),a ld a,7fh out (modctl2),a endif ; if dch ld a,16h out (modctl2),a endif ; if pmmi or dch ld hl,4000 ; offdly: dec l jp nz,offdly dec h jp nz,offdly ld a,origmod out (modctlp),a endif ; ret ; <--THIS RET MUST BE HERE ; crlf: ld a,cr call type ld a,lf ; type: push af push bc push de push hl ld c,a vtype: call $-$ pop hl pop de pop bc pop af ret ; stat: push bc push de push hl vstat: call $-$ pop hl pop de pop bc or a ret ; keyin: push bc push de push hl vkeyin: call $-$ pop hl pop de pop bc and 7fh ret ; ilprt: ex (sp),hl ; ilplp: ld a,(hl) or a jp z,ilpret call type inc hl jp ilplp ; ilpret: ex (sp),hl ret ; erxit: pop de ld c,9 call bdos ; mxit: call ilprt db cr,lf,'DON"T FORGET TO DISCONNECT MODEM' db cr,lf,0 ; exit: ld hl,(stack) ld sp,hl ret ; move128:ld b,128 ; move: ld a,(hl) ld (de),a inc hl inc de dec b jp nz,move ret ; rcvsno: db 0 sectno: db 0 errct: db 0 eoflg: db 0 secptr: dw dbuf secinbf:db 0 ds 60 stack: ds 2 dbuf equ $ ; end