War2.ru Slogan
News: New responsive forum theme available!
Click here to switch! More info here!


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.

Nerd's Corner 8139  157

Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #135 on: February 17, 2018, 02:47:47 AM »
CALCULATING  TERRAIN TILE VALUES

So I'm up to the terraforming bit of this whole map editor thing, and this is as good a place as any to document it as I go. The wc2 game background is made up of blocks of 8x8 pixel data that are constructed into 32x32 pixel 'tiles'. The tile value for each map location is stored as a 16 bit value in PUD files (MTXM section).

I use 3 letter abbreviations to denote the different terrain types as follows:

Code: [Select]
LTW - light water
DKW - dark water 
LTM - light mud(coast)
DKM - dark mud 
LTG - light grass
DKG - dark grass
TRE - trees
ROC - rocks
HWL - human wall
OWL - orc wall

Each 32x32 tile can be made up of either 1 or 2 terrain types. Tiles with only 1 terrain type I call solid tiles. Tiles with 2 terrain types I call border tiles.

NUMERICAL FORMAT

All tiles are stored as 16bit values, with the information encoded as a sequence of nibbles (4 bits). There are multiple versions of each tile which have slightly different graphics to create a more natural look to the map. For all tiles this pictorial variant is stored in the least significant nibble (bits 0-3) and these 4 bits have no other relevance to the game mechanics.

Code: [Select]
i.e.
0x0050 LTG variant 0
0x0051 LTG variant 1
0x0055 LTG variant 5
etc.

"FILLER" TILES

The light and dark mud and grass tiles have variants depicting objects - rocks plants skulls etc. numbered as follows:

Code: [Select]
LTG/DKG - 0-2 Plain Solid
LTG/DKG - 4-9 Filler Solid
LTM/DKM - 0-3 Plain Solid
LTM/DKM - 4-B Filler Solid
i.e. 0x0057 = LTG 4th filler tile (the one with the big rock)

Unused values for the variant nibble will be mapped as repeats of the other solid tiles.

SOLID TILE VALUES
Code: [Select]
0x001v - LTW
0x002v - DKW
0x003v - LTM
0x004v - DKM
0x005v - LTG
0x006v - DKG
0x007v - TRE
0x008v - ROC
0x009v - OWL (Single)
0x00Av - HWL (Single)
0x00Bv - OWL (central)
0x00Cv - HWL (central)
Where v designates the graphics variant.

SOLID WALL VARIANTS

Code: [Select]
v=0-1 Full
v=2   Damaged
v=3   Full
v=4   Destroyed
v=5-F Full

BORDER TILES

Border tiles are made up of 2 different terrain types. Not all terrain can co-exist on a border tile. Acceptable combinations are:

Code: [Select]
Value    (0) (1)
0x01Lv - LTW/DKW
0x02Lv - LTM/LTW
0x03Lv - LTM/DKM
0x04Lv - LTM/ROC
0x05Lv - LTG/LTM
0x06Lv - LTG/DKG
0x07Lv - LTG/TRE
Where v designates the graphics variant.
Where L designates the layout.

For border tiles the 2nd nibble represents the layout. Each bit in the nibble represents one quater of the tile.

Code: [Select]
  bit0 - bit1
   |      |
  bit2 - bit3

So for a grass/tree border tile like this:

Code: [Select]
TG
TT
(all trees except grass in the top right)
the bit values are

Code: [Select]
10
11

= 1101 binary

as border tile layouts dont represent solid tiles, the first value is 0001 not 0000 - which would be solid, however they are stored starting with 0 so at this point all values must have 1 subtracted from them

= 13 - 1
= 12   ( 0x0C )

so using 0x07Lv - LTG/TRE

this tile would be 0x07C0
or 0x07C1 for the other variant.

*border tiles have 2 variants each for corners and 3 variants for straight edges.

JOINED WALL TILES

Code: [Select]
0x08Lv - HWL Joined
0x09Lv - OWL Joined

The layout of joined wall tiles:

Code: [Select]
BIT  2
   3 # 1
     0

So for a 3-way join between walls left, right and below we need bits 3,1,0... so:
binary 1011 = decimal 11 (0x0B) -1 = decimal 10 (0x0A)

