Rejoin Room [TheLordScruffy]
#1
Rejoin Room [TheLordScruffy]
Version 1.3

If you disconnect from a Worldwide or Regional room, a new button appears on the Nintendo WFC main menu to rejoin it. You'll be denied immediately if the room is on the voting screen. The networking library is hardcoded to try 15 times to connect. If it sits there for a while, the room likely doesn't exist anymore.
The code makes a few BMG patches:
0xFA5 / "Rejoin"
0xFA6 / "Rejoin the last room you played."
0xFB1 / "You have not played\na room to rejoin."
0xFB7 / "You were unable to\nrejoin the room.\n\nPlease wait and try\nagain later."
0x1009 / "Rejoining room..."
It does not overwrite the IDs if text already exists.


NTSC-U
C2618C5C 00000005
2C000006 4C820020
38800FA6 38630B98
3D808084 618C1960
7D8903A6 4E800420
60000000 60000000
C0000000 0000003F
4E800020 00000000
FF000000 808B9904
00000000 00000000
FFFFFFFF 00000000
7C0802A6 9421FFE0
90010024 BF810010
7C7F1B78 7C9D2378
3C60809C 8063D508
83830000 80ACFFE4
2C050000 41A20068
807C0244 38800004
90831CF4 88ACFFE9
38800000 2C050005
41A20010 38800001
2C050008 40820040
3D80805E 618C53E4
4BFFFF69 3800008F
901F0F30 7FA3EB78
3D80805B 618C62E4
4BFFFF51 7FE3FB78
38800000 3D80805D
618CDBA8 4BFFFF3D
48000034 807C013C
386301A8 38800FB1
3D808060 618CC994
4BFFFF21 7FE3FB78
3880004D 38A00000
3D80805D 618CDCD0
4BFFFF09 80010024
7C0803A6 BB810010
38210020 4E800020
52656A6F 696E0052
656A6F69 6E207468
65206C61 73742072
6F6F6D20 796F7520
706C6179 65642E00
596F7520 77657265
20756E61 626C6520
746F0A72 656A6F69
6E207468 6520726F
6F6D2E0A 0A506C65
61736520 77616974
20616E64 20747279
0A616761 696E206C
61746572 2E005265
6A6F696E 696E6720
726F6F6D 2E2E2E00
387E1078 3D80805D
618C83A4 4BFFFE64
2C03FFFF 4D820020
7D8802A6 48000005
7CA802A6 38A5FF5F
5486083C 38FE1188
7D073214 38E8FFFE
7CA52214 8C850001
B4870002 2C040000
4082FFF4 7D8803A6
80BE107C 80DE1080
54601838 7CA50214
80E50008 7C07322E
2C000000 4C820020
7CC64050 90C50008
4E800020 00000007
045F3198 38601288
C2618670 00000004
48000005 7D2802A6
9089FFE8 38840001
3D80805D 618CDB7C
4BFFFDC9 60000000
C26188F4 00000022
387E0F34 3D80805B
618C5704 4BFFFDAD
7FC3F378 48000005
7C8802A6 8084FFAC
38BE0F34 38C00000
3D80805D 618CDB8C
4BFFFD89 387E0F34
3CA08089 60A4219F
48000011 44726966
7448656C 70000000
7CC802A6 7CC53378
38E00001 39000000
39200000 3D80805B
618C5874 4BFFFD4D
807E03B0 809E0604
3CA043FA 2C030000
41820008 90A3004C
90A4004C 389E0094
909E116C 38800006
909E1174 38800FA5
4BFFFEA9 38800000
4BFFFEB1 38800FA6
4BFFFE99 38800007
4BFFFEA1 38800FB7
4BFFFE89 38800028
4BFFFE91 38801009
4BFFFE79 3880006E
4BFFFE81 387E0F34
38800FA5 3D808060
618CC994 4BFFFCCD
7C6802A6 3863FCEC
93C30004 38830014
90830010 907E1168
7FC3F378 60000000
C26189B8 00000007
38000001 48000005
7C6802A6 8063FCB4
2C030000 40A20008
38000000 901F1178
901F1118 68000001
981F0FB4 3800FFFF
60000000 60000000
C25E51B4 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
C25E5394 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
045E5230 60000000
C25E5234 00000005
3880100A 2C000004
4082000C 38801009
48000014 28000001
3D80805E 618C5370
41A1FBF8 60000000
045E45C8 60000000
C25E45D4 00000005
38800FB2 2C000004
4082000C 38800FB7
48000014 28000001
3D80805E 618C4608
41A1FBC0 60000000
C2655C60 00000008
80830000 2C040000
41820030 88830005
2C040005 4182000C
2C040008 40A2001C
80830000 48000005
7D8802A6 948CFBA4
80830004 908C0004
38800008 60000000
C264EF10 00000008
800300E8 2C00000B
40A20030 48000005
7D8802A6 8C8CFB79
38000007 2C040005
41A20008 38000009
888CFFFF 2C0400FF
41A20008 3800FFFF
60000000 60000000
C264FEC8 00000003
800300E8 2C00000B
40A20008 38000001
60000000 60000000
C26532A4 00000003
2C00000B 40A20008
3800000A 2C000001
60000000 60000000
C265523C 00000006
80BF00E8 2C05000B
40A20020 48000005
7C8802A6 8CA4FAF0
54A5C9FE 68A50001
88C40001 7C662A14
2C030005 60000000
C265541C 00000004
806325EC 801F00E8
2C00000B 40820010
48000005 7C6802A6
8063FAB0 60000000
C25E3CBC 0000000A
801F1CF4 2C000004
40820040 387F0190
38800FA5 3D808084
618C1960 4BFFFA65
3FA0809C 809F018C
807DD918 3D808065
618C1D2C 4BFFFA4D
807DD918 3880000B
908300E8 3800FFFF
60000000 60000000


