Posts for Lord_Tom

1 2 3 4 5
15 16
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Zowayix wrote:
So is this something similar to the SMW arbitrary code glitch? A non-existent sprite/tile is interacted with, and when the game tries to jump to the (non-existent) subroutine for that sprite/tile, it jumps elsewhere? In that case, is the tile in question here not actually a real note block, but a glitch tile that looks like one?
It is similar to SMW, but not quite the same. In this case, the game is trying to change one valid tile type (0x03, hidden note block) to another valid tile type (0x80, black space) in response to Mario touching the tile. But Mario is out of bounds, so the game didn't read the tiles onscreen from the normal RAM area defining the tiles for the active level, $6000-$794F. That's why the screen layout is bizarre. Similarly, when the game tries to update this tile, the update is written to an invalid location: $9c70. This is what causes the crash, and you can see from the trace log that the next instruction executed after this update is from a totally different area of the ROM. I don't know why writing to $9c70 changes how the game maps addresses (it isn't defined as anything special in the disassembly I have), but you can write to that address manually using the emulator hex editor and it causes a similar crash.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
From what I understand, anyone more knowledgeable please correct: 1. Tile is encountered outside of valid area, CPU attempts to handle 2. Based on incorrect tile data, MMC3 register is configured incorrectly. This register's function is to map 16-bit addresses to locations in ROM. So if the register value is X, the instruction JSR $ABCD jumps to one subroutine in ROM. But if the register value is incorrect JSR $ABCD jumps to some unintended location, which could be anywhere. In the forum, this is what HHS means when he says the PRG layout gets changed. 3. The incorrect mapping, causes execution in an incorrect area of ROM -- essentially, arbitrary code execution, but in a bad way! Ultimately, the code executed executes RTS (return) when it is already at the base of the stack (S=FF). This overflows the stack to S=01, and the next jump location is read from memory location $0100. 4. $0100 is technically reserved for the stack (which fills from $01FF downward) but the game designers didn't ever anticipate its being used -- so they used $0100 and $0101 to store some configuration variables. At the time the glitch occurs, their values are 80 00. So I think what happens is the return location is read from this area of the stack, read least-significant byte first for $0080, a RAM location. 5. Though execution starts at $0081, so not sure if the stack stores address-1 or if I'm wrong somewhere...:/
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Ilari wrote:
OmegaWatcher wrote:
So, I should expect someone programming something in SMB3 to next April Fools, AGDQ marathon or pi day?
Using this bug for ACE is prbably quite hard if possible at all. This run needed to program only 3 bytes (a single jump instruction). The ACE input routines are far larger than that. I expect that very few games that aren't: - SNES games (because of controller autopoll registers). - Have serious inventory (one could write code to inventory) have ACE bugs. Credits glitches (like this one) are much less demanding (but still can require nontrivial amounts of code). E.g. PSX Castlevania: Symphony of the Night run had to use inventory as code.
Actually, I do have a prototype routine (see the SMB3 forum topic) that could be used for total control - though due to the limitations imposed by the NES and SMB3 a fairly elaborate setup is required. Basically, the 7-1 glitch can be used to implement a 9-byte setup loop (P1) that uses controller input to write a larger, but still small, program on the zero page (P2). P2 is able to use both controllers to write larger routines (P3) anywhere in memory to implement total control. I'm planning to do a run based on it, but will take my time to try to show off the maximum effects possible.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Thanks for those suggestions! I couldn't get your first example working as is, not sure why. You're right that the NMI reads the joypads. I found the NMI also updates the $15 counter, saving the need to waste byte(s) incrementing. This version works and is 12 bytes long, though one byte is a 00 so only 11 glitch activations would be needed. Appropriate placement of the final program bytes requires the correct starting value of $15.
Loop:
JSR $96E5 -- NMI
LDX $15 -- load counter into X
LDA $F7 -- controller one into accumulator
STA,X $0100 -- store byte at next location
BNE Loop -- loop if controller used
Program:
Your second suggestion is intriguing for implementing the staging program:
LDA $15
STA $01xx
JSR $897b
That's only 8 bytes so would be doable using a combination of the x and y sprite locations. It may end up preferable to use the $15 counter to define each byte here since not all values 0-255 are actually available via the controller (up + down and left + right are not recognized, independent of emulator settings). I don't think that limitation would be a show-stopper for writing the final program since there's a lot more flexibility with length there. Edit: Got a 9-byte version working, short enough that it should be possible to implement with a single invocation of the 7-1 glitch!
JSR $96e5   -- NMI
LDA $F7      -- load controller 1
STA ($15,y) -- store to zero-page, using $15 counter to advance to next byte
                  -- y never changes 
