Exploiting the 65C816S CPU

         by Jim Brain (j.brain@ieee.org) 

Introduction

For a CPU architecture that can trace its roots to the mid 1970's, the 65XX line has proved very successful. Finding its way into flagship systems such as Commodore, Apple, Atari, and other lesser known units, the CPU has toiled away for years in the single digit megahertz speeds. Programmers across the world have analyzed the CPU to death and documented every last one of its "undocumented" opcodes. Ask a "coder", and he or she will rattle off the cycles it takes to do an immediate load or an absolute store. In short, the CPU is road tested and well known.

However, how much do you know about its "children"? Yes, in the 1980's, while Commodore was busy tinkering with the NMOS version of the CPU designed by Chuck Peddle, Bill Mensch, and the ex-Motorola 6800 design crew, Bill Mensch started a new company, Western Design Center, and redesigned the 6502 to use the newer and faster CMOS fabrication process. In addition to the new 65C02, Mensch designed an upwardly compatible 16 bit brother, the 65C816. Although both were offered to Commodore, only the 65C02 was used and only in the never produced CBM Laptop computer. Apple, however, used the 'C02 in later models of the Apple II line and placed the 65C816 at the heart of the Apple IIGS system.

Although Commodore never took advantage of the WDC CPUs, third party products have offered their speeds to the Commodore community. Early models like the TurboMaster and TurboProcess offered 4 MHz speeds to the Commodore 64 owner, while newer products like the FLASH8 offered 8 MHz speeds. The fastest offering thus far is the CMD SuperCPU, offering speeds of 20 MHz to the Commodore owner. Of these, the TurboProcess, the FLASH8, and the CMD SuperCPU all use the 16 bit CPU, the 'C816.

Since the 'C816 is available now to the Commodore user, and with the SuperCPU poised to provide software compatibility never before achieved, it is likely that more and more Commodore applications will run on 'C816 equipped machines. So, why should the Commodore software developer care? Sure, the 65C816 will run 6502 based applications in 6502 emulation mode at substantial speed increases, so developers can opt to continue writing 6502 based applications. While I encourage developers to always provide 6502 based versions of applications when possible, there are useful features available only in the Native mode of the 65C816. This article describes some of these features and how to utilize them.

Disclaimer

The following information is based on following resources:

Most of the following information is system independent, but any information specific to the CMD SuperCPU is preliminary and subject to change.

It is not the intention of this article to detail all the possible 65C816S opcodes nor their addressing modes. It is also not the intention of the article to describe the operation of the SAS assembler. For more information on both of these products, please consult the manuals listed above.

Diving Right In

As this article is geared toward the programmer, we're going to dive right into the new features. Commodore World issue #12 has an overview of the CPU for those just arriving on the scene. For those who know an index register from an accumulator, read on

Overview of Registers

One of the features of operating in Native mode of the CPU is the enhanced set of registers available to the programmer. They are also key to explaining the other features of the CPU. So, let us go over the new register set:

        8 bits                   8 bits                  8 bits
------------------------------------------------------------------------
[  Data Bank Register   ][   X Register High    ][   X Register Low*   ]
[  Data Bank Register   ][   Y Register High    ][   Y Register Low*   ]
[          00           ][ Stack Register High  ][ Stack Register Low* ]
                         [   Accumulator High   ][   Accumulator Low*  ]
[ Program Bank Register ][ Program Counter High*][ Program Counter Low*]
[          00           ][ Direct Register High ][ Direct Register Low ]
------------------------------------------------------------------------

* Original NMOS 65XX register set

These registers are referred to in the remainder of the article by their acronyms, as follows:

Data Bank Register    (DBR) 
Program Bank Register (PBR) 
X Register High       (XH) 
X Register Low        (XL) 
Stack Register High   (SH) 
Stack Register Low    (SL) 
Y Register High       (YH) 
Y Register Low        (YL) 
Accumulator High      (B) 
Accumulator Low       (A) 
Program Counter High  (PCH) 
Program Counter Low   (PCL) 
Direct Register High  (DH) 
Direct Register Low   (DL) 

In addition, the 16 bit combination of B:A is called C, the 16 bit X and Y registers are called simply X and Y, the 16 bit Direct Register is called simply D, and the 16 bit Stack Register is called S.

One more register requires discussion before we can delve into programming the '816: the Status Register (P)

