War2.ru Slogan
News: Watch live streams at War2TV and replays of
past streams at War2TV Reruns!


Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
Welcome to the forums! We're glad to have you here! :) You can register your account here, then feel free to introduce yourself in the Server.War2.ru board & let us know who you are on the server.
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Lambchops

Pages: [1] 2 3 ... 82
I dont understand why ppl want change  this game,

- free repair till bulding is complete
- voice repair is like hit by peon
- you can go back with 2-100(125) wood
- going to mine/wood when peon got allready gold/wood
- if my units just stay they will go insta attack if they see opponents in unit sight
-really points
-tower had 6 range and he just focus  hall not peons mining

also i saw(maybe in diffrent version) when i could go to my ally base and start mining from his gold to his hall with my peon ......

Agree.

Wargus is well written. It is good programming - but it is bad wc2.

I just played this again and remembered why I've always hated it:

It's a bad cover version of a classic song. :(

2) Server.War2.ru / Re: March 10th - Newbs + Pros Tournament | #2
« on: March 11, 2019, 06:00:48 AM »
Kudos for organizing this xurnt. Sounds like lots of fun :) I would definitely join in if I wasn't on the other side of the earth :'(

3) Mods & Development / Re: A better AI, selecting more than 9 units at a time
« on: March 10, 2019, 08:59:10 AM »
Not really. IIRC I think you can get 10 my using the mage multicast method and getting 9 units to follow a 10th unit, but in practical use the lead unit is usually one of the 9 anyway.

Does this work? Anyone?

Usually this is one of 2 things: on a cheap &/or older system it is possibly earth leakage from power supply or HDD etc (earth loops don't help either), but the most common reason for this remains (as it always has been) crappy shielding on cheap cables - in this case the ones that connect your headset to the computer.

You could also check the connector from your sound hardware (probably onboard MOBO) to the panel that houses your phone/mic jacks if that is seperate (i.e. front panel of a tower PC) ... replug it a few times and try some contact cleaner... but it's probably just a cheap headset with crappy shielding.

don't judge me

It's ok tk, we all gave up judging you years ago lol

5) Strategy & Replays / Re: beating bloodlust
« on: March 06, 2019, 08:56:34 AM »
You should ATTACK with demo squads... not detonate - demos are op they will pwn the ogres  :thumbsup:

6) Mods & Development / Re: War2 fonts (.fnt)
« 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).


7) Mods & Development / Re: War2 fonts (.fnt)
« 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:


8) Mods & Development / Re: War2 fonts (.fnt)
« 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 ???

9) Mods & Development / Re: War2 fonts (.fnt)
« 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.


10) Mods & Development / Re: War2 fonts (.fnt)
« 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?


11) Mods & Development / Re: War2 fonts (.fnt)
« 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.



12) Mods & Development / Re: Nerd's Corner
« on: March 01, 2019, 06:52:19 AM »
Source code for War2FontTool.exe (description)
Code: [Select]
// Warcraft II font Extractor/Compiler
// Lambchops Feb 2019

#include <windows.h>
#include <shlwapi.h>

#define INVALID_FILE  1
#define INVALID_INPUT 2
#define READ_ERROR    3
#define WRITE_ERROR   4
#define ALLOC_FAIL    5

#define BG_COLOR 0x18
#define MAX_CHAR_SIZE 4108


