update with latest changes (thanks to PhilZ for most of this)