Bit:	Description 

 7      N flag 
 6      V flag 
 5      1 in Emulation mode 
        M flag in Native mode (memory select bit) 
           0 = 16 bit accumulator 
           1 = 8 bit accumulator 
 4      B flag in Emulation mode 
        X flag in Native mode (Index Register Select) 
           0 = 16 bit X and Y registers 
           1 = 8 bit X and Y registers 
 3      D flag 
 2      I Flag 
 1      Z flag 
 0      C flag 
        E flag (Emulation flag)  (Can not be accessed directly) 
           0 = Native mode 
           1 = Emulation mode 

It is important to note that there are 3 more flags available in the Native mode version of the status register. Since there were 7 flags used before, how did WDC squeeze in the extra flags? Well, the E flag cannot be accessed or seen in the status register. The only way to change it is to set up the C flag to the intended stats of the E flag and issue the eXchange Carry and Emulation flags (XCE) opcode. Another flag, M, takes the place of the static 1 state in the old status register. M controls the length of the accumulator. The last flag, the X flag, controls the length of both index registers. Note that this flag takes the place of the B flag. Thus, the B flag is unavailable in Native mode. Since the B flag is used to determine whether a hardware IRQ or a software BRK opcode caused an IRQ interrupt, the Native mode provides separate interrupt vectors for BRK and hardware IRQs.

The X and M flags are especially important in Native mode, so much so that each programmer will become intimately familiar with these flags. When a register is selected to be 8 bits wide, it emulates the operation of the register in Emulation mode. However, when the register is flipped into 16 bit operation, its length doubles everywhere. For instance, a push of the accumulator with the M flag reset causes 2 bytes to appear on the stack. Likewise, an immediate load of the accumulator will require a 3 byte instruction: one for the opcode, and a 2 byte operand. This opens up one of the nastiest gothcas on the chip, but we'll detail this later in the article.

More Memory

As you may be aware, the Native mode of the '816 allows the programmer contiguous access to up to 16 megabytes of RAM. This access doesn't involve tricks such as DMA, page flipping, or RAM "windows". At any given point in time, an application can access a memory location and request a memory location more than 64 kB higher in the next instruction. In order to access the new memory locations using standard 6502 addressing modes, the new DBR and PBR registers have been added. The PBR serves as the 3rd byte of the PC, allowing code to run at any location in memory. The DBR register functions as the 3rd byte for memory accesses in addressing modes like absolute mode. Of course, there are restrictions, like the inability to execute code that crosses a 64kB boundary, but these restrictions can be overcome, as you'll see below.

For clarity, we will refer to the 3rd bytes of an address as the "bank", and refer to the 2 lowest bytes of an address as the offset. Alternate names include "segment" and offset, but that naming scheme was previously used with the Intel 80X86 CPU line and carries with it many bad connotations.

Since memory addresses can now be 3 bytes wide and contain 6 hexadecimal digits, an obvious representation would be $xxxxxx. However, many '816 references write the address as a two part quantity, with the bank register and the 16 bit offset separated by a colon, ":". Therefore, $xxyyyy and $xx:yyyy are equivalent. In this article, the former notation is used for emphasis and because ":" notation also brings up bad connotations from Intel 80X86 CPU line.

Increased Stack

As the S register is now 16 bits wide, the stack can now reside in all of bank 0, giving the programmer 64 kB of stack area. As well, the S register can be set to any location in bank 0. This allows one to start stack from any non-aligned page in bank 0.

Enhancements to Old Addressing Modes

Even though the '816 supports the traditional 14 addressing modes of the 6502, it extends some of them to handle the extra features in the '816. Note that the opcodes and parameters have not changed for these addressing modes; rather the way the CPU treats them differs slightly. Of special note is the term "zero-page", which has been expanded into "Direct Mode". Let's take a look at what changes you can expect.

Absolute Modes

In the 65XX CPU, modes such as absolute and its indexed siblings each could access a memory location in the 64 kB memory map. In the '816, these modes are now capable of accessing memory above and beyond 64 kB. When accessing memory, the DBR register is prepended to the address being accessed, thus forming a 24 bit effective address. When transferring control, the PBR register is prepended. Thus, if the DBR contains a $05, the following:

   af ff ff     lda $ffff 

would load a value into the .A register from $05ffff. If the M flag is set to 16 bit mode, the 16 bit value in $05ffff and $060000 will be loaded. If the M flag is set to 8 bit, only $05ffff will be loaded. Notice that this example also shows "temporary-bank-incrementing". While loading a 16 bit value with the instruction above, the DBR is "temporarily" incremented to allow access of data from bank $06. The actual DBR is left unchanged, so the next instruction will find the DBR back at $05.

