Skip to content

Commit 05a59ee

Browse files
committed
Initial commit
0 parents  commit 05a59ee

File tree

4 files changed

+243
-0
lines changed

4 files changed

+243
-0
lines changed

build.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
g++ -c fif2png.cpp -O2 -Wall `libpng-config --cflags`
3+
g++ fif2png.o -o fif2png `libpng-config --ldflags`
4+
rm fif2png.o

fif2png.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//C++ FastIF decoder
2+
//Copyright (C) 2020 Extrasklep
3+
4+
#include <iostream>
5+
#include <fstream>
6+
#include <png++/png.hpp>
7+
#include "fif_decoder.h"
8+
9+
int main(int argc, char** args) {
10+
if(argc<3) {
11+
std::cout << "Usage: " << args[0] << " [FIF input file] [PNG output file]\n";
12+
return 0;
13+
}
14+
FIF* fif = new FIF;
15+
std::ifstream ifile(args[1],std::ios::in|std::ios::binary|std::ios::ate);
16+
if(!ifile.is_open()) {
17+
perror(args[1]);
18+
exit(1);
19+
} else {
20+
std::streampos size = ifile.tellg();
21+
ifile.seekg(0);
22+
fif->data = new unsigned char[size];
23+
ifile.read((char*)fif->data,size);
24+
ifile.close();
25+
}
26+
27+
//Read FIF
28+
signed int res = 0;
29+
while((res = FIF_read(fif))) {
30+
if(res == 0) break;
31+
if(res < 0) {
32+
std::cout << "FIF error " << (int)res << ".\n";
33+
exit(2);
34+
}
35+
}
36+
37+
//Write output
38+
png::image<png::rgb_pixel> image(fif->width,fif->height);
39+
for(unsigned int y=0;y<fif->height;y++) {
40+
for(unsigned int x=0;x<fif->width;x++) {
41+
image[y][x] = png::rgb_pixel(fif->decoded_data[y*fif->width+x].r,fif->decoded_data[y*fif->width+x].g,fif->decoded_data[y*fif->width+x].b);
42+
}
43+
}
44+
image.write(args[2]);
45+
46+
FIF_free(fif);
47+
delete fif;
48+
return 0;
49+
}

