I’ve been coding a basic line buffer renderer for the XGS, I say basic because firstly it’s two colour (one being black) and secondly it’s still in need of a good optimisation.

The current code takes up just under one page (<512 words). With a lot of spare cycles there’s the opportunity to reduce the code size whilst still meeting the tight timing criteria. The largest chunk of the 512 words is taken up by the numerous uses of the DELAY macro in generating the HSYNC delays, shifting this to a subroutine would make quite a difference.

Line Buffer

The buffer itself handles 200 pixels with 4 pixel padding either side, giving a horizontal resolution of 200 active pixels and 8 overscan. Vertically it uses 208 active lines with 48/52 lines for top/bottom overscan and 4 vsync lines totalling 312 vertical lines. Although I’m considering reducing the overscan lines and increasing vsync to 10 lines to provide a greater number of spare cycles in one chunk for gameplay logic.

The line buffer uses 25 bytes of internal RAM (banks 1 & 2) for storage with each byte holding 8 pixels (thus the reason for single colour only)

The line buffer is populated during each of the hsync periods utilising the spare cycles. During the active line period the code generates the required tv signal to output each pixel of the line buffer with only 20 cycles (250ns) per pixel available.

Spare Cycles

Currently the biggest question is whether 900 cycles will be enough time to generate 200 pixels worth of data and cache it to the line buffer banks. With a player sprite, enemy sprites and missiles in the mix the cycle count could be quite tight.

The main rendering loop still has quite a few cycles to spare, around 12 per pixel, however using these will mean tightly coupling the line buffer generation with the rendering, which is something I would like to avoid.

Although not in place yet, the plan is the for game logic to run during vsync, which assuming we use 10 lines would provide just over 50,000 cycles for game logic. A further 420k cycles are available during the overscan generation which means there’s plenty of room for gameplay logic and music.


Part way through building the line buffer I attempted to generate a pal signal with the colour GREEN for an on pixel and BLACK for an off pixel. However, my TV would not recognise the signal as PAL with colour only output when using the NTSC setting.

PAL has a few extra requirements1 to NTSC.

  1. Colour burst on alternative lines must be phase shifted +- 45 degrees
  2. Each colour output must be phase shifted by 180 degrees on alternative lines

With James' help and a fair amount of time reading the PAL specs and XGS specs, the TV finally detected the PAL signal and displayed bars in all their colour.

XGS PAL Output

XGS PAL Output

Next step will be finalising the hsync callback code to render a player sprite under joystick control.

At a later date I’ll probably look into increasing the size of the line buffer to 100 bytes which would allow 200 pixels at a bit depth of 4. Then increasing the sprites from an 8bit x 8bit block to support 4 bits of colour information per pixel. Using a palette this would allow for 16 colours.

A larger bit depth is plausible especially if the buffer is moved to the external SRAM, however doing so may require some creative thinking in order to meet the timing requirements of 20 cycles per pixel.

Once the code is more functional and rendering a few sprites I’ll get it uploaded, perhaps with a pdf explaining everything for any XGS owners who are interested

  1. Forum post detailing this no longer exists ( ↩︎