Jump to content
IGNORED

Positioning p0 sprite horizontally according to variable (0-150)?


Recommended Posts

Hi everybody,

 

I thought this would be a good question to post in the newbie forum.

I am aware of an algorithm that Joe Decuir wrote up "back in the day" (I believe for Combat), where you could take a value between say, 1 and 150, and based on that value, set RESP0 and HMP0 appropriately. However, if I remember right, this position algorithm happens during VBLANK. I need something like this to happen during the kernel.

 

So, I'm looking for a routine that say... in 2-3 scanlines during the kernel does the calculations based on a horizontal position variable in Ram.

Does anyone have any code like this that they would be willing to share?

 

For new programmers, this is useful code for the case that you have multiple things going on in the kernel (say, at the top of the screen you use P0 for a score, at the middle, you use P0 as a character that can move left and right on the screen, and at the bottom of the screen, you have a "lives" counter).

 

Regards,

-John

Link to comment
Share on other sites

Here's my version, starting with horizontal position in A and sprite number (0 = P0, 1 = P1, 2 = M0, etc.) in X:

   sec
  sta HMCLR
  sta WSYNC
DivideLoop
  sbc #15
  bcs DivideLoop
  eor #7
  asl
  asl
  asl
  asl
  sta.wx HMP0,X
  sta RESP0,X
  sta WSYNC
  sta HMOVE

This will run in constant time, which is almost necessary for in-kernal use. Starting after the first STA WSYNC, it will end exactly 79 cycles later for all horizontal positions <= 160. Plus it's general, compact, and very easy to use. I've use this routine, or variations, in every 2600 program I've written. ;)

 

There is also a table version, something like this:

   sta WSYNC
  sec
  sta HMCLR
DivideLoop
  sbc #15
  bcs DivideLoop
  tay
  lda HMPxTable,Y;not crossing page boundary
  sta HMP0,X
  sta RESP0,X
  sta WSYNC
  sta HMOVE

You have to set up the table carefully so that either you always cross a page boundary when you read it or so that you never do (since Y will hold -1 through -15).

 

Just make sure that the STA RESP0,X instruction ends at cycle 23 when the BCS branch is not taken (i.e., the horizontal position < 15) for the timing to work.

Edited by vdub_bobby
Link to comment
Share on other sites

I used a variation of this in Stay Frosty so that Frosty's sprite and color could still be updated on scan lines that the fireballs were positioned on. There is a tradeoff, the X range is 4-147. The range can be expanded if only the sprite(and not the color) is updated, but for Stay Frosty it didn't matter as the platforms are only drawn using PF1 and PF2, so the fireballs couldn't travel that afar (well, they could on the bottom level).

 

PosPlayer1:	  ; A holds X position for player 1
	sec	  ; X holds GRP0
	sta WSYNC; Y holds COLUP0
	stx GRP0	 ; 3
	sty COLUP0; 3	6
DivideLoop1:
	sbc #15	  ; 2	8
	bcs DivideLoop1; 2   10
	eor #7	; 2   12
	asl		  ; 2   14
	asl		  ; 2   16
	asl		  ; 2   18
	asl		  ; 2   20
	sta RESP1	; 2   23 <- set object position
	sta HMP1	 ; 3   26
	sta WSYNC
	sta HMOVE
	rts

Edited by SpiceWare
Link to comment
Share on other sites

Since you weren't using Y as a scanline counter - at least for that line - you could have saved a few cycles by using the table method I posted above (at the expense of a 15-byte table). Could have an X-range of 4-159. Of course, if you don't need the range, no point in changing what works. ;)

Link to comment
Share on other sites

  • 3 weeks later...

I still don't get this code. Can someone help me? I posted my code.

 

	processor 6502
include "vcs.h"
include "macro.h"
org $F000



START
CLEAN_START

lda #$FF
sta GRP0
lda #$F0
sta COLUP0


STARTFRAME

lda #0
sta VBLANK

lda #2
sta VSYNC

sta WSYNC
sta WSYNC
sta WSYNC

lda #0
sta VSYNC

ldy #37
ldx #0
lda #0
VERT
sta WSYNC

		
	sec
  	sta HMCLR
  	sta WSYNC
DivideLoop
  	sbc #15
  	bcs DivideLoop
  	eor #7
  	asl
  	asl
  	asl
  	asl
  	sta.wx HMP0,X
  	sta RESP0,X
  	sta WSYNC
  	sta HMOVE

dey
bne VERT

ldy #192

picture
sta WSYNC



dey
bne picture

ldy #30
over
dey
sta WSYNC
bne over



jmp STARTFRAME








org $FFFA
.word START
.word START
.word START

Edited by Wickeycolumbus
Link to comment
Share on other sites

I used a variation of this in Stay Frosty so that Frosty's sprite and color could still be updated on scan lines that the fireballs were positioned on.

 

One approach you could use if you want to 'do stuff' on scan lines where you perform horizontal positioning would be to execute different routines when the object to be places is near the right of the screen than when it's near the left; in the former scenario, you'll have time to do stuff after the RESPX; in the latter scenario you'll have time before. Two caveats with this approach:

 

-1- You'll probably end up updating a sprite mid-line. Provided you have a choice of two times at least three cycles apart where the update can take place, this needn't pose a problem; simply use whichever one won't overlap the display of the sprite, and adjust the position up or down a scan line based upon whether your update happens before or after the sprite.

 

-2- Although this approach could be used to maintain a full-width non-symmetric playfield (using non-reflected mode), hitting PF2 at the right cycle for using reflected mode would mean that certain sprite positions could not be reached with a single HMOVE.

 

Still, the approach would offer the ability to offer some nice flexibility in a game with mid-frame horizontal repositioning.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...