Difference between revisions of "Ikari Warriors/Game Mechanics"

From SDA Knowledge Base

Jump to: navigation, search
m (Continue code)
 
(60 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
[[Ikari_Warriors_(NES)]]
 
[[Ikari_Warriors_(NES)]]
 
==Items==
 
==Items==
* F - Your bullets will be able to pass through walls and multiple enemies.
+
'''Pink soldier drops'''<br />
* L - Longer bullet range.
+
* [[File:F_ik1.png]] F - Your bullets will be able to pass through walls and multiple enemies. The bullets can now destroy buildings (but not tanks).
* S - Faster firing rate (bullets).
+
* [[File:L_ik1.png]] L - Longer bullet range.
* B - Grenades will finish with a huge blast upon impact.
+
* [[File:S_ik1.png]] S - Shots will travel faster (bullets and projectiles when in tank or helicopter). Grenades are not affected.
* SS - Your speed on foot is increased.
+
* [[File:B_ik1.png]] B - Grenades will finish with a huge blast upon impact.
* Gun - Bullets are restored to 99.
+
These drops are always fixed. There are a few fake pink soldiers throughout the game that don't drop anything.<br /><br />
* Grenade - +50 grenades
+
 
* Gas can - Bullets are restored to 99, +50 grenades, gas is restored to 99
+
'''Green soldier drops'''<br />
* H - Bullets and grenades are restored to 99 and gas is restored to 199
+
* [[File:K_ik1.png]] K - Smart bomb, kill all the enemies on screen
* Knife - Touching an enemy inflicts damage corresponding to a bullet. Enemies that are immune to bullets will either be rendered harmless (for example the "big men") or will still kill you (helicopters and tanks). The knife also allows you to run through gates destroyable buildings.
+
Green soldiers always drop K.<br /><br />
* Heart - Allows you to keep all collected items if you die or clear the level. Without a heart, you'll start from scratch. Once used, you need to collect another heart.
+
 
* Golden heart - Same as the heart, but gives you all upgrades and replenishes your inventory to the max.
+
'''Tank drops'''<br />
* K - Smart bomb, kill all the enemies on screen
+
* [[File:Gas_can_ik1.png]] Gas can - Bullets are restored to 99, +50 grenades, gas is restored to 99
* Various other items (girl, clock, gold box etc) - Points (useless)
+
Tanks can drop gas cans, a tank or nothing. The type of drop is determined by the RAM-address the tank is allocated to. If the tank gets the first object address, $500, it will drop a tank. If it's in the third object address, $502, it will drop a fuel. For more information about the address allocation of objects and some special cases of drop manipulation, see [[Ikari Warriors (NES)/Fuel drop manipulation|fuel drop manipulation]].<br /><br />
 +
 
 +
'''Destroyable environment (gates, parked trucks, ...) drops'''<br />
 +
* [[File:Gas_can_ik1.png]] Gas can - (explained above)
 +
* [[File:Gun_ik1.png]] Gun - Bullets are restored to 99.
 +
* [[File:Grenades_ik1.png]] Grenades - +50 grenades
 +
The drops from the destroyable environment are always predictable (with the exception of the garbage sprites around the helicopter in area 4).<br /><br />
 +
 
 +
'''Hidden items'''<br />
 +
* [[File:SS_ik1.png]] SS - Your speed on foot is increased.
 +
* [[File:H_ik1.png]] H - Bullets and grenades are restored to 99 and gas is restored to 199.
 +
* [[File:Knife_ik1.png]] Knife - Touching an enemy inflicts damage corresponding to a bullet. Enemies that are immune to bullets will either be rendered harmless (for example the "big men") or will still kill you (helicopters and tanks). The knife also allows you to run through gates and destroyable environment.
 +
* [[File:Heart_ik1.png]] Heart - Allows you to keep all collected items if you die or clear the area. Without a heart, you'll start from scratch. Once used, you need to collect another heart.
 +
* [[File:Golden_heart_ik1.png]] Golden heart - Same as the heart, but gives you all upgrades and replenishes your inventory to the max.
 +
* [[File:Triple_shot_ik1.png]] Triple shot - Replaces L, S and F with a triple shot (similar to the helicopter gun). If you pick up L, S or F again, you'll lose the triple shot and go back to the normal gun with only the power-up you just collected. This power-up must be avoided at absolutely all cost.
 +
* Various other items (girl, clock, gold box etc) - Point items that have no use in a speedrun.
 +
These items are always in the same spot and can only be revealed with the gun or a tank shot.<br /><br />
  
 
Collecting several upgrades of the same kind does nothing more than add points to the total.<br /><br />
 
Collecting several upgrades of the same kind does nothing more than add points to the total.<br /><br />
  
 
==Movement speed==
 
==Movement speed==
Diagonal movement in this game is done at a 45o angle on a flat surface. Slopes change this angle (more about this below). All levels go from bottom to top of the screen so it's important to keep the vertical movement speed up as much as possible. Below ratios are with respect to the foot speed with the SS power for the vertical speed (unless stated otherwise).<br />
+
The speeds below refer to the change in y-position per update cycle (every 4 frames). For the relevant addresses, see the memory address section on this page.<br />
Diagonal/Straight speed ~70% (on a flat surface, regardless of in the water, in a tank etc)<br />
+
Foot (SS) - 3<br />
Foot ~67%<br />
+
Foot (SS) diagonal - first and last frame of diagonal movement: 2 and 196 sub (y) and 1 and 32 sub (x), subsequent diagonal movements: 2 and 28 sub (both x and y)<br />
Tank ~83%<br />
+
Foot water (SS) - 2 and 64 sub<br />
Heli 100%<br />
+
Foot water diagonal (SS) - first and last frame of diagonal movement: 2 and 19 sub (y) and 216 sub (x), subsequent diagonal movements: 1 and 107 sub (both x and y)<br />
Foot (SS) water ~74%<br />
+
Foot (SS) uphill - 2<br />
Foot (SS) uphill slope ~70%<br />
+
Foot - 1 slower than with SS in all vertical scenarios. The y-speed during diagonal movement is however better preserved than with SS.<br />
Foot (SS) uphill diagonally ~55%<br />
+
Tank - 2 and 128 sub<br />
Foot (SS) downhill (horizontal speed)^ ~121%<br />
+
Tank diagonal - first and last frame of diagonal movement: 2 and 78 sub (y) and 240 sub (x), subsequent diagonal movements: 1 and 194 sub (both x and y)<br />
Foot (SS) uphill (horizontal speed)^^ ~61%<br />
+
Heli - speed same as foot (SS)<br />
Foot (SS) diagonally uphill (horizontal speed)^^^ ~45%<br />
+
Heli diagonal - 2 and 28 sub (both x and y), there is no difference between the first and subsequent diagonal movements<br /><br />
Foot (SS) diagonally downhill (horizontal speed)^^^^ ~100%<br /><br />
+
  
^ It's not possible to move in a straight horizontal line on a sideways slope. You will lose 4 units of height for every 10 horizontal units.<br />
+
Some additional comments:
^^ The opposite of ^.<br />
+
* It's faster to save the diagonal movement for when the diagonal speed is higher. For example, it's better to wait until you get out of the water before starting to move diagonally.
^^^ You will gain 12 units of height for every 10 horizontal units.<br />
+
* In terms of traveled distance, the first cycle of diagonal movement is extremely close to subsequent ones in all scenarios. For all practicable purposes, the difference can be neglected. However, the first diagonal movement is still considerably more efficient since it allows you to travel in a straighter line between two points (obviously assuming there are no obstacles impacting the trajectory). As a rule of thumb, one movement frame (so 4 actual frames) is saved by dividing one continuous diagonal movement into 5 segments of diagonal movements. Each such segment will contain two cycles of the more efficient diagonal movement (one at the start and one at the end). Assuming it's in an area without obstacles or enemies that have to be dealt with, there is no downside in dividing the diagonal movement in this way as opposed to a continuous diagonal movement.
^^^^ You will gain 6 units of height for every 10 horizontal units.<br /><br />
+
* In the water areas, it's slightly faster to walk uphill and then on flat ground instead of staying in the water the whole time. This is very marginal though, but still useful in areas 3 and 4.
 
+
* Again in the water areas, you can sometimes walk over corners of slopes. It's slightly faster to walk over the corner (uphill and then downhill) instead of staying in the water.
Some comments on how to use the above for speed considerations:
+
* As a rule of thumb, moving diagonally "one block" (so the width of a bush or an item token) at SS speed costs roughly 2 movement frames of vertical movement.<br /><br />
* Helicopter and foot (with the SS power) speed are equal and the fastest modes of movement.
+
* Diagonal speed is "geometrically correct". Since the diagonal movement is done at 45o, the speed ratio of ~70% corresponds to the inverted square of two as it should be. This also means that diagonal movement should be done when traveling at the fastest movement speed. For example, it's better to wait until you get out of the water to start moving diagonally.
+
* In water areas, it's slightly faster to walk uphill and then downhill again instead of staying in the water the whole time. This is very marginal though and only useful in level 4 (could possibly be used in the water section of level 3 with a new route).<br /><br />
+
  
 
==Glitches==
 
==Glitches==
=Flying glitch=
+
===Flying glitch===
If you hold A, B and up at the same time while in the helicopter (they don't need to start to be pressed down simultaneously, you just need to hold them down at the same time), Paul/Vince will exit the helicopter and continue traveling vertically at helicopter speed as long as A and/or B is kept held down (the glitch doesn't work with the tank). In this state, you're invincible, can't interact with anything in the game (such as collecting items or the terrain) and can't use your weapons. If you let go of A and B, you will either be teleported back to the helicopter (if it's still on screen) or land in a glitched state. Your movement speed will be back to walking speed, but the movement doesn't correspond to the graphical terrain (you'll appear to walk in water while on land, there will be invisible walls etc). You'll still be in the invincible state, you're still unable to collect items or use your weapons. The only way to revert back to normal is to exit the level. This glitch has the potential to completely break the game, but is of limited use with the current knowledge due to some unlucky circumstances:
+
https://www.youtube.com/watch?v=kQF-OpUh99o<br />
- In level 1 you still need to collect 3 items (SS, the knife and the heart) after the helicopter section. If you activate the flying glitch and fly through the whole level and exit, you will start level 2 without any power-ups. This saves 30-40 seconds (obviously depending a lot on what the alternative route was). As a strike of luck, the two most important power-ups, SS and B, are available very early in level 2, making it possible to start building up the character again.<br />
+
If you hold A, B and up at the same time while in the helicopter (they don't need to start to be pressed down simultaneously, you just need to hold them down at the same time), the character will exit the helicopter and continue traveling vertically at helicopter speed as long as A and/or B is kept held down (the glitch doesn't work with the tank). In this state, you're invincible and can't interact with items on the screen.<br />
- There is unfortunately no helicopter in level 2.<br />
+
If you let go of A and B, you will be teleported to the "small y"-position you left the helicopter on. Your hitbox will however still be linked to the helicopter position. If the helicopter is off-screen, this means you're still in the invincible state and unable to interact with the environment (including shots and grenades).<br /><br />
- Since you need to "fight" a boss at the end of level 3 and 4, activating the flying glitch here is essentially the same as soft-locking the game.<br /><br />
+
 
 +