typedef struct   _FontHeader {
   DWORD  FourCC;              //   Always "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;

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;

BYTE clrndx[ ] = {BG_COLOR,0xC8,0xC7,0x4A,0xC0,0x00};

char f_ext[] = "fnt";
char b_ext[] = "bmp";
char szBmpTmpl[] = "_%3.3d.bmp";
char szFntTmpl[] = ".fnt";
char szFont4cc[] = "FONT";
char pathbuf[512];
char szHelpText[]   = "  Warcraft II Font Extractor/Compiler - Lambchops Feb 2019\r\rDrop a .fnt file to extract.\rDrop one of the extracted .bmp files to compile.\r\r *Make sure you only use the existing colors when editing\r  unknown colors will be deleted.";


// --- FILE/PATH --- //

int get_flen(CHAR* path){
    HANDLE fn = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    int r = GetFileSize(fn,NULL);
    CloseHandle(fn);
    return r;
}

CHAR* filename(CHAR* lppath){
CHAR* r = lppath+lstrlen(lppath);
while(r>lppath){
if(*r==0x5C)return (r+1);
r--;
}
return lppath;
}

CHAR* get_extension(CHAR* lppath){
CHAR* r = lppath+lstrlen(lppath);
CHAR* def = r;
while(r>lppath){
if(*r==0x2E)return (r+1);
r--;
}
return def;
}

int loadlen;

HANDLE bload(char* path){
    // Allocate global memory and read in a file
    HANDLE fn = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    DWORD nb;
    HANDLE fdat;

    if(fn!=INVALID_HANDLE_VALUE){
        loadlen = GetFileSize(fn,NULL);

        // allocate a buffer
        fdat = GlobalAlloc(GPTR,loadlen);

        // read file into buffer
        ReadFile(fn,fdat, loadlen, &nb, NULL);
        CloseHandle(fn);

       if(nb==loadlen)return fdat;             
       GlobalFree(fdat);
    }
    return NULL;
}



// --- BITMAP --- //

int bmp8len = 0x1436;
DWORD bmp8[] = {0x14364D42,0,0x04360000,0x00280000,0x00400000,0x00400000,0x00010000,0x00000008,0x10000000,0,0,0,0,0,0x94FC0000,
0xD0000000,0xFF0000FC,0x00FC0000,0x00FC0000,0x00FC0000,0x00FC0000,0x00FC0000,0x00FC0000,0x28280000,0x00FC00CC,0xFC480000,0xCC2800FC,0xA01000E4,0x740000CC,0x240000B4,0x2C000000,
0x34000000,0x40040014,0x4804000C,0x540C0024,0x5C100028,0x6414002C,0x6C1C003C,0x7828004C,0x8030005C,0x8C3C006C,0x4C000080,0x20540000,0x285C0000,0x2C640000,0x30680000,0x34700000,
0x38740004,0x44780004,0x50800008,0x5C880010,0x487C0018,0x4C80000C,0x4880000C,0x447C000C,0x40780008,0x38740008,0x38740004,0x38740004,0x38740004,0x40780004,0x50840008,0x5C8C0010,
0x6C940018,0x608C0024,0x5888001C,0x50840014,0x20040010,0x2808003C,0x34100048,0x042C0058,0x042C00FC,0x540000FC,0x60040000,0x70340010,0x7C1C003C,0xA038004C,0x04040080,0x10100004,
0x18180010,0x24240018,0x30300024,0x3C3C0030,0x4848003C,0x50500048,0x5C5C0050,0x6868005C,0x74740068,0x7C7C0074,0x8888007C,0x94940088,0xA0A00094,0xACAC00A0,0x440000AC,0x14000000,
0x1C000018,0x20000024,0x2C000030,0x30000040,0x38000050,0x40000060,0x4404006C,0x4C000074,0x54080078,0x6018007C,0x6C280088,0x7C3C0090,0x844C0098,0x3C0000A0,0x14140000,0x1C1C0014,
0x2828001C,0x34340028,0x40400034,0x4C4C0040,0x5858004C,0x64640058,0x6C6C0064,0x7878006C,0x84840078,0x90900084,0x9C9C0090,0xA8A8009C,0xB4B400A8,0xC0C000B4,0xCCCC00C0,0xD8D800CC,
0x343400D8,0x44400044,0x54500054,0x64600068,0x78700078,0x8880008C,0x9C90009C,0xB0A400B0,0xC4B400C0,0x485800D4,0x5C6C0030,0x74800044,0x8C94005C,0x9CA4007C,0x14000090,0x18000024,
0x2000002C,0x24040034,0x2C04003C,0x30080048,0x380C0050,0x40140058,0x4C180064,0x581C006C,0x60240078,0x6C280080,0x7830008C,0x84380094,0x944000A0,0xA04800A8,0x340000B4,0x40000018,
0x4C00001C,0x58000024,0x64040028,0x70040030,0x80080034,0x8810003C,0x9414004C,0xA018005C,0xAC20006C,0xB828007C,0x34140090,0x48140074,0x6418009C,0x841400C4,0x000000F0,0x00000018,
0x0000002C,0x00000044,0x0000005C,0x00000074,0x00000088,0x000000A0,0x000000B8,0x381000D0,0x4C1C0060,0x64280074,0x7C3C0088,0x9054009C,0xA87400B4,0xC49800CC,0x002400E8,0x00300000,
0x04400000,0x0C4C0000,0x185C0000,0x28700000,0x34780000,0x40840004,0x5090000C,0x60980018,0x70A40024,0x80B00034,0xF4580044,0xB43800FC,0x601800FC,0x000000FC,0x300000FC,0x4000005C,
0x50040068,0x64080078,0x780C0088,0x8C100098,0xA41400A8,0xC01C00BC,0xE02000D0,0x000000F4,0x000000FC,0x94FC00B0,0xD0000000,0x000000FC,0x00FC00FC,0xFC000000,0,0x000000A4,
0x0400007C,0x0400005C,0x48CC0044,0x28A0000C,0x14740004,0x044C0000,0xB4940000,0x845C002C,0x542C0014,0x280C0004,0x48B00000,0x2C840098,0x18580074,0x082C0050,0x8C14002C,0x601000F8,
0x3C1000C8,0x200C0098,0x283C006C,0x1C2C0028,0x1420001C,0x0C140014,0xE0E0000C,0x98B400E0,0x54800098,0x284C0054,0x40140024,0x58200068,0x7030007C,0x00000090,0x5CA00000,0x34780018,
0x50840004,0x6C8C0010,0x80E40018,0x8448001C,0xF8F000A8,0xA0A400FC,0x808000A0,0x00000080,0xFC0000FC,0xFC000000,0x00FC00FC,0x00FC0000,0xFCFC00FC,0xFCFC0000,0x000000FC,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

BYTE* bmptr = (BYTE*)bmp8;
BYTE* pixmap;
int linew,bmw,bmh;

void init_bmp(int w,int h){
    // initialize the bitmap buffer for the supplied size
   
    BITMAPFILEHEADER* bfh = (BITMAPFILEHEADER*)bmptr;
    BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(bmptr+sizeof(BITMAPFILEHEADER));
                   pixmap = bmptr+bfh->bfOffBits;
                    linew = ((w+3)>>2)<<2;
    int             psize = linew*h;
   
    bfh->bfSize  = bfh->bfOffBits+psize;
    bih->biWidth = w;
    bih->biHeight= h;
    bmw = bih->biWidth;
    bmh = bih->biHeight;
    FillMemory(pixmap,psize,BG_COLOR);
}



void set_pixel(int x,int y,int c){
    // set a pixel in the current bitmap
    BYTE* pptr = pixmap+(linew*(bmh-y-1))+x;
    *pptr = c;
}

int get_pixel(int x,int y){
    // get a pixel from the current bitmap
    BYTE* pptr = pixmap+(linew*(bmh-y-1))+x;
    return *pptr;
}

void normalize_bmp(){
    // change palette indexes to font indexes     
    //  change unknown values to transparent

    int c;
    for(int y=0;y<bmh;y++){
        for(int x=0;x<bmw;x++){
            c = get_pixel(x,y);
            set_pixel(x,y,0);
            for(int i=0;i<=5;i++){
                if(c==clrndx[i]){
                    set_pixel(x,y,i);
                    break;
                }
            }
        }
    }
}

int bmp_yos(){
    // find non-zero Y offset
    for(int y=0;y<bmh;y++){
        for(int x=0;x<bmw;x++){
            if(get_pixel(x,y)!=0)return y;
        }
    }
    return -1;
}

int bmp_xos(){
    // find non-zero X offset
    for(int x=0;x<bmw;x++){   
        for(int y=0;y<bmh;y++){
            if(get_pixel(x,y)!=0)return x;
        }
    }
    return -1;
}

BOOL save_bmp(char* path){
    // save the current bitmap
    BITMAPFILEHEADER* bfh = (BITMAPFILEHEADER*)bmptr;   
    HANDLE fn = CreateFile(path,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
    DWORD nb;
   
    if(fn!=INVALID_HANDLE_VALUE){
        if(WriteFile(fn,bmptr,bfh->bfSize,&nb,NULL)){
            CloseHandle(fn);
            return TRUE;
        }
        CloseHandle(fn);
    }
    return FALSE;
}



BOOL load_bmp(char* path){
    BITMAPFILEHEADER* bfh = (BITMAPFILEHEADER*)bmptr;
    BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(bmptr+sizeof(BITMAPFILEHEADER));
    HANDLE fn = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    DWORD nb;

    if(fn!=INVALID_HANDLE_VALUE){
        loadlen = GetFileSize(fn,NULL);

        // read file into buffer
        ReadFile(fn,bmp8, loadlen, &nb, NULL);
        CloseHandle(fn);

       if(nb==loadlen){
           bmw    = bih->biWidth;
           bmh    = bih->biHeight;
           pixmap = bmptr+bfh->bfOffBits;
           linew  = ((bmw+3)>>2)<<2;
             
           return TRUE;
       }
    }
    return FALSE;   
}

BITMAPINFOHEADER* bmp_info(){
    return (BITMAPINFOHEADER*)(bmptr+sizeof(BITMAPFILEHEADER));               
}

// --- EXTRACT --- //


BOOL extract_char(HANDLE hFont,int base,int c,char* path){
    FontLetterRaw* flr;
    BYTE*  bptr = (BYTE*)hFont;
    DWORD* dptr = (DWORD*)hFont;
    int    px = 0;
    int    py = 0;

    // get file offset   
    dptr += (c-base+2);
    if(!(*dptr))return FALSE;
    bptr +=(*dptr);
   
    // read character header
    flr   =(FontLetterRaw*)bptr;
    bptr += sizeof(FontLetterRaw);
   
    // initialize output bitmap
    init_bmp( flr->Width+flr->XOffset, flr->Height+flr->YOffset );
   
    // set pixels
    while(py<flr->Height){
               
        // read data byte
        c = *bptr;       
        bptr++;
       
        // apply shift
        px+=(c>>3);
        c&=7;
       
        // wrap
        while(px>=flr->Width){
            px -= flr->Width;
            py++;
        }
       
        // set pixel
        if(c&&py<flr->Height){
            set_pixel( px+flr->XOffset, py+flr->YOffset, clrndx[c] );   
            px++;
        }
    }
    save_bmp(path);
}

BOOL test4cc(char* a,char* b){
    for(int i=0;i<4;i++){
        if(*a!=*b)return FALSE;       
        a++;
        b++;
    }
    return TRUE;
}

int do_extract(char* path){
    FontHeader* fh;
    char* bpath;
    HANDLE hFont = bload(path);
       
    if(hFont!=NULL){
        // verify 4CC
        if(test4cc((char*)szFont4cc,(char*)hFont)){
           
            // prepare output path
            lstrcpy(pathbuf,path);
            bpath = get_extension(pathbuf)-1;
                                                   

            // read the file header
            fh = (FontHeader*)hFont;
           
            // process the characters
            for(int c=fh->LowIndex;c<=fh->HighIndex;c++){
                // make bmp filename
                wsprintf(bpath,szBmpTmpl,c);
                // extract the character
                extract_char(hFont,fh->LowIndex,c,pathbuf);
            }
           
            GlobalFree(hFont);   
            return EXIT_SUCCESS;

        }
        GlobalFree(hFont);
        return INVALID_FILE;

    }
    return READ_ERROR;
}


// --- COMPILE --- //

int compile_char(BYTE* optr){
    // write raw data for current bmp char at optr
    // return data size in bytes
   
    int c,t;
    FontLetterRaw* flr = (FontLetterRaw*)optr;
    optr+=sizeof(FontLetterRaw);   
   
    // set character header
    int yos = bmp_yos();
    if(yos==-1)return 0;
    flr->YOffset = yos;
    flr->XOffset = bmp_xos();
    flr->Width   = bmw-flr->XOffset;
    flr->Height  = bmh-flr->YOffset;
   
    // compile pixels
    t=0;
    for(int y=flr->YOffset;y<bmh;y++){
        for(int x=flr->XOffset;x<bmw;x++){
            c=get_pixel(x,y);
            if(c){
                *optr=(t<<3)+c;
                t=0;
                optr++;
            }else{
                t++;
                if(t==31){
                    *optr=0xF8;
                    optr++;
                    t=0;
                }
            }
        }
    }
    if(t){
        *optr=(t<<3);
        optr++;             
    }
   
    return (int)optr-(int)flr;
}


int do_compile(CHAR* path){
    HANDLE fn;
    DWORD nb;
    int len;
    BITMAPINFOHEADER* bih;
    FontHeader* fh;
    BYTE* hFont;
    char* bpath;
    DWORD* fptr;
    BYTE* optr;
    int datsize;
    int maxw = 0;
    int maxh = 0;
    int minc = 0x20;
    int maxc = 0;
    int nchar= 0;
   
    // enum char bitmaps
    lstrcpy(pathbuf,path);
    bpath = get_extension(pathbuf)-5;

    for(int i=1;i<256;i++){
        wsprintf(bpath,szBmpTmpl,i);
        if(PathFileExists(pathbuf)){       
            if(get_flen(pathbuf)<=bmp8len){
                if(i<minc)minc=i;
                if(i>maxc)maxc=i;
                load_bmp(pathbuf);
                bih = bmp_info();
                if(bih->biWidth>maxw)maxw=bih->biWidth;
                if(bih->biHeight>maxh)maxh=bih->biHeight;
            }                   
        }
    }
       
    if(!maxw*maxh*maxc)return INVALID_INPUT;
    if(maxc<minc){ minc=maxc; maxc=0x20; }
    nchar = maxc-minc+1;
   
    // allocate output buffer
    hFont = (BYTE*)GlobalAlloc(GPTR,nchar*MAX_CHAR_SIZE);
    if(!hFont)return ALLOC_FAIL;
   
    // set up pointers
    fh=(FontHeader*)hFont;
    fptr=(DWORD*)(hFont+sizeof(FontHeader));
    optr=(BYTE*)(hFont+sizeof(FontHeader)+nchar*4);
   
    // write font header
    lstrcpy((char*)hFont,szFont4cc);
    fh->LowIndex  = minc;
    fh->HighIndex = maxc;
    fh->MaxWidth  = maxw;
    fh->MaxHeight = maxh;
   
    // compile characters
    for(int c=minc;c<=maxc;c++){
        datsize = 0;
        wsprintf(bpath,szBmpTmpl,c);
        if(PathFileExists(pathbuf)){
            len = get_flen(pathbuf);
            if(len&&len<=bmp8len){
                if(!load_bmp(pathbuf)){
                    GlobalFree(hFont);
                    return READ_ERROR;
                }
                normalize_bmp();
                datsize = compile_char(optr);
            }
        }
        // write file offset
        if(datsize)*fptr=optr-hFont;
        fptr++;
        optr+=datsize;
    }
   
    // write fnt file
   
    datsize=optr-hFont;
    lstrcpy(bpath,szFntTmpl);
    fn = CreateFile(pathbuf,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
   
    if(fn==INVALID_HANDLE_VALUE){
        GlobalFree(hFont);
        return WRITE_ERROR;
    }else{
        if(WriteFile(fn,hFont,datsize,&nb,NULL)){
            CloseHandle(fn);
            GlobalFree(hFont);
            if(nb==datsize)return 0;
            return WRITE_ERROR;
        }
        CloseHandle(fn);
        GlobalFree(hFont);
        return WRITE_ERROR;
    }
}


// --- HELP --- //

int do_help(){
    MessageBox(0,szHelpText,"War2 Font Tool",0);
    return EXIT_SUCCESS;
}
// --- MAIN --- //


int main(int argc, char *argv[]){
    CHAR* e;
    if(lstrlen(argv[1])>3){
        e=get_extension(argv[1]);
        if(lstrlen(e)!=3)return INVALID_FILE;
        if(!lstrcmpi(e,f_ext))return do_extract(argv[1]);
        if(!lstrcmpi(e,b_ext))return do_compile(argv[1]);
    }else{
        return do_help();
    }
}

13) Mods & Development / Re: War2 fonts (.fnt)
« 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

Have changed this to use decimal file names so it can be compatible with iL's project.

14) General Discussion / Re: Longtime Warcraft 2 player playing again
« on: February 27, 2019, 09:59:59 PM »

Welcome back mate :)

Good to see another old player returning to the original awsome RTS.

BTW: While whirlwinds are mostly just annoying individually when you multicast a heap of them they can seriously mess up an entire base.


15) Mods & Development / Re: Nerd's Corner
« on: February 27, 2019, 09:52:21 PM »
Font .fnt format here

Pages: [1] 2 3 ... 82