Character Definitions - HoraceAndTheSpider/Bloodwych-68k GitHub Wiki

Character definitions and graphics renderer

This page describes how Bloodwych SPS 439 builds the humanoid characters numbered $00 to $55. A character is not stored as one complete picture. The game selects a head and a body definition, colours several component masks, and then assembles the correct artwork for the character's distance and facing.

The labels and binary positions below refer to SPS 439. Extracted filenames follow the Extracted Data File Types convention.

Rendering in plain English

For each visible character, the game:

  1. Uses the character number to read one entry from characters.bodies and one from characters.heads.
  2. Uses the selected body number to find four graphic bases and one of two component-layout families.
  3. Uses the viewing distance and facing direction to choose a source picture, mirror it when required, and find its screen position.
  4. Draws the legs, torso, two arms, and head separately at the four nearer graphic distances.
  5. Uses a precomposed distant character picture for the final two graphic distances.
  6. Replaces the four mask colours for each part using the corresponding group in characters.colours.

The multiple distances in BodyParts.gfx and HeadParts.gfx are separately stored Atari ST four-plane strips. They are not produced by scaling the nearest picture at run time.

Per-character selection and colours

There are 86 character types, from $00 through $55 inclusive.

Extracted file SPS 439 binary position Size Meaning
data/characters.bodies $A418 $56 One body-definition number for each character type.
data/characters.heads $A596 $56 One head-definition number for each character type. There are 18 known head definitions, numbered $00 to $11.
data/characters.colours $34E44 $6B8 Twenty palette selections for each character: five parts multiplied by four replacement colours.
gfx/HeadParts.gfx $354FC $3E70 The raw head pictures for all definitions, distances, and facing variants.
gfx/BodyParts.gfx $3936C $8640 Raw legs, torso, arms, and distant precomposed character pictures.

Each character's 20-byte colour record contains five consecutive groups of four palette indices:

head colours
leg colours
torso colours
arm colours
distant-composite colours

The distant picture therefore has its own four-colour selection. It is not recoloured by combining the nearer head and body groups.

Body definitions

Character_BodyDefinitions is extracted as data/characters-body-definitions.layout.

Source label SPS 439 binary position Size
Character_BodyDefinitions $A50A $8C

The table contains 14 records of ten bytes. Each record is five big-endian words:

Word Purpose
0 Component-layout selector. Zero chooses the standard layout; any non-zero value chooses the alternate layout.
1 Base offset of the body's legs in BodyParts.gfx.
2 Base offset of the torso.
3 Shared base offset of the arm pictures.
4 Base offset of the precomposed distant character pictures.

The character's body selection is masked with $0F, so the existing selection mechanism can address up to 16 records. Only 11 of the 14 supplied body definitions are selected by the SPS 439 character table. Adding records 14 and 15 is therefore structurally possible if space is provided. A third genuinely different layout family would require a code change because the current test treats word 0 as a Boolean choice: standard or alternate.

Near and middle-distance components

The standard and alternate component layouts are each 304 bytes:

Source label Extracted file SPS 439 binary position Size
Character_RenderLayout_Standard data/characters-standard-render.layout $18480 $130
Character_RenderLayout_Alternate data/characters-alternate-render.layout $185C0 $130

Each layout contains three regions:

  1. 160 position bytes: four component distances × four facings × five parts × signed X/Y pairs.
  2. Five height tables: twelve bytes per part, arranged as four distances × three source variants.
  3. Five source-offset tables: twelve big-endian words per part, with the same four-distance × three-variant arrangement.

The five part indexes are head, legs, torso, first arm, and second arm. The two arm entries share the body's arm graphic base but have independent positions, facing rules, and animation adjustments.

Why the render-table offsets are one resource

Character_RenderTableOffsets is a single 20-byte table extracted as data/characters-render-table-offsets.lookup at $A5EC.

It contains five interleaved pairs of big-endian words:

part 0 height-table offset, part 0 source-table offset
part 1 height-table offset, part 1 source-table offset
...
part 4 height-table offset, part 4 source-table offset

Both offsets are relative to the selected standard or alternate render-layout block. They are not two independent data resources and should not produce two overlapping INCBIN statements.

The internal source label at the second word is represented as:

_Offset_Character_RenderTableOffsets_0x02

The relabeller can then rewrite references to Character_RenderTableOffsets+$02, while the source build inserts the whole 20-byte lookup only once at Character_RenderTableOffsets.

Facing, mirroring, and animation

Character_PartFacingVariants is extracted as data/characters-part-variants.lookup at $A600. Its 20 bytes are five parts × four facing directions.

Each entry selects a source variant. Bit 7 requests horizontal mirroring, while $FF suppresses that component. This allows the two side facings to share artwork without requiring another stored picture.

Animated arms use Character_ArmAnimationPositions, extracted as data/characters-arm-animation.positions at $A778. Its 72 bytes contain two 36-byte blocks, one for each layout family. Each block supplies:

  • four Y corrections selected by component distance;
  • 32 X corrections selected by four distances × two arms × four facings.

When an arm is animated, the renderer selects the animation source variant and applies these corrections. Side-facing animated arms also reverse their normal mirroring rule.

The two distant character slots

The final two graphic distances use precomposed character pictures instead of drawing five components. Each position table contains four signed X/Y pairs, one per facing.

Source label Extracted file SPS 439 binary position Size
Character_Distant4_Positions_Standard data/characters-standard-distant-4.positions $185B0 $08
Character_Distant5_Positions_Standard data/characters-standard-distant-5.positions $185B8 $08
Character_Distant4_Positions_Alternate data/characters-alternate-distant-4.positions $186F0 $08
Character_Distant5_Positions_Alternate data/characters-alternate-distant-5.positions $186F8 $08

The distant source block contains three directional variants. One side direction is mirrored to produce the fourth facing.

The distant picture dimensions and strides are immediate values in Draw_Character, rather than table data:

Layout Slot 4 Slot 5
Standard height 22, stride $B0 height 17, stride $88, group offset $210
Alternate height 21, stride $A8 height 16, stride $80, group offset $1F8

These values are reasonable future EQU candidates if body formats are to be expanded. They do not need separate extracted files in the current source layout.

Source labels and spreadsheet treatment

The relevant code entry point is Draw_CharacterComponent at the former label adrCd00A998. It is a function label, not data, so its spreadsheet row needs a relabel and source comment but no extracted filename or data action.

The extracted tables should use normal data rows, producing one INCBIN for each non-overlapping source block. The symbolic +2 label inside Character_RenderTableOffsets is the exception: it has no file and no data action because it names an address within the preceding resource.

Modification implications

  • Character colours, head selection, and body selection are naturally editable per character.
  • Layout positions are shared by every body using the same standard or alternate family. They are useful advanced controls but a change affects several character types.
  • A new body can reuse an existing layout while selecting different legs, torso, arms, and distant graphic bases.
  • New or resized pictures require regenerated source offsets and heights, plus enough relocated space for the graphic data and any expanded definition tables.
  • The 14 body records and two layout families should remain explicit project data rather than hard-coded knowledge in a graphics editor.

See also: