NES Journey to Silius Wrong Death Warp

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

I had not examined $32 but I was able to confirm that every 16 Macro Frame counts the 017E will increment by 1. Falling down a gap may work the same way, but just vertically.
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

The only spawn upon death within a level is based on 017E, in order to spawn to a boss or another level then this would be a different address, and as of yet I have not seen any way to manipulate this but if you can find one then that would be cool! As for this extra increment issue, I am wondering if it could be done anywhere else, so far only this one location.
User avatar
B00daW
Posts: 586
Joined: Thu Jan 03, 2008 1:48 pm

Re: NES Journey to Silius Wrong Death Warp

Post by B00daW »

Yeah... I corrected that oversight! Not enough sleep. Checking the value of the vertical scroll is a part of the checkpoint incrementation routine as well.

Something we should probably do is map out the possible "valid" respawn locations from the ROM look-up tables. As you can see in my previous post, each level has a table of "valid" respawn locations that it compares and sets to $17E upon death and restart. All ROM addresses will be >$8000.

Each level you can see where the indirect pointer is indicating ROM space by looking at the death restart routine. There should be an decremental string of values in ROM from $xx (end of level) to $xx (start of level). See the post about "valid" locations.

(Now... I'm at work, so I'm just postulating at the moment and can't verify right now.)

For example, let's say level 3 has a string of values is as follows: (end) 2E, 17, 12, 0A, 07, 04, and (start) 00. The "checkpoint validator" routine increments the ROM lookup value for the table and compares (CMP) until the value is greater than or equal to $17E...

So... If you know your value of $17E gets buffered to $24, when you die it will spawn you at checkpoint $17.

Are you able to rip the spawn location values per level on your own? This should be a valuable tool for your research. To save time with speedruns you should know which value to buffer to and suicide for optimal warping.
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

I will be honest, I know little to nothing about these things. My mind is blank when I stare at the Trace Logger and Debugger. All of my research comes from trial and error, looking at memory addresses, using a lua script to manipulate an address, etc. When I found a correlation between the Micro Frame Location, Macro Frame Location, and the Spawn Location to see more of what is happening with the extra increments I merely wrote down all the ram addresses listed in Trace Logger and Debugger from the one frame when this occurs and then view both an instance when it did and when it didn't in a TAS Editor, and made a list of observations. That is when I made the correlations.

I would be able to make a list of spawn locations by mere trial and error but using lua script to set 017E and then dying to see where it takes me and that new value written to 017E would be a spawn point. Since the manipulation of 017E has only occurred where I mentioned the one and only death abuse for a good spawn point would be value 26 in level 4, since this would save a net of 10 seconds or so.

While I compile the spawn point values, the one thing that is most concern for me right now and has the best practical value is to find out why the extra increments occur beyond screen scrolling and reaching scroll barriers. IF we knew why this one location seems special we may be able to apply it to other areas in the game and potentially find another warp location where the data of all level spawn points would be very useful.
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

Here is a list of valid spawn points done by trial with lua script. As far as I can tell this is accurate and complete.

Level one:
3, 7, 11, 14

Level two:
4, 9, 14, 18

Level three:
5, 8, 15, 23, 26

Level four:
5, 10, 15, 20, 26, 33

Level five:
8
User avatar
B00daW
Posts: 586
Joined: Thu Jan 03, 2008 1:48 pm

Re: NES Journey to Silius Wrong Death Warp

Post by B00daW »

Cool! I'll verify them by doing dumps later on...

Just to teach you to get into good habits, start thinking with hexadecimal... When you wrap your mind around thinking only in hexadecimal, it's easier to start thinking in bitwise operations. ...And then all videogames and speedrunning hacking. :)

Hex is 0-F (0-15). There are 8 bits in a byte, they are ordered as: 76543210 (yes this order). Think of those as "powers" of binary. Binary means two values. 2 to the power of 0 is 1. 2 to the power of 1 is 2... etc. In hex the representation (right to left) goes as: $01, $02, $04, $08, $10, $20, $40, $80. Notice the pattern? Then the bits values are just added together.

Bitwise values go from most valuable to least valuable. NES/Famicom does this with 16-bit (2 byte) addresses as well. This is called "little endian" (ends on the little value -- reading left to right.) So if you are tracing some code in the debugger at address $8000, there may be an assembly opcode addressing it in data as 0080. Now that you know binary, you would know that this is also represented as 00000000 10000000.

Another neat trick is when a videogame thinks about negative values. Values $01-$7F (1 through 127) are considered to be positive. Values $FF-$80 (-1 through -128) are considered to be negative. This is called "two's compliment." Videogames use this all the time!

Hex is easier. ;)

Edit: derp-128!
Last edited by B00daW on Fri Sep 08, 2017 5:07 pm, edited 1 time in total.
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

