Macross 6502, an assembler for people who hate assembly language

There are many MOS 6502 cross-assemblers available. Here’s a new one. Or actually a very old one. “Macross”, a very powerful 6502 macro assembler, which was used to create Habitat, Maniac Mansion and Zak McKracken, was developed between 1984 and 1987 at Lucasfilm Ltd. and is now Open Source (MIT license):

https://github.com/Museum-of-Art-and-Digital-Entertainment/macross

Some History

Starting in 1984, a team at Lucasfilm Ltd. was developing one of the first online role-playing games, originally called “Microcosm”, which was released as “Habitat” in 1986 and later renamed to “Club Caribe”. The client ran on a Commodore 64, which conntected to the central server through the Quantum Link network.

The client software was developed on a 68K-based Sun workstation running the SunOS variant of Unix using cross-development tools developed by Chip Morningstar (who was also the Habitat lead): The “Macross” assembler and the “Slinky” linker. They were used on every 6502 (Atari 400/800, Commodore 64, and Apple II) game produced at Lucasfilm Games, from 1984 up until those machines ceased to be relevant to the games market*.

In 2014, The Museum of Art and Digital Entertainment got a hold of

  • the source of the original development tools (Macross/Slinky)
  • the source of the C64 client
  • the source of the server (written in PL/I)
  • lots of documentation and development logs

which originated from an archive created in 1987 in the context of the technology transfer to Fujitsu, which bought all Habitat assets.

Since Macross and Slinky were written for Unix, it was easy to get them compiling with modern compilers (K&R syntax notwithstanding) and running on a modern Unix system. At the time of writing, the code in the official repository has been fixed to compile with clang on OS X. Further fixes and cleanups are very welcome.

Compiling Macross

Enter “make” both in the toplevel directory and in the “slinky” directory, then copy “macross” and “slinky” into your path. There are man files in the “doc” directory that you may want to install as well.

Writing Code

The syntax of Macross source files is very different from modern 6502 cross assembler, and more similar to Commodore’s own “A65″ assembler. Here is a small “Hello World” for the C64:

define strout = 0xab1e

hello:
    lda #/text
    ldy #?text
    jmp strout

text:
    byte "HELLO WORLD!", 0

As you can see, hex values have to be specified in C notation (binary is prefixed with “0b”), and the operators to extract the low and high bytes of a 16 bit value are “/” and “?”, respectively.

Compile and link the source file like this:

macross -c -o hello.o hello.m
slinky -e -o hello.bin -n -m hello.sym -l 0xc000 hello.o
dd if=hello.bin bs=1 skip=2 count=2 of=hello.prg
dd if=hello.bin bs=1 skip=6 >> hello.prg

The “dd” lines convert Slinky’s output, which is a “standard a65-style object file” (which has a header of FF FF, followed by the start address, followed by the end address) into a C64 .PRG file that is only prefixed by the start address.

Here is a slightly more complex example:

define bsout = 0xffd2

hello:
    ldx #0
    do {
        lda x[text]
        cmp #'A'
        if (geq) {
            tay
            iny
            tya
        }
        inx
        jsr bsout
    } while (!zero)
    
    rts

text:
    byte "HELLO WORLD!", 0

Macross supports C-style if/else, while and do/while, as well as do/until, where the condition can be one of:

  • zero/equal
  • carry
  • lt/leq/gt/geq
  • slt/sleq/sgt/sgeq
  • positive/plus/negative/minus
  • overflow

…as well as their negated versions.

Also note that the “absolute, x-indexed” addressing mode has a different syntax than commonly used.

Macros

Macross has a very powerfull macro language. Here is an example:

org 0xc000

function makeFirstByte(operand) {
    mif (isImmediateMode(operand)) {
        freturn(/operand)
    } melse {
        freturn(operand)
    }
}

function makeSecondByte(operand) {
    mif (isImmediateMode(operand)) {
        freturn(?operand)
    } melse {
        freturn(operand + 1)
    }
}

macro movew src, dst {
    lda makeFirstByte(src) 
    sta makeFirstByte(dst)
    lda makeSecondByte(src)
    sta makeSecondByte(dst)
}

macro hook_vector index, new, dst {
    ldx #index * 2
    movew x[0x0300], dst
    movew #new, x[0x0300]
}

define VECTOR_INDEX_IRQ = 10

    hook_vector VECTOR_INDEX_IRQ, irq, return + 1
    rts

irq:
    inc 0xd020
return:
    jmp 0xffff

The “hook_vector” line will emit the following assembly code:

    ldx #$14
    lda $0300,x
    sta $C01D
    lda $0301,x
    sta $C01E
    lda #$19
    sta $0300,x
    lda #$C0
    sta $0301,x

(The example is a little contrived, since adding the index could have been done at assembly time, but the example nicely demonstrates that macros can preserve addressing modes.)

The file doc/macros.itr contains many useful macros. they are documented in doc/genmacros.itr.

Full Documentation

The complete documentation of Macross is available in the file doc/writeup_6502.itr in the repository. It is in troff format and can viewed like this:

nroff -ms doc/writeup_6502.itr

Future

Macross is a very different approach to 6502 development, and with the source available, I think it’s a viable project that should be continued.

I will happily accept pull requests for compile fixes (GCC, VS, …), cleanups (C99, converting docs from troff to markdown, …) and features (BIN and PRG output, support for more a modern notation, PETSCII, …).

xhyve – Lightweight Virtualization on OS X Based on bhyve

The Hypervisor.framework user mode virtualization API introduced in Mac OS X 10.10 (Yosemite) cannot only be used for toy projects like the hvdos DOS Emulator, but is full-featured enough to support a full virtualization solution that can for example run Linux.

xhyve is a lightweight virtualization solution for OS X that is capable of running Linux. It is a port of FreeBSD’s bhyve, a KVM+QEMU alternative written by Peter Grehan and Neel Natu.

  • super lightweight, only 230 KB in size
  • completely standalone, no dependencies
  • the only BSD-licensed virtualizer on OS X
  • does not require a kernel extension (bhyve’s kernel code was ported to user mode code calling into Hypervisor.framework)
  • multi-CPU support
  • networking support
  • can run off-the-shelf Linux distributions (and could be extended to run other operating systems)

xhyve may make a good solution for running Docker on your Mac, for instance.

Running Tiny Core Linux on xhyve

The xhyve repository already contains a small Linux system for testing, so you can try out xhyve by just typing these few lines:

$ git clone https://github.com/mist64/xhyve
$ cd xhyve
$ make
$ ./xhyverun.sh

And you will see Tiny Core Linux booting in your terminal window:

Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Initializing cgroup subsys cpuacct
Linux version 3.16.6-tinycore64 (tc@box) (gcc version 4.9.1 (GCC) ) #777 SMP Thu Oct 16 10:21:00 UTC 2014
Command line: earlyprintk=serial console=ttyS0 acpi=off
e820: BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
BIOS-e820: [mem 0x0000000000100000-0x000000003fffffff] usable
NX (Execute Disable) protection: active
SMBIOS 2.6 present.
AGP: No AGP bridge found
e820: last_pfn = 0x40000 max_arch_pfn = 0x400000000
x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106
CPU MTRRs all blank - virtualized system.

[...]

 (?- 
 //\   Core is distributed with ABSOLUTELY NO WARRANTY.
 v_/_           www.tinycorelinux.com

tc@box:~$

To shut down the VM and exit to the Mac’s command line, enter:

$ sudo halt

Running Ubuntu on xhyve

You can also install a more complete Linux distribution on xhyve. The tricky bit is that xhyve doesn’t come with a BIOS or EFI booter, so it is necessary to extract the kernel and initrd from the Linux image and pass them to xhyve manually.

First download Ubuntu Server (the desktop version doesn’t support the text mode installer) into the directory “ubuntu” inside the “xhyve” directory:

$ ls -l
total 1218560
-rw-r--r--@ 1 mist  staff  623902720  6 Jun 22:14 ubuntu-14.04.2-server-amd64.iso

We need to extract the kernel and initrd, which is a little tricky, because OS X doesn’t recognize the hybrid file system on the image without a little hack:

$ dd if=/dev/zero bs=2k count=1 of=/tmp/tmp.iso
$ dd if=ubuntu-14.04.2-server-amd64.iso bs=2k skip=1 >> /tmp/tmp.iso
$ hdiutil attach /tmp/tmp.iso
$ cp /Volumes/Ubuntu-Server\ 14/install/vmlinuz .
$ cp /Volumes/Ubuntu-Server\ 14/install/initrd.gz .

Create a virtual hard disk image (8 GB in the example):

$ dd if=/dev/zero of=hdd.img bs=1g count=8

Then create a script to run xhyve with the correct arguments for the installer:

#!/bin/sh

KERNEL="ubuntu/vmlinuz"
INITRD="ubuntu/initrd.gz"
CMDLINE="earlyprintk=serial console=ttyS0 acpi=off"

MEM="-m 1G"
#SMP="-c 2"
NET="-s 2:0,virtio-net"
IMG_CD="-s 3,ahci-cd,ubuntu/ubuntu-14.04.2-server-amd64.iso"
IMG_HDD="-s 4,virtio-blk,ubuntu/hdd.img"
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
LPC_DEV="-l com1,stdio"

build/xhyve $MEM $SMP $PCI_DEV $LPC_DEV $NET $IMG_CD $IMG_HDD -f kexec,$KERNEL,$INITRD,"$CMDLINE"

You will want networking enabled, so it’s easiest to run the script as root (this requirement is lifted if you codesign the binary):

$ sudo ./xhyverun_ubuntu_install.sh

You will see the Ubuntu text mode installer:

  ┌───────────────────────┤ [!!] Select a language ├────────────────────────┐
  │                                                                         │
  │ Choose the language to be used for the installation process. The        │
  │ selected language will also be the default language for the installed   │
  │ system.                                                                 │
  │                                                                         │
  │ Language:                                                               │
  │                                                                         │
  │                               C                                         │
  │                               English                                   │
  │                                                                         │
  │     <Go Back>                                                           │
  │                                                                         │
  └─────────────────────────────────────────────────────────────────────────┘

<Tab> moves; <Space> selects; <Enter> activates buttons

All answers should be straightforward, and the defaults are usually fine. Make sure to select “Yes” when asked “Install the GRUB boot loader to the master boot record”.

At the very end, on the “Installation complete” screen, select “Go back” and “Execute a shell”, so you can copy the installed kernel and initrd to the Mac side. In the VM, type this:

# cd /target
# sbin/ifconfig
# tar c boot | nc -l -p 1234

On the Mac, type this, replacing the IP with the output from ifconfig before:

$ cd ubuntu
$ nc 192.168.64.7 1234 | tar x

In the VM, exit the shell:

# exit

Then select “Finish the installation”.

To run the Ubuntu installation from the virtual hard disk, create the following script, fixing up the kernel and initrd version numbers:

#!/bin/sh

KERNEL="ubuntu/boot/vmlinuz-3.16.0-30-generic"
INITRD="ubuntu/boot/initrd.img-3.16.0-30-generic"
CMDLINE="earlyprintk=serial console=ttyS0 acpi=off root=/dev/vda1 ro"

MEM="-m 1G"
#SMP="-c 2"
NET="-s 2:0,virtio-net"
IMG_HDD="-s 4,virtio-blk,ubuntu/hdd.img"
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
LPC_DEV="-l com1,stdio"

build/xhyve $MEM $SMP $PCI_DEV $LPC_DEV $NET $IMG_CD $IMG_HDD -f kexec,$KERNEL,$INITRD,"$CMDLINE"

Then run the script:

$ sudo ./xhyverun_ubuntu.sh

To make your Linux installation useful, you may want to install an SSH server:

$ sudo apt-get install openssh-server

Or install a full UI that you can access using VNC:

$ sudo apt-get install xubuntu-desktop vnc4server

Then run the VNC server:

$ vnc4server :0 -geometry 1024x768

And conntect to it by pasting this into Finder’s Cmd+K “Connect to Server” dialog:

vnc://ubuntu.local

If you also follow skerit’s Ubuntu VNC tutorial, you’ll get to a desktop like this.

Next Steps

xhyve is very basic and lightweight, but it has a lot of potential. If you are a developer, you are welcome to contribute to it. A list of current TODOs and ideas is part of the README file in the repository.

Reconstructing Some Source of Microsoft BASIC for 8080

Microsoft BASIC for 6502 exists digitally in source form – the older version of the Intel 8080 CPU only exists on paper though: as a printout in the archives of Harvard University. Some snippets of the code are public though:

  • Ian Griffiths held the printout in his hands and took notes. He copied down several lines from the first page.
  • In Harry Lewis’s blog post, he shows a picture of some lines of the reproduction that is display on the the wall of the ground floor lounge of the Maxwell Dworkin building at Harvard.
  • David J. Malan has a collection of photos of the Maxwell Dworkin reproductions online.

The Computer History Museum in Mountain View, California has a video on display in the software section that tells the story of the company Microsoft. In this video, they show the first page of 8080 BASIC:


Together with the other two sources, we can reconstruct the start of the first page:

00100	MCSSIM(STARI)
00120
00140	TITLE	BASIC MCS 8080	GATES/ALLEN/DAVIDOFF
00160	IFNDEF	LENGTH,<PRINTX !!! MUST HAVE COM !!
00180		END>
00200	IF1;<
00220	IFE	LENGTH,<PRINTX /SMALL/ >
00240	IFE	LENGTH-1;<PRINTX /MEDIUM/ >
00260	IFE	LENGTH-2;<PRINTX /BIG/ >
00280	IFE	STRING,<PRINTX /NO $$/ >
00300	IFN	STRING,<PRINTX /$$ $$/ >
00320	>
00340	SUBTTL	VERSION 1.1 -- MORE FEATURES TO COME
00360	COMMENT *
00380
00400	-------------------------------------------
00420	COPYRIGHT 1975 BY BILL GATES AND PAUL ALLEN
00440	-------------------------------------------
00460
00480
00500	WRITTEN ORIGINALLY ON THE PDP-10 AT HARVARD FROM
00520	FEBRUARY 9 TO APRIL 27
00540
00560	PAUL ALLEN WROTE THE NON-RUNTIME STUFF.
00580	BILL GATES WROTE THE RUNTIME STUFF.
00600	MONTE DAVIDOFF WROTE THE MATH PACKAGE.
00620
00640	THINGS TO DO:
00641	SYNTAX PROBLEMS (OR)
00642	NICE ERRORS
00643	ALLOW ^W AND ^C IN LIST COMMAND
00646	TAPE I/O
00648	BUFFER I/O
00650	USR ??
00652	ELSE
00660	USER-DEFINED FUNCTIONS(MULTI-ARG,MULTI-LINE,STRINGS)
00680	MAKE STACK BOUNDARY STUFF EXACT
	(FOUT 24 FIN 14)
	PUNCH, DELETE;,.
	INLINE CONSTANT CONVERSION -- MAKE IT WORK
	SIMPLE STRINGS

While this is nice, it would be much nicer to have more, maybe all of the original source.

Can someone take high resolution photos of the first eight pages on display on the the wall of the ground floor lounge of the Maxwell Dworkin building at Harvard?

Can someone make a copy of the printout at the Harvard University archives? Applications like Microsoft Office Lens can make high quality copies of printouts with a phone.

Making Obsolete Code Run Again: The mxass 6502 Cross Assembler

Here’s the challenge: Take code that you wrote some 20 years ago in an obsolete programming language for an obsolete platform, make it run on a modern system (without emulation!)… and actually make it useful!

In 1995, I started developing a 6502 Cross Assembler for MS-DOS, in my then favorite languages: PowerBASIC for the bulk of it, and lots of 8086 inline assembly to speed up string operations. I mostly used it for my own C64 projects, and I was very proud of its speed: A fraction of a second to produce several KB of binary code on a 386.

In September 1996, I decided that Turbo Pascal was actually the better language, and converted the source line by line, but keeping all the inline assembly. Development continued until June 1998.

In January 2008, I rediscovered the source and wanted to see whether it could be ported to run on modern computers. I used p2c to convert the Pascal source into C, and spend two days cleaning up the C and rewriting the assembly in C until it correctly compiled my regression test – but the code was still using Pascal strings, for example.

Recently, I dug into my floppy disk collection to recover as many revisions of the source as possible, converted the whole (surviving) history into a git repository, and put it on

github.com/mist64/mxass.

The C version of mxass should run on any modern operating system, and it’s actually a useful piece of software, with some unique features. It supports 6502 with illegal opcodes, 65816 and Z80 assembly, and it tries to be backwards compatible with the “64′er” set of assemblers (Hypra-Ass, Giga-Ass, Vis-Ass, Assblaster, F8-Assblaster), in fact, F8-Assblaster source printed to a file in an emulator should assemble with very few changes.

That said, please do not use it for new projects. Use cc65 for that.

What is the oldest source you have written for an obsolete platform that have ported forward to modern systems?

Emulating the Intel 8080 on a MOS 6502

Emulating older computers on modern, much faster systems, is very common nowadays – but how about emulating the Intel 8080 (1974) on a MOS 6502 system like the KIM-1 (1975)? The “8080 Simulator for the 6502″ by Dann McCreary from 1978 does exactly that.

Why imitate one microprocessor with another? You probably purchased this 8080 simulator package to do one or more of the following:

  • Run existing 8080 software on your 6502
  • Write, test and debug your own 8080 software without having to purchase a complete 8080 based system
  • Learn something about the architecture and instruction set of the 8080 via hands-on experience

The emulator is extremely size-optimized and fits in less than 1 KB of RAM. This was done by compressing the 256-entry opcode space into 25 sections of similar instructions that could be handled by one generic function.

The four-page article “8080 Simulation with a 6502″ (MICRO – The 6502 Journal, issue 16, September 1979) explains the motivation and design of the software in detail:


Dann McCreary: 8080 Simulation with a 6502 [1979]

And here is the original commented source code with usage instructions:


Dann McCreary: An 8080 Simulator for the 6502, KIM-1 Version [1978]

Thanks a lot to Dann McCreary, who provided scans of his original work, as well as additional insights:

I wrote this by hand, pencil and paper assembly (BTW, did you ever read Carl Helmer’s article about pencil and paper in one of the very early issues of BYTE magazine? ;) and much of the simulator was written as I rode the bus to and from work… ;)

