Tuesday, 9 September 2014

More work on remote display

We had a thunderstorm pass right overhead during the night, with one lightning strike close enough that I was woken by the shockwave.  So awake in the middle of the night, I have done a little work on the real-time streaming of video frames from the C65GS.

The previous post showed the initial progress, lacking horitzontal and vertical sync, and having all sorts of artifacts.  Things are now better as the following image shows:


With the work overnight, some artifacts clearly remain, but horizontal sync is now solved.

Vertical-sync is also still a work in progress, and it took a few goes to capture a frame that was more or less centred in the capture, although imperfectly, as the top and bottom borders should be equal size.

The colours aren't right, as the video capture process doesn't include the palette (yet), and I am using the C64 palette, so the colours are less saturated than on the real thing.  Red on a real C65 is just about bright enough to burn your socks off, for example.

Soon I will use the horizontal sync marks to also include a 72KHz audio stream.

I also still have a bit of work to do on the packet encapsulation.  Right now I have to use libpcap to sniff the packets, because my IPv6 encapsulation of them has something messed up.  Once I fix that,  it should be possible to just create a raw IP socket bound to the right IPv6 multicast address, and read the packets as they arrive.

Monday, 8 September 2014

Working towards remote head

I have been doing a bit of work to support full-resolution remote display of the C65GS via the ethernet port.  My idea is that I can provide internet access for interacting with a C65GS in real-time and at full 60Hz so that people can get a feel for the machine, and also contribute to and test software on it.  In other words, I intend that in a few weeks time it will be possible to use a C65GS remotely via a web browser.

The first step is taking the video output from the VIC-IV and compressing it enough to go out on the 100mbit ethernet port.  This requires compressing the video to 10% of its original size. I have implemented a simple run-length encoder as a first step, which should be fine for 40 and 80 column text displays.  I will make this more sophisticated in time.

I want the remote display to be completely independent of the CPU, so that it can keep displaying even if the CPU is paused for debugging. To achieve this I have implemented a direct communications channel from the VIC-IV to the ethernet adapter that bundled and transmits the data as it arrives. There is a register that enables and disables remote display.

While there is obviously more work to do as the following images show, I was surprised at just how quickly I was able to get it to this point.  Next step will be to figure out what is causing the lost pixels in the stream so that it stays properly registered, and fix the horizontal and vertical synchronisation marks.  But I thought I would include these initial real-time frame captures as a taste of what is to come.



Thursday, 4 September 2014

Boulder Mark at 48MHz, with working sound

Boulder Mark seems to work now, even though I can't think what I might have fixed that would have addressed the problem it was having.  It does still crash occasionally, but it usually runs to completion.  

So I thought I would post a video of boulder mark running on it to give an idea of how fast the C65GS is.  That turns out to be about 500 frames per second in this test, which is very nearly 100x the score of a stock C64.  The vacuum-like sound is boulder mark making a noise every frame.


As I have mentioned before, boulder mark is a non-linear benchmark, because the first few hundred frames are much more work to draw.

So it is probably a better comparison between the C65GS and Chameleon, since both are fast enough that the slow frames are only a small fraction of the score.

On that basis, the C65GS is about double the speed of the Chameleon, rather than the 4x that SynthMark would suggest.  This makes sense, since SynthMark places a fairly heavy weighting on operations that read from IO and colour RAM, even though they are relatively rare operations.  So, depending on the workload, the speed difference is likely to be somewhere between 2x and 4x, if using normal 6502 opcodes.

SID audio at last, plus CPU and VIC-IV redesign catching

I finally had some time over the last couple of days to get the redesigned CPU and VIC-IV to some reasonable degree of working, so that I can finally begin enjoying the benefit of the work, and making use of the about 2/3 of the FPGA that the redesign has freed up.

I have fixed bugs with the read-modify-write instructions, PLP, PHW, the $nn,Y addressing mode (it had a copy and paste error and was acting like $nn,X), the MAP instruction was no inhibiting interrupts and numerous others.

I also finally got around to making the dummy write in read-modify-write instructions only happen if the target address is $D019, i.e., to acknowledge VIC-II interrupts, thus avoiding an extra cycle in those instructions.

The CPU now passes the Lorenz 6502 tests for all the legal opcodes, and C64 and C65 mode BASIC both work, as does the DOS for the internal drive, making it easier to test a wider variety of software again.  The Lorenz test suite takes about half an hour on a real C64, but all the official 6502 opcodes can be tested on the C65GS in under a minute. This really is a fast 8-bit computer.

