551 lines
10 KiB
NASM
551 lines
10 KiB
NASM
B>type bolts.asm
|
|
|
|
.title "PLASMA BOLTS"
|
|
.sbttl "FRENZY"
|
|
.ident BOLTS
|
|
.insert equs
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Bolt Data Structure
|
|
; bit number
|
|
; +---7-+---6-+---5-+---4-+---3-+---2-+---1-+---0-+
|
|
; |down | up |right| left| Length of | VX.VY
|
|
; | v | ^ | > | < | Bolt 1-6 |
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
|
; BUL1:
|
|
; ---- VX.VY [DURL in top,length in bottom]
|
|
; ---- PX [position in x]
|
|
; ---- PY [ " in y]
|
|
; .
|
|
; :
|
|
; ---- oldX [Old positions *6]
|
|
; ---- oldY
|
|
;------------------------
|
|
; Equates
|
|
VX.VY == 0 ; byte offsets to bolt contents
|
|
PX == 1
|
|
PY == 2
|
|
LEFT == 0 ; direction bit numbers
|
|
RIGHT == 1
|
|
UP == 2
|
|
DOWN == 3
|
|
GREY == 77H ;mirror color
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Do all bolts
|
|
;_______________________________
|
|
BUL.V:: exx
|
|
push b ;set up wall color in alt set
|
|
lda Wcolor
|
|
mov b,a ;save
|
|
ani 0F0H ;hi nib in C
|
|
mov c,a
|
|
mov a,b ;lo nib in b
|
|
ani 0Fh
|
|
mov b,a
|
|
exx
|
|
mvi B,2 ;# man's bolts
|
|
call BOLT ;do 2 bolts
|
|
mvi B,2 ;# man's bolts
|
|
call BOLT ;do 2 bolts
|
|
mvi b,BOLTS ;do all bolts
|
|
call BOLT
|
|
exx
|
|
pop b
|
|
exx
|
|
ret
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Vector (B) Bolts
|
|
;_______________________________
|
|
BOLT: lxi h,BUL1 ;-> at 1st bolt
|
|
B.LOP: push b ;save counter
|
|
push h ;save pointer
|
|
call VEC.B ;erase/write a single bolt
|
|
pop h ;restore pointer
|
|
pop b ;restore counter
|
|
lxi d,Blength ;point at next bolt
|
|
dad d
|
|
djnz B.LOP ;do for B bolts
|
|
ret
|
|
.page
|
|
.sbttl /Erase Bolts/
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Vector Bolts
|
|
;_______________________________
|
|
; HL->bolt top
|
|
VEC.B:
|
|
mov a,m ;vx.vy
|
|
PUSH PSW ;save vxy.len
|
|
ani 0Fh ;isolate length
|
|
jrnz ..cont
|
|
POP PSW
|
|
RET
|
|
; ERASE Oldest position
|
|
..cont:
|
|
lxi b,PX
|
|
dad b ;->PX
|
|
add a ;double length
|
|
mov c,a ;bc=length*2
|
|
dad b ;->oldestX
|
|
mov e,m ;oldX
|
|
inx h ;oldestY
|
|
mov d,m ;oldY
|
|
xchg
|
|
mov a,l
|
|
ora h ;no write if 0
|
|
jrz ..skip
|
|
;BC=Length, DE->OldestY, HL=YX
|
|
call RELX ;convert to screen coords
|
|
mvi M,80h ;write dot
|
|
..skip:
|
|
POP PSW ;restore vxy.len
|
|
ani 0F0h ;check if still writing
|
|
jrnz ..ok
|
|
lxi h,-1
|
|
dad d
|
|
dsbc b ;->vxy.len
|
|
dcr M ;one less in length
|
|
RET
|
|
; Move array of old positions down
|
|
..ok: mov h,d
|
|
mov l,e ;->oldestY
|
|
dcx h
|
|
dcx h ;->previous
|
|
LDDR ;move down
|
|
inx h ;->px
|
|
; Update coords & WRITE DOT
|
|
; A=Vxy&F0, BC=0, DE->newest, HL->PX
|
|
rrc ;do table jump
|
|
rrc
|
|
rrc
|
|
mov c,a ;bc=offset (DURL*2)
|
|
xchg ;de->px
|
|
lxi h,JTable ;look up vectoring
|
|
dad b ;add offset
|
|
mov a,m ;routine in table
|
|
inx h ;and jump to it
|
|
mov h,m
|
|
mov l,a
|
|
xchg
|
|
mov c,m
|
|
inx h
|
|
mov b,m ;bc=YX
|
|
xchg
|
|
pchl ;jump
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Update Coords
|
|
;_______________________________
|
|
JTable: .word Rstop ;0
|
|
.word RLeft ;1
|
|
.word RRight ;2
|
|
.word Rstop ;3
|
|
.word RUp ;4
|
|
.word RUL ;5
|
|
.word RUR ;6
|
|
.word Rstop ;7
|
|
.word RDown ;8
|
|
.word RDL ;9
|
|
.word RDR ;10
|
|
.word Rstop ;11
|
|
.word Rstop ;12
|
|
.word Rstop ;13
|
|
.word Rstop ;14
|
|
.word Rstop ;15
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; all these routines get as input
|
|
; BC=pYpX, de->pY, hl=label address
|
|
;_______________________________
|
|
Rstop: xchg ;hl->py
|
|
Stop: xra a ;0
|
|
mov m,a ;py=0
|
|
dcx h ;->px
|
|
mov m,a ;px=0
|
|
dcx h ;->vxy.len
|
|
mov a,m ;get vxy.len
|
|
ani 0Fh ;leave length
|
|
mov m,a ;stop bolt
|
|
RET
|
|
;set to 4 to protect outer walls
|
|
wallo == 0
|
|
.define ULIMIT=[mov a,b
|
|
cpi 4+wallo ;;check limit
|
|
jrc STOP
|
|
]
|
|
.define DLIMIT=[mov a,b
|
|
cpi 200-wallo
|
|
jrnc STOP
|
|
]
|
|
.define RLIMIT=[mov a,c
|
|
cpi 252-wallo
|
|
jrnc STOP
|
|
]
|
|
.define LLIMIT=[mov a,c
|
|
cpi 8+wallo
|
|
jrc STOP
|
|
]
|
|
|
|
RUp: xchg ; hl->py de=YX
|
|
dcr b ;y--
|
|
ULIMIT
|
|
jmp Writ
|
|
|
|
RDown: xchg
|
|
inr b ;y++
|
|
DLIMIT
|
|
jmp Writ
|
|
|
|
RRight: xchg
|
|
inr c ;x++
|
|
RLIMIT
|
|
jmp Writ
|
|
|
|
RLeft: xchg
|
|
dcr c ;x--
|
|
LLIMIT
|
|
jmp Writ
|
|
|
|
RUL: xchg
|
|
dcr c ;x--
|
|
dcr b ;y--
|
|
ULIMIT
|
|
LLIMIT
|
|
jmp Writ
|
|
|
|
RUR: xchg
|
|
inr c ;x++
|
|
dcr b ;y--
|
|
ULIMIT
|
|
RLIMIT
|
|
jmp Writ
|
|
|
|
RDL: xchg
|
|
dcr c ;x--
|
|
inr b ;y++
|
|
DLIMIT
|
|
LLIMIT
|
|
jmp Writ
|
|
|
|
RDR: xchg
|
|
inr c ;x++
|
|
inr b ;y++
|
|
DLIMIT
|
|
RLIMIT
|
|
jmp Writ
|
|
.sbttl /Write Dots/
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Write the Dot
|
|
;_______________________________
|
|
; hl->py,bc=YX
|
|
Writ: mov m,b ;update py
|
|
dcx h ;->px
|
|
mov m,c ;update px
|
|
xchg ;de->px, hl?
|
|
mov h,b ;get pY
|
|
mov l,c ;pX
|
|
call RELX ;convert to screen addr
|
|
mvi M,80h ;write the dot
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Check for intercepts
|
|
;_______________________________
|
|
;BC=yx,DE->px, hl->screen
|
|
in WHATI
|
|
rlc
|
|
RNC
|
|
; Erase dot
|
|
mvi m,80h ;erase the dot
|
|
shld Temp ;save address for reflect
|
|
dcx d ;->vxy.len
|
|
; Hit Check by looking at the color bolt hit
|
|
push b ;save YX
|
|
srlr b ;index the 4x4 box
|
|
srlr b ;y/2
|
|
srlr b ;YX/8
|
|
rarr c
|
|
srlr b
|
|
rarr c
|
|
srlr b
|
|
rarr c ;carry=Low nibble
|
|
exaf
|
|
lda Flip ;test cocktail
|
|
ora a
|
|
jz ..norm
|
|
lxi h,EndColor
|
|
dsbc b ;subtract box offset
|
|
pop b ;restore YX
|
|
exaf
|
|
cmc ;complement hi/lo
|
|
jmp ..tt
|
|
..norm: lxi h,ColorScreen ;base of color area
|
|
dad b ;add box offset
|
|
pop b ;restore YX
|
|
exaf
|
|
..tt: jc LoNib
|
|
; Check hi nibble
|
|
mov a,m ;get 2 color boxes
|
|
ani 0f0h ;isolate left one
|
|
cpi GREY&0f0h ;gry=mirror
|
|
jz REFLECT
|
|
exx
|
|
cmp c ;hi nib wall color
|
|
exx
|
|
jz WALLHIT
|
|
;must have hit another bolt or object
|
|
jmp HITCHK
|
|
; Check Lo Nibble
|
|
LoNib:
|
|
mov a,m ;add box offset
|
|
ani 0fh ;isolate right one
|
|
cpi GREY&0fh ;gry=mirror
|
|
jz REFLECT
|
|
exx
|
|
cmp b ;lo nib wall color
|
|
exx
|
|
jz WALLHIT
|
|
;must have hit another bolt or object
|
|
jmp HITCHK
|
|
.sbttl /Reflect the bolt/
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Reflect the bolt
|
|
;_______________________________
|
|
;BC=yx, DE->vxy.len
|
|
REFLECT:
|
|
ldax d ;get vxy
|
|
ani 0C0h ;check for any up/down
|
|
jrz ..Ve ;right/left hit only verticals
|
|
lhld Temp ;get magic address
|
|
res 5,h ;convert to normal
|
|
mov a,m ;get pixels of wall
|
|
mvi h,90h ;left nibble test
|
|
bit 2,C ;if ((x.mod.8)<4)
|
|
jrz ..test ; then left nibble
|
|
mvi h,09h ;right nibble test
|
|
..test: exaf ;save pixels
|
|
lda Flip
|
|
ora a
|
|
jz ..on
|
|
mvi a,99h
|
|
xra h
|
|
mov h,a
|
|
..on: exaf ;restore pixels
|
|
ana h ;look for non 60(vertical)
|
|
jnz ..Ho
|
|
..Ve: lxi b,VerTab ;vertical table
|
|
jmp ..Go
|
|
..Ho: lxi b,HorTab ;horizontal table
|
|
;bc=table de->vxy,hl->screen
|
|
..Go: ldax d ;get vxy
|
|
ani 0f0h
|
|
rrc
|
|
rrc ;vxy*4
|
|
mov l,a
|
|
mvi h,0
|
|
dad b ;->RefTab[vxy]
|
|
ldax d ;->vxy.length
|
|
ani 0fh ;keep length
|
|
ora m ;new vxy
|
|
stax d ;update vxy.len
|
|
inx d ;->px
|
|
inx h ;->offset x
|
|
ldax d ;get px
|
|
add m ;add offset
|
|
mov c,a ;save new x
|
|
stax d ;update px
|
|
inx d ;->py
|
|
inx h ;->offset y
|
|
ldax d ;get py
|
|
add m ;add offset
|
|
mov b,a ;save new y
|
|
stax d ;update py
|
|
;now write the new dot
|
|
mov h,b ;pY
|
|
mov l,c ;pX
|
|
call RELX
|
|
mvi m,80h ;write the new head
|
|
sta RFSND ;make ping sound
|
|
RET
|
|
|
|
.define RE[vxy,xoffset,yoffset]=
|
|
[ .byte vxy<4,xoffset,yoffset,0
|
|
]
|
|
VerTab: RE 0,0,0 ;0 stoped
|
|
RE 2,1,-4 ;1 Left
|
|
RE 1,-1,-4 ;2 Right
|
|
RE 0,0,0 ;3
|
|
RE 8,3,1 ;4 Up-stop
|
|
RE 6,1,-1 ;5 UL->ur
|
|
RE 5,-1,-1 ;6 UR->ul
|
|
RE 0,0,0 ;7
|
|
RE 4,3,-1 ;8 Down-stop
|
|
RE 10,1,1 ;9 DL->dr
|
|
RE 9,-1,1 ;10 DR->dl
|
|
RE 0,0,0 ;11
|
|
RE 0,0,0 ;12
|
|
RE 0,0,0 ;13
|
|
RE 0,0,0 ;14
|
|
RE 0,0,0 ;15
|
|
; the horizontal version
|
|
HorTab: RE 0,0,0 ;0 stoped
|
|
RE 2,1,-4 ;1 Left stop
|
|
RE 1,-1,-4 ;2 Right stop
|
|
RE 0,0,0 ;3
|
|
RE 8,4,1 ;4 Up
|
|
RE 9,-1,1 ;5 UL->dl
|
|
RE 10,1,1 ;6 UR->dr
|
|
RE 0,0,0 ;7
|
|
RE 4,4,-1 ;8 Down
|
|
RE 5,-1,-1 ;9 DL->ul
|
|
RE 6,1,-1 ;10 DR->ur
|
|
RE 0,0,0 ;11
|
|
RE 0,0,0 ;12
|
|
RE 0,0,0 ;13
|
|
RE 0,0,0 ;14
|
|
RE 0,0,0 ;15
|
|
.page
|
|
.sbttl /Hit a Wall routine/
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Blast the Wall
|
|
;_______________________________
|
|
;BC=yx, DE->vxy, hl->color
|
|
WallHit:
|
|
ldax d ;get vxy
|
|
ani 0fh ;stop the vxy
|
|
stax d ;store 0.len
|
|
xra a ;0
|
|
inx d ;->px
|
|
stax d ;px=0
|
|
inx d ;->py
|
|
stax d ;py=0 (finished with DE)
|
|
; change color box to robot color
|
|
bit 2,C ;left/right nibble bit(4)
|
|
lxi d,0ff0h ;left half mask
|
|
jrz ..fix
|
|
lxi d,#0ff0h ;right mask
|
|
..fix: lda Flip
|
|
ora a
|
|
jrz ..auk
|
|
mov a,d ;swap em
|
|
mov d,e
|
|
mov e,a
|
|
..auk: mov a,m ;get 2 color boxes
|
|
ana d ;mask valid part
|
|
mov d,a ;save
|
|
lda Rcolor ;get robot color
|
|
ana e ;isolate nibble
|
|
ora d ;combine nibbles
|
|
mov m,a ;store new color
|
|
;index the box's pixels = (Y&!3) (X&!3)
|
|
mov a,b ;pY
|
|
ani #3 ;move to nearest multiple of 4
|
|
mov h,a
|
|
mov a,c ;pX
|
|
ani #3
|
|
mov l,a
|
|
call RELAnd
|
|
xchg
|
|
lxi h,WallPts ;add 1 pt
|
|
mov a,m ;for hitting wall
|
|
adi 1
|
|
daa
|
|
mov m,a
|
|
sta WLSND ;make sound
|
|
lxi h,Cross
|
|
jmp Plot#
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Special Relative to Absolute
|
|
;_______________________________
|
|
;save all but hl,af
|
|
;HL=YX
|
|
RELAnd::
|
|
RELX: push b
|
|
mvi B,90H ;xor write
|
|
call RtoA#
|
|
pop b
|
|
ret
|
|
.page
|
|
.sbttl /Hit Check for objects/
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Find Out What Got hit
|
|
;_______________________________
|
|
; BC=YX,de->vxy
|
|
HITCHK:
|
|
ldax d ;get vxy
|
|
ani 0fh ;stop it
|
|
stax d ;store 0,len
|
|
mvi a,MaxVec ;number of vectors to check
|
|
lxi x,Vectors ;->first vector
|
|
..LOOP:
|
|
exaf ;save count
|
|
bit Move,V.Stat(x) ;check if moving
|
|
jz ..next
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; Check Vector[ix] Against Bolt
|
|
;_______________________________
|
|
;NOTE: should mans bolt kill him?
|
|
;ix->object, BC=YX, a'=counter
|
|
mov a,c ;bolt X
|
|
sub P.X(x) ;object Y
|
|
inr a
|
|
; mov c,a ;save it
|
|
jm ..next ;outside on left?
|
|
cpi 10 ;max width
|
|
jrnc ..next ;ok in x
|
|
mov a,b ;now do y
|
|
sub P.Y(x)
|
|
inr a
|
|
jm ..next
|
|
cpi 30
|
|
jnc ..next
|
|
;check with real pattern size
|
|
mov h,D.P.H(x) ;get pattern pointer
|
|
mov l,D.P.L(x)
|
|
mov e,m ;get address of pattern
|
|
inx h
|
|
mov d,m
|
|
xchg ;hl->pattern
|
|
mov e,m ;get width in bytes of pattern
|
|
inx h
|
|
mov d,m ;get height
|
|
bit 7,d ;check for DROP
|
|
jz ..ok
|
|
xchg ;special for otto drop
|
|
dad h
|
|
dad h
|
|
dad h ;drop/32
|
|
sub h ;adjust delta Y
|
|
xchg
|
|
inx h ;now get real Y height
|
|
mov e,m
|
|
inx h
|
|
mov d,m
|
|
..ok: inr d ;adjust for 1 higher in Y
|
|
inr d
|
|
; now check if bolt y is in pattern
|
|
cmp d ;a still y delta
|
|
jnc ..next
|
|
;now x NOT NEEDED ALL ARE 8 WIDE
|
|
; mov a,c ;restore delta
|
|
; sub P.X(x)
|
|
; slar e ;multiply X.size**NEW
|
|
; slar e ;by 8 cuz of 8 bits to byte
|
|
; slar e ;of pattern
|
|
; inr e ;add one for slop
|
|
; cmp e ;is in past right side?
|
|
; jrnc ..next
|
|
; hit this vector, so set his inept bit
|
|
set Hit,V.STAT(x)
|
|
set INEPT,V.STAT(x) ;cause an explosion
|
|
RET ;leave loop
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
; End of Loop
|
|
;_______________________________
|
|
..next: lxi d,VLEN ;distance to
|
|
dadx d ;next vector
|
|
..exit: exaf ;get counter
|
|
dcr a ;any more vectors left?
|
|
jrnz ..LOOP ;if not,go check this one
|
|
ret ;go do another bolt
|
|
|
|
; Pattern of wall
|
|
Cross: .byte 1,4
|
|
.byte 060h,0f0h,0f0h,060h
|
|
|
|
.end
|