Posts for sockfolder


Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
If it fails on illegal opcode, that is the correct behavior. However, the only place there should be illegal opcodes is at the values determined by that 23 sec wait. Perhaps the original TAS saved frames by going earlier than you should, when there are still illegal opcodes. Have you tried waiting a few frames longer at that wait? I think after 23.25 secs is when it is easiest (though I think there is an earlier time that works). Oh wait, I forgot. The other place there can be illegal opcodes is if you get/don't get certain items. I am still on my laptop so I can't look up the list I had. Perhaps you can look at the console ACE and see if there is a difference in the items obtained.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I made a real time full total control method (i.e. you can execute arbitrary code of arbitrary length), though it can be adapted and improved for TAS. Then the goal would be to find the minimum instructions needed to beat the game. Also, I didn't realize sadly that you can add characters after ZELDA and still get second quest, so this method can be improved easily. So first, if you trigger the glitch with AB, then you branch based on the note of the music. If you get a large branch, you actually jump just before the names of your files. That is, you just execute your names as code. The major limitation is the name characters only go up to $64. My (now obsolete) strat is first set the first two names with the bytes:
File 1:
$0e 45 06   ASL $0645
$46 12      LSR $12   // Reload first are
$46 16      LSR $16   // Change active file to file 1
$60         RTS

