Vectrex: Morph

Morph1

Morph3

Morph2

 

These routines are part of Vectrex Frogger, but can be used “seperatly”, since they are easily seperated. The routines take 2 vector lists as input, and produce vector lists, that change from one to the other.

(For variable definitions end the like take a look at the sources of Vectrex Frogger)

 

; this file is part of vectrex frogger, written by Malban
; in March-April 1998
; all stuff contained here is public domain
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; morphing subroutines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;***************************************************************************
; below are all subroutines for morphing
; (only two) set_up_morphing(), do_one_morph_step()
;***************************************************************************
; this sets up a morph
; in U a pointer to a morph structure is expected,
;structure:
; DW ; morph from vector list
; DW ; morph to vector list
; DB ; morph steps
; DB ; delay between one morph step
; DW ; optional (0 or structure)
; ; pointer to next morph structure
; DB ; startup delay
;
; vector list must have (as usual with my routines) the following style
; count, rel y, rel x, rel y, rel x, ...
;
; maximal vectors for morphing is now 63 (127/2)
; if more are needed than something below cries for a 16 bit change...
; vector list don't need to have the same length anymore
; for optimal performance use a power of two step counter (-1)
; (8, 16, 32, 64 are supported with fast DIV routines)
;
; this routine sets up three vector lists (sort of) in RAM
; current_morph_vectorlist_org
; current_morph_vectorlist
; current_morph_vector_diffs
;
; current_morph_vectorlist_org
; is the original startlist, but possibly lengthened to the
; max vectorlist length of the two passed vectors (filled with 0,0 coordinates)
;
; current_morph_vectorlist
; is the storage area for the next to be drawn vectorlist
; is set to the original vector list (not max length)
;
; current_morph_vector_diffs
; not a real vector list, this contains the difference between the
; points of the two passed vector lists
; used in 'do_one_morph_step' to calculate the next vector
;
; further some variables are set, like delay, div routine, and morph_structure...
;
;
set_up_morphing:
 JSR DP_to_C8
 direct $c8
 STU morph_structure ; remember current morph structure
 ; first clear all current stuff, since we
 ; don't know how long all vectors will be
 ; could be optimized to a later fill
 ; with only the fills we need,
 ; but at this point vectrex should be fast enough
 ; so it doesn't matter to waste a bit time here...
 ;
 ; since current_morph_vectorlist_org, current_morph_vectorlist and current_morph_vector_diffs
 ; are neighbours one Clear_x_d should be enough...
 LDX #current_morph_vectorlist_org  ; address to clear
 LDD #((3*(2*MAX_VECTOR_MORPH+1))-1); number of bytes - 1 to clear
 JSR Clear_x_d                      ; clear sub routine in ROM
 LDX ,U                             ; X = pointer to 'from'
 LDY 2,U                            ; Y = pointer to 'to'
 LDA ,X                             ; load number of vectors
 CMPA ,Y                            ; compare number of vectors
 BHS A_is_high_vector_counter       ; which vector list is longer ?
 LDA ,Y                             ; load number of vectors 'to', the second...

A_is_high_vector_counter:
                                    ; in A is the higher vector count
 STA current_morph_vectorlist_org   ; set high value in vector lists
 INCA                               ; add 1
 ASLA                               ; multiply by two, since every vector has two coordinates
 STA tmp2                           ; remember in tmp2
                                    ; copy 'from' to original
 LDX #(current_morph_vectorlist_org+1) ; destination pointer
 LDU ,U                             ; source pointer
 LDA ,U+                            ; load length and step over length byte
 INCA                               ; increase 1, since one is missing
 ASLA                               ; times two, since there are two coordinates
 JSR Move_Mem_a                     ; and copy it
 LDU morph_structure                ; load current morph structure
                                    ; copy 'from' to current
 LDX #(current_morph_vectorlist)    ; destination pointer
 LDU ,U                             ; source pointer
 LDA ,U                             ; load length
 INCA                               ; increase 1, since one is missing
 ASLA                               ; times two, since there are two coordinates
 INCA                               ; add 1 since counter is also copied
 JSR Move_Mem_a                     ; and copy it
 LDU morph_structure                ; load current morph structure

 ; copy 'to' to 'buffer' (buffer is now 'current_morph_vector_diffs')
 ; destination pointer
 LDX #current_morph_vector_diffs    ; no +1 here, since in diffs only the offsets are relevant anyway
 LDU 2,U                            ; source pointer
 LDA ,U+                            ; load length and step over length byte
 INCA                               ; increase 1, since one is missing
 ASLA                               ; times two, since there are two coordinates
 JSR Move_Mem_a                     ; and copy it
 LDU morph_structure                ; load current morph structure
 LDA 4,U                            ; load morph steps to A
 INCA                               ; plus one
 STA morph_counter                  ; and save it this is variable
 STA morph_steps                    ; and again not variable
 LDA 8,U                            ; load morph delay A
 STA morph_delay                    ; and save it
 LDA #MORPHING_WORKING              ; and mark the whole thing as active
 STA morph_status                   ; and store it

 ; now we must calculate the current_morph_vector_diffs
 ; we must determine the difference between the two sets of coordinates
 ; use tmp2 as loop counter
 ; number of vectors to process * 2
 LDX #(current_morph_vectorlist_org+1)
 LDY #current_morph_vector_diffs    ; Y = pointer to 'to' (buffer)
                                    ; and Y = pointer to vector diffs