fif_decoder.h

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//C++ FastIF decoder
2+
//Copyright (C) 2020 Extrasklep
3+
4+
#pragma once
5+
#include <iostream>
6+
#include <cstring>
7+
8+
struct FIFrgb {
9+
unsigned char r = 0;
10+
unsigned char g = 0;
11+
unsigned char b = 0;
12+
};
13+
14+
struct FIF {
15+
const unsigned char* data = nullptr;
16+
unsigned int width = 0;
17+
unsigned int height = 0;
18+
unsigned long datapos = 0;
19+
bool eof = 0;
20+
FIFrgb currentBG;
21+
FIFrgb currentFG;
22+
FIFrgb* decoded_data = nullptr;
23+
};
24+
25+
#include "utils.h"
26+
27+
const unsigned char fif_bitindex[8] = {0,2,4,1,3,5,6,7};
28+
29+
void FIF_renderchar(FIF* fiffile, unsigned int x, unsigned int y, unsigned char c) {
30+
const bool* bits = fif_getbits(c);
31+
unsigned int pos = (x*2)+(y*4)*fiffile->width;
32+
for(unsigned char i=0;i<8;i++) {
33+
unsigned int wpos = pos + ((fif_bitindex[i] / 2) * fiffile->width) + (fif_bitindex[i] % 2);
34+
if(wpos >= fiffile->width*fiffile->height) {std::cout << "Writer went out of bounds (X: " << x << " Y: " << y << ").\n"; return;};
35+
fiffile->decoded_data[wpos] = bits[i] ? fiffile->currentFG : fiffile->currentBG;
36+
}
37+
}
38+
39+
/*
40+
* Main read function
41+
*
42+
* Returns:
43+
* 0 - success, done decoding file
44+
* >0 - sleep operation, ms to sleepyes
45+
* <0 - error
46+
*/
47+
signed int FIF_read(FIF* fiffile) {
48+
if(fiffile->eof) return 0;
49+
if(fiffile->datapos == 0) {
50+
//Magic
51+
char* str = fif_readbytesAsString(fiffile,6);
52+
if(strcmp(str,"FastIF") != 0) {
53+
std::cout << "Invalid FIF file.\n";
54+
return -1;
55+
}
56+
//Width and height
57+
fiffile->width = fif_readbyte(fiffile) * 2;
58+
fiffile->height = fif_readbyte(fiffile) * 4;
59+
//Initialize memory
60+
fiffile->decoded_data = new FIFrgb[fiffile->width*fiffile->height];
61+
fiffile->currentBG.r = 0;
62+
fiffile->currentBG.g = 0;
63+
fiffile->currentBG.b = 0;
64+
fiffile->currentFG.r = 0;
65+
fiffile->currentFG.g = 0;
66+
fiffile->currentFG.b = 0;
67+
}
68+
69+
//Main reading loop
70+
while(!fiffile->eof) {
71+
unsigned char opbyte = 0;
72+
switch(opbyte = fif_readbyte(fiffile)) {
73+
//BG color
74+
case 0x01: {
75+
fiffile->currentBG.r = fif_readbyte(fiffile);
76+
fiffile->currentBG.g = fif_readbyte(fiffile);
77+
fiffile->currentBG.b = fif_readbyte(fiffile);
78+
break;
79+
}
80+
//FG color
81+
case 0x02: {
82+
fiffile->currentFG.r = fif_readbyte(fiffile);
83+
fiffile->currentFG.g = fif_readbyte(fiffile);
84+
fiffile->currentFG.b = fif_readbyte(fiffile);
85+
break;
86+
}
87+
//Horizontal line
88+
case 0x10: {
89+
unsigned int x = fif_readbyte(fiffile);
90+
unsigned int y = fif_readbyte(fiffile);
91+
unsigned int s = fif_readbyte(fiffile);
92+
for(unsigned int i=0;i<s;i++) {
93+
FIF_renderchar(fiffile,x+i,y,fif_readbyte(fiffile));
94+
}
95+
break;
96+
}
97+
//Fill
98+
case 0x11: {
99+
unsigned int x = fif_readbyte(fiffile);
100+
unsigned int y = fif_readbyte(fiffile);
101+
unsigned int fw = fif_readbyte(fiffile);
102+
unsigned int fh = fif_readbyte(fiffile);
103+
unsigned char c = fif_readbyte(fiffile);
104+
for(unsigned int ix=0;ix<fw;ix++) {
105+
for(unsigned int iy=0;iy<fh;iy++) {
106+
FIF_renderchar(fiffile,x+ix,y+iy,c);
107+
}
108+
}
109+
break;
110+
}
111+
//Sleep
112+
case 0x12: {
113+
return fif_readbyte(fiffile) * 10;
114+
break;
115+
}
116+
//Vertical line
117+
case 0x13: {
118+
unsigned int x = fif_readbyte(fiffile);
119+
unsigned int y = fif_readbyte(fiffile);
120+
unsigned int s = fif_readbyte(fiffile);
121+
for(unsigned int i=0;i<s;i++) {
122+
FIF_renderchar(fiffile,x,y+i,fif_readbyte(fiffile));
123+
}
124+
break;
125+
}
126+
//EOF
127+
case 0x20: {
128+
fiffile->eof = 1;
129+
return 0;
130+
}
131+
//Unsupported
132+
default: {
133+
std::cout << "Unsupported opcode " << std::hex << (unsigned int)opbyte << " at offset " << fiffile->datapos-1 << ".\n";
134+
return -1;
135+
}
136+
}
137+
}
138+
return 0;
139+
}
140+
141+
//Free FIF struct memory
142+
void FIF_free(FIF* fiffile) {
143+
delete[] fiffile->data;
144+
delete[] fiffile->decoded_data;
145+
}

utils.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#pragma once
2+
3+
unsigned char* fif_slice;
4+
char* fif_slicestring;
5+
6+
//Read bytes of data
7+
unsigned char* fif_readbytes(FIF* fiffile,unsigned long length) {
8+
delete[] fif_slice;
9+
fif_slice = new unsigned char[length];
10+
for(unsigned int i=0;i<length;i++) {
11+
fif_slice[i]=fiffile->data[fiffile->datapos++];
12+
}
13+
return fif_slice;
14+
}
15+
16+
//Get slice as a null terminated string
17+
char* fif_readbytesAsString(FIF* fiffile,unsigned long length) {
18+
unsigned char slicestr[length+1];
19+
unsigned char* bytes=fif_readbytes(fiffile,length);
20+
for(unsigned int i=0;i<length;i++) {
21+
slicestr[i]=bytes[i];
22+
if(slicestr[i]=='\0') {slicestr[i]=' ';}
23+
}
24+
slicestr[length]='\0';
25+
delete[] fif_slice;
26+
fif_slicestring = new char[length+1];
27+
for(unsigned int i=0;i<length+1;i++) {
28+
fif_slicestring[i]=slicestr[i];
29+
}
30+
return fif_slicestring;
31+
}
32+
33+
//Get slice and convert it to a number
34+
unsigned char fif_readbyte(FIF* fiffile) {
35+
return fiffile->data[fiffile->datapos++];
36+
}
37+
38+
bool fif_bits[8] = {0};
39+
const bool* fif_getbits(unsigned char b) {
40+
unsigned char mask=1;
41+
for(unsigned char i=0;i<8;i++) {
42+
fif_bits[i]=(b & (mask << i)) != 0;
43+
}
44+
return fif_bits;
45+
}

0 commit comments

Comments
 (0)