A simple question and asking advice

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

Post Reply
klonoa
Posts: 59
Joined: Mon Nov 21, 2011 3:53 pm

A simple question and asking advice

Post by klonoa » Wed Apr 10, 2013 11:30 am

Hey All

I attempted nes programming about a year ago with very basic programming skills.
I successfully got my name on the screen and could move it around with the controller.
But it took me days and a bucket of frustration.
Now after a year of learning C# at school, i'm really eager to try it again.

I read you can program nes game using C at the cost of speed. (i'm fine with that. I'm not going to program anything fancy)
What do you guys think of using C?
Is it a good start or should i just go back and use assembly?

so far i used this tutorial to get me started with using c http://www.dreamincode.net/forums/topic ... ng-part-1/

and this my code:

Code: Select all

#include <nes.h>

void write_string (char *teken)
{
*((unsigned char*)0x2006) = 0x20;
*((unsigned char*)0x2006) = 0x41;     //put the "hallo nes" characters in name table 0 
while (*teken)
{
*((unsigned char*)0x2007) = *teken;
teken++;
}
*((unsigned char*)0x2006) = 0x20;
*((unsigned char*)0x2006) = 0x4f;  //puts a 2 after "hallo nes", Just expirimenting here.
*((unsigned char*)0x2007) = 0x32;


}




int main()
{
waitvblank();

*((unsigned char*)0x2006) = 0x3F;
*((unsigned char*)0x2006) = 0x03;   //white on 3f03
*((unsigned char*)0x2007) = 0x30;

*((unsigned char*)0x2006) = 0x3F;
*((unsigned char*)0x2006) = 0x00;    // blue on 3f00
*((unsigned char*)0x2007) = 0x12;

*((unsigned char*)0x2006) = 0x3F;
*((unsigned char*)0x2006) = 0x02;    // red on 3f02
*((unsigned char*)0x2007) = 0x16;

write_string("hallo nes!");

*((unsigned char*)0x2005) = 0x00;
*((unsigned char*)0x2005) = 0x00;

*((unsigned char*)0x2001) = 0x08;


while(1);
return 0;



}
now for my question: How do i select a background color?
I know i put blue on 3f00 witch means that even if background rendering is switched off it will show blue. Right?
But how do i tell the nes to make it's background red(f302).

Thanks!

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Re: A simple question and asking advice

Post by Shiru » Wed Apr 10, 2013 11:43 am


User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Re: A simple question and asking advice

Post by MottZilla » Wed Apr 10, 2013 11:44 am

You need to find the color you want in the NES global palette.

http://nesdev.com/nespalette.zip

NES does not use a RGB system for colors. Find the color and it's value in the file linked above.

You can program NES games in C, others have done it. It could work out reasonably well.

User avatar
rainwarrior
Posts: 7818
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: A simple question and asking advice

Post by rainwarrior » Wed Apr 10, 2013 2:11 pm

I think C is great for NES development. Yes, you may have performance issues, but these things have solutions. You can monitor your program's performance as you go, and you can write additional assembly code where performance becomes critical. Otherwise, I find the productivity increase writing C code versus assembly is immense.

Last year I made a music program for NES, mostly in C except for a minimal assembly layer for interacting with the NES: http://www.youtube.com/watch?v=i5vyQO81qNc
I released the source, feel free to use it as an example, if you need one: http://rainwarrior.ca/music/coltrane_src.zip

klonoa
Posts: 59
Joined: Mon Nov 21, 2011 3:53 pm

Re: A simple question and asking advice

Post by klonoa » Sun Apr 14, 2013 5:35 pm

rainwarrior wrote:I think C is great for NES development. Yes, you may have performance issues, but these things have solutions. You can monitor your program's performance as you go, and you can write additional assembly code where performance becomes critical. Otherwise, I find the productivity increase writing C code versus assembly is immense.

Last year I made a music program for NES, mostly in C except for a minimal assembly layer for interacting with the NES: http://www.youtube.com/watch?v=i5vyQO81qNc
I released the source, feel free to use it as an example, if you need one: http://rainwarrior.ca/music/coltrane_src.zip
Thanks! I'll check it out!