You'll rarely see such bank changes when accessing data as above, but it is common when using indexing modes. With the DBR at $05, executing:

   a2 ff ff     ldx #$ffff 
   bd ff ff     lda $ffff,x 

will load values from $06fffe and possibly $06ffff, depending on the size of the accumulator.

When using absolute mode on opcodes like JMP and JSR, the PBR register is used to form the 24 bit effective address. Unlike the DBR, the PBR does not exhibit "temporary-bank-incrementing". It simply rolls over within the same bank. Keep that in mind.

Direct Modes

To enhance the capabilities of the '816, the CPU offers Direct Mode, which is a superset of "zero-page mode". Basically, all z-page opcode operands are added to the D register to form a 16 bit effective address. This allows using the entire bank 0 as effective z-page memory. With the D register set to $0200, executing:

   a5 10        lda $10 

would load the accumulator from $000210 (and possibly $0211). Direct mode is not allowed to increment into bank 1. If the above instruction is executed while D = $ffff, the accumulator would start accessing data from $000009. This highlights an important yet subtle change. No longer is lda $10 guaranteed to access data from $000010. It will access data from D + $10.

Indexing changes little with respect to Direct mode. After the D register is added to the 8-bit offset, the appropriate register is added, and the effective address is normalized to fall within bank 0. There is no way to reference outside bank 0 in Direct mode. Even if index registers are set to 16 bit mode and hold $ffff, the instruction will access bank 0.

Direct Indexed Indirect Mode

Most programmers forget, but this mode executes in two parts. Now, it becomes important. In the first part, the 8-bit offset is added to the D register and then the X register. The result is normalized to 16 bits, and two values are accessed from bank 0. The second part takes those two bytes as the effective address, and PREPENDS the DBR register to form a final address. In this way, you can access memory outside bank 0 with this mode, but you must store the address to access in bank 0. Read that sentence again.

Direct Indirect Indexed Mode

Like its relation above, this mode work in two parts. In part 1, the 8 bit offset is added to the D register and normalized to 16 bits. Two bytes are accessed from bank 0, and then the 16 bit value returned is appended to the DBR to form a 24 bit effective address. In part 2, the Y register is added to this effective address to form the final address for access. As above, part 1 cannot access outside bank 0, but part 2 can.

Stack Mode (Implied)

Usually lumped in with the Implied addressing mode by most 6502 developers, stack mode has changed to accommodate the new widths of the registers. Depending on the width of the register, stack operations will push and pull either 1 or 2 bytes. This can cause problems if you push a 16 bit register and try to pull it off as an 8-bit register. Caveat Emptor.

Immediate Mode

In Emulation mode, immediate mode was simple. You specified an 8 bit immediate value to be loaded into a register. In Native mode, however, registers can be 16 bits. Everyone knows the opcode can do an immediate 8-bit load, but what opcode performs a 16-bit immediate load? Answer: the same opcode! If the register is set to 8 bits via the X or M flags, the immediate load on that register will pull in 8-bits. If the register is set to 16 bits, the instruction will load a 16 bit value. The effects of this change are monumental. An 8-bit immediate load requires 2 bytes, while a 16 bit load requires 3.

This presents some problems. Since neither the opcode nor the mnemonic differs between the two forms, the assembler cannot tell which form is required from context. The develop must tell the assembler which form to use by use of assembler directives. However, this doesn't guarantee success. The developer must ensure that the flags are set correctly before executing an immediate load of any register. Improper settings will either cause the instruction to pull the next opcode into the high byte of the register or treat the high byte of the intended register value to be executed as an opcode. In my biased opinion, this is severely shortsighted. I would rank this as the number one bug that '816 developers will face. However, simple macros employed in your assembler can help minimize this problem.

New Addressing Modes

The 816 can utilize all 14 original addressing modes of the 65XX line, and adds 10 more for a total of 24. The new addressing modes are as follows:

Let's take each under consideration:

Absolute Long Mode, Absolute Long Indexed Mode

These modes allow a programmer to access a fully qualified memory location without using the DBR. The benefits include pulling data from one bank to store in another without constantly changing the DBR. The disadvantages include the extra size of the instruction. The long forms of these two absolute modes takes an extra byte in memory and an extra cycle to load into the CPU. Note that only the X register is supported as an index register for absolute long indexed mode.