There are two ways to return to the normal state after activating the flying glitch.<br />
 +
- The first is to fly to the end of an area and exit. You will then start the next area in the normal state. Since areas 3 and 4 have bosses at the end, this method only works in area 1 (no helicopter in area 2).<br />
 +
- The other method is to buffer a death when initiating the flying state. Upon breaking the flying state, the player dies and then restarts in the normal state as after a normal death. To buffer a death, the helicopter needs to be destroyed before it's scrolled off-screen. This can either be done by firing a missile just before entering the flying state (so press A slightly before pressing B) or have an enemy destroy the helicopter. The latter can e.g. be done by triggering a kamikaze soldier to explode near the helicopter. This method allows the flying glitch to be used in areas 3 and 4, since the bosses at the end of these areas require you to be in the normal state to defeat them.<br /><br />
 +
 
 +
===Visual glitches===
 +
The game often gets confused when trying to represent the sprites for the item drops if there are several possible drops on the screen available. For example, if you kill a pink guy when there is an item hidden nearby, the pink guy's drop will look like the hidden drop. However, if you pick it up, you will still only get the normal drop from the pink guy and not the hidden drop. You can even have item drops appear as parts of enemies in certain situations. Again, it's only a visual glitch.<br /><br />
 +
 
 +
===Garbage sprites in area 4===
 +
