Regarding the Bilinear filtering:
What I do is a two-stage filtering system. First, use a nearest-neighbour algorithm to scale to the nearest integer scaling. For example, if you're running at say, 800x600 and your "screen" is 320x256 then you'd scale to 640x512. This will render with nice sharp pixels.
Then you scale up (or down) from there to 800x600. The pixels still appear sharp, but the minimal bilinear filtering applied smooths out the jaggies without blurring.
If you've got a current copy of zxspin, you can see this option working if you select Direct3D rendering and "reduce filter blurring" in the display options/effects tab. The only drawbacks are a very slight performance hit and the increased video-ram usage due to the intermediate stage.