However, not everything is right, since Bouldermark crashes for a reason I have yet to discover.  Synthmark64 runs fine, however, and the speed is almost unchanged from the last test.  The slight slow-down is due to putting back a necessary wait-state when reading from colour RAM.

Obligatory screen shot of Synthmark64 running very fast indeed.

I also put some effort into tracking down some bugs in the newly added parts, including the emulated stereo SIDs (although they both come out the same mono audio jack right now).  Apart from some speed issues, which is just as likely due to the 60Hz screen refresh rate as anything, sound is now working, as tested in Bouldermark and Lemmings.

The VIC-IV reimplementation is not yet complete, with multi-colour and bitmap graphics modes still having a few bugs to shake out.  I did manage to get extended colour mode and bitmap modes working to some degree, although multi-colour mode and bitmap modes both have some problems to work out, which I have yet to fully explore.

Along the way I also added support for the DMAgic DMA controller to DMA memory from outside the 1MB C65 address range.  This is used to copy the disk chooser program from the Kickstart ROM to $C000 at start up.  Similarly, chained DMA lists are now supported, and one chained DMA list does the copy as well as clear the screen and colour RAM.  Clearing 4KB RAM and copying another 4KB RAM all takes about 13,000 cycles, about the equivalent of five rasters on a real C64.

The next steps will probably be to debug the multi-colour graphics problems to figure out what is going on there, so that graphics looks right.  Then I might finally get started on implementing writing to SD card and implementing sprites, at which point all core functionality will exist, however flawed and imperfect it may be.

My plan for sprites is to have the 8 normal C64 sprites, plus another 8 (or 16 if I can manage it) 64x64 256-colour sprites.  These will each require up to 4KB of data.  I am thinking about how I can make the sprite data fetching character based, so that the sprites can be made up from 8x8 pixel character tiles, making for much more efficient use of memory.  In principle I could re-use the character generator machinery

Friday, 8 August 2014

De jevu: C65 startup banner and dead BASIC, again.

The title says it all: The 48MHz CPU is almost working, but there is clearly something fruity going on.  Sadly it isn't the same issue as when I got to this point last time, but I have some extra clues, like BASIC in C64 mode also behaves similarly. There are also some other nuisances, like IRQs don't seem to be getting masked properly.  But it is getting pleasingly close.

I am also interested to know whether people think the display is better with little side borders, or whether people would prefer no side borders in 80 column mode.  I personally think that having little ones adds to the authentic feel, but without sacrificing acres of screen.  Also, the real C65 has quite narrow side borders compared with the C64.  But I would like to hear what you think


Oh, and if you got this far, you might be able to spot the display glitch that I have to fix.  If you can, and can accurately explain the cause (I already know it), I'll greet you on the next screen shot I post on the blog.

Thursday, 7 August 2014

80 column now has side borders and other misc progress

I am conscious that I haven't had many fun screenshots to share lately as the CPU redesign drags on.

Fortunately, the CPU design is almost complete, and I am now shaking out the bugs that are still lurking so that I can get back to where I was up to before the redesign.

Today I made some changes so that I could simulate booting the C65 ROM.  This requires disabling Kickstart, since that would look for the SD card, and I don't have the means to simulate that (yet).  So instead I made a model for the slowram that holds the ROM after it has been loaded by Kickstart, and made a control flag to supress Kickstart when in simulation.

This means I can easily simulate the system booting the C65 ROM, and look for anything odd with nice cycle-by-cycle memory access information at my fingertips.  This has already allowed me to fix some DMAgic bugs in the redesigned CPU (DMAgic lives in the CPU in the C65GS).

Simulation is nice, because with tools I created and described in an earlier post, I can capture the VGA output digitally which is nice for screenshots here.  

However, simulation is REALLY slow -- taking between 20 minutes and an hour to simulate one frame of activity.  This isn't quite as bad as it sounds, because the C65GS can do a LOT in one frame. With the CPU at 48MHz and a 60Hz display, this means 800,000 CPU cycles per frame.

The slowness of simulation means that it is a good idea to avoid any unnecessary delays in the startup process of the ROM.  The main problem in this area is the PAL/NTSC detection routine, which has to wait until the end of the frame to work out if the machine is PAL or NTSC based on whether it has more than 263 raster lines.  

