FAST-40Copyright © 2025 8-Bit Guru
FAST-40 is a utility program for the Commodore VIC-20 which reconfigures the stock 22x23 text screen to display a denser 40x24 mode. It is written entirely in 6502 assembly language and requires a 3K RAM expansion.
No video hardware modification is required.
Earlier 40-column programs typically suffered from some combination of sluggish performance, visual glitching, or screen-editor functionality issues. FAST-40 was designed from the start to render an artifact-free 40x24 text mode whilst faithfully reproducing standard screen-editor functionality, with performance intended to be comparable to (or better than) the native 22x23 display.
FAST-40 works equally well on real VIC-20 hardware or under emulation - it can be attached as an auto-start cartridge in VICE, LOADed as a program into BLK5 (if configured as RAM) and run manually, or burned/flashed/uploaded into a suitable EPROM or 'soft' cartridge such as the Final Expansion 3.
Both PAL and NTSC video standards are supported.
The JiffyDOS v6.01 Kernal ROM is supported if detected.
NOTE: FAST-40 expects to run on a real or emulated VIC-20 with an NMOS 6502 and makes use of several undocumented opcodes. It will not operate correctly on later 6502 variants (e.g. the CMOS 65C02) which disable or repurpose these opcodes.
The FAST-40 project is hosted on GitHub.
Creation of modified or derivative works using, in whole or in part, any sourcecode, assets, or binary artifact originating from this project is subject to the following:
-
Free for non-commercial use (you must clearly include a credit link to this project within your project).
-
Commercial use is expressly forbidden except by explicit consent from the copyright holder.
If you're familar with VICE and just want to dive straight in...
-
clone the repository, which includes an artifacts folder containing:
- FAST-40 built as an autostart cartridge (fast40.bin)
- FAST-40 built as a LOADable program (fast40.prg)
- a disk image (fast40.d64) containing the program build, a simple performance-comparison program written in BASIC, and a copy of the BASIC adventure game CITADEL adjusted for a 40-column display
-
invoke xvic with xvic.exe -memory all -cartA fast40.bin
This will start the emulator with the FAST-40 cartridge installed and 24K for BASIC to play with.
-
Editor
My personal choice is Visual Studio Code, but any editor you're comfortable with will suffice. I also use a 3rd-party VSCode extension called Kick Assembler 8-Bit Retro Studio 0.23.3 which provides a bunch of useful functionality including syntax highlighting and automated invocation of KickAssembler and VICE without needing to switch out to a command prompt. -
Assembler
The sourcecode syntax targets KickAssembler 5.25. No other build tool is required.
Note that KickAssembler is written in Java and requires a Java runtime to operate. My preference is AdoptJDK. -
Emulator
The code builds a binary cartridge image which can be used with xvic, the VIC-20 emulator shipped with VICE.
To generate the autostart cartridge ROM artifact (fast40.bin):
java -jar [Your_KickAssembler_Path]\KickAss.jar main.asm -o fast40.bin -binfile
To generate the LOADable program artifact (fast40.prg):
java -jar [Your_KickAssembler_Path]\KickAss.jar main.asm -o fast40.prg
To start xvic with the cartridge ROM from the commandline:
[Your_VICE_Path]\bin\xvic.exe -memory all -cartA fast40.bin
To use the LOADable program within xvic, enable all RAM blocks, attach the fast40.d64 disk image, and type:
LOAD"FAST40",8,1
SYS64802
Consult the VICE documentation for full details regarding commandline options associated with attachment and autostarting of disk images and programs.
FAST-40 supports all VIC-20 character glyphs and control characters, including those for cursor positioning, colour selection, reverse-mode, etc. The VIC-20 keyboard does not emit visible characters for the SHIFT/C= key combination (which performs the toggle between upper-case and lower-case character sets) but these non-printing characters do exist and are supported.
Unlike the stock VIC-20, FAST-40 allows both upper- and lower-case graphics charactersets to be displayed simultaneously.
Performance tests yield a character output rate superior to the native 22x23 mode - ranging between 7% to 40% faster, depending on the workload complexity.
The FAST-40 program occupies the BLK5 ($A000-$BFFF) ROM/RAM area and uses areas of pages zero and two as working storage. Additionally all of the 4K unexpanded RAM area is needed for video display reconfiguration, and the text buffer is placed in the 3K expansion RAM area in BLK0. Slightly less than 2K of this block is left free for BASIC ($0400-$0AFF).
If 8K (or 16K or 24K) expansion RAM is also present in BLK1/2/3 then FAST-40 will make these blocks entirely available for BASIC and the 'lost' memory in BLK0 remains available for machine-code programs.
FAST-40 provides a new BASIC command to easily reset the system and switch between memory configurations without having to swap cartridges. Note that memory is cleared during a system reset.
RESET [0|3|8] Switch to specified video/memory configuration
RESET Switch to 40x24 3K/8K+ mode
RESET 0 Switch to 22x23 unexpanded mode
RESET 3 Switch to 22x23 3K mode
RESET 8 Switch to 22x23 8K+ mode (if RAM is present in BLK1/2/3)
On a stock VIC-20 the SHIFT/RUNSTOP key combination causes the commands LOAD and RUN to be injected into the keyboard buffer to initiate an automatic start of the next program found on tape. Modern users prefer to use disk (or pseudo-disk devices such as SD cards) for storage instead of tape, and will often make use of the JiffyDOS Kernal ROM which disables tape operations in order to provide extended disk functionality.
FAST-40 detects the presence of JiffyDOS and alters the SHIFT/RUNSTOP commands to favour disk users as follows:
- If JiffyDOS is not present, the sequence
LOAD"$",8is executed to read the directory of the disk - If JiffyDOS is present (featuring the preferred
@$command to view the directory) the sequenceLOAD"*",8is executed to load the first program on the disk
On a stock VIC-20 the SHIFT/C= key combination (or programmatic equivalent) causes the VIC to switch between two charactersets stored in ROM at $8000 and $8800. The first set contains upper-case letters and a wide selection of PETSCII graphics characters, whereas the second contains both upper- and lower-case letters and a smaller choice of PETSCII characters. Switching charactersets instantly affects all visible characters on the screen, not just those which are displayed after the switch occurs.
The initial FAST-40 release took pains to reproduce this behaviour, ensuring that the entire screen was refreshed whenever a characterset switch occurred. However since characterset switches typically happen before any characters are output (rarely being useful otherwise) the engineering overhead to drive the refresh and the associated rendering throughput performance impact was largely suboptimal. The refresh feature was therefore dropped in later releases.
FAST-40 makes changes to numerous memory areas, VIC registers, and system vectors in order to configure and manage the 40x24 display mode.
Memory areas:
$0003-$0004 Not normally used by BASIC/KERNAL. [only used if BRK debugging is enabled on build]
$00D9-$00F1 Normally used as the BASIC screen editor line-link table.
$02A1-$02FF Not normally used by BASIC/KERNAL.
$0B00-$0FFF Top of 3K RAM expansion (BLK0).
$1000-$1FFF Normally used as the unexpanded screen and RAM area.
$9400-$95FF Normally used as colour memory when RAM is in BLK1/2/3.
VIC registers:
$9000 Screen x-position
$9001 Screen y-position
$9002 Screen memory address and columns
$9003 Screen rows and character height
$9005 Screen memory address and character generator address
System vectors:
$028F/$0290 SHIFT/CTRL/C= key decode
$0308/$0309 BASIC decode
$0314/$0315 IRQ interrupt
$0316/$0317 BRK interrupt
$0324/$0325 Character input
$0326/$0327 Character output
These vectors may be modified by other programs wishing to provide additional functionality alongside FAST-40. Such programs should preserve the vector chain by first capturing the target address of whichever vector(s) they need before replacing them with their own, and finalise their processing by passing control to those captured addresses.
The VIC-20 has no memory protection hardware and therefore FAST-40 cannot 'lock' the various memory areas, vectors, and VIC registers it uses. The following cautions apply for other programs wishing to operate in the 40x24 mode:
-
Programs should not read/write video or colour memory directly, but instead use the PRINT statement (in BASIC) or call the CHROUT vector at $FFD2 (in machine-code). Both are designed to route their output through the character input/output vectors which point to the custom display logic within FAST-40, and thereby allow it to manage screen output.
-
Common programming techniques such as switching character-case by altering the value at address 36869 ($9005), adjusting cursor blink phase, frequency, or position by altering the relevant zero-page values at $CC/$CD/$CF/$D3/$D6, or otherwise directly interacting with screen editor functionality via zero-page or other addresses is discouraged. Such interactions are unlikely to yield the expected result and will probably disrupt FAST-40 operation.
-
Limitations in the VIC design mean there is no way to preserve the usual 1:1 relationship between individual text-mode characters and their respective colour attributes when in 40x24 mode. All text colours are supported but they operate on 2x2 blocks of characters; in other words, the colour resolution is half that of the text resolution and colour layout should therefore be planned accordingly to avoid attribute clash.
In the event that a program inadvertantly 'breaks' FAST-40 by overwriting something it depends upon to generate the 40x24 mode, recovery can be achieved in the following ways:
-
Writes to the text buffer, display bitmap, colour memory, and screen-editor management areas will be repaired whenever the screen is cleared with SHIFT/CLRHOME or PRINT CHR$(147).
-
Writes to the VIC registers, system vectors, and/or most other runtime memory structures can almost always be repaired via a RUNSTOP/RESTORE 'soft' reset.
-
Any catastrophic breakage that exceeds the capacity of FAST-40 to repair itself will require a system reset to resolve. This can be achieved by power-cycling the machine, hitting a hardware reset button if available, or by using the new RESET command. Note that memory is cleared during a system reset.
The following VIC-20 afficionados at Denial actively participated in the beta-test phase. Their time and effort spent testing, sending bug reports, and assisting with crash diagnosis is greatly appreciated:
- tokra
- mathom
- Initial release for testing.
- Fixed a bug where entering long BASIC lines would sometimes lose the character in column 40, causing syntax errors (reported by tokra@denial)
- Fixed a bug where data fed to the INPUT command included the prompt in the returned value and therefore broke it (reported by mathom@denial)
- Fixed a bug where inserting a character into a long line would sometimes erroneously insert a blank line after it
- Fixed a bug where doing a character insert in column 40 erroneously placed the inserted space character into column 39
- Fixed a bug in the screen-scrolling logic where it forgot that the text buffer layout is not linear
- Fixed a bug where RUNSTOP/RESTORE didn't reset the default text colour and character-case
- Added a BRK handler to display CPU registers (to help debug a JiffyDOS showstopper crash reported by mathom@denial)
- Added an alternate build option to do LOAD"$",8 / LIST on SHIFT/RUNSTOP
- Tweaked the PAL/NTSC startup test to save the result for RUNSTOP/RESTORE and thereby avoid repeated re-tests
- Tweaked the cursor blink phase timings to help cursor visibility during rapid/repeated movement (reported by mathom@denial)
- Fixed a bug introduced in Beta 2 which corrupted the Stack and broke the INS/DEL routines (reported by tokra@denial)
- Fixed a bug where deleting a character from column 1 replaced the character in column 39 on the previous line instead of column 40
- Fixed a bug where deleting a character from column 1 of an unlinked line produced an unwanted side-effect on the previous line
- Fixed a bug where the screen-scroll CTRL-delay code intermittently failed to execute properly (reported by tokra@denial)
- Fixed a bug where the startup RAM detection wasn't triggering a clean system reset if BLK1 is empty
- Fixed the JiffyDOS showstopper crash (JiffyDOS rearranges some code in the SHIFT/CTRL/C= ROM keypress logic)
- Added the JiffyDOS banner to the startup message (if JiffyDOS is detected)
- Fixed a bug where line continuation markers were not correctly reset after a screen-scroll event
- Fixed a bug in the SHIFT/C= keypress handler to prevent keybounce
- Tweaked SHIFT/RUNSTOP keypress behaviour to better suit JiffyDOS users
- Tweaked startup colours back to stock blue-on-white for NTSC visual clarity (prompted by gunner@denial)
- Restructured memory usage so FAST-40 only needs 3K in BLK0 and leaves all 8K blocks free for BASIC
- Refactored bitmap rendering path logic (FAST-40 draws 40x24 mode faster than the stock ROM draws 22x23)
- Refactored logic in INS/DEL keypress, bitmap line-refresh, and logical line extension routines
- Removed case-switch bitmap refresh which caused a race condition crash (reported by boray@denial)
- Added \artifacts folder to the repository, containing
- fast40.bin - pre-built cartridge version
- fast40.prg - pre-built LOADable version (prompted by boray@denial)
- fast40.d64 - disk image containing fast40.prg plus a simple performance-comparison program written in BASIC and a copy of the BASIC adventure game CITADEL adjusted for a 40-column display
- Fixed a bug where the BRK handler wasn't being set properly (reported by mike@denial)
- Refactored startup logic so the RUNSTOP/RESTORE handler can do better breakage recovery
- Add a SHIFT-key modifier to the scroll CTRL-delay logic to toggle a scroll-lock until released
- Added overwrite protection so SHIFT/RUNSTOP actions trigger LOAD ERROR if there is a BASIC program in memory
- Removed the queued LIST and RUN commands from SHIFT/RUNSTOP actions as they were not processed correctly
8-Bit Guru (also: Eight-Bit Guru, 8BitGuru, 8BG) is the nom de guerre of Mark Johnson. I'm a professional coder from the UK who has been telling computers what to do since 1981. My day job is all about C# and Azure, whilst my hobby projects mostly involve writing 6502 assembly language for the VIC-20 (my first computer, back in '81).