Jump to content
IGNORED

Can someone explain pointers to me?


Recommended Posts

...and how they're used for animated sprites?

 

I've looked at multiple examples and it still makes no sense.

 

I honestly have no idea what language you're talking about, but having a general knowledge of what pointers are can go a long way.

 

In short, you use pointers to access addresses in memory. This is useful if you want to read side-by-side variables with really efficient code.

 

For example, if I wanted to animate an 8x8 sprite, I would first set up each frame sequentially (following the first frame). To animate, you would set the pointer to the address of the first frame, and then add 8 to the pointer to go to the next frame, and so on.

 

I'm pretty sure you've heard that before, so what's causing trouble for you?

Link to comment
Share on other sites

I honestly have no idea what language you're talking about, but having a general knowledge of what pointers are can go a long way.

 

Sorry, 6502 Assembly

 

For example, if I wanted to animate an 8x8 sprite, I would first set up each frame sequentially (following the first frame). To animate, you would set the pointer to the address of the first frame, and then add 8 to the pointer to go to the next frame, and so on.

 

I've been trying to do this but I'm having trouble with it.

 

I'm pretty sure you've heard that before, so what's causing trouble for you?

 

I'm confused about the whole high and low pointers thing and how to animate a sprite. I guess I don't understand it enough. Any links/resources I could check out?

Link to comment
Share on other sites

 

Sorry, 6502 Assembly

 

 

I've been trying to do this but I'm having trouble with it.

 

 

I'm confused about the whole high and low pointers thing and how to animate a sprite. I guess I don't understand it enough. Any links/resources I could check out?

 

Random Terrain's Page is a good source for almost all 2600 programming, along with the 6502 Opcodes List. And you can always ask me :)

 

There are multiple ways to accomplish this. The most efficient way would be to use the X register as a pointer to go through the frames. Just read the row by LDA row_foo,X and add 8 to the X register as often as needed

 

You won't need to do it any other way for sprites but for maps it can be really handy to store an address in memory and go off that address. These are "true" pointers, and work by storing the entire address of a variable (say my map is at 0xF000) in ram. To access the data pointed to by them you would use an opcode like LDA (foo_pointer)

 

Finally, I'll try to explain the high and low bytes. An absolute address on the 6502 is two bytes long. The high byte is equivalent to the 1 in 10, while the low byte is equivalent to the 0. On big endian machines, the high byte comes first, and on little endian it's the opposite. The 6502 is big endian the last time I checked, but I'm probably wrong so it wouldn't hurt to check yourself

  • Like 1
Link to comment
Share on other sites

I've actually been using those exact links lol

They've been very helpful so far.

 

I try to be as self-sufficient as I can, but sometimes I can't figure something out.

 

Thanks!

 

 

Finally, I'll try to explain the high and low bytes. An absolute address on the 6502 is two bytes long. The high byte is equivalent to the 1 in 10, while the low byte is equivalent to the 0. On big endian machines, the high byte comes first, and on little endian it's the opposite. The 6502 is big endian the last time I checked, but I'm probably wrong so it wouldn't hurt to check yourself

 

I don't get it. What do you mean by "comes first"?

Edited by Electrk
Link to comment
Share on other sites

I don't get it. What do you mean by "comes first"?

Comes first in RAM. Let's say you have the number 256 (0x100 in hex). You store it in a big endian machine, and in memory it looks like the bytes 0x01 0x00. On a little endian, it looks like 0x00 0x01.

Link to comment
Share on other sites

Comes first in RAM. Let's say you have the number 256 (0x100 in hex). You store it in a big endian machine, and in memory it looks like the bytes 0x01 0x00. On a little endian, it looks like 0x00 0x01.

 

How does that affect programming?

Link to comment
Share on other sites

I guess I just don't understand why it's used/what it's useful for

It's kinda useless compared to other methods for sure, but if your sprite is at address 0xF000 you could keep the high byte(0xF0) and increment the low byte

Edited by Gip-Gip
Link to comment
Share on other sites

It's kinda useless compared to other methods for sure, but if your sprite is at address 0xF000 you could keep the high byte(0xF0) and increment the low byte

 

I'm really not getting this, sorry. I'll just have to read more, I guess.

My problem has been solved though as I got sprite animation to work. Thank you!

  • Like 1
Link to comment
Share on other sites

 

I'm really not getting this, sorry. I'll just have to read more, I guess.

My problem has been solved though as I got sprite animation to work. Thank you!

No problem. It took me a while too; it isn't that easy to learn entirely new concepts. Hope everything works out!

  • Like 1
Link to comment
Share on other sites

When you see < and >, you are seeing the 8 bit 6502 handle a 16 bit number. Think of it like our use of comma when writing a big number- like 65,536. Telling the machine to LDA <... and LDA >... would be like saying fetch the 536 and then fetch the 65 from the above number. Note- since we only use binary, 65,536 is really 11111111,11111111. So that's 16 1s. We fetch 8 at a time to move the whole number.

 

In your case, you are fetching a memory address, those are 16 bits so you have to do it this way.

  • Like 2
