Jeremy Likness' Blog

Commodore 64 Meets AngularJS and TypeScript

In case you haven’t noticed, I’ve been spending a lot of time working with a combination of technologies that I believe make it easier and more efficient for large development teams to build enterprise web applications. TypeScript gives JavaScript some discipline and AngularJS brings XAML-like declarations to HTML. Although I’ve been using this power-packed duo in a large system for months now, it is a proprietary code base so I can’t use a lot of what I use in my day-to-day activities as examples for this blog. Small, targeted examples like the ones I share in my WintellectNOW video Fundamentals of AngularJS are helpful to understand the system but at some point you need a larger example to see how everything ties together.

I decided if I was going to take all of my free time left over between consulting full time, writing a book, authoring videos, training, and letting my wife and daughter catch a glimpse of me on occasion to write an example application, I might as well make it fun. I’ve always wanted to write a Commodore 64 emulator and this was the perfect excuse. To be fair, this is more of a 6502 instruction set simulator and there is no hardware emulation (it also doesn’t handle cycle timing) but it was a fun project to run nonetheless and demonstrate how these technologies were used.

The T6502 emulator (hint, that link will get you to a working version) is still very much a work in progress. You can download the latest source here. I have some sample programs that will load and run, including a few graphics routines as well as “test programs” that verify the accuracy of the emulation. The packed decimal program fails now, but I don’t suspect I’ll waste too much time tracking that down as it is such a rare mode. I also don’t have all op codes in place (I’ve taken the approach of finding the program I want to run, then building out the op codes that support it).

I’m going to use this reference software to write a series about building apps with TypeScript and AngularJS. In this introductory session, I want to share why I believe this is the right set of tools for building enterprise web apps. First, let’s discuss the “what” …

What is It?

The software emulates the 6502 instruction set. It features a compiler that recognizes basic assembly with support for setting the memory location and assigning / using labels and literals in both decimal and hexadecimal format, a disassembler, a memory dump feature, a debugger (yes, you can step through op codes line by line), a dashboard that displays the current program counter and register values, a console for diagnostic information and output, and a 32 x 32 display that uses SVG to emulate a memory-mapped display with a 256-color palette (I realize this is not how the Commodore worked but hey, this is 2013).

The assembler supports the use of DCB to load bytes (i.e. DCB 0x02, 0x03, 0x04 will load those values into subsequent memory locations). The video memory is mapped starting at $FC00 and goes left to right, top to bottom. There is a zero page address for random numbers and I plan to add a character input, character output (to the console), and clock for some more interesting programs. The default program start is $200, just above the stack. The reason I mapped video to $FC00 is because you can BNE off the high byte to know you’re off the edge so to speak.

How is it Done?

This is a bit more interesting. I took a Test-Driven Development (TDD) approach although some components I did write before tests. The majority of op codes and all of the compiler features were written this way. I used Jasmine for client-side tests (just click on the specs links). For the compiler, I might write a test for a new feature I wanted to implement like this:

describe("given compiler when decompiler called with code", () => {

    beforeEach(() => {
        var jmpAbsolute = new Emulator.JmpAbsolute();
        var address = cpu.rPC;

        // $0200: JMP $0200
        cpu.poke(cpu.rPC, jmpAbsolute.opCode);
        cpu.poke(cpu.rPC + 1, address & Constants.Memory.ByteMask);
        cpu.poke(cpu.rPC + 2, address >> Constants.Memory.BitsInByte);
    });

    it("then should return the decompiled code", () => {        
        var actual = compiler.decompile(cpu.rPC);
        expect(actual).toContain("$" + toHexAddress(cpu.rPC) + ": JMP $" + toHexAddress(cpu.rPC));
    });
});

This would cause the test to fail. Then, I’d update the compiler to implement the feature:

public decompile(startAddress: number): string {
            
    var address: number = startAddress & Constants.Memory.Max;
    var instructions: number = 0;
    var lines: string[] = [];

    while (instructions < Constants.Memory.MaxInstructionsDecompile &&
address <= Constants.Memory.Max) {
            
        var opCode: number = this.cpu.peek(address);

        var parms = [
            opCode,
            this.cpu.peek(address + 1), 
            this.cpu.peek(address + 2)
        ];

        var operation = this.cpu.getOperation(opCode);

        if (!operation) {
            operation = new InvalidOp(opCode);    
        }

        lines.push(operation.decompile(address, parms));

        instructions += 1;
        address += operation.sizeBytes;
    }

    return lines.join("\r\n");
}

And run the test. This is also how I did the op codes. There are hundreds of tests and I’ll add more as I evolve the instruction set. I’m using some of the cool TypeScript features as well, including generics:

$http.get(url).then((result: ng.IHttpPromiseCallbackArg<string>) => {
    this.$scope.compilerInfo = result.data;
});

Interfaces to describe what I’m interacting with (so the CPU just uses the interface and doesn’t care about the implementation):

export interface IOperation {
    execute(cpu: Emulator.ICpu);
    addressingMode: number;
    opCode: number;
    opName: string;
    sizeBytes: number
    decompile(address: number, bytes: number[]): string;
}

Inheritance to avoid repeating code:

export class BaseOpCode implements IOperation {
        
    constructor(
        public opName: string
        public sizeBytes: number
        public addressingMode: number
        public opCode: number) {        
    }

    public decompile (address: number, bytes: number[]): string {
        return OpCodes.ProcessLine(address, this, bytes);                
    }

    public execute(cpu: Emulator.ICpu) {
        return;
    }
}

And classes to organize op codes into testable units:

export class AddWithCarryZeroPageX extends BaseOpCode {
    constructor() {
        super("ADC", 0x02, OpCodes.ModeZeroPageX, 0x75);
    }
    public execute(cpu: Emulator.ICpu) {
        OpCodes.AddWithCarry(cpu, cpu.peek(cpu.addrZeroPageX()));
    }
}

When you look at the main page, you’ll see the AngularJS at play. For example, the display of stack registers a hexadecimal filter to show the hex values and a bit filter to show the individual bits in the processor status byte (oh design people don’t hate me for resorting to tables):

<tr>
    <td>{{cpu.rPC | hexadecimal}}</td>
    <td>{{cpu.rSP | hexadecimal}}</td>
    <td>{{cpu.rA | hexadecimal}}</td>
    <td>{{cpu.rX | hexadecimal}}</td>
    <td>{{cpu.rY | hexadecimal}}</td> 
    <td>{{cpu.rP | eightbits}}</td> 
    <td>{{cpu.elapsedMilliseconds / 1000 | number:3}}</td>               
    <td>{{cpu.instructionsPerSecond}}</td>               
</
tr>

And then both the console and the display use Angular directives:

<div class="column"><console></console></div>
<
div class="column">
    <div style="width: 200px;">&nbsp;</div>
    <display></display>
</
div>

I’ll continue to post to this series and describe how I built the compiler and step through TypeScript and AngularJS as a part of that. For now I wanted to share where it’s at and what it is.

What It’s Not

There is a large list of things “to do” but I will eventually get to them as this is a fun hobby for me. I’ve always wanted to write an emulator and find it ironic that I’ve finally tackled it using web technologies like SVG and JavaScript. There are tons of op codes not implemented yet – I used sample code and built up to support it and am just now walking through the entire stack so that will take some time unless someone joins that project and helps extent them. I haven’t implemented the zero page magic yet like recognizing a key press or providing a timer. These are just repeatable extensions to the base that’s there, however, and the main structure, processor, logic, etc. is all there.

What’s Next?

I’m looking to wrap up as much of this as I can by DevLink to use in my talk about AngularJS and JavaScript, but I plan to release a series of blog posts now that I have the example application finished. You can find tons of how-to for TypeScript and AngularJS on the web, so for this I’m going to tie it directly to the project – for example, how did I solve the problem of having a console that components can write to without depending on the directive that renders it? How did I create a testable filter to show hexadecimal? How did I implement the pixel-based display? Why use an interface? What do generics in TypeScript solve for me? I hope these practical, hands-on examples will help you with your projects.

That’s it for now, I’m off to work on my Windows 8.1 book but I’ll be back with my first post “in the details” soon.

On Aug 9 2013 8:41 AMBy jlikness With 1 Comment

Comments (1)

  1. Why did you select AngularJS and TypeScript over other technologies? Was it merely an exercise to see if it could be done or was the article a piece "encouraged" and compensated by MSFT?

Leave a Comment