home *** CD-ROM | disk | FTP | other *** search
-
- ; -------------------------------------------------------
- ; Adaptation of VTI to use Solid State Music video board
- ; model VB1-B with CP/M I-O routines on UAP's IMSAI 8080.
- ; [Version October 27,1978]
- ;
- ; VB1-B - Copyright (C) 1978
- ; Universidad Autonoma de Puebla
- ;
- ; written by Harold V. McIntosh, summer 1978, with
- ; reference to: Harvey A. Cohen, "The Oznaki LIFE",
- ; Dr. Dobbs Journal of Computer Calisthenics and
- ; Orthodontia, volume 3, issue 4 (April 1978) pp. 10-11;
- ; and with acknowledgements to the hospitality of the
- ; Quantum Theory Project, University of Florida,
- ; Gainesville, Florida.
- ; ------------------------------------------------------
-
- org 0100H
-
- jmp main ;create entry point for demonstration
-
- ; -------------------------------------------------------
- ; Constants defining screen size and location. Note that
- ; while the programmer has some discretion in assigning
- ; these constants, there is highly implicit usage of the
- ; assumption that the screen memory begins at a 1K Hex
- ; boundary, and that the row length is a power of 2.
- ; Thus the video board origin may be changed through its
- ; address switches, and new parameters defined without
- ; difficulty; nevertheless adaptation to an 80-column
- ; board would require restructuring the subroutines.
- ; -------------------------------------------------------
-
- vorg: equ 0F800H ;origin of video screen memory area
- vsiz: equ 00400H ;size of video screen memory area
- rsiz equ 00040H ;length of a single display line
- rmsk: equ rsiz-1 ;mask for single row addresses
-
- ; -------------------------------------------------------
- ; Data storage locations required by the subroutines.
- ; -------------------------------------------------------
-
- ma: equ 00CC9H ;bit mask to locate pixel within byte
- wy: equ 00CCAH ;row count * 16 - 16 rows total
- ex: equ 00CCBH ;column count * 4 - 64 columns total
- ts: equ 00CCCH ;temporary storage
-
- ; -----------------------------------------------------
- ; Entry vector designed to systematize communication with
- ; calling programs written in BASIC or other external
- ; languages. These entry points will persist even though
- ; the subroutines are revised, corrected, or otherwise
- ; modified. A further advantage is that the same
- ; arrangement can be used by the drivers for different
- ; video boards, allowing program interchangability.
- ; --------------------------------------------------------
-
- vb1: jmp home ;place cursor at screen center
- jmp culi ;illuminate the cursor
- jmp cuex ;extinguish the cursor
- jmp cure ;reverse the cursor
- jmp cuse ;sense the cursor (use jz afterward)
- jmp xpl ;move cursor right one pixel
- jmp xmi ;move cursor left one pixel
- jmp ypl ;move cursor up one pixel
- jmp ymi ;move cursor down one pixel
- jmp blak ;make the whole screen black
- jmp whit ;make the whole screen white
- jmp reve ;reverse the whole screen
- jmp cart ;form (ma, wy, ex) from (D,E)
- jmp line ;line segment with increments (dx,dy)
- jmp ekspl ;rotate whole screen right
- jmp eksmi ;rotate whole screen left
- jmp wyepl ;rotate whole screen up
- jmp wyemi ;rotate whole screen down
- jmp ee ;move cursor east one cell
- jmp ww ;move cursor west one cell
- jmp nn ;move cursor north one cell
- jmp ss ;move cursor south one cell
- jmp kk ;deactivate cell under cursor
- jmp ll ;activate cell under cursor
- jmp hh ;advance through one cycle of LIFE
- jmp eas ;rotate screen and cursor one cell east
- jmp wes ;rotate screen and cursor one cell west
- jmp nor ;rotate screen and cursor one cell north
- jmp sou ;rotate screen and cursor one cell south
- jmp doli ;illumate a two-pixel dot
- jmp doex ;extinguish a two-pixel dot
- jmp xppl ;move cursor one byte right
- jmp xmmi ;move cursor one byte left
- jmp eksppl ;rotate whole screen one byte right
- jmp eksmmi ;rotate whole screen one byte left
-
- ; =======================================================
-
- ; move cursor up one pixel
-
- ypl: lxi h,ma
- mov a,m
- ani 009H
- jnz yp1
- mov a,m
- rrc
- mov m,a
- ret
- yp1: rlc
- rlc
- mov m,a
- lda wy
- sui 010H
- sta wy
- ret
-
- ; move cursor down one pixel
-
- ymi: lxi h,ma
- mov a,m
- ani 024H
- jnz ym1
- mov a,m
- rlc
- mov m,a
- ret
- ym1: rrc
- rrc
- mov m,a
- lda wy
- adi 010H
- sta wy
- ret
-
- ; move cursor right one pixel
-
- xpl: lxi h,ma
- mov a,m
- ani 038H
- jnz xp1
- mov a,m
- rlc
- rlc
- rlc
- mov m,a
- ret
- xp1: rrc
- rrc
- rrc
- mov m,a
- lda ex
- adi 004H
- sta ex
- ret
-
- ; move cursor left one pixel
-
- xmi: lxi h,ma
- mov a,m
- ani 007H
- jnz xm1
- mov a,m
- rrc
- rrc
- rrc
- mov m,a
- ret
- xm1: rlc
- rlc
- rlc
- mov m,a
- lda ex
- sui 004H
- sta ex
- ret
-
- ; fast movement of cursor right two pixels
-
- xppl: lda ex
- adi 004H
- sta ex
- ret
-
- ; fast movement of cursor left two pixels
-
- xmmi: lda ex
- sui 004H
- sta ex
- ret
-
- ; load A with the bit mask, HL with a byte address
- ; given the cursor positioning data at (ma,wy,ex)
-
- dot: lhld wy
- mov a,h
- mvi h,vorg/0400H
- dad h
- dad h
- rrc
- rrc
- ora l
- mov l,a
- lda ma
- ret
-
- ; initialize cursor parameters
-
- home: lxi h,8080H
- shld wy
- mvi a,001H
- sta ma
- ret
-
- ; extinguish the cursor
-
- cuex: call dot
- ora m
- mov m,a
- ret
-
- ; light the cursor
-
- culi: call dot
- cma
- ana m
- mov m,a
- ret
-
- ; reverse the cursor
-
- cure: call dot
- xra m
- mov m,a
- ret
-
- ; sense the cursor
-
- cuse: call dot
- ana m
- ani 03FH
- ret
-
- ; clear the whole screen to black
-
- blak: lxi d,vsiz
- lxi h,vorg
- bl1: mvi m,0FFH
- inx h
- dcr e
- jnz bl1
- dcr d
- jnz bl1
- ret
-
- ; clear the whole screen to white
-
- whit: lxi d,vsiz
- lxi h,vorg
- whi: mvi m,080H
- inx h
- dcr e
- jnz whi
- dcr d
- jnz whi
- ret
-
- ; reverse the whole screen
-
- reve: lxi d,vsiz
- lxi h,vorg
- rev1: mov a,m
- xri 03FH
- mov m,a
- inx h
- dcr e
- jnz rev1
- dcr d
- jnz rev1
- ret
-
- ; transform cartesian coordinates in the form of x,y
- ; transmitted through registers (D,E) to a mask and
- ; byte address.
-
- cart: mvi b,018H
- mvi c,004H
- mov a,e
- cma
- adi 031H
- car1: cmp b
- jc car2
- sub b
- car2: cmc
- adc a
- dcr c
- jnz car1
- mov c,a
- ani 00FH
- rlc
- rlc
- rlc
- rlc
- sta wy
- mov a,c
- ani 0F0H
- jnz car3
- mvi a,008H
- car3: mov c,a
- mov a,d
- dcr a
- mov b,a
- rlc
- ani 0FCH
- sta ex
- mov a,b
- ani 001H
- mov a,c
- jnz car4
- rrc
- rrc
- rrc
- car4: sta ma
- ret
-
- ; draw a line with increments dx,dy = (D,E). Increment
- ; may be + or - using complementary arithmetic, but ought
- ; to be less than 64 in absolute value to avoid overflow
- ; problems.
-
- line: lxi h,ypl
- mov a,e
- ora a
- jp lin1
- cma
- inr a
- mov e,a
- lxi h,ymi
- lin1: lxi b,xppl
- mov a,d
- ora a
- jp lin2
- cma
- inr a
- mov d,a
- lxi b,xmmi
- lin2: cmp e
- jnc lin3
- push h
- push b
- pop h
- pop b
- mov d,e
- mov e,a
- lin3: mov a,d
- sta ts
- mov a,e
- add a
- mov e,a
- sub d
- push psw
- sub d
- mov d,a
- lin4: pop psw
- push h
- lxi h,doli
- xthl
- cpi 001H
- jm lin5
- push h
- add d
- jmp lin6
- lin5: add e
- lin6: push b
- push psw
- lda ts
- dcr a
- sta ts
- jnz lin4
- pop psw
- ret
-
- ; the movements in one byte necessary to shift the
- ; whole screen right one pixel.
-
- expl: mov a,m
- ani 03FH
- mov b,a
- ani 007H
- rlc
- rlc
- rlc
- ora c
- mov c,a
- mov a,b
- rrc
- rrc
- rrc
- ani 007H
- mov b,c
- mov c,a
- ret
-
- ; the movements within one byte necessary for shifting
- ; the whole screen left one pixel.
-
- exmi: mov a,m
- ani 03FH
- mov b,a
- rrc
- rrc
- rrc
- ani 007H
- ora c
- mov c,a
- mov a,b
- ani 007H
- rlc
- rlc
- rlc
- mov b,c
- mov c,a
- ret
-
- ; the movements necessary within one byte to shift the
- ; whole screen down one pixel.
-
- wymi: mov a,m
- ani 03FH
- mov b,a
- ani 01BH
- rlc
- ora c
- mov c,a
- mov a,b
- rrc
- rrc
- ani 009H
- mov b,c
- mov c,a
- ret
-
- ; the movements necessary within one byte to shift the
- ; whole screen up one pixel.
-
- wypl: mov a,m
- ani 03FH
- mov b,a
- rrc
- ani 01BH
- ora c
- mov c,a
- mov a,b
- ani 009H
- rlc
- rlc
- mov b,c
- mov c,a
- ret
-
- ; rotate the whole screen right one pixel
-
- ekspl: lxi h,vorg
- lxi d,rsiz-1
- eksp1: push h
- dad d
- call expl
- pop h
- eksp2: call expl
- mov a,b
- ori 080H
- mov m,a
- inx h
- mov a,l
- ani rmsk
- jnz eksp2
- mov a,h
- cpi (vorg+vsiz)/0100H
- jnz eksp1
- ret
-
- ; rotate the whole screen left one pixel
-
- eksmi: lxi h,vorg+vsiz-1
- lxi d,-rsiz+1
- eksm1: push h
- dad d
- call exmi
- pop h
- eksm2: call exmi
- mov a,b
- ori 080H
- mov m,a
- mov a,l
- ani rmsk
- dcx h
- jnz eksm2
- mov a,h
- cpi (vorg/0100H)-1
- jnz eksm1
- ret
-
- ; rotate the whole screen up one pixel.
-
- wyepl: lxi h,vorg+vsiz-1
- wyep1: lxi d,-vsiz+rsiz
- push h
- dad d
- call wypl
- pop h
- push h
- lxi d,-rsiz
- wyep2: call wypl
- mov a,b
- ori 080H
- mov m,a
- dad d
- mov a,h
- cpi (vorg/0100H)-1
- jnz wyep2
- pop h
- mov a,l
- ani rmsk
- dcx h
- jnz wyep1
- ret
-
- ; rotate the whole screen down one pixel
-
- wyemi: lxi h,vorg
- wyem1: lxi d,vsiz-rsiz
- push h
- dad d
- call wymi
- pop h
- push h
- lxi d,rsiz
- wyem2: call wymi
- mov a,b
- ori 080H
- mov m,a
- dad d
- mov a,h
- cpi (vorg+vsiz)/0100H
- jnz wyem2
- pop h
- inx h
- mov a,l
- ani rmsk
- jnz wyem1
- ret
-
- ; fast right rotation by two pixels = one byte
-
- eksppl: lxi h,vorg
- lxi d,rsiz-1
- ekspp1: push h
- dad d
- mov c,m
- pop h
- ekspp2: mov b,m
- mov m,c
- mov c,b
- inx h
- mov a,l
- ani rmsk
- jnz ekspp2
- mov a,h
- cpi (vorg+vsiz)/0100H
- jnz ekspp1
- ret
-
- ; fast left rotate by two pixels = one byte
-
- eksmmi: lxi h,vorg+vsiz-1
- lxi d,-rsiz+1
- eksmm1: push h
- dad d
- mov c,m
- pop h
- eksmm2: mov b,m
- mov m,c
- mov c,b
- mov a,l
- ani rmsk
- dcx h
- jnz eksmm2
- mov a,h
- cpi (vorg/0100H)-1
- jnz eksmm1
- ret
-
- ; Add to the neighbor count of adjoining cells according
- ; to the bits in this byte. We do the middle pixel,
- ; adding to the count of three successive neighbors in
- ; registers B,C,D.
-
- alfa: mov a,m
- rlc
- rlc
- rlc
- jc alf1
- inr b
- inr c
- inr d
- alf1: rlc
- jc alf2
- inr b
- inr d
- alf2: rlc
- rc
- inr b
- inr c
- inr d
- ret
-
- ; shift the neighbor count as we move forward one byte in
- ; a row scan
-
- beta: mov b,c
- mov c,d
- mvi d,00H
- inx h
- mov a,l
- ani 03FH
- rnz
- push d
- lxi d,-rsiz
- dad d
- pop d
- ret
-
- ; PRINCIPAL PROGRAM for carrying out a cycle of LIFE.
- ; Only the middle pixel in each byte is calculated
- ; so that three passes are necessary after each of three
- ; shifts. Two adjacent pixels are used, the right to hold
- ; the present living status and the left for information
- ; for the next cycle.
-
- epsi: lxi h,vorg+rsiz-1
- gama: mvi d,00H
- call alfa
- call beta
- call alfa
- delt: push h
- call beta
- call alfa
- xthl
- mov a,b
- cpi 002H
- jz eta
- cpi 003H
- jz zeta
- mov a,m
- ori 002H
- mov m,a
- jmp thet
- zeta: mov a,m
- ani 0FDH
- mov m,a
- jmp thet
- eta: mov a,m
- ani 0FDH
- mov e,a
- ani 010H
- rrc
- rrc
- rrc
- ora e
- mov m,a
- thet: pop h
- mov a,l
- ani rmsk
- jnz delt
- push d
- lxi d,2*rsiz-1
- dad d
- pop d
- mov a,h
- cpi (vorg+vsiz)/0100H
- jnz gama
- ret
-
- ; updating loop, moving left pixel to right
-
- cycl: lxi h,vorg
- cyc1: mov a,m
- ani 007H
- mov b,a
- rlc
- rlc
- rlc
- ora b
- ori 080H
- mov m,a
- inx h
- mov a,h
- cpi (vorg+vsiz)/0100H
- jnz cyc1
- ret
-
- ; execute a single cycle of LIFE by updating the middle
- ; pixel and making three sweeps while shifting each time
-
- hh: call epsi
- call wyepl
- call epsi
- call wyepl
- call epsi
- call wyemi
- call wyemi
- jmp cycl
-
- ; extinguish cursor, move two pixels east, light cursor
-
- ee: call cure
- call xppl
- jmp cure
-
- ; extinguish cursor, two pixels west, light cursor
-
- ww: call cure
- call xmmi
- jmp cure
-
- ; extinguish cursor, one pixel north, light cursor
-
- nn: call cure
- call ypl
- jmp cure
-
- ; extinguish cursor, one pixel south, light cursor
-
- ss: call cure
- call ymi
- jmp cure
-
- ; extinguish a life cell
-
- kk: call xpl
- call cuex
- jmp xmi
-
- ; activate a life cell
-
- ll: call xpl
- call culi
- jmp xmi
-
- ; move whole screen right one life cell, with cursor
-
- eas: call eksppl
- jmp xppl
-
- ; move the whole screen left one life cell, with cursor
-
- wes: call eksmmi
- jmp xmmi
-
- ; move the whole screen up one life cell, with cursor
-
- nor: call wyepl
- jmp ypl
-
- ; move the whole screen down one life cell, with cursor
-
- sou: call wyemi
- jmp ymi
-
- ; light a two-pixel dot
-
- doli: call culi
- call xpl
- call culi
- jmp xmi
-
- ; extinguish a two-pixel dot
-
- doex: call cuex
- call xpl
- call cuex
- jmp xmi
-
- ; =======================================================
- ; driver subroutines for diverse demonstrations
- ; =======================================================
-
- bdos: equ 0005H ;entry point for CP/M service routines
- morg: equ 4000H ;area for defining macros
-
- ; build up one-byte decimal number from digit string
- ; null string =1, minus creates negative modulo 256
- ; to correct an error type four zeroes and start over
- ; decm: places number in D, terminal character in A
- ; coop: places number in D, terminal character in E
-
- coop: call decm
- mov e,a
- ret
- decm: mvi d,01H
- call read
- cpi '-'
- jnz dec1
- lxi h,dec3
- push h
- call read
- dec1: cpi '0'
- rc
- cpi '9'+1
- rnc
- mvi d,00H
- dec2: cpi '0'
- rc
- cpi '9'+1
- rnc
- sui '0'
- mov e,a
- mov a,d
- rlc
- rlc
- add d
- rlc
- add e
- mov d,a
- call read
- jmp dec2
- dec3: push sp
- mov a,d
- cma
- inr a
- mov d,a
- pop sp
- ret
-
- ; get (D,E) = (X,Y); for example a pair of coordinates
- ; first read d=x, then e=y
-
- pair: call decm
- push d
- call decm
- pop sp
- mov e,d
- mov d,a
- ret
-
- ; place a dot with coordinates x,y on the screen
-
- pp: call pair
- call cart
- jmp culi
-
- ; draw a line with increments (dx,dy)
-
- ii: call pair
- jmp line
-
- ; repeat the subroutine in (H,L) for the number of times
- ; in D.
-
- rept: mov a,e
- push h
- push d
- lxi b,repi
- push b
- pchl
- repi: pop d
- pop h
- dcr d
- rz
- jmp rept
-
- ; turn one ASCII digit into a macro location
- ; address is returned in (H,L)
-
- mloc: lxi h,0005H
- dad sp
- mov e,m
- mvi d,00H
- mvi m,01H
- lxi b,morg
- xchg
- dad h
- dad h
- dad h
- dad h
- dad h
- dad b
- ret
-
- ; record a macro definition
-
- mdef: call mloc
- mde1: call coop
- mov m,d
- inx h
- mov m,e
- inx h
- mvi a,01BH
- cmp e
- rz
- push h
- lxi h,vect
- call rept
- pop h
- jmp mde1
-
- ; execute a defined macro
-
- mxec: call mloc
- push h
- mxe1: pop h
- mov d,m
- inx h
- mov a,m
- inx h
- cpi 01BH
- rz
- cpi ')'
- jz rpar
- cpi '('
- jz lpar
- mov e,a
- push h
- lxi h,vect
- call rept
- jmp mxe1
- rpar: pop psw
- dcr a
- jz rpa1
- pop h
- push h
- push psw
- push h
- jmp mxe1
- rpa1: xthl
- jmp mxe1
- lpar: push h
- mov a,d
- push psw
- push h
- jmp mxe1
-
- ; directory vector for LIFE demonstration
-
- vect: cpi 'N' ;rotate screen north
- jz nor
- cpi 'S' ;rotate screen south
- jz sou
- cpi 'E' ;rotate screen east
- jz eas
- cpi 'W' ;rotate screen west
- jz wes
- cpi 06EH ;'n' - move cursor north
- jz nn
- cpi 073H ;'s' - move cursor south
- jz ss
- cpi 065H ;'e' - move cursor east
- jz ee
- cpi 077H ;'w' - move cursor west
- jz ww
- cpi 06BH ;'k' - deactivate cell
- jz kk
- cpi 06CH ;'l' - activate cell under cursor
- jz ll
- cpi 'C' ;clear screen to black
- jz blak
- cpi 'R' ;reverse the screen
- jz reve
- cpi 068H ;'h' - advance one cycle of LIFE
- jz hh
- cpi 067H ;'g' - repeat cycles of LIFE
- jz gg
- cpi '.' ;reverse cursor illumination
- jz cure
- cpi '!'
- jz mdef
- cpi '?'
- jz mxec
- cpi 069H
- jz ii
- cpi 070H
- jz pp
- cpi ';' ;exit to monitor
- jz 0000H
- vend: ret
-
- ; call hh repeatedly unless keyboard input is waiting
-
- gg: call stat
- rnz
- call hh
- jmp gg
-
- ; read program using invariant CP/M calls
-
- read: push h
- push d
- push b
- mvi c,01H
- call bdos
- pop b
- pop d
- pop h
- ret
-
- ; keyboard status using invariant CP/M calls
-
- stat: push h
- push d
- push b
- mvi c,0BH
- call bdos
- ora a
- pop b
- pop d
- pop h
- ret
-
- ; MAIN PROGRAM for LIFE demonstration
- ; commands consist of a count and a letter. An operation
- ; is repeated the number of times required, null and zero
- ; both being taken as once. The correspondence between
- ; letters and operations is established by a sequence of
- ; CPI's and JZ's in the array vect.
-
- main: call home
- loop: call coop
- lxi h,vect
- call rept
- jmp loop
-
- end
-