so OWL like this:
Code: [Select]
###
 #
= 0x09A0

*corners/joins have 1 variant straight joined walls (above&below or left&right) have 2 variants.

Death Knight Posts: 2977 Karma: +69/-2 retired, be in music section *********

easycompany

  • Death Knight
  • *********
  • Posts: 2977
  • retired, be in music section
    • View Profile
Re: Nerd's Corner
« Reply #136 on: February 18, 2018, 03:35:19 PM »
opps having to much fun...but i think i have may located units.

found some old dos stuff this is some kinda mod...not played it yet anyone knew these people?

and i believe units are here as i had every icon upgrading to a town hall...which is stats not a grp change.

and yes peons will go to it:P

well i can successfully hop out a foot archer or balista on paladin spot ..and put all units in the game and it has thier prices icon but it will not allow it to be made as some other part is stopping it....

what i think its doing is sending me back to the barracks to call it a orc barracks before a grunt can be made value, idk i hope not it cant be that dam difficult.

keep up with the good work lamby.
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #137 on: February 19, 2018, 03:13:46 PM »
Almost ready for an alpha test of the basic editor. Have the terrain / terraforming / unit placement working reasonably well. Everything works at any zoom, so you can even view a large map full screen and still edit it. Can place half terrain tiles - like thin rivers etc.  :fro:

Havn't done a mini-map yet and it really doesn't need one - you just zoom in/out with the mouse wheel at any time. Will probably add one at some point I guess but it's not at the top of the list.

Still have a half-page TO DO list of things to tweak. Hopefully I'll get those done tomorrow then I'll need some testers (@easycompany and @tupac spring to mind :) ).

Still haven't done any unit editing - starting conditions ... etc. etc. although all that + all the tricks can be added once the basic GUI is nice and tight....  At the moment it does pretty much everything my old editor can't do and none of the things that it can lol.

 :critter:






Death Knight Posts: 2516 Karma: +79/-2 *********

tupac

  • Death Knight
  • *********
  • *
  • Posts: 2516
    • View Profile
Re: Nerd's Corner
« Reply #138 on: February 19, 2018, 10:12:22 PM »
Almost ready for an alpha test of the basic editor. Have the terrain / terraforming / unit placement working reasonably well. Everything works at any zoom, so you can even view a large map full screen and still edit it. Can place half terrain tiles - like thin rivers etc.  :fro:

Havn't done a mini-map yet and it really doesn't need one - you just zoom in/out with the mouse wheel at any time. Will probably add one at some point I guess but it's not at the top of the list.

Still have a half-page TO DO list of things to tweak. Hopefully I'll get those done tomorrow then I'll need some testers (@easycompany and @tupac spring to mind :) ).

Still haven't done any unit editing - starting conditions ... etc. etc. although all that + all the tricks can be added once the basic GUI is nice and tight....  At the moment it does pretty much everything my old editor can't do and none of the things that it can lol.

 :critter:







I'll test the shit out of it. Spawn the beta ;)
Death Knight Posts: 2977 Karma: +69/-2 retired, be in music section *********

easycompany

  • Death Knight
  • *********
  • Posts: 2977
  • retired, be in music section
    • View Profile
Re: Nerd's Corner
« Reply #139 on: February 20, 2018, 02:49:27 AM »
if u didt get that szawg i dont know how else to tell ya
Berserker Posts: 720 Karma: +36/-0 *****

Szwagier

  • Berserker
  • *****
  • Posts: 720
    • View Profile
Re: Nerd's Corner
« Reply #140 on: February 20, 2018, 11:16:44 AM »
if u didt get that szawg i dont know how else to tell ya
Maybe im blind, but where did u change missing objective  build 6 farms not 4??
Death Knight Posts: 2977 Karma: +69/-2 retired, be in music section *********

easycompany

  • Death Knight
  • *********
  • Posts: 2977
  • retired, be in music section
    • View Profile
Re: Nerd's Corner
« Reply #141 on: February 20, 2018, 11:55:26 AM »
naw i deleted dam it ..someday im gonna drink beer...we got a bigger mission...making units....well ill make it my goal,

ask tupac he messed with them at one time maybe in his sticky


---maybe a peon seeting in pud would allow it to build no idea.. just for lookage for now

lots of values if u  want to hex ill put u in the spot, so we can find out what everything is.
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #142 on: March 25, 2018, 11:46:24 PM »
ALLIED COLORS ON MINI-MAP


This one was another idea from Nedro, it makes all allies blue and all enemies red on the mini-map.

You can toggle it on/off by pushing F2.



Death Knight Posts: 2516 Karma: +79/-2 *********

tupac

  • Death Knight
  • *********
  • *
  • Posts: 2516
    • View Profile
Re: Nerd's Corner
« Reply #143 on: March 26, 2018, 07:43:34 AM »
ALLIED COLORS ON MINI-MAP


This one was another idea from Nedro, it makes all allies blue and all enemies red on the mini-map.

You can toggle it on/off by pushing F2.





I like that!!!
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #144 on: March 26, 2018, 09:38:32 AM »
I like that!!!

Cool. I assume it worked for you?

There's one case with windows 8 that I know of where it won't work. Probably some stupid windows security thing that is stopping it writing to the wc2 process. It works on XP and 7 so far.
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #145 on: August 21, 2018, 02:34:04 AM »
@tupac @iL

No-CD crack ....

War2noCDloader.exe not needed


--------------
No-CD Patch

File offset 0x2877F
old: E8:2C:06:00:00
new: 90:90:90:90:90
(5 bytes)

File offset 0x2878D
old: 75
new: 74
(1 byte)
-----------------


My first attempt worked but flagged the game as a spawned version so half the stuff was knobbled.
This version seems to work properly.

>>>> Please Test <<<<


----  EDIT ----

Been using it for a couple of weeks now, works for me :)

Oh. Tupac has pointed out that this does not work for single player campaigns - only for multiplayer. I will have to look into that when I get some spare time  :-\

Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #146 on: September 16, 2018, 05:00:03 AM »
OK I have finally done a little bit more on PUDPIC.

You can get the new version HERE.


I wrote an ASM image resize/blend procedure so it can produce a pic of the size you want. Also has a jpeg save option.

i.e.

    PUDPIC /s:500  MyMap.pud

will make a 500x500 32 bit blended bitmap

Without the /s switch it will default to producing a full size 8bit bitmap with the original game palette (the current behavior).

   PUDPIC /j:80 ThisMap.pud

will save the full size 8 bit image as a quality 80 jpeg

   PUDPIC /s:1024 /j:90 Maposaurus.pud

will resize to 1024x1024 and save as quality 90 .jpg file

 ^- THESE SETTINGS SEEM TO BE PRETTY GOOD FOR A GENERAL PURPOSE POST ON FORUM/DISCORD ETC IMAGE
( give you around a 300KB file that looks ok if you dont zoom in too close)




... also if you want you can just rename the exe file to include the size/quality.

i.e.  if you rename it to "PUDPICs500.exe" it will automatically make a 500x500 bitmap any time you drop a file on it.

or if you rename it to "PUDPICs1024j90.exe" it will automatically make a 1024x1024 quality 90 jpeg any time you drop a file on it.

You can even have multiple copies of the exe file with different sizes you use and just drop your pud file on the one you want.

Like this:




I *think* the command line switches will work in a UNICODE environment - but please let me know if you have any problems.

Have fun  :critter:


Grunt Posts: 72 Karma: +7/-0 ***

Cel

  • Grunt
  • ***
  • Posts: 72
    • View Profile
*

Cel

Re: Nerd's Corner
« Reply #147 on: October 09, 2018, 09:26:22 AM »
@Lambchops May we have the sources of that nice little program of yours?  (The PUDPIC program) ^-^
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #148 on: October 10, 2018, 08:04:20 PM »
@Lambchops May we have the sources of that nice little program of yours?  (The PUDPIC program) ^-^


Yeah I dont mind sharing, but it's a pretty tangled mess of code ... 2 ASM dll projects and C++ project that uses the dlls

The C++ is from a half written pud editor that still has lots of stuff not used by the pudpic program.

