Learn Multi platform 6502 Assembly Programming... For Monsters!

Advanced Lessons

Introduction to the Advanced Series...
In the advanced series, we'll cover topics you may never need, but are important fundamentals of the processor all the same... this will include rare commands, tricks and commands added to later revisions of the 6502

Lesson A1 - Extra commands in the 65c02 (Snes,Lynx & Apple II) and 6280 (PC Engine) processor

The 6280 has some special commands we need to understand if we're going to write PC engine games... and the 65c02 has some extra cool stuff you may want to use... we won't use them very often, but the 6280 ones are essential to programming the graphics hardware of the machine!
Lets see what 'Special Stuff' is on offer to us!...


Extra commands on the 65c02!
We have various new commands we can check out!

INC and DEC... no need to use adc to increment or decrement the accumulator any more, we can do it directly!

PHX,PLX and PHY,PLY.... no need to transfer the index registers to the accumulator to get them on the stack, we can now do it directly!

STZ .... want to set a byte of ram to zero? do it directly with this command!


we also have BRA - a branch always command for relative jumps irrespective of flags..

As well as new commands, many existing commands have new addressing mode options, check out the Cheatsheet to see the details!
as shown in the example, we can now push and pop X and Y (we used it to swap them over)... we can also inc A directly... and we cleared a byte of the zero page with STZ
Some Commands on the 6280, like BBR,BBS SMB and RMB also exist on SOME 65c02 processors but when tested they don't work on the Apple II or Lynx - so you're going to have to do without them on those systems, but you may see them in your 65c02 documentation - so be careful!

Extra commands on the PC Engine 6280
As well as the 65c02 stuff, the 6280 has a TON of special new commands, you probably don't many of then, but they're possibly a real time saver, and can do things MUCH faster - especially as some are really designed around the PC-Engine hardware

TAM and TMA

The PC engine uses an effective 21 bit memory map...  13 bits of the address specified, and 8 bits from the MPR register
The topmost 3 bits are mapped through a Memory Management unit which maps to Ram/Rom or hardware

This is all a bit confusing, but it's really pretty easy
This Memory management unit has 8 registers, each of which handles a range of $2000 of the memory map, and a bank from $00-$FF... $FF is the hardware I/O ... $F8 is the 8k of basic ram... $00 is the first page of your cartridge rom.

To page in a bank, we need to specify it by 'bit position' (so bank 7 has bit 7 set... so 128)
we load A with the bitmask for that MPR, then use the special command TAM (transfer A to MPR)

eg: - lets load bank $F8 into MPR page 1 ($2000-$3FFF)
    lda #$F8  ;ram bank
    TAM #2   ;bit 2 for bank 2 (%00000010)

NOTE: The ZeroPage is at $2000 , and the Stack is at $2100 ... this is unaffected by the MPR's.... this causes problems in VASM, where if  we try to write STA $0000 ... the assembler will optimize it to STA $00


MPR Setting From To MPR Page
0 1 $0000 $1FFF $FF (I/O)
1 2 $2000 $3FFF $F8 (RAM)
2 4 $4000 $5FFF ????
3 8 $6000 $7FFF ????
4 16 $8000 $9FFF ????
5 32 $A000 $BFFF ????
6 64 $C000 $DFFF ????
7 128 $E000 $FFFF $00 (Card Rom)
TAM allow us to set  the memory Mapper...
we just load the bank into A, and set a bitmask for the banks we want to switch (each bit is a different MPR bank)

TMA reads back the current memory mapper segment.


when we use TAM with bit 2 set, we're switching the $4000-5FFF range -

First we've switched in the cartridge,

Next we switched in the ram area (&F8) in this example... then we pulled back the current setting with FMA - and showed it to the screen with the monitor

ST0, ST1 and ST2 - for accessing graphics hardware on the PC Engine
when we want to write bytes to VRAM, we need to use 3 registers to control the hardware...

The first selects a video register, the second and third set or return the L and H bytes for that register....

The Most common ones we'll use are Reg 0 - to select an address, and Reg 2 - to write data to that address.

IO registers are mapped to the $0000-1FFF range... they repeat throughout this range, but using $0000-$0003 will cause problems as VASM will think they are the zero page, so we'll use $0100-$0103 instead...

However... rather than writing to these memory locations via the accumulator, in many cases we'll want to use ST0, ST1 and ST2 to set these to fixed values quickly!
Memory address Command  Purpose
$0?00 ST0 xx Select Register xx
$0?02 ST1 xx Reg Val L=xx
$0?03 ST2 xx Reg Val H=xx
We're going to write some bytes into the tilemap... at VRAM $0000... each byte pair will set one tile of the map... each line of the tile map uses 64 bytes, as each address contains 2 bytes, the next line will start at $0020 (address 32)


