Not for font rendering though, for that you’re using SpritesB:

(Unless the names aren’t being rendered with Font3x6, but I would assume they probably are.)

So… downgraded to the older 1.6.21 AVR boards package, recompiled Curse, and the glitches went away… so it seems like whatever is causing them is something that was introduced in the gcc version change from 4.9.2 up to 5.4.0 in AVR boards package 1.6.22 and onwards? :face_with_raised_eyebrow:

(the recompiled .hex was too big for uploading to an Arduboy - but the FPGA doesn’t have this restriction)

1 Like

Mmmm … strange. Is it worth stripping the code back and see whether its the ArdBitmap library or the sound code you put in?

Compiling with the old gcc vs. new gcc produced the same kind of glitches in Rooftop Rescue - so it must be something common between the two games, drawOverwrite maybe?

I’m just throwing a few random rubber ducks here:

  • comparison operation between both signed and unsigned.
  • plain char changed and became signed/unsigned (essentially same as above)
  • missing return value in function (that happened to work because it used the return-value register as temporary)
  • missing volatile qualifier / compiler started ignoring it

Been burned by those by accidents before on compiler changes. And “Oh, would you look at that… This-or-that warning isn’t enabled by default, because reasons.”


Test that hypothesis with some code.
And don’t forget to compare Sprites to SpritesB to see if there’s a difference.

It’s possible the compiler’s changed the way it allocates registers,
and registers have caused Sprites to spontaneously combust before:

Just to check, the size of the platform’s int hasn’t changed between versions has it?

Because I know of one part of the Sprites code that assumes int is 16 bits and depends on 16-bit overlflow, and I’ve seen that part cause bugs on systems where int is 32 bits.

If anyone is using plain char in arithmetic or mixing signed and unsigned values in comparisons then they probably deserve the bugs.

That probably sounds harsh, but I’ve seen far too many people say “it doesn’t matter if it’s undefined/implementation-defined, it works for my system” or “well it’s working now, so that doesn’t matter”.

But the fact of the matter remains that the compiler authors reserve the right to change how those things are implemented, and if they do and it breaks someone’s code then it’s not the compiler authors who are in the wrong - they’re still conforming to the standard - it’s the code that’s relying on behaviour that could change without warning.

This wouldn’t even be possible if the Arduino IDE didn’t use that god-awful -fpermissive flag.
That sort of thing should be a hard error, but -fpermissive demotes it to a warning.

Mini rant about -fpermissive

I’m assuming they use -fpermissive because they believe it makes writing code easier for beginners because beginners find errors scary/annoying,
but in the process they end up creating bugs that cause problems that can even trip up experts,
which beginners would probably struggle to diagnose,
so in the long run they’re actually making life harder for everyone.

Speaking of volatile, in C++20 (due to be ratified this year),
certain uses of volatile will be deprecated:

Stuff slips through sometimes. It’s even easier to accidentally do with templates.
Doesn’t take long to fix but it still happens.

Yeah. Those kind-of make sense but only from a pure language-lawyer point of view and not a practical one IMHO.

(volatile int &)X += 5;

can’t be guaranteed atomicity by every CPU on its own but it’s still (or would be still) useful way to tell the compiler “re-read, increment, and write right here and sync your register values, but cache it otherwise for the rest of the loop. I don’t care that it gets flushed right this instant.”

Very common for lock-less FIFO buffers where one thread writes, one reads, and delayed flush is more than acceptable on a giant NUMA system. I’ve ran a few tests on my 1950X and even old i7 and it makes a pretty large difference with hyper-threading.

The “correct” C++ solutions I saw all involves brutal overkill synchronisation primitives that choke the internal CPU cache bus with unnecessary writes on the reading thread’s end or even involve an OS kernel round-trip.


I’ll have to take your word for it because I’ve honestly never had that happen to me.

There’s a very interesting video by JF Bastien (compiler engineer and head of C++ development at Apple) discussing some of the motivations behind the deprecation of volatile in certain situations.

To cut a long story short, support for compound assignment operators on volatile lvalues was removed because there was a lot of confusion about what they actually mean and how they’re allowed to be implemented.
E.g. people who assumed they were atomic vs people who assumed they actually can’t be atomic.

+People who assumed it was implementation-defined and wrote a bunch of AtomicOP() templates for where it matters.

Great, this means now that it’s deprecated I need to make myself a VolatileDec/Inc/Add/etc template set too and got some eventual refactoring ahead of me…

What’s another set of operator replacement wrappers…
Sometimes I wonder why C++ even bothers to have operators. :stuck_out_tongue:

Thanks for the heads up. Been a busy year and I haven’t kept up with the newest C++ proposals.

I don’t use multithreading very often, so I could be wrong,
but isn’t that what std::atomic is for?

Compound assignment operators are defined for std::atomic<T> when T is an integral type (as of C++11) or a floating type (as of C++20).

Though I think whether they’re actually ‘CPU atomic’ or whether they acquire a lock is CPU-dependent, checkable via is_lock_free.

All atomic types except for std::atomic_flag may be implemented using mutexes or other locking operations, rather than using the lock-free atomic CPU instructions.

