Sunday, July 27, 2014

Screen decoding

As you may have noted from previous posts, ZX Prism goes through a number of different stages to convert values in memory into what's displayed on the screen.

Firstly, the addresses in VRAM to be read are calculated; this takes into consideration a number of things: the type of mode being displayed - (standard (pixel+attribute), 16bit attribute (pixel+2 attribute), planar, text, tiled), the size of attribute (8x8, 8x1) etc. The appropriate parts of memory are then read.

If a planar screen mode is selected, the pixel data from each plane is combined to produce a "logical colour" number. If a pixel+attribute screen mode is selected data is then decoded using a selectable attribute decode method, producing a "logical colour" number.

Finally, the logical colour number is decoded into a physical colour - There are three selectable palettes to do this.

The Default palette's first 16 colours are mapped to be the same as the colours on the ZX Spectrum (including colour 8 - "bright black" being identical to colour 0). The next 16 colours are the same again except duller.

There is also a fully redefinable 256 colour palette. Finally, there's a palette which is directly mapped to the 256 colours available to choose from in ULAplus (this palette is automatically selected when ULAplus is used)

These different parts of the screen data decoding process are all controlled using ZX Prism's 4-bit control registers. The registers are manipulated with an OUT to port 0x8E3B (36411).

The value to be sent to port 0x8E3B is constructed as follows: The most significant 4 bits of the value choose the register to be written to (in the case of the attribute decode method, this is register 3 - "0011" in binary). The least significant 4 bits of the value is the data to be sent to the register. Again, using attribute decode method as an example:

0000 selects Spectrum attribute decode (3 bits ink colour, 3 bits paper colour, 1 bit bright, 1 bit flash)
0001 selects 16+16 attribute decode (3 bits ink, 3 bits paper, 1 bit bright for ink, 1 bit bright for paper)
0010 selectes 32 colour mode (3 bits ink, 3 bits paper, 2 bits bright)
0100 selectes 256 colour mode 1 (8 bits ink colour, paper colour is same as the border colour)
0110 selects 16 colour planar mode (which doesn't use an attribute byte at all!)

    OUT 36411,48 selects spectrum attribute decode
    OUT 36411,49 selects 16+16 mode
    OUT 36411,50 selects 32 colour mode
    OUT 36411,52 selects 256 colour mode 1

256 colour mode 1, default palette

16+16 mode - you can see instances of bright ink over non-bright paper and vice-versa)

32 colour mode - 4 levels of bright

256 colour mode 1, but with the ggggrrrrbb palette

Thursday, July 24, 2014

Getting intense...

Yesterday I wired up the remaining lines on the video DACs. ZX Prism now has more than 8 colours - in fact it has a total of 4096 colours available (though currently you can only choose up to 256 of them for use at one time).

I again tested the 4-plane planar mode with RGBI attribute decoding. When doing so, I initially forgot to put the appropriate test data back into the VRAM pages - instead four loading screens were loaded (from an earlier 512x384 test). What resulted was both a complete mess and also a great demo of planar mode, so I decided to take a picture and put it up here.

Can you work out which game was loaded into which bitplane?
For fun, I did another one too...

Saturday, July 19, 2014

16 Colour Planar Mode Revisited

So the toesocks in last post's 'planar mode' screenshots looked a little different to those in the gigascreen screenshot... I initially thought it was because I'd gotten the planes muddled up, but it turned out that my test data was inverted! (Thanks again to Guesser for swiftly providing me with corrected test data) OK, so I did also get the plane data muddled - but only once! Anyway, here's a couple of planar mode screenshots to give a rough idea of what can be done. I'm not an artist, so just used an automated tool to convert the prism+planets image... it didn't turn out great ;)

Thursday, July 17, 2014

16 Colour "colour-clash free" planar mode and Hardware Gigascreen

I put a plea out on the World of Spectrum forums for somebody to help me by producing some test screens in different formats. Guesser very quickly produced some files which enabled me to implement and test the 16 colour planar mode. This worked great first time, except that I forgot that the Spectrum's colours are in order of intensity, not in RGB binary order so I loaded the colour planes into the wrong VRAM pages. Oops. Well, you live and learn... What's more, when I tried to fix the order I got it wrong again. D'oh.
256x192 16 colour planar... with the bitplanes loaded into the wrong VRAM pages so the colours are muddled. Oops.

Take 2... still not right, but it proves the mode works - the colours being wrong are 50% me being distracted by baby and 50% me not having eaten dinner (since remedied)

Hardware Gigascreen - it appears to work without too much shimmer. I'll do more tuning once 4 bit per channel VGA is connected up - I suspect we lose something by having no "BRIGHT" colours at the moment (shortfall of the dev board, not ZX Prism)

Wednesday, July 16, 2014

Development moves to Cyclone IV

Back again after a bit of a break - apologies for the radio silence once again, but real life has a habit of getting in the way of things like blogs!

