This is a long-running personal project I've had to write an optimizing compiler from scratch. Everything was done by me, including the lexer/parser, SSA-based IR, high-performance data structures, and code generator.<p>Originally I wasn't targeting the NES. It started as a scripting language, then it morphed into a C++ replacement, and then finally I turned it into what it is today. The large scope of the project and colorful history means it's still a little rough around the edges, but it's now working well enough to post.
As someone trying to undertake some personal projects like this, I have a question. How do you keep motivated enough to work on this for so long and dedicatedly? As a solo developer, how did you manage things like getting stuck on technical issues that were either bugs out of your control or something you didn't have the knowledge to know how to fix?
This is a really interesting approach. One thing that surprised me from the code snippet:<p><pre><code> fn play_sound()
{$4015}(%100)
{$4008}($FF)
</code></pre>
Are these hard-coded memory addresses meaningful to NES devs? I'm surprised that they don't have more readable aliases, like $SOUND_ROM_BASE_ADDR or whatever.
I have long dreamed of a language for 8-bit computers/consoles with a compiler that helps scheduling routines.<p>For example, let's say I have a short snippet of code that needs to run every H blanking period.
I should just declare something like<p>@every_hblank
Blabla_code()<p>Or scheduling some code for X pixels into a line.<p>Actual scheduling can be done however the compiler wants to, using interrupts or inserting dummy instructions for delays.<p>I guess in the end it's a constraint problem to solve where all these snippets fit in.<p>I imagine this makes it easier to write games/special effects as you remove the tricky cycle counting. Easier, but maybe less fun...
Just read through the documentation. There are so many great ideas for generating efficient code. `goto mode` in particular is an awesome idea. Generalizing the program to have multiple "entry" points and overlapping their global variables to save RAM, I've never heard of that technique before.<p>The inline assembly integration looks nice too -- accessing the arguments and return address as fields on the function makes a lot of sense.
I didn’t take a deep dive, but I’m interested in how you keep the binary size small. Is it simply that LLVM, etc., all have too much function overhead and don’t take advantage of routines over subroutines (function calls)? Or is your back-end just specialized enough to take advantage of architecture-specific features the larger compiler suites don’t have the time to care about?<p>Anyway, this looks dope. Truthfully, we could use more hyper-specific languages like this in all sorts of areas.
Congrats on the release! Website and code look super clean, and looks like super useful for anyone getting into NES game development.<p>- What languages did you use as inspiration?<p>- Is it possible to write a game to a physical cartridge and play it on a real snes?<p>Thanks for sharing your amazing work!
Really cool stuff! Is there an syntax highlighter available on any IDE's like VSCode available? I'm having a hard time following the documentation without it as it's hard for me to know what is a keyword and what is a variable for example. Single letter types can be hard for me to follow, but I can definitely appreciate their style.<p>Nice work.
Hey I think a lot of nostalgic people sometimes want to hack the game ROMs instead of making a new one. For example, they may want to add more characters, use enemy roles, add more skills and fun things, does your programming language can also provide such purposes?
I got a Windows Defender alert when downloading the Windows binary:<p>Detected: Trojan:Script/Wacatac.H!ml<p>Status: Removed<p>Details: This program is dangerous and executes commands from an attacker.
This is awesome! I'm currently learning programming NES in assembler with FamicomParty[0], and this look like a great next step!!<p>0. <a href="https://famicom.party" rel="nofollow">https://famicom.party</a>
> Handling banks is normally a tedious affair for programmers, but NESFab handles it for you. The compiler smartly allocates code and data into banks, with the gritty details abstracted away.<p>Killer feature, but is there a cost to bank switching? Could abstracting it result in a lot of performance cost?
Pretty cool project. While I never did NES games, I did assembler on the C64 for a while. The language alone minus the NES parts would already have been super useful back then at least for the high level parts of the programs I wrote.
Its nice that people are still writing code for the NES, but I have to ask what makes this better than using ca65... assembly isn't hard to learn.
Why spaces and not tabs for indents?<p>I know this conversation has probably been had many times before. But if I prefer a 2 space tab, and you prefer a 4 space tab, we both get them how we want them with tabs.<p>With spaces, I have to put up with your stupidly wide indents, and try not to scratch my eyes out from the pain.