Page 1 of 3

First time Homebrewer

Posted: Tue Jan 24, 2012 3:58 pm
by Camronas
Hello everyone, I am very interested in making homebrew nes games and can't wait to get started. I am studying game design at my uni and want to test my metal as a designer with older styles of games "that is what I like more".

I have read many tutorials explaining how assembly works and I "think" I have a clear enough understanding to start. I would like to know though are there any practical nes assembly tutorials out there? By that I mean any that show you start to finish how to program a game for the nes?

If not I would like to just ask question as I need them until I become more competent with my assembly programming. For the record I have learned several language before but none this low level.

Cheers for your time :)

Posted: Tue Jan 24, 2012 4:01 pm
by 3gengames
I'd start reading the nerdy nights to get the ideas behind 6502, some basic functions, and reference the wiki for registers and start reading up on everything. Ask here for any problems, but if you search before odds are somebody has probably had the same question and it's already answered. You can PM me too for help, but you better have a good grasp as I try to teach the right way off the bat first time. :)

Posted: Tue Jan 24, 2012 4:47 pm
by Camronas
Thanks ill do that :)
I started reading Nerdy Nights and its been very interesting so far, but then I came across this in the comments:

http://www.nintendoage.com/forum/messag ... adid=33287

It has been easier for me to understand so far, and might encourage others to read it to if their starting out like I am. But I haven't read it all so I'm not 100% sure how good it really is.

Has anyone else read this before? If so can you tell me if its good before I invest more time into it?

Posted: Tue Jan 24, 2012 4:49 pm
by 3gengames
Yeah, it's good to teach you some basics. Any registers on there though that it doesn't explain in detail you should read up on on the wiki, the wiki has everything you'll need once you learn 6502 though.

Posted: Tue Jan 24, 2012 5:44 pm
by Kasumi
I have always been a fan of this guide: http://nesdev.com/6502guid.txt

for straight 6502. That's what made it "click" for me. It may not be the same for you, though. One thing is doesn't quite explain is the addressing modes, but I bet you'll pick up what you need to know about that (sans the name) from Nerdy Nights. If not, ask away.

I spend a lot of my time writings books-of-posts, so if you're into lots of reading :lol:... I'm available for help as well!

Edit: Here's a topic of someone else who started from absolute zero and made progress. It's a long thread, but there's a lot a of really useful posts and explanations in there.

Posted: Tue Jan 24, 2012 6:00 pm
by Camronas
Thanks Ill keep that in mind, at the moment I'm just downloading files other people have done and am trying to revers engineer it to see if I really understand whats going on. So far little success :P But Error is a part of learning.

Posted: Tue Jan 24, 2012 6:21 pm
by Camronas
Quick question, and most likely a stupid one. Is their a staple of MUST have codes in assembly "nes in particular" becasue in c++ you need to include all of your other files and stuff. So do you need to declare anything? Other then sprites, pallets, and variables of course.

Posted: Tue Jan 24, 2012 6:54 pm
by Kasumi
I'm not sure I understood the question, but here's some information based on what I think you mean.

If you mean is there required code like

Code: Select all

#include <stdio.h>

void main(){

}
to do basic things for NES, sort of.

In C, the program starts at main(), for NES you put the starting address at $FFFC in the rom. There's also some some startup code (technically optional) and setting the parameters for the rom's header (if you want to run the game in an emulator or powerpak), which Nerdy Nights will explain better than I could.

There's actually very little else that's needed. You don't need to declare anything or even name any variables in 6502 (lda $00 is just as valid as lda variable), and there are no libraries you need to worry about. Everything that can be done on the NES is done with the 56 different 6502 instructions. Interfacing with the actual NES hardware is done by storing numbers in specific locations, there aren't standard functions for doing so.

Edit: About including, there's not a special format.

.db $00 inserts the byte $00.

Let's say you have a file that is exactly 1 byte, and that byte is $00.

.incbin "file.bin"

would behave identically to the above. There's no extern or anything like that.

Posted: Tue Jan 24, 2012 7:18 pm
by Camronas
My god this is confusing lol as I'm sure it was for everyone else when they started :P
One part in the tutorial that is confusing me the most is how to load in and draw a picture. I have a file with the Mario sprites to make it easier, I am trying to figure out how to load Mario as an entity and then later be able to move him around.

Posted: Tue Jan 24, 2012 8:11 pm
by Kasumi
I am assuming you are familiar with hex and binary.

A page of RAM is 256 bytes. $XX00-$XXFF.

On the NES, XX can be 00-07.

There is no need to load a picture. (at least not with the basic setup you will start with.) All the graphics you will use are just always there if you incbin'd the file as described in the tutorial.

Storing a number to location $4014 causes the PPU to copy a page of RAM to the PPU which will then display sprites using that information without any more of your input. The page of RAM that is copied is determined by the number written to $4014. You also must set the low byte where the transfer starts with $2003. This is usually #$00.

Code: Select all

lda #$00
sta $2003  ; set the low byte (00) of the RAM address

lda #$02;
sta $4014;$0200-$02FF is copied.