Its about 130 source files in all. A lot of that is just all the WC2 graphics repackaged into LambRES.dll


>> What do you want to do with it?


Probably your easiest path to drawing WC2 stuff is to call the functions from the 2 dll files:

Code: [Select]

// This stuff in .h file  <-----

extern "C" { 
    typedef struct pudsect {
        DWORD Reserved;
        DWORD name;
        DWORD size;
        LPVOID data;
    }PUDSECT;
}

extern "C" { 
    typedef struct hmibmp {
        BITMAPFILEHEADER* pFile;
        BITMAPINFOHEADER* pInfo;
        RGBQUAD*          pPal;
        BYTE*             pBits;
        int               width;
        int               height;
        int               bpp;
        int               linew;
        int               usage;
        int               size;
    }HMIBMP;
}


// LambRES.dll
extern "C" typedef CHAR*   (__stdcall *rfngetname )(int utype);
extern "C" typedef LPVOID  (__stdcall *rfntileset )(int ntileset);
extern "C" typedef LPVOID  (__stdcall *rfngetpal  )(int npalette);
extern "C" typedef LPVOID  (__stdcall *rfngetgrp  )();


//PUDfile.inc
extern "C" typedef LPVOID  (__stdcall *pfnpudload )(CHAR* path);
extern "C" typedef int     (__stdcall *pfnpudsave )(LPVOID hpud,CHAR* path);

//PUDpud.inc
extern "C" typedef int     (__stdcall *pfnsectcnt )(LPVOID hpud);
extern "C" typedef void    (__stdcall *pfndestroy )(LPVOID hpud);
extern "C" typedef LPVOID  (__stdcall *pfndelsect )(LPVOID hpud,LPVOID hsect);
extern "C" typedef PUDSECT*(__stdcall *pfnfindsect)(LPVOID hpud,DWORD sectname);
extern "C" typedef int     (__stdcall *pfnupdsect )(LPVOID hpud,LPVOID hsect,LPVOID lpnew,int nbytes);
extern "C" typedef PUDSECT*(__stdcall *pfngetsect )(LPVOID hpud,int nsect);
extern "C" typedef int     (__stdcall *pfnsectndx )(LPVOID hpud,DWORD sectname);
extern "C" typedef LPVOID  (__stdcall *pfnsectset )(LPVOID hpud,LPVOID hsect,int nsect);
extern "C" typedef BOOL    (__stdcall *pfnsectcre )(LPVOID hpud,DWORD sectname,LPVOID lpnew,int nbytes);
extern "C" typedef LPVOID  (__stdcall *pfnrealloc )(PUDSECT* hSect,int nbytes);

//PUDunit.inc
extern "C" typedef int     (__stdcall *pfnunitsize)(int utype);
extern "C" typedef int     (__stdcall *pfnuniticof)(int utype);
extern "C" typedef int     (__stdcall *pfnlistget )(int list,int ndx);
extern "C" typedef int     (__stdcall *pfnlistnext)(int list,int utype);
extern "C" typedef int     (__stdcall *pfnlistprev)(int list,int utype);
extern "C" typedef LPVOID  (__stdcall *pfnlistname)(int list);

//PUDtile.inc
extern "C" typedef void    (__stdcall *pfnrndrmap )(LPVOID hbmp,LPVOID mtxm,int mapw);
extern "C" typedef void    (__stdcall *pfnrndrtile)(LPVOID hbmp,int tile,int x,int y);
extern "C" typedef LPVOID  (__stdcall *pfngettile )(int tile);
extern "C" typedef void    (__stdcall *pfntileset )(LPVOID tileset);
extern "C" typedef void    (__stdcall *pfnblack   )(HDC dc,int x,int y,int w,int h);

//hmibmp.inc
extern "C" typedef HMIBMP* (__stdcall *pfnmakebmp )(int w,int h,int bpp);
extern "C" typedef void    (__stdcall *pfnfreebmp )(HMIBMP* bmp);
extern "C" typedef int     (__stdcall *pfnzerobmp )(HMIBMP* bmp);
extern "C" typedef void    (__stdcall *pfnsavebmp )(CHAR* path,HMIBMP* bmp);
extern "C" typedef void    (__stdcall *pfnsavejpg )(CHAR* path,HMIBMP* bmp,int quality);
extern "C" typedef void    (__stdcall *pfnperfbmp )(HMIBMP* bmp);
extern "C" typedef void    (__stdcall *pfncopyimg )(HMIBMP* src,int scrx,int srcy,int srcw,int scrh,HMIBMP* dst,int dstx,int dsty,int transp);
extern "C" typedef int     (__stdcall *pfncopyfull)(HMIBMP* dstbmp,HMIBMP* srcbmp,int transp);
extern "C" typedef void    (__stdcall *pfndispimg )(HDC destDC,int x,int y,int w,int h,HMIBMP* bmp,int dx,int dy,int dw,int dh);
extern "C" typedef void    (__stdcall *pfnsetpal  )(HMIBMP* bmp,LPVOID palette);
extern "C" typedef void    (__stdcall *pfndrawrect)(HMIBMP* bmp,int x,int y,int w,int h,int color);
extern "C" typedef HMIBMP* (__stdcall *pfnsizebmp )(HMIBMP* bmp,int w,int h);

//PUDgrp.inc
extern "C" typedef LPVOID  (__stdcall *pfngrpinit )(LPVOID grplubase);
extern "C" typedef void    (__stdcall *pfndrawgrp )(int grp,int nframe,LPVOID daddr,int dwidth,int owner,int centre,int mirror);
extern "C" typedef void    (__stdcall *pfndrawbtn )(LPVOID bmp, int xpos, int ypos, int icon, int state);




extern rfngetname      RESgetName;
extern rfntileset      RESgetTileset;
extern rfngetpal       RESgetPalette;
extern rfngetgrp       RESgetGrp;

extern pfnpudload      PUDload;
extern pfnpudsave      PUDsave;

extern pfnsectcnt      PUDsection_count;
extern pfndestroy      PUDdestroy;
extern pfndelsect      PUDdelete_section;
extern pfnfindsect     PUDfind_section;
extern pfnupdsect      PUDupdate_section;
extern pfngetsect      PUDget_section;
extern pfnsectndx      PUDsection_index;
extern pfnsectset      PUDsection_set_index;
extern pfnsectcre      PUDcreate_section;
extern pfnrealloc      PUDsection_realloc;

extern pfnunitsize     PUDunitSize;
extern pfnuniticof     PUDunitIconFrame;
extern pfnlistget      PUDlistGet;
extern pfnlistnext     PUDlistNext;
extern pfnlistprev     PUDlistPrev;
extern pfnlistname     PUDlistName;

extern pfnrndrmap      PUDrenderMap;
extern pfnrndrtile     PUDrenderTile;
extern pfngettile      PUDgetTile;
extern pfntileset      PUDtileset;
extern pfnblack        PUDblack;

extern pfnmakebmp      make_bitmap;
extern pfnfreebmp      free_bitmap;
extern pfnzerobmp      zero_bitmap;
extern pfnsavebmp      save_bitmap;
extern pfnsavejpg      save_jpeg;
extern pfnperfbmp      perforate_bitmap;
extern pfncopyimg      copy_image;
extern pfncopyfull     copy_full_image;
extern pfndispimg      display_image;
extern pfnsetpal       set_palette;
extern pfndrawrect     draw_rect;
extern pfnsizebmp      size_bitmap;

extern pfngrpinit      GRPinit;
extern pfndrawgrp      GRPdraw;
extern pfndrawbtn      GRPdrawButton;


///////////////////////////////////////////////////////////////////////////////

// This stuff in .cpp file   <-------



HMODULE hResDll  = LoadLibraryA("LambRES");
HMODULE hLambDll = LoadLibraryA("LambWC2");


rfngetpal   RESgetPalette       = (rfngetpal  )GetProcAddress(hResDll , "RESgetPalette"       );
rfngetgrp   RESgetGrp           = (rfngetgrp  )GetProcAddress(hResDll , "RESgetGrp"           );
rfngetname  RESgetName          = (rfngetname )GetProcAddress(hResDll , "RESgetName"          );
rfntileset  RESgetTileset       = (rfntileset )GetProcAddress(hResDll , "RESgetTileset"       );


pfnpudload  PUDload             = (pfnpudload )GetProcAddress(hLambDll, "PUDload"             );
pfnpudsave  PUDsave             = (pfnpudsave )GetProcAddress(hLambDll, "PUDsave"             );

pfnsectcnt  PUDsection_count    = (pfnsectcnt )GetProcAddress(hLambDll, "PUDsection_count"    );
pfndestroy  PUDdestroy          = (pfndestroy )GetProcAddress(hLambDll, "PUDdestroy"          );
pfndelsect  PUDdelete_section   = (pfndelsect )GetProcAddress(hLambDll, "PUDdelete_section"   );
pfnfindsect PUDfind_section     = (pfnfindsect)GetProcAddress(hLambDll, "PUDfind_section"     );
pfnupdsect  PUDupdate_section   = (pfnupdsect )GetProcAddress(hLambDll, "PUDupdate_section"   );
pfngetsect  PUDget_section      = (pfngetsect )GetProcAddress(hLambDll, "PUDget_section"      );
pfnsectndx  PUDsection_index    = (pfnsectndx )GetProcAddress(hLambDll, "PUDsection_index"    );
pfnsectset  PUDsection_set_index= (pfnsectset )GetProcAddress(hLambDll, "PUDsection_set_index");
pfnsectcre  PUDcreate_section   = (pfnsectcre )GetProcAddress(hLambDll, "PUDcreate_section"   );
pfnrealloc  PUDsection_realloc  = (pfnrealloc )GetProcAddress(hLambDll, "PUDsection_realloc"   );


pfnunitsize PUDunitSize         = (pfnunitsize)GetProcAddress(hLambDll, "PUDunitSize"         );
pfnuniticof PUDunitIconFrame    = (pfnuniticof)GetProcAddress(hLambDll, "PUDunitIconFrame"    );
pfnlistget  PUDlistGet          = (pfnlistget )GetProcAddress(hLambDll, "PUDlistGet"          );
pfnlistnext PUDlistNext         = (pfnlistnext)GetProcAddress(hLambDll, "PUDlistNext"         );
pfnlistprev PUDlistPrev         = (pfnlistprev)GetProcAddress(hLambDll, "PUDlistPrev"         );
pfnlistname PUDlistName         = (pfnlistname)GetProcAddress(hLambDll, "PUDlistName"         );

pfnrndrmap  PUDrenderMap        = (pfnrndrmap )GetProcAddress(hLambDll, "PUDrenderMap"        );
pfnrndrtile PUDrenderTile       = (pfnrndrtile)GetProcAddress(hLambDll, "PUDrenderTile"       );
pfngettile  PUDgetTile          = (pfngettile )GetProcAddress(hLambDll, "PUDgetTile"          );
pfntileset  PUDtileset          = (pfntileset )GetProcAddress(hLambDll, "PUDtileset"          );
pfnblack    PUDblack            = (pfnblack   )GetProcAddress(hLambDll, "PUDblack"            );

pfnmakebmp  make_bitmap         = (pfnmakebmp )GetProcAddress(hLambDll, "make_bitmap"         );
pfnfreebmp  free_bitmap         = (pfnfreebmp )GetProcAddress(hLambDll, "free_bitmap"         );
pfnzerobmp  zero_bitmap         = (pfnzerobmp )GetProcAddress(hLambDll, "zero_bitmap"         );
pfnsavebmp  save_bitmap         = (pfnsavebmp )GetProcAddress(hLambDll, "save_bitmap"         );
pfnsavejpg  save_jpeg           = (pfnsavejpg )GetProcAddress(hLambDll, "save_jpeg"           );
pfnsizebmp  size_bitmap         = (pfnsizebmp )GetProcAddress(hLambDll, "size_bitmap"         );
pfnperfbmp  perforate_bitmap    = (pfnperfbmp )GetProcAddress(hLambDll, "perforate_bitmap"    );
pfncopyimg  copy_image          = (pfncopyimg )GetProcAddress(hLambDll, "copy_image"          );
pfncopyfull copy_full_image     = (pfncopyfull)GetProcAddress(hLambDll, "copy_full_image"     );
pfndispimg  display_image       = (pfndispimg )GetProcAddress(hLambDll, "display_td_image"    );
pfnsetpal   set_palette         = (pfnsetpal  )GetProcAddress(hLambDll, "set_palette"         );
pfndrawrect draw_rect           = (pfndrawrect)GetProcAddress(hLambDll, "draw_rect"           );

