Skip to content

Commit

Permalink
Load bitmaps with ASCII chars, hex oder decimal encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
chregu82 committed Aug 16, 2020
1 parent 6c5aa80 commit 151e150
Show file tree
Hide file tree
Showing 20 changed files with 213 additions and 7 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ See [Here](https://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg) for a
reference of the provided xterm color palette.

## Bitmap handling
A maximum of 128 bitmaps can be loaded to the PiGFX, either as list of pixels, or RLE compressed. Loaded bitmaps can then be put onto the background. A transparent color can be specified, these pixels won't be drawn. RLE compression expects a list of 2 byte values: first byte is the pixel color, second byte is the number of pixels to draw with this color.
A maximum of 128 bitmaps can be loaded to the PiGFX, either as list of binary pixels, list of ASCII decimal encoded pixels or list of ASCII hex encoded pixels. All of these can be RLE compressed. Loaded bitmaps can then be put onto the background. A transparent color can be specified, these pixels won't be drawn. RLE compression expects a list of 2 values: first one is the pixel color, second one is the number of pixels to draw with this color.

See [terminal_codes](doc/terminal_codes.txt) for the specific commands.

There are 3 examples for loading bitmaps: [load bitmap](shapes/load_bitmap_sample.bin), [load RLE bitmap](shapes/load_rle_bitmap_sample.bin), [load 10 RLE dinosaur bitmaps](shapes/load_dinos.bin).
There are a few examples in [this directory](sprite/sample).

The Xterm palette is used. A RGB pixel can be converted to this palette by the following formula:

Expand All @@ -189,7 +189,7 @@ Once a sprite is active, you should not manipulate or reload its bitmap source,

Animations could be realized by redefining the sprite with a different bitmap source.

There's a [example](shapes/anim_dinos.bin) for a moving dinosaur (after first loading them).
There's a [example](shapes/sample/anim_dinos.txt) for a moving dinosaur (after first loading them in hex or binary).

There is no collision detection yet.

Expand Down
Binary file modified bin/kernel.img
Binary file not shown.
Binary file modified bin/kernel7.img
Binary file not shown.
Binary file modified bin/kernel8-32.img
Binary file not shown.
Binary file modified bin/recovery7l.img
Binary file not shown.
12 changes: 10 additions & 2 deletions doc/terminal_codes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ Graphics
<ESC>[#<x0>;<y0>;<r>c Fill a circle with center at <x0>,<y0> and radius <r>
<ESC>[#<x0>;<y0>;<r>C Draw a circle with center at <x0>,<y0> and radius <r>
<ESC>[#<x0>;<y0>;<x1>;<y1>;<x2>;<y2>T Draw a triangle from <x0>,<y0> to <x1>,<y1> to <x2>,<y2>
<ESC>[#<idx>;<x>;<y>b Load raw bitmap to index 0-127 with width x and height y pixels. Expects x*y pixel bytes sent after this command.
<ESC>[#<idx>;<x>;<y>B Load RLE compressed bitmap to index 0-127 with width x and height y pixels. Expects RLE compressed pixel data after this command, e.g. 0x10 0x20 draws color 16 for the next 32 pixels.
<ESC>[#<idx>;<x>;<y>;<b>a Load ASCII encoded bitmap to index 0-127 with width x and height y pixels, base=10 for decimal, 16 for hex.
Expects x*y semicolon separated pixels of ASCII encoded colors, e.g. 12;23;44;44;130;130; or for hex C;17;2C;2C;82;82;
A semicolon after the last pixel needs to be sent.
<ESC>[#<idx>;<x>;<y>;<b>A Load RLE compressed ASCII encoded bitmap to index 0-127 with width x and height y pixels, base=10 for decimal, 16 for hex.
Expects RLE compressed ASCII encoded semicolon separated pixel data after this command,
e.g. 16;32; or with hex 10;20; draws color 16 for the next 32 pixels.
Repeat values must be between 1 and 255, of 1 and FF for hex.
A semicolon after the last repeat value needs to be sent.
<ESC>[#<idx>;<x>;<y>b Load raw bitmap to index 0-127 with width x and height y pixels. Expects x*y binary pixel bytes sent after this command.
<ESC>[#<idx>;<x>;<y>B Load RLE compressed bitmap to index 0-127 with width x and height y pixels. Expects RLE compressed binary pixel data after this command, e.g. 0x10 0x20 draws color 16 for the next 32 pixels.
<ESC>[#<idx>;<x>;<y>d Draw bitmap with index 0-127 at position x, y.
<ESC>[#<idx>;<ref>;<x>;<y>s Draw a sprite with index 0-255 from bitmap <ref> at position <x>, <y>.
<ESC>[#<idx>;x Remove sprite with index 0-255, restore background.
Expand Down
2 changes: 1 addition & 1 deletion pigfx_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#define PIGFX_MAJVERSION 1 /* Major version number */
#define PIGFX_MINVERSION 7 /* Minor version number */
#define PIGFX_BUILDVERSION 3 /* Build version. */
#define PIGFX_BUILDVERSION 4 /* Build version. */

/** Versions:

Expand Down
4 changes: 4 additions & 0 deletions sprite/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ png2xterm256: png2xterm256.cpp
g++ png2xterm256.cpp -I../fonts/ -o png2xterm256
rlecomp: rlecomp.cpp
g++ rlecomp.cpp -o rlecomp
bin2hex: bin2hex.cpp
g++ bin2hex.cpp -o bin2hex
bin2dec: bin2dec.cpp
g++ bin2dec.cpp -o bin2dec
60 changes: 60 additions & 0 deletions sprite/bin2dec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <iostream>
#include <fstream>

using namespace std;

int main( int argc, char* argv[] )
{
if( argc!=3 )
{
std::cout << "USAGE:" << std::endl;
std::cout << "bin2dec <source> <dest>" << std::endl;
return 0;
}

std::cout << "Loading " << argv[1] << std::endl;
ifstream inputfile;
inputfile.open(argv[1], ios::binary | ios::ate);
unsigned int filesize = inputfile.tellg();
std::cout << "Input is " << filesize << " bytes" << std::endl;
inputfile.close();
inputfile.open(argv[1], ios::binary | ios::in);

std::ofstream ofs( argv[2], std::ios::binary );


unsigned char binchar;
char high, mid, low;
for (unsigned int i=0; i<filesize; i++)
{
inputfile.read((char*)&binchar, 1);
high = binchar / 100;
binchar = binchar % 100;

mid = binchar / 10;

low = binchar % 10;

if (high > 0)
{
high += '0';
ofs << high;
}
if ((high > 0) || (mid > 0))
{
mid += '0';
ofs << mid;
}
low += '0';
ofs << low;

ofs << ';';
}

ofs.flush();
std::cout << ofs.tellp() << " bytes written." << std::endl;
ofs.close();
inputfile.close();

return 0;
}
51 changes: 51 additions & 0 deletions sprite/bin2hex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <iostream>
#include <fstream>

using namespace std;

int main( int argc, char* argv[] )
{
if( argc!=3 )
{
std::cout << "USAGE:" << std::endl;
std::cout << "bin2hex <source> <dest>" << std::endl;
return 0;
}

std::cout << "Loading " << argv[1] << std::endl;
ifstream inputfile;
inputfile.open(argv[1], ios::binary | ios::ate);
unsigned int filesize = inputfile.tellg();
std::cout << "Input is " << filesize << " bytes" << std::endl;
inputfile.close();
inputfile.open(argv[1], ios::binary | ios::in);

std::ofstream ofs( argv[2], std::ios::binary );


unsigned char binchar;
char high, low;
for (unsigned int i=0; i<filesize; i++)
{
inputfile.read((char*)&binchar, 1);
high = binchar / 16;
low = binchar % 16;
if (high > 0)
{
if (high < 10) high += '0';
else high = high + 'A' - 10;
ofs << high;
}
if (low < 10) low += '0';
else low = low + 'A' - 10;
ofs << low;
ofs << ';';
}

ofs.flush();
std::cout << ofs.tellp() << " bytes written." << std::endl;
ofs.close();
inputfile.close();

return 0;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions sprite/sample/load_dec.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sprite/sample/load_dec_rle.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[#3;100;100;10A9;255;9;255;9;255;9;255;9;20;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;50;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;20;15;80;9;50;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;80;15;20;9;255;9;255;9;255;9;255;9;20;
1 change: 1 addition & 0 deletions sprite/sample/load_hex.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sprite/sample/load_hex_rle.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[#3;100;100;16A9;FF;9;FF;9;FF;9;FF;9;14;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;32;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;14;F;50;9;32;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;50;F;14;9;FF;9;FF;9;FF;9;FF;9;14;
1 change: 1 addition & 0 deletions sprite/sample/load_hex_rle_dinos.txt

Large diffs are not rendered by default.

80 changes: 79 additions & 1 deletion src/gfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ typedef struct {
struct
{
unsigned char loading;
unsigned char asciiMode;
unsigned char asciiByte;
unsigned char asciiBase;
unsigned short asciiRepeat;
unsigned char rleCompressed;
unsigned char index;
unsigned char chars;
Expand Down Expand Up @@ -1138,7 +1142,42 @@ void gfx_term_load_bitmap(char pixel)
{
char* dest = 0;
unsigned char nbPixels, i;


if (ctx.bitmap.asciiMode)
{
// Convert data to binary
if (pixel == ';')
{
// process binary data
pixel = ctx.bitmap.asciiByte;
ctx.bitmap.asciiByte = 0;
}
else if ((ctx.bitmap.asciiBase == 10) && (pixel >= '0') && (pixel <= '9'))
{
ctx.bitmap.asciiByte = ctx.bitmap.asciiByte * 10 + pixel - '0';
return;
}
else if (ctx.bitmap.asciiBase == 16)
{
if ((pixel >= '0') && (pixel <= '9')) ctx.bitmap.asciiByte = ctx.bitmap.asciiByte * 16 + pixel - '0';
else if ((pixel >= 'A') && (pixel <= 'F')) ctx.bitmap.asciiByte = ctx.bitmap.asciiByte * 16 + pixel - 'A' + 10;
else if ((pixel >= 'a') && (pixel <= 'f')) ctx.bitmap.asciiByte = ctx.bitmap.asciiByte * 16 + pixel - 'a' + 10;
else
{
// syntax error
ctx.bitmap.loading = 0;
}
return;
}
else
{
// syntax error
ctx.bitmap.loading = 0;
return;
}

}

dest = (char*)ctx.bitmap.pBitmap[ctx.bitmap.index]+8+ctx.bitmap.actPos;
if (ctx.bitmap.rleCompressed)
{
Expand All @@ -1150,6 +1189,7 @@ void gfx_term_load_bitmap(char pixel)
{
nbPixels = pixel;
pixel = *dest;

for (i=0;i<nbPixels;i++)
{
*dest++ = pixel;
Expand Down Expand Up @@ -1480,6 +1520,43 @@ int state_fun_final_letter( char ch, scn_state *state )
goto back_to_normal;
break;

case 'a':
case 'A':
// load a bitmap ASCII encoded
// expects bitmap index, x size, y size, encoding base (10 or 16)
// followed by x*y ASCII encoded color indexes for pixels (decimal or hex)
// A is RLE compressed
if (state->cmd_params_size == 4)
{
if ((state->cmd_params[0] < MAXBITMAPS) && (state->cmd_params[1]) && (state->cmd_params[2]) && ((state->cmd_params[3] == 10) || (state->cmd_params[3] == 16)))
{
// release old data
if (ctx.bitmap.pBitmap[state->cmd_params[0]]) nmalloc_free((void**)&ctx.bitmap.pBitmap[state->cmd_params[0]]);

// alloc mem
ctx.bitmap.pBitmap[state->cmd_params[0]] = nmalloc_malloc(8+state->cmd_params[1]*state->cmd_params[2]); // Header 8 bytes for x and y, then data
if (ctx.bitmap.pBitmap[state->cmd_params[0]])
{
ctx.bitmap.loading = 1;
uint32_t* px = (uint32_t*)ctx.bitmap.pBitmap[state->cmd_params[0]];
uint32_t* py = px+1;
*px = state->cmd_params[1];
*py = state->cmd_params[2];
ctx.bitmap.pixels = state->cmd_params[1]*state->cmd_params[2];
ctx.bitmap.actPos = 0;
ctx.bitmap.index = state->cmd_params[0];
if (ch == 'A') ctx.bitmap.rleCompressed = 1; else ctx.bitmap.rleCompressed = 0;
ctx.bitmap.chars = 0;
ctx.bitmap.asciiByte = 0;
ctx.bitmap.asciiMode = 1;
ctx.bitmap.asciiBase = state->cmd_params[3];
}
}
}
retval = 0;
goto back_to_normal;
break;

case 'b':
case 'B':
// load a bitmap
Expand Down Expand Up @@ -1507,6 +1584,7 @@ int state_fun_final_letter( char ch, scn_state *state )
ctx.bitmap.index = state->cmd_params[0];
if (ch == 'B') ctx.bitmap.rleCompressed = 1; else ctx.bitmap.rleCompressed = 0;
ctx.bitmap.chars = 0;
ctx.bitmap.asciiMode = 0;
}
}
}
Expand Down

0 comments on commit 151e150

Please sign in to comment.