lda #$07
sta $4014;$0700-$07FF is copied.

The page of RAM you want to use for sprites is up to you. (It's not wise to use $00 or $01, though.)
Note that the write to $4014 should happen in your NMI interrupt code. (If you don't know what this is, ask and I'll explain that)

You will also want to enable rendering by writing the values you want to $2000 and $2001. See here for what the bits of each register do.

Code: Select all

lda #%10010000
sta $2000
Would start NMIs (you generally want them enabled if you want graphics), and set the tiles used for the background to the second half of your CHR-ROM. You can see how by looking at how the set bits correspond to the information in the wiki.

Code: Select all

lda #%00011110
sta $2001
Will start displaying sprites and the background.

There are 64 sprites. So each sprite uses 4 bytes.

Let's say you're using page 2.

Byte 0 is the sprite's y position. So writing #$10 to $0200 would set one of the 64 sprite's y position to #$10. Writing #$20 to $0204 would set the next sprite's y position to #$20. Etc.

Byte 1 is the sprite's tile. Whatever byte you write here is the tile graphic the sprite will use. $0201 refers to one sprite. $0205 refers to the next. etc. To know which tile to write, load your rom in FCEUX and go to debug, PPU Viewer. Mouse over the graphic you want, and it will give you its tile number.

Byte 2 ($0202, $0206 etc) is broken down like this:

Code: Select all

76543210
||||||||
||||||++- Palette (4 to 7) of sprite
|||+++--- Unimplemented
||+------ Priority (0: in front of background; 1: behind background)
|+------- Flip sprite horizontally
+-------- Flip sprite vertically
But you can just write #$00 there for now.

Byte 3 ($0203, $0207) is the sprite's X position.

So to make a sprite appear, write its X and Y positions to the RAM in the page you have chosen for sprites. Then write its tile number.

The sprite will be drawn automatically next time the NMI interrupt happens. To move it, load its location, adc (or subtract) the number of pixels you want it to move by, and then store it's location.

Code: Select all

lda $0200
clc
adc #$01
sta $0200
Like that.

Posted: Wed Jan 25, 2012 1:37 am
by Camronas
OMG I AM SOME KIND OF TECHNO WIZARD!!! I was able to make the background red instead of blue!?! Thanks a lot :) I know you basically said the same thing as the tut but I got your way more. Thanks ill keep you posted if I have more trouble.

Posted: Wed Jan 25, 2012 2:43 am
by Camronas
Ok so I am up to making the sprites move:

Code: Select all

LatchController:
  LDA #$01
  STA $4016
  LDA #$00
  STA $4016       ; tell both the controllers to latch buttons


ReadALeft: 
  LDA $4016       ; player 1 - A
  AND #%00000001  ; only look at bit 0
  BEQ ReadADone   ; branch to ReadADone if button is NOT pressed (0)
                  ; add instructions here to do something when button IS pressed (1)
  LDA $0203       ; load sprite X position
  CLC             ; make sure the carry flag is clear
  ADC #$01        ; A = A + 1
  STA $0203       ; save sprite X position
ReadADone:     ; handling this button is done
  

ReadB: 
  LDA $4016       ; player 1 - B
  AND #%00000001  ; only look at bit 0
  BEQ ReadBDone   ; branch to ReadBDone if button is NOT pressed (0)
                  ; add instructions here to do something when button IS pressed (1)
  LDA $0203       ; load sprite X position
  SEC             ; make sure carry flag is set
  SBC #$01        ; A = A - 1
  STA $0203       ; save sprite X position
ReadBDone:        ; handling this button is done
The tutorial wants me to make the sprites move using the arrow keys instead of A and B. I cant see the difference between the two function to be able to see what needs to change, this code works though.

Posted: Wed Jan 25, 2012 2:49 am
by Camronas
Wait I got it :) I need to list all the controls in order from A to Right.

Posted: Wed Jan 25, 2012 5:29 am
by tokumaru
I don't know why the tutorials insist on reading the controller like that... This method is bad because it mixes hardware bahavior with game logic, and that's not professional at all... Also, there's no easy/quick/small way for you to know more than what buttons are pressed now. Many times you need to know what buttons are down now but weren't last frame, in order to avoid repeated button detection, such as when navigating a menu... If you don't apply any restriction there, when you press a direction the cursor will move through the options insanely fast, because people always hold buttons down longer than a frame (at 60 fps this is no surprise).

The better way is to read the state of all the buttons at once and buffer them in a byte, and later have the game code check this byte, not the hardware directly. You should always separate hardware details from game logic when possible. It makes your code easier to maintain and even port to other systems, in case you decide to.

Posted: Wed Jan 25, 2012 11:16 am
by bunnyboy
tokumaru wrote:I don't know why the tutorials insist on reading the controller like that...
Because it is one of the early lessons in a simple beginners tutorial. Reading all the buttons at once needs shifting, variables, and subroutines. Just a few lessons later those are covered and the controller reading is changed.

Newbies need simplicity to learn first, being "professional" is overwhelming instead of teaching.