Fortunately, when you control the hardware, you can tweak things, and so on power up, the VIC-IV's VIC-II raster number register is purposely incorrectly set to raster 264 at the start of the frame. This means that the PAL/NTSC detection routine takes just a couple of dozen cycles to decide that it is on a PAL machine.  The register gets reset at the bottom of the frame, and then works as per normal in all successive frames, so the solution is a nice one.

The end result is that the C65 ROM does all its preliminary work in <100 physical rasters.  You get an idea for how fast this is in the following screen shot. The black part is the rest of the frame that would have been drawn, except that I stopped the simulation before it got that far.  

If you make it full size, you can see a couple of rasters of junk at the very top.  That is the time from when the CPU powers up until the ROM sets the VIC-II/VIC-III video registers for 80-column mode and sets the border colour. 

Then it is all border until the 80-column text starts, during which time various bits of memory are being setup by the Kernal and possibly internal drive DOS, and then uses the DMAgic to clear the screen.  The first line of text shows the wrong contents either because the badline happened at the very top of the display, and no badline happens because of the changing value of $D011 in the middle, or because the CPU does actually take a few dozen rasters to set everything up.  I haven't looked into which is actually the case, and it doesn't really matter.  What is clear is that by the second row of text the CPU has already cleared the screen.  Of course, it should also be showing the C65 start-up banner, which it isn't, and so I have some more bugs to hunt.

The other interesting feature of the screen shot is that it shows the reworked 80-column mode using the new horizontal hardware scaler that allows non-integer numbers of physical pixels per logical pixel.  By judicious selection of the scale factor, we now have some little side borders so that it feels much more 8-bit than when it occupied the full width of the display.


Monday, 4 August 2014

Ethernet receiving now has hardware CRC check, and IRQs are close

I managed to get a little time this evening to work on the remaining bugs in ethernet reception.

The main bug was caused by using a bad example ethernet frame that had reversed bit-order in every byte.  I confirmed this by capturing a real ethernet frame, and using that as the test vector in simulation.  CRC check failed, so I tried reversing the bit order, and viola, I had valid CRC detection.

Of course, I could have left CRC calculation to software, but it is a rather boring thing to implement, and modern network cards all do this, so it seemed like a good idea to do.  After all, if I can make it work once in the hardware, then all software can ignore it forever after.

This is one of the nice things about FPGA design, in that it is much more realistic to make the hardware nice to program, because the incremental cost of making an interface that bit nicer is quite low.

Another thing I have almost working for the ethernet is IRQ triggering on packet sending and receiving, so that you don't have to poll the ethernet adapter all the time to know if you there is a packet to receive, or if you can send another frame yet.

To give an idea of how simplified the interface to this ethernet adapter is, here are the register addresses that matter:

$DE800 - $DEFFF - 2KB received frame buffer.  First two bytes are the length of the frame.  If bit 15 is high, then the frame failed the CRC check.  Frames with a bad CRC don't trigger IRQs.
$DE041 -  bit 7 - Enable IRQ on frame RX
$DE041 -  bit 6 - Enable IRQ on completion of frame TX
$DE041 -  bit 5 - A frame has been received since $DE041 was last written.
$DE041 -  bit 4 - A frame has been sent since $DE041 was last written.
$DE041 -  bit 2 - Which RX buffer was last written to by the ethernet adapter.
$DE041 -  bit 1 - Which RX buffer is mapped at $DE800 - $DEFFF for reading.
$DE041 -  bit 0 - Set to 1 to force ethernet PHY into reset state.  Reset to 0 to allow normal operation.

As described above, there are two receive buffers, so that you don't have to worry too much about losing frames while reading them out, or similarly having the part of the frame overwritten in the buffer while you are reading it out.

To clear any IRQs write anything to $DE041, although this should normally be whatever you read from it, so an LDA / STA pair or similar is the best bet for now.  I might change the interface in time so that DEC can be used to do it a little quicker, but not just yet.

To send a frame, you write the bytes to $DE800 - $DEFFF, write the frame length to $DE043/$DE044, and then write $01 to $DE045.  Note that the TX buffer is mapped to the same address range as the RX buffer.   In other words, the TX buffer is write-only, while the RX buffers are read-only.  When you transmit a frame, the ethernet adapter automatically calculates and appends the ethernet CRC to the end of the frame.  This still has some bugs, so the CRC is incorrect, but you hopefully get an idea of how easy it is to send and receive ethernet frames with this ethernet adapter.  I might add automatic IP checksum calculation later on, too.