home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol167 / vb1.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  14.9 KB  |  1,030 lines

  1.  
  2. ;    -------------------------------------------------------
  3. ;    Adaptation of VTI to use Solid State Music video board 
  4. ;    model VB1-B with CP/M I-O routines on UAP's IMSAI 8080.
  5. ;        [Version October 27,1978]
  6. ;
  7. ;        VB1-B  -  Copyright (C) 1978
  8. ;        Universidad Autonoma de Puebla
  9. ;
  10. ;    written by Harold V. McIntosh, summer 1978, with
  11. ;    reference to: Harvey A. Cohen, "The Oznaki LIFE",
  12. ;    Dr. Dobbs Journal of Computer Calisthenics and
  13. ;    Orthodontia, volume 3, issue 4 (April 1978) pp. 10-11;
  14. ;    and with acknowledgements to the hospitality of the
  15. ;    Quantum Theory Project, University of Florida,
  16. ;    Gainesville, Florida.
  17. ;    ------------------------------------------------------
  18.  
  19.     org    0100H
  20.  
  21.     jmp main    ;create entry point for demonstration
  22.  
  23. ;    -------------------------------------------------------
  24. ;    Constants defining screen size and location.  Note that
  25. ;    while the programmer has some discretion in assigning
  26. ;    these constants, there is highly implicit usage of the
  27. ;    assumption that the screen memory begins at a 1K Hex
  28. ;    boundary, and that the row length is a power of 2.
  29. ;    Thus the video board origin may be changed through its
  30. ;    address switches, and new parameters defined without
  31. ;    difficulty; nevertheless adaptation to an 80-column 
  32. ;    board would require restructuring the subroutines.
  33. ;    -------------------------------------------------------
  34.  
  35. vorg:    equ    0F800H    ;origin of video screen memory area
  36. vsiz:    equ    00400H    ;size of video screen memory area
  37. rsiz    equ    00040H    ;length of a single display line
  38. rmsk:    equ    rsiz-1    ;mask for single row addresses
  39.  
  40. ;    -------------------------------------------------------
  41. ;    Data storage locations required by the subroutines.
  42. ;    -------------------------------------------------------
  43.  
  44. ma:    equ    00CC9H    ;bit mask to locate pixel within byte
  45. wy:    equ    00CCAH    ;row count * 16  -  16 rows total
  46. ex:    equ    00CCBH    ;column count * 4  -  64 columns total
  47. ts:    equ    00CCCH    ;temporary storage
  48.  
  49. ;    -----------------------------------------------------
  50. ;    Entry vector designed to systematize communication with
  51. ;    calling programs written in BASIC or other external
  52. ;    languages. These entry points will persist even though
  53. ;    the subroutines are revised, corrected, or otherwise
  54. ;    modified. A further advantage is that the same
  55. ;    arrangement can be used by the drivers for different
  56. ;    video boards, allowing program interchangability.
  57. ;    --------------------------------------------------------
  58.  
  59. vb1:    jmp    home    ;place cursor at screen center
  60.     jmp    culi    ;illuminate the cursor
  61.     jmp    cuex    ;extinguish the cursor
  62.     jmp     cure    ;reverse the cursor
  63.     jmp    cuse    ;sense the cursor (use jz afterward)
  64.     jmp    xpl    ;move cursor right one pixel
  65.     jmp    xmi    ;move cursor left one pixel
  66.     jmp    ypl    ;move cursor up one pixel
  67.     jmp    ymi    ;move cursor down one pixel
  68.     jmp    blak    ;make the whole screen black
  69.     jmp    whit    ;make the whole screen white
  70.     jmp    reve    ;reverse the whole screen
  71.     jmp    cart    ;form (ma, wy, ex) from (D,E)
  72.     jmp    line    ;line segment with increments (dx,dy)
  73.     jmp    ekspl    ;rotate whole screen right
  74.     jmp    eksmi    ;rotate whole screen left
  75.     jmp    wyepl    ;rotate whole screen up
  76.     jmp    wyemi    ;rotate whole screen down
  77.     jmp    ee    ;move cursor east one cell
  78.     jmp    ww    ;move cursor west one cell
  79.     jmp    nn    ;move cursor north one cell
  80.     jmp    ss    ;move cursor south one cell
  81.     jmp    kk    ;deactivate cell under cursor
  82.     jmp    ll    ;activate cell under cursor
  83.     jmp    hh    ;advance through one cycle of LIFE
  84.     jmp    eas    ;rotate screen and cursor one cell east
  85.     jmp    wes    ;rotate screen and cursor one cell west
  86.     jmp    nor    ;rotate screen and cursor one cell north
  87.     jmp    sou    ;rotate screen and cursor one cell south
  88.     jmp    doli    ;illumate a two-pixel dot
  89.     jmp    doex    ;extinguish a two-pixel dot
  90.     jmp    xppl    ;move cursor one byte right
  91.     jmp    xmmi    ;move cursor one byte left
  92.     jmp    eksppl    ;rotate whole screen one byte right
  93.     jmp    eksmmi    ;rotate whole screen one byte left
  94.  
  95. ;    =======================================================
  96.  
  97. ;    move cursor up one pixel
  98.  
  99. ypl:    lxi h,ma
  100.     mov a,m
  101.     ani 009H
  102.     jnz yp1
  103.     mov a,m
  104.     rrc
  105.     mov m,a
  106.     ret
  107. yp1:    rlc
  108.     rlc
  109.     mov m,a
  110.     lda wy
  111.     sui 010H
  112.     sta wy
  113.     ret
  114.  
  115. ;    move cursor down one pixel
  116.  
  117. ymi:    lxi h,ma
  118.     mov a,m
  119.     ani 024H
  120.     jnz ym1
  121.     mov a,m
  122.     rlc
  123.     mov m,a
  124.     ret
  125. ym1:    rrc
  126.     rrc
  127.     mov m,a
  128.     lda wy
  129.     adi 010H
  130.     sta wy
  131.     ret
  132.  
  133. ;    move cursor right one pixel
  134.  
  135. xpl:    lxi h,ma
  136.     mov a,m
  137.     ani 038H
  138.     jnz xp1
  139.     mov a,m
  140.     rlc
  141.     rlc
  142.     rlc
  143.     mov m,a
  144.     ret
  145. xp1:    rrc
  146.     rrc
  147.     rrc
  148.     mov m,a
  149.     lda ex
  150.     adi 004H
  151.     sta ex
  152.     ret
  153.  
  154. ;    move cursor left one pixel
  155.  
  156. xmi:    lxi h,ma
  157.     mov a,m
  158.     ani 007H
  159.     jnz xm1
  160.     mov a,m
  161.     rrc
  162.     rrc
  163.     rrc
  164.     mov m,a
  165.     ret
  166. xm1:    rlc
  167.     rlc
  168.     rlc
  169.     mov m,a
  170.     lda ex
  171.     sui 004H
  172.     sta ex
  173.     ret
  174.  
  175. ;    fast movement of cursor right two pixels
  176.  
  177. xppl:    lda ex
  178.     adi 004H
  179.     sta ex
  180.     ret
  181.  
  182. ;    fast movement of cursor left two pixels
  183.  
  184. xmmi:    lda ex
  185.     sui 004H
  186.     sta ex
  187.     ret
  188.  
  189. ;    load A with the bit mask, HL with a byte address
  190. ;    given the cursor positioning data at (ma,wy,ex)
  191.  
  192. dot:    lhld wy
  193.     mov a,h
  194.     mvi h,vorg/0400H
  195.     dad h
  196.     dad h
  197.     rrc
  198.     rrc
  199.     ora l
  200.     mov l,a
  201.     lda ma
  202.     ret
  203.  
  204. ;    initialize cursor parameters
  205.  
  206. home:    lxi h,8080H
  207.     shld wy
  208.     mvi a,001H
  209.     sta ma
  210.     ret
  211.  
  212. ;    extinguish the cursor
  213.  
  214. cuex:    call dot
  215.     ora m
  216.     mov m,a
  217.     ret
  218.  
  219. ;    light the cursor
  220.  
  221. culi:    call dot
  222.     cma
  223.     ana m
  224.     mov m,a
  225.     ret
  226.  
  227. ;    reverse the cursor
  228.  
  229. cure:    call dot
  230.     xra m
  231.     mov m,a
  232.     ret
  233.  
  234. ;    sense the cursor
  235.  
  236. cuse:    call dot
  237.     ana m
  238.     ani 03FH
  239.     ret
  240.  
  241. ;    clear the whole screen to black
  242.  
  243. blak:    lxi d,vsiz
  244.     lxi h,vorg
  245. bl1:    mvi m,0FFH
  246.     inx h
  247.     dcr e
  248.     jnz bl1
  249.     dcr d
  250.     jnz bl1
  251.     ret
  252.  
  253. ;    clear the whole screen to white
  254.  
  255. whit:    lxi d,vsiz
  256.     lxi h,vorg
  257. whi:    mvi m,080H
  258.     inx h
  259.     dcr e
  260.     jnz whi
  261.     dcr d
  262.     jnz whi
  263.     ret
  264.  
  265. ;    reverse the whole screen
  266.  
  267. reve:    lxi d,vsiz
  268.     lxi h,vorg
  269. rev1:    mov a,m
  270.     xri 03FH
  271.     mov m,a
  272.     inx h
  273.     dcr e
  274.     jnz rev1
  275.     dcr d
  276.     jnz rev1
  277.     ret
  278.  
  279. ;    transform cartesian coordinates in the form of x,y
  280. ;    transmitted through registers (D,E) to a mask and
  281. ;    byte address.
  282.  
  283. cart:    mvi b,018H
  284.     mvi c,004H
  285.     mov a,e
  286.     cma
  287.     adi 031H
  288. car1:    cmp b
  289.     jc car2
  290.     sub b
  291. car2:    cmc
  292.     adc a
  293.     dcr c
  294.     jnz car1
  295.     mov c,a
  296.     ani 00FH
  297.     rlc
  298.     rlc
  299.     rlc
  300.     rlc
  301.     sta wy
  302.     mov a,c
  303.     ani 0F0H
  304.     jnz car3
  305.     mvi a,008H
  306. car3:    mov c,a
  307.     mov a,d
  308.     dcr a
  309.     mov b,a
  310.     rlc
  311.     ani 0FCH
  312.     sta ex
  313.     mov a,b
  314.     ani 001H
  315.     mov a,c
  316.     jnz car4
  317.     rrc
  318.     rrc
  319.     rrc
  320. car4:    sta ma
  321.     ret
  322.  
  323. ;    draw a line with increments dx,dy = (D,E).  Increment
  324. ;    may be + or - using complementary arithmetic, but ought
  325. ;    to be less than 64 in absolute value to avoid overflow
  326. ;    problems.
  327.  
  328. line:    lxi h,ypl
  329.     mov a,e
  330.     ora a
  331.     jp lin1
  332.     cma
  333.     inr a
  334.     mov e,a
  335.     lxi h,ymi
  336. lin1:    lxi b,xppl
  337.     mov a,d
  338.     ora a
  339.     jp lin2
  340.     cma
  341.     inr a
  342.     mov d,a
  343.     lxi b,xmmi
  344. lin2:    cmp e
  345.     jnc lin3
  346.     push h
  347.     push b
  348.     pop h
  349.     pop b
  350.     mov d,e
  351.     mov e,a
  352. lin3:    mov a,d
  353.     sta ts
  354.     mov a,e
  355.     add a
  356.     mov e,a
  357.     sub d
  358.     push psw
  359.     sub d
  360.     mov d,a
  361. lin4:    pop psw
  362.     push h
  363.     lxi h,doli
  364.     xthl
  365.     cpi 001H
  366.     jm lin5
  367.     push h
  368.     add d
  369.     jmp lin6
  370. lin5:    add e
  371. lin6:    push b
  372.     push psw
  373.     lda ts
  374.     dcr a
  375.     sta ts
  376.     jnz lin4
  377.     pop psw
  378.     ret
  379.  
  380. ;    the movements in one byte necessary to shift the
  381. ;    whole screen right one pixel.
  382.  
  383. expl:    mov a,m
  384.     ani 03FH
  385.     mov b,a
  386.     ani 007H
  387.     rlc
  388.     rlc
  389.     rlc
  390.     ora c
  391.     mov c,a
  392.     mov a,b
  393.     rrc
  394.     rrc
  395.     rrc
  396.     ani 007H
  397.     mov b,c
  398.     mov c,a
  399.     ret
  400.  
  401. ;    the movements within one byte necessary for shifting
  402. ;    the whole screen left one pixel.
  403.  
  404. exmi:    mov a,m
  405.     ani 03FH
  406.     mov b,a
  407.     rrc
  408.     rrc
  409.     rrc
  410.     ani 007H
  411.     ora c
  412.     mov c,a
  413.     mov a,b
  414.     ani 007H
  415.     rlc
  416.     rlc
  417.     rlc
  418.     mov b,c
  419.     mov c,a
  420.     ret
  421.  
  422. ;    the movements necessary within one byte to shift the
  423. ;    whole screen down one pixel.
  424.  
  425. wymi:    mov a,m
  426.     ani 03FH
  427.     mov b,a
  428.     ani 01BH
  429.     rlc
  430.     ora c
  431.     mov c,a
  432.     mov a,b
  433.     rrc
  434.     rrc
  435.     ani 009H
  436.     mov b,c
  437.     mov c,a
  438.     ret
  439.  
  440. ;    the movements necessary within one byte to shift the
  441. ;    whole screen up one pixel.
  442.  
  443. wypl:    mov a,m
  444.     ani 03FH
  445.     mov b,a
  446.     rrc
  447.     ani 01BH
  448.     ora c
  449.     mov c,a
  450.     mov a,b
  451.     ani 009H
  452.     rlc
  453.     rlc
  454.     mov b,c
  455.     mov c,a
  456.     ret
  457.  
  458. ;    rotate the whole screen right one pixel
  459.  
  460. ekspl:    lxi h,vorg
  461.     lxi d,rsiz-1
  462. eksp1:    push h
  463.     dad d
  464.     call expl
  465.     pop h
  466. eksp2:    call expl
  467.     mov a,b
  468.     ori 080H
  469.     mov m,a
  470.     inx h
  471.     mov a,l
  472.     ani rmsk
  473.     jnz eksp2
  474.     mov a,h
  475.     cpi (vorg+vsiz)/0100H
  476.     jnz eksp1
  477.     ret
  478.  
  479. ;    rotate the whole screen left one pixel
  480.  
  481. eksmi:    lxi h,vorg+vsiz-1
  482.     lxi d,-rsiz+1
  483. eksm1:    push h
  484.     dad d
  485.     call exmi
  486.     pop h
  487. eksm2:    call exmi
  488.     mov a,b
  489.     ori 080H
  490.     mov m,a
  491.     mov a,l
  492.     ani rmsk
  493.     dcx h
  494.     jnz eksm2
  495.     mov a,h
  496.     cpi (vorg/0100H)-1
  497.     jnz eksm1
  498.     ret
  499.  
  500. ;    rotate the whole screen up one pixel.
  501.  
  502. wyepl:    lxi h,vorg+vsiz-1
  503. wyep1:    lxi d,-vsiz+rsiz
  504.     push h
  505.     dad d
  506.     call wypl
  507.     pop h
  508.     push h
  509.     lxi d,-rsiz
  510. wyep2:    call wypl
  511.     mov a,b
  512.     ori 080H
  513.     mov m,a
  514.     dad d
  515.     mov a,h
  516.     cpi (vorg/0100H)-1
  517.     jnz wyep2
  518.     pop h
  519.     mov a,l
  520.     ani rmsk
  521.     dcx h
  522.     jnz wyep1
  523.     ret
  524.  
  525. ;    rotate the whole screen down one pixel
  526.  
  527. wyemi:    lxi h,vorg
  528. wyem1:    lxi d,vsiz-rsiz
  529.     push h
  530.     dad d
  531.     call wymi
  532.     pop h
  533.     push h
  534.     lxi d,rsiz
  535. wyem2:    call wymi
  536.     mov a,b
  537.     ori 080H
  538.     mov m,a
  539.     dad d
  540.     mov a,h
  541.     cpi (vorg+vsiz)/0100H
  542.     jnz wyem2
  543.     pop h
  544.     inx h
  545.     mov a,l
  546.     ani rmsk
  547.     jnz wyem1
  548.     ret
  549.  
  550. ;    fast right rotation by two pixels = one byte
  551.  
  552. eksppl:    lxi h,vorg
  553.     lxi d,rsiz-1
  554. ekspp1:    push h
  555.     dad d
  556.     mov c,m
  557.     pop h
  558. ekspp2:    mov b,m
  559.     mov m,c
  560.     mov c,b
  561.     inx h
  562.     mov a,l
  563.     ani rmsk
  564.     jnz ekspp2
  565.     mov a,h
  566.     cpi (vorg+vsiz)/0100H
  567.     jnz ekspp1
  568.     ret
  569.  
  570. ;    fast left rotate by two pixels = one byte
  571.  
  572. eksmmi:    lxi h,vorg+vsiz-1
  573.     lxi d,-rsiz+1
  574. eksmm1:    push h
  575.     dad d
  576.     mov c,m
  577.     pop h
  578. eksmm2:    mov b,m
  579.     mov m,c
  580.     mov c,b
  581.     mov a,l
  582.     ani rmsk
  583.     dcx h
  584.     jnz eksmm2
  585.     mov a,h
  586.     cpi (vorg/0100H)-1
  587.     jnz eksmm1
  588.     ret
  589.  
  590. ;    Add to the neighbor count of adjoining cells according
  591. ;    to the bits in this byte.  We do the middle pixel,
  592. ;    adding to the count of three successive neighbors in
  593. ;    registers B,C,D.
  594.  
  595. alfa:    mov a,m
  596.     rlc
  597.     rlc
  598.     rlc
  599.     jc alf1
  600.     inr b
  601.     inr c
  602.     inr d
  603. alf1:    rlc
  604.     jc alf2
  605.     inr b
  606.     inr d
  607. alf2:    rlc
  608.     rc
  609.     inr b
  610.     inr c
  611.     inr d
  612.     ret
  613.  
  614. ;    shift the neighbor count as we move forward one byte in
  615. ;    a row scan
  616.  
  617. beta:    mov b,c
  618.     mov c,d
  619.     mvi d,00H
  620.     inx h
  621.     mov a,l
  622.     ani 03FH
  623.     rnz
  624.     push d
  625.     lxi d,-rsiz
  626.     dad d
  627.     pop d
  628.     ret
  629.  
  630. ;    PRINCIPAL PROGRAM for carrying out a cycle of LIFE.
  631. ;    Only the middle pixel in each byte is calculated
  632. ;    so that three passes are necessary after each of three
  633. ;    shifts. Two adjacent pixels are used, the right to hold
  634. ;    the present living status and the left for information
  635. ;    for the next cycle.
  636.  
  637. epsi:    lxi h,vorg+rsiz-1
  638. gama:    mvi d,00H
  639.     call alfa
  640.     call beta
  641.     call alfa
  642. delt:    push h
  643.     call beta
  644.     call alfa
  645.     xthl
  646.     mov a,b
  647.     cpi 002H
  648.     jz eta
  649.     cpi 003H
  650.     jz zeta
  651.     mov a,m
  652.     ori 002H
  653.     mov m,a
  654.     jmp thet
  655. zeta:    mov a,m
  656.     ani 0FDH
  657.     mov m,a
  658.     jmp thet
  659. eta:    mov a,m
  660.     ani 0FDH
  661.     mov e,a
  662.     ani 010H
  663.     rrc
  664.     rrc
  665.     rrc
  666.     ora e
  667.     mov m,a
  668. thet:    pop h
  669.     mov a,l
  670.     ani rmsk
  671.     jnz delt
  672.     push d
  673.     lxi d,2*rsiz-1
  674.     dad d
  675.     pop d
  676.     mov a,h
  677.     cpi (vorg+vsiz)/0100H
  678.     jnz gama
  679.     ret
  680.  
  681. ;    updating loop, moving left pixel to right
  682.  
  683. cycl:    lxi h,vorg
  684. cyc1:    mov a,m
  685.     ani 007H
  686.     mov b,a
  687.     rlc
  688.     rlc
  689.     rlc
  690.     ora b
  691.     ori 080H
  692.     mov m,a
  693.     inx h
  694.     mov a,h
  695.     cpi (vorg+vsiz)/0100H
  696.     jnz cyc1
  697.     ret
  698.  
  699. ;    execute a single cycle of LIFE by updating the middle
  700. ;    pixel and making three sweeps while shifting each time
  701.  
  702. hh:    call epsi
  703.     call wyepl
  704.     call epsi
  705.     call wyepl
  706.     call epsi
  707.     call wyemi
  708.     call wyemi
  709.     jmp cycl
  710.  
  711. ;    extinguish cursor, move two pixels east, light cursor
  712.  
  713. ee:    call cure
  714.     call xppl
  715.     jmp  cure
  716.  
  717. ;    extinguish cursor, two pixels west, light cursor
  718.  
  719. ww:    call cure
  720.     call xmmi
  721.     jmp  cure
  722.  
  723. ;    extinguish cursor, one pixel north, light cursor
  724.  
  725. nn:    call cure
  726.     call ypl
  727.     jmp  cure
  728.  
  729. ;    extinguish cursor, one pixel south, light cursor
  730.  
  731. ss:    call cure
  732.     call ymi
  733.     jmp  cure
  734.  
  735. ;    extinguish a life cell
  736.  
  737. kk:    call xpl
  738.     call cuex
  739.     jmp xmi
  740.  
  741. ;    activate a life cell
  742.  
  743. ll:    call xpl
  744.     call culi
  745.     jmp  xmi
  746.  
  747. ;    move whole screen right one life cell, with cursor
  748.  
  749. eas:    call eksppl
  750.     jmp xppl
  751.  
  752. ;    move the whole screen left one life cell, with cursor
  753.  
  754. wes:    call eksmmi
  755.     jmp  xmmi
  756.  
  757. ;    move the whole screen up one life cell, with cursor
  758.  
  759. nor:    call wyepl
  760.     jmp  ypl
  761.  
  762. ;    move the whole screen down one life cell, with cursor
  763.  
  764. sou:    call wyemi
  765.     jmp  ymi
  766.  
  767. ;    light a two-pixel dot
  768.  
  769. doli:    call culi
  770.     call xpl
  771.     call culi
  772.     jmp xmi
  773.  
  774. ;    extinguish a two-pixel dot
  775.  
  776. doex:    call cuex
  777.     call xpl
  778.     call cuex
  779.     jmp xmi
  780.  
  781. ;    =======================================================
  782. ;    driver subroutines for diverse demonstrations
  783. ;    =======================================================
  784.  
  785. bdos:    equ    0005H    ;entry point for CP/M service routines
  786. morg:    equ    4000H    ;area for defining macros
  787.  
  788. ;    build up one-byte decimal number from digit string
  789. ;    null string =1, minus creates negative modulo 256
  790. ;    to correct an error type four zeroes and start over
  791. ;    decm: places number in D, terminal character in A
  792. ;    coop: places number in D, terminal character in E
  793.  
  794. coop:    call decm
  795.     mov e,a
  796.     ret
  797. decm:    mvi d,01H
  798.     call read
  799.     cpi '-'
  800.     jnz dec1
  801.     lxi h,dec3
  802.     push h
  803.     call read
  804. dec1:    cpi '0'
  805.     rc
  806.     cpi '9'+1
  807.     rnc
  808.     mvi d,00H
  809. dec2:    cpi '0'
  810.     rc
  811.     cpi '9'+1
  812.     rnc
  813.     sui '0'
  814.     mov e,a
  815.     mov a,d
  816.     rlc
  817.     rlc
  818.     add d
  819.     rlc
  820.     add e
  821.     mov d,a
  822.     call read
  823.     jmp dec2
  824. dec3:    push sp
  825.     mov a,d
  826.     cma
  827.     inr a
  828.     mov d,a
  829.     pop sp
  830.     ret
  831.  
  832. ;    get (D,E) = (X,Y); for example a pair of coordinates
  833. ;    first read d=x, then e=y
  834.  
  835. pair:    call decm
  836.     push d
  837.     call decm
  838.     pop sp
  839.     mov e,d
  840.     mov d,a
  841.     ret
  842.  
  843. ;    place a dot with coordinates x,y on the screen
  844.  
  845. pp:    call pair
  846.     call cart
  847.     jmp culi
  848.  
  849. ;    draw a line with increments (dx,dy)
  850.  
  851. ii:    call pair
  852.     jmp line
  853.  
  854. ;    repeat the subroutine in (H,L) for the number of times
  855. ;    in D.
  856.  
  857. rept:    mov a,e
  858.     push h
  859.     push d
  860.     lxi b,repi
  861.     push b
  862.     pchl
  863. repi:    pop d
  864.     pop h
  865.     dcr d
  866.     rz
  867.     jmp rept
  868.  
  869. ;    turn one ASCII digit into a macro location
  870. ;    address is returned in (H,L)
  871.  
  872. mloc:    lxi h,0005H
  873.     dad sp
  874.     mov e,m
  875.     mvi d,00H
  876.     mvi m,01H
  877.     lxi b,morg
  878.     xchg
  879.     dad h
  880.     dad h
  881.     dad h
  882.     dad h
  883.     dad h
  884.     dad b
  885.     ret
  886.  
  887. ;    record a macro definition
  888.  
  889. mdef:    call mloc
  890. mde1:    call coop
  891.     mov m,d
  892.     inx h
  893.     mov m,e
  894.     inx h
  895.     mvi a,01BH
  896.     cmp e
  897.     rz
  898.     push h
  899.     lxi h,vect
  900.     call rept
  901.     pop h
  902.     jmp mde1
  903.  
  904. ;    execute a defined macro
  905.  
  906. mxec:    call mloc
  907.     push h
  908. mxe1:    pop h
  909.     mov d,m
  910.     inx h
  911.     mov a,m
  912.     inx h
  913.     cpi 01BH
  914.     rz
  915.     cpi ')'
  916.     jz rpar
  917.     cpi '('
  918.     jz lpar
  919.     mov e,a
  920.     push h
  921.     lxi h,vect
  922.     call rept
  923.     jmp mxe1
  924. rpar:    pop psw
  925.     dcr a
  926.     jz  rpa1
  927.     pop h
  928.     push h
  929.     push psw
  930.     push h
  931.     jmp mxe1
  932. rpa1:    xthl
  933.     jmp mxe1
  934. lpar:    push h
  935.     mov a,d
  936.     push psw
  937.     push h
  938.     jmp mxe1
  939.  
  940. ;    directory vector for LIFE demonstration
  941.  
  942. vect:    cpi 'N'        ;rotate screen north
  943.     jz  nor
  944.     cpi 'S'        ;rotate screen south
  945.     jz  sou
  946.     cpi 'E'        ;rotate screen east
  947.         jz  eas
  948.     cpi 'W'        ;rotate screen west
  949.     jz  wes
  950.     cpi 06EH    ;'n' - move cursor north
  951.     jz  nn
  952.     cpi 073H    ;'s' - move cursor south
  953.     jz  ss
  954.     cpi 065H    ;'e' - move cursor east
  955.     jz  ee
  956.     cpi 077H    ;'w' - move cursor west
  957.     jz  ww
  958.     cpi 06BH    ;'k' - deactivate cell
  959.     jz  kk
  960.     cpi 06CH    ;'l' - activate cell under cursor
  961.     jz  ll
  962.     cpi 'C'        ;clear screen to black
  963.     jz  blak
  964.     cpi 'R'        ;reverse the screen
  965.     jz  reve
  966.     cpi 068H    ;'h' - advance one cycle of LIFE
  967.     jz  hh
  968.     cpi 067H    ;'g' - repeat cycles of LIFE
  969.     jz  gg
  970.     cpi '.'        ;reverse cursor illumination
  971.     jz  cure
  972.     cpi '!'
  973.     jz mdef
  974.     cpi '?'
  975.     jz mxec
  976.     cpi 069H
  977.     jz  ii
  978.     cpi 070H
  979.     jz  pp
  980.     cpi ';'        ;exit to monitor
  981.     jz  0000H
  982. vend:    ret
  983.  
  984. ;    call hh repeatedly unless keyboard input is waiting
  985.  
  986. gg:    call stat
  987.     rnz
  988.     call hh
  989.     jmp gg
  990.  
  991. ;    read program using invariant CP/M calls
  992.  
  993. read:    push h
  994.     push d
  995.     push b
  996.     mvi c,01H
  997.     call bdos
  998.     pop b
  999.     pop d
  1000.     pop h
  1001.     ret
  1002.  
  1003. ;    keyboard status using invariant CP/M calls
  1004.  
  1005. stat:    push h
  1006.     push d
  1007.     push b
  1008.     mvi c,0BH
  1009.     call bdos
  1010.     ora a
  1011.     pop b
  1012.     pop d
  1013.     pop h
  1014.     ret
  1015.  
  1016. ;    MAIN PROGRAM for LIFE demonstration
  1017. ;    commands consist of a count and a letter.  An operation
  1018. ;    is repeated the number of times required, null and zero
  1019. ;    both being taken as once.  The correspondence between
  1020. ;    letters and operations is established by a sequence of
  1021. ;    CPI's and JZ's in the array vect.
  1022.  
  1023. main:    call home
  1024. loop:    call coop
  1025.     lxi h,vect
  1026.     call rept
  1027.     jmp loop
  1028.  
  1029.     end
  1030.