Absolute Indirect Mode

This mode, denoted as (a), functions similar to (d), but does not require the D register. The locations in bank 0 specified as the operand in this mode are accessed, and the results form the lower 16 bits of the effective address. The PBR is prepended to this address to form a final 24 bit address. The PBR is used since only the JMP opcode uses this mode.

Absolute Indexed Indirect Mode

This mode, denoted as (a,x), functions similar to (d,x), but the D register is not involved. Thus, as with the (a) mode above, these modes are to direct modes as absolute long modes are to absolute modes.

Direct Indirect Long Mode

This mode functions similar to Direct Indirect Mode, except that in part 2, all three address bytes are pulled from memory. The DBR and PBR are not involved, but the D register is used. If locations $10 - $12 contained $10, $11, $12, and the D register contained #08, then:

    a7 08       lda [$08] 

would load the accumulator with data starting at $121110. Do you see how that works? The D register is added to $08, and the result ($10) is accessed to fetch the 24 bit memory address, in low byte order.

Direct Indirect Long Indexed Mode

As Direct Indirect Indexed Mode extends Direct Indirect Mode, this mode extends the above mode by adding the Y register to the effective address pulled from bank 0. Note that even though this mode uses a fully qualified 24 bit address (no DBR or PBR involved), it can still increment into the next bank to access memory. Thus if we use the above example, and Y = $ffff, executing:

    b7 08       lda [$08],y 

will fetch the accumulator starting at ($121110 + $ffff, or $131109).

Stack Relative Mode

Denoted as "d,s", this mode is completely new to 6502 programmers. It starts off the set of modes that work with the S register (Stack Pointer). As the Stack Pointer is now 16 bits in width, the stack can fill all of bank 0. Although 65XX programmers have traditionally used stack locations only for saving return addresses from JSR and interrupt sources, the '816 allows one to store data on the stack. In this mode, the 8 bit operand is added to the S register and normalized to 16 bits. Memory in bank zero is accessed starting at this effective address. Since the S register points to the next location to hold data, executing:

   a3 00        lda $00,s 

would prove meaningless, unless you wanted to get the last byte pulled off the stack. This mode allows one to access the last 255 bytes off the stack in the order they would be pulled off.

Stack Relative Indirect Indexed Mode

By far the most complex Addressing Mode to understand in the '816, this mode can be used to access data referenced by pointer values on the stack. Denoted as "(d,s),y", the effective address formed by the 8 bit operand and the S register is normalized to 16 bits and 2 bytes are accessed. The resulting 16 bits are appended to the DBR register and the 24 bit effective address is added to the Y register to form a final 24 bit memory address. This can be used to access data passed by "reference" (not the value, but the pointer to the value, is stored in the stack).

Relative Long

Only one opcode uses this addressing mode, Branch Long (BRL), and it fulfills the desire of every 65XX programmer to have a relocatable jump instruction. Unlike normal branches, BRL can cross page boundaries. However, BRL is constrained to the current bank. It cannot cross banks. Although viewed as a disadvantage, this presents a few possibilities. If a programmer was at $xxff00 and wanted to jump to $xx0000, he or she can use BRL, even though the offset appears wider than $32767, the maximum offset for BRL. In actuality, the assembler computes a branch to the next bank, which is only 256 bytes away. The CPU negates the bank increment, thus forcing execution to begin at the current bank.

Block Move

Along with stack relative indirect indexed mode, this mode is complex. However, unlike its stack counterpart, this complex mode is easier to understand. Denoted as xyc, this mode allows the programmer to quickly move areas of memory from one bank to another. An example will prove helpful:

   a2 00 20     ldx #2000 
   a0 00 30     ldy $3000 
   a9 ff 0f     lda $0fff 
   44 02 01     mvn $01,$02 

Basically, we are moving $1000 bytes from $012000 to $123000. The X register holds the offset into the source bank; the Y register holds the offset into the destination bank. The accumulator holds the number of bytes to move MINUS 1. Remember that. The opcode Move Negative (MVN) takes the source bank and the destination bank as operands. The only opcodes that utilize this mode are MVN and Move Positive (MVP). MVP assumes the X and Y registers hold the top of the data areas to move, while MVN assumes the opposite.

Hints And Tips That Will Decrease Your Stress

Writing Machine language applications on any platform is bound to create stress in your life, but this section is presented to make the programmer aware of some "gotchas" in the '816. Here goes.

Initialization

To switch the processor from emulation mode into native mode, perform the XCE (eXchange Carry with Emulation) mnemonic with the carry bit reset:

   18           clc 
   fb           xce 

The next thing to do is determine the initial size of your registers. The 816 can use any register as 8 bits or 16 bits. By default, the registers are 8 bit, but just to make sure:

   c2 30        rep #%00110000	; set index and acc to 8 bit 

By stuffing $30 into the processor status, we are setting both the X and M flags to 8 bit.

At this point, it should become obvious that if the programmer wishes to flip between 8 and 16 bit modes many times, macros need be employed to do this quickly and painlessly.

Now, the development can begin.

Register Usage

Never underestimate the power of immediate mode to mess your program up. If at all possible, switch to one size of registers and stay that way. If that can't be accomplished, thoroughly document where you changed the size of either set of registers. Remember, the assembler cannot trace program execution, so don't assume the assembler will fix everything up for you. On the preliminary version of the SAS assembler, the opcodes to instruct the assembler to alter immediate mode behavior are:

   .inl   ; INdex registers Long 
   .ins   ; INdex registers Short 
   .acl   ; ACcumulator Long 
   .ins   ; ACcumulator Short 

What happens when you change a register's size? Well, let's treat the index registers and the accumulator separately. When changing from 8 to 16 bits, the index registers are simply extended by padding with zero. When the index registers are changed from 16 bit to 8 bit, the high byte of each index register is lost and forced to zero. On the other hand, the accumulator is actually made up of two 8 bit registers. When changing from 8 to 16 bit, the accumulator's high byte becomes the value in the hidden B register. When moving from 16 to 8 bit, the high byte of the accumulator is forced to zero, but the B register is left intact. Thus, changing from 8 to 16 bit and back to 8 bit won't affect the accumulator, but it will force the high bytes of the index registers to zero.

When using the MVN and MVP opcodes, the size of the index registers make a difference. If set to 8 bits, one can only transfer memory from page 0 of any bank. However, unlike the index registers, MVN and MVP treats the Accumulator as 16 bits wide, regardless of the state of the M flag.

Also, what length the registers are set to determines how many bytes are pulled or pushed during register to stack operations. Remember that when pushing from one location and pulling in another.

To execute emulation mode code in Native mode, simply set all registers to 8 bit widths, load the D register with 0, and load the stack with $01ff. By manipulating the DBR and PBR, you can execute up to 256 emulation mode programs, while at the same time using this method.

In the '816, there is no need to use a register to zero out memory. The "stz" opcode can be used in the same manner as "sta" to zero out memory. Note that, like "sta", stz will store a single or double byte 0 depending on the state of the M flag.

Remember that, when the accumulator is set to 16 bits, the BIT instruction no longer copies bits 6 and 7 to flags in the P register, but bits 15 and 14.

Timing

Beware of absolute long addressing. It takes 1 more byte and 1 more cycle to utilize. Use it sparingly.

In Native mode, there is no penalty for crossing a page in memory. This should allow some programs to actually run faster in Native mode.

BRL can be used at any location a JMP would be used. The advantages include self-relocatable code, but the disadvantages include an extra cycle for execution.

By now, you have noticed that MVN and MVP provide a fast way of moving data areas. However, they can also be used as a fast fill. Simply store the fill pattern into the first address of the memory area, load the X register with the start of the fill area. Load Y with the start plus the length of the fill pattern. Load A with the size of the fill area minus the fill pattern size minus 1. Then, do a mvn h,h, where h is the bank you want to fill. Any size pattern can be used.

Stack Instructions

Many of the added instructions in the 65816 deal with enhanced stack operations. In addition to the S register and accumulator pushes and pulls, you can now programmatically push all the registers except PC onto the stack, and pull all but the PBR and PC register off the stack. Note that some registers have variable sizes, while others are fixed in width. The breakdown is as follows:

Fixed at 8 bits: DBR, PBR, P
Fixed at 16 bits: D, S, PC
Variable: X, Y, A

In addition to using the stack to save and restore data and registers, addresses can now be programmatically pushed to and pulled from the stack. The following opcodes are available:

   f4 34 21     pea $1234   ; Push Effective Address 1234 on stack 
   d4 21        pei ($21)   ; Push Effective Indirect Address at D + $21 
                            ; on stack 
   62 e1 7f     per DATA    ; Push Effective Relative Address on stack 
                            ; when executed, the address PC + $7fe1 will 
                            ; be pushed on the stack.  Useful for 
                            ; determining data area locations in 
                            ; relocatable code 

