• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Reverse-engineering the Lapis ProColorServer 8 II


Well-known member
I made a quick FPGA emulator thing, so I could confirm my observations before making any attempts. Good thing I did, I'd read some of the check values wrong, and in practice the check values for the horizontal counter are offset to account for propagation delays.

The HBlank values are actually correct, but the HSync values are off by 16 pixels. The VSync values are off by 2 lines, and the VBlank lasts two lines more than normal.

The HSync part would be tricky to fix due to how the circuitry is laid out -- bits 0 and 1 of the horizontal counter are checked together, for either 00 or 11. The required values for HSync start and end would be 0x51 and 0x5D respectively, but they would require changing the circuitry to check bits 0 and 1 separately. The values used are 0x53 and 0x5F -- 16 pixels off to the right. One could go for 0x50 and 0x5C, 'only' 8 pixels off to the left, but I'm not sure if it's worth trying because I don't know how tolerant monitors are.

The vertical counter doesn't exhibit this sort of weirdness, so I was able to fix it by hand-editing the bitstream. I also modified the final HSYNC output to be just HSYNC instead of being XORed with VSYNC, and modified the TLC34075 parameters to disable sync-on-green.

The results of this quick attempt are certainly nice. My Philips monitor picks up the card's picture perfectly, no misalignment, no green tint. My Acer monitor, the picky one, picks up the picture, but it's dim and there's shimmering on the left edge. I guess it doesn't like HSYNC being off, but this is a start -- it used to just completely refuse to pick up the picture and stay in powersaving mode.

I might just call this good enough for now.


As for the XC3xxx bitstream viewer, I'm close to putting up a first version of it online. I will create a new thread for it I think. Do you folks have any ideas for it? Features you would want to see in it?


Well-known member
The final status update about this project!

Screenshot 2024-03-22 at 22-01-12 XC3000 display.png

This is the part of the horizontal counter logic. The counter starts at EB.

Logic blocks ED and EE check for the sync and blanking conditions, respectively. They both take 5 inputs: bit 0-1, 2, 3, and inputs from other logic blocks which check bits 4-7.

As I stated previously, the values for the blanking checks are correct, but the sync checks are 16 pixels off. I figured out a way to properly fix that.

What I did was connect ED.B to EB.X (bit 0 of the counter), and reroute FC.Y (bit 1 carry) so it still reaches EE.B. Since the blanking checks are correct, EE can be left alone.

I was able to free some routing space by finding out that FF.X and FF.Y are the same value, and thus we only really need one to be routed to ED.

Screenshot 2024-03-22 at 22-15-37 XC3000 display.png

With this rerouting, HSYNC perfectly matches the nominal VGA timing. Checking only bit 0 and ignoring bit 1 has the side effect that the HSYNC on/off signals are fired twice, but it doesn't matter -- these signals are fed into what is functionally a SR latch.

I quickly gave it a try, and nicely enough, it works perfectly! My picky monitor picked up the picture absolutely perfectly.


Not bad.

I'm providing the fixed ROM if it interests anybody. I only fixed the 640x480 bitstream, I haven't been able to test the other bitstreams or see if they exhibit similar timing problems.

I'll polish the XC3000 bitstream viewer thingy and put it up online soon.


  • LAPISFIXED.bin.zip
    9.4 KB · Views: 0


Well-known member
You are amazing. I never would have considered the possibility of patching an FPGA bitstream to fix an issue like this. Really nice work figuring it all out! Super duper impressive.


Well-known member
I concur. The bitstream reverse part is impressive, and also a good read

Keep up the good work


Well-known member
Thanks! This fix was challenging, too, because I had to figure out a way to get it working with minimal editing. Basically, working with the available routing resources, making sure not to short any other nets, dealing with limitations like how switch matrices don't support all possible pin combinations, etc.

By the way, I made a thread for the XC3-family bitstream viewer. I put up a first version of it online: https://blargcity.kuribo64.net/xc3000/


New member
Just wanted to chime in and say how fun it is to follow along. The Xilinx reverse-engineering and tweaking is amazing! I used to do firmware for Radius interface cards so this brings back memories, but our Nubus cards used discrete logic, then ASICs, as well as Brooktree RAMDAC and Chrontel (or similar) programmable clock chips. We could drive just about anything up to the maximum pixel rate of a given board design and RAMDAC (often 80MHz or 100MHz for a full two page display, and lower for 13" Apple and VGA as well as 16" and other timings).


Well-known member
It's nice to hear from people on "the other side", if you will -- those who were making that hardware we're looking at today. I'd be curious as to why Lapis designed their FPGA gateware the way it is, and what kind of monitors they tested it with -- maybe the older monitors were more tolerant of these oddities? The different bitstreams in the Lapis PCS are clearly built from the same model, and maybe they just had to do the horizontal counter this way due to space constraints.


Well-known member
CRT monitors were *much* more tolerant of off-spec timings. That was a big deal for MAME after CRT monitors fell out of use on computers, because very few arcade games were exactly 60.0 Hz refresh (NTSC 59.94 Hz timings were common-ish even on games designed in Europe, but so were things like 60.1 Hz and 57.8 Hz). So you either got tearing or you forced the game to run at not quite the right speed, which in turn would glitch the sound. Modern variable-refresh-rate panels fix that, fortunately.


Well-known member
Oh yeah, makes sense. I have a 12" CRT (640x480 monochrome LC monitor) and that one seemed to work with the Lapis PCS.