BNE loop:    -- loop while controller1 input non-zero
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
I've been brainstorming ways one might use the 7-1 glitch to obtain robust control of the game, similar to the SMW Pong example. I looked for a case where I could over-write a function pointer as was done in the recent Super Metroid, but it doesn't seem possible -- jumps are always defined in ROM (unmodifiable) or in the few indirect cases that jump based on RAM the target address is set immediately prior to the jump (no chance to modify). Another technique which seems promising is writing a false location directly at the base of the stack ($01FE). The false location would point to a small program in memory which would perform some logic then JMP back to the originally intended location. This works to misdirect execution once, but the stack data gets overwritten after the JMP back to the main game loop. What I'm working on now will probably work but be very tedious to implement: repeatedly invoking the glitch in 7-1 and manipulating the sprites such that each time, another byte is added to a "staging program" in some unused spot of RAM, and a JSR command is executed that pops Mario back to 7-1 (e.g. JSR $9100 aka 20 00 91). On the final iteration, execution would be jumped to the staging program, whose function is to loop each frame and write a "total control" program, one byte per frame, using controller input. This "total control" program would simulate the logic of the main game loop, but with logic (triggered by controller-2 input) to rewrite a "custom" section whenever desired. I've written a working prototype of a "staging" program. Since each byte in this program requires invoking the 7-1 glitch, this needs to be very short:
Start:
STY $20   -- save y register
JSR GraphicsBuf_Prep_And_WaitVSync  -- timing 1 iteration/frame
JSR Read_Joypads -- read the controllers
LDY $20 -- restore y register value
INY -- advance to next byte location
LDA $f7 -- load controller-1 input
STA,y $1111 -- store this byte (location arbitrary; maybe bonus-game ram would be good) 
BEQ 03 -- stop looping if controller input=0
JMP Start -- loop
JSR $1111 -- jump to "total control" program
I've acquired a basic working knowledge of 6502 assembly looking at Metroid and SMB3 code the past couple years, but if anyone has ideas/advice on a better way to do this I'd be very grateful. I've got a lot of ideas for what to do with this sort of "invokable rewrite" capability in a playaround TAS. EDIT: BTW, Tompa & I are almost done with that any % TAS using the glitch, there's one minor technical hurdle holding us back a bit.
Post subject: Re: Good Atari 2600 graphics!
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
dwangoAC wrote:
I watched before reading any submission notes. I found this to be interesting because I didn't realize Atari 2600 graphics could be this good. The fly-in at the beginning looked genuinely 3D. It's over quick, sure, but I was entertained. Yes vote. A.C. ******
Seconded, that and the starfield animation were surpisingly immersive given the console.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Having it jump to the credits *IS* arbitrary code execution. But if you mean can this be used to introduce significant new programming as was done with SMW playing Pong, I don't know for sure but I imagine it's possible. I don't know if this is how it was done with SMW, but if you were able to set up a loop that repeatedly executes the bytes corresponding to the controller states, you could presumably use controller inputs to write whatever program you want, byte by byte, somewhere in memory and then jump to it.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
HHS understands the details best, I think, but I'll try. Basically it's similar to in SMW -- the game ends up trying to read game data (enemy & Mario locations, etc) as programming instructions. Normally, this would induce random/useless behavior -- like if you tried to figure out how to fix your car by reading a phone book. But by manipulating pieces of the data you know the game is going to try to translate into instructions, you can essentially write your own little program that tells it to skip to the ending. In this case, we're really just trying to get it run 1 command: JSR $e38f (Jump to a subroutine at address $e38f, corresponding to the ending credits) So the challenge is how to manipulate things you can affect by playing the game (enemies, Mario) to generate that command and have the game run it. Well, the command above in digital form consists of 3 bytes; in hex: 0x20, 0xe3, 0x8f. In decimal the three values are 32, 227 and 143. So amidst whatever happens when the game goes haywire, if it ends up trying to read an instruction out of those 3 bytes (in order), it'll jump to the ending credits.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Agreed, there are much faster strats available if you're willing to tolerate lower completion %. The upper room strat focused on just proving the glitch could be done on console by a human.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
For the upper-room strat, there's about a 4-frame window to kill the flying koopa. For the other koopa killed in that top room there's only a 2-frame window (shell needs to stop on the right single pixel, but turtles only walk every other frame). For the other realtime strat that doesn't use the upper room there are 2, 2-frame windows to hit, so about twice as hard.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
That's awesome. I updated the subtitles on the demo run to note that you need to kill the flying koopa in the top room while it's going upward, not downward. Thanks to Jokaah for helping figure that out.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
True wrote:
Console verifying shortly. Been sick as fuck and everything here is a mess. Edit: here is the result
That is amazing to see. Thank you!
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Jokaah wrote:
I tried everything in real time and got the following: http://imgur.com/lVtFnIR.jpg but it didn't work :( Do I need to get into the pipe first attempt or something?
Those memory addresses are correct, but there are others upstream that can also mess things up (though the strat was designed to minimize that). Unfortunately, I can't help just based on that screenshot, but if you pass along a movie file (.fm2 or bizhawk) I could take a look. Edit: Best of all would be to run the Lua script I posted just before you jump in the glitch area. If it says "Fail" something clearly identifiable is wrong.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
HHS wrote:
The forum broke the code. Try again with "Disable HTML in this post" checked. Edit: Lol. Guess where I am.
You try to get it to take u to W1? True: thanks a lot, rest up no rush
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Thanks, fixed it above. Also, was able to get a successful demo of the hopefully easier upper room realtime strat. Optimization continues on the TAS, we're definitely under 3:00 though. Edit: Updated link with from-power-on version.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
I figured out why all the #'s periodically go dark in HHS' script - as written, the first row of values (0x81-0x8D) is cut off the top of the screen. That explains a lot! I reformatted and commented his script in an attempt to understand it better, with some minor modifications that are in progress.
Language: lua