Much has happened with ZX Prism since my last post. The most major thing is that development moved from an Altera Cyclone II based dev board onto my shiny new Cyclone IV dev board. This has the major advantage that the Cylclone IV EP4CE15 FPGA used on this board has enough internal memory cells to implement the majority of the planned ZX Prism screen modes. Some of the more "out there" modes I had planned may fall by the wayside but there will still be plenty to choose from.

Since moving to the new dev board, progress has been swift. I got the basic video driver ported across in just a couple of hours and then set about building a Spectrum-like computer. In just under 2 days, I had ZX Prism initialising and displaying the hallowed "(c) 1982 Sinclair Research Ltd" message. In the top left of a 512x384 resolution screen :)  I tried alternative ROMS too, just to prove it wasn't a fluke and all worked happily - SE Basic and the ROM versions of JetPac and Pssst all booted fine.

Since then I've been battling getting a PS/2 keyboard working. It worked for about an hour and then stopped working entirely without me changing anything. Some poking and prodding about the dev board with a multimeter showed that the data signal wasn't making it to the FPGA anymore.  Routing the signal myself doesn't seem to have fixed things. I'll leave this for now - it's just led to several days of frustration and no further progress on Prism. I can come back to PS/2 later when I wire up the SD Card slots and replacement VGA connector. Yes, despite boasting a shiny new Cyclone IV, this dev board only has 1 bit VGA - that's right, at the moment ZX Prism only has 8 colours!

Anyway it's been ages since my last post so here's some pictures of ZX Prism showing off it's 4 different screen resolutions:

Standard 256x192 resolution, standard palette, standard attribute decoding
 512x192 resolution, standard palette, standard attribute decoding
(I will also add the monochrome Timex 512x192 mode later) 

 256x384 resolution, standard palette, standard attribute decoding

512x384 resolution, standard palette, standard attribute decoding

Booting the original Spectrum ROM in 512x384 resolution :)

Friday, July 26, 2013

Selecting screen modes, data decoding methods and palettes

ZX Prism lets you select from a number of different screen data decoding methods. Like the ZX Spectrum, many of these modes use an 'attribute' byte to define the ink and paper colours in each 8x8 square. Like the Timex range of Spectrum compatibles, these modes also support 8x1 attributes. Unlike either range of machines, ZX Prism lets you choose how the attributes are decoded into a logical colour number, and then how that logical colour is translated into the colour which displayed on screen.

Screen resolution and 8x8/8x1 attribute selection is made using 4bit register 0010.
Not all resolutions or features are available for all screen data decode methods. Where a resolution is not available, Prism reverts to 256x192, 8x8 attributes and non-gigascreen*.

OUT 8E3B, 0010xxxx  Screen resolution selection where xxxx is:
     0000 – 256x192 8x8 attributes
     0001 – 512x192 (vertically halved display) 8x8 attributes
     0010 – 256x384 (horizontally halved display) 8x8 attributes
     0011 – 512x384 (quartered display) 8x8 attributes
     0100 – 256x192 8x1 attributes (“hicolour”)
     0101 – 512x192 (vertically halved display) 8x1 attributes
     0110 – 256x384 (horizontally halved display) 8x1 attributes
     0111 – 512x384 (quartered display) 8x1 attributes
     1000 – 256x192 Hardware GIGASCREEN 8x8 attributes *
     1001 – 512x192 Hardware GIGASCREEN 8x8 attributes *
     1010 – reserved
     1011 – reserved
     1100 – 256x192 Hardware GIGASCREEN 8x1 attributes *
     1101 – reserved
     1110 – reserved
     1111 – reserved

*Hardware gigascreen is an experimental feature which on even frames interlaces the even lines of screen 0 with odd lines of screen 1 and on odd frames interlaces the odd lines of screen 0 with even lines of screen 1.

Screen data decoding method selection is made using 4bit register 0011:

OUT 8E3B, 0100xxxx  ZX Prism palette selection where xxxx is:
     0000 – DEFAULT
          ATTR: D0-D2 ink, D3-D5, paper, D6 bright, D7 Flash

     0001 – 16+16 Colour
          ATTR: D0-D2 ink, D3-D5, paper, D6 ink bright, D7 paper bright

     0010 - 32 Colour
          ATTR: D0-D2 ink, D3-D5, paper, D6 bright, D7 NOT halfbright

     0011 - 16C (4 bits per pixel chunky mode)

     0100 – 256 Colour mode 1
          ATTR: D0-D7 - ink colour, BORDER – paper colour

     0101 – 256 Colour mode 2 - 2 byte attribute read.
          ATTR: D0-D7 - ink colour, D8-D15 - paper colour

     0110 – 16 colour Planar mode

     0111 – [Reserved]
     1000 – [Reserved]
     1001 – [Reserved]
     1010 – [Reserved]
     1011 – [Reserved]
     1100 – [Reserved]
     1101 – Rasterscan (pixel colour = BORDER colour)
     1110 – [Reserved]
     1111 – 256 colour chunky (8 bits per pixel) mode