pfngrpinit  GRPinit             = (pfngrpinit )GetProcAddress(hLambDll, "GRPinit"             );
pfndrawgrp  GRPdraw             = (pfndrawgrp )GetProcAddress(hLambDll, "GRPdraw"             );
pfndrawbtn  GRPdrawButton       = (pfndrawbtn )GetProcAddress(hLambDll, "GRPdrawButton"       );




The pud load/save routines and format are from HERE



Make sure you first do:

Code: [Select]
PUDtileset(RESgetTileset(0));
GRPinit(RESgetGrp());


This sets some internal pointers, otherwise you will get GP faults if you try to use stuff.


I have to go out right now, I can give you more info later when I have more time.
Sappers Posts: 975 Karma: +62/-0 ******

Lambchops

  • Sappers
  • ******
  • *
  • Posts: 975
    • View Profile
Re: Nerd's Corner
« Reply #149 on: October 11, 2018, 05:59:36 AM »
@Cel

Ok so the HMIBMP structure is what I use internally to handle bitmaps.

Its just a conveniant way to handle device independent bitmaps without having to get bogged down with a lot of the unnecessary/unused stuff, although you can still get to the underlying windows structures if you need to.


It has these members:

Code: [Select]
pFile        pointer to the BITMAPFILEHEADER struct
pInfo        pointer to the BITMAPINFOHEADER struct
pPal         pointer to the palette (if the bitmap has one)
pBits        pointer to the pixmap (actual pixel data - depends on the format)
width        duh
height       duh
bpp          bits per pixel (this will be 8 for most WC2 things)
linew        internal size in bytes for one line of pixels
usage        (pixel color values or palette entries)
size         total size of all structures


so if you do:

Code: [Select]
HMIBMP* MyBmp = make_bitmap(300,200,8);

You will get a handle to a 300x200 8-bit bitmap. All the underlying windows structures are created automatically.

when finished use:

Code: [Select]
free_bitmap(MyBmp);

to deallocate all the memory.

*** These bitmap functions are not complete for every format, I have just added to them whenever I needed to do something .... most of it works for 8-bit bitmaps - because that's what I mostly play with for WC2 stuff. Some things work for 32 or 24 bit bitmaps. Pretty much none of it will work for 4 or 16 bit bmps (but who cares about that crap lol). ***

For WC2 stuff you will just want 8-bit bmps, the only thing you would use any other format for is the size_bitmap() func which will resize an 8-bit bmp and blend the colors then return a 32-bit bitmap of the requested size.

Code: [Select]
LPVOID MyPud = PUDload("c:\\someMap.pud");

Will return a handle to a linked list of PUDSECT structures, which contain pointers to the actual data for each section.

You can get a pointer to the data for a given section like this:

Code: [Select]
BYTE* sectionData(LPVOID hPud, DWORD sname){
    PUDSECT* sptr = PUDfind_section(hPud,sname);
    if (sptr!=NULL) return sptr->data;
    return NULL;
}

NOTE: the section name is a DWORD not a string .... all pud section names are 4 bytes, so you want constants like this:


Code: [Select]
#define sTYPE 0x45505954 // "TYPE"
#define sVER_ 0x20524556 // "VER "
#define sDESC 0x43534544 // "DESC"
#define sOWNR 0x524E574F // "OWNR"
#define sERA_ 0x20415245 // "ERA "
#define sERAX 0x54415245 // "ERAX"
#define sDIM_ 0x204D4944 // "DIM "
#define sUDTA 0x41544455 // "UDTA"
#define sUNIT 0x54494E55 // "UNIT"
#define sUGRD 0x44524755 // "UGRD"

