I'm still (slowly) working on my SNES game project with PVSNESLib (so C code with tcc816 + Wlalink backend).

I know that this toolset has many quirks and limitations, but I've encountered a strange behavior that maybe some of you have dealed with:Is there some kind of "limit" in the overall code size for the game? (at least for this toolset)

I'm starting to have a quite large game (about 2000 lines in C code, if you exclude comments and PVSNESlib components, in a single c file.). After adding a large function, the code randomly crashes the console. To be more specific, it seems to crash the SPC700, which crashes the console whenever it doesn't like the code or data you sent to it.

At first, I thought it was another case of the "no more than 32k of code in a single function" problem, that I've already encountered earlier in the project. So I again moved some code away from my "main" function, with various results: some time it still crashes, some time it work but the sound streaming functions have problems (sound is glitched).

However, when I comment out large chunk of code in the new functions I created (or in another function called by the main loop), it all goes back to normal.

I've tried to expand the total ROM size, to modify the bank of the sound data, etc. - nothing makes it work with all the code in .

My theory is that the total code is simply "too large" for tcc-816, and it can't process it for some reason, whether it's inside a function or not. And I guess that the code that is "left out" by the compiler, is unfortunately the "SPC driver" from the lib (SNESmod), making the SPC700 crash whenever I trigger a sound play.

Did anything similar ever happened to you?

If yes, is there some kind of workaround for this issue (splitting the code in several .c files? etc.)

Before posting here, I've also contacted Shiru, who has a lot of experience with this toolset. He thinks that there isn't any "total code limit", but that it's related to the lack of reliance of the tools (code can't stop working due to a misalignement of compiled code).

EDIT: this is issue is solved (look at the last post) - it was a bug when the code of the SNESmod lib isn't stored in bank 0.

Last edited by drludos on Tue Feb 06, 2018 2:33 pm, edited 2 times in total.

I must confess I'm a total noob regarding ASM (although I start to get a few glimpse of it after using it to declare resources in PVSNESLib, or when I had issues with SNESmod).

Is BSNES debugger available in compiled form (windows) somewhere?

In the meantime, I tried to do this manipulation with NoSNS:

I've made several different builds (crashing, non-crashing, etc.), and when the game was crashed (or rather "stuck"), I looked at the lines in the NoSNS debugger. By using "animate", I noticed that two cursor is jumping between two lines when the game is stuck:crashing code (but sound glitch):

Code:

0001:FAAB EC 40 21 cmp x,[2140]0001:FAAE D0 FB jnz FAA7

(I have no clue about what those line are doing - is it some kind of "while (x == 2140){ }")

If I remove some code elsewhere, I can have a non-crashing build, but with sound glitch. The same code as above is present, but in different lines:

Code:

0001:FAA7 EC 40 21 cmp x,[2140]0001:FAAA D0 FB jnz FAA7

And, last but not least, whenever I remove the last function I programmed entirely, it reverses the game to a "no crash / no glitch" state. The two lines above aren't present (using "Search" I can't find them, and they are not located around the 0001:FAAA space - I've searched them manually)

So could it be a simpler case of badly produced code in the last function I wrote, which will make the game crash / glitch only if there as at least XXX lines of codes in the total program?

It seems very strange to me, because if I keep this last function, but I remove another one, the games run great (no glitch no crash). So it's the addition of my previous code + the new one that doesn't please the compiler. At least it would match the "broken toolchain" theory (both Shiru and you seem to agree on this point).

If that's the case, what would be the best way to fix it?

Do I simply try to rewrite my function in a different way so the compiled code is different?

Or are there known workaround / guideline to try to avoid such compiler quirks?

Could you maybe find that line 20 in the Game.asm file that's throwing the error and copy it? "Out of 16 bit range" iirc is an error when the operand is not a valid number to subtract, eg/ larger than a 16 bit number...

I'm pretty fluent in the ASM but not the tools you're using. I know WLA has some quirks with operand sizes and maybe you've found a specific case where the C library didn't account for that?

