It took me a while to convert the DYCP part from VIMM, and again I contacted Anders Carlsson for the music. He didn't disappoint me, and produced a very small music player (track player) with a test music and a little larger music player (duration player) with some tunes.
I was talking about color splits with Aleksi, so I also demonstrated how to get a lot of independent colors on screen with a routine, which later became the second routine for the unexpanded demo collection, called 19-split.
I continued converting the VIMM parts, and used all of my skills to fit everything into the 5.5kB of RAM (color memory nybbles included) available. Fortunately I always found some way to implement the effects or memory management better than in the so-called original versions. Of course sometimes sacrifices had to be made.
The following chapters goes throught the parts in order, talks about the general idea, code specifics, memory layout, how memory was saved, joystick control and other hidden bonus features, in addition to how the part actually performs and looks like. (Some of these things will be added to this page when I have time.)
Note that only PAL VIC20 is currently supported. You can also load other parts than 3k-vimmii and 3k-vicpic (plus vicpic's data files) separately. Just say"poke795,0" to select manual mode so that they won't try to call the loader.
This part also starts the music for the first actual part and plays the music while the part is loaded. I first had the next part in the same file, but decided that the smaller the first part is the better.
This part is a 3x2 16-line character font upscroller. The font originally took 3072 bytes so I had to do something to crunch it or there would not be any space for code, not to mention music, after the font and the video matrix is in place. I used a really simple dictionary compression that is also used by big font designer programs in C64: identical 16-byte chunks in the font data are left out and a mapping from the character code to the font is used when writing to video matrix. I edited the font a little to make this character packing more effective. After this the packed font takes 2032 bytes and the mapping table 180 bytes. That's savings enough to fit everything else in, so I stopped there.
Vicpic displays a picture of resolution 100(w)x160(h). The format is in general the same as in the previous vicgfx routine. However, some sacrifices had to be made:
The picture display is turned off while a new picture is being loaded. Pictures are loaded in order and when no more pictures are found, the next part is loaded. VIMMII contains 10 pictures. Anders Carlsson has also converted some pictures.
The colors are not quite the same (seem to be a lot darker) in VICE as in the real machine (and I can't seem to be able to load new palettes in xvic 1.8), so I have included better conversions.
a.k.a dycp unexpanded is the most traditional part. Nothing really special here, except that I had to leave out double-buffering to conserve memory. This also simplified the code a bit.
The scrolling and color-changing border bars were added for release in the unexpanded demo collection. Before this addition I considered dropping this part completely from VIMMII, but now it is cool enough :-)
A new implementation made the plasma look a lot better. We'll start with some background stuff.
The VIMM part faked 8-line characters by having three 24-character patterns. One set has both halves the same, while the others have lighter and darker bottom halves. Character and border colors can be only from 0 to 7. Two sets of patterns are needed to switch colors so that character and border colors are always from 0 to 7, whatever colors are on-screen. The VIMM way thus needed 2304 bytes for the character patterns, but I found a better way. The new way only needs three 32-character patterns, 1536 bytes.
The major change is that the old version used a fixed map to which a running offset was added to cycle the colors. The size of the map was 1044 bytes. Another map was activated while the next part was loaded. I decided to use a 'real' plasma, which did not need a full map. A sine value is calculated for each row and column, each location value is the sum of the row and column values. The frequency and offset of row and columns sines are varied to morph the display. No map is needed, and the sine table only takes 256 bytes.
The scroller is implemented by clearing the multicolor bit in the color memory in the right places. Because the plasma routine always initializes the double-buffered color memory, the routine doesn't do actual scrolling, but plots the pixels anew every frame. Scrolling up emulates 8-line characters by moving the screen start location and only really scrolling every second frame. The plasma row sine calculation is properly compensated so that the plasma display does not jump around. The font is generated from the ROM font by logically oring with a right-shifted version.
The scroller actually demonstrates a dual-color plasma, because when the multicolor bit is cleared, the color memory is also initialized to the right color. The screen cycles with 4 simultaneous colors, the scroller with 2 simultaneous colors.
a.k.a 19-split came into being from some discussions with Aleksi Eeben. He and Britelite had a little competition about who could make the most color splits so I demonstrated an easy way to have two splits in 8 cycles and mentioned how you can have 21 splits total (two splits each 6 cycles) if you only have enough memory. Aleksi urged me to make it happen, and I did a part which had 18 unique background splits with one split rotating on the foreground.
The implementation isn't magic, of course. It is simply 16 lines worth of lda #0 and sta $900f pairs with some other instructions thrown in, and each lda updated each frame with the right colors.
Overlapping chessboards with a wave effect is the part that is most closely just copied from VIMM. The scroller below and a graphics line above are left out, otherwise the code is only slightly changed.
The credits part in VIMM had two overlapping scrolls, one font for each, totalling 6kB. I had already made an improved version of the horizontal scroller, omitting the vertical scroller completely. However, even that improved version used very much too much memory: 3kB for font, two 896-byte buffers and the same amount for actual display area, totalling 5.6kB. And that is already over the 5kB limit, without any space reserved for code, music, video matrix, and other data tables that you end up needing, which made me a little skeptical, but also quite excited.
The display area was filled from the two source buffers, that contained the characters currently on-screen. Different effects are made by transforming the data a bit when copying it to the display area. Two buffers were needed for quarter-character scrolling speed, because horizontal scrolling precision is only one cycle, i.e. half a character. Data in the other buffer is one multicolor pixel rotated compared to the first buffer. This slow scrolling speed was the first feature to remove -- the scroll speed can easily be allowed to be twice as fast, because quarter of a character per frame was actually too slow anyway.
The source buffers are handled like ring buffers, i.e. when a new column of a character appears, only that column must be printed to the buffer, the whole buffer does not need to be scrolled. When copying to display area, only the source pointers need to be scrolled so that the target data is moved by one column while the source data remains the same. This also made it easy to use two buffers, because the same copy routine could be used, just the source pointers were changed to point to the right source buffer.
Actually, we don't even need to change the pointers at all, but scroll the video matrix contents instead. At first the columns corresponds to character codes 0/1..54/55 (two rows, 28 columns). When scrolling new data is copied to charactes 0 and 1, and the video matrix columns are set to 2/3..54/55,0/1.
But the pointers can be set to point to the font itself instead of the source buffer (there is only one now, because we eliminated the shifted one), eliminating the use of a temporary graphics buffer completely. Now we only have the 3kB font and the 896-byte graphics display area, and the pointers have the information about which column of which character corresponds to which column of display data.
This is much better than the original, but still too much. The copying routine requires that each source 'slice' is consequtive 32 bytes and the effects assume that first line of the font is empty. The character packing that is used in the 3k-vimmii part can be applied here, the unit is simply 32 bytes instead of 16 bytes, i.e. only identical columns are removed. To save enough space I had to edit the font more dramatically, I even left out WXZ that were not used in the scrolltext. The result is 1536 bytes for the font, 84 bytes for the mapping table.
The improved scroller allowed two effects and no-effect on-screen simultaneously. Each character (or in fact each column of a character) could select any of these. This required a 120-byte table and the effect code was a little more complicated than necessary. One effect (or no effect) for the whole display only needs one 40-byte table and simplified effect code. Also, I had to drop some effects. Two of the remaining ones use the same data tables and the third leaves the table to 'normal' state after finishing.
Some of the tables are located in color memory (just remember to clear the top nybble), and the loader is not used anymore, so also that 200 bytes is free for grabs. Sprinkled on top with Anders Carlsson's very tiny trackplayer and tune ($90 for music data, $d0 for player) the part is finished.
There is also some bug in the VICE/xvic memory handling: if you leave this part running long enough, xvic or the emulated program crashes.
The source code is provided for the interested parties to encourage the development of new and innovative software for VIC20, whether it is demos, games, or application software.
Ignore the SYSTEM definitions in the source code, only PAL is actually supported.
Download the source: vimmii-2002-src.lha
Update 20090320: Source code for NTSC is now available.
Download the source: vimmii-2002-src-ntsc.zip