Atari Project

SPECIFICATION

NSCAD INTERNAL DOCUMENT

GABRIEL Oshiro Zardo

SAMUEL Nascimento Pagliarini

Date: Feb 2009

Rev: 1.1

Index

Index	2

List of Figures	3

List of Tables	4

Document versions	5

Acronyms	6

Overview	7

RTL Design	8

Modular Design	8

Synchronous Design	8

Original ATARI	9

6507 CPU	9

RIOT Chip	10

TIA Chip	10

Bus Controller	11

Clock Generator	11

Video and Audio Output	12

Game Cartridge	12

System Design Overview	13

USB or EPROM	14

Bus Controller	15

Keyboard interface	16

RIOT	17

RAM	18

TIMER	18

I/O	18

References	19

Attachment 01 – 6502/6507 OPCODES	20

Attachment 02 – 6502/6507 Addressing Modes	25

Attachment 03 – Original TIA Pins and Registers	27

Attachment 04 – RIOT Registers	30

List of Figures

Fig. 1: Synchronous system	8

Fig. 2: Original ATARI block diagram.	9

Fig. 3: New Atari system design	13

Fig. 4: ROM block diagram.	14

Fig. 5: Bus controller block diagram.	15

Fig. 6: Keyboard controller block diagram.	16

Fig. 7: RIOT block diagram	17

Fig. 8: TIA pins	27

List of Tables

Tab. 1: Document versions.	5

Tab. 2: ROM signals description.	14

Tab. 3: Bus controller signal description	15

Tab. 4: Keyboard controller signals description	16

Tab. 5: RIOT signals description	17

Tab. 6: TIA pins description	28

Document versions

Version Number	Date	Author	Summary of Changes
1.0	19 FEB 2009	Gabriel and Samuel	First SPEC version. Contains all the original ATARI blocks and theirs descriptions.
1.1	02 MAR 2009	Gabriel and Samuel	Several changes to reflect the new proposed ATARI system. New block diagram developed.

Tab. 1: Document versions.

Acronyms

ASIC	Application Specific Integrated Circuit
CPU	Central Processing Unit
FPGA	Field Programmable Gate Array
FSM	Finite State Machine
I/O	Input / Output
NTSC	National Television System Committee
PAL	Phase Alternate Lines
PLL	Phase-locked Loop
PS/2	Personal System/2
RAM	Random Access Memory
RIOT	RAM-I/O-Timer
RISC	Reduced Instruction Set Computer
ROM	Read Only Memory
RTL	Register transfer level
SoC	System on Chip
TIA	Television Interface Adapter
VGA	Video Graphics Array

Overview

The Atari 2600 is a computer system from the early 1980s. One of the first gaming consoles, it provides an interesting look at early hardware architecture and programming for a system with limited resources. However, few working units of the original hardware are available today, preventing easy access to the system. Furthermore, any schematics and design details for the system use outdated design methodologies and refer to obsolete hardware, making it hard to reconstruct a working system using them.

This project goal is to redesign an Atari 2600 using functional descriptions of the parts and blocks. Several software-based solutions (emulators) are available but for a truly rebuild of the system, a hardware design is necessary.

This is where our project differentiates from others: an entire system on chip (SoC) will be designed, one that simulates all the original Atari 2600 console, not only its microprocessor. In parallel with the intrinsic design challenges, this projects also aims at creating a documentation that may be used as a true guidance for further projects, documentation which should be available on the Internet presented as a Wiki.

RTL Design

The design is implemented using industry standard hardware programming languages, tailored to run either on prototyping hardware or as a standalone ASIC chip.

Modular Design

This project is made up of a number of logical modules, with a top level module which connects all the lower level modules. Each module has its own functionality and can operate independently of the others, giving the system a hierarchical structure and making it easier to understand. Modules can be reused and also exported for use as part of other projects. This also allows for a structured testing process where a verification test suite can be made for each module, supplying it with test inputs and checking for the correct outputs.

Synchronous Design

Most digital circuits designed today in computer systems follow the technique of synchronous design. The idea behind the technique is to reduce the entire system to a state and logic to update the state. The update logic can include inputs to the system, and output logic uses the current state to create the outputs. The resulting state machine (FSM) can be analyzed, verified or simulated in order to obtain the correct outputs.

Fig. 1: Synchronous system

A diagram of a synchronous system is shown above. A global clock signal is distributed throughout the system and used to signal all updates. The state is kept in registers, and updated on every edge of the clock signal. Synchronous design simplifies the timing analysis of the system. The maximum clock speed can be determined from the amount of time the update logic takes to resolve (although not applicable for this project since we must comply with very strict clock speeds).

Original ATARI

A block diagram view of the original ATARI 2600 system is shown below:

Fig. 2: Original ATARI block diagram.

The Atari 2600 had three main modules: the TIA chip which generates audio and video, the RIOT chip which contains the RAM and timers, and the 6507 CPU. All three modules share common data and address busses which can also connected via a header to an external cartridge ROM. The CPU controls the address bus, using it to address the cartridge ROM, the RAM, and various functions on the modules like memory mapped I/O. All modules have an input and output data line connected to the bus controller, which makes the correct connections between them according to the address. Also, the default audio and video outputs are represented.

6507 CPU

