I think I need to offer a retraction. It could be that mp3tag is the one getting it right and it could be that foobar2000 doesn't display non-native fields.
I'm not sure why I've kept going with this.... Not knowing was bugging me once I started, I guess.
According to MediaInfo, fb2k writes INVOLVEDPEOPLE as a TXXX frame.
00000A TXXX - User defined text information frame (103 bytes)
00000A Header (10 bytes)
00000A Frame ID: TXXX
00000E Size: 93 (0x0000005D)
000012 Flags: 0 (0x0000)
000014 Tag alter preservation: 0 (0x0000000000000000)
000014 File alter preservation: 0 (0x0000000000000000)
000014 Read only: 0 (0x0000000000000000)
000014 Compression: 0 (0x0000000000000000)
000014 Encryption: 0 (0x0000000000000000)
000014 Grouping identity: 0 (0x0000000000000000)
000014 Text_encoding: 1 (0x01)
000015 Short_content_descrip: INVOLVEDPEOPLE
000033 Null: 0 (0x0000)
000035 The_actual_text: Role1:Person1;Role2:Person2;
000071 Padding (2048 bytes)
000071 Data: (2048 bytes)
MusicBrainz Picard does the same, although it seems to create an (empty?) IPLS too.
000063 IPLS - Involved people list (11 bytes)
000063 Header (10 bytes)
000063 Frame ID: IPLS
000067 Size: 1 (0x00000001)
00006B Flags: 0 (0x0000)
00006D Tag alter preservation: 0 (0x0000000000000000)
00006D File alter preservation: 0 (0x0000000000000000)
00006D Read only: 0 (0x0000000000000000)
00006D Compression: 0 (0x0000000000000000)
00006D Encryption: 0 (0x0000000000000000)
00006D Grouping identity: 0 (0x0000000000000000)
00006D Data: (1 bytes)
00006E TXXX - User defined text information frame (103 bytes)
00006E Header (10 bytes)
00006E Frame ID: TXXX
000072 Size: 93 (0x0000005D)
000076 Flags: 0 (0x0000)
000078 Tag alter preservation: 0 (0x0000000000000000)
000078 File alter preservation: 0 (0x0000000000000000)
000078 Read only: 0 (0x0000000000000000)
000078 Compression: 0 (0x0000000000000000)
000078 Encryption: 0 (0x0000000000000000)
000078 Grouping identity: 0 (0x0000000000000000)
000078 Text_encoding: 1 (0x01)
000079 Short_content_descrip: INVOLVEDPEOPLE
000097 Null: 0 (0x0000)
000099 The_actual_text: Role1:Person1;Role2:Person2;
0000D5 Padding (6804 bytes)
0000D5 Data: (6804 bytes)
Mp3tag does create an IPLS frame (when saving INVOLVEDPEOPLE) but MediaInfo doesn't tell me what it contains. I don't know if that's normal.
00000A IPLS - Involved people list (39 bytes)
00000A Header (10 bytes)
00000A Frame ID: IPLS
00000E Size: 29 (0x0000001D)
000012 Flags: 0 (0x0000)
000014 Tag alter preservation: 0 (0x0000000000000000)
000014 File alter preservation: 0 (0x0000000000000000)
000014 Read only: 0 (0x0000000000000000)
000014 Compression: 0 (0x0000000000000000)
000014 Encryption: 0 (0x0000000000000000)
000014 Grouping identity: 0 (0x0000000000000000)
000014 Data: (29 bytes)
000031 Padding (2048 bytes)
000031 Data: (2048 bytes)
When I create a mapping for mp3tag to map IPLS to INVOLVEDPEOPLE, a field saved as INVOLVEDPEOPLE also becomes TXXX. That explains why fb2k sees it.
mp3tag tag saves IPLS as TXXX (without the previous mapping). fb2k and MusicBrainz Picard save IPLS the same way.
The problem when saving a tag with TagBox wasn't the removal of the semi-colon from the field value as I thought. On closer inspection it's also inserting a space when saving. That's seen as two TXXX frames by MusicBrainz Picard, mp3tag and MediaInfo. Only fb2k displays it as a single IPLS frame.
00000A TXXX - User defined text information frame (53 bytes)
00000A Header (10 bytes)
00000A Frame ID: TXXX
00000E Size: 43 (0x0000002B)
000012 Flags: 0 (0x0000)
000014 Tag alter preservation: 0 (0x0000000000000000)
000014 File alter preservation: 0 (0x0000000000000000)
000014 Read only: 0 (0x0000000000000000)
000014 Compression: 0 (0x0000000000000000)
000014 Encryption: 0 (0x0000000000000000)
000014 Grouping identity: 0 (0x0000000000000000)
000014 Text_encoding: 1 (0x01)
000015 Short_content_descrip: IPLS
00001F Null: 0 (0x0000)
000021 The_actual_text: Role1:Person1
00003F TXXX - User defined text information frame (53 bytes)
00003F Header (10 bytes)
00003F Frame ID: TXXX
000043 Size: 43 (0x0000002B)
000047 Flags: 0 (0x0000)
000049 Tag alter preservation: 0 (0x0000000000000000)
000049 File alter preservation: 0 (0x0000000000000000)
000049 Read only: 0 (0x0000000000000000)
000049 Compression: 0 (0x0000000000000000)
000049 Encryption: 0 (0x0000000000000000)
000049 Grouping identity: 0 (0x0000000000000000)
000049 Text_encoding: 1 (0x01)
00004A Short_content_descrip: IPLS
000054 Null: 0 (0x0000)
000056 The_actual_text: Role2:Person2
000074 Padding (2048 bytes)
000074 Data: (2048 bytes)
So it looks I was wrong about much of it. Chances are, mp3tag is remapping INVOLVEDPEOPLE to IPLS correctly and fb2k won't display it, MusicBrainz Picard displays it incorrectly, and MediaInfo won't tell me what it contains for some reason.
I hadn't noticed before, but when the only frame save to an ID3v2 tag is IPLS, courtesy of mp3tag, fb2k doesn't see the MP3 as having a tag at all. I hadn't noticed before because I was testing with mp3s that already had tags. It would have been a hint that fb2k was ignoring IPLS, otherwise.
As a side note, if you tell fb2k to optimise such an mp3, it removes the padding while apparently ignoring everything else.
Before:
00000A IPLS - Involved people list (77 bytes)
00000A Header (10 bytes)
00000A Frame ID: IPLS
00000E Size: 67 (0x00000043)
000012 Flags: 0 (0x0000)
000014 Tag alter preservation: 0 (0x0000000000000000)
000014 File alter preservation: 0 (0x0000000000000000)
000014 Read only: 0 (0x0000000000000000)
000014 Compression: 0 (0x0000000000000000)
000014 Encryption: 0 (0x0000000000000000)
000014 Grouping identity: 0 (0x0000000000000000)
000014 Data: (67 bytes)
000057 Padding (2048 bytes)
000057 Data: (2048 bytes)
After:
00000A IPLS - Involved people list (77 bytes)
00000A Header (10 bytes)
00000A Frame ID: IPLS
00000E Size: 67 (0x00000043)
000012 Flags: 0 (0x0000)
000014 Tag alter preservation: 0 (0x0000000000000000)
000014 File alter preservation: 0 (0x0000000000000000)
000014 Read only: 0 (0x0000000000000000)
000014 Compression: 0 (0x0000000000000000)
000014 Encryption: 0 (0x0000000000000000)
000014 Grouping identity: 0 (0x0000000000000000)
000014 Data: (67 bytes)