Hi,
While working on the Wolfenstein hack, I had a programming epiphany.
I realized that all the examples I had seen for positioning an object
horizontally have been less than optimal. All the methods I have
seen on this list given as optimal have divided the x-pos by 16 to form
a counter value for the rough positioning loop, and then done some
gymnastics to get the fine adjust value.
It occurred to me that the Rough positioning loop is really nothing
more than a division by 1. Ideally we want to divide the X-pos by 15
because our timing loop takes 5 cycles * 3 color clocks = 15 pixels.
SBC #15 takes 2 cycles the same as DEY or DEX. Therefore, we can
simply divide X-pos by 15. It turns out the remainder of the division
is easily converted to the correct fine adjust value! Using this new
system it is possible to completely reposition an object using only a
single scanline!
Here is the new routine:
; Positions an object horizontally
; Inputs: A = Desired position.
; X = Desired object to be positioned (0-5).
; scanlines: If control comes on or before cycle 73 then 1 scanline is
consumed.
; If control comes after cycle 73 then 2 scanlines are consumed.
; Outputs: X = unchanged
; A = Fine Adjustment value.
; Y = the "remainder" of the division by 15 minus an
additional 15.
; control is returned on cycle 6 of the next scanline.
PosObject SUBROUTINE
STA WSYNC ; 00 Sync to start of scanline.
SEC ; 02 Set the carry flag so no borrow will be applied during the
division.
.divideby15
SBC #15 ; 04 ; Waste the necessary amount of time dividing X-pos by
15!
BCS .divideby15 ; 06/07 - 11/16/21/26/31/36/41/46/51/56/61/66
TAY ; 08 ; At this point the value in A is -1 to -15. In this
code I use a table
; to quickly convert that value to the fine adjust value
needed.
LDA fineAdjustTable,Y ; 13 -> Consume 5 cycles by guaranteeing we
cross a page boundary
; In your own code you may wish to consume only 4.
STA HMP0,X ; 17 Store the fine adjustment value.
; EOR #%00000111 ; Alternately, instead of using a table, we can
calculate the fine adjust
; ADC #1 ; value using this commented out code instead of the table.
This code
; ASL ; uses less ROM, but takes more cycles.
; ASL
; ASL
; ASL
; STA HMP0.X
STA RESP0,X ; 21/ 26/31/36/41/46/51/56/61/66/71 - Set the rough
position.
STA WSYNC
RTS
;-----------------------------
; Here is the table I use to convert the "remainder" of the division by
15 (-1 to -15) to the correct
; fine adjustment value. I put this table at the top of a page of
memory to guarantee the processor
; will cross a page boundary and waste a cycle I need to waste in order
to be at the precise position
; I want the RESP0,X to happen at.
ORG $F000
fineAdjustBegin
DC.B %01110000 ; Left 7
DC.B %01100000 ; Left 6
DC.B %01010000 ; Left 5
DC.B %01000000 ; Left 4
DC.B %00110000 ; Left 3
DC.B %00100000 ; Left 2
DC.B %00010000 ; Left 1
DC.B %00000000 ; No movement.
DC.B %11110000 ; Right 1
DC.B %11100000 ; Right 2
DC.B %11010000 ; Right 3
DC.B %11000000 ; Right 4
DC.B %10110000 ; Right 5
DC.B %10100000 ; Right 6
DC.B %10010000 ; Right 7
fineAdjustTable EQU fineAdjustBegin - %11110001 ; NOTE: %11110001 = -15
----------------------------------------------------------------------------------------------
Archives (includes files) at http://www.biglist.com/lists/stella/archives/
Unsub & more at http://www.biglist.com/lists/stella/