There
are many differences between the port addresses on the
Atari 800 and 5200... most of these were just the hardware
developers being mean, and making sure the software for
the computer and console couldn't be shared... for some reason the PIA is not present on the console... maybe to save cost?... so we'll have to use analog joysticks on the 5200 |
![]() |
Port | Address | Bits & Joystick | |
PIA (800 only) | PORTA | $D300 | RLDURLDU 22221111 |
PIA (800 only) | PORTB | $D301 | RLDURLDU 44443333 |
On the Atari 5200 we need
to read in the analog paddles to get the X-Y position of
the joysticks... we need to read UD and LR, which will
return a value from 0-255.... On the Atari, Top Left of the joystick is 0,0... and Bottom Right is 255,255 |
X-Y Joystick Axis and returned 8 bit values:![]() |
Port | Atari 800 Address | Atari 5200 Address | Purpose | |
POKEY | POT0 | $D200 | $C200 | game paddle 0 |
POKEY | POT1 | $D201 | $C201 | game paddle 1 |
POKEY | POT2 | $D202 | $C202 | game paddle 2 |
POKEY | POT3 | $D203 | $C203 | game paddle 3 |
POKEY | POT4 | $D204 | $C204 | game paddle 4 |
POKEY | POT5 | $D205 | $C205 | game paddle 5 |
POKEY | POT6 | $D206 | $C206 | game paddle 6 |
POKEY | POT7 | $D207 | $C207 | game paddle 7 |
Port | Atari 800 Address | Atari 5200 Address | Purpose | |
GTIA | TRIG0 | $D010 | $C010 | joystick trigger 0 |
GTIA | TRIG1 | $D011 | $C011 | joystick trigger 1 |
GTIA | TRIG2 | $D012 | $C012 | joystick trigger 2 |
GTIA | TRIG3 | $D013 | $C013 | joystick trigger 3 |
Reading the fire buttons is the same on the 5200 (Though the port is different) - but everything else changes, as we now have to parse 'analog' (0-255) values and convert them into movements. | ![]() |
![]() |
Once again, we may
not need both joysticks, and we can disable Joy 2 by not
defining UseDualJoy to save memory In fact the 'Jum52' emulator only seems to support a single joystick, so if you're using that, then there will be no benefit to the extra code for Joy 2 |
![]() |
Lesson
P12 - Joystick Reading on the Apple II The Apple 2 also uses analog joysticks - we'll have to read in the analog values and convert them to digital, so we can use them in our game |
![]() |
![]() JoyTest.asm
|
|
![]() |
On the Apple 2, we'll be using Analog Joysticks... these
return a value for the X and Y axis in a range of 0-100 0,0 is Top,Left.... 100,100 is Bottom,Right We're going to read these in and convert them to Digital Values |
![]() |
||||||||||||||||||
In the Z80 tutorials we used registers HL for reading the
joystick... on the 6502 we'll use Zeropage addresses defined
as z_h and z_l... we'll use one bit per button on the
joystick/joypad for each bit, a 1 means the button is up (unpressed) a 0 means the button is down (pressed) We'll load player 1's joystick data into z_h... and player 2's into z_l |
|
||||||||||||||||||
Our test program is very simple, all it does is read in the two controllers, and show the value of the z_h and z_l to the screen. | ![]() |
Port | Name | Details | Notes |
$C060 | BUTN3 | Switch Input 3 | Bit 7=0 when Down |
$C061 | RDBTN0 | Switch Input 0 / Open Apple | Bit 7=0 when Down |
$C062 | BUTN1 | Switch Input 1 / Solid Apple | Bit 7=0 when Down |
$C063 | RD63 | Switch Input 2 / Shift Key | Bit 7=0 when Down |
$C064 | PADDL0 | Analog Input 0 | Bit 7=0 when Count reached |
$C065 | PADDL1 | Analog Input 1 | Bit 7=0 when Count reached |
$C066 | PADDL2 | Analog Input 2 | Bit 7=0 when Count reached |
$C067 | PADDL3 | Analog Input 3 | Bit 7=0 when Count reached |
$C070 | PTRIG | Analog Input Reset | Reset Analog Count |
Switch 2
isn't easy to use, as it seems to cause another firebutton
to trigger at the same time - and fire button 3 doesn't seem
to work at all! Maybe it's just the emulator used in these tutorials? |
![]() |
![]() |
The Analog
reading code here was based on the example from Understanding
the
Apple II - page 7-24 If you want to learn more about the analog sticks, please see the manual - in fact it's the best resource for all Apple II stuff! |
![]() |
Lesson
P13 - Joystick Reading on the Atari Lynx The Lynx has a digital Joystick, 2 fires, 2 'option' buttons and a pause... Lets learn how to use them! |
![]() |
![]() JoyTest.asm
|
|
![]() |
Bits | |||||||||
Port | Purpose | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
$FCB0 | Joystick | Up | Down | Left | Right | Option-1 | Option-2 | Inner Fire | Outer Fire |
$FCB1 | Switches | - | - | - | - | - | Cart 1 Strobe | Cart 0 Strobe | Pause |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Meaning | Start (Opt1) | F3 (Opt2) | F2 (Inner) | F1 (Outer) | Right | Left | Down | Up |
For some
reason, even if you hold down the buttons, it seems the
Lynx will intermittantly register them as not pressed! It didn't cause any problems for Grime 6502 - but you may need to compensate if you're detecting if a button is held down. |
![]() |
![]() |
The Lynx supports
left handed play - if you press Pause+Option2 together, the
screen and controls should flip... but to support this you'll
have to do it in software... It just depends if you can be bothered to do the programming work to support the 'SouthPaws' ! |
Joypad | Select bit (Bit 0 $1000) |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | CD
addon (1=yes) |
Country (0=jpn) |
- | - | Left | Down | Right | Up |
1 | 0 | CD
addon (1=yes) |
Country (0=jpn) |
- | - | Run | Start | B | A |
2 | 1 | CD
addon (1=yes) |
Country (0=jpn) |
- | - | Left | Down | Right | Up |
2 | 0 | CD
addon (1=yes) |
Country (0=jpn) |
- | - | Run | Start | B | A |
The PC
Engine actually supports 5 joypads, but Joypads 3-5 work
in exatly the same way, we just need to keep reading in
from the same port. |
![]() |
In the Z80 tutorials we used registers HL for reading the
joystick... on the 6502 we'll use Zeropage addresses defined
as z_h and z_l... we'll use one bit per button on the
joystick/joypad for each bit, a 1 means the button is up (unpressed) a 0 means the button is down (pressed) We'll load player 1's joystick data into z_h... and player 2's into z_l |
|
||||||||||||||||||
Our test program is very simple, all it does is read in the two controllers, and show the value of the z_h and z_l to the screen. | ![]() |
![]() |
There are some 6 button joypads for the PC engine - primarily released so Street Fighter 2 could work well on the PC-Engine, but they're rare, and outside the scope of these tutorials... |
Mode | Port | Purpose | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Write | $4016 | Strobe (reset) | - | - | - | - | - | - | - | Strobe |
Read | $4016 | Joypad 1/3 | - | - | - | - | - | Mic | Pad3 | Pad1 |
Read | $4017 | Joypad 2/4 | - | - | - | - | - | - | Pad4 | Pad2 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Right | Left | Down | Up | Start | Select | B | A |
While the
Famicom can support them, We won't be using Pad 3 or 4 in
these tutorials... We also won't be using the Microphone!... of course the Microphone is only supported by the Japanese model anyway. |
![]() |
![]() |
The SNES Hardware |
F | E | D | C | B | A | 9 | 8 | |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | - | - | - | R | L | X | A | Right | Left | Down | Up | Start | Select | Y | B |
Address | Name | Purpose | Bits |
$4218 | JOY1L | Joypad #1 status (set during interrupt) | AXLR---- |
$4219 | JOY1H | Joypad #1 status (if $4200 is set) | BYSTUDLR |
$421A | JOY2L | Joypad #2 status | AXLR---- |
$421B | JOY2H | Joypad #2 status | BYSTUDLR |
$421C | JOY3L | Joypad #3 status | AXLR---- |
$421D | JOY3H | Joypad #3 status | BYSTUDLR |
$421E | JOY4L | Joypad #4 status | AXLR---- |
$421F | JOY4H | Joypad #4 status | BYSTUDLR |
![]() |
You can read from
$4218-$421F just fine - but in these tutorials we try to go
direct to the hardware itself... But it's up to you, you can use the alternates if you prefer! |
In the Z80 tutorials we used registers HL for reading the
joystick... on the 6502 we'll use Zeropage addresses defined
as z_h and z_l... we'll use one bit per button on the
joystick/joypad for each bit, a 1 means the button is up (unpressed) a 0 means the button is down (pressed) We'll load player 1's joystick data into z_h... and player 2's into z_l |
|
||||||||||||||||||
Our test program is very simple, all it does is read in the two controllers, and show the value of the z_h and z_l to the screen. | ![]() |
Address | Purpose | Bits | Detail |
$911F | Port A | R------- | Joystick Right |
$9120 | Port B | --FLDU-- | Joystick Fire,Up, Down, Left |
$9122 | Data direction register B | DDDDDDDD | Direction 0=read 1=write |
$9123 | Data direction register A | DDDDDDDD | Direction 0=read 1=write |
We need to set bit 0 of port B to READ - we do this by
writing 127 to $9122 We also need to read from bits 2-5 of port A... but in practice we don't actually need to set this! |
![]() |
Now we need to read in the 'Right' button... we'll store
this into z_as for later We then set all the bits of z_h and z_l to 1 .... we're only reading in one joystick, so we'll only use z_h |
![]() |
We then read in the other
buttons from $911F, and shift them into z_h one by one We have to insert 'Right' in the correct position form z_as... Once we're done we can just return, though if we want to reset port B back to the correct state, we need to write 255, to set all its bits back to write... This would be needed by the firmware for keyboard reading. |
![]() |
It
should be noted that the VIC can also support an analog
joystick, however it's outside of the scope of these
tutorials, which focus on digital controls. |
![]() |
![]() |
Lesson
P17 - Palette definitions on the BBC In these tutorials we use a common RGB palette definition which uses 1 nibble per color in -GRB format... The BBC only has a fixed 8 color palette, so we'll need to convert those colors via a lookup table, and set them in the hardware, Lets learn how! |
![]() |
![]() |
|
![]() |
In these tutorials we use a fixed definition that uses two bytes per channel, we'll use one nibble to define each color, and we'll have to map these colors to the 8 colors the BBC is capable of | ![]() |
Our palette definitions contain 4 nibbles... the first is
unused (0)... the second is the Green component, the third is
Red, and the last is Blue... This was based on the format used by the CPC+, and has become the standard for these tutorials. |
![]() |
In these tutorials we'll define
a function called 'SetPalette'... it takes two parameters... A will contain a palette number (0= background)... on the BBC the maximum valid palette entry will be 3 zero page entries z_h and z_l are a two byte pair containing the color definition we want the color to have... this will be converted according to the capabilities of the hardware |
![]() |
On The BBC we use the
ULAConfig to set the palette, we saw this before when we
looked at setting up the bitmap screen. We have to set the
bottom nibble of 4 bytes per color, then send all the bytes to
the hardware, It's confusing and doesn't look very logical, but it works! |
![]() |
We need to send 16 bytes to
the hardware to map the bitmap data in Ram to the Colors the
screen will show. Each Color 0-3 uses 4 bytes... The top Nibble is the Bitmap data color, we should leave it alone! The bottom Nibble is the palette color, this is what we want to change. |
![]() |
We need to send the 16 bytes to the ULA hardware, at port $FE21, this will update the color information for the visible screen. | ![]() |
![]() |
This code
will set the colors on ALL the systems in our 6502 tutorials
(where colors can be set!).... In fact, the -GRB color definitions in this example also work on the Z80 and 68000 systems in these tutorials - so you don't need to recalculate your palette when porting your game from one system to another! |
We're going to use a 3x3x3
lookup table to convert the colors, this will be stored in
ram, and we'll use the formula Offset=(G*9)+(R*3)+B to calculate the color of the equivalent GRB color for the BBC |
![]() |
When we call our SetPalette
function, we set A to the palette entry, and z_h and z_l as
the word defining the new color (in $-GRB format) In the mode we're using, The BBC only uses 4 colors, so we'll skip any colors 4 or above. We then want to calculate the palette entry, using the formula we just mentioned... We're going to use two functions One is 'PalcolConv' - which will take a high nibble, and convert it to a value 0-2.... The other is PalConvR - which will take the low nibble and do the same.... Once we've calculated the offset, we store it into Y |
![]() |
We're going to use that calculated offset, read the entry from the palette map, and store it into z_b | ![]() |
Now we need to update the 4 entries of the 'ULAconfig' in ram that define that color... first we need to calculate the offset in that data, then we need to load z_hl with the pointer to the start of that config. | ![]() |
We need to process all 4 bytes
of the config... we need to keep the top nibble, but set the
bottom nibble to the value we got from the lookup table. We repeat 4 times... finally we call SendULA to update the graphics hardware with the updated ULAConfig Our palette change is done! |
![]() |
Our palette conversion routines
use the following RGB conversions to convert a nibble to a
value 0-2 0-4...0 5-9...1 10-15...2 |
![]() |
The SendULA
command is doing the work of transferring the colors to the
hardware... If you want to see how this command works, please see Lesson P1 from the tutorials |
![]() |
![]() |
Lesson
P18 - Palette definitions on the Atari 800 / 5200 The Atari 5200 and 800 have a limited palette that doesn't easily convert from RGB... We're going to use the same 'look up table' functions as we did on the BBC to covert our $-GRB color to a usable palette number. |
![]() |
![]() BmpTest.asm
|
|
![]() |
xF | 0F | 1F | 2F | 3F | 4F | 5F | 6F | 7F | 8F | 9F | AF | BF | CF | DF | EF | FF |
x8 | 08 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 | 98 | A8 | B8 | C8 | D8 | E8 | F8 |
x0 | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | A0 | B0 | C0 | D0 | E0 | F0 |
Name | Description | Address A80 | Address A52 |
COLPF0 | Color/brightness of setcolor 0 | $D016 | $C016 |
COLPF1 | color/brightness of setcolor 1 | $D017 | $C017 |
COLPF2 | color/brightness of setcolor 2 | $D018 | $C018 |
COLBK | color/brightness of setcolor 4 | $D01A | $C01A |
![]() |
The We're
going to have to convert our GRB values to the Atari
palette... there won't be a 'perfect' mapping, but at least
we'll have something to start from... The reason we're doing this is to allow us to write multi platform code easily... you can always use an alternative mapping, or directly access the hardware for the Atari if these mappings don't suit your games needs |
We're going to have to convert our 'ideal' GRB values into the nearest match for the Atari hardware. | ![]() |
Our palette definitions contain
4 nibbles... the first is unused (0)... the second is the
Green component, the third is Red, and the last is Blue... This was based on the format used by the CPC+, and has become the standard for these tutorials. |
![]() |
In these tutorials we'll define
a function called 'SetPalette'... it takes two parameters... A will contain a palette number (0= background)... on the BBC the maximum valid palette entry will be 3 zero page entries z_h and z_l are a two byte pair containing the color definition we want the color to have... this will be converted according to the capabilities of the hardware |
![]() |
We're going to use a 3x3x3
table of color conversions to convert our one nibble per
channel $-GRB definition to something valid for the Atari Offset=(G*9)+(R*3)+B to calculate the color of the equivalent GRB color for the BBC |
![]() |
When we call our SetPalette
function, we set A to the palette entry, and z_h and z_l as
the word defining the new color (in $-GRB format) In the mode we're using, The Atari only uses 4 colors, so we'll skip any colors 4 or above. We then want to calculate the palette entry, using the formula we just mentioned... We're going to use two functions One is 'PalcolConv' - which will take a high nibble, and convert it to a value 0-2.... The other is PalConvR - which will take the low nibble and do the same.... Once we've calculated the offset, we store it into Y |
![]() |
Now we've worked out our offset, we can read in the new color definition from the palette | ![]() |
We need to work out the correct
address to write to within the GTIA ($D016-D01A on the Atari
800 or $C016-C01A on the 5200) Color 0's address is $D01A Color 1's address is $D016 Color 2's address is $D017 Color 3's address is $D018 Once we've calculated the palette address to write to, we just output the new color we got from the lookup table to the destination address |
![]() |
Our palette conversion routines
use the following RGB conversions to convert a nibble to a
value 0-2 0-4...0 5-9...1 10-15...2 |
![]() |
It's
important to note that there may be discrepencies in the
exact colors depending on if the system is NTSC or PAL If you have problems, you can always use an alternative look up table for NTSC systems. |
![]() |
![]() |
Lesson
P19 - Palette definitions on the
Atari Lynx Despite being a handheld, the Lynx is graphically very powerful! With a 4 bit per channel RGB palette, we've got a great range of colors! Lets learn how to set the 16 colors of the Atari Lynx |
![]() |
![]() BmpTest.asm
|
![]() |
From | To | Name | Bits |
FDA0 | FDAF | Green � Colors (0-15) | -----GGGG |
FDB0 | FDBF | Blue/Red � Colors (0-15) | BBBBRRRR |
In these tutorials we use a common format on all systems - one nibble per channel in -GRB format... so all we need to do is convert that to -GBR format | ![]() |
Our palette definitions contain
4 nibbles... the first is unused (0)... the second is the
Green component, the third is Red, and the last is Blue... This was based on the format used by the CPC+, and has become the standard for these tutorials. |
![]() |
In these tutorials we'll define
a function called 'SetPalette'... it takes two parameters... A will contain a palette number (0= background)... on the BBC the maximum valid palette entry will be 3 zero page entries z_h and z_l are a two byte pair containing the color definition we want the color to have... this will be converted according to the capabilities of the hardware |
![]() |
Because our source, and the
destination use 4 bits per channel our job is easy! We use zero page entry z_bc as a temp store for the address we're going to write to, we're going to write the Green part first, which goes in address $FDA0-$FDAF The number of the palette entry (0-15) was in A, but we store it in Y, so we can use it as an offset... First we write the Green part (in the lower nibble ----GGGG) from z_h... Next we change z_b to z, as we need to write the Red and Blue parts to ($FDB0-$FDBF) We want to write these from z_l, but they're in the wrong order, so we call SwapNibbles to swap RRRRBBBB to BBBBRRRR... |
![]() |
![]() |
Lesson
P20 - Palette definitions on
the PC Engine (TurboGrafx-16) The PC Engine uses 3 bits per color, and has a huge 512 onscreen colors! This is split up, 256 are used for background tiles, and 256 are used for Sprites! |
![]() |
![]() BmpTest.asm
|
![]() |
|
|
Our palette definitions contain
4 nibbles... the first is unused (0)... the second is the
Green component, the third is Red, and the last is Blue... This was based on the format used by the CPC+, and has become the standard for these tutorials. |
![]() |
In these tutorials we'll define
a function called 'SetPalette'... it takes two parameters... A will contain a palette number (0= background)... on the BBC the maximum valid palette entry will be 3 zero page entries z_h and z_l are a two byte pair containing the color definition we want the color to have... this will be converted according to the capabilities of the hardware |
![]() |
These
Tutorials use a 34 bit per channel color definition, but the
PC Engine uses only 3, therefore 1 bit will be unused. It's a bit of a waste, but it means we can write code that works on all the systems more easily. |
![]() |
![]() |
In these examples we're going to set
Sprite and Backgroudn colors together, so we'll set palette
entry 0 and 256 at the same time... This will help make things easier for us when it comes to using sprites -which we'll do later! |
On the PC Engine, We'll only be using the 3 of 4 bit
definition, and we'll need to shift some of the bits around. To make using Hardware Sprites easier later, we'll also set the Sprite colors at the same time as the background ones |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
When we call SetPalette, A is the color number, and z_hl is
the color in -GRB format. We're going to set the Background (0-255) and Sprite (256-511) colors at the same time, so we're going to set two palette entries at the same time.. We set X to A... and Y to Zero (using CLY a special HuC6280 command) and set the background color... Then we set Y to 1 via inc... and set the equivalent sprite color! |
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
To select the palette entry we
want to change we write the low byte (now in X) to $0402, and
the high byte (in Y) to $0403 We now need to move all our bits around, we need to take 3 of the 4 bits of each color channel, and reposition them, Once the data is now in the correct format, we write the low byte to $0404, and the high byte to $0405 |
![]() |