信号狂欢节
Signal Carnival

原始链接: https://www.quiss.org/signal_carnival/

C64作品《信号狂欢节》(Signal Carnival) 创新地交换了音频和视频线缆,同时保持了有意义的输出。音频通过使用CIA定时器以高频(246kHz)操纵VIC芯片的寄存器来产生波形,并将这些波形发送到屏幕颜色寄存器。这有效地利用了屏幕颜色的亮度来产生声音,并通过使用光笔电路进行视频稳定来弥补定时器的不足。 视频由SID芯片的音量寄存器驱动,允许立即输出信号,尽管由于C64的模拟带通滤波器存在限制,导致像素模糊且宽大。演示通过利用模糊感来创建纹理并专注于垂直轴向效果来弥补模糊。视频同步是自定义生成的,使用略高于标准C64的水平频率。 自定义加载程序优先在加载过程中持续输出音频,采用动态GCR解码和千字节缓冲区。该加载程序是为这个特定的演示而定制的,缺乏更强大的加载程序的功能。

Hacker News 最新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 Signal Carnival (quiss.org) 14 分 adunk 42 分钟前 | 隐藏 | 过去 | 收藏 | 讨论 加入我们,参加 6 月 16-17 日在旧金山举办的 AI 初创公司学校! 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系我们 搜索:

原文

At Revision 2025, we released "Signal Carnival" (csdb, YouTube). This demo asks you to switch the audio and video cable of your C64:

Diagram of audio and video crossed (Diagram by Felidae)

Technically, "misplugging" those cables is not a completely new idea. In the 90s, it was a common thing to connect audio to both speaker and video, to get screen flickering timed with the music beats.

However, "Signal Carnival" is the first production to switch both these cables, while still being able to play meaningful audio and video.

How to drive audio using a video signal

The C64's VIC chip operates at a frequency of 7.9Mhz, and new values can be written to it by the 6502 at a rate of up to 246kHz. Since even high quality audio rarely exceeds 44kHz, this is easily a high enough frequency to generate music.

Inspired by the music routine from freespin, we combined two timers to get an interesting waveform, which is adjusted once per frame. This is the code that drives audio:

lda $dc06
ora $dd06
eor $02
sta $d020

Here, $dc06 and $dd06 are the lower bytes of the B timers of CIA #1 and #2, respectively. They're in turn increased every time their A timers overflow. And those are set to a new value for every new note.

Eor-ing with the value at zeropage $02 allows to slightly tweak the waveform (and volume!), and then the result is written to $d020, which is the screen color. Only the brightness of said color matters (chrominance is encoded at the PAL color carrier frequency, which is outside of the human hearing range). There's no obvious relationship between the brightness of the C64 color and its number, but that's fine - it actually makes the waveforms more interesting.

Of course, the above uses up all four timers the C64 CIAs have, which means there are no timers left for e.g. video stabilization, which is instead done through the lightpen circuitry. (Finally! A use case for $d013. :))

Music is just one voice, but the song switches between voices (and waveforms) often enough to sound mildly polyphonic.

How to drive video using an audio signal

The SID chip of the C64 internally operates (for PAL) at 9.85Mhz, and, like the VIC, can be fed with new values at a rate of up to 246kHz.

The SID has a number of audio features. It can generate three voices using multiple waveforms, it has an ADSR envelope generator, can sync between voices, and apply filters. Unfortunately, all this circuitry works at a (for video) glacial pace: The highest frequency the chip can output is 3906Hz, which is the equivalent of changing the video output every four rasterlines. Similar with ADSR, for which the smallest possible configurable attack time is 2 ms, so about 32 rasterlines.

But thankfully, there's also circuitry that is wired more directly and and gives instant output: the volume register ($d418)! This has been used in the past to generate samples at high frequencies (16+ khz), and is a good choice for generating video, as well.

However, the C64 mainboard also, vexingly, passes the SID signal through a analogue bandpass filter. And this always happens, regardless of whether filtering is on or not.

Subsection of C64 mainboard circuit diagram

This means that the pixels we work with are very wide, and also horizontally blurred. Here's one "pixel", displayed on my 1084 monitor:

Photo of 1084 display, with a blurry horizontal "pixel"

This blurryness poses an interesting constraint on effects. While technically, you do have some degree of horizontal resolution, the blurriness makes it unenticing to use it for scrollers. Here are a few letters, for illustration:

Photo of three letters, heavily blurred

Signal Carnival makes heavy use of both axis, but to cope with the bluriyness, the x axis is used for graphics elements that are fine to blur, like e.g. textures.

Other than that, driving the video is just your normal vanilla video bitbanging. Due to the bandpass filter, horizontal syncs (i.e., pulling the signal line to ground) need to be precisely timed, so they get recognized, but not mistaken for vertical syncs. (which differ from horizontal syncs only in that the signal is pulled to ground a little bit longer)

Video sync generation is happening at the same refresh frequency that the VIC would have produced (so we can use raster interrupts and query the lightpen), but we use a different horizontal frequency (64 cycles per line instead of 63), since having that extra cycle proved useful in a lot of effects. And besides, if you're generating your own video signal, you might as well make your own rules!

Loading

I've written a new loader for probably every demo I've ever released on the C64, and this one is no exception. Since a lot of the effects are quite memory-hungry (we even play a sample at the end), loading breaks are long enough that we can't just pause audio while they happen.

Hence, we have to bitbang audio the entire time. Also while transferring data from the drive to the C64. Also during decrunching. (The decruncher actually unrolls all copy loops, also for that reason)

The loader has a few gimmicks, like doing on-the-fly GCR decoding that allows to write to any page (not just stack), and it buffers (stashes) a full kilobyte. But it's also a one-off, so it's missing tons of features seen in fully-fledged C64 loaders. It doesn't even support loading from tracks 18 and above yet (the demo uses 1-10.) Also no checksumming. (So remember, kids, dust off your 1541 drives, or Signal Carnival might not work!)

Talking about GCR decoding, I found it tedious to handcode the decoding tables, so we instead wrote a solver that generates them given the code that uses the tables, and the desired input/output. Very useful tool, hopefully to be released soon.

联系我们 contact @ memedata.com