Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2832
Location: US
Oh, nice thanks for making that video! The run continues to get shorter bit by bit I saved another 100 frames. I also found a glitch that saves some lag, whereby you pick up a treasure one frame before getting hit by an enemy (in this case an arrow.) With enough actions on screen the damage animation of the hearts doesn't occur, its helpful only once but stops a lot of lag. EDIT: I finished the key map above. If there is another warp similar to 'C' then it is the fourth bit in 064A. I also found a new 'hidden key' (XX, the 3rd bit of 0642) but as yet I don't know what it does. It is located in the same room as 'F' near the bottom of the chains. Actually, it is activated when you kill the red enemy near where the 'F' path opens up. Although I can't yet determine why this one enemy triggers this bit or what effect it has.
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11475
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Alyosha wrote:
Actually, it is activated when you kill the red enemy near where the 'F' path opens up. Although I can't yet determine why this one enemy triggers this bit or what effect it has.
You would need to find an exclusive room where that particular bit is read.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2832
Location: US
Alright new WIP, got down to 4:57. http://tasvideos.org/userfiles/info/19629482226888684 NOTE: I tried using the [!] ROM but when I did it loaded boomerang kid instead of Robin hood, so... I think I will just stick with my current [!p] ROM for now. I looked at the secrets again, and they are mapped also to 0661 and 0662, there doesn't seem to be room for another secret since 0662 starts at 'I'. I also looked at the new enemy killing secret but it doesn't seem to impact anything higher in memory, which from what I can tell means it only effects the current room, even though I don't know exactly how.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2832
Location: US
As I search for a more interesting project, I decided I'd look at Boomerang kid. I looked back at RChokler's WIP and re-synced it. It turns out there are 2 faster stage choices (so far.) I also did some other minor optimizations. So far I am a few seconds ahead. Well, after the menu anyway, somehow he was able to start game input about 100 frames earlier then me, which I'm guessing is emulator or ROM differences. This is on FCEUX 2.2.2 and the !p ROM. http://tasvideos.org/userfiles/info/19826986828362588 Also I noticed this from the submission of Robin Hood:
Dwedit wrote:
According to Bootgod's NesCartDB, the ROM with the CRC32 of B89888C9 is the correct dump, and it doesn't work correctly in FCEUX. The alternate dump rearranges the banks to work around emulation errors. FCEUX seems to be emulating mapper 232 just plain wrong. Writing 10 to 9000 should select outer bank 02, but it selects outer bank 01 instead. edit: checked the code, it intentionally has a hack to work around bad dumps, that should be taken out.
But I'm not really sure what the implications are. Quattro Adventure seems to be a rather rare case.
Post subject: Quattro Adventure: Super Robin Hood
Vhyrro
He/Him
Joined: 12/6/2020
Posts: 8
Location: Poland
EDIT: DID not notice that there already was a thread for this game! Well, here we are. I'll start off with the strategies that are already known:
    * The strategies described here and here * It is possible to perform a hyperjump on the top of a ladder (discovered by Samsara, big shoutout) * Subpixel positions greatly affect jumps and collisions * The game's official source code can be found here
Things that need work:
    * Subpixel positions and how they affect jumps * A reliable way to calculate how much velocity and what subpixel position is needed in order to perform a clip as seen in the beginning of this run * A way to clip through two rows of blocks at once (if someone finds a way to do this I will die of happiness) * Maybe a way to clip through a wall that is on Robin's right-hand side? * More weird angles that Robin can jump at and break the game entirely
