Warcraft II Forum

Warcraft II => Mods & Development => Topic started by: iL on January 23, 2019, 03:00:53 PM

Title: War2 fonts (.fnt)
Post by: iL on January 23, 2019, 03:00:53 PM
Anybody knows any software to work with war2 .fnt-files?

I know the .fnt-file format, but how to work with it if i'm a user, not a programmer? What if i want to add a new language into war2?
I can't trust there's no software for that purposes, but i googled any .fnt-related software for war2/starcraft and find nothing except the description of font/letter headers.

Looks like i have to write my own program, but i'm lazy for that.
Any ideas?
Title: Re: War2 fonts (.fnt)
Post by: Szwagier on January 24, 2019, 03:03:36 AM
Hex editor work with it, you need Just translate everything
Title: Re: War2 fonts (.fnt)
Post by: iL on January 24, 2019, 03:42:12 AM
im still not sure if this is the fnt war2 is using
Yes, as i understand that uses a well-known old dos .fnt-format that is not compatible with war2 (just the same file extension as it's also a font).

At least, war2 fonts looks completely different than any other .fnt-files.

So, still looking for any war2-font-working software, let me know if you know something...
Title: Re: War2 fonts (.fnt)
Post by: iL on January 24, 2019, 06:44:00 PM
Well, i'll just publish my source code here, i used it to fix russian fonts about 10 years ago.
That program can be started as:
prog.exe font.fnt
it shows all the letters raster in text mode (each point is a number).
Program is most likely useless, except the source code to read and parse the whole .fnt-file
You can make something useful based on it.
Here's it:
Code: [Select]
// fontwar2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<stdio.h>
#include<windows.h>

#define MAX_LEETER_NUM 256
void bmp2fnt();
void cp2win(char *,int,int);
int getletter(char *,unsigned,char *);

typedef struct _FontHeader {
DWORD Name; // Always is "FONT"
BYTE LowIndex; // Index of first letter in file
BYTE HighIndex; // Index of the last letter in file
BYTE MaxWidth; // Maximum width
BYTE MaxHeight; // Maximum height
DWORD Unk1; // Unknown / Unused
} FontHeader;

typedef struct  _FontLetterRaw {
BYTE Width; // Width of the letter
BYTE Height; // Height of the letter
BYTE XOffset; // X Offset for the topleft corner of the letter.
BYTE YOffset; // Y Offset for the topleft corner of the letter.
} FontLetterRaw;

//DWORD letterofs[MAX_LEETER_NUM];
//FontHeader fontheader;
//FontLetterRaw letterheader;


int main(int argc, char* argv[])
{
/* FILE *in;
int i,pixelcounter,toskip;
BYTE c;
if(argc<2){printf("Usage: fontwar2 <filename.fnt> [-w]\n");return 0;}
in=fopen(argv[1],"rb");
if(!in){printf("Data error reading file %s\n",argv[1]);return 1;}
if(!fread(&fontheader,sizeof(FontHeader),1,in)){printf("Error in %s\n",argv[1]);return 2;}
printf("ok: %d, %d, %d, %d",fontheader.LowIndex,fontheader.HighIndex,fontheader.MaxWidth,fontheader.MaxHeight);
for(i=fontheader.LowIndex;i<fontheader.HighIndex;i++)
{
if(i>=MAX_LEETER_NUM){printf("Error! too many letters\n");return 3;}
fread(&letterofs[i],4,1,in);
// printf("%d ",letterofs[i]);
}

printf("\n");

for(i=fontheader.LowIndex;i<fontheader.HighIndex;i++)
{
if(letterofs[i]==0){printf("skip\n");continue;}
fseek(in,letterofs[i],SEEK_SET);
fread(&letterheader,sizeof(FontLetterRaw),1,in);
printf("%d %d^\n",letterheader.Width,letterheader.Height);
toskip=0;
printf("Begin %d\n",i+1);
for(pixelcounter=0;pixelcounter<letterheader.Width*letterheader.Height;pixelcounter++)
{
if(toskip-->0)
{
printf("-");
}
else{
if(pixelcounter)printf("%d",c&7);
c=fgetc(in);
toskip=c>>3;
}
if(pixelcounter%letterheader.Width==0)printf("\n");
}
printf("%d\n",c&7);
printf("End\n");
}
printf("!%d!\n",ftell(in));
fclose(in);

// bmp2fnt();
if(argc>2&&strcmp(argv[2],"-w")==0)cp2win(argv[1],fontheader.LowIndex,fontheader.HighIndex);*/
char buf[1024]; // FIXME! insecure
// if(argc<4){printf("Usage: fontwar2 <source1.fnt> <source2.fnt> <target.fnt>\n");return 0;}

int outfnt[32768]; // FIXME! insecure
int outfnt_seek=0,letsize;
char header[]={'F','O','N','T',0x20,0xff,0x0e,0x0e};
FontHeader outfh;
outfh.LowIndex=header[4];
outfh.HighIndex=header[5];
outfh.MaxWidth=header[6];
outfh.MaxHeight=header[7];

memset(outfnt,0,sizeof(outfnt));
memcpy(outfnt,header,sizeof(header));
outfnt_seek=(outfh.HighIndex+1-outfh.LowIndex)*4+sizeof(header);

if(argc==2)
{
for(int i=outfh.LowIndex;i<=outfh.HighIndex;i++)
getletter(argv[1],i,(char *)outfnt+outfnt_seek);
return 0;
}

for(int i=outfh.LowIndex;i<=outfh.HighIndex;i++)
{
switch(i)
{
case 128:letsize=getletter(argv[2],'З',(char *)outfnt+outfnt_seek);break;
case 129:letsize=getletter(argv[2],'ь',(char *)outfnt+outfnt_seek);break;
case 130:letsize=getletter(argv[2],'й',(char *)outfnt+outfnt_seek);break;
case 131:letsize=getletter(argv[2],'в',(char *)outfnt+outfnt_seek);break;
case 132:letsize=getletter(argv[2],'д',(char *)outfnt+outfnt_seek);break;
case 133:letsize=getletter(argv[2],'а',(char *)outfnt+outfnt_seek);break;
case 134:letsize=getletter(argv[2],'е',(char *)outfnt+outfnt_seek);break;
case 135:letsize=getletter(argv[2],'з',(char *)outfnt+outfnt_seek);break;
case 136:letsize=getletter(argv[2],'к',(char *)outfnt+outfnt_seek);break;
case 137:letsize=getletter(argv[2],'л',(char *)outfnt+outfnt_seek);break;
case 138:letsize=getletter(argv[2],'и',(char *)outfnt+outfnt_seek);break;
case 139:letsize=getletter(argv[2],'п',(char *)outfnt+outfnt_seek);break;
case 140:letsize=getletter(argv[2],'о',(char *)outfnt+outfnt_seek);break;
case 141:letsize=getletter(argv[2],'м',(char *)outfnt+outfnt_seek);break;
case 142:letsize=getletter(argv[2],'Д',(char *)outfnt+outfnt_seek);break;
case 143:letsize=getletter(argv[2],'Е',(char *)outfnt+outfnt_seek);break;
case 144:letsize=getletter(argv[2],'Й',(char *)outfnt+outfnt_seek);break;
case 145:letsize=getletter(argv[2],'ж',(char *)outfnt+outfnt_seek);break;
case 146:letsize=getletter(argv[2],'Ж',(char *)outfnt+outfnt_seek);break;
case 147:letsize=getletter(argv[2],'ф',(char *)outfnt+outfnt_seek);break;
case 148:letsize=getletter(argv[2],'ц',(char *)outfnt+outfnt_seek);break;
case 149:letsize=getletter(argv[2],'т',(char *)outfnt+outfnt_seek);break;
case 150:letsize=getletter(argv[2],'ы',(char *)outfnt+outfnt_seek);break;
case 151:letsize=getletter(argv[2],'щ',(char *)outfnt+outfnt_seek);break;
case 152:letsize=getletter(argv[2],'я',(char *)outfnt+outfnt_seek);break;
case 153:letsize=getletter(argv[2],'Ц',(char *)outfnt+outfnt_seek);break;
case 154:letsize=getletter(argv[2],'Ь',(char *)outfnt+outfnt_seek);break;
case 155:letsize=getletter(argv[2],'ш',(char *)outfnt+outfnt_seek);break;
// case 156:letsize=getletter(argv[2],'Ь',(char *)outfnt+outfnt_seek);break;
case 157:letsize=getletter(argv[2],'Ш',(char *)outfnt+outfnt_seek);break;
case 158:letsize=getletter(argv[2],'Ч',(char *)outfnt+outfnt_seek);break;
// case 159:letsize=getletter(argv[2],'Я',(char *)outfnt+outfnt_seek);break;
case 160:letsize=getletter(argv[2],'б',(char *)outfnt+outfnt_seek);break;
case 161:letsize=getletter(argv[2],'н',(char *)outfnt+outfnt_seek);break;
case 162:letsize=getletter(argv[2],'у',(char *)outfnt+outfnt_seek);break;
case 163:letsize=getletter(argv[2],'ъ',(char *)outfnt+outfnt_seek);break;
case 164:letsize=getletter(argv[2],'с',(char *)outfnt+outfnt_seek);break;
case 165:letsize=getletter(argv[2],'С',(char *)outfnt+outfnt_seek);break;

case 181:letsize=getletter(argv[2],'Б',(char *)outfnt+outfnt_seek);break;
case 182:letsize=getletter(argv[2],'В',(char *)outfnt+outfnt_seek);break;
case 183:letsize=getletter(argv[2],'А',(char *)outfnt+outfnt_seek);break;
case 198:letsize=getletter(argv[2],'г',(char *)outfnt+outfnt_seek);break;
case 199:letsize=getletter(argv[2],'Г',(char *)outfnt+outfnt_seek);break;
case 208:letsize=getletter(argv[2],'р',(char *)outfnt+outfnt_seek);break;
case 209:letsize=getletter(argv[2],'Р',(char *)outfnt+outfnt_seek);break;
case 210:letsize=getletter(argv[2],'К',(char *)outfnt+outfnt_seek);break;
case 211:letsize=getletter(argv[2],'Л',(char *)outfnt+outfnt_seek);break;
case 212:letsize=getletter(argv[2],'И',(char *)outfnt+outfnt_seek);break;
case 214:letsize=getletter(argv[2],'Н',(char *)outfnt+outfnt_seek);break;
case 215:letsize=getletter(argv[2],'О',(char *)outfnt+outfnt_seek);break;
case 216:letsize=getletter(argv[2],'П',(char *)outfnt+outfnt_seek);break;
case 222:letsize=getletter(argv[2],'М',(char *)outfnt+outfnt_seek);break;
case 224:letsize=getletter(argv[2],'У',(char *)outfnt+outfnt_seek);break;
case 225:letsize=getletter(argv[2],'Я',(char *)outfnt+outfnt_seek);break;
case 226:letsize=getletter(argv[2],'Ф',(char *)outfnt+outfnt_seek);break;
case 227:letsize=getletter(argv[2],'Т',(char *)outfnt+outfnt_seek);break;
case 228:letsize=getletter(argv[2],'х',(char *)outfnt+outfnt_seek);break;
case 229:letsize=getletter(argv[2],'Х',(char *)outfnt+outfnt_seek);break;
case 231:letsize=getletter(argv[2],'ю',(char *)outfnt+outfnt_seek);break;
case 232:letsize=getletter(argv[2],'Ю',(char *)outfnt+outfnt_seek);break;
case 233:letsize=getletter(argv[2],'Ъ',(char *)outfnt+outfnt_seek);break;
case 234:letsize=getletter(argv[2],'Ы',(char *)outfnt+outfnt_seek);break;
case 235:letsize=getletter(argv[2],'Щ',(char *)outfnt+outfnt_seek);break;
case 236:letsize=getletter(argv[2],'э',(char *)outfnt+outfnt_seek);break;
case 237:letsize=getletter(argv[2],'Э',(char *)outfnt+outfnt_seek);break;
case 246:letsize=getletter(argv[2],'ч',(char *)outfnt+outfnt_seek);break;
default:
if(i<128)letsize=getletter(argv[2],i,(char *)outfnt+outfnt_seek);
else letsize=getletter(argv[1],i,(char *)outfnt+outfnt_seek);
}

printf("len: %d\twriting %x\t",letsize,letsize?outfnt_seek:0);
outfnt[i-outfh.LowIndex+sizeof(header)/4]=letsize?outfnt_seek:0;
outfnt_seek+=letsize;
}
// int i=getletter(argv[1],247,buf);
// printf("len: %d\n",i);
FILE *out=fopen(argv[3],"wb");
if(!out){printf("!out");return 1;}
if(!fwrite(outfnt,outfnt_seek,1,out))printf("Error writing %s\n",argv[3]);

printf("!%x!",getletter(argv[1],33,(char *)outfnt));
return 0;
}
int getletter(char *filename,unsigned letnum,char *buf)
{
FILE *in;
FontHeader fh;
FontLetterRaw flr;
int pixelcounter;
int ofs=0,toskip=0,in_ofs;
char c;
in=fopen(filename,"rb");
letnum=(letnum+256)%256;
printf ("let:%d:num\t",letnum);
if(!in){printf("Data error reading file %s\n",filename);return 1;}
if(!fread(&fh,sizeof(FontHeader),1,in)){printf("Error in %s\n",filename);return 2;}
if(letnum<=fh.LowIndex||letnum>fh.HighIndex)return 0;
fseek(in,8+(letnum-fh.LowIndex)*4,SEEK_SET);
if(!fread(&in_ofs,4,1,in)){printf("Error in %s\n",filename);return 2;}
//printf("letofs: %X\n",in_ofs);
if(in_ofs==0)return 0;
fseek(in,in_ofs,SEEK_SET);
if(!fread(&flr,sizeof(FontLetterRaw),1,in)){printf("Error in %s\n",filename);return 2;}
memcpy(buf+ofs,&flr,sizeof(flr));
ofs+=sizeof(flr);
for(pixelcounter=0;pixelcounter<flr.Width*flr.Height;pixelcounter++)
{
if(toskip-->0)
{
printf("-");
}
else{
if(pixelcounter)printf("%d",c&7);
c=fgetc(in);
toskip=c>>3;
buf[ofs++]=c;
}
if(pixelcounter%flr.Width==0)printf("\n");
}
printf("%d\n",c&7);
return ofs;
}
/*void cp2win(char *fntfilename,int low,int high)
{
DWORD cp[256];
DWORD win[256];
FILE *fnt;
fnt=fopen(fntfilename,"r+b");
if(!fnt){printf("!fnt\n");return;}
fseek(fnt,12,SEEK_SET);
memset(cp,0,sizeof(cp));
memset(win,0,sizeof(win));
if(fread(cp+low,4,high-low,fnt)!=(unsigned)(high-low)){printf("!fread\n");return;}
//for(int i=low;i<high;i++)printf("%4X ",cp[i]);
for(int i=low;i<high;i++)
{
//      if(i>=0x80-1&&i<0xb0-1)win[i]=cp[i+0x40];
// else if(i>=0xc0-1&&i<0xf0-1)win[i]=cp[i-0x40];
// else if(i>=0xb0-1&&i<0xc0-1)win[i]=cp[i+0x40];
// else if(i>=0xf0-1&&i<0x100-1)win[i]=cp[i-0x10];
// if(i==128)win[i]=cp[129];
// else
// win[i]=cp[i];
// switch(i)
// {
// case "└":win[]=cp[i];
// }
}
fseek(fnt,12,SEEK_SET);
if(fwrite(win+low,4,high-low,fnt)!=(unsigned)(high-low)){printf("!fwrite\n");return;}
printf("font file written successfully\n");
fclose(fnt);
}
/*void bmp2fnt()
{
BYTE fnt[65536];
BYTE buf[16][16];
int fnt_len=0;
int width=14,bmp_width=16,height=14,letternum=239-32;

int i,j,k,len,seek,c,toskip=0;
FILE *in=fopen("game.bmp","rb");
if(!in){printf("!in");return;}
FILE *out=fopen("out.fnt","wb");
if(!out){printf("!out");return;}
fseek(in,0,2);
len=ftell(in);

memcpy(fnt+fnt_len,&fontheader,sizeof(FontHeader));
fnt_len+=sizeof(FontHeader);
fnt_len+=letternum*4;
for(k=0;k<letternum;k++)
{
seek=len-k*bmp_width*height;
for(j=0;j<height;j++)
for(i=0;i<bmp_width;i++)
{
seek--;
if((len-seek)%16==1||(len-seek)%16==2)continue;
fseek(in,seek,0);
buf[bmp_width-1-i][j]=fgetc(in);
}
for(j=0;j<height;j++)
{
for(i=0;i<width;i++)
printf("%2x",buf[i][j]);
printf("\n");
}
}
}
*/
Title: Re: War2 fonts (.fnt)
Post by: iL on February 23, 2019, 11:35:18 AM
Created a repository for previously created and now rewritten utility for blizzard (war2) font:
https://bitbucket.org/ilwar2/fontblizzard

It's just a 1-st step, i planned to make something useful to work with, but i still have no time, so commited it as is. Only reading the font content and print it to stdout.
Title: Re: War2 fonts (.fnt)
Post by: iL on February 23, 2019, 04:14:15 PM
@easycompany
Where are your posts with your projects you shared here?
Sad to not see them anymore...
Title: Re: War2 fonts (.fnt)
Post by: WarKid on February 26, 2019, 06:35:40 AM
Just courious, why are you trying to edit the fonts? To translate perhaps?  ???
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on February 26, 2019, 07:15:06 AM
ok look at this no beer..any ideas?   this is what i was running into last time..
its wierd cause i can draw in the paint prog and it will still be ok in game.

ec if you post the fnt file your playing with here i'll have a look at it ... saves me having to mess around with mpq extractors (lazybones).
Title: Re: War2 fonts (.fnt)
Post by: iL on February 26, 2019, 03:00:34 PM
Just courious, why are you trying to edit the fonts? To translate perhaps?

My part was to make russian fonts for war2 bne. Russian fonts from war2td are not compatible with bne (different charset as i remember). So, i had to find every letter in dos war2 font and set it to proper place.
My next step is to fix existing russian fonts.
They are beautiful, but russian letters have no shadow. Also, +1 letter required to add.
That's why i need a program to work with fonts.
Also, that program will be required only once, to make several beautiful russian fonts. But why not to share is to community?

[url]http://www.stormcoast-fortress.net/cntt/formats/font/[/url] = prob the same as war2

Yes, the structures are the same. I don't remember where i got that format and it's description years ago when i wrote the 1-st version, but it is it.

il has a reader..he just doesn't have time to finish up.

Yes, i planned to get +2-3 days to finish writer, but then real life and work stole my time as usual... :)
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on February 27, 2019, 01:35:10 PM
the best thing to do is just a paint box's for each character..they are all diff sizes
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on February 27, 2019, 09:39:13 PM
Here's the format:

