Arduboy Title not showing on boot

So I have been developing a game on the arduboy for a few days now and the game is getting pretty beefy.

I suddenly noticed the “ARDUBOY” title is not showing up when the arduboy boots and the lights don’t flash different colors like they used to.

I used to get the “ARDUBOY” title earlier in my game development, but I do not know what changed.

I installed a couple of community games via a hex uploader. I see the “ARDUBOY” title when those games start up but when I flash my game back onto the arduboy, no title and no flashing lights again.

The games runs just fine but I feel like I am supposed to be seeing the title screen and flashing lights and the fact that I am not makes it seem like I have broke something.

Did you replace arduboy.begin() with arduboy.boot()?
Or (more worryingly) are you not calling either?

Alternatively, are you writing to EEPROM?

(Without actually having access to the code, we can only make guesses at what the probable cause is.)

@Pharap i call arduboy.begin() at the beginning of setup. I am not using arduboy.boot() anywhere.

I am not accessing EEPROM at all.

I can’t paste the code here because I am not at my workstation at the moment but I pushed it to github here. That is the most up to date push

I can’t see anything immediately obvious.
By the looks of it arduboy.begin() is the first thing that’s called so the logo should show up if it’s also appearing for other games.

I can’t actually compile the code to test it myself because I don’t have LinkedList.h and I’m not sure which linked list library that’s supposed to be.
(If it’s this one then I’d strongly suggest finding a cheaper alternative.)


Even if you aren’t using EEPROM it’s possible that one of the other games you’ve used has accidentally overwritten the part of EEPROM that determines whether the Arduboy logo appears.

Have you used any of the games on this list:

And is your Arduboy still showing the Arduboy logo when you load other games onto it?

@Pharap
That is actually the linkedlist library I am using. I wasn’t expecting to be using so much of the program space so I will probably switch to something better, but it works for now.

I have not used any of the games from that list

I flashed the Arduboy with Omega Horizon and the Logo appears just fine.
I flashed the Arduboy with the button example and the Logo actually does not show up.

I just ran my code on the emulator here and it did not show the logo there either.

Another update: I ran the SetSystemEEPROM example used the options to reset the EEPROM to system default used for Arduboy. I flashed and ran the buttons example again and this time it blinked the lights and showed the arduboy logo.

Then I flashed my game onto the arduboy and it DID show the Arduboy title and flashed the lights.

I think the EEPROM might have been overwritten by a failed firmware upload attempt.
Whatever it was, the SetSystemEEPROM example fixed it and now it is back to normal.

Now on to finding a size friendly alternative to LinkedList.

Thanks for the help

1 Like

Now that I know which library you’re using I was able to compile and run it, and when I run it, the logo appears, even on Project ABE.

I’m slightly concerned that it might have been another game though, because that would imply there’s another one we aren’t aware of.

I did check just in case Omega Horizon overwrote it,
but that’s only writing to eeprom in one place and it’s using the Arduboy2 sound library to do so so it’s almost certainly not that.

A failed upload might be possible, but usually uploading doesn’t affect EEPROM, so if that were the case then it’s a very rare fluke.

I may have or know of a suitable replacement, but the most suitable replacement depends on what characteristics you need.

E.g. insertion from the front and back, insertion in the middle, indexed random access, upper limit on the size of the list et cetera.

If you definitely need dynamic allocation then I’d suggest trying this one, but to be honest using new and any kind of dynamic allocation really chew into memory and increase the chance of heap fragmentation so they’re generally avoided on Arduboy games.


Edit:
I tried substituting with a slightly modified version of my old List class.
I had to cut the number of allowed objects down to take the RAM below the danger line, but using my List instead of the LinkedList brought progmem usage down from 99% to 54%.
That means that LinkedList class is chewing through almost half of progmem!

Also if you want any more advice on saving memory I’d be happy to help.

I can already see that you could probably save quite a bit with the flash string trick.

@Pharap
I will go ahead and try substituting linkedlist with your list library because those results sounds great!
How did you go about making the substitution. I was looking at the library and the usage looks like it would be about the same, but I am having trouble creating a list of structs for the menus.

This is what I tried, forked from what I believe is the point I grabbed the repo at (you’ve added some changes since then):

The numbers will most likely need to be tweaked,
and it’s entirely possible that I’ve accidentally broken something,
but it seems to work more or less as it should.

One thing I noticed while making the edits is that you add ‘nodes’ to your menus in setup and then seem to never modify them ever again, so you unless you’re planning on modifying them later, you might as well just make the data constant (and perhaps even put it in progmem), which would probably save you a bit of effort.

