Any Atari sprite algorithm you know of?
Moderator: Moderators
-
- Posts: 318
- Joined: Mon Jan 30, 2017 5:20 pm
- Location: Colorado USA
Any Atari sprite algorithm you know of?
I tried asking for help on AtariAge and those people were kind of jerks, so I figured I'd ask you. I have one way that would have a register increment every TIA cycle, and then have another register increment every scanline, but that would eat up a lot of precious CPU cycles and ROM space, so how would I do that? I can understand moving sprites vertically, you could just increment a register during horizontal retrace. But how would I do horizontal movement?
Re: Any Atari sprite algorithm you know of?
Interesting side note. Besides producing 5 popular game consoles (2600, 5200, 7800, Jaguar, Lynx), Atari also sold many popular home computers (400,800,1200xl, etc.).
I can't just assume that you mean a specific console, when you say "Atari". So, you should probably say "2600" if that's what you mean.
Also, dude, are you for real?
I can't just assume that you mean a specific console, when you say "Atari". So, you should probably say "2600" if that's what you mean.
Also, dude, are you for real?
nesdoug.com -- blog/tutorial on programming for the NES
Re: Any Atari sprite algorithm you know of?
The one with TIA video is the 2600.
Re: Any Atari sprite algorithm you know of?
You can't possibly increment a register every TIA cycle. The TIA is 3 times faster than the CPU, and INX/INY take 2 CPU cycles, so the minimum you can have is one increment every 6 TIA cycles/pixels. But this is not how you go about positioning sprites anyway.
If you never reuse objects during the frame, moving objects can be really simple, because they retain their positions from one frame to the next, so you can simply use the HMOVE registers to move stuff up to 8 pixels to the left or 7 pixels to the right. If you're not comfortable with timing all the RESET writes, you can even reset everything to the far left and use HMOVE across several scanlines to get everything to the correct positions.
If you do need to reposition sprites mid-screen though, you better get acquainted with the method of counting cycles and resetting them near the desired position and adjusting with HMOVE. There are countless general-purpose routines for this that anyone can use, if you don't want to write your own.
As for vertical positioning, that happens completely in software, since the TIA itself only has enough state for 1 scanline (or even less, if you consider that the playfield is mirrored or reflected), so it's entirely up to you to count scanlines and figure out what should be displayed when.
One simple way to do it is to maintain an scanline counter in RAM, and every scanline (or every other scanline, in the case of a 2-scanline kernel) subtract the sprite's position from the scanline index, so that the result is the index of the row of graphics to use. If the row is valid, use it to fetch the graphics, otherwise, clear the graphics to make the object invisible. For example, say you find yourself with the following state:
Scanline: 27
SpriteY: 28
Sprite height: 16
GraphicsRow = 27 - 28 = -1
The result is not a valid row (i.e. between 0 and 15), so the sprite should not be displayed. Then, on the next scanline:
Scanline: 28
SpriteY: 28
Sprite height: 16
GraphicsRow = 28 - 28 = 0
Now we have a valid graphics row index, that can be used to fetch sprite patterns, by loading this index in Y and indexing from a pointer. The row index will remain valid until scanline 43. After that, we have the following situation:
Scanline: 44
SpriteY: 28
Sprite height: 16
GraphicsRow = 44 - 28 = 16
Index 16 is no longer valid, so we can stop drawing the sprite. If you were paying attention, you may have noticed that a single verification can tell you whether the index is valid, since negative numbers in 2's complement are > 127, so the check for > 15 will also catch negative numbers:
As long as you have 128 or less scanlines where this sprite can be. There are several ways to optimize this further, but this is the basic idea.
If you never reuse objects during the frame, moving objects can be really simple, because they retain their positions from one frame to the next, so you can simply use the HMOVE registers to move stuff up to 8 pixels to the left or 7 pixels to the right. If you're not comfortable with timing all the RESET writes, you can even reset everything to the far left and use HMOVE across several scanlines to get everything to the correct positions.
If you do need to reposition sprites mid-screen though, you better get acquainted with the method of counting cycles and resetting them near the desired position and adjusting with HMOVE. There are countless general-purpose routines for this that anyone can use, if you don't want to write your own.
As for vertical positioning, that happens completely in software, since the TIA itself only has enough state for 1 scanline (or even less, if you consider that the playfield is mirrored or reflected), so it's entirely up to you to count scanlines and figure out what should be displayed when.
One simple way to do it is to maintain an scanline counter in RAM, and every scanline (or every other scanline, in the case of a 2-scanline kernel) subtract the sprite's position from the scanline index, so that the result is the index of the row of graphics to use. If the row is valid, use it to fetch the graphics, otherwise, clear the graphics to make the object invisible. For example, say you find yourself with the following state:
Scanline: 27
SpriteY: 28
Sprite height: 16
GraphicsRow = 27 - 28 = -1
The result is not a valid row (i.e. between 0 and 15), so the sprite should not be displayed. Then, on the next scanline:
Scanline: 28
SpriteY: 28
Sprite height: 16
GraphicsRow = 28 - 28 = 0
Now we have a valid graphics row index, that can be used to fetch sprite patterns, by loading this index in Y and indexing from a pointer. The row index will remain valid until scanline 43. After that, we have the following situation:
Scanline: 44
SpriteY: 28
Sprite height: 16
GraphicsRow = 44 - 28 = 16
Index 16 is no longer valid, so we can stop drawing the sprite. If you were paying attention, you may have noticed that a single verification can tell you whether the index is valid, since negative numbers in 2's complement are > 127, so the check for > 15 will also catch negative numbers:
Code: Select all
lda Scanline
sbc SpriteY
cmp SpriteHeight
bcc Fetch
lda #$00
beq Draw
Fetch:
lda (SpritePattern), y
Draw:
sta GRP0
Re: Any Atari sprite algorithm you know of?
I realize that Spiceware's tutorial might be a bit much for a beginner, but Andrew Davie's tutorial that you linked to in your AtariAge post has all this information. People here and on AtariAge are pretty willing to help, but, like people have been saying to you both here and there, you'll get a lot better answers to your questions if you refer to the tutorial, and then ask questions specifically based on what you read. It's not likely that a forum reply is going to have more in-depth explanation than 3 chapters of a tutorial, unless you have a very specific question about a part of the tutorial that you didn't understand.DementedPurple wrote:I tried asking for help on AtariAge and those people were kind of jerks, so I figured I'd ask you. I have one way that would have a register increment every TIA cycle, and then have another register increment every scanline, but that would eat up a lot of precious CPU cycles and ROM space, so how would I do that? I can understand moving sprites vertically, you could just increment a register during horizontal retrace. But how would I do horizontal movement?
So to answer your question, read
Chapter 21 - Sprites
Chapter 22 - Sprite Horizontal Positioning
Chapter 23 - Sprite Vertical Positioning
then if you're still confused about it, put a post in the 2600 Programming for Newbies section of the AtariAge forums, and ask about the parts you didn't understand.
My games: http://www.bitethechili.com
Re: Any Atari sprite algorithm you know of?
It seems to me that you don't have the patience to go through an entire tutorial, like most beginners do. For some reason you want to skip all the basics and go straight to the "good stuff". Problem is, skipping stuff is clearly not working well for you. It's already been a while since you first started asking about iNES headers here, and from one of your recent threads it looks like you still aren't able to assemble a working ROM.
Anyone who follows the Nerdy Nights tutorials property can get a simple sprite moving on the screen in a few hours, but you, in your attempt to "save time" by not reading any of the uninteresting stuff, couldn't do that in months.
Please take some time to revise your strategy and the way you're approaching retro game development. There are no shortcuts for becoming a good programmer, and you certainly won't be coding anything impressive on your first few tries, but all the boring stuff you go through will prepare you for more interesting projects.
Sometimes when you find the existing documentation overwhelming, you come to the forum hoping to find a simpler answer, but like I said before, there are no shortcuts. The documentation wasn't made exceedingly complicated for the heck of it, the subjects are actually that complicated, and we can't possibly compact all the information in a short forum post that's easier to understand. We can, however, clarify parts of the documentation you don't understand, explain certain details differently or even give a simpler overview of a complex subject that might help you get started, but certainly won't give you everything you all the answers.
Anyone who follows the Nerdy Nights tutorials property can get a simple sprite moving on the screen in a few hours, but you, in your attempt to "save time" by not reading any of the uninteresting stuff, couldn't do that in months.
Please take some time to revise your strategy and the way you're approaching retro game development. There are no shortcuts for becoming a good programmer, and you certainly won't be coding anything impressive on your first few tries, but all the boring stuff you go through will prepare you for more interesting projects.
Sometimes when you find the existing documentation overwhelming, you come to the forum hoping to find a simpler answer, but like I said before, there are no shortcuts. The documentation wasn't made exceedingly complicated for the heck of it, the subjects are actually that complicated, and we can't possibly compact all the information in a short forum post that's easier to understand. We can, however, clarify parts of the documentation you don't understand, explain certain details differently or even give a simpler overview of a complex subject that might help you get started, but certainly won't give you everything you all the answers.
Re: Any Atari sprite algorithm you know of?
^That post needs to be stickied or something
Re: Any Atari sprite algorithm you know of?
Dictionary of Phrase and Fable, E. Cobham Brewer, 1894 wrote: Euclid, having opened a school of mathematics at Alexandria, was asked by King Ptolemy whether he could not explain his art to him in a more compendious manner. “Sir,” said the geometrician, “there is no royal road to learning.”
-
- Posts: 318
- Joined: Mon Jan 30, 2017 5:20 pm
- Location: Colorado USA
Re: Any Atari sprite algorithm you know of?
I have one more question. The tutorial says you need to divide by 15 to figure out how many CPU cycles you wait before writing to the Sprite Reset registers, and it says you can do it with this code:
Which makes me wonder, would it be possible to divide by 15 using only bit-operations and maybe increments? I would think that you could because 15 in hexadecimal is F
Code: Select all
Divide15
.POS SET 0
REPEAT 160
.byte .POS / 15
.POS SET .POS + 1
REPEND
-
- Posts: 271
- Joined: Sun Mar 27, 2011 10:49 am
- Location: Victoria, BC
Re: Any Atari sprite algorithm you know of?
No, but you can divide by 16 using only bit shifts, because binary is a base 2 system and 16 is a power of 2.
It's the exact same principle as why you can divide by powers of 10 in our decimal base 10 system using only a "digit shift" - e.g. 600/10 = 60, or 600/100 = 6.
At any rate: that code isn't dividing at run time on the 2600, it's dividing at assembly time, so it really doesn't matter how you do the division.
It's the exact same principle as why you can divide by powers of 10 in our decimal base 10 system using only a "digit shift" - e.g. 600/10 = 60, or 600/100 = 6.
At any rate: that code isn't dividing at run time on the 2600, it's dividing at assembly time, so it really doesn't matter how you do the division.
Re: Any Atari sprite algorithm you know of?
That code is building a look-up table at assembly time, so that the 6502 code can quickly look up the answer of any division by 15 at runtime, it doesn't get any faster than this.
Most TIA object positioning routines I've seen perform the division in real-time, because a subtraction loop can be made to take 5 cycles (or 15 pixels) per iteration:
This would take the same amount of time as if you were DEX'ing a value loaded from a look-up table, but without the look-up table, saving you 160 bytes of precious ROM space.
Most TIA object positioning routines I've seen perform the division in real-time, because a subtraction loop can be made to take 5 cycles (or 15 pixels) per iteration:
Code: Select all
lda ObjectX
DivideBy15
sbc #15
bcs DivideBy15
sta RESxx
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
Re: Any Atari sprite algorithm you know of?
tokumaru wrote:It seems to me that you don't have the patience to go through an entire tutorial, like most beginners do. For some reason you want to skip all the basics and go straight to the "good stuff". Problem is, skipping stuff is clearly not working well for you. It's already been a while since you first started asking about iNES headers here, and from one of your recent threads it looks like you still aren't able to assemble a working ROM.
DementedPurple's only 12, I think what's going on is he's growing up in the 21st century, and the world is damn noisy. So much information coming from all angles. Gets into coding. Gets interested in retro games. Finds SO MUCH INFORMATION ABOUT IT. Gets excited about EVERYTHING. I had *some* of this as a teenager but there was so much less available out there, that it constrained what I could even do and I think it helped give me some focus? (completely by accident of having been born in the 80's, thus, less access to internet at same full-of-energy age) That's why I keep recommending to try something like Pico 8 and stick with that for a while. What do you think DementedPurple? Perhaps even seek out a mentor. Mentors can help you stay focused, too. That's a bit of an arcane idea these days too, isn't it? We just use google now I guess, no need to ask a human for help. Oh well.dougeff wrote: Also, dude, are you for real?
That was part old man rant and part "gee I wish I could help this kid focus." I sincerely wish you the best whatever you wind up digging into.
-
- Posts: 3140
- Joined: Wed May 19, 2010 6:12 pm
Re: Any Atari sprite algorithm you know of?
I don't think this is a dumb question at all, because getting the Atari 2600 to display sprites requires a lot of CPU optimization because it has to do all the sprite multiplexing, while always taking 76 cycles.
- GradualGames
- Posts: 1106
- Joined: Sun Nov 09, 2008 9:18 pm
- Location: Pennsylvania, USA
- Contact:
Re: Any Atari sprite algorithm you know of?
I don't think anybody thought this was a dumb question; we're just alarmed at the number of things DementedPurple is trying to tackle, and gently suggesting things to maybe focus on for a while first. It's all up to him in the end though
-
- Posts: 318
- Joined: Mon Jan 30, 2017 5:20 pm
- Location: Colorado USA
Re: Any Atari sprite algorithm you know of?
I'd imagine my autism doesn't help with this...Gets excited about EVERYTHING.
One of the traits my autism gives me is that when I have an interest in something, I tend to get too excited about that thing, which might be why I post so frequently. But obviously I'm on the low-end of the spectrum because I'm able to talk, walk, and pretty much everything anyone else can, as a matter of fact, I think my autism is more of an advantage rather then a disability, I mean, I probably wouldn't know how to program without it! So the point is, sorry, I'll try to do more research before asking questions on forums.