Conversation
src/pokeathlon/pokeathlon_course.c
Outdated
| struct { | ||
| void *ptr; | ||
| u8 bytes[4]; | ||
| } *stateInfo = dest; |
There was a problem hiding this comment.
You have identified the structure stored at the memory address dest, therefore you know the dest argument points to an instance of this struct, instead of an ambiguous void *. The function prototype should make this clear. :)
Try backtracking the function call, see where this dest takes its value from. It's the pointer to a member of PokeathlonCourseData. Can you somehow fit a StateInfo object inside PokeathlonCourseData so that the code still matches? As a hint, this will give you insight into what u8 bytes[4] actually contains.
src/pokeathlon/pokeathlon_course.c
Outdated
| void *dest = PokeathlonCourse_GetPlayerProfile(data->heapAllocPtr1, 0); | ||
| void *src = Save_PlayerData_GetProfile(data->args->saveData); | ||
| PlayerProfile_Copy(src, dest); |
There was a problem hiding this comment.
I feel like you're relying on void pointers too much. Take a look at this for example. You have a call to Save_PlayerData_GetProfile. Looking at the function prototype, you know the parameter is of type SaveData*, and the return value is of type PlayerProfile*. This should be enough for you to
- define
saveDatainPokeathlonCourseArgsas aSaveData*instead ofvoid*, - define the
srcvariable you're initialising here asPlayerProfile*instead ofvoid*, - modify
PokeathlonCourse_GetSaveDatafunction declaration so that it returns aSaveData*instead ofvoid*...
By modifying the type of PokeathlonCourseArgs::saveData first, you should get a bunch of compile warnings about implicit conversions, which will help you find all spots in the code you need to update to the new type.
Likewise, PlayerProfile_Copy takes a PlayerProfile* as the second argument, so that should be the type of dest.
src/pokeathlon/pokeathlon_course.c
Outdated
| void *PokeathlonCourse_GetPlayerProfile(void *profiles, int index) { | ||
| return (u8 *)profiles + (PlayerProfile_sizeof() * index); | ||
| } |
There was a problem hiding this comment.
Once you apply the changes suggested above, you'll see that you've initialised a PlayerProfile* by calling PokeathlonCourse_GetPlayerProfile. This lets you know that PokeathlonCourse_GetPlayerProfile returns a PlayerProfile*, and you should update the function prototype to reflect that. It also suggests that void *profiles is actually an array of PlayerProfile objects.
On a side note, is the cast to (u8 *) really necessary? It matches for me without it.
adrienntindall
left a comment
There was a problem hiding this comment.
I agree with what Laquinh is saying.
Most of the void* calls are actually pointers to structs or function pointers that you haven't defined yet and that need to be defined, even if they're left as unknowns for now.
src/pokeathlon/pokeathlon_course.c
Outdated
| } | ||
|
|
||
| BOOL ov96_021E5C2C(PokeathlonCourseData *data) { | ||
| typedef BOOL (*StateFunc)(PokeathlonCourseData *, void **); |
There was a problem hiding this comment.
Don't typedef in a local scope
src/pokeathlon/pokeathlon_course.c
Outdated
| typedef BOOL (*StateFunc)(PokeathlonCourseData *, void **); | ||
| void **stateDataPtr = (void **)&data->stateArgsBase; | ||
| u8 index = data->stateIndex; | ||
| void **functionTable = data->stateData; |
There was a problem hiding this comment.
Why is this a void** instead of a StateFunc* data type?
src/pokeathlon/pokeathlon_course.c
Outdated
| BOOL result; | ||
|
|
||
| do { | ||
| statePtr = (void **)data->state; |
There was a problem hiding this comment.
Should be a StateHandlerFunc* data type
src/pokeathlon/pokeathlon_course.c
Outdated
| } | ||
|
|
||
| void *PokeathlonCourse_GetParticipantData1(PokeathlonCourseData *data, int index) { | ||
| return (u8 *)&data->participantData1Base + (0x7C * index); |
There was a problem hiding this comment.
Define participantData1Base struct, this is obvious struct access to it.
src/pokeathlon/pokeathlon_course.c
Outdated
| } | ||
|
|
||
| void *PokeathlonCourse_GetParticipantData2(PokeathlonCourseData *data, int index) { | ||
| return &data->participantData2[0x7C * index]; |
There was a problem hiding this comment.
Might be a struct array where participantData2 is a struct of size 0x7C
src/pokeathlon/pokeathlon_course.c
Outdated
| } | ||
|
|
||
| void *ov96_021E5D78(PokeathlonCourseData *data, int index) { | ||
| return &data->field_72C[0x60 * index]; |
There was a problem hiding this comment.
Might be a struct array where field_72C is a struct of size 0x60
adrienntindall
left a comment
There was a problem hiding this comment.
Forgot to request changes on previous review
|
Thanks for all your feedbacks. I'll try to have a look and fix that soon! |
|
I tried to make it better based on your reviews, but I cannot get all of it yet. So maybe we keep it close to what we currently have and you can have a look later if you want to improve it. Let me know what you think. |
| PokeathlonFieldData *ov96_021E5D6C(PokeathlonCourseData *data) { | ||
| return (PokeathlonFieldData *)data->field_72C; | ||
| } |
There was a problem hiding this comment.
This function makes me believe that field_72C is, in fact, an array of PokeathlonFieldData instead of an array of u8. That would allow us to get rid of the casting.
And PokeathlonFieldData takes up 0x60 bytes! Maybe that has something to do with field_72C's 0x60 stride? :)
| PokeathlonParticipantData *PokeathlonCourse_GetParticipantData1(PokeathlonCourseData *data, int index) { | ||
| return (PokeathlonParticipantData *)((u8 *)&data->participantData1Base + (0x7C * index)); | ||
| } | ||
|
|
||
| PokeathlonParticipantData *PokeathlonCourse_GetParticipantData2(PokeathlonCourseData *data, int index) { | ||
| return (PokeathlonParticipantData *)&data->participantData2[0x7C * index]; | ||
| } |
There was a problem hiding this comment.
This is a similar case. It smells a lot like there's gotta be a PokeathlonParticipantData array somewhere inside PokeathlonCourseData, especially given that we're using a 0x7C stride here, and PokeathlonParticipantData takes up 0x7C bytes.
May I ask where you got the idea that the fields are divided in participantData1Base and participantData2? a 4-element array of PokeathlonParticipantData in participantData1Base's place would fit perfectly, and would clean the PokeathlonCourse_GetParticipantData1 function a lot. As for PokeathlonCourse_GetParticipantData2, maybe it's accessing a member of PokeathlonParticipantData? And that would explain the +0x04 offset you were probably seeing in the assembly. From what i know, you don't really have any proof that PokeathlonCourse_GetParticipantData2 returns a PokeathlonParticipantData*, after all.
Afterwards, the functions should be renamed, so the one above is something like PokeathlonCourse_GetParticipantData (not 1), and the one below is something like PokeathlonCourse_GetParticipantUnk04 (this is a suggestion, idk if others may have a different opinion on how to name such a function).
| void PokeathlonCourse_InitStateInfo(const void *src, PokeathlonStateInfo *dest) { | ||
| dest->ptr = (void *)src; | ||
| dest->field_04 = 1; | ||
| dest->stateArgsBase = 0; | ||
| dest->stateIndex = 0; | ||
| dest->field_07 = 0; | ||
| } |
There was a problem hiding this comment.
Not a fan of naming the parameters src and dest. It suggests that you're going to copy the contents of src onto dest or something like that, which you're not doing.
| } | ||
|
|
||
| PlayerProfile *PokeathlonCourse_GetPlayerProfile(PlayerProfile *profiles, int index) { | ||
| return (PlayerProfile *)((u8 *)profiles + (PlayerProfile_sizeof() * index)); |
There was a problem hiding this comment.
I don't have too much spare time right now and I haven't managed to match changing any of this, but I'm pretty confident there should be a cleaner way to write this function.
|
|
||
| // Participant data structure (0x7C = 124 bytes each) | ||
| typedef struct PokeathlonParticipantData { | ||
| u8 data[0x7C]; // Opaque data for now |
There was a problem hiding this comment.
As explained in the other comment, there appears to be a function (PokeathlonCourse_GetParticipantData2) that returns the 4th element of this array. May be worth to un-opaque that one element (?), like
| u8 data[0x7C]; // Opaque data for now | |
| u8 field_00[0x03]; | |
| u8 field_04; | |
| u8 field_05[0x78]; |
Not sure if this is something we usually do, though.
Laquinh
left a comment
There was a problem hiding this comment.
Definitely an improvement :)
|
This pull request has had no activity for 60 days and will be marked stale. If there is no further activity, it will be closed in 30 days. |
|
Hey @Laquinh @adrienntindall I don't think I'll have more time (in upcoming days) to improve the code here. So either we merge that and you're free to improve it later, or we let the PR close and we loose all of that (would be sad right?) What do you think? |
I think that the current state of the PR isn't up to the repository's standards to merge. Asking maintainers to clean up code in your stead when we have already asked for changes isn't fair to anyone actively working on the project. It is ok if you take a while to get things done, but if the PR remains inactive then it will be closed. If you want to finish it at a later date and reopen it after that then that's fine, but we will still be asking for all the requested changes to me made. |
Same idea as #416 but I'm doing the next functions.