Friday, October 10, 2014

Another small update for September and the beginning of October

Apologies once more for the lack of updates in the last month or so. Mister Polomint prodded me a week ago to make some kind of post, so here it is. Steady progress is being made with a whole heap of testing and tuning and a few new features added. No pretty pictures or videos just yet, but there's been some more sceen modes added

Again, rather than write an essay, I'll just post the last few additions to the changelog for now.

ZX Prism version 0.16 10/10/2014 (non-released, flashed to board)

  • Added an extra bit to the Flash ROM address bus so the whole chip can be utilised.
  • Added check for CPU_RD on data bus multiplex (fixed Shadow Warriors and several others)
  • Added switch to limit memory to 128K (when used, fixes turbo outrun amongst others): OUT 36411,24 limits the page at 0xC000 to pages 0 to 7. OUT 36411,16 re-enables 512K.
  • Hooked MMC signals into the glue logic (but the associated IO registers not implemented yet)
  • More interrupt tuning for different CPU speeds. Speeds 0-6 (3.5MHz - 28Mhz) work with all games/demos tested. Speed 7 (56MHz) needs further tuning


ZX Prism version 0.15 19/9/2014 (non-released, flashed to board)

  • Fixed the main ZX Prism palette. (until this fix, all 3 colour elements were getting set at the same time, meaning you could only select from black and 15 shades of grey!)
  • Added write masks for writes to 0x4000 - 0x5FFF (0=currently paged, 1-15=combos of planes). This makes working with the new video modes easier - for example, you can write to multiple planes of a planar mode at the same time, or quickly modify existing software to work in an overlay mode by adding an OUT to the beginning and end of the sprite routine so sprites are written to the shadow screen and overlaid over the main screen to avoid colour clash... etc etc. Care must be taken when using this feature from BASIC (so as not to stop writes to system variables...) 
  • Removed "64 ink, 4 paper" mode and replaced it with 3 plane planar mode (as defined by Andrew Owen) This mode avoids using memory at 0x6000
  • Added overlay options register which selects the attribute decode methods for upper and lower overlays
  • Added readable register IN 0x8E3B (36411) returns CPU speed and available system memory:

D4-D7 = Available memory
0000 – 48K
0001 – 128K
0010 – 256K
0011 – 512K
0100 – 1024K
0101 – 2048K
0110 – 4096K
0111 – 8192K
D0-D3 = CPU speed

  • Added readable register IN 0x9E3B (40507) returns microcode version (mainly to save me wondering which build of the FPGA code is currently running whilst I'm testing different versions!)


ZX Prism version 0.14 10/9/2014 (non-released, flashed to board)

  • In Quartus: Turned on "Auto RAM to Logic Cell Conversion" in Analysis&Synthesis More Settings
  • In Quartus: Changed optimization technique to "speed" (from "Balanced") in Analysis&Synthesis More Settings
  • In Quartus: Changed Optimization technique to "speed" (from "Balanced") in the Analysis & Synthesis page (diff to above)
  • Added attribute decode method 0111 - 64 inks (colours 0-63), 4 papers (colours 0-4) PpIiiiii  (this mode was removed in version 0.15)
  • -Swapped default colours 0-15 with colours 24-31 so difference between bright 0 and bright 1 is more spectrum-like
  • Added a rudimentary floating bus (127 if reading screen, 255 if drawing border) - enough for Arkanoid to run (though the bat and ball flicker!)
  • Added overlay mode 1 (Polo Mode) - ink and paper colour 0 and 8 on top layer are treated as transparent and reveal the lower layer.
  • Added overlay mode 2 - ink and paper colour 0 on top layer are treated as transparent and reveal the lower layer
  • Added 256 colour mode 2 screen 0/1=ink1 colour + pixel data, screen 2/3=ink2 colour+pixel data, paper=border
  • Switched to spectrum 128/+2 partial decoding of IO 7FFD to see if that helps with some of the compatibility issues. This will need to change back if port 1FFD etc are used in future.
  • Added check for interrupt on function keys (to avoid crashes when changing CPU speeds)
  • Started adding an OSD


ZX Prism version 0.13 31/8/2014 (non-released, flashed to board)

  • Refactored cpu speed code. Default speed (speed 0000) is now 3.5MHz
  • As SRAM and FLASH share FPGA pins, wrote pin multiplexor to facilitate use of both. SRAM signals are mapped to the pins when SRAM_nCS is 0, FLASH signals are mapped when FLASH_nCE is 0. When bothare '1' the pins are set to high impedence so they can be used for other things (eg ROM cartridge, SID, general sound etc - will require fast bus transceiver to translate voltage levels and leave bus at high impedence when FLASH/SRAM are in use)
  • For the time being, the memory multiplex is "locked" to talk to SRAM only
  • Changed memory mapping so that VRAM is used by both video and cpu for page 5 and 7 (previously CPU writes were being mirrored by VRAM, with CPU reads using SRAM and video reads using VRAM..) this frees up 32K of SRAM for other uses.
  • More interrupt tuning (frame length, int start, int duration for speed 0) to fix Mikie (was freezing) and others which weren't detecting keypresses. FUSETEST now detects this as a 48K spectrum due to frame length

Friday, August 29, 2014

Progress report for August

Apologies for being quiet for a while - lots of tuning and small changes have been taking place. It's probably easiest to report just what's been going on by sharing this excerpt from the changelog:

ZX Prism version 0.12
Archived: 25/8/2014 (non-released, but flashed to board)

  • After noting that shadow warriors screen corruption stopped in 7MHz mode (though it still crashed), added check for CLK_EN='0' for SRAM_WE. This stopped the screen corruption in all CPU speeds though the game still crashes.
  • added clock enable check for port 7FFD
  • Altered CPU speed selection to give choice of spectrum clock derived CPU speeds or Video clock derived speeds: 3.18MHz, 3.5MHz, 6.375MHz, 7MHz, 12.75MHz, 14MHz, 25.5MHz, 28MHz and 51MHz
  • Altered interupt generator so it generates a CPU or Video clock derived interrupt.
  • Fixed interrupt frequencies (CPU speed derived interrupt was being generated at 100Hz  not 50Hz!
  • Fixed odd crashes at higher speeds... Now works up to 51MHz. 
  • Disabled 56MHz clock speed as I couldn't get it to run without random crashing
  • Reinstated partial address decoding for port 7FFD (fixes crashes/odd behavior in some 128K games which don't fully address the port). Am currently using the partial decoding as used on the Spectrum +3, +2A and +2B
  • Fixed another problem with interrupts - the video clock derived interrupts were running at half speed.
  • "tuned" interrupt signal duration so that they are different for each clock speed, using R-Type as a test. Settled now for values for each clock speed which i) don't cause R-Type to crash, ii) Allow R-Type to detect keypresses, iii) Allow R-Types screen updating to happen properly. These will not likely be the final durations ;)
  • Made video domain interrupt calculator equal frame length equal to 1 VGA frame (oops)
  • Successfully loads Speedlocked game (Sabre Wulf from They Sold a Million) at double speed (with CPU at 7MHz) and quad speed (with CPU at 14MHz) from audio CD

  • Flashed this version to FPGA board via Active Serial (so that it runs as soon as the board is turned on instead of having to be configured by the PC each time)
Loading a ULAplus enhanced game

And another ULAplus enhanced game. Hurrah for The Mojon Twins!

ZX Prism version 0.11
Archived: 18/8/2014 (non-released)


  • Added support to read palette entries from ULAplus (IN 65339)
  • Altered Mike Stirling's keyboard driver to handle cases where multiple keyboard rows are scanned by software (fixes "press any key" problem in Pssst etc etc etc)
  • Fixed bus timing issues introduced/uncovered by changing keyboard driver (!)
  • CPU speed stable to 28MHz
  • Fully implemented rest of port 7FFD including latch locking for ports 7FFD and 1FFD
  • Small update to VIDEO driver to allow screen selection
  • Implemented scanning of function keys. F12 sends a reset signal to CPU etc. F1-F11 send signals to the "buswatch" glue logic block to act as NMI keys, turbo buttons etc.
  • Implemented F12 = reset
  • Implemented F9 = Unlock ports 7FFD/1FFD if locked
  • Implemented F5 - F8 as CPU speed selectors (allows me to test games at different CPU speeds without having to hack their loaders which was getting tedious..)
  • Made keyboard scanning synchronous with CPU at whatever speed (stops Starstrike II crashing)
  • implemented F1-F4 as NMI keys (all 4 just send NMI to CPU at this stage)
  • fixed VRAM timing error which resulted in noise on screen on some games (eg Gyroscope)



ZX Prism version 0.1
Archived: 12/8/2014 (non-released)

FPGA:

  • Spectrum ROM implemented as on-chip memory, hard-coded into 0x0000
  • Implemented extra sceen resolutions (512x192, 256x384, 512x384)
  • Implemented screen decode methods: Standard, 16+16, 32 colour, 256 colour 1, 4 plane planar
  • Implemented SRAM for 512K memory pagable into 0xC000; page 2 hard-coded into 0x8000
  • VRAM page 0 hard-coded into 0x4000, no shadow screen selection yet
  • Port 7FFD partially implemented (memory select on bits 0-2, 6 and 7)
  • CPU speed selectable. Tested at 3.5Mhz and 7MHz
  • Default palette defined (except last 8 entries!)
  • ULA2 palette implemented but colour definition currently broken
  • Basic ULAplus implementation (can turn on and off and redefine RGB palette)
  • PS/2 keycode -> spectrum keyboard scanning implemented (based on Mike Stirling's FPGA Spectrum keyboard code)

Hardware:

  • Simple kempston joystick using on-devboard keys
  • Reset key implemented
  • PS/2 re-implemented off-devboard due to hardware issue and 2 dead FPGA pins
  • VGA re-implemented off-devboard to achieve 16 levels of red, green and blue (on-board VGA is 8 colour total)
  • Current RAM and ROM page displayed on 7-seg LED array
  • Tape IN and Tape OUT implemented via MX3232 RS232 UART.
  • Tape interface thoroughly tested and tweaked
  • Tape OUT tested with headphones only, haven't tried to SAVE
  • Beeper output directed to TAPE OUT for now (beeper port of ULA is XORed with the tape out port - some music routines, eg Manic Miner, don't work properly)


Software tested against v0.1 (and subsequently used to test fixes in later revisions):

  • Aquaplane (as expected the border effect doesn't work due to VGA timings and lack of contended memory)
  • Manic Miner (music didn't work due to how beeper is mixed with tape-out; ie digitally rather than in analog circuit)
  • Myth (seemed to work fine)
  • PSSST! (from ROM) (worked fine except 'press any key' only accepted keypress from a single row)
  • Fred (worked fine)
  • Kokotoni Wilf (graphical corruption; this may have been a dodgy load, must verify)
  • Gilligan's Gold (worked fine)
  • The Pyramid (worked fine)
  • Starbike (worked fine)
  • Match Point (worked fine)
  • Freddy Hardest (worked fine)
  • Buck Rogers (worked fine)
  • Midnight Resistance (loaded fine, redefine keys option didn't work)
  • Skool Daze (worked fine)
  • Slap Fight (worked fine though Slap Fight logo appeared to have some minor corruption -load error?)
  • Saboteur (worked fine)
  • Horace Goes Skiing (worked fine, seemed a little fast though - lack of contention?)
  • Bionic Commando 128 (crashes after loading first block on tape)
  • Super Sprint (worked fine except border effect didn't work, as expected)
  • Where Time Stood Still (worked fine)
  • Sabre Wulf (alkatraz loader from Ultimate Collected Works) (worked fine)
  • Uridium Plus (seemed to be working but couldn't move ship up and down - fire and reverse direction worked)
  • - Shadow Warriors (graphical corruption then crash)

ZX Prism loading Ghouls N Ghosts from (audio) CD

Saturday, August 9, 2014

Small update

Just a small update for today as it's been a fairly busy week so I've not had much time to spend working on ZX Prism lately.

Firstly, ZXPrism now has 512K available to it (in addition to the 32K video RAM). Up until this week, ZX Prism was running as a 32K machine, with its video RAM paged into the memory space 0x4000 - 0xBFFF. This arrangement was merely for testing. Prism's memory arrangement is now much more like you'd expect on a Spectrum 128, with video RAM at 0x4000 - 0x7FFF and 'ordinary' RAM between 0x8000 and 0xFFFF.

Like on the Spectrum 128 etc, the extra RAM is split into 16K banks which get paged into the area 0xC000 - 0xFFFF; as ZX Prism has 512K, this equals 32 x 16K pages of RAM which I'll refer to as pages 0 - 31. Page 2 is always paged into memory area 0x8000 - 0xBFFF (currently; this page may be changed to be selectable in future). The memory which is paged into 0xC000 - 0xFFFF is selected using IO port 7FFD - the same as on the Spectrum 128 - but of course ZX Prism has more pages available than on the 128 so ZX Prism uses bits 6 and 7 of port 7FFD in addition to bits 0 to 2. This matches the way that the Russian Pentagon 512 does it:

PORT 7FFD -

D0 - page[0]
D1 - page[1]
D2 - page[2]
D3 - display screen[bit 1] (msb - ZX Prism has 3 shadow screens, not 1)
D4 - ROM bank select[bit 0] (Prism will eventually have 512K flash ROM)
D5 - Prevent further memory paging (also known as "48K mode")
D6 - page[3]
D7 - page[4]

ZX Prism's SRAM is actually 256K of 16 bit RAM. Bit 4 of the page number determines if the upper or lower byte of the 16 bit data bus are to be used, effectively splitting the SRAM into two lots of 256K which is how 512K is achieved.

Currently ZX Prism's ROM is stored on the FPGA and is the original Sinclair ROM from the 16/48K Spectrum. As such, the ROM bank select currently does nothing. The "lock" to 48K mode also isn't yet implemented (though it would be trivial to do so), so ZX Prism currently perpetually runs in "USR 0" mode.

The additional memory was tested a number of ways - firstly RAMTOP was set to below 0xC000 and then unique test data was written to each page; then the data from each page was read back and verified. Of course there's not much 512K software (at least not that's available as a TAP/TZX file) to test, but I've tested several 128K games.

Speaking of tapes, I'd been finding loading to be a little unreliable. Everything would be OK for 3 or so minutes but then it would fail. It didn't matter if this was a turbo loader or standard loader. Eventually I found that one of the resistors in the tape-in circuit was getting very warm - when I swapped that out for a resistor of the same value but higher current rating, things got a lot more reliable. I still seem to have to use a higher volume level than on a normal Spectrum - I suspect that's due to the Spectrum's ULA working at 5v, and the Max3232 RS232 UART that I'm using to buffer input between tape and FPGA is expecting a higher voltage.

Finally, I've started hooking up the MMC slots so I can start implementing DivMMC and getting ESXDOS working. I'll have to do some more research on when exactly ESXDOS needs to be paged in and out of the ROM area (it reacts to an NMI switch, pages in as a shadow ROM on RST8, and has tape traps at least... and I have no idea of what triggers them - or what triggers a page out). I also need to know how the DivMMC does its ROM/RAM paging. If anyone can help, leave me a comment or seek me out on WoSF.

I've already done a bunch of Googling and searching threads on the World of Spectrum forums... Looks like I'll have to ask the designers/coders (or an emulator author perhaps) directly. Andrew Owen's already managed to give me a certain amount of insight, but I'm far from clear on all points!

Finally, a picture of ZX Prism as it currently looks. Please ignore any dodgy soldering you might notice. I've just got a new soldering iron, and it's a huge upgrade from my last one!


The dev board is a Black Gold Cyclone IV kit, which is very nice but you have to translate all the documentation from Chinese! This dev board comes with 256K of 16 bit SRAM, a similar sized FLASH, about 4MB of SDRAM, RS232, VGA, USB, PS/2 (which was broken on my board), and a LAN socket as well as the 7 segment displays and LCD screen. The veroboard contains the analogue circuitry for tape-in and (untested as yet) tape-out, the dual MMC sockets, and also the break-out connector for the PS/2 and VGA daughterboard (not pictured) which replace the implementation of each on the main dev board (the PS/2 socket was broken on delivery, and the on-board VGA was 8 colour only)

Sunday, August 3, 2014

ULAplus support

Spent the weekend tying up some loose ends and working on the user-definable palettes. ULAplus support is pretty much working now (it's currenlty missing the ability to read the palette back, and the ULAplus specification includes the Timex screen modes which aren't implemented yet).


I've also hooked the SRAM up, so Prism now has 48K. There's 512K SRAM on the dev board and Prism will have access to all that once I've implemented bank switching.

Wednesday, July 30, 2014

2 days solid progress

The PS/2 woes bug me no more! After a LOT (and I mean a LOT) of head-scratching, troubleshooting and trying new sockets, USB keyboard adapters, alternative keyboards etc I discovered that the 2 pins on the FPGA which were linked to the PS/2 socket were permanently shorted to ground. This wasn't down to wiring or anything on the board - the inputs themselves were buggered. A bit of testing later found that my original PS/2 keyboard was dead as a Norwegian Blue and appeared to be the original source of my woes.

Wiring the PS/2 clock and data inputs to two spare FPGA pins, and using a newly acquired PS/2 keyboard finally got ZX Prism responding to key presses. Hurrah! Some changes to interrupt generation which I'd made whilst troubleshooting the original problem got reverted and tuned over a nice game of Pssst.

Pssst was "loaded" by way of using an image of the Psst IF1 cartridge in place of the Spectrum ROM. This was all well and fine, but I decided tonight that I'd try my hand at a tape interface. I started out by using the RXD input of the RS232 UART as the source of the "tape in" bit of the ULA port (IN 0xFE). The UART is tolerant of (relatively) high voltages and thus protects the FPGA from the crappy old 80s cassette players. Between the RXD pin of the UART and the tape socket is the usual circuitry found on an issue 3B spectrum between the tape socket and the ULA. I expected to have to do some tweaking, but no. Horace and the Spiders loaded first time.

So in the last couple of days, there's been some good solid progress! Next, I'll try to get an MMC slot wired up and ESXDOS working. The MMC slot on ZX Prism was initially going to mirror the way ZXMMC works (same ports etc), which is the same way Mike Stirling implemented MMC on FPGA Spectrum, however DivMMC has recently been released and is very popular, so I'll use DivMMC's ports - this has a number of advantages, not least that the DivMMC version of ESXDOS will be able to be used.

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!)

So:
    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...