Tuesday, August 23, 2011

Paletted 256 colour mode

ZX Prism currently has 3 different screen modes. The first is, of course, the standard ZX Spectrum mode (256x192 pixels, 8 colours, 2 per 8x8 attribute square, 2 brightness levels - 1 only per 8x8 attribute square). The second is a 32 colour mode as pictured in a previous blog entry (256x192 pixels, 8 colours, 2 per 8x8 attribute square, 4 brightness levels, 1 per 8x8 square).

The third mode is the one which I've been working on recently and had success with last night. It's one of several proposed 256 colour modes. This one uses the attribute byte to determine the logical ink colour (0-255). The paper colour is determined by the ULA2 border colour stored in a latch at 0x4E3B.

Testing 256 colour mode (mode 72) - random palette

Testing 256 colour mode (mode 72) - random palette

Atic Atac loading in 256 colour mode with a randomised palette.
Note the effects of the timing issue on the Ultimate logo
The rainbow stripes don't work when there's only one paper colour!

(C) 1982 Sinclair Research in lime green. 
It had to be done.

There are a number of bugs/"features" with this mode:

  • Background colour is dictated by the ULA2 border colour. The ULA2 border is only active when the ULA border is set to black (BORDER 0). Careful manipulation of the ULA2 border colours during the screen refresh should be able to increase the number of colours on-screen. Other, similar effects can be achieved by switching screen mode at appropriate times during screen refresh.
  • It follows that setting the ULA border to a colour other than black means you can have a border that doesn't match the 'paper' colour. If the ULA border colour isn't matched in the 256 colour palette, then you have an extra colour on-screen (if anyone's counting).
  • A noise effect is notable on the colour whose palette entry is being updated due to lack of contention on the dual-port palette RAM. This could potentially be fixed, however it could also be exploited as a special effect. For now I'm leaving it alone.
  • The pixel colour can be selected from BASIC by manipulating ink, paper, bright and flash values. 
  • As can be seen from the pictures - there are timing issues caused by the palette lookup cycle (at least I think this is the cause). These will need to be fixed, however the display being created is stable, and the which is very encouraging. 
Having a single paper colour for the whole screen isn't particularly useful for detailed graphics. Other similar paletted modes are to be implemented which will be more useful:
  • 16 inks, 16 papers. Paletted. 2 colours in each 8x8 attribute square
  • 32 inks, 8 papers. Paletted. 2 colours in each 8x8 attribute square
  • 64 inks, 4 papers. Paletted. 2 colours in each 8x8 attribute square
  • 128 inks, 2 papers. Paletted. 2 colours in each 8x8 attribute square
  • 256 colours, Paletted. 2 colours in each 8x8 attribute square. 2 byte attributes.
  • The above modes, but with 8x1 pixel attributes.
  • ULAplus mode (see http://www.zxshed.co.uk/sinclairfaq/index.php5?title=ZX_Spectrum_64_Colour_RGB_Mode )

Sunday, August 21, 2011


One other major thing that has changed recently in ZX Prism is the master clock frequency.

Mike's original FPGA Spectrum source derives the CPU and video clocks from a 28MHz phase locked loop. The 14MHz video clock was derived from every odd tick (equalling four ticks for every eight of the master clock: 1,3,5 and 7) and the 3.5MHz CPU clock was derived from the first even tick of every eight (tick 0). The 7MHz CPU mode was derived from ticks 0 and 4.

Recently, to prepare for the more complex video modes and to allow faster CPU clock frequencies I doubled the master clock frequency to 56MHz. For now, I've adjusted the way the CPU and Video clocks are derived so they still run at 14Mhz and 3.5 or 7MHz.

The on-FPGA palette memory seems quite happy at these speeds, so all is looking good for the new screen modes.

The next thing to do is to increase the video clock to 28Mhz and adjust the read/store cycle for reading the data and attribute bytes. Some of the new screen modes need more data to be shifted around than the standard Spectrum mode. I'll be attempting to do the majority of the screen modes with the same contention patterns (at least when the CPU is running at 3.5Mhz) so that games with special screen effects (split borders etc) work. The chunky and planar screen modes will probably incur more contention - though the CPU speed can be increased to compensate of course.

Speaking of contention... I've still not had complete success with implementing it - however I am a lot closer now. The increase in master clock frequency and the redesign of the video decode/encode subsystem gives me a chance to change how the timing of everything fits together - including ensuring contention is correctly applied at faster CPU speeds to avoid the crashes that currently happen when the CPU is running at 14 or 28MHz. Time to get the pencils and paper out and start counting clock ticks...

Mode switching

Recently, I've been doing a number of tests of different attribute byte decoding schemes, but of course the ultimate goal has always been to be able to switch screen mode from basic or machine code. Today I made inroads into making the screen mode switchable. An 8 bit latch at 0x1E3B serves as the screen mode selector. 5 bits controls how the video data is decoded to determine pixel colour. The remaining 3 bits control the screen resolution: M4 M3 M2 M1 M0 R2 R1 R0

Currently I have 3 screen modes implemented:
  • 00000xxx - Normal Spectrum mode ( Fl Br P2 P1 P0 I2 I1 I0 )
  • 00001xxx - 32 colour mode (Br1 Br0 P2 P1 P0 I2 I1 I0)
  • 01010xxx - 256 colour mode, paletted (I7 I6 I5 I4 I3 I2 I1 I0), paper=border colour
(key: Fl = flash, Br=bright, Px=paper, Ix=ink)

In the 256 colour mode, the paper colour is determined by the 256 colour border colour stored in another 8 bit latch at 0x4E3B. The 256 colour border is available in all modes when the "normal" spectrum border is set to colour 0.

This is a paletted mode, and by default all colours are set to black. The palette is controlled as follows:

OUT 48699,colour number
OUT 65083,red level
OUT 65083,green level
OUT 65083,blue level

The colour to be redefined is stored in a counter at 0xBE3B. Then the red,green and blue levels for that colour are output to 0xFE3B. Each successive write to 0xFE3B goes to the next colour element - red, then green, then blue. After the blue level is written, the colour number increments and therefore a subsequent write to 0xFE3B will define the red level for the next colour and so on.

Initial tests of the paletted mode are encouraging. The colours are able to be redefined, however there are some interesting effects due to timings which will need to be ironed out.

Sunday, August 14, 2011

Progressing slowly....

This past weekend has seen a number of steps forward. The unpaletted 32 colour mode proof-of-concept code was expanded to allow the border to be one of 256 colours (bits 7..0 equating to 2 bits blue, 3 bits green, 3 bits red - BbGggRrr). This tested the ULAplus-style 8 bit palette.

The border is currently controlled by an OUT to an 8 bit latch and currently replaces the usual 3 bit border. Another latch has been implemented which selects the CPU speed and in the future will also reflect "machine type" (or at least which memory paging system to use). Setting and unsetting bits 0 and 1of this latch selects between the 4 CPU speeds implemented.
  • 00 - (default) 3.5MHz
  • 01 - 7Mhz
  • 10 - 14Mhz
  • 11 - 21Mhz
As at this point only 3.5MHz and 7Mhz modes work correctly. 14MHz doesn't work yet as the video ram is on the same data and address bus as "normal" (uncontended) RAM and memory contention isn't yet implemented. Likewise, 21MHz causes bus collisions (and some rather pretty crashes)

Speaking of implementing memory contention. At 3.5Mhz I want this to be as accurate to ZX Spectrum timings as possible.  My attempts thus far to implement ANY sort of delay when the CPU address space is within video RAM have been unsuccessful:

  • Machine seemed to run as usual. Could load from tape successfully. Aquaplane's border effect switches colour around 12 lines early - this is the same as without the contention circuit. Conclusion: contention enabling logic was incorrect.
  • Machine seemed to run as usual. Loading from tape was unsuccessful - pilot tones were detected, but data wasn't correctly decoded. Conclusion: CPU was being disabled for too many cycles.
  • Machine seemed to run as usual. Loading from tape was unsuccessful - pilot tones were not detected. Conclusion: CPU was being disabled for too many cycles.
  • Machine displayed garbage on screen and didn't initialise. Conclusion: as soon as contention was applied, the CPU was effectively halted (this was backed up by monitoring the address bus)
Additionally, I've confirmed that code using the R register fails consistently. Speedlock 1 works right up until the loading completes and then crashes. Most machine test suites (ulatest3, fusetest etc) fail spectacularly - the two aforementioned test suites crash in fact. 

I shall revisit memory contention later. For now, I can live with the fact that some software which relies on cycle-accurate memory contention (eg for border effects) will look odd. The crashes and apparently incorrect CPU behaviour is more of an issue, but again I can do little about it at the moment. The T80 code isn't well documented at all and I'm still learning the ropes with VHDL really. A little bird tells me that someone working on another "advanced Spectrum" style project has done some bugfixes to command timing and flag behaviour, so I'm hoping they'll share them with other T80 users in the future.

Finally, I talked to Andrew Owen regarding reserving a block of IO addresses in the ZXI standard. This means that the ZX Prism's IO addressing won't clash with any other ZXI certified device, for example Spectranet and ULAplus (though of course ZX Prism will be providing ULAplus functionality at its usual ports anyway). This is especially important if I intend to add an edge connector to ZX Prism so that it can use existing ZX Spectrum peripherals like divIDE etc, or should I build a plug-in for a standard ZX Spectrum which provides some or all of the ZX Prism's extended functionality.

The range I have been allocated is xE3Bh which gives me 16 IO addresses which should be plenty. Currently I've earmarked:
  • 0E3Bh - ZXPrism hardware control (CPU speed, memory paging method select, etc)
  • 1E3Bh - ZXPrism screen resolution select/attribute decode method select
  • 4E3Bh - Border colour
  • 6E3Bh - Memory Page at 8000h
  • 7E3bh - Memory Page at C000h
  • BE3Bh - (write only) ULA2 palette (colour select)
  • FE3Bh - (write only) ULA2 palette (R/G/B data)
Currently I'm planning using 16K memory pages (per Spectrum 128/Scorpion/Pentagon). This may change to 8K pages (Timex/Spectrum SE/ZX81) or be switchable, however I don't want the memory bank switching to become too complicated.  

Tuesday, August 9, 2011

32 colours!

Today I started rewriting Mike's video code. As a test, I disabled FLASH and used bit 7 of the attribute byte to make a 2-bit BRIGHT: 4 different brightness levels of 7 different colours plus 4 identical shades of black... So technically 29 colours.

Obviously I made the non-bright, non-flash colour level a little too dark, but as a test it sufficed admirably.

Yesterday out of interest I ran a number of test suites with interesting results. ULAtest3 completely crashed - reset the machine. Fusetest did a few tests and then crashed. Z80test failed on all MEMPTR tests and most of the register tests involving the R flag. Taking another look at Mike's VHDL I noticed he's using the T80se core - and it states that it doesn't match true Z80 timings. It's also an older version. I'll download the latest version of the normal T80 core and see if I can replace it.

Finally, here's a picture of Aquaplane showing the broken border effect due to issues with the T80se core having different timings and the lack of bus contention. 

Sunday, August 7, 2011

More testing

Today I looked at some other open-source FPGA based Spectrum compatibles but had very limited success. Nonetheless, there were some interesting ideas in the implementations which might be drawn on later.

In short, I'll be pulling some ideas (and perhaps using a bit of code) from ZXGate and from the 128 Spectrum implementation which is part of Alex Freed's FPGApple - but the basic foundation of ZX Prism will be the T80 open core Z80, and some of Mike Stirling's FPGA Spectrum code.

Further testing of Mike's Spectrum, with the likes of Aqua Plane and reading some of the comments in his VHDL code confirmed my suspicions - as the implementation handles bus arbitration differently, there are speed differences between it and a real Spectrum when the CPU wants to use the video RAM at the same time as the video circuit.

So my first task will be to make some alterations to make a nice sturdy "foundation" for all the bolt-ons mentioned yesterday to bolt onto:

  • To use the DE1's FLASH memory for its ROM
  • To use the DE1's SDRAM instead of the SRAM
  • To more accurately emulate the Spectrum's floating bus and contended RAM

Saturday, August 6, 2011

We have lift-off

Today I trialled Mike Stirling's open source FPGA Spectrum on the DE1. I successfully loaded Atic Atac from tape with no problems but Beach Head failed - possibly because of a loading error or possibly due to Speedlock 1 being quite... finicky.

The spectrum screen is slightly misplaced on the display - there's a blank area before the border starts on the left. A few tweaks to the clock code didn't help this but I didn't spend much time on it - at the moment I'm looking at a number of open source FPGA Spectrum solutions to select which one I wish to use as a basis for the Prism - or I might use bits and bobs from different solutions. Basically I just need a basic framework on which to add my mods/extensions.

Currently, using Mike's code, the Prism is as follows:

  • 48K Spectrum compatible
  • Tape Input
  • PS/2 keyboard interface
  • Switchable VGA/RGB output

When deciding which code framework to start from I'll also be looking at ZXGate (which does Spectrum, ZX81 and Jupiter Ace) and another which is an offshoot from an FPGA Apple machine and emulates a Spectrum 128. All look to have their benifits (ZXGate has the '81 support, the other has 128 memory paging etc and Mike's was written on the DE1 hardware which I'm using for Prism)

Planned mods/extensions:

  • Expanded memory - probably 1024K 
  • 64K video RAM
  • Pentagon 1024/Spectrum 128/+3 CP/M compatible memory paging 
  • 8K paging mode (towards ZX81/Timex/Spectrum SE compatibility) will also help when using some expanded screen modes
  • ULAplus compatibility
  • 256x192, 256x384, 512x192 and 512x384 screen resolutions
  • 8x8 and 8x1 screen attributes (8 bit attributes - either ULA or ULAplus)
  • 8x8 screen attributes (16 bit attributes - 256 colours, paletted)
  • 256x192 "chunky" 256 colour mode - 1 byte per pixel
  • 256x192 16 colour "planar" mode (paletted/RGBI)
  • ZX81 compatible text mode
  • possibly other text modes
  • Look at hardware flicker-free multitech/gigascreen modes
  • Built in magic button (multiface-esque)
  • Expanded sound - "beeper", AY ACB/ABC stereo and SID
  • Support for adding a real SID and/or AY
  • DivIDE
  • +3 disk interface
  • "fast" modes - CPU speeds selectable 3.5, 7, 14, 28 MHz, possibly faster
  • Kempston/AGP and Sinclair joystick interfaces on break-out board
  • K-Mouse interface on break-out board