Special Links: Youtube, NicoNico (with extra displays; watch w/o register), 日本語
Castlevania: Dawn of Sorrow is a one of famous Castlevania games, and it is also the sequel to Castlevania: Aria of Sorrow (GBA).
I recommend downloading my release package as it includes the movie file as well as other accessories such as memory watch files, lua scripts, etc.
This run aims for the fastest time to complete the game with the good ending, on normal difficulty. The run starts with no predefined save, but it completes the game in 8 minutes and 20.12 seconds, by utilizing a variant of a famous zipping glitch. The in-game completion time of this run should be 00:07:18 (26310 frames), but since game timers have been overwritten by a glitch, it is shown as 00:43:43 after the game has been completed.
  • Emulator used: DeSmuME 0.9.4+ (with no lag reduction options; i.e. official timing)
    • The game sometimes lags more than the real console, because of the emulator's inaccurate timing emulation.
    • I recommend OpenGL. Both OpenGL and SoftRasterizer work well, but I think SoftRasterizer causes a minor display glitch.
  • Aims for fastest time (to get the good ending)
  • Abuses programming errors in the game / Uses zipping glitch
  • Manipulates luck (for soul/item drops, boss moves, etc.)
  • Takes damage to save time
  • Genre: Action, Platform, RPG
  • Colors a warp room

About the run

The run completes the game in the following process.
  1. Prologue
  2. Meet Yoko and Julius, obtain Magic Seal 1
  3. Obtain Axe from Axe Armor
  4. Defeat Flying Armor
  5. Defeat Balore
  6. Save game for later glitch use
  7. Obtain Magic Seal 2
  8. Defeat Dmitrii
  9. Perform zipping to collect achieve things and suspend/restart the game
  10. Go to Warp Room and warp to The Abyss. The castle will self-destruct in a few seconds
It is well known that the famous zipping glitch, which is called Succubus glitch, allows you to obtain a bunch of souls and items immediately. That Succubus glitch is used in a few of speedruns. However, they needed to get to The Pinnacle to obtain Succubus' soul.
While making this run, I invented a variation of Succubus glitch, a method to interrupt special attack by a cutscene. It allowed me to perform a zipping much earlier than before. Moreover, I enthusiastically investigated what can be done by the zipping, and I finally concluded that the last warp room can be activated and also Menace can be skipped.
Since the emulator generates a ridiculous amount of lags, I did not mind lags and 1 frame losses very strictly (still I generally did my best, of course!). Instead, I tried to optimize the whole route/strategy hard, and also to discover general tricks of the game.

Tricks

Here I show you what I have found.

Backdash

There are three methods of move, backdash-jump, forward-backdash-blank and backdash-crouching. I compared their average speeds to see which is faster. I show the comparison on flat ground below.
  • Backdash-jump: (13784+13232+12680+12128+11576+11024+10472+9920+9368+8816+8264+7712)/12 = 10748
  • Forward-backdash-blank: (6144 + 13784 + 11384)/3 = 10437.3333
  • Backdash-crouching: (13784+13232+12680+12128+11576+11024+8624+0)/8 = 10381 (8 frame pattern = fastest one)
  • Additional note: Replacing crouching to subweapon use seems to be slightly faster if it does not lag. It will greatly decrement your MP, though.
That is why Soma jumps again and again. Crouching is used as an alternative move method, when Soma is on a downslope, or when Soma wants to jump earlier. Sometimes, it is also used for some luck-manipulations.
Actually, I also considered about one more method, "forward, backward + backdash, release". It has never been used since it was slower than the two methods above.

Motion cancels

  • Backdash can cancel an attack motion. It is a well-known behavior.
  • Landing can cancel an attack motion of some weapons. It is a well-known behavior, too.
  • Axe Armor's ability can cancel a landing motion after damage.
  • To cancel Black Panther's ability just before landing can cancel a landing motion.

Randomness

Some rooms (more precisely, enemies, backgrounds, and other effects) change the randomness on every frame, some rooms do not.
Soma can affect the randomness at least by a normal attack (changes it once), backdashing (sometimes changes it while doing that), or turning around (changes it once). It cannot be changed by jumping, crouching, or using a soul that I used in the run. Backdash+crouching is a handy way to manipulate randomness without losing speed much.
The recurrence equation of RNG is identical with later 2 DS games, Portrait of Ruin and Order of Ecclesia. Also, it is almost identical with Aria of Sorrow. It is a sort of linear congruential generator. The following C code emulates the behavior of the RNG.
static int32_t x = 0; // $020c07e4
int32_t rand() {
    x = (x >> 8) * 0x3243f6ad + 0x1b0cb175;
    return x;
}
I wrote a Lua script that displays how many times the RNG is called in a frame (I learned about the implementation of RNG after I finished the run, so the script was not used for the run).

