Submission #6603: Jigwally's NES Romance of the Three Kingdoms II "save glitch" in 05:46.15

(Link to video)
Nintendo Entertainment System
save glitch
BizHawk 2.3.2
20803
60.0988138974405
29755
Unknown
Romance of The Three Kingdoms II (U) [!].nes
Submitted by Jigwally on 1/22/2020 5:56:35 AM
Submission Comments
  • Arbitrary Code Execution
  • Major skip glitch
  • Uses a game restart sequence
  • Corrupts save data
  • Abuses opposite D-Pad presses (U+D/L+R)
  • Minor luck manipulation
  • Genre: Strategy
I guess I've now made it a goal to achieve a save glitch win in as many Koei games as possible.
I use the same basic method in my L'Empereur TAS of a mid-frame reset to create a general pointing to controller input. However unlike L'Empereur, there is no single RAM address I can write to in order to trigger the ending. Instead, I perform rudimentary arbitrary code execution to jump to the ending by writing code to RAM.
  • Through testing I found Scenario 5 allowed for the fastest route to the save corruption. The game's initial RNG seed is determined when you first press start during the intro sequence (beginning w/ the Koei logo's appearance), so I tested multiple seeds to get to my turn the fastest.
  • Controller input is at 0x6E, and I already have a general (Fei Shi) w/ address 0x6B6E. So it's just a matter of saving the game, sending Fei Shi to another province & resetting mid-frame to create a general w/ address 0x006E.
  • Beforehand, I reassign soldiers to fix the checksum of the future corrupted save. Note that the game designates generals with no soldiers as 0xFF, so setting a general to exactly 0 soldiers actually INCREASES the checksum. Here I balanced it out exactly.
I went through trial and error of different methods of writing the code I need to the zero page but the method I came up with ended up being really simple. Like my last TAS, you instantiate entries in the general list by holding down the appropriate button combinations. Appointing a general as governor places them at the start of the linked general list. In order to write a specific value to the zero page, first you make a general w/ that value, appoint them General, then create a general representing the address and appoint them. This causes the previous general to be written to that address. There are some caveats:
  • The value you're writing needs to also represent a writable RAM address, otherwise the general list will get obliterated.
  • Sometimes when appointing a glitched general, the resulting text message will contain a name string so long that it overflows over crucial data, which can crash the game. (This didn't happen here)
  • Traversing some values when filling the general list will sometimes hit an infinite loop which can also crash the game.
By writing 0x6EA4 to 0x1F and 0x63DD to 0x22 I get the following code (in the Koei VM bytecode):
  • A4 6E 00 ; load PAD1/PAD2 input to left register
  • DD ; call pointer in left register
  • 63 (this value is irrelevant, I just picked the first byte that didn't crash)
Now in order to actually run this code I need to clear the program counter for the virtual machine (0x06) so that the game starts executing values in the zero page. To do so I simplify instantiate an officer @ 0x06 and then dismiss them, which causes zero to be written to it (removal from linked list). The game then starts executing the "code" starting at 0x00, and eventually comes to the code we've written. At this point, by holding down the button combo for the ending function (0xE037), it gets called.
NOTE: The game uses the name of the ruler of Province 1 as the winning ruler, since normally the game ending is only triggered when all provinces have a singular ruler. The name is glitched because Province 1 is unoccupied so it does a name lookup on an invalid ID.
Future improvements are possible, there might exist a way to have sufficient code in the zero page to leverage the ending skip using only a single memory write in combination with values that are already there.
In addition to this rudimentary ACE I've also written a full ACE bootstrap for a potential total-control TAS. The setup for it was around 10 minutes but using this new method I should be able to shave that down considerably. A simple demonstration of using it to draw custom graphics: https://www.youtube.com/watch?v=EKCj2jXPqIU
Last Edited by adelikat on 11/2/2023 2:13 PM
Page History Latest diff List referrers