Good call with the change to dir by the way, an int will be both cheaper and faster.

You could go a step further and use uint8_t to avoid wasting the upper byte of int.
For that matter there’s probably a lot of ints you could replace with uint8_t to cut size down.
The ones on your Player, Powerup, Enemy et cetera are the most important ones because you’re storing multiple copies of them so any waste is multiplied.

@Pharap
You are absolutely right about the ints. I will make those changes once I get the library change working. I did get it to compile with the changes, but you are correct in your suspicion that something may have broken. For some reason when using the RPG weapon, the game will randomly quit back to the main menu. Not only does it do that, but it will also not offer the menu option to start the game again.

I did have intentions to expand the menus a bit later down the line.

Edit: game freeze issue is not just limited to the RPG and it will actually sometimes freeze with the enemies and character still on the screen.

Could just be RAM. Need to tweak the numbers like you said.

Sorry, I forgot to remove the #include "LinkedList.h" line right near the top.
Just remove that and it should work.

As in add more entries, or add entries that are unlocked as the game progresses?

Both can have the menu data stored in an immutable way, the latter would just require a way to track which entries are visible, like a bit vector or just an index specifying how many should be visible (if they’re unlocked sequentially).

I’ve identified the bug. Without meaning to gloat, I’m happy to report it’s not my fault. :P

The problem is in runExplosions.

When explosions.removeAt(i); is called, the continue takes the code back to the enemies loop, but not the explosions loop, which means i < explosions.getCount() isn’t re-checked, and in the case that explosions.removeAt(i) has caused explosions to become empty, i will refer to an invalid item and the next call to removeAt will try to remove a nonexistant object, which will subsequently fail.

The best way to solve this is to check that i is still valid after calling removeAt, and take that as a cue to exit the outer loop. I like this solution because it avoids extra work.

Originally I had some assert functions in removeAt that would have detected this problem and reported it, but I commented them out when I tore the file out of the library it was originally a part of because I assumed it wouldn’t be necessary to bring them along.

This is a logic error with the calling code, hence it should break in a loud and nasty way.
Silently consuming the error would just be setting the calling code up for further failures, as well as being less efficient because of the extra checking.


I think a good solution would be:

explosions.removeAt(i);

if(explosions.isEmpty())
	break;
	
continue;

That fixes the explosion, but there’s a similar error elsewhere that needs to be tracked down.

I think I’ve found the other problem in runShots:

shots.removeAt(i);

//enemies[z].dead = true;
enemies.removeAt(z);
//Serial.println("Enemies remaining: " + (String)enemies.getCount());
player.kills++;
		
if(shots.isEmpty())
	break;

continue;

I figured it would be in a similar NxM loop that was attempting two removeAts in quick succession.
Sure enough that seems to have fixed the problem.
Now there are explosions everywhere without a reset in sight.

Hahaha before I get to the code change, I must say you are killing it with finding the bugs. Go ahead and gloat! It’s my code and I can’t even find these issues myself.

As for runExplosions, In a push I made after the version you are working with, this is what runExplosions looks like

void runExplosions() {
  //for (int i = 0; i < explosions.size(); i++) {
  for (int i = 0; i < explosions.getCount(); i++) {
    
    //Explosion explosion;
    //explosion.x = explosions[i].x;
    //explosion.y = explosions[i].y;
    //explosion.r = explosions[i].r + 1;
    //explosion.lim = explosions[i].lim;

    explosions[i].r = explosions[i].r + 1;
    
    if (explosions[i].r > explosions[i].lim) {
      explosions.removeAt(i);
      continue;
    }
    //else
    //  explosions[i] = explosion;
    
    //for (int z = 0; z < enemies.size(); z++) {
    for (int z = 0; z < enemies.getCount(); z++) {
      float distance = sqrt(sq(explosions[i].x - enemies[z].x) + sq(explosions[i].y - enemies[z].y));

      // Check if enemy in explosion radius
      if (distance <= explosions[i].r + circle_width) {
        enemies.removeAt(z);
        player.kills++;
      }
    }
    arduboy.drawCircle(explosions[i].x, explosions[i].y, explosions[i].r, WHITE);
  }
}

I will make the changes you suggested to runShots though because I have not done that.

Something else I have noticed is that right now, the game won’t make it past wave 14 or 15 without crashing and sometimes crashes even sooner like at wave 4.

I adjusted the fps from 60 to 30, and the game ran all the way until wave 20…but then I died because I suck at the game.

I am going to try your change suggestions back up to 60fps

Update: It looks like the code changes worked. Ran it on 60fps and made it to wave 34 then died.
Only problem is that the kills are not being counted properly. Working on fixing it now

