Over the years I've developed several pseudo 3D renderers similar to Wolfenstein 3D for various bits of hardware. Most recently Catacombs Of The Damned! for the Arduboy which runs on an Atmega chip with only 2.5KB of RAM. I also developed a demo for the Uzebox, another microcontroller based console which works without a framebuffer and generates a composite signal on the fly in software.
I recently acquired a Sharp PC-3000 which is an XT compatible DOS based palmtop computer (although higher clocked) and was considering the possibility of writing a 3D renderer for it. I was hoping to pick the brains of those who are familiar with the XT class hardware!
For a high level overview of what I was considering:
It certainly looks like it could be too much for such a limited system, so here are some of my thoughts of corner cutting:
Does anyone with experience with the real hardware think that this would all be possible to do at an interactive framerate? Any obvious shortfalls or better ways of approaching the above?
I recently acquired a Sharp PC-3000 which is an XT compatible DOS based palmtop computer (although higher clocked) and was considering the possibility of writing a 3D renderer for it. I was hoping to pick the brains of those who are familiar with the XT class hardware!
For a high level overview of what I was considering:
- The 3D effect will be built using vertical 'slices' similar to Wolf3D. Could use raycasting, BSP or portals to build a 1-D array which stores for each screen column, the scale of the wall and which slice of texture to use.
- Each slice can then be rendered by using a 'coded scaler', similar to Wolf3D (it is described in detail in Fabien Sanglard's Wolfenstein Black Book) Essentially, at load time, you generate a set of specialised functions for rendering wall slices at different sizes in an unrolled loop, so that you can avoid calculating the scaling at run time.
- Sprites are drawn in a similar way to walls by rendering slices with scaler functions, but with some changes to handle transparency.
It certainly looks like it could be too much for such a limited system, so here are some of my thoughts of corner cutting:
- The first easy win: render the 3D portion in a smaller window at e.g. 256x128 (which works out to about 50% of the framebuffer pixels) with the rest of the screen having a nice border, status bar etc
- The renderer could be set up to support both 320x200 4 colour and 160x200 composite colour modes. In the 4 colour RGB mode, use vertical stripe / dither patterns to fake extra colours. Effectively render at 160x200 in both modes. With the reduced size window this is actually 128x128 logical size.
- Rendering at this resolution means that instead of 2 bits per pixel, it is effectively like rendering at 4 bits per pixel / one nybble per pixel. This still complicates all the rendering functions somewhat: to write a pixel, you have to first read the relevant byte, mask it, shift your value, OR it, write it back. Since the CGA card only has enough VRAM to store one framebuffer, for a renderer like this you would need to store a buffer in main RAM and then copy the contents to VRAM once you have finished. It then struck me: the buffer in main RAM could be stored at 1 byte per pixel (which works out to 16K with the 256x128 window), and the routine that blits to VRAM could be a big unrolled loop which squashes it back down into the 4 bits per pixel format as it writes to VRAM. With some special care, the scaling routines could output either the high or low nybble depending on if it is an even or odd column, so the inner loop of the blit routine could be as simple as 2 word reads, 2 OR instructions, and one word write.
- If the texture maps are simplified, e.g. all walls have a very basic brick pattern, then the texture details themselves can be coded right into the wall scaler functions so texture details don't have to be loaded from RAM.
Does anyone with experience with the real hardware think that this would all be possible to do at an interactive framerate? Any obvious shortfalls or better ways of approaching the above?