The 6507 is a budget version of the widely used MOS6502 CPU from the MOS Technology corporation. The 6502 processor is an 8-bit RISC processor that features an accumulator, two general purpose registers, a stack pointer, and many different addressing modes optimized for different situations. It has the ability to address 64 kilobytes of memory and supports both maskable and non-maskable interrupts. An enable control allows the CPU to be halted. The 6507, on the other hand, can only address 8 kilobytes of memory and cannot respond to interrupts.

Instructions are variable length, consist of an opcode and possibly an immediate value, and can be 1 or 2 bytes long. One interesting feature of the processor is that it has over 100 undocumented opcodes, many of which vary depending on the manufacturing specifics of the chip. These opcodes were used by Atari programmers to pack multiple operations into a single instruction.

Check the attachments 01 and 02 for the opcode listing and a complete address mode definition.

RIOT Chip

The RIOT chip, or MOS Technology’s 6532, contains the Atari’s RAM, timers, and partial I/O system. Communication with the CPU is done via an address line and data line. There are 128 bytes of RAM on the chip, all of which can be read from and written to.

In addition there are 16 I/O lines, each of which can be set as an input or output using an I/O direction register. An I/O data register is then used to either set the output levels or read the input levels. One of the I/O lines can be used to detect input level edges and signal an interrupt. Finally, the chip contains a counter and status register. The counter’s update is tied to the input clock, but can be prescaled by 1, 8, 64, or 1024 counts. The clock is continuously running, but can be reset by preloading it with a count. When the count hits 0, an interrupt is signaled and a flag in the status register is raised.

TIA Chip

The TIA chip, a custom chip from Atari, provides the Atari’s sprite and video generation, sound generation, and extra I/O capabilities. Access to the TIA chip is done using the shared address bus and data busses. Like the RIOT chip, the function of the chip is selected by the address. Most addresses access registers that change the TIA behavior, while a few trigger events when the address is strobed or written to.

The video generator is effectively a shift register that can be loaded in parallel with the screen objects. Video lines loaded into the TIA are constantly sent out to the display at the correct speed, along with the horizontal sync signal needed to synchronize the display to the video signal. Vertical sync signals must be manually triggered by the Atari programmer as well as vertical blank signals.	The Atari creates frames that are 160x192 pixels with 68 pixels of horizontal blanking per line, 40 lines of vertical sync and vertical blank per frame, and 30 lines of overscan per frame. Screen objects can include two 8 pixel wide sprites, a ball, two missiles, and a background image or playfield. For every scanline the Atari programmer loads single line sprite slices, ball and missile graphics, and a slice of the playfield into the TIA for each line. The ball and missile graphics are picked from a list of preset graphics. The position of each of these objects on the scanline can be changed, as well as their colors and ordering. The graphics can be stretched and duplicated, while the playfield can be reflected. Also, a delay bit allows graphics to be loaded but delayed to the next scanline.

The TIA performs collision detection between all the screen objects. If two objects are drawn on the same pixel, a specific bit in the collision latch is set to high depending on what layers the two objects are on. The collision latch register can be read by the programmer to check for collisions.

Another feature the TIA provides is synchronization control. Synchronizing the CPU with the video output is very important to proper execution of the software. The main method the TIA provides is to halt the processor until the beginning of the next scanline. An Atari programmer triggers this by strobing the WSYNC address, after which they can be guaranteed that the next instruction executed corresponds to the next scanline.

The TIA provides two special types of I/O ports for specific purposes. The first are the two latched input ports, which latch to a low input until they are reset to high. These are used for the controller button inputs, so the programmer can check if the user pressed a button even if the button was not held down. There are also two dumped inputs, which are normally pulled to logic low internally in the TIA. When they are triggered by the programmer, the pull-down is disconnected allowing the line to be pulled externally to logic high. The level of the line can then be read, allowing the programmer to check how long it takes for the line to be pulled high and effectively determine the capacitance on the port. This is used for to determine the state of a paddle controller connected to the port, as the paddle consists of variable capacitor connected to a knob.

Bus Controller

In the original Atari, all the chips used the same data bus for reading and writing with the help of tri-state buffers that removed their connection to the bus if they were not being addressed.

Clock Generator

Execution of the Atari code and video generation rely on steady and accurate global clocks. This is because the software written for the system is timed on a cycle by cycle basis, with programmers required to count cycles when writing the code. For example, the Atari video kernel is run in software, requiring exact synchronization with the NTSC clock to display video on the screen.

The system is driven by two separated clocks: a 3.58 Mhz “pixel clock” and a 1.19 Mhz bus clock. The pixel clock runs at NTSC speed, running the video generator and pixel counter. The bus clock runs the CPU, the bus communications, and all the module operations.

Video and Audio Output

The original video output was done in either PAL or NTSC, aimed for televisions. Both formats required exhaustive synchronism between the system and the television, requiring special hardware and code organization. Since none of these formats will be implemented, it is not in the the scope of this project to explain such synchronism.

The audio output was done using a mono noise tone generator. The TIA chip had to set several registers (sound volume, frequency, pattern) to successfully create an audible sound. Again, it is not in the the scope of this project to explain such patterns. As for now the register functionality will be kept for maintaining compatibility but no sound generation system was thought of.

Game Cartridge

