Updated quite a bit to make it easier to port