[Wiki] Using PokittoDisk (Saving & Loading)

That’s because you’re doing this:

The function doesn’t return the value, it returns how many bytes have been read, so you’re reading the value and then overwriting it with how many bytes have been read (which will always be 2 if it’s worked properly).

That’s why in my example:

I am using two different variables, one of which is named bytesRead because it’s the number of bytes that have been read.

3 Likes

I’m attempting to save a screenshot of my game on hardware

I assume the following should work, but I’m getting nothing…

[code]
bool saveRAW() {
pokInitSD();

fileOpen("image1.raw",FILE_MODE_READWRITE);

if(fileOK() != 0) {
	// File hasn't opened properly,
	// handle this.
	return false;
}

fileSetPosition(0);

// Save immediate area
for (char y = 0; y < 88; y++) {
	for (char x = 0; x < 110; x++) {
        char pix = game.display.getPixel(x,y);
		char 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;

/*
filePutChar®;
filePutChar(g);
filePutChar(b);
*/
fileWriteBytes(reinterpret_cast<uint8_t *>(&r), static_cast<uint16_t>(sizeof®));
fileWriteBytes(reinterpret_cast<uint8_t *>(&g), static_cast<uint16_t>(sizeof(g)));
fileWriteBytes(reinterpret_cast<uint8_t *>(&b), static_cast<uint16_t>(sizeof(b)));
}
}

fileClose();
return true;

}[/code]

I’m guessing you’re using the older SD library? (petitfatfs)

The old SD library requires the file to already exist and be the correct size. It won’t create, rename or resize files.
The newer SD library (SDFileSystem) will fix this.


Also, what are the multiplications and adding for?:

The numbers seem a bit arbitrary.

656 to 888 rgb conversion

Will as in, not available yet?

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