Jason777 Posted April 2, 2012 Share Posted April 2, 2012 This is basically a place that I'll go to to post ideas and or little bits of information that I'll probably be interested in using or creating in the near future. Basically, I usually forget about a lot of mildly good ideas and this is to combat that problem For the moment, I have one particular thing in which I'm interested and currently creating... a new item which will yet again be paired with a regular item and equipped to the D-Pad. Basically what it does is it is paired with the Mirror Shield. While the shield is equipped, if you press D-pad up once, it'll freeze all enemies within a 20 unit radius, mirror shield is replaced with a new shield, redead scream sound is played, and your magic slowly decreases. You press D-pad up again to unfreeze all actors and to get the mirror shield back to normal. Medusa's Glare Basic Routine Breakdown: if shield equipped is Mirror Shield... if there is Magic... if Magic Decrease Flag is not set (0x00) if D-Pad Up is Pressed... Swap mirror shield display list with Medusa's Glare display list Play Redead Scream Sound Freeze or Stun all actors within a 20 unit radius Set Magic Decrease Flag (0x01) return else if Magic Decrease Flag is set (0x01) if D-Pad Up is Pressed... Swap Medusa's Glare display list with mirror shield display list Unfreeze or "unstun" all actors currently in a frozen/stunned state Clear Magic Decrease Flag (0x00) return Decrease Magic Amount return else return else if there is no Magic... if Magic Decrease Flag is set (0x01) Swap Medusa's Glare display list with mirror shield display list Unfreeze or "unstun" all actors currently in a frozen/stunned state Clear Magic Decrease Flag (0x00) return else return RAM Addresses to work with: 80211174 -- Make any Non-Zero value to "freeze" all actors 8015E693 -- Magic amount 8001CE60 - 80157D90 -- code.zdata (to fix some display list pointers) 80223E0B -- Number of map actors (nulled after actors are spawned iirc) 80223E18 -- Pointer to map actor list with position/rotation of stuff RAM Addresses/Functions that may need to be found are... PlaySound Function -- to play Redead Scream Shield Equipped Address -- to find out which shield is equipped Stun Flag in actor -- In case the freeze all actors address doesn't work out as planned Variables: Magic Decrease Flag ...And I'll have to import a custom display list into object_link_boy So what this means is that I'll have to distribute this via patch if ever completed. 1 Link to comment Share on other sites More sharing options...
Guest sakura Posted April 2, 2012 Share Posted April 2, 2012 Very neat idea, best of luck with implementing it Link to comment Share on other sites More sharing options...
spinout Posted April 2, 2012 Share Posted April 2, 2012 0x80211174 - This address is for all actors - including link. You'll have to go about "freezing" other actors another way.0x8002F828 - this is the function that plays sounds. Breakpoint it to get the arguments.As for another way to freeze actors, I would suggest perhaps modifying the logic which executes actor code. Actors, when running, have two chunks of code which are executed: logic and visuals. Execute logic only, they will be invisible, and execute visuals only, and they will stay still. I'm not sure on the details, but whatever parses the array of double linked lists of actors (http://wiki.spinout182.com/w/Actors#Loaded_Actors see "At 0x80213C50 within RAM..." ).If needed, give me a RAM dump with a few different kinds of actors loaded and I will analyze it and provide you with an example of how it works if the article I provided isn't sufficient. Link to comment Share on other sites More sharing options...
Jason777 Posted April 2, 2012 Author Share Posted April 2, 2012 Thanks for the info, spinout, I wasn't sure how I would begin to look for the sound function other than looking an unknown/specific function call within a disassembled ReDead actor... so you saved me quite a bit of trouble there, thanks again.I'll be reading up on the documentation on loaded actors in the RAM, too.I was planning to spawn a deku nut instead of messing with the freeze all actors address but realized that deku nuts don't have the same effect on every enemy Link to comment Share on other sites More sharing options...
Jason777 Posted May 10, 2012 Author Share Posted May 10, 2012 I realized that people who might find this topic interesting might find the below quote and download to be somewhat useful. Also, you'll find some documentation on how z64-tex-ext works... Admins, be warned, there may be a few OoT Debug ROMs in there: You really are taking on quite a bit of work, soulofdeity But it will be greatly appreciated and not in vain! Alright, I just decided to throw everything in together... so basically, the download contains alot of C hacks and a few little personal notes. Disclaimer: not everything in the download works; for example, ovl_en_PZGD_mask doesn't work properly and neither does Sword_of_Sages. The folder that you are interested in is "ovl_en_example", I decided to just release it in the simplest form possible-- it only contains code that is REQUIRED to have a working custom actor (except for the two lines of code that represent the main function): http://www.mediafire.com/?x6qpj8kqsy9vzv5 NOTE: Compressed with 7-ZIP Link to comment Share on other sites More sharing options...
Jason777 Posted May 20, 2012 Author Share Posted May 20, 2012 So I realized that I never tried to code the Medusa's Glare hack mentioned earlier in the thread... Well, I took the day off and gave it a shot. It's a bit different than I imagined it and not everything I planned is in it, but it's not too bad. Little video of me showing off the way it works and some of the bugs: Changes... There is no ReDead sound. I put a BPX on the PlaySound function spinout mentioned earlier... and a break was going off every single frame and the parameters varied greatly. Perhaps another time. Instead of all type 5 actors within a certain radius freezing, I couldn't get that to work since for some reason I couldn't read the pointers to the "next" actor correctly. No display list shield swap for the Mirror Shield, you just press D-Pad Up. Since I couldn't get the audio to play, I felt like the whole point of doing this was lost Instead we have...Z-Target a certain actor. Press D-Pad Up and it freezes. Press D-Pad Up again and it unfreezes. You can only freeze one actor at a time. So don't try freezing another actor while one actor is already frozen. It'll just unfreeze. Bugs...The timer is kinda buggy/shitty so you'll find yourself pressing D-Pad Up and nothing happens every now and then. I shouldn lengthen the wait timer but I really don't care. Every now and then after freezing and unfreezing an actor, they can't harm you and/or you can't harm them. There's probably some code within that certain actor which reads if the "Logic" routine pointer is NULL and causes this effect. Download: http://www.mediafire.com/?fy63l94ld22dq(The file is called "Medusas_Glare.7z") Link to comment Share on other sites More sharing options...
Jason777 Posted July 23, 2012 Author Share Posted July 23, 2012 Alright, I have something else now... I wrote this while bored on an airplane and I still don't have any emulator to test it out on (N64iPhone can't handle this stuff), but it should work in theory. If not, well I'll give you all the information one would need (someone like DeathBasket, spinout, or sakura) to fix it! My god, assembly is a bitch compared to hacking with C. It also doesn't help that I tried to use as little registers as possible. I don't have too much experience with assembly (this hack was for practice), so I can't really spot any errors right now (damn delay slot -.-) but I'm sure someone who is more knowledgable can. Alright, I present to you a semi-complete fix for being able to use both the Bow (including the magical arrows) and the Slingshot as Young Link!: .ORG 0x801064B0 J 0x80600000 .ORG 0x80600000 LUI AT, 0x8016 # AT = 0x80160000 LW K1, 0xE664(AT) # Load word @ 0x8015E664 into K1 BNE K1, R0, CLeft # If word @ 0x8015E664 = 0x0000001, Jump to "CLeft" routine LUI A3, 0x8060 # Delay Slot; A3 will be used for Jump Returns B Exit # In case you are Adult Link, exit routine NOP CLeft: # C-Left; 0x80600018 LUI GP, 0x0002 # GP = C-Left Value LB K1, 0xE6C9(AT) # K1 = Item equipped to C-Left B Check # Unconditional branch to "Check" routine ADDIU A3, A3, 0x0025 # Delay Slot; A3 = 0x80600028 CBottom: # C-Bottom; 0x80600028 LUI GP, 0x0004 # GP = C-Bottom Value LUI AT, 0x8016 LB K1, 0xE6CA(AT) # K1 = Item equipped to C-Bottom B Check # Unconditional Branch to Check Routine ADDIU A3, A3, 0x0014 # Delay Slot; A3 = 0x8060003C CRight: # C-Right; 0x8060003C LUI GP, 0x0001 # GP = C-Right Value LUI AT, 0x8016 LB K1, 0xE6CB(AT) # K1 = Item equipped to C-Right B Check # Unconditional branch to "Check" routine ADDIU A3, A3, 0x0014 # Delay Slot; A3 = 0x80600050 Exit: # Exit; 0x80600050 MOVE GP, R0 # Clear GP MOVE AT, R0 # Clear AT ADDIU K1, R0, 0x0AAA # Restore K1 back to 0x00000AAA ADDIU A3, R0, 0x0003 # Restore A3 back to 0x00000003 JR RA ADDIU T2, R0, 0x2000 # Delay Slot; Restore T2 back to 0x00002000 Check: MOVE T2, R0 # Clear T2 for future use ADDIU AT, K1, 0xFFFD # 0xFFFFFFFD = -0x03 (Bow) BEQ AT, R0, Bow NOP ADDIU AT, K1, 0xFFFC # 0xFFFFFFFC = -0x04 (Fire Arrows) BEQ AT, R0, Fire NOP ADDIU AT, K1, 0xFFFA # 0xFFFFFFFA = -0x06 (Slingshot) BEQ AT, R0, Sling NOP ADDIU AT, K1, 0xFFF4 # 0xFFFFFFF4 = -0x0C (Ice Arrows) BEQ AT, R0, Ice NOP ADDIU AT, K1, 0xFFEE # 0xFFFFFFEE = -0x12 (Light Arrows) BEQ AT, R0, Light NOP JR A3 # Jump to next C-button check or Exit routine (address in A3) MOVE AT, R0 # Delay Slot; Clear AT register of previous value Bow: LUI K1, 0x0603 # K1 = 0x06030003 ADDIU K1, K1, 0xFE7D # 0x06030003 + 0xFFFFFE7D = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 ORI T2, T2, 0x0490 # T2 = 0x06030490 (Bow String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Button currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0002 # Delay Slot; AT = Regular Arrow Spawn (0x0002) B ClearData # Else, branch to "ClearData" routine NOP Fire: LUI K1, 0x0603 # K1 = 0x06030004 ADDIU K1, K1, 0xFE7C # 0x06030004 + 0xFFFFFE7C = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 ORI T2, T2, 0x0490 # T2 = 0x06030490 (Bow String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0003 # Delay Slot; AT = Fire Arrow Spawn (0x0003) B ClearData # Else, branch to "ClearData" routine NOP Ice: LUI K1, 0x0603 # K1 = 0x0603000C ADDIU K1, K1, 0xFE74 # 0x0603000C + 0xFFFFFE74 = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 ORI T2, T2, 0x0490 # T2 = 0x06030490 (Bow String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Button currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0004 # Delay Slot; AT = Ice Arrow Spawn (0x0004) B ClearData # Else, branch to "ClearData" routine NOP Light: LUI K1, 0x0603 # K1 = 0x06030012 ADDIU K1, K1, 0xFE6E # 0x06030012 + 0xFFFFFE6E = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 ORI T2, T2, 0x0490 # T2 = 0x06030490 (Bow String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Button currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0005 # Delay Slot; AT = Light Arrow Spawn (0x0005) B ClearData # Else, branch to "ClearData" routine NOP Sling: LUI K1, 0x0602 # K1 = 0x06020006 ADDIU K1, K1, 0x8042 # 0x06020006 + 0xFFFF8042 = 0x06018048 (Slingshot FPS) LUI T2, T2, 0x0602 # T2 = 0x06020000 ORI T2, T2, 0x21A8 # T2 = 0x060221A8 (Slingshot String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Button currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0009 # Delay Slot; AT = Deku Seed Spawn (0x0009) B ClearData # Else, branch to "ClearData" routine NOP FixDisplay: MOVE GP, R0 # Clear GP for future use LUI GP, 0x8012 # GP = 0x80120000 SW K1, 0x5F3C(GP) # Store FPS display list pointer in K1 @ 0x80125F3C SW T2, 0x6144(GP) # Store String display list pointer in T2 @ 0x80126144 LUI GP, 0x8017 # GP = 0x80170000 B ClearData # Unconditional branch to "ClearData" routine SH AT, 0x8232(GP) # Delay Slot; Store Projectile Spawn Actor variable in AT @ 0x80168232 ClearData: MOVE AT, R0 # Clear AT for future use MOVE K1, R0 # Clear K1 for future use MOVE T2, R0 # Clear T2 for future use JR A3 # Jump to next C-button check or Exit routine (address in A3) MOVE GP, R0 # Delay Slot; Clear GP for future use Notes: # 0x0602FE80 = Bow Display List # 0x06030490 = Bow String Display List # 0x06018048 = Slingshot Display List # 0x060221A8 = Slingshot String Display List # 0x80125F3C = Bow/Slingshot FPS Mode Pointer (RAM) # 0x80126144 = Bow/Slingshot String Pointer (RAM) # 0x00B9D0DC = Bow/Slingshot FPS Mode Pointer (ROM) # 0x00B9D2E4 = Bow/Slingshot String Pointer (ROM) # 0x8015E664 (word) = Link Age? # 0x8015E667 (byte or bit) = Young Link Flag (0x01 for Young; 0x00 for Adult) # 0x8015E6C9 = Left C-Button Item # 0x8015E6CA - Bottom C-Button Item # 0x8015E6CB - Right C-Button Item # 0x03 = Bow # 0x04 = Fire Arrows # 0x06 = Slingshot # 0x0C = Ice Arrows # 0x12 = Light Arrows # 0x00C0323A = Projectile Spawn Actor (ROM) # 0x80168232 = Projectile Spawn Actor (RAM) # 0x0009 = Deku Seeds # 0x0002 = Regular Arrows # 0x0003 = Fire Arrows # 0x0004 = Ice Arrows # 0x0005 = Light Arrows # 0x8015E6EF = Arrow Amount # 0x8015E6F2 = Deku Seed Amount # 0x80166AF0 = Player 1 # 0x0001 = C-Right # 0x0002 = C- Left # 0x0004 = C-Bottom # Hook @ 0x801064B0 = JR RA # Free Registers = AT, S4, S5, S6, S7, S8, GP # Non-Changing Registers = A0, A3, T0, T1, T2, S1, S3, K0, K1, RA # A0 = 0x80146020 # A3 = 0x00000003 # T0 = 0x80002000 # T1 = 0x80001FF0 # T2 = 0x00002000 # S1 = 0x801666A0 # S3 = 0x80166668 # K0 = 0xA430000C # K1 = 0x00000AAA # RA = 0x800C8D7C # Registers in Use = AT, GP, K1, A3, T2 More notes concerning how to change the arrow spawn variable before the ActorSpawn function is called...: Some stuff from DeathBasket: -------------------------------------------------------------------------------------------------------------- I've been looking into this further and it turns out that there seems to be an additional actor spawning function, or at least that I didn't know about. I just realised from actually looking at the function that it actually appears to set up the data for the actor spawn function before jumping to it. 80032458 = address of function a0 = 80213C44 a1 = RAM address of 'parent' actor a2 = 80212020 a3 = actor number 0x2A(SP) = variable x,y and z positions should also be stored at some offset close to the variable. Spawning arrows with the 'beta' variables just makes them look like fire arrows, but I haven't tested their effects on enemies. At the moment I'm just setting an execute breakpoint at 80032458 and changing the variable's value in memory. The variable seems to be determined by: func_80834380: lui t0,0x8016 addiu t0,t0,-6560 lw t6,4(t0) li t7,3 li t4,6 bne t6,$zero,$L000141 li t5,9 .. from: http://spinout182.com/mqd/ovl_player_actor.S Which is a check to see if Link is an adult (uses variable 0009 if he isn't, if he is it presumably goes on to determine which type of arrows are equipped). The variable is in register t5. Relevant to the topic: You can make the slingshot shoot arrows with this information but it won't look good unless you give Young Link a bow. To make the slingshot shoot arrows, go to 0xC0323A in ROM and change 0009 to 0002. Arrows won't work properly as an adult anymore though, so you'll need a bit of assembly hacking to get around that. -------------------------------------------------------------------------------------------------------------- Some stuff from me (Jason777): -------------------------------------------------------------------------------------------------------------- Looking at the routine at 0x80032458, we see how it sets up data to call the actor spawn function for arrow spawning... 0x80032470 : LH T9, 0x005A (SP) # And later we see... # 0x80031F50 = ActorSpawn function # SP + 0x0024 = Actor variable argument 0x800324A4 : JAL 0x80031F50 0x800324A8 : SW T9, 0x0024(SP) # After putting a BPX on 0x80032470... # SP = 801681D8 # T9 = halfword @ 0x80168232 (0x801681D8 + 0x005A) # T9 = Arrow variable 0x80032470: LH T9, 0x005A (SP) # So, I went to 0x80168232 and sure enough, the arrow variable was stored there... The only problem is... 0x80168232 only contains the arrow's variable whenever you're about to shoot it. I think I have to fix the hook... -------------------------------------------------------------------------------------------------------------- I can see some problems arrising from my hook, seeing as how the arrow actor variable at 0x80168232 is only present as you're about to shoot the arrow and before the actor spawn function is called. However, the hook I have right now executes my hack every frame so it may not be a problem... I currently don't have an emulator to test this hack out on right now nor do I have a way to assemble this into a GS code. Also, as you can see, in order to adapt this hack to work with your own display list ports, you would have to change a few LUI/ADDIU or LUI/ORI pairs in the hack since I use these offsets as my display lists: # 0x0602FE80 = Bow Display List # 0x06030490 = Bow String Display List # 0x06018048 = Slingshot Display List # 0x060221A8 = Slingshot String Display List ^^ Those instructions I am referring to, are in the last few labels: Bow, Fire, Ice, Light, Sling. Things that I haven't put into the hack yet, that should be noted: Firing an arrow decreases the deku seed amount. Firing a magical arrow doesn't decrease the magic amount. ENJOY Also, can anybody give me some pointers on writing cleaner assembly? I don't quite get how the delay slot is used (if the condition isn't met, doesn't skip the instructions in the delay slot?) and if I can use the JR opcode the way I am using it in the hack (I use "JR A3" instead of the usual "JR RA"). Link to comment Share on other sites More sharing options...
DeathBasket Posted July 23, 2012 Share Posted July 23, 2012 I don't quite get how the delay slot is used (if the condition isn't met, doesn't skip the instructions in the delay slot?) and if I can use the JR opcode the way I am using it in the hack (I use "JR A3" instead of the usual "JR RA"). Whether or not the instruction in the delay slot executes depends on the branch instruction. Branch instructions ending in l (ex. beql) will only execute what is in the delay slot if the condition is met, branch instructions not ending in l will always execute what is in the delay slot.You can use the jr instruction like that, yes. Also, as you can see, in order to adapt this hack to work with your own display list ports, you would have to change a few LUI/ADDIU or LUI/ORI pairs in the hack since I use these offsets as my display lists: # 0x0602FE80 = Bow Display List # 0x06030490 = Bow String Display List # 0x06018048 = Slingshot Display List # 0x060221A8 = Slingshot String Display List ^^ Those instructions I am referring to, are in the last few labels: Bow, Fire, Ice, Light, Sling. You could always do something like: #define bow_dl 0x0602FE80 ... li t0, bow_dl Then if somebody had the code, they'd only need to change that line to adapt it for their own purposes. A few tips: Since you added your code at the end of a function that doesn't seem to be returning anything, you should be able to use all v, a, t and f registers without messing anything up. t registers can always be used freely if you are putting code at the start or end of a function. You also don't need to set registers to zero before using them unless they needed to be zero in the first place. ex. MOVE GP, R0 # Clear GP for future use LUI GP, 0x8012 # GP = 0x80120000You only needed the second line since gp would be set to 0x80120000 regardless of what it already was. Link to comment Share on other sites More sharing options...
Jason777 Posted July 23, 2012 Author Share Posted July 23, 2012 Whether or not the instruction in the delay slot executes depends on the branch instruction. Branch instructions ending in l (ex. beql) will only execute what is in the delay slot if the condition is met, branch instructions not ending in l will always execute what is in the delay slot. You can use the jr instruction like that, yes. Thanks for clearing that up, it was bothering me whenever I came to the situation where I could reduce the amount of code by putting an instruction in the delay slot and not knowing if that code would execute whether or not the condition was met. You could always do something like: #define bow_dl 0x0602FE80 ... li t0, bow_dl Then if somebody had the code, they'd only need to change that line to adapt it for their own purposes. I was thinking about that, and decided to try to not use any psuedo-opcodes like "la" and "li". However, I did use the "b" opcode because I was lazy They are psuedo-opcodes, yes? A few tips: Since you added your code at the end of a function that doesn't seem to be returning anything, you should be able to use all v, a, t and f registers without messing anything up. t registers can always be used freely if you are putting code at the start or end of a function. You also don't need to set registers to zero before using them unless they needed to be zero in the first place. ex. MOVE GP, R0 # Clear GP for future use LUI GP, 0x8012 # GP = 0x80120000You only needed the second line since gp would be set to 0x80120000 regardless of what it already was. So you're saying that registers will clear their value when a branch occurs? The reason I thought I had to clear the GP value before moving on is because I assumed that it would preserve its previous value across a branch. This is what I mean: # I am assuming that the button value GP has is C-left (0x0002) Bow: LUI K1, 0x0603 # K1 = 0x06030003 (Before we got to this area of code, K1 was equal to 0x03) ADDIU K1, K1, 0xFE7D # 0x06030003 + 0xFFFFFE7D = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 ORI T2, T2, 0x0490 # T2 = 0x06030490 (Bow String) LUI AT, 0x8016 LW AT, 0x6AF0(AT) # AT = Button currently pressed AND AT, AT, GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay (now AT and GP equal 0x00020000) ADDIU AT, R0, 0x0002 # Delay Slot; AT = Regular Arrow Spawn (0x0002) B ClearData # Else, branch to "ClearData" routine (^^ AT = 0x0002 and GP = 0x00020000) NOP ... # Assuming the button was pressed... # GP = 0x00020000 # AT = 0x00000002 FixDisplay: MOVE GP, R0 # Clear GP for future use (or else the next line may change.... wait, shit -.-) # ^^ I just realized that GP had an the 0x0002 in the upper immediate; this means the next line would overwrite that value LUI GP, 0x8012 # GP = 0x80120000 SW K1, 0x5F3C(GP) # Store FPS display list pointer in K1 @ 0x80125F3C SW T2, 0x6144(GP) # Store String display list pointer in T2 @ 0x80126144 LUI GP, 0x8017 # GP = 0x80170000 B ClearData # Unconditional branch to "ClearData" routine SH AT, 0x8232(GP) # Delay Slot; Store Projectile Spawn Actor variable in AT @ 0x80168232 (AT = 0x0002) ... # Assuming the button wasn't pressed... # GP = 0x00020000 # AT = 0x00000002 ClearData: MOVE AT, R0 # Clear AT for future use MOVE K1, R0 # Clear K1 for future use MOVE T2, R0 # Clear T2 for future use JR A3 # Jump to next C-button check or Exit routine (address in A3) MOVE GP, R0 # Delay Slot; Clear GP for future use ^^ If what all your saying is true (and I hope it is), I can cut the length of the code quite significantly o: Thanks for the help and tips. Hmmm... I'll be studying over this. Link to comment Share on other sites More sharing options...
DeathBasket Posted July 23, 2012 Share Posted July 23, 2012 So you're saying that registers will clear their value when a branch occurs? The reason I thought I had to clear the GP value before moving on is because I assumed that it would preserve its previous value across a branch. No. Registers never clear themselves. What I am saying is that you don't need to initialise a register before putting a number in it. A register can have any value in it but if you use an instruction like lui, li, la, etc. it's the same as saying register = constant, so there is no need to clear the register first. ex. lw a0, 0 ($sp) //a0 here could be anything (a0 = *sp) li a0, 255 //now a0 = 255, since this is the same as addiu a0, $zero, 255 (a0 = 0 + 255) lui a0, 0x8016 //now a0 = 0x80160000 I guess what I'm trying to say is that these instructions will ignore what was already in the register and just set it equal to whatever value you gave them, which is what you seem to be confused about. There is never any need to set it to zero before putting another number in it. LUI K1, 0x0603 # K1 = 0x06030003 (Before we got to this area of code, K1 was equal to 0x03) ADDIU K1, K1, 0xFE7D # 0x06030003 + 0xFFFFFE7D = 0x0602FE80 (Bow FPS) Now you should see that this piece of code would give k1 = 0x0602FE7D, not k1 = 0x0602FE80, since the first line set k1 to be 0x06030000. Also, pseudo-instructions are useful because they make writing the code easier and quicker so there's not really any point in avoiding them. move is a pseudo-instruction too, by the way (r1 = r2 | 0 / or r1,r2,$zero). Link to comment Share on other sites More sharing options...
Jason777 Posted July 23, 2012 Author Share Posted July 23, 2012 No. Registers never clear themselves. What I am saying is that you don't need to initialise a register before putting a number in it. A register can have any value in it but if you use an instruction like lui, li, la, etc. it's the same as saying register = constant, so there is no need to clear the register first. ex. lw a0, 0 ($sp) //a0 here could be anything (a0 = *sp) li a0, 255 //now a0 = 255, since this is the same as addiu a0, $zero, 255 (a0 = 0 + 255) lui a0, 0x8016 //now a0 = 0x80160000 I guess what I'm trying to say is that these instructions will ignore what was already in the register and just set it equal to whatever value you gave them, which is what you seem to be confused about. There is never any need to set it to zero before putting another number in it. LUI K1, 0x0603 # K1 = 0x06030003 (Before we got to this area of code, K1 was equal to 0x03) ADDIU K1, K1, 0xFE7D # 0x06030003 + 0xFFFFFE7D = 0x0602FE80 (Bow FPS) Now you should see that this piece of code would give k1 = 0x0602FE7D, not k1 = 0x0602FE80, since the first line set k1 to be 0x06030000. Also, pseudo-instructions are useful because they make writing the code easier and quicker so there's not really any point in avoiding them. move is a pseudo-instruction too, by the way (r1 = r2 | 0 / or r1,r2,$zero). Awesome! I can reduce the number of lines of code by a shitload now Thanks again. Link to comment Share on other sites More sharing options...
Jason777 Posted July 24, 2012 Author Share Posted July 24, 2012 UPDATE: Alright, I've hopefully fixed the hack and will assemble it into a GS code later (did you know that the iPhone has GCC tools on it?). Of course, there's still a few areas where I could shorten the code, but I really don't feel like it now...: .ORG 0x801064B0 J 0x80600000 .ORG 0x80600000 LUI AT, 0x8016 # AT = 0x80160000 LW K1, 0xE664(AT) # Load word @ 0x8015E664 into K1 BNE K1, R0, CLeft # If word @ 0x8015E664 = 0x0000001, Jump to "CLeft" routine LUI A3, 0x8060 # Delay Slot; A3 will be used for Jump Returns B Exit # In case you are Adult Link, exit routine NOP CLeft: # C-Left; 0x80600018 LUI GP, 0x0002 # GP = C-Left Value LB K1, 0xE6C9(AT) # K1 = Item equipped to C-Left B Check # Unconditional branch to "Check" routine ADDIU A3, 0x0025 # Delay Slot; A3 = 0x80600028 CBottom: # C-Bottom; 0x80600028 LUI GP, 0x0004 # GP = C-Bottom Value LUI AT, 0x8016 # AT = 0x80160000 LB K1, 0xE6CA(AT) # K1 = Item equipped to C-Bottom B Check # Unconditional Branch to Check Routine ADDIU A3, 0x0014 # Delay Slot; A3 = 0x8060003C CRight: # C-Right; 0x8060003C LUI GP, 0x0001 # GP = C-Right Value LUI AT, 0x8016 # AT = 0x80160000 LB K1, 0xE6CB(AT) # K1 = Item equipped to C-Right B Check # Unconditional branch to "Check" routine ADDIU A3, 0x0014 # Delay Slot; A3 = 0x80600050 Exit: # Exit; 0x80600050 MOVE GP, R0 # Clear GP MOVE AT, R0 # Clear AT ADDIU K1, R0, 0x0AAA # Restore K1 back to 0x00000AAA ADDIU A3, R0, 0x0003 # Restore A3 back to 0x00000003 JR RA ADDIU T2, R0, 0x2000 # Delay Slot; Restore T2 back to 0x00002000 Check: ADDIU AT, K1, 0xFFFD # 0xFFFFFFFD = -0x03 () BEQ AT, R0, Arrow NOP ADDIU AT, K1, 0xFFFC # 0xFFFFFFFC = -0x04 (Fire Arrows) BEQ AT, R0, Fire NOP ADDIU AT, K1, 0xFFFA # 0xFFFFFFFA = -0x06 (Slingshot) BEQ AT, R0, Sling NOP ADDIU AT, K1, 0xFFF4 # 0xFFFFFFF4 = -0x0C (Ice Arrows) BEQ AT, R0, Ice NOP ADDIU AT, K1, 0xFFEE # 0xFFFFFFEE = -0x12 (Light Arrows) BEQ AT, R0, Light NOP JR A3 # Jump to next C-button check or Exit routine (address in A3) NOP Arrow: LUI AT, 0x8016 # AT = 0x80160000 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP # AT &= GP BNE AT, R0, BowSetup # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0002 # Delay Slot; AT = Regular Arrow Spawn (0x0002) JR A3 # Else, jump to next C-button check or Exit routine (address in A3) NOP Fire: LUI AT, 0x8016 # AT = 0x80160000 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP # AT &= GP BNE AT, R0, BowSetup # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0003 # Delay Slot; AT = Fire Arrow Spawn (0x0003) JR A3 # Else, jump to next C-button check or Exit routine (address in A3) NOP Ice: LUI AT, 0x8016 # AT = 0x80160000 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP # AT &= GP BNE AT, R0, BowSetup # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0004 # Delay Slot; AT = Ice Arrow Spawn (0x0004) JR A3 # Else, jump to next C-button check or Exit routine (address in A3) NOP Light: LUI AT, 0x8016 # AT = 0x80160000 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP # AT &= GP BNE AT, R0, BowSetup # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0005 # Delay Slot; AT = Light Arrow Spawn (0x0005) JR A3 # Else, jump to next C-button check or Exit routine (address in A3) NOP Sling: LUI K1, 0x0602 # K1 = 0x06020000 ADDIU K1, K1, 0x8048 # 0x06020000 + 0xFFFF8048 = 0x06018048 (Slingshot FPS) LUI T2, T2, 0x0602 # T2 = 0x06020000 ORI T2, T2, 0x21A8 # T2 = 0x060221A8 (Slingshot String) LUI AT, 0x8016 # AT = 0x80160000 LW AT, 0x6AF0(AT) # AT = Buttons currently pressed AND AT, AT, GP # AT &= GP BNE AT, R0, FixDisplay # If button value stored in GP is pressed, branch to FixDisplay ADDIU AT, R0, 0x0009 # Delay Slot; AT = Deku Seed Spawn (0x0009) JR A3 # Else, jump to next C-button check or Exit routine (address in A3) NOP BowSetup: LUI K1, 0x0603 # K1 = 0x06030000 ADDIU K1, K1, 0xFE80 # 0x06030000 + 0xFFFFFE80 = 0x0602FE80 (Bow FPS) LUI T2, T2, 0x0603 # T2 = 0x06030000 B FixDisplay # Unconditional branch to "FixDisplay" routine ORI T2, T2, 0x0490 # Delay Slot; T2 = 0x06030490 (Bow String) FixDisplay: LUI GP, 0x8012 # GP = 0x80120000 SW K1, 0x5F3C(GP) # Store FPS display list pointer in K1 @ 0x80125F3C SW T2, 0x6144(GP) # Store String display list pointer in T2 @ 0x80126144 LUI GP, 0x8017 # GP = 0x80170000 JR A3 # Jump to next C-button check or Exit routine (address in A3) SH AT, 0x8232(GP) # Delay Slot; Store Projectile Spawn Actor variable in AT @ 0x80168232 EDIT: Gah, with the syntax that mips-as uses, it'll take a while before I turn this into a GS code -.- Link to comment Share on other sites More sharing options...
KamAlsh Posted July 26, 2012 Share Posted July 26, 2012 Ugh, coding makes my brain hurt, mainly because my poor brain makes no effort to understand it or try to learn it. Link to comment Share on other sites More sharing options...
JDYoungLink1 Posted July 27, 2012 Share Posted July 27, 2012 Ugh, coding makes my brain hurt, mainly because my poor brain makes no effort to understand it or try to learn it. I don't understand it either, I can't write in code yet. So don't think your the only one . Link to comment Share on other sites More sharing options...
Recommended Posts