The page is in a sense continuation of the previous ANGV Undergroud Page. This one is however focused on internals of the release version of Austerlitz: Napoleon's Greatest Victory game created by Breakaway Games company.
It is fun in itself afterall
Last Updated: Saturday, 16th of September 2002
This page is still in statu nascendi.
Having any remarks, questions, problems or insults you can contact me here: email@example.com
Saturday, 16th of September 2002
Added information about JumpMap feature. Updated Universal Patch includes options allowing proper working of jump maps (both hand-made and simplified engine-drawn) in custom campaigns. Took me longer then expected - bottomline is: never trust a programmer - when he estimates something will take him say two days then all you can (usually) count on is that it will take no more then about twenty days :).
Next I plan to finish work promised for Peninsula Mod. It likely will take me more time then expected (:-) so next update of the page will be rather not soon. There is couple of possible improvements I'd like to make available in custom maps (for example making available more occupable flags/buildings, maybe also with ability to adjust their defensive morale bonus). Another thing I'm tempted to try is attempt to modify parts of battlefield simulation mechanics. The thing which could go over the top first is forcing routed units to loose stragglers/prisoners when pushed to move. Wouldn't be easy (don't have all parts of the puzzle right now) but what's the satisfaction if it would work! :-)
Friday, 6th of September 2002
Opening new page. Currently you can find on the page so-called Universal Patch, which offers a couple of options unavailable in original ANGV. Most important is, I think, that it tries to fix the problem with FOG initialisation and thus allows loading of custom campaign's maps without the crash. Beside the patch you may find there some info about FOG effect, color maps and in-game daylight conditions.
back to top of page
back to top of page
Sorry, I'm not in the mood to explain it now. Maybe next time ;-).
The name is certainly exaggerated. Anyway technique used is much more flexible then the methods I used previously (for the 1st Edition of the page :). So much that (I believe) it deserves some special name :). For these curious here is how it is supposed to work. First the seemingly normal patch procedure must be done. This time however patch program does not modify the code of ANGV program on file. Its task is to assure that once ANGV program is started it will first try to load special DLL library (it is named JPIEXAE.DLL in that case. A stands for Austerlitz; E for English version; EX means EXtension; JPI is just a prefix :). That DLL should be located in ANGV main directory. Once loaded DLL replaces the original WinMain procedure (program entry point) by its own version. That version calls of course the original WinMain but that call is bracketed by calls to two other procedures Init and Exit. First one is responsible for doing all the real program patching (note that it is done in-memory only - EXE file is not modified at the moment); second call is for doing any needed clean-up. This way is more flexible because I can now do more then just patch a couple of bytes. In theory it is now (relatively) easy to extend the original ANGV executable by pieces of code (written in C not assembelr!) contained in the DLL. It is also more convenient because after initial patch all what is needed to update the patch (correct bugs or add new functionality) is replacing the extension DLL by its new version.
Patch installation is to be done by hand. ZIP file contains two main files: UniPatch.exe and JPIEXAE.DLL. Extract them to game's main folder. Now is good time to backup your Austerlitz.EXE file. Next run UNIPATCH program (from Explorer window or DOS prompt) - be sure to do it from ANGV main folder. This is Win32 console program. It should do some sanity checks (including verifying ANGV executable CRC), make its own backup of original EXE, next do its main task (assuring that ANGV will load DLL at startup) and print a couple of diagnostic messages. Note that patched ANGV should be 8KB larger then original file. That's it - you do not need to do anything with DLL except assuring that it is present in ANGV folder. Note that if ANGV will for any reason fail to load extension DLL it should silently continue to load - in that case of course it will behave like original, non-patched version. Patch functionality is controlled by couple of home-invented properties. Some of them (global) are looked for in [extension] section of the Austerlitz.ini file, others (local to the given campaign) in the same section of the campaign's CONFIGnn.CFG file. Short description of available options is provided at the end of this section. Note that ZIP file contains two files which maybe be helpful as reference points Austerlitz.ini.example and config44.cfg.example.
Words of caution are in place here. If you decide to try it out
you do it at your own risk. Read carefully the formal disclaimer above and
remember that I'm not responsible for any problems or disasters you may
experience. I can also not guarantee that the particular options will work
as described nor even that the patch will work at all for you. I did my
tests on Win95 machine (still... :). There is small but real possibility
that - because of the technique used - it will not work at all on newer
platforms. And of course there is host of other reasons why the patch may
malfunction in your particular configuration.
List of available options
Here is the Universal Patch version 1.01:
If you already patched ANGV then all you need to do is replace JPIEXAE.DLL in game's main folder by new version (well, if not counting setting values for new properties).
New properties available in version 1.01 (default values used when they apply):
As already noticed by some modders there are problems with MultiCampaign in the ANGV release. Due to apparent bug in ANGV code the game is virtually guaranteed to crash when one tries to use its MultiCampaign feature. It is the case even when one prepares the CONFIG file such that it refers to original Austerlitz campaign MAPDATA assets. In fact it is the same problem which I encoutered some time ago during my experiments with ANGV Demo (you can read about it on the WaterlooAtANGV.html page. Particularly see the text under heading "First Blood - MultiCampaign is not easy").
On the page mentioned above I suggested that the problem has something to do with the initialisation of the FOG data. In that time I made a quick fix and skip over the issue. I suspected that the strange lighting conditions visible in the custom campaign maps may be a side effect of that dirty patch. It turned out however that it is not the case - the night-like conditions are the normal "feature" of the custom campaign maps (read more about it - and how to make things looking a bit better - in the topic below).
What is really wrong with the FOG initialisation? For Austerlitz campaign during the MAPDATA loading preparation phase one special procedure is called. It sets a couple of FOG related variables (FogStart, FogEnd variables amongst other) to the proper values. That procedure however is not called for the custom campaigns. This means that the related variables are left uninited which next leads quickly to the DIVIDE BY ZERO exception. In theory it should not be a problem when the FOG file fails to load as in that case a flag variable is set to prevent accessing of the FOG related code. Unfortunately one piece of code is not properly guarded by that flag. As a result no matter if one prepares fog file data or not the exception and program crash seems to be unavoidable.
Any solution? The ultimate one is of course the BAG patch. For the moment you may consider using my "Universal Patch" (see section above). It tries to fix the problems with the FOG code described above. By default it calls the forgotten procedure which inits the all-important variables and thus allows using the FOG feature in the custom campaigns. If you desire you can also explicitly disable the FOG mechanics for custom campaigns. In that case FOG related code will NOT be called after initialisation which should be another way to cure current vulnerability. To disable the FOG you should set the SwitchFogOff=1 property(default is 0 of course) in the [Extension] section of your campaign's CONFIGnn.CFG file. For more details see above and/or consult the example CONFIG file enclosed in the patch ZIP package.
On the previous
edition of underground page I described a few facts and guesses about
the FOG feature in general. Most of them I still consider to be correct.
At least one thing however turned out to be more complicated then I
expected. I suggested that the meaning of the single byte in the FOG file
is very simple: 0 - no fog in square; 255 (FFh) - highest fog density. It
is not so simple unfortunately. Here is how I think currently the FOG
mechanics is working (of course that description can be still incomplete
or plain wrong). The FOG display routine seems to except FOG intensity
values in the range 0-10h. The initial intensity values for the squares
are defined in the fog file but as all te players know FOG intensity is
not constant - in the given square it gradually decreases until it vanish
completely. At the initialisation decreasing time interval is calculated:
What about preparing FOG effect for the custom campaign's map? The FOG file can be edited using any HEX editor. Creating this way FOG file adapted to the custom map is time-consuming but not impossible task. In future it seems to be possible to create little program which would generate FOG data automatically based on the Elevation (more fog in the valleys) and Terrain (more fog nearby the water - like streams and marsh terrain) files prepared previously for the given map (plus a couple of params). Of course the ultimate solution would be full-fledged map editor with the ability (amongst other) to edit visually the fog layer. But that seems to be rather the story of the far future...
In the paragraphs above I mentioned FogStart
and FogEnd variables. Unfortunately their values
are hardcoded into the game engine. However once you apply the "Universal
Patch" you will be able to specify them both for the custom campaigns as
well as for the Austerlitz one. For the Austerlitz campaign (Campaign=2) you should set that properties in the
[Extension] section of the AUSTERLITZ.INI file. For custom campaigns the right
place is the same section but located in the corresponding CONFIGnn.CFG file. The time values for both variables
should be provided in the so-called military format - four digits without
separator (otherwise they will be ignored and defaults will be used). Here
is how it may look in the CONFIG file:
back to top of page
What is color map? Well, it seems to be one of these things which
everybody see and enjoy but nobody notice - until it is missed. Once you
apply the Universal Patch or in other way manage
to load the map through MultiCampaign mechanism
you will immediately notice its missing and likely start to appreciate the
very feature. The fact is that all custom campaign's maps are displayed
using night daylight conditions (hmm... sounds like oxymoron?:) with no
single sunbeam touching the slopes of hills - monotonous dark green colour
everywhere. It is not only a bit depressing but also makes virtually
impossible feeling of the elevation differences without setting GRID
option ON. With GRID ON battlefield looks much better - at least it should
not hamper game playability.
So how really ANGV uses its 24 color maps? It is somewhat fancy but
lets try to catch it. The engine checks which color map should be used
every minute of the game time. The procedure called for that purpose uses
two variables: DayStart, DayEnd and the current game time CurrentTime. First the DayStart is decremented by two hours and DayEnd incremented by the same interval. It is
apparently done to take into account dawn and dusk conditions so lets call
such modified variables DawnStart and DuskEnd. Then if...
What will happen if the color map prepared for Waterloo or Austerlitz
battlefield will be applied to the custom campaign's map with different
topography and (usually) different dimensions? Effect is easy to predict.
The stains of light and dark will have no relation to the actual
topography. That may look somewhat odd and misleading. Certainly it is
rather matter of taste if this is more disturbing then monotonous
darkness. Nevertheless BAG apparently decided that darkness is better and
by design disabled loading of color map for custom campaigns. In that case
the color of the square should be determined by the contents of the Graphics\GroundColor.raw file. That is only the theory -
because of the apparent bug instead of the value defined in aforesaid file
(almost) always the value of RGB=(0,0,0) is used. Lets defer the
discussion about GroundColor mechanism details (including its file format
and bug fix) to the later paragraph.
What is the format of the color map files? Like fog file they are binary files; and like may other MAPDATA related files color map file is expected to be two dimentional matrix of values. Dimentions of the matrix are (of course) to be the same as dims of the given custom map and each value corresponds to the single map square. What is unique for color maps the single value is in that case three bytes long. That value is (you guessed :-)) just the color specifid in device independent RGB format (Red comes first in the file). Quite flexible solution, I think. One remark seems to be on place here. Though the colors in the file are specified in the 24-bit RGB form the graphics engine works internally with 16-bit '565' colors (or with 15-bit '555' form; it depends on device caps). So the RGB values have to be translated during loading process to the internal form. In practice it means that if you specify two similar R color values they may be translated into single R color value internally (more precisely lower three bits of every R, G, B byte are meaningless to the engine).
There is one essensial side effect of the color map loading process
which may be very important for people trying to prepare custom maps for
WNLB (US version). As said above for the map of the X*Y size the color map
file is expected to contains 3*X*Y bytes. If the program fails to open the
file (likely because it does not exist) it will revert to use the
GroudColor/darkness lighting conditions. If the file exists however then -
because of the details of color map loading - if the file size is lower
then expected (like in the case of custom map BIGGER then standard
Waterloo 145*100 map AND standard Waterloo TeenieMap.raw file) the program crash during the
initialisation phase is virtually inevitable. To avoid that you should
extend the size of your color map file to be at least the mentioned 3*X*Y
bytes. For the biggest WNLB map (255x255) the TeenieMap.raw extended to the size of 196608 bytes
should be enough. One way to extend the file is by using the HEX editor.
If this is not feasible at the moment you can try following quick and
dirty appoarch: open your command shell (DOSBox window), go to the
GRAPHICS directory of your WNLB game, and being there type the following
commands (backup original TeenieMap first!):
What if one wants something more however? How to create color map which
will correctly express topography of the custom campaign's map? Doing it
by hand - using HEX editor - looks like a never-ending job even if one
decides to limit himself to only one color map (remember that to provide
variable daylight conditions one needs to create 24 maps! :-/)
As said above patched ANGV allows you to use the color maps(s) on the
custom campaign's maps in the way similar to the standard Austerlitz
campaign. To enable that feature you should set the ColourMap property in the [extension] section of campaign's CONFIGnn.CFG file. The default for that property is 0
(disabled). When ColourMap=1 ANGV engine should
behave like WNLB (US ver.). That is it should try to load the single color
map - the variable daylight feature is to be disabled. Default name of
that file is Graphics\ColourMapCnn.raw (nn here
are two digits of campaign number). You can change the name of the file by
using ColourMapFile property. (Warning: when using that option don't specify the file
extension! '.raw' extension is appended automatically)
Time for couple of pictures to illustrate concepts described here. All
pictures were made using one and the same campaign config file (config44.cfg). It
is prepared so that it just loads the standard Austerlitz campaign's
MAPDATA assets through MultiCampaign feature -
so it is useful to verify the transparency of of the MultiCampaign mechanics. Note that these pictures
suggest that there is something wrong with JumpMap displaying. But
that's different story...
Time to talk about GroundColor.raw file, its
format, how it was supposed to work and (last but not least) promised Fix.
As explained above GroundColor is used in case when either color map is
not loaded by design (ANGV custom campaigns) or the color map file does
not exist (may be the case for both ANGV and WNLB US ver.)
back to top of page
First time I managed to load scenario through MultiCampaign mechanism the thing which drew my attention (right after batlefield darkness) was strange apperance of Jump Map Frame. In fact this frame didn't appear at all. Frame area was completely transparent with the exception of menu buttons on the right side and groups of blue/red dots (representing units) spread in frame space (sometimes also outside of the frame - it depends on custom map size and units locations). Transparency in itself may be not bad thing - a bit more of main map is visible afterall. It is also easy to avoid by providing custom Jump Map bitmap in GRAPHICS folder and specifying its name in JumpMapImage property (default is JumpMapNN.BM2; where NN is campaign number). However the real problem is that parts of the main map are unreachable by mouse clicking on the jump map area and that in cases where "jumping" mechanism works it often jumps to slightly (sometimes not so slightly) different parts of main map then expected.
What is source of problems? Proper working of Jump
Map feature depends on consistent implementation of two fundamental
transformations. One procedure is needed to transform main map coordinates
(in squares) into jump map coordinates measured in pixels (and counted
from the upper left of Jump Map bitmap). This is needed for displaying
units (and VP locations) in right place on Jump Map bitmap. Second
procedure is responsible for converting mouse click coords (in pixels)
into main map coords (in squares). That is the essence of "jumping"
Updated Universal Patch provides means to
specify necessary values on per-campaign basis. So once you've prepared
custom version of Jump Map for your campaign next - to get it working
properly - you will have to specify four properties in [extension] section of campaign's CONFIGnn.CFG. All four are numbers measured in pixels.
First pair - JumpMapOffsetX and JumpMapOffsetY - defines place on JumpMap bitmap where
actual map rectangle (its upper left point) begins. For JumpMapOffsetY please do NOT count upper 48 lines of
transparent area which is necessary according to MAPCREATION.TXT. Using again Waterloo JumpMap as an
example proper setting here is JumpMapOffsetY=3
and NOT JumpMapOffsetY=51 (48+3).
If you have read MAPCREATION.TXT you would
likely wonder how to get that simplistic version of Jump Map with main
map's roads&pikes network indicated. Indeed it shows up in WNLB
(assuming you did not prepare your own Jump Map of course). To achieve the
same in unpatched ANGV it is enough to copy JumpMap01.BM2 into WaterMisc.BAG container. But even then it will suffer
from the similar reasons like these described above: hardcoded mapping
parameters. Still for some (main) map dimensions mechanism should work
pretty well. Most likely for maps which dimensions are ALMOST equal but
with Y dim slightly larger then X one. I suppose it may somewhat explain
why the map dimesions of 145x150 are choosen at least for some battles of
Peninsula Mod project.
Words of cautions: it has to be said that functionality
described wasn't tested long enough to make me confident it will be
working as expected in all possible combinations of conditions. Based on
tests I made I still hope it will work correctly with your custom maps
(assuming you provide correct values for properties described). In case of
troubles I'd love to hear about them and will try to fix them as time
allows me. In fact one of the problems with testing it was limited number
of different test cases (different custom maps and jump map pictures). One
another property which may be helpful in case of troubles is JumpMapFix. Setting this global property to zero
disables JumpMap patch - so ANGV should handle
JumpMap as original non-patched version. Note that it is default value and
to get JumpMap feature (hopefully) fixed you
need to put JumpMapFix=1 in [extension] section of Austerlitz.ini file.
back to top of page
back to top of page