Transfer and Exchange Operations

When using the accumulator as an 8 bit register, the special hidden B register can be used as a "hidden" register. Move it into focus with the XBA (Exchange B with A) opcode. Note that this is a swap, not a transfer.

Transferring between same size registers in unambiguous. Transfers between different size registers is tricky. If the accumulator is set to 8 bits, only that much can be transferred in, but all 16 bits will be transferred out to any 16 bit register, regardless of the state of the M flag. If an index register is set to 8 bits, only that much will be transferred in or out.

Addressing Modes

Beware of Direct Mode. Any address that can be represented by a single byte will be assembled into Direct Mode. Sometimes, absolute zero page addresses are desired. Use the "!" directive to force absolute addressing.

Beware of Direct Mode II. Remember that zero-page is no more. If you intend to use z-page as before, remember to set D to $0000.

Miscellaneous

This article is presented to new CMD SuperCPU programmers. Whether you write SuperCPU applications in Emulation or Native mode, however, you will find the following information helpful:

The SuperCPU contains a set of registers to control operation of the unit programmatically. These new registers are located in "mirror" locations of the VIC-II (6567/6569) IC. On a stock system, these locations return $ff when read, and writing these locations does not affect RAM under the "mirror" locations while I/O is switched in. These locations are considered relatively "safe" and have been chosen to contain these important CMD SuperCPU registers:

Location   Purpose
---------  --------------------------------------------------
$D074 (1)  GEOS Optimization (mirror VIC bank 2, $8000-$BFFF)
$D075 (1)  VIC bank 1 Optimization (mirror $4000-$7FFF)
$D076 (1)  BASIC Optimization (mirror $0400-$07FF)
$D077 (1)  No Optimization (Default; mirror all memory)

$D07A (2)  Software Speed Select - Turbo Off (1 MHz)
$D07B (2)  Software Speed Select - Turbo On (20 MHz)

$D07E (3)  Hardware Register Enable
$D07F (3)  Hardware Register Disable

Notes:
(1) Write only, hardware registers must be enabled to access location.
(2) Write only, may be accessed with hardware registers enabled or
    disabled, but does not over-ride hardware Speed switch.
(3) Write only.
The first 4 locations specify how much and what areas of RAM will be synchronized between the SuperCPU and on-board RAM images.

These registers have been created using a "sandwich" method that minimizes irregular operation due to memory fills. As such, each register has a "shadow" that falls two bytes away from the register itself. During a memory fill, a fill might turn off fast mode by writing to $d07a, but any access to $d079 or $d07b will turn fast mode back on. This would cause the machine to operate in the wrong state for at most one instruction period. Only one address of each register is documented, as the shadows of each register should not be used for program development.

To utilize the above registers, the programmer need simply to write a value into the appropriate location. In the tradition of CMD, it is not relevant what value is stored at a location. Rather, that a memory write occurred at that location suffices.

In addition to these outlined registers, there are additional "bit- mapped" registers in the VIC-II register map that signal the state of the SuperCPU hardware and software. These flags are read only when hardware registers are disabled, and read write when the hardware registers are enabled. More information about these flags and their locations will be included in the SuperCPU Developer's Guide. Programmers should use and modify these flags with extreme caution.

In addition to the above registers, there are two pages of RAM present at $d200 and $d300 on the SuperCPU. Although this memory is present, it is dedicated for SuperCPU use and should not be otherwise utilized.

Conclusion

Well, there you have it. I am learning something new about this CPU every day, and some of these modes still baffle me. However, I hope that each of you takes an interest in developing '816 applications, as the possibilities are endless. Just when you thought you had the 65XX line all figured out...

C= Hacking Home | Issue 13 Contents


Copyright © 1992 - 1997 Commodore Hacking

Commodore, CBM, its respective computer system names, and the CBM logo are either registered trademarks or trademarks of ESCOM GmbH or VISCorp in the United States and/or other countries. Neither ESCOM nor VISCorp endorse or are affiliated with Commodore Hacking.

Commodore Hacking is published by:

Brain Innovations, Inc.
10710 Bruhn Avenue
Bennington, NE 68007

Last Updated: 1997-03-11 by Jim Brain