Excited to see what we find next!
We break those records baby :)
Post subject: Video games huh
Really_Tall
She/Her
Editor, Player (185)
Joined: 9/29/2014
Posts: 122
Location: Scotland
Vhyrro cut this game down to 2:06 yesterday: https://www.youtube.com/watch?v=8-IfdpT-Fu0 Then today, I figured out you can hyperjump instantly from a ladder with some precise inputs, instead of having to wait through the crouching animation. This cut probably another 20 seconds from the TAS, because you can use the trick in the room at 1:15 in Vhyrro's video to skip the moving platform and the whole detour to actually get onto it. I also found that you can chain hyperjumps: the way they work is pretty great. In Super Robin Hood, for each frame you run, the value for a jump increases by 1 to a max of 47. Letting go of left/right will halve it for each frame you do so, and crouching will decrease it by 1 each frame. However, when you set up a hyperjump and the value goes to 255 these properties still apply. I didn't check the source code, but I'm guessing the game checks for a value of exactly 47: as long as we stay above that value we can keep abnormal speed values for as long as we want! You have to keep running left, avoid hitting any walls while grounded, and make sure to not let your speed wrap around from 255 to 0, but these requirements aren't too bad, and we can do several hyperjumps in the same room when going from right to left. Vhyrro then found a great spot for a ceiling clip in the very first room that opened up a completely different route that he and I devised together. I made a quick test TAS and it came out to 1:24, more than halving the submission from only three days ago! Here it is: Link to video Since then Samsara added in a reset at the start and some small optimisations which took it to 1:18. Vhyrro is working on optimising it properly now, and if you want to get in on the fun, all the Super Robin Hood action is in the TASVideos Discord server!
Really_Tall
She/Her
Editor, Player (185)
Joined: 9/29/2014
Posts: 122
Location: Scotland
How speed works Firstly, here's a load of useful RAM addresses. There are bunch Vhyrro gave me, and then I tested while referencing the "VARS.PDS" file in the source code to find everything useful. User movie #68108177071818206 Robin's X speed (0x311) increases by 1 each frame you're running, to a max of 47. If you crouch it instead decreases by 1 each frame, for the crouch duration of 21 frames. Stopping will set it to 0, and turning will set it 0 turning left, or 2 turning right. The subpixel value (0x307) starts at 0, and each frame it either decreases (while moving left) or increases (while moving right) by the value of your X speed on the next frame multiplied by 5. So if you run left from the start, it will go 0, 251 (-5), 241 (-10), 226 (-15), 206 (-20), etc, changing by 5 more each time. This is up to a max change of 230 on the frame you reach 46 speed, and then the subpixel value stays constant once you have 47 speed (the max). But how are these values used? Well: - to begin, you move one pixel each frame - if the subpixel value wraps around, you move an extra pixel - jumping always moves you an extra pixel on the exact frame you jump, and doubles the amount the subpixel value changes for one frame only. This means it can wrap around twice on one frame, for a total of four pixels that frame - for the rest of the jump, the amount the subpixel value changes by is constant, since your X speed is constant (unless you hit a wall) So after you run for 46 frames, you'll run at a constant 2 pixels a frame. If you jump while at max speed then you'll always move two pixels each frame in the air. On the frame you jump, you'll move at least two pixels, up to a max of four. Note that there is one frame that you don't move when landing from a jump, so four pixels at the start and zero at the end cancel out: it isn't faster to do extra jumps along the ground for no reason. There's also a small discrepancy between running left and running right: when you run right the X speed of 1 is skipped, and it goes from 0 to 2. This means your X subpixel will start by going from 0 to 10. Here's an example: starting with a subpixel of 0, you run right for 12 frames and then jump on the 13th frame. The values while running are: 0, 10 (+10), 25 (+15), 45 (+20), 70 (+25), 100 (+30), 135 (+35), 175 (+40), 220 (+45), 14 (+50), 69 (+65), 129 (+70), 194 (+75). On the 10th frame (in bold) the speed wraps around, so Robin moves two pixels instead of one. Then the jump. The next increase is 70, which gets doubled to 140, and 194 + 140 = 334 which comes out to 78 with a wrap around. This means he moves two extra pixels this frame: one that always comes on the first jump frame, and one from the wrap around. So the total pixels moved comes out to: 1 for each of the 13 frames +1 for the one frame the subpixel value wrapped around while running +2 for the jump, from the constant and then the wrap around Totalling 16 pixels! And if you check in game, you'll see that's what happens. The X speed address also happens to be the address set to 255 for hyperjumps. Having a value above 47 messes with the calculation in ways I don't understand, and it means you no longer have that two pixel per frame guarantee from reaching max speed. There is an upside, however: some speed values will give you really nice jumps that are *almost* constantly two pixels per frame. One such value is 146, which (while moving left, since hyperjumps only work going left) decreases the subpixel value by 249 each frame, larger than normally possible. So you only lose a pixel roughly every 37 frames compared to a regular full speed jump! Instead of figuring out the formula, I just looked at each value to get a list of the best, with the most important in bold:
    X Speed: Subpixel Increase 047: +00 (no glitch) 052: +23 059: +23 068: +23 079: +07 082: +16 095: +23 102: +07 139: +23 146: +07 165: +24 168: +07 201: +05 205: +16 228: +07 244: +24 247: +07 255: +04