I’ve had a lot of practice.

Also I use Serial.println to narrow down the point where it breaks.
When the game resets or freezes, the last thing printed to the serial monitor will give you an indication of where the bug is.

Ah, that looks a lot better.

That shouldn’t have any bugs because getCount is always checked every time after removeAt.

I’d like to take this opportunity to point out that these bugs existed before, but LinkedList was effectively swallowing/burying them.

Think of it like this: the code was bashing its head against the wall and LinkedList was putting a plaster on it.
With these changes, the code is no longer hitting its head against the wall. :P

In what way?

If each ‘shot’ in runShort is supposed to remove more than one enemy then I can see why it would be breaking and I can see a fix for it.

@Pharap
Haha yea I was wondering why these bugs only showed up after LinkedList was removed, but that would explain it.

So the kill count is actually coming up short. The number of enemies spawned per wave is equivalent to the number of the wave. So in order to calculate how many enemies should be killed by wave 34, you would get the sum of all numbers between 1 and 34…but my “kill count” at the end was 84 or something.

The only time multiple enemies get killed is if a nuke powerup is detonated or if you group a bunch of enemies together and shoot an RPG at them. RPG shots have the potential to kill multiple enemies in one shot, but I believe I accounted for both the nuke and RPG shots in the runExplosions method.

Could it have something to do with storing kill count as uint8_t instead of int

Update: Changed kill count to int, made it to wave 44, had 970 kills when I died without killing all of the enemies on the 44th wave. That adds up just about.

The bugs should be fixed for now and now I have plenty of space to add more feature. Thanks again for the help.

Changes have been pushed to github

1 Like

uint8_t is an 8-bit unsigned integer, which goes up to 255 (28 - 1).
int is a 16-bit signed integer, hence it goes up to 32767 (215 - 1).
But you should probably use uint16_t, which goes up to 65535 (216 - 1).
Or if you really think you need it, uint32_t goes up to 4294967295 (232 - 1),
which is hopefully more than you’ll ever need.
(If you need more, there is a uint64_t, but that’s just madness. :P)

(Do I take it you aren’t quite up to scratch with binary? Or just the data type sizes? Either way I have some helpful online resources that might be of use if you want them.)

You don’t have to worry so much about keeping the stats small because there’s only one of each.
(Still keep them small if you can, but their singularity makes them less of a concern.)
It’s the things that have multiple instances that are the concern because every bit of waste is multiplied.
If you have 16 bullets with a single byte of waste that’s 16 bytes wasted.

Yea I will get more granular with the data types as I progress. I am decent enough with binary, but not familiar with the different integer types. Haven’t had this many constraints on my program in a while so I haven’t had to use different uints as often.

The types are documented here:
https://en.cppreference.com/w/c/types/integer

(Note: although the Arduboy is programmed with C++, Arduino only implementes the C standard library, not the C++ standard library, hence why that’s the documentation for the C standard library types rather than the C++ equivalents.)

The rules of thumb are:

  • 4 unsigned types, uint8_t, uint16_t, uint32_t and uint64_t
    • The lowest value of all unsigned types is 0
    • The highest value is equal to 2N - 1 where N is the number of bits, either 8, 16, 32 or 64 respectively
  • 4 signed types, int8_t, int16_t, int32_t and int64_t
    • The highest value is equal to -(2N - 1) where N is the number of bits, either 8, 16, 32 or 64 respectively
    • The highest value is equal to 2N - 1 - 1 where N is the number of bits, either 8, 16, 32 or 64 respectively

Types like char, int, short, long and long long vary between platform.
In particular int is often 32-bits wide on most desktop computers and certain other embedded systems (e.g. ARM) but on the Arduboy it’s 16-bits wide.
Hence it’s typically better to use the exact types because they’re more portable, express the intent better, and are generally less surprising.

This is probably the biggest surprise for people used to cutting code in any modern language on a PC - you don’t really consider the memory a variable uses so everything becomes a ‘full sized’ integer or worse a variant. This little platform isn’t so forgiving and you quickly realise that you have to be much more economical with your memory use.

Its a good thing ultimately :slight_smile:

@filmote
Yea I am mostly used to writing for ESP8266 and ESP32 projects. Even though you don’t get as much space as you would developing an app on a PC, it is certainly more than an ATmega32u4.

The challenge of trying to find tiny spots to save space is fun though.

@Pharap
I am going to start paying better attention to which data types I use in the future on the arduboy. I imagine the other developers who contribute to the community games pay special attention judging by how many features I see packed into these games with such little space. Thank you for the resources.

2 Likes

If you want more interesting resources, have a look at my resource collection: