You're correct, you need a FAR pointer to access memory at arbitrary locations, such as CGA at B800:0000. If you can inline assembler, this becomes a lot easier, as you can just set ES:DI directly to B800:0000 and DS:SI to the source of your graphics. Good luck!
Recent community posts
From the primary author of GCC-IA16: "This is true of the Mentor version. Since then, TK Chia has made some patches to add far pointer support. I haven't tried them yet and don't know where to get a binary (perhaps I'll try to make a new release at the start of April). I have heard that the FreeDOS folks have had some success with Chia's version and can now use that to build instead of Watcom, so if you can track down one of those guys they might have a good lead. Searching twitter for gcc ia16 might be a good start. "
My personal advice is to try to work within near pointers. Far pointers is something you do because you have to, not because you want to.
You have a few options in 2017 for making 16-bit DOS games coming from a 32/64-bit GCC background: An old 16-bit compiler like Borland C or Turbo C; OpenWatcom which can compile to a 16-bit output; or probably the best option, a newly-released toolchain based on GCC 6.2 available here: https://blogs.mentor.com/embed... (if the link didn't make it through, google for "Sourcery CodeBench Lite for IA16").
My DOS retrocoding is in a mix of Turbo Pascal and assembler, as the TP IDE allows coding/debugging on the old hardware itself. But I'm old, and quite insane.