c0pperdragon / C64-Video-Enhancement

Component video modification for the C64 8-bit computer
MIT License
256 stars 36 forks source link

question #15

Closed bwack closed 5 years ago

bwack commented 5 years ago

I sent an email a while talking about making a video about this project. I dont have my email right now i hope here is ok to ask. I was interested in the implementation/emulation part of the project. Also id like to understand the angle you took to solve this problem. What approach. What information or reversengineering techniques were used to get where the VHDL code design is now. For example did you look at FPGA64 or vice source code, and how you would debug a demo with crazy abuse of the vic II? Also it would be cool to know a little about you and your background if it is ok.

I have looked at the VHDL code from time to time. I found it interesting that you look for a ras or cas cant remember, access pattern and synchronize the emulation module to that. I guess if the design has to know what data is accessed by the vic, having the module (?) Synced to the real vic, and the fact that the access sequence is fixed, the module can know when to store sprites, char/graphics pointers (videomatrix/badline), and so on. Register access i guess you can pick up by control lines and address bus.. I noticed there was a PLL IP. Does it produce a close to exact PAL/NTSC frequency?

c0pperdragon commented 5 years ago

That are quite a lot of questions. Lets try to tackle them one by one.

My first (and main) source of information is the awesome document "The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64". The parts that were not clear from this I tried to reverse-engineer on my own, and during this I also found some small parts of the document that are plain wrong. Using the WIN-VICE testbench programs I tried to narrow down on a correct implementation by doing a side-by-side comparison of the original VIC output and my emulator. By now I have it in a state that it can play most demos (including Edge of Disgrace) flawlessly, but some very strange glitches still remain (one is in the last part of the Brutality Demo).

Syncing the emulation is indeed very important, otherwise I could not make any sense of the various signals. There it was lucky that the DRAM refresh done by the VIC has a very distinct addressing pattern that does not occur anywhere else and that can also be used to determine which is the first scan line. Monitoring register writes is easy enough as there are the RW and CS lines set by the CPU. All the memory accesses the VIC does on its own can be predicted pretty accurately, and by sensing the AES line and the address lines, a bit more information can be gained about what the VIC is up to. As it turns out, I never even use the BA line that is also part of the signals that are monitored. But when I designed the device, I was not sure on that, so I included it just in case.

Creating a proper pixel clock in the emulator was one of the trickier parts. The pixel clock of the C64 is very shaky because of the weird way the 8701 works. But the CPU clock itself is super-stable because the 8701 repeats its shaky signal pattern exactly every 4 pixels, so after this clock is divided by 8 the signal edges are perfect. Multiplying this CPU clock by 16, I generate a very stable and reasonably fast clock for the whole processing that allows me to generate pixels at double rate for use in 525p/480p modes. The details of the clock multiplications are pretty intricate as I can not simply use a PLL, because the PLL on the chip must be fed with an input clock of at least 5MHz. Instead I implemented a kind of custom frequency multiplier based on a high-frequency clock and loads of logic. Works really well now.

All pixel output timings are coupled to the CPU clock, so there is never any slip. I even went to the effort to match the delay of my digital signal path as closely as possible to the analog signals. You can now even use the original luma on the A/V port with my Pb/Pr lines to get a proper Y/Pb/Pr signal (but the original luma of course has all the known signal artefacts).

My personal background is being a professional software-engineer since 1997. I was always interested in the hardware side of things, and as the retro-computing/gaming wave started, I decided to again do some more serious stuff there. As I am doing programming for a living, I wanted to do more manual soldering and stuff for a change, but as it turns out, electronic engineering nowadays is again mostly done on the computer :-P I am living in Vienna with a wife and 2 children.

bwack commented 5 years ago

