[stella] A new way to position objects horizontally!

Subject: [stella] A new way to position objects horizontally!
From: RMundschau <rmundschau@xxxxxxxxxxxxx>
Date: Thu, 25 Mar 2004 23:37:22 -0600
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/


Current Thread