I figured representing it as an increase was clearer here: +4 means -252 and the value wrapped around. So jumping with a speed of 255 only loses a pixel every 256 / 4 = 64 frames! These values are the most important ones because the initial speed you have from the hyperjump is either 235 or 255 depending on if you get the crouch animation or not. From 235, 244 is the first good value, and then 247 and 255 are very close. In situations where you need to chain hyperjumps you can't reuse the same value constantly (it always increases by at least 1), making this combination a great choice. From 255, it takes one frame to halve your speed to 128, or two frames to get it to 64. That means it takes 19 frames to reach 146 speed, but only 17 frames to reach 79. If you don't need much more than regular height then that makes 79 the best value! But if you need considerable height then 146 will get you up anywhere. I hope this explanation was vaguely comprehensible. The subpixel value is never, ever cleared, even on death, which makes optimising and syncing pretty tricky, given how it works. One final neat thing is you can actually manipulate your subpixel while clipping through a ceiling, without losing frames. I managed to get it to 64 different values going from the first to the second room, 1/4 of the total, which should be a lot to work with! I'm not sure what value will be best. It might simply be the highest, 253, to start gaining pixels as soon as possible when moving right in the second room? It will certainly all need tested carefully.
Post subject: speed display Lua script
Editor, Reviewer, Skilled player (1358)
Joined: 9/12/2016
Posts: 1646
Location: Italy
I'm not following your explanations about how speed works, so I've just written a Lua script that calculates the speed by performing a simple difference between the current and the previous' frame X position. Have it there by clicking on the download button on the right: Download robin.lua
Language: lua

