Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Mugen - Trying to load Sff with c++, strange error

This thread is locked; no one can reply to it. rss feed Print
Mugen - Trying to load Sff with c++, strange error
kingcools
Member #11,882
April 2010

Hello guys, Im trying to open/load a sff file from Mugen, a beat em up maker, but im getting a colour error.
Here is the definition of the sff file type:

/*--| SFF file structure
|--------------------------------------------------*\
Version 1.01
HEADER (512 bytes)
------
Bytes
00-11 "ElecbyteSpr\0" signature [12]
12-15 1 verhi, 1 verlo, 1 verlo2, 1 verlo3 [04]
16-19 Number of groups [04]
20-24 Number of images [04]
24-27 File offset where first subfile is located [04]
28-31 Size of subheader in bytes [04]
32 Palette type (1=SPRPALTYPE_SHARED or 0=SPRPALTYPE_INDIV) [01]
33-35 Blank; set to zero [03]
36-511 Blank; can be used for comments [476]

SUBFILEHEADER (32 bytes)
-------
Bytes
00-03 File offset where next subfile in the "linked list" is [04]
located. Null if last subfile

04-07 Subfile length (not including header) [04]
Length is 0 if it is a linked sprite
08-09 Image axis X coordinate [02]
10-11 Image axis Y coordinate [02]
12-13 Group number [02]
14-15 Image number (in the group) [02]
16-17 Index of previous copy of sprite (linked sprites only) [02]
This is the actual
18 True if palette is same as previous image [01]
19-31 Blank; can be used for comments [14]
32- PCX graphic data. If palette data is available, it is the last
768 bytes.

On the basis of this specification AND example code from this site(thx for this)
I came up with this

#SelectExpand
1#ifndef SFF_LOADER 2 #define SFF_LOADER 3 4 #include <allegro.h> 5 #include <iostream> 6 #include <fstream> 7 #include <string> 8 #include <sstream> 9 using namespace std; 10 11 12 RGB colours[256]; 13 typedef struct { 14 char magic[12]; 15 char version[4]; 16 int countGroups; 17 int countImages; 18 int offsetFirstSubFile; 19 int sizeOfSubfileHeader; 20 char palType; 21 char padding[3]; 22 char comment[476]; 23 } SFFHeader; 24 25 typedef struct { 26 int nextSubFile; 27 int sizeOfData; 28 short x; 29 short y; 30 short group; 31 short curIndex; 32 short prevIndex; 33 char reusePalette; 34 char comment[13]; 35 //char pcxData[1]; 36 37 } SFFSubFileHeader; 38 39 typedef struct 40 { 41 char identity; 42 char pcxver; 43 char compression; 44 char bpp; 45 short pos[4]; 46 short hor_dpi; 47 short ver_dpi; 48 char colormap[16][3]; 49 char reserved; 50 char colourplanes; 51 short byteperline; 52 short palinfo; 53 short width; 54 short height; 55 char fill[54]; 56}PCXhead; 57 58 59 RGB pal[256]; 60 61 62 typedef struct SFFEntryStruct { 63 short x, y, group, curIndex, prevIndex; 64 char isLinkedImage; 65 RGB* pal; 66 BITMAP* image; 67 char comment[13]; 68 69 struct SFFEntryStruct *next; 70 } SFFEntry; 71 72 #define SFF_LOAD_RET_TYPE SFFEntry* 73 74 SFF_LOAD_RET_TYPE sffLoad(const char* filename); 75 SFF_LOAD_RET_TYPE sffLoadFromMemory(void *memory); 76 #endif 77 78 79int main(){ 80 81int size; 82 allegro_init(); 83 install_keyboard(); 84 set_color_depth(16); 85 set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0); 86 87 88SFFHeader head; 89SFFSubFileHeader subhead; 90PCXhead pcx; 91 92char data[625];//size is just for this example I KNOW the first image has 25*25byte 93string write; 94BITMAP* bmp = create_bitmap_ex(8, 25, 25); 95 96 stringstream blabla; 97 98 fstream myfile("kfm.sff",ios::in | ios::binary); //Opening the file 99 myfile.read((char*)&head,sizeof(SFFHeader));//reading the Sffheader(works) 100 101 myfile.read((char*)&subhead,sizeof(SFFSubFileHeader)); //works 102 myfile.read((char*)&pcx,sizeof(PCXhead));//works as well 103 104 int index = 0; 105 106 107 unsigned char c; 108 while(index < 625)//here might be an error, the PCX file is RLE encoded, sp 109 { //Im decoding here 110 c = (char)myfile.get(); 111 if(c > 192) //if c > 192, the first to bits are set so this is a length 112 { // byte 113 114 c = c -(128+64);//decreasing by 192, to get the times i have to use the 115 // byte AFTER the length byte 116 117 char colour = (char)myfile.get(); 118 for(int i = 0; i < c;i++) 119 { 120 data[index] = colour; 121 index++; 122 } 123 124 } 125 else if(c == 192)//meaning the next byte has a colourindex > 191 126 { 127 data[index] = (char)myfile.get(); 128 index++; 129 130 131 } 132 else if(c < 192) 133 { 134 135 data[index] = c; 136 index++; 137 } 138 139 } 140 141 c = (char)myfile.get(); 142 if(c == 12)//if c = 12, a palette is used 143 { 144 145 for(int i = 0; i <256;i++) 146 { 147 //here im loading the palette 148 pal[i].r = (char)myfile.get(); 149 pal[i].g = (char)myfile.get(); 150 pal[i].b = (char)myfile.get(); 151 } 152} 153 int j = 0; 154//here I'm filling the BMP with the right pixel colours 155 for(int i = 0; i < 25;i++) 156 { 157 for(int k = 0; k < 25; k++) 158 { 159 bmp -> line[i][k] = makecol(pal[data[j]].r,pal[data[j]].g,pal[data[j]].b);//makecol(pal[data[j]].r,pal[data[j]].g,pal[data[j]].b); 160 j++; 161 } 162 } 163 draw_sprite(screen, bmp, 50, 50); 164 165 166 167 168 169 myfile.close(); 170 171 172 173 174 175 176 177 while(key[KEY_ESC]==0) 178 { 179 } 180 181 return 0; 182} 183END_OF_MAIN(); 184;

Sadly, im loading something wrong:/
Here a comparison:
How i should be(taken from another program)
http://up.picr.de/4209914.jpg
my version:
http://up.picr.de/4209907.jpg

As you can see, the face is somewhat there, but somehow it only loads black and white. As far as I can tell, the position within the PCX file is correct, because the other headers have correct values(e.g. correct width or colordepth).
I might load the palette wrong, though the check for "c = 12" should guarantee a palette is there.

Does anyone have a clue?
Thank you very much :)

kenmasters1976
Member #8,794
July 2007

Couldn't open your images. The palette in the SFF file may be incorrect. Try loading one of the ACT palettes, instead.

kingcools
Member #11,882
April 2010

try it now.
I just tried that, but with no effect(ok the background color changed from white to pink)

kenmasters1976
Member #8,794
July 2007

Oh yeah, there's something about Allegro 4's palettes; only the last 6 bits of the color components are significative, so you'll probably want to divide the MUGEN palette values by 4.

[EDIT:] Also, in case you're interested, there's a SFF loader by spellcaster that is near perfect. You can find it by doing a search in the forum.

kingcools
Member #11,882
April 2010

Thank you, I just tried this, but it only changes the background color from white to like something redish.

The thing that irritates me is, that my data array, which contains all the bytes of the image, seems to contain only like 2 different values(because if i use bmp -> line[i][k] = data[j]; i get the rough image(see above), which contains only black and white).

I attached my 2 files, hoping it will help someone to help me^^
Ignore the german writing within it and the txt file it creates its just for debugging(it writes down all the colour values).

edit:

Thanks, He was the one I took the basic structures from. Already looked at it, but understanding someone else's code is tough IMO. Thus I will try solving my own problems and if I can't work it out, I'll try his version :)
Kind of you to point this out :)

kenmasters1976
Member #8,794
July 2007

This line seems a bit strange:

bmp -> line[i][k] = makecol(pal[data[j]].r,pal[data[j]].g,pal[data[j]].b);

Since you're creating an 8 bit bitmap, you should just fill it with the corresponding color index, so I see no need for the makecol() call.

[EDIT:] Also, you're not calling set_palette(). That might be the problem.

kingcools
Member #11,882
April 2010

I thought the value within the pixelbytes in the PCX refer to a palette entry, thus if i got a colourbyte with the value 0, it isnt like colour 0 but the colour of palette[0]?!

Edit:

WOOOOOOOOHOOOOOOO GUYS ITS DONE HAHAHA IT WORKS.
I used set_palette() AND I used the hint to divide the paletteentries by four.
Looks perfect now.
Thank you soooo much :)

edit2:

one more question about set_palette:what if i have more than one Bitmap and want them to have different palettes?!
I mean the function set_palette doesnt refer to a special bitmap?!

kenmasters1976
Member #8,794
July 2007

kingcools said:

... thus if i got a colourbyte with the value 0, it isnt like colour 0 but the colour of palette[0]?!

Yes, that's the way 8 bit bitmaps work.

The missing set_palette() call seems to be the problem. This is what I get after doing a few small changes to your code:

601137

The changes are basically changing the RGB array for a PALETTE and calling set_palette() before drawing. Also, changing the line I mentioned earlier with:

bmp -> line[i][k] = data[j];

[EDIT:] I was replying as you edited your post.

Quote:

one more question about set_palette:what if i have more than one Bitmap and want them to have different palettes?! I mean the function set_palette doesnt refer to a special bitmap?!

OK, here's where things can get a bit tricky. As long as you use a color depth of 15 or more bits for your application, you can change the palette and draw a new bitmap with the new palette and they will both be drawn with their corresponding palette each. If you were using an 8 bit color depth, then things would be different.

Go to: