Page 2 of 2

Re: I'm attempting bi-directional scrolling in Super Mario B

Posted: Tue Jul 14, 2015 8:20 pm
by tokumaru
Deemar wrote:I've got a Computer Science degree, 10 years of business software development experience and I know at least 10 other languages, mostly web based and object oriented application languages.
Yeah, that should help a lot. Game development is somewhat different from business programming, though. Business programming is usually very linear... things often go like this: input -> processing -> output. Games on the other hand have to perform all their tasks little bits at a time every frame, in order to create the overall impression that everything is being processed and animated simultaneously as time goes by. Just something to keep in mind.
I'll read through everything posted and I think I've decided I'm going to start by building my own scrolling environment from scratch and keep building as I go.
Yeah, this is certainly better than jumping head first into an unknown engine which uses unknown concepts in an unknown language. I suggest you get some basic stuff running, like a static background with sprites moving around. This will teach you the basics of interacting with the hardware. Then, in order to make a good game engine, you should abstract the hardware layer, by creating systems that handle the visual representation of the game world, like a scrolling system, a metasprite system, and so on.

Re: I'm attempting bi-directional scrolling in Super Mario B

Posted: Tue Jul 14, 2015 9:32 pm
by Deemar
Thanks. Should I keep posting my progress here or should I make a new topic? It'll be question heavy for sure.

Re: I'm attempting bi-directional scrolling in Super Mario B

Posted: Wed Jul 15, 2015 5:39 am
by tokumaru
I'd say here is fine, just rename the thread since this is not about SMB anymore. Other users have had their "general questions" threads before.

Re: I'm attempting bi-directional scrolling in Super Mario B

Posted: Thu Jul 16, 2015 12:56 am
by mikaelmoizt
*just thinking out loud here*

Maybe there should be some kind of sticky (or something) in the newbie section, just like "Getting started" with SMB specific questions and resources, seeing it is such a "hot topic".
There is like a hundred threads on this forum dealing with everything from bi-directional scrolling, two player mode, expanding the romfile, hacking this and hacking that

:?:

Re: Starting From Scratch With Bi-Directional Scrolling

Posted: Sun Jul 26, 2015 10:08 pm
by Deemar
I'm detemriend to leearn this in the minimal time I have available right now.
Looking at Nerdy Night Tutorial Week 6, it shows the following image:

Image

Looking at the code, I see the entire background is loaded via this code:

Code: Select all

LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down
Can someone please explain this to me? How does it know to get the specific coin image for the background? How does it know to loop the entire background?

Then I see the top 4 rows of sky and bricks are loaded with this code:

Code: Select all

  .org $E000
palette:
  .db $22,$29,$1A,$0F,  $22,$36,$17,$0F,  $22,$30,$21,$0F,  $22,$27,$17,$0F   ;;background palette
  .db $22,$1C,$15,$14,  $22,$02,$38,$3C,  $22,$1C,$15,$14,  $22,$02,$38,$3C   ;;sprite palette

sprites:
     ;vert tile attr horiz
  .db $80, $32, $00, $80   ;sprite 0
  .db $80, $33, $00, $88   ;sprite 1
  .db $88, $34, $00, $80   ;sprite 2
  .db $88, $35, $00, $88   ;sprite 3


background:
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 1
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;all sky

  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;row 2
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24  ;;all sky

  .db $24,$24,$24,$24,$45,$45,$24,$24,$45,$45,$45,$45,$45,$45,$24,$24  ;;row 3
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$53,$54,$24,$24  ;;some brick tops

  .db $24,$24,$24,$24,$47,$47,$24,$24,$47,$47,$47,$47,$47,$47,$24,$24  ;;row 4
  .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$55,$56,$24,$24  ;;brick bottoms