NTSC-J
C264B5DC 00000005
2C000006 4C820020
38800FA6 38630B98
3D80807E 618C90A4
7D8903A6 4E800420
60000000 60000000
C0000000 0000003F
4E800020 00000000
FF000000 808BF104
00000000 00000000
FFFFFFFF 00000000
7C0802A6 9421FFE0
90010024 BF810010
7C7F1B78 7C9D2378
3C60809C 80630E98
83830000 80ACFFE4
2C050000 41A20068
807C0244 38800004
90831CF4 88ACFFE9
38800000 2C050005
41A20010 38800001
2C050008 40820040
3D808060 618C942C
4BFFFF69 3800008F
901F0F30 7FA3EB78
3D80805B 618CD908
4BFFFF51 7FE3FB78
38800000 3D808060
618C1BFC 4BFFFF3D
48000034 807C013C
386301A8 38800FB1
3D808063 618CD420
4BFFFF21 7FE3FB78
3880004D 38A00000
3D808060 618C1D24
4BFFFF09 80010024
7C0803A6 BB810010
38210020 4E800020
52656A6F 696E0052
656A6F69 6E207468
65206C61 73742072
6F6F6D20 796F7520
706C6179 65642E00
596F7520 77657265
20756E61 626C6520
746F0A72 656A6F69
6E207468 6520726F
6F6D2E0A 0A506C65
61736520 77616974
20616E64 20747279
0A616761 696E206C
61746572 2E005265
6A6F696E 696E6720
726F6F6D 2E2E2E00
387E1078 3D80805F
618C8564 4BFFFE64
2C03FFFF 4D820020
7D8802A6 48000005
7CA802A6 38A5FF5F
5486083C 38FE1188
7D073214 38E8FFFE
7CA52214 8C850001
B4870002 2C040000
4082FFF4 7D8803A6
80BE107C 80DE1080
54601838 7CA50214
80E50008 7C07322E
2C000000 4C820020
7CC64050 90C50008
4E800020 00000007
04623798 38601288
C264AFF0 00000004
48000005 7D2802A6
9089FFE8 38840001
3D808060 618C1BD0
4BFFFDC9 60000000
C264B274 00000022
387E0F34 3D80805B
618CCD28 4BFFFDAD
7FC3F378 48000005
7C8802A6 8084FFAC
38BE0F34 38C00000
3D808060 618C1BE0
4BFFFD89 387E0F34
3CA08089 60A48B8F
48000011 44726966
7448656C 70000000
7CC802A6 7CC53378
38E00001 39000000
39200000 3D80805B
618CCE98 4BFFFD4D
807E03B0 809E0604
3CA043FA 2C030000
41820008 90A3004C
90A4004C 389E0094
909E116C 38800006
909E1174 38800FA5
4BFFFEA9 38800000
4BFFFEB1 38800FA6
4BFFFE99 38800007
4BFFFEA1 38800FB7
4BFFFE89 38800028
4BFFFE91 38801009
4BFFFE79 3880006E
4BFFFE81 387E0F34
38800FA5 3D808063
618CD420 4BFFFCCD
7C6802A6 3863FCEC
93C30004 38830014
90830010 907E1168
7FC3F378 60000000
C264B338 00000007
38000001 48000005
7C6802A6 8063FCB4
2C030000 40A20008
38000000 901F1178
901F1118 68000001
981F0FB4 3800FFFF
60000000 60000000
C26091FC 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
C26093DC 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
04609278 60000000
C260927C 00000005
3880100A 2C000004
4082000C 38801009
48000014 28000001
3D808060 618C93B8
41A1FBF8 60000000
04608610 60000000
C260861C 00000005
38800FB2 2C000004
4082000C 38800FB7
48000014 28000001
3D808060 618C8650
41A1FBC0 60000000
C2659754 00000008
80830000 2C040000
41820030 88830005
2C040005 4182000C
2C040008 40A2001C
80830000 48000005
7D8802A6 948CFBA4
80830004 908C0004
38800008 60000000
C2652A04 00000008
800300E8 2C00000B
40A20030 48000005
7D8802A6 8C8CFB79
38000007 2C040005
41A20008 38000009
888CFFFF 2C0400FF
41A20008 3800FFFF
60000000 60000000
C26539BC 00000003
800300E8 2C00000B
40A20008 38000001
60000000 60000000
C2656D98 00000003
2C00000B 40A20008
3800000A 2C000001
60000000 60000000
C2658D30 00000006
80BF00E8 2C05000B
40A20020 48000005
7C8802A6 8CA4FAF0
54A5C9FE 68A50001
88C40001 7C662A14
2C030005 60000000
C2658F10 00000004
806325EC 801F00E8
2C00000B 40820010
48000005 7C6802A6
8063FAB0 60000000
C2607D10 0000000A
801F1CF4 2C000004
40820040 387F0190
38800FA5 3D80807E
618C90A4 4BFFFA65
3FA0809C 809F018C
807D1138 3D808065
618C5820 4BFFFA4D
807D1138 3880000B
908300E8 3800FFFF
60000000 60000000