The basic Atari software cartridge is a simple addressable ROM chip containing 2 kilobytes or 4 kilobytes of memory, the largest amount of contiguous memory addressable using the address lines. As the Atari got more mature, companies started packing more into the cartridge including extra memory that could be bank switched, more RAM, or even special processing units. Bank switching allows the Atari to address more memory by separating the memory into 4 kilobyte banks, then specifying a special address that can be used to switch the banks into the main address space. Using this method, as much as 128 kilobytes of data were fit into a single Atari cartridge, though only 4 kilobytes were accessible at a time.

System Design Overview

A full project block diagram is shown below:

Fig. 3: New Atari system design

The main differences are listed:

Controllers: Will be replaced by a PS/2 keyboard.

Clock generator: Will not be necessary anymore. The original ATARI used two clock frequencies, one for the system itself and one for the NTSC or PAL TV output. There will be only one master clock, set at 1.193182 MHz.

TIA and its outputs: The TIA chip contains analog and RF sections. These sections will not be available in our design. The default NTSC output will become a VGA output. The digital section (collision handler, drawings and audio registers) will be kept. The sound related sections will be removed for now.

Cartridge: The original cartridges are hard to find and hard to interface/test. When testing on FPGA the USB port may be used to emulate the cartridge ROM and on a final design an programmable EPROM could be used.

All the above blocks are described in detail in the following sections. Also, they are presented in the same manner they will be coded. Some raw programming times are also presented.

USB or EPROM

This block emulates the cartridge ROM. It should provide the software (game) to the system. A more detailed view of the block is shown below:

Fig. 4: ROM block diagram.

Signal Name	Direction	Description
enable	input	Enables the chip.
clock	input	Master clock at 1.19Mhz
address	input	System address bus.
data_out	output	The data being read output.

Tab. 2: ROM signals description.

Either one of the blocks should be enabled, but not both. An #ifdef directive should handle the usage. Since the preliminary goal is to prototype using a FPGA then the USB handler will be developed first.

The USB handler should provide to the system the same addressing the original Atari 2600 used or it should perform the necessary changes within itself (in the original Atari 2600 the ROM was mapped in the E000-FFFF address range). In another words, it should work as a wrapper.

Estimated development time: one week.

Possible drawbacks: If the address translations becomes necessary maybe the estimated development time is inaccurate. Also, possibly each FPGA has it's own USB handling procedure, which will make the task more difficult since no default handshake exists.

Bus Controller

This block is responsible for connecting the other blocks. A more detailed view of the block is shown below:

Fig. 5: Bus controller block diagram.

Signal Name	Direction	Description
clock	input	Master clock at 1.19Mhz
address	input	System address bus.
cpu_data_out	input	The data output from the CPU.
riot_data_out	input	The data output from the RIOT block.
video_data_out	input	The data output from the VIDEO block.
data_out	output	The muxed data that will become either cpu_data_in, riot_data_in or video_data_in

Tab. 3: Bus controller signals description

A single address bus is used, strictly controlled by the CPU. For the data signals there is more than one bus merely for simplicity. The original Atari had tri-state busses for such task but in our design these will be suppressed.

The coding of this block is quite simple: it is a multiplexer controlled by the address signal.

Estimated development time: one day.

Possible drawbacks: none.

Keyboard interface

This block is responsible for emulating the joysticks and switches of the original console by mapping it to a keyboard (PS/2). A more detailed view of the block is shown below:

Fig. 6: Keyboard controller block diagram.

Signal Name	Direction	Description
keyboard_in	input	The keys pressed on the keyboard.
riot_io_lines	output	Signals that will raise the I/O latches on the RIOT block.

Tab. 4: Keyboard controller signals description

The FPGA only provides the PS/2 connector. All the key translation and debounce must be coded (at least this is true for the Spartan 3). Being so, the FPGA and ASIC versions are more alike which is good for reducing the project complexity. Since this coding may be complex (the PS/2 is a serial port), the keyboard controller could be simplified and transformed into a DIP-Switch or original Atari controller wrapper.

Estimated development time: four days.

Possible drawbacks: Serial port complexity. Translating keys may not be trivial.

RIOT

This block contains the system RAM and timer. It also handles the console switches and controllers. A more detailed view of the block is shown below:

Fig. 7: RIOT block diagram

Signal Name	Direction	Description
clock	input	Master clock at 1.19Mhz
riot_io_lines	input	Signals that will raise the I/O latches on the RIOT block.
address	input	System address bus.
data_out	output	Output when a read operation occurs.

Tab. 5: RIOT signals description

Each of the RIOT original chip functionalities is represented by a different block: RAM, TIMER and I/O. All these blocks have some complexity therefore they will be described separately:

RAM

This is the main system memory. Its a 128 byte wide RAM memory, addressed from HEX 80 to FF. It will be implemented as a array of registers. Further in the project it must be redesigned using the XFAB memory compiler utility.

Estimated development time: three days.

Possible drawbacks: Memory access timing issues.

TIMER

The RIOT timer is quite simple. It contains some registers that allow the user to count in multiples of 1, 8, 64 or 1024 clocks. It also contains a register to read the timer and a register that signal if the counter reached zero.

Estimated development time: three days.

Possible drawbacks: None.

I/O

This is the block responsible for receiving the inputs from the player, either from the original joystick or the console switches. It contains a series of registers that are read and written by the CPU. Also, the original Atari console supported a keyboard and a paddle controller. Both controllers internal registers must be kept and correctly handled although the controllers will not be functional.

Estimated development time: three days.

Possible drawbacks: Some registers receive a special treatment using a Data Direction Register (DDR).