set_up_morphing_loop2:
 LDB ,Y                             ; load the second's vector coordinate
 NEGB                               ; neg it, since we actually want a 'a=a-b' style
 
 ; what we do is
 ; invert b and do a b=-b+a
 ADDB ,X+                           ; and add the source coordinate
 STB ,Y+                            ; store is (back) to vector diffs
 DEC tmp2                           ; decrease vector counter by 1
 BNE set_up_morphing_loop2          ; and continue with next vector if not done
 JSR DP_to_D0
 direct $d0
 RTS                                ; all done now, return

;***************************************************************************
; uses tmp1 and tmp2
; destroys everything
;
; what it does:
; current_morph_vectorlist is set to a (possibly) newly calculated vector
;
; but hardcoded
; 16 steps,
; not using JSR for DIV
; saves 1000 cycles on intro screen!!!
do_one_morph_step_16:
 direct $d0
 LDA morph_status                   ; load the status
 CMPA #MORPHING_WORKING             ; and look what there is to do
 BEQ morphing_now_16                ; morphing now?
 CMPA #MORPHING_COMPLETE            ; or complete?
 BEQ no_new_morph_structure         ; should a new morph be initialized?
                                    ; here we come with MORPHING_DONE
 LDX morph_structure                ; load the current morph structure
 LDU 6,X                            ; look if there is a next structure
 BEQ no_new_morph_structure         ; no? than go out
 JSR set_up_morphing                ; yes? than initialize it
 RTS                                ; go back

no_new_morph_structure:
 LDA #MORPHING_COMPLETE             ; load completeness flag to A
 STA morph_status                   ; and store it
 RTS                                ; go back

morphing_now_16:
 DEC morph_delay                    ; decrease delay value
 BEQ delay_done_16                  ; only morph when zero
 RTS                                ; otherise go back

delay_done_16:
 LDU morph_structure                ; in the current morph structure
 LDA 5,U                            ; look for the next delay value
 STA morph_delay                    ; and set it
 LDA morph_counter                  ; load counter of morph steps
 BEQ no_morphing_is_last            ; are we done ?
 SUBA morph_steps                   ; no, than calculate offset to number of steps
 BEQ no_morphing_is_first           ; is it the beginning?
                                    ; no, than we go on
 LDX #current_morph_vectorlist_org  ; pointer to original vectorlist
                                    ; (RAM), but the (maybe) longer version
 LDA ,X+                            ; load length of vectorlist and increment X
 STA current_morph_vectorlist       ; only needed the first time we are in here...
                                    ; A current number of vectors in (RAM) vectorlist
 INCA                               ; since it misses allways one, add one
 ASLA                               ; multiply by two, since every vector has
                                    ; start and end point
 STA tmp2                           ; use tmp2 as loop counter see below
 LDU #current_morph_vector_diffs    ; U = pointer to vector diffs (RAM)
 LDY #(current_morph_vectorlist+1)  ; target memory pointer (RAM)
                                    ; plus one, since we don't need the vector counter
 LDB morph_steps                    ; load number of steps to B
 SUBB morph_counter                 ; invert the morph counter
 STB morph_tmp                      ; store..., so we don't have to calculate in the loop
 CLR morph_sign                     ; clear signess... (that's positiv)

do_morph_loop2_16:                  ; loop through all vector coordinates of list
 LDA ,U+                            ; load the difference between the 'to' coordinates to A
 BPL no_minus_morph_16              ; check if negative sign
 INC morph_sign                     ; mark as negative
 NEGA                               ; and make positiv

no_minus_morph_16:
 LDB morph_tmp                      ; initiated above..., this is the

 ; 'morph step' of number of morph_steps we are makeing
 MUL                                ; multiply, B should be smaller
                                    ; than A (B is cycle relevant)
 MY_DIV_D_16_UNSIGNED
 TST morph_sign                     ; is it signed?
 BEQ no_minus_morph2_16             ; no, than go on
 NEGB                               ; otherwise restore the 'minus'
 DEC morph_sign                     ; and reset sign memory

no_minus_morph2_16:
 NEGB                               ; negate the div value
 ;
 ; this is again a formal a=a-b
 ; what we do is
 ; invert b and do a b=-b+a
 ADDB ,X+                           ; add the resulting difference to original coordinate
 STB ,Y+                            ; and store it to the current vectorlist
 DEC tmp2                           ; decrement the vectorlist loop counter by one
 BNE do_morph_loop2_16              ; and if not done,.. repeat
                                    ; on first entry vectorlist is allready set

no_morphing_is_first:
 DEC morph_counter                  ; decrement morph step counter
 RTS                                ; and go back

no_morphing_is_last:
 LDU morph_structure                ; load current morph structure
                                    ; copy 'to' to current_morph_vectorlist
 LDX #(current_morph_vectorlist)    ; destination pointer
 LDU 2,U                            ; source pointer
 LDA ,U                             ; load length
 INCA                               ; increase 1, since one is missing
 ASLA                               ; times two, since there are two coordinates
 INCA                               ; increase 1, since now we also copy the counter
 JSR Move_Mem_a                     ; and copy it
 LDA #MORPHING_DONE                 ; no we are done with morphing...
 STA morph_status                   ; and store it
 RTS                                ; go back...
;***************************************************************************
; end of morph routine section
;***************************************************************************

     			  			

Leave a Reply

Your email address will not be published. Required fields are marked *