DEFAULT decode mode is just like a ZX Spectrum - Ink and Paper are effectively chosen from two CLUTs of 8 colours each (if the default palette is used, this is identical to choosing colours 0-7 with bright set to either 0 or 1)
16+16 Mode is similar to DEFAULT decode mode, except that ink and paper can be selected from a single group of 16 colours (if the default palette is used, this effectively gives you a separate bright bit each for paper and ink)
32 Colour mode is similar to DEFAULT decode mode except that ink and paper are both selected from one of four different CLUTs of 8 colours each. If the default palette is used, this effectively gives you 4 levels of bright - the flash bit is an inverse "half-bright" bit (it's "on" when unset, off when set) to prevent the DEFAULT palette being too dark when used in 16 colour modes
256(i) colour mode uses the entire attribute byte to dictate the ink colour. Paper colour is dictated by the BORDER colour stored at IO address 0x9E3B.
256(ii) colour mode uses two attribute bytes. The first to dictate the ink colour, the second to dictate the paper colour.
16 colour planar mode uses 4 256x192 pixel bitplanes to dictate pixel colour. In DEFAULT palette mode this equates to plane 1 (stored in page 5a) being a blue plane, plane 2 (page 7a) being a red plane, plane 3 (page Da) being a green plane and plane 4 (page Fa) being a "bright" plane.
256 colour chunky mode uses a byte per pixel. A single screen takes up 48K of VRAM. This mode is only really of use for title (or otherwise static) screens due to the amount of data that needs to be shifted around.

There are 3 methods of decoding the "logical colour" into a physical colour:
  • Default palette. This is a hard-coded palette. The first 16 colours are identical to the ZX Spectrum's colours, the next 16 are dimmer versions of the first 16. Colours 0-7 – intensity 1 colours; Colours 8-15 = intensity 3 versions of colours 0-7; Colours 16-23 = intensity 0 versions of colours 0-7; Colours 24-31 = intensity 2 versions of colours 0-7. [The remainder of the default palette are awaiting definition] 
  • Prism palette. This is a user-defined palette. Each colour can be assigned 8 bit red, green and blue elements. Whilst the Prism specification allows 24bit definitions for each colour, some implementations may transcode these into 9bit colour (3 bits per element), 12 bit colour (4 bits per element) etc. My implementation currently uses 12 bit colour (4 bits per element) as shown in the diagrams above
  • GggRrrBb (aka G3R3D2 encoding) is a hard-coded palette as used by ULAplus, MSX etc. Bits 0 and 1 define the blue element; 2,3 and 4 define the red element and 5,6 and 6 define the green element.
Palette selection is made using 4bit register 0100:

OUT 8E3B, 0011xxxx  ZX Prism palette selection where xxxx is:

     0000 – DEFAULT

          Colour 0 – Black, Colour 1 – Blue, Colour 2 – Red, Colour 3 – Magenta
          Colour 4 – Green, Colour 5 – Cyan, Colour 6 – Yellow, Colour 7 – White

            Colours 0-7 – intensity 1 colours (as numbered above)
            Colours 8-15 = intensity 3 versions of colours 0-7
            Colours 16-23 = intensity 0 versions of colours 0-7
            Colours 24-31 = intensity 2 versions of colours 0-7

      0001 – GGGRRRBB

          bit (0) – blue(0)
          bit (1) – blue(1)
          bit (2) – red(0)
          bit (3) – red(1)
          bit (4) – red(2)
          bit (5) – green(0)
          bit (6) – green(1)
          bit(7) – green(2)

     0010 – ZX Prism PALETTE

          Colour 0-255 looked up vs the user-defined ZXPrism Palette

Thursday, July 18, 2013

ZX Prism 1024K mode Memory Map

This may go some way to explaining why ZX Prism's codename was "Project Overkill" for a while.

Some further explanation/clarification:

In 1024K mode, the memory page at 0xC000 is chosen using port 0x7FFD in the same way as the 1024K Pentagon (as documented in the ZX Profi documentation by Velesoft):
  • 7FFD bit 0 = Page # bit 0
  • 7FFD bit 1 = Page # bit 1
  • 7FFD bit 2 = Page # bit 2
  • 7FFD bit 6 = Page # bit 3
  • 7FFD bit 7 = Page # bit 4
  • 7FFD bit 5 = Page # bit 5
It should be noted that outside of 1024K mode, port 7FFD bit 5 when true works as expected (ie it locks the current memory configuration and prevents any further memory paging - known as "48K mode" in some circles).

Due to the way this locking works in ZX Prism, enabling 1024K mode from "48K mode" has the effect of re-enabling memory paging.