Font Header is as mentioned in iL's source except for the "DWORD Unk1" at the end.
This is actually the pointer to the pixel data for the first character, but as the first character in this font is 0x20 (decimal 32) which is a SPACE, there is no pixel data, so the pointer is set to 0.

typedef struct   _FontHeader {
   DWORD   Name;      //   Always is "FONT"
   BYTE   LowIndex;           //   Index of first letter in file
   BYTE   HighIndex;           //   Index of the last letter in file
   BYTE   MaxWidth;           //   Maximum width
   BYTE   MaxHeight;           //   Maximum height
} FontHeader;

  -----------------

This is followed by a DWORD file pointer to the pixel data for each character.
So there are (HighIndex-LowIndex)+1 DWORDS

If the pointer is 0 there is no pixel data for that character.

 ----------

Immediately following file pointers is the pixel data ( indexed by the file pointer DWORD array )

The data for each character is as follows:

( from iL's source )
typedef struct  _FontLetterRaw {
   BYTE   Width;      //   Width of the letter
   BYTE   Height;      //   Height of the letter
   BYTE   XOffset;   //   X Offset for the topleft corner of the letter.
   BYTE   YOffset;   //   Y Offset for the topleft corner of the letter.
} FontLetterRaw;

this is followed by the actual pixel data which is encoded like this:

B=Byte

while B>=8 {
   B-=8 // skip 1 pixel (transparent)
}

B = pixel color

 ---------

EXAMPLE: if the bytes are: 9,5,2

9>=8 so skip a pixel
9-8 = 1
5
2

so that would be 4 pixels:

transparent,1,5,2


there are only 4 colors used

1 = yellow ( palette entry 0xC8 )
2 = beige  ( 0xC7 )
4 = brown ( 0xC0 )
5 = black   ( 0x00 )

value 3 is not used in the font you posted - maybe in the others idk.

Would be interesting to see what color is displayed for a 0x03 byte.


I have attached an edited copy of the font file where I have changed a bunch of the pixels in the '3' character to the pixel value of 3.

@easycompany If you want you could try importing that into the game data then type a bunch of 33333333's in game chat and see what color is displayed. IDK maybe its a different color, maybe its nothing, maybe it will even crash - just could be interesting :) (you will have to rename it back to the original name ofc)

If I get time I'll try to write a quick extractor/packer so you can edit them easily (no promises)

Title: Re: War2 fonts (.fnt)
Post by: shesycompany on February 27, 2019, 10:07:06 PM
i think its yellow if ur orc/white if human..be cool if u could get a font to put in..looks like forever to draw them.

03 is a grey on human, so its probably a shade of beige orc etc

this is all im gonna be doing to mine a chr and a black background   ..fancy looks like it take awhile

lol tried a rus char ..about as good as i can do for that one :D

3 is the number "3"  i can look at "4" and its smaller size to make it so its not really using a 6x10 grid

"0A-0D" there should be one of these in every char somewhere.... i say is making bits move i can do ff and it will split the char in half so something reads here ..but if its black or white it wont matter ...it will then display as to what u have drawn.

and these big symbols with lots of stuff going on looks impossible for the size limit..it would need something that is bigger to draw them.


Title: Re: War2 fonts (.fnt)
Post by: iL on February 28, 2019, 01:30:49 AM
@Lambchops, thanks, for such detailed format description, i've been too lazy to describe it anywhere, i just hope such format is obvious from my source code.
there are only 4 colors used

1 = yellow ( palette entry 0xC8 )
2 = beige  ( 0xC7 )
4 = brown ( 0xC0 )
5 = black   ( 0x00 )

value 3 is not used in the font you posted - maybe in the others idk.
I also saw 6(instead of 5 for shadow) and even 0(1 or 2 bytes) in other fonts. Not sure if they are not bugs, i didn't load and check that font.

Font Header is as mentioned in iL's source except for the "DWORD Unk1" at the end.
This is actually the pointer to the pixel data for the first character, but as the first character in this font is 0x20 (decimal 32) which is a SPACE, there is no pixel data, so the pointer is set to 0.
You mean that is not a "DWORD Unk1" in font header, but it's an address of 1-st character (which is NULL because it's SPACE)? Same idea, at least everything works after i commented "DWORD Unk1" and used that way to act.

