home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol026 / sysmon.asm < prev    next >
Assembly Source File  |  1985-02-09  |  36KB  |  1,477 lines

  1. ;
  2. ; sysmon.asm - system monitor
  3. ;
  4. ; revision 02.00 - 05/12/81
  5. ;
  6. ; Copyright (C) 1978, 1979, 1980, 1981 by Terence M. Kennedy
  7. ; All Rights Reserved Worldwide
  8. ;
  9. ; Permission is hereby granted to the SIG/M library to distribute
  10. ; this work in whatever form and manner it pleases. This permission
  11. ; is non-transferable.
  12. ;
  13. ; Computer hobbyists may use this code, in any form, modified or
  14. ; unmodified, for non-commercial purposes.
  15. ;
  16. ; Refer all requests for commercial distribution to the SIG/M Library.
  17. ;
  18. ; I define 'Commercial distribution' to include distribution by
  19. ; the 'CP/M User's Group' run by Intersoft Corp. (Lifeboat Associates)
  20. ;
  21. ; NOTE: CP/M is a (registered) trademark of Digital Research, Inc.,
  22. ;    Pacific Grove, California. Reference to this trademark within
  23. ;    the body of this text is only to indicate that this code will
  24. ;    interface with said trademarked product, and does not imply
  25. ;    that the owner of the trademark owns, approves, or uses this
  26. ;    code.
  27. ;
  28. false    equ    0        ;logical false value
  29. true    equ    not false    ;logical true value
  30. ;
  31. testing    equ    true        ;if testing
  32. help    equ    true        ;if '?' command to display commands desired
  33. cpmio    equ    true        ;if using CP/M console I/O instead of hardware
  34. ;
  35.     if    (not testing) and cpmio
  36. --> cannot have cpmio true and testing false <--
  37.     endif
  38. ;
  39.     if    testing
  40. pbase    equ    00100h        ;program base
  41. dbase    equ    02000h        ;data area base
  42.     endif
  43. ;
  44.     if    not testing
  45. pbase    equ    0e000h        ;program base in bytesaver
  46. dbase    equ    0bf00h        ;data area base (below bytesaver)
  47.     endif
  48. ;
  49.     if    cpmio        ;if using CP/M I/O calls
  50. conrdy    equ    006h        ;console status
  51. conin    equ    009h        ;console input
  52. conout    equ    00ch        ;console output
  53.     endif
  54. ;
  55. wboot    equ    0000h        ;CP/M warm boot entry point
  56. ;
  57. ; misc. equates
  58. ;
  59. cr    equ    0dh        ;carriage return
  60. lf    equ    0ah        ;line feed
  61. bs    equ    08h        ;back space
  62. sl    equ    '/'        ;slash
  63. cntrlc    equ    'C'-40h        ;control-C
  64. cntrlq    equ    'Q'-40h        ;control-Q
  65. cntrls    equ    'S'-40h        ;control-S
  66. cntrlx    equ    'X'-40h        ;control-X
  67. cntrlz    equ    'Z'-40h        ;control-Z
  68. bell    equ    07h        ;ring console bell
  69. ;
  70. ; device equates
  71. ;
  72. fpanel    equ    0ffh        ;front panel device address
  73. consta    equ    000h        ;console status port
  74. condat    equ    001h        ;console data port
  75. rdrsta    equ    002h        ;reader status port
  76. rdrdat    equ    003h        ;reader data port
  77. dsksta    equ    07fh        ;disk drive status
  78. dskcmd    equ    07fh        ;disk drive command port
  79. dskc2    equ    07ch        ;disk drive 2nd command port
  80. dmah    equ    07eh        ;high order byte of dma address
  81. dmal    equ    07dh        ;low order byte of dma address
  82. ;
  83. ; device control bits
  84. ;
  85. trk0    equ    004h        ;if at track 0
  86. iof    equ    008h        ;if I/O is complete
  87. notrdy    equ    080h        ;if drive is not ready
  88. done    equ    notrdy or iof    ;done w/ command (one way or another)
  89. errors    equ    0f0h        ;error bits
  90. tbe    equ    080h        ;transmit buffer empty (all serial ports)
  91. rda    equ    040h        ;data available (all serial ports)
  92. readf    equ    0bfh        ;read disk function
  93. ;
  94. ; data areas (uninitialized)
  95. ;
  96.     org    dbase
  97. ;
  98. userpc:    ds    2        ;user's PC for R command
  99. svc:    ds    1        ;supervisor call no.
  100. ibuf:    ds    128        ;input buffer
  101. stack:    ds    64        ;program stack
  102. pflag1:    ds    1        ;parameter flags
  103. pflag2:    ds    1
  104. param1:    ds    2        ;parameters
  105. param2:    ds    2
  106. cbuf:    ds    1        ;command buffer
  107. dmpad:    ds    2        ;dump address
  108. temp:    ds    10h        ;temp. workspace for B, I & O commands
  109. oflst    equ    temp        ;object file loader state
  110. oflce    equ    temp+1        ;object file loader checksum error flag
  111. oflcs    equ    temp+2        ;object file loader checksum
  112. oflbc    equ    temp+3        ;object file loader byte count
  113. oflbb    equ    temp+4        ;object file loader byte buffer
  114. oflla    equ    temp+5        ;object file loader load address (word value)
  115. oflfrr    equ    temp+7        ;object file loader first record read flag
  116. addr:    ds    2        ;hexmon current address
  117. data:    ds    1        ;hexmon working data
  118. diagfg:    ds    1        ;diagnostic load flag
  119. srcnam:    ds    10h        ;name of tape file searching for
  120. fndnam:    ds    10h        ;name of tape file found
  121. ;
  122. ; code area
  123. ;
  124.     org    pbase
  125. ;
  126. monitr:    jmp    main        ;jump to main code
  127. super:    jmp    supvsr        ;jump to supervisor
  128. main:    lxi    sp,stack+64    ;set up sp
  129.     lxi    h,0        ;clear user PC to 0
  130.     shld    userpc
  131.     lxi    h,cs        ;clear screen code
  132.     call    wasc        ;send it
  133.     in    fpanel        ;read sense switches
  134.     cpi    0ffh        ;test for no front panel
  135.     jz    main1        ;if no panel
  136.     cpi    80h        ;test if entering sysmon
  137.     jnz    boot        ;no, boot disk right away
  138. main1:    lxi    h,signon    ;get signon message
  139.     call    wasc        ;send to con:
  140.     call    weolc        ;do cr/lf
  141. prompt:    mvi    a,'@'        ;our prompt
  142.     call    wacc        ;to console
  143.     lxi    h,ibuf        ;input buffer pointer
  144.     call    rasc        ;get command line
  145.     mov    a,m        ;test if terminated with '/'
  146.     cpi    sl
  147.     jz    hexmon        ;if so, use hex monitor
  148.     mvi    m,' '        ;insure at least one blank at end
  149.     inx    h        ;followed by cr
  150.     mvi    m,cr
  151.     lxi    d,ibuf        ;points to 1st character of input line
  152. parse:    ldax    d        ;get command
  153.     cpi    ' '        ;test for null command
  154.     jz    prompt        ;if so, re-issue prompt
  155.     sta    cbuf        ;if not, put command keyword in cbuf
  156.     inx    d        ;points to param1 now
  157. parse1:    xra    a        ;clear parameter flags
  158.     sta    pflag1
  159.     sta    pflag2
  160.     call    dhs        ;decode first parameter
  161.     jc    comerr        ;if command error in param.
  162.     sta    pflag1        ;save parameter flag
  163.     shld    param1        ;and parameter
  164.     call    dhs        ;decode second parameter (same as first)
  165.     jc    comerr
  166.     sta    pflag2
  167.     shld    param2
  168.     lda    pflag1        ;get first parameter flag
  169.     ora    a        ;see if set
  170.     jnz    $+9        ;yes, skip next code
  171.     lxi    h,100h        ;no, default to 100 hex
  172.     shld    param1
  173.     lda    pflag2        ;get second parameter flag
  174.     ora    a        ;test it
  175.     jnz    $+9        ;if already got one
  176.     lhld    param1        ;else default it to same as first one
  177.     shld    param2
  178. decode:    lxi    h,ctable    ;lookup table for keywords
  179. decod1:    lxi    d,cbuf        ;points to command input by user
  180.     mvi    c,1        ;compare only 1 character
  181.     mvi    b,1        ;set match flag
  182. decod2:    ldax    d        ;get command
  183.     cmp    m        ;compare w/ keyword table
  184.     jz    $+5        ;if match
  185.     mvi    b,0        ;else reset match flag
  186.     inx    d
  187.     inx    h
  188.     dcr    c        ;this would flush rest of keyword if >1 char.
  189.     jnz    decod2
  190.     dcr    b        ;test match flag
  191.     jz    match        ;if successful match
  192.     inx    h        ;else skip address field
  193.     inx    h
  194.     mov    a,m        ;test if end of table
  195.     ora    a
  196.     jnz    decod1        ;if not at end
  197.     lxi    h,badcom    ;at end, send 'bad command' message
  198.     call    wasc
  199.     jmp    prompt        ;and go back to main prompt
  200. match:    mov    e,m        ;copy address to DE
  201.     inx    h
  202.     mov    d,m
  203.     lxi    b,prompt    ;create return address
  204.     push    b        ;this puts prompt on stack for second RET
  205.     push    d        ;this puts the routine address on the stack
  206.     lhld    param2        ;put second parameter in DE (see xchg below)
  207.     xchg
  208.     lhld    param1        ;put first parameter in HL
  209.     ret            ;this causes jmp to address in D, pushed above
  210. comerr:    lxi    h,badstx    ;give 'bad syntax' message
  211.     call    wasc
  212.     jmp    prompt
  213. ;
  214. ; command table
  215. ;
  216. ctable:    db    'D'        ;dump command
  217.     dw    dump
  218.     db    'H'        ;halt command
  219.     dw    halt
  220.     db    'B'        ;boot standard system
  221.     dw    boot
  222.     db    'S'        ;boot diagnostic system
  223.     dw    diag
  224.     db    'R'        ;display register set
  225.     dw    regdis
  226.     db    'E'        ;enter command
  227.     dw    enter
  228.     db    'M'        ;move command
  229.     dw    move
  230.     db    'F'        ;fill command
  231.     dw    fill
  232.     db    'G'        ;go command
  233.     dw    go
  234.     db    'I'        ;input command
  235.     dw    rip
  236.     db    'O'        ;output command
  237.     dw    wop
  238.     db    'L'        ;load diagnostic tape
  239.     dw    loader
  240. ;
  241.     if    help
  242.     db    '?'        ;output command summary
  243.     dw    hlpdis
  244.     endif
  245. ;
  246.     if    testing
  247.     db    'Q'        ;quit command
  248.     dw    wboot        ;to CP/M warm boot
  249.     db    'T'        ;supervisor call test
  250.     dw    svctst
  251.     endif
  252. ;
  253.     db    0        ;end of command table
  254. ;
  255. ; supvsr - supervisor call handler
  256. ;
  257. supvsr:    push    h        ;save user parameters
  258.     push    d
  259.     push    b
  260.     push    psw
  261. sup1:    lxi    h,stable    ;supervisor call table pointer
  262. sup2:    lda    svc        ;get supervisor call no.
  263.     cmp    m        ;compare with call no. in table
  264.     inx    h        ;point to address in any case
  265.     jz    sup3        ;if found
  266.     inx    h        ;skip to next svc no.
  267.     inx    h
  268.     mov    a,m
  269.     cpi    0ffh
  270.     jz    sup4        ;if at end of table
  271.     jmp    sup2        ;and retry
  272. sup3:    mvi    a,jmp        ;stuff a jump in temp. area
  273.     sta    temp
  274.     mov    e,m        ;get address from table
  275.     inx    h
  276.     mov    d,m
  277.     xchg            ;put in hl
  278.     shld    temp+1        ;save address in temp+1
  279.     pop    psw        ;restore user's registers
  280.     pop    b
  281.     pop    d
  282.     pop    h
  283.     jmp    temp        ;go to routine
  284. sup4:    mvi    b,8        ;8 bytes to remove
  285. sup5:    inx    sp
  286.     dcr    b
  287.     jnz    sup5        ;if not done
  288.     lxi    h,ilsum1    ;print illegal supervisor call message
  289.     call    wasc
  290.     lda    svc        ;print svc no. causing error
  291.     call    whbc
  292.     lxi    h,ilsum2    ;print rest of message
  293.     call    wasc
  294.     inx    sp        ;get high byte
  295.     lxi    h,0        ;copy sp to hl
  296.     dad    sp
  297.     mov    d,m        ;get byte 1
  298.     dcx    h
  299.     mov    e,m
  300.     xchg
  301.     dcx    h        ;point to call address
  302.     dcx    h
  303.     dcx    h
  304.     mov    a,h        ;output hi byte
  305.     call    whbc
  306.     mov    a,l        ;output low byte
  307.     call    whbc
  308.     call    weolc        ;do 2 cr/lf's
  309. sup6:    call    weolc        ;do cr/lf
  310.     lxi    sp,stack+64    ;reset sp
  311.     jmp    prompt        ;and issue prompt
  312. ;
  313. ; supervisor call table
  314. ;
  315. stable:    db    0        ;return to monitor
  316.     dw    sup6
  317.     db    1        ;return version number
  318.     dw    vers
  319.     db    2        ;console in
  320.     dw    racc
  321.     db    3        ;console out
  322.     dw    wacc
  323.     db    4        ;console status
  324.     dw    const
  325.     db    5        ;console string in
  326.     dw    rasc
  327.     db    6        ;console string out
  328.     dw    wasc
  329.     db    7        ;do cr/lf on console
  330.     dw    weolc
  331.     db    8        ;ring bell on console
  332.     dw    ding
  333.     db    9        ;test for legal digit
  334.     dw    legal
  335.     db    10        ;decode hex string
  336.     dw    dhs
  337.     db    11        ;write hex digit to console
  338.     dw    whdc
  339.     db    12        ;write hex byte to console
  340.     dw    whbc
  341.     db    13        ;dump hex & ascii on console
  342.     dw    dmp
  343.     db    14        ;dump register set
  344.     dw    regdis
  345.     db    15        ;compute difference
  346.     dw    diff
  347.     db    16        ;move up
  348.     dw    moveup
  349.     db    17        ;move down
  350.     dw    movedn
  351.     db    18        ;boot dos
  352.     dw    boot
  353.     db    19        ;boot ddos
  354.     dw    diag
  355.     db    20        ;delay
  356.     dw    delay
  357.     db    21        ;read byte from reader
  358.     dw    reader
  359.     db    22        ;process object byte
  360.     dw    ofl
  361.     db    0ffh        ;end of table
  362. ;
  363. ; loader - load specified diagnostic from tape
  364. ;
  365. loader:    lxi    h,askfil    ;ask for filename
  366.     call    wasc
  367.     lxi    h,srcnam    ;input buffer address
  368.     call    rasc        ;read user's response
  369.     lxi    h,askply    ;tell him to press play
  370.     call    wasc        ;do cr/lf
  371. load1:    call    reader        ;get character
  372.     cpi    ';'        ;test for header
  373.     jnz    load1        ;skip till found
  374.     lxi    h,fndnam    ;pointer to 'found name'
  375. load2:    call    reader        ;get filename
  376.     cpi    cr        ;see if all done
  377.     jz    load3
  378.     mov    m,a        ;store away
  379.     inx    h        ;next free loc.
  380.     jmp    load2        ;do next char
  381. load3:    mvi    m,0        ;force end of string
  382.     lxi    h,found        ;print 'Found '
  383.     call    wasc
  384.     lxi    h,fndnam    ;send name we found on tape
  385.     call    wasc        ;to console
  386.     lxi    d,srcnam    ;pointer to search name
  387.     lxi    h,fndnam    ;pointer to name found on tape
  388.     mvi    b,10h        ;max. no. of bytes to compare
  389. load4:    mov    c,m        ;byte from found name
  390.     ldax    d        ;byte from wanted name
  391.     cpi    cr        ;test if last byte in source
  392.     jz    load5        ;if so...
  393.     cmp    c        ;compare
  394.     jnz    load1        ;if not a match
  395.     inx    h        ;next bytes
  396.     inx    d
  397.     dcr    b        ;see if have done 10h yet...
  398.     jnz    load4        ;if not
  399. load5:    lxi    h,loadng    ;print 'Loading'
  400.     call    wasc
  401.     xra    a        ;initialize loader
  402.     sta    oflst
  403.     sta    oflce
  404.     sta    oflfrr
  405. load6:    call    reader        ;get character
  406.     cpi    cntrlz        ;test if eof
  407.     jz    load7        ;if so...
  408.     call    ofl        ;process byte
  409.     lda    oflce        ;test for checksum error
  410.     ora    a
  411.     jz    load6        ;if ok
  412.     jmp    load8        ;if error
  413. load7:    lxi    h,execad    ;print 'Execute address: '
  414.     call    wasc
  415.     lhld    addr        ;now print address
  416.     mov    a,h        ;hi byte first
  417.     call    whbc
  418.     mov    a,l        ;next, the low byte
  419.     call    whbc
  420.     call    weolc        ;do cr/lf
  421.     call    weolc
  422.     ret            ;return to main monitor
  423. load8:    lxi    h,cksume    ;print 'Checksum error'
  424.     call    wasc
  425.     ret
  426. ;
  427. ; diag - boot diagnostic system from disk
  428. ;
  429. diag:    mvi    a,0ffh        ;set diagnostic flag
  430.     jmp    bootd        ;proceed as a standard boot
  431. ;
  432. ; boot - boot DOS from diskette (maybe)
  433. ;
  434. boot:
  435. ;
  436.     if    testing        ;prevent odd things from
  437.     jmp    main1        ;happening to first-time SIG/M users
  438.     endif
  439. ;
  440.     mvi    a,0        ;reset diag. flag
  441. bootd:    sta    diagfg
  442.     in    dsksta        ;get disk status
  443.     cpi    0ffh        ;test if no disk in computer
  444.     jnz    boot2        ;if disk is there
  445. boot1:    lxi    h,wutdsk    ;what disk?
  446.     call    wasc
  447.     jmp    main1        ;back to system monitor
  448. boot2:    mvi    a,0ffh        ;issue null commands to update status
  449.     out    dskc2
  450.     out    dskcmd
  451.     mvi    a,35        ;do 35 ms head load delay
  452.     call    delay
  453. boot21:    in    dsksta        ;get status again
  454.     ani    trk0        ;test track 0 bit
  455.     jz    boot3        ;if at track 0
  456.     mvi    a,0ffh        ;this code steps the head in
  457.     out    dskcmd
  458.     ani    0fdh
  459.     out    dskcmd
  460.     ori    002h
  461.     out    dskcmd
  462.     mvi    a,8        ;delay 8 ms between steps
  463.     call    delay        ;do delay
  464.     jmp    boot21        ;test track 0 again
  465. boot3:    mvi    a,0f0h        ;set dma address to 1000h(-3)
  466.     out    dmah
  467.     mvi    a,002h
  468.     out    dmal
  469.     mvi    a,0        ;track 0
  470.     sta    0ffdh        ;@ dma-3
  471.     mvi    a,1        ;sector 1
  472.     sta    0ffeh        ;@ dma-2
  473.     mvi    a,0fbh        ;sd id mark (not really needed)
  474.     sta    0fffh
  475.     mvi    a,readf        ;issue read function
  476.     out    dskcmd        ;issue as command
  477. boot4:    in    dsksta        ;read status
  478.     ani    done        ;test if done
  479.     jz    boot4        ;not yet...
  480.     in    dsksta        ;read status again
  481.     push    psw        ;save full byte for later
  482.     ani    errors        ;test for errors
  483.     jz    boot5        ;if no errors
  484.     lxi    h,booter    ;say boot error
  485.     call    wasc        ;send
  486.     pop    psw        ;get status back
  487.     call    whbc        ;to console
  488.     call    weolc        ;do cr/lf
  489.     jmp    main1        ;to main monitor
  490. boot5:    pop    psw        ;clean up stack
  491.     lxi    h,1000h        ;source address of move
  492.     lxi    d,80h        ;no. of bytes to move
  493.     lxi    b,0        ;destination address
  494.     call    moveup        ;do move
  495.     lda    0        ;get first byte of bootstrap
  496.     cpi    0e5h        ;test for push h
  497.     jnz    boot6        ;if not, execute code
  498.     lxi    h,nosys        ;say no system
  499.     call    wasc        ;send
  500.     jmp    main1        ;go to monitor
  501. ;
  502.     if    not testing    ;if running from rom
  503. boot6:    lda    diagfg        ;get diagnostic flag
  504.     cpi    0ffh        ;see if set
  505.     jz    0        ;if so, proceed directly to boot
  506.     lxi    h,bootc        ;source
  507.     lxi    d,0bh        ;no. of bytes
  508.     lxi    b,temp        ;destination
  509.     call    moveup        ;do move
  510.     jmp    temp        ;turn off rom, turn on ram, jmp to bootstrap
  511.     endif
  512. ;
  513.     if    testing        ;if running from ram
  514. boot6:    jmp    0        ;we don't need to turn off rom board
  515.     endif
  516. ;
  517.     if    not testing
  518. bootc:    db    3eh,0        ;mvi a,0
  519.     db    0d3h,40h    ;out 40h
  520.     db    3eh,1        ;mvi a,1
  521.     db    0d3h,41h    ;out 41h
  522.     db    0c3h,0,0    ;jmp 0
  523.     endif
  524. ;
  525.     if    help
  526. ;
  527. ; hlpdis - display help menu [optional]
  528. ;
  529. hlpdis:    lxi    h,hlpmsg    ;print the whole thing
  530.     call    wasc
  531.     jmp    weolc        ;exit w/ cr/lf
  532.     endif
  533. ;
  534.     if    testing
  535. ;
  536. ; svctst - test supervisor call
  537. ;
  538. svctst:    mov    a,l        ;put svc no. into A
  539.     sta    svc        ;save in svc
  540.     call    super        ;call supervisor
  541.     jmp    weolc        ;exit w/ cr/lf
  542.     endif
  543. ;
  544. ; regdis - display 8080 register set
  545. ;
  546. regdis:    push    h        ;save registers
  547.     push    d
  548.     push    b
  549.     push    psw
  550.     lxi    h,regmsg    ;issue register message
  551.     call    wasc
  552.     lhld    userpc        ;get user's PC
  553.     call    reg1        ;display it
  554.     lxi    h,regsp        ;issue SP message
  555.     call    wasc
  556.     lxi    h,0
  557.     dad    sp        ;sneaky way to get SP
  558.     call    reg1
  559.     lxi    h,regaf        ;issue AF message
  560.     call    wasc
  561.     pop    h        ;get AF
  562.     call    reg1
  563.     lxi    h,regbc        ;issue BC message
  564.     call    wasc
  565.     pop    h        ;get BC
  566.     call    reg1
  567.     lxi    h,regde        ;issue DE message
  568.     call    wasc
  569.     pop    h        ;get DE
  570.     call    reg1
  571.     lxi    h,reghl        ;issue HL message
  572.     call    wasc
  573.     pop    h        ;get HL
  574.     call    reg1
  575.     jmp    weolc        ;exit via cr/lf
  576. reg1:    mov    a,h        ;get high byte
  577.     call    whbc
  578.     mov    a,l        ;get low byte
  579.     call    whbc
  580.     ret            ;return to caller
  581. ;
  582. ; rip - read input port
  583. ;
  584. rip:    mvi    a,in        ;input instruction
  585.     sta    temp        ;save in temp code area
  586.     mov    a,l        ;HL (param1) has input port address
  587.     sta    temp+1
  588.     mvi    a,ret        ;return instruction
  589.     sta    temp+2
  590.     call    temp        ;execute code just built
  591.     call    whbc        ;write result on console
  592.     jmp    weolc        ;equal to call weolc ! ret
  593. ;
  594. ; wop - write output port
  595. ;
  596. wop:    mvi    a,out        ;output instruction
  597.     sta    temp        ;mainly the same as above
  598.     mov    a,l
  599.     sta    temp+1
  600.     mvi    a,ret
  601.     sta    temp+2
  602.     mov    a,e        ;get value to send from param2
  603.     call    temp
  604.     jmp    weolc
  605. ;
  606. ; halt - halt computer
  607. ;
  608. halt:    hlt            ;that was simple!!!
  609. ;
  610. ; dump - dump memory to console in hex & ascii
  611. ;
  612. dump:    lda    pflag1        ;see if address was typed
  613.     ora    a
  614.     jz    weolc        ;no, exit
  615.     call    diff        ;get difference between param1 & param2 in DE
  616.     inx    d        ;+1
  617.     shld    dmpad        ;save param1 as starting dump address
  618.     jmp    dmp        ;do actual dump
  619. ;
  620. ; enter - enter bytes into memory
  621. ;
  622. enter:    mov    a,h        ;prompt w/ current load address
  623.     call    whbc
  624.     mov    a,l
  625.     call    whbc
  626.     mvi    a,':'
  627.     call    wacc
  628.     mvi    a,' '
  629.     call    wacc
  630.     push    h        ;save load address
  631.     lxi    h,ibuf        ;read user's input
  632.     call    rasc
  633.     dcr    b        ;test for empty line
  634.     jz    enter3        ;empty, exit
  635.     lxi    d,ibuf        ;pointer to buffer
  636. enter1:    call    dhs        ;decode 1 byte
  637.     jc    enterr        ;if error
  638.     ora    a        ;test for end of line
  639.     jz    enter2
  640.     mov    a,l        ;L has low byte of entered value
  641.     pop    h        ;restore load address
  642.     mov    m,a        ;move byte into memory
  643.     inx    h        ;increment load address
  644.     push    h        ;save again...
  645.     jmp    enter1        ;do next byte on line
  646. enter2:    pop    h        ;restore load address
  647.     jmp    enter        ;get next line
  648. enter3:    pop    h        ;clean up stack
  649.     jmp    weolc        ;exit w/ cr/lf
  650. enterr:    pop    h        ;clean up stack
  651.     lxi    h,badval    ;send 'bad hex value' message
  652.     jmp    wasc        ;exit
  653. ;
  654. move:    lda    pflag1        ;make sure we have two parameters
  655.     ora    a
  656.     jz    moverr
  657.     lda    pflag2
  658.     ora    a
  659.     jz    moverr
  660.     call    diff        ;find difference between param1 & param2
  661.     inx    d        ;+1
  662.     push    d        ;save param1 & param2
  663.     push    h
  664.     lxi    h,moveto    ;ask 'to?'
  665.     call    wasc
  666.     lxi    h,ibuf        ;get answer
  667.     call    rasc
  668.     lxi    d,ibuf        ;reset pointer
  669.     call    dhs        ;decode answer
  670.     jnc    move1        ;if ok
  671.     pop    h        ;else clean up stack
  672.     pop    d
  673.     jmp    enterr+1    ;print 'bad hex value' message
  674. move1:    xchg            ;DE= address to move to
  675.     mov    b,d        ;copy to BC
  676.     mov    c,e
  677.     pop    h        ;get source address
  678.     call    diff        ;compute distance to move
  679.     pop    d        ;restore size of block to move
  680.     jnc    movedn        ;move downward
  681.     jmp    moveup        ;move upward
  682. moverr:    lxi    h,twopar    ;issue 'two parameters' message
  683.     jmp    wasc
  684. ;
  685. ; fill - fill memory with specified value
  686. ;
  687. fill:    lda    pflag1        ;test for two parameters
  688.     ora    a
  689.     jz    moverr
  690.     lda    pflag2
  691.     ora    a
  692.     jz    moverr
  693.     call    diff        ;compute # of bytes to fill
  694.     inx    d        ;+1
  695.     push    h        ;save parameters (h now has length)
  696.     push    d
  697.     lxi    h,fillw        ;print 'With?'
  698.     call    wasc
  699.     lxi    h,ibuf        ;get answer
  700.     call    rasc
  701.     lxi    d,ibuf
  702.     call    dhs        ;decode it
  703.     jnc    fill1        ;if ok
  704.     pop    d
  705.     pop    h        ;clean up stack
  706.     jmp    enterr+1    ;print 'bad hex value'
  707. fill1:    mov    b,l        ;byte to fill w/ --> B
  708.     pop    d
  709.     pop    h        ;restore source & length
  710. fill2:    mov    a,d        ;return when count=0
  711.     ora    e
  712.     rz
  713.     mov    m,b        ;place fill byte
  714.     inx    h        ;loc=loc+1
  715.     dcx    d        ;# to do=# to do-1
  716.     jmp    fill2
  717. ;
  718. ; go - go to location specified by param1
  719. ;
  720. go:    mvi    a,call        ;stuff call instruction
  721.     sta    temp        ;place in temp code
  722.     shld    temp+1        ;save param1 as address of call
  723.     mvi    a,jmp        ;save jump
  724.     sta    temp+3
  725.     lxi    h,go1        ;where to return to...
  726.     shld    temp+4
  727.     jmp    temp        ;execute code
  728. go1:    jmp    weolc        ;exit w/ cr/lf
  729. ;
  730. ; hexmon - hexadecimal monitor
  731. ;
  732. hexmon:    call    wacc        ;echo '/'
  733.     lxi    d,ibuf        ;decode address(?) just entered
  734.     call    dhs
  735.     jc    hex8        ;if not valid
  736.     shld    addr        ;save address
  737. hex1:    mvi    a,' '        ;send a blank
  738.     call    wacc
  739.     mov    a,m        ;get data that's there
  740.     call    whbc        ;and send to console
  741. hex2:    mvi    a,' '        ;another blank
  742.     call    wacc
  743. hex3:    call    racc        ;get character
  744.     cpi    cr        ;test cr
  745.     push    psw        ;save flags
  746.     cz    weolc        ;do cr/lf if cr
  747.     pop    psw        ;restore flags
  748.     jz    prompt        ;if so, go back to main prompt
  749.     cpi    '^'        ;test for open previous
  750.     jz    hex5        ;if match...
  751.     cpi    lf        ;test for open next
  752.     jz    hex7        ;if match...
  753.     push    psw        ;save value
  754.     call    legal        ;test for legal value
  755.     jc    hex10        ;if invalid, kill stack and retry
  756.     rlc            ;move to high nibble
  757.     rlc
  758.     rlc
  759.     rlc
  760.     sta    data        ;save as data byte
  761.     pop    psw        ;restore ascii version
  762.     call    wacc        ;echo to console
  763. hex4:    call    racc        ;get next nibble
  764.     push    psw
  765.     call    legal        ;test if valid
  766.     jc    hex9        ;if not, kill pushed stuff & try again
  767.     mov    b,a        ;save in B
  768.     lda    data        ;data already has hi nibble
  769.     ora    b        ;add in low nibble
  770.     sta    data        ;save as data again
  771.     pop    psw        ;restore ascii
  772.     call    wacc
  773.     lhld    addr        ;get working address
  774.     lda    data        ;get data
  775.     mov    m,a        ;move
  776.     call    weolc        ;do cr/lf
  777.     inx    h        ;next address
  778.     jmp    hex6
  779. hex5:    call    wacc        ;echo '^'
  780.     call    weolc        ;do cr/lf
  781.     lhld    addr
  782.     dcx    h        ;prev. address
  783. hex6:    shld    addr        ;save as current
  784.     mov    a,h        ;print on console
  785.     call    whbc
  786.     mov    a,l
  787.     call    whbc
  788.     mvi    a,sl        ;put up slash
  789.     call    wacc
  790.     jmp    hex1        ;go to entry mode
  791. hex7:    call    weolc        ;open next address
  792.     lhld    addr
  793.     inx    h
  794.     jmp    hex6
  795. hex8:    lxi    h,baddr        ;say bad address
  796.     call    wasc
  797.     jmp    prompt        ;return to prompt
  798. hex9:    pop    psw        ;kill old char.
  799.     call    ding        ;ring bell
  800.     jmp    hex4        ;try again
  801. hex10:    pop    psw        ;kill old
  802.     call    ding
  803.     jmp    hex3        ;and retry
  804. ;
  805. ; utility routine section - many are available by external programs
  806. ;
  807. ;
  808. ; ding - ring console bell
  809. ;
  810. ding:    push    psw        ;save user's A
  811.     mvi    a,bell
  812.     call    wacc        ;print a bell
  813.     pop    psw        ;restore user's A
  814.     ret            ;return to caller
  815. ;
  816. ; vers - return version number in hl
  817. ;
  818. vers:    lxi    h,0100h        ;version 01.00
  819.     ret            ;give to user
  820. ;
  821. ; moveup - move memory towards zero
  822. ;
  823. moveup:    mov    a,d        ;de=# of bytes to move
  824.     ora    e
  825.     rz            ;if done moving
  826.     mov    a,m        ;get byte from source
  827.     inx    h        ;increment source address
  828.     stax    b        ;save in destination
  829.     inx    b        ;increment destination address
  830.     dcx    d        ;decrement # of bytes left to move
  831.     jmp    moveup        ;go do another...
  832. ;
  833. ; movedn - move memory towards ffff
  834. ;
  835. movedn:    dad    d        ;add source address to # of bytes, giving last
  836.     mov    a,c        ;byte to move
  837.     add    e
  838.     mov    c,a
  839.     mov    a,b
  840.     adc    d
  841.     mov    b,a
  842. movdn1:    mov    a,d        ;see if done
  843.     ora    e
  844.     rz            ;if done
  845.     dcx    h        ;decrement source address
  846.     mov    a,m        ;get byte
  847.     dcx    b        ;decrement destination address
  848.     stax    b        ;store at dest. address
  849.     dcx    d        ;1 less byte to move...
  850.     jmp    movdn1        ;go again
  851. ;
  852. ; diff - compute difference between de & hl and place in de
  853. ;
  854. diff:    mov    a,e        ;do first 8-bit subtract
  855.     sub    l
  856.     mov    e,a        ;return to E
  857.     mov    a,d        ;now do second
  858.     sbb    h
  859.     mov    d,a        ;and return to D
  860.     ret            ;return to caller
  861. ;
  862. ; dmp - dump memory in hex and ascii to console
  863. ;
  864. dmp:    mov    a,d        ;see if done
  865.     ora    e
  866.     jz    weolc        ;if so, exit via weolc
  867. ;
  868.     if    not cpmio    ;if hardware I/O
  869.     in    condat        ;get current data from console
  870.     cpi    cntrlc        ;see if ^C typed...
  871.     jnz    dmp1
  872.     endif
  873. ;
  874.     if    cpmio
  875.     jmp    dmp1        ;can't stop output under CP/M
  876.     endif
  877. ;
  878.     jmp    weolc        ;...and exit
  879. dmp1:    call    weolc        ;start new line
  880.     lda    dmpad+1        ;get high byte of address
  881.     call    whbc        ;write to console
  882.     lda    dmpad        ;do same w/ low byte
  883.     call    whbc
  884.     push    h        ;save address
  885.     push    d        ;save count
  886.     mvi    c,16        ;16 bytes per line
  887. dmp2:    mov    a,d        ;test if done with hex for this line
  888.     ora    e
  889.     jz    dmp3
  890.     mvi    a,' '        ;put a blank between bytes
  891.     call    wacc
  892.     mov    a,m        ;get byte to be dumped
  893.     inx    h        ;increment pointer
  894.     call    whbc        ;print hex byte on console
  895.     push    h        ;save address
  896.     lhld    dmpad        ;increment user's relative address
  897.     inx    h
  898.     shld    dmpad
  899.     pop    h        ;restore our address
  900.     dcx    d        ;decrement # of bytes left
  901.     dcr    c        ;decrement # of bytes left on this line
  902.     jnz    dmp2        ;if more
  903.     jmp    dmp4        ;if not more, do ascii
  904. dmp3:    inr    c        ;this puts ascii in right place if last address
  905.     dcr    c        ;to dump was not on 16 byte boundary
  906.     jz    dmp4        ;if done
  907.     mvi    a,' '        ;print 3 spaces
  908.     call    wacc
  909.     call    wacc
  910.     call    wacc
  911.     jmp    dmp3+1        ;continue
  912. dmp4:    pop    d        ;restore byte count
  913.     pop    h        ;restore pointer
  914.     mvi    a,' '        ;print 2 spaces
  915.     call    wacc
  916.     call    wacc
  917.     mvi    c,16        ;16 ascii bytes / line
  918. dmp5:    mov    a,d        ;test if done
  919.     ora    e
  920.     jz    weolc
  921.     mov    a,m        ;fetch next byte
  922.     inx    h        ;increment pointer
  923.     ani    7fh        ;mask out parity bit
  924.     cpi    20h        ;test if printable
  925.     jnc    $+5        ;if it isn't .lt. 20h
  926.     mvi    a,'.'        ;else use .
  927.     cpi    7fh        ;see if rubout
  928.     jc    $+5        ;if not
  929.     mvi    a,'.'        ;it is, substitute rubout
  930.     call    wacc        ;output to console
  931.     dcx    d        ;1 less byte to do
  932.     dcr    c        ;1 less on this line also
  933.     jnz    dmp5        ;if still more on this line
  934.     jmp    dmp        ;start a new line
  935. ;
  936. ; whbc - write hex byte to console
  937. ;
  938. whbc:    push    psw        ;save byte
  939.     rrc            ;do high nibble first
  940.     rrc
  941.     rrc
  942.     rrc
  943.     call    whdc        ;do digit
  944.     pop    psw        ;get byte back
  945.     push    psw        ;save again
  946.     call    whdc        ;do low nibble
  947.     pop    psw        ;return w/ value
  948.     ret
  949. ;
  950. ; whdc - write hex digit to console
  951. ;
  952. whdc:    ani    0fh        ;only look at low nibble
  953.     cpi    10        ;see if A-F
  954.     jc    $+5        ;no, 0-9
  955.     adi    7        ;make A-F
  956.     adi    '0'        ;make ascii
  957.     jmp    wacc        ;send & exit
  958. ;
  959. ; weolc - do cr/lf on console
  960. ;
  961. weolc:    push    psw        ;save acc
  962.     mvi    a,cr        ;send cr
  963.     call    wacc
  964.     mvi    a,lf        ;send lf
  965.     call    wacc
  966.     pop    psw        ;restore acc
  967.     ret            ;exit
  968. ;
  969. ; wasc - write ascii string to console
  970. ;
  971. wasc:    mov    a,m        ;get character
  972.     inx    h        ;increment pointer
  973.     ora    a        ;see if terminator
  974.     rz            ;return if so
  975.     call    wacc        ;else send character
  976.     jmp    wasc        ;and do another...
  977. ;
  978. ; rasc - read ascii string from console
  979. ;
  980. rasc:    push    h        ;save buffer pointer
  981.     mvi    b,0        ;0 characters entered
  982. rasc1:    call    racc        ;get a character
  983.     cpi    cntrlx        ;test for control-x
  984.     jnz    rasc2        ;no it, continue
  985.     call    rasc7        ;skip old line
  986.     pop    h        ;restore buffer pointer
  987.     jmp    rasc        ;try again
  988. rasc2:    cpi    bs        ;test for backspace
  989.     jnz    rasc3        ;if not
  990.     inr    b        ;see if at beginning of line
  991.     dcr    b
  992.     jz    rasc1        ;if so, simply input again
  993.     dcx    h        ;decrement pointer
  994.     dcr    b        ;decrement count
  995.     mvi    a,bs        ;do bs/space/bs
  996.     call    wacc
  997.     mvi    a,' '
  998.     call    wacc
  999.     mvi    a,bs
  1000.     call    wacc
  1001.     jmp    rasc1        ;get another character
  1002. rasc3:    mov    m,a        ;put in buffer
  1003.     inr    b        ;increment count
  1004.     mov    a,b        ;test if room left in buffer
  1005.     cpi    126
  1006.     jm    rasc4        ;if still room
  1007.     mvi    m,cr        ;else stuff cr
  1008.     pop    h        ;restore pointer
  1009.     ret            ;and exit
  1010. rasc4:    mov    a,m        ;get character back
  1011.     cpi    cr        ;test for cr
  1012.     jz    rasc5        ;if so, exit
  1013.     cpi    sl
  1014.     jz    rasc6        ;test for slash
  1015.     inx    h        ;increment pointer
  1016.     call    wacc        ;echo character
  1017.     jmp    rasc1        ;and go get another
  1018. rasc5:    inx    sp        ;kill stuff on stack
  1019.     inx    sp
  1020.     jmp    weolc        ;and exit
  1021. rasc6:    inx    sp        ;kill stuff on stack
  1022.     inx    sp
  1023.     ret            ;return to user w/o cr
  1024. rasc7:    mov    a,b        ;get count to backspace over
  1025.     cpi    0
  1026.     rz            ;if none, exit...
  1027.     mov    a,m        ;get character
  1028.     dcx    h
  1029.     cpi    20h
  1030.     jc    rasc8        ;if not printing
  1031.     cpi    7fh
  1032.     jz    rasc8        ;likewise
  1033.     mvi    a,bs        ;backspace over current char
  1034.     call    wacc
  1035.     mvi    a,' '
  1036.     call    wacc
  1037.     mvi    a,bs
  1038.     call    wacc
  1039. rasc8:    dcr    b
  1040.     jnz    rasc7
  1041.     ret
  1042. ;
  1043. ; dhs - decode hex string (ascii string @DE into binary in HL)
  1044. ;
  1045. dhs:    lxi    h,0        ;set result=0
  1046.     push    b        ;save B register
  1047.     mvi    b,0        ;clear 'digits found' counter
  1048. dhs1:    ldax    d        ;get character
  1049.     cpi    cr        ;test for cr
  1050.     jz    dhs5
  1051.     inx    d
  1052.     cpi    ' '        ;test for space
  1053.     jz    dhs1        ;skip if so
  1054.     cpi    ','        ;test for comma
  1055.     jz    dhs1        ;skip if so
  1056. dhs2:    dad    h        ;HL=HL*16
  1057.     dad    h
  1058.     dad    h
  1059.     dad    h
  1060.     cpi    61h        ;see if l/c
  1061.     jc    dhs3        ;no
  1062.     sui    20h        ;make it u/c
  1063. dhs3:    sui    '0'        ;convert to binary
  1064.     jc    dhserr        ;if error
  1065.     cpi    10        ;see if <10
  1066.     jc    dhs4        ;yes
  1067.     sui    7        ;no, adjust for A-F
  1068.     cpi    10        ;see if maybe between 9 & A
  1069.     jc    dhserr
  1070. dhs4:    cpi    16        ;test if within bounds
  1071.     jnc    dhserr        ;no, error
  1072.     add    l        ;add to result
  1073.     mov    l,a        ;replace
  1074.     jnc    $+4
  1075.     inr    h        ;if carry
  1076.     inr    b        ;increment 'digits found' counter
  1077.     ldax    d        ;get next byte
  1078.     cpi    cr        ;all these cause an exit
  1079.     jz    dhs5
  1080.     cpi    ' '
  1081.     jz    dhs5
  1082.     cpi    ','
  1083.     jz    dhs5
  1084.     cpi    sl        ;test for slash
  1085.     jz    dhs5
  1086.     inx    d        ;points to next
  1087.     jmp    dhs2        ;decode value in A
  1088. dhs5:    ldax    d        ;normal exit
  1089.     mov    a,b        ;count to A
  1090.     pop    b        ;restore old B (user's)
  1091. yup:    stc            ;general purpose 'yes'
  1092.     cmc
  1093.     ret
  1094. dhserr:    dcx    d        ;error exit
  1095.     ldax    d        ;put offending character in A
  1096.     pop    b        ;restore user's BC
  1097. nope:    stc            ;general purpose 'no'
  1098.     ret            ;exit
  1099. ;
  1100. ; legal - test if an ascii character is a legal hex value
  1101. ;
  1102. legal:    sui    '0'        ;remove ascii offset
  1103.     jc    nope        ;if less, it isn't
  1104.     cpi    10        ;if less than 10...
  1105.     jc    legal1        ;...it's ok
  1106.     sui    7        ;test for a-f
  1107.     cpi    10
  1108.     jc    nope
  1109. legal1:    cpi    16        ;now see if < 16
  1110.     jnc    nope        ;if greater
  1111.     jmp    yup        ;if less than
  1112. ;
  1113. ; ofl - Intel object file loader
  1114. ;    Thanks to: L. E. Hughes / 8080 SDC / Florida
  1115. ;
  1116. ofl:    push    psw        ;save character
  1117.     lda    oflst        ;check state
  1118.     cpi    1
  1119.     jnc    ofl1
  1120.     pop    psw        ;state 0 - wait for a colon
  1121.     cpi    ':'
  1122.     rnz            ;wasn't it - throw away
  1123.     xra    a        ;clear checksum
  1124.     sta    oflcs
  1125.     inr    a        ;set state=1
  1126.     sta    oflst
  1127.     ret
  1128. ofl1:    cpi    2        ;test if state 1
  1129.     jnc    ofl2        ;no, skip
  1130.     inr    a        ;set state=2
  1131.     sta    oflst
  1132.     call    oflcb        ;clear byte buffer
  1133.     pop    psw
  1134.     jmp    oflad        ;accum. first digit of byte count
  1135. ofl2:    cpi    3        ;test if state 2
  1136.     jnc    ofl3        ;no, skip
  1137.     inr    a        ;set state=3
  1138.     sta    oflst
  1139.     pop    psw
  1140.     call    oflad        ;get 2nd digit of byte count
  1141.     sta    oflbc        ;save result as byte count
  1142.     jmp    ofluc        ;add result into checksum
  1143. ofl3:    cpi    4        ;test if state 3
  1144.     jnc    ofl4        ;no, skip
  1145.     inr    a
  1146.     sta    oflst        ;set state=4
  1147.     call    oflcb        ;clear byte buffer
  1148.     pop    psw
  1149.     jmp    oflad        ;accum. 1st digit of hi address byte
  1150. ofl4:    cpi    5        ;test if state 4
  1151.     jnc    ofl5        ;no, skip
  1152.     inr    a
  1153.     sta    oflst        ;set state=5
  1154.     pop    psw
  1155.     call    oflad        ;accum. 2nd digit of hi address byte
  1156.     sta    oflla+1        ;save hi byte of load address
  1157.     jmp    ofluc        ;update checksum
  1158. ofl5:    cpi    6        ;test if state 5
  1159.     jnc    ofl6        ;no, skip
  1160.     inr    a
  1161.     sta    oflst        ;set state=6
  1162.     call    oflcb        ;clear byte buffer
  1163.     pop    psw        ;accum. 1st digit of low address byte
  1164.     jmp    oflad
  1165. ofl6:    cpi    7        ;test if state 6
  1166.     jnc    ofl7        ;no, skip
  1167.     inr    a
  1168.     sta    oflst        ;set state=7
  1169.     pop    psw        ;accum. 2nd digit of low address byte
  1170.     call    oflad
  1171.     sta    oflla        ;save low byte of load address
  1172.     push    psw        ;save for later
  1173.     lda    oflfrr        ;see if first address
  1174.     cpi    0
  1175.     jnz    ofl61        ;no, skip this...
  1176.     inr    a        ;say not first time
  1177.     sta    oflfrr
  1178.     lhld    oflla        ;get load address
  1179.     shld    addr        ;save for user
  1180. ofl61:    pop    psw        ;restore low byte
  1181.     jmp    ofluc        ;update checksum
  1182. ofl7:    cpi    9        ;test if state 8
  1183.     jnc    ofl8        ;no, skip
  1184.     inr    a
  1185.     sta    oflst        ;set state=9
  1186.     pop    psw        ;ignore record type
  1187.     ret
  1188. ofl8:    cpi    10        ;test if state 9
  1189.     jnc    ofl10        ;no, skip
  1190.     inr    a
  1191.     sta    oflst        ;set state=10
  1192.     lda    oflbc        ;get byte count
  1193.     ora    a
  1194.     jz    ofl9        ;skip if no data bytes in record
  1195.     call    oflcb        ;clear byte buffer
  1196.     pop    psw
  1197.     jmp    oflad        ;accum. 1st digit of next data byte
  1198. ofl9:    mvi    a,11        ;set state=12 (all data bytes read)
  1199.     sta    oflst
  1200.     jmp    ofl11
  1201. ofl10:    cpi    11        ;test if state 10
  1202.     jnc    ofl11        ;no, skip
  1203.     dcr    a        ;loop at previous state
  1204.     sta    oflst
  1205.     pop    psw
  1206.     call    oflad        ;accum. 2nd digit of next data byte
  1207.     push    h
  1208.     lhld    oflla
  1209.     mov    m,a        ;load byte
  1210.     inx    h        ;increment load address
  1211.     shld    oflla
  1212.     pop    h
  1213.     call    ofluc        ;update checksum
  1214.     lda    oflbc        ;decrement byte count
  1215.     dcr    a
  1216.     sta    oflbc
  1217.     ret
  1218. ofl11:    cpi    12        ;test if state 11
  1219.     jnc    ofl12        ;no, skip
  1220.     inr    a
  1221.     sta    oflst        ;set state=12
  1222.     call    oflcb        ;clear byte buffer
  1223.     pop    psw
  1224.     jmp    oflad        ;accum. 1st digit of checksum
  1225. ofl12:    pop    psw
  1226.     call    oflad        ;accum. 2nd byte of checksum
  1227.     call    ofluc        ;add into new checksum
  1228.     sta    oflce        ;save as checksum
  1229.     xra    a
  1230.     sta    oflst        ;back at state 0
  1231.     ret
  1232. oflcb:    xra    a        ;clear byte buffer
  1233.     sta    oflbb
  1234.     ret
  1235. oflad:    call    legal        ;convert to binary
  1236.     push    b        ;accum. hex digit
  1237.     mov    b,a
  1238.     lda    oflbb        ;fetch byte buffer
  1239.     add    a        ; * 16
  1240.     add    a
  1241.     add    a
  1242.     add    a
  1243.     add    b        ;add in new digit
  1244.     sta    oflbb        ;replace old value
  1245.     pop    b
  1246.     ret
  1247. ofluc:    push    h        ;update checksum
  1248.     lxi    h,oflcs        ;point to checksum
  1249.     add    m        ;add in new byte
  1250.     mov    m,a
  1251.     pop    h
  1252.     ret    
  1253. ;
  1254. ; this is the console driver
  1255. ;
  1256. ;
  1257. ; racc - read ascii character from console
  1258. ;
  1259.     if    not cpmio    ;if hardware I/O
  1260. racc:    in    consta        ;read status port
  1261.     ani    rda        ;test rda bit
  1262.     jz    racc
  1263.     in    condat        ;get data
  1264.     ani    7fh        ;strip parity bit
  1265.     endif
  1266. ;
  1267.     if    cpmio        ;if running w/ CP/M I/O calls
  1268. racc:    push    b        ;save user registers
  1269.     push    d
  1270.     push    h
  1271.     mvi    a,conin        ;perform conin function
  1272.     call    cbios
  1273.     pop    h        ;restore registers
  1274.     pop    d
  1275.     pop    b
  1276.     endif            ;fall thru to case changer
  1277. ;
  1278.     cpi    61h        ;translate to u/c
  1279.     rm
  1280.     cpi    7bh
  1281.     rp
  1282.     sui    20h
  1283.     ret
  1284. ;
  1285. ; wacc - write ascii character to console, handling ^S/^Q
  1286. ;
  1287.     if    not cpmio    ;if hardware I/O
  1288. wacc:    push    psw        ;save user's A
  1289.     in    consta        ;get status
  1290.     ani    rda        ;see if something typed
  1291.     jz    wacc1        ;no, do straight output
  1292.     in    condat        ;yes, get char.
  1293.     cpi    cntrls        ;test for ^S
  1294.     jz    wacc2        ;yes, do wait loop
  1295. wacc1:    in    consta        ;get status again
  1296.     ani    tbe        ;test tbe
  1297.     jz    wacc+1        ;not there, wait
  1298.     pop    psw        ;restore character
  1299.     out    condat        ;send it
  1300.     ret            ;exit
  1301. wacc2:    in    consta        ;wait for ^Q
  1302.     ani    rda
  1303.     jz    wacc2        ;wait for a key
  1304.     in    condat
  1305.     cpi    cntrlq        ;test if ^Q
  1306.     jnz    wacc2        ;no, get another
  1307.     jmp    wacc1        ;return & output
  1308.     endif
  1309. ;
  1310.     if    cpmio        ;if running w/ CP/M I/O calls
  1311. wacc:    push    b        ;save user registers
  1312.     push    d
  1313.     push    h
  1314.     push    psw
  1315.     mov    c,a        ;put char in C
  1316.     mvi    a,conout    ;do conout function
  1317.     call    cbios
  1318.     pop    psw
  1319.     pop    h        ;restore user registers
  1320.     pop    d
  1321.     pop    b
  1322.     ret
  1323.     endif
  1324. ;
  1325.     if    cpmio        ;link to CP/M I/O handler
  1326. ;
  1327. ; cbios - call bios routine
  1328. ;
  1329. cbios:    push    h
  1330.     push    d
  1331.     lhld    wboot+1
  1332.     sui    3
  1333.     mov    e,a
  1334.     mvi    d,0
  1335.     dad    d
  1336.     pop    d
  1337.     xthl
  1338.     ret
  1339.     endif
  1340. ;
  1341. ; delay - delay @(A) milliseconds
  1342. ;
  1343. delay:    mvi    c,0b0h        ;time constant (2 mhz)
  1344. delay1:    dcr    c
  1345.     jnz    delay1
  1346.     dcr    a
  1347.     jnz    delay
  1348.     ret
  1349. ;
  1350. ; const - see if user has typed anything
  1351. ;
  1352.     if    not cpmio    ;if using hardware I/O calls
  1353. const:    in    consta        ;get status
  1354.     ani    rda        ;test rda
  1355.     rz            ;A=0=nothing
  1356.     mvi    a,0ffh        ;A=FF=something
  1357.     ret
  1358.     endif
  1359. ;
  1360.     if    cpmio        ;if using CP/M I/O calls
  1361. const:    push    h        ;save registers
  1362.     push    d
  1363.     push    b
  1364.     mvi    a,conrdy    ;issue cbios call
  1365.     call    cbios
  1366.     pop    b
  1367.     pop    d
  1368.     pop    h
  1369.     σσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσin    rdrdat        ;get data
  1370.     ani    7fh        ;strip parity
  1371.     ret            ;exit to caller
  1372. ;
  1373. ; message text area - all texts go here
  1374. ;
  1375. ;
  1376. cs:    db    27,28,0        ;clear screen code, terminated w/ a zero
  1377. ;
  1378. signon:    db    'SYSMON 02.00 - 04/10/81',cr,lf
  1379. ;
  1380.     if    help
  1381.     db    'Type ? for command summary...',cr,lf
  1382.     endif
  1383. ;
  1384.     db    0
  1385. ;
  1386. badcom:    db    bell,'Unknown command',cr,lf,0
  1387. ;
  1388. badstx:    db    bell,'Syntax error in command',cr,lf,0
  1389. ;
  1390. badval:    db    bell,'Non-hexadecimal value entered',cr,lf,0
  1391. ;
  1392. moveto:    db    'Move to? ',0
  1393. ;
  1394. fillw:    db    'Fill with? ',0
  1395. ;
  1396. twopar:    db    bell,'Two parameters are required',cr,lf,0
  1397. ;
  1398. wutdsk:    db    bell,'Disk drive not ready...',cr,lf,0
  1399. ;
  1400. booter:    db    bell,'Boot error, controller status: ',0
  1401. ;
  1402. nosys:    db    bell,'No system image on disk...',cr,lf,0
  1403. ;
  1404. baddr:    db    bell,bs,' <-- Bad address entered...',cr,lf,0
  1405. ;
  1406. askfil:    db    'Filename? ',0
  1407. ;
  1408. askply:    db    cr,lf,'Press PLAY on tape unit...',cr,lf,0
  1409. ;
  1410. found:    db    cr,lf,'Found ',0
  1411. ;
  1412. loadng:    db    cr,lf,'Loading...',0
  1413. ;
  1414. execad:    db    cr,lf,'Execute address: ',0
  1415. ;
  1416. cksume:    db    cr,lf,bell,'Checksum error!',cr,lf,0
  1417. ;
  1418. regmsg:    db    'Register set:'
  1419.     db    cr,lf,'  PC: ',0
  1420. regsp:    db    cr,lf,'  SP: ',0
  1421. regaf:    db    cr,lf,'  AF: ',0
  1422. regbc:    db    cr,lf,'  BC: ',0
  1423. regde:    db    cr,lf,'  DE: ',0
  1424. reghl:    db    cr,lf,'  HL: ',0
  1425. ;
  1426. ilsum1:    db    cr,lf,bell,'Illegal SVC (',0
  1427. ilsum2:    db    ') from user PC: ',0
  1428. ;
  1429.     if    help
  1430. hlpmsg:    db    cr,lf,'                  *** Command Summary ***',cr,lf,lf
  1431.     db    '  B               - Boot operating system from disk.',cr,lf
  1432.     db    '  D [start] [end] - Dump memory in ascii & hex from',cr,lf
  1433.     db    '                    [start] to [end], inclusive.',cr,lf
  1434.     db    '  E [address]     - Enter hex data beginning at [address].',cr,lf
  1435.     db    '                    Terminate w/ blank line.',cr,lf
  1436.     db    '  F [start] [end] - Fill memory with constant value. The',cr,lf
  1437.     db    '                    system will ask for the [constant].',cr,lf
  1438.     db    '  G [address]     - Jump to [address] and execute the code',cr,lf
  1439.     db    '                    there. Exit w/ a RET instruction.',cr,lf
  1440.     db    '  H               - Halt the computer.',cr,lf
  1441.     db    '  I [port]        - Input and display the data at [port].',cr,lf
  1442.     db    '  L               - Load diagnostic tape from tape unit.',cr,lf
  1443.     db    '                  - The system will ask for the [filename].',cr,lf
  1444.     db    '  M [from] [len]  - Move [len] bytes of data from address',cr,lf
  1445.     db    '                    [from]. The system will ask for the',cr,lf
  1446.     db    '                    [to] address.',cr,lf
  1447.     db    '  O [port] [data] - Output [data] to [port].',cr,lf
  1448. ;
  1449.     if    testing
  1450.     db    '  Q               - Quit and return to operating system.',cr,lf
  1451.     endif
  1452. ;
  1453.     db    '  R               - Display 8080 register set.',cr,lf
  1454.     db    '  S               - Perform load of diagnostics disk.',cr,lf
  1455. ;
  1456.     if    testing
  1457.     db    '  T [call]        - Tests user SVC [call] with whatever is',cr,lf
  1458.     db    '                    currently in BC, DE, & HL.',cr,lf
  1459.     endif
  1460. ;
  1461.  
  1462.     db    lf
  1463.     db    '  [addr]/         - Open memory location [addr] and display',cr,lf
  1464.     db    '                    its contents. Enter CR to return to the',cr,lf
  1465.     db    '                    prompt, LF to open the next location, ^',cr,lf
  1466.     db    '                    to open the previous one, or 2 hex dig-',cr,lf
  1467.     db    '                    its to replace the ones displayed.',cr,lf
  1468.     db    lf
  1469.     db    '  Arguments default to 100h except for M & F, which must be',cr,lf
  1470.     db    'explicitly entered. Do not enter the [], they are used only',cr,lf
  1471.     db    'for illustration. Arguments may be seperated by '','' or '' ''.',cr,lf
  1472.     db    lf
  1473.     db    0
  1474.     endif
  1475. ;
  1476.     end
  1477.