It is currently Tue Oct 15, 2019 7:39 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Wed Apr 10, 2013 11:30 am 
Offline

Joined: Mon Nov 21, 2011 3:53 pm
Posts: 43
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/152401-nes-game-programming-part-1/

and this my code:

Code:
#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!


Top
 Profile  
 
PostPosted: Wed Apr 10, 2013 11:43 am 
Offline

Joined: Sat Jan 23, 2010 11:41 pm
Posts: 1161
Check this.


Top
 Profile  
 
PostPosted: Wed Apr 10, 2013 11:44 am 
Offline
User avatar

Joined: Wed Dec 06, 2006 8:18 pm
Posts: 2832
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.


Top
 Profile  
 
PostPosted: Wed Apr 10, 2013 2:11 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7598
Location: Canada
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


Top
 Profile  
 
PostPosted: Sun Apr 14, 2013 5:35 pm 
Offline

Joined: Mon Nov 21, 2011 3:53 pm
Posts: 43
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!


Top
 Profile  
 
PostPosted: Sun Apr 14, 2013 5:38 pm 
Offline

Joined: Mon Nov 21, 2011 3:53 pm
Posts: 43
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!


Top
 Profile  
 
PostPosted: Mon Apr 15, 2013 10:01 am 
Offline
User avatar

Joined: Wed Dec 06, 2006 8:18 pm
Posts: 2832
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.


Top
 Profile  
 
PostPosted: Mon Apr 15, 2013 10:34 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3141
Location: Tampere, Finland
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


Top
 Profile  
 
PostPosted: Mon Apr 15, 2013 5:06 pm 
Offline

Joined: Mon Nov 21, 2011 3:53 pm
Posts: 43
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:
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.


Top
 Profile  
 
PostPosted: Mon Apr 15, 2013 5:10 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 4210
Location: A world gone mad
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.


Top
 Profile  
 
PostPosted: Tue Apr 16, 2013 2:58 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7598
Location: Canada
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).


Top
 Profile  
 
PostPosted: Thu Apr 18, 2013 1:07 pm 
Offline
User avatar

Joined: Wed Dec 06, 2006 8:18 pm
Posts: 2832
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.


Top
 Profile  
 
PostPosted: Thu Apr 18, 2013 1:55 pm 
Offline

Joined: Mon Nov 21, 2011 3:53 pm
Posts: 43
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.


Top
 Profile  
 
PostPosted: Thu Apr 18, 2013 2:20 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7598
Location: Canada
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.)


Top
 Profile  
 
PostPosted: Thu Apr 18, 2013 2:38 pm 
Offline

Joined: Sat Jan 23, 2010 11:41 pm
Posts: 1161
There is KNES as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group