#define sSIDE 0x45444953 // "SIDE"
#define sSGLD 0x444C4753 // "SGLD"
#define sSLBR 0x52424C53 // "SLBR"
#define sSOIL 0x4C494F53 // "SOIL"
#define sAIPL 0x4C504941 // "AIPL"

#define sMTXM 0x4D58544D // "MTXM"
#define sSQM_ 0x204D5153 // "SQM "
#define sOILM 0x4D4C494F // "OILM"
#define sREGM 0x4D474552 // "REGM"

#define sSIGN 0x4E474953 // "SIGN"
#define sALOW 0x574F4C41 // "ALOW"


so you can get the map size of a pud file from the "DIM " section like:

Code: [Select]
int getPudDim(LPVOID hpud){
    WORD* pdim = (WORD*) sectionData(hpud,sDIM_)
    if (pdim) return (int) *pdim;
    return 0;
}

If you get a "tile" value from the MTXM section you can draw that square of terrain on the bitmap at (x,y) with:

Code: [Select]
PUDrenderTile(MyBmp, tileValue , int x, int y);

or

Code: [Select]
PUDrenderMap(MyBmp, MTXM_section, size);

will do the terrain for the whole map - but make sure the bitmap is the right size or you will crash.


The different terrain styles can be selected like this:

Code: [Select]
#define FOREST     0
#define WINTER     1
#define WASTELAND  2
#define SWAMP      3

PUDtileset(RESgetTileset( WINTER ));

you will also need to set the appropriate palette in your bitmap or the colors will come out wrong.

Code: [Select]
set_palette(MyBmp , RESgetPalette( WINTER ));


so you should be able to make a bmp file of just the terrain for a PUD file with something like:

Code: [Select]
//     # UNTESTED # - probably has errors/typos

#include <windows.h>
//#include HEADER FILE WITH IMPORT DEFS FROM PREVIOUS POST AND CONSTANT DEFS (ABOVE)



CHAR* pudpath = "myMap.pud";
CHAR* bmppath = "this.bmp";


// load the pud file
LPVOID hPud = PUDload(pudpath);


BYTE* sectionData(LPVOID hpud, DWORD sname){
    PUDSECT* sptr = PUDfind_section(hpud,sname);
    if (sptr!=NULL) return (BYTE*)sptr->data;
    return NULL;
}

int getPudSize(LPVOID hpud){
    WORD* pdim = (WORD*) sectionData(hpud,sDIM_);
    if(pdim) return (int) *pdim;
    return 0;
}

int getTerrainType(LPVOID hpud){
    WORD* pter = (WORD*) sectionData(hpud,sERA_);
    if(pter) return (int) *pter;
    return 0;
}


// get some info from the pud
int   mapsize = getPudSize(hPud);
int   terrain = getTerrainType(hPud);


// make a bitmap in memory (tiles are 32x32 pixels)
HMIBMP* hbm = make_bitmap(mapsize*32,mapsize*32,8);

// use the tiles for the map terrain type
PUDtileset(RESgetTileset(terrain));

// don't forget this if you are using GRPs, only needs to be done once to initialize
// can't remember if it needs to be done for only the terrain, but it cant hurt lol
GRPinit(RESgetGrp());

//paste all the tile graphics for the pud onto the bitmap
PUDrenderMap( hbm, sectionData(hpud,sMTXM) , mapsize);


// ensure the bmp file has the correct palette for the terrain type
set_palette(hbm , RESgetPalette( terrain ));

// save the bitmap to a file
save_bitmap(bmppath,hbm);

// dispose of the bitmap
free_bitmap(hbm);

// dispose of the pud structure
PUDdestroy(hPud);


Obviously you will also need the two dlls from PUDPIC, #define statements for used constants, and the function import stuff and structure defs from the previous post.

Play with that stuff and let me know how you go ....      HF :)




p.s. also if you want you can display your bitmap (or part of it) on a Windows device context with:

Code: [Select]

display_image( dc, windowX, windowY, displayWidth, displayHeight, hbm, bmX, bmY, bmW, bmH   );


if you pass 0 for the width and height they will default to the bitmap width and height, so:
Code: [Select]
display_image(dc,0,0,0,0,hbm,0,0,0,0);
will just display the bitmap on the window without any resizing.

                                                                                               :critter: