It is currently Mon Dec 11, 2017 2:42 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 100 posts ]  Go to page 1, 2, 3, 4, 5 ... 7  Next
Author Message
 Post subject: Making a NES game in C++
PostPosted: Tue Nov 01, 2016 7:14 pm 
Offline

Joined: Fri Mar 22, 2013 7:41 am
Posts: 34
Hi. So I've seen I couple of videos of Jason Turner where he makes a Commodore 64 game in C++17. And now while watching his Cppcon talk it just clicked. He uses i386 to 6502 translator but NES has this CPU! So I think it is possible to use his approach to game NES games in C++.

I'm certainly interested in this because I hate assembler and love C++ and I want to know how NES works to enhance my NSF player.

Thoughts?


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 2:39 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
It's a cute demo, but I don't think this approach would work for projects much larger than the Pong that he was doing.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 3:38 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1509
FaTony wrote:
I'm certainly interested in this because I hate assembler and love C++ and I want to know how NES works to enhance my NSF player.

Thoughts?

C++ not so much, unless you find a compiler for it. But since object orientation isn't really necessary for an NES game anyway, you can program in C. Just get cc65.

There are still a few things that you need to do in Assembly, but the majority, i.e. the whole game logic, can be done in C.

And don't let people tell you that you can only do tiny, slow games in C.
My upcoming game "City Trouble" is a quick jump'n'run with up to four characters on screen at once and I still have plenty of rendering time (about 40% or so) that I could fill with something before a lag would happen.
And about the space: If it wasn't for the fat voice sample and a good bunch of dialog texts, I would still have tons of ROM space in a standard 32 KB cartridge, so the fact that compiled C code is larger than hand-written Assembly code is not that much of an issue if you keep some things in mind.

So, yeah, it's definitely possible to write a decent game in C and only bother with Assembly for low level stuff: Initializing the NES, updating the screen during vblank, updating the sprites and maybe some general purpose functions like a memcpy version, randomizer etc.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 4:58 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
FaTony wrote:
Hi. So I've seen I couple of videos of Jason Turner where he makes a Commodore 64 game in C++17. And now while watching his Cppcon talk it just clicked. He uses i386 to 6502 translator but NES has this CPU! So I think it is possible to use his approach to game NES games in C++.

I'm certainly interested in this because I hate assembler and love C++ and I want to know how NES works to enhance my NSF player.

Thoughts?

Before "loving" and "hating" things you need to get a deeper understanding on them it seems. (You probably hate assembly, not assembler, as the assembler is the program compiling (*) assembly langage into binary form).

You liking high level language better than assembly is just fine. However you should figure that C++ is just one high level language among a pool of thousands, and that C++ in particular is a weirdo in the sense it is, basically, the C language added with features from every single other language in existance and that this turned into the monster feature-creeped language called C++. This has advantages and drawbacks. The advantage is that if there is any feature you like in any high-level programming language, it is doable in C++ rather easily. Another advantage is that there is multiple ways to do something, so you can just do it the way you like best. The inconvenient is that it's almost impossible to deeply know the C++ language well (unless it's your speciality and that you're doing exclusively that in computer science), and another inconvenient is that it's very easy to be lost and not do exactly what you wanted to do, for instance leaking memory.

Nevetheless I think you should look into other high level programming language first. I made a post listing all realistic possibilities to programm the NES using any high level language. I did not test much of those possibilities, nor would I have any serious idea in what is the best suitable for a game. In addition to what is listed, anyone could make up other tools, but this is hard, time consuming, and error prone.

Finally, you should understand that the NES is a limited platform and that even if you do no want to code a full game in pure assembly, knowing assembly and coding critical parts in assembly will be required.

(*) Some purist would say "assembling" and refuse the term "compiling" in this particular domain


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 7:22 am 
Offline

Joined: Fri Mar 22, 2013 7:41 am
Posts: 34
DRW wrote:
C++ not so much, unless you find a compiler for it. But since object orientation isn't really necessary for an NES game anyway, you can program in C. Just get cc65.


No. I can can't handle C with it's pointers and manual memory management. I'm tired of writing low level stuff by hand. That's why I use C++.

Bregalad wrote:
Nevetheless I think you should look into other high level programming language first. I made a post listing all realistic possibilities to programm the NES using any high level language. I did not test much of those possibilities, nor would I have any serious idea in what is the best suitable for a game. In addition to what is listed, anyone could make up other tools, but this is hard, time consuming, and error prone.


C++ is by far the best language I have worked with. Here's what I love about C++:
  • Has an ISO standard
  • Not owned by a single company
  • Has free implementation
  • Runs on hardware without any VM
  • Has lots of high level features
  • Static typing
  • Has a huge standard library

I haven't seen a single language that comes close.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 7:57 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1509
FaTony wrote:
No. I can can't handle C with it's pointers and manual memory management. I'm tired of writing low level stuff by hand. That's why I use C++.

Believe me: You won't need pointers and memory management when you write an NES game. If you can imagine a scene where you would need malloc or new in an NES game, then you have done something wrong. You shouldn't use the heap at all. And even stack variables should be used at a minimum.
The key to success in writing NES games in C (or C++) is: Global variables. This might be bad style for PC programs, but necessary for an NES game to keep ROM space and execution time small.
Therefore, the advantages that C++ has over C couldn't be used in an NES game anyway.

For example, when a new opponent appears, you wouldn't use vector.push_back to put it to the list of opponents. You would have a global fixed-size array with the maximum number of possible opponents and you would simply use the next free slot in this array.

FaTony wrote:
C++ is by far the best language I have worked with. Here's what I love about C++:
  • Has an ISO standard
  • Not owned by a single company
  • Has free implementation
  • Runs on hardware without any VM
  • Has lots of high level features
  • Static typing
  • Has a huge standard library

All of this is also true for C.
I'm surprised that you didn't mention object orientation and templates. Because those are the major things that really make it distinct from C.

But those should not be used when creating an NES game.

Templates are a waste of space anyway.

And object orientation: Each function in the style of object.Function() internally works like Function(&object). And you should avoid function parameters as much as possible anyway. So, for an NES game, you would need to use functional programming instead of object oriented one since methods in classes always work with a pointer/reference to the object that called the function.

And about the standard library: You won't need this when programming an NES game. The only useful thing is maybe memcpy and the like, but you're better off writing your own version in Assembly. A version that only takes a byte value as the length indicator instead of size_t since you will rarely need to copy more than 255 bytes at once and size_t only complicates things.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 8:44 am 
Offline

Joined: Fri Mar 22, 2013 7:41 am
Posts: 34
DRW wrote:
For example, when a new opponent appears, you wouldn't use vector.push_back to put it to the list of opponents. You would have a global fixed-size array with the maximum number of possible opponents and you would simply use the next free slot in this array.


I guess that'll be std::array<std::optional<Enemy>, N> inside an object which will have a push_back member function.

DRW wrote:
I'm surprised that you didn't mention object orientation and templates. Because those are the major things that really make it distinct from C.


That goes under "Has lots of high level features". I love OO and templates. About 70% of all my code is templates. I've made a few libraries that are 100% templates.

DRW wrote:
Templates are a waste of space anyway.


That video shows how templates can be zero overhead.

DRW wrote:
And object orientation: Each function in the style of object.Function() internally works like Function(&object). And you should avoid function parameters as much as possible anyway. So, for an NES game, you would need to use functional programming instead of object oriented one since methods in classes always work with a pointer/reference to the object that called the function.


That can be optimized away.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 8:47 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19322
Location: NE Indiana, USA (NTSC)
The problem, as usual, is one of finding someone with the detailed knowledge of both the C++ standard and the 6502 architecture to create a Sufficiently Smart Compiler.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 9:09 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1509
FaTony wrote:
I guess that'll be std::array<std::optional<Enemy>, N> inside an object which will have a push_back member function.

Well, the first problem is: Even an array of a struct is slow. In C for the NES, you'll have to do something like this:
Code:
struct EnemyData
{
    int X[EnemiesNumber];
    int Y[EnemiesNumber];
    byte Energy[EnemiesNumber];
};

struct EnemyData AllEnemyData;

instead of this:
Code:
struct EnemyData
{
    int X;
    int Y;
    byte Energy;
};

struct EnemyData AllEnemyData[AllEnemiesNumber];


The first version, despite unintuitive, is much more effective.
And there goes your object orientation, templates and dynamic arrays. Because these kinds of things work like the below code and are therefore ineffective.

FaTony wrote:
That video shows how templates can be zero overhead.

Not overhead, but additional space because, as far as I know, two instances of the same template class, each with a different template type, are copied twice into the executable. Or did they change this in the meantime?

FaTony wrote:
DRW wrote:
And object orientation: Each function in the style of object.Function() internally works like Function(&object). And you should avoid function parameters as much as possible anyway. So, for an NES game, you would need to use functional programming instead of object oriented one since methods in classes always work with a pointer/reference to the object that called the function.