Link to comment
Share on other sites

Pointers are used because the Atari's graphics are done one line at a time.

 

For example, if your sprite starts at line 100 of the screen, you would set your pointer 100 places above your graphics in the code. The code in that location is useless to you and is not used. The goal is to just start counting from there. So when your kernel reaches line 100, your pointer has also moved 100 places to the exact starting point of the graphics you want on the screen. Then at line 101, the pointer is on the second line of your graphics, and so on.

  • Like 2
Link to comment
Share on other sites

When you see < and >, you are seeing the 8 bit 6502 handle a 16 bit number. Think of it like our use of comma when writing a big number- like 65,536. Telling the machine to LDA <... and LDA >... would be like saying fetch the 536 and then fetch the 65 from the above number. Note- since we only use binary, 65,536 is really 11111111,11111111. So that's 16 1s. We fetch 8 at a time to move the whole number.

 

In your case, you are fetching a memory address, those are 16 bits so you have to do it this way.

 

This is a great explanation! It makes a lot more sense now. Thank you!

Edited by Electrk
Link to comment
Share on other sites

Have you worked through my Collect tutorial? Do note the blog shows newest first, so start at the bottom of page 2.

 

 

In short pointers point at things. In computers they point to memory. Consider this bit of code:

 

lda #7
lda $7


The two instructions look very similar, but do different things. The first takes the value of 7 and puts it in the accumulator. In the second instruction the number points to where the value is - and the value found there is what ends up in the accumulator (on the 2600 that'd be TIA register CXPPMM). So that second LDA is using a pointer. In this case it's a fixed pointer because it always points to the same place.

 

To make things more interesting, you can add the X or Y register into the mix like this:

 

ldx #1
ldy #2
lda $F800,x
lda $F800,y
...
; location $F800
.byte $00, $05, $0a, $0f, ...


So in this example we take the pointer, add X or Y to the pointer to get a new pointer, then go there to find the data. The lda $F800,x would end up going to $F801 and put the $05 it finds there into the accumulator. The lda $F800,y would go to $F802 so the accumulator ends up with $0f. Adding labels makes the code clearer:

 

ldx #1
ldy #2
lda Times5,x
lda Times5,y
...
; location $F800
Times5:  .byte $00, $05, $0a, $0f, ...

Using pointers like this is handy for things like the playfield in games like Combat because those graphics don't change. They're not that useful for an animated sprite. For those we end up using a pointer that points to a pointer. This is known on the 6502 as Indirect mode. This instruction:

lda ($80),y

is an example of that. The first pointer is the $80, which points to address $80 in the computer. Address $80 and $81 (because we need a 16-bit address and only 8 bits can be held in a memory location) point to the next location. Finally add in Y to find the final location in memory to fetch the value from. The value in the parentheses must be $00-$ff, which is known as zero page memory.

 

lda #<$F800
sta $80
lda #>$F800
sta $81
ldy #1
lda ($80),y
ldy #2
lda ($80),y

lda #<$F880
sta $80
lda #>$F880
sta $81
ldy #2
lda ($80),y
ldy #3
lda ($80),y

; location $F800
.byte $00, $05, $0a, $0f, ...
; location $F880
.byte $00, $0a, $14, $1e, ...

Similar to before, but the first set of lda ($80),y return $05 and $0a while the second set return $14 and $1e. As before, labels help clarify things:

TimesTablePtr = $80

lda #<Times5
sta TimesTablePtr
lda #>Times5
sta TimesTablePtr+1
ldy #1
lda (TimesTablePtr),y
ldy #2
lda (TimesTablePtr),y

lda #<Times10
sta TimesTablePtr
lda #>Times10
sta TimesTablePtr+1
ldy #2
lda (TimesTablePtr),y
ldy #3
lda (TimesTablePtr),y

; location $F800
Times5: .byte $00, $05, $0a, $0f, ...

; location $F880
Times10: .byte $00, $0a, $14, $1e, ...

 

The instructions for DASM has this to say about the < and >:

20 <exp take LSB byte of a 16 bit expression

20 >exp take MSB byte of an expression

LSB is Least Significant Byte while MSB is Most Significant Byte. A 16-bit address written in hex is comprised of 4 digits, such as $1234. The LSB is the $34 part of the address while the MSB is the $12 part.

 

For the instructions

lda #<Times10
lda #>Times10

the compiler first replaces the labels with the values:

lda #<$F880
lda #>$F880

It then extracts the MSB and LSB:

 lda #$80
lda #$F8

When prepping indirect pointers the LSB goes into Pointer while MSB goes into Pointer+1

 

 

Note: there is an indirect mode using X, but it works different than the one with Y. You can ignore it for now, and maybe forever. I've never used it myself, and I started coding 6502 assembly on my VIC 20 back in 1982.

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

 

Ha!- Lost you where? Do you know how a television draws its pictures?

 

OH

jesus

 

for some reason I read that as putting the pointer 100 lines above where the graphics start in the actual code. I was like "what the fuck that doesn't make any sense" lol

your post makes sense now

Edited by Electrk
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...