CPU

This block contains the system CPU, which is basically an ALU and a FSM for the control logic. There are also some registers like PC, SP, etc.

The 6507 is a simple 8-bit CPU in which an instruction can take from 1 to 5 cycles to execute, as the processor is able to overlap an instruction fetch and execution. Instructions are variable length, consist of an opcode and possibly an immediate value, and can be 1 or 2 bytes long.

Fig. 8: CPU block diagram.

Signal Name	Direction	Description
clock	input	Master clock at 1.19Mhz
data	inout	Data from or to bus controller.
address	output	System address bus.

Tab. 6: CPU signals description.

FSM

This is the control logic for the CPU. It must handle all the different addressing modes and must be cycle accurate with the original 6507.

Estimated development time: 10 days.

Possible drawbacks: Cycle accuracy. Pipelining.

ALU

This is the arithmetic and logic unit. It is responsible for executing the operations.

Estimated development time: 10 days.

Possible drawbacks: None.

VIDEO

This block contains the system video generation and a module for compatibility with the old TIA chip.

Fig. 9: VIDEO block diagram.

Signal Name	Direction	Description
clock	input	Master clock at 1.19Mhz
address	input	System address bus.
data	inout	Data from or to bus controller.
video_out	output	Video output in VGA format.

Tab. 7: VIDEO signals description.

OLD_TIA

The old TIA chip must be “emulated” because the system needs several of its features, such as the collision detection and the extensive register bank. Although several register are necessary for the NTSC format they will be kept to avoid compatibility issues.

Estimated development time: 10 days.

Possible drawbacks: The TIA chip originally run at a higher clock. In our system the clock will be the same as the CPU therefore the WSYNC operation must be properly handled.

VGA

The proposed video output is strictly VGA. Therefore the implemented hardware must be designed in such a way that it reads the old TIA registers, performs some treatment and output the result into VGA format.

Estimated development time: 10 days.

Possible drawbacks: The lack of expertise with VGA protocol/format.

References

“Atari 2600 Specifications”. http://nocash.emubase.de/2k6specs.htm

“Atari 2600 Schematics – NTSC”.

http://www.atariage.com/2600/archives/schematics/index.html

“Addressing Modes”. http://www.obelisk.demon.co.uk/6502/addressing.html

“Television Interface Adapter”. http://en.wikipedia.org/wiki/Television_Interface_Adapter

“Tia Pinouts”. http://atarihq.com/danb/tia.shtml

“STELLA PROGRAMMER'S GUIDE”. http://atarihq.com/danb/files/stella.pdf

“XFAB Memory Compiler ”.https://https-sec.xfab.com/fo/xfmc/shared/xfmc_first_page.jsp

Attachment 01 – 6502/6507 OPCODES

Opcodes with a * by them in the above list are 'undocumented'.

Effects of the extra opcodes

----------------------------

HALT - Halts the processor, only a RESET will restart.

NOP - Does nothing, may apparently take an address, and so

can effectively skips more than just one byte. The

addressing modes shown are extrapolated from the

other instructions the NOPs appear within.

ASL-ORA - Performs an ASL on the data, and then ORAs the result

into the A register.

AND #n-MOV b7->Cy - ANDs A with the data, and copies bit 7 of A to the

Carry flag

ROL-AND - Performs a ROL on the data, and then ANDs the result

into the A register.

LSR-EOR - Performs a LSR on the data, and then EORs the result

into the A register

ROR-ADC - Performs a ROR on the data, and then ADCs the result

into the A register

STA-STX - Stores the A register and the X register into memory.

I need to test this myself, to find out exactly which

or what is stored, as obviously, both cannot be

stored

TXA-AND #n - Tranfers the X register into the A register, and then

ANDs it with #n

LDA-LDX - Loads the data into both the A register and the X

register

DEC-CMP - Decrements the data, and then compares the A register

with the result

INC-SBC - Increments the data, and then subtracts the result

from the A register

00 BRK

01 ORA (zp,X)

02 * HALT

03 * ASL-ORA (zp,X)

04 * NOP zp

05 ORA zp

06 ASL zp

07 * ASL-ORA zp

08 PHP

09 ORA #n

0A ASL A

0B * AND #n/MOV b7->Cy

0C * NOP abs

0D ORA abs

0E ASL abs

0F * ASL-ORA abs

10 BPL rel

11 ORA (zp),Y

12 * HALT

13 * ASL-ORA (zp),Y

14 * NOP zp

15 ORA zp,X

16 ASL zp,X

17 * ASL-ORA abs,X

18 CLC

19 ORA abs,Y

1A * NOP

1B * ASL-ORA abs,Y

1C * NOP abs

1D ORA abs,X

1E ASL abs,X

1F * ASL-ORA abs,X

20 JSR abs

21 AND (zp,X)

22 * HALT

23 * ROL-AND (zp,X)

24 BIT zp

25 AND zp

26 ROL zp

27 * ROL-AND zp

28 PLP

29 AND #n

2A ROL A

2B * AND #n-MOV b7->Cy

2C BIT abs

2D AND abs

2E ROL abs

2F * ROL-AND abs

30 BMI rel

31 AND (zp),Y

32 * HALT

33 * ROL-AND (zp),Y

34 * NOP zp

35 AND zp,X

36 ROL zp,X

37 * ROL-AND zp,X

38 SEC

39 AND abs,Y

3A * NOP

