Learn Multi platform 6502 Assembly
Programming... For Monsters!
Introduction to the
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
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!
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!
want to set a byte of ram to zero? do it directly with this
we also have BRA
- a branch always command for relative jumps irrespective of
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
Extra commands on the PC Engine 6280
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!
TAM and TMA
|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
|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
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
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)
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
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!
|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
Swapping and clearing registers
|The 6280 has extra commands for transferring data between
registers in a single byte command
swap X and Y
swap A and X
swap A and Y
finally we have CL
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
|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!
command will set the CPU into Slow mode
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
|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
|The T flag allows
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
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
|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
easy... it copies from the source to the destination in
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.
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
because TIA writes all the bytes to two locations the last
Bit level operations
|The 6280 has a wide range of bit
reset (zero) a bit in ZeroPage memory
set a bit of ZeroPage memory
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
test (set the flags) and clear bits bit using the accumulator
and the zero page... bits will be cleared where they are 1 in
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
We also have some new branching commands.
branch if a bit is set (1)
branch if a bit is reset (0)
|The Results of the various bit setting, clearing and testing
operations will be show to the screen!
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 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!
Chibi Akumas V1.666 has taken over 350 hours of development, if you want to support my work, and learn all the secrets of the game's development, please back me on patreon!
Thanks to Homebrew Legends for help promoting my game!
Buy ChibiAkuma(s) games now!