When we want to select a memory address.. .we need to select Reg 0 (address select) with ST0... then we write the Low byte of the address with ST1... then the High byte with ST2

We've selected our address, now we want to write our data to it

Our font starts from pattern 256... 256+1 is the '!' symbol

we select Reg 2 (data write) with ST0 .... then we write the Low byte with ST1 (1)... and high byte with ST2 (1 = 256)

The address autoincs, so we can write a second byte easily...


Of course we don't HAVE to use ST0,ST1 and ST2...  We can access them any time from $0100,$0102 and $0103

In fact, we can access them from ANY address space if we map the IO registers in using TAM with bank $FF (IO)
Our characters will be show to the screen...

Depending on the address, we can set tiles...define patterns, and using other registers, we can change the tilemap position and other graphics operations

TAM and ST? are pretty much essential to PC-Engine programming, however the other commands are less essential, because we're programing for multiple systems in these tutorials, we won't really be using them much - but if you want the fastest, most efficient code, you'll want to know about them!

Swapping and clearing registers
The 6280 has extra commands for transferring data between registers in a single byte command

SXY will swap X and Y

SAX will swap A and X

SAY will swap A and Y

finally we have CL and CLY to quickly clear the registers
We could achieve the same effect with 2 byte commands, but if we're only compiling for the PC-Engine, these commands will be the best option

Speed Changes

The 6280 CPU can run in 2 different speed modes 1.78 and 7.16... we'll probably want to just run in full speed... but as there was a hand-held version of the PC-Engine, there may be times you would want to slow down the CPU to make the battery last... or you could slow the CPU if your game is too fast!

the SCL command will set the CPU into Slow mode

the CSH command will set the CPU into Fast mode

We're going to create a program that draws characters slowly (via a delay loop) to the screen, and we'll repeat the process in both modes to see the difference!
The image shown won't demonstrate the effect...

You're really going to have to check out the video or download the example to see this one!

The T flag!
We can use SET to set the 'T flag' a flag unique to the 6280

The T flag is a bit special... it allows us to use the commands ADC, AND, EOR, ORA and SBC...

But rather than these commands affecting the accumulator they will affect the zero page address contained in the X register.

Only the next ONE command will be affected - the T flag is immediately turned off again - the purpose of the command is  it allows us to use these commands, and leave the Accumulator unchanged!
In this example we've loaded $60 into Zeropage $00, we've set A to 0

we do an ADC #1 after SET turned on the T flag
because the T flag is on  X is 0 this makes the ADC change the Zero page entry $00... and A is unchanged

because the T turns itself off... the second ADC #2 actually affects the accumulator...

Next we increment X, set the T flag again with SET, and do ADC #2... because X is now 1, Zero page entry $01 is changed this time.
The T flag allows us to use accumulator like commands directly on the zero page, but we're effectively adding a byte to the length of the command, and we need X to be pointing to the right zero page entry.

There may be times this is useful when you need to keep the accumulator, or if you want to alter a range of zero page entries in a loop

Bulk copying with TII,TDD (like LDIR), and special copying with TIN and TIA
These commands are used for bulk copying (like LDIR on the Z80) all these commands take the same 3 parameters... for example TII:

TII source,destination,byte count

TII is easy... it copies from the source to the destination in ascending order.

TDD is similar... except Source and Destination are the END of the range to copy

TIN is a bit odd... all the source bytes are copied to the SAME destination - why would you want to do this? Well, we can use this to stream data to an IO port.

TIA is also odd... it writes the bytes, alternating to a pair of addresses - Destination and Destination+1... this can be used to fill the VRAM using the pair

Unfortunately , these commands always work with fixed ranges, not specified by the Zero page or registers.
We can see the results here...

The first TII command fills the range,

The TDD clears it - there's no visible difference in this case - but the command worked backwards

because TIN writes all the bytes to one location only the last remains

because TIA writes all the bytes to two  locations the last two remain

Bit level operations
The 6280 has a wide range of bit testing commands:

RMB will reset (zero) a bit in ZeroPage  memory

SMB will set a bit of ZeroPage memory

TSB will test (set the flags) and Set bits bit using the accumulator and the zero page... bits will be set where they are 1 in the accumulator

TRB will test (set the flags) and clear bits bit using the accumulator and the zero page... bits will be cleared where they are 1 in the accumulator

TST takes two parameters, one is a bitmask, the other is an address - this command can use the Zeropage with or without offset, or an absolute address... the Z flag is set as the result of an AND command


We also have some new branching commands.

BBS will branch if a bit is set (1)

BBR will branch if a bit is reset (0)

The Results of the various bit setting, clearing and testing operations will be show to the screen!

As we've seen, the 6280 has lots of special commands that non of the other 6502 machine have... in fact most of them aren't even on the 65816!

The 6280 was a powerful custom chip for the PC-Engine, and along with the graphics hardware for the machine was mistaken for a 16 bit machine!