Game objectives

  • Emulator used: BizHawk 2.9.1 (SubNesHawk core)
  • Aims for fastest time
  • Corrupts memory
This run beats NES "Kaettekita! Gunjin Shogi: Nanya Sore!?" under a second with the DPCM exploit.
Note: I don't know whether this movie syncs on a real console, but I think theoretically you can beat this game like this way on a real console.
Note: There are no sound in the ending, possibly due to uninitialized RAM state (I will describe the details later). I also made another movie for zero-initialized RAM, where the game plays sound correctly (encode). I don't know much about initial RAM state, sorry.

About the game

"Kaettekita! Gunjin Shogi: Nanya Sore!?" is the only Gunjin Shogi game for NES. There are five opponents, but all of them seem to have the same AI. When you win three times against each of them, the last opponent will appear. When you beat the last opponent, the ending starts.

Comments

DPCM exploit

In this game, you can easily cause a stack overflow by continuing to stall the input processing routine with subframe inputs. And, this game doesn't repurpose the stack page for other variables. So, the remaining problem is a setup for a credit warp.
The ending routine is located at $E9B0. The goal is let the program counter jump there. It is possible by taking some detours, though it is difficult to directly write the address as a return address.
First, when a NMI occurs, the stack grows as shown below (the NMI handler pushes A, X, Y registers in this order):
+---+---+---+---+----------+
| Y | X | A | P | rti_addr |
+---+---+---+---+----------+
And, when the input processing routine stalls, there are more stuffs on the stack:
+------+------+---------------+------+------+---+---+---+---+----------+
| 0xCA | 0xFD | player2_input | 0x54 | 0xFF | Y | X | A | P | rti_addr |
+------+------+---------------+------+------+---+---+---+---+----------+
So, when the stack overflows, you can let the program counter jump to $xxFD by overwriting the stack as below:
+------+----------------------+
|  P   |       rti_addr       |
+------+----------------------+
             ^
             |
+------+------+---------------+
| 0xCA | 0xFD | player2_input |
+------+------+---------------+
I let the program counter jump to $FD by setting player2_input to 0. $FD is the mirror variable of PPU_SCROLL x ($2005), and it's value is 0. This is brk instruction. On IRQ/BRK, this game simply returns with rti . So, the program counter proceeds to $FF (note that brk instruction skips the next byte).
$FF is the mirror variable of PPU_CTRL ($2000), and it's value is 0x90. This is bcc instruction. Its operand is fetched from $0100, and you can manipulate this while you are corrupting the stack. I write 0xF4 to $0100. So, the program counter branches to $F5 (note that the carry flag is false, because I copied 0xCA to the status register on the stack).
$F5-$F8 is the input buffer. $F5-$F6 contains the edge inputs of player1/player2, and $F7-F8 contains the raw inputs of player1/player2. I write [0x20, 0xB0, 0xE9] here. This is jsr $E9B0 . (This is possible because 0x20 is a "subset" of 0xE9, considering a byte as a bitset.) The game executes this code, and the program counter jumps to the ending routine. By the way, the ending routine never returns, so you don't have to worry about after the jsr instruction.
When you stall the input processing routine once, the stack will grow at most by 11 bytes. But, you can manipulate the consumed amount of the stack by adjusting the timing of NMI, using player2 inputs. (This game compares the inputs of player1/player2 separately, and the consumed CPU cycle differs slightly for each.)

Uninitialized RAM

On boot, This game doesn't initialize RAM so much, and it reads some uninitialized RAM (even without DPCM exploit). In this run, I think the game reads the uninitialized RAM below:
addrdescription
$17Some counter. Incremented by NMI handler without initialization.
$23OAM DMA flag.
$2AInput buffer. This will have no problem.
$2BInput buffer.
$F5Input buffer.
$F6Input buffer.
$F7Input buffer. Read as "previous input" without initialization.
$F8Input buffer. Read as "previous input" without initialization.
$075DVariable for audio driver, probably.
$075EVariable for audio driver, probably.
Especially, $075D and $075E will be problematic. Probably these are variables for the audio driver, and they have initial value 0xFF on NesHawk. I think this is the reason of no sound in the ending.

Memory map

addrtypedescription
$F5u8player1 edge input
$F6u8player2 edge input
$F7u8player1 raw input
$F8u8player2 raw input
$FCu8mirror variable of PPU_SCROLL y ($2005)
$FDu8mirror variable of PPU_SCROLL x ($2005)
$FEu8mirror variable of PPU_MASK ($2001)
$FFu8mirror variable of PPU_CTRL ($2000)
$E9B0codeending routine
$FDBAcodeinput processing routine
$FF00codeNMI handler
Inputs are in ABSTUDLR format.

Trivia

This game has a cheat which jumps to the ending. But it's slower than the DPCM exploit.
This game has weird bugs. Sometimes an enemy piece appears from nothing, and sometimes even an ally piece changes into an enemy piece. (example)

nymx: Claiming for judging.
nymx: This looks really good, just like your last submission. I didn't say this the last time, but this is proof that the emulator core is very accurate, as it mimics the DPCM hardware problem. I look forward to more of these runs. Great job.
Accepting.

despoa: Processing...


TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15527
Location: 127.0.0.1
Site Admin, Skilled player (1250)
Joined: 4/17/2010
Posts: 11468
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
TaoTao, do you have a preference on which file should be used for publication - with or without sound? If they are so similar than it's impossible to notice the difference in gameplay (real-time duration is the same too), it sounds like the one with audio would be more beneficial. We can technically publish both movies in the same publication, but I don't know if the silent version is so helpful to have primarily featured like that.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Experienced player (918)
Joined: 9/18/2008
Posts: 153
Location: Japan
feos wrote:
TaoTao, do you have a preference on which file should be used for publication - with or without sound?
I prefer the one with sound. This game changes the music in the ending, so it will help viewers to notice the mini scene change. (This is a tiny easter egg. That is, if you wait for about 15 seconds in the ending, the game displays the messages from the staffs, as shown in my encodes.)
Post subject: Movie published
TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15527
Location: 127.0.0.1
This movie has been published. The posts before this message apply to the submission, and posts after this message apply to the published movie. ---- [5780] NES Kaettekita! Gunjin Shougi: Nanya Sore!? "game end glitch" by TaoTao in 00:00.56