I have found a SNES sdk for the C language; however, does this console have the oomph to run C-language games? Are there any coders who use C to develop for the SNES? Is it a good idea, in your evaluation?

There is a C compiler for the Apple IIGS (65816) called ORCA/C. WDC also has their own (never used it). The topic has come up a couple times on the cc65 mailing list (from the look of it) and it's been rejected multiple times due to the large undertaking required. Hint: it's not easy and you probably will not end up with very optimal code.

Whether or not either of these could be used for SNES development is completely unknown (by me) at this time. And regardless of the possibility, I would suggest sticking with assembly language on classic consoles.

Even though this topic is about the SNES, Shiru from the forum here did a write-up on doing C on the NES (6502). Again: painful.

You can do it of course, as the 65xx is turing complete. But you cannot do it well. And on a 2.68MHz processor with an instruction throughput around 0.4MIPS ... you had better not try.

The 65xx is just an awful design for C code. However, I'm not convinced that the only alternative is to go right to pure assembler. I think it just needs a language somewhere between C and ASM that plays on its strengths. But to date, my attempts to design such a language have failed.

The problem with pure ASM is that no matter how much you comment it, if you leave and come back a few months later, the code will be almost unreadable. Much like commentless Perl, and very much not like well-written C++.

You can do it of course, as the 65xx is turing complete. But you cannot do it well. And on a 2.68MHz processor with an instruction throughput around 0.4MIPS ... you had better not try.

The 65xx is just an awful design for C code. However, I'm not convinced that the only alternative is to go right to pure assembler. I think it just needs a language somewhere between C and ASM that plays on its strengths. But to date, my attempts to design such a language have failed.

The problem with pure ASM is that no matter how much you comment it, if you leave and come back a few months later, the code will be almost unreadable. Much like commentless Perl, and very much not like well-written C++.

Isn't C just a step up from assembly? I don't think there is a better bridge between the two. Sorry if that sounds uneducated. I'm an electrical engineer that only dabbles in ASM and C so I'm not that well educated on the matter.

Yes, but no... C really relies on passing parameters and allocating local variables on the stack. The 6502's stack is really only for subroutine calls, although you can stuff other things into it. And it's only 256 bytes total, so you can't allocate many things into it anyway.

This lack of a low-overhead way of using dynamic allocations of memory, coupled with the comparatively small amount of RAM provided by the NES, means that a lot of things we take for granted with more-modern languages on more-modern hardware are awkward on the NES, and only a little better on the C64.

You can do it of course, as the 65xx is turing complete. But you cannot do it well. And on a 2.68MHz processor with an instruction throughput around 0.4MIPS ... you had better not try.

0.4MIPS wait what? That puts it in a much worse light than the 68000 on the Mega Drive, especially when you consider how much the 68000 can do compared with the 65816 given the same amount of instructions. I thought that MIPS-wise they were closer to each other?

byuu wrote:

The problem with pure ASM is that no matter how much you comment it, if you leave and come back a few months later, the code will be almost unreadable. Much like commentless Perl, and very much not like well-written C++.

I disagree, I still can read my old 68000 asm code just fine, it's perfectly doable. Agreed that you probably need to do more commenting (since asm opcodes tend to lack context), but it's doable.

Fusion916 wrote:

Isn't C just a step up from assembly?

No, not even remotely close. C makes a lot of abstractions. It also tries to be as portable as possible so a lot of things end up being unoptimal, especially for 8-bit processors (C was designed for Unix which originally ran on much more powerful processors, so it wasn't anywhere as bad for those).

C isn't much at all like hand-optimized assembly language on the older 1 MHz 8 bit processors. Stack setup and tear-down is horrifically expensive in terms of clock ticks on them.

In my opinion, C has to assume a lot about variable access and making sure their value can be read later, even if it never does. C memory pointers have to be a certain overly huge size... For example, even if an 8-bit register using a single special indexed mode instruction could theoretically be used to access an array element in the first 256 bytes of memory, the compiler maker has to write in a more general purpose, less efficient block of indexing code to handle the worst case, just because the address value COULD be that big (even if it isn't).

Hand-written assembly destroys or overwrites things merely for the sake of convenience and speed and less instructions. The author knows that variable "X" isn't going to be used anywhere else in the procedure, and thus adds and shifts it as needed right there in a register, and suddenly it's morphed into another value, instead of C's stack-based read-modify-write necessity after every elemental operation. It needs to do this because again the C programmers MIGHT (not will, MIGHT) put an assignment operator somewhere in a long string of math operations. C can go X = X + ++Y + 1 + Z++; Therefore again it has to be more stack oriented and ultimately inefficient for the sake of the language.

Coming from the other angle Gigahertz level CPU's are so starved of instructions that it doesn't typically matter if a procedure is less optimized and takes up say 10 more clocks than it needs to. Getting the result out of the chip into the memory or registers happens at a much slower rate than it can compute individual instructions at. This is the opposite problem on 8-bitters, that any little trick to gain speed has a huge effect visually and on possible game complexity.

Now this is my total opinion, that C programmers are lazy, and like to write in the least amount of symbols, because to them it looks simpler. The IF statements without a comparison operator, the abuse of FOR loops with multiple counters... what may seem simpler visually might not match with what number instructions these poor little 8 bitters need to execute to deal with these assumptions. So it's like you need to be aware of the assembly instructions anyway lest you write something terribly slow.

But, here's my ultimate opinion: it would be stupid nowadays to write an entire large game completely in assembly language. Use C for the logical decisions and its ability for handling call complexity. The core graphics and memory copying routines would have to be in assembly. If you know the processor's assembly instructions and know C, and have a compiler that allows you to mix the two freely, then you're unstoppable.

Note that practically everything you said is caught by a modern compiler and optimized out... They analyze when variables are used and will ditch them as soon as they aren't needed anymore, they don't bother retaining intermediate values if there's a faster way to get to the same result, in some extreme cases they may completely rewrite the code (GCC seems to like doing this a lot with loops, to the point that it may outright eliminate some variables and replace them with decrementing loop counters even if the original check didn't have counters at all).

Bigger problems come from C always casting to int when a type is shorter, lack of rotate operations (compilers have to guess when those are usable), etc.

I think you can go pretty far with C on a platform like this. You can go a lot farther if you also know assembly, and can optimize the parts that need it.

The incredible optimizing abilities of modern compilers aren't terribly relevant to this, though, most compilers for these targets are pretty poor in that respect.

Try to use global variables instead of the stack. Profile your code, and when things get too slow find the routines taking the most time and rewrite them in assembly. C code will be really bloated compared to assembly, but this is more of a problem on the NES than it is SNES, since space is much more precious on the NES.

Writing, iterating on, and debugging assembly code takes longer than equivalent C code. This is just a natural fact.

If your development time is limited (and it is; you are going to die someday), it is reasonable to concern yourself with the amount of time you will spend developing the code. This will be a factor in whether or not you can finish your project. There are probably thousands of posts about unfinished projects on this board; some of them would be finished if they could have been done faster.

Honestly, I've seen more reluctance to use C around here than I've seen reluctance to use assembly.

(and you don't want to know why I just happen to have that list handy :P)

Even if it were possible, you would spend way more instructions working around the horrible limitations to do the same thing anyway.

So I tend to think of 6 cycles as being the average for doing something useful (clc + long-adc, jsl subroutine, stuff that eg the 680x0 can easily do (and then some) in one instruction.) That gets you to 0.447MIPS.

If you want to be more optimistic, you could say 4 cycles is more reasonable, which only brings you to 0.671MIPS. FastROM can also help a bit, but is heavily crippled by not being usable on RAM.

Regardless, said performance is absolutely dreadful. You really do have to micro-optimize the living hell out of SNES ASM. Especially if you ever try something as reckless as "drawing proportional fonts." It can take entire frames to render a proportional font screen.

> I disagree, I still can read my old 68000 asm code just fine, it's perfectly doable.

You're comparing apples and carburetors. 680x0 is very readable compared to 65816.

Fun exercise for the reader: try and do muls.l #23,d0 (signed multiply) on the 65816.

> I don't understand this fear of the assembly.

You haven't written enough.

I tried to make a fan translation for Dai Kaijuu Monogatari. I hacked 95% of the game, reprogrammed all of the text engines and window displays entirely. It was about 200 - 300KB of pure 65816 ASM, commented as best I could.

I sat around for a year asking for anyone to please help me translate the script. I went back to look at the code and realized ... it was only maybe 5% better than looking at a raw disassembly.

Why? Because all math was done on the accumulator (and optimized like my mul 23 above that renders it unreadable), speed optimizations resulted in nasty tricks with the stack and register sizes (no common calling convention or assumptions on A/X sizes inside called functions), branching was abused heavily for performance (the bad kind of goto), memory was all hard-coded addresses, and there was no grander structure beyond basic functions.

This isn't a problem at all for writing 65816. But when you come back to it after months of inactivity, you can't look at the code and intuitively understand all of the speed hacks and accumulator math at first glance. You basically have to study and relearn each function you wrote in order to be able to use them again.

With C++, all of my expressions are in pure math, I can work with all the variables I want at one time, I can build classes with member functions, inherit from base classes and obtain polymorphism transparently, and allocate memory dynamically on the heap.

Absolute world of difference. I know 65816 very well, and I've reverse engineered and programmed massive blocks of code in it. There are many as good as me, but quite possibly no one better at it. But I'm not going to pretend it's easy to write large-scale 65816 applications because of that.

Also, I think immediate 8-bit loads only take two cycles. Unfortunately there are no store instructions that fast...

Is it the whole instruction that slows down when slow memory is involved (doesn't seem plausible), or just the actual read/write? Or some other way of handling it? I mean, if you wrote sta $7E1234 in FastROM, shouldn't it take 32 master cycles rather than 40?

I seem to recall hearing about a manual that breaks down instructions by cycle, and I'm pretty sure it wasn't the WDC one. Do you know what I'm talking about?

byuu wrote:

Fun exercise for the reader: try and do muls.l #23,d0 (signed multiply) on the 65816.

Code:

sta $211B; xba; sta $211B; lda #$17; sta $211C; lda $2134

Boom; done.

...I'll get my coat.

Last edited by 93143 on Sun Nov 16, 2014 2:59 am, edited 5 times in total.

I coded a little shmup in 2 days , I don't think I would have been C significantly faster.A video game for me what is the longest it's algorithm.There are very good macro assembly, which allows to code quickly.

The assembler is difficult to understand, because when I read the source code, I see that the variables are little to name it, unwanted little keyword, and the code is compressed and has not Indent style.

Who is online

Users browsing this forum: No registered users and 6 guests

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