Tool-assisted game movies
When human skills are just not enough

Submission #2258: DarkKobold's Genesis Shining Force in 1:59:59.05

Console: Sega Genesis
Game name: Shining Force
Game version: USA
ROM filename: Shining Force (U) [!].bin
Emulator: (unknown)
Movie length: 1:59:59.05
FrameCount: 431943
Re-record count: 25111
Author's real name: K. Thomson
Author's nickname: DarkKobold
Submitter: DarkKobold
Submitted at: 2009-05-25 17:19:52
Text last edited at: 2009-06-06 02:27:31
Text last edited by: adelikat
Download: Download (28709 bytes)
Status: published
Click to view the actual publication
Submission instructions
Discuss this submission (also rating / voting)
List all submissions by this submitter
List pages on this site that refer to this submission
View submission text history
Back to the submission list
Author's comments and explanations:
Finally!!! Shining Force 1 in under 2 hours! I can never look at this game again!

Battles with Big savings (>30sec)

#3 to Alterone

Killed less of the Dwarves, saves a ton of time.

#7 - Marionette Battle

Bought the Spear for Mae in chapter 1, and this was the reason. Saved 37 seconds.

#12 - Elliott Battle

I spent FOREVER on this battle, but it paid off in the end. Not killing all the enemies in the middle allowed me to just fly past them. Finding a Battle Order that worked to get everything required took way too long. However, it was the battle with the most saving - 49 seconds.

#24 - Colossus Battle

Went right instead of left, and saved an entire round. I tried this way back when, but without the speed ring, it never worked. A few runs back I got the speed ring, but never bothered to try again. Saved 45 seconds.

Battles with Mediocre savings (8+ seconds)

#1 The Gate of Guardiana

This battle improvement taught me not to open my big mouth about perfection. My "perfect" battle was slow by 8 seconds.

#13 Battling into Urbanatol

A different route for the birds results in less enemy movement and kills.

#22 Battle to the Ancient Tower

This is actually probably my favorite improved level. The last run, Balbaroy killed enemies, while Amon was bait to arrange enemies for Z (Max) to kill. This time, Balbaroy dual tasked as the bait and the enemy killer, leaving me the ability to kill off Amon earlier in battle 20. The fact that I was able to manipulate enemy movement and still put Balbaroy in places to kill enemies was monumental to m.

#24 The Battle with Chaos

While the actual battle is almost the exact same length, using Balbaroy to kill Chaos meant less swapping of the movement ring, which takes around 4 seconds of menu time outside of battle, and 2 in the next battle.

#26 Ramaldu's Creatures

Swapping the movement ring to Z instead of mushashi saves needing to equip it in 27, as well as 4 seconds of menu time. Additionally, Z kills 4 enemies instead of 1 in round 2, saving 1 second per enemy.

#29 Darksol's Final Stand

Looks like I never needed to kill anything but Darksol. Musashi walks around the enemies to kill Darksol this time around.


I ended up writing 15 scripts to do this run, and regularly had 7 script windows open, to execute the various tasks. I'm going to discuss a few of the scripts I wrote here, and talk generally about how much Lua kicks ass. This run would NOT have ever been completed without Lua. Additionally, all my code will be posted to the appropriate thread in the gens forum.

  • StartBattle - Generates the input to get the correct starting order for a battle.
  • BattleOrderExecute - Generates the input mid-battle to get the right next battle order
  • LevelModifier - Finds the characters level up, and then gives options that can be selected for the coming level. Checks to make sure the correct level up is found.
  • MoveChars - Inspired by XKeeper's moving mario script - moves characters around the battle field. Great for testing new strategies.
  • crits - Tells you the input required to get a critical,miss, double critical, etc.
  • gotarget - Tells the input required for a specific value of the RNG (defined in the script). This was used less, after I developed all the other scripts.
  • Spell - Brute forces a spell action scene. The RNG plays heavily into how fast these execute. I brute forced about 2-3K tries, and took the fastest one. Faster ones may be possible
  • dump - Dumps the current character positions into a text file. Good for matlab.

This may be the first run where a majority of the luck manipulation was done with a Lua. At least, it is the first where Lua's luck manipulation did not rely on brute-forcing, and instead on measurements and calculation. The first three scripts saved the most time. Generally speaking, using MATLAB or gotarget, takes about 5-10 minutes to get the next desired RNG value. This means that recreating a single battle with no changes takes a good 2 hours, and 3-5 if there are changes and tests. With those scripts, a battle reproduction could be done in about 30 minutes! Obviously, this means it was less cumbersome to check new strategies, try new ideas, and etc. Lua pretty much kicks ass, and has been the best addition to the TAS community since emulation itself.


Thanks go to Nitsuja, Upthorn, and adelikat for their work on Gens - this run wouldn't have been possible without Lua for Gens. Also, thanks to Nitrodon for explaining uh... math, and how you can actually calculate things that use remainder operations. Still makes my head spin.

Watching -

I spent hours making sure that the cursor movements were totally optimized, and battle scenes occur as fast as possible, which is.... Extremely boring to the majority of TAS watchers. This script removes all cursor movements and battles from the TAS, shortening the watch time down to probably 2/3rds.

CHECK = savestate.create(); gui.register( function () if memory.readbyte(0xFFF009)==0 then savestate.save(CHECK); if (memory.readbyte(0xFF0FFD) == 16) then while (memory.readbyte(0xFF0FFD) == 16) do gens.emulateframefast(); end; else

if (memory.readbyte(0xFF0002) < 12) then
  for i = 1,85,1 do
end; if (memory.readbytesigned(0XFF00F7) == -84) then savestate.load(CHECK); else while (memory.readbytesigned(0XFF00F7) ~= -84) do gens.emulateframeinvisible(); end; for i = 1,85,1 do gens.emulateframeinvisible(); end; end; else savestate.load(CHECK); end; end; end; end)

Will write more later...

adelikat: Accepting as an improvement to the published movie.

Similar submissions (by title and categories where applicable):