That can be optimized away.

How? In object orientation, the function is written to be able to be called by any object of the class. MyClass::MyFunction cannot know if it is called by MyClass a or by MyClass b, therefore, whenever this is referenced, it is referenced as a pointer. This means: Indirect access. Which means: More execution time than if you simply access a fixed location in memory.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 9:13 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1864
Location: DIGDUG
Interesting fact. The NES uses (essentially) the same processor as the Atari. 1977. 8-bit. Super slow.

C++ compilers today worry about ...should this be 32bit code or 64bit code.

None of them would be of any use toward 8-bit code for a 40 year old processor.

There are no compilers that will do what you want, so the whole 'C++ is better than C' argument is moot. We have a C compiler and we have assembly. That's it.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 9:38 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1509
What I'm also trying to tell him: Even if there was a full ISO Standard C++ compiler for the NES, the code in the end would look basically identically to the corresponding C code because you wouldn't be able to use all the C++-specific functions anyway because it would eat up too much ROM space and too much CPU time. The only real advantage of a C++ compiler would be:

Inline functions instead of macros. (You would still need macros for tons of other things, though.)

Local variables can be declared everywhere in the function instead of only at the start of a block.

void Function() is parameterless, unlike in C where void Function() means you can pass any parameter to this function and you have to write void Function(void) for a parameterless function.

Those are the only real C++ advantages over C that I can think of right now that you can also use in an NES game. But std::array? :lol: Forget it.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 10:47 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Quote:
We have a C compiler and we have assembly. That's it.

No, there's plenty of other mid-level langauges that are in competition with C, see the post I linked to in my 1st post in this thread.

Quote:
No. I can can't handle C with it's pointers and manual memory management. I'm tired of writing low level stuff by hand. That's why I use C++.

C can indeed be awfully complex for some tasks, and some other mid-level programming language can solve some of C's problems. The only reason C and C++ are so popular is just a snowball effect, they aren't really better or worse than any other programming languages out there.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 11:04 am 
Offline
User avatar

Joined: Fri Feb 27, 2009 2:35 pm
Posts: 215
Location: Fort Wayne, Indiana
DRW wrote:
The only real advantage of a C++ compiler would be:

Inline functions instead of macros. (You would still need macros for tons of other things, though.)

Local variables can be declared everywhere in the function instead of only at the start of a block.
Not sure about the void parameter functions, but for the other two advantages you wouldn't even need C++, just support for more C99 features. It already has one, flexible array struct members.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 11:20 am 
Offline

Joined: Fri Mar 22, 2013 7:41 am
Posts: 34
DRW wrote:
How? In object orientation, the function is written to be able to be called by any object of the class. MyClass::MyFunction cannot know if it is called by MyClass a or by MyClass b, therefore, whenever this is referenced, it is referenced as a pointer. This means: Indirect access. Which means: More execution time than if you simply access a fixed location in memory.


There will be no classes and functions if compiler is smart enough.

Watch the video in the 1st post and compare source code to the assembly. The reassembler is on GitHub.


Top
 Profile  
 
PostPosted: Wed Nov 02, 2016 11:37 am 
Offline

Joined: Thu Aug 28, 2008 1:17 am
Posts: 591
FaTony wrote:
No. I can can't handle C with it's pointers and manual memory management. I'm tired of writing low level stuff by hand. That's why I use C++.

Then why are you even messing around with the NES? The only way you're going to get anything reasonable out of this system, is by getting your hands dirty with low level work. Unless you're aiming to create stuff that isn't to the potential of the system (pong, puzzle games, crippled games, etc). And C is particularly high level, in the context of the NES. If you need some additional functionality on top of that (CC65), then write a pre-processor. But honestly, maybe you should move onto something like the Genesis, if you with C++ style environment.

Don't get me wrong; I understand the novelty of seeing something being done for an old system like this - "just because" line of reasoning. But there's a difference between novelty and efficiency, and I think CC65 already kinda straddles that line. Going beyond CC65 and expecting something more than novelty, is unrealistic.


That said, definitely thanks for posting the link. Like I said, I do like see stuff like this; modern concepts on old machines. I even have my own ideas of implementing some type object/class design into 65x arch. Nothing fancy mind you, and nothing that improves efficiency. More of just the fun of seeing it implemented.

_________________
__________________________
http://pcedev.wordpress.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 100 posts ]  Go to page 1, 2, 3, 4, 5 ... 7  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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