Difference between revisions of "Cv1/tricks"

From Castlevania Speedrunning
Jump to: navigation, search
m (fix typo)
m
 
(2 intermediate revisions by the same user not shown)
Line 155: Line 155:
 
*Stage 14-2
 
*Stage 14-2
  
=== Enemy Patterns ===
+
=== RNG ===
A lot of enemy patterns are only a function of how many frames have elapsed since the start of the screen and Simon's current position on screen. This allows for pattern manipulation on enemies such as the Bat Boss, Birds, and the Mummies.
+
==== In Summary ====
White Skeletons are also affected by RNG on top of the factors mentioned above. Notably, they have a set amount of patterns (sometimes a single possible pattern) depending on those two factors. The exact pattern gets chosen at random. This allows for a smaller extent of manipulation.
+
Some enemy patterns are only a function of how many frames have elapsed since the start of the screen and Simon's current position on screen. This allows for pattern manipulation on enemies such as the Bat Boss and the Mummies.
 +
Other enemies patterns instead, on top of Simon's current position on screen, depend on RNG.<br />
 +
The RNG algorithm is a factor of the previous RNG value, as well as how many frames have elapsed since the start of the screen. On certain frames, the RNG value can be very predictable. This allows for a smaller extent of manipulation, for example on white skeletons, by simply losing a certain amount of frames before ancountering said enemies. This can force them into a limited set of patterns chosen at random, or sometimes even a single possible pattern.
 +
 
 +
==== The Technical Version ====
 +
In Castlevania, whenever the code is finished doing everything it needed to do for the current frame, it enters an idle loop while waiting for the NMI interrupt to occur, signaling the start of the next frame. During this idle loop, the RNG value gets advanced over and over. Here's the code of the idle loop (taken from [https://github.com/josephstevenspgh/Castlevania-Labelled-Disassembly this public disassembly]):
 +
 +
<nowiki>Legend:
 +
CurrentRandomBonusId = $6F
 +
FrameCounter = $1A
 +
BonusTable = $C03F
 +
 
 +
MainLoop
 +
$C030  A5 6F:      lda CurrentRandomBonusId
 +
$C032  05 1A:      ora FrameCounter
 +
$C034  29 0F:      and #$0F
 +
$C036  A8:          tay
 +
$C037  B9 3F C0:    lda BonusTable,y
 +
$C03A  85 6F:      sta CurrentRandomBonusId
 +
$C03C  4C 30 C0:    jmp MainLoop
 +
 
 +
BonusTable
 +
$C03F              .byte $33,$BB,$3F,$80,$2E,$A9,$61,$87,$AD,$C3,$B2,$C8,$7C,$25,$48,$7A</nowiki>
 +
 
 +
On one hand, the fact that the RNG algorithm is placed in the idle loop can make it very hard to manipulate its value, because the length of this loop will be affected by how many things the game has already processed on that frames, where in the loop the NMI interrupt happened on the previous frame (since it will resume exactly where it left off on the next frame), as well as CPU/PPU sync (which is deterministic on most emulators but random on a real console).<br />
 +
On the other hand, this RNG algorithm is extremely prone to getting stuck on either a single value, or a very limited set of values. In other words, the idle loop will pretty much always loop over a limited set of values. There are even values from the BonusTable array that are never going to get picked.<br />
 +
On top of that, the RNG value will always reset every 16 frames (to value 0x7A). This gives the value that the RNG will assume a degree of predictability.
 +
 
 +
Assuming the loop runs for at least a few interations (which it pretty much always does, outside of laggy areas), here is a list of all the possible value that the RNG can contain on any of the 16 values of the room's frame counter:
 +
 
 +
<nowiki>Legend:
 +
The value on the left represents the value of the current room's frame counter, modulo 16 (since that's what the RNG algorithm uses), as well as the conditions that have to be met for the values stated on the right to potentially  occur (which is essentially a specific value from the previous frame).
 +
The value(s) on the right represent the set of possible values that the RNG could contain at the end of the idle loop, on the specific frame and conditions specified.
 +
 +
