Posts for Omnigamer


1 2
6 7 8
11 12
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
Great job! That's some massive improvement. Glad to see you've come a very long way since first picking the game up, both in recognizing optimizations and technical ability to dig through the code. Sucks about the ending, but at the same time it's pretty much irrelevant. Btw, I voted no on accident (mixed up tabs) but the vote should be a yes!
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
"Screw with" is relative here, since almost anything and everything you do will affect the bug. In the case of the pause screen, the current screen position and some other things are stored when you pause, so if your last pause was in a scrolling room, then yes the memory values will change and the warp will be "different". Doing pauses here and there will not break the glitch though.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
Whatever it's called aside, the structure I'm referring to is a list where newest items appear at the lowest index and all other items are moved to higher indices. There's a number of ways that this can be done (including in the opposite direction) but for Capcom at least I've seen lowest index for newest elements as the convention.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
My guess is that it is something to do with how the game handles powerups and then also a flawed flag for the boomerang. Something along the lines of after you grab the powerup that the boomerang is holding, it does checks after to see if the item still exists before deactivating the flag. Past Capcom games have used an indexable stack sort of setup for keeping track of enemies and things, so it wouldn't surprise me if they used the same thing here. So when you grab the item with the boomerang, it pops it off the stack. However, that same frame you move another object on-screen, which gets pushed on to the stack. The boomerang still has an active flag for thinking that it's holding something with a reference to that particular index (probably some other checks occur too), so now the new thing that appears is instead considered grabbed by the boomerang and has its position updated to match the boomerang. Again, I have not played around with the bug nor looked into it at all, so this is just speculation.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I spent a little time playing with clipping into walls and such, particularly in Stage 5 at the key door. Dragon can fit in to the spot between the door and the ledge, but I wasn't able to do anything with it. For Green though, holding away from the wall and doing his teleport gradually moves you left until you go too far in and it zips you to the right. Still no way to bypass the door though. EDIT: Most likely won't have to worry about it, but it would be good to avoid this: Link to video
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I did some very rudimentary testing on Stage 2 to get a feel of time advantages for each of the forms. As expected, Dragon/Blue is easily the fastest even after accounting for the time spent waiting for the gem. Green is the slowest overall, but is not all that different from Red. Green has some advantages in dealing out damage to bosses, but the delay on his dodge just kills any movement sections. I imagine this holds true for most of the other stages as well. For now I'm thinking Blue x4 is the fastest strategy for bad ending, just because dragon movement is too good. For Good ending, I think the order is such: Green -> Red -> Blue -> Silver This puts Green in good position for the shortest overall section (Stage 2) where his attacks get the most leverage. Red can deal fine with getting through Stages 3 and 4 since 4 is almost entirely on autoscroller. Stage 5 is stupidly long, but Blue should be able to move and deal with bosses well enough. Still lots of room for testing, but we'll see what happens.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
Just as a heads-up, I have a mostly working hitbox viewer set up for this game. I'm still chasing down a few things, but I'll release it after I've reduced the number of false positives and checked on a few inconsistencies. EDIT: Script available at http://pastebin.com/YpRe4iER . It's not very pretty and still has a few bugs, but for the most part it's good. Most of the commented blocks are for debugging purposes and I'm too lazy to remove them. Created on/for BizHawk, but it should be pretty simple to convert. Notes: -Some enemies have scripted attacks that produce a disjointed hitbox. These hitboxes are generated by hardcoded values in each enemy's subroutines; I'm not going to dig through to find all of the offsets. It should be fairly obvious where these hitboxes are though. -There are still some anomalies for some of your attacks. For example, the trailing effects on many of the charge attacks don't actually do damage. I could not find a way to differentiate them however. I removed the few consistent ones that don't do damage based on ID. -Enemies occasionally have the wrong HP, in particular the slimes. I don't know why this is, but it's uncommon enough that I'm not going to investigate for the time being. -Hitboxes for stage hazards (spikes, lava, etc) are currently not tracked. -The Giant Worm miniboss takes 1 point of damage from any attack and can only be damaged once per cycle. The HP is stored in an unusual place, but he has 5 HP total. I can dig up that address from my notes if it helps. If you notice anything else please let me know. EDIT2: Unrelated to the above, but I noticed that you can "time over" down to 0 HP before a screen transition and you'll appear on the next screen with 0 HP but still alive. May be useful somehow, but just an oddity for now. By "screen transition" I specifically have done this on the spider miniboss. Just kill him with only a few seconds left and you'll transition before the time over animation plays all the way out.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I spent some time working with PJ on the door glitch to better understand what happens with it while he was routing this category. I don't need any mention, but for posterity's sake it would be good to have it fleshed out further in the run notes or in the game's thread. Simply put, the game tracks what room you are currently in and uses a table with some offsets (doors) to decide where you end up next. What you end up doing is having the game advance the room you are in without actually travelling there, and then by entering a different door you are able to go where that index would have taken you in the room the game thinks you're in. I can dig up memory addresses from my notes later, but it's a significant enough bug that some more experimentation may prove useful for future iterations of this TAS. Traveling to a non-existent index will usually send you to Area 1, but with playing around with the value I've also gone to some junk rooms.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
If it's anything like some other late-era Capcom games, the RNG will be per-frame but easily predictable. I can try looking into it when I get back from my vacation.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
A note on the "frankencode" version, it is very much memory-dependent, and there is likely a memory leak somewhere such that it becomes unstable. There may yet be other bugs too; processing time actually increases as the incrementer starts to affect bytes 4 and 5. Somehow it was finding less and less collisions at this point, even though the hash table was still consistent... so either there really were 12M new unique values per byte, or I'm not setting up something right. In any case, summary is to try at your own risk, and it's probably better to wait until micro500 has the redundant calculations worked out.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
If it's indexed by X, it usually means that it's just some data table in the ROM. I have absolutely no context on what is changing here, but my guess is that you'd find a table of values about 32 to 256 wide at position $92FB3B in the ROM. It helps you more to trace where the X comes from in this instance.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
For what it's worth, you may look at re-purposing the code on the tcrf.net page. It seems to be well set-up for tracking blocks such that it is easy to distribute randomized 32-bit blocks to people to process in the background. It's also parallelizable if you set up the RANDOM1 option so that individual instances of the program execute on different "long blocks" as he calls them. I have about 23 instances running right now and piping the results to a separate folder. I have a separate program parse out codes that actually result in useable program code, but it's probably better if that's built into the program. EDIT: I'm using a modified version of that code which checks for valid opcodes throughout the decoded string. It's compiled for 64-bit and takes approximately 5 seconds to cover a 65k space. Across 23 instances, this means that it takes about 4 hours to cover a 32-bit space. Assuming there's only one likely code (hint: there's more than one), we are likely to stumble across it in a little less than a million years at that rate. Progress! FPGA implementation is still coming along, but I need to decide if it's better to keep it small and plan to have a lot of simultaneous cores or pipeline the hell out of it and maintain high throughput. I'll probably make both to compare, but we'll see. EDIT2: Just to make sure my thought process in the final checking portion is correct, does it make sense to establish a "machine code chain" on the decoded string? I've made an array of how many bytes all of the opcodes are (with 0 for invalid/undocumented opcodes) that I use in iterating through the string until I find an invalid opcode. Code example is below:
while(iter<0x51){
									if(opcode_table[decoded_handler[iter]]==0)
										break;
									else
										iter+=opcode_table[decoded_handler[iter]];
								}