About the tools used to create this program:

Honestly, I don’t remember for certain… BUT… MORE THAN LIKELY, it is
a FAKE – i.e., I probably just text-edited a listing in “assembler
listing” format for the purpose of publishing the code and “looking
professional”… ;)

CONSEQUENTLY, be on the lookout for typographical (and thus operational)
errors that could be “in there” …

The all-upper-case makes me think I printed this stuff out on an old
drum printer that I resurrected from the American Surplus Computer
company in Boston back in the ’70s… And there’s yet another story! :)

The text editor may likely have been running on my Apple ][…. or maybe
“borrowed” from some company where I was working at the time?

Apple-80

Dann later ported the simulator to the Apple-][. The tape dump of the resulting product “Apple-80″ can be found at brutaldeluxe.fr.

Converting VisAss and F8 AssBlaster Source

If you have developed applications for the Commodore 64 in the 80s or 90s, chances are you still have your old floppy disk with the original assembly sources. If you have used the VisAss or
F8 AssBlaster assemblers, you can use a new command line tool I wrote to convert the encoded binary files into ASCII, so they can be published or you can continue development using modern tools like cc65.

Get it at github.com/mist64/vis2ascii.

If you need any help converting old C64 source in other formats, contact me, I’ll be happy to help!

Reverse-Engineered Final Cartridge III Source Code

The Final Cartridge III was one of the major multi-function extension cartridges for the Commodore 64. It contained BASIC extensions, floppy and tape speeders, centronics printer support, screen editor extensions including F-key shortcuts, a monitor, a freezer – and a GEOS-like windowing system called “Desktop”. In all this, the FC3 integrated seamlessly with the look-and-feel of the stock Commodore 64: It did not change anything (same screen colors and banner!), it only extended functionality in consistent ways.

The 64 KB ROM in the FC3 consists of 4 banks. I reverse engineered and commented the first bank, which contains the BASIC and editor extensions, the floppy and tape speeder, fast format, the centronics printer driver, and the monitor. The cc65 suite can compile the set of .s files into the exact original binary.

The project can be found at github.com/mist64/final_cartridge.

The source is useful in many ways. Since the components are quite independent of each other, they can be extracted and used in other projects. The build system is configured so it can build a stand-alone RAM version of the monitor, for example. Another idea would be to use the source as a base for an improved version of the Final Cartridge. Components that are obsolete nowadays can be swapped with more useful functionality, for example. Refer to the README in the repository for more information.

Contributions welcome!

Source of “The Wave” Web Browser for C64/C128 GEOS Wheels

“The Wave” is a Web Browser for GEOS (with the Wheels extension) on C64/C128 machines with a SuperCPU and a RAM extension.

A while ago, Maurice Randall, the author, published the source of the V1.0 version as a WR3 archive that contained the assembly source in GeoWrite format and some developer documentation.

I converted the files into plain text and published them at github.com/mist64/thewave.

geowrite2rtf, a GeoWrite to RTF converter

geowrite2rtf is a tool that converts Commodore 64/128 GEOS GeoWrite documents into RTF format. Most formatting will be preserved, but some formatting and graphics will be discarded.

The C64/C128 GEOS GeoWrite file format is a rich text format, which is, like most GEOS file formats, not a sequential file, but a VLIR file, a collection of up to 127 sequential streams. For a VLIR file to exist outside of a C64 disk image (D64, D71, D81 etc.), it has to be in serialized .CVT format. You can use tools like c1541 or DirMaster to extract them from disk images.

You can find it at github.com/mist64/geowrite2rtf.

If you are looking for GeoWrite files to test this on, here is the gateWay OS manual, or search for “CVT” at cbm8bit.com

Comparative C64 ROM Disassembly Study Guide

The Commodore 64 ROM has been subject to immense reverse engineering. Many commented disassemblies were published over the decades, scattered over different media such as books, magazines, disks, and later, the internet – and there are even some commentaries that apply to the C64 ROM, but were written with other systems in mind that shared Microsoft’s BASIC interpreter.

In the past weeks, I have collected and published several of these comentaries in a unified format:

Wouldn’t it be nice to see the comments of all these sources at the same time when looking up code in the C64 ROM?

At pagetable.com/c64rom, you can now see a cross-referenced HTML of the disassembled C64 ROM, with four commentaries side-by-side – the Comparative C64 ROM Disassembly Study Guide:

If you can’t fit all columns on your screen, try reducing the text size in your browser.

The raw txt files with the commentaries as well as the script to combine them are maintained at github.com/mist64/c64rom. Improvements welcome.

And, as mentioned previously, there are many more commentaries in existence, if you want to help me convert them into the canonical format, send me an email.