Posts for MESHUGGAH

MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
hungry in Hungary
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
While I tried to understand coroutines, callbacks and threads, I had no success attempt at making them fully async. Also since I don't use IDE, it's hard to debug force close issues. I hold this project until I get success between 2 instances with full async.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
feos wrote:
How about IPC?
This actually looks like a really good and reliable approach. However never done that before and source code is not available.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
Post subject: TASing multiple emulators simultaneously
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I've started a little project a few days ago to help AngerFist to record 9 TASes with 1 input. My basic idea was to make a C# app that launches the 9 FCEUX instances and sends the desired input individually. As far as I know, simulating input can only be done by using SendInput (DirectInput) to the active focused window (SetForegroundWindow). Since it doesn't changes instantly, and GetForegroundWindow neither can tell that it was really that window was the active one on that very moment and even other applications could steal focus (or the user mistakenly presses alt-tab etc), I'm not sure is it still a good approach to deal with simulating input rather than changing the appropriate memory values. I'm currently implementing the "Add input to input list" -> "Send input for each FCEUX individually" -> "Check it's really worked" (if not, try again). I also think that... - It could be trouble some to inject code or alter the way FCEUX works. - While reading memory shouldn't be a problem, writing memory could crash the instance. However it wouldn't be troublesome to relaunch it and resume to TASing, and this would also eliminate the "focus" problem (the only way to send "simulated" input). I'm looking for mainly advices and/or thoughts about which approach should be used. edit: a screenshot if you don't understand what I'm talking about
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I've tried a lot of different ways to feed input to FCEUX but I have no idea what I'm missing. I know that 32bit/64bit need to be dealt (and I tried to use similar things from pinvoke) but I get either 1008 marshal result or 0 on 64bit. Source (and debug exe): http://users.atw.hu/warcataclysm/mih1.zip For debugging purposes it just launches 2 instances of fceux. For testing, stop the movie file (or edit the arguments of launching the processes) and just simply press the button at virtual controller. It would try to send the button "A". edit: and it would be still better if you would contact AnS about the possibility to link multiple instances to 1 TASEditor (some functions should be removed for efficiency)
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
feos wrote:
So, back to what spawned this thread, the Defender of the Crown submission that ends input later, having NO gameplay improvements, should obsolete the same run that finishes input sooner?
Just let me share my opinion again with different wording. For me, (accepted) TASes are a series of input that will ensure the game will be finished and reaches a positive end game state in the future. Using that example, the TASer spent fewer time to "implement" a strategy that will guarantee a success completion of the game while the published one takes more time to feed the game with enough input to get that positive end game state. I think the different viewpoints ("input time vs avi time") could be distributed to 1. The time you need to "play" the game to get the ending 2. The time you need to "wait" to get the ending. I wonder what kind of explanation would satisfy those who favors "ending screen comes up earlier".
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I've made a little test run up to stage 3 early part, I've merely translated that youtube video to a TAS. I'm not sure I will continue it and I didn't even checked your submission. But feel free to use my movie.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
easy yes vote
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Let me share my point of view. I think there's no need to make specific endpoint rules. The main goal of a TAS is to complete the game as fast as possible. This means that the TAS has enough button presses to make the game reach it's credits. Using the Defender of the crown TASes as an example, the published one requires fewer input to finish the game to reach the ending while the submitted one requires longer input to finish the game and reach the ending faster.
Baxter wrote:
Games like Defenders of the Crown make you wonder what our real goal is though, to provide TASes that completes the game as fast as possible, or to provide the shortest possible input file.
The published one makes those actions and end them as earlier as possible that will "guarantee" a success completion of the game. I would say you should always aim for shortest input as long as it meets the goals (so TASes targeting smallest in-game time don't need to aim for input length too). If we would have specific endpoints (1st ending screen, 1st frame of changing some memory value that only occurs when ending is being loaded, etc) it would be too ambigous and I believe that "completing" a game is a process and not a specific state that you aim to bring it as fast as possible to clarify yourself about the end of this process. For vault, I would say shortest input should be used and other tiered TASes should aim for the more entertaining version if the viewers demand it.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I've found an improvement that saves 5 frames already (manipulated one of the pink monster even better at ~2800th frame which lead to a faster ~3822th frame scene), so I cancel this submission and will resubmit when I'm done with it (probably a week at least). AnS: this isn't a random number. The reason I have many files is - I keep all possible routes in different .fm3 files and compare multiple ones with multiple fceux instances, so I don't need to memorize multiple values just watch the screen. - Most of the .fm3 files are obviously very similar, I just don't want to lose already done routes. My first TAS test wip (03:28.09) were made by 41 .fm3 files, later everytime I found an improvement, I had to resync the whole TAS which means I had to test all possible positions again since the 6th lag frame rule can be placed at an unfortunate frame. For example using the door can be made only on "not fake or real lag" frames, so if you are 1 frame faster and the frame you used U earlier was after a fake lag frame, next time you will have a lag frame there where you would use that. I think you understand what I'm talking about. And of course, this is still just a statistical value and only numberophiles get enjoyed by that.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
mklip2001 wrote:
This looks pretty good. It's not as entertaining as Superb Joe though, mostly because the enemy density is a lot less most of the time. Also, the more I watched the video, the more I was getting annoyed that the character can grapple but never swings on the grapple. I know that what you did is faster, and I support that, but ultimately it makes for a less enjoyable run. I'm going to have to go with Meh on entertainment, personally; I feel this doesn't really offer anything too rewarding beyond what Superb Joe mode does. Good job with the technical quality though!
Thank you! Well, trading speed for entertainment is not an option for me. I've tried to spice up the run as much as I could without making huge desyncs, so I manipulated sometimes the movement pattern sound, made a few "close calls" on pinky monsters (spawned from clowns), and I think that some routes I pulled of are clearly not the intended ones. I've also let the swinging sometimes when I didn't had to build up speed fast to avoid being too frequent of that noise. Also the swinging positions in a row at same ceiling heights are different for that similar reason (some variety). I mean scenes like this: https://www.youtube.com/watch?v=KpMYOHU85pI&feature=player_detailpage&t=102 until the next door. Also for comparison: RTA WR - 4:17.49 An unoptimized TAS by "byrz" - 3:42.15 (doesn't uses the 1st secret door) And mine: 3:25.79 For me, being so much faster is always adds to my own entertainment. edit: btw I made 139 fm3 files through out the making of this TAS (and I started the very first level after submitting my 1st superb joe mode run (2013.02.20))
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
TASeditor wrote:
MESHUGGAH = TASing robot of the year. Yes vote.
Aglar bested me a lot of times during the WIPs, he actually improved all of the levels with at least 1 frame.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Just a few notes to reminder me and Aglar about the movie.
    - Our WIP now really uses the hardest difficulty which needs an extra frame to select it. However we get 1 lag frame fewer (with trading) so if everything goes well, it will be the same length as the normal difficulty run. - Level 3 boss "transforming to a ball until transforming back to hittable" is 212 frames if it's the fastest (214 if it's slower). RNG resync needed. - Level 4 goat should be very similar to the non-hard movie (so lag frame should be traded again by removing "R" before that)
And we target for a final time of 07:05.48 (=length of normal difficulty) (not sure if 1 frame improvement by Aglar on level 4 will save extra frame(s)).
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
I grab the second vine 1 frame faster here by that subpixel thing.
You are right, it's really faster by 1 frame. Not changing the X subpos and jumping from the flower to the bee gives a much better Y position on the 2nd vine. I didn't saw that the game doesn't changes the Y spd (only Y pos) when grabbing vines but talespin (the guy in the helicopter). However I'm still don't understand how could you made that very good jump with just 38 rerecords. I would be glad if we could work as a team (and I'm okay with being a coauthor and you as an author). edit: I've created the Wiki: GameResources/NES/DuckTales page for more recent things. Updating continuously RNG is at $C2E6 subroutine
A:00 X:06 Y:01 S:BF P:nvUBdIZc $DC23:20 E6 C2  JSR $C2E6
A:00 X:06 Y:01 S:BD P:nvUBdIZc   $C2E6:A2 00     LDX #$00
A:00 X:00 Y:01 S:BD P:nvUBdIZc   $C2E8:A0 04     LDY #$04
A:00 X:00 Y:04 S:BD P:nvUBdIzc   $C2EA:B5 C0     LDA $C0,X @ $00C0 = #$85
A:85 X:00 Y:04 S:BD P:NvUBdIzc   $C2EC:29 02     AND #$02
A:00 X:00 Y:04 S:BD P:nvUBdIZc   $C2EE:85 00     STA $0000 = #$8D
A:00 X:00 Y:04 S:BD P:nvUBdIZc   $C2F0:B5 C1     LDA $C1,X @ $00C1 = #$1E
A:1E X:00 Y:04 S:BD P:nvUBdIzc   $C2F2:29 02     AND #$02
A:02 X:00 Y:04 S:BD P:nvUBdIzc   $C2F4:45 00     EOR $0000 = #$00
A:02 X:00 Y:04 S:BD P:nvUBdIzc   $C2F6:18        CLC
A:02 X:00 Y:04 S:BD P:nvUBdIzc   $C2F7:F0 01     BEQ $C2FA
A:02 X:00 Y:04 S:BD P:nvUBdIzc   $C2F9:38        SEC
A:02 X:00 Y:04 S:BD P:nvUBdIzC   $C2FA:76 C0     ROR $C0,X @ $00C0 = #$85
A:02 X:00 Y:04 S:BD P:NvUBdIzC   $C2FC:E8        INX
A:02 X:01 Y:04 S:BD P:nvUBdIzC   $C2FD:88        DEY
A:02 X:01 Y:03 S:BD P:nvUBdIzC   $C2FE:D0 FA     BNE $C2FA
A:02 X:01 Y:03 S:BD P:nvUBdIzC   $C2FA:76 C0     ROR $C0,X @ $00C1 = #$1E
A:02 X:01 Y:03 S:BD P:NvUBdIzc   $C2FC:E8        INX
A:02 X:02 Y:03 S:BD P:nvUBdIzc   $C2FD:88        DEY
A:02 X:02 Y:02 S:BD P:nvUBdIzc   $C2FE:D0 FA     BNE $C2FA
A:02 X:02 Y:02 S:BD P:nvUBdIzc   $C2FA:76 C0     ROR $C0,X @ $00C2 = #$14
A:02 X:02 Y:02 S:BD P:nvUBdIzc   $C2FC:E8        INX
A:02 X:03 Y:02 S:BD P:nvUBdIzc   $C2FD:88        DEY
A:02 X:03 Y:01 S:BD P:nvUBdIzc   $C2FE:D0 FA     BNE $C2FA
A:02 X:03 Y:01 S:BD P:nvUBdIzc   $C2FA:76 C0     ROR $C0,X @ $00C3 = #$28
A:02 X:03 Y:01 S:BD P:nvUBdIzc   $C2FC:E8        INX
A:02 X:04 Y:01 S:BD P:nvUBdIzc   $C2FD:88        DEY
A:02 X:04 Y:00 S:BD P:nvUBdIZc   $C2FE:D0 FA     BNE $C2FA
A:02 X:04 Y:00 S:BD P:nvUBdIZc   $C300:60        RTS (from $C2E6) -----------------
Boss 2 RNG is loaded at the last "smoke" sprite before transforming to a bird
f7351   A:22 X:0F Y:26 S:BB P:nvUbdIzc     $8020:6C 00 00  JMP ($0000) = $A335
f7351   A:22 X:0F Y:26 S:BB P:nvUbdIzc     $A335:BD 90 06  LDA $0690,X @ $069F = #$00
f7351   A:00 X:0F Y:26 S:BB P:nvUbdIZc     $A338:F0 0A     BEQ $A344
f7351   A:00 X:0F Y:26 S:BB P:nvUbdIZc     $A344:BD 00 07  LDA $0700,X @ $070F = #$E1
f7351   A:E1 X:0F Y:26 S:BB P:NvUbdIzc     $A347:29 0F     AND #$0F
f7351   A:01 X:0F Y:26 S:BB P:nvUbdIzc     $A349:A8        TAY
f7351   A:01 X:0F Y:01 S:BB P:nvUbdIzc     $A34A:B9 85 A5  LDA $A585,Y @ $A586 = #$86
f7351   A:86 X:0F Y:01 S:BB P:NvUbdIzc     $A34D:85 00     STA $0000 = #$35
f7351   A:86 X:0F Y:01 S:BB P:NvUbdIzc     $A34F:B9 8A A5  LDA $A58A,Y @ $A58B = #$A3
f7351   A:A3 X:0F Y:01 S:BB P:NvUbdIzc     $A352:85 01     STA $0001 = #$A3
f7351   A:A3 X:0F Y:01 S:BB P:NvUbdIzc     $A354:6C 00 00  JMP ($0000) = $A386
f7351   A:A3 X:0F Y:01 S:BB P:NvUbdIzc     $A386:BD 20 06  LDA $0620,X @ $062F = #$2A
f7351   A:2A X:0F Y:01 S:BB P:nvUbdIzc     $A389:C9 2A     CMP #$2A
f7351   A:2A X:0F Y:01 S:BB P:nvUbdIZC     $A38B:D0 29     BNE $A3B6
f7351   A:2A X:0F Y:01 S:BB P:nvUbdIZC     $A38D:BD 10 06  LDA $0610,X @ $061F = #$01
f7351   A:01 X:0F Y:01 S:BB P:nvUbdIzC     $A390:F0 23     BEQ $A3B5
f7351   A:01 X:0F Y:01 S:BB P:nvUbdIzC     $A392:BD 30 06  LDA $0630,X @ $063F = #$05
f7351   A:05 X:0F Y:01 S:BB P:nvUbdIzC     $A395:C9 05     CMP #$05
f7351   A:05 X:0F Y:01 S:BB P:nvUbdIZC     $A397:D0 1C     BNE $A3B5
f7351   A:05 X:0F Y:01 S:BB P:nvUbdIZC     $A399:A9 5E     LDA #$5E
f7351   A:5E X:0F Y:01 S:BB P:nvUbdIzC     $A39B:9D 20 06  STA $0620,X @ $062F = #$2A
f7351   A:5E X:0F Y:01 S:BB P:nvUbdIzC     $A39E:A9 00     LDA #$00
f7351   A:00 X:0F Y:01 S:BB P:nvUbdIZC     $A3A0:9D 30 06  STA $0630,X @ $063F = #$05
f7351   A:00 X:0F Y:01 S:BB P:nvUbdIZC     $A3A3:9D 10 06  STA $0610,X @ $061F = #$01
f7351   A:00 X:0F Y:01 S:BB P:nvUbdIZC     $A3A6:A5 C0     LDA $00C0 = #$7A
f7351   A:7A X:0F Y:01 S:BB P:nvUbdIzC     $A3A8:65 C2     ADC $00C2 = #$0D
f7351   A:88 X:0F Y:01 S:BB P:NVUbdIzc     $A3AA:85 C1     STA $00C1 = #$F8
f7351   A:88 X:0F Y:01 S:BB P:NVUbdIzc     $A3AC:29 03     AND #$03
f7351   A:00 X:0F Y:01 S:BB P:nVUbdIZc     $A3AE:A8        TAY
f7351   A:00 X:0F Y:00 S:BB P:nVUbdIZc     $A3AF:B9 8F A5  LDA $A58F,Y @ $A58F = #$68
f7351   A:68 X:0F Y:00 S:BB P:nVUbdIzc     $A3B2:9D B0 06  STA $06B0,X @ $06BF = #$3C
f7351   A:68 X:0F Y:00 S:BB P:nVUbdIzc     $A3B5:60        RTS ------------------------------
If he finished his last pattern, he goes to the next
f7372   A:5E X:0F Y:01 S:BB P:nvUbdIzC     $A3B6:20 84 F2  JSR $F284
f7372   A:5E X:0F Y:01 S:B9 P:nvUbdIzC       $F284:BD 60 06  LDA $0660,X @ $066F = #$AB
f7372   A:AB X:0F Y:01 S:B9 P:NvUbdIzC       $F287:38        SEC
f7372   A:AB X:0F Y:01 S:B9 P:NvUbdIzC       $F288:FD B0 07  SBC $07B0,X @ $07BF = #$80
f7372   A:2B X:0F Y:01 S:B9 P:nvUbdIzC       $F28B:9D 60 06  STA $0660,X @ $066F = #$AB
f7372   A:2B X:0F Y:01 S:B9 P:nvUbdIzC       $F28E:BD 40 06  LDA $0640,X @ $064F = #$6A
f7372   A:6A X:0F Y:01 S:B9 P:nvUbdIzC       $F291:FD C0 07  SBC $07C0,X @ $07CF = #$03
f7372   A:67 X:0F Y:01 S:B9 P:nvUbdIzC       $F294:9D 40 06  STA $0640,X @ $064F = #$6A
f7372   A:67 X:0F Y:01 S:B9 P:nvUbdIzC       $F297:60        RTS (from $F284) -----------------
f7372   A:67 X:0F Y:01 S:BB P:nvUbdIzC     $A3B9:BD 40 06  LDA $0640,X @ $064F = #$67
f7372   A:67 X:0F Y:01 S:BB P:nvUbdIzC     $A3BC:DD B0 06  CMP $06B0,X @ $06BF = #$68
f7372   A:67 X:0F Y:01 S:BB P:NvUbdIzc     $A3BF:B0 2A     BCS $A3EB
f7372   A:67 X:0F Y:01 S:BB P:NvUbdIzc     $A3C1:A5 C1     LDA $00C1 = #$0F
f7372   A:0F X:0F Y:01 S:BB P:nvUbdIzc     $A3C3:65 C3     ADC $00C3 = #$D4
f7372   A:E3 X:0F Y:01 S:BB P:NvUbdIzc     $A3C5:85 C2     STA $00C2 = #$CB
f7372   A:E3 X:0F Y:01 S:BB P:NvUbdIzc     $A3C7:29 07     AND #$07
f7372   A:03 X:0F Y:01 S:BB P:nvUbdIzc     $A3C9:A8        TAY
f7372   A:03 X:0F Y:03 S:BB P:nvUbdIzc     $A3CA:B9 97 A5  LDA $A597,Y @ $A59A = #$B0
f7372   A:B0 X:0F Y:03 S:BB P:NvUbdIzc     $A3CD:9D C0 06  STA $06C0,X @ $06CF = #$00
f7372   A:B0 X:0F Y:03 S:BB P:NvUbdIzc     $A3D0:98        TYA
f7372   A:03 X:0F Y:03 S:BB P:nvUbdIzc     $A3D1:29 01     AND #$01
f7372   A:01 X:0F Y:03 S:BB P:nvUbdIzc     $A3D3:A8        TAY
f7372   A:01 X:0F Y:01 S:BB P:nvUbdIzc     $A3D4:B9 93 A5  LDA $A593,Y @ $A594 = #$96
f7372   A:96 X:0F Y:01 S:BB P:NvUbdIzc     $A3D7:9D B0 06  STA $06B0,X @ $06BF = #$68
f7372   A:96 X:0F Y:01 S:BB P:NvUbdIzc     $A3DA:A9 00     LDA #$00
f7372   A:00 X:0F Y:01 S:BB P:nvUbdIZc     $A3DC:9D D0 06  STA $06D0,X @ $06DF = #$00
f7372   A:00 X:0F Y:01 S:BB P:nvUbdIZc     $A3DF:9D E0 06  STA $06E0,X @ $06EF = #$00
f7372   A:00 X:0F Y:01 S:BB P:nvUbdIZc     $A3E2:B9 95 A5  LDA $A595,Y @ $A596 = #$02
f7372   A:02 X:0F Y:01 S:BB P:nvUbdIzc     $A3E5:9D E0 07  STA $07E0,X @ $07EF = #$02
f7372   A:02 X:0F Y:01 S:BB P:nvUbdIzc     $A3E8:FE 00 07  INC $0700,X @ $070F = #$E1
f7372   A:02 X:0F Y:01 S:BB P:NvUbdIzc     $A3EB:60        RTS ------------------------------
Will further debug later.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I don't know if yours would be faster, but here's my latest WIP. Also here's my modified lua script:
Language: lua