File 2:
$33 02      RLA(0x02), Y
$4C 38 06   end: JMP start ($0638)
$36 2F 64   input: JMP ($642f)	 // Turns into $6C 2F 64
This changes the second name and saves it. Then you rename the first file for the final code package:
File 1:
$20 45 06   start:	JSR input ($0645)
$0A         ASL A
$0A         ASL A
$0A         ASL A
$10 02      BPL end (#$2)

File 2:
$33 02      RLA(0x02), Y
$4C 38 06   end: JMP start ($0638)
$6C 2F 64   input: JMP ($642f)
In the first pass, it changes the second file name to bypass the character limit. Then the second pass does a loop calling the "retrieve input" subroutine. Reg. A is the buttons just pressed, and reg. Y is the complete set of buttons held. It writes on a start press, shifting in whether or not select was pressed at that time into a register determined by Y. In short, the location you write is determined by A, B, and the directions. You shift in a 1 if you hit select and start at the same time, and you shift in a 0 if you hit select before start. Using this you can write more code, and you escape the tight loop by first breaking an ASL instruction, and then breaking the JMP. Now that I know you have 3 more bytes from the ZELDA file name, the above method could be done in a single pass. Also, TAS can use other things such as ghost position for addition instructions. One question is, what exactly is the minimum to call credits?
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
Nice job figuring out that section. That is certainly an interesting way to do RNG. Using that memory would require frame precision. Timing that with the right music note would also be hard. I didn't see any way to get something useful with the Y instruction. Feels like we need the music to do something else to make this possible real time (my primary interest).
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I've been looking at this a little bit. Basically, what happens is: You blow the whistle which wants to create actor $5E. There are no blank spots and the index underflows and starts trying to write it into the state for the ghosts. The ghost is in state 0 during the acceleration period after being stopped. Blowing the whistle at this time makes the ghost state $5E, which causes the ghost AI to jump to $0602. From $0602, it executes some instructions based on the note in the music (I think), and tends to hit a JMP $0000 instruction (after some side effects). At $0000, there are a bunch of mostly fixed values (i.e. fixed instructions). It executes a couple of instructions based on Link's X, Y. Then it moves into a chaotic section that I don't know how to manipulate yet and in the movie, jumps to $EC6E and from there, back into the normal game play without any side effects other than the game being totally screwed up.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
In a given area, the "Position Component" will always have the same address. So if you want, you can manually look at the 4byte pointer at 0x803C0668. Then add 0x30, 0x34, 0x38 to that value to get the address for the X, Y, and Z for that area.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
Well I can supply some useful addresses if you need them. The Spongebob object is stored starting at location 0x803C0558. At 0x803C0668, there is a pointer to the "Position Component" that stores the position of Spongebob among some other values. The XYZ are stored starting at offset 0x30 from the start of the "Position Component". At 0x803C066C, it has a "Position Component" for the position on the previous frame. At 0x803C06E0, it stores a velocity towards the camera. At 0x803C06F0, it stores a velocity side to side (relative to the camera). There are other (maybe?) useful memory addresses near those. There may be a better speed measure I didn't find, but at least that is something.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
Yeah I did get total control. The final state I got was a short program in map data that would read controller input (1 byte) each frame into another part of map data and run after the composition of input after 255 frames. Obviously this is enough for total control. I didn't do anything with it though because I didn't see how to get left+right stuff in the emulator at the time, and because it took longer than expected and I was tired. I will describe how I did the important part. When you do Veran warp, it starts by trying to run OAM (actually it starts executing a bit before 0xFB00). OAM is normally inaccessible and read as 0xFF (instruction = rst 0x38). However, for some reason, if you want like 20seconds or so, when you click the tile, it will read OAM as it is. It all depends how the LCD writing timer and the code sync up, which was behaving erratically. It would often take many many tries before the code would run, which is why this is quite frustrating. The OAM code I used would read of a timer at 0xCC00 that ticked every frame, and write that into an array at 0xFC00, where it would be run next time the magic map square was selected. The first stuff I wrote was a branch to 0xCB00 (where the copy of OAM is) so that the timing was no longer an issue. From there, total control is straight forward. The annoying thing about the OAM code is that y is always set to E0 since most of the sprites are disabled. Then you can code in x, somewhat in the tile#, and then in the attribute. Also, E0 starts a 2byte instruction, which would steal away the x byte, the only truly controllable value. Then the attribute of the previous sprite needs to be the start of a 2byte instruction. Also, you can manipulate some tiles (bombs, rupees, fairies, and in a separate group enemies) in multiples of 0x20 since they are dynamically created. All you have to do is go through time enough times until they are the multiple you want. So, here is the code (OAM): 1. E0 5D 72 28 Link facing right, left half 2. E0 65 70 28 Link facing right, right half 3. E0 1E 1A 08 Mystery seed poof, left half 4. E0 26 1A 28 Mystery seed poof, right half 5. E0 32 08 2A Fire, right half 6. E0 12 70 28 Link, right half 7. E0 12 70 28 Link, right half 8. E0 6F 70 28 Link, right half 9. E0 26 FC 00 Spider thing, right half 10. E0 5E 1A 28 Mystery poof, right half 11. E0 5E 1A 28 Mystery poof, right half 12. E0 47 70 28 Link, right half 13. E0 4F C0 22 Fairy You just create these sprites in these positions from bottom to top, using stuff like bombing, bombing on the side of the screen, sword slashing, playing music, or pegasus seeding to fill up sprites to get things to the right position.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
What is it you want to know sephiroth? I've tried to clarify how a lot of it works in this thread. The final payload used in the TAS is the following code: 0x26 0x82 0x61 0x12 addiu r2,r20,0x6112 0x84 0x24 0x58 0x12 lh r4,0x5812(r1) 0xA4 0x40 0x99 0x66 sh r0, -0x669A (r2) 0xA0 0x59 0x9E 0x2E sb r25, -0x61D2 (r2) 0x3C 0x0A 0x80 0x0E * lui r10, 0x800E 0x35 0x4A 0x41 0x42 * ori r10, r10, 0x4142 0x08 0x03 0x90 0x49 jr 0xE4124 0xA1 0x44 0x67 0x92 * sb r4, 0x6792 (r10) The instructions marked with * were added for the TAS since there was extra time and it just messed up some of the palette code for the weird looking Alucard at the end. I separated each byte because each byte corresponds to an item in a slot in the inventory. So a 0x12 for example corresponds to the Basilard item. Coding is simply a process of arranging the items in your inventory to match the above order (each line must be reversed due to Little Endian order though).
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I did find a way to get the gold strategy to work. If you set the music pointer to 0xA8660 and restart it, it will overwrite the data read for the stats of the glitch armor. In particular, it overwrites the pointer used for the name of the armor and thereby avoids the crash. However, I did find if the control nibble has bit 1 set (and not bit 4), it often starts timers in certain locations. I used this to find another way to get total control with the timer. If you set the Music Pointer to 0x800F6090, then the code at 0x800F60FC will change over time. After 23-23.5 seconds, it forms a jalr r20,r27 instruction. This code is run when you open the relic menu, and r20 is set to the relic spot the cursor is at in that menu, which is located right before your inventory. You can run code either using item quantities (harder), or just using where stuff is in your inventory. I used this to run the credits. The basic idea is you need to call function 0x800E4124 with parameter 9 (in r4). This runs an 'ending' cutscene. Then you need to set 0x800978B4 to either 3 (best ending) or 5 (normal ending). By moving my inventory around, I create the code: 0x26826012 addiu r2, r20, 0x6012 0x84245812 lh r4,0x5812(r1) 0x08039049 j 0x000e4124 0xA0599F2E sb r25, -0x60d2(r2) With the cursor 2 slots above the fairy card, this will write 3 for best ending and call the credits. The real time record with this trick is 13:37 (also first real time completion), with substantial improvements possible. http://www.twitch.tv/sockfolder/c/3801775 To be honest, I'm not sure this approach is best for TAS because of the super fast menuing possible there and the 23 second wait. There might be a better approach, maybe such as setting music pointer to 0x801B4FA0, which should jump to 0x80097C14 (right below inventory) when going into the shop buy menu.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
SotN is such an unlucky game. First of all, it shouldn't be so difficult to jump to your inventory considering all the code in the game and the power of the music pointer corruption. But okay, so I did the previously mentioned technique to set my gold amount. As a side effect, it turned armors to 0x7f007f. When you select the armor slot, it 'corrects' to 0x7f which happens to be one of the glitch armors that crash. Unlucky. But you are okay if you never select them, except that for some reason, going into the buy menu of the shop will 'correct' them and cause you to crash when you go to equip something again. Unlucky. Sadly, since the gold amount is 0x01E00000, the only way to get the last 4 byte not to be 0 is to buy stuff. You can use SoS% though to try to store over the 0x7F items in advance though so you don't crash. Except, 0x7F is a 2 Handed Greatsword, and apparently 2 handed weapons "absorb" their own swap value, so you can't write any memory locations beyond the weapon slot. If 0x7F was any single handed item, this would be possible. Unlucky. So long story short, the method mentioned in my previous post doesn't work. There might possibly be a modification if someone can figure out the Music Pointer better, but it seems a little complex.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I finally found a total control vector I'm pretty happy with. I found some more controllable manipulations of the music pointer. Namely, if the 'control nibble' is 2,8, or A, the 'modified byte' is set to 0x00, 0x01, or 0x01 respectively. Using this, I found the following Muramasa based total control. Type B change at 0x80016F68 (Music Pointer = 0x80016F40). This is triggered when Muramasa is equipped or highlighted in your inventory. It jumps to 0x80097BE8, shortly before your gold amount. Unfortunately, gold itself cannot have the most significant byte set to something != 0 due to the 999999 cap, and that byte controls the op code of the instruction. But, after some experimentation, I found if you set the Music Pointer to 0x80097BA8 and restart the music, the gold gets set to 0x01E00000 and all the values around it are valid instructions. So with that, you can buy some stuff and Swap Overflow over the 0x01 to make a branch to jump to your inventory. One nice thing about this glitch is that r31 has the correct return value. So, if there is a function that starts the credits, we could probably just jump to it to end the game, and everything should behave well (no stack overflows or infinite loops). I was planning on streaming when everything was more solid, but I guess I can start showing the final steps of getting this to work.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I spent a while looking for new vectors for total control, i.e. new values for the music pointer (which I will call MP). The key pattern I use is that if the last nibble of the int at MP+0x90 is 8, then the first byte of the int at MP+0x28 is set to 0x01 and the aforementioned nibble is set to 0. Then you can modify code either by changing the 8 to a 0 (Type A), or by changing a byte to 0x01 (Type B). The goal is to change the code so that it jumps to a controllable area. The two ways I consider doing this are: 1) Create a jump to register instructions. 2) Corrupt the stack so that the jr r31 instruction goes to somewhere good. You can do this by messing up the instructions modifying r29 (the stack pointer), or by messing up the instructions storing or loading r31 into/from the stack. SotN code is quite large, so I couldn't check very much by hand. However, I went and took the open source emulator PCSX-Reloaded and changed the emulator so it would test those types of corrupts as it ran. So, now I have a lot of possible vectors, but sadly and surprisingly, I didn't find any that would that good. Key criteria are that all bytes in the music pointer are 1-169 (easiest to set values), easy to trigger code, minimal "fixing" of whatever was corrupted, and jumping to a good location. I will list some methods. I will refer only to the line of code modified, not to the music pointer itself. Original Method: Type B change at 0x800F52D8, making a jalr r8, r16. Jumps to 0x80097C1C, requiring setting resists using glitch armor items from Elixir and Item 155. This makes an instruction jumping past the music pointer (which is dangerous to change). Then you have to use Swap Overflow to modify the next nonzero int, and make it an instruction to jump to your inventory. You also have to fix r16. New Methods: 1) Type B change at 0x800E446C, making a jr. Jumps to 0x80097BA8, where stats are located. Then you'd have to set your gold to a value so that it makes an instruction to jump to the inventory. This is easy to make, but sadly has the large flaw this code is triggered halfway through a loading zone, which makes it hard to use. Possibly the best though. 2) Type A change at 0x8010E1D4, causing a stack corruption. Jumps to 0x80097410. This area includes flags for what enemies are killed (could be used for an instruction) and the input, which can also be used to jump into the inventory. Triggered on level up and heart refreshes (only once). You can't use any potions or spells or it will cause an invalid jump. This MP also fails the 1-168 criteria. TAS might able to use the adjustable input to some effect though... 3) Type B change to 0x800F8920, causing stack corruption. Jumps to 0x80097BD4 (so gold used as instruction). Activates when opening the sort menu. Fails the 1-168 criteria BARELY. Very sad about this. There are quite a few others, but those are probably the best or at least equal to others. It would be helpful to find more controllable memory regions from which it is possible to jump to inventory. There were also a few others that were inconsistent or something. I still have some hope of finding a method that is clearly the best.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
I can't say I really understand this SMS glitch, but from what it sounds like and if Saturn works in the same way, you might already have enough to do the glitch. All it takes is a single missing/incorrect value in the inventory and you can swap overflow. Just figure out what value is missing (X). Then, assuming you have quantity 0 of item X, you just acquire it (by buying it, picking it up, or unequipping it). Then it should swap whatever the value is in the first empty spot with the first value of X it finds, which would be past the inventory. Preferably, X would be a low value (a value between 1-89) and the first empty spot would be a high value (above 89). Then you should get a glitch armor in your inventory, at which time you basically have complete, if slow, control over the weapon values in the inventory.
Experienced Forum User, Published Author, Player (249)
Joined: 1/26/2014
Posts: 14
So I've done quite a bit of work on this glitch, and this seems like the best place to share my knowledge of how the glitch works. As some background, the inventory is stored in the following order: first the quantity for each weapon, then the quantity for each armor, then the order in inventory for all your weapons (you always 'have' all weapons in your inventory, just with quantity 0), then the order for your armor. Then there are fields like your stats, timer, familiar level, then several pointers. Also, an equipped weapon doesn't count towards your quantity (as is clear by the fact that equipping something you only have one of removes the text from your inventory). The glitch starts with save corruption, the point of which is to get you sorting menu to have at least 1 extra S.Sword sort, but usually entirely S.Sword. I will assume you get all 11 S.Swords in the sort menu. Also, I will say you own an item if you have at least 1 of it. The sorting program works as follows: 0) Start from the start of the inventory. 1) For each type listed in the sort menu, put all owned items of the type in order next in the inventory. 2) After that, put all unowned items in their original order. 3) If there are left over spaces, fill in the spaces with item value equip to the index in the inventory (like slot 168 gets item 168). So when you start with 1 Short Sword, it multiples to 11, then 121, then filling your inventory when you use the sort command. Unowned spaces towards the bottom get erased first when doing this, so occasionally you want to move these spaces to the top. Also, if you have alot of non-sword swords, you can restore some high values to your inventory after you've destroyed it by doing a sort without a short sword in your inventory. Once your inventory is missing some values, you can start swap overflowing shenanigans. This exploits how the game behaves when you get a new item (an item with quantity 0. It is allowed to be in your hand). This can be from buying it, unequipping it, or picking it up. The intended behavior is that it swaps the item up from its current location to the first empty slot (recall all items are in inventory from the beginning). The function is: You are getting item X. 1) From the beginning of the inventory, search for the first slot containing an unowned item. If you find slot with value X, stop. Let Y be the value of the empty slot. Store X in that slot. 2) Continue searching for the first slot containing value X. Store Y in this location. (Note these values are bytes). The problem is this searches even past the inventory bounds if it doesn't find X. It will swap using the first empty slot, even if that slot is in the armor area of inventory or beyond (note: by empty, I mean you have none of that WEAPON, even if you have an armor in that slot). Typically, this is used by choosing a byte in memory you want to modify, and dropping an item with that value (X). You set the value of the first empty slot to whatever you want to store in that byte. Then the swap puts the desired byte in that location (if that is the first byte with value X). If you put a value above 89 in the armors, you get a glitched armor where the quantity is equal to the weapon value is a slot in your inventory. This is because directly after armor quantities in inventory are your weapon item values. For example, equipping armor #92 reduces the item value in slot 3 of your weapons by 1. Using this, you can control pretty precisely the items in your inventory (at least for values 1-168). For item values above 99, you can chain equip glitch armor to quickly reduce the value down to up to 99. For other values, unequipping glitch armor works so this method doesn't work anymore. Instead, you have to equip the glitch armor, swap another slot with the weapon 'glitch slot', unequip it, then swap it back and reequip the glitch armor. By repeating this process, you can slowly reduce the item value of a slot (while increasing the item value of a different slot). However, you cannot increase an item value beyond 99. There is a pointer with initial value 0x80138460 that I refer to as the Music Pointer just after the main inventory stuff. By changing its value, you can change almost any spot in memory, though a bit uncontrollably. If you reload the shop music, it will change a large block, which is useful if you point it to data, but will cause crashes if changing code. However, there is often a smaller change when you change the pointer, even if the song doesn't get reloaded. It seems to be effected by the byte 0x90 from the pointer location, but I don't really understand it. By setting the pointer to 0x800F52B0, you change an instruction that causes the PC to jump to a spot just after the inventory, from which you can jump into the inventory using some swap overflow shenanigans. However, there is hopefully (maybe probably) some superior value that will get control directly into the inventory, from which total control can be obtained.