Thursday, 8 March 2012

In Which Things Begin To Appear


If you've been paying attention, you'll remember that one of the design goals of this new ROM is to build 40-column text display capability into the heart of the OS, which means reconfiguring the VIC to do something other than the Commodore design of a 22-column display. Their decision to go with this mode was partly dictated by the capabilities of the VIC chip, by the choice of the 8 x 8-pixel PET character-set as the one to use in the VIC-20, and to memory constraints for the VIC-20 hardware configuration - that is, whilst the machine is entirely capable of supporting a 'hi-res' display (and thus of drawing 40-column text if the character-set glyph matrix was smaller) this requires more memory than was available in the baseline VIC-20 if they wanted to leave any free for user programs. The VIC chip can display a high-resolution bitmap of a variety of sizes, just by altering the dimensions of the screen through the VIC registers - but the bigger the bitmap, the more memory the screen needs. The standard configuration (22 x 23 characters, or 176 x 184 pixels) needs 506 bytes for the video matrix, where each byte of the video matrix points to an 8 x 8 cell somewhere else in memory for what to actually display - normally this means the 4K Character Generator ROM at $8000.

By tweaking the VIC registers to alter the screen dimensions, and telling the chip to look elsewhere for the 8 x 8 cell glyphs, it is possible even on the unexpanded VIC-20 to create user-defined graphics, or even draw limited hi-res images. If you plug-in some expansion RAM, you can make the screen larger and draw more sophisticated images - and the few 40-column solutions that existed for the machine basically used this technique. The native VIC++ 40-column mode will work in a similar way, but with one sizeable advantage - whereas all other solutions had to consume some precious RAM to hold their user-defined 40-column character-set, I can simply replace the actual Character Generator ROM image with a customised one which sits at $8000 as normal (occupying no RAM) but which contains the binary data for a smaller, 5 x 8 cell character-set. Note: depending on how this actually ends-up looking, I might drop a 4 x 8 cell binary in there instead, but we'll see how it goes.

I've chosen 5 x 8 as the glyph size for a specific reason; the maximum number of columns that the VIC can normally display before running-off the edge of the screen is around 28 (it varies by the display mode - PAL or NTSC - and how far to the left and right you can adjust the edges of the screen matrix) which gives us 224 pixels. So that would give us a maximum glyph width of 5.6 pixels, and since we can't use 0.6 of a pixel, it gets rounded-down to 5. That then means the width of the screen can be set to 200 pixels, giving us room for 40 glyphs in a row, and we can therefore tweak the VIC screen registers to set the width to 200 and centre the video matrix horizontally. For the depth of the screen, I wanted to try to better the 23 rows the standard VIC configuration provides, and in fact by experimentation I've found that we can comfortably fit 32 rows into a PAL screen, yielding a 256-pixel drop. I haven't finalised this (I might reduce the line count to make the memory footprint a little smaller) or the horizontal centring / vertical depth of the video matrix for NTSC displays yet, but once the basic screen-handling code is done I'll come back and tune the VIC register values for an appropriate display format.

Since the VIC++ ROM initialises the screen to start at $1000 and we're replacing the Character Generator ROM at $8000, initialising the VIC registers really just becomes a matter of plugging-in the specific values to define and centre a 200 x 256 video matrix. The matrix itself will require 800 bytes of RAM, which is a fraction over 3 pages so it'll be rounded-up to 4, meaning 1024 bytes (1K). Accordingly, as well as defining the VIC register values and writing the little initialisation routine, I've also gone back to the .initos routine to bump up the pointer to the start of user code space (_USERCODE at $02) so that it leaves room for the enlarged video matrix and starts at $1400 instead of $1200. However, that's not the whole story, because we also need a chunk of memory for the bitmap - the place where I'll assemble glyphs into a display, and which the bytes in the video matrix will point to. On an unexpanded VIC-20, the video matrix alone leaves about 3K for user code and the Symbol Table - not a lot, which is why the ROM is designed to find and use any expansion memory you can throw at it. The bitmap area will consume even more of this, so it's highly likely that VIC++ will need at least the 3K expansion configuration in place.

The code to initialise the VIC registers is dead simple - the values are stashed in a table (_VICDATA) and conditionally assembled for either the PAL or NTSC settings, so the routine is just this:

_VICDATA
DC.B $09,$17,$19,$3E,$00,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08 ; PAL settings

LDX #$0F ; [2] register value index
.setreg
LDA _VICDATA,X ; [4] get register value byte
STA _VIC,X ; [5] set VIC register
DEX ; [2] decrement index
BPL .setreg ; [3/2] loop for next byte

See, told you it was simple. What wasn't quite so simple was defining some binary data to load into VICE as the replacement Character Generator ROM - in the end, I used a rather nice little VIC-20 character editor program called LCE to design some test glyphs, exported the data into XVI32, and saved it. Then I made a quick alteration to the command-line parameters for VICE to add the '-chargen' option so that it loads my glyph data instead of the Commodore patterns, and added a little test routine to the VIC++ ROM to poke the first 36 glyph codes to the screen...

S U C C E S S ! !

You can't see me grinning, but trust me: I am.

Now the astute and keen-eyed amongst you will be looking at this, and saying: "Hold on, I count 25 characters across that screen, not 40 - who are you kidding?".

Yep, guilty as charged, your honour - what's actually going on here is that the VIC is doing what it's designed to do, which is to take 8 x 8 glyphs and throw them on the screen at 8 pixel intervals; it doesn't realise that I've played a mean and dirty trick on it by swapping the expected 8 x 8 Character Generator ROM for a 5 x 8 one, and in fact there's no way to tell it that I've done so. In order for the glyphs to be displayed at 5-pixel intervals, I have to assume responsibility for drawing the screen, and for mapping 5 x 8 glyphs into 8 x 8 cells that the VIC can play with. That's next.

Oh, you might also be thinking: "That font sucks!". Hey, I'm a programmer, not an artist - I said they were test glyphs. If you think you can do better, let me know - if I use a copyright-free font submitted by a reader, they'll get a credit both here and in the ROM binary itself.




















No comments:

Post a Comment