-- HUD (all functions except stuff()) by Pasky13 -- rest made by mostly feos and MESHUGGAH local camx lastXpos = 0 function findbit(p) return 2 ^ (p - 1) end function hasbit(x, p) return x % (p + p) >= p end local function hex(val) val = string.format("%X",val) if string.len(val) == 1 then val = "0" .. val end return val end local function axis(x,y,color) gui.line(x,y-16,x,y+16,color) gui.line(x-16,y,x+16,y,color) end local function camera() camx = memory.readbyte(0xF2) + (memory.readbyte(0xF3) * 256) end local function player() local x = (memory.readbyte(0x720) + memory.readbyte(0x730) * 256) - camx local y = memory.readbyte(0x640) local offset = memory.readbytesigned(0x7D0) local action = memory.readbyte(0x620) if hasbit(action,findbit(3)) == true then axis(x,y,"#FF0000") else axis(x,y,"#FFB000") end end local function objects() for i = 1,15,1 do if memory.readbytesigned(0x700 + i) < 0 then local x = (memory.readbyte(0x720 + i) + memory.readbyte(0x730 + i) * 256) - camx local y = memory.readbyte(0x640 + i) local fill = "#FF0000FF" local outl = "#FF000030" local xrad = 0 local yrad = 0 local enemy = false local offset = 0 local etype = memory.readbytesigned(0x7D0 + i) if etype < 0 then if bit.band(etype,0x70) == 0 then fill = "#FFFF00FF" outl = "#FFFF0030" else enemy = true end offset = bit.band(etype,0x7F) if enemy == true then if memory.readbyte(0x620) == 3 then offset = offset + 7 end end xrad = rom.readbyte(0x1F4C8 + offset) yrad = rom.readbyte(0x1F4A8 + offset) if xrad < 0x50 then gui.box(x+xrad,y+yrad,x-xrad,y-yrad,outl,fill) end else offset = memory.readbyte(0x610 + i) xrad = rom.readbyte(0x18675 + offset) offset = bit.band(memory.readbyte(0x7D0+i),0x7F) yrad = rom.readbyte(0x1F4A8 + offset) if xrad < 0x50 then gui.box(x+xrad,y+yrad,x-xrad,y-yrad,outl,fill) end end --gui.text(x,y,"E" .. hex(i) .. "/" .. hex(offset) .. "/" .. hex(xrad) .. "/" .. hex(yrad)) end end end function Stuff() camera() player() objects() local Xpos = memory.readbyte(0x720) + memory.readbyte(0x730) * 0x100 local Xsub = memory.readbyte(0x670) local Ypos = memory.readbyte(0x640) local Ysub = memory.readbyte(0x660) local Yspd = memory.readbyte(0x7C0) + memory.readbyte(0x7B0) / 1000 local Xspd = Xpos + (Xsub / 1000) - lastXpos local bossHP = memory.readbyte(0xB1) local bossInv = memory.readbyte(0x6FF) local scrnX = memory.readbyte(0x650) gui.text(scrnX-10, Ypos+10, string.format("%.3f\n%.3f",Xspd,Yspd), "#ffff00ff") gui.text( 0, 8, string.format("X: %4d.%3d\nY: %4d.%3d",Xpos,Xsub,Ypos,Ysub)) gui.text(70, 8, string.format("Boss HP:%d\nBoss Inv:%d",bossHP,bossInv)) lastXpos = Xpos + Xsub / 1000 end emu.registerafter(Stuff)
I'm gonna look at boss RNG now. I know that "killing enemies differently" can change boss 1 and boss 3 behaviour. Boss 2 (didn't started to debug yet) depends on in-game timer. So if I remove a lag frame (by not holding that arrow before the lag frame) will be the same as entering the boss fight 1 frame later (literally, saves 1 frame).
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
Got to the first vine 1 frame faster here. In this and similar cases, test what exact pixel you need to be at in order to hit an enemy (vertically in this case), then try to position yourself so that you're as close to that pixel as possible at the frame before you would hit it.
I did that already (actually have 896.0 because I change subposition at wall). Currently I have to delay 5 frames at level 2 boss start to get the "fastest" hit for 1st time (so boss flies up a little bit and starts to move right and down). So I'm trying the other possible routes (level 1 - level 5 - level 2 for example). However sometimes this spawns extra lag frames.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
Yup, the value increases by 51 every frame which is the minimum y-speed when falling of a platform. For more details, read the subpixel paragraph in my Chip 'n' Dale submission. Replace 85 with 51 and 171 with 205. Thus, in this game, 205 is the best y-subpixel value to jump from if you're looking for the highest jump height.
Thank you AnS and Aglar for helping with figuring this out! And feos for telling me to write in to this thread. I wonder if it's possible to abuse this everchanging Y subposition other than highest jump / fastest fall down. Now that I write this sentence, maybe this is the reason your newer wip has scrooge humping the air after beating the 1st boss in Duck Tales?
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
Well just as Ans pointed out, one Y sub is for position (0x0660) and the other is for speed (0x07B0), which explains the misunderstanding. Think about that the position should be unsigned to make it easier to read.
A lua script that implements this idea:
local lastXpos = memory.readbyte(0x720) + memory.readbyte(0x730) * 0x100 + memory.readbyte(0x670)/400
local lastYpos = memory.readbyte(0x640) + memory.readbyte(0x660)/400

