Difference between revisions of "User:Remark/Icon2ppm.c"
Jump to navigation
Jump to search
m (Oops.) |
m (Icon2ppm.c moved to User:Remark/Icon2ppm.c) |
||
(2 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | + | <source lang="c"> | |
− | + | // DSi icon2ppm - #dsidev | |
− | + | // written by remark | |
+ | // thanks to loopy_, bLASTY | ||
+ | |||
+ | // Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org> | ||
+ | // Licensed under the terms of the GNU GPL, version 2 | ||
+ | // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | typedef unsigned long u32; | ||
+ | typedef unsigned short u16; | ||
+ | typedef unsigned char u8; | ||
+ | |||
+ | u16 be16(const u8 *p) | ||
+ | { | ||
+ | return (p[0] << 8) | p[1]; | ||
+ | } | ||
+ | u32 be32(const u8 *p) | ||
+ | { | ||
+ | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | ||
+ | } | ||
− | + | #define BNR_VER 0x0301 | |
− | + | #define FLAG_FLIPV 0x80 | |
− | + | #define FLAG_FLIPH 0x40 | |
+ | typedef struct { | ||
+ | u16 version; | ||
+ | u16 crcs[4]; | ||
+ | u8 padding[0x16]; | ||
+ | u8 bitmap[0x200]; | ||
+ | u16 palette[0x10]; | ||
+ | u8 title_jap[0x100]; | ||
+ | u8 title_eng[0x100]; | ||
+ | u8 title_fr[0x100]; | ||
+ | u8 title_ger[0x100]; | ||
+ | u8 title_ita[0x100]; | ||
+ | u8 title_spa[0x100]; | ||
+ | u8 title_unk[0x100]; | ||
+ | u8 title_unk2[0x100]; | ||
+ | u8 padding2[0x800]; | ||
+ | u8 bitmaps[8][0x200]; | ||
+ | u16 palettes[8][0x10]; | ||
+ | u16 sequence[0x40]; | ||
+ | } bannerstruct; | ||
+ | |||
+ | int flength(FILE *f) | ||
+ | { | ||
+ | int pos,end; | ||
+ | pos = ftell (f); | ||
+ | fseek (f, 0, SEEK_END); | ||
+ | end = ftell (f); | ||
+ | fseek (f, pos, SEEK_SET); | ||
+ | return end; | ||
+ | } | ||
+ | |||
+ | void do_bitmap(u8* bitmap, u16* palette, char* fname) | ||
+ | { | ||
+ | FILE *fp = fopen(fname, "wb"); | ||
+ | if (fp == NULL) | ||
+ | { | ||
+ | fprintf(stderr, "file cannot be opened: %s\n", fname); | ||
+ | exit(1); | ||
+ | } | ||
+ | fprintf(fp, "P6 %d %d 255\n", 32, 32); | ||
− | + | // fix 8x8 tiling | |
− | + | u8 tilebuf[0x204]; | |
− | + | int x,y,z; | |
− | + | for(x=0; x<4; x++) | |
− | + | { | |
+ | for(y=0; y<8; y++) | ||
+ | { | ||
+ | for(z=0; z<8; z++) | ||
+ | { | ||
+ | memcpy(tilebuf+(x*128)+(16*y)+(4*z), | ||
+ | bitmap+(x*128)+(32*z)+(4*y), 4); | ||
+ | } | ||
+ | } | ||
+ | } | ||
− | + | // convert to rgb888 | |
+ | int i,j; | ||
+ | u8 pixeldata[32*32][3]; | ||
+ | for(i=0; i<0x200; i++) | ||
{ | { | ||
− | + | u8 off = tilebuf[i]; | |
+ | int offs[2]; | ||
+ | offs[0] = off&0x0F; | ||
+ | offs[1] = (off&0xF0)>>4; | ||
+ | |||
+ | u16 colors[2]; | ||
+ | colors[0] = *(palette+offs[0]); | ||
+ | colors[1] = *(palette+offs[1]); | ||
+ | |||
+ | for(j=0; j<2; j++) | ||
+ | { | ||
+ | u8 r = (colors[j] ) & 0x1f; | ||
+ | u8 g = (colors[j] >> 5) & 0x1f; | ||
+ | u8 b = (colors[j] >> 10) & 0x1f; | ||
+ | pixeldata[i*2+j][0] = (r << 3); | ||
+ | pixeldata[i*2+j][1] = (g << 3); | ||
+ | pixeldata[i*2+j][2] = (b << 3); | ||
+ | } | ||
} | } | ||
− | + | ||
+ | if(fwrite(pixeldata, sizeof(pixeldata), 1, fp) != 1) | ||
{ | { | ||
− | + | fprintf(stderr, "writing output-file failed\n"); | |
+ | exit(1); | ||
} | } | ||
+ | |||
+ | fclose(fp); | ||
+ | } | ||
− | + | int main(int argc, char* argv[]) | |
− | + | { | |
− | + | if(argc != 2) | |
− | + | { | |
− | + | fprintf(stderr, "usage: %s <icon.bin>\n", argv[0]); | |
− | + | exit(0); | |
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | } | ||
− | + | FILE* fp = fopen(argv[1], "rb"); | |
+ | if(fp == NULL) | ||
{ | { | ||
− | + | fprintf(stderr, "input file not found\n"); | |
− | + | exit(1); | |
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | int f_len = flength(fp); | |
+ | char* f_buf = malloc(f_len); | ||
+ | if(f_buf == NULL) | ||
{ | { | ||
− | + | fprintf(stderr, "not enough memory\n"); | |
− | + | exit(1); | |
− | + | } | |
− | + | if(fread(f_buf, f_len, 1, fp) != 1) | |
− | + | { | |
− | + | fprintf(stderr, "file read failure\n"); | |
− | + | exit(1); | |
− | + | } | |
− | + | ||
− | + | char dirname[256]; | |
− | + | snprintf(dirname, sizeof(dirname), "%s.out", argv[1]); | |
− | + | mkdir(dirname, 0777); | |
− | + | chdir(dirname); | |
− | + | ||
− | + | bannerstruct* bnr = (bannerstruct*) f_buf; | |
− | + | // check magic | |
− | + | if(be16((u8*)&bnr->version) != BNR_VER) | |
− | + | { | |
− | + | fprintf(stderr, "invalid banner icon (magic mismatch)\n"); | |
− | + | exit(1); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | // extract default bitmap | |
+ | do_bitmap(bnr->bitmap, bnr->palette, "default.ppm"); | ||
+ | |||
+ | // loop through all sequences | ||
+ | u16* pseq = bnr->sequence; | ||
+ | u16 seq, i; | ||
+ | for(i=0; (seq = be16((u8*) pseq+i)) != 0; i++) | ||
{ | { | ||
− | + | // masking out | |
− | + | int bid = (seq&0x7); | |
− | + | int pid = (seq&0x38)>>3; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | int | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | char | + | // write to logfile |
− | snprintf( | + | char fname[256]; |
− | + | snprintf(fname, sizeof(fname), "seq#%d.txt", i); | |
− | |||
− | + | FILE* flog = fopen(fname, "w+"); | |
− | + | if(flog == NULL) | |
− | if( | ||
{ | { | ||
− | fprintf(stderr, " | + | fprintf(stderr, "log-file couldn't be created\n"); |
exit(1); | exit(1); | ||
} | } | ||
− | + | fprintf(flog, "duration : %d frames\n", (seq&0xFF00)>>8); | |
− | + | fprintf(flog, "bitmap : #%d\n", bid); | |
+ | fprintf(flog, "palette : #%d\n", pid); | ||
+ | fclose(flog); | ||
− | + | // todo: flipz! | |
− | + | if((seq & FLAG_FLIPV) == FLAG_FLIPV) | |
− | + | fprintf(stderr, "warning: vertical flip ignored on sequence #%d\n", i); | |
− | + | if((seq & FLAG_FLIPH) == FLAG_FLIPH) | |
− | + | fprintf(stderr, "warning: horizontal flip ignored on sequence #%d\n", i); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | // change extension to .ppm | |
− | + | char* dot_pos = strchr(fname, '.'); | |
+ | strcpy(dot_pos, ".ppm"); | ||
− | + | // extract bitmap to file | |
+ | do_bitmap(bnr->bitmaps[bid], bnr->palettes[pid], fname); | ||
} | } | ||
+ | |||
+ | fclose(fp); | ||
+ | free(f_buf); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </source> |
Latest revision as of 23:16, 10 August 2009
// DSi icon2ppm - #dsidev
// written by remark
// thanks to loopy_, bLASTY
// Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <stdio.h>
#include <unistd.h>
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
u16 be16(const u8 *p)
{
return (p[0] << 8) | p[1];
}
u32 be32(const u8 *p)
{
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
#define BNR_VER 0x0301
#define FLAG_FLIPV 0x80
#define FLAG_FLIPH 0x40
typedef struct {
u16 version;
u16 crcs[4];
u8 padding[0x16];
u8 bitmap[0x200];
u16 palette[0x10];
u8 title_jap[0x100];
u8 title_eng[0x100];
u8 title_fr[0x100];
u8 title_ger[0x100];
u8 title_ita[0x100];
u8 title_spa[0x100];
u8 title_unk[0x100];
u8 title_unk2[0x100];
u8 padding2[0x800];
u8 bitmaps[8][0x200];
u16 palettes[8][0x10];
u16 sequence[0x40];
} bannerstruct;
int flength(FILE *f)
{
int pos,end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
void do_bitmap(u8* bitmap, u16* palette, char* fname)
{
FILE *fp = fopen(fname, "wb");
if (fp == NULL)
{
fprintf(stderr, "file cannot be opened: %s\n", fname);
exit(1);
}
fprintf(fp, "P6 %d %d 255\n", 32, 32);
// fix 8x8 tiling
u8 tilebuf[0x204];
int x,y,z;
for(x=0; x<4; x++)
{
for(y=0; y<8; y++)
{
for(z=0; z<8; z++)
{
memcpy(tilebuf+(x*128)+(16*y)+(4*z),
bitmap+(x*128)+(32*z)+(4*y), 4);
}
}
}
// convert to rgb888
int i,j;
u8 pixeldata[32*32][3];
for(i=0; i<0x200; i++)
{
u8 off = tilebuf[i];
int offs[2];
offs[0] = off&0x0F;
offs[1] = (off&0xF0)>>4;
u16 colors[2];
colors[0] = *(palette+offs[0]);
colors[1] = *(palette+offs[1]);
for(j=0; j<2; j++)
{
u8 r = (colors[j] ) & 0x1f;
u8 g = (colors[j] >> 5) & 0x1f;
u8 b = (colors[j] >> 10) & 0x1f;
pixeldata[i*2+j][0] = (r << 3);
pixeldata[i*2+j][1] = (g << 3);
pixeldata[i*2+j][2] = (b << 3);
}
}
if(fwrite(pixeldata, sizeof(pixeldata), 1, fp) != 1)
{
fprintf(stderr, "writing output-file failed\n");
exit(1);
}
fclose(fp);
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: %s <icon.bin>\n", argv[0]);
exit(0);
}
FILE* fp = fopen(argv[1], "rb");
if(fp == NULL)
{
fprintf(stderr, "input file not found\n");
exit(1);
}
int f_len = flength(fp);
char* f_buf = malloc(f_len);
if(f_buf == NULL)
{
fprintf(stderr, "not enough memory\n");
exit(1);
}
if(fread(f_buf, f_len, 1, fp) != 1)
{
fprintf(stderr, "file read failure\n");
exit(1);
}
char dirname[256];
snprintf(dirname, sizeof(dirname), "%s.out", argv[1]);
mkdir(dirname, 0777);
chdir(dirname);
bannerstruct* bnr = (bannerstruct*) f_buf;
// check magic
if(be16((u8*)&bnr->version) != BNR_VER)
{
fprintf(stderr, "invalid banner icon (magic mismatch)\n");
exit(1);
}
// extract default bitmap
do_bitmap(bnr->bitmap, bnr->palette, "default.ppm");
// loop through all sequences
u16* pseq = bnr->sequence;
u16 seq, i;
for(i=0; (seq = be16((u8*) pseq+i)) != 0; i++)
{
// masking out
int bid = (seq&0x7);
int pid = (seq&0x38)>>3;
// write to logfile
char fname[256];
snprintf(fname, sizeof(fname), "seq#%d.txt", i);
FILE* flog = fopen(fname, "w+");
if(flog == NULL)
{
fprintf(stderr, "log-file couldn't be created\n");
exit(1);
}
fprintf(flog, "duration : %d frames\n", (seq&0xFF00)>>8);
fprintf(flog, "bitmap : #%d\n", bid);
fprintf(flog, "palette : #%d\n", pid);
fclose(flog);
// todo: flipz!
if((seq & FLAG_FLIPV) == FLAG_FLIPV)
fprintf(stderr, "warning: vertical flip ignored on sequence #%d\n", i);
if((seq & FLAG_FLIPH) == FLAG_FLIPH)
fprintf(stderr, "warning: horizontal flip ignored on sequence #%d\n", i);
// change extension to .ppm
char* dot_pos = strchr(fname, '.');
strcpy(dot_pos, ".ppm");
// extract bitmap to file
do_bitmap(bnr->bitmaps[bid], bnr->palettes[pid], fname);
}
fclose(fp);
free(f_buf);
return 0;
}