--NES Super Robin Hood position and speed v1.0 by ThunderAxe31 local x_sub_addr = 0x0307 local x_addr = 0x0308 local x_old = 0 local x_spe = 0 local framecount = -1 local u8 = memory.read_u8 or memory.readbyte local u16 = memory.read_u16_le or memory.readword local text = gui.pixelText or gui.text local text_y_offset = 0 if u8 == memory.read_u8 then --check if using BizHawk text_y_offset = 200 end while true do local x_new = u16(x_addr) local x_sub_new = u8(x_sub_addr) local x_spe = x_new*256 +x_sub_new -x_old x_old = x_new*256 +x_sub_new local output = string.format("X:%4i %3i", x_new, x_sub_new) if framecount == emu.framecount()-1 then output = output .. string.format(" %+4i", x_spe) end text(1, 9 +text_y_offset, output) -- tells the position framecount = emu.framecount() emu.frameadvance() end
my personal page - my YouTube channel - my GitHub - my Discord: thunderaxe31 <Masterjun> if you look at the "NES" in a weird angle, it actually clearly says "GBA"
Post subject: Bruteforcing script
Vhyrro
He/Him
Joined: 12/6/2020
Posts: 8
Location: Poland
All right, I've gone ahead and made a script to bruteforce all possible ways to jump at a block, and from my testing, it works as expected - it can be found here! I'm in the process of bruteforcing the first block above robin hood when he spawns in order to gather all the x, subpixel positions and velocities required to clip into the block. Afterwards, I hope to maybe find a way to clip into right-hand side blocks!
We break those records baby :)
Really_Tall
She/Her
Editor, Player (185)
Joined: 9/29/2014
Posts: 122
Location: Scotland
Optimised but outdated TAS: User movie #68217386723731530 Link to video Since that TAS, I figured out the "warp glitch" used at the start of the previous route (https://www.youtube.com/watch?v=X8BvFsagciQ). It's an underflow of the lower byte of Robin's X position, so it only works at X positions that are a multiple of 256. With a correctly aligned tile, the clip into it takes the lower X position byte from 249 to 255. Landing moves you forward a pixel which makes it 0, and then jumping inside a tile moves you back a pixel, causing the underflow. You need to have enough velocity to rise through the bottom half of the tile, as otherwise you'll fall back through without landing. That requirement means the minimum velocity for areas with three tiles between the ground and the ledge is 40, though you might be able to do the clip in areas with only a two tile gap as well, by jumping out of a crouch. The ledge must also be only one tile high vertically because otherwise the tile above will block you instead. So the warp glitch requirements are to: - use a tile aligned with a multiple of 256 (16x16 tiles, so 1/16 work) - use a tile with no tile above it - jump and clip into it from the left side - have the velocity to rise halfway through it (will usually be 40 when jumping) Note that the clip works going either left or right, but the "warp" will of course only work when you clip going right. The clip itself does not have many requirements. It'll be useless if there's a tile above the tile used, though, so that one is still effectively in place. The main thing to bear in mind for the clip is it will not work at a full speed of 47. This is because an essential part of the setup is travelling just 1 pixel on a specific frame, and at max speed you have a constant 2px/f. For this description of the setup, the X pos you get from jumping and hitting the wall will be X, and the Y pos you get jumping and hitting the ceiling will be Y (247 and 189 for the clip in the first room). Your position needs to go through these values: (X-2, Y), (X, Y-4), (X+2, Y-8), (X+3, Y-11) (but the final position becomes (X+8, Y-11) with the clip). So this is (245, 189), (247, 185), (249, 181), (255, 178) in the first room. This is why subpixels matter: you have to travel 2px/f on the first two frames, then only 1px on the third frame. If you don't then your X position simply increases by 2 again (up to 251 in the first room) and there isn't a clip. Also note that a lower Y speed/position can still give you the clip, but you won't avoid the ceiling. While I didn't find another place to use the warp in either of the current routes, I did find a place for the clip itself. It can be used to skip the final moving platform in the run, which means we don't need the high key in the trip to the left, only the key on the table which opens the gate to the final room. This discovery should take my TAS down by about 5 seconds! The coordinates for this clip (X=711, Y=109) are (709, 109), (711, 105), (713, 101), (719, 98), and they match the formula perfectly: that's how I got it to work here, after all. Link to video
Player (206)
Joined: 5/29/2004
Posts: 5712
Congratulations on your discoveries and runs made so far! That's some thorough research and big time saves! I guess the source code helps. It was interesting to learn some things like how any key that does anything other than lift a door or start a moving platform actually has a secret on top of it to make the other effect happen. I wish I had more to contribute; I was reminded of Codemasters' NES games last year, so I started documenting version differences and other unused stuff for The Cutting Room Floor, but for Super Robin Hood all I found was that Super Adventure Quests makes the usual changes of erasing the Camerica logo and replacing color 0D with 0E. This message has got me intrigued with some research I was doing, though:
Alyosha wrote:
Also I noticed this from the submission of Robin Hood:
Dwedit wrote:
According to Bootgod's NesCartDB, the ROM with the CRC32 of B89888C9 is the correct dump, and it doesn't work correctly in FCEUX. The alternate dump rearranges the banks to work around emulation errors. FCEUX seems to be emulating mapper 232 just plain wrong. Writing 10 to 9000 should select outer bank 02, but it selects outer bank 01 instead. edit: checked the code, it intentionally has a hack to work around bad dumps, that should be taken out.
But I'm not really sure what the implications are. Quattro Adventure seems to be a rather rare case.
I had just read that the 1993 releases of Codemasters' 4-in-1s in Europe or on Aladdin Deck Enhancer had their main bank-switching bits swapped compared to the original golden cartridges. This all adds up if that's how the games are indexed: 00 and 11 would remain the same, but 01 and 10 would be swapped, so that's how you'd get the second and third options loading each others' games. (Does this mean that the game ROMs were slightly modified for Aladdin and the American versions of Quattro Adventure and Quattro Sports each have two valid dumps? But as Dwedit said, Bootgod gave them the same CRC32s...) Something I noticed by stepping through with a debugger is that Boomerang Kid is the only game whose bank switch happens at the end of the Codemasters bootup logo instead of the beginning. (Apparently the menu uses the same bank as Treasure Island Dizzy, so Boomerang Kid seems to be borrowing Treasure Island Dizzy's startup logo to save space or something.) This might be why bad emulation has selecting 2-Super Robin Hood give you Boomerang Kid with no bootup logo while selecting 3-Boomerang Kid gives you Super Robin Hood with two bootup logos. So, while the original Quattro series works right on emulators with higher compatibility like Nestopia and Mesen, they still have the swapped 2nd and 3rd games problem on the European ROMs of Super Adventure Quests, the Plug-Thru version of Super Sports Challenge (both versions of which call themselves "Quattro Sports" in-game, only with a different background color and version number on the menu--and V3 works right now?), and the Pegasus 4-in-1. Actually, the Pegasus 4-in-1 totally freezes/crashes from bad opcodes if I select the 2nd or 3rd game in Mesen. FCEUX 2.2.2 mishandles it differently: It boots directly into Go Dizzy Go after only flashing the menu for an instant, but if I do a soft reset, it loads the game menu and lets me enter all four games correctly. (This might be why I've seen the same ROM image mislabeled as a standalone version of Go Dizzy Go.) But then that same version of FCEUX also swaps games 2 and 3 in Quattro Adventure, Quattro Sports, and Quattro Arcade, which I don't recall it doing on the American versions before... but maybe I had the hacked ROMs that Dwedit called out back then. So after reading up on NES 2.0 mappers, I realized that the submapper for Aladdin/European 4-in-1s might be what was needed to fix that whole problem in the ROM header, since I had also learned of a fix to the third version of Micro Machines where its header had been given the wrong mirroring mode. But when I edited that submapper into each ROM with everything left as normal and loaded it up, instead of a menu, I got some garbage lines in a completely different palette, apparently unplayable. So either that's not the fix, or I'm doing something wrong in editing the headers. Maybe there's an NES development forum you can point me to where this stuff has already been discussed. Editing to add: Yup, I tried setting a breakpoint on writes to 8000-BFFF, only this time I took the opportunity to change the Accumulator from hex 10 to 8 or vice versa, and that made all those multicarts load the correct games in Mesen, including the Pegasus one. Now I wonder if any emulators contained swap hacks activated by the more recognized of these ROMs... Final edit?!: I figured it out. It's not enough to choose submapper 1; all UNROM-style boards like Codemasters' require 8 KB of CHR-RAM to function, which the NES 2.0 header format is required to specify, so just remember to set CHR RAM to 8 KB and then you should be good to go.
put yourself in my rocketpack if that poochie is one outrageous dude
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2832
Location: US
I have console verified the most recent Super Robin Hood WIP (as well as the other existing Quattro Adevnture TASes.) not sure what's left to do for a new TAS, but it should be verifiable whenever it gets done. Link to video Note that Quattro runs use a reset in order to skip the opening code masters screen. In the verifications this is done manually, as it is not too timing sensitive, but it does require an extra poll added to the input file as the bot detects it as a poll.