Open Bkrouse95 opened 1 month ago
None of the standard link cable / wireless adapter features work online. Those communication sync up constantly so would fail due to network latency.
Getting online trading working meant writing a writing a new trade function that doesn't care about latency. The same would be required for all the other link cable features and some of them are quite difficult. For example I wrote function to try and make online battles work without needing to constantly communicate but every time someone did a turn with multiple actions (e.g baton pass, where you do a move, then switch) the games would end up out of sync with each other. 😞
I will probably get record mixing and online battles working in the future but that would be 2025
Appreciate the reply, great job on what you've got so far. Going to try and get it to work on my expansion fork. Gen 3 online battles are coming eventually
Not tried building on the expansion myself but MelonSpeedruns sent me a change they'd done to get it compiling.
at a minimum there are only 6 files of my changes that you need.
- src/main.c -> WaitForVBlank optimization changes (you may already have this)
- include/net_conn.h -> net_conn header file
- src/net_conn.c -> net_conn main file (you will need to remove some of those network functions you're not using to get it to compile)
- data/specials.inc -> the new special function definition to call network tasks
- include/constants/network.h -> for network constants
- include/gba/io_reg.h -> register definitions for serial communication
your io_reg.h file in network seems to be missing the #define TIMER_COUNTUP 0x04 define by default expansion has the FRONTIER_PARTY_SIZE set to 3, and not 6 like your code expects in Task_DownloadBattleProcess
case DOWNLOAD_BATTLE_FINISH: // Process the data (create the ereader data from what is now stored in gStringVar3) default: { u32 i; u32 offset = 0;
FillEReaderTrainerWithPlayerData();
StringFill(gSaveBlock2Ptr->frontier.ereaderTrainer.name, CHAR_SPACER, PLAYER_NAME_LENGTH);
StringCopy_PlayerName(gSaveBlock2Ptr->frontier.ereaderTrainer.name, trainerName);
gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass = FACILITY_CLASS_RS_BRENDAN;
gSpecialVar_0x8003 = 1;
for (i = 0; i < DOWNLOAD_TRAINER_PARTY_SIZE; i++)
{
offset = DOWNLOAD_TRAINER_POKEMON_SIZE * i;
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].species = (u16) (gStringVar3[ 0 + offset] | gStringVar3[ 1 + offset] << 8);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].level = gStringVar3[ 2 + offset] ;
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].heldItem = (u16) (gStringVar3[ 3 + offset] | gStringVar3[ 4 + offset] << 8);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[0] = (u16) (gStringVar3[ 5 + offset] | gStringVar3[ 6 + offset] << 8);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[1] = (u16) (gStringVar3[ 7 + offset] | gStringVar3[ 8 + offset] << 8);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[2] = (u16) (gStringVar3[ 9 + offset] | gStringVar3[10 + offset] << 8);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[3] = (u16) (gStringVar3[11 + offset] | gStringVar3[12 + offset] << 8);
StringFill(gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].nickname, CHAR_SPACER, POKEMON_NAME_LENGTH);
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].nickname[0] = gStringVar3[13 + offset];
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].nickname[1] = gStringVar3[14 + offset];
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].nickname[2] = gStringVar3[15 + offset];
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].nickname[3] = 0xFF;
// Basic validation to make sure we got something sensible back from the server/wii (ideally this would be a checksum from the server)
if (gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].species > NUM_SPECIES ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].level > MAX_LEVEL ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].heldItem > ITEMS_COUNT ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[0] > MOVES_COUNT ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[1] > MOVES_COUNT ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[2] > MOVES_COUNT ||
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].moves[3] > MOVES_COUNT )
{
gSpecialVar_0x8003 = 0;
}
}
// Basic validation to make sure we got something sensible back from the server/wii
if (gSaveBlock2Ptr->frontier.ereaderTrainer.party[0].species == 0)
gSpecialVar_0x8003 = 0;
sSendRecvMgr.state = NET_CONN_STATE_DONE;
break;
}
gTasks[taskId].func = Task_NetworkTaskLoop;
} }`
Thank you I tried a few times but got hung up on some compiling errors regarding FillEreaderTrainerWithPlayerData and Task_StartNetworkTask. Thank you again
I don't think Task_StartNetworkTask
is used anymore so can just be deleted.
This section can be removed too because it won't work for the expansion
else
{
gSaveBlock2Ptr->frontier.ereaderTrainer.party[i].species = 0;
}
As for FillEreaderTrainerWithPlayerData it would need to not be marked as static or unused anymore and also declared in battle_tower.h
I made the above changes and appears i'm down to 2 things.
/opt/devkitpro/devkitARM/bin/../libexec/gcc/arm-none-eabi/14.1.0/cc1 -quiet ~~~~~~
include/constants/flags.h:48:9: note: this is the location of the previous definition
48 | #define FLAG_ROUTE101CHARMANDER 0x23 // Unused Flag
| ^~~~~~~
src/net_conn.c: In function 'Task_DownloadBattleProcess':
src/net_conn.c:682:13: error: implicit declaration of function 'FillEReaderTrainerWithPlayerData' [-Wimplicit-function-declaration]
682 | FillEReaderTrainerWithPlayerData();
| ^~~~~~~~
src/net_conn.c: In function 'Task_PostMailProcess':
src/net_conn.c:1216:17: warning: unused variable 'i' [-Wunused-variable]
1216 | u32 i;
| ^
make: [Makefile:403: build/modern/src/net_conn.o] Error 1
make: Deleting file 'build/modern/src/net_conn.o'
I guess I just don't know what to put for "i" and where to change it, and i'm not sure how to change FillEreaderTrainerWithPlayerData from static. I think im close to being able to compile expansion 1.9.3 with your online code.
That looks like 1 actual issue and 2 warnings that are stopping the compile because it's running in strict mode.
FLAG_ROUTE101CHARMANDER
, that's not even my code. But you can see the it's doing a define on line 48 then replacing that definition on line 1565 of the same file. Basically, the compiler is warning you something is wrong because the constant gets defined then overwritten before it's even used. To fix this you could change line 48 to be FLAG_UNUSED_0x023
The compiler is warning you because the variable is being created for no reason. You can just delete u32 i;
from line 1216 . Be careful to only delete it from the case POST_MAIL_FINISH:
part of the switch statement (as 'i' is also defined in the POST_MAIL_SEND_REQUEST
case where it is actually used.
FillEReaderTrainerWithPlayerData
. net_conn.c has no knowledge of a function with that name. The compiler is saying that the function FillEReaderTrainerWithPlayerData
is being called but the file net_conn.c
doesn't know about the function. This is because the function is declared in battle_tower.c
To let net_conn.c
access the function from battle_tower.c
you need to make sure a few conditions are met.
Make sure net_conn.c
is including battle_tower.h
so it can access functions that are made accessible through battle_towers header file. You should see the line #include "battle_tower.h"
in the include statements at the top of the net_conn.c
Make sure battle_tower.h
is declaring FillEReaderTrainerWithPlayerData
as a function that other files can access. You should see the line void FillEReaderTrainerWithPlayerData(void);
somewhere the list of functions declared in battle_tower.h
.
Make the declaration of FillEReaderTrainerWithPlayerData
in battle_tower.c
non static (and not UNUSED). In battle_tower.c
you will see the line static void UNUSED FillEReaderTrainerWithPlayerData(void)
. There are two issues with this. Firstly the function is marked with UNUSED
. This tells the compiler that it shouldn't worry about the fact that the function is never called. However, now we are calling it, we don't want that anymore! Secondly the function is marked as static
. This tells the compiler that no other files need access to the function. Again, this is not true anymore, as we do want another file to have access to the function! (specifically net_conn.c
). To fix both issues you simply need to remove the keywords. When done your method signature will look like this void FillEReaderTrainerWithPlayerData(void)
Thank you. I will try this tomorrow. Appreciate the help
Hey that actually worked. I have the emerald expansion 1.9.3 and your net demo compiled together.
Was able to connect 2 instances on a local machine no problem. I did remove the net mail script because even after making sure I added include script menu.h I could not get rid of the undefined reference.
Is it possible to connect to players online from the Pokemon center?