[Wiki] Using PokittoDisk (Saving & Loading)

I was hoping for an explanation of the magic numbers.
I’m guessing that means you don’t know how the numbers are derived?
(And subsequently I’ll have to look elsewhere.)

That’s the latest topic I could find about the matter, so I’m assuming yes - it’s announced but not released.

Until then, you can pad a file to the right size and only store a limited number of screenshots.

I double checked, seems it’s been added to the lib:

But there’s no Pokitto-specific tutorial yet, so you’ll have to read the documentation or check to see if there’s a tutorial for the original.

There’s a Pokitto example here though:

Yeah, I just googled that, if it worked, i’d probably change it, but I don’t seem to be able to write anything to a pre-existing file.

however if I wrote it myself it would be…

char r = ((color >> 11) & 0x1F) *8; // first 5 bits * 8
char g = ((color >> 5) & 0x3F)*6; // next 6 bits * 6
char b = (color & 0x1F)*8; // last 5 bits * 8

Might be more readable and may give the same reults

That is a fully working example. Just copy the settings to your project, and use fprintf and other common file accessing calls. In addition, it is a clean implementation of the SDFilesSystem, so you can use any examples from mbed.com without changes.

1 Like

Fair enough.

Most likely the person who wrote it either wanted to make use of a fused shift and add instruction or there’s some mathematically significant reason involving advanced colour theory (like spreading the colour across the colour plane better).

For what it’s worth though, it might be better to just do the inverse of the Pokitto’s Display::RGBto565 function, which is defined as:

uint16_t Display::RGBto565(uint8_t R,uint8_t G,uint8_t B) {
    uint16_t color;
    color = B>>3;
    color |= ((G >> 2) << 5);
    color |= ((R >> 3) << 11);
    return color;
}

Hence the inverse would be (excuse the stylistic differences)

uint32_t rgb565ToRgb888(uint16_t colour)
{
    uint8_t b = static_cast<uint8_t>(((colour >> 0) & 0x1F) << 3);
    uint8_t g = static_cast<uint8_t>(((colour >> 5) & 0x3F) << 2);
    uint8_t r = static_cast<uint8_t>(((colour >> 11) & 0x1F) << 3);
    return static_cast<uint32_t>(r << 16 | g << 8 | b << 0);
}

Or to optimise it (if you don’t trust the compiler to optimise it for you, though I’m willing to bet this version results in the exact same code):

uint32_t rgb565ToRgb888(uint16_t colour)
{
    return static_cast<uint32_t>
        (
        ((colour & 0x001Fu) << 3) |
        ((colour & 0x07E0u) << 5) |
        ((colour& 0xF800u) << 8)
        );
}

(I tested to check, they give the same results.)

Obviously this leaves the last 2-3 bits truncated, but that can’t be fixed without looking into how the rgb565 values are interprepted by the screen, and to be honest it’s probably not crucial.

If in doubt, fill the 2-bit cases with 0x2 or 0x1 and the 3-bit cases with 0x4 or 0x3.


For what it’s worth, I did some testing and the code you’re using doesn’t line up with the way the Pokitto converts to 565.
I can provide the code I threw together to test if you want (it’s in C#, but there’s no reason it wouldn’t behave the same in C++ as far as I can tell).
I’m guessing it’s some sort of ‘corrected’ system designed to shift the colours more evenly across the colour plane or something.

1 Like

Hi @spinal I am also looking into saving and loading something to/from the SD card. However I was wondering if there is an error in this piece of your code:

If the file is opened correctly, fileOk() will return true so saveRaw() will do no nothing and return false I think.
Maybe this is the reason why it wasn’t working?

I should have came back to this sooner, I got it working, the code is still in my Pokittaire game. I think the issue was something about not including the correct headers, or the build settings were slightly wrong or something like that.

bool saveBMP(char* filename){
// no longer used
char w=110, h=88;

FILE *f;
int filesize = 54 + 3*w*h;  //w is your image width, h is image height, both int

unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
unsigned char bmppad[3] = {0,0,0};

bmpfileheader[ 2] = (unsigned char)(filesize    );
bmpfileheader[ 3] = (unsigned char)(filesize>> 8);
bmpfileheader[ 4] = (unsigned char)(filesize>>16);
bmpfileheader[ 5] = (unsigned char)(filesize>>24);

bmpinfoheader[ 4] = (unsigned char)(       w    );
bmpinfoheader[ 5] = (unsigned char)(       w>> 8);
bmpinfoheader[ 6] = (unsigned char)(       w>>16);
bmpinfoheader[ 7] = (unsigned char)(       w>>24);
bmpinfoheader[ 8] = (unsigned char)(       h    );
bmpinfoheader[ 9] = (unsigned char)(       h>> 8);
bmpinfoheader[10] = (unsigned char)(       h>>16);
bmpinfoheader[11] = (unsigned char)(       h>>24);

f = fopen(filename,"wb");
fwrite(bmpfileheader,1,14,f);
fwrite(bmpinfoheader,1,40,f);


for(int y=0; y<h; y++){
    for(int x=0; x<w; x++){
        int pix = game.display.getPixel(x,h-y-1);
        int color = game.display.palette[pix];
        char r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6;
        char g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6;
        char b = (((color & 0x1F) * 527) + 23) >> 6;
        fwrite(&b , 1 , sizeof(b) , f);
        fwrite(&g , 1 , sizeof(g) , f);
        fwrite(&r , 1 , sizeof(r) , f);
    }
    fwrite(bmppad,1,(4-(w*3)%4)%4,f);
}

fclose(f);
}
1 Like
#include "Pokitto.h"

Pokitto::Core game;

bool saved = false;
bool success = false;

uint16_t counter = 0;
uint16_t readByte = 0;
int reader = 0;
int helper = 0;

int main()
{
    game.begin();

    while (game.isRunning())
    {
        if (game.update())
        {
            if (!saved)
            {
                if (fileOpen("data.txt", FILE_MODE_READWRITE)) success = true;
                while (counter <= 50)
                {
                    fileSetPosition(sizeof(uint16_t) * counter);
                    fileWriteBytes((uint8_t*)&counter, sizeof(uint16_t));
                    counter++;
                    game.display.print((int)counter);
                    game.display.update();
                }
                fileClose();
                saved = true;
            }
            else
            {
                if (game.buttons.released(BTN_A))
                {
                    fileOpen("data.txt", FILE_MODE_READONLY);
                    fileSetPosition(sizeof(uint16_t) * reader);
                    fileReadBytes((uint8_t*)&readByte, sizeof(uint16_t));
                    fileClose();
                    reader++;
                    helper++;
                }
                game.display.print(readByte);
                game.display.setCursor(0,20);
                game.display.print(success);
            }
        }
    }
    return 0;
}

I can’t figure out what mistake I made. It’s just showing a 0 every time. Any ideas?

Zero bytes in reading? Have you checked that the file in sd contains data?

It don’t contains data. There’s a problem with the saving i guess.

I think fileWriteBytes is broken. Better switch to SDFileSystem, if you can.

Ok. I will try that.

What is yhe data file like?

#include "Pokitto.h"
#include "../Pokitto/POKITTO_LIBS/SDFileSystem/SDFileSystem.h"

Pokitto::Core game;

bool saved = false;
bool success = false;

uint16_t counter = 0;
uint16_t readByte = 0;
int reader = 0;
int helper = 0;

SDFileSystem sd(P0_9,P0_8, P0_6, P0_7,"sd");
FILE* fp;

int main()
{
    game.begin();

    if (!saved)
    {
        if (fp = fopen("/sd/data.txt", "wb")) success = true;
        while (counter <= 50)
        {
            fwrite(&counter, sizeof(uint16_t), 1, fp);
            counter++;
            game.display.print((int)counter);
            game.display.update();
        }
        fclose(fp);
        saved = true;
    }

    while (game.isRunning())
    {
        if (game.update())
        {
            if (game.buttons.released(BTN_A))
            {
                fp = fopen("/sd/data.txt", "rb");
                fseek(fp, reader * sizeof(uint16_t), SEEK_SET);
                fread(&readByte, sizeof(uint16_t), 1, fp);
                fclose(fp);
                reader++;
                helper++;
            }
            game.display.print(readByte);
            game.display.setCursor(0,20);
            game.display.print(reader);
            game.display.update();
        }
    }
    return 0;
}

Now using SDFileSystem. The display flickers and nothing happens, that’s not really better.

Zuzu, start by telling what is it that you are trying to do. Then it is much easier to help.

STORYTIME !

When I was in school, I always went to the tool store keeper (a Mr. Malminen, great guy) to ask for tool X. Then he brought it to me. Before he handed it over the counter, he held on to it lingeringly and asked: “what are you trying to do?”. After I explained, he said “I know a better tool for doing that”, took tool X back to the shelf, brought me tool Y, and I went back to class with it. This happened dozens of times. And not only to me, I later heard the same story from all my classmates.

1 Like

not sure if this is helpfull but i recently did some saving for pokitbeast using pokittodisk

void save(){
    uint8_t px[2] = {player.x,player.y};
    if(!fileOpen("SAVE.TST", FILE_MODE_OVERWRITE)){
        fileWriteBytes(px,2);
        fileClose();
    }
}

void load(){
    uint8_t px[2];
    if(!fileOpen("SAVE.TST", FILE_MODE_READONLY)){
        fileReadBytes(px,2);
        player.x = px[0];
        player.y = px[1];
        fileClose();
    }
}

the file has to already exist on sd card since PokittoDisk cant create new files as far as i understand

I’m trying to figure out how to write things to SD :joy:
I’ll need it later to safe game-data. This test program should put numbers on a file and read it afterwards.
It’s important that i can write every object data. Btw i’m testing the r/w speed also.

1 Like

There are 3 options for doing that:

  1. PetitFatFS (built in SD library, used in the loader)
  • fastest, smallest memory use
  • can not create, delete or resize files
  • save file must exist and be correct size (fill it zeroes or other dummy data)
  1. SDfileSystem (external mbed library)
  • can do pretty much anything including creating files
  • not as fast as PetitFatFS
  1. Pokitto::Cookie class (EEPROM cookies for small data, like highscores etc)
    -works without SD
    -very simple to use
    -data size is limited (I would say absolute max 512 bytes, if more use SD instead)
2 Likes

I’m fine with the SDFileSystem, it’s perfect, if it would work for me. I’m don’t know why the code above does’nt work. I’ll debug it now. If anyone knows the issue please tell me :smile:

First, check whether the file is actually being created on the SD card. Put it in an adapter and take a look at it. Use a hex editor to check the values in the file are what you intended.

Then begin debugging the other part

The file is not created because it allready exists. It writes the bytes perfectly aswell. There’s a problem with the reading