Storing map data in PROGMEM?

So I’m making a platformer, and i needed to use arrays to store maps.
However, when i add PROGMEM to the map data, it reads other parts of the memory that aren’t the map!
Does anyone know why, and how can i fix it? Here’s the source code of the project.
Thanks!

1 Like

I’m guessing you aren’t using pgm_read_byte and friends?

If you put something in progmem you can’t read it normally,
you have to use one of the special pgm_read functions to read it.

(There’s a very good technical (hardware) reason for this,
but I won’t go into it unless you want to know more.)

There’s a handy thread here:

And all the progmem functions are documented here:
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

I can’t really provide any more specific advice unless you can specify what you want to read from progmem (integers, Tiles, Players).


Ah, that explains that like I received the other day.

You might also find this thread useful:

And subsequently this:


By the way, instead of:

for (uint8_t y = 0; y < 8; y++) {
	for (uint8_t x = 0; x < 16; x++) {
		switch (maps[level][y][x]) {
			case Tiles::Sol:
				Sprites::drawOverwrite(x * 8, y * 8, tileset, 0);
				break;
			case Tiles::Spi:
				Sprites::drawOverwrite(x * 8, y * 8, tileset, 1);
				break;
			case Tiles::Coi:
			case Tiles::Exi:
				Sprites::drawOverwrite(x * 8, y * 8, tileset, 3);
				break;
		}
	}
}

You could do something like this:

int getTileIndex(Tiles tile)
{
	switch (tile)
	{
		case Tiles::Sol:
			return 0;
		case Tiles::Spi:
			return 1;
		case Tiles::Coi:
		case Tiles::Exi:
			return 3;
		default:
			return -1;
	}
}

for (uint8_t y = 0; y < 8; ++y)
{
	for (uint8_t x = 0; x < 16; ++x) 
	{
		const int index = getTileIndex(maps[level][y][x]);
		
		if(index > 0)
			Sprites::drawOverwrite(x * 8, y * 8, tileset, index);
	}
}

It should work out cheaper.

(Also I’d recommend renaming Tiles to Tile because each Tile only represents a single tile,
and possibly use full tile names instead of short 3-character names because at the moment I have no idea what ‘Coi’ and ‘Spi’ mean.)

1 Like

I tried pgm_read_byte(); and it worked! Thank you!

WHOOPS, I forgot to rename them! The only reason I used 3-character names is to make level editing easier.

1 Like

If you find manually typing levels awkard you could type something short and then do a find & replace afterwards.
(Which is a lot easier with a different code editor - the Arduino IDE is pretty terrible for anything other than compiling and basic text editing.)

You could also write a level editor, but that’s a lot of effort to go to.

Something that takes a bit of effort but less effort than writing a proper level editor is to write a level ‘converter’ that lets you produce levels in a different format and then ‘convert’ that to C++ code.
E.g. something that takes a .png and interprets pixels of particular colours as particular tile types (e.g. (0, 255, 0) for grass, (255, 255, 255) for air, (0, 0, 255) for water), then you can make your levels in an image editor.


If you need any more help/advice with anything, don’t hesitate to ask.

1 Like