A Neovim plugin for C64 Assembler development using Kick Assembler, featuring LSP support, VICE emulator integration, and helpful development tools. Made with Love for the Retro Computing Community.
-
LSP Integration: Full Language Server Protocol support via a Kick Assembler Language Server i created alongside this project kickass_ls
- Semantic token highlighting
- Real-time diagnostics
- Code completion
- Symbol navigation
- Advanced C64-specific analysis (zero-page optimization, hardware bug detection, etc.)
-
Build Integration: Direct Kick Assembler compilation from Neovim
- Automatic error parsing
- Quickfix list integration
- Success/error notifications
-
VICE Emulator Integration: Launch and test your programs instantly
- One-keypress execution
- Automatic PRG file detection
- Debug mode with VICE monitor and symbol file support
- Remote monitor integration for advanced debugging
-
Telescope Integration: Quick access to C64-specific references
- C64 Reference Manual Search - Search and browse the complete C64 Programmer's Reference Guide directly in Neovim
- Memory map browser
- Register and constant lookup
- Neovim quickfix list integration with Telescope for assembly errors
-
Diagnostic Display Modes: Flexible diagnostic visualization
- Virtual text mode (inline diagnostics)
- Virtual lines mode (separate lines for diagnostics)
- Signs only mode (minimal clutter)
- Easy toggle between modes
-
C64 Ultimate Integration: Direct hardware deployment (NEW!)
- Upload and run programs on real C64 Ultimate hardware
- One-command workflow: assemble → upload → run
- Drive management (mount/unmount disk images)
- Machine control (reset, memory operations)
- Works with both Ultimate64 and Ultimate-II+ hardware
-
Customizable: Extensive configuration options for LSP, highlighting, and keybindings
Code completion with intelligent suggestions, inline documentation, and syntax highlighting powered by the Kick Assembler Language Server i created: kickass_ls.
Real-time diagnostics with custom icons showing errors, warnings, and hints. Features include branch distance validation, dead code detection, and C64-specific hardware analysis. All powered by the Kick Assembler Language Server i created: kickass_ls.
Browse all diagnostics with Telescope (<leader>dd for current buffer, <leader>dw for workspace). Jump directly to any issue with preview. Diagnostics created by the Kick Assembler Language Server i created: kickass_ls.
Quick symbol navigation with <leader>ts. Browse all constants, variables, functions, and labels in your document with live preview.
Search the C64 Programmer's Reference Manual with <leader>cr. Find information about SID, VIC, memory maps, and more.
Selected chapters open in a vertical split with full Markdown rendering for easy reading alongside your code.
Note: The C64 Reference integration is currently work in progress and may be subject to changes.
When assembly fails, errors are automatically parsed and loaded into Telescope's quickfix list. Jump directly to any error with preview.
Debug your programs with the VICE remote monitor in a floating terminal. Supports symbol files, breakpoints, memory inspection, and all VICE monitor commands.
Before installing c64.nvim, ensure you have the following:
- Neovim 0.11+ - Required for native LSP features
- Java Runtime - Required to run Kick Assembler
- Kick Assembler (kickass.jar) - Download here
- VICE Emulator - Download here
- The
x64binary must be in your PATH
- The
- kickass_ls Language Server - Available here
- The
kickass_lsbinary must be in your PATH
- The
- telescope.nvim (optional) - For enhanced UI features
-
nvim-cmp - If installed, c64.nvim will automatically integrate with it for enhanced completion
- When not installed, c64.nvim uses Neovim's native completion system
- No additional configuration needed - auto-detection handles everything
-
c64u CLI - For C64 Ultimate hardware integration (See tools/c64u)
- Enables direct upload to C64 Ultimate hardware
- Drive management and machine control from Neovim
- See Installing c64u CLI below for installation options
Using lazy.nvim
Add this to your lazy.nvim plugin configuration (usually in ~/.config/nvim/lua/plugins/ or in your init.lua):
return {
"cybersorcerer/c64.nvim",
dependencies = {
"nvim-telescope/telescope.nvim", -- Optional, for enhanced UI
"hrsh7th/nvim-cmp", -- Optional, for enhanced completion (auto-detected)
},
ft = { "kickass" }, -- Lazy load only for Kick Assembler files
config = function()
require("c64").setup({
-- Path to your kickass.jar file
kickass_jar_path = vim.fn.expand("~/tools/kickass.jar"),
-- Optional: customize paths if binaries are not in PATH
-- vice_binary = "x64",
-- kickass_ls_binary = "kickass_ls",
})
end,
}The c64u CLI tool enables direct interaction with C64 Ultimate hardware from Neovim. You can install it either by downloading pre-built binaries or by building from source.
Download the appropriate binary for your platform from the GitHub Releases page:
macOS:
# For Apple Silicon (M1/M2/M3)
curl -L -o c64u https://github.com/cybersorcerer/c64.nvim/releases/latest/download/c64u-darwin-arm64
chmod +x c64u
sudo mv c64u /usr/local/bin/
# For Intel Macs
curl -L -o c64u https://github.com/cybersorcerer/c64.nvim/releases/latest/download/c64u-darwin-amd64
chmod +x c64u
sudo mv c64u /usr/local/bin/Linux:
# For x86_64
curl -L -o c64u https://github.com/cybersorcerer/c64.nvim/releases/latest/download/c64u-linux-amd64
chmod +x c64u
sudo mv c64u /usr/local/bin/
# For ARM64 (e.g., Raspberry Pi)
curl -L -o c64u https://github.com/cybersorcerer/c64.nvim/releases/latest/download/c64u-linux-arm64
chmod +x c64u
sudo mv c64u /usr/local/bin/Windows:
# Download from: https://github.com/cybersorcerer/c64.nvim/releases/latest/download/c64u-windows-amd64.exe
# Rename to c64u.exe and add to your PATHRequirements:
- Go 1.22 or later
cd tools/c64u
make installThis will build and install c64u to ~/.local/bin/ (make sure it's in your PATH).
c64u versionCreate a configuration file at ~/.config/c64u/config.toml:
# C64 Ultimate hostname or IP address
host = "c64u.local" # or use IP like "192.168.1.100"
# HTTP port (default: 80)
port = 80Alternatively, use environment variables:
export C64U_HOST="c64u.local"
export C64U_PORT=80Or specify on the command line:
c64u --host c64u.local --port 80 aboutOnce c64u is installed and configured, enable it in your c64.nvim configuration:
require("c64").setup({
-- ... other config ...
c64u = {
enabled = true, -- Enable C64 Ultimate integration
host = nil, -- Use c64u CLI config (recommended)
port = nil, -- Use c64u CLI config (recommended)
},
})Now you can use the C64 Ultimate keymaps (<leader>ku*) to upload, run, and manage your programs on real hardware!
require("c64").setup({
-- Path to kickass.jar
kickass_jar_path = vim.fn.expand("~/tools/kickass.jar"),
-- VICE emulator binary name (must be in PATH)
vice_binary = "x64",
-- Language server binary name (must be in PATH)
kickass_ls_binary = "kickass_ls",
-- LSP configuration
lsp = {
-- Completion mode: 'auto' (default), 'native', 'external', 'none'
-- 'auto': Auto-detects nvim-cmp and uses it if available, otherwise native completion
-- 'native': Forces Neovim native completion (vim.lsp.completion)
-- 'external': Uses external completion plugin (e.g., nvim-cmp) only
-- 'none': Disables completion
completion = 'auto',
settings = {
kickass_ls = {
warnUnusedLabels = false,
zeroPageOptimization = {
enabled = true,
showHints = true,
},
branchDistanceValidation = {
enabled = true,
showWarnings = true,
},
illegalOpcodeDetection = {
enabled = true,
showWarnings = true,
},
hardwareBugDetection = {
enabled = true,
showWarnings = true,
jmpIndirectBug = true,
},
memoryLayoutAnalysis = {
enabled = true,
showIOAccess = true,
showStackWarnings = true,
showROMWriteWarnings = true,
},
magicNumberDetection = {
enabled = true,
showHints = true,
c64Addresses = true,
},
deadCodeDetection = {
enabled = true,
showWarnings = true,
},
styleGuideEnforcement = {
enabled = true,
showHints = true,
upperCaseConstants = true,
descriptiveLabels = true,
},
},
},
},
-- Customize syntax highlighting
highlight = {
['@lsp.type.mnemonic.kickass'] = { link = 'Function' },
['@lsp.type.directive.kickass'] = { link = 'Keyword' },
['@lsp.type.preprocessor.kickass'] = { link = 'PreProc' },
['@lsp.type.macro.kickass'] = { link = 'Macro' },
['@lsp.type.pseudocommand.kickass'] = { link = 'Special' },
['@lsp.type.function.kickass'] = { link = 'Function' },
['@lsp.type.label.kickass'] = { link = 'Label' },
['@lsp.type.number.kickass'] = { fg = '#ff9800' },
['@lsp.type.variable.kickass'] = { link = 'Identifier' },
},
-- Customize keybindings
keymaps = {
assemble = "<leader>ka",
run_vice = "<leader>kr",
debug_vice = "<leader>kd",
show_diagnostics = "<leader>d",
},
-- C64 Ultimate integration (optional)
c64u = {
enabled = true, -- Enable C64 Ultimate integration
host = "c64u.homelab.local", -- C64U hostname/IP (nil = use c64u CLI config)
port = 80, -- HTTP port (nil = use c64u CLI config)
},
})c64.nvim sets omnifunc for LSP completion and works seamlessly with:
- nvim-cmp (recommended) - automatic integration
- Manual completion - trigger with
<C-x><C-o>
If you have a global LspAttach autocmd that enables native completion for all LSP clients, you may see duplicate completion menus (one from native completion, one from nvim-cmp).
Solution: Skip kickass_ls in your global completion setup:
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(ev)
local client = vim.lsp.get_client_by_id(ev.data.client_id)
-- Skip native completion for kickass_ls (uses nvim-cmp)
if client and client.name == "kickass_ls" then
return
end
-- Enable native completion for other LSP clients
if client:supports_method("textDocument/completion") then
vim.lsp.completion.enable(true, client.id, ev.buf, { autotrigger = true })
end
end,
})c64.nvim uses native Neovim LSP (vim.lsp.start) and integrates seamlessly with your existing setup:
What c64.nvim configures:
- LSP server registration and activation
- Diagnostic signs and virtual text styling
- Semantic token highlighting for Kick Assembler
- Completion (based on
completionmode)
What c64.nvim does NOT configure:
- LSP keybindings (uses your global
LspAttachautocmd) - General diagnostic behavior (only adds c64-specific enhancements)
This design ensures c64.nvim works harmoniously with your existing Neovim configuration without requiring nvim-lspconfig.
| Key | Action | Description |
|---|---|---|
<leader>ka |
Assemble | Compile current file with Kick Assembler |
<leader>kr |
Run | Launch current program in VICE emulator |
<leader>kd |
Debug | Launch VICE with monitor and symbol file |
| Key | Action | Description |
|---|---|---|
<leader>d |
Show Diagnostics | Show line diagnostics in floating window |
<leader>dv |
Virtual Text Mode | Enable inline diagnostic text |
<leader>dl |
Virtual Lines Mode | Enable diagnostic lines (requires lsp_lines.nvim) |
<leader>ds |
Signs Only Mode | Show only diagnostic icons in sign column |
<leader>dt |
Toggle Mode | Cycle through diagnostic display modes |
| Key | Action | Description |
|---|---|---|
<leader>cr |
C64 Reference | Search C64 Programmer's Reference Manual |
<leader>cm |
Memory Map | Browse C64 memory map |
<leader>cR |
Registers | Browse C64 registers and constants |
<leader>dd |
Buffer Diagnostics | Show diagnostics for current buffer only (requires Telescope) |
<leader>dw |
Workspace Diagnostics | Show diagnostics for all buffers (requires Telescope) |
<leader>cs |
Telescope Symbols | Show document symbols (requires Telescope) |
| Key | Action | Description |
|---|---|---|
<leader>kuR |
Assemble & Upload | Assemble and upload to C64 Ultimate, then run |
<leader>kuu |
Upload PRG | Telescope picker to select and upload PRG file |
<leader>kud |
File Browser | FTP file browser for C64 Ultimate filesystem |
<leader>kux |
Machine Control | Telescope picker for machine operations (reset/reboot/pause/resume/poweroff) |
<leader>kuv |
Version | Show C64 Ultimate API version |
<leader>kuc |
Create Disk Image | Create disk image (d64/d71/d81/dnp) |
<leader>kum |
Create Directory | Create directory on C64U partition |
FTP File Browser (<leader>kud):
Prerequisites: Requires an FTP client (ftp or ftp.exe) in your PATH.
Navigation:
Enteron directory - Navigate into directoryEnteron file - Show file information..entry - Navigate to parent directory
Operations:
Ctrl+c- Create disk image (d64/d71/d81/dnp) in current directoryCtrl+d- Create new directory via FTPCtrl+m- Mount selected disk image (drive name extracted from path)Ctrl+u- Unmount disk image from drive
Machine Control (<leader>kux):
Enter- Execute selected command (picker stays open for multiple operations)- Available operations: Reset, Reboot, Pause, Resume, Power Off (U64 only)
Esc- Close the pickerCtrl-c- Close the picker (alternative)
These are automatically set when editing Kick Assembler files:
| Key | Action | Description |
|---|---|---|
gD |
Go to Declaration | Jump to symbol declaration |
gd |
Go to Definition | Jump to symbol definition |
K |
Hover | Show documentation |
gi |
Go to Implementation | Jump to implementation |
<C-k> |
Signature Help | Show function signature |
gr |
References | Show all references |
<space>rn |
Rename | Rename symbol |
<space>ca |
Code Action | Show code actions |
<space>f |
Format | Format document |
The plugin provides the following user commands:
| Command | Description |
|---|---|
:C64Assemble |
Assemble the current file with Kick Assembler |
:C64Run |
Run the current program in VICE emulator |
:C64Debug |
Run the program in VICE with debug mode enabled |
:C64Enable |
Manually enable c64.nvim for current buffer |
:C64CreateMarker |
Create .kickass marker file in current directory |
c64.nvim provides powerful Telescope integrations for enhanced development workflow:
Press <leader>cr to search the complete C64 Programmer's Reference Guide:
- Fuzzy search through all sections (searches both titles and content)
- Live preview of sections as you navigate
- Vertical split display - see reference alongside your code
- Markdown rendering with syntax highlighting
- No need to leave Neovim or open PDFs!
Usage:
:Telescope c64 reference
# or use the keymap:
<leader>crType to search (e.g., "sprite", "vic", "sid"), navigate with j/k, press Enter to open in a split.
Browse C64 memory locations and hardware registers:
:Telescope c64 memory_map # or <leader>cm
:Telescope c64 registers # or <leader>cRSelect an entry to insert it at your cursor position.
The plugin uses intelligent multi-level detection to identify Kick Assembler files and avoid conflicts with other assemblers (NASM, MASM, etc.).
Files with extensions *.asm, *.s, or *.inc are automatically analyzed using this strategy:
- Detects Kick Assembler-specific syntax like
.import,.macro,.namespace,.var, etc. - If found, filetype is set to
kickass
- Searches for
.kickass,kickass.cfg, or.kickassemblerfile in the project directory tree - If found, all
.asmfiles in that project are treated as Kick Assembler files
- Detects C64-specific memory addresses and Kernal routines (e.g.,
$D000,CHROUT) - Requires at least 2 C64-specific references to trigger
If automatic detection doesn't work, you can manually enable c64.nvim:
:C64EnableThis command sets the current buffer's filetype to kickass and activates all plugin features.
To ensure all .asm files in your project are recognized as Kick Assembler files, create a marker file:
:C64CreateMarkerThis creates a .kickass file in your current working directory. All .asm files in this directory (and subdirectories) will automatically be detected as Kick Assembler files.
You can also manually create this file:
touch .kickassOr create a kickass.cfg with your Kick Assembler configuration.
c64.nvim offers flexible diagnostic visualization with three display modes:
Diagnostics appear inline next to your code:
10: lda #$00 ● Error: Invalid syntaxDiagnostics appear in separate lines below the code (requires lsp_lines.nvim):
10: lda #$00
┗━ Error: Invalid syntaxOnly icons appear in the sign column, minimal distraction:
10: lda #$00Use <leader>d to see full diagnostics in a floating window.
- Error: (red alert circle)
- Warning: (yellow alert)
- Hint: (blue lightbulb)
- Info: (cyan information)
- Open a Kick Assembler file:
nvim myprogram.asm - Write your code with LSP assistance (completions, diagnostics, etc.)
- Need help? Press
<leader>crto search the C64 Reference Manual - Assemble: Press
<leader>kato compile - Errors? Telescope opens with clickable error list
- Fix errors and reassemble
- Test: Press
<leader>krto launch VICE and test your program - Debug: Press
<leader>kdto launch VICE with monitor and symbols loaded
When you press <leader>kd, the plugin:
- Starts VICE with the
-remotemonitorflag (enables remote monitor on port 6510) - Automatically loads your
.symsymbol file with-moncommands - Shows a notification with monitor activation instructions
In VICE:
- Press
Alt+Hto activate the monitor - Use your labels directly in monitor commands (e.g.,
break Main,d loop) - Monitor commands:
break,watch,d(disassemble),m(memory),r(registers),z(continue)
Example debug session:
(monitor) break Main # Set breakpoint at Main label
(monitor) z # Continue execution
(monitor) r # Show registers
(monitor) d Main Main+20 # Disassemble from Main to Main+$20
(monitor) m $0400 $04ff # Show screen memory
- Press
<leader>crto open the reference search - Type to search (e.g., "sprite" or "vic")
- See live preview in Telescope
- Press
Enterto open in vertical split - Reference stays open while you code
- Press
qto close the reference
- Ensure
kickass_lsis in your PATH:which kickass_ls - Check Neovim's LSP logs:
:LspLog
- Verify your
kickass_jar_pathis correct - Ensure Java is installed:
java -version - Check the error in the Neovim quickfix list:
:copen
- Ensure
x64is in your PATH:which x64 - Make sure you assembled the file first (
<leader>ka) - Check that a
.prgfile was created
Contributions are welcome! Please feel free to submit issues or pull requests.
Apache 2.0
- Built for Kick Assembler by Mads Nielsen
- Integrates with VICE Emulator
- Uses kickass_ls Language Server
- Uses Documentation from the great Retro Community
- The Commodore Reference Guide by [PS(hv)] which you can find here
- Data from The Commodore 64 Memory Map