If I get time I'll try to write a quick extractor/packer so you can edit them easily (no promises)
look at my code: extractor is already working (still not sure about character with X-offset), packer for that format is next step to finish that program.
Created a repository for previously created and now rewritten utility for blizzard (war2) font:
https://bitbucket.org/ilwar2/fontblizzard
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on February 28, 2019, 03:09:26 AM
can people type in game in russian?

meant for text =white/ bg =black...


there we go!
Title: Re: War2 fonts (.fnt)
Post by: iL on February 28, 2019, 04:18:23 AM
can people type in game in russian?

meant for text =white/ bg =black...
Sure, i spent several days in 2007 or 2008 to translate main russian font (font10x or font12x, i don't remember exactly) to let people use russian font.
If your combat contains russian, you can type and see russian, otherwise you can't.
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on February 28, 2019, 04:27:28 AM
this is the russian keyboard correct?
http://russian.typeit.org/ (http://russian.typeit.org/)


ahh ok got the russian just looking
wow nice job!

well i cant get around the thing that flips half my char as of right now... again good job thats impressive
Title: Re: War2 fonts (.fnt)
Post by: iL on February 28, 2019, 09:57:04 AM
this is the russian keyboard correct?
[url]http://russian.typeit.org/[/url] ([url]http://russian.typeit.org/[/url])

Yes, russian characters are ok, but they are located on improper buttons. This looks like russian "qwerty". I think, not important.

ahh ok got the russian just looking
wow nice job!

Also, order of russian characters in blizzard russian font is very strange: not alphabetic (a-z), not small, then capital or w/e, looks like random mix of capital and small letters. I didn't understand any regularity in that order.

well i cant get around the thing that flips half my char as of right now... again good job thats impressive

Hm, my code i posted here and then my code from bitbucket i also shared here work fine with all chars. Looks like something wrong with your code then...
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on February 28, 2019, 04:51:53 PM
mmm yes it seems :D
but the chinese dudes could put text on the grp's
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 01, 2019, 06:48:12 AM
@Lambchops, thanks, for such detailed format description, i've been too lazy to describe it anywhere, i just hope such format is obvious from my source code.


@iL Yw. :) Thanks for posting your source, it saves time when you can see what others have done.

