john_smith_account Posted May 26, 2013 Share Posted May 26, 2013 *REMOVED* 2 Link to comment Share on other sites More sharing options...
0 Airikita Posted June 10, 2013 Share Posted June 10, 2013 Kinda a long shot, but you might see if you can find anything in the code for the Beamos that makes it aim at link. Use that as a reference. You know, I was just thinking about that this morning... You also have 3 planes to work with... unlike 2D which only has one. Your (X,Y), (X,Z) and (Z,Y). That should be useful to know how many angles you're dealing with. When I was messing in RAM in my "Link Rotations" video, I saw a good list of degree values, and I think 0x8000 is 360 degrees. Link to comment Share on other sites More sharing options...
0 DeathBasket Posted June 11, 2013 Share Posted June 11, 2013 There's at least one inverse trigonometric function (arctan I think) there but you don't even need to use it (directly) to get the actor to face Link. There is a function that will return the rotation value you need for any actor to face another actor, 80078068. Its arguments are: a0 = (pointer to current actor + 0x24), a1 = (pointer to target actor + 0x38). Take the return value of that function and store it to 0xB6 in your actor's RAM structure and it will face the target actor at all times. If you want more detail on how it works, the game basically gets a direction vector from the x and z positions of the actors and works out the angle using the ratio and size of the two components and the direction of the vector. The function it uses to do that doesn't figure out the angle directly, it just converts the (magnitude of the) ratio into an index it uses to look up a result from a table (8012D310), which it then adds or subtracts numbers from to get the right direction (inverse trigonometric functions aren't 1 to 1). 3 Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 11, 2013 Share Posted June 11, 2013 I love you, DeathBasket. Well, now that I have aiming working correctly, I have encountered one last problem: collision. While implementing function calls to initialize collision (DeathBasket, you sent me a PM on this a while ago), nOVL simply crashes when I try converting the ELF to an overlay. There are no error codes, etc; nOVL just "stops responding". Link to comment Share on other sites More sharing options...
0 Airikita Posted June 11, 2013 Share Posted June 11, 2013 I would love to have the modified actor Jason777 when it's ready. I have an idea where I will be using it. I think I will make it a code stub, or expand another actor to work with it. I don't want it to be made into a totem pole, I want the raw code if it works. Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 13, 2013 Share Posted June 13, 2013 Honestly, I think I may have to straight-up write the actor in assembly; I'm experiencing issues with both nOVL and GCC's MIPS C compiler that I think can be avoided if I just choose not to write it in C. I think that in the end it may be an issue with nOVL and relocation data so I don't know if I'll be able to fix it entirely. Maybe there's something I'm not doing correctly here... Any of you who are experienced in writing actors in C might be able to find somewhere where I messed up. There are a lot of commented out things that I was mainly using for testing purposes. For some reason whenever I try to save the pointer that is returned by func_80032458, spawning no longer works correctly. There's also the issue of nOVL crashing whenever I try updating collision sphere placement... #include <zelda64.h>#include <actor.h>#include <mips.h>/* ----- Actor-specific values ----- */#define EXAMPLE_ACT 0x0082 /* Actor 0x0082 is the BETA vase entry so it can be used for testing purposes */#define EXAMPLE_OBJ 0x0086 /* Object 0x0086 is the BETA vase entry so it can be used for testing purposes */#define EN_AROW_TRAP_ACT 0x0081 /* En_Arow_Trap's actor # *//* ----- General in-game functions which set up an actor ----- */extern void func_8002d62c(struct z64_actor_t *, u32); /* Sets scale */extern void func_8002b1e0(void *, u32, void *, u32); /* I don't know what this function does yet */extern void func_80035260(void *, u32); /* Sets display list to render */extern void func_8005dc4c(void *, void *, void *); /* Sets where to draw collision */extern void func_8005c364(void *, void *); /* Helps initialize collision */ extern void func_8005c4ac(void *, void *, struct z64_actor_t *, u32 *); /* Helps initialize collision */extern u16 func_80078068(void *, void*); /* Returns rotation value to face a specified actor */extern struct z64_actor_t * func_80032458(void *, void *, void *, u16, f32, f32, f32, u16, u16, u16, u16); /* ActorSpawn but for different unknown purposes... possibly for scaling *///extern u32 func_80031f50(u32, u32, u16, f32, f32, f32, u16, u16, u16, u16); /* Regular ActorSpawn */extern char obj_8002B5EC; /* I'm guessing this is where object 0x0086 is always loaded into the RAM? *//* ----- These are the actual user-defined functions which vary from actor to actor ----- */extern void example_init(struct z64_actor_t * a, void * o); /* Initialization */ extern void example_null(struct z64_actor_t * a, void * o); /* NULL */extern void example_main(struct z64_actor_t * a, void * o); /* Main AI */extern void example_render(struct z64_actor_t * a, void * o); /* Model Rendering *//* ----- Actor header ----- */MK_AHEAD( En_Arow_Trap_Util, /* Actor Name: Masks */ EXAMPLE_ACT, /* Actor #: 0x0082 */ 6, /* Actor Type: Item */ 0, /* Actor Status... Whatever the hell that is */ 0x10, /* Unknown */ EXAMPLE_OBJ, /* Object #: 0x0086 */ 0x14C, /* Unknown */ example_init, /* Address of Initialization Function */ example_null, /* Address of NULL Function */ example_main, /* Address of Main AI Function */ example_render /* Address of Render/Display Function */);u32 Collision[] = {0x0a000039, 0x20010000, 0, 0, 0, 0, 0, 0x00000100, 0x00140040, 0, 0};struct z64_actor_t * En_Arow_Trap;/* ----- Initialization/Constructor function ----- */void example_init(struct z64_actor_t * a, void * o){ /* Set actor scale of ovl_en_example's object (IEEE 754 float) */ func_8002d62c(a, 0x3C23D70A); /* Set spawn XYZ coordinates to current XYZ coordinates? */ //a->coords_3 = a->coords_2; /* Allocate actor and its object? I really don't know */ //func_8002b1e0(AADDR(a, 0x00B4), 0, &obj_8002B5EC, 0x40C00000); /* Set up collision */ //func_8005c364(o, AADDR(a, 0x194)); //func_8005c4ac(o, AADDR(a, 0x194), a, Collision); /* Spawn En_Arow_Trap at current XYZ coordinates and Y rotation... I was using the bomb for testing purposes */ func_80032458((void*)(0x80213C44), AADDR(a, 0x0), o, 0x0010, AVAL(a, f32, 0x24), AVAL(a, f32, 0x28), AVAL(a, f32, 0x2C), 0, AVAL(a, u16, 0xB6), 0, 0xFFFF); //En_Arow_Trap = func_80032458((void*)(0x80213C44), a, (void*)(0x80212020), 0x0081, AVAL(a, f32, 0x24), AVAL(a, f32, 0x28), AVAL(a, f32, 0x2C), 0, AVAL(a, u16, 0xB6), 0, 0xFFFF); //func_80031f50(0x80213C44, 0x80212020, 0x0010, AVAL(a, f32, 0x24), AVAL(a, f32, 0x28), AVAL(a, f32, 0x2C), 0, 0, 0, 0xFFFF);}/* ----- NULL function ----- */void example_null(struct z64_actor_t * a, void * o){ /* NULL function: for some reason it's necessary to have */ return;}/* ----- Rendering/Display function ----- */void example_render(struct z64_actor_t * a, void * o){ /* BETA Vase model */ func_80035260(o, 0x06000000); /* Update collision sphere */ /* AVAL(a, u16, 0x1DA) = (u16)AVAL(a, f32, 0x24); AVAL(a, u16, 0x1DC) = (u16)AVAL(a, f32, 0x28); AVAL(a, u16, 0x1DE) = (u16)AVAL(a, f32, 0x2C); func_8005dc4c(o, (void*)(0x80212020 + 0x11E60), AADDR(a, 0x194)); */}/* ----- Main AI function ----- */void example_main(struct z64_actor_t * a, void * o){ struct z64_actor_t * Link = (void*)LINK; //a->coords_2 = Link->coords_2; // This works... // Incorrect usage of pointers... //(*(f32*)(a + 0x24)) = (*(f32*)(Link + 0x24)); // This doesn't... //(*(f32*)(a + 0x28)) = (*(f32*)(Link + 0x28)); // Or this... //(*(f32*)(a + 0x2C)) = (*(f32*)(Link + 0x2C)); // Or this... // Ah! I wasn't using pointers correctly //AVAL(a, f32, 0x24) = AVAL(Link, f32, 0x24); // Works! //AVAL(a, f32, 0x28) = AVAL(Link, f32, 0x28) + 50.0f; // And this! //AVAL(a, f32, 0x2C) = AVAL(Link, f32, 0x2C); // And this! /* Copy Link's rotation... */ //AVAL(a, u16, 0xB4) = AVAL(Link, u16, 0xB4); //AVAL(a, u16, 0xB6) = AVAL(Link, u16, 0xB6); //AVAL(a, u16, 0xB8) = AVAL(Link, u16, 0xB8); /* Have actor face Link... */ AVAL(a, u16, 0xB6) = func_80078068(AADDR(a, 0x24), AADDR(Link, 0x38)); //AVAL(En_Arow_Trap, u16, 0xB6) = AVAL(a, u16, 0xB6); } This is where it fucks up: Here: // Simply uncommenting this line of code causes spawning to mess up and Link can't shoot arrows or pull out bombs, etc.En_Arow_Trap = func_80032458((void*)(0x80213C44), a, (void*)(0x80212020), 0x0081, AVAL(a, f32, 0x24), AVAL(a, f32, 0x28), AVAL(a, f32, 0x2C), 0, AVAL(a, u16, 0xB6), 0, 0xFFFF);And here: // nOVL just crashes.../* Update collision sphere */ AVAL(a, u16, 0x1DA) = (u16)AVAL(a, f32, 0x24); AVAL(a, u16, 0x1DC) = (u16)AVAL(a, f32, 0x28); AVAL(a, u16, 0x1DE) = (u16)AVAL(a, f32, 0x2C); func_8005dc4c(o, (void*)(0x80212020 + 0x11E60), AADDR(a, 0x194));} Here are macros that one may need to know: /* Get a value of arbitrary type from any address in the actor *//* Broken?#define AVAL(a,t,o) ( *((t)((u8*)(a) + (o))) )*//* Fixed? I wasn't sure if the "t" value was on purpose */#define AVAL(a,t,o) ( *((t*)((u8*)(a) + (o))) )/* Get the address */#define AADDR(a,o) ( (void*)((u8*)(a)+(o)) ) ... And here's the modified en_arow_trap actor with its timer removed (for those who care): #include "mips.h" .set noreorder .set noat .text# Entry point: 0x809B37D0## NAME VSTART VEND SIZE# .text 0x809B37D0 0x809B38D0 256# .data 0x809B38D0 0x809B38F0 32# .rodata 0x809B38F0 0x809B38F0 0# .bss 0x809B38F0 0x809B38F0 0data_809B37D0: addiu $sp,$sp,-24 // make space on stack sw a1,28($sp) // save global context sw $ra,20($sp) // save return address lui a1,0x3c23 ori a1,a1,0xd70a // A1 = 0.01f jal set_actor_size sw a0,24($sp) // save RAM actor pointer lw a0,24($sp) // restore RAM actor pointer li t6,80 // T6 = 80 (0x50) lw t8,36(a0) // T8 = Actor X position lw t7,40(a0) // T7 = Actor Y position sw $zero,332(a0) // AVAL(a, u32, 0x14C) = NULL sw t8,56(a0) // AVAL(a, u32, 0x38) = Actor X position lw t8,44(a0) // T8 = Actor Z position sw t6,336(a0) // AVAL(a, u32, 0x150) = 80 sw t7,60(a0) // AVAL(a, u32, 0x3C) = Actor Y position sw t8,64(a0) // AVAL(a, u32, 0x40) = Actor Z position lw $ra,20($sp) // restore return address addiu $sp,$sp,24 // fix stack jr $ra // return nop // nothingdata_809B3824: sw a0,0($sp) // save actor pointer? It's an unusal place to save on the stack... jr $ra // return sw a1,4($sp) // save global context? It's an unusal place to save on the stack...data_809B3830: addiu $sp,$sp,-56 // make space on stack sw $ra,52($sp) // save return address sw s0,48($sp) // save S0 lui $at,0x43c8 // AT = 400.0f mtc1 $at,$f4 // F4 = 400.0f lwc1 $f6,144(a0) // F6 = AVAL(a, f32, 0x90); or s0,a0,$zero // S0 = RAM actor pointer/* This right here is probably the proximity check Airikita was talking about */ c.le.s $f6,$f4 // (F6 <= F4) ? FP = 1 : FP = 0 nop // nothing bc1fl $L000000 // if (FP == 0) goto L000000 lw $ra,52($sp) // { restore return address } lw t6,336(a0) // T6 = AVAL (a, u32, 0x150) addiu t7,t6,-1 // T7 = T6 - 1 /* Hack starts here... removing timer */ /* bne t7,$zero,$L000001 // if (T7 != 0) goto L000001 */ sw t7,336(a0) // Delay Slot: AVAL(a, u32, 0x150) = T7 lwc1 $f8,40(s0) // F8 = Actor Y position lw a3,36(s0) // A3 = Actor X position li t2,-1 // T2 = 0xFFFF swc1 $f8,16($sp) // SP + 0x10 = Y position lwc1 $f10,44(s0) // F10 = Actor Z position addiu a0,a1,7204 // A1 = 80213C44 li a2,22 // A2 = 22 (0x16) swc1 $f10,20($sp) // SP + 0x14 = Z position lh t9,180(s0) // T9 = Actor X rotation sw t9,24($sp) // SP + 0x18 = X rotation lh t0,182(s0) // T0 = Actor Y rotation sw t0,28($sp) // SP + 0x1C = Y rotation lh t1,184(s0) // T1 = Actor Z rotation sw t2,36($sp) // SP + 0x24 = Variable jal ActorSpawn // ActorSpawn(); sw t1,32($sp) // Delay Slot: SP + 0x20 = Z rotation li t3,80 // T3 = 80 (0x50) sw t3,336(s0) // AVAL(a, u32, 0x150) = 80$L000001: lw $ra,52($sp) // restore return address$L000000: lw s0,48($sp) // restore addiu $sp,$sp,56 // fix stack jr $ra // return nop // nothing nop // nothing nop // nothing .section .data .byte 0x00 .byte 0x81 .byte 0x06 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x10 .byte 0x00 .byte 0x01 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x01 .byte 0x54 .word data_809B37D0 // Initialization .word data_809B3824 // ? -- It only saves A0 and A1 at strange places on the stack .word data_809B3830 // MAIN .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x00# 0x809B38F0 .bss Link to comment Share on other sites More sharing options...
0 john_smith_account Posted June 13, 2013 Author Share Posted June 13, 2013 Any luck with 0024 0040 ? (ovl_En_Scene_Change) Uses Jabu Jabu Obj yet? Link to comment Share on other sites More sharing options...
0 spinout Posted June 14, 2013 Share Posted June 14, 2013 Try to avoid using variables in that manner (Collision and En_Arrow_Trap) - they end up in the .data section. Instead, use the AVAL macros on whatever space isn't used in the actor panel. EDIT: Also try running nOVL with maximum verbosity - command line -vvv option. It may give you more insight as to why it is crashing. Link to comment Share on other sites More sharing options...
0 Airikita Posted June 16, 2013 Share Posted June 16, 2013 I'm starting to think we just need to make an actor spawn these arrows instead, not the arrow trap. This is obviously doing no good... anyways, I think the variable for the arrows to hurt Link were 0030 or 0050. I forget as I have been very busy the past few weeks. Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 17, 2013 Share Posted June 17, 2013 I'm starting to think we just need to make an actor spawn these arrows instead, not the arrow trap. This is obviously doing no good... anyways, I think the variable for the arrows to hurt Link were 0030 or 0050. I forget as I have been very busy the past few weeks.That's what I was originally planning... I was going to make a few modifications here and there to en_arow_trap (remove the timer, remove proximity check) and then I was going to write a custom actor with collision, aiming, and a model which spawned en_arow_trap through its initialization function. Currently, both are done but the custom actor is running into some problems upon compiling. EDIT: Alright the problem with collision is that nOVL seems to be handling virtual addresses as out-of-bounds memory addresses. I was under the impression that it should only be doing that for addresses that are less than or equal to 0x807FFFFF (within the range of absolute RAM addresses). As for spawning, I don't quite know why that isn't working correctly, yet. As you can see in the picture below, nOVL starts by looking for relocations in the main function and then proceeds to look for more in the display function. Upon finishing its search it encounters a function call to func_8005dc4c and crashes upon scanning the delay slot. I say the delay slot because it follows immediately after the function call... that's a guess though. Yeah... writing the custom actor in assembly seems like the only option at this point. EDIT 2: Funny. I commented out one of the AVALs in the display function and the actor compiled. However, looking at the log given off by nOVL still shows how messed up it is: Well, apparently the function prototype for the spawning function was incorrect. Spawning may be possibly fixed now; nOVL recognizes the function call to 0x80032458, but I have yet to test it. EDIT 3: Alright well it turns out that spawning was working correctly but XYZ placement was not. The only thing that this actor lacks is collision... How does a progress video sound to you all? Link to comment Share on other sites More sharing options...
0 haddockd Posted June 17, 2013 Share Posted June 17, 2013 DO IT!!!! lol Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 17, 2013 Share Posted June 17, 2013 Link to comment Share on other sites More sharing options...
0 spinout Posted June 19, 2013 Share Posted June 19, 2013 Jason777, do remember that nOVL 'skipping' an address isn't a bad thing - it only handles addresses within the actor's VMA. Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 26, 2013 Share Posted June 26, 2013 Well, I finally got off my ass today and rewrote the actor in assembly just to make sure that it wasn't a problem with my coding... I'm happy to say that the actor works exactly as intended! I will link to a new topic in this thread later today with the custom actor, its source, as well as other modifications I made to get everything working (including the original C actor that I ended up rewriting). Collision will be a part of a later release. In the meantime, I'll be throwing together a model and making a video after I'm done running errands and doing real-life shit today. Happy day Link to comment Share on other sites More sharing options...
0 haddockd Posted June 26, 2013 Share Posted June 26, 2013 Nice work man! Looking forward to seeing it in action. Link to comment Share on other sites More sharing options...
0 Jason777 Posted June 26, 2013 Share Posted June 26, 2013 And here we are: https://www.the-gcn.com/topic/2496-utilizing-en-arow-trap/ Link to comment Share on other sites More sharing options...
0 Airikita Posted November 28, 2013 Share Posted November 28, 2013 ovl_Scene_Change uses JAL 0x800C69CC, which allocates graphics. Link to comment Share on other sites More sharing options...
0 Three_Pendants Posted November 28, 2013 Share Posted November 28, 2013 Yes, but which graphics and where? I recall deleting the file from the game and never saw anything out of the ordinary. It was theorized it was used as an early shiny coat or something for Lord Jabu Jabu, but the changes in his model?/actor? made them not function correctly. Link to comment Share on other sites More sharing options...
0 Airikita Posted November 28, 2013 Share Posted November 28, 2013 From what I could tell, it changes the textures... I'm guessing... you might be right about the shiny coat, but the name makes me curious... No spawning or model rendering. EDIT: I spawned it from Jabu Jabu during the cutscene when Jabu swallows Link, replacing the sparklies that appear to represent the air being sucked into Jabu's mouth. It doesn't crash, but it doesn't seem to do anything. When I observed the actor, there are no spare object groups, just 0040. It's possible it's part of Jabu Jabu, but it has no significance other than possibly what is assumed... a possible shader to Lord Jabu Jabu? I'm tempted to attach this code to Lord Jabu Jabu somehow... perhaps its beta code doesn't work in this game anymore, or it just needs to be Linked it Jabu's model. It could be possible that it was used to render Lord Jabu Jabu's model before it was loaded into the map. That being said, I'll have to dig through it, and attempt expanding Jabu's AI to insert the code, reconfiguring it to work. If I finish my work early today, I'll look into it tonight. Link to comment Share on other sites More sharing options...
Question
john_smith_account
*REMOVED*
Link to comment
Share on other sites
Top Posters For This Question
10
10
22
9
Popular Days
May 26
15
Jun 9
8
Jun 6
8
Jun 1
5
Top Posters For This Question
Jason777 10 posts
john_smith_account 10 posts
Airikita 22 posts
Three_Pendants 9 posts
Popular Days
May 26 2013
15 posts
Jun 9 2013
8 posts
Jun 6 2013
8 posts
Jun 1 2013
5 posts
Popular Posts
DeathBasket
There's at least one inverse trigonometric function (arctan I think) there but you don't even need to use it (directly) to get the actor to face Link. There is a function that will return the rotation
john_smith_account
*REMOVED*
Airikita
I found that ovl_En_Arow_Trap is actually what it says... A TRAP!!! It's definitely beta as it doesn't work if you just add the actor to the map, the actor has to be spawned through a code. It also re
68 answers to this question
Recommended Posts