Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will online battles be implemented? #4

Open
Bkrouse95 opened this issue Oct 22, 2024 · 10 comments
Open

Will online battles be implemented? #4

Bkrouse95 opened this issue Oct 22, 2024 · 10 comments

Comments

@Bkrouse95
Copy link

Is it possible to connect to players online from the Pokemon center?

@KittyPBoxx
Copy link
Owner

KittyPBoxx commented Oct 22, 2024

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

@Bkrouse95
Copy link
Author

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

@KittyPBoxx
Copy link
Owner

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.

  1. src/main.c -> WaitForVBlank optimization changes (you may already have this)
  2. include/net_conn.h -> net_conn header file
  3. 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)
  4. data/specials.inc -> the new special function definition to call network tasks
  5. include/constants/network.h -> for network constants
  6. 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;
}
}`

@Bkrouse95
Copy link
Author

Thank you I tried a few times but got hung up on some compiling errors regarding FillEreaderTrainerWithPlayerData and Task_StartNetworkTask. Thank you again

@KittyPBoxx
Copy link
Owner

KittyPBoxx commented Oct 22, 2024

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

@Bkrouse95
Copy link
Author

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 -o build/modern/src/net_conn.o src/net_conn.c
In file included from include/global.h:11,
from src/net_conn.c:1:
include/constants/flags.h:1565:9: warning: "FLAG_ROUTE101CHARMANDER" redefined
1565 | #define FLAG_ROUTE101CHARMANDER (SYSTEM_FLAGS + 0xC1) // Route101 Charmander
| ^~~~~~~~~~~~~~~~~~~~~~~
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.

@KittyPBoxx
Copy link
Owner

KittyPBoxx commented Oct 23, 2024

That looks like 1 actual issue and 2 warnings that are stopping the compile because it's running in strict mode.


  1. 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


  1. Unused u32 i. A variable called i is getting defined in the function but it's never getting used.

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.


  1. implicit declaration of 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)

@Bkrouse95
Copy link
Author

Thank you. I will try this tomorrow. Appreciate the help

@Bkrouse95
Copy link
Author

Hey that actually worked. I have the emerald expansion 1.9.3 and your net demo compiled together.

@Bkrouse95
Copy link
Author

image
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants