[Moto G 2015 Themes and Apps] makers_mark:
SOURCE:

MotoLogoCodec.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#define OUT_FILE "logo.bin"
#define MOTOLOGO_BARE_HEADER 13
#define MOTOLOGO_IMG_BLK_SIZE 32
#define BIT_SET 0x8000
#define IS_BIT_SET(x) (x & BIT_SET)
#define COLORS 3
#define SWAP(x) (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8))

typedef struct {
unsigned short count;
unsigned char color[COLORS];
} motoSet;

typedef struct {
char header[8];
unsigned short width;
unsigned short height;
} motoHead;

typedef struct {
char name[24];
unsigned long offset;
unsigned long size;
unsigned short totalBlocks;
unsigned long totalSize;
motoHead imageHead;
} imageHead;

typedef struct {
unsigned char r;
unsigned char g;
unsigned char b;
} pixel;

void MotoRunEncode(void);
int FindMotoLogo(void);
int ParseHeader(unsigned long, int);
void CutMRImageOut(int, char*, unsigned long);
unsigned long int BlockIt(unsigned long int);
void MotoDecode(int, char*, unsigned short, unsigned short, unsigned long, int);

unsigned short pad = 1;
unsigned short addDetails = 0;
unsigned short cutMR = 0;
unsigned short decode = 0, encode = 0;
unsigned short blockSize = 512;
unsigned short pos = 0;
unsigned short filesFound = 0;
unsigned short logoOutput = 1;
unsigned short width = 0, height = 0;
char *inputFile, *base, *path;
char *motoLogoHeader;
unsigned long start, end;
FILE *inStream;
FILE *outStream;
char command[512];
char padByte = 0xff;

void MotoRunEncode(void)
{
unsigned int i,ind, m;
pixel line[width];
unsigned short count;
motoHead motoRunHeader;

if ((inStream = fopen(inputFile, "rb")) == NULL){
fclose(inStream);
fprintf(stderr, "\n%s\nCould not be opened.", inputFile);
return;
}
if ((outStream = fopen(base, "wb")) == NULL){
fclose(inStream);
fclose(outStream);
fprintf(stderr, "\n%s\nCould not be opened.", base);
return;
}
motoRunHeader.header[0] = 0x4D;
motoRunHeader.header[1] = 0x6F;
motoRunHeader.header[2] = 0x74;
motoRunHeader.header[3] = 0x6F;
motoRunHeader.header[4] = 0x52;
motoRunHeader.header[5] = 0x75;
motoRunHeader.header[6] = 0x6E;
motoRunHeader.header[7] = 0x00;
motoRunHeader.width = SWAP(width);
motoRunHeader.height = SWAP(height);

fwrite(&motoRunHeader, 1, sizeof(motoRunHeader), outStream);
for (i = 1; i <= height; i++){

fread(line, COLORS, width, inStream);

for (ind = 0, count = 0 ; ind <= width - 1; ){

if ((memcmp(&line[ind], &line[ind+1], 3) == 0)){
ind++;
count = 1;
while((ind <= width - 2) && ((memcmp(&line[ind], &line[ind+1], 3))== 0)){
count++;
ind++;
}
if (count == 1){
count++;
ind++;
goto LOOP;

} else {
count++;
count |= BIT_SET;
count = SWAP(count);
fwrite(&count, 1, 2, outStream);
fwrite(&line[ind], 1, 3, outStream);
}
ind++;
} else {
count = 1;
ind++;
LOOP:
while (((ind >= width -2)&&(ind <= width -1)) || ((ind <= width - 2) && (memcmp(&line[ind], &line[ind+1], 3) != 0)) || ((ind <= width - 3) && (memcmp(&line[ind+1], &line[ind+2], 3) != 0))){
count++;
ind++;
}

count = SWAP(count);
fwrite(&count, 1, 2, outStream);
fwrite(&line[ind - SWAP(count)], SWAP(count), COLORS, outStream);
continue;
}
}
}

return;

}