attribute:
  .db %00000000, %00010000, %01010000, %00010000, %00000000, %00000000, %00000000, %00110000

  .db $24,$24,$24,$24, $47,$47,$24,$24 ,$47,$47,$47,$47, $47,$47,$24,$24 ,$24,$24,$24,$24 ,$24,$24,$24,$24, $24,$24,$24,$24, $55,$56,$24,$24  ;;brick bottoms
I see it loads the palettes which will be used, I get that.
How does it know which sprites are loaded from memory? If they're all just loaded from a single .chr file, how is it getting one complete sprite at a time and not pulling random chunks from the file? How does it know specifically where that specific sprite's boundaries are within that .chr file to pull the correct data?

This is the most confusing part for me, the background section. How is this loaded exactly? Is it a full row of sky, another full row of sky, then a row with some brick tops and a row with some brick bottoms? I tried changing some of the $24 in row 3 to $45 but it didn't give me random brick tops instead of sky, the ROM never changed how it looked at all. I still had the same sky and bricks, nothing was different. Why? I even added a fifth row of brick bottoms and it didn't change anything, why? I'm assuming if I put the correct address reference for a sprite there, it'll put that piece of sprite on the screen in that position. Is that wrong?

Thanks again, this is really helping a lot.

Re: Starting From Scratch With Bi-Directional Scrolling

Posted: Sun Jul 26, 2015 10:55 pm
by mikaelmoizt
tiless.jpg
Debug -> PPU viewer

The background is a result of the nametable containing just zeroes.
As you can see, right hand side of the table is for tiles, and the left side is for sprites.

Re: Starting From Scratch With Bi-Directional Scrolling

Posted: Sun Jul 26, 2015 11:05 pm
by nicklausw
When messing with Nerdy Nights: all I'll say is, might want to add some defines such as these (probably not the best) so that the code makes more sense, and the hardware registers don't confuse you as much.

Re: Starting From Scratch With Bi-Directional Scrolling

Posted: Sun Jul 26, 2015 11:35 pm
by tokumaru
Deemar wrote:

Code: Select all

LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero
                        ; if compare was equal to 128, keep going down
Can someone please explain this to me?
The code is pretty well commented, there's not much more to it. First it sets the VRAM address to $2000, which is the beginning of the first name table, then it goes into a loop that repeats 128 times, each time reading a byte from the table named "background", sending it to VRAM and advancing to the next memory position.
How does it know to get the specific coin image for the background?
I don't see any coins in the image you posted. I see a lot of 0s, which are there probably because tile index 0 contains the number 0, and the emulator you're using cleared the name tables for you (on a real console, memory in undefined on power up).
How does it know to loop the entire background?
It's only copying 128 bytes, the rest is left untouched it seems. An entire screen is 960 (32x30 name table entries) + 64 (attribute bits) = 1024 bytes.
I see it loads the palettes which will be used, I get that.
This part is not code, it's just data, so it isn't "doing" anything. Other parts of the program are using this data to do things.
How does it know which sprites are loaded from memory?
The sprite data here are simply 4 static OAM entries. Each OAM entry is an 8x8 (or, optionally, 8x16) sprite that gets rendered to the screen. Each entry is 4 bytes long, formatted as described in the wiki.
If they're all just loaded from a single .chr file, how is it getting one complete sprite at a time and not pulling random chunks from the file? How does it know specifically where that specific sprite's boundaries are within that .chr file to pull the correct data?
The CHR data is just a dictionary of tiles that can be used by the program, but it doesn't contain any information about color or where each tile will be used. The name tables are the ones responsible for specifying which tiles go where on the screen. They are two-dimensional maps of tile indices, which the PPU scans every frame, and fetches the specified tiles from the CHR in order to draw them. The attribute tables specify which palette these tiles will use. As for sprites, the OAM entries specify which tiles get rendered at which screen coordinates, using which palettes, whether they're flipped and whether they are in front or behind the background.
Is it a full row of sky, another full row of sky
Yes, but your emulator seems to be cropping the topmost (and the bottommost) 8 scanlines of the picture, so you only see one row of sky. Some emulators do this by default because most TVs crop a similar area of the picture, and some games have glitches in those areas. As a programmer though, you should know that the full picture is always 240 scanlines, and you should disable this cropping so you can see it all.
then a row with some brick tops and a row with some brick bottoms? I tried changing some of the $24 in row 3 to $45 but it didn't give me random brick tops instead of sky, the ROM never changed how it looked at all.
It should have changed. Did you close the emulator and opened it again? Usually, resetting or power cycling isn't enough, because the emulator caches the ROM. If that isn't the problem, try comparing the modified ROM against the original one in a file comparison tool to make sure that you are successfully assembling a modified file.
I even added a fifth row of brick bottoms and it didn't change anything, why?
Adding a fifth row should indeed do nothing. Remember, this is just data, so by adding another row you're just making it available for the program to use, but since the code that draws the background is configured to read only 128 bytes, it will never read the fith row. To see that row you'd have to change the code to read 160 bytes instead of 128.
I'm assuming if I put the correct address reference for a sprite there, it'll put that piece of sprite on the screen in that position. Is that wrong?
Wait, weren't we talking about backgrounds? Be careful not to get the terminology wrong, otherwise things can get pretty confusing. Name and attribute tables are used to draw the background, while the OAM is used for drawing sprites. Which are you talking about here?