-- address we're targeting target = 0xae -- table of the lengths of the various instructions lengths={ 2,2,2,2, -- 0x(0,2,4,6,8,A,C,E)0-3 2,2,2,2, -- 0x(0,2,4,6,8,A,C,E)4-7 1,2,1,2, -- 0x(0,2,4,6,8,A,C,E)8-B 3,3,3,3, -- 0x(0,2,4,6,8,A,C,E)C-F 2,2,0,2,-- 0x(1,3,5,7,9,B,D,F)0-3 2,2,2,2,-- 0x(1,3,5,7,9,B,D,F)4-7 1,3,1,3,-- 0x(1,3,5,7,9,B,D,F)8-B 3,3,3,3 -- 0x(1,3,5,7,9,B,D,F)C-F } -- main loop while true do -- each frame, always start from same address with all variables reset except for target startAddress=0x81 displayCol=0 displayRow=0 jumpFlag=false postJump=false message = 'Fail'; branchMsg = 'No Branches'; -- will show up to 16 rows while displayRow<16 do -- get the instruction and determine its length op=memory.readbyte(startAddress) opLength=lengths[AND(op,31)+1] -- start of instruction, white color='#ffffff' -- we got to our target! Hooray! if startAddress==target and not jumpFlag then color='#00ff00' message='Success' end -- JSR (20) and JMP (4c,6c) have length 3, special color if op==0x20 or op==0x4c or op==0x6c then color='#ff0000' -- red opLength=3 jumpFlag=true -- RTI (40), RTS (60), AND(1000 1111) == 2 --> 0xxx 0010 --> 02, 12, 22...72 -- length 0 for 0x12, 32...F2. elseif opLength==0 or AND(op,0x8f)==2 or op==0x40 or op==0x60 then color='#ff0000' -- red opLength=1 jumpFlag=true -- Branch instructions -- essentially we warn elseif AND(op,31)==0x10 then color='#880000' -- light red branchMsg = "May Branch" end -- process the bytes in an operation for i=0,opLength-1 do -- read the byte x=memory.readbyte(startAddress) -- mark bytes beyond a jump -- dark/not executed if postJump then color='#502020' end -- display the byte! gui.text(displayCol*16,8+displayRow*8,string.format('%02X',x),color) -- next byte in this instruction startAddress=startAddress+1 color='#0000ff' -- data bytes -- advance display, use next row if needed displayCol=displayCol+1 if displayCol==16 then displayCol=0 displayRow=displayRow+1 end -- note that we're now beyond a jumping instruction, so further bytes won't be executed if jumpFlag then postJump = true end end -- terminate (for this frame) if beyond target if startAddress>target+2 or startAddress<0x80 then gui.text(10*18,(displayRow+1)*8,message,'#ffffff'); gui.text(10*18,(displayRow+2)*8,branchMsg,'#ffffff'); break end end FCEU.frameadvance(); end
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Real-time Strat Demo I made a from-power-on demo of the most realtime-friendly strat I've been able to find. It's still not very realtime friendly...:D True - if you're able to console-verify this one, I'm sure the speedrunners would appreciate it so they know they're going for something attainable. An easier strat I'd been working at with Producks turned out not to work despite having the correct memory addresses. Unlike the prior TAS's it involved going up to the top room of the level. In emulator testing with HHS's script, something seems to get messed up when you go that high up and all the numbers go permanently dark. It can also happen if you kill the first upward-facing plant when it's fully extended. Any insights from the rom-knowledgable?
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
That's right, so I say verify away if/when you get the chance.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Latest WIP finishes in 3:00.90 with room for improvement. I think I can get it under 3 and then some.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Producks wrote:
I got the warp on my nes real time! Thank you so much lord tom and HSS The hard part is getting those 3 frame perfect object and probably gonna take forever to get in a good run but it's doable
That's amazing, congratulations!!! Did you use a similar sequence? How many attempts? I'd love to see a vid if you recorded. I discovered that the rightmost object can actually be at x=223,225,226 or 227 and it still works, but the other two need to have x=32 and 143 exactly. Feel free to PM if you have any technical q's.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
No, the last falsely executed address is $00b0 in my WIP.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
The fire flower is not required at all - for these demos I just used it b/c it's easier (effort-wise) to kill enemies and position shells. For an optimized run, I suspect keeping the tail after 1-Fortress will be best since there's no way to get a flower without losing seconds of time. What to do in terms of obsoletion will be a big discussion, no doubt. I haven't really put much thought into it, was just using the terminology from Rygar, which has published glitched and any% branches due to a similar sequence break.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
SMB3 "Glitched" in 3:42.48 :-) Unoptimized proof-of-concept from power-on; I just hexed onto the current warps run -- no problem other than matching the x/y subpixels.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
2-player input is not required; I fixed the file at the link above to use only port 0. I think RAT196's original demo used Luigi so I had my emulator settings using both pads for the same keyboard input. For the speed-runners, it's interesting to even think about reproducing this. None of the steps are timing-dependent per se, but you do have to have pixel-perfect placement of 3 objects. At minimum, a lot of patience/planning would be required, but I suspect using the piranha and stopping two walking koopas on the right pixel would be doable. One would want to separate the koopas vertically enough that the first one despawns before it starts walking again. I'll clarify how each enemy is used, in the order they're killed: 1st koopa: killed at arbitrary position Top piranha: killed any position Koopa between ? blocks: killed any position Koopa walking on bent pipe: killed so despawns at x=143 (address 0xB0) Right piranha: killed totally inside of pipe, x=128 (0xAD) Left piranha: killed when x=32 (address 0xAE) Flying Koopa: stopped when x=227 (address 0xAF) Finally, Mario's x coordinate also gets executed, x=240 worked, others may also work.
Lord_Tom
He/Him
Experienced Forum User, Published Author, Expert player (3277)
Joined: 5/25/2007
Posts: 399
Location: New England
Derakon wrote:
Whelp. So much for the SMB3 run making a lick of sense.
Indeed...and I note we're just 2 days shy of 10 years since Bisqwit started this thread! Fitting.
1 2 3 4 5
15 16