Digging into this further I found something that might be what I'm looking for, SvxLink.
While this might work I'm still curious about other options. Once I clean up some computer and network issues about the house I'll play with this.
You can find the code in packjt77.f90. Callsign encoding (for "standard" callsigns that don't require hashing) is in function pack28. A quick summary:
Adjust a few strange prefixes that don't follow the usual arrangement of letters and numbers. Swaziland 3DA0* will be encoded as if it was 3D0* instead, and Guinea 3XA1A will be encoded as if it was QA1A ...