if(iter==0x51){
									printf("  SUCCESS!!);
								}
I'm fairly certain this should be correct unless they put a data table somewhere in the space. Are there any issues with checking in this manner? I may be getting caught up in some endian shenanigans that I'm not considering.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
jlun2 wrote:
How is it going?
The current iteration of the code is unfortunately too slow to cover the space in a reasonable time, but I am working on an FPGA version that should better cover speed issues. I also spent some time in developing inverters for some of the functions, but it's...messy. A lot of it is directly invertible, but there's a lot of control logic checks that make it tricky to deal with. The non-invertible functions depend on unknown bits, which pretty drastically increases the search space. I think it's still smaller than the initial 64-bit search space, but it will be an order of magnitude slower to find workable solutions. We also don't have the actual specific result either though, which limits the feasibility of inverting the function. I'll post some performance metrics when my FPGA implementation is done and we can decide if it covers the search space efficiently enough.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
Yeah, for future reference RAM space is only mirrored the first 0x2000 addresses for any given bank, that is every address xx1FFF and below. There is more RAM space than that, but it is not addressable unless it explicitly loads from banks 7E or 7F. Which is to say that 7E4000 is a RAM address, but 804000 is not. If you see things changing that are outside of that range (such as 80213C) you can bet they are some special register.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
$213C is a hardware register, specifically the horizontal scanline location. My guess is that it decrements every time it is read, but I'm not too familiar with the register interactions. Source: http://www.proprofs.com/flashcards/story.php?title=snes-registers If I'm reading the trace right it checks $A5 to see if any of the last 6 bits are set (and #$3F). Assuming that the possible values of $A5 cover the full byte space, you have 4/256 chance to hit the bounty, for values of $00, $40, $80, and $C0. It sounds like $A5 is the RNG, and it triggers on-call, meaning it will be static so long as you're not doing anything that uses randomness. What will be important is finding a trace with the RNG update subroutine to see where it grabs its entropy, which from what you say should involve a frame counter and/or user input. My advice is to watch $A5 and find a frame where it changes, and then use a trace of that frame to track it down.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I figured out the trigger for the glitch before; it has nothing to do with the projectiles. You can test a lot of things by forcing 7E1B9C to 01, which triggers the bug. If I remember right, that address is used as the frame counter until enemies can move again during the robo super. I don't remember all the details, but it essentially breaks the mapper and fills some locations with the chests. I think that all chests on a map are in a vector, and this only grabs a specific index of that vector. I don't have notes from before, but I do have a few disassemblies I can share as well as some of my candid analysis from ~6 months ago.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
For what it's worth, the ending did play out normally when this occurred on console.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I just want to clarify something on the glitch that occurs here. It is fundamentally a nested loop that looks something like this (going from memory):
for( i=1;i!=0;--i)
    for( j=&memAddr+3;j!=0;j--)
        copy(memAddr+1,memAddr+2);
        memAddr++;
    end
end
So what happens is that the initial i value is assumed to be initialized, but due to a bad branch setup earlier on the value starts off at 0 in 16-bit mode. So when the initial subtraction is performed, it underflows to FFFF, and will go through a huge portion of the memory space. This is why it's so hard to predict how it will execute; every value in memory has the potential to be both the inner loop counter or a "swapped" value. This gets particularly messy when it overwrites the variables themselves over the course of the bug. I believe the full crashes occur when the variables get messed up enough that it starts to write into ROM space. If the loop exits gracefully (that is, after FFFF executions of the main loop have occurred) then the "game end glitch" occurs.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
There are unconfirmed reports from GFAQs that lockups have occurred at the ice temple and one instance at a chest in the fire cave, but for the most part this is the only situation we can confirm that triggers the ending sequence.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
To answer it a bit better, we know what causes the bug, but we don't specifically know what causes the game ending sequence to start. Crashes occur when the counting variables get overwritten/messed up enough such that it starts trying to write to ROM space, while the game ending bug occurs only when the loop exits gracefully.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I'm also excited to see what happens with this. Do you intend to look into both the normal and true ending routes?
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I can appreciate the difficulty of performing the run, but as for a watch I can't really say I was entertained. Too many things to try to watch lead to me not actually watching anything at all, and all the audio mixed together made me never want to hear the mario jumping noise again. Voted meh.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
PJ found a glitch some time ago that causes treasures to shift locations when activated. I did some digging and found the affected memory locations to test it, however we didn't have a full understanding of it by the end. In particular the goal was to move some of the critical items (magnet boots, IIRC) to a different location on the map, but we couldn't find a way to achieve this. I will check my notes when I get home, but you can activate it simply by triggering the robot helper's special. While the special is active, some of the mapping mechanics will break and enemies/chests will be out of place.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I did some basic memory hunting for this game a while back. I will try to pull up my notes and if I have time this weekend I might look for the damage formulas.
Experienced Forum User, Published Author, Player (33)
Joined: 2/16/2012
Posts: 282
I have not been able to watch the videos on Nico, but I'm curious if you're using the ammo overwrite glitch in the run?
1 2
6 7 8
11 12