int FindMotoLogo(void)
{
char header[] = {0x4D,0x6F,0x74,0x6F,0x4C,0x6F,0x67,0x6F,0x00};

unsigned long int firstOffset;
int readByte;
char string[9];

if ((inStream = fopen(inputFile, "rb")) == NULL){
fclose(inStream);
fprintf(stderr, "\n%s\nCould not be opened.", inputFile);
return;
}
int inNumber = fileno(inStream);

while ((readByte = fgetc(inStream)) != EOF){
if (readByte == header[pos]){
if (pos == 8){
start = (ftell(inStream) - 9);
fseek(inStream, start + 9, SEEK_SET);
read(inNumber, &end, 4);

fseek(inStream, start + 9 + 4 + 24, SEEK_SET );
read(inNumber, &firstOffset, 4);
fseek(inStream, start + firstOffset, SEEK_SET );
read(inNumber, &string, 9);
if (strcmp(string, "MotoRun") == 0){
fseek(inStream, start + 13, SEEK_SET );
return (ParseHeader(end, inNumber));

} else {
pos = 0;
fseek(inStream, start + 9, SEEK_SET );
continue;
}

} else {
pos++;
continue;
}
}
pos = 0;
}

close(inNumber);
fprintf(stderr,"\n%d MotoLogo (logo.bin) files found.", filesFound);
return;

}

int ParseHeader(unsigned long end, int inNumber)
{
unsigned int imageCounter = (end - MOTOLOGO_BARE_HEADER) / MOTOLOGO_IMG_BLK_SIZE;
imageHead motomoto[imageCounter];
int i;
unsigned long logoSize, pos;

for(i=0; i < imageCounter; i++){
read(inNumber, &motomoto[i], 32);
motomoto[i].totalSize = BlockIt(motomoto[i].size);
motomoto[i].totalBlocks = (motomoto[i].totalSize /blockSize);
fprintf(stdout,"\nName: %s\nOffset in Logo.bin: %ld\nImage Data Size: %ld",motomoto[i].name, motomoto[i].offset, motomoto[i].size);
fprintf(stdout,"\nTotal Size: %ld",motomoto[i].totalSize);
fprintf(stdout,"\nTotal Blocks: %d",motomoto[i].totalBlocks);
pos = ftell(inStream);
fseek(inStream, start + motomoto[i].offset, SEEK_SET);
if (cutMR){
CutMRImageOut(inNumber, motomoto[i].name, motomoto[i].size);
fseek(inStream, start + motomoto[i].offset, SEEK_SET); //moved this line inside the parentheses
}

read(inNumber, &motomoto[i].imageHead, 12);
motomoto[i].imageHead.width = SWAP(motomoto[i].imageHead.width);
motomoto[i].imageHead.height = SWAP(motomoto[i].imageHead.height);
fprintf(stdout,"\nWidth x Height: %dx%d",motomoto[i].imageHead.width,motomoto[i].imageHead.height);
fprintf(stdout,"\nHeader: %s\n\n",motomoto[i].imageHead.header);
if (decode){
MotoDecode(inNumber, motomoto[i].name, motomoto[i].imageHead.width, motomoto[i].imageHead.height, motomoto[i].size , i+1);
}
fseek(inStream, pos, SEEK_SET);

}

logoSize = motomoto[imageCounter-1].offset + motomoto[imageCounter-1].totalSize;
fprintf(stdout,"\nLogo.bin contains %ld image files and is %ld bytes in size", i, logoSize);
if (!(logoOutput)){
return 0;
}
sprintf(command,"%s\\%s", path , OUT_FILE );
if ((outStream = fopen(command, "wb")) == NULL){
fclose(outStream);
fprintf(stderr, "\n%s\\%s could not be opened.", path, OUT_FILE);
return 1;
}
int outNumber = fileno(outStream);
fseek(inStream, start, SEEK_SET );
char* logobin = malloc(logoSize);
read(inNumber, logobin, logoSize);

write(outNumber, logobin, logoSize);
close(outNumber);
free(logobin);
return 0;
}

void CutMRImageOut(int inNumber, char* name, unsigned long size){
char newName[26];
FILE *txt;

sprintf(command,"%s\\%s.mr", path , name );
if ((txt = fopen("build.ID", "a")) == NULL){
fclose(txt);
fprintf(stderr, "\nBuild.ID could not be opened.\n");
return;
}
if ((outStream = fopen(command, "wb")) == NULL){
fclose(outStream);
fclose(txt);
fprintf(stderr, "\n%s\\%s.mr could not be opened", path, name);
return;
}
sprintf(command,"%s\n", command );

sprintf(newName, "%s?", name);
fwrite(newName, strlen(newName), 1, txt);
fwrite(command, strlen(command), 1, txt);
fclose(txt);

int outNumber = fileno(outStream);
char *dataStream = malloc(size);
read(inNumber, dataStream, size);

write(outNumber, dataStream, size);
if (pad){
if ((size % blockSize) != 0){
unsigned int max = blockSize - (size % blockSize ), i;
for (i = 0; i < max; i++){
write(outNumber, &padByte , 1);
}
fprintf(stdout,"\n%d bytes padded to %s", max, name);
}
}
close(outNumber);
free(dataStream);
return;
}

unsigned long int BlockIt(unsigned long int isize){
if ((isize % blockSize) == 0){
return isize;
}else{
return isize + (blockSize - (isize %blockSize));
}
}

void MotoDecode(int inNumber, char* name, unsigned short width, unsigned short height, unsigned long size, int index)
{
unsigned short repeats, count;
unsigned char color[3];
unsigned long counter = 0;
motoSet data;
if (addDetails){
sprintf(command, "%s\\%03d_%dx%d_%s.bgr24", path , index, width, height, name);
} else {
sprintf(command, "%s\\%s.bgr24", path, name);
}

if ((outStream = fopen(command, "wb")) == NULL){
fclose(outStream);
fprintf(stderr, "\n%s\nCould not be opened.", command);
return;
}

int outNumber = fileno(outStream);

while((read(inNumber, &data, 5) != EOF) && (counter < size)){
counter += 5;
if ((counter >= size ) || (data.count == 0xffff)){
close(outNumber);
return;
}
data.count = SWAP(data.count);
if (IS_BIT_SET(data.count)){

data.count &= ~BIT_SET;
for (repeats = 0;repeats < data.count; repeats++){
write(outNumber, &data.color, COLORS);
}
} else {
write(outNumber, &data.color, COLORS);

for (repeats = 0; repeats < data.count -1; repeats++){
counter += COLORS;
if ((read(inNumber, color, COLORS) == EOF) || counter >= size){
write(outNumber, &color, COLORS);
close(outNumber);
return;
}
write(outNumber, &color, COLORS);
}
}
}
close(outNumber);
return;

}

int main(int argc, char **argv)
{

int c;

while ((c = getopt (argc, argv, "i:o:p:b:w:h:cdezna")) != -1){
switch(c)
{
case 'a':
addDetails = 1;
break;	//add index number and resolution to decoded filenames
case 'i':
inputFile = optarg;
break;
case 'o':
base = optarg;
break;
case 'p':
path = optarg;
break;
case 'b':
blockSize = atoi(optarg);
break;
case 'c':
cutMR = 1;
break;
case 'd':
decode = 1;
break;
case 'e':
encode = 1;
break;
case 'z':
pad = 0;
break;
case 'n':
logoOutput = 0;
break;
case 'w':
width = atoi(optarg);
break;
case 'h':
height = atoi(optarg);
break;
}
}
if (encode == 1){
MotoRunEncode();
return;
}
return(FindMotoLogo());

}

MotoLogoValidator.c

/*

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#define MOTOLOGO_BARE_HEADER 13
#define MOTOLOGO_IMG_BLK_SIZE 32
#define BIT_SET 0x8000
#define IS_BIT_SET(x) (x & BIT_SET)
#define COLORS 3
#define SWAP(x) (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8))

typedef struct {
unsigned short count;
unsigned char color[COLORS];
} motoSet;

typedef struct {
char header[8];
unsigned short width;
unsigned short height;
} motoHead;

typedef struct {
char name[24];
unsigned long offset;
unsigned long size;
unsigned short totalBlocks;
unsigned long totalSize;
motoHead imageHead;
} imageHead;

typedef struct {
unsigned char r;
unsigned char g;
unsigned char b;
} pixel;

int FindMotoLogo();
int ValidateMotoLogoHeader();
unsigned long int BlockIt(unsigned long int);
int VerifyImages(char*, unsigned short, unsigned short, unsigned long);

unsigned short pos, inNumber, blockSize = 512;
char *inputFile;
unsigned long start, end;
FILE *inStream;
FILE *txt;

char command[512];
char padByte = 0xff;

int FindMotoLogo()
{
char header[] = {0x4D,0x6F,0x74,0x6F,0x4C,0x6F,0x67,0x6F,0x00};
unsigned long int firstOffset;
int readByte;
char string[9];

for (pos = 0 ; pos <= 8 ; pos++ ){

if ((readByte = fgetc(inStream)) == header[pos]){

fprintf(stdout,"\nHeader:\n%d %02x",pos, header[pos]);

if (pos == 8){
fprintf(stdout, "\nHeader Match");
start = 0;
fseek(inStream, start + 9, SEEK_SET);
read(inNumber, &end, 4);

fseek(inStream, start + 9 + 4 + 24, SEEK_SET );
read(inNumber, &firstOffset, 4);
fseek(inStream, start + firstOffset, SEEK_SET );
read(inNumber, &string, 9);
if (strcmp(string, "MotoRun") == 0){
fseek(inStream, start + 13, SEEK_SET );
fprintf(stdout,"\nEnd of MotoLogo Header is byte %d.\n", end);
return 0;
} else {
fprintf(stderr,"\nFirst offset in MotoLogo header doesn't point to an image header.");
return 1;
}

} else {
continue;

}
} else {
fprintf(stderr,"\nFile: %s\ndoes not start with a valid MotoLogo header.", inputFile);
return 1;
}
}

return 1;
}

int ValidateMotoLogoHeader()
{
unsigned int imageCounter = (end - MOTOLOGO_BARE_HEADER) / (MOTOLOGO_IMG_BLK_SIZE);
fprintf(stdout,"\n%d images referenced in header.\nChecking Images.\n", imageCounter);
imageHead motomoto[imageCounter];
int i;
char motoRunHeader[] = "MotoRun\0";

fseek(inStream, 13, SEEK_SET);
for(i=0; i < imageCounter; i++){
read(inNumber, &motomoto[i], 32); //add an if parameter switch for the last element not to include the padding
motomoto[i].totalSize = BlockIt(motomoto[i].size);
motomoto[i].totalBlocks = (motomoto[i].totalSize /blockSize);
fprintf(stdout,"\nName: \"%s\"\nOffset In File: %ld\nImage Data Size: %ld",motomoto[i].name, motomoto[i].offset, motomoto[i].size);
fprintf(stdout,"\nTotal Size With Padding: %ld",motomoto[i].totalSize);
fprintf(stdout,"\nTotal Blocks: %d",motomoto[i].totalBlocks);

if (i != 0){
if ((motomoto[i-1].offset + motomoto[i-1].totalSize) == (motomoto[i].offset)){
fprintf(stdout, "\nOffsets match!");
} else {
fprintf(stderr, "\nOffsets do not match between %s and %s.\nVALIDATION FAILURE!\n", motomoto[i-1].name, motomoto[i].name);
return 1;
}
} else {
if (motomoto[i].offset == BlockIt(end)){
fprintf(stdout, "\nOffsets Match!");
} else {
fprintf(stderr, "\n%d is offset and %d is the end of the MotoLogo Header\nVALIDATION FAILURE!\n", motomoto[i].offset, BlockIt(end));
return 1;
}
}
pos = ftell(inStream);
fseek(inStream, motomoto[i].offset, SEEK_SET);

read(inNumber, &motomoto[i].imageHead, 12);
motomoto[i].imageHead.width = SWAP(motomoto[i].imageHead.width);
motomoto[i].imageHead.height = SWAP(motomoto[i].imageHead.height);

fprintf(stdout,"\nWidth x Height: %dx%d",motomoto[i].imageHead.width,motomoto[i].imageHead.height);
fprintf(stdout,"\nExpected Pixels: %d", (motomoto[i].imageHead.width * motomoto[i].imageHead.height));
if(strcmp(motoRunHeader, motomoto[i].imageHead.header) != 0){
fprintf(stderr, "\nHeader Should be \"%s\", not \"%s\"\nVALIDATION FAILED!\n", motoRunHeader, motomoto[i].imageHead.header);
return 1;
}
fprintf(stdout,"\nHeader: \"%s\"",motomoto[i].imageHead.header);

if (!VerifyImages(motomoto[i].name, motomoto[i].imageHead.width, motomoto[i].imageHead.height, motomoto[i].size - 12)){
fseek(inStream, pos, SEEK_SET);
continue;
} else {
return 1;
}
}
if ((txt = fopen("MoID.ID", "w")) == NULL){
fclose(txt);
fprintf(stderr, "\nMoID.ID could not be opened.\n");
return 1;
}
for(i=0; i < imageCounter; i++){
fprintf(txt, "%s,%d,%d,%d,%d,", motomoto[i].name, motomoto[i].imageHead.width, motomoto[i].imageHead.height, motomoto[i].totalSize, motomoto[i].totalBlocks);
fprintf(txt, "%d,%d\n", motomoto[i].offset, motomoto[i].size);

}
fclose(txt);

return 0;
}

unsigned long int BlockIt(unsigned long int isize){
if ((isize % blockSize) == 0){
return isize;
}else{
return isize + (blockSize - (isize %blockSize));
}
}

int VerifyImages(char* name, unsigned short width, unsigned short height, unsigned long size)
{
unsigned short line = 0, pixelsonline = 0;
unsigned long pixelsDecoded = 0, totalPixels = 0, bytesRead = 0;
motoSet data;
unsigned long posi;

while(bytesRead < size){

if ((bytesRead += read(inNumber, &data, 5)) == EOF){
return 0;
}

data.count = SWAP(data.count);
if (IS_BIT_SET(data.count)){
data.count &= ~BIT_SET;
pixelsonline += data.count;
} else {
posi = ftell(inStream);
fseek(inStream, (posi + (COLORS * (data.count - 1))), SEEK_SET);
pixelsonline += data.count;
bytesRead = bytesRead + (COLORS * (data.count - 1));

}
if (pixelsonline == width){
line++;
pixelsDecoded += pixelsonline;
pixelsonline = 0;
}
if ((pixelsonline == width) && ((pixelsDecoded / line) == pixelsonline)){
line++;
pixelsonline = 0;

}

}
fprintf(stdout,"\nPixels Decoded: %d\nBytes Read: %d\nSize Minus Header: %d\nLines Properly Terminated: %d", pixelsDecoded, bytesRead, size , line);
if ((pixelsDecoded == width * height) && (bytesRead == size) && (height == line )){
fprintf(stdout,"\n\"%s\" Is Encoded Correctly\n", name);
return 0;
}
if (pixelsDecoded != (width * height)){
fprintf(stderr, "\nThe total pixels decoded, %d, doesn't equal the resolution: %dx%d=%d",pixelsDecoded, width, height, (width * height));
}
if (bytesRead != size){
fprintf(stderr, "\nThe total bytes read, %d, is not equal to the encoded size, %d.", bytesRead, size);
}
if (height != line ){
fprintf(stderr, "\nAt least one run in the encoding runs past the edge of the screen.\nThis will not work.");
}
fprintf(stderr, "\n%s is not encoded correctly\nVALIDATION FAILURE!\n", name);
return 1;

}

int main(int argc, char **argv)
{

int c;

while ((c = getopt (argc, argv, "i:b:")) != -1){
switch(c)
{

case 'i':
inputFile = optarg;
break;

case 'b':
blockSize = atoi(optarg);
break;

}
}
if ((inStream = fopen(inputFile, "rb")) == NULL){
fclose(inStream);
fprintf(stderr, "\n%s\nCould not be opened.\n", inputFile);
return 1;
}
inNumber = fileno(inStream);

if (!FindMotoLogo()){
if (!ValidateMotoLogoHeader()){
fclose(inStream);
return 0;
}
}

fclose(inStream);

return 1;

}

BuildMotoLogo.c v1.1

/* Version 1.1
Fixed error with encoded files that have a file size that is
evenly divisible by 512
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

typedef struct {
char name[24];
unsigned long offset;
unsigned long size;
unsigned long sizeWithPadding;
} imageHead;

unsigned long int ReadList(void);
unsigned int GetHeaderSize(void);
unsigned long int BlockIt(unsigned long int);

char *txtFileName;
FILE *inFile;
FILE *outFile;
char *outputFileName;
unsigned short images = 0;
unsigned short blockSize = 512;

unsigned long int ReadList(void){

char header[] = {0x4D,0x6F,0x74,0x6F,0x4C,0x6F,0x67,0x6F,0x00};
char line[512];
int readByte;
imageHead Item[images];
unsigned long int totalDataSize = 0;
int i = 0 , k = 0 , l = 0;
unsigned char padByte = 255;
unsigned long sizes[images];
char *s = "?";
char *tok;
unsigned long int hs;

if ((outFile = fopen (outputFileName, "wb")) == NULL){
perror("\nError opening output file:");
fclose(outFile);
}
hs = GetHeaderSize();
for ( i = 0 ; i < hs ; i++){
fputc(padByte, outFile);
}
i = 0;
hs = (images * 32) + 13;
while(fgets(line, sizeof line , stdin) != NULL){
tok = strtok(line, s);
sprintf(Item[i].name, "%s",tok);
tok = strtok(NULL, s);
for ( l = 24 ; l - strlen(Item[i].name) > 0 ; l-- ){
Item[i].name[l] = '\0';
}

for (k = 0; k < strlen(tok); k++){

if (( tok[k] == '\n') || (tok[k] == '\r' )){
tok[k] = '\0';
}

}

if ((inFile = fopen( tok , "rb")) == NULL){
perror("\nError opening mr file:");
fclose(inFile);
return 0;
}
while( ( readByte = fgetc(inFile) ) != EOF ){
fputc(readByte, outFile);
}

Item[i].size = ftell(inFile);
fprintf(stdout, "\n%d" , Item[i].size);
if ((Item[i].size % 512) != 0){

for ( k = 0 ; k < (blockSize - (Item[i].size % blockSize)) ; k++){
fputc(padByte, outFile);
}
}
Item[i].sizeWithPadding = BlockIt(Item[i].size);
totalDataSize += Item[i].sizeWithPadding;
if (i == 0){
Item[i].offset = BlockIt(hs);
} else {
Item[i].offset = ((Item[ i - 1 ].sizeWithPadding) + (Item[ i - 1 ].offset));

}
fprintf(stdout, "\n%ld", Item[i].offset);
i++;
fclose(inFile);
}

fseek(outFile, 0 , SEEK_SET);
fwrite(&header, sizeof header, 1 , outFile);
fwrite(&hs, 4, 1 ,outFile);
fprintf(stdout, "\n Size of Header is %d.", hs);

for (i = 0 ; i < images ; i++ ){
fwrite(&Item[i].name, 1 , 24 , outFile);
fwrite(&Item[i].offset, 4, 1 , outFile);
fwrite(&Item[i].size, 4, 1, outFile);
}

fclose(outFile);
fclose(inFile);
return totalDataSize;
}

unsigned int GetHeaderSize(void){

unsigned int ret = BlockIt(13 + ( 32 * images));
return ret;

}

unsigned long int BlockIt(unsigned long int isize){
if ((isize % blockSize) == 0){
return isize;
}else{
return isize + (blockSize - (isize %blockSize));
}
}

int main(int argc, char **argv){
int c;

while ((c = getopt (argc, argv, "o:n:")) != -1){
switch(c)
{

case 'o':
outputFileName = optarg;
break;
case 'n':
images = atoi(optarg);
break;
}
}
ReadList();

return;

}