there are only 4 colors used

1 = yellow ( palette entry 0xC8 )
2 = beige  ( 0xC7 )
4 = brown ( 0xC0 )
5 = black   ( 0x00 )

value 3 is not used in the font you posted - maybe in the others idk.

I also saw 6(instead of 5 for shadow) and even 0(1 or 2 bytes) in other fonts. Not sure if they are not bugs, i didn't load and check that font.


OK. Well the only .fnt file I have looked at so far is the font10x.fnt that @easycompany posted, if there are other possible combinations of byte values/colors that info must be stored somewhere else because it isn't in the .fnt file. Possibly there could be a corresponding "font palette" file stored seperately.

Font Header is as mentioned in iL's source except for the "DWORD Unk1" at the end.
This is actually the pointer to the pixel data for the first character, but as the first character in this font is 0x20 (decimal 32) which is a SPACE, there is no pixel data, so the pointer is set to 0.

You mean that is not a "DWORD Unk1" in font header, but it's an address of 1-st character (which is NULL because it's SPACE)? Same idea, at least everything works after i commented "DWORD Unk1" and used that way to act.


Yes.

If I get time I'll try to write a quick extractor/packer so you can edit them easily (no promises)

look at my code: extractor is already working (still not sure about character with X-offset), packer for that format is next step to finish that program.


