The W65C265QBX§

The W65C265QBX MENSCH Microcomputer is a simple, relatively cheap single-board computer based on the WDC 65C816 microprocessor. You might or might not recognize the 65C816 as the processor used in the AppleIIGS or as the basis of the Ricoh 5A22 and Super Accelerator 1 (SA-1) chips used in the SNES.

At any rate, after (probably) years of listening to @luthwyhn talk about the 65C816, I decided to pick one of these W65C265QBXs up and play with it. Unfortunately, one: the WDC Tools provided by Western Design are Windows-only and two: the documentation is sparse and not so great. Hopefully, this little guide will help you and/or future me with getting set up to develop on it with Linux.

This tutorial borrows heavily from this post on the forums about getting set up with a different board from Western Design, and I wouldn't have gotten as far as I have without it.

Necessary hardware§

The QBX has a 6-pin serial interface you can use to communicate with the monitor software that comes flashed into the ROM, but it needs some kind of adapter. I bought one of these knockoff FTDI serial to USB converters. It was also helpful for talking to the HC-06 bluetooth adapter I got to use with my STM32F3, but that's another story. Connecting it was really simple, I just had to use some female-to-female dupont wires to connect it up. Check the pin-out but mine were literally just connected straight across.


The WDC Tools come bundled with a Windows build of Joe Davisson's tool called EasySXB. Luckily for us, the source is available on GitHub, along with instructions on how to compile it. We'll be using this to talk with the monitor software and to upload program binaries.

We're also going to be using CC65's assembler (ca65) and linker (ld65). There should be a package for your distribution, but I did have to install it from AUR on Arch.

Finally, we'll also need SRecord, a "collection of tools for manipulating EPROM load files". Frankly, I don't fully understand S-Records, but I do know they're a format EasySXB can load onto the MENSCH, and that the file tells it the where and what of how to place our program in memory. Like CC65, there should be a package for your distro. I had to get it from AUR, too.

The code§

Now, let's throw together a test program. Again, this is just a direct port of the code from the forum thread I mentioned above.

There's better resources out there on 65c816 assembly, so I won't belabor the code too much, but I do want to point a few things out. First of all, there's the .org line. This tells the assembler and linker where in memory we're going to be placing the final binary. In this case, we're going to be placing it at $00:00C0. This means we're using bank zero ($00:) and an offset of 0x0C from the start. The reference manual tells us that this is a good place to put user programs in memory. Next are .a8 and .i16. These are directives that tell cc65 that we're going to be using an 8-bit accumulator (register A) and 16-bit index registers (registers X and Y). These registers can be configured to be either 8- or 16-bits wide, so make sure your assembly matches your configuration, but for what it's worth, this is how my board came. From what I understand, this is a common register configuration, but don't ask me why. I haven't gotten that far yet.

You can check the configuration inside EasySXB by clicking the GET button on the left-hand side, and looking at the configuration information in the bottom pane. This is what mine looks like:

Register configuration in EasySXB

We'll also be using two subroutines built into the MENSCH monitor software: PUT_CHR, located at $00:E04B, and SEND_CR, located at $00:E066. PUT_CHR takes the ASCII code of a character placed in the accumulator and sends it to the user over serial. SEND_CR sends a carriage return over serial. These subroutines, along with the rest of the available subroutines, are listed in the back of the reference manual.

Place the following code into a file called hi.asm:

;;; hi.asm - print "Hi! " ten times with some newlines
;;; Assembler directives
        .org $C0                ; Code start. Pass as --offset to srec_cat
        .a8                     ; Set accumulator to 8 bits
        .i16                    ; Set index registers (X/Y) to 16 bits

;;; Start of code
        ldx #$0a                ; Set X to number of times (10) to print "Hi! "
        jsl $00e066             ; Print newline
        jsl $00e066             ; Print newline
        lda #'H'
        jsl $00e04b
        lda #'i'
        jsl $00e04b
        lda #'!'
        jsl $00e04b
        lda #' '
        jsl $00e04b
        dex                     ; Decrement counter in X
        cpx #0                  ; Compare X to 0
        beq done                ; If zero, branch to done
        jmp main                ; Else, loop
        jsl $00e066             ; Print newline
        brk                     ; Return to monitor

Assembling, linking, and SRECing§

Now let's get this text file turned into a binary we can run on the QBX. First, we're going to use ca65 to assemble the program into an object file. Since this is using 65816 assembly, we are predictably going to pass --cpu 65816 as a parameter:

ca65 --cpu 65816 hi.asm

This will produce an object file called hi.o that we're going to link into a binary called hi.bin. I don't totally understand why we pass --target none here, though my understanding is that it has something to do with relocating code, which we don't want it to do.

ld65 --target none -o hi.bin hi.o

Finally, we have to turn this binary into a format the QBX recognizes. One of those is SREC, which is what we'll be using. I believe the WDC Tools use some kind of HEX file, but as far as I can tell, these work just as well. Note that we're passing --offset 0xC0 to srec_cat. This needs to match the parameter given to the .org directive in the assembly code above.

srec_cat hi.bin -binary --offset 0xC0 -o hi.srec

Transferring and running§

Now that we have hi.srec, we have a file the QBX is capable of loading and running. Head over to EasySXB and get it connected to the device. First, you'll want to make sure your Board Model is set to W65C265SXB:

Board configuration in EasySXB

Then, go to File > Connect to SXB... and enter the device location. Mine shows up at /dev/ttyUSB0, but YMMW. At this point you should be connected and you can type a question mark at the prompt to make sure the monitor responds. It should look something like this:

Monitor response to ?

Click on File > Upload Program... and navigate to your hi.srec file, making sure to switch the file type filter to SREC File(*.srec). Select your file, and you should see the monitor respond:

Program being uploaded

Type j to execute a jsl instruction to your code and enter the address we used above 00:00C0. Your program should be executed:

Program being uploaded

Wrapping up§

And there we have it! From code to execution on the device in a few easy steps. There's a bunch more to learn about ca65, the board, and the 65816, which I hope to keep sharing here as I learn, but hopefully this helps you get started. If not, well, hopefully it'll help me some time in the future when I'm setting this up on another machine. Until next time 💜