3B * ROL-AND abs,Y

3C * NOP abs

3D ORA abs,X

3E ASL abs,X

3F * ROL-AND abs,X

40 RTI

41 EOR (zp,X)

42 * HALT

43 * LSR-EOR (zp,X)

44 * NOP zp

45 EOR zp

46 LSR zp

47 * LSR-EOR zp

48 PHA

49 EOR #n

4A LSR A

4B * AND #n-LSR A

4C JMP abs

4D EOR abs

4E LSR abs

4F * LSR-EOR abs

50 BVC rel

51 EOR (zp),Y

52 * HALT

53 * LSR-EOR (zp),Y

54 * NOP zp

55 EOR zp,X

56 LSR zp,X

57 * LSR-EOR abs,X

58 CLI

59 EOR abs,Y

5A * NOP

5B * LSR-EOR abs,Y

5C * NOP abs

5D EOR abs,X

5E LSR abs,X

5F * LSR-EOR abs,X

60 RTS

61 ADC (zp,X)

62 * HALT

63 * ROR-ADC (zp,X)

64 * NOP zp

65 ADC zp

66 ROR zp

67 * ROR-ADC zp

68 PLA

69 ADC #n

6A ROR A

6B * AND #n-ROR A

6C JMP (abs)

6D ADC abs

6E ROR abs

6F * ROR-ADC abs

70 BCS rel

71 ADC (zp),Y

72 * HALT

73 * ROR-ADC (zp),Y

74 * NOP zp

75 ADC zp,X

76 ROR zp,X

77 * ROR-ADC abs,X

78 SEI

79 ADC abs,Y

7A * NOP

7B * ROR-ADC abs,Y

7C * NOP abs

7D ADC abs,X

7E ROR abs,X

7F * ROR-ADC abs,X

80 * NOP zp

81 STA (zp,X)

82 * HALT

83 * STA-STX (zp,X)

84 STY zp

85 STA zp

86 STX zp

87 * STA-STX zp

88 DEY

89 * NOP zp

8A TXA A

8B * TXA-AND #n

8C STY abs

8D STA abs

8E STX abs

8F * STA-STX abs

90 BCC rel

91 STA (zp),Y

92 * HALT

93 * STA-STX (zp),Y

94 STY zp

95 STA zp,X

96 STX zp,Y

97 * STA-STX zp,Y

98 TYA

99 STA abs,Y

9A TXS

9B * STA-STX abs,Y

9C * STA-STX abs,X

9D STA abs,X

9E * STA-STX abs,X

9F * STA-STX abs,X

A0 LDY #n

A1 LDA (zp,X)

A2 LDX #n

A3 * LDA-LDX (zp,X)

A4 LDY zp

A5 LDA zp

A6 LDX zp

A7 * LDA-LDX zp

A8 TAY

A9 LDA #n

AA TAX

AB * LDA-LDX

AC LDY abs

AD LDA abs

AE LDX abs

AF * LDA-LDX abs

B0 BCS rel

B1 LDA (zp),Y

B2 * HALT

B3 * LDA-LDX (zp),Y

B4 LDY zp

B5 LDA zp,X

B6 LDX zp,Y

B7 * LDA-LDX zp,Y

B8 CLV

B9 LDA abs,Y

BA TSX

BB * LDA-LDX abs,Y

BC LDY abs,X

BD LDA abs,X

BE LDX abs,Y

BF * LDA-LDX abs,Y

C0 CPY #n

C1 CMP (zp,X)

C2 * HALT

C3 * DEC-CMP (zp,X)

C4 CPY zp

C5 CMP zp

C6 DEC zp

C7 * DEC-CMP zp

C8 INY

C9 CMP #n

CA DEX

CB * SBX #n

CC CPY abs

CD CMP abs

CE DEC abs

CF * DEC-CMP abs

D0 BNE rel

D1 CMP (zp),Y

D2 * HALT

D3 * DEC-CMP (zp),Y

D4 * NOP zp

D5 CMP zp,X

D6 DEC zp,X

D7 * DEC-CMP zp,X

D8 CLD

D9 CMP abs,Y

DA * NOP

DB * DEC-CMP abs,Y

DC * NOP abs

DD CMP abs,X

DE DEC abs,X

DF * DEC-CMP abs,X

E0 CPX #n

E1 SBC (zp,X)

E2 * HALT

E3 * INC-SBC (zp,X)

E4 CPX zp

E5 SBC zp

E6 INC zp

E7 * INC-SBC zp

E8 INX

E9 SBC #n

EA NOP

EB SBC #n

EC CPX abs

ED SBC abs

EE INC abs

EF * INC-SBC abs

F0 BEQ rel

F1 SBC (zp),Y

F2 * HALT

F3 * INC-SBC (zp),Y

F4 * NOP zp

F5 SBC zp,X

F6 INC zp,X

F7 * INC-SBC zp,X

F8 SED

F9 SBC abs,Y

FA * NOP

FB * INC-SBC abs,Y

FC * NOP abs

FD SBC abs,X

FE INC abs,X

FF * INC-SBC abs,X

Attachment 02 – 6502/6507 Addressing Modes

The 6502 processor provides several ways in which memory locations can be addressed. Some instructions support several different modes while others may only support one. In addition the two index registers can not always be used interchangeably. This lack of orthogonality in the instruction set is one of the features that makes the 6502 trickier to program well.

Implicit

For many 6502 instructions the source and destination of the information to be manipulated is implied directly by the function of the instruction itself and no further operand needs to be specified. Operations like 'Clear Carry Flag' (CLC) and 'Return from Subroutine' (RTS) are implicit.

Accumulator

Some instructions have an option to operate directly upon the accumulator. The programmer specifies this by using a special operand value, 'A'. For example:

LSR A ;Logical shift right one bit

ROR A ;Rotate right one bit

Immediate

Immediate addressing allows the programmer to directly specify an 8 bit constant within the instruction. It is indicated by a '#' symbol followed by an numeric expression. For example:

LDA #10 ;Load 10 ($0A) into the accumulator

LDX #LO LABEL ;Load the LSB of a 16 bit address into X

LDY #HI LABEL ;Load the MSB of a 16 bit address into Y

Zero Page

An instruction using zero page addressing mode has only an 8 bit address operand. This limits it to addressing only the first 256 bytes of memory (e.g. $0000 to $00FF) where the most significant byte of the address is always zero. In zero page mode only the least significant byte of the address is held in the instruction making it shorter by one byte (important for space saving) and one less memory fetch during execution (important for speed).

An assembler will automatically select zero page addressing mode if the operand evaluates to a zero page address and the instruction supports the mode (not all do).

LDA $00 ;Load accumulator from $00

ASL ANSWER ;Shift labelled location ANSWER left

Zero Page,X

The address to be accessed by an instruction using indexed zero page addressing is calculated by taking the 8 bit zero page address from the instruction and adding the current value of the X register to it. For example if the X register contains $0F and the instruction LDA $80,X is executed then the accumulator will be loaded from $008F (e.g. $80 + $0F => $8F).

NB:

The address calculation wraps around if the sum of the base address and the register exceed $FF. If we repeat the last example but with $FF in the X register then the accumulator will be loaded from $007F (e.g. $80 + $FF => $7F) and not $017F.

STY $10,X ;Save the Y register at location on zero page

AND TEMP,X ;Logical AND accumulator with a zero page value

Zero Page,Y

The address to be accessed by an instruction using indexed zero page addressing is calculated by taking the 8 bit zero page address from the instruction and adding the current value of the Y register to it. This mode can only be used with the LDX and STX instructions.

LDX $10,Y ;Load the X register from a location on zero page

STX TEMP,Y ;Store the X register in a location on zero page

Relative

Relative addressing mode is used by branch instructions (e.g. BEQ, BNE, etc.) which contain a signed 8 bit relative offset (e.g. -128 to +127) which is added to program counter if the condition is true. As the program counter itself is incremented during instruction execution by two the effective address range for the target instruction must be with -126 to +129 bytes of the branch.

BEQ LABEL ;Branch if zero flag set to LABEL

BNE *+4 ;Skip over the following 2 byte instruction

Absolute

Instructions using absolute addressing contain a full 16 bit address to identify the target location.

JMP $1234 ;Jump to location $1234

JSR WIBBLE ;Call subroutine WIBBLE

Absolute,X

The address to be accessed by an instruction using X register indexed absolute addressing is computed by taking the 16 bit address from the instruction and added the contents of the X register. For example if X contains $92 then an STA $2000,X instruction will store the accumulator at $2092 (e.g. $2000 + $92).

STA $3000,X ;Store accumulator between $3000 and $30FF

ROR CRC,X ;Rotate right one bit

Absolute,Y

The Y register indexed absolute addressing mode is the same as the previous mode only with the contents of the Y register added to the 16 bit address from the instruction.

AND $4000,Y ;Perform a logical AND with a byte of memory

STA MEM,Y ;Store accumulator in memory

Indirect

JMP is the only 6502 instruction to support indirection. The instruction contains a 16 bit address which identifies the location of the least significant byte of another 16 bit memory address which is the real target of the instruction.

For example if location $0120 contains $FC and location $0121 contains $BA then the instruction JMP ($0120) will cause the next instruction execution to occur at $BAFC (e.g. the contents of $0120 and $0121).

JMP ($FFFC) ;Force a power on reset

JMP (TARGET) ;Jump via a labelled memory area

Indexed Indirect

Indexed indirect addressing is normally used in conjunction with a table of address held on zero page. The address of the table is taken from the instruction and the X register added to it (with zero page wrap around) to give the location of the least significant byte of the target address.

LDA ($40,X) ;Load a byte indirectly from memory

STA (MEM,X) ;Store accumulator indirectly into memory

Indirect Indexed

Indirect indirect addressing is the most common indirection mode used on the 6502. In instruction contains the zero page location of the least significant byte of 16 bit address. The Y register is dynamically added to this value to generated the actual target address for operation.

LDA ($40),Y ;Load a byte indirectly from memory

STA (DST),Y ;Store accumulator indirectly into memory

Attachment 03 – Original TIA Pins and Registers

Vss 1 <- SYNC 2 <- ~RDY 3 <- Ø0 4 <- LUM1 5 <- BLK 6 <- LUM2 7 <- LUM0 8 <- COL 9 -> DEL 10 -> OSC 11 <- AUD0 12 <- AUD1 13 -> D0 14 -> D1 15 -> D2 16 -> D3 17 -> D4 18 -> D5 19 Vcc 20	TIA	40 I0 <-- 39 I1 <-- 38 I2 <-- 37 I3 <-- 36 I4 <-- 35 I5 <-- 34 D6 <-> 33 D7 <-> 32 A0 <-- 31 A1 <-- 30 A2 <-- 29 A3 <-- 28 A4 <-- 27 A5 <-- 26 Ø2 <-- 25 R/~W <-- 24 ~CS0 --> 23 CS1 --> 22 ~CS2 --> 21 ~CS3 -->

