8x16 and whatever else unreg wants to know

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:Shiru, I want to buy the SNES one... how do I find it?
I don't have a link (and I think we're not allowed to link to that kind of thing here), but I'm pretty sure it's available online.

Keep in mind that official manuals usually only contain explanations about the capabilities of the system, and detailed descriptions of the various registers used to control the hardware. It's nothing that will help you with the actual programming of games if you're not familiar with all the logic involved in creating a game world.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples »

To give you an idea of what to expect: At best, an official manual will be about as detailed as the official manual for something like SDL or Pygame. For example, where the SDL or Pygame docs explain the arguments of a function call, official console devkit docs might explain the bits of a register.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

Thank you tokumaru and tepples for replying. I didn't realize that the documentation was destroyed due to contractual agreements and legal stuff... I'm no longer interested. :)
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru, somewhere you wrote that if I draw 16 pixels, one metatile column, a frame... that would prevent my girl from reaching the side of the screen. Well I checked my drawRAMbuffer and drawOurColumn and both of them draw two 8pixel columns... one two to my RAMbuffer and one two to the screen, respectively. That will prevent her from reaching the edge of the screen (cause the max she moves is 10 pixels during a frame) right? Cause, she reaches the edge and I'm going insane trying to figure this out. Could it be only drawing one 8bit column of tiles? What else do you think it could it be?

edit.

