Sunday, August 11, 2024
Save capability added to C64 version of VWAS6502 monitor
Tuesday, July 16, 2024
6502 Help References included in 6502 monitor
![]() |
| 6502 mini-assembler help system |
The help system recently added to the 6502 monitor (vwas6502) includes
- help commands
- monitor commands reference
- 6502 instruction set mnemonics
- 6502 addressing modes references, listing valid instructions
- opcodes with addressing modes available for a specific instruction mnemonic
Friday, July 12, 2024
Mini-assembler with disassembler, display, edit, and run
| Sample assembly entry and run example |
Everyone (in a small corner of the retro programming community) has their favorite machine language monitor. Mine is HESMON for the Vic-20 which I got in the early 80s. I probably also used TinyMon, and have used SuperMon in recent years. The VICE monitor (ALT+H) is great, especially like the symbolic label support which I use to debug my programs assembled with ACME. Also the Commodore monitors are great too, including Commodore 128 and Plus/4 (and family).
But recently I've been playing with WozMon, both in a a minimal emulated 6502 system, and compiled for Commodore. But I didn't have a great disassembler and assembler to go with it. I looked around a little (probably not enough).
My programming brain and fingers were itching to build my own. So I set out to prototype the assembler portion in C#, the disassembler in 6502 using tables generated by the C# experience, and finally created a wozmon compatible monitor in 6502 with both disassembler and mini-assembler as we see here today.
Let's cover the syntax briefly.
Display memory is a single address (up to 4 hex characters) either by itself, or two addresses separated by a dot for a range of memory. Below we are looking at the C64 jiffy clock by entering "A0.A2". The result is the starting address followed by a colon and three bytes of memory from that range.
Tuesday, July 9, 2024
Disassembler for use with WozMon
| Disassembler disassembling WozMon |
WozMon is a great little monitor program in 256 bytes which Steve Wozniak wrote for his Apple 1 release in 1976. It was small but powerful allowing for memory inspection, entry of 6502 machine code programs and bytes, and launching of programs in ROM and RAM (jumping to address).
But being small, it is missing features that monitor users have learned to depend on, including a mini-assembler and disassembler.
So here I am today presenting a disassembler I wrote for 6502 which can be integrated with WozMon run command. Once the disassembler gets control, the Y register contains a pointer to the last character read from the input buffer, and continues parsing for a hex address. If not found, it simply returns to WozMon. But if found, it will disassemble 20 statements starting at that address. (Note: Vic-20 port above, changed to 17 statements due to the smaller screen size).
The syntax may be lengthier than other monitors, but it allows for an integration with the normally ROM based WozMon without modifications. Plus you get what you pay for. The disassembler is open source, so feel free to change it.
The disassembler came into being as part of developing a mini-assembler. First I'd written a prototype in C# .NET.
The assembler included tables of information for the 6502 instruction set and addressing modes that lent itself to be used as a disassembler (came second) which was prototyped as a 6502 program that disassembles itself. Third came the disassembler compatible for use with WozMon.
Each prototype and program is one step along the way for the goal of creating a mini-assembler for my 6502 minimal system. Not there yet, but getting closer with each step!
| Also works with original WozMon in Apple 1 style environment |
| Also works on C64 and C128 systems |
Sunday, June 2, 2024
BANKTEST for C64
While adding banking support to my own C64 emulator back in the good 'ole days (April 14, 2020, maybe only good for hunkering down on retro stuff), I also wrote a test program to help verify the results. This may help you visualize how you can access more RAM and ROM on the C64.
The program works by switching to the RAM only bank writing a signature high byte to four addresses, then cycles through the standard list of banks reading the value at those locations. Of course the first line for bank zero shows the bytes as expected. But the other banks tell a different story.
A000-BFFF is BASIC ROM. Appears ROM is active in banks 3 & 7 only, otherwise is RAM.
C000-CFFF is always RAM.
D000-DFFF is usually I/O (banks 5-7) including color RAM at D8000 (notice the high nibble changes in this run). May also appear as RAM (banks 0 & 4), CHAR ROM (banks 1-3).
E000-FFFF is BASIC ROM (banks 2, 3, 6, 7), otherwise RAM (banks 0, 1, 4, 5).
It is interesting to see the similarities and differences in this chart.
The key code to switching banks includes
sei
lda $01
and #$f8
ora #bank_selection
sta $01
rts
Only clear the interrupt flag (cli instruction) once you have returned to the normal bank (7) so IRQ vectors and the KERNAL/BASIC ROMs will work as expected.
I have also color encoded the banks in this chart to represent their effects:
Links
- Source: bank_test.asm
- Program: bank_test.prg
Thursday, May 9, 2024
Running SWEET16, Steve Wozniak's "The Dream Machine" from WozMon
![]() |
| Also imagine 60K RAM and 4K ROM here (oops!) |
# SWEET16 compiled for EE80 start addressEE70: 20 EA EE 68 85 1E 68 85EE78: 1F 20 7F EE 4C 79 EE E6EE80: 1E D0 02 E6 1F A9 EF 48EE88: A0 00 B1 1E 29 0F 0A AAEE90: 4A 51 1E F0 0B 86 1D 4AEE98: 4A 4A A8 B9 C8 EE 48 60EEA0: E6 1E D0 02 E6 1F BD CBEEA8: EE 48 A5 1D 4A 60 68 68EEB0: 20 F6 EE 6C 1E 00 B1 1EEEB8: 95 01 88 B1 1E 95 00 98EEC0: 38 65 1E 85 1E 90 02 E6EEC8: 1F 60 00 F7 02 9B 0B 9CEED0: 23 AD 14 B0 45 B7 4F BEEED8: 2D C7 59 D0 83 DB 6C 03EEE0: 31 E6 6E 91 1C E5 63 E5EEE8: E5 E5 85 20 86 21 84 22EEF0: 08 68 85 23 D8 60 A5 23EEF8: 48 A5 20 A6 21 A4 22 28EF00: 60 10 B3 B5 00 85 00 B5EF08: 01 85 01 60 A5 00 95 00EF10: A5 01 95 01 60 A5 00 81EF18: 00 A0 00 84 1D F6 00 D0EF20: 02 F6 01 60 A1 00 85 00EF28: A0 00 84 01 F0 ED A0 00EF30: F0 06 20 64 EF A1 00 A8EF38: 20 64 EF A1 00 85 00 84EF40: 01 A0 00 84 1D 60 20 24EF48: EF A1 00 85 01 4C 1D EFEF50: 20 15 EF A5 01 81 00 4CEF58: 1D EF 20 64 EF A5 00 81EF60: 00 4C 41 EF B5 00 D0 02EF68: D6 01 D6 00 60 A0 00 38EF70: A5 00 F5 00 99 00 00 A5EF78: 01 F5 01 99 01 00 98 69EF80: 00 85 1D 60 A5 00 75 00EF88: 85 00 A5 01 75 01 A0 00EF90: F0 E9 A5 1E 20 17 EF A5EF98: 1F 20 17 EF 18 B0 0E B1EFA0: 1E 10 01 88 65 1E 85 1EEFA8: 98 65 1F 85 1F 60 B0 ECEFB0: 60 0A AA B5 01 10 E8 60EFB8: 0A AA B5 01 30 E1 60 0AEFC0: AA B5 00 15 01 F0 D8 60EFC8: 0A AA B5 00 15 01 D0 CFEFD0: 60 0A AA B5 00 35 01 49EFD8: FF F0 C4 60 0A AA B5 00EFE0: 35 01 49 FF D0 B9 60 A2EFE8: 18 20 64 EF A1 00 85 1FEFF0: 20 64 EF A1 00 85 1E 60EFF8: 4C AE EE 00 00 00 00 00
1000: 20 00 FE A9 2A 20 70 EE
1008: 11 12 34 12 56 78 21 A2
1010: 33 00 8D F8 FF 00
20 00 FE JSR $FE00
A9 2A LDA #$2A
20 70 EE JSR $EE70
11 12 34 SET R1,$3412
12 56 78 SET R2,$7856
21 LD R1
A2 ADD R2
33 ST R3
00 RTN
8D F8 FF STA $FFF8
00 BRK
JSR $EE70 switches to SWEET16 interpretation, and these are SWEET16 instructions through RTN, before being back in 6502. The vectors are set such that a BRK will return to WozMon. ($FE00 is my specific UART initialization routine for MC6850, and storing a byte to $FFF8 will send it across the UART).
All this program does is set the R1 and R2 16-bit registers to constant values, the LD instruction loads the 16-bit accumulator from R1, then ADD R2 adds R2 to the accumulator, and the result is stored in R3 by the ST instruction. RTN returns to normal 6502 operation.
7. To run the program, enter the following into WozMon:
1000R
8. Display the results by entering
0.1FR
From the last two steps the output should look something like the following (blank lines added for separation)
1000R1000: 20*\0.1F0000: 68 AC 12 34 56 78 68 AC0010: 00 00 00 00 00 00 00 000008: 00 00 00 00 00 00 00 000018: 00 00 00 00 00 06 12 10
And the accumulator (R0) at addresses 0 and 1 now has the value $AC68 which appears to be the sum of the other two 16-bit values, with a copy also stored at R3 (addresses 6/7). The asterisk is printed to demonstrate registers being saved/restored and 6502 operation returning to normal.
That's just a quick example. Hopefully you've got a little taste of WozMon and SWEET16.
![]() |
| Example run of SWEET16 |
But that's not all!
# Commodore port of SWEET161540: 85 22 86 23 84 24 08 681548: 85 25 d8 60 a5 25 48 a51550: 22 a6 23 a4 24 28 60 001558: 00 00 00 00 00 00 00 001560: 00 00 00 00 00 00 00 001568: 00 00 00 00 00 00 00 001570: 00 00 00 00 00 00 00 001578: 00 00 00 00 00 00 00 001580: 20 40 15 68 85 7e 68 851588: 7f 20 8f 15 4c 89 15 e61590: 7e d0 02 e6 7f a9 16 481598: a0 00 b1 7e 29 0f 0a aa15a0: 4a 51 7e f0 0b 86 7d 4a15a8: 4a 4a a8 b9 d8 15 48 6015b0: e6 7e d0 02 e6 7f bd db15b8: 15 48 a5 7d 4a 60 68 6815c0: 20 4c 15 6c 7e 00 b1 7e15c8: 95 61 88 b1 7e 95 60 9815d0: 38 65 7e 85 7e 90 02 e615d8: 7f 60 00 f7 02 9b 0b 9c15e0: 23 ad 14 b0 45 b7 4f be15e8: 2d c7 59 d0 83 db 6c 0315f0: 31 e6 6e 91 1c e5 63 e515f8: e5 e5 00 00 00 00 00 001600: 00 10 c3 b5 60 85 60 b51608: 61 85 61 60 a5 60 95 601610: a5 61 95 61 60 a5 60 811618: 60 a0 00 84 7d f6 60 d01620: 02 f6 61 60 a1 60 85 601628: a0 00 84 61 f0 ed a0 001630: f0 06 20 64 16 a1 60 a81638: 20 64 16 a1 60 85 60 841640: 61 a0 00 84 7d 60 20 241648: 16 a1 60 85 61 4c 1d 161650: 20 15 16 a5 61 81 60 4c1658: 1d 16 20 64 16 a5 60 811660: 60 4c 41 16 b5 60 d0 021668: d6 61 d6 60 60 a0 00 381670: a5 60 f5 60 99 60 00 a51678: 61 f5 61 99 61 00 98 691680: 00 85 7d 60 a5 60 75 601688: 85 60 a5 61 75 61 a0 001690: f0 e9 a5 7e 20 17 16 a51698: 7f 20 17 16 18 b0 0e b116a0: 7e 10 01 88 65 7e 85 7e16a8: 98 65 7f 85 7f 60 b0 ec16b0: 60 0a aa b5 61 10 e8 6016b8: 0a aa b5 61 30 e1 60 0a16c0: aa b5 60 15 61 f0 d8 6016c8: 0a aa b5 60 15 61 d0 cf16d0: 60 0a aa b5 60 35 61 4916d8: ff f0 c4 60 0a aa b5 6016e0: 35 61 49 ff d0 b9 60 a216e8: 18 20 64 16 a1 60 85 7f16f0: 20 64 16 a1 60 85 7e 6016f8: 4c be 15
![]() |
| C64 running WozMon and SWEET16 |
A9 2A LDA #$2A
20 80 15 JSR $1580
11 12 34 SET R1,$3412
12 56 78 SET R2,$7856
21 LD R1
A2 ADD R2
33 ST R3
00 RTN
20 D2 FF JSR $FFD2
4C 00 14 JMP $1400
Friday, April 19, 2024
Edit Programmable Characters on Vic-20 and C64
The current release is considered fully functional and complete.
Links:
Vic-20 D64 (1541 image) and source
Commodore 64 D64 (1541 image) and source
The Commodore Vic-20 video chip added multiple features beyond what the original PET Model 2001 offered. Besides color support, it also includes the ability to change to user defined character sets. These can be used to customize the look and feel of a program, and also to provide bitmapped graphics.
Back in the 80s I was proud of my development of a character editor program that utilized a few machine language routines to perform quick operations via keyboard selections. Unfortunately I don't have direct access to that program today (haven't been able to read the tape back into the computer yet). So I decided to rewrite it again.
This time it is purely 6502 assembly code. I started using the VICE monitor to write the initial functionality, and soon afterwards transitioned to ACME source to ease edits and additions.
After mocking up the look of the screen, identifying operations that would be nice to have, and testing out memory layout and configuring the video chip to use character images from RAM, I got to work.
1. Initial screen layout including editor and commands.
2. Navigation of character selection, displaying bit patterns for editing to screen, and displaying hex character value and byte values.
3. Editing the pixels in a single character.
4. Saving font to floppy disk.
5. Continuing to iterate with new features and enhancements
Description of key operations
pressing a key on the keyboard as shown below will perform an operation:
@ - toggle between RAM/ROM character sets
SPACE - toggle pixel on/off
B - navigate back one character
C - copy
F - flip upside down
M - mirror the image left to right, right to left
N - navigate forward to next character
R - rotate 90 degress to the right
S - save to FONT.BIN (WARNING: overwrites any previous saves)
V - paste
X - cut
Y - redo
Z - undo
- minus - navigate 16 characters back
+ plus - navigate 16 characters forward
< > - shift pixels left/right
↑ - shift pixels up (^ carrat on PC)
Shift V - shift pixels down
CLR - erase all pixels
CURSOR keys - move cursor left/right/up/down
HOME - move cursor to upper left position
RVS - inverse the pixels
STOP - exit (usually mapped to ESC on PC)
There are up to 24 levels of undo [Z] (25 levels of redo [Y]) when editing a character. Navigating will clear the undos/redos. And there is a virtual clipboard which you can copy[C]/cut[X]/paste[V] a single character. Note in this program you do not use the Ctrl key for clipboard as you do on a PC.
Notes:
- When launching the program for the first time, the ROM font will be copied to RAM, including moving the start of programs up to $1800 past the RAM characters. Subsequent runs from that address will not recopy from ROM. If you want to restart fresh from ROM, either reset your computer and run again, or POKE 44,16:SYS 6157. You don't have to memorize the entry point, you can also LIST the line of BASIC that calls into the entry point.
- Saving overwrites FONT.BIN. So if you want to save your work permanently, it is recommended to rename your file to something else.
OPEN 15,8,15,"R0:COOL=FONT.BIN":CLOSE 15 - To LOAD your font for editing, be sure to run the program at least once, then load before running to enter back into edit mode. Be sure to include the ,1 otherwise you will wipe the font editor out of memory, then best to restart your Commodore and try again.
LOAD "COOL",8,1 - Pressing COMMODORE+SHIFT while in programmable characters will shift to a second set of characters which we don't have room for in RAM, so you will see bitmapped images of the program and video memory. Press the key combination again to return to the first set of characters. [Disabled in the C64 port]
Update 2024 April 26: more documentation
H - hide UI except pixels and character for a minimalist experience
/ - swap between two RAM character sets (C64 version edits total of 512 characters)
F1 - foreground color
F2 - cursor color
F3 - background color
F4 - character set 1 color
F5 - border color
F6 - character set 2 color
F7 - large pixel set color (editor)
F8 - large pixel cleared color (editor)
, - change titles color
. - change menus color
1,2,3,4,5,6,7,8,9,0 - select theme (colors and grid mode)
As the C64 has a different memory layout, video memory is at a lower address $0400 and more memory available, the memory map is a bit different. The start of the program is still at $1800, but the programmable characters are now from $0800 to $17FF, a full 4K (512 characters).
Note that only the first character set (256 characters) is visible at this address without moving the character set to another location (planned for future). But the editor can handle this by swapping the character sets in RAM for editing, swapping them back and forth, so one set is always edited from the lower $0800-$0FFF range that is visible. Just be sure to swap back to the first set before saving, otherwise the character sets will be out of order.
To use both character sets in your own programs, it is necessary to manually relocate them or load them at another address, unless you use the swapping technique used by the editor.
It is not presently possible to use raster interrupts to show both sets because the second set is at an address that is mapped to ROM characters instead. Another reason it is planned to move these in the future, for example to $3000-$3FFF but in the middle of BASIC RAM it may be too challenging to be useful to others.
Probably a better solution is to move both VIC-II memory to another bank of 16K, which also requires moving video memory. Say bank 4 with characters at $F000-$FFFF, and video ram at $CC00-$CFFF. Then move the start of BASIC to $0400, resulting in 39933 (39K) bytes available for BASIC, an increase of 1K the size of the video screen memory.
Leaving the editor, you have lost 4K of RAM from BASIC. To reclaim 2K for the not visible second character set, POKE 44, 20: POKE 20*256, 0: NEW but don't load any of your double character sets or you will wipe out the first 2K of your BASIC program. Best to leave 4K lost at start of BASIC in that case, or resize your character sets to a single set.
We're in the weeds here. Back to the fun -- please enjoy the programmable character sets and the graphical opportunities they provide!
Update 2024 April 27: raster interrupts implemented as described above, with two sets on screen, and working area using ROM font so doesn't change. Second set is copied to $3800-$3FFF for display purposes, while the two sets remain at $0800-$17FF.
Update 2024 April 28: themes implemented (10) and grid mode added, new C64 keys updated above. Themes allow quickly changing between color sets and grid options using the numeric keys.
Update 2024 May 1: wrote an article on moving video and programmable character memory.
Update 2024 May 4: have fixed many issues, and more enhancements, including moving programmable characters to $2000-$2FFF to make more usable, eliminate need to have separate edit/view copies. But loses more BASIC RAM ($0800-$1FFF 6K now available for other uses) while reserving memory for characters.
| Primary Color Theme |