* = Regardless of previous value
 +
if 0xXX = If the value from the previous frame was 0xXX
 +
 
 +
0x0: 0x7A, 0x3F, 0xB2
 +
 
 +
0x1, *: 0xC8, 0xC3, 0x80, 0xBB
 +
 
 +
0x2, *: 0xB2, 0x3F, 0x7A
 +
 
 +
0x3, if 0xB2: 0x80
 +
0x3, if 0x3F: 0xC8
 +
0x3, if 0x7A: 0xC8
 +
 
 +
0x4, *: 0x7C
 +
 
 +
0x5, *: 0x25, 0xA9
 +
 
 +
0x6, if 0x25: 0x87
 +
0x6, if 0xA9: 0x48
 +
 
 +
0x7, if 0x87: 0x87
 +
0x7, if 0x48: 0x7A
 +
 
 +
0x8, *: 0xB2
 +
 
 +
0x9, *: 0xC8, 0xC3
 +
 
 +
0xA, *: 0xB2
 +
 
 +
0xB, *: 0xC8
 +
 
 +
0xC, *: 0x7C
 +
 
 +
0xD, *: 0x25
 +
 
 +
0xE, *: 0x48
 +
 
 +
0xF, *: 0x7A</nowiki>
 +
 
 +
These values will then be read on demand by an enemy, which will determine their pattern (interpreted in a unique way for every enemy). Note that this RNG read will not additionally advance the RNG.<br />
 +
For a practical example, with the standard strat of entering Dracula's room without losing any frames, Dracula's pattern will be determined with the frame counter reading 0xC7.<br />
 +
On this frame, the possible values are either 0x87 or 0x7A. If it reads 0x87, this will make Dracula do the fast fireball pattern, while if it reads 0x7A, this will make Dracula do the slow fireball pattern. This essentially makes either pattern a 50% chance that is impossible to control in an RTA setting.
 +
 
 +
=== Score Management ===
 +
In some games, having certain scores can cause more lag due to the game having to spend more computations to display it on screen.<br />
 +
In Castlevania, this is not the case. The current score is stored in memory in a "decimal" format, which makes it fairly quick for the game to then display it on screen and also makes it the same speed for any combination of digits.<br />
 +
On the other hand, the moment points are acquired, there could be a little bit of variance in the amount of computations performed depending on the current score and the score added, but this is usually just a handful of CPU cycles in total, which is pretty negligible.<br />
 +
The bottom line is, score doesn't really matter for lag in Castlevania.
 +
 
  
 
=== Additional Links ===
 
=== Additional Links ===
 
