2018-10-13 03:22:39 +01:00
|
|
|
# *.mnu
|
|
|
|
|
|
|
|
These files appear to be the UI definitions for Chaos Gate. Some relate to
|
2018-12-30 23:23:08 +00:00
|
|
|
system menus, other to in-game menus. Their names are hardcoded into the
|
|
|
|
`WH40K.exe` binary. Each has a `.obj` file associated with it.
|
|
|
|
|
|
|
|
It's an ASCII-formatted text file with a 12-line header, followed by a number
|
|
|
|
of descriptor records.
|
|
|
|
|
|
|
|
Here's the top of `MainGame.mnu`:
|
|
|
|
|
|
|
|
```
|
|
|
|
MainGame.obj
|
|
|
|
BACKGROUND COLOR 0..255..-1 trans : 0
|
|
|
|
HYPERTEXT COLOR 0..255 : 120
|
|
|
|
FONT TYPE 0..5 : 10
|
|
|
|
wh40k_12
|
|
|
|
basfnt12
|
|
|
|
wh40k_47
|
|
|
|
wh40k_12_red
|
|
|
|
wh40k_12_blue
|
|
|
|
wh40k_12_green
|
|
|
|
wh40k_12_yellow
|
|
|
|
NULL
|
|
|
|
```
|
|
|
|
|
|
|
|
The first line of the header is a `.obj` file containing sprites we want to
|
|
|
|
display on-screen. We see entries further down have a `SPRITEID`, which must
|
|
|
|
reference entries in that file.
|
|
|
|
|
|
|
|
In `SaveGame.mnu`, we can see multiple `.obj` files can be referenced.
|
|
|
|
|
|
|
|
There are then 3 lines that seem to be fixed descriptor names with values
|
|
|
|
that vary. Is this font colour, perhaps? Unsure.
|
|
|
|
|
|
|
|
Next is a variable-length list of font names, referencing files in the `Fonts`
|
|
|
|
directory.
|
|
|
|
|
|
|
|
Finally, there's a list of records that specify the menu itself. Truncated
|
|
|
|
contents of `SaveGame.mnu`:
|
|
|
|
|
|
|
|
```
|
|
|
|
#rem..........Background
|
|
|
|
MENUID : 1
|
|
|
|
MENUTYPE : 0
|
|
|
|
MOVEABLE : 0
|
|
|
|
ACTIVE : 1
|
|
|
|
SPRITEID : 0
|
|
|
|
ACCELERATOR: 0
|
|
|
|
DRAW TYPE : 0
|
|
|
|
SHARE : -1
|
|
|
|
X-CORD : -1
|
|
|
|
Y-CORD : -1
|
|
|
|
DESC :
|
|
|
|
*
|
|
|
|
#rem..........MAIN BACKGROUND
|
|
|
|
MENUID : 2
|
|
|
|
MENUTYPE : 45
|
|
|
|
MOVEABLE : 0
|
|
|
|
ACTIVE : 1
|
|
|
|
SPRITEID : 0
|
|
|
|
ACCELERATOR: 0
|
|
|
|
DRAW TYPE : 0
|
|
|
|
SHARE : -1
|
|
|
|
X-CORD : -1
|
|
|
|
Y-CORD : -1
|
|
|
|
DESC :
|
|
|
|
#rem.......... MAIN BACKGROUND
|
|
|
|
SUBMENUID : 1
|
|
|
|
SUBMENUTYPE: 31
|
|
|
|
FONTTYPE : 20
|
|
|
|
ACTIVE : 0
|
|
|
|
SPRITEID : -1
|
|
|
|
ACCELERATOR: 0
|
|
|
|
DRAW TYPE : 0
|
|
|
|
SHARE : 0
|
|
|
|
SOUNDTYPE : 0
|
|
|
|
DESC :
|
|
|
|
*
|
|
|
|
#rem..........Chat List Box Menu
|
|
|
|
MENUID : 21
|
|
|
|
MENUTYPE : 1
|
|
|
|
MOVEABLE : 0
|
|
|
|
ACTIVE : 1
|
|
|
|
SPRITEID : 764
|
|
|
|
ACCELERATOR: 0
|
|
|
|
DRAW TYPE : 0
|
|
|
|
SHARE : -1
|
|
|
|
X-CORD : -1
|
|
|
|
Y-CORD : -1
|
|
|
|
DESC :
|
|
|
|
[...]
|
|
|
|
*
|
|
|
|
~
|
|
|
|
```
|
|
|
|
|
|
|
|
We start processing these as soon as we see `MENUID`, I suppose. Each toplevel
|
|
|
|
item is `*`-delimited, and the list is terminated with `~`.
|
|
|
|
|
|
|
|
Each menu has a list of parameters:
|
|
|
|
|
|
|
|
| Name | Examples | Purpose |
|
|
|
|
|---------|----------|---------|
|
|
|
|
| `MENUID`| `1`, `2`, `3` | Maybe linking between menus? |
|
|
|
|
| `MENUTYPE` | `0`, `1`, `2`, `3`, `45`, `300` | ? |
|
|
|
|
| `MOVEABLE` | `0` | Unimplemented functionality? |
|
2019-01-02 06:51:30 +00:00
|
|
|
| `ACTIVE` | `0`, `1`, `1,0` | ? |
|
|
|
|
| `SPRITEID` | `-1`, `0`, `123`, `16,-1,1` | Select from `.obj` file? |
|
2018-12-30 23:32:44 +00:00
|
|
|
| `ACCELERATOR` | | ? |
|
|
|
|
| `DRAW TYPE` | | ? |
|
|
|
|
| `SHARE` | | ? |
|
|
|
|
| `X-CORD` | `-1`, `0`, `200` | X coordinate to draw at |
|
|
|
|
| `Y-CORD` | `-1`, `0`, `200` | Y coordinate to draw at |
|
|
|
|
| `FONTTYPE` | | Choose a font from the above? |
|
|
|
|
| `SOUNDTYPE` | | ? |
|
|
|
|
| `DESC` | `CHARACTER SELECT`, `51005` | Text, or reference to `Data/USEng.dta` |
|
2018-12-30 23:23:08 +00:00
|
|
|
|
|
|
|
Submenus also show a couple of unique values:
|
|
|
|
|
2018-12-30 23:32:44 +00:00
|
|
|
| Name | Examples | Purpose |
|
|
|
|
|---------------|---------------|---------------|
|
|
|
|
| `SUBMENUID` | `1`, `2`, `3` | As `MENUID` |
|
|
|
|
| `SUBMENUTYPE` | `0`, `1`, `2` | As `MENUTYPE` |
|
2018-10-13 03:22:39 +01:00
|
|
|
|
2018-12-31 13:38:35 +00:00
|
|
|
It seems .mnu files can also include other files, which have the extension
|
|
|
|
`.mni` (presumably for "Menu include"). Examples:
|
|
|
|
|
|
|
|
```
|
|
|
|
*
|
|
|
|
$GenDialog.mni
|
|
|
|
$GenLoad.mni
|
|
|
|
```
|
|
|
|
|
|
|
|
It looks like we just interpolate the named file into the text when we come
|
|
|
|
across one of these lines.
|
2019-01-02 06:51:30 +00:00
|
|
|
|
2020-04-13 21:03:54 +01:00
|
|
|
The `MENUID` in `GenDialog` and `GenLoad` is a 2-element list, like `1000,1`
|
|
|
|
or `2000,2`. The second number corresponds to the offset in the list of object
|
|
|
|
files.
|
|
|
|
|
|
|
|
## `MENUTYPE`
|
|
|
|
|
|
|
|
Here's the full list of
|
|
|
|
|
|
|
|
## `SUBMENUTYPE`
|
|
|
|
|
2019-01-02 06:51:30 +00:00
|
|
|
## (Sub)menu types
|
|
|
|
|
|
|
|
The types seem to refer to different types of UI widget. Here's a list of unique
|
|
|
|
values:
|
|
|
|
|
|
|
|
|
|
|
|
| Value | Meaning |
|
|
|
|
|-------|---------|
|
|
|
|
| 0 | Background |
|
|
|
|
| 1 | Logical menu grouping? |
|
|
|
|
| 2 | ? |
|
|
|
|
| 3 | Standard button? |
|
|
|
|
| 30 | Equipment? |
|
|
|
|
| 31 | "Character helmet" / "Slot" |
|
|
|
|
| 40 | "X Line Y" |
|
|
|
|
| 41 | "X Line Y" |
|
|
|
|
| 45 | ? |
|
|
|
|
| 45,10,11,9 | ? |
|
|
|
|
| 45,11,12,10 | ? |
|
|
|
|
| 45,14,15,13 | ? |
|
|
|
|
| 45,17,18,16 | ? |
|
|
|
|
| 45,3,4,2 | ? |
|
|
|
|
| 45,5,6,4 | ? |
|
|
|
|
| 45,6,7,5 | ? |
|
|
|
|
| 45,7,8,6 | ? |
|
|
|
|
| 45,8,9,7 | ? |
|
|
|
|
| 45,9,10,8 | ? |
|
|
|
|
| 50 | ? |
|
|
|
|
| 60 | Other text to display? (`UltEquip.mnu`) |
|
|
|
|
| 61 | Text to display |
|
|
|
|
| 70 | Hypertext to display |
|
|
|
|
| 91 | ? |
|
|
|
|
| 100 | ? |
|
|
|
|
| 110 | ? |
|
|
|
|
| 120 | ? |
|
|
|
|
| 200 | Drop-down button? |
|
|
|
|
| 205 | Single list box item? |
|
|
|
|
| 220 | Psyker power? |
|
|
|
|
| 221 | Page? |
|
|
|
|
| 228 | Big buttons in `Main.mnu` |
|
|
|
|
| 232 | ? |
|
|
|
|
| 233 | ? |
|
|
|
|
| 300 | Pop-up dialog box |
|
|
|
|
| 400,0,0,{8, 16} | ? |
|
|
|
|
| 400,22,22,{2, 4, 5, 6, 7, 8, 9, 9, 10, 13, 16} | ? |
|
|
|
|
| 400,30,-1,5 | ? |
|
|
|
|
| 405,0,0,{8, 16} | ? |
|
|
|
|
| 405,22,22,{2, 4, 5, 6, 7, 8, 9, 10, 13, 16} | ? |
|
|
|
|
| 405,30,-1,5 | ? |
|
2020-03-21 00:56:35 +00:00
|
|
|
|
|
|
|
## Positioning
|
|
|
|
|
|
|
|
The X-CORD and Y-CORD values would seem to be related, to this, but they are
|
|
|
|
universally set to 0 or -1.
|
|
|
|
|
|
|
|
Far more important are the XOffset and YOffset values for each sprite in the
|
|
|
|
associated .obj files. Taking these into account is enough to draw `Options.mnu`
|
|
|
|
successfully, for instance:
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
## Animation
|
|
|
|
|
|
|
|
This seems to be done by choosing a different sprite to draw every N ticks. They
|
|
|
|
are laid out sequentially, but I don't yet know how to animate them. It's likely
|
|
|
|
to be the same approach as used for other obj files.
|
|
|
|
|
2020-03-21 18:50:26 +00:00
|
|
|
Looking at Main.mnu, it points at the object fail Main.obj. This has 118
|
|
|
|
sprites, which can be described as follows:
|
|
|
|
|
|
|
|
| Start | Count | Desc |
|
|
|
|
| ------ | ----- | ---- |
|
|
|
|
| 0 | 1 | Background image |
|
|
|
|
| 1 | 3 | New game button: base, pressed, disabled |
|
|
|
|
| 4 | 3 | Load game button: base, pressed, disabled |
|
|
|
|
| 7 | 3 | Multiplayer button: base, pressed, disabled |
|
|
|
|
| 10 | 3 | Settings button: base, pressed, disabled |
|
|
|
|
| 13 | 3 | Quit button: base, pressed, disabled |
|
|
|
|
| 16 | 20 | New game button: 20 animation frames |
|
|
|
|
| 36 | 20 | Load game button: 20 animation frames |
|
|
|
|
| 56 | 20 | Multiplayer button: 20 animation frames |
|
|
|
|
| 76 | 20 | Settings button: 20 animation frames |
|
|
|
|
| 96 | 20 | Quit button: 20 animation frames |
|
|
|
|
| 116 | 1 | Section of background ("Menu title") |
|
|
|
|
| 117 | 1 | Version hotspot |
|
|
|
|
|
|
|
|
So we have 5 buttons with very similar characteristics, but at different sprite
|
|
|
|
offsets, and two distinct ranges per button, plus some others. Here's some
|
|
|
|
attributes plucked from `Main.mnu`:
|
|
|
|
|
|
|
|
| Name | (SUB)MENUTYPE | "Active" | "SPRITEID" | "DRAW TYPE" | "SHARE" |
|
|
|
|
| ---------- | ------------- | -------- | ---------- | ----------- | ------- |
|
|
|
|
| Background | 1 | 1 | 0 | 0 | -1 |
|
|
|
|
| Start menu | 1 | 1 | -1 | 0 | -1 |
|
|
|
|
| New game | 228 | 1,0 | 16,-1,1 | 20 | 1 |
|
|
|
|
| Load game | 228 | 1,0 | 36,-1,4 | 20 | 4 |
|
|
|
|
| MP game | 228 | 1,0 | 56,-1,7 | 20 | 7 |
|
|
|
|
| Options | 228 | 1,0 | 76,-1,10 | 20 | 10 |
|
|
|
|
| Quit | 228 | 1,0 | 96,-1,13 | 20 | 13 |
|
|
|
|
| Menu title | 61 | 1 | -1 | 0 | 116 |
|
|
|
|
| V hotspot | 61 | 1 | -1 | 0 | 117 |
|
|
|
|
|
|
|
|
The buttons, menu title and version hotspot are submenus of the start menu.
|
|
|
|
|
|
|
|
### `MENUTYPE`
|
|
|
|
|
|
|
|
This is the only menu where we see a type of 228. ~750 other unique values are
|
|
|
|
observed, suggesting structure. For instance, we have `24`, `240`, `241` and
|
|
|
|
`2410`, but not `2411` or `2409`. Sometimes we have a comma-separated list,
|
|
|
|
e.g.: `400,30,-1,5`.
|
|
|
|
|
2020-04-11 01:01:05 +01:00
|
|
|
A listing of some currently-known values:
|
2020-03-22 22:12:59 +00:00
|
|
|
|
|
|
|
| Value | Type |
|
|
|
|
| ----- | ---------------- |
|
|
|
|
| 0 | Static image |
|
|
|
|
| 1 | Menu |
|
|
|
|
| 3 | Button |
|
2020-04-11 01:01:05 +01:00
|
|
|
| 45 | Thumb |
|
2020-03-22 22:12:59 +00:00
|
|
|
| 50 | Invoke? Button? |
|
|
|
|
| 61 | "Overlay" |
|
|
|
|
| 70 | "Hypertext" |
|
|
|
|
| 91 | Checkbox |
|
|
|
|
| 220 | Animation sample |
|
|
|
|
| 228 | Main menu button |
|
|
|
|
| 232 | Slider |
|
|
|
|
|
2020-04-11 01:01:05 +01:00
|
|
|
Hypothesis: `MENUTYPE` and `SUBMENUTYPE` are actually distinct lists of values.
|
|
|
|
So far, I've been treating them as the same thing, but, e.g., `MainGame.mnu` has
|
|
|
|
a `MENUTYPE: 45` which is labelled "MAIN BACKGROUND", while `SUBMENUTYPE: 45`
|
|
|
|
is tentatively labelled a "thumb" and used in text boxes. There are also a few
|
|
|
|
cases where I've had to manually override the `MENUTYPE` because it coincides
|
|
|
|
with `Button`.
|
|
|
|
|
2020-03-21 18:50:26 +00:00
|
|
|
### `ACTIVE`
|
|
|
|
|
|
|
|
There are only 4 values seen across all menus: `0`, `1`, `1,0`, `102` and `1,1`.
|
|
|
|
Perhaps this represents possible states?
|
|
|
|
|
|
|
|
### Sprite selection
|
|
|
|
|
|
|
|
For the background (`MENUTYPE: 1`), this points simply at the sprite index in
|
|
|
|
the object file. For the start menu, it's `-1` (no sprite, I assume). For the
|
|
|
|
menu title and version hotspot (`MENUTYPE: 61`, it's `-1` too.
|
|
|
|
|
|
|
|
For the buttons, it's a list pointing to the start of the 20 animated frames,
|
|
|
|
`-1`, then the start of the 3 static frames.
|
|
|
|
|
|
|
|
`DRAW TYPE` is the number of animated frames. We only use the animated frames
|
|
|
|
when the button is focused. `SHARE` repeats the start of the static frames, and
|
|
|
|
is the only place they're found for the menu title and version hotspot.
|