edit2: Do you think keeping track of each 8 bit column of tiles with a counter would be a good idea? Or a waste of time, why? :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:Well I checked my drawRAMbuffer and drawOurColumn and both of them draw two 8pixel columns... one two to my RAMbuffer and one two to the screen, respectively. That will prevent her from reaching the edge of the screen (cause the max she moves is 10 pixels during a frame) right?
Yeah, if a character moves less than the area you can update each frame it's mathematically impossible for it to reach the edge.
Cause, she reaches the edge and I'm going insane trying to figure this out. Could it be only drawing one 8bit column of tiles? What else do you think it could it be?
I can't guess. You should be able to debug this with FCEUX or Nintendulator. Use the name table viewer to see how the column updates are working.
edit2: Do you think keeping track of each 8 bit column of tiles with a counter would be a good idea? Or a waste of time, why? :)
What do you mean keep track? Normally these things can be deduced from the camera position. For example, if the camera (it's left side) is at position $00FD, and moves to $0102 (5 pixels to the right), it crosses a 16-pixel boundary, meaning you have to draw a new column. In order to know which column to draw, you can simply add the width of the screen (256 pixels) to the camera coordinate and you'll know exactly which column you have to update.

Keeping many separate counters for things that are interconnected is an invitation for bugs, because updating everything in sync is way harder than keeping track of a few numbers/positions and calculating the rest from those whenever necessary.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru wrote:
unregistered wrote:Well I checked my drawRAMbuffer and drawOurColumn and both of them draw two 8pixel columns... one two to my RAMbuffer and one two to the screen, respectively. That will prevent her from reaching the edge of the screen (cause the max she moves is 10 pixels during a frame) right?
Yeah, if a character moves less than the area you can update each frame it's mathematically impossible for it to reach the edge.
WOOOHOOOO!!!!!!!! Thanks so much tokumaru!! :D
tokumaru wrote:
Cause, she reaches the edge and I'm going insane trying to figure this out. Could it be only drawing one 8bit column of tiles? What else do you think it could it be?
I can't guess. You should be able to debug this with FCEUX or Nintendulator. Use the name table viewer to see how the column updates are working.
Ha ha I can't do that cause the columns aren't being drawn right now; my fault :x. I'll do this! :)
tokumaru wrote:
edit2: Do you think keeping track of each 8 bit column of tiles with a counter would be a good idea? Or a waste of time, why? :)
What do you mean keep track? Normally these things can be deduced from the camera position. For example, if the camera (it's left side) is at position $00FD, and moves to $0102 (5 pixels to the right), it crosses a 16-pixel boundary, meaning you have to draw a new column. In order to know which column to draw, you can simply add the width of the screen (256 pixels) to the camera coordinate and you'll know exactly which column you have to update.
SWEET MESQUITE! I can see itwadbe inc CameraX+1 :D
tokumaru wrote:Keeping many separate counters for things that are interconnected is an invitation for bugs, because updating everything in sync is way harder than keeping track of a few numbers/positions and calculating the rest from those whenever necessary.
THANKS TOKUMARU!! :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

Kasumi[color=#00BFFF], on page 66,[/color] wrote:Continuing from this:
If cameraposition/8 - oldcameraposition/8 is not equal to 0, we moved at least one tile and need to update the nametables.
columntoupdate = cameraposition / 8.

Edit: Well, when scrolling left anyway. When scrolling right, columntoupdate = (cameraposition+256)/8
My general question is: Since I have chosen to divide my cameraposition by 16 to find my columntoupdate... does that account for the screen scrolling slower? I was thinking that maybe that's my problem where my character still reaches the edge of the screen which is mathematically impossible. Just wondering... thought I would ask, thanks. :)

edit: forgot to add this note.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: 8x16 and whatever else unreg wants to know

Post by Kasumi »

Since I have chosen to divide my cameraposition by 16 to find my columntoupdate... does that account for the screen scrolling slower?
Your scroll keeps track of a pixel position. The division is because tiles/attribute columns are not 1 pixel wide. If you move one pixel, you can still be in the same tile/attribute column. It's wherever the scroll is, divided. How fast it got there doesn't matter. (Well... if you scroll faster than 8 pixels in a frame, a tile could be skipped without extra logic. But going slow doesn't matter at all.)

The difference between dividing by 8 or dividing by 16 is just because you're choosing whether you're updating a tile at a time (8 pixels across) or two tiles at a time (16 pixels across).

Edit: So short answer: If you've implemented that correctly, that's not why the character reaches the edge of the screen.

Edit2: More edition: Your character's on screen position is their actual position minus the scroll. When a character is in the middle of the screen while moving right, it means that the scroll position and the character's position are increasing at the same rate. (128-0 is 128. 256-128 is 128. 404-276 is 128.) They reach the edge of the screen when the scroll is not allowed to increase further with the character's position. Level is 1024 pixels wide, scroll has a maximum of 768. If the player moves beyond 896, they are now more than 128 pixels from the scroll. If they keep moving right, they will get closer to the edge of the screen because the scroll cannot follow them further.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

Kasumi wrote:Edit2: More edition: Your character's on screen position is their actual position minus the scroll.
!!!!!!THANKS KASUMI!!!!! The rest of your post is really helpful... I just quoted that part because I totally forgot that and your reminder is so appreciated!! :D Thank you for your entire enabling and extremely helpful post!! :D :mrgreen:

edit.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

unregistered[color=#FFBF80], on page 48,[/color] wrote:...FCEUX's debugger is so great!! :D I think I've learned what step-over and step-out do too!
    • Step-over allows you to run the code that the method jsrs to but skip it entirely; it skips to the next line!
    • Step-out let's you step out of a method and it also skips to the same next line that step-over would have skipped to... that's there for people like me who accidentally press step-into too many times. :)
Now debugging is even faster! :D Please correct me on anything I've not described correctly... it's just what I've noticed while debugging.
I just figured out something else about Step-out... sometimes after pressing Step-out I get a message "A Step-out is already in progress... cancel it and run a new Step-out?" and I never understood that until today. Here is what my code looks like in the debugger...

Code: Select all

[draw_RAMbuffers]
  sta $FF
  ...
  jsr colors
  [colors] 
    sta $FF
    ...
    rts
  rts
lda iBeginAtOne
...tokumaru gave me the idea of setting a breakpoint for a write to address $ff and so each sta $ff causes my debugger to take a break.

So, today, I returned to my computer and found it inside draw_RAMbuffers taking a break at its sta $ff. Then I thought I would like to Step-out of draw_RAMbuffers and I'd be at the first instruction after draw_RAMbuffers ends... the lda iBeginAtOne. But :shock: that didn't happen!! It stopped at another sta $ff instead :x and I became mad thinking I had clicked the Step-out button, but it misunderstood me and had responded to the Run button being clicked. I had a feeling that this had happened before. :evil:

OH GOODNESS GEE! I need to go run before it gets too dark... sorry brb...
edit:back. Ok... I was very mad... for totally the wrong reason. ...I'll explain...

edit2: ...wooooooooooah.... water with ice is excellent!!! :D... ... ...my feeling of it happening before was because these exact feelings had happened like at least twice in the past... but this time I handled it well. I clicked Step-out again and it gave me another message like, "A Step-out is already in progress... cancel it and run a new Step-out?"... and I had noticed that colors runs at the end of draw_RAMbuffers ...and so I thought well maybe it could be working correctly now...maybe I should click the no button (that would be the first time clicking the "no" button... all the other times I clicked "yes".). I clicked the no button and after an uncertain pause I then clicked the Run button AND IT PAUSED AT lda iBeginAtOne!!! :o :D :D

Food is here Amazing Race is starting. Must go eat!

last edit. (frosty the snowman rocks! : ))

edited once more because I needed to add a note above.
Last edited by unregistered on Wed Apr 29, 2015 3:34 pm, edited 1 time in total.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

tokumaru[color=#00BFBF], on page 50,[/color] wrote:The exact formula obviously depends on how your maps are stored, but the typical way to convert pixel coordinates into map offsets is more like (y / MetatilesWidth) * NumberOfMetatilesPerRow + (x / MetatileHeight).
tokumaru[color=#00BFBF], a few posts further down... also on page 50,[/color] wrote: The formula for reading data from a 2D array which is stored in memory linearly is always Y * ElementsPerRow + X, that doesn't change. But you also have to take into consideration that the base unit is the type of element you are accessing, in this case, metatiles. If you have pixel coordinates, you have to first convert them to metatile coordinates, hence the need to divide both X and Y by the dimensions of your metatiles before applying that formula.
I highlighted your words so that others might read all of them. The problem I'm experiencing now is that my code is working weirdly... and I was wondering, well, I'm trying to use metatile with a row-length of 32. So my pseudo code almost reads like

Code: Select all

	;Calculate the index of the metatile: (Y / 16) * 32 + (X / 16) = LINEAR_POSITION  p.50  -Not me.-
   ;= ... (Y / 16) * (2 * 16) + (X / 16)
	;= ... ((Y / 16) * 16) * 2 + (X / 16)
Is that correct? I mean... is it ok that I'm trying to cram two screens of 16x16 metatiles into one row?
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered »

qbradq[color=#8080FF], on [url=http://forums.nesdev.com/viewtopic.php?p=102563#p102563]page 54[/url],[/color] wrote:How are you storing your collision data? That has a lot to do with how to scroll it :D
My collision data is kept in a 15 rows by 32 columns table in 0600-07DF. This is so I don't have to scroll it... I just have to update it once every two screens. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

unregistered wrote:

Code: Select all

;= ... (Y / 16) * (2 * 16) + (X / 16)
;= ... ((Y / 16) * 16) * 2 + (X / 16)
Is that correct?
Looks correct to me. Take care with that optimization you did though: you might look at (Y / 16) * 16 and feel tempted to skip all the shifting, but then you'll be keeping the lower 4 bits of Y, which will screw up the result when you add (X / 16) later. The correct way to optimize this formula is (Y AND $F0) * 2 + (X / 16). Multiplications and divisions are obviously done by shifting bits.

Also, since you have only 2 screens worth of collision data, you should ignore the higher bits (you only need bits 0 through 8) of the X coordinate, otherwise you might end up with a pointer to a memory location past the area you have defined for collision data.
unregistered wrote:My collision data is kept in a 15 rows by 32 columns table in 0600-07DF.
If you add $600 to the result from the formula above, you'll end up with a 16-bit pointer you can use to read from this table. You could even skip adding (X / 16) to the pointer and put that into the Y registers instead. The complete code might look like this:

Code: Select all

lda PixelY ;8-bit Y coordinate
and #$0f ;same as shifting right 4 times and then left 4 times
asl ;shift one more time to complete the multiplication by 32
sta Pointer+0 ;the low byte of the pointer is ready
lda #$06 ;prepare to add the high byte of the base address
adc #$00 ;add to the highest bit (carry) of PixelY * 32
sta Pointer+1 ;the high byte of the pointer is ready
lda PixelX+1 ;high byte of 16-bit X coordinate
lsr ;get the only bit we need from it
lda PixelX+0 ;low byte of the 16-bit X coordinate
ror ;put the high bit in
lsr ;shift 3 times to complete the division by 16
lsr
lsr
tay ;put the row offset in the index register
lda (Pointer), y ;get the collision data
This is just one way to do it. Another approach would be to store the collision data a bit differently, as 2 16x15 blocks, instead of a single 32x15 one. That way you could use only the lower bytes of the coordinates to form an 8-bit index and check the 9th bit of the X coordinate to decide between reading from the first or the second collision table. The options are endless, so pick what works best for you. =)
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples »

tokumaru wrote:Another approach would be to store the collision data a bit differently, as 2 16x15 blocks, instead of a single 32x15 one.
This is what Super Mario Bros. does: a 32x13-metatile sliding window stored as two 16x13 halves.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru »

tepples wrote:This is what Super Mario Bros. does: a 32x13-metatile sliding window stored as two 16x13 halves.
This might be a good approach because it better matches the name table layout, in addition to the possibility of accessing any part of each table with an 8-bit index.
Post Reply