Crystal blocks

Crystal blocks are shattered by touching the screen (Balore's soul needed). In a tool-assisted speedrun, so many blocks can be shattered immediately, by moving the stylus incredibly fast.

Go down floating footholds without losing speed (not used)

I just discovered it after I finished the run, so I cannot tell you the detail at present. I assume that it happens under a limited pixel conditions. This trick might improve the run a little. I hope it will because it looks good.

Activate a switch behind the wall (not used)

One of famous glitches. The Cutall/Cinquedea/Alucard Sword's special attack is teleporting behind an enemy and stabbing it. By utilizing that, you can activate a switch, which is on the other side of the wall.

Infinite jump glitch (not used)

I don't know the detail since I have never had a look at it.

Zipping: General info

When Soma goes outside the room, the game writes "visited" flag to abnormal location. As a result, it causes various things like the run has done.
In other words, the write address is determined from Soma's location. I studied how to calculate the exact write address from Soma's position, and wrote up a lua script which shows the write address in realtime. It definitely helped me to consider the optimal route of the zipping part.
When Soma goes to the right as long as one room, the write bit gets shifted to the left. However, the range of the write address changes per 16 rooms (i.e. 2 bytes). Read the script below for details.
-- Address view for memory writing with zipping
-- Open the memory viewer to see what's actually going on.

if not emu then
  error("This script runs under DeSmuME.")
end

if not bit then
  require("bit")
end

function cvdosPosToMapFlag(x, y)
  x, y = x % 256, y % 256

  local xl, xh = x % 16, math.floor(x / 16) % 16
  local i = (y * 16) + (xh * 46 * 16) + xl
  local pos = 0x20F6E34 + math.floor(i / 8)
  local mask = math.pow(2, math.floor(i % 8))
  return pos, mask
end

gui.register(function()
  local x = memory.readbyte(0x0210F018)
  local y = memory.readbyte(0x0210F014)
  local i = (y * 16) + x
  local pos, mask = cvdosPosToMapFlag(x, y)
  agg.text(140, 5, string.format("%08X:%02x", pos, mask))
  agg.text(140, 24, string.format("[%04X-%04X]", cvdosPosToMapFlag(x - (x % 0x10), 0) % 0x10000, cvdosPosToMapFlag(bit.bor(x, 0x0f), 255) % 0x10000))
  agg.text(140, 43, string.format("[%04X-%04X]", cvdosPosToMapFlag(x - (x % 0x10) + 0x10, 0) % 0x10000, cvdosPosToMapFlag(bit.bor(x, 0x0f) + 0x10, 255) % 0x10000))
  agg.text(140, 62, string.format("(%03d/%X,%03d)", x, x % 16, y))
end)
Here are some of addresses I planned to (not) manipulate in the run.
AddressSizeDescription
020F70D7lower 4 bitsYorick
020F70E0lower 4 bitsSuccubus
020F70E1lower 4 bitsErinys
020F70EBhigher 4 bitsBlack Panther
020F70F3higher 4 bitsFinal Guard
020F70FChigher 4 bitsGolem
020F70FDhigher 4 bitsLilith
020F7104higher 4 bitsDraghignazzo
020F7109lower 4 bitsStolas
020F710Ahigher 4 bitsMalphas
020F710Blower 4 bitsDoppelganger
020F710Bhigher 4 bitsRahab
020F710Clower 4 bitsHippogryph
020F710Chigher 4 bitsProcel
020F710Dlower 4 bitsMud Demon
020F71E2lower 4 bitsCutall
020F71E2higher 4 bitsCinquedia
020F71EDlower 4 bitsKaladbolg
020F71F2higher 4 bitsClaimh Solais
020F720Elower 4 bitsDracula's Tunic
020F7216higher 4 bitsDeath's Robe
020F721Blower 4 bitsRosary
020F7226lower 4 bitsChaos Ring
020F6E201 byteRoom X position (for start from suspend)
020F6E221 byteRoom Y position (for start from suspend)
020F6DFC4 bytesIf the value bitand 0x44000007 is non-zero, disable Suspend
020F70184 bytesX position for start from suspend
020F701C4 bytesY position for start from suspend
020F703C4 bytesIngame time
020F7187bit2|bit3 (04|08)Save Room & Warp Room first time message flag
020F718A1 byteMenace related flags ($30 is the best value to skip him)
020F71A82 bytesActivated warp destinations (bit11/$0800 = The Abyss)
020F72282 bytes * 6Button settings
020F72562 bytesDisable Suspend/Pause (Julius Mode)
020F72591 byteHard Mode if nonzero
Note: As you can see in the run, Soma can move through the wall by sliding.

Zipping: The Succubus glitch and its variations

All of these glitches cancels a special attack halfway to go into the wall. The difference is only how to cancel an attack.
The steps to achieve the most famous Succubus glitch are:
  1. Equip Cutall/Cinquedea/Alucard Sword and Succubus
  2. Use its special attack then cancel the motion by Succubus immediately
  3. Walk/Attack for about 2.5 seconds (do not stop, jump, backdash, and so on. It's important)
  4. Use the special attack again against the wall
  5. The special attack will be canceled in the wall if it succeed
Axe also can be used to perform the glitch. Here is a demonstration video (youtube). When you use Axe, you'll need to switch your equipment during the glitch, because Axe's special attack is too long.
Axe also can be used to perform the glitch. However, you'll need to unequip the Axe once after you used a special attack (it's good to use Doppelganger to unequip a weapon quickly, by the way), because Axe's special attack is too long.
A cutscene after the boss fight also cancels the special attack (it's the core of the run). It can be used earlier since it doesn't require a Succubus' soul.
Additionally, there are some special locations you can perform the zipping (flat ground + door, narrow gap + Skeleton Ape): http://www.youtube.com/watch?v=lkohuZnKPAg

Memory addresses

Most of the zipping related addresses are shown above.
AddressLengthDescription
020CAA404 bytesX position
020CAA444 bytesY position
020CA95C4 bytesX position (next)
020CA9604 bytesY position (next)
020CA9682 bytesX velocity
020CA96C2 bytesY velocity
020C07E44 bytesRandom number
020F703C4 bytesIngame frame
020CA9F31 byteSoma invulnerability 1
020CAA241 byteSoma invulnerability 2
020F74102 bytesCurrent HP value
020F74122 bytesMax HP value
020F74142 bytesCurrent MP value
020F74162 bytesMax MP value
020F74484 bytesCurrent EXP value
0210AF422 bytesLeft of sprite hitbox
0210AF462 bytesRight of sprite hitbox
0210AF442 bytesTop of sprite hitbox
0210AF482 bytesBottom of sprite hitbox
020F2A881 byteMagic Seal Step
020F2A8C1 byteMagical Seal Substep
020CED884 bytesSuccubus timer
The following addresses might change randomly.
AddressLengthDescription
020D36A82 bytesFlying Armor HP
020D35131 byteFlying Armor invincibility #1
020D35141 byteFlying Armor invincibility #2
020D35151 byteFlying Armor invincibility #3
020D26E82 bytesBalore HP
020D25531 byteBalore invincibility #1
020D25541 byteBalore invincibility #2
020D25551 byteBalore invincibility #3
020D2EC82 bytesDmitrii HP
020D2D331 byteDmitrii Invisibility #1
020D2D341 byteDmitrii Invisibility #2
020D2D351 byteDmitrii Invisibility #3
Also, I posted some info about cheat codes before.

Stage by stage comments

Prologue

In fact, the first Skeleton can be defeated 1 frame faster, by not jumping at second backdash and sliding earlier.
Golem battle is one of my favorite parts. Soma attacks him with insane speed.

Lost Village - Up to Flying Armor

Actually, Soma moves faster than a bone of Skeleton's soul. So it's rather difficult to throw a bone optimally. After all, I tested all patterns I came up with. I am not so smart :P
It might be better to defeat Peeping Eye by using Knife (with backdash and 2 frame jump) instead of Armor Knight, but I am not sure.
The Axe Armor room is very luck-manipulative room. You need to manipulate the randomness to obtain Axe Armor's soul and Axe, and also to manipulate Zombies' positions. I manipulated the randomness hard by brandishing a knife here and there, but I could not manage to eliminate one zombie who is just after Axe. Also, this is the first room I really wanted a lag-free emulator :P
Upgrading Axe Armor's soul here (and possibly in Wizardry Lab) might save time later (if a lag-free version of the emulator is used). Perhaps it will make that luck-manipulative room even harder. *shivers*
Stylus can be used in the menu screen. It is sometimes faster than using keys.

Lost Village & Wizardry Lab - From Flying Armor, up to Balore

As Atma told me in the forum, in the Flying Armor battle, I need to manipulate him to position as low as possible to make attacking him easier, and defeat him with scrolling to the left as far as is possible. I tried hard but I could not get to the most left side of the room. A better luck might improve the battle a little.
You may think that I can perform the cutscene zipping with Flying Armor. That is right, but I cannot do anything during the zipping so that it takes a few minutes to return. Additionally, I can get nothing there (the range of write address: 020f6e34-020f7033).
After I used Flying Armor, I switched it back to Armor Knight soon, to make the Balore battle a bit faster and to cancel damage motions. I considered that it is faster than keeping Flying Armor equipped.
If I can go down floating footholds without losing speed here and there, it will save 10-20 frames.

Wizardry Lab & Garden of Madness - From Balore, up to the save room

Balore is defeated without Mind Up. It makes the battle about 3 seconds longer, but later I can gain about 10 seconds. After I defeated Balore, there is a chance to leave a message on crystal blocks. However, I did not do that since it lags too much. This is one of obvious improvable point, isn't it? ;)
I used two Potions after the Balore battle, but I guess it might be a mistake. Reducing the amount of damage might make the run faster, rather than potion use.
In the Slaughterer room, it might be better to take damage instead of defeat them. It gives Soma less exps, and it might allow us to defeat more enemies later. By the way, it was a little hard to manipulate Slaughterer's position and hitbox. If you want to make a tas of the game, I suggest to you writing a hitbox display lua.
To activate the suspend command, I saved the game in Garden of Madness. Particles in the room might affect the time, but I really did not care. Even a zipping cannot skip this process. That is known via memory value.

Garden of Madness & The Dark Chapel - Up to the end of the Dmitrii battle

I didn't defeat enemies much because it causes a levelup and it freezes Soma for a few seconds. Also, I didn't equip Breastplate because it takes time a little to equip and I assumed that it doesn't save time after all.
I did not go up until the last axe hits Yorick. If I go, the collision detection will be skipped and I cannot defeat him.

Outside of the world - The zipping part

It's the most difficult section to explain... Well, read the general info section about zipping above first of all.
What I did in the run are:
  1. Obtain Black Panther
  2. Obtain Hippogryph (optional; I think it saves time rather than not use it, or more than obtaining Malphas instead)
  3. Set $30 to $020F718A to skip Menace (as a result, the game considers the first conversation and the battle are already done)
  4. Activate the warp to The Abyss
What I did not do in the run (because it seems to take time to do that) are:
  • Obtain Malphas
  • Skip the "Warp Room" description of the first time
I sometimes stopped to not overwrite the starting position after suspend much.
I constructed this route in the following steps:
  1. List up all possible useful locations (and dangerous locations as well)
  2. Divide them into 4 groups (odd number address or even number address, in higher 4 bit or in lower 4 bit)
  3. Count the minimum horizontal distance to get to each location, and group them by it (in the 16-bit alignment)
  4. See what is near/far each other and consider about how to visit them
One vertical loop takes a few seconds, so that I think it is not so smart to wait again and again to visit more locations.

The finale

In the room of lift, I compared which is faster, going from the upper or lower. They were the same.
When I fall from high position, I cancel Black Panther immediately just before the landing and cancel the motion.

Comments

I had never thought that I would invent such a odd route. In fact, before I met DeSmuME-rerecording, I had never considered about the speedrun of the game.
One day, I wanted to try recording a DS TAS movie with a new emulator, so I TASed the very beginning part of this game (the first battle against three enemies) just for curiosity. I learned some of the basic mechanisms of the game through the recording, and it told me that I can improve Atma's demonstration TAS in the forum. This is why I started working on the game suddenly. I had never expected that I would make a Castlevania TAS.
After I decided to work on the game, I watched Groobo's semi-TAS video on YouTube (and Satoryu's non tool-assisted speedrun).
The video completes the game in 28:58, by utilizing famous two glitches. One is a way to open a gate from the opposite side of a switch by Cutall's special attack, and the other is the one called "Succubus glitch" which allows us to go through/into a wall, and get a bunch of souls and items (details are described later). My original aim was to optimize his speedrun, and I assumed the completion time would be 20+ minutes at best.
However, that was not true. I'd like to thank all people who supported/encouraged me. I could not make the run without them.

Special thanks

  • Satoryu: for his non tool-assisted speedrun
  • Groobo: for his semi tool-assisted speedrun
  • People in the Dawn of Sorrow topic: You guys are always kind. Especially, I thank Atma for posting his first TAS attempt of the game. That motivated me a lot.
  • #TASers: A Japanese IRC channel. They motivate me always! Especially, I thank pirohiko for inventing a new style of video editing! ヽ(>ヮ<)
Hope you enjoy the run, thank you!

Screenshots

gocha: Hi! I am an idiot. I took a few screenshots of this movie and placed them here. Here goes! Feel free to clean up the list.

adelikat: Accepting for publication under one condition. A video like the one on the nicovideo be the published MKV.
ShinyDoofy: Processing...