Fig. 10: TIA pins

Pin Name	Function
Vss	Ground
SYNC	Composite video sync (Horizontal and Vertical)
RDY	This output goes to the RDY input of the 6507, allows the TIA to halt the processor
O0	Phase 0 clock to the 6507
LUM0,LUM1,LUM2	Video luminance outputs
BLK	Vertical blank output
COL	Video color output
DEL	Color delay input
OSC	Clock input
AUD0,AUD1	Audio outputs
D0...D7	Processor data bus. Only D6 and D7 are bidirectional
Vcc	+5 vdc
CS0,CS1,CS2,CS3	CS0, CS2, CS3 must be low and CS1 must be high to enable chip
R/~W	Read write signal from 6507
O2	Phase clock from 6507
A0...A5	Address bus from 6507
I0,I1,I2,I3	Dumped input ports (used for paddles)
I4,I5	Latched input ports (used for joystick/Paddle triggers)

Tab. 8: TIA pins description

TIA REGISTERS:

--------------------------------------------

$0000 - $003F = TIA.......(write)......(read)

--------------------------------------------

$0000 = TIA Address $00 - (VSYNC)......(CXM0P)

$0001 = TIA Address $01 - (VBLANK).....(CXM1P)

$0002 = TIA Address $02 - (WSYNC)......(CXP0FB)

$0003 = TIA Address $03 - (RSYNC)......(CXP1FB)

$0004 = TIA Address $04 - (NUSIZ0).....(CXM0FB)

$0005 = TIA Address $05 - (NUSIZ1).....(CXM1FB)

$0006 = TIA Address $06 - (COLUP0).....(CXBLPF)

$0007 = TIA Address $07 - (COLUP1).....(CXPPMM)

$0008 = TIA Address $08 - (COLUPF).....(INPT0)

$0009 = TIA Address $09 - (COLUBK).....(INPT1)

$000A = TIA Address $0A - (CTRLPF).....(INPT2)

$000B = TIA Address $0B - (REFP0)......(INPT3)

$000C = TIA Address $0C - (REFP1)......(INPT4)

$000D = TIA Address $0D - (PF0)........(INPT5)

$000E = TIA Address $0E - (PF1)........(UNDEFINED)

$000F = TIA Address $0F - (PF2)........(UNDEFINED)

$0010 = TIA Address $10 - (RESP0)......(CXM0P)

$0011 = TIA Address $11 - (RESP1)......(CXM1P)

$0012 = TIA Address $12 - (RESM0)......(CXP0FB)

$0013 = TIA Address $13 - (RESM1)......(CXP1FB)

$0014 = TIA Address $14 - (RESBL)......(CXM0FB)

$0015 = TIA Address $15 - (AUDC0)......(CXM1FB)

$0016 = TIA Address $16 - (AUDC1)......(CXBLPF)

$0017 = TIA Address $17 - (AUDF0)......(CXPPMM)

$0018 = TIA Address $18 - (AUDF1)......(INPT0)

$0019 = TIA Address $19 - (AUDV0)......(INPT1)

$001A = TIA Address $1A - (AUDV1)......(INPT2)

$001B = TIA Address $1B - (GRP0).......(INPT3)

$001C = TIA Address $1C - (GRP1).......(INPT4)

$001D = TIA Address $1D - (ENAM0)......(INPT5)

$001E = TIA Address $1E - (ENAM1)......(UNDEFINED)

$001F = TIA Address $1F - (ENABL)......(UNDEFINED)

$0020 = TIA Address $20 - (HMP0).......(CXM0P)

$0021 = TIA Address $21 - (HMP1).......(CXM1P)

$0022 = TIA Address $22 - (HMM0).......(CXP0FB)

$0023 = TIA Address $23 - (HMM1).......(CXP1FB)

$0024 = TIA Address $24 - (HMBL).......(CXM0FB)

$0025 = TIA Address $25 - (VDELP0).....(CXM1FB)

$0026 = TIA Address $26 - (VDELP1).....(CXBLPF)

$0027 = TIA Address $27 - (VDELBL).....(CXPPMM)

$0028 = TIA Address $28 - (RESMP0).....(INPT0)

$0029 = TIA Address $29 - (RESMP1).....(INPT1)

$002A = TIA Address $2A - (HMOVE)......(INPT2)

$002B = TIA Address $2B - (HMCLR)......(INPT3)

$002C = TIA Address $2C - (CXCLR)......(INPT4)

$002D = TIA Address $2D - (UNDEFINED)..(INPT5)

$002E = TIA Address $2E - (UNDEFINED)..(UNDEFINED)

$002F = TIA Address $2F - (UNDEFINED)..(UNDEFINED)

$0030 = TIA Address $30 - (UNDEFINED)..(CXM0P)

$0031 = TIA Address $31 - (UNDEFINED)..(CXM1P)

$0032 = TIA Address $32 - (UNDEFINED)..(CXP0FB)

$0033 = TIA Address $33 - (UNDEFINED)..(CXP1FB)

