Skip to content

πŸ“Š Fully annotated disassembly of VisiCalc (1979) for Apple II β€” line-by-line 6502 assembly documentation

License

Notifications You must be signed in to change notification settings

hwatkins/visicalc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

VisiCalc β€” Buildable Apple II Disassembly

A complete 6502 disassembly of VisiCalc (VC-208B0-AP2) for the Apple II, with build systems for both Merlin32 and ca65 assemblers.

The original disassembly was produced by Brutal Deluxe Software using The Flaming Bird Disassembler. This project reorganizes it into a buildable form and provides tooling to assemble, link, and create a bootable Apple II disk image.

Prerequisites

Install the cc65 cross-development suite (includes ca65 and ld65):

brew install cc65

Optional tools:

  • Merlin32 β€” brew install merlin32 (for the Merlin build path)
  • a2kit β€” cargo install a2kit (for creating .dsk disk images)
  • An Apple II emulator such as AppleWin or [Virtual ]

Or install everything at once:

make deps

Building

Build with the ca65/ld65 toolchain (recommended):

make ca65

This assembles ca65/vc.s and produces three binaries:

File Load address Description
ca65/visicalc.bin $0800 Main program
ca65/loader.bin $0200 Secondary loader routines
ca65/zpinit.bin $0000 Zero-page initialization data

Build with Merlin32 (if installed):

make merlin

Creating a Disk Image

make disk

This creates visicalc.dsk, a DOS 3.3 disk image with the assembled binary. Load it in an Apple II emulator and run:

BRUN VC

Verifying Builds

If both assemblers are installed, verify they produce identical main binaries:

make verify

Regenerating the ca65 Source

The ca65 source is mechanically converted from the Merlin source. To regenerate it after editing merlin/vc.s:

make convert

The conversion script (scripts/merlin2ca65.py) handles:

  • Comment syntax (* β†’ ;)
  • Directives (EQU β†’ =, DB β†’ .byte, DS β†’ .res, etc.)
  • Label colons (Merlin labels have no colon; ca65 requires :)
  • DCI strings β†’ .byte sequences with high-bit toggling
  • Force-absolute addressing (| β†’ a:)
  • Address gap detection and .res padding
  • Auto-generation of equates for undefined labels

Project Structure

visicalc/
β”œβ”€β”€ merlin/
β”‚   β”œβ”€β”€ vc.s              # Original Merlin syntax source
β”‚   └── Makefile
β”œβ”€β”€ ca65/
β”‚   β”œβ”€β”€ vc.s              # ca65 syntax source (generated)
β”‚   β”œβ”€β”€ visicalc.cfg      # ld65 linker configuration
β”‚   └── Makefile
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ merlin2ca65.py    # Merlin β†’ ca65 conversion script
β”‚   └── fix_data_regions.py # Correct data-as-code in da65 output
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ VisiSource.pdf    # Brutal Deluxe disassembly notes
β”‚   └── 10911-2212_VisiCalc_Apple_II_Jan82.pdf  # VisiCalc User's Guide
β”œβ”€β”€ Makefile              # Top-level build
β”œβ”€β”€ README.md
└── .gitignore

Source Notes

The disassembly covers three memory regions:

  • $0800–$6FFF β€” Main VisiCalc program (26,624 bytes)
  • $0200–$0400 β€” Secondary routines (513 bytes)
  • $0000–$00FF β€” Zero-page variables (256 bytes)

Recovered Regions

Two address ranges within the main segment ($2356–$2E97 and $49D3–$57B3) were not decoded by the original Flaming Bird Disassembler. These have been recovered by disassembling the original binary with da65, revealing 62 entry points including core routines like string output (L2905), character output (L28ED), and cell navigation.

Deviations from the Original Disassembly

This project is based on the Brutal Deluxe disassembly but uses a slightly later version of VisiCalc than the one Brutal Deluxe worked from. The differences are minimal β€” the binary layout and code structure are the same, with only minor byte-level variations in a few routines.

In addition to recovering the two undecoded regions above, the da65 disassembler initially misidentified several data areas as 6502 instructions. These have been corrected by scripts/fix_data_regions.py, which replaces ~600 lines of nonsensical instructions with proper data directives:

  • String table ($50D2–$53D4) β€” ~45 UI prompt strings (command menus, replicate prompts, error messages) restored as ASC/DB directives
  • Lookup tables ($505D–$50D1) β€” three indexed tables restored as HEX
  • Function name table ($53D5–$5400) β€” DCI-encoded built-in function names (SUM, SIN, COS, etc.) restored as ASC/DB
  • Data tables ($2756–$2848) β€” dispatch/lookup table restored as HEX
  • Inline data after JSR L2336 and JSR L63B9 β€” floating-point constants and encoded command streams restored as DB directives

All corrections produce byte-identical binaries β€” only the source representation changed.

Historical Significance

VisiCalc (1979) was the first spreadsheet program for personal computers and is widely considered the Apple II's "killer app." It legitimized personal computers as serious business tools and created the entire spreadsheet software category.

About

πŸ“Š Fully annotated disassembly of VisiCalc (1979) for Apple II β€” line-by-line 6502 assembly documentation

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors