home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / program / jmon.arc / JMON.Z80 < prev    next >
Encoding:
Text File  |  1990-07-22  |  19.1 KB  |  1,082 lines

  1. ;
  2. ;JMON-monitor for banked BIOS
  3. ;
  4. ;Vers Date    Name    Notes
  5. ;1.00 88Jan22 Loke J    Release of MicroBee version for ZASM
  6. ;            Pages switched in banks of 56k (0000h-DFFFh)
  7. ;            Bank switching using port 0Ah
  8. ;                out    (0Ah),a        ;A=bank 0..3
  9. ;            Common memory 0E000h-0FFFFh
  10. ;            My version uses RAM at 0F800h for this program
  11. ;            with self-modifying code.
  12. ;            ZASM has no PHASE directive, so I had to use
  13. ;            an offset for EVERY absolute reference.  e.g.
  14. ;            (and no laughing)
  15. ;                ld    sp,stk+poff    ;+poff offset
  16. ;            When writing the JVDU.Z80 and the JKBDST.Z80
  17. ;            overlays be sure to use +poff in the same
  18. ;            manner.
  19. ;0.32 88Jan15 Loke J    Fixed Sxxxx stepping bug
  20. ;0.31 88Jan07 Loke J    Added Hxxxx,yyyy option, Z display option
  21. ;            increased some constants to take more room
  22. ;            more $0 to $7, changed dispr and reg to make
  23. ;            use of regtbl.  Added .R and .A option to prsadr
  24. ;            Added command list in comments below
  25. ;0.30 88Jan05 Loke J    Added code for bootstrap loader from
  26. ;            CP/M TPA, patch loading code
  27. ;            Revised register display, and prsadr
  28. ;            Added Qxxxx option, changed $0 to $7
  29. ;            Added S,$$$ option
  30. ;0.20 87Aug28 Loke J    Merged KBD.Z80, fixed reverse-order
  31. ;            breakpoint resetting
  32. ;0.10 87Jul25 Loke J    Original version, uses include KBD.Z80
  33. ;            Uses a hardware scroll VDU driver
  34. ;
  35. ;Commands
  36. ;    B        display all breakpoints
  37. ;    Bxxxx        toggle breakpoint at xxxx
  38. ;
  39. ;    C        clear all breakpoints
  40. ;
  41. ;    D        dump 128 bytes from current pointer
  42. ;    Dxxxx        dump 128 bytes from xxxx
  43. ;    Dxxxx,yyyy    dump from xxxx to yyyy
  44. ;    D,yyyy        dump from last addr to yyyy
  45. ;
  46. ;    Fxxxx,yyyy    fill from xxxx to yyyy with 00
  47. ;    Fxxxx,yyyy,nn    fill from xxxx to yyyy with nn
  48. ;
  49. ;    G        go to PC
  50. ;    Gxxxx        go to xxxx
  51. ;    Gxxxx,yyyy    go to PC, temporary breakpoint at yyyy
  52. ;
  53. ;    Hxxxx,yyyy    display sum and difference (hexadecimal)
  54. ;
  55. ;    Inn        input from port nn
  56. ;    Inn,oo        input from port nn, put oo on A8..A15
  57. ;
  58. ;    Mxxxx,yyyy,zzzz    move memory from xxxx..yyyy to zzzz
  59. ;
  60. ;    Onn,oo        output value oo to port nn
  61. ;
  62. ;    Q        quit to ROM monitor
  63. ;    Qxxxx        quit to address xxxx
  64. ;
  65. ;    R        display registers
  66. ;    Rrxxxx        set register r to xxxxx, where r in [ABDHXYSPZ]
  67. ;    RFfff        set flag(s) f in flag register, f in [SZHPNC]
  68. ;
  69. ;    S        substitute memory contents from last address
  70. ;    Sxxxx        substitute memory contents at xxxx
  71. ;
  72. ;    Z        display current PAGE register
  73. ;    Zxxxx        set PAGE register to xxxx
  74. ;
  75. ;notes
  76. ;    field    description        example    notes
  77. ;
  78. ;    nn    hex number        I0    input from port 00h
  79. ;
  80. ;    xxxx    hex number        G,0DF3    go with temp brkpt at 0DF3h
  81. ;        or PC spec        D.    dump from PC onwards
  82. ;        or PC relative target    B.r    brkpt assuming PC at JR
  83. ;        or PC absolute target    B.a    brkpt e.g. with PC at CALL
  84. ;
  85. ;    rr    register name        RA38    set A to 38h
  86. ;                    RH1234    set HL to 1234h
  87. ;
  88. ;    ffff    flag name        RFZPS    set FLAGS Z P and S
  89. ;
  90. ;Constants
  91. ;
  92. buflen    equ    16    ;size of input buffer
  93. maxbrk    equ    8    ;max number of breakpoints
  94. stklvl    equ    16    ;stack size
  95. brkval    equ    0FFh    ;opcode for break
  96. brkadr    equ    0038h    ;location for RST
  97. rommon    equ    0E003h    ;Entry point for ROM monitor
  98. pdest    equ    0F800h
  99. ;
  100. ;
  101.     org    0100h
  102.     jp    cboot
  103.     db    13,'JMON monitor for banked BIOS',13,10,26
  104. cboot:    ld    a,(005Ch+8+1)    ;look at TYPE byte
  105.     cp    ' '        ;which PCG/Colour bank
  106.     ld    a,40h        ;switch for Colour bank
  107.     jr    z,cboot1
  108.     xor    a        ;switch for PCG bank
  109. cboot1:    out    (08h),a
  110.     ld    hl,patbas
  111.     ld    de,pdest
  112.     ld    bc,pattop-patbas
  113.     ldir
  114.     ld    a,(005Ch+1)
  115.     cp    ' '        ;execute?
  116.     ret    z
  117.     jp    pdest
  118. ;
  119. ;
  120. ;
  121.     org    0180h
  122. patbas    equ    $
  123. poff    equ    pdest-patbas
  124. ;
  125. ;Entry vector
  126. jmon:    jp    poff+boot
  127. ;
  128. ;
  129. ;Re-entry trap to monitor
  130. trap:    nop
  131.     nop
  132. ;Store registers
  133.     ld    (xhl+poff),hl
  134.     ld    (xde+poff),de
  135.     ld    (xbc+poff),bc
  136.     ld    (xix+poff),ix
  137.     ld    (xiy+poff),iy
  138.     pop    hl
  139.     dec    hl
  140.     ld    (xpc+poff),hl
  141.     ld    (xsp+poff),sp
  142.     ld    sp,stk+poff
  143.     push    af
  144.     pop    hl
  145.     ld    (xaf+poff),hl
  146. ;Calculate & store active page
  147.     ld    a,(brkadr+1)
  148.     sub    a,0+((trap+poff) and 255)
  149.     ld    (xz+poff),a
  150. ;Restore restart bytes
  151.     ld    hl,brkadr
  152.     ld    de,poff+xrst
  153.     ld    b,3        ;For each of 3 bytes
  154. tp1:    xor    a
  155.     ld    c,a        ;C=A=0
  156. tp2:    out    (0Ah),a
  157.     ld    a,(de)
  158.     ld    (hl),a
  159.     inc    de
  160.     inc    c
  161.     ld    a,c
  162.     cp    3        ;Loop for each of 3 pages
  163.     jr    c,tp2
  164.     inc    hl
  165.     djnz    tp1
  166. ;Restore breakpoint bytes
  167.     ld    hl,nbrk+poff
  168.     ld    a,(hl)        ;A=no of breakpoints
  169.     inc    hl
  170.     ld    b,a        ;B=A
  171.     add    a,a
  172.     jr    z,tp4        ;skip if no breakpoints
  173.     add    a,a        ;A*=4 bytes for each breakpoint
  174.     call    poff+addhla    ;HL+=A
  175. tp3:    dec    hl
  176.     ld    c,(hl)        ;C=old byte
  177.     dec    hl
  178.     ld    d,(hl)
  179.     dec    hl
  180.     ld    e,(hl)        ;DE=address
  181.     dec    hl
  182.     ld    a,(hl)        ;A=page
  183.     out    (0Ah),a
  184.     ld    a,c
  185.     ld    (de),a        ;restore old byte
  186.     djnz    tp3
  187. tp4:
  188. ;Restore temporary breakpoint if applicable
  189. trppat    equ    $+1
  190.     jr    tp6
  191. gbkpag    equ    $+1
  192. tp5:    ld    a,00h
  193.     out    (0Ah),a
  194. gbkint    equ    $+1
  195.     ld    a,00h
  196. gbkadr    equ    $+1
  197.     ld    (0000h),a
  198. tp6:
  199. trpskp    equ    tp6-tp5
  200. ;
  201. ;Display registers
  202. disp:
  203. ;Display flags register
  204.     ld    a,(poff+xaf)
  205.     ld    c,a        ;C=flags
  206.     ld    b,8        ;8 flags
  207.     ld    hl,flnam+poff    ;HL=>flag names
  208. dsp1:    ld    a,' '
  209.     rl    c
  210.     jr    nc,dsp2
  211.     ld    a,(hl)
  212. dsp2:    call    poff+wr$a
  213.     inc    hl
  214.     djnz    dsp1
  215. ;Display A, B,D,H,X,Y, Z, S,P
  216.     call    poff+wrsppc    ;A
  217.     db    'A','='+80h
  218.     ld    a,(poff+xaf+1)
  219.     call    poff+wra8
  220.  
  221.     ld    hl,poff+regtbl
  222.     ld    b,5
  223. dsp3:    call    poff+dspr    ;B,D,H,X,Y
  224.     djnz    dsp3
  225.  
  226.     call    poff+wrsppc
  227.     db    'Z','='+80h
  228.     ld    a,(poff+xz)
  229.     call    poff+wra8
  230.  
  231.     call    poff+dspr    ;S
  232.     call    poff+dspr    ;P
  233. ;
  234. brk:
  235. warm:    ld    sp,stk+poff
  236.     call    poff+wrcrlf
  237. warm1:    ld    a,(poff+xz)
  238.     out    (0Ah),a
  239.     call    poff+wr$pc
  240.     db    '$'+80h
  241.     call    poff+rdbuff
  242.     call    poff+getch    ;Z if eoln
  243.     jr    z,warm1
  244.     ld    de,poff+cmdtbl
  245.     call    poff+vswpc
  246.     jr    warm
  247. ;
  248. ;Error trap
  249. monerr:    call    poff+wr$pc
  250.     db    '?'+80h
  251.     jr    brk
  252. ;
  253. ;Dump [addr1[,addr2]]
  254. lstdmp    equ    $+1
  255. dump:    ld    hl,0000h
  256.     call    poff+prsadr
  257. dmp1:    ex    de,hl        ;DE=start addr
  258.     ld    hl,007Fh
  259.     ld    c,l        ;C=NZ flag for dump end
  260.     add    hl,de
  261.     call    poff+prsadr
  262.     ex    de,hl        ;HL=start addr,DE=end addr
  263. dmp2:    ld    a,(poff+xz)    ;A=page
  264.     call    poff+wra8
  265.     call    poff+wr$pc
  266.     db    ':'+80h
  267.     ld    b,16
  268.     push    hl        ;Stack start of row
  269.     call    poff+wrhl16    ;Dump address
  270.     call    poff+wr$spc
  271. dmp3:    ld    a,l
  272.     and    03h
  273.     call    z,poff+wr$spc    ;write space before every 4th byte
  274.     ld    a,(hl)
  275.     call    poff+wra8
  276.     call    poff+hlcpde
  277.     jr    nz,dmp4
  278.     ld    c,0        ;set C=0 to flag end of dump
  279. dmp4:    inc    hl
  280.     djnz    dmp3
  281. dmp5:    pop    hl        ;HL=start of row
  282.     call    poff+wr$spc
  283.     ld    b,16
  284. dmp6:    ld    a,l
  285.     and    07h
  286.     call    z,poff+wr$spc    ;write space before every 8th byte
  287.     ld    a,(hl)
  288.     cp    20h
  289.     jr    nc,dmp7
  290.     ld    a,'.'
  291. dmp7:    call    poff+wr$a
  292.     inc    hl
  293.     djnz    dmp6
  294.     ld    (lstdmp+poff),hl
  295.     call    poff+wrcrlf
  296.     inc    c
  297.     dec    c
  298.     jr    nz,dmp2
  299.     ret
  300. ;
  301. ;Go [addr1[,addr2]]
  302. go:    call    poff+prsadr
  303.     jr    nc,go1
  304.     ld    (xpc+poff),hl    ;Set up target PC
  305. ;Set up temporary breakpoint
  306. go1:    call    poff+prsadr    ;Test for temporary breakpoint
  307.     ld    a,trpskp
  308.     jr    nc,go2
  309.     ld    a,(hl)        ;A=byte
  310.     ld    (hl),brkval
  311.     ld    (gbkadr+poff),hl
  312.     ld    (gbkint+poff),a
  313.     ld    a,(poff+xz)
  314.     ld    (gbkpag+poff),a
  315.     xor    a        ;A=0
  316. go2:    ld    (trppat+poff),a
  317. ;Set up breakpoints
  318.     ld    hl,nbrk+poff
  319.     ld    b,(hl)        ;B=no of breakpoints
  320.     inc    hl
  321.     inc    b
  322.     jr    go4
  323. go3:    ld    a,(hl)        ;Page number
  324.     inc    hl
  325.     out    (0Ah),a        ;Select page
  326.     ld    e,(hl)
  327.     inc    hl
  328.     ld    d,(hl)        ;DE=address
  329.     inc    hl
  330.     ld    a,(de)        ;A=previous byte
  331.     ld    (hl),a        ;Store byte
  332.     inc    hl
  333.     ld    a,brkval
  334.     ld    (de),a        ;Set up breakpoint
  335. go4:    djnz    go3        ;Loop for next byte
  336. ;Set up restart bytes
  337.     ld    hl,brkadr
  338.     ld    de,poff+xrst
  339.     ld    b,3        ;For each of 3 bytes
  340. go5:    xor    a
  341.     ld    c,a        ;C=A=0
  342. go6:    out    (0Ah),a
  343.     ld    a,(hl)
  344.     ld    (de),a
  345.     inc    de
  346.     inc    c
  347.     ld    a,c
  348.     cp    3        ;Loop for each of 3 pages
  349.     jr    c,go6
  350.     inc    hl
  351.     djnz    go5
  352. ;
  353.     ld    hl,brkadr
  354.     ld    bc,0300h    ;B=3,C=0
  355. go7:    ld    a,c
  356.     out    (0Ah),a
  357.     ld    (hl),0C3h
  358.     inc    c
  359.     djnz    go7
  360.     ld    hl,trap+poff
  361.     ld    bc,0300h    ;B=3,C=0
  362. go8:    ld    a,c
  363.     out    (0Ah),a
  364.     ld    (brkadr+1),hl
  365.     inc    l
  366.     inc    c
  367.     djnz    go8
  368. ;Set up registers
  369. xz    equ    $+1
  370. go9:    ld    a,00h
  371.     out    (0Ah),a
  372. xaf    equ    $+1
  373.     ld    hl,0000h
  374.     push    hl
  375.     pop    af
  376. xbc    equ    $+1
  377.     ld    bc,0000h
  378. xde    equ    $+1
  379.     ld    de,0000h
  380. xhl    equ    $+1
  381.     ld    hl,0000h
  382. xix    equ    $+2
  383.     ld    ix,0000h
  384. xiy    equ    $+2
  385.     ld    iy,0000h
  386. xsp    equ    $+1
  387.     ld    sp,0100h
  388. xpc    equ    $+1
  389.     jp    0100h
  390. ;
  391. ;Quit JMON [addr]
  392. quit:    call    poff+wr$pc
  393.     db    1Ah+80h        ;clear screen
  394.     call    poff+prsadr    ;check if an address was given
  395.     jr    nc,quit1    ;skip if no address
  396.     ld    (poff+xpc),hl    ;set PC if an address was given
  397.     jr    go9        ;execute program if address given
  398. quit1:    xor    a        ;else go to ROM monitor
  399.     out    (0Ah),a
  400.     in    a,(0Ah)        ;Switch ROM in
  401.     jp    rommon        ;Jump to ROM monitor
  402. ;
  403. ;Registers [regnum1]
  404. reg:    call    poff+getch
  405.     jp    z,disp+poff    ;No parameter
  406.     call    poff+toupper
  407.     ld    e,a        ;E=char
  408.     sub    'F'        ;A=0,Z if flags
  409.     jr    z,regf        ;special case for flags
  410.     call    poff+prsadr
  411.     jp    nc,monerr+poff    ;No value error
  412.     push    hl
  413.     ld    a,e
  414.     ld    hl,poff+regtbl
  415. reg1:    bit    7,(hl)
  416.     jr    nz,reg3
  417.     cp    (hl)
  418.     inc    hl
  419.     ld    e,(hl)
  420.     inc    hl
  421.     ld    d,(hl)
  422.     inc    hl
  423.     jr    nz,reg1
  424.     ex    de,hl
  425.     pop    de
  426.     ld    (hl),e
  427.     inc    hl
  428.     ld    (hl),d        ;store new value
  429.     ret
  430. ;
  431. ;Special cases
  432. reg3:    pop    de        ;E=new value
  433.     cp    'A'
  434.     ld    hl,poff+xaf+1
  435.     jr    z,reg4        ;Set accumulator
  436.     cp    'Z'
  437.     jp    nz,poff+monerr    ;skip if not flags
  438.     ld    hl,poff+xz    ;set page
  439. ;
  440. reg4:    ld    (hl),e
  441.     ret
  442. ;
  443. ;Set flags
  444. regf:    ld    c,a        ;C=flag image (initially 0)
  445. rgf1:    call    poff+getch
  446.     jr    z,rgf4        ;Exit
  447.     call    poff+toupper
  448.     ld    b,80h        ;B=10000000b
  449.     ld    hl,flnam+poff    ;HL=>flag names
  450. rgf2:    cp    (hl)
  451.     jr    z,rgf3
  452.     inc    hl
  453.     or    a        ;CY=0
  454.     rr    b
  455.     jr    nc,rgf2
  456. rgferr:    jp    monerr+poff
  457. rgf3:    ld    a,b
  458.     or    c
  459.     ld    c,a
  460.     jr    rgf1
  461. rgf4:    ld    a,c
  462.     ld    (xaf+poff),a
  463.     ret
  464. ;
  465. ;Set page register
  466. pag:    call    poff+prsnum
  467.     ld    de,xz+poff
  468.     ld    a,(de)
  469.     jp    nc,poff+wra8
  470.     ld    a,l
  471.     and    03h
  472.     ld    (de),a
  473.     ret
  474. ;
  475. ;Clear breakpoint
  476. clrbpt:    ld    hl,nbrk+poff
  477.     ld    (hl),0        ;Clear all breakpoints
  478.     ret
  479. ;
  480. ;Break [Addr1|.]
  481. setbpt:    call    poff+prsadr
  482.     jr    nc,sbp5        ;Skip to show breakpoints
  483. sbp1:    push    hl        ;Stack addr
  484.     ld    a,(poff+xz)
  485.     ld    c,a        ;C=page
  486.     ld    hl,nbrk+poff
  487.     ld    b,(hl)        ;B=no of breakpoints
  488.     inc    hl
  489.     inc    b
  490.     jr    sbp4
  491. sbp2:    ld    a,(hl)
  492.     inc    hl
  493.     cp    c        ;Same page?
  494.     jr    nz,sbp3        ;Skip if different page
  495.     ld    e,(hl)
  496.     inc    hl
  497.     ld    d,(hl)
  498.     dec    hl        ;DE=old addr
  499.     ex    (sp),hl
  500.     call    poff+hlcpde
  501.     ex    (sp),hl        ;Same address?
  502.     jr    z,sbp8        ;Old address, delete it
  503. sbp3:    inc    hl
  504.     inc    hl
  505.     inc    hl
  506. sbp4:    djnz    sbp2        ;Test another address
  507.     pop    de        ;DE=new addr
  508. ;Add a new address C:DE
  509.     ld    a,(poff+nbrk)
  510.     cp    maxbrk
  511.     jp    nc,monerr+poff    ;Skip if no more room
  512.     inc    a
  513.     ld    (nbrk+poff),a
  514.     ld    (hl),c        ;Store page
  515.     inc    hl
  516.     ld    (hl),e
  517.     inc    hl
  518.     ld    (hl),d
  519.     ret
  520. ;
  521. ;Show breakpoints
  522. sbp5:    ld    hl,nbrk+poff
  523.     ld    b,(hl)
  524.     inc    hl
  525.     inc    b
  526.     jr    sbp7
  527. sbp6:    ld    a,(hl)
  528.     inc    hl
  529.     call    poff+wra8
  530.     call    poff+wr$pc
  531.     db    ':'+80h
  532.     ld    e,(hl)
  533.     inc    hl
  534.     ld    d,(hl)
  535.     inc    hl
  536.     call    poff+wrde16    ;swaps DE<->HL
  537.     ex    de,hl
  538.     inc    hl
  539.     call    poff+wrcrlf
  540. sbp7:    djnz    sbp6
  541.     ret
  542. ;
  543. ;Toggle breakpoint off
  544. sbp8:    pop    af        ;Drop old addr
  545.     dec    hl
  546.     ex    de,hl        ;DE=>current entry
  547.     ld    hl,4
  548.     add    hl,de        ;HL=>next entry
  549.     ld    a,b
  550.     dec    a        ;A=no of entries to move
  551.     jr    z,sbp9        ;Skip if none
  552.     add    a,a
  553.     add    a,a        ;A=4*no of entries to move
  554.     ld    c,a
  555.     ld    b,0        ;BC=A
  556.     ldir            ;Move entries
  557. sbp9:    ld    hl,nbrk+poff
  558.     dec    (hl)
  559.     call    poff+wr$pc
  560.     db    '-'+80h
  561.     ret
  562. ;
  563. ;Substitue [addr]
  564. lstsbt    equ    $+1
  565. subst:    ld    hl,0000h
  566.     call    poff+prsadr
  567.     ex    de,hl        ;DE=start addr
  568. stp1:    ld    a,(poff+xz)
  569.     call    poff+wra8    ;Show page:addr
  570.     call    poff+wr$pc
  571.     db    ':'+80h
  572.     call    poff+wrde16    ;Swaps DE<->HL
  573.     ex    de,hl
  574.     call    poff+wr$spc
  575.     ld    a,(de)
  576.     call    poff+wra8    ;Show old value
  577.     call    poff+wr$spc
  578.     call    poff+rdbuff    ;Read a line
  579.     inc    b
  580.     djnz    stp2        ;skip if not eoln
  581.     inc    de        ;step address
  582.     jr    stp1
  583. stp2:    call    poff+prsnum    ;Get new value
  584.     jr    nc,stp4        ;Skip if no new value
  585.     ld    a,l
  586.     ld    (de),a        ;Store new value
  587.     inc    de
  588.     jr    stp2
  589. stp4:    cp    ','        ;comma introduces string
  590.     jr    nz,stp6
  591. stp5:    call    poff+getch
  592.     jr    z,stp1        ;byte values to end of line
  593.     ld    (de),a        ;store byte value
  594.     inc    de
  595.     jr    stp5
  596. stp6:    ld    (lstsbt+poff),de
  597.     cp    '.'
  598.     jr    nz,stp1        ;loop for a new line
  599.     ret
  600. ;
  601. ;Move memory addr1,addr2,addr3
  602. move:    call    poff+prsadr
  603.     ex    de,hl        ;DE=start
  604.     call    c,poff+prsadr
  605.     push    hl        ;(SP)=end
  606.     call    c,poff+prsadr    ;HL=dest
  607.     jp    nc,monerr+poff    ;Skip if bad parameters
  608.     call    poff+hlcpde    ;Is dest>=start
  609.     ld    c,l
  610.     ld    b,h        ;BC=dest
  611.     pop    hl        ;HL=end
  612.     jr    nc,mv2        ;If dest>=start, do lddr
  613.     ccf
  614.     sbc    hl,de        ;HL=end-start
  615.     inc    hl
  616. mv1:    ld    a,(de)
  617.     ld    (bc),a
  618.     inc    de
  619.     inc    bc
  620.     dec    hl
  621.     ld    a,h
  622.     or    l
  623.     jr    nz,mv1
  624.     ret
  625. mv2:    push    hl        ;Stack end
  626.     sbc    hl,de        ;HL=end
  627.     ld    e,l
  628.     ld    d,h
  629.     add    hl,bc
  630.     ld    c,l
  631.     ld    b,h        ;BC=dest end
  632.     pop    hl        ;HL=end
  633.     inc    de
  634. mv3:    ld    a,(hl)
  635.     ld    (bc),a
  636.     dec    hl
  637.     dec    bc
  638.     dec    de
  639.     ld    a,d
  640.     or    e
  641.     jr    nz,mv3
  642.     ret
  643. ;
  644. ;Fill addr1,addr2[,num]
  645. fill:    call    poff+prsadr
  646.     ex    de,hl        ;DE=start
  647.     call    c,poff+prsadr
  648.     jp    nc,monerr+poff    ;Bad parameters
  649.     push    hl        ;End
  650.     ld    l,0
  651.     call    poff+prsnum    ;CY=0
  652.     ld    c,l        ;C=byte fill
  653.     pop    hl        ;HL=end
  654.     sbc    hl,de        ;HL=end-start
  655.     ex    de,hl        ;HL=start
  656.     inc    de        ;DE=count
  657. fl1:    ld    (hl),c
  658.     inc    hl
  659.     dec    de
  660.     ld    a,d
  661.     or    e
  662.     jr    nz,fl1
  663.     ret
  664. ;
  665. ;Out addr,num
  666. pout:    call    poff+prsnum
  667.     ld    c,l        ;C=port
  668.     call    c,poff+prsnum
  669.     jr    nc,perr
  670.     ld    b,l        ;B=val
  671.     out    (c),b
  672.     ret
  673. ;
  674. ;Inp addr[,num]
  675. pinp:    call    poff+prsnum
  676. perr:    jp    nc,monerr+poff
  677.     ld    c,l        ;C=port
  678.     ld    l,0
  679.     call    poff+prsnum
  680.     ld    b,l        ;B=val
  681.     in    b,(c)
  682.     ld    a,b
  683.     jp    poff+wra8
  684. ;
  685. ;Hex math num1[,num2]
  686. hmath:    call    poff+prsadr    ;get num1
  687.     jr    nc,perr        ;skip if no num1
  688.     ex    de,hl
  689.     call    poff+prsadr    ;get num2
  690.     jr    c,hmath1    ;skip if got num2
  691.     sbc    hl,hl        ;HL=0
  692.     ex    de,hl        ;HL=num1,DE=0
  693. hmath1:    push    hl
  694.     add    hl,de
  695.     call    poff+wrhl16    ;display num1+num2
  696.     call    poff+wr$pc
  697.     db    ','+80h
  698.     pop    hl
  699.     or    a
  700.     ex    de,hl
  701.     sbc    hl,de
  702.     jp    poff+wrhl16    ;display num1-num2
  703. ;
  704. ;Subroutines
  705. ;
  706. ;HL+=A
  707. addhla:    add    a,l
  708.     ld    l,a
  709.     ret    nc
  710.     inc    h
  711.     ret
  712. ;
  713. ;Compare HL,DE (flags=HL-DE)
  714. hlcpde:    push    hl
  715.     or    a
  716.     sbc    hl,de
  717.     pop    hl
  718.     ret
  719. ;
  720. ;Read a null terminated string into buffer
  721. rdbuff:    ld    hl,buff+poff
  722. ;
  723. ;Read a null terminated string into $HL0
  724. readln:    ld    (rptr+poff),hl    ;Store current position
  725.     ld    b,0        ;Char counter
  726. rl1:    call    poff+kbdst
  727.     jr    z,rl1        ;Wait for a char
  728.     cp    20h
  729.     jr    c,rl3        ;Skip if control code
  730.     cp    7Fh
  731.     jr    z,rl5        ;Skip if DEL
  732. ;
  733. ;Add char to string
  734.     ld    c,a
  735.     ld    a,b
  736.     cp    buflen
  737.     jr    nc,rl4        ;Skip if no more room
  738.     ld    a,c
  739.     ld    (hl),a
  740.     inc    hl
  741.     inc    b
  742. ;
  743. ;Echo char
  744. rl2:    call    poff+wr$a
  745.     jr    rl1        ;Another char
  746. ;
  747. ;Control codes
  748. rl3:    cp    08h
  749.     jr    z,rl5        ;Backspace
  750.     cp    18h
  751.     jr    z,rl6        ;Cancel
  752.     cp    03h
  753.     jp    z,brk+poff    ;CTRL-C
  754.     cp    0Ah
  755.     jr    z,rl9        ;Exit
  756.     cp    0Dh
  757.     jr    z,rl9        ;Exit
  758. ;
  759. ;Bad key, do a beep
  760. rl4:    ld    a,7
  761.     jr    rl2
  762. ;
  763. ;Backspace/Delete
  764. rl5:    inc    b
  765.     dec    b
  766.     jr    z,rl1
  767.     call    poff+bsb
  768.     dec    hl
  769.     dec    b
  770.     jr    rl1
  771. ;
  772. ;Cancel
  773. rl6:    inc    b
  774.     jr    rl8
  775. rl7:    call    poff+bsb
  776.     dec    hl
  777. rl8:    djnz    rl7
  778.     jr    rl1
  779. ;
  780. ;Carriage return
  781. rl9:    ld    (hl),0        ;Nul at end of string
  782. ;
  783. ;Write CRLF
  784. wrcrlf:    call    poff+wr$pc
  785.     db    13,10+80h
  786.     call    poff+kbdst
  787.     ret    z
  788.     cp    'S'-'@'
  789.     ret    nz
  790. wcl1:    call    poff+kbdst
  791.     jr    z,wcl1
  792.     cp    'C'-'@'
  793.     ret    nz
  794.     jp    brk+poff
  795. ;
  796. ;Backspace, space, backspace
  797. bsb:    call    poff+wr$pc
  798.     db    8,20h,8+80h
  799.     ret
  800. ;
  801. ;Get char into A, Z if end of line
  802. getch:    push    hl
  803. rptr    equ    $+1
  804.     ld    hl,buff+poff
  805.     ld    a,(hl)
  806.     or    a
  807.     jr    z,gchxt        ;Can't read beyond end
  808.     inc    hl
  809.     ld    (rptr+poff),hl
  810. gchxt:    pop    hl
  811.     ret
  812. ;
  813. ;Get a char, test if in punc
  814. gcpunc:    call    poff+getch
  815. ;
  816. ;Test if A in punc, Z if yes, NZ if no
  817. punc:    or    a        ;End of line?
  818.     ret    z
  819.     cp    20h        ;Space
  820.     ret    z
  821.     cp    '.'        ;Dot
  822.     ret    z
  823.     cp    ','        ;Comma
  824.     ret
  825. ;
  826. ;To upper function
  827. toupper:cp    'a'
  828.     ret    c
  829.     cp    'z'+1
  830.     ret    nc
  831.     sub    a,'a'-'A'
  832.     ret
  833. ;
  834. ;Parse address into HL, destroys A,BC, preserves DE
  835. ;Return NC if no number
  836. ;Return CY and HL=number
  837. ;Return CY if . (dot), HL=PC
  838. ;Handles . (dot) modifiers
  839. ;.R for relative address
  840. ;.A for absolute address
  841. ;error if bad parse
  842. prsadr:    call    poff+prsnum
  843.     ret    c        ;return if a number was available
  844.     cp    '.'        ;is a PC spec used?
  845.     scf
  846.     ccf            ;CY=0
  847.     ret    nz        ;return if no number here
  848. prsad1:    ld    hl,(xpc+poff)    ;HL=PC
  849. prsad2:    call    poff+gcpunc    ;loop for a punctuation
  850.     jr    z,prsad4    ;skip if delimiter
  851.     call    poff+toupper
  852.     cp    'A'        ;absolute spec?
  853.     jr    z,prsad5
  854.     sub    'R'        ;relative spec? A=0,Z if yes
  855.     jr    nz,prsad2    ;skip if not .R
  856. ;
  857.     inc    hl        ;HL=PC+1
  858.     ld    c,(hl)
  859.     inc    hl
  860.     ld    b,a
  861.     bit    7,c
  862.     jr    z,prsad3
  863.     dec    b
  864. prsad3:    add    hl,bc        ;HL=relative jump target
  865.     jr    prsad2
  866. ;
  867. prsad5:    inc    hl
  868.     ld    a,(hl)
  869.     inc    hl
  870.     ld    h,(hl)
  871.     ld    l,a        ;HL=absolute jump target
  872.     jr    prsad2
  873. ;
  874. prsad4:    cp    '.'
  875.     jr    z,prsad1
  876.     scf
  877.     ret            ;return CY
  878. ;
  879. ;Parse number into HL, destroys A,BC, preserves DE
  880. ;Return NC if no number, HL=number, error if bad parse
  881. prsnum:    call    poff+gcpunc
  882.     ret    z        ;Return if NC,Z if no number
  883. p160:    ld    hl,0000h    ;Init accumulator
  884. p161:    call    poff+toupper
  885.     sub    a,'0'
  886.     jr    c,p16err    ;Skip if not a number
  887.     cp    9+1
  888.     jr    c,p162
  889.     sub    a,7
  890.     cp    9+1
  891.     jr    c,p16err
  892.     cp    15+1
  893.     jr    nc,p16err
  894. p162:    add    hl,hl
  895.     add    hl,hl
  896.     add    hl,hl
  897.     add    hl,hl        ;HL*=16
  898.     add    a,l
  899.     ld    l,a        ;HL+=A
  900.     call    poff+gcpunc
  901.     jr    nz,p161
  902.     scf            ;cause CY
  903.     ret
  904. p16err:    jp    monerr+poff
  905. ;
  906. ;Write space, then $PC
  907. wrsppc:    call    poff+wr$spc
  908. ;
  909. ;Write $PC
  910. wr$pc:    ex    (sp),hl
  911. wr$pc1    ld    a,(hl)
  912.     and    7Fh
  913.     call    nz,poff+wr$a
  914.     ld    a,(hl)
  915.     inc    hl
  916.     add    a,a
  917.     jr    c,wr$pc2
  918.     jr    nz,wr$pc1
  919. wr$pc2:    ex    (sp),hl
  920.     ret
  921. ;
  922. ;Write a space
  923. wr$spc:    call    poff+wr$pc
  924.     db    ' '+80h
  925.     ret
  926. ;
  927. ;Display register contents from table at HL
  928. dspr:    call    poff+wr$spc    ;write space
  929.     ld    a,(hl)
  930.     inc    hl
  931.     call    poff+wr$a    ;write register name
  932.     call    poff+wr$pc
  933.     db    '='+80h        ;write = sign
  934.     ld    e,(hl)
  935.     inc    hl
  936.     ld    d,(hl)        ;DE=address of register contents
  937.     inc    hl
  938.     push    hl
  939.     ex    de,hl
  940.     ld    a,(hl)
  941.     inc    hl
  942.     ld    h,(hl)        ;HL=register contents
  943.     ld    l,a
  944.     call    poff+wrhl16    ;display register contents
  945.     pop    hl
  946.     ret
  947. ;
  948. ;Write DE hex 16
  949. wrde16:    ex    de,hl
  950. ;
  951. ;Write HL hex 16
  952. wrhl16:    ld    a,h
  953.     call    poff+wra8
  954.     ld    a,l
  955. ;
  956. ;Write A hex 8
  957. wra8:    push    af
  958.     rrca
  959.     rrca
  960.     rrca
  961.     rrca
  962.     call    poff+wra4
  963.     pop    af
  964. ;
  965. ;Write A hex 4
  966. wra4:    and    0Fh
  967.     cp    9+1
  968.     jr    c,wa41
  969.     add    a,7
  970. wa41:    add    a,'0'
  971. ;
  972. ;Fall into wr$a
  973. ;
  974. ;Provide subroutine wr$a
  975. ;write char [A] on VDU preserving all registers
  976. ;
  977. *include jvdu.z80
  978. ;
  979. ;Switch PC using case toupper(A) from table at DE, default=last entry
  980. vswpc:    call    poff+toupper
  981. vswpc1:    ex    de,hl
  982. vswpc2:    bit    7,(hl)
  983.     jr    nz,vswpc3
  984.     cp    (hl)
  985.     inc    hl
  986.     jr    z,vswpc4
  987.     inc    hl
  988.     inc    hl
  989.     jr    vswpc2
  990. vswpc3:    inc    hl
  991. vswpc4:    ld    a,(hl)
  992.     inc    hl
  993.     ld    h,(hl)
  994.     ld    l,a
  995.     ex    de,hl
  996.     push    de
  997.     ret
  998. ;
  999. ;Provide subroutine kbdst
  1000. ;
  1001. ;Returns A=ASCII key,NZ else A=0,Z if no key
  1002. ;Preserves all other registers
  1003. *include jkbdst.z80
  1004. ;
  1005. ;Command table
  1006. cmdtbl:
  1007.     db    'B'
  1008.     dw    poff+setbpt
  1009.     db    'C'
  1010.     dw    poff+clrbpt
  1011.     db    'D'
  1012.     dw    poff+dump
  1013.     db    'F'
  1014.     dw    poff+fill
  1015.     db    'G'
  1016.     dw    poff+go
  1017.     db    'H'
  1018.     dw    poff+hmath
  1019.     db    'I'
  1020.     dw    poff+pinp
  1021.     db    'M'
  1022.     dw    poff+move
  1023.     db    'O'
  1024.     dw    poff+pout
  1025.     db    'Q'
  1026.     dw    poff+quit
  1027.     db    'R'
  1028.     dw    poff+reg
  1029.     db    'S'
  1030.     dw    poff+subst
  1031.     db    'Z'
  1032.     dw    poff+pag
  1033.     db    80h
  1034.     dw    poff+monerr
  1035. ;
  1036. flnam:    db    'SZ?H?PNC'
  1037. ;
  1038. ;Table of register names and addresses
  1039. regtbl:    db    'B'
  1040.     dw    poff+xbc
  1041.     db    'D'
  1042.     dw    poff+xde
  1043.     db    'H'
  1044.     dw    poff+xhl
  1045.     db    'X'
  1046.     dw    poff+xix
  1047.     db    'Y'
  1048.     dw    poff+xiy
  1049.     db    'S'
  1050.     dw    poff+xsp
  1051.     db    'P'
  1052.     dw    poff+xpc
  1053.     db    80h
  1054. ;
  1055. nbrk:    db    0        ;number of breakpoints
  1056. ;
  1057. ;Boot up monitor program
  1058. boot:    ld    sp,stk+poff
  1059.     call    poff+wr$pc
  1060.     db    1Ah,'JMON v1.00 by J.Loke 88Jan22',13,10+80h
  1061.     ld    hl,warm+poff
  1062.     ld    (jmon+1+poff),hl
  1063.     jp    (hl)
  1064. pattop    equ    $
  1065.     if    $+poff >= 0000h
  1066.     dl    $+poff *** Image overflow ***
  1067.     endif
  1068. ;
  1069.     org    boot
  1070.     ds    4*maxbrk    ;storage for breakpoints (grows down)
  1071.                 ;contents,hi addr,lo addr,page
  1072. xrst:    ds    3*3        ;storage for bytes overwritten by RST
  1073. buff:    ds    buflen        ;buffer for commands
  1074.     ds    stklvl*2
  1075. stk    equ    $
  1076. ;
  1077.     if    $+poff >= 0000h
  1078.     dl    $+poff *** Page overflow ***
  1079.     endif
  1080. ;
  1081.     end
  1082.