OK, here it is.

This will extract all the characters out of a .fnt file into a bunch of individual .bmp files so you can edit them. Just drop a .fnt file onto War2FontTool.exe.

When you edit them (with MSPaint or whatever) make sure to copy the existing color values and not use any other colors. Any unknown colors will be removed.

You can add extra .bmps for missing chars (do this by copying an existing .bmp then rename and edit).

You can change the width/height of the bitmaps to resize the chars. The X/Y offsets are calculated automatically.

The green color will be transparent.

When you have finished editing the bitmaps, just drop any one of them onto War2FontTool.exe to compile them all into a .fnt file.
This will overwrite the original file without warning, so keep a backup.

The maximum size allowed for an individual character is 64x64 pixels.

The .fnt file will always be declared to include character 0x20 (space).


  ---  ---  ---


As mentioned, the only file I have tested this with is font10x.fnt, but I expect that it will probably work with the others ... please test :)

The original font10x.fnt file declares characters 0x20 -> 0xEF although the highest character image it contains is 0xE1.

To recompile a byte-for-byte identical .fnt file from the extracted .bmps you can create an empty (0 Byte length) file called "font10x_EF.bmp". This will force the compiler to declare the range 0x20 -> 0xEF. I don't know if there is any internal reason why WC2 requires this to be declared, I suspect there is not.

Anybody who is interested in this stuff please experiment and let me know if there are any issues  ... HF

                                                                                                                                                               :critter:


-- edit --

