Serious neslib bug when used from C

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Serious neslib bug when used from C
by on (#165245)
Every neslib function that returns an 8-bit value is buggy. According to cc65 calling conventions, every function must return at minimum 16 bits, which means that a function returning 8 bits must zero the X register.

None of the neslib 8-bit functions do this.

I've emailed Shiru about this, I don't think he reads this forum anymore.


This manifests in a lot of ways:
- var = foo + rand8() -> completely wrong value.
- calling a function that takes a constant 16-bit parameter after calling a buggy neslib function will mangle that parameter
- lots of other ways
Re: Serious neslib bug when used from C
by on (#165247)
It's strange that I've never found this issue, and I've coded quite a few games using neslib already.
Re: Serious neslib bug when used from C
by on (#165259)
calima wrote:
every function must return at minimum 16 bits, which means that a function returning 8 bits must zero the X register.

Really? That sounds very strange. Is this in the documentation anywhere?
Re: Serious neslib bug when used from C
by on (#165273)
Not sure where it is in cc65 docs, but here's the main dev comment:
https://github.com/cc65/cc65/issues/268 ... -189147836

Quote:
It's quite common that compilers
presume all functions to return "at least" an (unsigned) int. This is to
simplify the implicit promotion to int for expressions as described by the
C spec.


Shiru replied that he won't fix this, since he hasn't hit this bug in any of his projects. It's quite a shame the #1 platform library can't be trusted.
Re: Serious neslib bug when used from C
by on (#165275)
neslib is just a subset the default cc65 NES runtime.

Of course Shiru won't fix it, it's not his code.


... C's type promotion rules are actively stupid on an 8-bit CPU.
Re: Serious neslib bug when used from C
by on (#165278)
lidnariq wrote:
neslib is just a subset the default cc65 NES runtime.

Of course Shiru won't fix it, it's not his code.

No, shiru's neslib includes a lot of stuff of his own that is useful for game development, and the problems in question are definitely with code that he wrote.

...which he wrote with the assumption that an 8-bit return type means only A is relevant to the return value, but apparently CC65 doesn't have such a convention and all return values are 16-bit. Hence, bugs that manifest only in specific situations (e.g. where the return value is immediately promoted to int).

I made that assumption myself too, but I was lucky that I mostly used void functions, and the cases where I didn't were luckily never used in promotion.
Re: Serious neslib bug when used from C
by on (#165280)
Maybe that's why I didn't hit the problem in the past, most likely. My usage of integers is quite limited.

Anyways, workarounds should be easy. Whenever you identify this problem, just "& 0xff" the return value. Fixing the lib should be easy as well, there are not many functions which return values. Wouldn't a LDX #0 just before the RST do the trick?
Re: Serious neslib bug when used from C
by on (#165491)
Since this isn't the first issue I've had with neslib that Shiru isn't interested in, I'm forking it. It's also been a pain to download from a personal site inside a zip file.

I'm far from the best person for this, my 6502 asm is rudimentary at best, but since nobody else is... Pull requests welcome.

https://github.com/clbr/neslib
Re: Serious neslib bug when used from C
by on (#165557)
Since this little factoid about CC65 not really having 8-bit returns is omitted from the documents, I wrote a new document to explain how function calls work in general, hopefully it gets picked up:
https://github.com/cc65/cc65/pull/274

It turns out there is also a wiki, which has differently organized information, but this info is now available there too (at long last?):
https://github.com/cc65/wiki/wiki/Parameter-passing-and-calling-conventions
Re: Serious neslib bug when used from C
by on (#190225)
Hit another bug with neslib. Its init code does not disable the APU frame counter IRQ, which caused infinite IRQs the moment I executed "cli". Fun tracking that one down.
Re: Serious neslib bug when used from C
by on (#190227)
What IRQ source were you trying to use? Does neslib include facilities to configure mapper IRQ or DMC IRQ? If not, then perhaps neslib's mentality is "This library does nothing to support IRQs. If you have an IRQ source, configure it with a library for that particular IRQ source."
Re: Serious neslib bug when used from C
by on (#190229)
tepples wrote:
Does neslib include facilities to configure mapper IRQ or DMC IRQ? If not, then perhaps neslib's mentality is "This library does nothing to support IRQs. If you have an IRQ source, configure it with a library for that particular IRQ source."

Is this from a parallel universe where neslib is some robust modular library with a community of thousands contributing plugins and for $21 you can register for neslib premium?

neslib just doesn't do IRQs. ;P its irq handler is explicitly implemented as an rti (shared from NMI to save a byte). no cli is expected.

The actual mentality is that shiru tried to save space as much as he could manage, so cut things like initialization for unused features.
Re: Serious neslib bug when used from C
by on (#190234)
Its init code does disable DMC IRQs, so the frame counter is clearly an oversight. It's fixed in my fork.
Re: Serious neslib bug when used from C
by on (#190239)
calima wrote:
Its init code does disable DMC IRQs, so the frame counter is clearly an oversight.

Heh, I'd actually presume that disabling the DMC IRQ is the oversight. (He really does seem to have a mandate to keep the code size small. I remember having a rather difficult time trying to follow the carry flag assumptions around in Famitone.)