*[http://tasvideos.org/GameResources/NES/Castlevania.html TASVideos tricks page]
 
*[http://tasvideos.org/GameResources/NES/Castlevania.html TASVideos tricks page]

Latest revision as of 13:12, 1 November 2023

This page could use some gifs and pictures

Movement

Simon moves at a consistent 1 pixel per frame. Walking is the same speed as jumping. While traveling on stairs, he moves more slowly. A damage boost has Simon travel at 1 pixel per frame, but loses 23 (22? needs confirmation) frames to hit and recovery frames. Whipping or using a subweapon takes 23 frames on the ground or 22 frames while in the air. If landing with an attack, Simon will not be able to move until the attack animation is over.
If falling or jumping off of a 4-block height or higher, Simon goes into a clunk animation which loses 16 frames. This can be prevent by whipping on landing (can only be done off of a jump), as the whip animation takes precedence over the clunk. The earlier the whip, the less frames Simon has to spend locked on the ground on landing. With a perfect whip, zero frames can be lost from the landing.
Falling off a small height loses 2 frames. This can be avoided by simply jumping over it.

Staircases

When pressing up in proximity of stairs, Simon gets pulled towards them and stars climbing the first step. It's possible to do this movement more optimally by pushing up while perfectly below stairs, instead of while in proximity.
When approaching stairs frontally (such as the ending staircase in stage 01), the timed up press saves time on a 2-frame window, where the first frame save either 1 or 2 frames, and the second frame saves either 2 or 3 frames. If late on the up press, 1 frame is lost if late by one frame, 3 frames are lost if late by two frames, 5 frames are lost if late by three frames, and so on.
When approaching stairs from the back (such as the staircase in stage 07-1), the timed up press saves either 1 or 2 frames on a 1-frame window, and being late still loses time. This is not recommended on these stairs.
It's also possible to achieve this time save with a jump that lands Simon perfectly below the stairs, and a buffered up press. It's important to note that the forward direction needs to also be held on landing in order to not lose time.
This also works on stairs that go downward as well (such as the final staircase in stage 13).
Chained staircases (the ones in stage 07-2, stage 08-1 and stage 17-4) have some subtleties to them as well. Compared to purely holding up:

  • In stage 07-2, holding right+up loses 1 frame, while holding left+up saves 2 frames.
  • In stage 08-1, holding either right+up or left+up saves 2 frames.
  • in stage 17-4, holding left+up loses 1 frame, while holding right+up saves 2 frames.

Backward Jump

By pressing the opposite direction that Simon is currently facing and the jump button on the same frame, it's possible to get what's known as a "backward jump", which makes Simon jump in the direction that was pressed but with him facing the other way. It's also possible to get a backward jump while coming off of a staircase by buffering the direction opposite of the staircase and jumping on the first possible frame.

Critical Hit Glitch

The whip's hitbox is normally only active for one frame. But if Simon gets hit the frame after the whip's hitbox spawns, it glitches out and remains active for more time. There are multiple kinds of Crits:

  • Normal Crit - This one occurs when a hit is taken in normal conditions. The whip hits for 5 or 6 frames.
  • Stairs Crit - Crit while Simon is on a staircase. This hits for a lot more damage.
  • 2-Block Crit - When a Crit occurs as Simon is standing in a narrow height (2 blocks), it hits for a lot more damage than the Normal Crit as well.
  • Ceiling Crit - If a Crit occurs just below a ceiling, and the hit causes Simon to fast fall to the ground, the Crit lasts until SImon touches the ground again.

Clips

If Simon gets hit just below a standable platform during the ascent of his jump, he will clip through it.

Scroll Glitch

This glitch is related to Castlevania's way of loading tilesets offscreen. Blocks may only be loaded every 2 frames, and only while Simon is moving. This means that by moving only on frames when blocks are not being updated, they will fail to load properly and instead leave on screen a predetermined, consistent "garbage" tileset. Attempts to load the blocks will continue until Simon is close enough to them. Usually this requires the user to perform 20+ 1-frame movements on the correct frames, which is unfeasible in a Real Time setting. There is another exploit to this mechanic though: if, on the frame a tileset would normally load, Simon moves BACK instead of forward, the block will fail to load, and no further attempts will be made to load it until 8 more frames of movement on "loading frames", at which point another turnaround will be needed. Usually two or three turnarounds are needed to permanently prevent a tileset from being loaded. This method is feasible in Real Time and leads to a number of skips.

Please see Scroll Glitch for more info.


Items

Subweapons

  • Cross: Goes in a straight line piercing anything that it comes into contact with, then comes back like a boomerang.
  • Axe: Arcs upwards.
  • Dagger: Fires in a straight line, disappears upon making contact with something. Avoid, this is not Ghosts 'N Goblins.
  • Stopwatch: Freezes enemies in place for a bit of time. It also freezes the In-Game Timer throughout its duration. Does not work on bosses with the exception of the Bat Boss and Medusa.
  • Holy Water: Splashes down and explodes in a flame which stuns and damages all enemies that stand on it. The bottle itself also damages and temporarily stuns anything that it goes though. Simon is invincible from enemies that are currently stunned.

If Simon breaks a subweapon candle and he's already in possession of said subweapon, it'll turn into either a Small Heart or a Money Bag.

Whip Upgrades

  • Leather Whip: The basic whip that SImon starts with.
  • Short Chain Whip: Also referred to as Short Whip. It deals more damage than the Leather Whip and also has a slightly bigger hitbox.
  • Long Chain Whip: Also referred to as Long Whip. It deals the same damage as the Chain Whip, but has a longer hitbox horizontally.

The Short Whip may drop if Simon has at least 4 hearts, and the Long Whip may drop if Simon has at least 8 hearts. A Whip Upgrade will replace any Small Heart or Money Bag drop.

Multipliers

Simon can normally throw a sigle subweapon at a time. Until it's off the screen, additional subweapons may not be fired. Multipliers allow to get around that. The Double Shot and Triple Shot allow for two and three subweapons to be on screen at the same time respectively. After hitting 10 enemies with a subweapon, the next Small Heart or Money Bag will turn into a Double Shot, or if into possession of that already, a Triple Shot, which will apply to Simon's current subweapon. If another subweapon is collected, the Multiplier gets removed and the hit count gets reset (unless playing on the FC version's Easy Mode). If a Multiplier drops but is not collected, the next Small Heart or Money Bag will not turn into a Multiplier and the hit count will have to be raised to 10 again. If a Multiplier is collected without any subweapons or while in possession of the Stopwatch, it will simply award Simon with some points. The Multiplier reward can be stored through death and may drop without being in possession of any subweapons, but the reward will be canceled if Simon whips any candle that does not contain a Small Heart or a Money Bag.
It is possible to get a Multiplier to drop, collect another subweapon and then collect the Multipler. This will apply the Multiplier to the newly collected subweapon.
There are certain scenarios where all 10 hits may be accumulated immediately. The Holy Water for example may do this by simply exploding on top of a Bone Pillar or an Axe Knight, or while its bottle goes through a Bone Dragon. The Cross can also do this by going through Dracula's body.
A Multiplier drop will take precedence over a Whip Upgrade, when attempting to turn a Small Heart or Money Bag into something.

Other Items

  • Rosary: Clears all enemies from the screen (with the exception of bosses).
  • Invincibility Potion: Grants Simon invincibility for a period of time.
  • Small Heart: Gives Simon 1 heart.
  • Big Heart: Gives Simon 5 hearts.
  • Money Bag: Gives Simon points. Also known in the business as pointless.
  • White Money Bag: Gives Simon point. It is a guaranteed drops off of certain candles and may never turn into another item.




Important-Item Rule

An Important Item is any of the following: Cross, Axe, Dagger, Stopwatch, Holy Water, Whip Upgrade, Rosary, Potion, Big Heart. The rule states that there may only be a single important item on screen at a time. If another attempts to drop from an enemy, it gets turned into a Money Bag, while if it attempts to drop from a candle, it gets turned into either a Small Heart or a Money Bag.

Enemy Item Drops

Items that drop off of enemies are manipulable. Whether or not an item drops off an enemy is dependent on a frame counter that starts at the beginning of any given screen. Every 16 frames of that counter, a check is made to see whether an enemy is dying on that exact frame, and if it is, it drops an item.
Which item it drops is controlled by this chart:

Level Slot 0 Slot 1 Slot 2 Slot 3
Level 1 Stopwatch Holy Water Money Bag Rosary
Level 2 Rosary Money Bag Cross Holy Water
Level 3 Rosary Potion Money Bag Rosary
Level 4 Potion Axe Money Bag Rosary
Level 5 Stopwatch Potion Dagger Money Bag
Level 6 Stopwatch Rosary Money Bag Cross

(Note that technically this isn't exactly how the game's code sees this chart, but for the purposes of simplification it's been laid out this way)
When first booting up the game, this chart starts reading from Slot 0. When an enemy drops an item, it provides the item corresponding to the current slot, and then increments the current slot by one. After Slot 3, it cycles back to Slot 0. For example: the first item to drop in Level 1 would be a Stopwatch. If another item then drops off another enemy in Level 1, it will be Holy Water.
The current slot carries over throughout the levels, so getting a Stopwatch in Level 1 and then getting another item drop in Level 2 would result in a Money Bag.
If a subweapon attempts to drop, but Simon is already in possession of said subweapon, the game will SKIP that slot and provide the next item on the chart, thus incrementing the current slot once again.
If an Important Item is already present on screen, the item drop will turn into a Money Bag, and if a Multiplier is due it will turn into a Multiplier (or Whip Upgrade, needs confirmation). This will still increment the current slot (althought keep in mind that a small heart drop off of an enemy may still turn into a Multiplier, which will not increment the current slot).
A Money Bag from the chart may also turn into a Multiplier or a Whip Upgrade.
If a title screen demo gets an item drop, this will advance the current slot and carry over to the main game. It is recommended to reset the game before every run to prevent the demos from affecting gameplay.
Enemies may also drop other items such as Small Hearts (2 frames before an Item Drop) or Big Hearts (Hunchbacks and Axe Knights). These are unrelated to the item chart.

Orb Grabs

The conditions for the end-of-stage countdowns to start are three: Simon has to have grabbed the orb, he has to be touching the ground, and he has to not be in the whip animation. This means that simply grabbing the orb as fast as possible is usually not the optimal way to do it: it is also important to make sure that Simon touches the ground as soon as possible after grabbing it. For example, grabbing the orb during the descent of a jump is a lot better than grabbing it during the ascent. If the orb is considerably higher than Simon's current position, it's usually best to either let it fall on Simon or to catch it during the very final part of the jump.
There's also a very minor piece of tech for slightly better orb grabs involving the whip. After the last frame of animation of a mid-air whip, Simon gets frozen in place for an extra frame, only to be teleported where he was supposed to be, had that freeze frame not existed, the frame later. This means that whipping in mid-air does not influence time in the long run, but it does allow one extra frame to grab the orb with a perfect whip and sometimes save 2 frames. To get this extra frame, you should usually whip 17 frames after jumping, except in level 3 where an optimal orb grab whips 18 frames after jumping.

Framerules

A Framerule is a mechanic that only allows the player to progress in increments of x amount of frames. Imagine a bus stop, where every bus leaves every x amount of frames: it doesn't matter whether you arrive early, or just before the bus leaves, you will always catch the same bus and leave the bus stop at always the same time. That is, unless you miss the bus and have to wait for the next one to arrive. This means that to get a perfect time you don't need to play perfectly, but just well enough to catch the same bus as someone who played perfectly.
Screens that end with Simon transitioning through a door are affected by a 16-frame Framerule. Note that any other screen in NOT affected by Framerules, nor does it influence the screens that are. Screens that are affected by Framerules have their own timer that stars from the last black screen transition, and those rooms and those rooms alone can only be completed in increments of 16 frames. Any frames gained or lost in other rooms are truly gained or lost.
The way the game slows down the player to wait for the next Framerule is by holding the door semi-open until the moment the metaphorical bus arrives. This means that the door will open very quickly if a framerule has just been barely caught, and it will open very slowly if a framerule has barely been missed.
Lag frames are truly lost and don't count towards the Framerule timer. Screens that are affected by framerules are:

  • Stage 01-2
  • Stage 02
  • Stage 04-2
  • Stage 05-2
  • Stage 07-2
  • Stage 08-2
  • Stage 11
  • Stage 13-2
  • Stage 14-2

RNG

In Summary

Some enemy patterns are only a function of how many frames have elapsed since the start of the screen and Simon's current position on screen. This allows for pattern manipulation on enemies such as the Bat Boss and the Mummies. Other enemies patterns instead, on top of Simon's current position on screen, depend on RNG.
The RNG algorithm is a factor of the previous RNG value, as well as how many frames have elapsed since the start of the screen. On certain frames, the RNG value can be very predictable. This allows for a smaller extent of manipulation, for example on white skeletons, by simply losing a certain amount of frames before ancountering said enemies. This can force them into a limited set of patterns chosen at random, or sometimes even a single possible pattern.

The Technical Version

In Castlevania, whenever the code is finished doing everything it needed to do for the current frame, it enters an idle loop while waiting for the NMI interrupt to occur, signaling the start of the next frame. During this idle loop, the RNG value gets advanced over and over. Here's the code of the idle loop (taken from this public disassembly):

Legend:
 CurrentRandomBonusId = $6F
 FrameCounter = $1A
 BonusTable = $C03F

 MainLoop
	$C030  A5 6F:       lda CurrentRandomBonusId
	$C032  05 1A:       ora FrameCounter
	$C034  29 0F:       and #$0F
	$C036  A8:          tay 
	$C037  B9 3F C0:    lda BonusTable,y
	$C03A  85 6F:       sta CurrentRandomBonusId
	$C03C  4C 30 C0:    jmp MainLoop

 BonusTable
	$C03F               .byte $33,$BB,$3F,$80,$2E,$A9,$61,$87,$AD,$C3,$B2,$C8,$7C,$25,$48,$7A

On one hand, the fact that the RNG algorithm is placed in the idle loop can make it very hard to manipulate its value, because the length of this loop will be affected by how many things the game has already processed on that frames, where in the loop the NMI interrupt happened on the previous frame (since it will resume exactly where it left off on the next frame), as well as CPU/PPU sync (which is deterministic on most emulators but random on a real console).
On the other hand, this RNG algorithm is extremely prone to getting stuck on either a single value, or a very limited set of values. In other words, the idle loop will pretty much always loop over a limited set of values. There are even values from the BonusTable array that are never going to get picked.
On top of that, the RNG value will always reset every 16 frames (to value 0x7A). This gives the value that the RNG will assume a degree of predictability.

Assuming the loop runs for at least a few interations (which it pretty much always does, outside of laggy areas), here is a list of all the possible value that the RNG can contain on any of the 16 values of the room's frame counter:

Legend:
 The value on the left represents the value of the current room's frame counter, modulo 16 (since that's what the RNG algorithm uses), as well as the conditions that have to be met for the values stated on the right to potentially  occur (which is essentially a specific value from the previous frame).
 The value(s) on the right represent the set of possible values that the RNG could contain at the end of the idle loop, on the specific frame and conditions specified.
 
 * = Regardless of previous value
 if 0xXX = If the value from the previous frame was 0xXX

 0x0: 0x7A, 0x3F, 0xB2

 0x1, *: 0xC8, 0xC3, 0x80, 0xBB

 0x2, *: 0xB2, 0x3F, 0x7A

 0x3, if 0xB2: 0x80
 0x3, if 0x3F: 0xC8
 0x3, if 0x7A: 0xC8

 0x4, *: 0x7C

 0x5, *: 0x25, 0xA9

 0x6, if 0x25: 0x87
 0x6, if 0xA9: 0x48

 0x7, if 0x87: 0x87
 0x7, if 0x48: 0x7A

 0x8, *: 0xB2

 0x9, *: 0xC8, 0xC3

 0xA, *: 0xB2

 0xB, *: 0xC8

 0xC, *: 0x7C

 0xD, *: 0x25

 0xE, *: 0x48

 0xF, *: 0x7A

These values will then be read on demand by an enemy, which will determine their pattern (interpreted in a unique way for every enemy). Note that this RNG read will not additionally advance the RNG.
For a practical example, with the standard strat of entering Dracula's room without losing any frames, Dracula's pattern will be determined with the frame counter reading 0xC7.
On this frame, the possible values are either 0x87 or 0x7A. If it reads 0x87, this will make Dracula do the fast fireball pattern, while if it reads 0x7A, this will make Dracula do the slow fireball pattern. This essentially makes either pattern a 50% chance that is impossible to control in an RTA setting.

Score Management

In some games, having certain scores can cause more lag due to the game having to spend more computations to display it on screen.
In Castlevania, this is not the case. The current score is stored in memory in a "decimal" format, which makes it fairly quick for the game to then display it on screen and also makes it the same speed for any combination of digits.
On the other hand, the moment points are acquired, there could be a little bit of variance in the amount of computations performed depending on the current score and the score added, but this is usually just a handful of CPU cycles in total, which is pretty negligible.
The bottom line is, score doesn't really matter for lag in Castlevania.


Additional Links