Note that this is a very basic program, and everything is hardcoded, unlike a game. The program knows which tiles to use where because that information is hardcoded there, in the form of data tables. The code simply passes that information along to the PPU, without any processing whatsoever, so that the PPU knows what to do.

It appears to me that you don't quite understand how NES graphics work yet. It's fundamental that you do, otherwise the code is going to look way more confusing than it has to be. Remember when I said that thing about learning 2 things at once? So yeah, trying to learn 6502 logic while learning about the PPU's architecture at the same time will be tough. I suggest you take a few moments with FCEUX's PPU debugging tools. Open the PPU viewer (pattern tables and palettes) and the name table viewer while walking around in games you're used to playing, so you get an idea of how things are pieced together to form what you see on the screen. FCEUX doesn't have a sprite viewer, but you can disable the background layer and see just the sprites. IIRC, Nintendulator's debugger has a sprite viewer, so you should check that out too.

Also, don't underestimate the importance of reading these wiki pages:

http://wiki.nesdev.com/w/index.php/PPU_pattern_tables
http://wiki.nesdev.com/w/index.php/PPU_nametables
http://wiki.nesdev.com/w/index.php/PPU_attribute_tables
http://wiki.nesdev.com/w/index.php/PPU_OAM
http://wiki.nesdev.com/w/index.php/PPU_palettes
http://wiki.nesdev.com/w/index.php/PPU_scrolling (don't bother with anything past "The common case" for now)

These pages describe how the PPU knows what to draw. These are the data formats the PPU understands, so you really must understand the basic idea behind the way a picture is formed in order to understand why a 6502 program is writing data formatted in a certain way to certain locations in memory.

Re: Starting From Scratch With Bi-Directional Scrolling

Posted: Mon Jul 27, 2015 3:35 pm
by tepples
tokumaru wrote:
Deemar wrote:then a row with some brick tops and a row with some brick bottoms? I tried changing some of the $24 in row 3 to $45 but it didn't give me random brick tops instead of sky, the ROM never changed how it looked at all.
It should have changed. Did you close the emulator and opened it again? Usually, resetting or power cycling isn't enough, because the emulator caches the ROM.
In FCEUX for Windows, choosing the ROM from the Recent menu is enough to reload it.
FCEUX doesn't have a sprite viewer, but you can disable the background layer and see just the sprites. IIRC, Nintendulator's debugger has a sprite viewer, so you should check that out too.
For Super NES, NO$SNS has a sprite viewer. I haven't tried NO$NES, but NO$NES is likely to have one for NES because it's by the same author and probably shares a lot of the same GUI framework. VisualBoyAdvance has one for Game Boy Advance (and for NES games in PocketNES).