function Stuff()

	local Xpos = memory.readbyte(0x720) + memory.readbyte(0x730) * 0x100 + memory.readbyte(0x670)/400
	local Ypos = memory.readbyte(0x640) + memory.readbyte(0x660)/400
	local Yspdtemp = memory.readbyte(0x7C0) + memory.readbyte(0x7B0)/400
	
	local Xspd = Xpos - lastXpos
	local Yspd = Ypos - lastYpos
	local scrnX = memory.readbyte(0x650)

	gui.text(scrnX-10, Ypos+10, string.format("%.2f\n%.2f",Xspd,Yspd), "#ffff00ff")

	gui.text( 0, 8, string.format(
		"X: %.2f\nY: %.2f",Xpos,Ypos
	))
	gui.text(150,8, string.format("Y speed?: %.2f", Yspdtemp))

	lastXpos = Xpos
	lastYpos = Ypos
end

emu.registerafter(Stuff)
This way it shows Scrooge's Y position changes in every frame. And needless to say, depeding on when he jumps makes his jump peak vastly different. I'm not sure that this would be the solution. edit: however it seems to be right. using cheats, 07B0 does increases the Y speed and freezing a value to 0660 (Y sub) will make the same jump height. So the game really changes the Y subposition every frame? I don't understand the logic behind doing this.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
The reason why it desyncs is this: In your run at frame 7346 (the frame before you jump) your y-subpixel value is 108. If you do a jump at frame 7327 before this your y-subpixel value at frame 7346 will be 88. In your run this will result in a y peak position of 167.7 while the peak position in the other case naturally is 166.243, your position thus gets pushed to 167.51 while in the other it get pushed to 166.51 meaning that you'll reach position 180 (the one required for you to land) 1 frame earlier and thus it desyncs. Still can't see where those extra subpixels show up, other than if you simply look at this in a completely different way. I'm quite a lot more old-school than you for example :)
I can verify that jumping at different times (on the same position for the same length) can make a different maximum jumping height. Jumping height also changes depending on previous jumping. This is shown in my demonstration. Also note that the lua script doesn't shows the "correct" Y pos nor the Y sub position. This is because I can't calculate it. Since the only thing I found is the subroutine I added to the post, I can't really understand how would your description should match the debugged information even if I take away the Y sub 2 from the calculation (I mean that I'm not really sure about my theory either). edit: the memory values again: 0x07C0 - the vertical boost, jumping makes it 4...3..2... 0x07B0 - Y sub 1, changes only when you jump. Values like -120, 35, 84... 0x0660 - Y sub 2 at least what I think. Changes everytime during the in-game frames. -102, 68, -17... 0x0640 - Y position. 180, 175, 171... 0x07B0 and 0x660 starts the very same pattern similar but in different direction. 660 starts with 51, -103, 50 while 7B0 starts with -51, -102, 103.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Demonstration: http://tasvideos.org/userfiles/info/8276427459843689 Best way to test this is jumping multiple times on the same platform without touching the ceiling. Try to jump for 1 frame around boss 2 start (without changing the other inputs).
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
Aglar wrote:
I also started an improvement of this myself long ago, but put it aside and never got back into. Here it is, though I doubt it's better than yours. Feel free to finish the project.
That boss 1 ending (scrooge humping the air) is very nice, but I won't steal it.
Aglar wrote:
The constant y-subpixel change on ground is basically the same as in Chip 'n' Dale, with the difference of increasing 51 every frame instead of 85. I don't think there exist such things as a second set of subpixels though. as far as I recall the y-subpixels in air can only be changed by having different y-subpixels before jumping/falling.
It exists as the debugged information shows. You can easily verify this by doing 2 little jumps in a row. If you remove the 1st jump, the 2nd jump's vertical boost (and it's total height depending on the delay between the 2 jumps) will be changed. If Y sub 1 wouldn't change all the (in-game) time, every jump on the same platform would be equally high and would have the same boost. Currently I'm sticking to brute forcing all jump possibilities whenever I need to be higher or lower.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
I'm working on improving the previous submission by Aglar since I finished Duck Tales 2 with feos. I'm currently 15 frames ahead after leaving the icy stage at level 4 (I had to sacrifice 3 frame to manipulate away the hockey enemy). Now if this wouldn't be enough, the way the game calculates the Y sub position is ridiculous.
A:AB X:00 Y:00 S:BB P:nvUbdIZC     $E9ED:20 A1 F2  JSR $F2A1
A:AB X:00 Y:00 S:B9 P:nvUbdIZC       $F2A1:BD 60 06  LDA $0660,X @ $0660 = #$15 -- load y sub 1
A:15 X:00 Y:00 S:B9 P:nvUbdIzC       $F2A4:38        SEC                        -- set carry flag
A:15 X:00 Y:00 S:B9 P:nvUbdIzC       $F2A5:FD B0 07  SBC $07B0,X @ $07B0 = #$55 -- Y sub 1 - Y sub 2 - ~C
A:C0 X:00 Y:00 S:B9 P:NvUbdIzc       $F2A8:9D 60 06  STA $0660,X @ $0660 = #$15 -- store y sub 1
A:C0 X:00 Y:00 S:B9 P:NvUbdIzc       $F2AB:BD 40 06  LDA $0640,X @ $0640 = #$AB -- load Y pos
A:AB X:00 Y:00 S:B9 P:NvUbdIzc       $F2AE:FD C0 07  SBC $07C0,X @ $07C0 = #$04 -- vertical boost - Y sub 2 -~C
A:A6 X:00 Y:00 S:B9 P:NvUbdIzC       $F2B1:9D 40 06  STA $0640,X @ $0640 = #$AB -- store y pos
A:A6 X:00 Y:00 S:B9 P:NvUbdIzC       $F2B4:60        RTS (from $F2A1) -----------------
Y sub 1 changes on every in-game frame even when you are on ground. Y sub 2 changes only when you are jumping/falling. Needless to say, it's possible to abuse higher jumps and lower jumps. However I have no idea how to calculate it since the jump length depends on time of jumping, length of jumping and previous jumps. And here is a lua script.
-- HUD (all functions except stuff()) by Pasky13
-- rest made by mostly feos and MESHUGGAH

local camx

lastXpos = 0
lastYpos = 0

function findbit(p) 
	return 2 ^ (p - 1)
end

function hasbit(x, p) 
	return x % (p + p) >= p 
end

local function hex(val)
	val = string.format("%X",val)
	if string.len(val) == 1 then
		val = "0" .. val
	end
	return val
end

local function axis(x,y,color)
	gui.line(x,y-16,x,y+16,color)
	gui.line(x-16,y,x+16,y,color)
end

local function camera()
	camx = memory.readbyte(0xF2) + (memory.readbyte(0xF3) * 256)
end

local function player()
	local x = (memory.readbyte(0x720) + memory.readbyte(0x730) * 256) - camx
	local y = memory.readbyte(0x640)
	local offset = memory.readbytesigned(0x7D0)
	local action = memory.readbyte(0x620)
	if hasbit(action,findbit(3)) == true then
		axis(x,y,"#FF0000")
	else
		axis(x,y,"#FFB000")
	end
	
end

local function objects()
	for i = 1,15,1 do
		if memory.readbytesigned(0x700 + i) < 0 then
		
			local x = (memory.readbyte(0x720 + i) + memory.readbyte(0x730 + i) * 256) - camx
			local y = memory.readbyte(0x640 + i)
			local fill  = "#FF0000FF"
			local outl = "#FF000030"
			local xrad = 0
			local yrad = 0
			local enemy = false
			local offset = 0
			
			local etype = memory.readbytesigned(0x7D0 + i)
			if etype < 0 then
				if bit.band(etype,0x70)  == 0 then
					fill = "#FFFF00FF"
					outl = "#FFFF0030"
				else
					enemy = true
				end
				
				offset = bit.band(etype,0x7F)
				if enemy == true then
					if memory.readbyte(0x620) == 3 then
						offset = offset + 7
					end	
				end
				
				xrad = rom.readbyte(0x1F4C8 + offset)
				yrad = rom.readbyte(0x1F4A8 + offset)
				if xrad < 0x50 then
					gui.box(x+xrad,y+yrad,x-xrad,y-yrad,outl,fill)
				end
			else
				offset = memory.readbyte(0x610 + i)
				xrad = rom.readbyte(0x18675 + offset)
				offset = bit.band(memory.readbyte(0x7D0+i),0x7F)
				yrad = rom.readbyte(0x1F4A8 + offset)
				if xrad < 0x50 then
					gui.box(x+xrad,y+yrad,x-xrad,y-yrad,outl,fill)
				end
			end
			--gui.text(x,y,"E" .. hex(i) .. "/" .. hex(offset) .. "/" .. hex(xrad) .. "/" .. hex(yrad))
		end
		
	end
end



function Stuff()
	camera()
	player()
	objects()

	local Xpos = memory.readbyte(0x720) + memory.readbyte(0x730) * 0x100 + memory.readbyte(0x670)/400
	local Ypos = memory.readbyte(0x640) + memory.readbyte(0x7B0)/400
	local YposSub = memory.readbyte(0x660)/400
        camx = memory.readbyte(0xF2) + memory.readbyte(0xF3) * 0x100
	local Ycam = memory.readbyte(0xF1)
	local timer = memory.readbyte(0x92)
	local timer2 = memory.readbyte(0x95)
	local RNG = memory.readbyte(0x90)
	local bossHP = memory.readbyte(0xB1)
	local bossInv = memory.readbyte(0x6FF)

	local Xspd = Xpos - lastXpos
	local Yspd = Ypos - lastYpos

	gui.text(75, 8, string.format("Tmr: %3d:%3d\nRNG: later, ok?\nHP: %d\nInv: %d",timer,timer2,bossHP,bossInv))

	for i = 0, 16 do
		id		= memory.readbyte(0x620+i)
		xSub	= memory.readbyte(0x670+i)
		scrnX	= memory.readbyte(0x650+i)
		x		= memory.readbyte(0x720+i) + memory.readbyte(0x730+i)*256 - camx
		ySub	= memory.readbyte(0x7B0+i) -- or 660
		y		= memory.readbyte(0x640+i)
		state	= memory.readbyte(0x710+i)
		
		if x<0>242 then x=242 end
		 if id>0 and i>0 then
			gui.text(x-6, y-2, string.format("%X",id), "#ffffffa0")
		 end
		if i == 0 then gui.text(scrnX-10, Ypos+10, string.format("%.2f\n%.2f",Xspd,Yspd), "#ffff00ff") end
	end	
	gui.text( 0, 8, string.format(
		"X: %.2f\nY: %.2f",Xpos,Ypos
	))
	gui.text(150,8, string.format("Ysub: %.2f", YposSub))

	-- if memory.readbyte(0x80) == 2 then gui.box(1,1,256,256,"#FFFF00FF") end


	lastXpos = Xpos
	lastYpos = Ypos
end

emu.registerafter(Stuff)
edit: lua script modified
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
ColdStardust:Judging by his words, that stranger is either outskilled by a TAS or just simply bad at video games. The chat log is full of his contradictions. Okay, maybe he had a very bad day or just really ignorant. I recommend you to don't try to impress those who simply don't want to know something particular. He answered to TASing with "cheating". This is like telling about death metal music to JB fans. Next time you should explain what is the goal of TASing (the result of the movie will resemble God playing that game inhumanly fast/impossible), how are you doing it (frame by frame to make sure you test everything that could potentially shorten the gameplay), what are you doing (planning routes, comparing them, making researches to know rules that invisible to human eyes), why are you doing (entertaining? WR? etc).
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
MESHUGGAH
Other
Banned User, Skilled player (1896)
Joined: 11/14/2009
Posts: 1350
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
You are ridiculously awesome Masterjun! Good job as always! This game was the first one where I disassembled my controller to check the L+R glitch with red coins. Now I need to get my SNES back and try this too. I've played the game long time ago, but isn't there other places where Mousers also spawned and won't touch the floor once despawned? IIRC end of world 6 contains too, but it would be much more longer (collecting the red coins and that level's length). edit: next time I should read the posts (Post #351729) Easy yes vote.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...