Adding modding folder with a hacked build.

This commit is contained in:
ml
2026-09-26 08:53:08 +02:00
parent cdb960dc71
commit c91080aba7
755 changed files with 50424 additions and 0 deletions
+336
View File
@@ -0,0 +1,336 @@
## Game state and hacker information, resource 0x0FA1 (`Player` struct)
This resource contains everything about the hacker, together with general game-state information.
0000 20xbyte Hacker name (incl. 0x00 termination char). Game only allows 12 characters for input at start.
0014 byte Realspace Level; The level to return to after exiting cyberspace.
0015 4xbyte Difficulties (Game rating): combat, mission, puzzle, cyber. All 0..3
0019 3xbyte Unused.
001C uint32 Game time
0020 uint32 Last second update
0024 uint32 Last drug update
0028 uint32 Last ware update
002C uint32 Last animation check
0030 int32 Queue Time
0034 int32 Delta Time
0038 byte Detail Level
0039 byte Current level identifier
003A 22xint16 Initial SHODAN levels
0066 6xbyte Controls
006C int16 Player Object ID
006E [8]byte Realspace location; The point to return to after exiting cyberspace.
0076 int32 Version number of the data structure; Value: 6
007A [14]int16 General inventory references, Object IDs
0096 byte Posture
0097 byte Foot planted; 1: on the floor
0098 byte Lean X
0099 byte Lean Y
009A int16 Unused
009C byte Health; 0x00..0xFF
009D byte Cyberspace Integrity
009E uint16 Hitpoint regeneration per minute
00A0 8xbyte Damage rate per minute [explosion, energy, magnetic, radiation, gas, tranq, needle, bio]
00A8 uint16 Bio post expose
00AA uint16 Rad post expose
00AC byte Power 0x00..0xFF
00AD byte Power usage in JPM
00AE byte Power regeneration
00AF byte Energy out; 1: is out of energy
00B0 int16 Cyberspace trips
00B2 int32 Cyberspace time base
00B6 [64]uint8 512 Boolean game variables; Bytes are counted up, bits within byte counted from LSB; Example: bit[10] = 0x00 0x04 0x..
00F6 [64]int16 64 Integer game variables
0176 uint32 HUD modes; Bitfield as per hud.h
017A byte Unused
017B sint32 Fatigue
017F uint16 Fatigue spending; Current rate of fatigue expenditure in pts/sec
0181 uint16 Fatigue regeneration
0183 uint16 Fatigue regeneration base
0185 uint16 Fatigue regeneration maximum
0187 sint8 Accuracy
0188 byte Shield absorb rate, in percent
0189 byte Shield threshold
018A byte Light value; setting of lamp
Multi-Function-Display (MFD) state
018B [10]byte 2x5 MFD slot indices
0195 [7]byte MFD status
019C [7]byte MFD function IDs
01A3 [32]byte MFD function flags
01C3 [256]byte MFD function data
02C3 [2]byte current MFDs
02C5 [2]byte MFD empty functions
02C7 [64]byte MFD access puzzles
0307 [2]byte MFD save slots
Installed Hardware (0: not installed):
0309 byte version for infrared night vision
030A byte version for target info
030B byte version for Sensaround
030C byte version for "Aim Enhancement Hardware"
030D byte version for HUD (unknown function)
030E byte version for bioscan
030F byte version for navigation unit
0310 byte version for shield
0311 byte version for data reader
0312 byte version for lantern
0313 byte version for view control
0314 byte version for enviro suit
0315 byte version for booster
0316 byte version for jump jet
0317 byte version for system status
Installed Software(0: not installed):
0318 [7]byte offensive software
031F [3]byte defensive software
0322 [9]byte misc software
Full clips of ammunition
032B byte ML STANDARD ROUNDS
032C byte ML TEFLON COATED ROUNDS
032D byte SV NEEDLE DARTS
032E byte SV TRANQ DARTS
032F byte HOLLOW-TIP 2100 CLIP
0330 byte HEAVY SLUG 2100 CLIP
0331 byte DC RUBBER SLUGS
0332 byte MARK3 MAGNESIUM-TIP SHELLS
0333 byte MARK3 PENETRATOR SHELLS
0334 byte AM HORNET CLIP
0335 byte AM SPLINTER CLIP
0336 byte RF SLAG CLIP
0337 byte RF LARGE SLAG CLIP
0338 byte SG MAG PULSE CART
0339 byte MM RAIL CLIP
Ammunition not in full clips
033A byte ML STANDARD ROUNDS
033B byte ML TEFLON COATED ROUNDS
033C byte SV NEEDLE DARTS
033D byte SV TRANQ DARTS
033E byte HOLLOW-TIP 2100 CLIP
033F byte HEAVY SLUG 2100 CLIP
0340 byte DC RUBBER SLUGS
0341 byte MARK3 MAGNESIUM-TIP SHELLS
0342 byte MARK3 PENETRATOR SHELLS
0343 byte AM HORNET CLIP
0344 byte AM SPLINTER CLIP
0345 byte RF SLAG CLIP
0346 byte RF LARGE SLAG CLIP
0347 byte SG MAG PULSE CART
0348 byte MM RAIL CLIP
Patches
0349 byte STAMINUP STIMULANT
034A byte SIGHT VISION ENCHANCEMENT
034B byte BERSERK COMBAT BOOSTER
034C byte MEDIPATCH HEALING AGENT
034D byte REFLEX REACTION AID
034E byte GENIUS MIND-ENCHANCER
034F byte DETOX UNIVERSAL ANTIDOTE
Explosives
0350 byte FRAGMENTATION GRENADE
0351 byte EMP GRENADE
0352 byte GAS GRENADE
0353 byte CONCUSSION BOMB
0354 byte LAND MINE
0355 byte NITROPACK
0356 byte EARTH SHAKER EXPLOSIVE
0357 [294]byte Message status bitfield; 47 emails + 23 data fragments + (16 logs * 14 levels)
047D [14]byte Level log marker; On which level logs are in inventory
048B [5]byte First weapon
+0 byte Subclass (0xFF means no weapon)
+1 byte Type
+2 byte Rounds / Heat
+3 byte Ammunition type / Energy setting (0x80 bit is overload)
+4 byte Unused
0490 [5]byte Second weapon
0495 [5]byte Third weapon
049A [5]byte Fourth weapon
049F [5]byte Fifth weapon
04A4 [5]byte Sixth weapon
04A9 [5]byte Seventh weapon
04AE [15]byte Hardware on/off
04BD [19]byte Software status on/off
04D0 byte Jumpjet energy fraction
04D1 [32]byte email sender count
04F1 [7]byte Patches time remainder
04F8 [7]byte Patches intensity
04FF [7]uint16 Timer settings of explosives, in 0.1 seconds; Default: 0x46 = 7 seconds
050D uint16 Unused
050F uint16 Time to completion of current program (seconds). Essentially unused, although used to print some strings
0511 uint16 ObjectID of current target
0513 uint32 Last weapon fire time
0517 uint16 Weapon fire rate; Time needed before next fire.
0519 [10]byte HUD actives: weapon, grenade, drug, cart, hardware, combat soft, defense soft, misc soft, general, email
0523 uint16 Object under cursor before cyberspace
0525 uint16 Last panel reference
0527 sint32 Kill count
052B sint32 Time in cyberspace
052F sint32 Number of shots fired
0533 sint32 Number of hits
0537 sint32 Death count; How often hacker was resurrected.
053B int32 Tilt (eye position)
053F [12]fix Physics state (EDMS) - see below
056F byte Currently active inventory category
0570 byte Active bio tracks
0571 int16 current email
0573 [6]byte version
0579 byte dead flag
057A uint16 lean filter state
057C [2]byte unused
057E byte MFD save field
057F uint32 Auto fire click
0583 uint32 Posture state
0587 byte Option: Text Length (0: normal, 1: terse)
0588 uint32 Last head bob
058C [9]byte Padding
> In archive.dat, this table is (nearly) all 0x00, and also slightly smaller than necessary.
### Physics state (EDMS `State` structure, 48 bytes)
0000 fix X Coordinate (East -> West)
0004 fix Y Coordinate (North -> South)
0008 fix Z Coordinate (above ground)
000C fix Yaw; 0 is facing East, going counter-clockwise
0010 fix Upper body back force (?)
0014 fix Upper body left force (?)
0018 fix Forward force (?) -- X dot product
001C fix Left force (?) -- Y dot product
0020 fix Unknown -- Z dot product
0024 fix Unknown
0028 fix Unknown
002C fix Unknown
Rotation values are in range 0..2PI.
### Message status enumeration (1 byte)
0x80 Message received
0x40 Message read
0x3F Unused
### Game variables
Game variables are described on a [separate page](gameVariables.md)
### Initial game state
The original engine does not allow for having `archive.dat` specify the initial state for both the game and hacker.
The `System Shock Enhanced Edition Source Port` introduced a modified start behaviour,
which allows for (almost) full control on how and where the protagonist starts:
When the first field of the `physics state` (the `X` coordinate of EDMS state) is not zero,
then most default settings are skipped, and data is taken from `archive.dat`.
Still, some minimal setup is performed either way, in order to have a stable game.
> This behaviour exists already in the original engine, but it only considers the physics structure itself,
> and no further information, such as the current level or any game variable.
#### Mission-independent hardcoded defaults
The following defaults are being applied regardless of existing data in `archive.dat`.
##### Game state fields
| Offset | Name | Initial value |
|--------|----------------------------|-----------------------------------------------------|
| 0000 | Hacker name | as per start menu |
| 0015 | Difficulties | as per start menu |
| 0038 | Detail Level | as per configuration |
| 003A | Initial SHODAN levels | all to `-1` |
| 006C | Player Object ID | `0` |
| 00A0 | Damage rate per minute | all to `0` |
| 0511 | ObjectID of current target | `0` |
| 0513 | Last weapon fire time | `0` |
| ** | Various MFD fields | To a consistent (empty) MFD display |
| 0309 | Installed Hardware[10] | `1` to hardcode "fullscreen hardware" |
| 0570 | Active bio tracks | `0xFF` |
| 00F6 | Integer game variables[48] | Language, as per configuration |
The two "random" game variables (index 31 and 32) are randomized only if they are equal.
#### Mission-dependent defaults
The following defaults are being applied *only* if `physics state` field `X` is zero.
##### Game state fields
| Offset | Name | Initial value |
|--------|----------------------------|-----------------------------------------------------|
| 0039 | Current level identifier | `1` |
| 007A | General Inventory | all to `0` |
| 009C | Health | `212` |
| 009D | Cyberspace Integrity | `255` |
| 009E | Hitpoint regeneration | `0` |
| 00AC | Power | `255` |
| 00B2 | Cyberspace time base | `504000` (30 minutes in 280 ticks-per-second) |
| 0181 | Fatigue regeneration | `0` |
| 0183 | Fatigue regeneration base | `100` |
| 0183 | Fatigue regeneration max | `400` |
| 0187 | Accuracy | `100` |
| 0188 | Shield absorb rate | `0` |
| 0357 | Message status[26] | `0x80`, to mark email from Rebecca received |
| 048B | Weapons[*].type | `0xFF`, to mark no weapon in slot |
| 04FF | Explosives timer[*] | `70` (= 7 seconds) |
| 0519 | HUD actives[9] | `0xFF`, to mark email being active |
| 053F | Physics state (EDMS) | X=30.5, Y=22.5, Z=planted at floor, Alpha=West |
##### Variables
The following integer variables are set:
| Integer | Value |
|---------|--------|
| 3 | 2 |
| 12 | 3 |
| 51 | 256 |
And the following boolean variables are set to `true`:
```
0x001, 0x002, 0x003, 0x010, 0x012, 0x015, 0x016, 0x017, 0x018, 0x019, 0x01A,
0x020, 0x021, 0x024, 0x025,
0x04B, 0x04C, 0x04D, 0x04E, 0x04F,
0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F,
0x070, 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x07B, 0x07C, 0x07D, 0x07E, 0x07F,
0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9,
0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, 0x0CE, 0x0CF,
0x0E1, 0x0E3, 0x0E5, 0x0E7, 0x0E9, 0x0EB, 0x0ED, 0x0EF,
0x0F1, 0x0F3, 0x0F5, 0x0F7, 0x0F9, 0x0FB, 0x0FD, 0x0FF,
0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F,
0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F,
0x121, 0x123, 0x125, 0x127, 0x129, 0x12B,
```
+208
View File
@@ -0,0 +1,208 @@
## Game variables
This page lists all game variables with their index, their initital value, and their usage in the original game.
> At the moment not all variables have been catalogued. Only the initial values have been determined.
### Boolean variables
| Index | Initial Value | Usage |
|------:|--------------:|----------------------------------------------------------------------------------------------|
| 0 | 0 | Must always be 0, otherwise default conditions may break |
| 1 | 1 | Must always be 1, otherwise some locks may fail |
| 2 | 1 | Unknown |
| 3 | 1 | Unknown |
| 6 | 0 | Shield status (+ System Analyzer) |
| 8 | 0 | Laser status (+ System Analyzer); 0: charging, 1: destroyed |
| 10 | 0 | Delta grove launch enable (+ System Analyzer) |
| 11 | 0 | Alpha grove launch enable (+ System Analyzer) |
| 12 | 0 | Beta grove launch enable (+ System Analyzer) |
| 13 | 0 | Relay 428 report status; 0: functioning, 1: faulty; Set by main switch, checked by diag. |
| 14 | 0 | Relay 428 repair status; 0: faulty, 1: fixed; Set by panel, checked by main switch. |
| 15 | 0 | Beta grove jettisoned (+ System Analyzer) |
| 16 | 1 | Unknown |
| 18 | 1 | Unknown |
| 20 | 0 | Reactor on destruct, pods enabled; Quakes (+ System Analyzer) |
| 21 | 1 | Unknown |
| 22 | 1 | Unknown |
| 23 | 1 | Unknown |
| 24 | 1 | Unknown |
| 25 | 1 | Unknown |
| 26 | 1 | Medical armory lock on doors in level 1 |
| 30 | 0 | Switch to open armory doors on level 1 via cyberspace level 14 |
| 32 | 1 | Unknown |
| 33 | 1 | Unknown |
| 36 | 1 | Unknown |
| 37 | 1 | Unknown |
| 75 | 1 | Unknown |
| 76 | 1 | Unknown |
| 77 | 1 | Unknown |
| 78 | 1 | Unknown |
| 79 | 1 | Unknown |
| 80 | 1 | Unknown |
| 81 | 1 | Unknown |
| 82 | 1 | Unknown |
| 83 | 1 | Unknown |
| 84 | 1 | Unknown |
| 85 | 1 | Unknown |
| 86 | 1 | Unknown |
| 87 | 1 | Unknown |
| 88 | 1 | Unknown |
| 89 | 1 | Unknown |
| 90 | 1 | Unknown |
| 91 | 1 | Unknown |
| 92 | 1 | Unknown |
| 93 | 1 | Unknown |
| 94 | 1 | Unknown |
| 95 | 1 | Unknown |
| 112 | 1 | Unknown |
| 113 | 1 | Unknown |
| 114 | 1 | Unknown |
| 115 | 1 | Unknown |
| 116 | 1 | Unknown |
| 117 | 1 | Unknown |
| 118 | 1 | Unknown |
| 119 | 1 | Unknown |
| 120 | 1 | Unknown |
| 121 | 1 | Unknown |
| 122 | 1 | Unknown |
| 123 | 1 | Unknown |
| 124 | 1 | Unknown |
| 125 | 1 | Unknown |
| 126 | 1 | Unknown |
| 127 | 1 | Unknown |
| 145 | 0 | "Online" help (tooltips); 0: show, 1: off |
| 160 | 1 | Unknown |
| 161 | 1 | Unknown |
| 162 | 1 | Unknown |
| 163 | 1 | Unknown |
| 164 | 1 | Unknown |
| 165 | 1 | Unknown |
| 166 | 1 | Unknown |
| 167 | 1 | Unknown |
| 168 | 1 | Unknown |
| 169 | 1 | Unknown |
| 192 | 1 | Unknown |
| 193 | 1 | Unknown |
| 194 | 1 | Unknown |
| 195 | 1 | Unknown |
| 196 | 1 | Unknown |
| 197 | 1 | Unknown |
| 198 | 1 | Unknown |
| 199 | 1 | Unknown |
| 200 | 1 | Unknown |
| 201 | 1 | Unknown |
| 202 | 1 | Unknown |
| 203 | 1 | Unknown |
| 204 | 1 | Unknown |
| 205 | 1 | Unknown |
| 206 | 1 | Unknown |
| 207 | 1 | Unknown |
| 225 | 1 | Unknown |
| 227 | 1 | Unknown |
| 229 | 1 | Unknown |
| 231 | 1 | Unknown |
| 233 | 1 | Unknown |
| 235 | 1 | Unknown |
| 237 | 1 | Unknown |
| 239 | 1 | Unknown |
| 241 | 1 | Unknown |
| 243 | 1 | Unknown |
| 245 | 1 | Unknown |
| 247 | 1 | Unknown |
| 249 | 1 | Unknown |
| 251 | 1 | Unknown |
| 253 | 1 | Unknown |
| 255 | 1 | Unknown |
| 257 | 1 | Unknown |
| 259 | 1 | Unknown |
| 261 | 1 | Unknown |
| 263 | 1 | Unknown |
| 265 | 1 | Unknown |
| 267 | 1 | Unknown |
| 269 | 1 | Unknown |
| 271 | 1 | Unknown |
| 273 | 1 | Unknown |
| 275 | 1 | Unknown |
| 277 | 1 | Unknown |
| 279 | 1 | Unknown |
| 281 | 1 | Unknown |
| 283 | 1 | Unknown |
| 285 | 1 | Unknown |
| 287 | 1 | Unknown |
| 289 | 1 | Unknown |
| 291 | 1 | Unknown |
| 293 | 1 | Unknown |
| 295 | 1 | Unknown |
| 297 | 1 | Unknown |
| 299 | 1 | Unknown |
| 300 | 0 | Set to 1 while the data reader icon is flashing & beeping |
### Integer variables
| Index | Initial Value | Usage |
|------:|--------------:|---------------------------------------------------------|
| 1 | 0 | Incremented for each destroyed computer node lvls 1-7 |
| 3 | 2 | Engine state |
| 9 | 0 | Incremented by 1 for laser, beta grove, reactor |
| 12 | 3 | Number of groves |
| 13 | Mission value | Unknown |
| 14 | Cyber value | Unknown |
| 15 | Combat value | Unknown |
| 16 | L00 security | Security value of level |
| 17 | L01 security | Security value of level |
| 18 | L02 security | Security value of level |
| 19 | L03 security | Security value of level |
| 20 | L04 security | Security value of level |
| 21 | L05 security | Security value of level |
| 22 | L06 security | Security value of level |
| 23 | L07 security | Security value of level |
| 24 | L08 security | Security value of level |
| 25 | L09 security | Security value of level |
| 26 | L10 security | Security value of level |
| 27 | L11 security | Security value of level |
| 28 | L12 security | Security value of level |
| 29 | L13 security | Security value of level |
| 30 | Puzzle value | Unknown |
| 31 | random | Reactor code 1 (3-digit BCD) |
| 32 | random | Reactor code 2 (3-digit BCD) |
| 33 | 0 | Destroyed comp. nodes on lvl1 before showing digit |
| 34 | 0 | Destroyed comp. nodes on lvl2 before showing digit |
| 35 | 0 | Destroyed comp. nodes on lvl3 before showing digit |
| 36 | 0 | Destroyed comp. nodes on lvl4 before showing digit |
| 37 | 0 | Destroyed comp. nodes on lvl5 before showing digit |
| 38 | 0 | Destroyed comp. nodes on lvl6 before showing digit |
| 39 | 0 | Destroyed cyberguards in large cspace / open barrier |
| 40 | | Unknown |
| 41 | as per config | Audio music volume (0x00 .. 0x64) |
| 42 | 0x4A3D | Video gamma |
| 43 | as per config | Audio digital FX volume (0x00 .. 0x64) |
| 44 | as per config | Mouse handedness (Right: 0, Left: 1) |
| 45 | | Unknown |
| 46 | | Unknown |
| 47 | 0x5555 | Double click time |
| 48 | as per config | Selected language (0: ENG, 1: FRA, 2: GER) |
| 49 | as per config | Audio message volume (0x00 .. 0x64) |
| 50 | as per config | Video resolution |
| 51 | 256 | Joystick sensitivity |
| 52 | | Unknown |
| 53 | as per config | Audio messages (0: Text, 1: Speech, 2: Both) |
| 54 | | Unknown |
| 55 | | Unknown |
| 56 | | Unknown |
| 57 | | Unknown |
| 58 | as per config | Audio channels (0: 2ch, 1: 4ch, 2: 8ch) |
| 59 | | Unknown |
| 60 | | Unknown |
| 61 | | Unknown |
| 62 | | Unknown |
| 63 | | Unknown |
The two random codes (index 31, 32) will be randomized if they are equal.
> The two random codes are stored in [Binary-Coded-Decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal).
> The integer values from index 40 on seem to be all about in-game options.
> This may be the reason why it was earlier thought that there are only 40 game variables.
+80
View File
@@ -0,0 +1,80 @@
## Archives
This section covers the archive files. There is one template archive file, called ```archive.dat```, and a number of save-game files, called ```savgamXX.dat```. All of these files are regular resource files.
Any new game is based on the archive.dat file. All these archive files contain the complete game state, including the level layout. In other words: Citadel itself, with all its content, is represented through such a file; Properties and media for the content is in the other resource files.
## Map specific data
Each level has 98 resources reserved, but only 51 in use. The level-specific resources are grouped according to the level identifier. For example, on Citadel level R, the resources start with ID ```4002``` (decimal) up to ```4053```. Level 1 uses ```4102``` to ```4153``` and so forth.
On the following pages, resources identified as ```LXX``` refer to level-specific resource ```XX``` for any level. These numbers will always be given in decimal.
## Extra Resources
### Name of archive, resource 0x0FA0 (4000)
This resource contains the name of the archive (title of the save-game). It is a 0x00 terminated string, with a dynamic length of up to 32 bytes (including the termination character).
> The archive.dat file contains extra (unknown) data after the name in this resource, up to a complete length of 128 bytes. A save-game file has only the name in this resource. The name of the template archive is "Starting Game".
### [Game state resource 0x0FA1 (4001)](gameState.md)
This resource contains information about the game and the hacker.
It also contains the [level variables](levelVariables.md).
### Additional Resources
Save-game files contain 4 further resources that are not present in archive.dat :
* 0x0000 Unknown int32. ```0x00000000``` at first investigation
* 0x024E Unknown.
* 0x024F Unknown.
* 0x0F9F Unknown int32. ```0x00004444``` at first investigation
## Index
### By topic
* [Map Information](mapInformation.md)
* [Level Objects](levelObjects.md)
* [Surveillance Cameras](surveillanceCameras.md)
* [Loop Configuration](loopConfiguration.md)
### By level-specific resource ID
* ```L02``` Map version number. int32 with value ```0x0000000B``` for all maps.
* ```L03``` Object version number. int32 with value ```0x0000001B``` for all maps.
* ```L04``` [Basic level information](mapInformation.md)
* ```L05``` [Map Layout](mapInformation.md)
* ```L06``` [Level schedules](levelSchedules.md)
* ```L07``` [Level texture map](mapInformation.md)
* ```L08``` [Main object table](levelObjects.md#level-object-table)
* ```L09``` [Level object cross-reference table](levelObjects.md#level-object-cross-reference-table)
* ```L10``` to ```L24``` 15 object [class specific tables](levelObjects.md#class-tables-and-entries)
* ```L25``` to ```L39``` 15 object [class default info](levelObjects.md#class-default-information)
* ```L40``` Miscellaneous savefile version number. int32. For all maps: ```CD-Release```: ```0x0000000D```. All other: ```0x0000000B```
* ```L41``` Unused entry. byte with value ```0x00``` for all maps.
* ```L42``` [Texture animation](textureAnimation.md)
* ```L43``` [Surveillance Sources](surveillanceCameras.md)
* ```L44``` [Surveillance Surrogates](surveillanceCameras.md)
* ```L45``` [Level variables](levelVariables.md)
* ```L46``` [Map notes](mapInformation.md#map-notes)
* ```L47``` [Map notes pointer](mapInformation.md#map-notes)
* ```L48``` Unknown. 0x30 byte length.
* ```L49``` Unknown. 0x1C0 byte length.
* ```L50``` Unknown int16. ```0x0000``` for all maps.
* ```L51``` [Loop Configuration](loopConfiguration.md)
* ```L52``` Unknown int16. (Only present in ```CD-Release```)
* ```L53``` Unknown. 0x40 byte length, all zeroes. (Only present in ```CD-Release```)
### Levels of Citadel
This is the level list of the base game:
* Level 00: Reactor level
* Level 01-09: Levels 1-9
* Level 10: SHODAN cyberspace
* Level 11: Delta grove
* Level 12: Alpha grove
* Level 13: Beta grove
* Level 14: Cyberspace for levels 1 and 2
* Level 15: Cyberspace
+175
View File
@@ -0,0 +1,175 @@
## Level Objects
Instance data of [Level Objects](../levelObjects/index.md) is stored as part of an archive. Two resources describe general information, then further resources are object class specific.
### General Information
#### Level Object Table
```L08```, a compressed resource, contains a table with general entries about the objects in the current level.
This table contains 872 entries, which houses two lists.
**Level Object Entry** (`Obj` struct) (27 bytes)
0000 byte In use flag. 0: free, 1: in use
0001 byte Object class
0002 byte Object subclass
0003 int16 Class table index
0005 int16 Cross-Reference table index (also: used list head)
0007 int16 Next
0009 int16 Previous
000B uint16 X Coordinate
000D uint16 Y Coordinate
000F byte Z Coordinate (height)
0010 byte Pitch rotation (around X axis), increasing values turn upwards
0011 byte Yaw/Heading rotation (around Z axis), increasing values turn rightwards
0012 byte Roll/Bank rotation (around Y axis), increasing values turn rightwards
0013 byte Physics (0xFF for unaffected, the default)
0014 byte Object type
0015 sint16 Hitpoints
0017 [4]byte Extra
The starting point for both lists is the first entry (index zero). This entry is not in use (```In use flag``` is zero).
The `Cross-Reference table index` field of the starting point refers to the first object of a list of objects in use. For all object entries in use,
their ```Previous``` and ```Next``` fields form a double-linked list, with the exception of the starting point:
The last used object entry refers to the starting point with its ```Next``` value without being referred-to from the starting point.
The `Next` index of the starting point refers to the first object of a list of objects not in use.
For all object entries not in use, their `Next` field forms a single-linked list.
The `Previous` field of unused objects is not defined and contains arbitrary data.
The last unused object entry refers to the starting point with its ```Next``` value.
If an object is placed in the world, it has the X, Y and Z coordinates set, as well as the ```Cross-Reference table index``` pointing to a corresponding entry in the cross-reference table.
If an object was spawned by the engine without a location in the world, such as loot from corpses,
then the ```X``` field is ```0xFFFF```, ```Y``` and ```Z``` fields are zero, and the ```Cross-Reference table index``` is zero as well.
The ```extra``` field is a multi-purpose field, which may hold further properties and/or state. The exact features are environment specific and may also be dependent on the classification of the object.
##### Global extra
For some objects, the ```extra``` field is dependent on the object type or class, and the field is applicable to both real world and cyberspace.
**Basic Extra** (4 bytes)
0000 byte Make Info - a general index
0001 byte Current Frame - for animations
0002 byte Time Remainder - for animations
0003 byte Instance Flags - for various purposes
This is the layout as defined by the engine. Yet, these values may be interpreted/used specifically according to type and/or environment.
**Panel Extra** (4 bytes)
0000 byte Panel name index; Index into cybstrng 0x0869
0001 [3]byte Other
If the ```Panel name``` resolves to an unknown block or empty string, then the regular object name is displayed.
**Surfaces Extra* (4 bytes)
0000 byte Unknown
0001 byte Bitmap Index
0002 [2]byte Unknown
This is used for simple surfaces, such as icons (`7/2/1`) and paintings (`7/2/4`).
##### Cyberspace extra
In case the level is cyberspace, the ```extra``` field contains the following properties.
**Cyberspace Level Object Extra** (4 bytes)
0000 byte Other
0001 byte ICE presence
0002 byte Unknown
0003 byte ICE level
Level objects in cyberspace can be locked by ICE (Intrusion Countermeasures Electronics). ICE need to be defeated using the drill tool before the locked object can be acquired/used. The ```ICE presence``` field determines whether ICE is present. Any value != ```0x00``` has ICE present.
If present, the health of the ICE is determined by the health of the object.
The ```ICE level``` then determines how aggressive and powerful the ICE is. ```0x00``` is the weakest, ```0xFF``` is the highest.
> Although the vanilla game uses ICE only on software objects, the engine also supports ICE on other objects, such as cyberspace exits.
#### Level Object Cross-Reference Table
```L09```, a compressed resource, is a table that links level objects and the tiles they are in. The index field in the [Tile Map Entry](mapInformation.md) refers to this table, as well as the table index field in the **Level Object Entry**. This table contains 1600 entries.
**Level Object Cross-Reference Entry** (10 bytes)
0000 int16 Tile X
0002 int16 Tile Y
0004 int16 Index into level object entry table
0006 int16 Index for next object
0008 int16 Index for next tile of same object
Objects can extend over several tiles. The last field points to the next reference entry about the same object, with different tile coordinates.
This field creates a single-linked list, with the last entry pointing to the first one.
If the object is contained within one tile only, this field points to its own entry.
The major coordinates of the main object entry match those of the last entry of the cross-reference list. The cross-reference list only contains the X/Y values of the tiles - not sub-tile coordinates.
The ```Index for next object``` field creates a single-linked list, terminating with a zero value.
This list either refers to all objects within the same tile (if referred to from a tile), or creates a pool of unused cross-reference entries. The start of this pool is the first entry (index zero).
Unused cross-reference entries contain arbitrary data and only the next object index field is valid.
### Class Specific Information
In the following resources, all tables have a static count of entries. Each entry has a common prefix.
**Level Object Prefix** (6 bytes)
0000 int16 Index into level object entry table
0002 int16 Previous
0004 int16 Next
The tables contain two lists each, similar to the main object table:
The starting point is the first entry (index zero). The starting point refers to a double-linked list of used entries (via ```Next```), and a single-linked list of unused entries (via ```Previous```). Both lists are terminated by referring back to index zero.
The ```Index``` field of the starting point does not refer to a level object, it is the index within the same table of the last used entry. (The actual "previous" link to the double-linked list of used objects.)
> The sum of all possible entries is slightly higher than the total count of possible **Level Object Entries**.
#### Class Tables and Entries
The following table lists the the level resources per class type. It also lists how many entries each table contains and how big one entry is.
The name column links to the corresponding details.
| Class | Level Res | Name | Entry Count | Entry Size (incl. prefix) |
|:-----:|-------------|-------------------------------------------|-------------|---------------------------|
| 0 | ```L10``` | [Gun][L10] | 16 | 8 |
| 1 | ```L11``` | [Ammo][L11] | 32 | 6 |
| 2 | ```L12``` | Physics | 32 | 40 |
| 3 | ```L13``` | [Grenade][L13] | 32 | 12 |
| 4 | ```L14``` | [Drug][L14] | 32 | 6 |
| 5 | ```L15``` | [Hardware][L15] | 8 | 7 |
| 6 | ```L16``` | [Software][L16] | 16 | 9 |
| 7 | ```L17``` | [Big Stuff][L17] | 176 | 16 |
| 8 | ```L18``` | [Small Stuff][L18] | 128 | 16 |
| 9 | ```L19``` | [Fixture][L19] | 64 | 30 |
| 10 | ```L20``` | [Door][L20] | 64 | 14 |
| 11 | ```L21``` | Animating | 32 | 10 |
| 12 | ```L22``` | [Trap][L22] | 160 | 28 |
| 13 | ```L23``` | [Container][L23] | 64 | 21 |
| 14 | ```L24``` | [Critter][L24] | 64 | 46 |
[L10]: ../levelObjects/00_Gun/levelGunEntry.md
[L11]: ../levelObjects/01_Ammo/levelAmmoEntry.md
[L13]: ../levelObjects/03_Grenade/levelGrenadeEntry.md
[L14]: ../levelObjects/04_Drug/levelDrugEntry.md
[L15]: ../levelObjects/05_Hardware/levelHardwareEntry.md
[L16]: ../levelObjects/06_Software/levelSoftwareEntry.md
[L17]: ../levelObjects/07_BigStuff/levelBigStuffEntry.md
[L18]: ../levelObjects/08_SmallStuff/levelSmallStuffEntry.md
[L19]: ../levelObjects/09_Fixture/levelFixtureEntry.md
[L20]: ../levelObjects/10_Door/levelDoorEntry.md
[L22]: ../levelObjects/12_Trap/levelTrapEntry.md
[L23]: ../levelObjects/13_Container/levelContainerEntry.md
[L24]: ../levelObjects/14_Critter/levelCritterEntry.md
### Class Default Information
Each level has 15 further resources, ```L25``` to ```L39```, one for each object class. The length of these resources is the same as for one class entry of the corresponding specific entries.
This information is used as default for creating new objects. Most of the time, all their bytes are 0x00.
+119
View File
@@ -0,0 +1,119 @@
## Level Schedules
```L06``` is a dynamically sized list of currently active schedules. A schedule performs some delayed action at a specific time in the future.
It contains a number of live entries equal to the ```timer count``` field from ```L04``` [(Level Information)](mapInformation.md#Level-information).
Unless the list is full, this list always has one extra "terminator" entry at the end.
**Level Schedule Entry** (`SchedEvent` struct) (8 bytes)
0000 int16 Timestamp, with a scale of 0x100 = 10 seconds
0002 int16 Type
0004 byte[4] Data
```Time``` specifies the timestamp accoring to in-game time. Should the level become activated (either through loading of savegame load or level transition) and the current time is beyond the trigger time, the object is immediately triggered.
```Type``` specifies how the schedule should be handled on timeout. ```Data``` is then type-specific.
> The one terminator entry is required to exist, and does not have to contain any useful information at the beginning (can be all zero).
> The engine sorts the schedule entries according to their ```trigger time```.
For the schedule data, any object index refers to the main object table in the level.
### Schedule Type 0: Null Schedule Event
This event does nothing.
### Schedule Type 1: Grenade Schedule Event (`GrenSchedEvent` struct)
**Grenade Schedule Event Data** (4 bytes)
0000 int16 Grenade object index
0002 byte Unique identifier
0003 byte Unused
The ```unique identifier``` must match the value from the (live) grenade object in the level to be handled.
This event removes the grenade object on timeout.
### Schedule Type 2: Explosion Schedule Event
This event does nothing.
### Schedule Type 3: Door Schedule Event (`DoorSchedEvent` struct)
**Door Schedule Event Data** (4 bytes)
0000 int16 Object index
0002 uint16 Unique identifier
If the ```object index``` references an open door, then this door will be triggered to close.
If the ```object index``` references a "plastiqued antenna relay", then this event causes the explosion and the special handling of these fixtures.
### Schedule Type 4: Trap Schedule Event (`TrapSchedEvent` struct)
**Trap Schedule Event Data** (4 bytes)
0000 int16 Target object index
0002 int16 Source object index
Triggers the ```target object``` first (without condition check).
If ```source object``` is not -1, it is attempted next, including condition checks.
### Schedule Type 5: Exposure Schedule Event
**Exposure Schedule Event Data** (`SchedExposeData` struct) (4 bytes)
0000 sint8 Damage
0001 uint8 Type
0002 uint8 TSecs
0003 uint8 Count -- unused
This event exposes ```type``` to the hacker for half of the amount given in ```damage```. Damage values are rounded towards the greater number.
If the calculated half is not equal to the ```damage``` value, then another event is re-scheduled with an offset of ```tSecs```.
> An earlier version of the engine appeared to use ```count``` as a counter towards zero, though this was replaced with the damage-halving algorithm.
### Schedule Types 6, 7: Floor, Ceiling Schedule Events (`HeightSchedEvent` struct)
These events share the same event data and algorithm.
**Height Schedule Event Data** (4 bytes)
0000 sint8 Semaphor
0001 sint8 Key
0002 sint8 Steps Remaining
0003 sint8 SFX Code -- unused
This event references the height transition referenced by ```semaphor``` (stored in ```L53```) which has to have given ```key``` to be valid.
```Steps remaining``` indicates both the direction, as well as how many further steps to take. When this counter reaches zero, movement stops.
### Schedule Type 8: Light Schedule Event
This event has no specific data.
It turns off any muzzle light source and restores the state of the lamp hardware.
### Schedule Type 9: Bark Schedule Event (`BarkSchedEvent` struct)
This event has no specific data.
It is scheduled by specific ```trap message``` actions (action type 22) to automatically remove the side-image after a certain time from the side-MFD.
### Schedule Type 10: EMail Schedule Event (`EmailSchedEvent` struct)
**EMail Schedule Event Data** (4 bytes)
0000 sint16 Data Munge (EMail index)
0002 byte[2] Unused
This event is the delayed action of ```receive email``` actions (action type 15). This event is used if the action has a delay higher than zero.
@@ -0,0 +1,36 @@
## Level Variables
```L45``` contains level variables, including environmental settings.
**Level Variables** (94 bytes)
0000 int16 Data Length. = 94
0002 byte Mist; Unused (0x00)
0003 byte Gravity; Unused (0x00)
0004 byte Radiation poisoning level, in 0.5 LBP
0005 byte Gravity, in 25% OR bio contamination level, in 0.5 LBP
0006 byte Gravity switch. If 0, ```0005``` is bio contamination. Gravity mod otherwise.
0007 byte Bio contamination register. Must be >1 to have contamination to register
0008 byte Radiation register. Must be >1 to have radiation to register
0009 uint32 Exit Time; Unused in savegame
000D [3*27]byte 3 Automap Variables entries, for first, second, full-screen (see below)
> Hazards are notified from value 0x01, but affect only starting from value 0x02 (1 LBP).
**Automap Variables** (27 bytes)
0000 byte Initialized.
0001 byte Zoom; 1 (farthest) .. 5 (nearest)
0002 sint32 X-coordinate; (as fix32 value)
0006 sint32 Y-coordinate; (as fix32 value)
000A uint16 Unknown
000C uint16 Unknown
000E uint16 Follow object; The object to focus on; Always 0x0001 (hacker)
0010 uint16 Sensor object
0012 uint16 Note object
0014 uint16 Flags
0016 uint16 Available flags
0018 byte Version ID
0019 uint16 Sensor radius; Scan radius, in tiles and sub-tiles
@@ -0,0 +1,24 @@
## Loop Configuration
```L51``` is a table containing loop configuration. 64 entries are stored in this table, with unused entries set to 0x00.
> This table appears to be automatically filled by displaying objects, such as screens and the like.
> Although ```archive.dat``` contains valid information in this table, it is rewritten by the information from the level object properties.
**LoopConfigEntry** (15 bytes)
0000 int16 Object Table Index
0002 byte Loop type
0003 [10]byte Unused
000D int16 Frame time -- 0x0100 is 0.9 seconds; Default: 0x0080
**Loop Type**
0 Don't loop, stick with first frame
1 Loop forward
2 Play once (on finish, stick with last frame)
3 Loop backward
4 Loop back and forth
5 Loop back and forth
6 Loop back and forth
7 Loop back and forth
+252
View File
@@ -0,0 +1,252 @@
## Map Information
### Map layout
#### Level information
```L04```, a compressed resource, contains the basic information about a level (a map).
> In the original source, this structure is called ```FullMap```.
**Level Information** (58 bytes)
0000 sint32 X Size - always 64 in the archives.
0004 sint32 Y Size - always 64 in the archives.
0008 sint32 X Shift - always 6 in the archives.
000C sint32 Y Shift - always 6 in the archives.
0010 sint32 Z Shift
0014 byte[4] Placeholder - ignore
0018 byte Cyberspace flag. 0: real life, 1: cyberspace
0019 byte[12] Unused
0025 byte[21] Scheduler Info
> The engine doesn't support maps with more than 4096 tiles. By default, this is a map of 64x64 tiles.
> While other combinations of X/Y sizes are feasible, as long as the respective shift parameter matches, there is
> hardly a point to try something different than 64x64.
The ```z shift``` determines the height of the level as well as the size of one height unit for tiles.
The level is one tile width high (perfect cube) if the shift value is 5.
A shift value of 0 gives 32 tiles of height, a value of 7 one fourth (1/4) of a tile. So it's 32, 16, 8, 4, 2, 1, 1/2, 1/4 for 0..7.
> Most levels have a shift value of 3, giving 4 tile widths of height. Security (Level 8) has a shift value of 1 - 16 tiles.
One height unit is the 32th of the level height. The higher the level is, the larger are the visible jumps of any height value.
Although any level can be marked as cyberspace - even the starting level - only levels 10, 14 and 15 properly work.
This is due to the engine considering 10 and everything above 13 to be cyberspace.
Cyberspace items in other levels don't work as expected, especially the exit port either crashes the game or puts the player at the start of the cyberspace level again.
As a further hardcoded limitation, only cyberspace levels 14 and 15 have a time limit. Level 10 is without limit.
The ```placeholder``` has no use in the archives. In the engine, this field is used as a placeholder for a pointer within the game logic.
The ```schedule``` information is the primary entry for level-specific timers.
**Level Scheduler Information** (21 bytes)
0000 sint32 Size - always 64 in the archives
0004 sint32 Schedule count
0008 sint32 Element size - always 8 in the archives
000C byte Grow - always 0 in the archives
000D byte[4] Pointer1
0011 byte[4] Pointer2
```Size``` and ```element size``` require to be set to the values ```0x40``` and ```0x08``` respectively. Otherwise the level timers (stored in ```L06```) will not work properly.
The ```element size``` of 8 comes from the size of scheduler entries.
```Grow```, a boolean, would indicate to the scheduler system to allow reallocating the timer list to contain more than ```size``` amount of entries. Yet, the engine always initializes this with 0 (= don't grow).
The two pointer fields are used engine-internally.
#### Tile map
The tiles are described in the compressed resource ```L05```, a table of tile map entries. The first entry describes the lower left tile and the next entries go east first, then north (first columns, then rows). All levels have a size of 64x64 tiles as the engine supports (and expects) only this layout.
The outermost tiles of the level (the 'border') should always be solid tiles. If these tiles are non-solid, the graphics engine may have rendering issues (walls not shown, just black) and entering these tiles freezes the game. This gives an effective available space of 62x62 tiles.
**Tile Map Entry** (16 bytes)
0000 byte Type
0001 byte Floor Info
0002 byte Ceiling Info
0003 byte Slope height. Valid for any non-flat tile.
0004 sint16 Index to first object in cross-reference table.
0006 uint16 Texture Info
0008 uint32 Flags
000C byte Sub Clip -- always 0xFF
000D byte Clear Solid -- unknown
000E byte Unused
000F byte Light delta
**Type** (1 byte)
The type is an enumeration with the following constants:
0x00 solid
0x01 open
0x02 diagonal open s/e (nw edge closed off)
0x03 diagonal open s/w (ne edge closed off)
0x04 diagonal open n/w (se edge closed off)
0x05 diagonal open n/e (sw edge closed off)
0x06 slope s->n
0x07 slope w->e
0x08 slope n->s
0x09 slope e->w
0x0A valley se->nw
0x0B valley sw->ne
0x0C valley nw->se
0x0D valley ne->sw
0x0E ridge nw->se
0x0F ridge ne->sw
0x10 ridge se->nw
0x11 ridge sw->ne
All non-open tiles are given as low -> high. Valleys have 3 vertexes higher and one lower (at floor level). Ridges have one vertex higher and the remaining three at floor level. The given direction is that between the one vertex and its opposite one.
**Floor/Ceiling Info** (1 byte)
bits 0-4 Height (ceiling is units down from 0x20)
bits 5-6 Texture rotation. When viewed from above: 1: 90°, 2: 180°, 3: 270° - always clockwise
bit 7 Hazard flag. Floor has biohazard, ceiling has radiation hazard.
The exact behaviour for the hazard flags is determined by the [level variables](levelVariables.md).
**Texture Info** (2 bytes)
The texture info field contains information for the tile textures of the level.
For real world, it contains index values into the texture map (see next resource below).
Cyberspace levels specify the palette color index for floor and ceiling of the South-Western corner.
Real World:
bits 0-5 Wall texture
bits 6-10 Ceiling texture
bits 11-15 Floor texture
Cyberspace:
bits 0-7 Floor palette index
bits 8-15 Ceiling palette index
**Flags** (4 bytes)
Real World:
0x80000000 Tile visited (automapper)
0x70000000 Unused
0x0F000000 Ceiling shadow
0x00F00000 Unused
0x000F0000 Floor shadow
0x0000E000 Music index
0x00001000 Music "peril"
0x00000C00 Slope control. See below.
0x00000200 Deconstructed flag ("spooky" music)
0x00000100 Use wall texture from adjacent tile
0x00000080 Unused -- only set for computer room on level 7
0x00000040 Flip wall texture horizontally alternating
0x00000020 Flip wall texture horizontally
0x0000001F Offset for wall textures
Cyberspace:
0x01000000 Flight pull: Strong pull towards floor
0x000F0000 Flight pull
0x0000E000 Music index
0x00001000 Music "peril"
0x00000C00 Slope control. See below.
0x00000060 Game-Of-Life flags (either needs to be set)
```Ceiling shadow``` and ```Floor shadow``` specify the darkness intensity for the south-western corner of the tile.
The ceiling value darkens all four surrounding ceilings.
The walls made by surrounding top-pillars are darkened starting from the ceiling.
The walls made by surrounding bottom-pillars are darkened starting from their floor.
The floor value darkens all four surrounding floors.
The walls made by surrounding bottom-pillars are darkened starting from the floor.
The walls made by surrounding top-pillars are darkened starting from their ceiling.
> The actions to modify the light values can only give tiles more light, or remove previously added light.
> Thus, with shadow values of 0, these tiles are as bright as possible, without any chance of making them darker.
```Slope control``` specifies for the floor and ceiling how slopes (and valleys and ridges) should look like.
0: Ceiling is inverted to floor; A slope height of 0x1F will have ceiling and floor seal of the tile.
1: Ceiling is mirroring the floor; A slope height of 0x10 will have their most extent vertexes touch each other.
2: Ceiling is flat.
3: Floor is flat.
```Flip wall texture horizontally```
Wall textures can be flipped horizontally.
In the ```alternating``` case, flipping is based on the parities of the tile's two coordinates (even/odd status of the X and Y values).
Furthermore, North/South wall textures are flipped separately to East/West wall textures; If the North/South walls are flipped for a certain tile, the corresponding East/West walls will not be flipped. If the North/South walls are not flipped, then the East/West walls will be flipped.
> This ensures mirrored patterns are kept across corners without the need to change the flags for every other tile. This is heavily used on level 9 for the infested walls.
The North/South texture is to be flipped if the parities of the tile's two coordinates are different - East/West would be normal in this case.
The North/Shouth texture is normal if the parities of the tile's two coordinates match - East/West would be flipped in this case.
This alternation is inverted if additionally bit ```0x00000020```` is set.
```Flight pull``` specifies what default translation/rotation forces are in play
0: None
1: Weak pull towards East
2: Weak pull towards West
3: Weak pull towards North
4: Weak pull towards South
5: Medium pull towards East
6: Medium pull towards West
7: Medium pull towards North
8: Medium pull towards South
9: Strong pull towards East
10: Strong pull towards West
11: Strong pull towards North
12: Strong pull towards South
13: Medium pull towards ceiling
14: Medium pull towards floor
15: Strong pull towards ceiling
16: Strong pull towards floor (requires separate extra bit)
> The engine applies the force to the 'nose' of the hacker, i.e. it will pull the heading until the hacker looks straight
> at the origin of the force. This causes the implicit rotation. Only if the heading is exactly opposite to the origin,
> then no rotation happens (i.e., pulled backwards).
> All but the 'Strong' pulls can be countered.
**Light delta** (1 byte)
The high nibble specifies the light delta to the ceiling shadow. The low nibble specifies the light delta to the floor shadow.
The [Change lighting action](../levelObjects/Actions.md#action-type-7-change-lightning) modifies these values.
### Texture map
This resource is a list of int16 texture identifier in resource ```L07``` with a fixed length of 108 bytes.
The ```Texture Info``` fields in the tile map refer to these identifier.
Although the field for wall textures would allow for 64 textures, the resource can only hold up to 54 textures.
The first 32 textures can be used for floor/ceiling as well.
> The engine caches these textures when reloading a savegame with the same level.
> In the original source this list is also referred to as ```loaded textures``` or ```loved_textures```.
> The 'texture' index for space is 0x00CD, the observation grating has 0x00B1 (ceiling on groves and bridge)
See [Level Textures](../content/LevelTextures.md) for further information.
### Map notes
#### Text Data
Text for the map notes is stored in the level-specific resource ```L46```. The notes are stored sequentially, with the 0x00 character terminating a note.
The maximum length of one note is 40 bytes (including the termination character). The resource itself is pre-initialized with 0x00 bytes to a total length of 0x800 bytes.
Data in this resource is always defragmented. If a note is modified or removed, the notes are rearranged.
#### Next available space
Resource ```L47``` is a single uint32 offset, pointing to the first available byte in the text data resource.
@@ -0,0 +1,28 @@
## Surveillance Cameras
The engine supports up to 8 surveillance cameras per level.
Such a camera can be any object in the level, and an additional surrogate can determine when a linked screen should show static although the actual source would still be available.
### Surveillance Sources
The sources of surveillance screens are defined with ```L43```. This resource contains a list of up to 8 object table index values.
These referred objects provide the location and orientation for the video source of a screen. A screen then refers to one of these entries by using one of the corresponding [special values as 'picture source'](../levelObjects/07_BigStuff/levelBigStuffEntry.md).
**Surveillance Sources Table** (16 bytes)
0000 [8]int16 Source object table index
> For a source that is not an actual camera object, it is typical to find 'null' trigger objects to be the reference.
> Unused surveillance sources refer to the unused object at index 0.
### Surveillance Surrogates
Screens may be bound to a destructible object. If this surrogate is destroyed, the corresponding screen shows static. These associations are stored in ```L44```, a resource with a list of up to 8 object table index values.
**Surveillance Surrogates Table** (16 bytes)
0000 [8]int16 Deathwatch object table index
> For camera sources, it is typical to refer to the actual camera in this table.
@@ -0,0 +1,30 @@
## Texture Animation
```L42``` is a table containing animation information for textures. 4 entries are stored in this table.
The ```Animation Group``` field of the [Texture Properties](../fileFormat/PropertyFiles#properties-entry) specifies
the index into this table. A wall that has such a texture set will use further textures. According to the
```Number of frames``` field of this table entry, more textures are used from the [Texture Map](mapInformation.md#texture-map).
Meaning, if the level uses texture X which has an animation group set, the corresponding animation entry specifies
how many further textures are used for this animation. These then have all to be next to each other in the texture map.
The properties of the first texture determine how the remaining will behave (climbable, ...)
> Since most textures have their animation group set to 0x00 and have no animation, the first entry in this
> table is unused and the bytes always 0.
**Animation Entry** (7 bytes)
0000 int16 Frame time (in milliseconds)
0002 int16 Current frame time
0004 byte Current frame index
0005 byte Number of frames for loop
0006 byte Loop type/Loop state
**Loop Type** (1 byte)
0x00 Loop forward
0x01 Loop forth-and-back (forward state)
0x81 Loop forth-and-back (backward state)