It is possible to change it with HW indeed although it is not very simple because it requires script editing.
In the panel "Environment -> Fields", you need to find the field in which a new character joins (for Quina, it's the marsh's pond for example; for Freya it's the Lindblum's pub because that's where you name her).
Then "Edit Script" and find the lines initializing the character's datas. For Freya, they look like that for instance:
SetCharacterData( 4, 0, 4, 6, 4 )
Wait( 5 )
Menu( 1, 4 )
Wait( 10 )
set VAR_GenUInt8_6 |= 16
The point is to empty the party reserve right before the "SetCharacterData" call, because levels will be initialized by averaging the current party's levels (not only taking Zidane's level into account). And then you need to put the reserve back to what it should be. For instance, still about Freya:
SetPartyReserve( 0 )
SetCharacterData( 4, 0, 4, 6, 4 )
SetPartyReserve( Setting_PartyReserve )
Wait( 5 )
Menu( 1, 4 )
Wait( 10 )
set VAR_GenUInt8_6 |= 16
Then parse the function and validate everything.
The characters' datas are initialized in these functions:
Freya: Function Main_Loop of Lindblum/The Doom Pub (571)
Quina: Function Main_Loop (near the end) of Marsh/Pond (657)
Eiko: Function Main_Loop of Mountain Path/Trail (1550)
Amarant: Function Zidane_Loop (in case 113) of Mdn. Sari/Entrance (1600)