Source is HERE (http://forum.war2.ru/index.php/topic,2703.msg76190.html#msg76190)

Have changed this to use decimal file names so it can be compatible with iL's project.
Title: Re: War2 fonts (.fnt)
Post by: iL on March 01, 2019, 10:19:50 AM
OK, here it is.

This will extract all the characters out of a .fnt file into a bunch of individual .bmp files so you can edit them. Just drop a .fnt file onto War2FontTool.exe.

When you edit them (with MSPaint or whatever) make sure to copy the existing color values and not use any other colors. Any unknown colors will be removed.

You can add extra .bmps for missing chars (do this by copying an existing .bmp then rename and edit).

You can change the width/height of the bitmaps to resize the chars. The X/Y offsets are calculated automatically.

The green color will be transparent.

When you have finished editing the bitmaps, just drop any one of them onto War2FontTool.exe to compile them all into a .fnt file.
Wow, you are quick, that's a great project!
Just tried it, works fine for me!

Your idea about bmp export-import is absolutely right, looks like that is the only way to make it useful for people as a ready product.
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 01, 2019, 10:46:40 AM
Just tried it, works fine for me!

Cool :fro: Thanks for testing :)  I hope it's useful.

Your idea about bmp export-import is absolutely right

So many bitmap editors already written - no point in re-inventing the wheel.


Title: Re: War2 fonts (.fnt)
Post by: shesycompany on March 01, 2019, 09:21:40 PM
wow hell yea! paint editors is best for this stuff anyhow..works for me
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on March 02, 2019, 01:26:46 PM
lol fnt12 they all work  but there u go some complicated language like chinese can do just like windows games... phrases in the text idk

lol man this is cool as hell

my jpg looks like crap overlook the artifacts

could be used for kids also


Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 02, 2019, 08:25:12 PM
lol fnt12 they all work  but there u go some complicated language like chinese can do just like windows games... phrases in the text idk

lol man this is cool as hell

my jpg looks like crap overlook the artifacts

could be used for kids also



haha cool. We could add characters for common phrases like "gg no re" "get good newb" "wtf pard?" or "everyone rush 6" and use ALT+numbers.

Have you tested what happens if you make a much bigger character? ...like just one 50x50 char in the middle of the normal stuff?

Title: Re: War2 fonts (.fnt)
Post by: shesycompany on March 02, 2019, 10:16:26 PM
yeah it'll more than likely crash 12x should go wider than that ill test in morning..
the message box is funky  it may can stay a height and goes as long as you want..but be so big boom crashed..still in blizzard code

pbr right now doubt i can hit save Days of Thunder - Main Theme (2013 Extended Mix) - YouTube (http://www.youtube.com/watch?v=te9ez9zS6TI#)

u know them fucks at that sc1 site are all asm...hell the built my mini shit years ago :/ for use with sc1
Title: Re: War2 fonts (.fnt)
Post by: iL on March 02, 2019, 10:28:15 PM
I thought and just decided to continue working on my project: i need to make some improvements with my fonts:
- to compile fonts containing russian chars from russian fonts and other chars from english ones
- to add shadows to russian chars
- to add and probably fix some russian chars

I don't want to do that manually in bmp, i prefer to make most actions in c++ code.
At the same time i think working via .bmp is a very good idea.
So, my idea: to continue writing my code for exporting fnt to bmp and then to use your code to importing them back from .bmp to .fnt.

So, i stole your code working with bmp and added it to my project.
Also updated my project on bitbucket.

@Lambchops looks like your code and my code make different .bmp-files from the same fonts:
Differents touch palette only and increases from begin to end.
For example, i comparing mine and yours font10x_246.bmp (i changed char szBmpTmpl[] = "_%2.2X.bmp"; to char szBmpTmpl[] = "_%03d.bmp"; to make win sort files properly, that's the only change i made in your code):
Code: [Select]
0000042A: FC 00
0000042B: 00 C7
0000042E: FC 00
0000042F: FC 4A
00000432: FC 4A
00000433: FC 4A
As i understand, it's a palette, pixels begin from 00000436. And your code changes values from 1-st char to another, but my code gives similar values every time (and looks like they are similar with bmp8 array).
And i don't understand how that can happen: eighter you change the palette in bmp8 somehow (i didn't find that in your code) or that is a bug or something else i don't understand.
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 03, 2019, 09:00:53 AM
I thought and just decided to continue working on my project: i need to make some improvements with my fonts:
- to compile fonts containing russian chars from russian fonts and other chars from english ones
- to add shadows to russian chars
- to add and probably fix some russian chars
I don't want to do that manually in bmp, i prefer to make most actions in c++ code.

Ok cool. I was thinking about doing something like this as an example, just for fixed pitch fonts where I could easily extract them from a screen grab.

At the same time i think working via .bmp is a very good idea.
So, my idea: to continue writing my code for exporting fnt to bmp and then to use your code to importing them back from .bmp to .fnt.

Ok, but my code is very dependant on the format being exactly what it is expecting, so the format would have to be exactly the same. It would probably be easier to just use my export code as it is already 100% compatible with the import code. idc it's up to you.

So, i stole your code working with bmp and added it to my project.
Also updated my project on bitbucket.

You're very welcome to re-use my code. Thanks for crediting me in the comments :)

@Lambchops looks like your code and my code make different .bmp-files from the same fonts:
Differents touch palette only and increases from begin to end.



OK.

What I did for the bitmap handling in this project was this:

I got a wc2 .pcx SS and converted it to a bitmap (8 bit palette based, as is the native format for the game).
Then I discarded the pixel data (made it all black) and resized it to 64x64 pixels. Then I just converted the entire file to a c-style declaration. *Have attached the original .bmp file just for interest's sake.

This way it has all the default values for the bitmap headers and the wc2 palette already in place AND it is defined in the .data section so it can be also be directly used as the actual buffer (for read and write).

You can see that nowhere in the code is any other memory allocated to hold the bitmap - the BITMAPFILEHEADER and BITMAPINFOHEADER pointers are cast direcly over this initialsed data declaration, the pixels are modified there, when loading the files are read and written over this same place and when saving this region is saved directly to a file.

This was just a conveniant way to handle the bitmaps as only one bitmap is ever in memory at one time, so they can all use the same space. Plus all the values are already initialised, so less work... also I can cheat and define things like the pixmap pointer and the actual line width as globals (again less work ;))