klonoa
Posts: 59
Joined: Mon Nov 21, 2011 3:53 pm

Re: A simple question and asking advice

Post by klonoa » Sun Apr 14, 2013 5:38 pm

MottZilla wrote:You need to find the color you want in the NES global palette.

http://nesdev.com/nespalette.zip

NES does not use a RGB system for colors. Find the color and it's value in the file linked above.

You can program NES games in C, others have done it. It could work out reasonably well.
I know. But didn't i add the redish color to 3f02?
If yes. How do i tell it to use that color?

Thx for the reply!

User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Re: A simple question and asking advice

Post by MottZilla » Mon Apr 15, 2013 10:01 am

You need to write the palette at $3F00 if you want that to be the "clear screen" color. This color index is mirrored at $3F04, 08,0C and at 14,18, and 1C. If you are writing $3F02, you're just setting a background tile color. Not the color it uses when there is no BG or Sprite pixel to be drawn, aka the clear color.

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: A simple question and asking advice

Post by thefox » Mon Apr 15, 2013 10:34 am

MottZilla wrote:This color index is mirrored at $3F04, 08,0C and at 14,18, and 1C.
Not exactly right. $3F00 is mirrored at $3F10, $3F04 at $3F14, $3F08 at $3F18 and $3F0C at $3F1C. (But $3F04/08/0C/(10)/14/18/1C are never used during normal rendering (only when rendering is turned off and PPU address points at the palette area).)
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

klonoa
Posts: 59
Joined: Mon Nov 21, 2011 3:53 pm

Re: A simple question and asking advice

Post by klonoa » Mon Apr 15, 2013 5:06 pm

MottZilla wrote:You need to write the palette at $3F00 if you want that to be the "clear screen" color. This color index is mirrored at $3F04, 08,0C and at 14,18, and 1C. If you are writing $3F02, you're just setting a background tile color. Not the color it uses when there is no BG or Sprite pixel to be drawn, aka the clear color.
I see. How do i put a tile on the screen?

Also say i want to make a loop where the clear screen color changes.
How do i do that?

something like this?

Code: Select all

while(1)
{
waintvblank();                            //wait for the screen to be fully drawn
*((unsigned char*)0x2006) = 0x3F; 
*((unsigned char*)0x2006) = 0x02;    // red in 3f00 
*((unsigned char*)0x2007) = 0x12; //write to ppu                           
waitvblank();                             //wait for the screen to be fully drawn
*((unsigned char*)0x2006) = 0x3F;
*((unsigned char*)0x2006) = 0x00;    // blue on 3f00
*((unsigned char*)0x2007) = 0x12;

}
This gives me a glitched up screen.

User avatar
koitsu
Posts: 4217
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: A simple question and asking advice

Post by koitsu » Mon Apr 15, 2013 5:10 pm

You probably need to reset $2005 back to zero so that when the PPU begins feeding crap to the electron gun, it starts at $0000 and not the $3Fxx palette area. This is hard to explain exactly, so here's a document explaining it. Do not let it make you think that it's "about scrolling the screen" per se -- it's more about PPU behaviour:

http://wiki.nesdev.com/w/index.php/The_ ... _scrolling

Some other references (I can't find another good one from Bregalad, sadly):

viewtopic.php?p=53107#p53107

Also, what the hell does waitvblank() actually do? (Don't summarise, explain it) If you don't know, then screw using whatever it is you're using and just do everything in assembly.

I'd recommend you do this anyway (do everything in assembly), because as you go further and further along, you're going to run into nuances/complexities given platform limitations, lack of granular control, and start "fighting with the compiler" than if you just used assembly entirely.

User avatar
rainwarrior
Posts: 7818
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: A simple question and asking advice

Post by rainwarrior » Tue Apr 16, 2013 2:58 am

If you just want to set up the screen while rendering is turned off, it's fine to write registers in C like that. However, when you want to update the screen while rendering remains on (i.e. animation), since all changes have to fit in vblank, all of the NMI code will need to be written in assembly (C just won't cut it for performance).

In the example program I linked, what I did was create buffers that your program can fill up in C, and wrote an NMI handler in assembly that will dump them quickly to the PPU. That way you have the whole frame to fill up the buffers (so the performance of C code isn't critical), and the data gets sent during NMI by an assembly routine that you don't really have to worry about. See my nes.h for some documentation but basically in your C code you put your sprite data in ppu_oam[], your palette data in ppu_pal[], and a list of commands to alter the background nametable (you can only do a little bit per frame, there is not enough time to alter a lot) in ppu_nam[], and when you're done you do ppu_send=1 and then call ppu_nmi_wait() to wait for the data to be rendered before you start your next frame (see coltrane.c for a working example).

User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Re: A simple question and asking advice

Post by MottZilla » Thu Apr 18, 2013 1:07 pm

thefox wrote:
MottZilla wrote:This color index is mirrored at $3F04, 08,0C and at 14,18, and 1C.
Not exactly right. $3F00 is mirrored at $3F10, $3F04 at $3F14, $3F08 at $3F18 and $3F0C at $3F1C. (But $3F04/08/0C/(10)/14/18/1C are never used during normal rendering (only when rendering is turned off and PPU address points at the palette area).)
It's been awhile. ;) I knew it was mirrored somewhere but I couldn't recall.

klonoa
Posts: 59
Joined: Mon Nov 21, 2011 3:53 pm

Re: A simple question and asking advice

Post by klonoa » Thu Apr 18, 2013 1:55 pm

rainwarrior wrote:If you just want to set up the screen while rendering is turned off, it's fine to write registers in C like that. However, when you want to update the screen while rendering remains on (i.e. animation), since all changes have to fit in vblank, all of the NMI code will need to be written in assembly (C just won't cut it for performance).

In the example program I linked, what I did was create buffers that your program can fill up in C, and wrote an NMI handler in assembly that will dump them quickly to the PPU. That way you have the whole frame to fill up the buffers (so the performance of C code isn't critical), and the data gets sent during NMI by an assembly routine that you don't really have to worry about. See my nes.h for some documentation but basically in your C code you put your sprite data in ppu_oam[], your palette data in ppu_pal[], and a list of commands to alter the background nametable (you can only do a little bit per frame, there is not enough time to alter a lot) in ppu_nam[], and when you're done you do ppu_send=1 and then call ppu_nmi_wait() to wait for the data to be rendered before you start your next frame (see coltrane.c for a working example).
Thanks for the help!
I saw the methods and tried to use them turns out i had the wrong nes.h.

Question, Is there any way of knowing when a vblank is going to happen?
Is there anyway of saying something like:
If screan is fully drawn (all changes ar written to the ppu)
then show the new drawn screen.
else show old screen. (come to think of it this is a bit of a stupid question isn't it?)

I really appreciate the help.

User avatar
rainwarrior
Posts: 7818
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: A simple question and asking advice

Post by rainwarrior » Thu Apr 18, 2013 2:20 pm

In my thing, a new screen will not be drawn until you do ppu_send=1 (after which you call ppu_nmi_wait() to wait for the buffers to be transferred to the PPU on the next NMI). That way if you take a long time to draw a screen, it won't take effect until you tell it to with ppu_send. NMI happens regularly at 60hz, but you're not required to make changes to the screen every time.

If you're interested in the timing of your code, I made a function called debug_grey() which if you put just after your ppu_send=1 but before ppu_nmi_wait() it will show you visually how much time is left over in the frame before the next NMI by turning grey the portion of the screen that hasn't rendered yet. The PPU is constantly drawing the screen from top to bottom, over and over, at the same time as your code is running, so you can use it's current vertical position as a visual indication of timing.


Also, as an alternative you may want to look at shiru's guide for NES C programming. I dunno which is easier to use, mine was good enough for my own needs but I think shiru's might have more convenient stuff in it. (Also, yes, don't mix and match nes.h from my stuff and shiru's, they are entirely unrelated.)

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Re: A simple question and asking advice

Post by Shiru » Thu Apr 18, 2013 2:38 pm

There is KNES as well.

Post Reply