Thank you very much for taking the time to answer my questions. That is really interesting to know how you designed the emulation part. Yes the AEC line is pretty much a fixed signal, depending on which sprites are active or if there is a badline, Regarding BA and AEC, I looked at this in my previous video and made a logisim simulation from a circuit i've seen in the dieshots. The rom has only one spritebusavailable strobe for sprite0, where each sprite busavailable is triggered by the previous sprite. The dieshot shows (dynamic) shift registers propagating from one sprite to the next and each of them pulls on the BA line (if the sprite is enabled). Then the BA line runs down to the AEC pin and is mixed with PHI (and some more shift registers to delay it 3.5 times for the CPU to finish what it is doing(it takes at most 3 cycles to finish)). I need to refresh it has been too long since i made that video, but what you explain here is very interesting to me. Anyway this video is not about me though :) I believe the 8701 was a costreduction of the PLL design. I don't know exactly how the 8701 works, other than it generates ca clock adds fixed delays to phase-align two clocks (dotclock and phi0), and I guess it is important for the videoenhancement board ? Did you divide this clock by 8, and did you have to skip every 4 pixel to avoid the shaky bits of the clock ? oh wait maybe I got this wrong. The 8701 divide the that clock by 8? or was it the fpga? I was guessing that you might have used a high frequency and perhaps a counter to synthesize the right frequency ? Was there any special reason to run the fpga at 25 mhz and put tasks into phases ? I think it is very impressive that you have got this close, and also it not so often I hear that hardware is like programming. :) Usually I hear either they do HDL design for living or a hobby, or they think HDL Is so different from thinking programming. I do agree though. HDL does abstract the implementation to a higher level, especially when you use processes (in VHDL). Again thanks so much! Edit: oh I forgot to ask if you use a logic analyzer when you debug those glitches ? or if you look at disassembly of the demo ? Perhaps freeze it in an emulator ? :)

c0pperdragon commented 5 years ago

The 8701 seems to do the clock generation in a very "cheap" way. First it drives the crystal to generate the 4x subcarrier frequency that is fed into the VIC (17.7344 MHz in case of PAL). This signal is nice and stable, but it has a duty cycle of not exactly 50%. Internally it doubles this frequency by something like an XOR circuit that adds produces a positive level of a fixed length after each input level transition. This results in a 35.4 MHz signal where the individual flanks occur with very different time intervals. Using this signal the chip then does a weird divide-by 9 operation (or divide by 7 for NTSC) by toggling the output signal on rising or falling edges of clock. All this results in a pixel clock that is extremely shaky.

The VIC then drives all internal digital logic with this clock, but after dividing it by 8 for the CPU and everything else it again gets a super-stable clock for the rest of the board. My mod uses the CPU clock and internally divides it into 16 phases. These 16 phases are generated by my implementation of a clock divider that uses a high-frequency counter internally. I just use the 25MHz oscillator as an input to the PLL to drive this high-frequency counter. Why 25Mhz? As the PLL is freely programmable, nearly any frequency would be possible, but 25Mhz seem to be the most widely used standard and parts are fairly cheap.

HDL is indeed a very different thing than a conventional program. It took me several weeks to actually get my head around the basic concepts. But once you get it, is actually quite straight-forward. You basically have to think in terms of digital logic and express this in this strange HDL syntax.

I am not using a logic analyser, but try to figure out everything by trial and error

bwack commented 5 years ago

Thank you. I think I have enough info for the video now.

bwack commented 5 years ago

Hi I have drafted a script for the video I'm working on, would you like to have a look? If there are anything you would like me to add let me know, and also where I am wrong let me know about it, That would be very appreciated :) I was initially thinking of filming first then showing it to you for comments, but editing a script is more effective than editing the video later. https://docs.google.com/document/d/16VX2f096vfZyDsxRCxJZlhCugzEqhgru6QTygAl1rMA/edit?usp=sharing

c0pperdragon commented 5 years ago

I have read the script and this all seems very reasonable.

About availability for persons that do not want to build their own board: Maybe I can persuade he owner of https://www.videogameperfection.com/ to start a production. I guess the main issue is that I can not guess on the number of users willing to buy such a kit. Do you have any idea?