I’ve mostly been checking because I’ve got a ticket for the concept hype train.

You’re right but that’s (A) a c++11 thing (and C++20 for floats), my engine predates that by years. (B) actual implementation can be overkill or buggy.

And C) Console SDKs are often a disaster and way behind. :sob:

Things like “Oh, there’s no fopen, you have to use XBoyStationCetaceaOS4_DVDFileOpen(OPENFILE_STRUCT &result, const FILESPEC &file_path) instead.” or don’t even have a file system at all.

The best part is when fopen and the likes are “implemented” but returns failure for everything so you can’t even implement your own replacement fopen without rewriting the entire SDK’s build system just so you can use the approved SDK libs but still override some of their broken stub functions and pass their certification process.

The burden of evaluating the support of every neat C++11 (and newer) features before risking relying on them is often much more work and risk than just implementing a wrapper “just in case”.

Other example: I can’t use std::thread at all. Doesn’t work. Every console OS/SDK has some sort of threads (today) but they’ve all got some weird things going on with the way they work and their API (sometimes for valid reasons).

Lots of fun times.

1 Like

In that case what you really need is either a 3rd party library or platform-specific code.

I wouldn’t know, the closest I’ve been to a console SDK is XNA and Vita homebrew.
(The latter is really not fun to compile for if you don’t have a Linux computer.)

The usual answer to that is to complain to your standards implementor,
because that’s a problem with their implementation, not the standard,
but if console companies are anything like I think they are,
you’d probably have more luck complaining to the nearest available cat.
(As we all know, cats run the internet.)

Spoiler: when nobody’s looking, I reinvent the wheel.
I’ve written 80% of a <type_traits> and <utility> implementation about 3-4 times now.
I also once wrote a std::vector implementation and a std::shared_ptr implementation just for the hell of it.

1 Like

…there’s now an ‘official’ repo on the MiSTer-devel organisation:

1 Like

If anyone knows Verilog (or wants to learn :grin:) the hardware description language for the AVR instructions in alu.v probably has room for improvement - there are still some weird behaviours going on, for example - LEFT / RIGHT controls for the helicopter in Rooftop Rescue don’t respond, and there’s something happening with collision detection in Fire Panic where the jumpers fall straight through the ‘life net’ instead of bouncing off! :sweat_smile:

The Timers may also need some attention - sound from ArduboyTones is (mostly) working, but I still don’t hear anything in games using ArduboyBeep / Playtune.

This is all pretty exciting though - wouldn’t be too much of a leap to make a PCB for an FPGA-based Arduboy, that would be backwards-compatible with already compiled hex files, but also be easily expandable to whatever amount of peripherals or RAM / Flash Memory your heart desired! :heart:

1 Like

Turns out this is something around the FPGA’s interpretation of instructions in the absT() function - I changed this line in the PlayGameState.cpp:

uint8_t delta = absT(victimXCentre - playerXCentre);

to instead be:

uint8_t delta = (victimXCentre >= playerXCentre) ? (victimXCentre - playerXCentre) : (playerXCentre - victimXCentre);

and the victims then bounced as expected!

(Also tried changing from absT() to abs() and then even #undef abs to use the ‘non-macro’ version, but all of these still let the victims drop to the ground…)

Hrm, what happens if you try this?

uint8_t delta = static_cast<uint8_t>(absT<int>(static_cast<int>(victimXCentre) - static_cast<int>(playerXCentre)));

(It’s heavy on the casting because I want to be sure of the types.)
And also this?

uint8_t delta = static_cast<uint8_t>(absT<int>(victimXCentre - playerXCentre));

My instinct is that either:

  • The compiler isn’t properly promoting the two uint8_ts used in the subtraction to int, causing absT to be called with a T of uint8_t, which thus fails on overflow
  • Detecting the sign flag isn’t working properly, causing the v < 0 check to fail

It’s worth noting that abs, is implemented as*:

#define abs(x) ((x)>0?(x):-(x))

Which would imply integer promotion might be more likely.
Or perhaps the ‘two’s complement negate’ instruction?
That would be a weird thing to break though.

* Yes, this does mean that if x is 0, the result is effectively -0.
If you try using abs with 0.0 you’ll get a nasty surprise. :P

MorgothCreator managed to dig out the cause of all these bugs, turns out the SBIW instruction had been incorrectly documented?

ATmega SBIW wrong documentation


Hi, I have a small collection of arduboys since kickstarter way back when. Time passes, new interests, etc., even forgot my password to this forum, so imagine my surprise when I recently updated MiSTer to see the Arduboy core in root.

Just had to come in and say, “This is awesome! Thank you!”

One small little thing to make perfection, is it possible to have the Arduboy for MiSTer output 240p 15kHz?

1 Like

Sorgelig has obliged - with code added for a new 15kHz / 16:9 video mode for the core, give the new release a try? :wink:

Very happy with the progress on the FPGA core now! Have to give a sincere thanks to @filmote @Vampirics @Mr.Blinky @Pharap and anyone else I may have missed who has contributed to the Press Play on Tape games - honestly it is the sophistication of the code in these games that helped to bring a lot of issues in the FPGA implementation to the surface! :grinning: