![]() |
|
This thread is locked; no one can reply to it.
![]() ![]() |
1
2
|
Making a grabber for Mugen's SFF file format |
zesensei
Member #4,410
March 2004
![]() |
Hi, |
zebellah
Member #4,275
January 2004
![]() |
why you want to write a new grabber. It's also possible that you can load your file without a plugin. |
zesensei
Member #4,410
March 2004
![]() |
I don't specially want to write a new grabber, nor plugins, nor specific function. I just want to know if somebody have ever do it and would like to share his code with me to save me lot of time writing one of this solution. Especially because I'm not really familiar with file structure loading. |
spellcaster
Member #1,493
September 2001
![]() |
I'd like to help, but I can't find a file spec for either sff or fnt. -- |
zesensei
Member #4,410
March 2004
![]() |
Thanks a lot spellcaster, Quote:
/*--| SFF file structure SUBFILEHEADER (32 bytes) 04-07 Subfile length (not including header) [04] /*--| SND file structure SUBFILEHEADER *--------------------------------------------------------------------------*/ /*--| FNT file structure
*/ Version 1.0
I can't myself explain everything and hope this will look simplest for you than for me. |
spellcaster
Member #1,493
September 2001
![]() |
it seems to be pretty straight forward. -- |
zesensei
Member #4,410
March 2004
![]() |
It will realy help me, thanks a lot. |
spellcaster
Member #1,493
September 2001
![]() |
Just a couple of questions: Do you have some files I could test my loader with? -- |
zesensei
Member #4,410
March 2004
![]() |
You could download Mugen on my website:
and same for sound. |
spellcaster
Member #1,493
September 2001
![]() |
Ok, here's the sff loader. 1/**
2 loader.h
3
4 Mugen SFF Loader (Header)
5 written by Lennart Steinke (http://www.steinke.net)
6 */
7#ifndef SFF_LOADER
8#define SFF_LOADER
9
10#include <allegro.h>
11
12typedef struct {
13 char magic[12];
14 char version[4];
15 int countGroups;
16 int countImages;
17 int offsetFirstSubFile;
18 int sizeOfSubfileHeader;
19 char palType;
20 char padding[3];
21 char comment[476];
22} SFFHeader;
23
24typedef struct {
25 int nextSubFile;
26 int sizeOfData;
27 short x;
28 short y;
29 short group;
30 short curIndex;
31 short prevIndex;
32 char reusePalette;
33 char comment[13];
34 char pcxData[1];
35} SFFSubFileHeader;
36
37typedef struct SFFEntryStruct {
38 short x, y, group, curIndex, prevIndex;
39 char isLinkedImage;
40 RGB* pal;
41 BITMAP* image;
42 char comment[13];
43
44 struct SFFEntryStruct *next;
45} SFFEntry;
46
47#define SFF_LOAD_RET_TYPE SFFEntry*
48
49SFF_LOAD_RET_TYPE sffLoad(const char* filename);
50SFF_LOAD_RET_TYPE sffLoadFromMemory(void *memory);
51#endif
Here's the implementation of the loader: 1/**
2 loader.c
3 Mugen SFF Loader (source)
4 written by Lennart Steinke (http://www.steinke.net)
5 */
6
7#include <stdio.h>
8#include "loader.h"
9
10int sff_memloadInt(unsigned char *data, int *ofs) {
11 int a,b;
12 a = data[*ofs];
13 (*ofs)++;
14 b = data[*ofs];
15 (*ofs)++;
16 return a + (b <<8);
17}
18
19RGB* sffLoadPaletteFromMemory(unsigned char *data) {
20 RGB* pal = (RGB*) malloc(sizeof(RGB) * 256);
21 int a, ofs;
22 ofs = 0;
23 for (a=0; a < 256; ++a) {
24 pal[a].r = data[ofs++] / 4;
25 pal[a].g = data[ofs++] / 4;
26 pal[a].b = data[ofs++] / 4;
27 }
28 return pal;
29}
30
31BITMAP* sffLoadPcxFromMemory(char* data) {
32 BITMAP *bmp = NULL;
33
34 /* skip the first 3 bytes */
35 int ofs = 3;
36 char planes = data[ofs++];
37 int width = -sff_memloadInt(data, &ofs);
38 int height = -sff_memloadInt(data, &ofs);
39 int bpp = 0;
40 int bytesPerLine = 0;
41 int x,y;
42 int value;
43 int count;
44
45 width += sff_memloadInt(data, &ofs) +1;
46 height+= sff_memloadInt(data, &ofs) +1;
47
48 /* skip 4 bytes (dpi) */
49 ofs += 4;
50
51 /* skip 16 color palette */
52 ofs += 48;
53
54 /* padding */
55 ofs++;
56
57
58 bpp = data[ofs++] *8;
59 if (bpp != 8) { /* || bpp != 24) {*/
60 return NULL;
61 }
62
63 bytesPerLine = sff_memloadInt(data, &ofs);
64
65 /* image data starts at ofs 128*/
66 ofs = 128;
67 bmp = create_bitmap_ex(bpp, width, height);
68 for (y=0; y < height; ++y) {
69 x = 0;
70 while (x < bytesPerLine) {
71 value = data[ofs++];
72
73 /* check if upper 2 bit are set */
74 if ((value & 0xc0) == 0xc0) {
75 /* bits are set, that means the
76 lower 6 bit contain the repeat count,
77 and the color is stored in the next byte
78 */
79 count = value & 0x3f;
80 value = data[ofs++];
81 } else {
82 /* value contains the color already */
83 count = 1;
84 }
85 if (bpp == 8) {
86 while (count > 0) {
87 if (x < bmp->w) {
88 bmp->line[y][x] = value;
89 ++x;
90 }
91 count--;
92 }
93 }
94 }
95 }
96
97
98 return bmp;
99}
100
101SFF_LOAD_RET_TYPE sffLoadFromMemory(void *memory) {
102 char* data = (char*) memory;
103 SFFHeader* header = (SFFHeader*) memory;
104 SFFSubFileHeader *sub = NULL;
105 int index = 0;
106 SFFEntry* first = NULL;
107 SFFEntry* cur = NULL;
108
109 SFFEntry** sprArray = NULL;
110
111 sprArray = calloc(header->countImages, sizeof(SFFEntry*));
112
113 sub = (SFFSubFileHeader*) &data[header->offsetFirstSubFile];
114 while (sub != NULL) {
115 if (first == NULL) {
116 first = (SFFEntry*) calloc(1, sizeof(SFFEntry));
117 cur = first;
118 } else {
119 cur->next = (SFFEntry*) calloc(1, sizeof(SFFEntry));
120 cur = cur->next;
121 }
122 cur->x = sub->x;
123 cur->y = sub->y;
124 cur->group = sub->group;
125 cur->curIndex = sub->curIndex;
126 cur->prevIndex = sub->prevIndex;
127
128 if (sub->sizeOfData == 0) {
129 // This is just a link to another image
130 cur->isLinkedImage = TRUE;
131 cur->image = sprArray[index]->image;
132 } else {
133 cur->isLinkedImage = FALSE;
134 cur->image = sffLoadPcxFromMemory(sub->pcxData);
135 memcpy(cur->comment, sub->comment, 13);
136 if (!sub->reusePalette) {
137 /* Tha palette is stored in the last 768 bytes
138 of the pcx data
139 */
140 cur->pal = sffLoadPaletteFromMemory((unsigned char*) &(sub->pcxData[sub->sizeOfData - 768]) );
141
142 }
143 }
144 sprArray[index] = cur;
145
146 /*
147 According to the docs, the last subfile is indicated by a 0.
148 During tests it became obvious that this is not the case.
149 Thus I'm checking both for 0 and check if the index is
150 smaller than the number of sprites in the file.
151 */
152 ++index;
153 if (sub->nextSubFile != 0 && index < header->countImages) {
154 sub = (SFFSubFileHeader*) &data[sub->nextSubFile];
155 } else {
156 sub = NULL;
157 }
158 }
159
160 /* NOTE: You might want to return the sprArray instead;
161 if so, don't free it here :)
162 */
163 free(sprArray);
164
165 return first;
166}
167
168SFF_LOAD_RET_TYPE sffLoad(const char* filename) {
169 long size = file_size(filename);
170 long toGo = size;
171 long start = 0;
172 long count = 0;
173 FILE *f = NULL;
174 char *data = NULL;
175 SFF_LOAD_RET_TYPE ret = NULL;
176
177 if (size > 0) {
178 f = fopen(filename, "rb");
179 data = malloc(size);
180 while (toGo > 0 && !feof(f)) {
181 count = fread(&(data[start]),1,toGo, f);
182 if (count == 0) {
183 exit(0);
184 }
185
186 toGo -= count;
187 start += count;
188 }
189 fclose(f);
190 ret = sffLoadFromMemory(data);
191 free(data);
192 }
193 return ret;
194}
And here a small demo: 1/**
2 testloader.c
3
4 Mugen SFF Loader (test)
5 written by Lennart Steinke (http://www.steinke.net)
6 */
7
8#include <allegro.h>
9#include "loader.h"
10
11int setGfxMode(int w, int h) {
12 int bpp[] = {16, 15, 32, 24, 8, 0 };
13 int a;
14 for (a=0; bpp[a] > 0; ++a) {
15 set_color_depth(bpp[a]);
16 if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, 0, 0) >= 0) {
17 return 1;
18 }
19 }
20 return 0;
21}
22
23
24
25int main(int argc, char** argv) {
26
27 SFFEntry *first, *cur;
28 int lastKey = 0;
29 allegro_init();
30
31 first = sffLoad(argc > 1 ? argv[1] : "intro.sff");
32
33 if(!setGfxMode(640, 480)) {
34 allegro_message("oups!");
35 exit(0);
36 }
37 install_keyboard();
38 cur = first;
39
40 if (cur->pal) {
41 set_palette(cur->pal);
42 }
43
44 while (!key[KEY_ESC]) {
45 blit(cur->image, screen, 0, 0, cur->x, cur->y, cur->image->w, cur->image->h);
46
47 if (key[KEY_SPACE]) {
48 if (lastKey != KEY_SPACE) {
49 lastKey = KEY_SPACE;
50
51 if (cur->next) {
52 cur = cur->next;
53 } else {
54 clear(screen);
55 cur = first;
56 }
57 if (cur->pal) {
58 set_palette(cur->pal);
59 }
60 }
61 } else {
62 lastKey = 0;
63 }
64 }
65
66
67 return 0;
68}
69END_OF_MAIN()
Please note that the file specs above seem to be incorrect. -- |
zesensei
Member #4,410
March 2004
![]() |
Thanks a lot for the code, it works well. |
spellcaster
Member #1,493
September 2001
![]() |
Sure, just use it - that's why I wrote it Regarding the array: It's already there, I'm using it internally ofr index sprites - so if you want it, you could just change the return type to the array. That way you'd have both array (since it was returned) and the linked list (since the array members are still linked). I'm working on the other formats. Just a question to the FNT format - the txt file is pretty simple, but for some chars the it looks weird... mainly for the [ and ] I guess. Not sure why. Is there any documentation for the TXT part of the FNT? (oh... and please answer to this post, so I can add the new loaders in my next reply -- |
zesensei
Member #4,410
March 2004
![]() |
Thanks a lot, ==================== The fonts generated by fntmaker work for 2000.06.27 and newer versions pcx file - Supply a pcx file which contains all the characters in your font Fonts with more than one color use "color banks" in their palette to store I hope it could help you. |
spellcaster
Member #1,493
September 2001
![]() |
Thanks for that info... makes sense now Regarding the multiple color banks... allegro can't handle that. You could either "clone" the fonts to get different versions (in different color sets) or create totally new font rendering functions. Cloning would be faster, more easy to implement but does of course waste some memory. What do you prefer? -- |
Kitty Cat
Member #2,815
October 2002
![]() |
I know you weren't directing this at me, but here's an idea. What if you load all the font data as true-color bitmap (according to their color banks), then do an optimized palette generation on it and make it an 8-bit bitmap to cut up for the font? Granted it won't look the same, but if you're gonna put it in FONT, you won't have much choice. -- |
spellcaster
Member #1,493
September 2001
![]() |
The font is already an 8bit bmp. It has it's own palette (256 colors). The point is that you'd have to add an offset to each pixel to support the color bank feature. -- |
Kitty Cat
Member #2,815
October 2002
![]() |
Hmm.. I'm not sure I understand the color banks portion then. What does it do? Whats its purpose? -- |
spellcaster
Member #1,493
September 2001
![]() |
Assume you have a font with a gradient red->yellow using 8 colors. I guess that mugens font drawing allows you to specify the color bank... so you could draw a text with font A, color bank 0 (red->yellow text) or using color bank 1 (blue->white text). Allegro's glyph drawing functions don't work that way. So, I could either generate several fonts (not much efford, not really memory wasting) or create functions mimicing the color bank switching. I think, I'll go for the creation of multiple fonts -- |
zesensei
Member #4,410
March 2004
![]() |
I think the creation of clone fonts is a good idea, as it will become possible to have palettes that are not specify with the original font picture's pal. |
Evert
Member #794
November 2000
![]() |
Quote: Mugen use fixed fonts and proportional fonts. I don't understand really the differences In a fixed width font all characters are the same width (for instance, W and I). In a proportional font, W is wider than I. spellcaster: if you really wanted to, you could probably hack the FONT vtable so that it can draw the colourbanked fonts. That's probably going to be a lot of work for little obvious gain over what you're proposing. |
spellcaster
Member #1,493
September 2001
![]() |
Don't think that this is needed. Mugen fonts are pretty small - I doubt it'll be a big overhead if one would simply clone the fonts. I'll add a FONT* fntGetColorBankFont( FntFont* fnt, int bank);
to my code. Or something similar. If somebody can come up with a good name for that function, I'd be grateful Expect the font functions today (sorry... I was pretty busy yesterday). Regarding the proportional fonts: What evert said... in theory, at least. It seems like a lot of mugen fonts are labeled as "proportional" but are in fact fixed size... but that's not a big problem, IMO. I might need to bug Bruce about the wave formats, though -- |
zesensei
Member #4,410
March 2004
![]() |
Thanks again, |
spellcaster
Member #1,493
September 2001
![]() |
Here's the loader. -- |
zesensei
Member #4,410
March 2004
![]() |
Thanks again, and again, For the bugs, here are some fonts that didn't work with the testloader prog. And if I pass the same name as the exemple font you give in your zip file (name1.fnt) as an argument color banks seems to disappear. Pretty weird... I'll look later the how of this... It works with some fnt, a great beginning. |
spellcaster
Member #1,493
September 2001
![]() |
Get a new gcc - it should work with the later 3.0 versions... but to be honest, it was an mistake... Since it worked, I was assuming it would be ok. Quote: Same problem in loader.c where I got to declare int count, and char * txt
Sorry. But, as I said, it'll work in any c99 compiler (say the later gccs). But I changed that - it wasn't intentional in the first place. Quote: And if I pass the same name as the exemple font you give in your zip file (name1.fnt) as an argument color banks seems to disappear. Pretty weird...
Check the testloader code. There's a bug in name1.fnt. If you split it (I think I have the split.c code in that zip as well) and look into the txt.txt file, you'll see that it has colors=1 in it. And that's wrong. The numbers of colors should be 16 for that font. EDIT:
-- |
|
1
2
|