Even when playing normally, the game will create garbage sprites in the area where you find the helicopter in area 4. These sprites can be destroyed and the items they leave behind can be collected (including the much wanted fuel drop that allows you to cruise to the end of the area in the helicopter). They are spawned just like other random enemy soldiers. A plausible, but unconfirmed, explanation is that the game was intended to spawn a different type of enemy (different memory values) in this section. Instead, the corresponding calculation was set up incorrectly and now produces the values for these sprites. Why the memory values correspond to these sprites has not been looked into.<br /><br />
 +
 
 +
==Cheats==
 +
===Area select cheat===
 +
When the game starts, Paul and Vince will walk into the screen from below. Press start (or just wait) and you will see the title screen with the selection of 1 or 2 players. During this screen, press Up, Down, A, A, B, Left, Right, A, B, Up, A, Down, Right, Right, Left, B, Up, Left, A, Right, B, Left, Right, A, Left, Up, A, Down, A, Right, Left, B, and finally press Start. This has to be done before the demo starts playing. Getting the code to work is a small feat in itself. If done correctly, after the cutscene with the crash landing, you will get a black screen with the text "Area 1" (instead of the few seconds of normal black screen before the game starts). By pressing A and B, you can select the area to start at (A increases, B decreases, but it loops so it doesn't matter). Needless to say, you'll start without any upgrades.<br /><br />
 +
 
 +
===Continue code===
 +
One of the most well known continue codes throughout the NES library, A B B A. Just press the button combination after having lost the last life and before the game over screen. In a casual playthrough, it can be expected to input this code 100+ times. In that context, it can be worth highlighting that the game only polls player inputs at the same framerate as the game, i.e. 15fps. When inputting the code that many times in a playthrough, it's not too unlikely that one manages by accident to tap one of the inputs on three frames the game does not poll player inputs, leading to the code not working. Another risk is that two buttons are pressed in too rapid succession. There needs to be an empty input polled by the game between each button press. As long as the game over screen hasn't appeared, one can however attempt again to input the code. To prevent the code from not working, avoid tapping too fast and try instead to hold down each button (but not overlap any button presses).<br /><br />
 +
 
 +
The game checks for player inputs from instruction $FF89 and onward. Each correct button press increases the counter in $58. When it equals 4, the code branches to starting a continue (3 lives back etc).<br />
 +
 
 +
''Note: Pressing 'B' at the wrong time will reset $58 to 0, while pressing 'A' at the wrong time will reset $58 to 1.''<br /><br />
 +
 
 +
When reaching the end of a level (check of $73 at instruction $D1F0) or killing the boss in level 3 or 4, $FB is set to a non-zero value. This skips the ABBA-checking section in the code and continues are no longer possible until starting the next level.<br /><br />
 +
 
 +
There are reports of the ABBA code stopped working in the middle of a level. From the code sections referenced above, it's not clear how that could happen. It's possible that $FB could be written to from other sub-routines, but it's also possible (more likely?) that these reports are from incorrectly inputting the code. If someone manages to record an emulator movie of when the ABBA-code stops working mid-level, please post about it in the forum.<br />
 +
(Credits to 'Fo__' for contributions to the code analysis of this section)<br /><br />
  
 
==Some comments about various aspects of the game mechanics==
 
==Some comments about various aspects of the game mechanics==
=Airstrike target plates=
+
===Airstrike target plates===
Not dangerous themselves, they will trigger an airstrike when you get close to them. Sometimes the airstrikes come so quickly that it's literally not possible to avoid it. Sometimes it will take a while. The angle of attack is also different from time to time. The best way to understand this is to think of a steady stream of (invisible) bombers passing by from left to right. Their position when the target plate is activated determines the angle of attack and the speed. Once they cycled through from left to right (roughly 1000 frames), their distance will also be different. It hasn't been investigated how long time before the distance from the target plate is cycled back. While this information provides some understanding for what at first seems to be a random game mechanics, there is no known way to manipulate the airstrikes to not be undodgeable. The only way to mitigate the risk is to try and minimize the critical places where you have to travel next to or through these target plates.
+
[[File:Target_plate_ik1.png]]<br />
=Arrow shooting rocks=
+
Not dangerous themselves, they will trigger an airstrike when you get close to them. Every 16 movement frames (so 64 actual frames), the game will poll if you're in the vicinity of the target plate and then launch an airstrike. This actually leaves a little room to run past without triggering the airstrike, but it's too precise to be manipulable in real-time.<br />
These shoot arrows horizontally through a small hole in the side. The interval between arrows is not understood, but arriving at different time windows (very roughly 100 frames) will result in different arrow patterns. There is lots of randomness with these enemies, but also some individual behavior that can be taken advantage of.
+
* The airstrike's starting x-position is equal to the value of the global counter in $55 (0 being the far left of the screen and 255 being the far right). Since it takes 17 seconds (256*4/60.1) to cycle through all values, you're going to have a pretty good idea of where to expect an airstrike from in a speedrun setting, where you can assume to be at a specific point at a particular time with a fairly good accuracy.
=Vehicles=
+
* The airstrike's starting y-position is the top of the screen when the game polls for the character being within range of the target plate. Generally, it's not possible to predict the starting y-position as the RAM-address used for polling the airstrike ($65C, but neighboring addresses might also be possible?) is not reset or initialized before being used.<br />
- Entering a vehicle creates an immobility of around 1 second.<br />
+
Both the starting x- and y-position of the airstrike are of interest.<br />
- Leaving a vehicle creates an immobility of only a few frames (seems to vary a bit, but less than 10).<br />
+
* If the airstrike was launched from the side of the screen (so starting x-position either very low or very high), it might not reach the target plate before the target plate is scrolled off-screen. The airstrike will then target the spot with the same small y-position as the target plate had. If a new enemy or item appears and takes over the target plate's RAM-addresses, the airstrike will target that instead. While this can lead to some funny-looking moments, it usually poses a threat to the player because of the resulting explosion.
- If you approach a vehicle while holding down the A-button (the grenade button), you will enter the vehicle on the first possible frame.
+
* If the airstrike was launched more or less vertically and it was triggered early by the player, it can in worst case be impossible to dodge.
=Sprite limit=
+
Both of these unwanted cases can be routed out in a speedrun if the pace is sufficiently close between attempts. This is done by waiting at the start screen for a pre-defined amount of time to manipulate the starting x-position of the airstrikes. It would be helpful if there were a way to manipulate the starting y-position as well, but it's hard to see how that would be possible in real-time.
The game has a sprite limit that frequently comes into play. Enemies that are supposed to spawn in a certain area, but are prevented from doing so because of the sprite limit, will appear out of nowhere when one of the other sprites has disappeared off-screen. It hasn't been investigated in detail the exact rules for the sprite limit, but for the individual sections where it makes a difference, it's often easy enough to understand the triggers. The sprite limit (and the generally slow speed of the game - 15 fps!) means that lag is almost non-existant.
+
 
=RNG=
+
===Arrow-shooting rocks===
The game appears to use a fairly simple rng-algorithm. Some enemy types appearances seem to be fixed (although they can sometimes be missing) and some appear to spawn more randomly (but still restricted to certain areas). One of the random enemy types, the blue soldiers equipped with normal guns, move about in what at first seems to be a random pattern. However, even if it hasn't been investigated exactly how it works, it's quite evident by observations that some enemy movements repeat themselves too often for it to be random. It would take a lot of dedication to map out all those possible enemy patterns in all areas of the game and then what to respond in each case. Still, it's worth keep this in mind if there is a particular section, where the enemy movements come into play.
+
[[File:Arrow_shooting_rock_ik1.png]]<br />
 +
These shoot arrows horizontally through a small hole in the side. It hasn't been investigated in detail what determines whether this enemy shoots an arrow or not at a given time and position. Without a more detailed analysis of the underlying mechanics, there is a fair amount of randomness involved with dealing with these enemies, but also some individual behavior that can be taken advantage of (some can be ran past without risk, while others seem to be more aggressive and start firing arrows even when the player is quite far away).<br /><br />
 +
 
 +
===Vehicles===
 +
: - Entering a vehicle creates an immobility of around 1 second.<br />
 +
: - Leaving a vehicle creates an immobility of only a few frames (seems to vary a bit, but less than 10).<br />
 +
: - If you approach a vehicle while holding down the A-button (the grenade button), you will enter the vehicle on the first possible frame.<br />
 +
: - Changing direction of the tank cannon costs a minimum of 4 frames (because of the game running at 15 fps), but in practice costs more like 8 frames.<br /><br />
 +
 
 +
===Sprite limit===
 +
The game has a sprite limit that frequently comes into play. Enemies that are supposed to spawn in a certain area, but are prevented from doing so because of the sprite limit, will appear out of nowhere when one of the other sprites has disappeared off-screen. This can readily be studied for a section by looking how the object address values are attributed (see memory address $0500 and onwards). The sprite limit (and the generally slow speed of the game - 15 fps!) means that lag is not an issue in the game.<br /><br />
 +
 
 +
==='Half-diagonal' shots===
 +
Other than the 8 standard directions (4 straight and 4 diagonal), the game allows you, when on foot, to shoot in the 8 directions in-between, here called 'half-diagonals'. Getting these additional directions allows for time savers in several areas. To get a 'half-diagonal' shot, you need to shoot (press B) and change movement direction between straight and diagonal between two consecutive frame updates in the game. Since the game runs at 15 fps, this is therefore a 1-4 frame trick (depending on which of the "in-between" frames you initiate the trick).<br /><br />
 +
 
 +
===Enemy AI===
 +
The game appears to use a fairly simple RNG-algorithm. Some enemy types appearances seem to be fixed (although they can sometimes be missing) and some appear to spawn more randomly (but still restricted to certain areas). One of the random enemy types, the blue soldiers equipped with normal guns, move about in what at first seems to be a random pattern. However, even if it hasn't been investigated exactly how it works, it's quite evident by observations that some enemy movements repeat themselves too often for it to be random. The following clip demonstrates this effect: https://www.youtube.com/watch?v=gIFoTTkVTRM<br />
 +
The movement direction of the enemies is stored in addresses $63E and onwards. A study of how the code changes the values of these addresses has not been done.<br /><br />
 +
 
 +
==Memory addresses==
 +
Some addresses are mentioned in the respective relevant sections on this page. Below is a selection of addresses that have been identified during code analysis.
 +
 
 +
* $55 - Global counter that determines several random events/parameters in the game. The counter starts from 0 at the start screen (when you have the choice between 1 and 2 players). It then runs continuously, except for fixed breaks when the screen turns black (when the game starts and during the transition between areas). The value can at any given time, t1, be calculated with the following formula: [$55]=(t1-t0-55-142-x*840)/4, where t0 is 4 frames before $55 changed to 1 on the start screen and x is the number of area transitions.
 +
* $65 - Flag for two players
 +
* $73/$72 - Big/Small level progress
 +
* $74 - Relative position compared to the center of the screen (y-direction) (probably telling the game if the screen should be scrolled and/or if the level progress should increase)
 +
* $51C - Object screen position y (mid)
 +
* $6FC - Level flag (0 - level 1; 1 -level 2 etc)
 +
<br />
 +
 
 +
The below analysis of the memory addresses was made by TaoTao in http://tasvideos.org/forum/posting.php?mode=quote&p=450038.<br />
 +
<u>RAM</u><br />
 +
* $3D U8 $2000 mirror
 +
* $3E U8 $2001 mirror
 +
* $3F U8 $2005 x mirror
 +
* $40 U8 $2005 y mirror
 +
* $41 U8 tmp variable for input reading
 +
* $42 U8 tmp variable for input reading
 +
* $43/$45 U8 P1/P2 input, ABSTUDLR
 +
* $44/$46 U8 P1/P2 input modified, suppress continuous A
 +
* $6A U8 current sprite buffer page, 2..3
 +
* $E4/$E5 U8 P1/P2 life
 +
 
 +
$0200-$02FF    Sprite[64]      sprite buffer 1<br />
 +
$0300-$03FF    Sprite[64]      sprite buffer 2<br /><br />
 +
 
 +
- In object list, index 0 means player1, index 1 means player2.<br />
 +
- Object position seems to be signed 24-bit (lower 8-bit is subpixel).<br />
 +
- Calculation of y-position is weird a bit (see $DD02).<br /><br />
 +
 
 +
$04FE-  U8[]    object type etc?        # 0:not-exist<br />
 +
$0576-  U8[]    object position x mid<br />
 +
$0594-  U8[]    object position y lo    # subpx<br />
 +
$05B0-  U8[]    object position y mid<br />
 +
$05CC-  U8[]    object position y hi<br />
 +
$05E8-  U8[]    object position x lo    # subpx<br />
 +
$0604-  U8[]    object position x hi<br />
 +
$063C-  U8[]    object direction        # 0..15<br />
 +
$0674-  U8[]    object drop-related value<br />
 +
$067F/$0680  U8      P1/P2 ammo of gun<br />
 +
$0681/$0682  U8      P1/P2 ammo of grenade<br />
 +
 
 +
<u>ROM</u><br />
 +
$C271  code    read inputs<br />
 +
$D97E  code    check if object list is full?<br />
 +
$DC9E  code    calculate object velocity?<br />
 +
$DD02  code    move object<br />
 +
$DDF9  code    multiplication (S24 * U8 -> S24)

Latest revision as of 01:46, 2 June 2024

Ikari_Warriors_(NES)

Items

Pink soldier drops

  • F ik1.png F - Your bullets will be able to pass through walls and multiple enemies. The bullets can now destroy buildings (but not tanks).
  • L ik1.png L - Longer bullet range.
  • S ik1.png S - Shots will travel faster (bullets and projectiles when in tank or helicopter). Grenades are not affected.
  • B ik1.png B - Grenades will finish with a huge blast upon impact.

These drops are always fixed. There are a few fake pink soldiers throughout the game that don't drop anything.

Green soldier drops

  • K ik1.png K - Smart bomb, kill all the enemies on screen

Green soldiers always drop K.

Tank drops

  • Gas can ik1.png Gas can - Bullets are restored to 99, +50 grenades, gas is restored to 99

Tanks can drop gas cans, a tank or nothing. The type of drop is determined by the RAM-address the tank is allocated to. If the tank gets the first object address, $500, it will drop a tank. If it's in the third object address, $502, it will drop a fuel. For more information about the address allocation of objects and some special cases of drop manipulation, see fuel drop manipulation.

Destroyable environment (gates, parked trucks, ...) drops

  • Gas can ik1.png Gas can - (explained above)
  • Gun ik1.png Gun - Bullets are restored to 99.
  • Grenades ik1.png Grenades - +50 grenades

The drops from the destroyable environment are always predictable (with the exception of the garbage sprites around the helicopter in area 4).

Hidden items

  • SS ik1.png SS - Your speed on foot is increased.
  • H ik1.png H - Bullets and grenades are restored to 99 and gas is restored to 199.
  • Knife ik1.png Knife - Touching an enemy inflicts damage corresponding to a bullet. Enemies that are immune to bullets will either be rendered harmless (for example the "big men") or will still kill you (helicopters and tanks). The knife also allows you to run through gates and destroyable environment.
  • Heart ik1.png Heart - Allows you to keep all collected items if you die or clear the area. Without a heart, you'll start from scratch. Once used, you need to collect another heart.
  • Golden heart ik1.png Golden heart - Same as the heart, but gives you all upgrades and replenishes your inventory to the max.
  • Triple shot ik1.png Triple shot - Replaces L, S and F with a triple shot (similar to the helicopter gun). If you pick up L, S or F again, you'll lose the triple shot and go back to the normal gun with only the power-up you just collected. This power-up must be avoided at absolutely all cost.
  • Various other items (girl, clock, gold box etc) - Point items that have no use in a speedrun.

These items are always in the same spot and can only be revealed with the gun or a tank shot.

Collecting several upgrades of the same kind does nothing more than add points to the total.

Movement speed

The speeds below refer to the change in y-position per update cycle (every 4 frames). For the relevant addresses, see the memory address section on this page.
Foot (SS) - 3
Foot (SS) diagonal - first and last frame of diagonal movement: 2 and 196 sub (y) and 1 and 32 sub (x), subsequent diagonal movements: 2 and 28 sub (both x and y)
Foot water (SS) - 2 and 64 sub
Foot water diagonal (SS) - first and last frame of diagonal movement: 2 and 19 sub (y) and 216 sub (x), subsequent diagonal movements: 1 and 107 sub (both x and y)
Foot (SS) uphill - 2
Foot - 1 slower than with SS in all vertical scenarios. The y-speed during diagonal movement is however better preserved than with SS.
Tank - 2 and 128 sub
Tank diagonal - first and last frame of diagonal movement: 2 and 78 sub (y) and 240 sub (x), subsequent diagonal movements: 1 and 194 sub (both x and y)
Heli - speed same as foot (SS)
Heli diagonal - 2 and 28 sub (both x and y), there is no difference between the first and subsequent diagonal movements

Some additional comments:

  • It's faster to save the diagonal movement for when the diagonal speed is higher. For example, it's better to wait until you get out of the water before starting to move diagonally.
  • In terms of traveled distance, the first cycle of diagonal movement is extremely close to subsequent ones in all scenarios. For all practicable purposes, the difference can be neglected. However, the first diagonal movement is still considerably more efficient since it allows you to travel in a straighter line between two points (obviously assuming there are no obstacles impacting the trajectory). As a rule of thumb, one movement frame (so 4 actual frames) is saved by dividing one continuous diagonal movement into 5 segments of diagonal movements. Each such segment will contain two cycles of the more efficient diagonal movement (one at the start and one at the end). Assuming it's in an area without obstacles or enemies that have to be dealt with, there is no downside in dividing the diagonal movement in this way as opposed to a continuous diagonal movement.
  • In the water areas, it's slightly faster to walk uphill and then on flat ground instead of staying in the water the whole time. This is very marginal though, but still useful in areas 3 and 4.
  • Again in the water areas, you can sometimes walk over corners of slopes. It's slightly faster to walk over the corner (uphill and then downhill) instead of staying in the water.
  • As a rule of thumb, moving diagonally "one block" (so the width of a bush or an item token) at SS speed costs roughly 2 movement frames of vertical movement.

Glitches

Flying glitch

https://www.youtube.com/watch?v=kQF-OpUh99o
If you hold A, B and up at the same time while in the helicopter (they don't need to start to be pressed down simultaneously, you just need to hold them down at the same time), the character will exit the helicopter and continue traveling vertically at helicopter speed as long as A and/or B is kept held down (the glitch doesn't work with the tank). In this state, you're invincible and can't interact with items on the screen.
If you let go of A and B, you will be teleported to the "small y"-position you left the helicopter on. Your hitbox will however still be linked to the helicopter position. If the helicopter is off-screen, this means you're still in the invincible state and unable to interact with the environment (including shots and grenades).

There are two ways to return to the normal state after activating the flying glitch.
- The first is to fly to the end of an area and exit. You will then start the next area in the normal state. Since areas 3 and 4 have bosses at the end, this method only works in area 1 (no helicopter in area 2).
- The other method is to buffer a death when initiating the flying state. Upon breaking the flying state, the player dies and then restarts in the normal state as after a normal death. To buffer a death, the helicopter needs to be destroyed before it's scrolled off-screen. This can either be done by firing a missile just before entering the flying state (so press A slightly before pressing B) or have an enemy destroy the helicopter. The latter can e.g. be done by triggering a kamikaze soldier to explode near the helicopter. This method allows the flying glitch to be used in areas 3 and 4, since the bosses at the end of these areas require you to be in the normal state to defeat them.

Visual glitches

The game often gets confused when trying to represent the sprites for the item drops if there are several possible drops on the screen available. For example, if you kill a pink guy when there is an item hidden nearby, the pink guy's drop will look like the hidden drop. However, if you pick it up, you will still only get the normal drop from the pink guy and not the hidden drop. You can even have item drops appear as parts of enemies in certain situations. Again, it's only a visual glitch.

Garbage sprites in area 4

Even when playing normally, the game will create garbage sprites in the area where you find the helicopter in area 4. These sprites can be destroyed and the items they leave behind can be collected (including the much wanted fuel drop that allows you to cruise to the end of the area in the helicopter). They are spawned just like other random enemy soldiers. A plausible, but unconfirmed, explanation is that the game was intended to spawn a different type of enemy (different memory values) in this section. Instead, the corresponding calculation was set up incorrectly and now produces the values for these sprites. Why the memory values correspond to these sprites has not been looked into.

Cheats

Area select cheat

When the game starts, Paul and Vince will walk into the screen from below. Press start (or just wait) and you will see the title screen with the selection of 1 or 2 players. During this screen, press Up, Down, A, A, B, Left, Right, A, B, Up, A, Down, Right, Right, Left, B, Up, Left, A, Right, B, Left, Right, A, Left, Up, A, Down, A, Right, Left, B, and finally press Start. This has to be done before the demo starts playing. Getting the code to work is a small feat in itself. If done correctly, after the cutscene with the crash landing, you will get a black screen with the text "Area 1" (instead of the few seconds of normal black screen before the game starts). By pressing A and B, you can select the area to start at (A increases, B decreases, but it loops so it doesn't matter). Needless to say, you'll start without any upgrades.

Continue code

One of the most well known continue codes throughout the NES library, A B B A. Just press the button combination after having lost the last life and before the game over screen. In a casual playthrough, it can be expected to input this code 100+ times. In that context, it can be worth highlighting that the game only polls player inputs at the same framerate as the game, i.e. 15fps. When inputting the code that many times in a playthrough, it's not too unlikely that one manages by accident to tap one of the inputs on three frames the game does not poll player inputs, leading to the code not working. Another risk is that two buttons are pressed in too rapid succession. There needs to be an empty input polled by the game between each button press. As long as the game over screen hasn't appeared, one can however attempt again to input the code. To prevent the code from not working, avoid tapping too fast and try instead to hold down each button (but not overlap any button presses).

The game checks for player inputs from instruction $FF89 and onward. Each correct button press increases the counter in $58. When it equals 4, the code branches to starting a continue (3 lives back etc).

Note: Pressing 'B' at the wrong time will reset $58 to 0, while pressing 'A' at the wrong time will reset $58 to 1.

When reaching the end of a level (check of $73 at instruction $D1F0) or killing the boss in level 3 or 4, $FB is set to a non-zero value. This skips the ABBA-checking section in the code and continues are no longer possible until starting the next level.

There are reports of the ABBA code stopped working in the middle of a level. From the code sections referenced above, it's not clear how that could happen. It's possible that $FB could be written to from other sub-routines, but it's also possible (more likely?) that these reports are from incorrectly inputting the code. If someone manages to record an emulator movie of when the ABBA-code stops working mid-level, please post about it in the forum.
(Credits to 'Fo__' for contributions to the code analysis of this section)

Some comments about various aspects of the game mechanics

Airstrike target plates

Target plate ik1.png
Not dangerous themselves, they will trigger an airstrike when you get close to them. Every 16 movement frames (so 64 actual frames), the game will poll if you're in the vicinity of the target plate and then launch an airstrike. This actually leaves a little room to run past without triggering the airstrike, but it's too precise to be manipulable in real-time.

  • The airstrike's starting x-position is equal to the value of the global counter in $55 (0 being the far left of the screen and 255 being the far right). Since it takes 17 seconds (256*4/60.1) to cycle through all values, you're going to have a pretty good idea of where to expect an airstrike from in a speedrun setting, where you can assume to be at a specific point at a particular time with a fairly good accuracy.
  • The airstrike's starting y-position is the top of the screen when the game polls for the character being within range of the target plate. Generally, it's not possible to predict the starting y-position as the RAM-address used for polling the airstrike ($65C, but neighboring addresses might also be possible?) is not reset or initialized before being used.

Both the starting x- and y-position of the airstrike are of interest.

  • If the airstrike was launched from the side of the screen (so starting x-position either very low or very high), it might not reach the target plate before the target plate is scrolled off-screen. The airstrike will then target the spot with the same small y-position as the target plate had. If a new enemy or item appears and takes over the target plate's RAM-addresses, the airstrike will target that instead. While this can lead to some funny-looking moments, it usually poses a threat to the player because of the resulting explosion.
  • If the airstrike was launched more or less vertically and it was triggered early by the player, it can in worst case be impossible to dodge.

Both of these unwanted cases can be routed out in a speedrun if the pace is sufficiently close between attempts. This is done by waiting at the start screen for a pre-defined amount of time to manipulate the starting x-position of the airstrikes. It would be helpful if there were a way to manipulate the starting y-position as well, but it's hard to see how that would be possible in real-time.

Arrow-shooting rocks

Arrow shooting rock ik1.png
These shoot arrows horizontally through a small hole in the side. It hasn't been investigated in detail what determines whether this enemy shoots an arrow or not at a given time and position. Without a more detailed analysis of the underlying mechanics, there is a fair amount of randomness involved with dealing with these enemies, but also some individual behavior that can be taken advantage of (some can be ran past without risk, while others seem to be more aggressive and start firing arrows even when the player is quite far away).

Vehicles

- Entering a vehicle creates an immobility of around 1 second.
- Leaving a vehicle creates an immobility of only a few frames (seems to vary a bit, but less than 10).
- If you approach a vehicle while holding down the A-button (the grenade button), you will enter the vehicle on the first possible frame.
- Changing direction of the tank cannon costs a minimum of 4 frames (because of the game running at 15 fps), but in practice costs more like 8 frames.

Sprite limit

The game has a sprite limit that frequently comes into play. Enemies that are supposed to spawn in a certain area, but are prevented from doing so because of the sprite limit, will appear out of nowhere when one of the other sprites has disappeared off-screen. This can readily be studied for a section by looking how the object address values are attributed (see memory address $0500 and onwards). The sprite limit (and the generally slow speed of the game - 15 fps!) means that lag is not an issue in the game.

'Half-diagonal' shots

Other than the 8 standard directions (4 straight and 4 diagonal), the game allows you, when on foot, to shoot in the 8 directions in-between, here called 'half-diagonals'. Getting these additional directions allows for time savers in several areas. To get a 'half-diagonal' shot, you need to shoot (press B) and change movement direction between straight and diagonal between two consecutive frame updates in the game. Since the game runs at 15 fps, this is therefore a 1-4 frame trick (depending on which of the "in-between" frames you initiate the trick).

Enemy AI

The game appears to use a fairly simple RNG-algorithm. Some enemy types appearances seem to be fixed (although they can sometimes be missing) and some appear to spawn more randomly (but still restricted to certain areas). One of the random enemy types, the blue soldiers equipped with normal guns, move about in what at first seems to be a random pattern. However, even if it hasn't been investigated exactly how it works, it's quite evident by observations that some enemy movements repeat themselves too often for it to be random. The following clip demonstrates this effect: https://www.youtube.com/watch?v=gIFoTTkVTRM
The movement direction of the enemies is stored in addresses $63E and onwards. A study of how the code changes the values of these addresses has not been done.

Memory addresses

Some addresses are mentioned in the respective relevant sections on this page. Below is a selection of addresses that have been identified during code analysis.

  • $55 - Global counter that determines several random events/parameters in the game. The counter starts from 0 at the start screen (when you have the choice between 1 and 2 players). It then runs continuously, except for fixed breaks when the screen turns black (when the game starts and during the transition between areas). The value can at any given time, t1, be calculated with the following formula: [$55]=(t1-t0-55-142-x*840)/4, where t0 is 4 frames before $55 changed to 1 on the start screen and x is the number of area transitions.
  • $65 - Flag for two players
  • $73/$72 - Big/Small level progress
  • $74 - Relative position compared to the center of the screen (y-direction) (probably telling the game if the screen should be scrolled and/or if the level progress should increase)
  • $51C - Object screen position y (mid)
  • $6FC - Level flag (0 - level 1; 1 -level 2 etc)


The below analysis of the memory addresses was made by TaoTao in http://tasvideos.org/forum/posting.php?mode=quote&p=450038.
RAM

  • $3D U8 $2000 mirror
  • $3E U8 $2001 mirror
  • $3F U8 $2005 x mirror
  • $40 U8 $2005 y mirror
  • $41 U8 tmp variable for input reading
  • $42 U8 tmp variable for input reading
  • $43/$45 U8 P1/P2 input, ABSTUDLR
  • $44/$46 U8 P1/P2 input modified, suppress continuous A
  • $6A U8 current sprite buffer page, 2..3
  • $E4/$E5 U8 P1/P2 life

$0200-$02FF Sprite[64] sprite buffer 1
$0300-$03FF Sprite[64] sprite buffer 2

- In object list, index 0 means player1, index 1 means player2.
- Object position seems to be signed 24-bit (lower 8-bit is subpixel).
- Calculation of y-position is weird a bit (see $DD02).

$04FE- U8[] object type etc? # 0:not-exist
$0576- U8[] object position x mid
$0594- U8[] object position y lo # subpx
$05B0- U8[] object position y mid
$05CC- U8[] object position y hi
$05E8- U8[] object position x lo # subpx
$0604- U8[] object position x hi
$063C- U8[] object direction # 0..15
$0674- U8[] object drop-related value
$067F/$0680 U8 P1/P2 ammo of gun
$0681/$0682 U8 P1/P2 ammo of grenade

ROM
$C271 code read inputs
$D97E code check if object list is full?
$DC9E code calculate object velocity?
$DD02 code move object
$DDF9 code multiplication (S24 * U8 -> S24)

Personal tools