This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

NES Journey to Silius Wrong Death Warp

NES Journey to Silius Wrong Death Warp
by on (#204049)
In the NES game Journey to Silius a few people have experienced a wrong death warp, meaning once you pass a check point, if you die, then you will spawn at that check point. But a few people have had the game place them at the upcoming check point instead even though they never actually went that far in the stage. Without in-depth knowledge of assembly I ask for some mild assistance to determine what memory addresses are read at the time of death and how the game determines where to place the character after the death event. I suspect that it may be a single address that controls this but it may very well be something different. No one has been able to determine how to duplicate this phenomenon beyond the few times that people have seen it happen to them. Any help would be greatly appreciated. Here are some memory addresses that may be related to it. This is an NES programming mystery to be solved... who wants to solve it?

0506 - X Position (Cam) ; Unsigned 1 bit
0500 - X Position ------; Unsigned 1 bit
0501 - X Position (Sub) ; Unsigned 1 bit
0507 - Y Position (Cam) ; Unsigned 1 bit
0504 - X-Speed ---------; Signed 1 bit
001F - Boss HP ---------; Unsigned 1 bit
00B0 - Player HP -------; Unsigned 1 bit
00B1 - Player Ammo -----; Unsigned 1 bit
Re: NES Journey to Silius Wrong Death Warp
by on (#204055)
Not sure this is the best place for it, but…I wish you luck. I might be able to look into it later.

I'd check… http://datacrystal.romhacking.net/wiki/ ... _to_Silius doesn't have a ROM nor RAM map, oh. A thread on TASvideos has a handful more memory addresses.

I see you got the list of "useful addresses" from one of the latest TAS submission texts…including that "1 bit" claim. I suspect those are 1-byte variables instead.
Re: NES Journey to Silius Wrong Death Warp
by on (#204059)
Thanks for the links. I will post any findings here regarding this matter. Please feel free to look into how the game determines where you appear after a death. Finding out how this wrong warp occurs would be huge, and it is only a matter of someone who knows how to pick this apart, someone knowledgeable would be able to do it rather quickly.
Re: NES Journey to Silius Wrong Death Warp
by on (#204063)
What I'd suggest for step 1 is just record an FCEUX movie until you make the bug happen. Stop there and save the movie. (Or if this bug is exploited by an existing TAS, tell us where to get the .FM2 and at what frame it happens.)

That is basically required work for investigating this problem, and it's not something you have to have expert knowledge to do. Once you have a recorded case of the bug, give that to an expert.
Re: NES Journey to Silius Wrong Death Warp
by on (#204064)
Check the checkpoints. See if there are some flags/registers set in memory in correspondence to those flags. Find the address; edit the value of the address; kill the player. Does the spawn location change?
Re: NES Journey to Silius Wrong Death Warp
by on (#204066)
So far no one who TASed this game has been able to reproduce the bug. I spent two hours doing random things in the same spot, mimicking a video that captures this phenomenon and so far no results. So I moved on to looking at RAM addresses, particularly any value changes at the moment of when I pass through a check point, hoping that I would be able to see if there are ways to manipulate this address via game play, something I may be able to catch while doing trials. I have started the process messing with a lua script to write in values to different addresses to see if I can narrow a few of them.
Re: NES Journey to Silius Wrong Death Warp
by on (#204071)
Here is an example of what I mean by a wrong warp, finally was able to have it happen so now I can maybe cross reference the ram addresses in each state, hmmm, is there a quick way of doing that?

https://www.youtube.com/watch?v=xCHi_bzwrjU
Re: NES Journey to Silius Wrong Death Warp
by on (#204077)
Ok so I made some progress. Memory Address 017E determines the next spawn. This value goes up the farther you progress in the level, so what causes the wrong warp is that sometimes this value increases quicker than usual but I have not been able to isolate what influences this value to duplicate it. So if the value is 4 when you die it will put you back at the beginning of the level at value 0, but if you die at 6 then it puts you back at 5. So in the video above the value of the next spawn point is 10, and in the case where it does not work that value is only at a 9 so it places me back at 5, and in the case where it does work then that value is 11 so it places you at 10. :D Now to isolate why it increases quicker in the latter case.
Re: NES Journey to Silius Wrong Death Warp
by on (#204081)
This is the state of the debugger when a value increments this address but I am not sure what I am looking at here. Any thoughts?
Re: NES Journey to Silius Wrong Death Warp
by on (#204088)
OK. Here's some stuff:
Code:
Macro Frame Location = $30
Micro Frame Location = $31
"Ground level" Baseline Value = $32
Walking speed value added to $31 = $34
Lives = $53
Energy = $B0 ; #$FF-$#81 or #$00 = death / $#80 off-screen / #$01-#$7F = positive health
Gun Types Available = $B7 (bitwise)
Selected Gun Type = $B8
Restart Spawn Point = $B9 ; non-zero spawn again
Spawn at Boss = $153 ; #$10 or greater = Boss
P1 Control Values = $162/$163 ; mirrored for DPCM input corruption?
P2 Control Values = $164/$165 ; mirrored for DPCM input corruption? (Used?)
Level Checkpoint for Respawn = $170
Scrolling Boundary = $177; 0 = on / 1 = off
Area Checkpoint for Respawn = $17E ; not all values are respawnable

Titlescreen B Presses for Secret = $301 ; restarts if non-B pressed


Spawn locations are checked up with an indirect value that points to a table of "valid" checkpoint locations per level...
(Thought about if values could be changed during that sequence or read from others... Seems not.)
This is that routine:

Code:
  LDA #$00    ;             
  STA $BF     ; Turn character control on. / no control if nonzero             
  LDA $0170   ; What level should we be at?  ($0170 is only manipulated with an INC clause.)   
  ASL A       ; Shift value of level bitwise to left             
  TAY         ; Transfer shifted level value to Y             
  LDA $0153   ; Are we at a boss level?             
  BEQ $DCE9   ; If so, continue down; if not, skip ahead to Spawn Locations.             
  TYA           
  CLC                     
  ADC #$0A               
  TAY                     
  LDA $DD37,Y ; Data table Address of Spawn Locations LSB (little endian) plus Y           
  STA $00     ; " "             
  LDA $DD38,Y ; Data table Address of Spawn Locations MSB (little endian) plus Y           
  STA $01     ; " "             
  LDY #$00                 
  LDA ($00),Y ; Load the spawn location token to $02 and clear Y             
  STA $02     ; " "             
  INY         ;             
  LDA ($00),Y ; Load the value of the address of the spawn token plus 1.           
  CMP $017E   ; What's the achieved, current checkpoint location?           
  BCS $DD0A   ;             
  INY         ;             
  INY         ;             
  INY         ;             
  INY         ;             
  INY         ;             
  DEC $02     ;             
  BNE $DCFA   ;             
  INY         ;             
  LDA ($00),Y ; Check for the closest, valid checkpoint location value           
  STA $017E   ; compared to the data table and store it.               
  INY         ;             
  LDA ($00),Y ; If loaded a 00 value and stored into $0177, it's a boss level.           
  STA $0177   ; " "           
  INY         ;             
  LDA ($00),Y ;             
  STA $0500               
  AND #$F0                 
  STA $30                 
  INY                     
  LDA ($00),Y             
  STA $0502               
  AND #$F0                 
  STA $32                 
  LDA #$00                 
  STA $0501               
  STA $0503               
  STA $31                 
  STA $33                 
  RTS                     
 


Now... I've debugged the first level through a routine and the only way $017E is written to is an INC function, which happens after so many bytes (compared to a ROM address table) are reached. Is there a particular level where the death skip is reported more frequently?
Code:
  LDA $017B ; if $017B is nonzero then run the INC $017E routine!               
  BNE $DFEA ; " "               
  LDA $30   ; Where is the player? Increments when scrolls left.             
  LSR A     ;  MS(nibble) of $30 is the checkpoint value.             
  LSR A     ;               
  LSR A     ;               
  LSR A     ;               
  STA $00                 
  LDA $32 ; is player on the screen or not?                 
  AND #$F0 ;               
  ORA $00                 
  STA $00                 
  AND #$01                 
  TAX                     
  LSR $00                 
  LDY $00                 
  LDA ($54),Y             
  AND $E06B,X             
  CPX #$01                 
  BEQ $DFDE  ; skip to checking if it's #$0F or greater.
  LSR A                   
  LSR A                   
  LSR A                   
  LSR A                   
  AND #$0F  ;               
  CMP #$0F  ;               
  BEQ $DFEB ; go to scrolling/walking routine and do not increment. :(             
  STA $0177               
  INC $017E ; increment the checkpoint!               
  RTS

Dude, it looks like we'd need to find out how to continue incrementation of $30 in order to increment $017E... That or find a way to fake the game out to think it's scrolling when it's not.
Re: NES Journey to Silius Wrong Death Warp
by on (#204098)
The following link is to the video I did showing the death warp. Now, I have found that for some reason when you take a hit in the face at the bottom of the 2nd elevator it may cause address 017E to jump, and when it does I have observed that it can increase as much as 6, so instead of having a value of 8 at that point in the stage you end up with a 14! This is what enables you to die later in the stage when the value hits 26 and it will warp you forward to where that value is usually achieved. I also created a tas video attached that shows this occurring in level 4. You will just need to watch it up to that point, see video link for reference. And see what is happening in the ram as to why this spike in value occurs. That would be awesome!

https://www.twitch.tv/videos/172953158
Re: NES Journey to Silius Wrong Death Warp
by on (#204135)
This is the Trace Logger Data for the single frame when the extra increment occurs. This is when you are hit by the enemy and you boost backward scrolling the screen.
Code:
A:12 X:DD Y:00 S:F3 P:nvUbdIzC  $DEFC:18        CLC
A:12 X:DD Y:00 S:F3 P:nvUbdIzc  $DEFD:69 E0     ADC #$E0
A:F2 X:DD Y:00 S:F3 P:NvUbdIzc  $DEFF:A9 FF     LDA #$FF
A:FF X:DD Y:00 S:F3 P:NvUbdIzc  $DF01:65 30     ADC $0030 = #$60
A:5F X:DD Y:00 S:F3 P:nvUbdIzC  $DF03:4C 08 DF  JMP $DF08
A:5F X:DD Y:00 S:F3 P:nvUbdIzC  $DF08:29 F0     AND #$F0
A:50 X:DD Y:00 S:F3 P:nvUbdIzC  $DF0A:85 02     STA $0002 = #$20
A:50 X:DD Y:00 S:F3 P:nvUbdIzC  $DF0C:A5 30     LDA $0030 = #$60
A:60 X:DD Y:00 S:F3 P:nvUbdIzC  $DF0E:29 F0     AND #$F0
A:60 X:DD Y:00 S:F3 P:nvUbdIzC  $DF10:C5 02     CMP $0002 = #$50
A:60 X:DD Y:00 S:F3 P:nvUbdIzC  $DF12:F0 03     BEQ $DF17
A:60 X:DD Y:00 S:F3 P:nvUbdIzC  $DF14:20 B5 DF  JSR $DFB5
A:60 X:DD Y:00 S:F1 P:nvUbdIzC  $DFB5:AD 7B 01  LDA $017B = #$00
A:00 X:DD Y:00 S:F1 P:nvUbdIZC  $DFB8:D0 30     BNE $DFEA
A:00 X:DD Y:00 S:F1 P:nvUbdIZC  $DFBA:A5 30     LDA $0030 = #$60
A:60 X:DD Y:00 S:F1 P:nvUbdIzC  $DFBC:4A        LSR
A:30 X:DD Y:00 S:F1 P:nvUbdIzc  $DFBD:4A        LSR
A:18 X:DD Y:00 S:F1 P:nvUbdIzc  $DFBE:4A        LSR
A:0C X:DD Y:00 S:F1 P:nvUbdIzc  $DFBF:4A        LSR
A:06 X:DD Y:00 S:F1 P:nvUbdIzc  $DFC0:85 00     STA $0000 = #$60
A:06 X:DD Y:00 S:F1 P:nvUbdIzc  $DFC2:A5 32     LDA $0032 = #$20
A:20 X:DD Y:00 S:F1 P:nvUbdIzc  $DFC4:29 F0     AND #$F0
A:20 X:DD Y:00 S:F1 P:nvUbdIzc  $DFC6:05 00     ORA $0000 = #$06
A:26 X:DD Y:00 S:F1 P:nvUbdIzc  $DFC8:85 00     STA $0000 = #$06
A:26 X:DD Y:00 S:F1 P:nvUbdIzc  $DFCA:29 01     AND #$01
A:00 X:DD Y:00 S:F1 P:nvUbdIZc  $DFCC:AA        TAX
A:00 X:00 Y:00 S:F1 P:nvUbdIZc  $DFCD:46 00     LSR $0000 = #$26
A:00 X:00 Y:00 S:F1 P:nvUbdIzc  $DFCF:A4 00     LDY $0000 = #$13
A:00 X:00 Y:13 S:F1 P:nvUbdIzc  $DFD1:B1 54     LDA ($54),Y @ $806A = #$21
A:21 X:00 Y:13 S:F1 P:nvUbdIzc  $DFD3:3D 6B E0  AND $E06B,X @ $E06B = #$F0
A:20 X:00 Y:13 S:F1 P:nvUbdIzc  $DFD6:E0 01     CPX #$01
A:20 X:00 Y:13 S:F1 P:NvUbdIzc  $DFD8:F0 04     BEQ $DFDE
A:20 X:00 Y:13 S:F1 P:NvUbdIzc  $DFDA:4A        LSR
A:10 X:00 Y:13 S:F1 P:nvUbdIzc  $DFDB:4A        LSR
A:08 X:00 Y:13 S:F1 P:nvUbdIzc  $DFDC:4A        LSR
A:04 X:00 Y:13 S:F1 P:nvUbdIzc  $DFDD:4A        LSR
A:02 X:00 Y:13 S:F1 P:nvUbdIzc  $DFDE:29 0F     AND #$0F
A:02 X:00 Y:13 S:F1 P:nvUbdIzc  $DFE0:C9 0F     CMP #$0F
A:02 X:00 Y:13 S:F1 P:NvUbdIzc  $DFE2:F0 07     BEQ $DFEB
A:02 X:00 Y:13 S:F1 P:NvUbdIzc  $DFE4:8D 77 01  STA $0177 = #$02
Breakpoint 0 Hit at $DFE7: $017E:EC-W--
Logging finished.

And this is the last segment in the Debugger. There must be a reason why sometimes it will increment many times in successive frames upon taking this hit and sometimes it does not. Any thoughts?
Code:
07:DF8E:60        RTS -----------------------------------------
 07:DF8F:A5 32     LDA $0032 = #$20
 07:DF91:29 0F     AND #$0F
 07:DF93:C9 0F     CMP #$0F
 07:DF95:D0 0D     BNE $DFA4
 07:DF97:20 D6 E0  JSR $E0D6
 07:DF9A:A5 32     LDA $0032 = #$20
 07:DF9C:29 F0     AND #$F0
 07:DF9E:09 0E     ORA #$0E
 07:DFA0:85 32     STA $0032 = #$20
 07:DFA2:D0 D6     BNE $DF7A
 07:DFA4:A5 33     LDA $0033 = #$00
 07:DFA6:18        CLC
 07:DFA7:65 35     ADC $0035 = #$00
 07:DFA9:A5 32     LDA $0032 = #$20
 07:DFAB:69 FF     ADC #$FF
 07:DFAD:29 0F     AND #$0F
 07:DFAF:C9 0F     CMP #$0F
 07:DFB1:D0 C7     BNE $DF7A
 07:DFB3:F0 C2     BEQ $DF77
 07:DFB5:AD 7B 01  LDA $017B = #$00
 07:DFB8:D0 30     BNE $DFEA
 07:DFBA:A5 30     LDA $0030 = #$60
 07:DFBC:4A        LSR
 07:DFBD:4A        LSR
 07:DFBE:4A        LSR
 07:DFBF:4A        LSR
 07:DFC0:85 00     STA $0000 = #$13
 07:DFC2:A5 32     LDA $0032 = #$20
 07:DFC4:29 F0     AND #$F0
 07:DFC6:05 00     ORA $0000 = #$13
 07:DFC8:85 00     STA $0000 = #$13
 07:DFCA:29 01     AND #$01
 07:DFCC:AA        TAX
 07:DFCD:46 00     LSR $0000 = #$13
 07:DFCF:A4 00     LDY $0000 = #$13
 07:DFD1:B1 54     LDA ($54),Y @ $806A = #$21
 07:DFD3:3D 6B E0  AND $E06B,X @ $E06B = #$F0
 07:DFD6:E0 01     CPX #$01
 07:DFD8:F0 04     BEQ $DFDE
 07:DFDA:4A        LSR
 07:DFDB:4A        LSR
 07:DFDC:4A        LSR
 07:DFDD:4A        LSR
 07:DFDE:29 0F     AND #$0F
 07:DFE0:C9 0F     CMP #$0F
 07:DFE2:F0 07     BEQ $DFEB
 07:DFE4:8D 77 01  STA $0177 = #$02
>07:DFE7:EE 7E 01  INC $017E = #$08
 07:DFEA:60        RTS -----------------------------------------
Re: NES Journey to Silius Wrong Death Warp
by on (#204136)
Perhaps this subroutine is called more than once. Please don't post an trace of multiple frames (if so).

There's nothing here that explained why.

Check the code is that is calling this subroutine.
Re: NES Journey to Silius Wrong Death Warp
by on (#204149)
Pertinent Information
017E Spawn Location
0177 Scroll Boundary
0030 Macro Frame Location
0031 Micro Frame Location
0032 Vertical Location
0034 Run Speed

Basic Observation #1
The Run Speed value is added to Micro Frame Location each frame. The Run Speed value has an acceleration stage such that it increases, 4, 8, 12, 16, 20, 24, and then fluctuates between 22 and 26 each frame.

Basic Observation #2
While your character jumps the Run Speed value will fluctuate between 21, 22, and 23, so the length of a jump will also influence the final value of the Micro Frame Location upon reaching the Scroll Boundary.

Basic Observation #3
When the Scroll Boundary value changes, the code increments Spawn Location by 1.

Basic Observation #4
When the Micro Frame Location value exceeds 255 it will roll over to 0 and this will increment Macro Frame Location by 1.

Basic Observation #5
Every 16 counts on the Macro Frame Location value will increment the Spawn Location by 1. The Macro Frame Location value increases with scrolling to the right, and decreases with scrolling to the left. Likewise every 16 counts on the Vertical Location will also increment the Spawn Location by 1. Vertical Location increases with scrolling down and decreases with scrolling up.

Interestingly I can see what is occurring in order for this glitch to work but I do not understand why it happens. And if I could understand why then perhaps that knowledge could be used to determine if it could be exploited in other areas of the game and if so then where.

When you reach the top of the 2nd elevator in Stage 4, when you reach this Scroll Boundary the Macro Frame Location value seems to reach 96 every time, as the Micro Frame Location rolls over around this time. Depending upon the Run Speed values through this section of stage 4, as well as the value changes when in a jump animation, or knock backs, this may cause the Micro Frame Location value to roll over to 0 or it could go as high as 24 depending upon the Micro Frame Location value the previous frame. Such that if the Micro Frame Location value were 230 and the Run Speed was 26 then on the following frame the Micro Frame Location value will roll over to 0. Likewise, if the Micro Frame Location value was 254, then it would roll over to 24 with a Run Speed of 26 the previous frame.

Therefore, when you reach the top of the 2nd elevator in Stage 4, the Micro Frame Location value could be anywhere between 0 and 25.

When you reach the bottom of the 2nd elevator and get hit by an enemy bullet the screen will scroll to the left, and the Micro Frame Location value will decrease by 4 every frame while in the damage animation which scrolls the screen. Depending upon the Micro Frame Location value, such that if it were 24, then it would reach 0 after 6 frames. Interestingly enough each time the Micro Frame Location value decreases by 4 while the Macro Frame Location value is 96, the Spawn Location value will increment by 1 each frame.

Therefore, for some reason, once the Macro Frame Location reaches 95, the Spawn Location will no longer increment even though your character is in the same damage animation scrolling the screen. In other words, it is related to screen scrolling but the magic number seems to be Macro Frame Location value 96. As long as this value is 96, the Spawn Location value will increment by 1 each frame, otherwise it will not.

Here is a video of me demonstrating these additional increments: https://www.twitch.tv/videos/173221791

Here is a video of me demonstrating the strategy I developed in order to get the best death warp 50% of the time: https://www.twitch.tv/videos/173225643
Re: NES Journey to Silius Wrong Death Warp
by on (#204150)
Yes... Also remember that $32 (Vertical (up/down) frame location) is a part of the equation regarding checkpoint value incrementation. I've noticed areas in Level 2 simply by falling down gaps that the checkpoint counter increases.

(I've even tried seeing if for some reason someone could trigger a boss spawn on death as well.)

Edit: Yeah... I meant up/down. (Gotta get my sleep more regular. :))
Re: NES Journey to Silius Wrong Death Warp
by on (#204157)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204158)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204164)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204180)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204184)
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
Re: NES Journey to Silius Wrong Death Warp
by on (#204190)
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!
Re: NES Journey to Silius Wrong Death Warp
by on (#204191)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204192)
$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
Re: NES Journey to Silius Wrong Death Warp
by on (#204193)
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:
   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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204207)
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."
Re: NES Journey to Silius Wrong Death Warp
by on (#204237)
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
Re: NES Journey to Silius Wrong Death Warp
by on (#204243)
The 017E Increment occurs within this $DFB5 subroutine that is called. This subroutine does not occur in the non-increment variation.

Code:
 $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
Re: NES Journey to Silius Wrong Death Warp
by on (#204244)
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:
$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:
$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
Re: NES Journey to Silius Wrong Death Warp
by on (#204285)
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
Re: NES Journey to Silius Wrong Death Warp
by on (#204405)
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.
Re: NES Journey to Silius Wrong Death Warp
by on (#204588)
Hey CLChambers00,

Here's a Level Select patch for Journey to Silius (U) so you don't have to worry about using Raf World to practice. :)

(Still looking into other potential exploits when I have the time...)
Re: NES Journey to Silius Wrong Death Warp
by on (#204681)
Most excellent sir! Thank you very much! This is actually very helpful since the sprite of Jay McCray is larger in the US version, and therefore it would be better to practice on this for setting up visual cues, etc. Thank you!
Re: NES Journey to Silius Wrong Death Warp
by on (#204686)
Also, I am curious how you made this patch. Are there programs out there that you use to view rom code? Also how are you creating these ips files? Also, is there a program out there that can show the differences between two roms? A friend of mine made a hack of Who Framed Roger Rabbit a few months ago and it shows values of ram addresses when running etc, and I wanted to see what he did to it that made it do this. Or is there an easier way to beginning learning these things.

I would really like to dive into this a bit because there is a new mystery in Blaster Master, something that has only been seen once and has not yet been reproduced. It occurs here: https://youtu.be/g5Hq2eASg74?t=28m56s

I was thinking that I could start by finding the subroutine that loads the boss or something like that. Any direction on learning these things would be helpful. :D
Re: NES Journey to Silius Wrong Death Warp
by on (#204775)
CLChambers00 wrote:
Also, I am curious how you made this patch. Are there programs out there that you use to view rom code? Also how are you creating these ips files? Also, is there a program out there that can show the differences between two roms? A friend of mine made a hack of Who Framed Roger Rabbit a few months ago and it shows values of ram addresses when running etc, and I wanted to see what he did to it that made it do this. Or is there an easier way to beginning learning these things.

I would really like to dive into this a bit because there is a new mystery in Blaster Master, something that has only been seen once and has not yet been reproduced. It occurs here: https://youtu.be/g5Hq2eASg74?t=28m56s

I was thinking that I could start by finding the subroutine that loads the boss or something like that. Any direction on learning these things would be helpful. :D

Sure... A couple things... First off I saw that there was a Game Genie code for Level Select on TCRF.

There is also a Game Genie decoder program... You will need a Hex Editor program. Find one that you like. I like Hex Workshop; but there are others that are freeware. To compare files, there is a compare function. However... In this case, I found those decoded addresses by adding the offset of +$8000 to get into ROM space. The "compare" value is what the Game Genie expects. Once it finds the compare value at that bank it replaces it with the "value" value. This is essentially overwriting opcodes or values for opcodes. In the case of this code it is turning an RTS instruction to a NOP instruction which enters the level select routine. The secondary code increases the maximum value of levels to $06 instead of $05 so that the final boss is selectable during the boss selection portion. Not certain it's possible to jump into the level select routine naturally, but I haven't done much research yet.

Remember that hex code can be disassembled into assembly. You can find your differences that way through disassemblers and hex editors. :)
Re: NES Journey to Silius Wrong Death Warp
by on (#204957)
Thanks for the information, I greatly appreciate it! You have been very helpful on my journey to learn more about this stuff.