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 |
Wednesday, June 12, 2024
Strings or Compact directory utility for C64
Directory listings scrolling by too fast? Want to scan program for string literals? Here's a stupid (sometimes useful, definitely ugly) utility I created in the monitor for both scenarios. Compact display and pauses every 24 lines. Attempts to avoid control characters.
Note: operates on whatever loaded program is in memory, assuming BASIC.
Shown loading into tape buffer (828), can be relocated.
This source is an example of parsing a BASIC program. The beginning of BASIC is grabbed from $2B/2C, and each line of the program is iterated through traveling its linked list ending with a null pointer. In each line, a string starts with double quotes and ends with double quotes or end of line (zero or nul character). Multiple strings per lines are possible. Other memory addresses used include toggling the reverse flag ($C7), setting quote ($D4) and insert ($D8) modes, and counting each time at the left column ($D3). Outputs string characters via $FFD2, and waits for a key press via $FFE4.
This is a short program that can be studied. I hope you find it useful and informative. Enjoy!
Links:
original (compact) strings.prg
updated (one line) strings.prg
source at github
Copyright (c) 2024 by David R. Van Wagner
MIT LICENSE
UPDATE: (September 3, 2024) compact version was too ugly for me. Have since updated source to display one string per row of the screen, with an option (POKE 951, 96) to revert to compact functionality. See updated links above.
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
Sunday, May 26, 2024
LCD version of 6502 emulators ported to Windows
![]() |
LCDs and Windows too! |
Wednesday, May 1, 2024
C64 RAM locations for programmable characters
Taking the information from Jim Butterfield's interactive program we can determine a few optimal choices for configuring the location of video and character set memory. They both need to be in the same 16K bank of the C64 memory, video memory needs to be accessible to the KERNAL, and some locations are off limits (offsets $1000-$1FFF within VIC-II 16K banks 0, 2) because the VIC-II only sees D000-DFFF ROM characters there.
Option 1: easiest, video $0400, chars $2000-$2FFF |
Option 2: least BASIC free, video $8C00, chars $A000-$AFFF |
Option 3: largest free, video $CC00, chars $F000-$FFFF |
Option 4: single charset, video $C400, chars $C800-$CFFF |
Tuesday, April 30, 2024
Raster Interrupts for C64
Wednesday, February 7, 2024
Calculator for Commodore 64 and other CBM BASIC models
Introduction
Wow! A new desktop calculator for Commodore. Programmed all by myself in BASIC. Wow, so impressed! Or not. Doesn't even have decimals.
No, it's not the best thing since sliced bread, but it was fun. And it's just a start -- there's a bigger goal I'll get to in a while...
This was a puzzle programming exercise I challenged myself with. How to make the calculator, especially with the operator precedence feature.
Link: LOAD"CALC64",8
Implementation
Let's go through how it was implemented.
User Interface
First was the design of the user interface, by creating PRINT statements. Used reverse text to make a rectangular box with the keys displayed.
How to click on a key? I'm so used to a mouse or touch interface. Oops, Commodore doesn't have that usually, or not so easy. Ignoring the 1351 mouse for now. Most Commodore users are used to using the keyboard or joystick. Forget the joystick, this is not a game! Keyboard entry one key at a time will do just fine. Note that ENTER also acts as =, and DEL is equivalent to ←, and X is a synonym for *.
Entry of digits was the first processing, accepting up to the limit of the display. This stored as a string (V$) with keyed entries appended.
I started with 7 digits, but outgrew that in testing and increased to 9 digits.
At first, only positive numbers were supported, then fixed it to support negative numbers, with the negative sign taking up a position in the display. The N key toggles a number entry between positive and negative and back again.
Entries allowed by this calculator are interleaved numbers and binary (two argument) operators. Note that immediate operators like C and N usually take effect immediately, whereas binary operators require multiple arguments and a finalization (another binary operator or =).
There are exceptions allowed in entries to overwrite the prior value or the prior operator. Examples:
- 1+1=3 keyed entries will replace the 2 with a 3
- 2+x3 will replace the addition operator with multiplication operator
Precedence needs a Stack
One design requirement I set for myself was to include operator precedence. This means that multiplication and division have the same higher precedence over addition and subtraction at the same lower precedence. Usually math is evaluated left to right, but due to precedence issues, other operators may need to be done first. In other words the expression 1+2x3 is equivalent to 1 + (2x3) and then 1 + 6 and finally evaluates to 7. But 1 x 2 + 3 is equivalent to (1x2) + 3, then 2 + 3, and finally 5.
I simply put numbers and operators interchangeably on a stack in order of entry until enough information is present to start evaluating.
Rule 1 - if user presses =, then evaluate
Rule 2 - if first operator is multiplication or division, once the second number is finalized with a second operator, simply evaluate the first expressionRule 3 - if first operator is addition or subtraction, defer until the second operator and third number is finalized (third operator present!), then figure out what to do - either evaluate first or second expression, reducing the work
Subroutines
Error conditions
Limitations
Extras
Next
Saturday, December 9, 2023
Commodore keyboards go wireless for my portable emulators
The c-simple-emu6502-cbm project supports a number of ESP32 platforms to provide a subset of Commodore C64 (and Vic-20, C128) emulation, and many currently include BLE keyboard support. Originally for CardKB only, now I have added BLE support for Commodore keyboards (20 to 25 pins) to the m5, T-Display-S3, and ESP32-8048S070-7inch ports/branches into the encapsulated BLE_commodore_keyboard_server Arduino sketch.
![]() |
BLE options: (a) Commodore keyboard (b) CardKB |
No expense spared for these awesome graphics, seems retro eh?
![]() |
M5Stick-C with CardKB BLE connected to T-Display-S3 |
Actually we already had BLE CardKB support, and the protocol for the hard wired keyboard is exactly the same as sent over BLE (string of active C64 and C128 scan codes), it was just a little bit of further coding to make the choice between CardKB and hardwired keyboard. In fact, that code was already present for CardKB or hardwired keyboard in the M5 branch itself. The tiny bit of extra work was to duplicate that in the BLE keyboard server project. And voila! More options all the way around.
![]() |
Wired keyboards (a) Commodore (b) CardKB (c) Chrome Browser |
While wireless does have its convenience, it does require careful timing to pair correctly. Typically if both the BLE client and server are powered or reset at the same moment, they should pair. A few or more keystrokes may be necessary to confirm pairing is complete. If it doesn't work, just reset and try again.
Happy C64 computing over BLE!
Tuesday, December 5, 2023
7" LCD (ESP32) with C64 Text Emulator
![]() |
7" is giant compared to this much smaller screen |
Monday, December 4, 2023
New! and Improved! C64 text emulator
There has been a steady stream of improvements to my wearable C64/C128 text emulators and related projects since the Summer 2023 debut at VCF West 2023 in Mountain View. My Twitter/X account includes posts of many of these advancements.
- used a 6502 test suite to find problems in my emulation
- Vic-20 emulator
- Vic-20 upscaled resolution
- A few more hardware targets supported, including much smaller sizes
- M5Fire 320x200
- M5Atom S3 128x128
- M5Stick-C 160x80
- LilyGo T-Display-S3 320x170
- Downscaling resolution as necessary
- Tilt and pan for 1:1 resolution on tiny screen sizes
- FATFS partition for files when no SD present, and when PSRAM not present
- M5Stack CardKb support
- wireless keyboard (BLE server/client)
Vic-20
M5Atom S3
M5Stick-C
LilyGo T-Display-S3
CardKB
Wireless BLE Keyboard
Friday, June 30, 2023
Extremely small emulated C64 and C128
This "portable" Commodore 64 and 128 emulator (m5 source code branch) is my work in progress, one in a series of minimalist emulators ported to different hardware targets. Only text (on LCD) with background, foreground, border colors, keyboard entry via USB serial tethered web browser, and general 6502/6510 and C64 memory management emulation is present (no, won't play games, make sound, or do bitmapped graphics) with some D64 emulation [added 7/2/2023].
(Update 7/28/2023) Now with GO 128 command.
![]() |
GO 128 command |
Even my son asked, "Why do you need to do that?" Well, he has a point. I wanted a C64 that fit in my pocket or even on my wrist. And targeting new hardware platforms with my emulator is part of my hobby.
How does it work? Check out my highly technical drawing.
Now I already here you asking why I didn't connect Bluetooth to the M5Core, because certainly it has Bluetooth as well, and why didn't I use a USB keyboard connected to CoreS3, because it includes USB Host. But I've had trouble tracking down examples of HID Host examples for M5; client examples are prevalent, but host?
Pictured here is a phone is running Chrome with a custom copy of the html/javascript keyboard adapter including web-serial-polyfill because mobile Chrome doesn't directly include Serial API support. A Palm Pilot foldable keyboard has a Bluetooth adapter, paired with the phone. HID keystrokes are captured by the web page, converted to C64 key scan codes, and a list of the active key scan codes (or 64 when keys released) is sent over USB Serial to the M5Core device which is running the C64 ROMs which are tricked into thinking a real keyboard is attached; keystrokes are processed by the C64 KERNAL IRQ as normal.
The M5Core is being powered by the phone. Why M5Core? Because it's a polished packaged solution.
Yeah, we could just run a Commodore 64 emulator on the phone, but this way, I could have complete control over the keyboard emulation, what keys are present, how CTRL and Commodore keys work, etc. And it's just because I can, not because I should.
Why the Palm Keyboard? Because it folds in my pocket! And because I had one from back in the day. Any keyboard you can attach to a phone or computer should work. And this Bluetooth adapter just makes it so cool, and easier than a tethered keyboard.
The next step is to merge this solution with my Commodore 128 keyboard adapter to completely reject the portability feature. That would look really cool hooked up to my phone! Update (7/31/2023): check out YouTube for connection from ItsyBitsy/keyboard to Core Port.A.
![]() | ||
C128 Keyboard Adapter Breadboarded Prototype
|
I am excited about my nonsense crazy adventures. Even if only I enjoy them.
=====
Update (7/2/2023): D64 support is currently working with Core2 only (Basic Core doesn't usually have the additional SPI RAM, but not yet sure why CoreS3 is failing to attach SD).
Update (7/3/2023): Got CoreS3 working with SD switching header to M5Unified.h for that target (was M5Cores3.h) and adding special definition, override logic for SD_CS to use GPIO_NUM_4 instead of default. See updates to M5Core.h.
Update (7/28/2023): Commodore 128D extended keyboard working with UART connection to Port.A of Core, and Commodore 128 emulation is ported as well.
=====