For example, i comparing mine and yours font10x_246.bmp (i changed char szBmpTmpl[] = "_%2.2X.bmp"; to char szBmpTmpl[] = "_%03d.bmp"; to make win sort files properly, that's the only change i made in your code):
Code: [Select]
0000042A: FC 00
0000042B: 00 C7
0000042E: FC 00
0000042F: FC 4A
00000432: FC 4A
00000433: FC 4A
As i understand, it's a palette, pixels begin from 00000436. And your code changes values from 1-st char to another, but my code gives similar values every time (and looks like they are similar with bmp8 array).
And i don't understand how that can happen: eighter you change the palette in bmp8 somehow (i didn't find that in your code) or that is a bug or something else i don't understand.

Yes for this case the pixmap always starts at offset 0x436, this is defined in BITMAPFILEHEADER.bfOffBits ( it's the 0x04360000 which is the 3rd DWORD in the declaration ). Add this value to the base address of the data and you have the address of the pixel data.

I'm not sure how you got the values you have posted (starting at 0000042A), but I can see what has occurred. You mention font10x_246.bmp. 246 = 0xF6 and the font10x.fnt file stops at 0xEF so I do not know the bitmap you are working with...

... that being said, yes this area holds the end of the palette.  0x042A...  should be FC:00:FC:FC:FC:FC as per the first column you have posted.

This area has obviously been overwritten by pixel data as 00, C7 and 4A are all values from the clrndx[] array. Notably 0x4A is the grey color I put in for the .fnt pixel value of 3, and as previously mentioned the value 3 does not appear in font10x.fnt ( I just picked a grey color and put it there because EC said it was grey ).

MS .bmp format has a couple of peculiarities:
- Each line of pixel data is DWORD aligned.
- The pixel data is stored starting with the bottom line first and the top line last.

As the blizzard guys (and any other sane people) work with pixels from the top down, all the Y co-ordinates must be inverted when converting from .fnt to .bmp and back again.

This is handled in get_pixel() and set_pixel() by the line:
Code: [Select]
BYTE* pptr = pixmap+(linew*(bmh-y-1))+x;
bmh-y-1 inverts the pixel position then this is multiplied by linew

linew is the actual size of a pixel line in memory, which may be different from the width of the bitmap due to the DWORD alignment.

This size is calculated by:
Code: [Select]
linew  = ((bmw+3)>>2)<<2;
This just ensures that the width is rounded up to the next 4-byte boundary.

.... so: back to the issue ...

If the palette is being overwritten then at some stage there is an extra line of pixels being written at the bottom of a bitmap that won't fit... i.e. the bitmap has been defined with a height of 8 (lines 0->7) but then some pixels have been written to line 8.

When writing to a bitmap, if it is first defined with init_bmp(w,h) and set_pixel() is only used with x = 0 -> (w-1)  and  y = 0 -> (h-1) then the palette should never be written to.

I don't know what you are extracting when this error occurs, if you post the file you are using then I can comment more specifically.

The .bmp routines I wrote specifically for this project, they were not written to be 'safe' for general purpose use.

For debugging purposes you could use something like:

Code: [Select]
void Bmp::set_pixel(int x,int y,int c){
    // set a pixel in the current bitmap
    BYTE* pptr = pixmap+(linew*(bmh-y-1))+x;
    if(x>=0&&y>=0&&x<bmw&&y<bmh){
        *pptr = c;
    }else{
        std::cout << "Invalid Pixel Write Location\n";
    }
}
Checked out your bitbucket you have done lots of cool stuff there, and for Warcraft II in general. PMd you some suggestions :)  Hope this is useful.


 --- edit ---

Added an extra check to stop over-write. I didn't notice this because I was still looking at previous extracted bitmaps from before this issue was introduced. Had 0 effect on functionality, but better fixed. Thanks @iL for testing.

Title: Re: War2 fonts (.fnt)
Post by: shesycompany on March 03, 2019, 01:40:53 PM
ok there u go lamb ..long as im trying, tried some longer they was to long(it'll be a little square then)..

naw not messed with 50..got a idea though brb

with some modifications, i think one could change the interface to the language they wanted...

some kinda chinese example....  i think<--  :-X

im using 12x... 10x cant stretch as far so it seems.
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 04, 2019, 05:10:11 AM
ok there u go lamb ..

Cool, thanks man :)

It's increased the size of the space character. I thought this might happen:

Gold          separates          east          from          west

As there is no data for the 0x20 character it is basing the space width on FontHeader.MaxWidth  .... perhaps MaxWidth/2+1 or something.

Maybe MaxWidth could be independantly set to a smaller value ???
Title: Re: War2 fonts (.fnt)
Post by: iL on March 04, 2019, 09:50:04 AM
Ok, but my code is very dependant on the format being exactly what it is expecting, so the format would have to be exactly the same. It would probably be easier to just use my export code as it is already 100% compatible with the import code. idc it's up to you.
Sure, that's why i used your code in my project!

I got a wc2 .pcx SS and converted it to a bitmap (8 bit palette based, as is the native format for the game).
Then I discarded the pixel data (made it all black) and resized it to 64x64 pixels. Then I just converted the entire file to a c-style declaration. *Have attached the original .bmp file just for interest's sake.
Idea is simple and... perfect!
To export proper bmp-file you need nothing except to write it's pixels, wigth,height and decrease size to required value.

Thanks for such great tool and several great programming ideas!

UPD:
Also, i added a function to make a shadow (color 5) for letter, applied it to russian letters with no shadows, and looks like that's done for me.
I got 5 beautiful russian fonts as planned, so, no reason to continue working on this project for me.
Commited it into my bitbucket. You can use exe to unpack font to *.bmp (same format as Lambchops utility, with dec filenames instead of hex, just better for me). My project is useless without the source code again.
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 05, 2019, 03:40:10 AM
Also, i added a function to make a shadow (color 5) for letter, applied it to russian letters with no shadows, and looks like that's done for me.
I got 5 beautiful russian fonts as planned

Very cool :) I had fun collaborating on that. Happy to help next time you are doing something - let me know   :critter:

 
  --- --- ---


I think the next thing we need to think about is switching fonts actively in-game.

It is good that the Russian players will have a font that they can use to chat in Russian with ... but I think (not sure?) this will then scramble any English chat if they are using that font, ya? So then Russian players who have some English will not be able to see English chat properly.

I think you would also want to see if an english player says "hit s5 now" ....or even asking what teams: if someone says "me/bro/thumb vs" and you see "K#/^C+/!*#xW x$" that is not helpful... or maybe you can translate into English characters in your head? idk..

Also for hosting etc., won't you see the English map names as scrambled Russian characters? ... like "Garden of War.pud" will be "#%w^!& z@ X#<.=M&" or something?

So I think we need a method of switching fonts, so players using other languages can push a key and see the English when they want to. Probably be best to have it set to display English in the create game screen etc?

It is great that players can use other languages, but I would hate to see this split up the community because when people are using a Russian font they CAN'T also read or write English ???

I'm not sure exactly how much of a problem this would be because I don't understand Russian, but it is worth thinking about.


   --- --- ---


also thanks for the info in your PM - I have a day off work tomorrow I will look at it then  :thumbsup:

Title: Re: War2 fonts (.fnt)
Post by: iL on March 05, 2019, 04:08:09 AM
this will then scramble any English chat if they are using that font, ya? So then Russian players who have some English will not be able to see English chat properly.
English characters are all in the 1-st half of ASCII-table, 0-128. Russian characters are in the 2-nd half: 128-255.
So, no intersection here at all.
English is the main part for all the charsets in the world.

The problem can be related to other non-english languages (using russian font you will not be able to see some specific characters on other languages, maybe french, german, spanish, etc). I don't know other languages except english and russian, so i don't know how other languages looks like with russian charset.
What i saw: when someone hosts one or several map called "...Archers..." - i can see 1-2 russian characters instead of original. I think map name contains some specific symbols like A^ or A' or A` or w/e. That is the only problem i got with russian font instead of original.
Title: Re: War2 fonts (.fnt)
Post by: Lambchops on March 05, 2019, 05:17:15 AM
this will then scramble any English chat if they are using that font, ya? So then Russian players who have some English will not be able to see English chat properly.
English characters are all in the 1-st half of ASCII-table, 0-128. Russian characters are in the 2-nd half: 128-255.
So, no intersection here at all.
English is the main part for all the charsets in the world.

Oh good :) I wasn't sure about that (hopelessly monolingual here lol).

Title: Re: War2 fonts (.fnt)
Post by: Storycraft on March 29, 2019, 04:51:40 PM
Hello, Lambchops. I used the file you uploaded. But there is no response(font6.fnt / font10.fnt / font12.fnt / font32.fnt / font50.fnt) And another War2FontTool.exe(http://en.war2.ru/downloads/ (http://en.war2.ru/downloads/) ) in this section is also unresponsive.
Can you help me? I will make a Korean translation. Please send me the extracted bmp files. I will return it after editing.

Thank you!
Title: Re: War2 fonts (.fnt)
Post by: Muz on December 30, 2019, 06:53:38 PM
Is it me or the War2FontTool don't convert anything. I try dragging .fnt files into it, and nothing happen. Okay, it works, I don't know if Japanese keyboard is possible for this font.

i think its yellow if ur orc/white if human..be cool if u could get a font to put in..looks like forever to draw them.

03 is a grey on human, so its probably a shade of beige orc etc

this is all im gonna be doing to mine a chr and a black background   ..fancy looks like it take awhile

lol tried a rus char ..about as good as i can do for that one :D

3 is the number "3"  i can look at "4" and its smaller size to make it so its not really using a 6x10 grid

"0A-0D" there should be one of these in every char somewhere.... i say is making bits move i can do ff and it will split the char in half so something reads here ..but if its black or white it wont matter ...it will then display as to what u have drawn.

and these big symbols with lots of stuff going on looks impossible for the size limit..it would need something that is bigger to draw them.





(http://forum.war2.ru/index.php?action=dlattach;topic=4701.0;attach=2902)

What software is that to edit the characters?
Title: Re: War2 fonts (.fnt)
Post by: Storycraft on January 01, 2020, 05:22:26 AM
Do you need assistance? :) The key file is  "art/font12x.fnt" (o) not "font/font12.fnt" (x)

art/font10x.fnt
art/font12x.fnt
art/font32.fnt
art/font50.fnt

How to display 2 byte characters is, as yet, unknown.
You can use 128 letters(second part of the ASCII code), except for Chinese characters, it is not enough to use only Hiragana and Katakana.
Do you have any alternative ideas?

I succeeded in Korean translation. war1, war2bne, sc1, sc2 mass recall(fan remake).  I am also interested in Japanese translation.
Title: Re: War2 fonts (.fnt)
Post by: Muz on January 07, 2020, 12:35:03 PM
Can I see your Korean translation, Storycraft?
Title: Re: War2 fonts (.fnt)
Post by: shesycompany on January 08, 2020, 12:36:50 AM
im shure storykraft has got  a working version