The bit you posted, "cmp x,[2140], jnz FAA7" is an infinite loop because the branch condition (jump if not zero) is always met following the compare instruction. I'm not sure what it's comparing to so I can't really say why. The part that makes me suspicious is how it's always jumping to FAA7, even when changes you've made have relocated that bit of code from FAAB to FAA7. Maybe it's interpreting that branch instruction wrong?

Lot of theories, hard to say without more information but maybe something I've said will be helpful?

I think it's saying "out of 16 bit range" because it's trying to subtract a value stored in an address that is too far away to read with that sbc instruction. I believe if it's "out of 16 bit range" that means that it's trying to read from another bank. This fits your "too much code" theory in the sense that too much code will spill over into another bank, which might screw with parts of code trying to read data from across banks. You still have plenty of ROM space (I'd wager) but you might need to break things up into more manageable pieces so each one fits in a single bank.

I think you are indeed right. By reading the ".sym" file generated by the tools, it seems that the SPC related functions of my code are located at the end of the file. So it's logical that, if the code "overflows" from a single 32k rom bank, they are the ones that miss instructions and crash the console. This is a very useful lead, thanks a lot!

Khaz wrote:

Actually! I think I understand the last error.

I think it's saying "out of 16 bit range" because it's trying to subtract a value stored in an address that is too far away to read with that sbc instruction. I believe if it's "out of 16 bit range" that means that it's trying to read from another bank. This fits your "too much code" theory in the sense that too much code will spill over into another bank, which might screw with parts of code trying to read data from across banks. You still have plenty of ROM space (I'd wager) but you might need to break things up into more manageable pieces so each one fits in a single bank.

I do have several empty ROM banks, but how can I "break things up into more manageable pieces"?

From the beginning of the project, I've already split my code is several functions (although all of them are in a single .c file), thinking that it would help the compiler / linker to split the code over several banks. But it doesn't seem to work as I now have this issue.

How can I allow the compiler to split my code over several banks?(by splitting in several .c files maybe?)

Some additional info I think I understand after reading the wla.txt help file.

Each time you create a new function in your c source file, it'll be generated in it's own ".section superfree". So I guess that splitting your code in many functions should help the compiler / assembler to produce smaller "pieces".

And I've tried just that, and now the resulting asm file has many more ".section "uniquelabel" superfree" in it, each section corresponding to one function I wrote in the c source file.

However, for now it doesn't solve my issue: the game keeps on crashing / freezing.

So I guess that "splitting" the code in smaller ".section superfree" isn't enough to allow the linker to split the code over several banks.

So, it happens that my code was already split over several banks. Indeed, the tcc816 compiler wraps each C function inside a dedicated ".section" with the superfree status. So, when WLA-DX process the ASM code generated by tcc816, it automatically store the code inside the rom banks using its own algorithm (larger .sections first).

After long hours of testing, I've finally managed to pinpoint the source of my problem. It wasn't a "code overflow" as I suspected, but it was indeed related to the organization of the code in the rom.

It seems that the SNESmod library doesn't like to be stored in a rombank other than 0. When the SNESmod related functions are stored in Rombank 1 or 2, the streaming function of the library crashes (or, more specifically, are stuck in an endless loop). The problem is that, in PVSNESlib, the SNESmod related function are declared in ".section superfree" too.

On my case, when I created larger functions in the code of my game, WLA automatically stored these functions in a rom bank located before the ones related to SNESmod, thus crashing the library.

To slove this, for now I'm manually editing the ASM file generated by tcc816 in order to force some of my code to be stored in banks 1, 2 and 3, leaving room in bank 0 for the superfree sections like the ones related to SNESmod. Once I got this process working, I even made a small python script to automatically perform this modification in the ASM source.

So, for now, I can finally resume working on my game - I can't describe how happy I am that this issue is finally solved!

Thanks again to all of you for your tips and answers - I could never have figured out this all by myself (once again!)

Who is online

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