How a move works in the AKI wrestling games
How the six AKI N64 wrestling games store, play back and score a move, and what carried over when I gave Billy Kidman's Shooting Star Press to Andre the Giant.
In WCW/nWo Revenge, Billy Kidman throws a Shooting Star Press. Someone asked me whether that move could be given to Andre the Giant in WWF No Mercy, two games and two years later. To answer, I first had to work out what a move in these games actually is.
A move is 98 bytes a frame#
An animation in these games is a stack of whole poses, all the same size, with no curves, splines or compression. The Animations view of AKI Anvil sums up the shape in one line (header 4 B, frame 98 B, 19 bones, angle unit 0.3515625 degrees), and the line is the same for all six cartridges.
Each bone is one big-endian 32-bit word holding three 10-bit angles and two flag bits. The angle unit is 360/1024 degrees, a constant the tool reads from each game's unpacker instead of assuming it.
4 B header base angle (10 bits) | header kind (6 bits) | duration (u16, half frames)
98 B one frame, and every frame in the file is 98 B:
19 bones x 4 B rotation word = 76 B
1 root x 4 B absolute translation = 4 B
6 bones x 3 B translation relative to root = 18 B
98 B
bone word bits 0..9 angle about X x 360/1024 degrees
bits 10..19 angle about Y
bits 20..29 angle about Z
bit 30 this translation is the relative 3-byte form
bit 31 a translation block follows this word
file size 4 + 98 * frames Revenge 1BCF: 4 + 98 * 13 = 1278 BThe seven bones that carry a translation are exactly the seven with no parent in the skeleton; the other twelve get their position computed. In the header, the 16-bit value at byte 2 is the duration in half frames, because the streamer computes the frame number as time >> 1 (No Mercy RAM 0x800129FC). In 94.2 to 96.9 percent of each game's files, (duration >> 1) + 1 equals the frame count, and in no file is it larger.
To make sure no field is skipped, the tool also writes every animation back and compares the result with the original byte for byte. All 27,789 files and 694,093 frames of the six games come back identical. That required one convention the decoder never needed: a bone word without a translation still has bit 30 set, in every frame of every ROM.
Every bone turns in world space#
In a typical skeleton each angle is relative to the parent bone, so turning the upper arm carries the forearm with it. AKI does not work that way. Each of the 19 words is an absolute orientation in world space, and the parent contributes only a position.
The tool checks this by posing a frame and comparing it with the game's own pose routines running in a MIPS interpreter (a program that executes the console's machine code). For No Mercy file 2DD9, frame 1, the difference is 1.9e-7 in rotation and 9.5e-6 in position. As controls, chaining the rotations like an ordinary skeleton gives a deviation of 1.99, and inheriting positions gives 69.5 units. Revenge shows the same pattern.
Bone lengths are not in the animation at all. They sit in an 80-byte block that is byte for byte identical in all six games: 40 bytes of joint offsets, 20 of processing order and 20 of parents.
0 pelvis parent -1 joint offset 0, 10, 0 translation: absolute
1 lower_ab parent -1 joint offset 0, 23, 0 translation: relative
2 upper_body parent -1 joint offset 0, 35, 0 translation: relative
3 neck parent 2 joint offset 0, 58, 0
4 head parent 3 joint offset 0, 72, 0
6 upper_left_leg parent -1 joint offset 9, 6, 0 translation: relative
5 lower_left_leg parent 6 joint offset 9,-31, 0
7 left_foot parent 5 joint offset 9,-74, 0
11 upper_left_arm parent -1 joint offset 22, 56, 0 translation: relative
10 lower_left_arm parent 11 joint offset 24, 29, 0
8 left_hand parent 10 joint offset 24, 7, 0
9 left_fingers parent 8 joint offset 24, -4, 0
... and the right side, mirrored
for a bone with a parent:
position = parent matrix * (own joint offset - parent joint offset), z = 0The bones are listed in the order the pose loop walks them. Each name is fixed by where the bone sits: the head highest, the foot 74 units down, the hand 24 out to the side.
For anyone editing a pose, this is unforgiving. An elbow bend is the forearm's world angle minus the upper arm's, so turning a shoulder leaves the hand pointing where it did, floating in the wrong place. It is also the reason a move survives the trip to another cartridge: 19 absolute orientations need no context to mean what they mean.
The three angles are rotations about X, Y and Z, multiplied in that order. Emulated, each game's matrix routine returns exactly the transpose of R_x * R_y * R_z, with a largest deviation of 6.4e-8 in No Mercy and Revenge. The figure faces -z, which is where every textured model carries its face.
Half frames and the 180 degree flip#
A wrestler's animation timer advances one half frame per update (confirmed in No Mercy, RAM 0x80063080), so each stored frame is held for two updates and the odd half is a blend of two frames. Positions blend linearly. Angles are first wrapped into the range -180 to +180 and then scaled. In World Tour, VPW64 and No Mercy the wrap is a separate routine that, emulated over 15 probes, matches the tool exactly. In the other three the constants sit inline, so interpolation there is rated likely.
The strangest rule comes next. If the wrapped difference on X or Z exceeds a threshold, the player adds 180 degrees to both and wraps again, leaving Y alone, so a rotation that would sweep the long way round becomes a flip. In No Mercy this is a single site (RAM 0x800134CC to 0x80013534) with a threshold of 120. Revenge, WrestleMania 2000 and VPW2 have four sites each, two at 110 and two at 120. World Tour and VPW64 show no recognisable threshold. All of this is rated likely. On a stored frame the blend factor is 0 and the flip never fires, which is why a filmstrip of stored poses can look right while the motion between them does not.
The event track#
An animation says how a body moves, but not when the hit lands, when the opponent may reverse it, when the camera cuts or when the table breaks. That lives in a second file with one fixed-size record per animation, the event track: 36 bytes in Revenge and the later games, 32 in World Tour and VPW64. The game finds a record by arithmetic, pointer + (animation id - first animation id) * stride, which the tool proves by running each game's own unpacker on fake tables.
Every column has a name in the tool, from damage_begin and reversal_begin to table_break_frame, and each carries its status. The camera pair is confirmed in No Mercy: the camera reader at RAM 0x80011AE8 compares byte 0x0D with the animation timer and returns byte 0x0E once the timer reaches it. The other fields are rated likely. Read as half frames, most labelled columns fall inside the animation's duration in at least 98 percent of records (see the table below); read as whole frames, the same columns drop to 30 to 75 percent.
Revenge's animation 1BCF and No Mercy's 40D5 have byte-identical bone streams, yet their event records differ:
Revenge, animation 1BCF
file 020F, record 3478, 36 B, 13 frames, duration 25 half frames
No Mercy, animation 40D5
file 02BF, record 4860, 36 B, 13 frames, duration 25 half frames
field Revenge 1BCF No Mercy 40D5 status
damage_begin / _end unset unset likely
reversal_begin 8 8 likely
first_vulnerable unset unset likely
breakaway_frame unset unset likely
motion_effect_frame 14 10 likely
camera_effect_frame 0 0 confirmed
camera_effect_value 0 5 confirmed
effect pairs set 1,3,4,5,6 2,6,8 likely
of the 20 bytes the unpacker copies: 18 equal, 2 differ
of the 16 effect bytes: 5 equal, 11 differThis is the usual case. Of the 2202 bone streams Revenge and No Mercy share, only 526 carry an identical header and only 23 an identical event record. The event record belongs to the file id, not to the frames, so a move written into an existing file fires the events of the file it replaced.
How damage is computed#
Damage involves no randomness. I ran each game's hit routine in the interpreter against the cartridge's own memory, and the result is three sums and a clamp. The Checks view tests it per game with 24 to 27 named cases, 1000 swept cases and 200 cases from real ROM data, with zero deviations in all six.
base = the damage field of the move entry
(No Mercy: byte 0x06 of a 36-byte entry; the early games: bits 11..16
of word 0 of a 24-byte entry)
off, def = the two parameter slots the move names, each 0..4
part 1 = (condition[off] + 50) * base / 100 condition 0..50, 50 in special mode
part 2 = (attack[off] - defence[def]) * base / 10 both 1..5, from the parameters
part 3 = (spirit attacker - spirit defender) / 20 only when base is not 0
sum = max(0, part 1) + max(0, part 2) + max(0, part 3)
special mode: sum = trunc(sum * 1.2)
four of the six: sum = trunc(sum * level factor)
HP = min(MaxHP, HP - sum)
MaxHP -= sum / 4 floor 128 in the early three, 64 in the late three
condition[i] -= the move's body-part damage[i], floor 0Part 1 depends on the condition of the attacking body part, part 2 on attack against defence, and part 3 on spirit. A fresh limb has condition 50, which yields exactly the base damage. Special mode fixes the condition at 50 and multiplies by 1.2, so the same move hits harder when the meter is full. No Mercy alone adds a combo bonus: if an entry names a move at bytes 0x1C/0x1D and that move was played last, the base comes from byte 0x1B instead. The later games also have a hold bit, with which the routine computes the sum and takes none of it off health. Every entry with that bit is a pinning hold, such as School Boy or La Mahistral. No Mercy also leaves maximum health alone; in VPW2 and WrestleMania 2000 maximum health still drops.
Four of the six games scale the finished sum by a level factor from a seven-value table, [0.5 0.625 0.75 0.875 1 1.16 1.33]. That its index is the difficulty setting is a hypothesis. VPW2 and No Mercy have no such factor, and the absence is confirmed: the formula without it matches all 1000 swept and 200 real cases.
The formula also sets a ceiling. With damage 255, an attacker in perfect condition with every ability at maximum, spirit 100 against 0 and a defender with nothing, it gives 382 + 255 + 5 = 642 points, or 853 with the highest level factor. A health bar holds 255. Such a hit also removes 160 points of maximum health (213 with the level factor) for the rest of the match.
The flag word#
A move entry of the three later games ends in a 32-bit flag word, at byte 0x20 of No Mercy’s 36-byte entry and at byte 0x1C of the 32-byte entry of VPW2 and WrestleMania 2000. Each bit below is named by the branch in the game’s own code that tests it. The bit numbers and addresses are No Mercy’s; VPW2 and WrestleMania 2000 keep the same bits except where a row says otherwise. Bits 15, 25 and 28 to 31 are clear in every entry of all three games.
| Bit | What the game does with it | Tested at |
|---|---|---|
| 0 | The one grappled can reverse it, with a counter in the lock-up or a roll when the move starts. | 0x80128F84 |
| 1 | The attacker does not go back to his stance when it ends; the move’s ending picks his next state, such as dazed. | 0x80137318 |
| 4 | The one lying under it sells a splash, animation 12106 instead of 12107. Set on the splashes, the Shooting Star Press and the 450. | 0x800E8420 |
| 6 | A knockdown from it rolls the one hit over backward, 12626 instead of a fall on the back, 12565. | 0x80124C1C |
| 7 | A submission hold. While submissions count, the referee goes over to ask for a give-up. No Mercy only. | 0x8013F4A4 |
| 8 | A rope break ends it. With the rule on, the move is broken off once a joint of the one held reaches the ropes. | 0x801376CC |
| 9 | The move ends in a pin. The two go to the pin states 74 and 75 instead of 72 and 73. | 0x800ED02C |
| 11 | The move carries the two to the ropes. | 0x801288EC |
| 12 | The move carries the two to the turnbuckle the attacker faces. | 0x80129524 |
| 13 | The move works on a giant. Without it, against Andre the Giant it turns into record 161 or 159. Clear on the slams, suplexes, powerbombs and piledrivers. Not in WrestleMania 2000. | 0x80128E90 |
| 16 | The two run there, at speed class 8 instead of 2. Set on the Oklahoma Slam and the Sumo Attack. No Mercy only. | 0x80129E50 |
| 17 | The two go to the far corner, across from the nearest one. | 0x80129D0C |
| 18 | The trip ends when the one carried touches the turnbuckle or the ropes, not when the attacker gets there. | 0x80129A48 |
| 20 | The attacker leaps onto the opponent from the lock-up, animation 12099 or 12101, as in the Frankensteiners. | 0x8012763C |
| 21 | The one held cannot crawl to the ropes. Set on the stalling moves, the flurries and the chokes. | 0x80137624 |
| 22 | The move does not track contact with the ropes and turnbuckles. Set on the moves made there and on the flurries. | 0x80137168 |
| 23 | The referee asks for the give-up standing, 12948, instead of kneeling, 12941. No Mercy only. | 0x80135CF8 |
| 27 | The hit takes no health. It is the pinning holds’ bit. Bit 13 in WrestleMania 2000. | 0x80112228 |
The bits are what make a move behave like its kind. A Shooting Star Press without bit 4 lands on a man who does not sell a splash; a hold without bit 8 ignores the rope-break rule; a slam without bit 13 turns into another move against Andre. A move made new in the Move Builder copies the whole entry, flag word included, from the move it takes its damage values from, so it behaves like that move’s kind.
What differs between the six games#
The animation layer barely changed across the series: the same 98-byte frame, the same skeleton and the same angle unit. What changed is everything around the frames.
| World Tour | VPW64 | Revenge | WM2000 | VPW2 | No Mercy | |
|---|---|---|---|---|---|---|
| Product code | NWNE | NVPJ | NW2E | NWXE | NA2J | NW4E |
| Animation files | 2,598 | 4,423 | 4,017 | 4,671 | 6,291 | 5,789 |
| Distinct bone streams | 2,051 | 3,004 | 2,843 | 3,798 | 4,633 | 4,801 |
| Stored frames | 62,675 | 104,372 | 101,150 | 119,818 | 153,300 | 152,778 |
| Longest animation (frames) | 107 | 120 | 128 | 130 | 130 | 130 |
| Re-encoded byte for byte | 2598/2598 | 4423/4423 | 4017/4017 | 4671/4671 | 6291/6291 | 5789/5789 |
| Header kinds seen | 30 | 30 | 33 | 52 | 52 | 48 |
| Event record | 32 B | 32 B | 36 B | 36 B | 36 B | 36 B |
| Event columns that fit | 17 of 18 | 15 of 18 | 17 of 20 | 20 of 20 | 17 of 20 | 20 of 20 |
| Event time unit | likely | likely | likely | likely | likely | confirmed |
| Flip sites with a threshold | 0 of 2 | 0 of 1 | 4 of 4 | 4 of 4 | 4 of 4 | 1 of 1 |
| Display matrix per bone | no | no | no | yes | yes | yes |
| Move names in the game | none | none | none | 1,702 | 2,302 | 2,136 |
| AKI key file | — | — | — | 03B6 | 0280 | 01F8 |
| Damage entry | 24 B | 24 B | 24 B | 32 B | 32 B | 36 B |
| MaxHP floor | 128 | 128 | 128 | 64 | 64 | 64 |
| Level factor in the hit | yes | yes | yes | yes | none | none |
| Heaviest hit the engine computes | 853 | 853 | 853 | 853 | 642 | 642 |
| Max health it removes | 213 | 213 | 213 | 213 | 160 | 160 |
| Can be a transplant target | no | no | no | yes | yes | yes |
Revenge already has the 36-byte event record but keeps the old damage entry and has no move names, so the generations do not split in one place. The level factor ends after WrestleMania 2000, not after Revenge. And the three early games carry no move names at all, which matters for what follows.
Carrying a move to another game#
AKI reused motions between games without changing them, so a motion's identity is its bone stream from byte 4 on. The header bytes were renumbered between generations, and animation ids are local to each game. The Move Editor's reference catalogue links all six games in about a second: a checksum finds candidates, every pair is then compared byte for byte, and across all 30 ordered pairs of games there are no collisions.
| Pair | Files byte-identical | Distinct motions shared | Share of source | Named from target |
|---|---|---|---|---|
| VPW2 to No Mercy | 5,779 of 6,291 | 4,233 | 91 % | 1,472 |
| WM2000 to No Mercy | 4,327 of 4,671 | 3,501 | 92 % | 1,196 |
| Revenge to WM2000 | 3,292 of 4,017 | 2,275 | 80 % | 969 |
| Revenge to No Mercy | 3,179 of 4,017 | 2,202 | 77 % | 879 |
| VPW64 to No Mercy | 1,252 of 4,423 | 857 | 29 % | 289 |
| World Tour to No Mercy | 783 of 2,598 | 615 | 30 % | 141 |
This is what makes a nameless game searchable by name. Writing a move is harder. A target game needs a packed moveset whose loader indexes category lists, a damage table with a name and an AKI key (the move's internal code) per entry, a category list with room to grow, and an event table. WrestleMania 2000 has 129 category lists, 71 of them growable, and 67 writable moveset slots; VPW2 has 133, 73 and 83; No Mercy 138, 83 and 109. The early three name no category lists, so the tool refuses them as targets. That leaves 15 of the 30 ordered pairs.
A Shooting Star Press for Andre the Giant#
Finding the move#
Revenge has no move names. Kidman's roster row points to a moveset file, and the moveset file holds numbers:
Revenge roster index 19 "Kidman" ID2 0x2E ID4 0503 moveset file 0196
moveset slots 397 and 402 both hold 2756
first_move_animation_id 0x110B
0x110B + 2756 0x1BCF
animation 1BCF, as the tool lists it
File 1BCF: 1278 B, 13 frames, 19 bones
Header: base angle 0.000 degrees, kind 0,
duration 25 half frames = 13 played frames
Channels: 19 rotation, 1 absolute translation, 6 relative translationTwo slots hold the same animation because a move usually comes in pairs, one for each side of the ring or a phase and its follow-up. The name comes from No Mercy. The bone stream of 1BCF matches No Mercy's file 40D5 in all 1274 bytes, and No Mercy calls that animation "Shooting Star Press" (AKI key N3804AA1, damage index 1635). Kidman's move is one of 879 Revenge animations named this way.
An unused move in No Mercy#
No Mercy has everything the move needs: the animation, a damage entry, an AKI key, a place in a move category and a menu record. Master move 30D4 (damage index 1635, animation 40D5) sits in category list 98 between "Rios Back Flip Splash" and "Swanton Bomb". Yet across all 101 movesets and 15,857 slots it is used zero times, like "Back Flip Splash 02" and "Dragon Attack" from the same list. Edit mode can give it to a created wrestler, but none of the wrestlers the game ships with has it.
The motion#
Over thirteen frames the pelvis rotates about X from 158.6 to 393.8 degrees, a 235 degree somersault, while its Y and Z angles stay at 0.000 and 179.648. The root rises from a height of 181 to 239 at frame 7, lands at 158, below where it started, and travels 53 units along -z. One axis of rotation and a parabola is exactly what a shooting star press is.
The transplant#
In No Mercy, Andre the Giant's moveset slot 0x106 is a flying attack on a lying opponent and held "Body Splash". The Move Editor reads the Revenge file as 13 keyframes and writes it out again. The new file is also 1278 bytes, and 122 of them differ from the original:
file 1BCF, 1278 B differs after the round trip
4 B header 1 duration 25 -> 24 half frames
988 B 19 x 13 rotations 0 every angle of every bone, to the unit
52 B 13 root translations 0 the root, to the unit
234 B 6 x 13 relative 121 re-derived from the joint offsets
----
122
worst relative deviation: 3 half units
playerProof on the written file: angle deviation 0,
matrix deviation 3.0e-8,
root deviation 0Every rotation and the root carry over exactly. The six relative positions are recomputed from the joint offsets, so they land close to the stored values but not on them; across all 2199 shared Revenge motions the difference is 2 to 25 half units. A transplanted file is therefore never byte-identical to its source.
The tool chose the rest of the wiring itself. It overwrote file 411E, a byte-identical duplicate of 349F with the same event record, so nothing was lost, and re-pointed the one reference to it at the twin. Repacking found the 24 extra bytes the wiring needed and moved 19,352 files. A new master move 307B was appended to category list 97. One of the 89 placeholder damage rows No Mercy ships, named "((( none ok )))", was renamed "Shooting Star Press" and given the AKI id RV3804-A and the values of entry 1635: damage 35, body 3, speed 3, pin 1, spirit gain 10.
The tool's write check passes 18 items, fails none and leaves 2 unmeasured, and 19,449 files outside the plan are unchanged. Three independent programs agree: rom64 and n64crc accept the header checksum for the CIC-6102 boot chip, and a headless mupen64plus boots the clone to frame 200 with the same screen as the original.
What travels and what does not#
So the answer is yes, within limits. The motion travels perfectly: every angle of all 19 bones in all 13 frames arrived with zero error, and so did the root, because a world-space pose means the same thing on any cartridge that reads 98-byte frames. What does not travel is everything that was never in the frames. The event track belongs to the file you overwrite, the damage numbers are a row you choose, and the name lives in yet another file. A move in these games is four things in four places, and only one of them is the motion.
Revenge is an easy source, sharing 77 percent of its motions with No Mercy, while World Tour at 30 percent is a hard one. The clone boots.
What I did not expect was that No Mercy already had the move, animated and given a damage row, a key and a menu line, then assigned to nobody. Someone at AKI built the Shooting Star Press and left it in the box. Twenty-six years later, one byte-for-byte comparison with a Revenge cartridge finds it, and the Move Editor in AKI Anvil can give it to the biggest man in the game in an afternoon.
Naming the moves the early games never named#
World Tour, VPW64 and Revenge name no move: no list of move names turns up in their cartridges, in plain text or in any encoding their fonts suggest. Byte-identical motions carry a name across from No Mercy, but the early games re-made most of their animations, so most motions have no twin. AKI Anvil names them by motion instead. Every motion a moveset plays is compared with every motion No Mercy and WrestleMania 2000 name, with the wrestler's position and facing removed, the other hand mirrored, and time stretched so a slower take still lines up. A name is kept when the nearest named motion is close and clearly closer than the next different name.
The rule was set against motions whose names are known: each named motion of one modern game was predicted from the other with its own copy removed. A likely name is right 87.2 percent of the time (133 checked), a hypothesis 56.3 percent (71 checked), and the Moves view marks every name with the status it earned.
| Motions a moveset plays | World Tour | VPW64 | Revenge | VPW2 |
|---|---|---|---|---|
| Distinct animations | 2,036 | 3,386 | 3,290 | 1,150 |
| Named exactly (byte-identical) | 167 | 329 | 1,268 | 1,087 |
| Named, likely | 766 | 1,183 | 527 | 38 |
| Named, hypothesis | 88 | 135 | 116 | 5 |
| No name close enough | 1,015 | 1,739 | 1,379 | 20 |
The same works for the engine's own motions, the standing, walking and running a wrestler does between moves. No Mercy's code names them: every animation the engine plays passes one setter at 0x8012F848, and watching it in a match ties each file to the action that played it. Those names then travel by motion to the other five games, with one extra cue, because a walk plays in place and only the lifted feet show its direction. Only likely engine names are given; they are right 89.1 percent of the time (64 checked).
With motions named, a move is also one copy and one paste away: the Animations view copies Kidman's Shooting Star Press out of Revenge, and pasting it onto Andre the Giant in No Mercy carries every angle, translates the damage row column by column, and takes the events from the copy of the motion No Mercy already holds.
How I measured this#
Everything here was read from dumps of my own cartridges with AKI Anvil on 11 September 2026, and no ROM bytes are reproduced. The tool grades every statement as confirmed (emulated or re-encoded against a real ROM), likely (the location is pinned but the computation is not), auto (found by search alone) or hypothesis (observed only). The same MIPS interpreter is behind the pin mechanic, the engine ranking and the music format.
| Cartridge | Code | SHA-256 |
|---|---|---|
| WCW vs. nWo: World Tour (USA, rev A) | NWNE | 3711c8838b18374d1c7be0192ad824082d33978f00b886d145bc55a782325d4d |
| Virtual Pro-Wrestling 64 (Japan) | NVPJ | 8b7191ae5489fc71c7a18c05a0afba035a88d8f22a2b047253dd9c524fb88921 |
| WCW/nWo Revenge (USA) | NW2E | 66c137d326565c6f31f992daba8f67c0aee7f025a142dd249d27019708014b60 |
| WWF WrestleMania 2000 (USA) | NWXE | cbd44033868d3747241f5028206056e64836d744c756b5c39dc7b3a446e8ce5b |
| Virtual Pro-Wrestling 2 (Japan) | NA2J | 358e9a345438155c6bd57da4bbf0f7a9fa1b4f7d5b1b726e8076c38f0f987e52 |
| WWF No Mercy (USA, rev A) | NW4E | fc561fce443010b114cc8ea41226772b7b2a2d33055be163fad91ac9c3b096cb |
