6502 Newbie / First Game Prototype

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
NEStor
Posts: 4
Joined: Fri Aug 30, 2024 12:35 am
Location: Germany

6502 Newbie / First Game Prototype

Post by NEStor »

Hello NesDev community!

Making an own full-fledged game for a retro console like the NES has always been one of my biggest dreams. I often tried to learn Assembly but then gave up quickly.
It was when I stumbled upon Gustavo Pezzis (Pikuma.com) 6502 NES Assembly course, that I began to understand Assembly & the NES hardware structure.

I completed the course and would say that I am now over the "beginner" level. What I am quite comfortable with is:
- Load up Background tiles to nametables
- Load up palettes and attributes
- Load up multiple Sprites/MetaSprites
- Move Sprites around the screen by controller input
- Very simple AI (random sprite spawning/movement)
- Sprite to Sprite Collision
- Switching CHR banks
- Split Screen (Sprite0)

However I still can't figure out how to do an own small game.
Scrolling is giving Me a lot of headaches, so I would prefer for my first project not to do scrolling.
My idea was to do a top-down zelda like game with single screens that are transition from one to another.
I love the classic Final Fantasy Adventure (Mystic Quest) on the Game Boy and would love to create a "prototype" on the NES in that style.

What I have so far is:
CHR file with tiles for the player, one NPC, one enemy, one boss and background tiles for a overworld map and one for a dungeon.
In the current project I loaded up the first nametable with a overworld screen. Player Sprite can be moved around by Controller Inputs.
The enemy sprite is moving around randomly.

What I am struggling to accomplish is:
I am unsure how to do sprite animations (for the player and the enemy)
.
Also I have no idea how to implement background collision. I restricted the player movement to the edges of the screen, but the player can move through all the tiles, including trees and walls etc.
Where do I store and check tile definitions? I need at least to check if a tile is solid or not. Would also like to make tiles act as a "trigger" to start a event or something else.

How can I progress the player from one screen to another? For example if I move to the edge of a map where is not solid tile, it should transition to the next screen. On the next screen I should also be able to go back to the previous screen and so on.

It is really difficult to find more "advanced" tutorials.
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

Background collision is
TileX = PixelX/SizeOfTileX
TileY = PixelY/SizeOfTileY

maybe you set your collision in 8x8 blocks, maybe 16x16 block maybe 32x32 blocks, depends on your game. Where do you store your collision map, in RAM somewhere.

Player animations, you change which tile the player sprite shows, so the image changes, and then you change it every so many frames.

Transition screen.
If Player X > X_right_side_of_playarea then "go to next screen"
If Player X < X_left_side_of_playarea then "go to prev screen"
and likewise with the Y
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

I have a SNES port of my C64 game, there is also a CX16 port. So its not 1:1 a NES, but there is an 8bit only code that is 99.98% 6502, and it is heavily commented, which will help you understand the "engine aspects" https://github.com/oziphantom/QwakSNES
User avatar
tokumaru
Posts: 12454
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 6502 Newbie / First Game Prototype

Post by tokumaru »

NEStor wrote: Fri Aug 30, 2024 1:01 amI am unsure how to do sprite animations (for the player and the enemy)
At the simplest level, an animation is just a sequence of frames, each one displayed for X amount of time. For an NES game, you could store this information in ROM in a straightforward way like this:

Code: Select all

PlayerAttackAnimation:

;frame header
.db 4, 6 ;first frame has 4 sprites and displays for 6 NES frames

;first frame
.db $f8, $f8, $10, $00 ;relative X, relative Y, tile, attributes
.db $00, $f8, $11, $00
.db $f8, $00, $12, $00
.db $00, $00, $13, $00

frame header
.db 4, 4 ;second frame has 4 sprites and displays for 4 NES frames

;second frame
.db $f8, $f8, $14, $00 ;relative X, relative Y, tile, attributes
.db $00, $f8, $15, $00
.db $f8, $00, $16, $00
.db $00, $00, $17, $00

;loop command
.db $80 ;since it's impossible for frames to use 128+ sprites, we can use bit 7 as a flag for special commands
.dw PlayerAttackAnimation ;address of which animation frame to display next
Then you need to set aside some RAM for each object, allowing them to keep track of which animation frame they're in (a 16-bit address, that you can use when generating OAM entries for the object) and how long to wait until the next frame (an 8-bit counter). Next, you need a couple of functions to make this whole thing work:

A "StartAnimation" function can be used to set an object's animation pointer and initialize the delay counter for the first frame. You can call this function whenever an action that requires a new animation happens.

You also need a "PlayAnimation" function, that you call every frame for each object. It will decrement the delay counter, and when it reaches 0 it will advance to the next animation frame, updating the animation pointer and setting the new value for the delay counter. This function also needs to process special commands, such as "jump" or "stop".

Lastly, a "DrawSprite" function has to be used every frame on every object so that the correct animation frame for each one is actually displayed for players to see. Basically this function will take the pointer to the object's current animation frame and process each sprite, generating OAM entries. Normally you'd take the relative X and Y coordinates, add them to the object's reference coordinates, and if the resulting coordinates are not off-screen, you write them to the OAM buffer (usually $0200-$02ff) along with the tile index and attribute byte.

This is the basic gist of sprite animations. It's not ridiculously easy to do but not terribly advanced either. Take some time to design a good animation script format that works for you, code these few functions that make use of this data, and you're pretty much done.
Pokun
Posts: 2852
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 6502 Newbie / First Game Prototype

Post by Pokun »

NEStor wrote: Fri Aug 30, 2024 1:01 am Scrolling is giving Me a lot of headaches, so I would prefer for my first project not to do scrolling.
My idea was to do a top-down zelda like game with single screens that are transition from one to another.
Known as the "flip-screen" technique. It's a very sound idea as scrolling is a pretty advanced subject, flip-screens are easy to implement and just works very well for many types of games.


NEStor wrote: Fri Aug 30, 2024 1:01 am It is really difficult to find more "advanced" tutorials.
There used to be several tutorials on the Nintendo Age forums and I think they can still be found using Waybackmachine. Some of them covers sprite animations and things like that, but I don't think they were all very useful. The best ones of them are the Nerdy Nights tutorial series, but your level has already surpassed everything that one taught except perhaps the audio tutorial, which is also the largest one.



As for background collisions, I usually make the level map in RAM where each byte is a "metatile" that covers a screen area of 4x4 hardware tiles (16x16 pixels). This level map would be loaded to RAM when you move into a new screen and your level-drawing routine may also use the map to figure out what tiles to draw at in the nametable.
When the player or an enemy moves into a metatile you check the tile from a LUT (look-up table) to see if it's a solid tile or not and other things such as a damage floor or something and act accordingly. You need some math to calculate your metasprite's screen position into the position of the level map which uses metatiles. There are many discussion about metatiles on these forums if you search for them, but basically if you are using 16x16 pixel metatiles you divide by 16 (logical shift right 4 times).



I don't see if you have learned to buffer VRAM yet in your list. It's also a basic technique that about any game may need. It would be necessary if say for example you would have Zelda-style bombable walls. After bombing such a wall you may want to change the wall tile into a cave opening tile and you don't want to blank the whole screen just for this small change to the background, that would be very annoying to the player. To avoid that you need to be able to update part of the background during vblank. The OAM DMA routine takes care of this for sprites but there is no equalent DMA solution for VRAM (nametable, pattern table and palettes), you would need to assign a portion of RAM as a VRAM buffer and make a routine that run each vblank and scans this buffer and make any changes to VRAM found in it. The VRAM buffer needs to have the VRAM address that is to be changed and the data to write to it.



I recommend to search the wiki and these forums as they are both loaded with this type of information, but they might not always be easy to find.

Some useful links:
Mirror of Nerdy Nights
You might want to check out the sound tutorial, it also touches on VRAM buffering.

NMI thread
The Frame and NMIs
Tile compression
These are various subjects on VRAM buffering.
User avatar
NEStor
Posts: 4
Joined: Fri Aug 30, 2024 12:35 am
Location: Germany

Re: 6502 Newbie / First Game Prototype

Post by NEStor »

Thanks to all! That seems to be valuable information you gave Me.
At least in theory I have a better feeling now, of what needs to be done and how it could be done; But still not really sure how to accomplish it in a practical way within my CA65 code :)

I guess there are perhaps still some smaller „foundational“ topics I have to re-check too.

Ah, yes in the Pikuma 6502 NES course was also a section on Background Buffering, used to display Score on the Split Screen (HUD) section.
I will need to re-do that section to get more comfortable with it.

So regarding background collision and tile definition:
At the moment I have just the background data exported from NEXXT tile editor and include the binary file in ROM and use my LoadBackground routine to fetch the background data and fill the nametable with the background tiles, palette and attributes.

Did I understand correctly that I would need to re-Write the background data, to include attributes for each tile/metatile and re-write the LoadBackground routine too?

Can I keep the background data in ROM or does it have to go to RAM?
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

By the point you get to this stage your 6502 should be good enough and your understanding of the machine enough that the theory is all you need to start coding for general engine logic. If animating is change the tiles the sprites use every N frames in a loop across M frames isn't a "oh yeah okay I just code that", you should focus on practicing 6502 more before continuing.

you can store the map data in ROM, just that sometimes banking to read the map data for the current screen each time can be a pain, but then it gives you more RAM if you don't cache it.
Pokun
Posts: 2852
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 6502 Newbie / First Game Prototype

Post by Pokun »

Yeah ROM or RAM doesn't matter as long as you have the space. RAM has many benefits since it allows you to change the map during gameplay (Mario games benefits from this with their many breakable bricks), but ROM might be easier to start out with. In either case you may need some sort of compression, using metatiles can be considered a simple but effective form of compression.


Another thing that is a bit more advanced than the fundamentals but is still commonly needed in games is one or more entity systems. It's a system for handling enemies, powerups, missiles and other in-game objects. Basically you have a list of entities and when you spawn a new enemy or other entity you check that list for any empty entity slots to allocate the new enemy to a slot you find, when an enemy or item is destroyed you free its slot etc.
But you can worry about entities later, I'd focus on getting the level map to load, moving the player character and background collisions first.

Oziphantom wrote: Sat Aug 31, 2024 5:50 am you should focus on practicing 6502 more before continuing.
Practicing how though? Coding seems to be a way to practice to me. I guess if you know some good "programming kata" that may be good to repeat until it becomes second nature though.
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

There are plenty of books on the subject. With guides, and questions/challenges for one to improve ones self with if needed.
Pokun
Posts: 2852
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 6502 Newbie / First Game Prototype

Post by Pokun »

There are indeed many good books for old home computers that are scanned and can be downloaded. Since Apple and Commodore computers uses 6502 you could check out books for those.

I'm not sure if there are any that are easy to adapt for NES though or if you have to get into Apple or Commodore computing. If only there was an assembler for Family BASIC.

If OP wants to try out Apple II programming for any reason, I'd recommend the emulator Applewin, it's very easy to use (but it's obviously Windows only) and there are really tons of Apple II books.
I'm not sure about Commodore, but Vice is a popular emulator for C64. You could also try Commodore PET, you may just need a simple environment for playing around with 6502 in and PET is about as simple as you get for home computers (though rivaled by Apple I), Vice should emulate the PET too.

Apple II, PET, VIC-20 and C64 are probably all good choices, it all hang on what books you can find.
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

The Commodore community is 3 ivory towers in a massive complex with a lot of other smaller towers, huts, and general urban sprawl.
https://commodore.bombjack.org/commodore/books.htm is the easiest source, but there is also zimmers and then general online tutorial, documents, fan magazines, magazines from back in the day such as Compute and Ahoy etc. Bombjack also has an "other languages" section if English is not your native and you speak an European Language.

The archive also has an Apple section for those curious.

The general how to program 6502 books tend to focus on general, maths, algorithms etc so you could just code them in easy6502, but once you get into the game programming books, they are very tied to the C64 hardware. But the C64 uses similar concepts to a NES, sprites + chars so you could probably adapt them fairly easily. While Apple ][ is bitmap based.
Pokun
Posts: 2852
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 6502 Newbie / First Game Prototype

Post by Pokun »

Ah that's a great resource of books for all kinds of computers including all that I mentioned above.

There are also some books like Machine Language For Beginners which has examples for multiple systems.

If not willing to play around with another system, it might be best to to make a sandbox program for NES and try to adapt exercises that can't be done in easy6502 to that environment.
User avatar
NEStor
Posts: 4
Joined: Fri Aug 30, 2024 12:35 am
Location: Germany

Re: 6502 Newbie / First Game Prototype

Post by NEStor »

Thanks for all your replies and suggestions.
Surprisingly I have never thought about trying to find materials/tutorials etc. About the C64.
But I like the idea to go also that route in parallel.

I guess I could also need more know-how about general game engine things, both in theory and practical.
Currently trying to accomplish the things you mentioned.
Today I got an entity component system in place and it works together with the other routines like updating/drawing sprites etc.

It will loop through all entities, finding „free“ slots in the array and use them. The update/draw routines are then only doing the „active“ entities and free up the ones not active anymore.

Next I will try my luck with simple animation :)
And then background collision which is still the biggest question mark to Me.
Oziphantom
Posts: 1669
Joined: Tue Feb 07, 2017 2:03 am

Re: 6502 Newbie / First Game Prototype

Post by Oziphantom »

Sorry I missed you are from Germany, so I should have linked the German section https://commodore.bombjack.org/commodor ... german.htm

For entities you can do a "compacted array" as the order of update doesn't usually matter. so what you do is you keep an index of which is the last one, and then when you remove an entity you copy the last data into the slot you are removing and then decrement your "last entity" counter. Depends on how much entity data you have etc. If there is a lot of data you can make an "index array" that holds an index in to larger array, or make a linked list.
User avatar
tokumaru
Posts: 12454
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 6502 Newbie / First Game Prototype

Post by tokumaru »

Oziphantom wrote: Wed Sep 04, 2024 11:06 amFor entities you can do a "compacted array" as the order of update doesn't usually matter. so what you do is you keep an index of which is the last one, and then when you remove an entity you copy the last data into the slot you are removing and then decrement your "last entity" counter.
That's an interesting idea, but as games get more complex, I think it's more likely that the order of updates will matter (e.g. a moving platform may need to be updated before entities that are riding it), and that entities will reference others via their slot indices (e.g. objects being carried, multi-segmented objects, etc.), so I wouldn't recommend this approach.
Depends on how much entity data you have etc. If there is a lot of data you can make an "index array" that holds an index in to larger array, or make a linked list.
I personally am very partial toward linked lists, and they're pretty simple to use as far as lists of game entities go.

On your first project you shouldn't worry too much about these kinds of optimizations though, it's better to do these tasks in a way that feels natural to you. With time, as you gain experience, you're naturally going to notice possible shortcomings of basic techniques and gradually make things more robust, versatile and efficient.
Post Reply