Of what you have said here I understand that 0-F in Hex is 0-15, though I am not sure why FF would be negative -127 (this is the signed value?) but would be 255 as unsigned? And about the binary meaning two numbers, good. The rest in that segment did not make sense yet. Not even sure why FF would be an unsigned 255. Little endian then means that of the 8 bits the highest value is on the left, and lowest is on the right. I was not able to put together the $8000 and 0080 and then the 00000000 10000000. What does the $ mean? (Values $01-$7F (1 through 127) are considered to be positive. Values $FF-$80 (-1 through -127) are considered to be negative. ) - once again this would be "signed" values? Why is it called "two's compliment? Sorry for all the questions, the unsigned values seemed much easier for me and so I avoided hex when I started learning these things. I have yet to wrap my mind around hex. Thanks for the teachings, would like to understand it more, it is just too very new for much to sink in at the moment.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: NES Journey to Silius Wrong Death Warp

Post by tepples »

$FF is $F0 (15 * 16) plus $0F (15 * 1) which equals 255.
$FF as a signed number is -1 because it is $100 minus 1.

See also https://en.wikipedia.org/wiki/Two%27s_complement
russellsprouts
Posts: 53
Joined: Sun Jan 31, 2016 9:55 pm

Re: NES Journey to Silius Wrong Death Warp

Post by russellsprouts »

Here's a primer on two's complement.

Basically, there are many possible ways to represent negative numbers using only bits. Two's complement has a special property that the curcuits for adding and subtracting are the same for signed numbers and unsigned numbers, which makes things easier, so most computers use it.

If we to consider a hypothetical 4 bit two's complement system, which covers -8 to 7, the numbers would be represented like this:
0000: $0: 0
0001: $1: 1
0010: $2: 2
0011: $3: 3
0100: $4: 4
0101: $5: 5
0110: $6: 6
0111: $7: 7
1000: $8: -8
1001: $9: -7
1010: $A: -6
1011: $B: -5
1100: $C: -4
1101: $D: -3
1110: $D: -2
1111: $F: -1

Notice that at the half-way point, the numbers wrap from the highest possible (7) to the lowest possible (-8).
To prove that addition is the same, let's try adding 5 and -1, which should give us 4.

Here are the bit representations. You can add them just like in decimal, but remember if the number is 2 or 3, you need to carry the 1 to the next place.

Code: Select all

   0101
+  1111
----------
(1)0100
Remember, these are 4 bit numbers, so we only keep the lower 4 bits. We're left with 0100, which, as we wanted, is equal to 4.

If we extend this to 8 bit numbers, as on the 6502, we get a similar table of values:

0000 0000: $00: 0
0000 0001: $01: 1
...
0111 1111: $7F: 127
1000 0000: $80: -128
1000 0001: $81: -127
...
1111 1110: $FE: -2
1111 1111: $FF: -1

Each group of 4 bits can be represented as a hex digit.
Bavi_H
Posts: 193
Joined: Sun Mar 03, 2013 1:52 am
Location: Texas, USA
Contact:

Re: NES Journey to Silius Wrong Death Warp

Post by Bavi_H »

For another way to think about it, I like to use an odometer analogy.
  • Imagine a 4-digit odometer at 0000. If you roll it backwards one step you'll get 9999. Sometimes it's useful to say this 9999 represents -1. For example, on a 4-digit adding machine, if you enter 0007 + 9999 you'll get 0006 because it only keeps 4 digits. The 9999 is effectively working like a -1. You can keep going to represent other negative numbers: 9998 represents -2, 9997 represents -3, and so on.

    The same concept works in binary: If you have a binary odometer at 0000 and roll it backwards one step you'll get 1111. Sometimes it's useful to say this 1111 represents -1.

Why is it called two's complement? Here's my hypothesis.
  • The Wikipedia article Method of compelments says:
    The nines' complement of a number is formed by replacing each digit with nine minus that digit. [...] The nines' complement plus one is known as the tens' complement.
    I don't know if there's a better-sounding reason why it's called ten's complement other than it's the "nine's complement plus one". I tried searching online a little but didn't find anything.

    In binary the concepts are called one's complement (replacing each digit with one minus that digit) and two's complement (the one's complement plus one). Unless someone knows of a better-sounding reason, maybe it's just called two's complement because it's the "one's complement plus one."
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

Thank you for the information and ideas everyone. Ok, so I figured out how to get a Trace Log snap shot of a single frame of events. I gathered the data on the exact same frame, the first frame of the damage animation when you get hit at the bottom of the 2nd elevator in level 4. You can use the Find function in Chrome to see the only occurrence of 017E in Increment text. I am still working on trying to use Notepad++ of something similar to help me isolate some differences. Help is always appreciated.

Link to Increment - http://wiki.donkeykonggenius.com/Silius_Analysis
Link to Non-Increment - http://wiki.donkeykonggenius.com/~donke ... oldid=2435
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

The 017E Increment occurs within this $DFB5 subroutine that is called. This subroutine does not occur in the non-increment variation.

Code: Select all

 $DF14:20 B5 DF  JSR $DFB5                                    A:60 X:DD Y:00 S:F9 P:nvUbdIzC 
        $DFB5:AD 7B 01  LDA $017B = #$00                             A:60 X:DD Y:00 S:F7 P:nvUbdIzC 
        $DFB8:D0 30     BNE $DFEA                                    A:00 X:DD Y:00 S:F7 P:nvUbdIZC 
        $DFBA:A5 30     LDA $0030 = #$60                             A:00 X:DD Y:00 S:F7 P:nvUbdIZC 
        $DFBC:4A        LSR                                          A:60 X:DD Y:00 S:F7 P:nvUbdIzC 
        $DFBD:4A        LSR                                          A:30 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFBE:4A        LSR                                          A:18 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFBF:4A        LSR                                          A:0C X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFC0:85 00     STA $0000 = #$60                             A:06 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFC2:A5 32     LDA $0032 = #$20                             A:06 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFC4:29 F0     AND #$F0                                     A:20 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFC6:05 00     ORA $0000 = #$06                             A:20 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFC8:85 00     STA $0000 = #$06                             A:26 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFCA:29 01     AND #$01                                     A:26 X:DD Y:00 S:F7 P:nvUbdIzc 
        $DFCC:AA        TAX                                          A:00 X:DD Y:00 S:F7 P:nvUbdIZc 
        $DFCD:46 00     LSR $0000 = #$26                             A:00 X:00 Y:00 S:F7 P:nvUbdIZc 
        $DFCF:A4 00     LDY $0000 = #$13                             A:00 X:00 Y:00 S:F7 P:nvUbdIzc 
        $DFD1:B1 54     LDA ($54),Y @ $806A = #$21                   A:00 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFD3:3D 6B E0  AND $E06B,X @ $E06B = #$F0                   A:21 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFD6:E0 01     CPX #$01                                     A:20 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFD8:F0 04     BEQ $DFDE                                    A:20 X:00 Y:13 S:F7 P:NvUbdIzc 
        $DFDA:4A        LSR                                          A:20 X:00 Y:13 S:F7 P:NvUbdIzc 
        $DFDB:4A        LSR                                          A:10 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFDC:4A        LSR                                          A:08 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFDD:4A        LSR                                          A:04 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFDE:29 0F     AND #$0F                                     A:02 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFE0:C9 0F     CMP #$0F                                     A:02 X:00 Y:13 S:F7 P:nvUbdIzc 
        $DFE2:F0 07     BEQ $DFEB                                    A:02 X:00 Y:13 S:F7 P:NvUbdIzc 
        $DFE4:8D 77 01  STA $0177 = #$02                             A:02 X:00 Y:13 S:F7 P:NvUbdIzc 
        $DFE7:EE 7E 01  INC $017E = #$08                             A:02 X:00 Y:13 S:F7 P:NvUbdIzc 
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

Feos on TASvideos has observed the following. $0030 is the Macro Frame Location as I mentioned above. I have already observed that if this value is 0x60 or higher then the glitch occurs, and if it is 0x5F or lower then it does not. The question is why? I have not seen this occur anywhere else where $0030 is exactly 0x60. Perhaps it must scroll to the left when $0030 is 0x60 for it to occur? I can experiment by finding such a location in the game but if I can not cause this to happen with those variables then it must be something else.

https://i.imgur.com/9Dt3CAr.png

The value of $0030 makes the difference here. It gets loaded to the A register then bitwise AND is executed between that and 0xF0. The result is compared to the value of $0002 (which is likely some temp variable), and depending on which is bigger, the game either jumps to the subroutine than increments your number, of continues normal execution. The glitch succeeds if $0030 is 0x60, but not if it's 0x5F.

Code: Select all

$DF0C:A5 30     LDA $0030 = #$60                             A:50
$DF0E:29 F0     AND #$F0                                     A:60
$DF10:C5 02     CMP $0002 = #$50                             A:60
$DF12:F0 03     BEQ $DF17                                    A:60
$DF14:20 B5 DF  JSR $DFB5                                    A:60

Code: Select all

$DF0C:A5 30     LDA $0030 = #$5F                             A:50
$DF0E:29 F0     AND #$F0                                     A:5F
$DF10:C5 02     CMP $0002 = #$50                             A:50
$DF12:F0 03     BEQ $DF17                                    A:50
$DF17:A5 30     LDA $0030 = #$5F                             A:50
CLChambers00
Posts: 78
Joined: Wed Jul 19, 2017 10:23 am

Re: NES Journey to Silius Wrong Death Warp

Post by CLChambers00 »

It finally dawned on me today to ask the most basic of questions: 1) Can this work in another location in the game? and 2) Can we scroll the screen slower than 4?

And I can tell you that the answer is yes to both! I found another 017E memory address manipulation point in Level 3, under the same conditions as Level 4. And then I found that if I jumped straight up and did a one frame input to the left that my speed will maintain 1 every frame until I land. This made it so that we can effectually "convert" whatever micro frames (x position low byte) we have left to address 017E, the address that tracks your progress through the stage. Enjoy!

https://www.twitch.tv/videos/173708890
User avatar
Myask
Posts: 965
Joined: Sat Jul 12, 2014 3:04 pm

Re: NES Journey to Silius Wrong Death Warp

Post by Myask »

In case you didn't actually look at the links (and it seems useful at this point) remember that holding up while running stops that speed oscillation that you did notice on whatever value it is at the time.
Post Reply