PAL
C264BF70 00000005
2C000006 4C820020
38800FA6 38630B98
3D80807E 618C9A38
7D8903A6 4E800420
60000000 60000000
C0000000 0000003F
4E800020 00000000
FF000000 808BFFB4
00000000 00000000
FFFFFFFF 00000000
7C0802A6 9421FFE0
90010024 BF810010
7C7F1B78 7C9D2378
3C60809C 80631E38
83830000 80ACFFE4
2C050000 41A20068
807C0244 38800004
90831CF4 88ACFFE9
38800000 2C050005
41A20010 38800001
2C050008 40820040
3D808060 618C9CB8
4BFFFF69 3800008F
901F0F30 7FA3EB78
3D80805B 618CDF88
4BFFFF51 7FE3FB78
38800000 3D808060
618C2488 4BFFFF3D
48000034 807C013C
386301A8 38800FB1
3D808063 618CDDB4
4BFFFF21 7FE3FB78
3880004D 38A00000
3D808060 618C25B0
4BFFFF09 80010024
7C0803A6 BB810010
38210020 4E800020
52656A6F 696E0052
656A6F69 6E207468
65206C61 73742072
6F6F6D20 796F7520
706C6179 65642E00
596F7520 77657265
20756E61 626C6520
746F0A72 656A6F69
6E207468 6520726F
6F6D2E0A 0A506C65
61736520 77616974
20616E64 20747279
0A616761 696E206C
61746572 2E005265
6A6F696E 696E6720
726F6F6D 2E2E2E00
387E1078 3D80805F
618C8C88 4BFFFE64
2C03FFFF 4D820020
7D8802A6 48000005
7CA802A6 38A5FF5F
5486083C 38FE1188
7D073214 38E8FFFE
7CA52214 8C850001
B4870002 2C040000
4082FFF4 7D8803A6
80BE107C 80DE1080
54601838 7CA50214
80E50008 7C07322E
2C000000 4C820020
7CC64050 90C50008
4E800020 00000007
0462404C 38601288
C264B984 00000004
48000005 7D2802A6
9089FFE8 38840001
3D808060 618C245C
4BFFFDC9 60000000
C264BC08 00000022
387E0F34 3D80805B
618CD3A8 4BFFFDAD
7FC3F378 48000005
7C8802A6 8084FFAC
38BE0F34 38C00000
3D808060 618C246C
4BFFFD89 387E0F34
3CA08089 60A49A2F
48000011 44726966
7448656C 70000000
7CC802A6 7CC53378
38E00001 39000000
39200000 3D80805B
618CD518 4BFFFD4D
807E03B0 809E0604
3CA043FA 2C030000
41820008 90A3004C
90A4004C 389E0094
909E116C 38800006
909E1174 38800FA5
4BFFFEA9 38800000
4BFFFEB1 38800FA6
4BFFFE99 38800007
4BFFFEA1 38800FB7
4BFFFE89 38800028
4BFFFE91 38801009
4BFFFE79 3880006E
4BFFFE81 387E0F34
38800FA5 3D808063
618CDDB4 4BFFFCCD
7C6802A6 3863FCEC
93C30004 38830014
90830010 907E1168
7FC3F378 60000000
C264BCCC 00000007
38000001 48000005
7C6802A6 8063FCB4
2C030000 40A20008
38000000 901F1178
901F1118 68000001
981F0FB4 3800FFFF
60000000 60000000
C2609A88 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
C2609C68 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
04609B04 60000000
C2609B08 00000005
3880100A 2C000004
4082000C 38801009
48000014 28000001
3D808060 618C9C44
41A1FBF8 60000000
04608E9C 60000000
C2608EA8 00000005
38800FB2 2C000004
4082000C 38800FB7
48000014 28000001
3D808060 618C8EDC
41A1FBC0 60000000
C265A0E8 00000008
80830000 2C040000
41820030 88830005
2C040005 4182000C
2C040008 40A2001C
80830000 48000005
7D8802A6 948CFBA4
80830004 908C0004
38800008 60000000
C2653398 00000008
800300E8 2C00000B
40A20030 48000005
7D8802A6 8C8CFB79
38000007 2C040005
41A20008 38000009
888CFFFF 2C0400FF
41A20008 3800FFFF
60000000 60000000
C2654350 00000003
800300E8 2C00000B
40A20008 38000001
60000000 60000000
C265772C 00000003
2C00000B 40A20008
3800000A 2C000001
60000000 60000000
C26596C4 00000006
80BF00E8 2C05000B
40A20020 48000005
7C8802A6 8CA4FAF0
54A5C9FE 68A50001
88C40001 7C662A14
2C030005 60000000
C26598A4 00000004
806325EC 801F00E8
2C00000B 40820010
48000005 7C6802A6
8063FAB0 60000000
C260859C 0000000A
801F1CF4 2C000004
40820040 387F0190
38800FA5 3D80807E
618C9A38 4BFFFA65
3FA0809C 809F018C
807D20D8 3D808065
618C61B4 4BFFFA4D
807D20D8 3880000B
908300E8 3800FFFF
60000000 60000000


NTSC-K
C263A288 00000005
2C000006 4C820020
38800FA6 38630B98
3D80807D 618C7DF8
7D8903A6 4E800420
60000000 60000000
C0000000 0000003F
4E800020 00000000
FF000000 808AE424
00000000 00000000
FFFFFFFF 00000000
7C0802A6 9421FFE0
90010024 BF810010
7C7F1B78 7C9D2378
3C60809B 80630478
83830000 80ACFFE4
2C050000 41A20068
807C0244 38800004
90831CF4 88ACFFE9
38800000 2C050005
41A20010 38800001
2C050008 40820040
3D80805F 618C80D8
4BFFFF69 3800008F
901F0F30 7FA3EB78
3D80805A 618CBFE0
4BFFFF51 7FE3FB78
38800000 3D80805F
618C08A8 4BFFFF3D
48000034 807C013C
386301A8 38800FB1
3D808062 618CC0CC
4BFFFF21 7FE3FB78
3880004D 38A00000
3D80805F 618C09D0
4BFFFF09 80010024
7C0803A6 BB810010
38210020 4E800020
52656A6F 696E0052
656A6F69 6E207468
65206C61 73742072
6F6F6D20 796F7520
706C6179 65642E00
596F7520 77657265
20756E61 626C6520
746F0A72 656A6F69
6E207468 6520726F
6F6D2E0A 0A506C65
61736520 77616974
20616E64 20747279
0A616761 696E206C
61746572 2E005265
6A6F696E 696E6720
726F6F6D 2E2E2E00
387E1078 3D80805E
618C70A8 4BFFFE64
2C03FFFF 4D820020
7D8802A6 48000005
7CA802A6 38A5FF5F
5486083C 38FE1188
7D073214 38E8FFFE
7CA52214 8C850001
B4870002 2C040000
4082FFF4 7D8803A6
80BE107C 80DE1080
54601838 7CA50214
80E50008 7C07322E
2C000000 4C820020
7CC64050 90C50008
4E800020 00000007
04612444 38601288
C2639C9C 00000004
48000005 7D2802A6
9089FFE8 38840001
3D80805F 618C087C
4BFFFDC9 60000000
C2639F20 00000022
387E0F34 3D80805A
618CB400 4BFFFDAD
7FC3F378 48000005
7C8802A6 8084FFAC
38BE0F34 38C00000
3D80805F 618C088C
4BFFFD89 387E0F34
3CA08088 60A47E67
48000011 44726966
7448656C 70000000
7CC802A6 7CC53378
38E00001 39000000
39200000 3D80805A
618CB570 4BFFFD4D
807E03B0 809E0604
3CA043FA 2C030000
41820008 90A3004C
90A4004C 389E0094
909E116C 38800006
909E1174 38800FA5
4BFFFEA9 38800000
4BFFFEB1 38800FA6
4BFFFE99 38800007
4BFFFEA1 38800FB7
4BFFFE89 38800028
4BFFFE91 38801009
4BFFFE79 3880006E
4BFFFE81 387E0F34
38800FA5 3D808062
618CC0CC 4BFFFCCD
7C6802A6 3863FCEC
93C30004 38830014
90830010 907E1168
7FC3F378 60000000
C2639FE4 00000007
38000001 48000005
7C6802A6 8063FCB4
2C030000 40A20008
38000000 901F1178
901F1118 68000001
981F0FB4 3800FFFF
60000000 60000000
C25F7EA8 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
C25F8088 00000003
2C030004 4082000C
3800008B 901F1D00
38000006 60000000
045F7F24 60000000
C25F7F28 00000005
3880100A 2C000004
4082000C 38801009
48000014 28000001
3D80805F 618C8064
41A1FBF8 60000000
045F72BC 60000000
C25F72C8 00000005
38800FB2 2C000004
4082000C 38800FB7
48000014 28000001
3D80805F 618C72FC
41A1FBC0 60000000
C2648400 00000008
80830000 2C040000
41820030 88830005
2C040005 4182000C
2C040008 40A2001C
80830000 48000005
7D8802A6 948CFBA4
80830004 908C0004
38800008 60000000
C26416B0 00000008
800300E8 2C00000B
40A20030 48000005
7D8802A6 8C8CFB79
38000007 2C040005
41A20008 38000009
888CFFFF 2C0400FF
41A20008 3800FFFF
60000000 60000000
C2642668 00000003
800300E8 2C00000B
40A20008 38000001
60000000 60000000
C2645A44 00000003
2C00000B 40A20008
3800000A 2C000001
60000000 60000000
C26479DC 00000006
80BF00E8 2C05000B
40A20020 48000005
7C8802A6 8CA4FAF0
54A5C9FE 68A50001
88C40001 7C662A14
2C030005 60000000
C2647BBC 00000004
806325EC 801F00E8
2C00000B 40820010
48000005 7C6802A6
8063FAB0 60000000
C25F69BC 0000000A
801F1CF4 2C000004
40820040 387F0190
38800FA5 3D80807D
618C7DF8 4BFFFA65
3FA0809B 809F018C
807D0718 3D808064
618C44CC 4BFFFA4D
807D0718 3880000B
908300E8 3800FFFF
60000000 60000000



Source (assemble with GCC)

Code:
#define REGION 'P' /* Define a region RMC? */
#define BMG_PATCH /* Patch text with text in the code */
#define DRIFT_HELP_BUTTON /* Use the "DriftHelp" button style and position on the menu */
#define TOUCH_PANE_PATCH /* Patch the touch pane to make the DriftHelp button selectable */
#define INVISIBLE_BUTTON /* Only show the button if you have a room to rejoin */
#define CHECK_WW /* Enable a check if the Worldwide button exists */


#if REGION == 'E'
#define PORT(E, J, P, K) E
#elif REGION == 'J'
#define PORT(E, J, P, K) J
#elif REGION == 'P'
#define PORT(E, J, P, K) P
#elif REGION == 'K'
#define PORT(E, J, P, K) K
#else
#define PORT(E, J, P, K) 0
#endif


#define GCT_WRITE_8(ADDRESS, VALUE) \
    .long 0x00000000 | (ADDRESS & 0x1FFFFFF); \
    .long (VALUE & 0xFF)

#define GCT_FILL_8(ADDRESS, VALUE, COUNT) \
    .long 0x00000000 | (ADDRESS & 0x1FFFFFF); \
    .long (VALUE & 0xFF) | ((COUNT + 1) << 16)

#define GCT_WRITE_16(ADDRESS, VALUE) \
    .long 0x02000000 | (ADDRESS & 0x1FFFFFF); \
    .long (VALUE & 0xFFFF)

#define GCT_FILL_16(ADDRESS, VALUE, COUNT) \
    .long 0x02000000 | (ADDRESS & 0x1FFFFFF); \
    .long (VALUE & 0xFFFF) | ((COUNT + 1) << 16)

#define GCT_WRITE_32(ADDRESS, VALUE) \
    .long 0x04000000 | (ADDRESS & 0x1FFFFFF); \
    .long VALUE

#define GCT_WRITE_STRING(ADDRESS, STRING) \
    .long 0x06000000 | (ADDRESS & 0x1FFFFFF); \
    .long string_##ADDRESS##_size; \
string_##ADDRESS:; \
    .string STRING; \
    .set string_##ADDRESS##_size, . - string_##ADDRESS; \
    .align 3

#define GCT_STRING(NAME, ADDRESS) \
    .long 0x06000000 | (ADDRESS & 0x1FFFFFF); \
    .long NAME##_size; \
NAME:;
#define GCT_STRING_END(NAME) \
    .set NAME##_size, . - NAME; \
    .align 3

#define GCT_EXECUTE(NAME) \
    .long 0xC0000000; \
    .long (NAME##_size + 1) >> 3; \
NAME:
#define GCT_EXECUTE_END(NAME) \
    .align 3; \
    .set NAME##_size, . - NAME

#define GCT_INSERT(ADDRESS, NAME) \
    .long 0xC2000000 | (ADDRESS & 0x1FFFFFF); \
    .long (NAME##_size + 1) >> 3; \
    .set NAME##_start, .
#define GCT_INSERT_END(NAME) \
    nop; \
    .align 3; \
    .set NAME##_size, . - NAME##_start

#define GCT_WRITE_BRANCH(SRC, DEST) \
    .long 0xC6000000 | (SRC & 0x1FFFFFF); \
    .long DEST



#define B_CALL(ADDRESS) \
.ifdef asm_call_thunk; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    b asm_call_thunk; \
.else; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    mtctr r12; \
    bctr; \
.endif

#define BL_CALL(ADDRESS) \
.ifdef asm_call_thunk; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    bl asm_call_thunk; \
.else; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    mtctr r12; \
    bctrl; \
.endif

#define BC_CALL(CONDITION, ADDRESS) \
.ifdef asm_call_thunk; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    b##CONDITION- asm_call_thunk; \
.else; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    mtctr r12; \
    b##CONDITION##ctr-; \
.endif

#define BCL_CALL(CONDITION, ADDRESS) \
.ifdef asm_call_thunk; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    b##CONDITION##l- asm_call_thunk; \
.else; \
    lis r12, (ADDRESS)@h; \
    ori r12, r12, (ADDRESS)@l; \
    mtctr r12; \
    b##CONDITION##ctr##l-; \
.endif

#define STRING(REG, STRING, SYM) \
    bl str_##SYM##_end; \
str_##SYM:; \
    .string STRING; \
    .align 2; \
    str_##SYM##_end:; \
    mflr REG

#define SHORT_PTR(REG, SYM, DATA...) \
    bl short_##SYM##_end; \
short_##SYM:; \
    .short DATA; \
    .align 2; \
    short_##SYM##_end:; \
    mflr REG

#define FLOAT_PTR(REG, SYM, DATA...) \
    bl short_##SYM##_end; \
short_##SYM:; \
    .float DATA; \
    .align 2; \
    short_##SYM##_end:; \
    mflr REG

#define PTR(REG, NAME) \
    bl 4; \
    mflr REG; \
    addi REG, REG, (NAME) - (. - 4)

#define PTR_LWZ(REG, NAME, INDEX) \
    bl 4; \
    mflr REG; \
    lwz REG, (NAME) - (. - 4) + INDEX(REG)

#define PTR_LBZ(REG, NAME, INDEX) \
    bl 4; \
    mflr REG; \
    lbz REG, (NAME) - (. - 4) + INDEX(REG)

#define PTR_LWZU(REG, TMP_REG, NAME, INDEX) \
    bl 4; \
    mflr TMP_REG; \
    lwzu REG, (NAME) - (. - 4) + INDEX(TMP_REG)

#define PTR_LBZU(REG, TMP_REG, NAME, INDEX) \
    bl 4; \
    mflr TMP_REG; \
    lbzu REG, (NAME) - (. - 4) + INDEX(TMP_REG)

#define PTR_STW(REG, TMP_REG, NAME, INDEX) \
    bl 4; \
    mflr TMP_REG; \
    stw REG, (NAME) - (. - 4) + INDEX(TMP_REG)

#define PTR_STWU(REG, TMP_REG, NAME, INDEX) \
    bl 4; \
    mflr TMP_REG; \
    stwu REG, (NAME) - (. - 4) + INDEX(TMP_REG)

/* E, J, P, K addresses */
/* operator new(unsigned long), or rather, malloc */
.set __nw__FUl,                    PORT( 0x80229A48, 0x80229CEC, 0x80229DCC, 0x8022A140 )
/* Menu stuff */
.set Menu_Control_Construct,       PORT( 0x805B5704, 0x805BCD28, 0x805BD3A8, 0x805AB400 )
.set Menu_Control_LoadLayout,      PORT( 0x805B5874, 0x805BCE98, 0x805BD518, 0x805AB570 )
.set Menu_Control_SetAllText,      PORT( 0x8060C994, 0x8063D420, 0x8063DDB4, 0x8062C0CC )
.set Menu_Screen_InitControlList,  PORT( 0x805DDB7C, 0x80601BD0, 0x8060245C, 0x805F087C )
.set Menu_Screen_InsertControl,    PORT( 0x805DDB8C, 0x80601BE0, 0x8060246C, 0x805F088C )
.set Menu_Screen_ShowOnTop,        PORT( 0x805DDCD0, 0x80601D24, 0x806025B0, 0x805F09D0 )
/* Not 100% sure if the following two have the most accurate names */
.set Menu_Control_GetTransTimer,   PORT( 0x805B62E4, 0x805BD908, 0x805BDF88, 0x805ABFE0 )
.set Menu_Screen_StartTransition,  PORT( 0x805DDBA8, 0x80601BFC, 0x80602488, 0x805F08A8 )
/* GetTransTimer (shortened from GetTransitionTimer) returns a float of the amount of time
/  to wait before transitioning to the next screen. */
/* StartTransition starts the screen transition after the amount of time, passed as f1, is
/  over. The main way to use this is to pass on the value from Menu_Control_GetTransTimer. */
.set Menu_Mesg_MIDToIndex,         PORT( 0x805D83A4, 0x805F8564, 0x805F8C88, 0x805E70A8 )
.set Menu_HeaderText_SetText,      PORT( 0x80841960, 0x807E90A4, 0x807E9A38, 0x807D7DF8 )
/* I really dislike the "MenuData" name */
.set MenuData,                     PORT( 0x809BD508, 0x809C0E98, 0x809C1E38, 0x809B0478 )
.set SearchManager_SetGameMode,    PORT( 0x805E53E4, 0x8060942C, 0x80609CB8, 0x805F80D8 )
.set RKNetController_JoinFriend,   PORT( 0x806551F8, 0x80658CEC, 0x80659680, 0x80647998 )
.set RKNetController_SetupWWVS,    PORT( 0x80651D2C, 0x80655820, 0x806561B4, 0x806444CC )
.set RKNetController_sInstance,    PORT( 0x809BD918, 0x809C1138, 0x809C20D8, 0x809B0718 )

/* Some useful stuff */
.set button_str,                   PORT( 0x8089219F, 0x80898B8F, 0x80899A2F, 0x80887E67 )
.set WifiMenuSingleTop_str,        PORT( 0x808921A6, 0x80898B96, 0x80899A36, 0x80887E6E )
.set wifi_button_vtable,           PORT( 0x808B9904, 0x808BF104, 0x808BFFB4, 0x808AE424 )

#define REJOIN 4 /* SearchManager search mode */
#define REJOIN_MODE 11 /* RKNetController join mode */


/* Fix bottom text for highlighting Rejoin */
GCT_INSERT(PORT(0x80618C5C, 0x8064B5DC, 0x8064BF70, 0x8063A288), rejoin_bottom_text)
    cmpwi r0, 6
    bnelr-

    li r4, 4006
    //li r5, 0
    addi r3, r3, 2968
    lis r12, Menu_HeaderText_SetText@h
    ori r12, r12, Menu_HeaderText_SetText@l

/* This thunk to optimize call size is why we need this insert first */
asm_call_thunk:
    mtctr r12
    bctr
GCT_INSERT_END(rejoin_bottom_text)


/* Misc data and functions for use.
/  Could probably use goto instead of C0 + blr to do this. */
GCT_EXECUTE(data)
    blr

#if 0
/* Temporary location string to save to */
rejoin_location_temp:
    .long 0x00000000 // Group ID
    .byte 0xFF // Region ID
    .byte 0x00 // Status
    .byte 0x00 // Player count
    .byte 0x00 // Race count
#endif

/* Last room location string */
rejoin_location:
    .long 0x00000000 // Group ID
    .byte 0xFF // Region ID
    .byte 0x00 // Status
    .byte 0x00 // Player count
    .byte 0x00 // Race count

button_select_data:
    .long wifi_button_vtable
    .long 0
    .long 0
    .long -1
    .long 0

/* Function for pressing the Reconnect button */
rejoin_button_press_event:
    mflr r0
    stwu sp, -0x20(sp)
    stw r0, 0x24(sp)
    stmw r28, 0x20-0x10(sp)
    mr r31, r3 // wifi top screen
    mr r29, r4 // Rejoin button

    lis r3, MenuData@ha
    lwz r3, MenuData@l(r3)
    lwz r28, 0(r3)

    /* r12 is always a pointer to rejoin_button_press_event */
    lwz r5, rejoin_location - rejoin_button_press_event(r12)
    cmpwi r5, 0
    beq+ rejoin_button_display_msgbox
    
    /* Continue onward with rejoining room */
    lwz r3, 0x244(r28) // Screen 0x8F pointer

    /* Set the mode to 4 so we know we're rejoining a room */
    li r4, REJOIN
    stw r4, 0x1CF4(r3)

    lbz r5, rejoin_location - rejoin_button_press_event + 5(r12)

    li r4, 0 // VS
    cmpwi r5, 0x05
    beq+ rejoin_button_gamemode_label

    li r4, 1 // Battle
    cmpwi r5, 0x08
    bne- rejoin_button_display_msgbox

rejoin_button_gamemode_label:
    BL_CALL(SearchManager_SetGameMode)

    /* Setup screen transition */
    li r0, 0x8F // SearchManager screen ID
    stw r0, 0xF30(r31)

    mr r3, r29
    BL_CALL(Menu_Control_GetTransTimer)
    mr r3, r31
    li r4, 0
    BL_CALL(Menu_Screen_StartTransition)
    b rejoin_button_press_event_end

rejoin_button_display_msgbox:
    lwz r3, 0x13C(r28)
    addi r3, r3, 424
    li r4, 0xFB1
    //li r5, 0
    BL_CALL(Menu_Control_SetAllText)

    mr r3, r31
    li r4, 0x4D
    li r5, 0
    BL_CALL(Menu_Screen_ShowOnTop)

rejoin_button_press_event_end:
    lwz r0, 0x24(sp)
    mtlr r0
    lmw r28, 0x20-0x10(sp)
    addi sp, sp, 0x20
    blr


#ifdef BMG_PATCH
/* wifi_rejoin_button functions */
#define BMG_STRING(MID) (MID - bmg_strings)
bmg_strings:
mid_0xFA5:
.string "Rejoin"
mid_0xFA6:
.string "Rejoin the last room you played."
#ifndef INVISIBLE_BUTTON
mid_0xFB1:
.string "You have not played\na room to rejoin."
#endif
mid_0xFB7:
.string "You were unable to\nrejoin the room.\n\nPlease wait and try\nagain later."
mid_0x1009:
.string "Rejoining room..."
.align 2
.set bmg_strings_size, . - bmg_strings

get_mid_index_func:
    addi r3, r30, 0xF34 + 0x144
    B_CALL(Menu_Mesg_MIDToIndex)

overwrite_mid_func:
    cmpwi r3, -1
    beqlr- // MID doesn't exist

    /* This could probably be much more optimized */
    mflr r12
    PTR(r5, bmg_strings - 1)
    slwi r6, r4, 1
    addi r7, r30, 0xF34 + 0x254
    add r8, r7, r6
    subi r7, r8, 2
    add r5, r5, r4

overwrite_mid_loop:
    lbzu r4, 1(r5)
    sthu r4, 2(r7)
    cmpwi r4, 0
    bne+ overwrite_mid_loop
    mtlr r12
    
    lwz r5, 0xF34 + 0x144 + 4(r30)
    lwz r6, 0xF34 + 0x144 + 8(r30)
    slwi r0, r3, 3
    add r5, r5, r0

    lwz r7, 8(r5)
    lhzx r0, r7, r6
    cmpwi r0, 0
    bnelr- // MID is not blank, so we will not overwrite it

    subf r6, r6, r8
    stw r6, 8(r5) // Hacky file offset overwrite
    blr
#endif

#ifdef CHECK_WW
control_count:
    .long 7 // Control count
#endif

GCT_EXECUTE_END(data)

/* Create memory for the new button */
GCT_WRITE_32(PORT(0x805F3198, 0x80623798, 0x8062404C, 0x80612444),
#ifdef BMG_PATCH
    0x38600F34 + 0x254 + bmg_strings_size*2
#else
    0x38600F34 + 0x254
#endif
)

/* Update control count */
#ifndef CHECK_WW
GCT_WRITE_32(PORT(0x8061866C, 0x8064AFEC, 0x8064B980, 0x80639C98), 0x38800007);
#else
GCT_INSERT(PORT(0x80618670, 0x8064AFF0, 0x8064B984, 0x80639C9C), update_control_count)
    PTR_STW(r4, r9, control_count, 0)
    addi r4, r4, 1
    BL_CALL(Menu_Screen_InitControlList)
GCT_INSERT_END(update_control_count)
#endif

/* Construct new button on WFC menu top */
GCT_INSERT(PORT(0x806188F4, 0x8064B274, 0x8064BC08, 0x80639F20), wifi_rejoin_button)
    /* Construct the button */
    addi r3, r30, 0xF34
    BL_CALL(Menu_Control_Construct)

    mr r3, r30 // Screen class
#ifndef CHECK_WW
    li r4, 6 // Control ID
#else
    PTR_LWZ(r4, control_count, 0)
#endif
    addi r5, r30, 0xF34 // Control class
    li r6, 0 // ?
    BL_CALL(Menu_Screen_InsertControl)

    addi r3, r30, 0xF34
    lis r5, button_str@h
    ori r4, r5, button_str@l // Base folder
#ifndef DRIFT_HELP_BUTTON
    /* Use the unused ButtonGhostBattle element */
    ori r5, r5, WifiMenuSingleTop_str@l // bctrl name
    STRING(r6, "ButtonGhostBattle", btn_name) // bctrl element name
#else
    STRING(r6, "DriftHelp", btn_name) // bctrl element name
    mr r5, r6
#endif
    li r7, 1 // ?
    li r8, 0 // ?
    li r9, 0 // 1 if only selectable by wiimote pointer
    BL_CALL(Menu_Control_LoadLayout)

#ifdef DRIFT_HELP_BUTTON
#ifdef TOUCH_PANE_PATCH
    /* By default the new button wouldn't be selectable because the "touch" panes,
       the panes that decide where the cursor needs to be to select the button,
       of the Worldwide/Regional buttons are too big.
       The Friends button's "touch" is actually a little smaller, so without modifications,
    /  the new rejoin button is only selectable by pressing right there. */
    
    /* Touch pane pointers */
    lwz r3, 0x230 + 0x174 + 0xC(r30)
    lwz r4, 0x484 + 0x174 + 0xC(r30)

    /* I could do a check here (for compatibility) instead of a direct overwrite,
    /  but I don't know what to check :/ */
    lis r5, 0x43FA
#ifdef CHECK_WW
    cmpwi r3, 0
    beq- 8
#endif
    stw r5, 0x4C(r3)
    stw r5, 0x4C(r4)

#endif /* TOUCH_PANE_PATCH */
#endif /* DRIFT_HELP_BUTTON */

    addi r4, r30, 0x94
    stw r4, 0xF34 + 0x238(r30)
    li r4, 6
    stw r4, 0xF34 + 0x240(r30)

#ifdef BMG_PATCH
#define PATCH_MID(MID) \
    li r4, MID; \
    bl get_mid_index_func; \
    li r4, BMG_STRING(mid_##MID); \
    bl overwrite_mid_func

    /* Apply the button BMG patch. MID fa5 and fa6 are normally blank, so we will use those. */
    PATCH_MID(0xFA5)
    PATCH_MID(0xFA6)

    /* Apply other misc BMG patches */
#ifndef INVISIBLE_BUTTON
    PATCH_MID(0xFB1)
#endif
    PATCH_MID(0xFB7)
    PATCH_MID(0x1009)
#endif /* BMG_PATCH */

    addi r3, r30, 0xF34
    li r4, 0xFA5
    //li r5, 0
    BL_CALL(Menu_Control_SetAllText)

    mflr r3
    addi r3, r3, button_select_data - (. - 4)
    stw r30, 0x4(r3)
    addi r4, r3, rejoin_button_press_event - button_select_data
    stw r4, 0x10(r3)
    stw r3, 0xF34 + 0x234(r30)

wifi_rejoin_button_end:
    mr r3, r30 // Original instruction
GCT_INSERT_END(wifi_rejoin_button)


/* It should only display the rejoin button if you have a room to rejoin.
   A main button disappearing would be weird, so I'd recommend only using
/  this for the DriftHelp button. */
#ifdef INVISIBLE_BUTTON
GCT_INSERT(PORT(0x806189B8, 0x8064B338, 0x8064BCCC, 0x80639FE4), set_rejoin_visibility)
    li r0, 1
    PTR_LWZ(r3, rejoin_location, 0) // Group ID
    cmpwi r3, 0
    bne+ rejoin_visible_label
    li r0, 0
rejoin_visible_label:
    stw r0, 0xF34 + 0x244(r31) // If selectable
    stw r0, 0xF34 + 0x174 + 0x70(r31) // If selectable
    xori r0, r0, 1
    stb r0, 0xF34 + 0x80(r31) // If invisible

    li r0, -1 // Original instruction
GCT_INSERT_END(set_rejoin_visibility)
#endif


/* Set back button destination for rejoin button */
GCT_INSERT(PORT(0x805E51B4, 0x806091FC, 0x80609A88, 0x805F7EA8), rejoin_back_dest)
    cmpwi r3, REJOIN
    bne- rejoin_back_dest_end

    li r0, 0x8B
    stw r0, 0x1D00(r31)

    //li r3, -1
rejoin_back_dest_end:
    li r0, 6
GCT_INSERT_END(rejoin_back_dest)


/* Set screen to go to after join failure */
GCT_INSERT(PORT(0x805E5394, 0x806093DC, 0x80609C68, 0x805F8088), rejoin_fail_dest)
    cmpwi r3, REJOIN
    bne- rejoin_fail_dest_end

    li r0, 0x8B
    stw r0, 0x1D00(r31)

    //li r3, -1
rejoin_fail_dest_end:
    li r0, 6
GCT_INSERT_END(rejoin_fail_dest)


/* Set searching text */
GCT_WRITE_32(PORT(0x805E5230, 0x80609278, 0x80609B04, 0x805F7F24), 0x60000000)
GCT_INSERT(PORT(0x805E5234, 0x8060927C, 0x80609B08, 0x805F7F28), set_rejoin_search_text)
    li r4, 0x100A
    cmpwi r0, REJOIN
    bne- not_rejoin_search_text
    
    li r4, 0x1009
    b set_rejoin_search_text_end
not_rejoin_search_text:
    cmplwi r0, 1
    BC_CALL(gt, PORT(0x805E5370, 0x806093B8, 0x80609C44, 0x805F8064))
set_rejoin_search_text_end:
GCT_INSERT_END(set_rejoin_search_text)


/* Set search failure text */
GCT_WRITE_32(PORT(0x805E45C8, 0x80608610, 0x80608E9C, 0x805F72BC), 0x60000000)
GCT_INSERT(PORT(0x805E45D4, 0x8060861C, 0x80608EA8, 0x805F72C8), set_rejoin_fail_text)
    li r4, 0xFB2
    cmpwi r0, REJOIN
    bne- not_rejoin_fail_text

    li r4, 0xFB7
    b set_rejoin_fail_text_end
not_rejoin_fail_text:
    cmplwi r0, 1
    BC_CALL(gt, PORT(0x805E4608, 0x80608650, 0x80608EDC, 0x805F72FC))
set_rejoin_fail_text_end:
GCT_INSERT_END(set_rejoin_fail_text)


/* Save location */
GCT_INSERT(PORT(0x80655C60, 0x80659754, 0x8065A0E8, 0x80648400), save_location)
    lwz r4, 0(r3) // Group ID
    cmpwi r4, 0
    beq- save_location_end

    lbz r4, 5(r3)
    cmpwi r4, 0x05
    beq- save_location_end_label
    cmpwi r4, 0x08
    bne+ save_location_end

save_location_end_label:
    lwz r4, 0(r3)
    PTR_STWU(r4, r12, rejoin_location, 0)
    lwz r4, 4(r3)
    stw r4, 4(r12)

save_location_end:
    li r4, 8
GCT_INSERT_END(save_location)


/* We no longer force regional! */
GCT_INSERT(PORT(0x8064EF10, 0x80652A04, 0x80653398, 0x806416B0), rejoin_loc_match_type)
    lwz r0, 0xE8(r3)
    cmpwi r0, REJOIN_MODE
    bne+ rejoin_loc_match_type_end

    PTR_LBZU(r4, r12, rejoin_location, 5) // Match type

    li r0, 7
    cmpwi r4, 0x05
    beq+ rejoin_loc_match_type_label
    li r0, 9

rejoin_loc_match_type_label:
    lbz r4, -1(r12) // Region ID, if anyone has ever played Regional
    cmpwi r4, 0xFF // 0xFF if Worldwide
    beq+ rejoin_loc_match_type_end
    li r0, -1 // Skip switch

rejoin_loc_match_type_end:
GCT_INSERT_END(rejoin_loc_match_type)


/* Something I spotted to patch (Is this really necessary?) */
GCT_INSERT(PORT(0x8064FEC8, 0x806539BC, 0x80654350, 0x80642668), rejoin_match_patch_1)
    lwz r0, 0xE8(r3)
    cmpwi r0, REJOIN_MODE
    bne+ 8
    li r0, 1
GCT_INSERT_END(rejoin_match_patch_1)


/* New room match mode */
GCT_INSERT(PORT(0x806532A4, 0x80656D98, 0x8065772C, 0x80645A44), rejoin_match_mode)
//.set switch_mode_end, PORT(0x8065336C, 0x80656E60, 0x806577F4, 0x80645B0C)
    cmpwi r0, REJOIN_MODE // New type: 11
    bne+ setup_normal_match
setup_rejoin_match:
    /* Join friend */
    li r0, 10

setup_normal_match:
    cmpwi r0, 1 // Original instruction
GCT_INSERT_END(rejoin_match_mode)


/* Read from rejoin status */
GCT_INSERT(PORT(0x8065523C, 0x80658D30, 0x806596C4, 0x806479DC), swap_friend_status)
    lwz r5, 0xE8(r31)
    cmpwi r5, REJOIN_MODE
    bne+ swap_friend_status_end

    PTR_LBZU(r5, r4, rejoin_location, 4)
    srwi r5, r5, 7
    xori r5, r5, 1
    lbz r6, 1(r4)
    add r3, r6, r5

swap_friend_status_end:
    cmpwi r3, 5 // Original instruction
GCT_INSERT_END(swap_friend_status)


/* Replace join group ID with our own */
GCT_INSERT(PORT(0x8065541C, 0x80658F10, 0x806598A4, 0x80647BBC), swap_group_id)
    lwz r3, 0x25EC(r3) // Normal friend group ID / Original instruction
    lwz r0, 0xE8(r31) // RKNetController->joinType
    cmpwi r0, REJOIN_MODE
    bne- swap_group_id_end

    PTR_LWZ(r3, rejoin_location, 0) // Our group ID
swap_group_id_end:
GCT_INSERT_END(swap_group_id)


/* Setup rejoin room mode */
GCT_INSERT(PORT(0x805E3CBC, 0x80607D10, 0x8060859C, 0x805F69BC), use_rejoin_room_mode)
    lwz r0, 0x1CF4(r31)
    cmpwi r0, REJOIN
    bne- use_rejoin_room_mode_end

    addi r3, r31, 0x190
    li r4, 0xFA5
    //li r5, 0
    BL_CALL(Menu_HeaderText_SetText)

    lis r29, RKNetController_sInstance@ha
    lwz r4, 0x18C(r31)
    lwz r3, RKNetController_sInstance@l(r29)
    BL_CALL(RKNetController_SetupWWVS)
    lwz r3, RKNetController_sInstance@l(r29)
    li r4, REJOIN_MODE // Rejoin room mode
    stw r4, 0xE8(r3)

    li r0, -1 // Skip switch
use_rejoin_room_mode_end:
GCT_INSERT_END(use_rejoin_room_mode)
Reply
#2
Wow. Amazing code!! Is it fully tested? Is it safe to use on Wiimmfi?
Reply
#3
(10-05-2020, 05:58 PM)mapnov Wrote: Wow. Amazing code!! Is it fully tested? Is it safe to use on Wiimmfi?

I think it's been tested enough, and it is safe to use on Wiimmfi. It was entirely developed using Wiimmfi.
Reply
#4
Great stuff! Smile
Discord: Alina.#6309
Twitter: @RMCW01

[Image: Screenshot_2021-02-15_184623.png]
Reply
#5
Is it possible to modify this code to deny rejoining the room you disconnected from?
Reply
#6
Does this code work for Frooms?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)