home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / PROGRAMS / WSTAR / SYA13.LBR / SYA13.AZM / SYA13.ASM
Assembly Source File  |  2000-06-30  |  26KB  |  917 lines

  1.  
  2.  
  3.  
  4. TITLE    'SYA Vers. 1.3 4/2/85'  
  5.  
  6.     TRUE    EQU    0FFh    
  7.     FALSE    EQU    00h
  8.  ; User-definable Features:
  9. ;******************* Define Editor ********************************
  10. ;         *** One, and ONLY one, Editor Equate May be TRUE ***    *
  11. TSC     EQU    FALSE    ;TSC is a line editor that defines line  *
  12.             ; numbers with 3 bytes after each CR    *
  13. WORDSTAR30 EQU    TRUE    ;                                      *
  14. ;                                                             *
  15. ;*******************End Editor Definition*********************
  16. ;                   Terminal Definition
  17. ;    Right now only for Televideo 950 - to display TXTPTR and 
  18. ;    mode (scrolling, paging, or line-by-line)
  19. TVI950    EQU    FALSE    ;displays TXTPTR in status line (except scrolling)
  20. ;
  21. ;*********************End Terminal Definition*******************************
  22. ;
  23.     ORG    100H
  24.     JMP    START        ;jump over DW for start of edit space
  25.  
  26. IF    WORDSTAR30    ;if WORDSTAR 3.0
  27. ED$SP$STRT    DW    7849H
  28. ENDIF    ;WS 3.0
  29.  
  30. IF TSC
  31. ED$SP$STRT    DW    0249Bh    ;Start of Edit Space for XED22 
  32.                 ;(actually, 2498H, but first 3 bytes
  33. ENDIF    ;TSC            ; are LINO not preceded by CR)
  34.  
  35.  
  36. IF TVI950
  37. TVI950FLG:    DB    0FFh    ;set the flag to display the TVI950
  38. ELSE                ; flag as desired
  39. TVI950FLG    DB    00h
  40. ENDIF
  41.  
  42.  
  43.  
  44. START:
  45.     LXI    SP,STAK    ;set up stack pointer
  46.     CALL    ILPRT    ;do short starting message
  47.     DB    CR,LF,9
  48.     DB    'SYA (SAVE YOUR ASSets)',' v.1.3, '
  49. IF    TSC
  50.     DB    'for XED-22',CR,LF
  51. ENDIF    ;TSC
  52. IF    WORDSTAR30
  53.     DB    'for WordStar 3.0',CR,LF
  54. ENDIF
  55.     DB    9,'     (C) E.Stork, Arlington VA 22205',0
  56. ;
  57.     LHLD    ED$SP$STRT    ;get the starting point for the editor
  58.     SHLD    TXTPTR        ;and store it
  59.  
  60.  
  61.     ;enter MENU with all pointers saved.  MENU trashes all registers
  62. MENU:    
  63.     CALL    ILPRT
  64.     DB    CR,LF,LF,9,9,9,9
  65.     DB    'MENU:',CR,LF,LF,9
  66.     DB    '''D'' = Display Memory from Current Pointer Position',CR,LF,9
  67.     DB    '''L'' = Scroll, Page, or Line-by line Display',CR,LF,9
  68.     DB    '''B'' = Back up (Max 255 lines each time)',CR,LF,9
  69.     DB    '''T'' = Return to Top of Edit Space',CR,LF,9
  70.     DB    '''S'' = Save to a file, from Top to current Pointer Position',CR,LF,9
  71. IF TVI950    
  72.     DB    '''F'' = Toggle Textpointer display on TVI-950 Status Line ON/OFF',CR,LF,9
  73. ENDIF
  74.     DB    '''M'' = Display this Menu',CR,LF,9
  75.     DB    '''X'' = Exit Now                             : ',0
  76.     CALL    INKEY    ; and fall through
  77.  
  78. ;Table for menu selection
  79. FUNC$TST:
  80.     CPI    'D' ! JZ    DUMP
  81. IF TVI950
  82.     CPI    'F' ! JNZ    MEN1
  83.     LDA    STATLINFLG    ;if 'F', we want to complement the flag
  84.     CMA            ; so do it
  85.     STA    STATLINFLG ! JMP MENU ; and store it away.
  86. ENDIF    ;tvi950
  87. MEN1:    CPI    'B' ! JZ    BACKUP
  88.     CPI    'L' ! JZ    LINES
  89.     CPI    'M' ! JZ    MENU
  90.     CPI    'S' ! JZ    SAVE
  91.     CPI    'T' ! JZ    TOP
  92.     CPI    'X' ! JZ    WRMBOOT
  93.     CPI    03h ! JZ    WRMBOOT
  94.     CALL ILPRT
  95.     DB    CR,LF,LF,LF,LF,9
  96.     DB    'Only ''B'',''L'',''M'',''S'',''D'','
  97. IF TVI950 
  98.     DB    '''F'','
  99. ENDIF
  100.      DB    'and ''T'' are legal.',CR,LF,LF,9
  101.     DB    'Type any key to return to Menu, ^C to quit: ',0
  102.     CALL    INKEY
  103.     JMP    MENU
  104. ;end of menu selection table
  105.  
  106.  
  107.         ;DUMPing starts at value in TXTPTR
  108.         ;all registers available for use
  109. DUMP:
  110.     MVI    C,CONOUT
  111.     MVI    E,0AH    ;send LF to console first
  112.     CALL    BDOS
  113.     MVI    A,22    ;set up EOL counter
  114.     STA    EOLCNTR    ;set the counter to 22, for paging
  115. DMP1:    LHLD    TXTPTR    ;get the starting point
  116.     MOV    A,M    ;get the byte from memory
  117.     INX    H    ;bump the pointer
  118.     SHLD    TXTPTR    ;save it.
  119.     JMP    CNTRL$CHAR    ;check for control character
  120. DMP2:    MOV    E,A    ;put character into [E]
  121.     MVI    C,CONOUT 
  122.     CALL    BDOS    ;and output the character
  123.         ;now check for interrupt (any key will interrupt dumping)
  124.     MVI    C,DIRCONIO ;use non-echo conin function #6
  125.     MVI    E,0FFH    ;we want to get a character
  126.     CALL    BDOS    ;returns non-zero if char is waiting, and
  127.     ORA    A    ;it's zero until character is typed
  128.     JNZ    EOL1    ;jump out of here if character waiting
  129.     JMP    DMP1    ;loop and keep dumping
  130.  
  131.  
  132. EOLINE:        ;comes here from CNTRL$CHAR on EOL
  133.     PUSH    PSW    ;save [A]
  134. IF TSC    ;assemble only if TSC Editor equate is TRUE
  135.     CALL    SKIP$LINO
  136. ENDIF    ;end if TSC
  137.     LDA    SCROLFLG ;get the flag
  138.     ORA    A    ;is non-zero if scrolling is wanted
  139.     JZ    EOL0    ;if zero, jump over immediate return
  140.     JMP    EOL3    ;return without stopping.
  141. EOL0:    LDA    TVI950FLG
  142.     ORA    A    ;flag is non-zero if TVI950 status display wanted
  143. IF TVI950
  144.     CNZ    DISP$STAT ;in which case, do the routine
  145. ENDIF
  146.     LDA    SNGL$LN$FLG    ;if single line mode, skip the message
  147.     ORA    A
  148.     JNZ    EOL1    ;if it is, skip counter & messages, but wait for keyin
  149.     LDA    EOLCNTR    ;get the counter
  150.     DCR    A    ;bump the counter down one
  151.     STA    EOLCNTR    ;and save it
  152.     ORA    A    ;is it zero yet?
  153.     JNZ    EOL3    ;if not yet 0, go on
  154.     MVI    A,22    ;else reset the counter
  155.     STA    EOLCNTR    ; to 22 lines
  156. EOL1:
  157.     CALL    INKEY
  158. IF    TVI950    ;kill status line
  159.     PUSH    PSW    ;save the response to INKEY
  160.     CALL    ILPRT
  161.     DB    ESC,'g',ESC,'f',ESC,'G0',CR,0
  162.     POP    PSW    ;get INKEY response back for testing
  163. ENDIF    ;TVI950
  164.     CPI 'M' ! JZ EOL2
  165.     CPI 'L' ! JZ EOL2
  166.     CPI 'D' ! JZ EOL2
  167.     CPI 'B' ! JZ EOL2
  168.     CPI 'S' ! JZ EOL2
  169.     CPI 'T' ! JZ EOL2
  170.     CPI 'X' ! JZ WRMBOOT
  171.     CPI 03h ! JZ WRMBOOT
  172.     JMP    EOL3    ;anything else, go on
  173. EOL2:    POP    D    ;balance stack (the PUSH PSW in this routine)
  174.             ;(OK to trash [DE])
  175.     PUSH    PSW    ;save the selected function
  176.     MVI    C,CONOUT
  177.     MVI    E,0DH    ;send <cr> to console first
  178.     CALL    BDOS
  179.     POP    PSW    ;get the selected function back
  180.     JMP    FUNC$TST ;go see what is wanted, and do it
  181. EOL3:
  182.     POP    PSW    ;get [A] back
  183.     JMP    DMP2    ;send the char to console, and continue
  184.  
  185. EOLCNTR: DB    22    ;counter for EOLs
  186.  
  187.     IF TSC    
  188. SKIP$LINO:    ;routine used only for TSC Editor
  189.     LHLD    TXTPTR    ;get the text pointer
  190.     INX    H    ; .. and bump it twice
  191.     INX    H    ;  .. to get past 2 of the 3 LINO bytes
  192.             ;   .. that TSC inserts after CR
  193.     MVI    M,LF    ; Then put a carriage return into the 3rd one
  194.     SHLD    TXTPTR    ;and store the text pointer again.
  195.     RET        ;then return to calling routine
  196. ENDIF    ;end of TSC-only routine
  197.  
  198.  
  199.  ;CALLed from DUMP. Enters & returns with current character in [A], unless
  200.  ;control character other than CR, LF, and TAB, which are dumped.
  201.  ;Might want to changed for WS* version
  202. CNTRL$CHAR:    ;first make a few tests, in case we overran the text
  203.     CPI    0AFH    ;that's XRA A - quite common
  204.     JZ    BACKUP    ;get out of here
  205.     CPI    99H    ;sometimes memory has that
  206.     JZ    BACKUP    ;get out
  207.     CPI    0D1H    ;POP D
  208.     JZ    BACKUP
  209.     CPI    0E1H    ;POP H
  210.     JZ     BACKUP
  211.     CPI    0F1H    ;POP PSW
  212.     JZ    BACKUP
  213.  
  214.  ;In case this is a 2nd try and there are already ^Z (EOF) in memory,
  215.  ;we'll NULL them out.  If we did not, we could not SAVE past that point.
  216.     CPI    1AH    ;^Z
  217.     JZ    NOZ    ;Jump to routine to NULL it out
  218. ;
  219.     ANI    7fh    ;now reset high bit 0, just in case
  220.     CPI    7fh    ;we don't want deletes
  221.     JZ    CC1
  222.     CPI    CR
  223.     JZ    EOLINE    ;on CR, go do EOLINE routine
  224.     CPI    LF
  225.     JZ    CC2    ;linefeed is OK
  226.     CPI    TAB
  227.     JZ    CC2    ;TAB is OK
  228.     CPI    20h
  229.     JNC    CC2    ;this skips all other control chars
  230. CC1:    JMP    DMP1    ;If we get here, we don't
  231.             ; want to send it to the screen
  232. CC2:    JMP    DMP2    ;send it to screen, and keep going
  233.  
  234. NOZ:    LHLD    TXTPTR    ;get the pointer. It already points past the ^Z,
  235.     DCX    H    ;so decrement it by one
  236.     MVI    M,0    ;NULL the byte in memory
  237.     JMP    DMP1    ;DMP1 reloads the the pointer from earlier save,
  238.             ;and we did not distrub that value
  239.  
  240.  ;routine to back up 'n' lines
  241.  ;use all registers
  242. BACKUP:
  243.     CALL    ILPRT
  244.     DB    LF,LF,CR,0
  245. BAK0:    CALL    ILPRT
  246.     DB    CR,'Enter # of lines to back up '
  247.     DB    '(255 Max) or ''M'' for menu: ',7,0
  248.     CALL    GETNUM    ;routine to get number of lines to back up,
  249.             ; convert to binary, returns with value in [B] 
  250.             ; as well as in BIN$BUF
  251.     LHLD    TXTPTR
  252. BAK1:
  253.     DCX    H
  254.     MOV    A,M    ;get byte into [A]
  255.     CPI    CR    ;is it a carriage return?
  256.     JNZ    BAK1    ;loop if not CR
  257.     SHLD    TXTPTR
  258.     XCHG        ;get TXTPTR into [DE]
  259.     LHLD    ED$SP$STRT ; and start of edit space into [HL]
  260.     CALL    CMP16    ;If TXTPTR is equal to or less than ED$SP$STRT,
  261.             ; we return from CALL with s=1 and c=1.
  262.             ; So long as TXTPTR is greater than ED$SP$STRT,
  263.             ; the return is with C=0 and S=0. (Z=1 if equal.)
  264.     JC    BAK1A    ;TXTPTR is above start of Edit Space, so keep going.
  265.     LHLD    ED$SP$STRT    ;point to start of edit space
  266.     SHLD    TXTPTR        ;
  267.     JMP    DUMP    
  268. BAK1A:    LHLD    TXTPTR
  269.     LDA    BIN$BUF    ;number of lines to back up
  270.     DCR    A    ;take one away
  271.     STA    BIN$BUF    ;save it
  272.     JNZ    BAK1    ;and loop unless the line counter is zero
  273.     CALL    ILPRT
  274.     DB    7,0    ;ring bell when ready to go again
  275.     JMP    DUMP    ;When BIN$BUF=0, return to DUMP
  276.     ;end BACKUP routine
  277.  
  278.  
  279. LINES:        ;comes here from MENU (sets to Paging as default mode)
  280.     XRA    A    ;clear [A]
  281.     STA    SNGL$LN$FLG    ;clear the flags
  282.     STA    SCROLFLG
  283.     CALL    ILPRT
  284.     DB    CR,LF,9,'Type ''1'' for Single-Line Advance, '
  285.     DB    '''S'' for Scrolling,',CR,LF
  286.     DB    9,'any other key for Paging :',0
  287.     CALL    INKEY
  288.     PUSH    PSW    ;send a <cr> to the console before proceeding
  289.     MVI    C,CONOUT ;\ 
  290.     MVI    E,0DH    ;  \
  291.     CALL    BDOS    ;   \
  292.     POP    PSW    ;get it back
  293.     CPI    '1'    ;do we want single lines?
  294.     JNZ    LIN1A    ;no, so try scrolling
  295.     STA    SNGL$LN$FLG    ;else make the flag non-zero
  296.     JMP    DUMP    ;and continue dumping in that mode
  297. LIN1A:    CPI    'S'    ;Scrolling wanted?
  298.     JNZ    DUMP    ;if not scrolling, paging is the default mode
  299.     STA    SCROLFLG ;else make the flag non-zero
  300.     JMP    DUMP    ;and scroll 
  301.  
  302.         ;Routine to move TXTPTR to start of edit space
  303. TOP:
  304.     LHLD    ED$SP$STRT    ;point to start of edit space
  305.     SHLD    TXTPTR        ;
  306.     JMP    DUMP
  307.  
  308.  
  309.  
  310. ; reset disks system to assure disk can be written to
  311. RESET:    LDA    4    ;get current default disk into [A]
  312.     PUSH    PSW    ;save it on the stack
  313.     MVI    C,13    ;reset disk system, in case user forgot to do ^C
  314.     CALL    BDOS
  315.     POP    PSW    ;get default disk back into [A]
  316.     MOV    E,A    ;move it to [E]
  317.     MVI    C,SELDSK    
  318.     CALL    BDOS    ;Reselect former default disk
  319.     RET
  320.     ;end RESET routine
  321.  
  322.  
  323.         ;FILE SAVE ROUTINE
  324. SAVE:    
  325.     CALL    ILPRT
  326.     DB    CR,LF,LF,7
  327.     DB    9,'Are you SURE you want to SAVE now?',CR,LF,LF
  328.     DB    9,'You will save ONLY to the last line on '
  329.     DB    'the screen.',CR,LF,LF
  330.     DB    9,'Type ''Y'' if you want to proceed,',CR,LF
  331.     DB    9,'Any other key to return to MENU :',0
  332.     CALL    INKEY
  333.     CPI    'Y'
  334.     JNZ    MENU
  335.  
  336.     ;First insert EOFs and end of memory wanted
  337.     LHLD    TXTPTR    ;first point to next byte in memory
  338.     INX    H    ;bump it
  339.     MVI    M,CR     ;put in CR
  340.     INX    H    
  341.     MVI    M,EOF
  342.     INX    H    
  343. IF TSC    ;for EOS' editor
  344.     MVI    M,EOF    ;need a bunch because of SKIP$LINO routine
  345.     INX    H    
  346.     MVI    M,EOF
  347.     INX    H    
  348.     MVI    M,EOF
  349.     INX    H    
  350.     MVI    M,EOF
  351.     INX    H    
  352.     MVI    M,EOF
  353. ENDIF    ;TSC
  354.     SHLD    TXTPTR    ;store it away
  355.  
  356.     ;Now set up file into which to save
  357. SAV3:    CALL    ILPRT
  358.     DB    CR,LF,LF,9,'Enter Filename (not FTP) to save into :',0
  359.     LXI    D,F$NAM$BUF
  360.     MVI    C,RDCONBF    ;BDOS function 10
  361.     CALL    BDOS
  362.     LDA    F$NAM$BUF+1    ;see if anything put in buffer
  363.     ORA    A        ;if just <cr>, it's empty
  364.     JNZ    SAV3A        ;if not zero we don't need default filename
  365.     LXI    B,0        ;clear [BC]
  366.     MVI    B,8
  367.     LXI    H,DFLTNAM    ;point [HL] to default file name
  368.     LXI    D,EFCB+1    ; and [DE] to EFCB space
  369.     CALL    MOVER
  370.     JMP    SAV5        ;no need to capitalize default file name
  371. DFLTNAM: DB    'DEFAULT '    ;need total of 8 characters & spaces here    
  372.     ;capitalize filename, in case entered as lower case
  373. SAV3A    LXI    B,0        ;zero [BC]
  374.     MVI    B,8        ;set up [B] as counter
  375.     LXI    H,EFCB+1    ;make filename upper case
  376. UC1:    MOV    A,M        ;get the byte
  377.     CALL    UCASE
  378.     MOV    M,A
  379.     INX    H        ;bump the pointer
  380.     DCR    B
  381.     JNZ    UC1        ;loop until done
  382.     LXI    H,EFCB        ;point to first byte (used by F$NAM$BUF)
  383.     MVI    M,0        ;make it default disk
  384.  
  385.  
  386.     ;now define disk drive to save (CR for default)
  387. SAV5:    CALL    ILPRT
  388.     DB    CR,LF,LF
  389.     DB    9,'Save to which Disk (e.g., ''A'', or ''B'')',CR,LF
  390.     DB    9,'Type <cr> for Default Disk',CR,LF
  391.     DB    9,'Be SURE desired drive has disk inserted',CR,LF
  392.     DB    9,'Your choice?: ',0
  393.     CALL    INKEY
  394.     CPI    CR
  395.     JZ    SAV5A    ;leave it default
  396.     CPI    'A'
  397.     JC    NOGOOD
  398.     CPI    'P'+1
  399.     JNC    NOGOOD
  400.     SUI    40H    ;make binary
  401.     STA    EFCB    ;and store it away
  402.     JMP    SAV6
  403. NOGOOD: CALL ILPRT
  404.     DB    CR,LF,9,'Only ''A'' through ''P'' are valid entries '
  405.     DB    '- hit <cr> to try again',CR,LF
  406.     CALL    INKEY
  407.     JMP    SAV5
  408. SAV5A:    LDA    4    ;get default byte
  409.     ANI    0FH    ;0000 1111 - gets low nibble
  410.     INR    A    ;bump it one, because 0=A,1=B, etc
  411.     STA    EFCB    ;and put it into first byte of EFCB
  412.  
  413. SAV6:    LXI    D,EFCB    ;point to first char in EFCB
  414.     MVI    C,SRCHF    ;search for first occurrence
  415.     CALL    BDOS    ;search on CURLOG disk
  416.     CPI    0FFH    ;if file is not on disk, returns FFH
  417.     JZ    SAVE1    ;if no such file, go make it
  418.  
  419.     LDA    EFCB    ;get the disk byte
  420.     ADI    40H    ;make it ascii
  421.     STA    SAV6A    ;
  422.     CALL    ILPRT    ;print first part of message to console
  423.     DB    CR,LF,LF,LF,LF,LF,LF,'*** Output File '    
  424.     DB    'exists on disk '
  425. SAV6a:    DB    ' :'    ;space for disk identifier
  426.     DB    ' ***',CR,LF,LF
  427.     DB    9,9,'Type ''E'' to erase and proceed,',CR,LF
  428.     DB    9,9,9,' any other key to define another filename:  ',7,0
  429.         ;get decision on what to do
  430.     CALL    INKEY    ;char returned in [A]
  431.     CPI    'E'    
  432.     JNZ    SAV3    ;try again if 'E' was not typed
  433.     LXI    D,EFCB    ;point to outfile FCB
  434.     MVI    C,ERASE    ; to erase the existing file
  435.     CALL    BDOS    ;  that was identified above.
  436. SAVE1:    LXI    D,EFCB    ;point to the EFCB
  437.     MVI    C,MAKE    ;create file call
  438.     CALL    BDOS
  439.     CPI    0FFh    ;bad make?
  440.     JZ    WRT$ERR    
  441.             ;else fall through
  442.  
  443.  
  444.  ;this is where we start the real saving. The first 3 lines do set-up
  445.     LXI    B,0        ;set [BC] to zero, to indicate real data
  446.     LHLD    ED$SP$STRT    ;go to starting point
  447.     SHLD    TXTPTR        ;store it
  448.  
  449. SAV11:    LXI    D,EFCB        ;point [DE] to EFCB
  450.     LHLD    TXTPTR        ;get the pointer
  451.     MOV    A,M        ;get the character
  452.     INX    H        ;bump the pointer
  453.     SHLD    TXTPTR        ;store after bumping
  454. IF    TSC    ;for EOS' editor
  455.     CPI    CR        ;is it a CR?
  456.     CZ    SKIP$LINO    ;if so, bump pointer past LINO bytes
  457. ENDIF    ;TSC
  458.     CPI    EOF
  459.     JNZ    SAV12        ;not EOF
  460.     MVI    B,1        ;on EOF, set [B] to 1
  461. SAV12:    PUSH    B        ;[BC] is 0 unless EOF
  462.     CALL    PUTC        ;put the character
  463.     POP    B        ;was it EOF last time?
  464.     MOV    A,B        ;must be in [A] to test
  465.     ORA    A        ;if it was, we're non-zero
  466.     JNZ    FINISH        ;so go finish up
  467.     JMP    SAV11        ;else loop for more.
  468.  
  469. ;    PUTC  (Adapted from A.Johnson-Laird's Book, page 113)
  470. ;    This subroutine either puts the next chararacter out
  471. ;    to a sequential file, writing out completed 'records'
  472. ;    (128-byte sectors) or, if requested to, will fill the
  473. ;    remainder of the current 'record' with 1AH's to indicate
  474. ;    End of File to CP/M.
  475. ;
  476. ;    Entry Parameters
  477. ;
  478. ;        DE -> File Control Block
  479. ;        B = 0, A = next data character to be output
  480. ;        If B not 0, fill the current 'record' with 1AH's
  481. ;
  482. ;
  483. BUFSIZ    EQU    128        ;Buffer Size
  484. PUTBUF:    DS    BUFSIZ        ;Declare buffer
  485. CHAR$CNT: DB    0        ;Char. count (initially 'empty')
  486.  
  487. ;
  488. PUTC:
  489.     PUSH    D        ;Save EFCB Address
  490.     PUSH    PSW        ;Save data character
  491.     MOV    A,B        ;Check if end of file requested
  492.     ORA    A
  493.     JNZ    PUTCEF        ;Yes
  494.     CALL    PUTCGA        ;No, get address of next free byte
  495.                 ;HL -> next free byte
  496.                 ;E = Current Char. count (as well as A)
  497.     POP    PSW        ;Recover data character
  498.     MOV    M,A        ;Save in buffer
  499.     MOV    A,E        ;Get current character count
  500.     INR    A        ;Update character count
  501.     CPI    BUFSIZ        ;Check if buffer full
  502.     JZ    PUTCWB        ;Yes, write buffer
  503.     STA    CHAR$CNT    ;No, save updated count
  504.     POP    D        ;Dump EFCB Address for return
  505.     RET
  506. ;
  507. PUTCEF:                ;End of file
  508.     POP    PSW        ;Dump data character
  509.     CALL    PUTCGA        ;HL -> next free byte
  510.                 ;A = Current character count
  511. PUTCCE:                ;Copy EOF character
  512.     CPI    BUFSIZ        ;Check for end of buffer
  513.     JZ    PUTCWB        ;Yes, write out the buffer
  514.     MVI    M,EOF        ;No, store EOF in buffer
  515.     INR    A        ;Update count
  516.     INX    H        ;Update buffer pointer
  517.     JMP    PUTCCE        ;Continue until end of buffer
  518. ;
  519. PUTCWB:                ;Write buffer
  520.     XRA    A        ;Reset character count to 0
  521.     STA    CHAR$CNT
  522.     LXI    D,PUTBUF    ;DE -> Buffer
  523.     MVI    C,SETDMA    ;Set DMA Address -> Buffer
  524.     CALL    BDOS
  525.     POP    D        ;Recover EFCB Address
  526.     MVI    C,WRITE        ;Write Sequential Record
  527.     CALL    BDOS
  528.     ORA    A        ;Check if error
  529.     JNZ    WRT$ERR        ;Yes if A = NZ
  530.     RET            ;No, return to caller
  531. ;
  532. PUTCGA:                ;Return with HL -> next free char.
  533.                 ;and A = current char. count
  534.     LDA    CHAR$CNT        ;Get current character count
  535.     MOV    E,A        ;Make word value in DE
  536.     MVI    D,0
  537.     LXI    H,PUTBUF    ;HL -> Base of buffer
  538.     DAD    D        ;HL -> next free character
  539.     RET
  540.  
  541.  
  542. ;CMP16  Routine to compare two 16-bit values, from L.Leventhal's
  543. ;    8080/8085 Ass'y Language Routines, page 210.
  544. ;    Results expressed in PSW flags:
  545. ;    If minuend=subtrahend, z=1,s=0,c=0
  546. ;    If minuend>subtrahend, z=0,s=0,c=0
  547. ;    If minuend<subtrahend, z=0,s=1,c=1
  548. ;    Uses AF,DE,HL, so save and restore if they contain needed data.
  549. CMP16:    MOV    A,D
  550.     XRA    H
  551.     JM    DIFF
  552.  
  553.     MOV    A,L
  554.     SUB    E
  555.     JZ    EQUAL
  556.  
  557.     MOV    A,H
  558.     SBB    D
  559.     JC    CYSET    ;exit
  560.     JNC    CYCLR    ;exit
  561.  
  562. EQUAL:    MOV    A,H
  563.     SBB    D
  564.     RET
  565.  
  566. DIFF:    MOV    A,L
  567.     SUB    E
  568.     MOV    A,H
  569.     SBB    D
  570.     MOV    A,H
  571.     JNC    CYCLR
  572.  
  573. CYSET:    ORI    1
  574.     STC    
  575.     RET
  576.  
  577. CYCLR:    ORI    1
  578.     RET
  579. ;        end CPM16 - see reference for notation & explanation
  580.  
  581.  
  582. FINISH:    ;comes here after padding outfile with EOFs
  583.     LXI    D,EFCB    ;point to the EFCB
  584.     MVI    C,CLOSE
  585.     CALL     BDOS
  586.     CPI    0FFH    ;error?
  587.     JZ    WRT$ERR
  588.  
  589.  ;now send message to console
  590.     LDA    EFCB    ;get the disk designator byte
  591. FIN2:    ADI    40H    ;and make it into a letter
  592.     STA    FIN5    ;store it for display
  593.  
  594.     LXI    H,EFCB+1
  595.     LXI    D,FIN9
  596.     LXI    B,0
  597.     MVI    B,8
  598.     CALL    MOVER
  599.     CALL    ILPRT
  600.     DB    CR,LF,LF,9,7
  601.     DB    'Memory has been saved into '
  602. FIN5:    DB    ' :'
  603. FIN9:    DB    '        .SYA'    ;eight spaces to receive filename
  604. IF    TVI950
  605.     DB    ESC,'g',ESC,'f',ESC,'G0',CR    ;kill status line display, if on
  606. ENDIF    ;tvi950
  607.     DB    CR,LF,LF,0
  608.     JMP    WRMBOOT
  609.     ;end FINISH routine
  610.  
  611.  
  612.  
  613. GETNUM:        ;this routine accepts entry of a number    up to 255,
  614.         ;converts the number to binary,
  615.         ;stores it in BIN$BUF and RETurns with number in [B]
  616.     LXI    H,TMP$BUF+1    ;TMP$BUF is the console buffer
  617.     MVI    M,0        ;Zero it out, (exc. max length byte)
  618.     INX    H        ; to clear any data
  619.     MVI    M,0        ; from previous tries
  620.     INX    H               ;         /
  621.     MVI    M,0        ;        /
  622.     INX    H        ;       /
  623.     MVI    M,0        ;      /
  624.     LXI    D,TMP$BUF    ;now fill the buffer from console input
  625.     MVI    C,10
  626.     CALL    BDOS
  627.     LDA    TMP$BUF+2    ;test first character of buffer
  628.     CPI    03H        ;if ^C, quit
  629.     JZ    WRMBOOT
  630.     CALL    UCASE        ;capitalize
  631.     CPI    'M'        ;MENU wanted?
  632.     JZ    MENU        ;if yes, go there, else
  633.     ORA    A        ;is it zero, from a <cr> typed?
  634.     JNZ    CONVERT        ;fall through to CONVERT if not
  635.     POP    H        ;else balance the stack
  636.     JMP    BAK0        ; and try again - <cr> means the user got
  637.                 ; overshot, not knowing he hit end of file
  638.  
  639. CONVERT:    ;this routine converts the ASCII numerical value
  640.         ; in BUFF$TMP to its binary equivalent
  641.         ; (e.g., 65 is converted to 41H) and stores that
  642.         ; binary value in BIN$BUF
  643.  
  644.     LDA    TMP$BUF+1    ;get actual lenght of TMP$BUF into (A)
  645.     MOV    B,A        ;else store [A] in [B]
  646.     PUSH    B        ;and save it away
  647.     LXI    D,TMP$BUF+2    ;point (DE) to data in ASCII line-length buffer
  648.     LXI    H,0        ;and zero out HL
  649. ASC$BIN:
  650.     LDAX    D        ;get the character
  651.     INX    D        ;point (DE) to next char
  652.     CPI    '0'        ;is character <'0' (30h)?
  653.     JC    GET$NUM$ERR    ;non-numeric is error
  654.     CPI     '9'+1        ;is it more than 9 (39h)?
  655.     JNC    GET$NUM$ERR
  656.     SUI    '0'        ;make ASCII binary (-30h)
  657.     MOV    B,H        ;copy partial answer to (BC)
  658.     MOV    C,L        ; for later user in multiplying
  659.     DAD    H        ;HL = 2xHL now
  660.     DAD    H        ;HL = 4xHL now
  661.     DAD    B        ;HL = 5x HL now
  662.     DAD    H        ;HL = 10x orig HL now
  663.     ADD    L        ;adds L to accumulator
  664.     MOV    L,A        ;put answer back into (L)
  665.     STA    BIN$BUF        ;store in binary buffer &
  666.                 ; up-date on every loop till jumpout
  667.     POP    B        ;get the buffer length counter
  668.     DCR    B        ;reduce by 1
  669.     JZ    DONE        ;if 0, we're done converting
  670.     PUSH    B        ;if not 0, save for next loop
  671.     JMP    ASC$BIN     ;loop until done
  672.  
  673.  
  674. DONE:    LDA    BIN$BUF    ;we need to add 1 to make it look right
  675.     INR    A    ; on screen
  676.     STA    BIN$BUF    
  677.     RET
  678.  
  679. TMP$BUF:    DB    3    ;maximum number of bytes to be accepted
  680.         DB    0,0,0,0    ;this allows for max of 3 bytes
  681.                 ;first of above 4 is for actual length
  682.  
  683. BIN$BUF:    DB    0,0    ;storage space
  684.  
  685.  
  686. GET$NUM$ERR:
  687.     CALL    ILPRT
  688.     DB    CR,LF,LF
  689.     DB    9,'Only digits (0-9) are allowed-hit any key to try again'
  690.     DB    CR,LF,0
  691.     CALL    INKEY
  692.     POP    PSW    ;balance the stack from the CALL
  693.     JMP    BACKUP    ; and try again
  694. ;  end of GETNUM routine
  695.  
  696.  
  697.  
  698.  
  699. MOVER:        ;called with [HL] pointing to string to be moved to
  700.         ; area of memory pointed to by [DE]
  701.         ;Number of bytes to be moved in [BC]
  702.         ;Returns when [BC] is 0
  703.     MOV    A,M    ;get byte from input filename into [A]
  704.     STAX    D    ;and store it in output filename block
  705.     INX    H    ;else bump pointers
  706.     INX    D    ;
  707.     DCR    B    ;more to go?
  708.     MOV    A,B    
  709.     ORA    C
  710.     RZ        ;when [BC] = 0, return to  calling routine
  711.     JMP    MOVER    ;LOOP for more  characters
  712.  
  713.  
  714.  
  715. ;
  716. ;This routine sends the string that follows the command
  717. ;                       CALL ILPRT
  718. ;to the console until a binary 0 is encountered, then
  719. ;returns to the point in the program that FOLLOWS the string
  720. ;that was sent to the console.
  721. ;
  722. ;
  723. ILPRT:
  724.     XTHL        ;Swap top of stack with (HL)
  725.             ; {PC location following CALL ILPRT
  726.             ;  is now in (HL), stack top is trash}
  727. ILP1:    MOV    A,M    ;get character pointed to by (HL)
  728.     INX    H    ;increment our string pointer
  729.     CPI    0    ;was it the last one?
  730.     JZ    ILP2    ;if yes, quit
  731.     MOV    E,A    ;get ready to send char.to console
  732.     MVI    C,2    ;CP/M's output char. to console routine
  733.     PUSH    H    ;save pointer
  734.     CALL    BDOS    ;send character to console
  735.     POP    H    ;restore pointer
  736.     JMP    ILP1    ;Loop for more characters
  737. ILP2:    XTHL        ;(HL) points to PC after the '$' -- XTHL
  738.             ; switches to top of stack for return, but
  739.             ; trashes (HL)
  740.     RET        ;To location folowing string sent to console
  741.  
  742.  
  743.             ;routine to get character from keyboard
  744. INKEY:    MVI    C,DIRCONIO ;use non-echo conin function #6
  745.     MVI    E,0FFH    ;we want to get a character
  746.     CALL    BDOS
  747.     ORA    A    ;it's zero until character is typed
  748.     JZ    INKEY    ;so loop until we have a response.
  749. UCASE:    CPI    'a'    ;now make upper case
  750.     RC
  751.     CPI    'z'+1
  752.     RNC
  753.     SUI    'a'-'A'    ;subtract 20h
  754.     RET
  755.  
  756.  
  757.  
  758. IF    TVI950    ;assemble only for TVI950 TXTPTR display
  759.  
  760.  ;Binary to Hexadecimal Ascii Conversion
  761.  ;Converts one byte of binary data to two Ascii
  762.  ;characters that correspond to the 2 Hexadecimal
  763.  ;digits representing the value of the byte.
  764.  ;
  765.  ;Enter with binary byte to convert in [A]
  766.  ;Exit with most significant digit in [H], least in [L]
  767.  
  768.  ;Source: page 153, Leventhal's 8080 Subroutines book.
  769.  
  770. BN2HEX:
  771.     MOV    B,A    ;save incoming value for later use
  772.     ANI    0F0H    ;get the high nibble
  773.     RRC ! RRC ! RRC ! RRC ;move high nibble to low nibble
  774.     CALL    NASCII    ;convert high nibble to ASCII
  775.     MOV    H,A    ;put converted high nibble into [H]
  776.  
  777.     MOV    A,B    ;get incoming value back into [A]
  778.     ANI    0FH    ;get low nibble
  779.     CALL    NASCII    ;
  780.     MOV    L,A    ;put converted low niblle into [L]
  781.     RET        ;RETurn to caller
  782.  
  783. NASCII:
  784.     CPI    10    
  785.     JC    NAS1    ;jump if <10
  786.     ADI    7    ;else add 7 to skip 3Ah to 40h
  787. NAS1:    ADI    '0'    ;add 30h
  788.     RET
  789.     ;end BN2HEX routine
  790.  
  791. DISP$STAT:
  792.     LDA    STATLINFLG    ;get the flag
  793.     ORA    A        ;non-zero if status line is desired
  794.     RZ            ;so if zero, return now, else fall thru
  795.  ;put TXTPTR and ED$SP$STRT values into ASCII format
  796.     LHLD    ED$SP$STRT
  797.     XCHG        ;put TXTPTR value into [DE]
  798.     MOV    A,E    ;get the lowest significance byte
  799.     CALL    BN2HEX    ;return with ASCII equivalent in [HL]
  800.     MOV    A,L    ;and store for display
  801.     STA    DSPL+3    ;as the last byte
  802.     MOV    A,H    ;
  803.     STA    DSPL+2    ;and so on
  804.     MOV    A,D    ;now get most significant byte
  805.     CALL    BN2HEX    ;and do it all again
  806.     MOV    A,L
  807.     STA    DSPL+1
  808.     MOV    A,H
  809.     STA    DSPL
  810.  
  811.     LHLD    TXTPTR
  812.     XCHG        ;put start of edit space value into [DE]
  813.     MOV    A,E    ;get the lowest significance byte
  814.     CALL    BN2HEX    ;return with ASCII equivalent in [HL]
  815.     MOV    A,L    ;and store for display
  816.     STA    DSPL2+3    ;as the last byte
  817.     MOV    A,H    ;
  818.     STA    DSPL2+2    ;and so on
  819.     MOV    A,D    ;now get most significant byte
  820.     CALL    BN2HEX    ;and do it all again
  821.     MOV    A,L
  822.     STA    DSPL2+1
  823.     MOV    A,H
  824.     STA    DSPL2
  825.  
  826. ;now display status line
  827. DSX:    CALL    ILPRT    ;now send string to status line
  828.     DB    ESC,67H,ESC,66H,ESC,'G4'    ;status line reverse-video
  829.     DB    'Edit Space starts at at '
  830. DSPL:    DB    '    h            '
  831.     DB    'TXTPTR now at '
  832. DSPL2:    DB    '    h'
  833.     DB    CR,0        ;and send it to the console
  834.     RET
  835. STATLINFLG:    DB    0    ;default value is zero
  836.     ;end DISP$STAT routine
  837. ENDIF    ;TVI950 txtptrs display
  838.  
  839. ABRT$EX:
  840. CALL    ilprt
  841. DB    1BH,2AH,LF,LF,LF,9,9,'Good bye ....',7,0
  842. JMP WRMBOOT
  843.  
  844. MKE$ERR:
  845. CALL ILPRT
  846. DB    CR,LF,LF,LF,LF,9,9,'Cannot make  ',0
  847.     LXI    H,EFCB+1 ;OUTPUT FILENAME
  848.     LXI    D,MKE1
  849.     LXI    B,8
  850.     CALL    MOVER
  851.     CALL    ILPRT
  852. MKE1:    DB    '        .SYA'    ;eight spaces for filename
  853. DB    CR,LF,LF,LF,9,9,9,' - disk is probably full.',CR,LF,7,0
  854. JMP WRMBOOT
  855.  
  856. WRT$ERR:
  857. CALL    ILPRT
  858. DB    CR,LF,LF,LF,LF,9,9,'Ooops ...   File Write Error',LF,CR
  859. DB    LF,9,9,9,'Disk may be full.',CR,LF,7,0
  860. JMP WRMBOOT
  861.  
  862.  
  863.     ;DATA AND BUFFERS
  864. BAKCNTBUF: DB 3,0,0,0,0,0    ;buffer
  865. TXTPTR:    DW    ED$SP$STRT ;initialize to start of edit space
  866. SNGL$LN$FLG:    DB    0    ;non-zero means advance line by line
  867. SCROLFLG:    DB    0    ;non-zero means    scrolling
  868.  
  869. F$NAM$BUF:    DB    8    ;in effect, F$NAM$BUF & EFCB are the same
  870. EFCB:    DB    0,'        ','SYA',0,0,0,0 ;8 spaces for filename in EFCB
  871.  
  872.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    ;for blocks
  873.     DB    0    ;33 bytes total, last one is current record
  874.  
  875.     DS    100    ;SAVE SPACE FOR STACK
  876. STAK:    EQU    $    ;STACKTOP
  877.  
  878.  
  879.  ;standard equates
  880. WRMBOOT        EQU    0    ;location for warmboot
  881. EOF        EQU    1AH    ;END OF FILE SYMBOL
  882. FCB        EQU    5CH    ;default FCB
  883. BDOS        EQU    5    ;location for BDOS calls or jumps
  884. ESC        EQU    1BH    ;escape character
  885. ;
  886. CONIN        EQU    1    ;Console input to (A)
  887. CONOUT        EQU    2    ;Send char in (E) to console
  888. LSTOUT        EQU    5    ;send char out list device
  889. DIRCONIO    EQU    6    ;direct console i/o
  890.  ;
  891. PRNTSTR        EQU    9    ;print to CONSOLE string pointed to
  892.                 ; by (DE), end string w/ '$'
  893.  ;
  894. RDCONBF        EQU    10    ;read console line into buffer
  895.                 ; pointed to by (DE)
  896.  ;
  897. CONST        EQU    11    ;get console status in (A)
  898.                 ; FFh if char is ready, 00h if not
  899. SELDSK        EQU    14    ;select disk defined in [E] (A=0,B=1,etc.)
  900. OPEN        EQU    15    ;Open a file, FCB in (DE)
  901. CLOSE        EQU    16    ;Close a file, FCB in (DE)
  902. SRCHF        EQU    17    ;search for first file, FCB in (DE)
  903. SRCHN        EQU    18    ;search for next file, FCB in (DE)
  904. ERASE        EQU    19    ;erase file, FCB in (DE)
  905. READ        EQU    20    ;read file sector, FCB in (DE)
  906. WRITE        EQU    21    ;write file sector, FCB in (DE)
  907. MAKE        EQU    22    ;make new file, FCB in (DE)
  908. REN        EQU    23    ;rename file, FCB in (DE)
  909. SETDMA        EQU    26    ;set DMA address as define in (DE)
  910. CR        EQU    0DH    ;CARRIAGE RETURN
  911. LF        EQU    0AH    ;LINE FEED
  912. TAB        EQU    09    ;Tab character
  913.  
  914.  
  915.  
  916.     END
  917.