$0034 = TIA Address $34 - (UNDEFINED)..(CXM0FB)

$0035 = TIA Address $35 - (UNDEFINED)..(CXM1FB)

$0036 = TIA Address $36 - (UNDEFINED)..(CXBLPF)

$0037 = TIA Address $37 - (UNDEFINED)..(CXPPMM)

$0038 = TIA Address $38 - (UNDEFINED)..(INPT0)

$0039 = TIA Address $39 - (UNDEFINED)..(INPT1)

$003A = TIA Address $3A - (UNDEFINED)..(INPT2)

$003B = TIA Address $3B - (UNDEFINED)..(INPT3)

$003C = TIA Address $3C - (UNDEFINED)..(INPT4)

$003D = TIA Address $3D - (UNDEFINED)..(INPT5)

$003E = TIA Address $3E - (UNDEFINED)..(UNDEFINED)

$003F = TIA Address $3F - (UNDEFINED)..(UNDEFINED)

Attachment 04 – RIOT Registers

-------------------------------------

$0080 - $00FF = RIOT RAM (read/write)

-------------------------------------

$0080 - $00FF = RIOT RAM, Addresses $00-$7F

---------------------------------------------

$0280 - $029F = RIOT Read Addresses (not RAM)

---------------------------------------------

$0280 = (RIOT $00) - Read DRA

$0281 = (RIOT $01) - Read DDRA

$0282 = (RIOT $02) - Read DRB

$0283 = (RIOT $03) - Read DDRB

$0284 = (RIOT $04) - Read timer, disable interrupt (2)

$0285 = (RIOT $05) - Read interrupt flag

$0286 = (RIOT $06) - Read timer, disable interrupt (2)

$0287 = (RIOT $07) - Read interrupt flag

$0288 = (RIOT $08) - Read DRA

$0289 = (RIOT $09) - Read DDRA

$028A = (RIOT $0A) - Read DRB

$028B = (RIOT $0B) - Read DDRB

$028C = (RIOT $0C) - Read timer, enable interrupt (2)

$028D = (RIOT $0D) - Read interrupt flag

$028E = (RIOT $0E) - Read timer, enable interrupt (2)

$028F = (RIOT $0F) - Read interrupt flag

$0290 = (RIOT $10) - Read DRA

$0291 = (RIOT $11) - Read DDRA

$0292 = (RIOT $12) - Read DRB

$0293 = (RIOT $13) - Read DDRB

$0294 = (RIOT $14) - Read timer, disable interrupt (2)

$0295 = (RIOT $15) - Read interrupt flag

$0296 = (RIOT $16) - Read timer, disable interrupt (2)

$0297 = (RIOT $17) - Read interrupt flag

$0298 = (RIOT $18) - Read DRA

$0299 = (RIOT $19) - Read DDRA

$029A = (RIOT $1A) - Read DRB

$029B = (RIOT $1B) - Read DDRB

$029C = (RIOT $1C) - Read timer, enable interrupt (2)

$029D = (RIOT $1D) - Read interrupt flag

$029E = (RIOT $1E) - Read timer, enable interrupt (2)

$029F = (RIOT $1F) - Read interrupt flag

----------------------------------------------

$0280 - $029F = RIOT Write Addresses (not RAM)

----------------------------------------------

$0280 = (RIOT $00) - Write DRA

$0281 = (RIOT $01) - Write DDRA

$0282 = (RIOT $02) - Write DRB

$0283 = (RIOT $03) - Write DDRB

$0284 = (RIOT $04) - Write edge detect control - negative edge, disable int (1)

$0285 = (RIOT $05) - Write edge detect control - positive edge, disable int (1)

$0286 = (RIOT $06) - Write edge detect control - negative edge, enable int (1)

$0287 = (RIOT $07) - Write edge detect control - positive edge, enable int (1)

$0288 = (RIOT $08) - Write DRA

$0289 = (RIOT $09) - Write DDRA

$028A = (RIOT $0A) - Write DRB

$028B = (RIOT $0B) - Write DDRB

$028C = (RIOT $0C) - Write edge detect control - negative edge, disable int (1)

$028D = (RIOT $0D) - Write edge detect control - positive edge, disable int (1)

$028E = (RIOT $0E) - Write edge detect control - negative edge, enable int (1)

$028F = (RIOT $0F) - Write edge detect control - positive edge, enable int (1)

$0290 = (RIOT $10) - Write DRA

$0291 = (RIOT $11) - Write DDRA

$0292 = (RIOT $12) - Write DRB

$0293 = (RIOT $13) - Write DDRB

$0294 = (RIOT $14) - Write timer (div by 1) - disable int (2)

$0295 = (RIOT $15) - Write timer (div by 8) - disable int (2)

$0296 = (RIOT $16) - Write timer (div by 64) - disable int (2)

$0297 = (RIOT $17) - Write timer (div by 1024) - disable int (2)

$0298 = (RIOT $18) - Write DRA

$0299 = (RIOT $19) - Write DDRA

$029A = (RIOT $1A) - Write DRB

$029B = (RIOT $1B) - Write DDRB

$029C = (RIOT $1C) - Write timer (div by 1) - enable int (2)

$029D = (RIOT $1D) - Write timer (div by 8) - enable int (2)

$029E = (RIOT $1E) - Write timer (div by 64) - enable int (2)

$029F = (RIOT $1F) - Write timer (div by 1024) - enable int (2)