Migrating from CA65 to 64tass: Tips and Compatibility Notes

Getting Started with 64tass — Installation, Syntax, and Examples64tass is a modern, actively maintained assembler for the 6502 family of processors (including variants used in the Commodore 64, NES, Atari 8-bit, and others). It aims to be a clean, flexible, and portable replacement for older assemblers, offering modern features like a robust macro system, conditional assembly, multiple output formats, and improved error messages. This guide walks you through installing 64tass, using its core syntax, and building small example projects so you can start writing and assembling 6502 code confidently.


What 64tass offers (brief)

  • Cross-platform command-line tool compatible with Windows, macOS, and Linux.
  • Macro and include facilities for modular, reusable code.
  • Multiple output formats (PRG, BIN, HEX, and more) and symbol listing.
  • Support for many 6502 variants and addressing modes.
  • Improved diagnostics versus older assemblers.

Installation

Prebuilt binaries

  1. Visit the 64tass releases page or the project’s download area to fetch the latest prebuilt binary for your OS.
  2. On Windows, download the .zip, extract the executable (64tass.exe) and optionally add its folder to your PATH.
  3. On macOS and Linux, download the appropriate tarball or binary, make it executable (chmod +x 64tass), and place it in a directory on your PATH (for example /usr/local/bin).

Homebrew (macOS)

If you use Homebrew on macOS:

brew install 64tass 

Linux package managers

Some distributions may include 64tass in their repositories. For Debian/Ubuntu:

sudo apt-get install 64tass 

If a package isn’t available, use the prebuilt binary or compile from source.

Building from source

  1. Clone the repository:
    
    git clone https://github.com/poopy/64tass.git 
  2. Follow the repository’s build instructions—typically using a makefile or a simple build script. You may need a C++ compiler and standard build tools.

Basic usage

The 64tass executable is invoked from a shell. The simplest call assembles a source file into an output file:

64tass -o output.prg source.asm 

Common options:

  • -o FILE Set output filename.
  • -l FILE Write symbol/listing file.
  • -b Produce raw binary output.
  • -f FORMAT Set output format (e.g., cbm for Commodore PRG).
  • -v Verbose messages.
  • –help Show usage.

Example for Commodore 64 PRG:

64tass -f cbm -o hello.prg hello.asm 

Source file basics and syntax

64tass aims for readable assembly code. Key features and directives:

  • Labels: define with a trailing colon (optional) or bare identifier.
    
    start:   LDX #$00 
  • Comments: use semicolon (;) or // for end-of-line comments.
    
    LDA #$01  ; load immediate value 
  • Directives: start with a dot (.) for many directives, but 64tass supports various traditional forms.
    • .org ADDRESS — set origin.
    • .byte / .word — emit data.
    • .include “file.asm” — include another source file.
    • .define / .undef — macros or constants (alternative forms exist).
    • .equ — set an assembly-time constant.
    • .res / .space — reserve bytes.
    • .segment — manage named segments.

Example header:

        .org $1000 start:  SEI         CLD         LDX #$00 

Number and constant formats

  • Hex: $FF or 0xFF
  • Binary: %10101010
  • Decimal: 255
  • Character constants: ‘A’
  • Expressions: allowed with +, -, *, /, &, |, ^, <<, >> and parentheses.

Example:

val = $200 + 16 .byte val & $FF, val >> 8 

Addressing modes and instruction examples

64tass supports the full set of 6502 addressing modes. Examples:

  • Immediate:
    
    LDA #$10 
  • Zero page:
    
    STA $20 
  • Absolute:
    
    JMP $C000 
  • Indirect:
    
    JMP ($0300) 
  • Indexed:
    
    LDX $2000,Y 

Conditional branches and stack operations are identical to classic 6502 syntax (BEQ, BNE, PHA, PLA, RTS, etc.).


Macros and conditional assembly

Macros allow parameterized code reuse. Example:

.macro push16 reg     PHA     TXA     PHA .endmacro start:     .push16 A 

(Exact macro syntax may vary; check the assembler help—64tass supports powerful macro features including local labels and repetitions.)

Conditional assembly:

.equ USE_FEATURE = 1 .if USE_FEATURE     ; assembled only when enabled .endif 

Segments and banked code

For systems like the C64 where different memory regions matter, use segments and .org to manage layout:

.segment "CODE" .org $1000 ; code here .segment "BASIC" .org $8000 ; data or BASIC stub here 

For banked cartridges, 64tass can emit multiple banks and switch segments appropriately.


Examples

1) Minimal C64 PRG — Hello (prints screen characters)

source: hello.asm

        .org $0801       ; C64 BASIC start for autostart PRG         .word start-2         .byte $9e         .ascii "2064"         .byte 0,0 start:  ; basic stub jumps to code at $0810         JSR $0810         .org $0810 main:         LDX #$00 loop:         LDA message,X         BEQ done         JSR $FFD2     ; C64 ROM CHROUT to print char         INX         JMP loop done:         RTS message:         .byte "HELLO, C64!",0 

Assemble:

64tass -f cbm -o hello.prg hello.asm 

2) Simple machine code routine with labels and data

        .org $1000 start:         LDA #<message         STA $D020         LDA #>message         STA $D021         JMP done message:         .byte "HI",0 done:         RTS 

Assemble to binary:

64tass -b -o demo.bin demo.asm 

Debugging and listings

Use the -l option to produce a listing and symbol file:

64tass -l demo.lst -o demo.prg demo.asm 

The listing shows source, addresses, emitted bytes, and symbols — invaluable for tracing code layout and fixing addressing mistakes.


Integration with editors and toolchains

  • Many editors (VS Code, Sublime, Vim) have syntax files or extensions for 6502 assembly; configure tasks to call 64tass for building.
  • Combine 64tass with emulators (VICE for C64) by assembling into a PRG and loading it in the emulator.
  • Use makefiles to automate builds for multi-file projects and different targets.

Tips and best practices

  • Use .org and segments to explicitly place code/data — avoids surprises from implicit addresses.
  • Prefer labels over magic constants to improve readability.
  • Emit small test programs and verify in an emulator before running on real hardware.
  • Keep a separate include for hardware constants (VIC-II, CIA, etc.) to reuse across projects.
  • Use the listing (-l) during development to catch address and assembler-expansion bugs early.

Further resources

  • Official 64tass documentation and manual for in-depth directive and macro syntax.
  • Example repositories and demo collections (search GitHub for 64tass examples).
  • Commodore 64 programming guides for hardware specifics.

64tass is a powerful, flexible assembler that brings modern conveniences to classic 6502 development. With the steps and examples above you should be able to install it, write basic 6502 code, and assemble programs for the C64 and other 6502-based systems.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *