Jason777 Posted December 11, 2013 Share Posted December 11, 2013 I know of a lot of people who want to be able to use warps to travel from one area to another... and then they find out that exits and cutscenes are hardcoded and based on the scene you're currently in. Well, this hack makes it so that you can specify which area and cutscene to warp to. All you simply have to do is... Apply the patch Place a warp actor (0x005D) on a map Add the warp object (0x0048) Modify the Y rotation to be the exit number you want Modify the Z rotation to be the cutscene number you want (leave at 0x0000 if unsure) For those of you who are asking "why couldn't you just make use of the variable instead?": there were issues with crashing. Besides that, there would be no reason to have to modify the Y or Z rotation value for the warp actor in a non-hacked ROM anyways. Also, even with the patch applied all original warps in-game should work just the same (not thoroughly tested). The video above shows the result of... Adding an actor and object to Hyrule Field via ZAO-ADD v1.3 Placing the warp actor and modifying the Y rotation via SceneNavi beta 8 (Old) V1: http://www.mediafire.com/download/58wnmjfm738obsy/warp_exit.ppf (New) V2: http://www.cs.utexas.edu/~jason777/Modding/Zelda%2064/warp_exit/warp_exit_v2.ppf Here's a little something extra that I thought would be neat to show: https://www.youtube.com/watch?v=9CKDmo2sJ6E#t=112 A note about cutscene values: values range from 0xFFF0 to 0xFFFA (I think), where 0xFFF0 is cutscene 0, 0xFFF1 is cutscene 1, 0xFFF2 is cutscene 2, and so on. Notes and relevant data concerning hack: http://www.cs.utexas.edu/~jason777/Modding/Zelda%2064/warp_exit/ Exit list: http://wiki.cloudmodding.com/oot/Entrance_Table_(Data) Partial credit goes to Airikita for pointing out some free space where I could extend the code to support cutscene values. 2 Link to comment Share on other sites More sharing options...
HeavyZ Posted December 12, 2013 Share Posted December 12, 2013 This is awesome man. Great work! Link to comment Share on other sites More sharing options...
Airikita Posted December 12, 2013 Share Posted December 12, 2013 Oh I see, great idea! Wow... this will make manipulating warps SO much better. It makes sense this would work, considering I checked the warp portal... it checks for scene number if I remember correctly. Link to comment Share on other sites More sharing options...
Jason777 Posted December 12, 2013 Author Share Posted December 12, 2013 For those of you who want more info on the warp actor, this is a link to a folder containing the modified actor, some comments on the disassembled actor, and some other notes: https://www.mediafire.com/folder/hckbzmx7czdjy/Door_Warp1 1 Link to comment Share on other sites More sharing options...
Airikita Posted March 6, 2014 Share Posted March 6, 2014 Oh Jason777, I was just curious... is it possible to make the Z rotation force a cutscene value? I want to be able to change the cutscene value so I can force a custom cutscene rather than rely on the cutscene scene index list. Link to comment Share on other sites More sharing options...
Jason777 Posted March 6, 2014 Author Share Posted March 6, 2014 I don't see why not; looking at the source reveals that cutscene values are stored as halfwords at 0x8015FA72 (0x80160000 + -1422). You can see instances of "sh t3,-1422($at)" and similar.The only issue is making space for two more instructions to load the Z rotation and then store the cutscene value (I think). Link to comment Share on other sites More sharing options...
Airikita Posted March 7, 2014 Share Posted March 7, 2014 Space? No problem. Add code to the end and change the size value at the end, make a JAL reference to it and a relocator in the section of code. It's better than a code hook. This warp portal is a spare actor for my mod anyways. Link to comment Share on other sites More sharing options...
DeathBasket Posted March 7, 2014 Share Posted March 7, 2014 Or you can rewrite the code in the disassembled actor and re-assemble it after. That way you should have no trouble adding as much code as you need to. Link to comment Share on other sites More sharing options...
Airikita Posted March 7, 2014 Share Posted March 7, 2014 Or you can rewrite the code in the disassembled actor and re-assemble it after. That way you should have no trouble adding as much code as you need to. What I suggested only needs a few lines, but okay, sure... if you think that's simpler? I don't think that's even a good idea, because disassembled and re-assembled actors will crash on console (likely) especially if it's spinout's tool. Link to comment Share on other sites More sharing options...
DeathBasket Posted March 7, 2014 Share Posted March 7, 2014 imo it's a whole lot simpler than having to manually update relocations data etc. but I didn't know about it crashing on a console, I never tried any actors out that I modified. I did hear that my boss rush hack mostly worked (most actors were modified this way) but I don't know. Link to comment Share on other sites More sharing options...
Airikita Posted April 8, 2014 Share Posted April 8, 2014 Hey Jason777, I could work on the warp portal using z-rotation for storing a Cutscene value, unless you have this worked on? I don't know what spare time I'll have, but I could tinker with it when I have more time. I'm sure I can find the right stuff if you could point me to where you modified the code to change the y rotation storage. Link to comment Share on other sites More sharing options...
Jason777 Posted April 8, 2014 Author Share Posted April 8, 2014 I don't have much time to do it myself. In the mod source, there is a text document with notes that describe where I modified the actor to use Y rotation if it was not spawned by a boss. That area would be perfect to have the actor load Z rotation and establish cutscene values. I would do it myself but the warp actor just so happens to be one of those few actors that have trouble recompiling -- they reference virtual addresses that are out of bounds or in the .bss section -- so inserting a couple more commands will be tedious without nOVL and zOVLDis. Besides that, it was already hard enough to make the hack without needing extra space. Link to comment Share on other sites More sharing options...
Three_Pendants Posted April 8, 2014 Share Posted April 8, 2014 Hmm, this is rather neat! It gives a lot more freedom than what is originally presented, that's for certain. Link to comment Share on other sites More sharing options...
Jason777 Posted April 8, 2014 Author Share Posted April 8, 2014 A thorough explanation of how the hack works... If we look at the routine data_80999A68, specifically $L000046, we begin to see the logic that the warp applies when deciding the next exit. It starts off by checking to see if the player is in Dodongo's Cavern Boss room. This, in way, is check to see if the player just faught King Dodongo. From here it decides to take exit 0x013D and cutscene 0x000F. lh v0,164(s0) // Load current scene number li $at,18 bnel v0,$at,$L000049 // If current scene != Dodongo's Cavern Boss, goto $L000049 li $at,17 jal external_func_80035B4C // Seems to return something related to alternate headers or flags li a0,37 bne v0,$zero,$L000050 li t4,1146 // Exit 0x047A jal external_func_80035B74 li a0,37 or a0,s0,$zero jal external_func_80084D10 li a1,109 lui $at,0x1 addu $at,$at,s0 li t2,317 // Exit 0x013D sh t2,7706($at) // Set next exit lui $at,0x8016 li t3,0xfff1 // Cutscene 0x000F (0xFFF1 = -0x000F) b $L000051 // Goto exit label sh t3,-1422($at) // Set next cutscene We also see at $L000050 that exit 0x047A is taken. The conditional check in the above code snippet seems to have to do with event, scene, or map flags. If the player wasn't in the Dodongo's Cavern Boss room, it checks to see if they were in the Deku Tree Boss room at $L000049. If so, it decides to take exit 0x00EE and cutscene 0x000F. bnel v0,$at,$L000052 // If current scene != Deku Tree Boss, goto $L000052 li $at,19 jal external_func_80035B4C // Seems to return something related to alternate headers or flags li a0,7 bne v0,$zero,$L000053 li t7,1111 // Exit 0x0457 jal external_func_80035B74 li a0,7 jal external_func_80035B74 li a0,9 or a0,s0,$zero jal external_func_80084D10 li a1,108 lui $at,0x1 addu $at,$at,s0 li t5,238 // Exit 0x00EE sh t5,7706($at) // Set next exit lui $at,0x8016 li t6,0xfff1 // Cutscene 0x000F (0xFFF1 = -0x000F) b $L000051 // Goto exit label sh t6,-1422($at) // Set next cutscene We also see at $L000053 that exit 0x0457 is taken. The conditional check in the above code snippet seems to have to do with event, scene, or map flags. If the player wasn't in the Deku Tree Boss room, it checks to see if they were in the Jabu Jabu's Belly Boss room at $L000052. If so, it decides to take exit 0x010E and cutscene 0x0000. bne v0,$at,$L000051 // If current scene != JabuJabu's Belly Boss, goto $L000051 (exit label) li t8,270 // Exit 0x010E lui $at,0x1 addu $at,$at,s0 sh t8,7706($at) // Set next exit lui $at,0x8016 sh $zero,-1422($at) // Set next cutscene There may be logic concerning using an alternate exit, check $L000060. All other logic concerning exits in the elemental temples, can be seen in routine data_8099A5EC starting at $L000070. This routine is used before data_80999A68 and can be proven by tracing back function references. By now we should have picked up where exits and cutscenes are stored: Exit values can usually be found by looking for instances of ",7706(" and by looking at assembly beforehand, we can see that the exit number is stored at 0x80223E3A Cutscene values can usually be found by looking for instances of ",-1422(" and by looking at assembly beforehand, we can see that the cutscene number is stored at 0x8015FA72 With this in mind, and the order of checks that warp makes when deciding the exit, we begin to devise our hack.We don't want to interfere with any of the exits taken by boss warps so we should try to come up with an "else" statement where we apply our hack Because I don't want to go through the headache of recompiling the warp actor and/or fixing reallocations through manual addition of code, we want to keep within the original size of the actor Okay, so we see that $L000052 is the last check the actor makes before deciding the exit to take, this will be where we insert our "else" statement. Now we just need to find free space... well we're in luck because just above the start of $L000052 and in $L000053 we see this:lui $at,0x1 addu $at,$at,s0 sh t7,7706($at) // Set next exit lui $at,0x8016 b $L000051 // Goto exit label sh $zero,-1422($at) li $at,19 It's a part of $L000053 where we are taken to exit 0x0457. It is branched to from $L000049 and most likely the result of alternate header or event flag checks. What's so special about that code snippet? Well, with a little examination, we see that it makes an unconditional branch to $L000051 (which is a label where the warp is done deciding which exit to take), but that's besides that point. It's the code that follows immediately afterwards that's of interest: b $L000051 // Goto exit label sh $zero,-1422($at) li $at,19 We see in the delay slot (the instruction directly after the branch) that we set the cutscene number to 0x0000. The delay slot may be in use, but the instruction directly after the delay slot is never executed at all. This gives us exactly 1 unused instruction. Now we change the original branch to $L000052 in $L000051 to this: bnel v0,$at,$L000052 - 1 // If current scene != Deku Tree Boss, goto one instruction before $L000052 This won't actually compile, it's just to help make things more easily readible. So now we branch to the instruction located just before $L000052 which is: li $at,19 We're loading 19 into $at in order to make the scene number check at the start of $L000052. Now we consider that the new start of $L000052. We replace the instruction there with a check to see if the player is in the Jabu Jabu's Belly Boss room: bne v0,$at,PC + 2 // If current scene != JabuJabu's Belly Boss, goto 2 opcodes ahead This won't actually compile, it's just to help make things more easily readible. We jump two ahead because we still want to set an exit number. Now we replace the instruction at the original start of $L000052 with an instruction that reads the actor's Y rotation into $t8: bne $t8,0x00B6(s1) // Load Y rotation of actor into $t8 From previous checks, it was concluded that at this point in the actor's code, register s1 contained the address of the actor panel. Now the hack is complete. The way it works is that if the user is not in Jabu Jabu's Belly Boss room, it reads the Y rotation into $t8 and then merely skips the instruction that sets $t8 to exit 0x010E while continuing to execute the code in $L000052. If the user is in Jabu Jabu's Belly Boss room, then it still sets $t8 to the Y rotation of the actor but then $t8 is immediately overwritten with exit number 0x010E because the branch was not taken. Either way, the code for $L000052 is still executed. The logic can be written like so: if (CURRENT_SCENE == JABU_JABU_BOSS) { NEXT_EXIT = 0x010E; } else { NEXT_EXIT = Y_ROTATION; } NEXT_CUTSCENE = 0x0000; SetNextExit(NEXT_EXIT, NEXT_CUTSCENE); Hopefully this pseudo-code clears things up for you. In the end, here were the changes made to the actor file: 0x1438 : "54 41 00 1B" to "54 41 00 1A" <--- Changes a branch to $L000052 to branch to one opcode before $L000052 0x14A4 : "24 01 00 13" to "14 41 00 02" <--- Replaces an unused opcode located one opcode before $L000052 to a branch to 2 opcodes in front of it 0x14A8 : "14 41 00 06" to "86 38 00 B6" <--- Loads the Y rotation into t8Now, I doubt you'll be able to optimize the code in the actor file to load the cutscene value from the Z rotation and still have the same file size, but this should have given you a good idea why $L000052 would be the best place to insert the hack. In the end, you should try to model the code to represent this:if (CURRENT_SCENE == JABU_JABU_BOSS) { NEXT_EXIT = 0x010E; NEXT_CUTSCENE = 0x0000; } else { NEXT_EXIT = Y_ROTATION; NEXT_CUTSCENE = Z_ROTATION; } SetNextExit(NEXT_EXIT, NEXT_CUTSCENE); Link to comment Share on other sites More sharing options...
Airikita Posted April 8, 2014 Share Posted April 8, 2014 Oic, so it only works when not in a boss room. Well, that can make this easier for me then. Link to comment Share on other sites More sharing options...
Jason777 Posted April 8, 2014 Author Share Posted April 8, 2014 Oic, so it only works when not in a boss room. Well, that can make this easier for me then.Yup, I wanted the warp hack to work with an original unmodified game without completely screwing over the boss warps. I haven't completely tested all the warps, but they should work (in theory). 1 Link to comment Share on other sites More sharing options...
mzxrules Posted April 9, 2014 Share Posted April 9, 2014 FFF1 plays cutscene 1 not F since it ultimately loads scene setup 4 + 1. Setting the next cutscene to 0000 for Jabu should't play a cutscene I don't think. Link to comment Share on other sites More sharing options...
Jason777 Posted April 9, 2014 Author Share Posted April 9, 2014 I would totally understand it being that way. It really didn't make sense for the number to be 0xFFF1 and not be interpreted as a signed number so that's why I initially thought of it like that. Also, in DeathBasket's Boss Rush hack, he would use a cutscene value of 0xFFEC to disable playing a cutscene. Link to comment Share on other sites More sharing options...
mzxrules Posted April 9, 2014 Share Posted April 9, 2014 yea a lot of values "work" when it comes to not playing a cutscene. The default value the variable sits at is actually FFEF. I'm sort of curious as to why it's value range is what it is. Link to comment Share on other sites More sharing options...
Jason777 Posted March 3, 2015 Author Share Posted March 3, 2015 EDIT: New patch that allows cutscene values to specified in the Z-rotation: http://www.cs.utexas.edu/~jason777/Modding/Zelda%2064/warp_exit/warp_exit_v2.ppf Notes and relevant data have been updated: http://www.cs.utexas.edu/~jason777/Modding/Zelda%2064/warp_exit/ I just exchanged some messages with Airikita briefly, and we extended the hack to where it reads cutscene values from the Z-rotation. Apply the original patch and then write these next changes to the ROM: @ 0x00D531D4 in ROM write... 10 00 00 2C@ 0x00D531EC in ROM write... 10 00 00 26@ 0x00D53244 in ROM write... 10 00 00 10@ 0x00D5325C in ROM write... 10 00 00 0A@ 0x00D53264 in ROM write... 86 2F 00 B8 14 22 00 03 86 38 00 B6 24 18 01 0E 24 0F 00 00 3C 01 80 22 A4 38 3E 3A 3C 01 80 16 A4 2F FA 72 3C 04 80 9A A patch will be made if you all really need it. Link to comment Share on other sites More sharing options...
Recommended Posts