mirror of
https://github.com/problemkaputt/problemkaputt.github.io.git
synced 2024-05-13 10:09:21 -04:00
2341 lines
135 KiB
HTML
2341 lines
135 KiB
HTML
<HTML><HEAD>
|
|
<TITLE>Atari 2600 Specifications</TITLE>
|
|
<META NAME="GENERATOR" CONTENT="nocash XED2HTM converter">
|
|
</HEAD><BODY bgcolor="#ffffff" text="#000000" link="#0033cc" vlink="#0033cc" alink="#0033cc">
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="contents"></A><FONT SIZE=+2> Atari 2600 Specifications</FONT></TD></TR></TABLE><BR>
|
|
<B>Programming Specifications</B><BR>
|
|
<A HREF="#technicaldata">Technical Data</A><BR>
|
|
<A HREF="#memoryandiomap">Memory and I/O Map</A><BR>
|
|
<A HREF="#video">Video</A><BR>
|
|
<A HREF="#intervaltimer">Interval Timer</A><BR>
|
|
<A HREF="#audio">Audio</A><BR>
|
|
<A HREF="#controllers">Controllers</A><BR>
|
|
<A HREF="#cartridges">Cartridges</A><BR>
|
|
<A HREF="#cpu65xxmicroprocessor">CPU 65XX Microprocessor</A><BR>
|
|
<A HREF="#hardwaresoldering">Hardware / Soldering</A><BR>
|
|
<A HREF="#links">Links</A><BR>
|
|
<BR>
|
|
Writing this emulator simultaneously while US hi-tec machinery was
|
|
attacking Bagdad, it must be said that the Atari 2600 was shipped with a
|
|
war game called Combat, the Atari 2600's hardware sprites are notably
|
|
called "Players", "Missiles", and "Ball". Being manufactured in the cold
|
|
war era, the implied purpose of this gaming console is: Playing joyful war
|
|
games. War is not a game, war is no fun. War is murder.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="technicaldata"></A><FONT SIZE=+2> Technical Data</FONT></TD></TR></TABLE><BR>
|
|
Atari 2600 Video Computer System (VCS)<BR>
|
|
Manufacured 1977-1991<BR>
|
|
<BR>
|
|
<B>Chipset</B><BR>
|
|
CPU 6507 - 8bit, 1.19MHz<BR>
|
|
TIA 1A - Television Interface Adaptor Model 1A (Video, Audio, Input Ports)<BR>
|
|
PIA 6532 - (128 bytes RAM, I/O Ports, Timer)<BR>
|
|
<BR>
|
|
<B>CPU and Memory</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> CPU: 6507, 8bit, 1.19MHz (cutdown 6502 with only 8K address space)
|
|
RAM: 128 Bytes (additional 128 or 256 bytes in some cartridges)
|
|
VRAM: None (Picture controlled by I/O Ports only)
|
|
ROM: External Game Cartridge (usually 2KB or 4KB, or banked 2x4KB)
|
|
</TD></TR></TABLE><B>Video</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Output: Line-by-line (Registers must be updated each scanline)
|
|
Resolution: 160x192 pixels (NTSC 60Hz), 160x228 pixels (PAL 50Hz)
|
|
Playfield: 40 dots horizontal resolution (rows of 4 pixels per dot)
|
|
Colors: 4 colors at once (one color per object)
|
|
Palette: 128 colors (NTSC), 104 colors (PAL), 8 colors (SECAM)
|
|
Sprites: 2 sprites of 8pix width, 3 sprites of 1pix width
|
|
</TD></TR></TABLE><B>Input/Output Ports, Audio, Timer</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> I/O: Two 8bit I/O ports, six 1bit Input ports
|
|
Timer: One 8bit Timer (with prescaler; 1,8,64,1024 machine cycles)
|
|
Audio: Two sound channels (with Frequency, Volume, Noise control)
|
|
</TD></TR></TABLE><B>Console Switches</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Switches: Color/Mono Switch (PAL/NTSC only), and two Difficulty Switches
|
|
Buttons: Select Button, Reset Button (or Switches in older consoles)
|
|
Hardware: Power Switch, TV Channel Select Switch (not software controlled)
|
|
</TD></TR></TABLE><B>Connectors</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Slot: One 24 pin Cartridge Slot (with 4K address bus)
|
|
Controls: Two 9 pin Joystick ports (also used for Paddles, Keyboards)
|
|
TV: One Cinch Socket (Video/Audio TV Signal)
|
|
Power: 9V DC, 500mA (internally converted to 5V DC)
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="memoryandiomap"></A><FONT SIZE=+2> Memory and I/O Map</FONT></TD></TR></TABLE><BR>
|
|
<B>Overview</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0000-002C TIA Write
|
|
0000-000D TIA Read (sometimes mirrored at 0030-003D)
|
|
0080-00FF PIA RAM (128 bytes)
|
|
0280-0297 PIA Ports and Timer
|
|
F000-FFFF Cartridge Memory (4 Kbytes area)
|
|
</TD></TR></TABLE><BR>
|
|
Below lists address, name, used bits (ordered 76543210, "1"=used), and
|
|
function of all I/O ports and memory. Ports marked as <strobe> are
|
|
executing the the specified function when wrinting any data to it (the
|
|
written data itself is ignored).<BR>
|
|
<BR>
|
|
<B>TIA - WRITE ADDRESS SUMMARY (Write only)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 00 VSYNC ......1. vertical sync set-clear
|
|
01 VBLANK 11....1. vertical blank set-clear
|
|
02 WSYNC <strobe> wait for leading edge of horizontal blank
|
|
03 RSYNC <strobe> reset horizontal sync counter
|
|
04 NUSIZ0 ..111111 number-size player-missile 0
|
|
05 NUSIZ1 ..111111 number-size player-missile 1
|
|
06 COLUP0 1111111. color-lum player 0 and missile 0
|
|
07 COLUP1 1111111. color-lum player 1 and missile 1
|
|
08 COLUPF 1111111. color-lum playfield and ball
|
|
09 COLUBK 1111111. color-lum background
|
|
0A CTRLPF ..11.111 control playfield ball size & collisions
|
|
0B REFP0 ....1... reflect player 0
|
|
0C REFP1 ....1... reflect player 1
|
|
0D PF0 1111.... playfield register byte 0
|
|
0E PF1 11111111 playfield register byte 1
|
|
0F PF2 11111111 playfield register byte 2
|
|
10 RESP0 <strobe> reset player 0
|
|
11 RESP1 <strobe> reset player 1
|
|
12 RESM0 <strobe> reset missile 0
|
|
13 RESM1 <strobe> reset missile 1
|
|
14 RESBL <strobe> reset ball
|
|
15 AUDC0 ....1111 audio control 0
|
|
16 AUDC1 ....1111 audio control 1
|
|
17 AUDF0 ...11111 audio frequency 0
|
|
18 AUDF1 ...11111 audio frequency 1
|
|
19 AUDV0 ....1111 audio volume 0
|
|
1A AUDV1 ....1111 audio volume 1
|
|
1B GRP0 11111111 graphics player 0
|
|
1C GRP1 11111111 graphics player 1
|
|
1D ENAM0 ......1. graphics (enable) missile 0
|
|
1E ENAM1 ......1. graphics (enable) missile 1
|
|
1F ENABL ......1. graphics (enable) ball
|
|
20 HMP0 1111.... horizontal motion player 0
|
|
21 HMP1 1111.... horizontal motion player 1
|
|
22 HMM0 1111.... horizontal motion missile 0
|
|
23 HMM1 1111.... horizontal motion missile 1
|
|
24 HMBL 1111.... horizontal motion ball
|
|
25 VDELP0 .......1 vertical delay player 0
|
|
26 VDELP1 .......1 vertical delay player 1
|
|
27 VDELBL .......1 vertical delay ball
|
|
28 RESMP0 ......1. reset missile 0 to player 0
|
|
29 RESMP1 ......1. reset missile 1 to player 1
|
|
2A HMOVE <strobe> apply horizontal motion
|
|
2B HMCLR <strobe> clear horizontal motion registers
|
|
2C CXCLR <strobe> clear collision latches
|
|
</TD></TR></TABLE><B>TIA - READ ADDRESS SUMMARY (Read only)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 30 CXM0P 11...... read collision M0-P1, M0-P0 (Bit 7,6)
|
|
31 CXM1P 11...... read collision M1-P0, M1-P1
|
|
32 CXP0FB 11...... read collision P0-PF, P0-BL
|
|
33 CXP1FB 11...... read collision P1-PF, P1-BL
|
|
34 CXM0FB 11...... read collision M0-PF, M0-BL
|
|
35 CXM1FB 11...... read collision M1-PF, M1-BL
|
|
36 CXBLPF 1....... read collision BL-PF, unused
|
|
37 CXPPMM 11...... read collision P0-P1, M0-M1
|
|
38 INPT0 1....... read pot port
|
|
39 INPT1 1....... read pot port
|
|
3A INPT2 1....... read pot port
|
|
3B INPT3 1....... read pot port
|
|
3C INPT4 1....... read input
|
|
3D INPT5 1....... read input
|
|
</TD></TR></TABLE><B>PIA 6532 - RAM, Switches, and Timer (Read/Write)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 80..FF RAM 11111111 128 bytes RAM (in PIA chip) for variables and stack
|
|
0280 SWCHA 11111111 Port A; input or output (read or write)
|
|
0281 SWACNT 11111111 Port A DDR, 0= input, 1=output
|
|
0282 SWCHB 11111111 Port B; console switches (read only)
|
|
0283 SWBCNT 11111111 Port B DDR (hardwired as input)
|
|
0284 INTIM 11111111 Timer output (read only)
|
|
0285 INSTAT 11...... Timer Status (read only, undocumented)
|
|
0294 TIM1T 11111111 set 1 clock interval (838 nsec/interval)
|
|
0295 TIM8T 11111111 set 8 clock interval (6.7 usec/interval)
|
|
0296 TIM64T 11111111 set 64 clock interval (53.6 usec/interval)
|
|
0297 T1024T 11111111 set 1024 clock interval (858.2 usec/interval)
|
|
</TD></TR></TABLE><B>Cartridge Memory (4 Kbytes area)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> F000-FFFF ROM 11111111 Cartridge ROM (4 Kbytes max)
|
|
F000-F07F RAMW 11111111 Cartridge RAM Write (optional 128 bytes)
|
|
F000-F0FF RAMW 11111111 Cartridge RAM Write (optional 256 bytes)
|
|
F080-F0FF RAMR 11111111 Cartridge RAM Read (optional 128 bytes)
|
|
F100-F1FF RAMR 11111111 Cartridge RAM Read (optional 256 bytes)
|
|
003F BANK ......11 Cart Bank Switching (for some 8K ROMs, 4x2K)
|
|
FFF4-FFFB BANK <strobe> Cart Bank Switching (for ROMs greater 4K)
|
|
FFFC-FFFD ENTRY 11111111 Cart Entrypoint (16bit pointer)
|
|
FFFE-FFFF BREAK 11111111 Cart Breakpoint (16bit pointer)
|
|
</TD></TR></TABLE><BR>
|
|
See also:<BR>
|
|
<A HREF="#memorymirrors">Memory Mirrors</A><BR>
|
|
<A HREF="#cartridges">Cartridges</A><BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="memorymirrors"></A><FONT SIZE=+2> Memory Mirrors</FONT></TD></TR></TABLE><BR>
|
|
<B>CPU 8K Address Space Mirrors (Step 2000h)</B><BR>
|
|
The 6507 CPU is having only 13 address pins (8KBytes, 0000h-1FFFh). All
|
|
memory is mirrored in steps of 2000h (ie. at 2000h-3FFFh, 4000h-5FFFh,
|
|
and so on, up to E000h-FFFFh). The lower half of each area contains
|
|
internal memory (RAM, I/O Ports), the upper half contains external
|
|
memory (cartridge ROM or expansion RAM).<BR>
|
|
<BR>
|
|
<B>TIA Mirrors (Step 10h/40h,100h)</B><BR>
|
|
The TIA chip is addressed by A12=0, A7=0. Located in memory at
|
|
0000h-007Fh, 0100h-017Fh, 0200h-027Fh, etc., 0F00h-0F7Fh. Output ports
|
|
are mirrored twice in each window (at XX00h and XX40h), input port are
|
|
mirrored eight times in each window (at XX00h, XX10h, XX20h, XX30h, etc.
|
|
XX70h).<BR>
|
|
<BR>
|
|
<B>PIA RAM Mirrors (Step 100h,400h)</B><BR>
|
|
PIA RAM is selected by A12=0, A9=0, A7=1. Located in memory at
|
|
0080h-00FFh, 0180h-01FFh, 0480h-04FFh, 0580h-05FFh, etc. The mirror at
|
|
0180h is particulary important because it allows the CPU to access RAM
|
|
for stack operations.<BR>
|
|
<BR>
|
|
<B>PIA I/O Mirrors (Step 2h,8h,100h,400h)</B><BR>
|
|
PIA I/O is selected by A12=0, A9=1, A7=1. Located in memory at
|
|
0280h-02FFh, 0380h-03FFh, 0680h-06FFh, 0780h-07FFh, etc. Each 80h-area
|
|
contains 16 mirrors of the PIA I/O ports at XX80h, XX88h, XX90h, XX98h,
|
|
etc. And, each 8h-area contains two copies of INTIM (eg. 0284h,0286h)
|
|
and INSTAT (eg. 0285h,0287h).<BR>
|
|
<BR>
|
|
<B>Cartridge Mirrors</B><BR>
|
|
Cartridge memory is selected by A12=1. Small 2K cartridges are usually
|
|
mirrored twice into the 4K cartridge area. ROM-Bank ports (eg. 1FF8h)
|
|
aren't necessarily connected to A12, and may overlap the upper PIA I/O
|
|
mirror (eg. 0FF8h).<BR>
|
|
<BR>
|
|
<B>Note (Commonly used Mirrors)</B><BR>
|
|
In some cases, two different ports are located at the same memory
|
|
address, one port being Read-only, and the other being Write-only, of
|
|
course, there is no physical conflict with such 'overlapping' ports.<BR>
|
|
However, human users may prefer to use different memory addresses for
|
|
different ports. The following mirrors are used by many games (and in
|
|
this document): Timer outputs at 294h-297h (instead of 284h-287h), TIA
|
|
inputs at 30h-3Dh (instead of 00h-0Dh).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="video"></A><FONT SIZE=+2> Video</FONT></TD></TR></TABLE><BR>
|
|
The display controller operates on a line by line basis, always
|
|
outputting the same information every television line unless new data is
|
|
written into it by software.<BR>
|
|
<BR>
|
|
<A HREF="#videosynchronizationandblanking">Video Synchronization and Blanking</A><BR>
|
|
<A HREF="#videodimensionsandtimings">Video Dimensions and Timings</A><BR>
|
|
<A HREF="#videoplayfield">Video Playfield</A><BR>
|
|
<A HREF="#videomobshapeenable">Video MOB Shape/Enable</A><BR>
|
|
<A HREF="#videomobhorizontalpositioning">Video MOB Horizontal Positioning</A><BR>
|
|
<A HREF="#videomobhorizontalmotion">Video MOB Horizontal Motion</A><BR>
|
|
<A HREF="#videocollision">Video Collision</A><BR>
|
|
<A HREF="#videocolors">Video Colors</A><BR>
|
|
<A HREF="#videopriority">Video Priority</A><BR>
|
|
<BR>
|
|
"The 5 moveable objects can be positioned anywhere, and consists of 2
|
|
players, 2 missiles, and a ball.<BR>
|
|
The playfield, players, missiles, and ball are created and manipulated by
|
|
a series of registers in the TIA that the microprocessor can address and
|
|
write into.<BR>
|
|
Each type of object has certain defined capabilities."<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videosynchronizationandblanking"></A><FONT SIZE=+2> Video Synchronization and Blanking</FONT></TD></TR></TABLE><BR>
|
|
<B>00h - VSYNC - Vertical sync set-clear</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Not used
|
|
1 Vertical Sync (0=Stop sync, 1=Start sync)
|
|
2-7 Not used
|
|
</TD></TR></TABLE>Sync should be output for a duration of 3 scanlines, between the lower and
|
|
upper screen border periods.<BR>
|
|
<BR>
|
|
<B>01h - VBLANK - Vertical blank set-clear</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Not used
|
|
1 Vertical Blank (0=Stop blanking, 1=Start blanking)
|
|
2-5 Not used
|
|
6 INPT4-INPT5 Control (0=Normal Input, 1=Latched Input)
|
|
7 INPT0-INPT3 Control (0=Normal Input, 1=Dumped to ground)
|
|
</TD></TR></TABLE>Note: Disable latches (Bit6=0) also resets latches to logic true.<BR>
|
|
The blanking bit should be set for the duration of upper and lower screen
|
|
border periods. During blanking, playfield and moveable objects are hidden
|
|
and the screen area becomes black.<BR>
|
|
<BR>
|
|
<B>02h - WSYNC <strobe> - Wait for leading edge of horizontal blank</B><BR>
|
|
Writing any value to this address halts microporcessor (by RDY signal)
|
|
until end of current scanline, ie. until begin of next H-Blank period.<BR>
|
|
Note: Works also in 'hidden' scanlines, ie. during VBlank/VSync.<BR>
|
|
<BR>
|
|
<B>03h - RSYNC <strobe> - Reset horizontal sync counter</B><BR>
|
|
Writing any value to this address resets the horizontal sync counter to begin
|
|
of horizontal blank time (intended for chip testing purposes).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videodimensionsandtimings"></A><FONT SIZE=+2> Video Dimensions and Timings</FONT></TD></TR></TABLE><BR>
|
|
<B>Vertical Timing and Resolution</B><BR>
|
|
Vertical sync and blanking must be controlled by software. VBLANK should
|
|
be enabled during vsync and upper/lower border periods.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Type_______NTSC__PAL/SECAM______
|
|
V-Sync 3 3 scanlines
|
|
V-Blank 37 45 scanlines (upper border)
|
|
Picture 192 228 scanlines
|
|
Overscan 30 36 scanlines (lower border)
|
|
Frame Rate 60 50 Hz
|
|
Frame Time 262 312 scanlines
|
|
</TD></TR></TABLE>Because there is not enough CPU time to change all registers per scanline,
|
|
some objects must use a lower vertical resolution than 192 or 228 pixels.<BR>
|
|
Notes: V-Sync should be exactly 3 scanlines (if it is 2 or 4 scanlines, my TV
|
|
tends to ignore colors and to produce a black & white picture). Many PAL
|
|
games use only 192 picture scanlines (and according 45+18 upper, and 36+18
|
|
lower border lines).<BR>
|
|
<BR>
|
|
<B>Horizontal Timing and Resolution</B><BR>
|
|
Horizontal sync and blanking are done automatically by hardware. The
|
|
software may re-synchronize itself to begin of H-Blank by writing to
|
|
WSYNC.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Blanking 22.6 machine clocks (68 color clocks)
|
|
Picture 53.3 machine clocks (160 color clocks) (160 pixels)
|
|
Total 76.0 machine clocks (228 color clocks)
|
|
</TD></TR></TABLE>The playfield (which takes up the main part of the screen) is restricted
|
|
to a horizontal resolution of 40 dots. Moveable objects can be positioned
|
|
and drawn at full 160 pixels resolution.<BR>
|
|
<BR>
|
|
<B>Clocks</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Video Color Clock: 3.579545 MHz (NTSC), 3.546894 MHz (PAL)
|
|
CPU Machine Clock: 1.193182 MHz (NTSC), 1.182298 MHz (PAL)
|
|
</TD></TR></TABLE>The CPU Clock is derived from Video clock divided by three.<BR>
|
|
One color clock = 1 pixel. One machine clock = 3 pixels.<BR>
|
|
<BR>
|
|
Note: For the vertical blanking/overscan periods, it'd be recommended to
|
|
program the PIA Timer to blanking time (allowing to execute larger parts
|
|
of code without timing synchronization), followed by one WSYNC when the
|
|
timer has expired.<BR>
|
|
<BR>
|
|
Note: Most PAL games increase upper/lower border heights rather than
|
|
actually using the full 228 pixels picture height.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videoplayfield"></A><FONT SIZE=+2> Video Playfield</FONT></TD></TR></TABLE><BR>
|
|
Officially, a playfield consists of walls, clouds, barriers, and other
|
|
seldom moved objects. In practice, it consists of a 20 bit value, used to
|
|
display 20 low resolution dots (rows of 4 pixels per dot). The whole
|
|
screen width is 40 dots, the same 20 bit value is used both for the left
|
|
and right half (however, the right half may be horizontally mirrored, and,
|
|
software may change the PF registers somewhere in the middle of the
|
|
scanline).<BR>
|
|
<BR>
|
|
<B>0Dh - PF0 - Playfield Register 0 (LSB first) (only upper 4bit used)</B><BR>
|
|
<B>0Eh - PF1 - Playfield Register 1 (MSB first) (8bit)</B><BR>
|
|
<B>0Fh - PF2 - Playfield Register 2 (LSB first) (8bit)</B><BR>
|
|
Defines the colors of the separate playfield dots (0=COLUBK, 1=COLUPF).
|
|
Depending on the REF bit (CTRLPF.0), the screen output is composed of the
|
|
following bits/ordering:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Normal (REF=0) : PF0.4-7 PF1.7-0 PF2.0-7 PF0.4-7 PF1.7-0 PF2.0-7
|
|
Mirror (REF=1) : PF0.4-7 PF1.7-0 PF2.0-7 PF2.7-0 PF1.0-7 PF0.7-4
|
|
</TD></TR></TABLE>PF0, PF1, and PF2, should not be written to while the respective register
|
|
is currently output to the screen.<BR>
|
|
<BR>
|
|
<B>0Ah - CTRLPF - Control Playfield and Ball size</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Playfield Reflection (0=Normal, 1=Mirror right half)
|
|
1 Playfield Color (0=Normal, 1=Score Mode, only if Bit2=0)
|
|
2 Playfield/Ball Priority (0=Normal, 1=Above Players/Missiles)
|
|
3 Not used
|
|
4-5 Ball size (0..3 = 1,2,4,8 pixels width)
|
|
6-7 Not used
|
|
</TD></TR></TABLE>In "score" mode, the playfield is drawn by COLUP0/COLUP1 for left/right
|
|
half of screen (instead COLUPF in both halves). Intended to display
|
|
2-player mode scores at different colors by low-resolution playfield
|
|
graphics (used by older games like Combat).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videomobshapeenable"></A><FONT SIZE=+2> Video MOB Shape/Enable</FONT></TD></TR></TABLE><BR>
|
|
<B>(Ball Size: See CTRLPF)</B><BR>
|
|
<BR>
|
|
<B>04h - NUSIZ0 - Number-size player-missile 0</B><BR>
|
|
<B>05h - NUSIZ1 - Number-size player-missile 1</B><BR>
|
|
These addresses control the number and size of players and missiles.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-2 Player-Missile number & Player size (See table below)
|
|
3 Not used ???
|
|
4-5 Missile Size (0..3 = 1,2,4,8 pixels width)
|
|
6-7 Not used
|
|
</TD></TR></TABLE>Player-Missile number & player size (Picture shows shape, 8 pix per char)<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0 One copy (X.........)
|
|
1 Two copies - close (X.X.......)
|
|
2 Two copies - medium (X...X.....)
|
|
3 Three copies - close (X.X.X.....)
|
|
4 Two copies - wide (X.......X.)
|
|
5 Double sized player (XX........)
|
|
6 Three copies - medium (X...X...X.)
|
|
7 Quad sized player (XXXX......)
|
|
</TD></TR></TABLE>1/2 television line (80 clocks), 8 clocks per character<BR>
|
|
<BR>
|
|
<B>1Bh - GRP0 - Graphics (enable) player 0</B><BR>
|
|
<B>1Ch - GRP1 - Graphics (enable) player 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-7 Eight dots player shape (0=Transparent, 1=Player color)
|
|
</TD></TR></TABLE>The dots are usually drawn MSB first (from left to right), but can be
|
|
horizontally mirroed by REFP0 and REFP1 registers.<BR>
|
|
Use a value of 00h to hide/disable the object.<BR>
|
|
<BR>
|
|
<B>1Dh - ENAM0 - Graphics (enable) missile 0</B><BR>
|
|
<B>1Eh - ENAM1 - Graphics (enable) missile 1</B><BR>
|
|
<B>1Fh - ENABL - Graphics (enable) ball</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Not used
|
|
1 Missile/Ball Enable (0=Transparent, 1=Missile/Ball color)
|
|
2-7 Not used
|
|
</TD></TR></TABLE>The "shape" for these objects consists of a single dot, which may be
|
|
horizontally repeated or stretched by NUSIZ/CTRLPF registers.<BR>
|
|
Use a value of 00h to hide/disable the object. Missiles can be also hidden
|
|
by RESMPx registers (see Positioning chapter).<BR>
|
|
<BR>
|
|
<B>0Bh - REFP0 - Reflect player 0</B><BR>
|
|
<B>0Ch - REFP1 - Reflect player 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-2 Not used
|
|
3 Reflect Player Graphics (0=Normal/MSB first, 1=Mirror/LSB first)
|
|
4-7 Not used
|
|
</TD></TR></TABLE>Used to mirror the GRP0 and GRP1 registers.<BR>
|
|
<BR>
|
|
<B>25h - VDELP0 - Vertical delay player 0 (Delay GRP0 until writing to GRP1)</B><BR>
|
|
<B>26h - VDELP1 - Vertical delay player 1 (Delay GRP1 until writing to GRP0)</B><BR>
|
|
<B>27h - VDELBL - Vertical delay ball (Delay ENABL until writing to GRP1)</B><BR>
|
|
When VDELPx is set, writes to GRPx are delayed until GRPy is written to -
|
|
which may be done in the same scanline, in one of the next scanlines, or
|
|
in the next frame, or never - and may thus actually cause a horizontal,
|
|
vertical, framerate, or even endless delay.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Vertical Delay (0=No delay, 1=Delay until writing to GRP0/GRP1)
|
|
1-7 Not used
|
|
</TD></TR></TABLE>The misleading name "vertical" delay is used because these registers were
|
|
originally intended to be used to update GRPx in one scanline and to have
|
|
the changes delayed until GRPy is updated in the next scanline.<BR>
|
|
<BR>
|
|
<B>Notes on High Resolution Text and Vertical Delay</B><BR>
|
|
Many newer games (eg. Pacman) use high resolution text or graphics output,
|
|
of 6 characters or 48 pixels width. This is done by configuring NUSIZ to
|
|
"three copies close", and positioning GRP0 ("0_0_0") eight pixels to the
|
|
left of GRP1 ("1_1_1"), resulting in the pattern "010101".<BR>
|
|
Updating GRP0 and GRP1 multiple times within each scanline can be done to
|
|
change the pattern to 6 different characters ("012345"), the drawing
|
|
procedure requires proper timing, and typically uses "vertical" delay (in
|
|
this case behaving as horizontal delay), note that one usually needs 7
|
|
writes to GRP registers to draw 6 characters (with one final dummy write
|
|
to apply the last (delayed) character).<BR>
|
|
The GRPx registers actually consist of two registers each, hereby called
|
|
GRPxA (delayed data latch) and GRPxB (actual display data). When VDELx is
|
|
disabled, writes to GRPx go directly to GRPxB. When VDELx is enabled,
|
|
writes to GRPx go to GRPxA, and GRPxA is copied to GRPxB at the time when
|
|
writing to GRPy.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videomobhorizontalpositioning"></A><FONT SIZE=+2> Video MOB Horizontal Positioning</FONT></TD></TR></TABLE><BR>
|
|
<B>10h - RESP0 <strobe> - Reset player 0</B><BR>
|
|
<B>11h - RESP1 <strobe> - Reset player 1</B><BR>
|
|
<B>12h - RESM0 <strobe> - Reset missile 0</B><BR>
|
|
<B>13h - RESM1 <strobe> - Reset missile 1</B><BR>
|
|
<B>14h - RESBL <strobe> - Reset ball</B><BR>
|
|
Writing any value to these addresses sets the associated objects
|
|
horizontal position equal to the current position of the cathode ray beam,
|
|
if the write takes place anywhere within horizontal blanking then the
|
|
position is set to the left edge of the screen (plus a few pixels towards
|
|
right: 3 pixels for P0/P1, and only 2 pixels for M0/M1/BL).<BR>
|
|
Note: Because of opcode execution times, it is usually necessary to adjust
|
|
the resulting position to the desired value by subsequently using the
|
|
Horizontal Motion function.<BR>
|
|
<BR>
|
|
<B>28h - RESMP0 - Reset missile 0 to player 0</B><BR>
|
|
<B>29h - RESMP1 - Reset missile 1 to player 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Not used
|
|
1 Reset Missile to Player (0=Normal, 1=Hide and Lock on player)
|
|
2-7 Not used
|
|
</TD></TR></TABLE>As long as Bit 1 is set, the missile is hidden and its horizontal position
|
|
is centered on the players position. The centering offset is +3 for
|
|
normal, +6 for double, and +10 quad sized player (that is giving good
|
|
centering results with missile widths of 2, 4, and 8 respectively).<BR>
|
|
<BR>
|
|
<B>Note on Vertical Positioning</B><BR>
|
|
None such supported by the video controller. Moveable objects (and
|
|
playfield) must be enabled or disabled (or modified in shape) in the
|
|
appropriate scanlines by software.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videomobhorizontalmotion"></A><FONT SIZE=+2> Video MOB Horizontal Motion</FONT></TD></TR></TABLE><BR>
|
|
<B>20h - HMP0 - Horizontal motion player 0</B><BR>
|
|
<B>21h - HMP1 - Horizontal motion player 1</B><BR>
|
|
<B>22h - HMM0 - Horizontal motion missile 0</B><BR>
|
|
<B>23h - HMM1 - Horizontal motion missile 1</B><BR>
|
|
<B>24h - HMBL - Horizontal motion ball</B><BR>
|
|
Specifies the motion direction and step (in pixels). Writing to these
|
|
registers does not directly affect the objects position, unless when
|
|
subsequently using the HMOVE command.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-3 Not used
|
|
4-7 Signed Motion Value (-8..-1=Right, 0=No motion, +1..+7=Left)
|
|
</TD></TR></TABLE>Repeatedly writing to HMOVE will repeat the same movement (without having
|
|
to rewrite the motion registers).<BR>
|
|
<BR>
|
|
<B>2Ah - HMOVE <strobe> - Apply horizontal motion</B><BR>
|
|
Writing any value to this address applies horizontal motion: The motion
|
|
registers (HMP0, HMP1, etc) are added to the position of the moveable
|
|
objects (P0, P1, etc):<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> NewPos = ( OldPos +/- Motion ) MOD 160
|
|
</TD></TR></TABLE>Timing Restrictions: The HMOVE command should be used only immediately
|
|
after a WSYNC command, this ensures that the operation starts at the
|
|
beginning of, and finishes before end of, horizontal blanking (see notes
|
|
below). Also, the software should not change any of the motion registers
|
|
for at least 24 machine cycles after an HMOVE command.<BR>
|
|
<BR>
|
|
<B>2Bh - HMCLR <strobe> - Clear horizontal motion registers</B><BR>
|
|
Writing any value to this address resets all five motion registers
|
|
(HMP0, HMP1, etc) to zero.<BR>
|
|
<BR>
|
|
<B>HMOVE Extra Blanking</B><BR>
|
|
When HMOVE is executed inside of the horizontal blanking period (which
|
|
should be usually be so), then the leftmost 8 pixels of the following
|
|
scanline are covered by the border color (black).<BR>
|
|
That "feature" is probably intended to hide minor dirt effects in moveable
|
|
objects while processing motion. The resulting black lines could be
|
|
treated as a major dirt effect though (eg. Espial).<BR>
|
|
Some games (eg. Hero) issue HMOVEs in all scanlines (so that all scanlines
|
|
have masked left pixels, which looks better than only some lines being
|
|
masked). Also, the blanking may be of some use with objects that are moved
|
|
"half offscreen" (which would usually re-appear at the other side of the
|
|
screen).<BR>
|
|
Note: Collision checks still take place "below" of the extra blanking area.<BR>
|
|
<BR>
|
|
<B>HMOVE Extra Motion Offsets</B><BR>
|
|
When HMOVE is executed outside of the horizontal blanking period (which
|
|
should usually not be done), additional motion offets are added to the
|
|
position registers (additonally to the normal HMxx motion values):<BR>
|
|
Player Offsets:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 6,4,4,2,0 ;-more before blanking, disp RIGHT \
|
|
-2,-2,-4,-6,-8,-8 ;-area before blanking, disp LEFT /
|
|
14 dup (0) ;-blanking area, disp ZERO |
|
|
2,2,4,6,8,8,10,12 ;-area after blanking, disp RIGHT \
|
|
8,8,8,8,8... ;-remaining area, disp FAST RIGHT ""--__
|
|
</TD></TR></TABLE>Missile/Ball Offsets<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> -1,-2,-2,-3,-4,-5,-5,-6,-7,-8,-8 ;disp LEFT /
|
|
14 dup (0) ;-blanking area, disp ZERO |
|
|
1,1,2,3,4,4,5,6 ;-area after blanking, disp RIGHT \
|
|
0,0,0,0,0... ;-remaining area, disp ZERO |
|
|
</TD></TR></TABLE>In such cases, motion may occur even if HMxx registers are all zero.<BR>
|
|
<BR>
|
|
<B>Actually...</B><BR>
|
|
The above extra-offsets seem to apply ONLY when HMxx=0.<BR>
|
|
For other HMxx values the extra-offsets seem to change,<BR>
|
|
such like a LEFT offset becomes RIGHT offset or vice versa,<BR>
|
|
ie. there seem to be some kind of overflows occuring...?<BR>
|
|
And/or, the above extra-offsets apply only if the sprites<BR>
|
|
are at a specific position?<BR>
|
|
Anyways, HMOVE should be issued only immediately after WSYNC<BR>
|
|
(or N*76 cycles after WSYNC), otherwise the results are kinda<BR>
|
|
unpredictable.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videocollision"></A><FONT SIZE=+2> Video Collision</FONT></TD></TR></TABLE><BR>
|
|
<B>30h - CXM0P (R) - Collision Latch M0-P1, M0-P0 (Bit 7,6) (Read only)</B><BR>
|
|
<B>31h - CXM1P (R) - Collision Latch M1-P0, M1-P1 (Bit 7,6) (Read only)</B><BR>
|
|
<B>32h - CXP0FB (R) - Collision Latch P0-PF, P0-BL (Bit 7,6) (Read only)</B><BR>
|
|
<B>33h - CXP1FB (R) - Collision Latch P1-PF, P1-BL (Bit 7,6) (Read only)</B><BR>
|
|
<B>34h - CXM0FB (R) - Collision Latch M0-PF, M0-BL (Bit 7,6) (Read only)</B><BR>
|
|
<B>35h - CXM1FB (R) - Collision Latch M1-PF, M1-BL (Bit 7,6) (Read only)</B><BR>
|
|
<B>36h - CXBLPF (R) - Collision Latch BL-PF (Bit 7) (Read only)</B><BR>
|
|
<B>37h - CXPPMM (R) - Collision Latch P0-P1, M0-M1 (Bit 7,6) (Read only)</B><BR>
|
|
The TIA detects collisions between any of the 6 objects (the playfield and
|
|
5 moveable objects). There are 15 possible two-object collisions which are
|
|
stored in 15 one bit latches.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-5 Not used
|
|
6,7 Two Collsion Flags (0=No collision, 1=Collision occured)
|
|
</TD></TR></TABLE>The collision registers could be read at any time but is usually done
|
|
during vertical blank after all possible collisions have occurred.<BR>
|
|
Note: Use CXCLR to reset the collision latches after reading.<BR>
|
|
<BR>
|
|
<B>2Ch - CXCLR (W) <strobe> - Clear all collision latches</B><BR>
|
|
Writing any value to this address resets all collision latches
|
|
(CXM0P-CXPPMM) to zero.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videocolors"></A><FONT SIZE=+2> Video Colors</FONT></TD></TR></TABLE><BR>
|
|
See also CTRLPF.1 (SCORE), and SWCHB.3 (B/W) - and CTRLPF priority<BR>
|
|
<BR>
|
|
<B>06h - COLUP0 - Color Luminosity Player 0, Missile 0</B><BR>
|
|
<B>07h - COLUP1 - Color Luminosity Player 1, Missile 1</B><BR>
|
|
<B>08h - COLUPF - Color Luminosity Playfield, Ball</B><BR>
|
|
<B>09h - COLUBK - Color Luminosity Background</B><BR>
|
|
Selects color and luminance (brightness) for the specified object. The
|
|
console can display 128 colors (NTSC), or 104 colors (PAL), or 8 colors
|
|
(SECAM) on color TV sets, and 8 grayshades (NTSC/PAL/SECAM) on monochrome
|
|
TV sets.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0 Not used
|
|
1-3 NTSC/PAL Luminance (0-7) - SECAM: RGB (0-7) - Mono TV: Grayshade (0-7)
|
|
4-7 NTSC/PAL Color (0-15) - SECAM: Ignored - Mono TV: Ignored
|
|
</TD></TR></TABLE>A smaller luminance value drags the NTSC/PAL colors towards black, a
|
|
larger luminance value drags it towards white (pastelized). Software
|
|
should process the Color/Mono switch to select between different color
|
|
schemes for Color/Mono TV sets (if necessary). PAL Software may choose
|
|
luminance values that look okay both on Mono TV sets and on SECAM color TV
|
|
sets.<BR>
|
|
<BR>
|
|
<B>Color & Luminance Values</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> NTSC Colors PAL Colors NTSC/PAL Lum. SECAM RGB
|
|
0 White 0 White 0 Black 0 Black
|
|
1 Gold 1 Same as color 0 1 Dark grey 1 Blue
|
|
2 Orange 2 Yellow 2 ... 2 Red
|
|
3 Bright orange 3 Green-yellow 3 Grey 3 Magenta
|
|
4 Pink 4 Orange 4 ... 4 Green
|
|
5 Purple 5 Green 5 ... 5 Cyan
|
|
6 Purple-blue 6 Pink-orange 6 Light grey 6 Yellow
|
|
7 Blue 7 Green-blue 7 White 7 White
|
|
8 Blue 8 Pink
|
|
9 Light blue 9 Turquois
|
|
A Torq. A Pink-blue
|
|
B Green-blue B Light blue
|
|
C Green C Blue-red
|
|
D Yellow-green D Dark blue
|
|
E Orange-green E Same as color 0
|
|
F Light orange F Same as color 0
|
|
</TD></TR></TABLE><BR>
|
|
SECAM is a little weird. It takes the PAL software, but the console
|
|
color/black & white switch is hardwired as black & white. Therefore, it
|
|
reads the PAL black & white tables in software and assigns a fixed color
|
|
to each lum of black & white according to the table.<BR>
|
|
<BR>
|
|
<B>Screen Border Color</B><BR>
|
|
The screen border (HBLANK and VBLANK periods) is black.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="videopriority"></A><FONT SIZE=+2> Video Priority</FONT></TD></TR></TABLE><BR>
|
|
See also CTRLPF.1 (SCORE), and CTRLPF.2 (PRIORITY)<BR>
|
|
<BR>
|
|
<B>Object Colors and Priorities</B><BR>
|
|
When pixels of two or more objects overlap each other, only the pixel of
|
|
the object with topmost priority is drawn to the screen. The normal
|
|
priority ordering is:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Priority Color Objects
|
|
1 (highest) COLUP0 P0, M0 (and left side of PF in SCORE-mode)
|
|
2 COLUP1 P1, M1 (and right side of PF in SCORE-mode)
|
|
3 COLUPF BL, PF (only BL in SCORE-mode)
|
|
4 (lowest) COLUBK BK
|
|
</TD></TR></TABLE>Optionally, the playfield and ball may be assigned to have higher
|
|
priority (by setting CTRLPF.2). The priority ordering is then:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Priority Color Objects
|
|
1 (highest) COLUPF PF, BL (always, the SCORE-bit is ignored)
|
|
2 COLUP0 P0, M0
|
|
3 COLUP1 P1, M1
|
|
4 (lowest) COLUBK BK
|
|
</TD></TR></TABLE>Objects of the same color are having the same priority (it makes no
|
|
difference which pixel is drawn topmost if both pixels are having the
|
|
same color).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="intervaltimer"></A><FONT SIZE=+2> Interval Timer</FONT></TD></TR></TABLE><BR>
|
|
<B>284h - INTIM - PIA Current Timer Value (Read only)</B><BR>
|
|
Reading from this 8bit register returns the current timer value.<BR>
|
|
The initial value and interval can be set by TIM1T-T1024T registers.<BR>
|
|
<BR>
|
|
<B>285h - INSTAT - PIA Timer Status (Read only) (Undocumented)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-5 Not used (Seems to be always zero)
|
|
6 Underflow Flag 1 (1=Underflow, since last INSTAT read)
|
|
7 Underflow Flag 2 (1=Underflow, since last TIMnnT write)
|
|
</TD></TR></TABLE>Both bit 6 and 7 are set on underflow. Bit 6 is reset when reading from
|
|
INSTAT. Bit 7 is reset when writing to TIM1T..T1024T.<BR>
|
|
<BR>
|
|
<B>294h - TIM1T - PIA Set Timer & Select 1 clock interval (838ns/interval)</B><BR>
|
|
<B>295h - TIM8T - PIA Set Timer & Select 8 clock interval (6.7us/interval)</B><BR>
|
|
<B>296h - TIM64T - PIA Set Timer & Select 64 clock interval (53.6us/interval)</B><BR>
|
|
<B>297h - T1024T - PIA Set Timer & Select 1024 clock interval (858.2us/interval)</B><BR>
|
|
Writing a 8bit value in range of 00h..FFh to any of these four addresses
|
|
TIM1T-T1024T sets the timer to that value, and selects the prescaler
|
|
interval.<BR>
|
|
<BR>
|
|
<B>Normal Timer Decrement</B><BR>
|
|
The timer is decremented once immediately after writing (ie. value 00h
|
|
does immediately underflow). It is then decremented once every N clock
|
|
cycle interval (depending on the port address used).<BR>
|
|
<BR>
|
|
<B>Timer Underflow / Highspeed Decrement</B><BR>
|
|
Once when the timer does underflow, it restarts at FFh, and is then
|
|
decremented once per clock cycle, regardless of the selected interval
|
|
(this feature allows to calculate the exact underflow time at one clock
|
|
cycle resolution even if a larger interval was used).<BR>
|
|
<BR>
|
|
However, the interval is automatically re-actived when reading from the INTIM
|
|
register, ie. the timer does then continue to decrement at interval speed
|
|
(originated at the current value).<BR>
|
|
<BR>
|
|
<B>Note</B><BR>
|
|
The timer is particulary useful to specify and determine the end of the
|
|
vertical blanking periods (upper and lower screen border), allowing to
|
|
execute program code during that periods without permanent synchronization
|
|
with the cathode ray beam.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="audio"></A><FONT SIZE=+2> Audio</FONT></TD></TR></TABLE><BR>
|
|
The TIA chip is having two sound channels which are output, as mono signal,
|
|
to the TV set. According to the specs, it can make sounds like a "flute", a
|
|
"rocket motor", and an "explosion".<BR>
|
|
<BR>
|
|
<B>19h - AUDV0 - Audio Volume, Channel 0</B><BR>
|
|
<B>1Ah - AUDV1 - Audio Volume, Channel 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit 0-3, Volume 0-15 (0=Off, 15=Loudest)
|
|
</TD></TR></TABLE>Note: The recommended method to disable a sound channel is to set its
|
|
volume to zero.<BR>
|
|
Does that REALLY FULLY disable sound, or would it be required to be
|
|
combined with audc=0 to be fully muted ???<BR>
|
|
<BR>
|
|
<B>17h - AUDF0 - Audio Frequency Divider, Channel 0</B><BR>
|
|
<B>18h - AUDF1 - Audio Frequency Divider, Channel 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit 0-4, Frequency Divider (0..31 = 30KHz/1..30KHz/32)
|
|
</TD></TR></TABLE>The so-called "30KHz" is clocked twice per scanline, ie. at CPUCLK/38 aka
|
|
DOTCLK/114, so the exact rate is:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> PAL: 31113.1 Hz (3.546894MHz/114)
|
|
NTSC: 31399.5 Hz (3.579545MHz/114)
|
|
</TD></TR></TABLE>After applying the Frequency Divider, the resulting frequency is subsequently
|
|
divided by AUDC0/AUDC1, which provides additional division by 2, 6, 31, or 93
|
|
for pure tone; so the tone frequency range is circa 10Hz..15kHz (ie.
|
|
30KHz/32/93..30KHz/1/2).<BR>
|
|
<BR>
|
|
<B>15h - AUDC0 - Audio Noise/Division Control, Channel 0</B><BR>
|
|
<B>16h - AUDC1 - Audio Noise/Division Control, Channel 1</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> These registers control nine bit shift counters, and may select
|
|
different shift counter feedback taps and count lengths to produce
|
|
a variety of noise and tone qualities.
|
|
</TD></TR></TABLE>Bit 0-3, Noise/Division Control (0-15, see below)<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0 set to 1 8 9 bit poly (white noise)
|
|
1 4 bit poly 9 5 bit poly
|
|
2 div 15 -> 4 bit poly A div 31 : pure tone
|
|
3 5 bit poly -> 4 bit poly B set last 4 bits to 1
|
|
4 div 2 : pure tone C div 6 : pure tone
|
|
5 div 2 : pure tone D div 6 : pure tone
|
|
6 div 31 : pure tone E div 93 : pure tone
|
|
7 5 bit poly -> div 2 F 5 bit poly div 6
|
|
</TD></TR></TABLE>A setting of zero will disable the sound (PAL/NTSC), or it will produce an
|
|
"obnoxious background sound" (SECAM).<BR>
|
|
<BR>
|
|
<B>AUDC Pattern Shapes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> x Rep Pattern Shape
|
|
0 1 ----------------------------------------------------------------------
|
|
1 15 ----___-__--_-_----___-__--_-_----___-__--_-_----___-__--_-_----___-__
|
|
2 465 --------------------------------------------------------------________
|
|
3 465 ------______-___---__-----___-------___----___--__--_____---------___-
|
|
4 2 -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
|
|
5 2 -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
|
|
6 31 ------------------_____________------------------_____________--------
|
|
7 31 -----___--_---_-_-____-__-_--__-----___--_---_-_-____-__-_--__-----___
|
|
8 511 ---------_____----_-----___-_---__--__-_____-__-_-__---_--_-___----__-
|
|
9 31 -----___--_---_-_-____-__-_--__-----___--_---_-_-____-__-_--__-----___
|
|
A 31 ------------------_____________------------------_____________--------
|
|
B 1 ----------------------------------------------------------------------
|
|
C 6 ---___---___---___---___---___---___---___---___---___---___---___---_
|
|
D 6 ---___---___---___---___---___---___---___---___---___---___---___---_
|
|
E 93 -------------------------------------------------_____________________
|
|
F 93 ----------_____---_______----__________------___------____---------___
|
|
</TD></TR></TABLE><BR>
|
|
<B>AUDC Pattern Type Notes</B><BR>
|
|
Types 1,8,9 produce 4bit,9bit,5bit poly sound (see Formulas below).<BR>
|
|
Type 7 produces exactly the same sound as Type 9 (the additional "div2" is
|
|
eventually meant to use div2 transitions as clock, which is identical as
|
|
normal 1 cycle clock).<BR>
|
|
Type 2 fetches next 4bit poly (type 1) on each div31 (type 6) transition, the
|
|
duration of each Poly4 bit is thus multiplied by 18 or by 13.<BR>
|
|
Type 3 uses the most complicated mechanism (for reverse engineering). The
|
|
Poly5 operation takes place each cycle. If Poly5-Carry is 1, then the 4bit
|
|
poly operation is executed and the Poly4-Carry is output to the sound
|
|
channel, otherwise Poly4 (and sound output) are kept unchanged.<BR>
|
|
Types 4,5 both produce div2 tone, consisting of 1 HIGH and 1 LOW cycle.<BR>
|
|
Types 6,A both produce div31 tone, consisting of 18 HIGH and 13 LOW cycles
|
|
(that odd numbers are eventually based on 5bit poly being applied only when
|
|
lower 4bits all same, maybe).<BR>
|
|
Types 0,B both produce a permanent HIGH signal and the sound is effectively
|
|
disabled (at least with PAL/NTSC, however SECAM reportedly produces
|
|
"obnoxious background sound" in this case).<BR>
|
|
Types C,D,E,F are using same mechanism as types 4,5,6,7 but only each 3rd
|
|
transition is applied.<BR>
|
|
<BR>
|
|
<B>Internal Poly Formulas</B><BR>
|
|
Poly/Noise is generated by shift/xor operations. The rightmost bit of the
|
|
shift register is output to the sound channel (0=low, 1=high). The register
|
|
is shifted right and the new leftmost bit is calculated by an XOR operation:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> poly old bits output new bits calculation
|
|
4bit abcd d zabc z = c xor d
|
|
5bit abcde e zabcd z = c xor e
|
|
9bit abcdefghi i zabcdefgh z = e xor i
|
|
</TD></TR></TABLE><BR>
|
|
<B>Internal Poly Bitstreams</B><BR>
|
|
Below are example bitstreams, the rightmost bit is output to the sound
|
|
channel, the two x-marked bits are XORed by each other and used as new
|
|
leftmost bit in next cycle. The dots "..." indicate frozen poly4 settings.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 4bit 5bit 9bit poly 5bit->4bit
|
|
---xx- ---x-x- -----x---x- ---x-x---xx-
|
|
1111 11111 111111111 10011 1111
|
|
0111 01111 011111111 11001 0111
|
|
0011 00111 001111111 11100 ...1
|
|
0001 00011 000111111 11110 ...1
|
|
1000 10001 000011111 11111 0011
|
|
0100 11000 000001111 01111 0001
|
|
0010 01100 100000111 00111 1000
|
|
1001 10110 110000011 00011 0100
|
|
1100 11011 111000001 10001 0010
|
|
0110 11101 111100000 11000 ...0
|
|
1011 01110 011110000 01100 ...0
|
|
0101 10111 101111000 10110 ...0
|
|
1010 01011 110111100 11011 1001
|
|
1101 10101 111011110 11101 1100
|
|
1110 01010 111101111 01110 ...0
|
|
1111 00101 111110111 10111 0110
|
|
0111 00010 011111011 01011 1011
|
|
0011 00001 001111101 10101 0101
|
|
0001 10000 000111110 01010 ...1
|
|
1000 01000 100011111 00101 1010
|
|
0100 00100 010001111 00010 ...0
|
|
0010 10010 101000111 00001 1101
|
|
1001 01001 110100011 10000 ...1
|
|
1100 10100 111010001 01000 ...1
|
|
0110 11010 011101000 00100 ...1
|
|
1011 01101 001110100 10010 ...1
|
|
0101 00110 100111010 01001 1110
|
|
1010 10011 110011101 10100 ...0
|
|
1101 11001 011001110 11010 ...0
|
|
1110 11100 001100111 01101 1111
|
|
1111 11110 100110011 00110 ...1
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllers"></A><FONT SIZE=+2> Controllers</FONT></TD></TR></TABLE><BR>
|
|
<B>Specific Controller Types</B><BR>
|
|
<A HREF="#controllersjoysticks">Controllers: Joysticks</A><BR>
|
|
<A HREF="#controllerspaddles">Controllers: Paddles</A><BR>
|
|
<A HREF="#controllerskeypad">Controllers: Keypad</A><BR>
|
|
<A HREF="#controllerssteering">Controllers: Steering</A><BR>
|
|
<A HREF="#controllerslightgun">Controllers: Lightgun</A><BR>
|
|
<A HREF="#controllerstrackball">Controllers: Trackball</A><BR>
|
|
<A HREF="#controllersother">Controllers: Other</A><BR>
|
|
<BR>
|
|
<B>Basic Tech Info</B><BR>
|
|
<A HREF="#controllersconsoleswitches">Controllers: Console Switches</A><BR>
|
|
<A HREF="#controllersioregisters">Controllers: I/O Registers</A><BR>
|
|
<A HREF="#controllersexternalportpinouts">Controllers: External Port Pin-Outs</A><BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllersjoysticks"></A><FONT SIZE=+2> Controllers: Joysticks</FONT></TD></TR></TABLE><BR>
|
|
Joysticks are the most common controllers. Two joysticks can be connected.<BR>
|
|
<BR>
|
|
<B>Normal 4-Direction / 1-Button Joysticks</B><BR>
|
|
Configure Port A as input (SWACNT=00h). Joystick data can be then read
|
|
from SWCHA and INPT4-5 as follows:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin PlayerP0 PlayerP1 Expl.
|
|
1 SWCHA.4 SWCHA.0 Up (0=Moved, 1=Not moved)
|
|
2 SWCHA.5 SWCHA.1 Down ("")
|
|
3 SWCHA.6 SWCHA.2 Left ("")
|
|
4 SWCHA.7 SWCHA.3 Right ("")
|
|
6 INPT4.7 INPT5.7 Button (0=Pressed, 1=Not pressed)
|
|
</TD></TR></TABLE>Note: Connect all direction switches and push buttons to GND (Pin 8).<BR>
|
|
<BR>
|
|
<B>3-Button Joystick Adapter</B><BR>
|
|
The device fits on the shaft of standard Atari joysticks, it includes two
|
|
additional buttons, and is connected by separate cable between the normal
|
|
joystick plug and consoles joystick port.<BR>
|
|
The device comes up without any external pullup/pulldown resistors, it acts
|
|
somewhat similar than leftmost/rightmost paddle positions and must deal with
|
|
the capacitors/resistors inside of the console (see Paddles chapter for
|
|
details).<BR>
|
|
In general, software must drag INPT0-3 to ground for a moment (eg. during
|
|
vertical blanking period):<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin Bit Expl.
|
|
5,9 VBLANK.7 INPT0-INPT3 Control (0=Normal Input, 1=Dumped to ground)
|
|
</TD></TR></TABLE>Software must then wait a moment (eg. until end of picture drawing period)
|
|
before it can read the adapters button states:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin PlayerP0 PlayerP1 Expl.
|
|
5 INPT0.7 INPT2.7 2nd Button (1=Pressed/Charged)
|
|
9 INPT1.7 INPT3.7 3rd Button (1=Pressed/Charged)
|
|
</TD></TR></TABLE>Note: Connect the extra buttons to VCC (Pin 7).<BR>
|
|
The 3-button adapter is used by Omega Race and Thrust (both games aren't
|
|
actually using all 3 buttons for 3 unique purposes though).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllerspaddles"></A><FONT SIZE=+2> Controllers: Paddles</FONT></TD></TR></TABLE><BR>
|
|
A paddle consists of single knob (similar like the volume control of HiFi
|
|
amplifiers), and a single push button. Two paddles can be connected to
|
|
each port (four paddles can be used when using both ports). Paddles are
|
|
usually shipped as pair of two controllers which are attached (by Y-cable)
|
|
to a single plug.<BR>
|
|
<BR>
|
|
To read paddle buttons, configure SWCHA as input (SWACNT=00h), then read
|
|
from SWCHA:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin Bit Expl.
|
|
3 SWCHA.2 Paddle #3 button (right paddle, P1) (0=Pressed)
|
|
4 SWCHA.3 Paddle #2 button (left paddle, P1)
|
|
3 SWCHA.6 Paddle #1 button (right paddle, P0)
|
|
4 SWCHA.7 Paddle #0 button (left paddle, P0)
|
|
</TD></TR></TABLE>To read paddle pots, switch INPT0-3 to LOW by setting VBLANK.7, this
|
|
discharges the 68nF capacitors (inside of the console), then reset
|
|
VBLANK.7 again, the capacitors are now charged through linear 1M Ohm
|
|
potentiometers in the paddle (in series with 1.8K Ohm resistors in the
|
|
console).<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin Bit Expl.
|
|
5,9 VBLANK.7 INPT0-INPT3 Control (0=Normal Input, 1=Dumped to ground)
|
|
</TD></TR></TABLE>Then measure the time it takes until INPTx pins are getting high:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin Bit Expl.
|
|
9 INPT3.7 Paddle #3 pot (right paddle, P1) (1=Charged/Ready)
|
|
5 INPT2.7 Paddle #2 pot (left paddle, P1)
|
|
9 INPT1.7 Paddle #1 pot (right paddle, P0)
|
|
5 INPT0.7 Paddle #0 pot (left paddle, P0)
|
|
</TD></TR></TABLE>Note: Connect buttons to GND (Pin 8), pots to VCC (Pin 7), leave 3rd pot
|
|
pin not connected.<BR>
|
|
<BR>
|
|
<B>POT Timing Table (counted in scanline units)</B><BR>
|
|
Analogue timings are, of course, unstable. Expect the scanline count to
|
|
vary by at least +/-1 even if the POT is not moved. Counter range may vary
|
|
with different hardware, depending on accuracy/tolerance of the components
|
|
in the paddle and in the console, and on the room temperature. Also,
|
|
larger counter values may be measured when the circuit has warmed up
|
|
(after some minutes of operation).<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Position Left <--------- Center ---------> Right
|
|
Degrees -135 -90 -45 0 +45 +90 +135
|
|
Ohms 1M ... ... 500K ... ... 0
|
|
Scanlines 380 ... ... 190 ... ... 0
|
|
</TD></TR></TABLE>Note that it may take two or more frames until the maximum count is
|
|
reached, ideally, software should check INPTs throughout drawing and
|
|
blanking periods, and carry on in the next frame. Implement a timeout
|
|
after 1000 scanlines (to prevent the software getting hung, and/or to
|
|
detect the presence of paddles).<BR>
|
|
<BR>
|
|
According to AtariAge FAQ, paddles are used by 31 games: Astroblast
|
|
(joystick ok too), Bachelor Party, Backgammon, Beat Em' & Eat Em,
|
|
Blackjack, Breakout (Breakaway IV), Bugs, Bumper Bash, Canyon Bomber,
|
|
Casino (Poker Plus), Circus Atari (Circus), Demons to Diamonds,
|
|
Eggomania, Encounter at L-5, Fireball, Guardian, Kaboom!, Music Machine,
|
|
Night Driver, Party Mix, Picnic, Piece O Cake, Solar Storm, Star Wars:
|
|
Jedi Arena, Steeplechase, Street Racer (Speedway II), Super Breakout,
|
|
Tac-Scan, Video Olympics (Pong Sports), Warlords, Warplock.<BR>
|
|
Also by "actionmn.bin" ???<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllerskeypad"></A><FONT SIZE=+2> Controllers: Keypad</FONT></TD></TR></TABLE><BR>
|
|
The keypad or touchpad controller has 12 buttons arranged into 4 rows and
|
|
3 columns. The names "0..9,#,*" are printed directly on the controller.
|
|
Aside from this predefined names, software is usually shipped with
|
|
overlays: small cards (with holes for the keys) with custom names or
|
|
symbols printed on the card. The Basic Programming cartridge uses two
|
|
separate keypads (giving it 24 keys in total).<BR>
|
|
<BR>
|
|
To access the keypad, configure SWCHA as output (SWACNT=FFh), then select
|
|
a row by writing to SWCHA, then wait 400us, then read column bits from
|
|
INPTx registers.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin PlayerP0 PlayerP1 Dir Expl. Keys
|
|
1 SWCHA.4 SWCHA.0 Out Upper row (0=Select) 1,2,3
|
|
2 SWCHA.5 SWCHA.1 Out Second row (0=Select) 4,5,6
|
|
3 SWCHA.6 SWCHA.2 Out Third row (0=Select) 7,8,9
|
|
4 SWCHA.7 SWCHA.3 Out Bottom row (0=Select) *,0,#
|
|
5 INPT0.7 INPT2.7 In Left column (0=Pressed) 1,4,7,*
|
|
9 INPT1.7 INPT3.7 In Middle column (0=Pressed) 2,5,8,0
|
|
6 INPT4.7 INPT5.7 In Right column (0=Pressed) 3,6,9,#
|
|
</TD></TR></TABLE>Note: Pin 9 and 5 require external 4.7K Ohm pullups to pin 7.<BR>
|
|
<BR>
|
|
According to AtariAge FAQ, kid's controllers/keypads are used by 11
|
|
games: A Game of Concentration (Hunt & Score Memory Match), Alpha Beam
|
|
with Ernie, BASIC Programming, Big Bird's Egg Catch, Brain Games,
|
|
Codebreaker, Cookie Monster Munch, Grover's Music Maker (prototype),
|
|
MagiCard, Oscar's Trash Race, Star Raiders.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllerssteering"></A><FONT SIZE=+2> Controllers: Steering</FONT></TD></TR></TABLE><BR>
|
|
Which 2600 games use the driving controllers?<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Indy 500 and
|
|
Stell-A-Sketch (homebrew program)
|
|
</TD></TR></TABLE>The device looks about exactly like a paddle, using a knob as steering
|
|
'wheel', and a push button. Unlike paddles, only one device can be
|
|
connected to each game port (ie. no Y-cable pairs). Also unlike paddles,
|
|
the knob is attached to a 16 position rotary binary switch, which allows
|
|
endless rotation (ie. by more than 360 degrees).<BR>
|
|
Even though the 16 position switch provides 4 bit combinations, only 2
|
|
bits are connected, the output starts over at zero once every four
|
|
positions.<BR>
|
|
Configure Port A as input (SWACNT=00h). Steering data can be then read
|
|
from SWCHA and INPT4-5 as follows:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin PlayerP0 PlayerP1 Expl.
|
|
1 SWCHA.4 SWCHA.0 Pos (0=Closed, 1=Not closed)
|
|
2 SWCHA.5 SWCHA.1 Pos ("")
|
|
6 INPT4.7 INPT5.7 Button (0=Pressed, 1=Not pressed)
|
|
</TD></TR></TABLE>Note: Connect switch and push buttons to GND (Pin 8).<BR>
|
|
<BR>
|
|
16 Position Real Code Binary Rotary DIP-Switch:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> ________
|
|
| BIT1 |____________________ Pin 1 (Up)
|
|
| BIT2 |__ |__ ____
|
|
| BIT3 |__ |XOR \___ Pin 2 (Down)
|
|
| BIT0 |___________|____/
|
|
| Rotary | |__ ____ Pin 7 (Vcc)
|
|
| DIP | [10K]
|
|
| Switch |____________________ Pin 8 (Gnd)
|
|
| GND | | Button
|
|
|________| |___o--o____ Pin 6 (Button)
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllerslightgun"></A><FONT SIZE=+2> Controllers: Lightgun</FONT></TD></TR></TABLE><BR>
|
|
<B>Lightgun</B><BR>
|
|
The XG-1 lightgun has been released in 1987 (originally for use with Atari XE
|
|
computers). There are only a few Atari 2600 games supporting it:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Sentinel (1990) (Atari)
|
|
Shooting Arcade (prototype only)
|
|
Bobby needs Food (homebrew)
|
|
Guntest (homebrew test program) (Eckhard Stolberg)
|
|
</TD></TR></TABLE>"You can deduce the atari lightgun pinout combinig the sega light phaser
|
|
pinout with the schematic for the SMS gun to 7800 adapter. It should be like
|
|
this:"<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 1 trigger (active high)
|
|
2 -
|
|
3 -
|
|
4 -
|
|
5 -
|
|
6 light sensor (active low)
|
|
7 +5V
|
|
8 GND
|
|
9 -
|
|
</TD></TR></TABLE>So if the lightgun is connected in the left controller port you have:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> bit 4 of SWCHA = 1 if the trigger is pressed, 0 otherwise.
|
|
bit 7 of INPT4 = 0 if the sensor sees light, 1 otherwise.
|
|
</TD></TR></TABLE>If in the right controller port:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> bit 0 of SWCHA = 1 if the trigger is pressed, 0 otherwise.
|
|
bit 7 of INPT5 = 0 if the sensor sees light, 1 otherwise.
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllerstrackball"></A><FONT SIZE=+2> Controllers: Trackball</FONT></TD></TR></TABLE><BR>
|
|
The Atari "Trak-Ball" is some unreal thing.<BR>
|
|
<BR>
|
|
<B>Existing Trackball Hardware</B><BR>
|
|
Atari does have produced trackballs. In fact, they have even produced a whole
|
|
mess of different/incompatible variants, often without even changing the
|
|
CX-22 and CX-80 product numbers:<BR>
|
|
Trackballs with DIFFERENT product numbers aren't ALWAYS compatible with each
|
|
other. And worse, trackballs with SAME product numbers aren't ALWAYS
|
|
compatible with themselves.<BR>
|
|
<BR>
|
|
<B>Existing Trackball Software</B><BR>
|
|
Basically, there is NONE. The CX-22 manual states that the thing can be used
|
|
with Atari 2600 joystick games, and, in trackball mode, with special games -
|
|
but none such special games have been ever released for the Atari 2600. The
|
|
only exception is a homebrew hack of the Missile Command game (the game is
|
|
originally joystick controlled; different versions of the hack allow to use
|
|
it in trackball mode & in Atari/Amiga mouse modes).<BR>
|
|
<BR>
|
|
<B>Atari Trak-Ball Schematic</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> GND--||-------o----------------------------------- XCLK/Pin2 ;\Trackball
|
|
470pF | .------------. 100nF (YCLK/Pin4) ;/Mode
|
|
VCC---[10K]---o VCC--|RST 4538 C|--||--.
|
|
| VCC--|-TR multi RC|------o--[91K]--VCC
|
|
X1--o--[430K]---o .--|+TR vibr. Q|--.
|
|
(Y1) | .-----. | | '------------' | .----.
|
|
'--|+ | | | .--------. o--|4011|
|
|
|LM339|--o-----o--|D | | |NAND|-- Right/Pin4 ;\
|
|
Vref--|- | | Q|---------| | (Down/Pin2) ;
|
|
'-----' | 4113 /Q|---. | '----' ; Joystick
|
|
VCC---[10K]---. | flip | | | .----. ; Mode
|
|
| | flop | | '--|4011| ;
|
|
X2--o--[430K]---o | | | |NAND|-- Left/Pin2 ;
|
|
(Y2) | .-----. | GND--|SET | o-----| | (Up/Pin1) ;/
|
|
'--|+ | | GND--|RES | | '----'
|
|
|LM339|--o--------|CK | '------------- XDIR/Pin1 ;\Trackball
|
|
Vref--|- | '--------' (YDIR/Pin3) ;/Mode
|
|
'-----' ____
|
|
Vref--------. GND--o o--. VCC--[L1]--Pin7 ;\Supply
|
|
| ____ | GND--------Pin8 ; and Fire
|
|
GND--[8K1]--o--[100K]---VCC GND--o o--o-------- Fire/Pin6 ;/
|
|
</TD></TR></TABLE>The schematic is showing only X-Axis (and equivalent signals for Y-Axis in
|
|
brackets). Mode selection via 4019/4030 isn't shown. Component list is:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> LM339 quad comperator/amplifier ;-mouse and all trak-ball versions
|
|
4113 dual flip flop ;\
|
|
4538 dual multivibrator ; all trak-ball versions only
|
|
4011 quad NAND gates ;/
|
|
4019 eight-to-four multiplexer ;-trak-ball with trackball-mode only
|
|
4030 quad XOR gates ;-trak-ball with mouse-mode only
|
|
SW two position switch ;-trak-ball with trackball or mouse mode only
|
|
</TD></TR></TABLE><BR>
|
|
<B>Joystick Mode</B><BR>
|
|
The low-level X1/X2 signals are amplified via LM339. X2 raising edge is
|
|
loading X1 as direction bit into the flip-flop, which is then output to
|
|
joystick Left/Right signals accordingly. If the trackball isn't moved, then
|
|
the multivibrator and NAND gates will mask off the signals.<BR>
|
|
Joystick mode is compatible with normal joystick games, but aside from that,
|
|
it's just crap: the "analog" speed/direction informations are lost, and the
|
|
result is likely to be less precise than real joysticks.<BR>
|
|
<BR>
|
|
<B>Trackball Mode</B><BR>
|
|
This version contains a J/T mode switch and multiplexer which bypasses the
|
|
multivibrator and NAND stuff: The amplified X1 is directly output as XCLK
|
|
signal (toggles when ball is moved), and the /Q flipflop output is output as
|
|
direction signal.<BR>
|
|
<BR>
|
|
<B>Mouse Mode</B><BR>
|
|
The Atari mouse does contain only the LM339 chip, and amplified X1/X2 signals
|
|
are then output directly to the joystick port. The Amiga mouse works the
|
|
same, but has swapped pins on the connector.<BR>
|
|
The Trak-Ball with mouse-mode is containing flipflop, multivibrator, and NAND
|
|
gates for joystick mode, and extra XOR gates for mouse mode (details are
|
|
unknown, not quite clear if/how the XOR gates can switch between mouse and
|
|
joystick modes).<BR>
|
|
<BR>
|
|
<B>Trackball & Mouse - Models & Modes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Type/Modes Joystick Trackball Atari-Mouse Amiga-Mouse
|
|
Old Atari CX-22 Trak-Ball Yes - - -
|
|
New Atari CX-22 Trak-Ball Yes Yes - -
|
|
Old Atari CX-80 Trak-Ball Yes Yes - -
|
|
New Atari CX-80 Trak-Ball Yes? - Yes -
|
|
Atari Mouse - - Yes -
|
|
Amiga Mouse - - - Yes
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllersother"></A><FONT SIZE=+2> Controllers: Other</FONT></TD></TR></TABLE><BR>
|
|
<B>Foot Craz</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Video Jogger (Exus)
|
|
Video Reflex (Exus)
|
|
</TD></TR></TABLE><BR>
|
|
<B>Joyboard</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Mogul Maniac (Amiga)
|
|
Off Your Rocker (Amiga)
|
|
Surf's Up (Amiga)
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllersconsoleswitches"></A><FONT SIZE=+2> Controllers: Console Switches</FONT></TD></TR></TABLE><BR>
|
|
Aside from external controllers, the console includes five built-in
|
|
switches or buttons.<BR>
|
|
<BR>
|
|
<B>Accessing Console Switches</B><BR>
|
|
Configure Port B as input (SWBCNT=00h). Switch/Button data can be then
|
|
read from SWCHB as follows:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
SWCHB.0 Reset Button (0=Pressed)
|
|
SWCHB.1 Select Button (0=Pressed)
|
|
SWCHB.2 Not used
|
|
SWCHB.3 Color Switch (0=B/W, 1=Color) (Always 0 for SECAM)
|
|
SWCHB.4-5 Not used
|
|
SWCHB.6 P0 Difficulty Switch (0=Beginner (B), 1=Advanced (A))
|
|
SWCHB.7 P1 Difficulty Switch (0=Beginner (B), 1=Advanced (A))
|
|
</TD></TR></TABLE>Note: Older consoles used switches instead of buttons for reset/select.<BR>
|
|
SECAM consoles do not include a color switch (Bit 3 is grounded).<BR>
|
|
<BR>
|
|
<B>Software Switches/Buttons</B><BR>
|
|
Above buttons/switches may (or may not) be used by software for whatever
|
|
purpose. Namely, the Reset Button does not reset any hardware, and the
|
|
Color Switch does not have any effect on the video output (unless the
|
|
software processes it as such).<BR>
|
|
<BR>
|
|
<B>Hardware Switches</B><BR>
|
|
On the contrary, the Power Switch and TV Channel Select Switch cannot be
|
|
processed by software.<BR>
|
|
<BR>
|
|
<B>Data Direction Register (SWBCNT)</B><BR>
|
|
Port B is hardwired to console switches (inputs), normally SWBCNT should
|
|
be always 00h. However, the three unused bits could be configured as
|
|
output, the respective SWCHB bits can be then used to store 3bits of
|
|
custom read/writeable data (as done by Combat).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllersioregisters"></A><FONT SIZE=+2> Controllers: I/O Registers</FONT></TD></TR></TABLE><BR>
|
|
<B>38h - INPT0 (R) - 1....... TIA Dumped Input Port 1 (Pot 1)</B><BR>
|
|
<B>39h - INPT1 (R) - 1....... TIA Dumped Input Port 2 (Pot 2)</B><BR>
|
|
<B>3Ah - INPT2 (R) - 1....... TIA Dumped Input Port 3 (Pot 3)</B><BR>
|
|
<B>3Bh - INPT3 (R) - 1....... TIA Dumped Input Port 4 (Pot 4)</B><BR>
|
|
As long as bit 7 of register VBLANK is zero, these four ports are
|
|
general purpose high impedance input ports. When this bit is a 1 these
|
|
ports are grounded.<BR>
|
|
INPT0-3 can be used to read up to four paddle controllers, and, INPT0-1
|
|
can be used to read Keyboard columns 0 and 1.<BR>
|
|
<BR>
|
|
<B>3Ch - INPT4 (R) - 1....... TIA Latched Input Port 4</B><BR>
|
|
<B>3Dh - INPT5 (R) - 1....... TIA Latched Input Port 5</B><BR>
|
|
These two ports have latches that are both enabled by writing a "1" or
|
|
disabled by writing a "0" to D6 of VBLANK.<BR>
|
|
When disabled, the microprocessor reads the logic level of the port
|
|
directly.<BR>
|
|
When enabled, the latch is set for logic one and remains that way until
|
|
its port goes LOW (not sure what happens if it was already LOW ???).
|
|
When the port goes LOW the latch goes LOW and remains that way (until
|
|
re-disabled by VBLANK Bit 6) regardless of what the port does.<BR>
|
|
<BR>
|
|
<B>280h - SWCHA - PIA Port A; input or output (R/W)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-7 Data Inputs or Outputs (Direction depends on SWACNT)
|
|
</TD></TR></TABLE>Used to access various types of external controllers (joysticks, paddles,
|
|
or keyboard, etc.).<BR>
|
|
<BR>
|
|
<B>281h - SWACNT - PIA Port A DDR Data Direction Register (R/W)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-7 Data Direction for SWCHA Bit 0-7 (0=Input, 1=Output)
|
|
</TD></TR></TABLE>Use value 00h for joysticks and paddles. Use FFh for keypad.<BR>
|
|
<BR>
|
|
<B>282h - SWCHB - PIA Port B, Console Switches (R/W) (normally Read Only)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-7 Data Inputs or Outputs (Direction depends on SWBCNT)
|
|
</TD></TR></TABLE>Used to read console switches/buttons.<BR>
|
|
<BR>
|
|
<B>283h - SWBCNT - PIA Port B DDR Data Direction Register (R/W)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Expl.
|
|
0-7 Data Direction for SWCHB Bit 0-7 (0=Input, 1=Output)
|
|
</TD></TR></TABLE>Should be always 00h for reading buttons or switches.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="controllersexternalportpinouts"></A><FONT SIZE=+2> Controllers: External Port Pin-Outs</FONT></TD></TR></TABLE><BR>
|
|
<B>Joystick Ports (two ports, male 9pin SUBD each)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Pin Port 1 Port 2 Joystick Paddles Keyboard .---------.
|
|
1 SWCHA.4 SWACH.0 Up - Row 0 | 1 2 3 4 5 |
|
|
2 SWCHA.5 SWACH.1 Down - Row 1 \ 6 7 8 9 /
|
|
3 SWCHA.6 SWCHA.2 Left Button 1 Row 2 '-------'
|
|
4 SWCHA.7 SWCHA.3 Right Button 0 Row 3
|
|
5 INPT0 INPT2 - Pot 0 Column 0
|
|
6 INPT4 INPT5 Button - Column 2
|
|
7 +5V +5V - VCC/Pot Pull-ups
|
|
8 GND GND GND GND/Butt -
|
|
9 INPT1 INPT3 - Pot 1 Column 1
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartridges"></A><FONT SIZE=+2> Cartridges</FONT></TD></TR></TABLE><BR>
|
|
<A HREF="#cartrawromunbanked">Cart Raw ROM (unbanked)</A><BR>
|
|
<A HREF="#cart4kbankingbyportffxxh">Cart 4K-Banking (by Port FFxxh)</A><BR>
|
|
<A HREF="#cart2kbankingbyportffxxh">Cart 2K-Banking (by Port FFxxh)</A><BR>
|
|
<A HREF="#cart1kbankingbyportffxxh">Cart 1K-Banking (by Port FFxxh)</A><BR>
|
|
<A HREF="#cart2kbankingbyport3fh">Cart 2K-Banking (by Port 3Fh)</A><BR>
|
|
<A HREF="#cart4kbankingbyjsrrtsopcodes">Cart 4K-Banking (by JSR/RTS opcodes)</A><BR>
|
|
<A HREF="#cartpitfall2">Cart Pitfall 2</A><BR>
|
|
<A HREF="#cartexpansionram">Cart Expansion RAM</A><BR>
|
|
<A HREF="#cartpinouts">Cart Pin-Outs</A><BR>
|
|
<A HREF="#cartsummaryandgeneralinfo">Cart Summary and General Info</A><BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartrawromunbanked"></A><FONT SIZE=+2> Cart Raw ROM (unbanked)</FONT></TD></TR></TABLE><BR>
|
|
<B>4K and 2K ROMs</B><BR>
|
|
Cartridges of 4KBytes fit directly into the 4K cartridge area.<BR>
|
|
Cartridges of 2KBytes are mirrored twice in the 4K cartridge area.<BR>
|
|
<BR>
|
|
<B>Smaller ROMs</B><BR>
|
|
Cartridges of 1KByte size haven't been manufactured, however, some
|
|
homebrewn games may or may not use that filesize. A strange example is
|
|
"Cave 1K", which is actually "2K", because it inserts 1024 bytes padding
|
|
between (!) the program code and the reset vector (eventually intended for
|
|
compatibility with software that accepts only 2K rom-images as minimum
|
|
filesize).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cart4kbankingbyportffxxh"></A><FONT SIZE=+2> Cart 4K-Banking (by Port FFxxh)</FONT></TD></TR></TABLE><BR>
|
|
The bank number is selected by reading from (or by writing any value to)
|
|
specific addresses, the addresses and corresponding bank numbers are:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Size Banks FFF4 FFF5 FFF6 FFF7 FFF8 FFF9 FFFA FFFB
|
|
2K,4K 1 - - - - - - - -
|
|
8K 2 - - - - 0 1 - -
|
|
12K 3 - - - - 0 1 2 -
|
|
16K 4 - - 0 1 2 3 - -
|
|
32K 8 0 1 2 3 4 5 6 7
|
|
</TD></TR></TABLE>Banks are usually selected by "BIT FFFx" opcodes, after execution of
|
|
such opcodes the program counter is PC=PC+3, the new bank must contain
|
|
valid code at that address (that is usually implemented by placing code
|
|
at fixed addresses at the beginning or end of each ROM bank).<BR>
|
|
The initial bank number is undefined upon power-on, so each bank should
|
|
contain a valid entry point at [FFFC], and a small power-on procedure.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cart2kbankingbyportffxxh"></A><FONT SIZE=+2> Cart 2K-Banking (by Port FFxxh)</FONT></TD></TR></TABLE><BR>
|
|
burgtime,he_man: eight 2K banks (16K)<BR>
|
|
also used by bnj (but first 8K empty, only upper 8K used)<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> FFE0-FFE7 bank 0-7 for F000-F7FF
|
|
FFE8 used by burgtime ONLY, don't know, initialize something ???
|
|
expansion RAM at F800-F9FF
|
|
bank 7 fixed at FA00-FFFF
|
|
</TD></TR></TABLE><BR>
|
|
The game BNJ consists of four 2K banks. Bank 3 is permanently mapped to
|
|
F800-FFFF, and either bank 0,1,2 can be mapped to F000-F7FF, selected by
|
|
accessing FFE4,FFE5,FFE6. Note: For whatever reason, the Bnj.bin
|
|
rom-image at AtariAge is 16K, the first 8K are empty, the other 8K
|
|
contain bank 0-3. (NB. this obscure file format allows to detect
|
|
2K-banking.)<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cart1kbankingbyportffxxh"></A><FONT SIZE=+2> Cart 1K-Banking (by Port FFxxh)</FONT></TD></TR></TABLE><BR>
|
|
<B>Memory Addresses for 8x1K (8K) Banking</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> FFE0-FFE7 bank 0-7 for F000-F3FF
|
|
FFE8-FFEF bank 0-7 for F400-F7FF
|
|
FFF0-FFF7 bank 0-7 for F800-FBFF
|
|
bank 7 fixed at FC00-FFFF
|
|
</TD></TR></TABLE>Used by: Popeye, Gyruss, Sprcobra, Tutank, Dethstar, Qbrtcube, Ewokadvn,
|
|
Montzrev, Frogger2, Lordofth, James_bo, Swarcade, Toothpro.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cart2kbankingbyport3fh"></A><FONT SIZE=+2> Cart 2K-Banking (by Port 3Fh)</FONT></TD></TR></TABLE><BR>
|
|
<B>Memory Addresses for Port 3Fh 4x2K (8K) Banking</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> MOV [3F],n bank 0-2 for F000-F7FF
|
|
bank 3 fixed at F800-FFFF
|
|
</TD></TR></TABLE>Used by: Springer, Espial, Minrvol2, Mnr2049r, Riverp, Polaris.<BR>
|
|
<BR>
|
|
this port is NOT to be mirrored to [7F] - mnr2049r zerofills 40..FF memory<BR>
|
|
on power-on must be initially BANK 3 (polaris entrypt=7000, mirror of 7800)<BR>
|
|
access normal TIA ports only by mirrors at 40h-7Fh!<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cart4kbankingbyjsrrtsopcodes"></A><FONT SIZE=+2> Cart 4K-Banking (by JSR/RTS opcodes)</FONT></TD></TR></TABLE><BR>
|
|
JSR/RTS for banking (2x4K) (8K)<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> bank1 select by CALL DXXX opcode,
|
|
bank0 select by RET FXXX opcode
|
|
</TD></TR></TABLE>Used by Decathln only.<BR>
|
|
<BR>
|
|
does not use any PUSH/POP, banking done by STACK accesses, probably only
|
|
if SP.Bit0 is set (or cleared)<BR>
|
|
detect by clearmem-loop at F000, followed by call D000 opcode<BR>
|
|
entrypoint in bank0 only!<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartpitfall2"></A><FONT SIZE=+2> Cart Pitfall 2</FONT></TD></TR></TABLE><BR>
|
|
The Pitfall 2 cartridge includes eight counters. (Five sequential
|
|
video/data channels with automatically decrementing pointers, and one
|
|
3-channel audio/data generator). The program can read from the channels
|
|
and can then write the data directly to the TIA ports (without having to
|
|
adjust pointers/counters by software).<BR>
|
|
<BR>
|
|
<B>Cartridge I/O Map</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Channel Data Mask Max/y1 Min/y2 Lsb Msb
|
|
ch0 video 1008 1010 1040 1048 1050 1058
|
|
ch1 video 1009 - - - 1051 1059
|
|
ch2 video 100A - - - 1052 105A
|
|
ch3 video 100B 1013 1043 104B 1053 105B
|
|
ch4 video 100C - - - 1054 105C
|
|
ch5 audio /--\ - 1045 104D 1055 105D
|
|
ch6 audio 1006 - 1046 104E 1056 105E
|
|
ch7 audio \--/ - 1047 104F 1057 105F
|
|
poly8 1000 - - - - -
|
|
bank 0 1FF8 - - - - -
|
|
bank 1 1FF9 - - - - -
|
|
</TD></TR></TABLE>Addresses 1000h-103Fh read only, 1040h and up write only.<BR>
|
|
Area 1000h-107Fh (and 1800h-187Fh) in ROM should be not used (FFh filled).<BR>
|
|
<BR>
|
|
<B>Display Data Channels</B><BR>
|
|
The first 5 channels are used to retrieve video data. The LSB and MSB
|
|
registers contain a 11bit counter (the upper 5bit are unused?), used to
|
|
address data in the 2K ROM area.<BR>
|
|
Normal data access: Reading from the DATA register returns the addressed
|
|
byte and does automatically decrement the counter. Intended for general
|
|
purpose display data (GRP0,PF0,COLUP0,etc.).<BR>
|
|
Masked data access: Reading from the MASK register works in the same way
|
|
as above, but the returned data is forced to 00h if the channels output is
|
|
disabled. The output is initially disabled (when writing to
|
|
MIN/MAX/LSB/MSB?), output gets enabled when LSB=MAX, and gets disabled
|
|
when LSB=MIN. Intended for vertical positioning of moveable objects (eg.
|
|
hiding GRP0 in unused lines by forcing GRP0=00h).<BR>
|
|
(Pitfall2 program code uses masked access only for channel 0 and 3, not
|
|
sure if other channels can use that feature as well?)<BR>
|
|
<BR>
|
|
<B>Audio Data Channels</B><BR>
|
|
The other 3 channels are used to generate 3 channel square? wave audio
|
|
data. The LSB registers are 8bit counters automatically decremented at ca.
|
|
30kHz rate (or other speed?) (by external oscillator?), upon underflow,
|
|
LSB is automatically reset to MAX?, the wave output is switched high when
|
|
LSB=MAX, and low when LSB=MIN. For audio, the MSB serves as control
|
|
register rather than as counter? MSB Bit5 seems to enable the channel. MSB
|
|
Bit4 does something/what: volume, length, noise, else? Other MSB Bits
|
|
unused?<BR>
|
|
The output levels of the 3 channels are automatically added? together,
|
|
probably high=5, low=0?, and can be read from Port 1006h, intended to be
|
|
forwarded to AUDV0, with AUDC0=0 (always high), preferably at least once
|
|
per scanline. The AUDx1 registers can be used as normal, as fourth sound
|
|
channel.<BR>
|
|
<BR>
|
|
<B>ROM and Poly8</B><BR>
|
|
The first 8K (2000h) of the Pitfall ROM image contain normal program
|
|
code/data, using normal 4K Port 1FF8h/1FF9h bank switching. The next 2K
|
|
(800h) contain sequential data, used by channel 0-4, apparently in
|
|
reversed order (in rom-image and/or real rom?), ie. addressed by "NOT
|
|
counter". Finally, 255 bytes (FFh) of 8bit poly data are somewhat attached
|
|
to the Pitfall2 ROM-images being found in internet (resulting in the
|
|
obscure filesize of 28FFh bytes).<BR>
|
|
In reality, the poly data is likely to be generated by shift register, and
|
|
probably not stored in a ROM? The poly data is used for what purpose?
|
|
Audio? Not at all? Or Port 1000h? Pitfall reads from Port 1000h once every
|
|
4 frames, Bit 7 of the returned data seems to be used only? as color code
|
|
for the blinking electric eels? If so, does one really need external
|
|
hardware to produce blinking colors? The next poly value is generated
|
|
when: at fixed rate or after reading from any or specific register?<BR>
|
|
The poly stream can be produced by taking the parity of Bits 7,5,4,3 of
|
|
the current value, the new value is then shifted left, with the old parity
|
|
(1=even) shifted in to Bit 0. Example: 00, 01, 03, 07, 0F, 1E, 3D, 7A, F4,
|
|
E8, D0, A1, 43, 87, 0E, 1C, etc. The stream restarts each 255 cycles.<BR>
|
|
<BR>
|
|
All info (and all question marks) gained from examining the pitfall2
|
|
rom-image, but without having viewed/listened/debugged the original
|
|
cartridge.<BR>
|
|
<BR>
|
|
<B>NB.</B><BR>
|
|
When I first heard of the cartridge, having been wondering how it'd work,
|
|
my first bet was to write a value of FFh to [TIA+mirror], allowing the
|
|
cartridge to drag the databus to (FFh AND data). That method would take up
|
|
only 3 cycles per write (instead 4+3 per read+write as actually used in
|
|
pitfall2), and using different mirror address could be used for different
|
|
channels. Not sure if it'd work stable, and if it'd be of any use to
|
|
create games with higher video resolution, or for any other features.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartexpansionram"></A><FONT SIZE=+2> Cart Expansion RAM</FONT></TD></TR></TABLE><BR>
|
|
<B>Expansion RAM</B><BR>
|
|
Some cartridges include additional 128 bytes (or 256 bytes) of external
|
|
RAM, that memory is NOT (???) battery buffered. Because the cartridge
|
|
slot does not include a read/write signal, different memory addresses
|
|
must be used for reading and writing, mapped as such:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Cart Type 4K-Banking 4K-Banking 2K-Banking
|
|
RAM Size 128 bytes 256 bytes 256 bytes
|
|
RAM Write Area F000-F07F F000-F0FF F800-F8FF
|
|
RAM Read Area F080-F0FF F100-F1FF F900-F9FF
|
|
ROM Size 3.75K 3.5K 1.5K
|
|
ROM Area F100-FFFF F200-FFFF FA00-FFFF
|
|
</TD></TR></TABLE>The first 256 bytes (or 512 bytes) of each ROM bank are unused, these
|
|
areas should be 00h or FFh filled in ROM-images. (NB. That allows to
|
|
determine if a game uses external RAM. Omegarace and Digdug use garbage
|
|
filled area though.)<BR>
|
|
RAM can be accessed from inside of all ROM-banks (but it is always the
|
|
same 128 or 256 bytes of RAM, ie. RAM is NOT banked).<BR>
|
|
Note: Attempts to read from Write Addresses would overwrite the
|
|
addressed byte by garbage. Thus, external RAM cannot be used by
|
|
read-and-write opcodes (ie. INC, DEC, ASL, LSR, ROL, and ROR).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartpinouts"></A><FONT SIZE=+2> Cart Pin-Outs</FONT></TD></TR></TABLE><BR>
|
|
<B>Cartridge Slot (24 pins)</B><BR>
|
|
The A12 pin is used as CS (chip select, active HIGH), this works okay
|
|
with the type of ROMs used in original cartridges. Standard EPROMs are
|
|
expecting /CS though (active LOW), so that EPROM cartridges must include an
|
|
inverter (transistor circuit, or 7404 chip, or similar).<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> +--------------------------------------------------+
|
|
| |
|
|
| /EX +5V A8 A9 A11 A10 A12 D7 D6 D5 D4 D3 |
|
|
| A7 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 GND |
|
|
+--------------------------------------------------+
|
|
</TD></TR></TABLE>The /EXROM pin should be connected to GND inside of the cartridge, it
|
|
isn't actually used, but it would allow the console to detect if a
|
|
cartridge is inserted.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cartsummaryandgeneralinfo"></A><FONT SIZE=+2> Cart Summary and General Info</FONT></TD></TR></TABLE><BR>
|
|
<B>Available ROM and Expansion RAM Sizes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> ROM Type:Port RAM Used by how many games
|
|
1K - - 1 (Cave1k - when removing 2K-padding)
|
|
2K - - 51
|
|
4K - - 296
|
|
8K 2x4K - 111
|
|
8K 2x4K 128 3 (Stargate,Defendr2,Elevator)
|
|
8K 2x4K:JSR - 1 (Decathln)
|
|
8K 4x2K:3Fh - 6 (Springer,Espial,Minrvol2,Mnr2049r,Riverp,Polaris)
|
|
8K 4x2K 256 1 (Bnj - when removing 16K padding)
|
|
8K 8x1K - 13
|
|
10K 2x4K+2K - 1 (Pitfall2, with sequential data channels)
|
|
12K 3x4K 256 3 (Mtnking,Omegarac,Tunlrunr)
|
|
16K 4x4K - 31
|
|
16K 4x4K 128 13
|
|
16K 8x2K - 2 (Burgtime,He_man)
|
|
32K 8x4K 128 1 (Fatalrun)
|
|
</TD></TR></TABLE>AtariAge collection, 533 games in total.<BR>
|
|
<BR>
|
|
<B>ROM Origin & Entrypoint</B><BR>
|
|
ROM is usually originated at F000h, there are no headers or checksums
|
|
required, only the Entrypoint (and Breakpoint, if using the BRK opcode)
|
|
vectors are required to be located at following addresses:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> FFFC-FFFD CPU Entrypoint (16bit pointer)
|
|
FFFE-FFFF CPU Breakpoint (16bit pointer)
|
|
</TD></TR></TABLE>That is, these addresses must contain a 16bit pointer (data), which
|
|
points to the actual reset/break procedures (code). For small 2K ROMs,
|
|
addresses FFFXh are mirrors of F7FXh.<BR>
|
|
<BR>
|
|
<B>Bank Switching</B><BR>
|
|
ROMs bigger than 4KBytes are split into several banks of 4KBytes each,
|
|
and must include a small circuit that latches the current bank number.<BR>
|
|
<BR>
|
|
<B>Cartridge Mirrors</B><BR>
|
|
The 4K cartridge area is addressed by A12 signal, causing it to be
|
|
mirrored to all addresses with Bit 12 set, 1000h, 3000h, 5000h, etc. (2K
|
|
ROMs also to 1800h, 3800h, 5800h, etc.)<BR>
|
|
Most 2K and 4K programs are originated at F000h. Larger ROMS are often
|
|
using different addresses for each bank - for example, bank 0 at D000h,
|
|
and bank 1 at F000h (mainly to make .MAP files more obvious).<BR>
|
|
<BR>
|
|
<B>File Extension</B><BR>
|
|
The most common extension for Atart 2600 ROM-Images is ".bin".<BR>
|
|
Reportedly, some PAL games use ".pal". Also, some games use ".a26".<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpu65xxmicroprocessor"></A><FONT SIZE=+2> CPU 65XX Microprocessor</FONT></TD></TR></TABLE><BR>
|
|
<B>Overview</B><BR>
|
|
<A HREF="#cpuregistersandflags">CPU Registers and Flags</A><BR>
|
|
<A HREF="#cpumemoryaddressing">CPU Memory Addressing</A><BR>
|
|
<BR>
|
|
<B>Instruction Set</B><BR>
|
|
<A HREF="#cpumemoryandregistertransfers">CPU Memory and Register Transfers</A><BR>
|
|
<A HREF="#cpuarithmeticlogicaloperations">CPU Arithmetic/Logical Operations</A><BR>
|
|
<A HREF="#cpurotateandshiftinstructions">CPU Rotate and Shift Instructions</A><BR>
|
|
<A HREF="#cpujumpandcontrolinstructions">CPU Jump and Control Instructions</A><BR>
|
|
<A HREF="#cpuillegalopcodes">CPU Illegal Opcodes</A><BR>
|
|
<BR>
|
|
<B>Other Info</B><BR>
|
|
<A HREF="#cpuassemblerdirectivessyntax">CPU Assembler Directives/Syntax</A><BR>
|
|
<A HREF="#cpuglitches">CPU Glitches</A><BR>
|
|
<A HREF="#cputhe65xxfamily">CPU The 65XX Family</A><BR>
|
|
<A HREF="#cpulocalusage">CPU Local Usage</A><BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuregistersandflags"></A><FONT SIZE=+2> CPU Registers and Flags</FONT></TD></TR></TABLE><BR>
|
|
The 65XX CPUs are equipped with not more than three 8bit general purpose
|
|
registers (A, X, Y). However, the limited number of registers (and
|
|
complete lack of 16bit registers other than PC) is parts of covered by
|
|
comfortable memory operations, especially page 0 of memory (address
|
|
0000h-00FFh) may be used for relative fast and complicated operations,
|
|
in so far one might say that the CPU has about 256 8bit 'registers' (or
|
|
128 16bit 'registers') in memory. For details see Memory Addressing
|
|
chapter.<BR>
|
|
<BR>
|
|
<B>Registers</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bits Name Expl.
|
|
8 A Accumulator
|
|
8 X Index Register X
|
|
8 Y Index Register Y
|
|
16 PC Program Counter
|
|
8 S Stack Pointer (see below)
|
|
8 P Processor Status Register (see below)
|
|
</TD></TR></TABLE><BR>
|
|
<B>Stack Pointer</B><BR>
|
|
The stack pointer is addressing 256 bytes in page 1 of memory, ie.
|
|
values 00h-FFh will address memory at 0100h-01FFh. As for most other
|
|
CPUs, the stack pointer is decrementing when storing data. However, in
|
|
the 65XX world, it points to the first FREE byte on stack, so, when
|
|
initializing stack to top set S=(1)FFh (rather than S=(2)00h).<BR>
|
|
<BR>
|
|
<B>Processor Status Register (Flags)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Bit Name Expl.
|
|
0 C Carry (0=No Carry, 1=Carry)
|
|
1 Z Zero (0=Nonzero, 1=Zero)
|
|
2 I IRQ Disable (0=IRQ Enable, 1=IRQ Disable)
|
|
3 D Decimal Mode (0=Normal, 1=BCD Mode for ADC/SBC opcodes)
|
|
4 B Break Flag (0=IRQ/NMI, 1=RESET or BRK/PHP opcode)
|
|
5 - Not used (Always 1)
|
|
6 V Overflow (0=No Overflow, 1=Overflow)
|
|
7 N Negative/Sign (0=Positive, 1=Negative)
|
|
</TD></TR></TABLE><BR>
|
|
<B>Carry Flag (C)</B><BR>
|
|
Caution: When used for subtractions (SBC and CMP), the carry flag is
|
|
having opposite meaning as for normal 80x86 and Z80 CPUs, ie. it is SET
|
|
when above-or-equal. For all other instructions (ADC, ASL, LSR, ROL,
|
|
ROR) it works as normal, whereas ROL/ROR are rotating <through> carry
|
|
(ie. much like 80x86 RCL/RCR and not like ROL/ROR).<BR>
|
|
<BR>
|
|
<B>Zero Flag (Z), Negative/Sign Flag (N), Overflow Flag (V)</B><BR>
|
|
Works just as everywhere, Z it is set when result (or destination
|
|
register, in case of some 'move' instructions) is zero, N is set when
|
|
signed (ie. same as Bit 7 of result/destination). V is set when an
|
|
addition/subtraction exceeded the maximum range for signed numbers
|
|
(-128..+127).<BR>
|
|
<BR>
|
|
<B>IRQ Disable Flag (I)</B><BR>
|
|
Disables IRQs when set. NMIs (non maskable interrupts) and BRK
|
|
instructions cannot be disabled.<BR>
|
|
<BR>
|
|
<B>Decimal Mode Flag (D)</B><BR>
|
|
Packed BCD mode (range 00h..99h) for ADC and SBC opcodes.<BR>
|
|
<BR>
|
|
<B>Break Flag (B)</B><BR>
|
|
The Break flag is intended to separate between IRQ and BRK which are both
|
|
using the same vector, [FFFEh]. The flag cannot be accessed directly, but
|
|
there are 4 situations which are writing the P register to stack, which
|
|
are then allowing the examine the B-bit in the pushed value: The BRK and
|
|
PHP opcodes always write "1" into the bit, IRQ/NMI execution always write
|
|
"0".<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpumemoryaddressing"></A><FONT SIZE=+2> CPU Memory Addressing</FONT></TD></TR></TABLE><BR>
|
|
<B>Opcode Addressing Modes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Name Native Nocash
|
|
Implied - A,X,Y,S,P
|
|
Immediate #nn nn
|
|
Zero Page nn [nn]
|
|
Zero Page,X nn,X [nn+X]
|
|
Zero Page,Y nn,Y [nn+Y]
|
|
Absolute nnnn [nnnn]
|
|
Absolute,X nnnn,X [nnnn+X]
|
|
Absolute,Y nnnn,Y [nnnn+Y]
|
|
(Indirect,X) (nn,X) [[nn+X]]
|
|
(Indirect),Y (nn),Y [[nn]+Y]
|
|
</TD></TR></TABLE><BR>
|
|
<B>Zero Page - [nn] [nn+X] [nn+Y]</B><BR>
|
|
Uses an 8bit parameter (one byte) to address the first 256 of memory at
|
|
0000h..00FFh. This limited range is used even for "nn+X" and "nn+Y", ie.
|
|
"C0h+60h" will access 0020h (not 0120h).<BR>
|
|
<BR>
|
|
<B>Absolute - [nnnn] [nnnn+X] [nnnn+Y]</B><BR>
|
|
Uses a 16bit parameter (two bytes) to address the whole 64K of memory at
|
|
0000h..FFFFh. Because of the additional parameter bytes, this is a bit slower
|
|
than Zero Page accesses.<BR>
|
|
<BR>
|
|
<B>Indirect - [[nn+X]] [[nn]+Y]</B><BR>
|
|
Uses an 8bit parameter that points to a 16bit parameter in page zero.<BR>
|
|
Even though the CPU doesn't support 16bit registers (except for the program
|
|
counter), this (double-)indirect addressing mode allows to use variable 16bit
|
|
pointers.<BR>
|
|
<BR>
|
|
<B>On-Chip Bi-directional I/O port</B><BR>
|
|
Addresses (00)00h and (00)01h are occupied by an I/O port which is built-in
|
|
into 6510, 8500, 7501, 8501 CPUs (eg. used in C64 and C16), be sure not to
|
|
use the addresses as normal memory. For description read chapter about I/O
|
|
ports.<BR>
|
|
<BR>
|
|
<B>Caution</B><BR>
|
|
Because of the identical format, assemblers will be more or less unable
|
|
to separate between [XXh+r] and [00XXh+r], the assembler will most
|
|
likely produce [XXh+r] when address is already known to be located in
|
|
page 0, and [00XXh+r] in case of forward references.<BR>
|
|
Beside for different opcode size/time, [XXh+r] will always access page 0
|
|
memory (even when XXh+r>FFh), while [00XXh+r] may direct to memory in
|
|
page 0 or 1, to avoid unpredictable results be sure not to use
|
|
(00)XXh+r>FFh if possible.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpumemoryandregistertransfers"></A><FONT SIZE=+2> CPU Memory and Register Transfers</FONT></TD></TR></TABLE><BR>
|
|
<B>Register/Immeditate to Register Transfer</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Opcode Flags Clk Native Nocash Expl.
|
|
A8 nz---- 2 TAY MOV Y,A ;Y=A
|
|
AA nz---- 2 TAX MOV X,A ;X=A
|
|
BA nz---- 2 TSX MOV X,S ;X=S
|
|
98 nz---- 2 TYA MOV A,Y ;A=Y
|
|
8A nz---- 2 TXA MOV A,X ;A=X
|
|
9A ------ 2 TXS MOV S,X ;S=X
|
|
A9 nn nz---- 2 LDA #nn MOV A,nn ;A=nn
|
|
A2 nn nz---- 2 LDX #nn MOV X,nn ;X=nn
|
|
A0 nn nz---- 2 LDY #nn MOV Y,nn ;Y=nn
|
|
</TD></TR></TABLE><BR>
|
|
<B>Load Register from Memory</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> A5 nn nz---- 3 LDA nn MOV A,[nn] ;A=[nn]
|
|
B5 nn nz---- 4 LDA nn,X MOV A,[nn+X] ;A=[nn+X]
|
|
AD nn nn nz---- 4 LDA nnnn MOV A,[nnnn] ;A=[nnnn]
|
|
BD nn nn nz---- 4* LDA nnnn,X MOV A,[nnnn+X] ;A=[nnnn+X]
|
|
B9 nn nn nz---- 4* LDA nnnn,Y MOV A,[nnnn+Y] ;A=[nnnn+Y]
|
|
A1 nn nz---- 6 LDA (nn,X) MOV A,[[nn+X]] ;A=[WORD[nn+X]]
|
|
B1 nn nz---- 5* LDA (nn),Y MOV A,[[nn]+Y] ;A=[WORD[nn]+Y]
|
|
A6 nn nz---- 3 LDX nn MOV X,[nn] ;X=[nn]
|
|
B6 nn nz---- 4 LDX nn,Y MOV X,[nn+Y] ;X=[nn+Y]
|
|
AE nn nn nz---- 4 LDX nnnn MOV X,[nnnn] ;X=[nnnn]
|
|
BE nn nn nz---- 4* LDX nnnn,Y MOV X,[nnnn+Y] ;X=[nnnn+Y]
|
|
A4 nn nz---- 3 LDY nn MOV Y,[nn] ;Y=[nn]
|
|
B4 nn nz---- 4 LDY nn,X MOV Y,[nn+X] ;Y=[nn+X]
|
|
AC nn nn nz---- 4 LDY nnnn MOV Y,[nnnn] ;Y=[nnnn]
|
|
BC nn nn nz---- 4* LDY nnnn,X MOV Y,[nnnn+X] ;Y=[nnnn+X]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
<BR>
|
|
<B>Store Register in Memory</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 85 nn ------ 3 STA nn MOV [nn],A ;[nn]=A
|
|
95 nn ------ 4 STA nn,X MOV [nn+X],A ;[nn+X]=A
|
|
8D nn nn ------ 4 STA nnnn MOV [nnnn],A ;[nnnn]=A
|
|
9D nn nn ------ 5 STA nnnn,X MOV [nnnn+X],A ;[nnnn+X]=A
|
|
99 nn nn ------ 5 STA nnnn,Y MOV [nnnn+Y],A ;[nnnn+Y]=A
|
|
81 nn ------ 6 STA (nn,X) MOV [[nn+x]],A ;[WORD[nn+x]]=A
|
|
91 nn ------ 6 STA (nn),Y MOV [[nn]+y],A ;[WORD[nn]+y]=A
|
|
86 nn ------ 3 STX nn MOV [nn],X ;[nn]=X
|
|
96 nn ------ 4 STX nn,Y MOV [nn+Y],X ;[nn+Y]=X
|
|
8E nn nn ------ 4 STX nnnn MOV [nnnn],X ;[nnnn]=X
|
|
84 nn ------ 3 STY nn MOV [nn],Y ;[nn]=Y
|
|
94 nn ------ 4 STY nn,X MOV [nn+X],Y ;[nn+X]=Y
|
|
8C nn nn ------ 4 STY nnnn MOV [nnnn],Y ;[nnnn]=Y
|
|
</TD></TR></TABLE><BR>
|
|
<B>Push/Pull</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 48 ------ 3 PHA PUSH A ;[S]=A, S=S-1
|
|
08 ------ 3 PHP PUSH P ;[S]=P, S=S-1 (flags)
|
|
68 nz---- 4 PLA POP A ;S=S+1, A=[S]
|
|
28 nzcidv 4 PLP POP P ;S=S+1, P=[S] (flags)
|
|
</TD></TR></TABLE>Notes: PLA sets Z and N according to content of A. The B-flag and unused
|
|
flags cannot be changed by PLP, these flags are always written as "1" by PHP.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuarithmeticlogicaloperations"></A><FONT SIZE=+2> CPU Arithmetic/Logical Operations</FONT></TD></TR></TABLE><BR>
|
|
<B>Add memory to accumulator with carry</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 69 nn nzc--v 2 ADC #nn ADC A,nn ;A=A+C+nn
|
|
65 nn nzc--v 3 ADC nn ADC A,[nn] ;A=A+C+[nn]
|
|
75 nn nzc--v 4 ADC nn,X ADC A,[nn+X] ;A=A+C+[nn+X]
|
|
6D nn nn nzc--v 4 ADC nnnn ADC A,[nnnn] ;A=A+C+[nnnn]
|
|
7D nn nn nzc--v 4* ADC nnnn,X ADC A,[nnnn+X] ;A=A+C+[nnnn+X]
|
|
79 nn nn nzc--v 4* ADC nnnn,Y ADC A,[nnnn+Y] ;A=A+C+[nnnn+Y]
|
|
61 nn nzc--v 6 ADC (nn,X) ADC A,[[nn+X]] ;A=A+C+[word[nn+X]]
|
|
71 nn nzc--v 5* ADC (nn),Y ADC A,[[nn]+Y] ;A=A+C+[word[nn]+Y]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
<BR>
|
|
<B>Subtract memory from accumulator with borrow</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> E9 nn nzc--v 2 SBC #nn SBC A,nn ;A=A+C-1-nn
|
|
E5 nn nzc--v 3 SBC nn SBC A,[nn] ;A=A+C-1-[nn]
|
|
F5 nn nzc--v 4 SBC nn,X SBC A,[nn+X] ;A=A+C-1-[nn+X]
|
|
ED nn nn nzc--v 4 SBC nnnn SBC A,[nnnn] ;A=A+C-1-[nnnn]
|
|
FD nn nn nzc--v 4* SBC nnnn,X SBC A,[nnnn+X] ;A=A+C-1-[nnnn+X]
|
|
F9 nn nn nzc--v 4* SBC nnnn,Y SBC A,[nnnn+Y] ;A=A+C-1-[nnnn+Y]
|
|
E1 nn nzc--v 6 SBC (nn,X) SBC A,[[nn+X]] ;A=A+C-1-[word[nn+X]]
|
|
F1 nn nzc--v 5* SBC (nn),Y SBC A,[[nn]+Y] ;A=A+C-1-[word[nn]+Y]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
Note: Compared with normal 80x86 and Z80 CPUs, incoming and resulting
|
|
Carry Flag are reversed.<BR>
|
|
<BR>
|
|
<B>Logical AND memory with accumulator</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 29 nn nz---- 2 AND #nn AND A,nn ;A=A AND nn
|
|
25 nn nz---- 3 AND nn AND A,[nn] ;A=A AND [nn]
|
|
35 nn nz---- 4 AND nn,X AND A,[nn+X] ;A=A AND [nn+X]
|
|
2D nn nn nz---- 4 AND nnnn AND A,[nnnn] ;A=A AND [nnnn]
|
|
3D nn nn nz---- 4* AND nnnn,X AND A,[nnnn+X] ;A=A AND [nnnn+X]
|
|
39 nn nn nz---- 4* AND nnnn,Y AND A,[nnnn+Y] ;A=A AND [nnnn+Y]
|
|
21 nn nz---- 6 AND (nn,X) AND A,[[nn+X]] ;A=A AND [word[nn+X]]
|
|
31 nn nz---- 5* AND (nn),Y AND A,[[nn]+Y] ;A=A AND [word[nn]+Y]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
<BR>
|
|
<B>Exclusive-OR memory with accumulator</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 49 nn nz---- 2 EOR #nn XOR A,nn ;A=A XOR nn
|
|
45 nn nz---- 3 EOR nn XOR A,[nn] ;A=A XOR [nn]
|
|
55 nn nz---- 4 EOR nn,X XOR A,[nn+X] ;A=A XOR [nn+X]
|
|
4D nn nn nz---- 4 EOR nnnn XOR A,[nnnn] ;A=A XOR [nnnn]
|
|
5D nn nn nz---- 4* EOR nnnn,X XOR A,[nnnn+X] ;A=A XOR [nnnn+X]
|
|
59 nn nn nz---- 4* EOR nnnn,Y XOR A,[nnnn+Y] ;A=A XOR [nnnn+Y]
|
|
41 nn nz---- 6 EOR (nn,X) XOR A,[[nn+X]] ;A=A XOR [word[nn+X]]
|
|
51 nn nz---- 5* EOR (nn),Y XOR A,[[nn]+Y] ;A=A XOR [word[nn]+Y]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
<BR>
|
|
<B>Logical OR memory with accumulator</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 09 nn nz---- 2 ORA #nn OR A,nn ;A=A OR nn
|
|
05 nn nz---- 3 ORA nn OR A,[nn] ;A=A OR [nn]
|
|
15 nn nz---- 4 ORA nn,X OR A,[nn+X] ;A=A OR [nn+X]
|
|
0D nn nn nz---- 4 ORA nnnn OR A,[nnnn] ;A=A OR [nnnn]
|
|
1D nn nn nz---- 4* ORA nnnn,X OR A,[nnnn+X] ;A=A OR [nnnn+X]
|
|
19 nn nn nz---- 4* ORA nnnn,Y OR A,[nnnn+Y] ;A=A OR [nnnn+Y]
|
|
01 nn nz---- 6 ORA (nn,X) OR A,[[nn+X]] ;A=A OR [word[nn+X]]
|
|
11 nn nz---- 5* ORA (nn),Y OR A,[[nn]+Y] ;A=A OR [word[nn]+Y]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
<BR>
|
|
<B>Compare</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> C9 nn nzc--- 2 CMP #nn CMP A,nn ;A-nn
|
|
C5 nn nzc--- 3 CMP nn CMP A,[nn] ;A-[nn]
|
|
D5 nn nzc--- 4 CMP nn,X CMP A,[nn+X] ;A-[nn+X]
|
|
CD nn nn nzc--- 4 CMP nnnn CMP A,[nnnn] ;A-[nnnn]
|
|
DD nn nn nzc--- 4* CMP nnnn,X CMP A,[nnnn+X] ;A-[nnnn+X]
|
|
D9 nn nn nzc--- 4* CMP nnnn,Y CMP A,[nnnn+Y] ;A-[nnnn+Y]
|
|
C1 nn nzc--- 6 CMP (nn,X) CMP A,[[nn+X]] ;A-[word[nn+X]]
|
|
D1 nn nzc--- 5* CMP (nn),Y CMP A,[[nn]+Y] ;A-[word[nn]+Y]
|
|
E0 nn nzc--- 2 CPX #nn CMP X,nn ;X-nn
|
|
E4 nn nzc--- 3 CPX nn CMP X,[nn] ;X-[nn]
|
|
EC nn nn nzc--- 4 CPX nnnn CMP X,[nnnn] ;X-[nnnn]
|
|
C0 nn nzc--- 2 CPY #nn CMP Y,nn ;Y-nn
|
|
C4 nn nzc--- 3 CPY nn CMP Y,[nn] ;Y-[nn]
|
|
CC nn nn nzc--- 4 CPY nnnn CMP Y,[nnnn] ;Y-[nnnn]
|
|
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
|
|
Note: Compared with normal 80x86 and Z80 CPUs, resulting Carry Flag is
|
|
reversed.<BR>
|
|
<BR>
|
|
<B>Bit Test</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 24 nn xz---x 3 BIT nn TEST A,[nn] ;test and set flags
|
|
2C nn nn xz---x 4 BIT nnnn TEST A,[nnnn] ;test and set flags
|
|
</TD></TR></TABLE>Flags are set as so: Z=((A AND [addr])=00h), N=[addr].Bit7, V=[addr].Bit6.
|
|
Note that N and V are affected only by [addr] (not by A).<BR>
|
|
<BR>
|
|
<B>Increment by one</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> E6 nn nz---- 5 INC nn INC [nn] ;[nn]=[nn]+1
|
|
F6 nn nz---- 6 INC nn,X INC [nn+X] ;[nn+X]=[nn+X]+1
|
|
EE nn nn nz---- 6 INC nnnn INC [nnnn] ;[nnnn]=[nnnn]+1
|
|
FE nn nn nz---- 7 INC nnnn,X INC [nnnn+X] ;[nnnn+X]=[nnnn+X]+1
|
|
E8 nz---- 2 INX INC X ;X=X+1
|
|
C8 nz---- 2 INY INC Y ;Y=Y+1
|
|
</TD></TR></TABLE><BR>
|
|
<B>Decrement by one</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> C6 nn nz---- 5 DEC nn DEC [nn] ;[nn]=[nn]-1
|
|
D6 nn nz---- 6 DEC nn,X DEC [nn+X] ;[nn+X]=[nn+X]-1
|
|
CE nn nn nz---- 6 DEC nnnn DEC [nnnn] ;[nnnn]=[nnnn]-1
|
|
DE nn nn nz---- 7 DEC nnnn,X DEC [nnnn+X] ;[nnnn+X]=[nnnn+X]-1
|
|
CA nz---- 2 DEX DEC X ;X=X-1
|
|
88 nz---- 2 DEY DEC Y ;Y=Y-1
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpurotateandshiftinstructions"></A><FONT SIZE=+2> CPU Rotate and Shift Instructions</FONT></TD></TR></TABLE><BR>
|
|
<B>Shift Left Logical/Arithmetic</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0A nzc--- 2 ASL A SHL A ;SHL A
|
|
06 nn nzc--- 5 ASL nn SHL [nn] ;SHL [nn]
|
|
16 nn nzc--- 6 ASL nn,X SHL [nn+X] ;SHL [nn+X]
|
|
0E nn nn nzc--- 6 ASL nnnn SHL [nnnn] ;SHL [nnnn]
|
|
1E nn nn nzc--- 7 ASL nnnn,X SHL [nnnn+X] ;SHL [nnnn+X]
|
|
</TD></TR></TABLE><BR>
|
|
<B>Shift Right Logical</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 4A 0zc--- 2 LSR A SHR A ;SHR A
|
|
46 nn 0zc--- 5 LSR nn SHR [nn] ;SHR [nn]
|
|
56 nn 0zc--- 6 LSR nn,X SHR [nn+X] ;SHR [nn+X]
|
|
4E nn nn 0zc--- 6 LSR nnnn SHR [nnnn] ;SHR [nnnn]
|
|
5E nn nn 0zc--- 7 LSR nnnn,X SHR [nnnn+X] ;SHR [nnnn+X]
|
|
</TD></TR></TABLE><BR>
|
|
<B>Rotate Left through Carry</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 2A nzc--- 2 ROL A RCL A ;RCL A
|
|
26 nn nzc--- 5 ROL nn RCL [nn] ;RCL [nn]
|
|
36 nn nzc--- 6 ROL nn,X RCL [nn+X] ;RCL [nn+X]
|
|
2E nn nn nzc--- 6 ROL nnnn RCL [nnnn] ;RCL [nnnn]
|
|
3E nn nn nzc--- 7 ROL nnnn,X RCL [nnnn+X] ;RCL [nnnn+X]
|
|
</TD></TR></TABLE><BR>
|
|
<B>Rotate Right through Carry</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 6A nzc--- 2 ROR A RCR A ;RCR A
|
|
66 nn nzc--- 5 ROR nn RCR [nn] ;RCR [nn]
|
|
76 nn nzc--- 6 ROR nn,X RCR [nn+X] ;RCR [nn+X]
|
|
6E nn nn nzc--- 6 ROR nnnn RCR [nnnn] ;RCR [nnnn]
|
|
7E nn nn nzc--- 7 ROR nnnn,X RCR [nnnn+X] ;RCR [nnnn+X]
|
|
</TD></TR></TABLE><BR>
|
|
Notes:<BR>
|
|
ROR instruction is available on MCS650X microprocessors after June, 1976.<BR>
|
|
ROL and ROR rotate an 8bit value through carry (rotates 9bits in total).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpujumpandcontrolinstructions"></A><FONT SIZE=+2> CPU Jump and Control Instructions</FONT></TD></TR></TABLE><BR>
|
|
<B>Normal Jumps & Subroutine Calls/Returns</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 4C nn nn ------ 3 JMP nnnn JMP nnnn ;PC=nnnn
|
|
6C nn nn ------ 5 JMP (nnnn) JMP [nnnn] ;PC=WORD[nnnn]
|
|
20 nn nn ------ 6 JSR nnnn CALL nnnn ;[S]=PC+2,PC=nnnn
|
|
40 nzcidv 6 RTI RETI ;(from BRK/IRQ/NMI) ;P=[S], PC=[S]
|
|
60 ------ 6 RTS RET ;(from CALL) ;PC=[S]+1
|
|
</TD></TR></TABLE>Note: RTI cannot modify the B-Flag or the unused flag.<BR>
|
|
Glitch: For JMP [nnnn] the operand word cannot cross page boundaries, ie.
|
|
JMP [03FFh] would fetch the MSB from [0300h] instead of [0400h]. Very
|
|
simple workaround would be to place a ALIGN 2 before the data word.<BR>
|
|
<BR>
|
|
<B>Conditional Branches (conditional jump to PC=PC+/-dd)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 10 dd ------ 2** BPL nnn JNS nnn ;N=0 plus/positive
|
|
30 dd ------ 2** BMI nnn JS nnn ;N=1 minus/negative/signed
|
|
50 dd ------ 2** BVC nnn JNO nnn ;V=0 no overflow
|
|
70 dd ------ 2** BVS nnn JO nnn ;V=1 overflow
|
|
90 dd ------ 2** BCC/BLT nnn JNC/JB nnn ;C=0 less/below/no carry
|
|
B0 dd ------ 2** BCS/BGE nnn JC/JAE nnn ;C=1 above/greater/equal/carry
|
|
D0 dd ------ 2** BNE/BZC nnn JNZ/JNE nnn ;Z=0 not zero/not equal
|
|
F0 dd ------ 2** BEQ/BZS nnn JZ/JE nnn ;Z=1 zero/equal
|
|
</TD></TR></TABLE>** The execution time is 2 cycles if the condition is false (no branch
|
|
executed). Otherwise, 3 cycles if the destination is in the same memory
|
|
page, or 4 cycles if it crosses a page boundary (see below for exact info).<BR>
|
|
Note: After subtractions (SBC or CMP) carry=set indicates above-or-equal,
|
|
unlike as for 80x86 and Z80 CPUs.<BR>
|
|
<BR>
|
|
<B>Interrupts, Exceptions, Breakpoints</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 00 ---1-- 7 BRK Force Break B=1,[S]=PC+1,[S]=P,I=1,PC=[FFFE]
|
|
-- ---1-- 7 /IRQ Interrupt B=0,[S]=PC, [S]=P,I=1,PC=[FFFE]
|
|
-- ---1-- 7 /NMI NMI B=0,[S]=PC, [S]=P,I=1,PC=[FFFA]
|
|
-- ---1-- T+6? /RESET Reset B=1,S=S-3, I=1,PC=[FFFC]
|
|
</TD></TR></TABLE>Notes: IRQs can be disabled by setting the I-flag. BRK command, /NMI signal,
|
|
and /RESET signal cannot be masked by setting I.<BR>
|
|
BRK/IRQ/NMI first change the B-flag, then write P to stack, and then set the
|
|
I-flag, the D-flag is NOT changed and should be cleared by software.<BR>
|
|
The same vector is shared for BRK and IRQ, software can separate between BRK
|
|
and IRQ by examining the pushed B-flag only.<BR>
|
|
The RTI opcode can be used to return from BRK/IRQ/NMI, note that using the
|
|
return address from BRK skips one dummy/parameter byte following after the
|
|
BRK opcode.<BR>
|
|
Software or hardware must take care to acknowledge or reset /IRQ or /NMI
|
|
signals after processing it.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> IRQs are executed whenever "/IRQ=LOW AND I=0".
|
|
NMIs are executed whenever "/NMI changes from HIGH to LOW".
|
|
</TD></TR></TABLE>If /IRQ is kept LOW then same (old) interrupt is executed again as soon as
|
|
setting I=0. If /NMI is kept LOW then no further NMIs can be executed.<BR>
|
|
<BR>
|
|
<B>CPU Control</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 18 --0--- 2 CLC CLC ;Clear carry flag C=0
|
|
58 ---0-- 2 CLI EI ;Clear interrupt disable bit I=0
|
|
D8 ----0- 2 CLD CLD ;Clear decimal mode D=0
|
|
B8 -----0 2 CLV CLV ;Clear overflow flag V=0
|
|
38 --1--- 2 SEC STC ;Set carry flag C=1
|
|
78 ---1-- 2 SEI DI ;Set interrupt disable bit I=1
|
|
F8 ----1- 2 SED STD ;Set decimal mode D=1
|
|
</TD></TR></TABLE><BR>
|
|
<B>No Operation</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> EA ------ 2 NOP NOP ;No operation
|
|
</TD></TR></TABLE><BR>
|
|
<B>Conditional Branch Page Crossing</B><BR>
|
|
The branch opcode with parameter takes up two bytes, causing the PC to get
|
|
incremented twice (PC=PC+2), without any extra boundary cycle. The signed
|
|
parameter is then added to the PC (PC+disp), the extra clock cycle occurs
|
|
if the addition crosses a page boundary (next or previous 100h-page).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuillegalopcodes"></A><FONT SIZE=+2> CPU Illegal Opcodes</FONT></TD></TR></TABLE><BR>
|
|
<B>SAX and LAX</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 87 nn ------ 3 SAX nn STA+STX [nn]=A AND X
|
|
97 nn ------ 4 SAX nn,Y STA+STX [nn+Y]=A AND X
|
|
8F nn nn ------ 4 SAX nnnn STA+STX [nnnn]=A AND X
|
|
83 nn ------ 6 SAX (nn,X) STA+STX [WORD[nn+X]]=A AND X
|
|
A7 nn nz---- 3 LAX nn LDA+LDX A,X=[nn]
|
|
B7 nn nz---- 4 LAX nn,Y LDA+LDX A,X=[nn+Y]
|
|
AF nn nn nz---- 4 LAX nnnn LDA+LDX A,X=[nnnn]
|
|
A3 nn nz---- 6 LAX (nn,X) LDA+LDX A,X=[WORD[nn+X]]
|
|
B3 nn nz---- 5* LAX (nn),Y LDA+LDX A,X=[WORD[nn]+Y]
|
|
</TD></TR></TABLE>For SAX, both A and X are output to databus, LOW-bits are stronger than
|
|
HIGH-bits, resulting in a "forceful" AND operation.<BR>
|
|
For LAX, the same value is written to both A and X.<BR>
|
|
<BR>
|
|
<B>Combined ALU-Opcodes</B><BR>
|
|
Opcode high-bits, flags, commands:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 00+yy nzc--- SLO op ASL+ORA op=op SHL 1 // A=A OR op
|
|
20+yy nzc--- RLA op ROL+AND op=op RCL 1 // A=A AND op
|
|
40+yy nzc--- SRE op LSR+EOR op=op SHR 1 // A=A XOR op
|
|
60+yy nzc--v RRA op ROR+ADC op=op RCR 1 // A=A+op+cy
|
|
C0+yy nzc--- DCP op DEC+CMP op=op-1 // A-op
|
|
E0+yy nzc--v ISC op INC+SBC op=op+1 // A=A-op-(1-cy)
|
|
</TD></TR></TABLE>Opcode low-bits, clock cycles, operands:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 07+xx nn 5 nn [nn]
|
|
17+xx nn 6 nn,X [nn+X]
|
|
03+xx nn 8 (nn,X) [WORD[nn+X]]
|
|
13+xx nn 8 (nn),Y [WORD[nn]+Y]
|
|
0F+xx nn nn 6 nnnn [nnnn]
|
|
1F+xx nn nn 7 nnnn,X [nnnn+X]
|
|
1B+xx nn nn 7 nnnn,Y [nnnn+Y]
|
|
</TD></TR></TABLE><BR>
|
|
<B>Other Illegal Opcodes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0B nn nzc--- 2 ANC #nn AND+ASL A=A AND nn, C=N ;bit7 to carry
|
|
2B nn nzc--- 2 ANC #nn AND+ROL A=A AND nn, C=N ;same as above
|
|
4B nn nzc--- 2 ALR #nn AND+LSR A=(A AND nn) SHR 1
|
|
6B nn nzc--v 2 ARR #nn AND+ROR A=(A AND nn), V=Overflow(A+A),
|
|
A=A/2+C*80h, C=A.Bit6
|
|
CB nn nzc--- 2 AXS #nn CMP+DEX X=(X AND A)-nn
|
|
EB nn nzc--v 2 SBC #nn SBC+NOP A=A-nn cy?
|
|
BB nn nn nz---- 4* LAS nnnn,Y LDA+TSX A,X,S = [nnnn+Y] AND S
|
|
</TD></TR></TABLE><BR>
|
|
<B>NUL/NOP and KIL/JAM/HLT</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> xx ------ 2 NOP (xx=1A,3A,5A,7A,DA,FA)
|
|
xx nn ------ 2 NOP #nn (xx=80,82,89,C2,E2)
|
|
xx nn ------ 3 NOP nn (xx=04,44,64)
|
|
xx nn ------ 4 NOP nn,X (xx=14,34,54,74,D4,F4)
|
|
xx nn nn ------ 4 NOP nnnn (xx=0C)
|
|
xx nn nn ------ 4* NOP nnnn,X (xx=1C,3C,5C,7C,DC,FC)
|
|
xx ------ - KIL (xx=02,12,22,32,42,52,62,72,92,B2,D2,F2)
|
|
</TD></TR></TABLE>NOP doesn't change any registers or flags, the operand (if any) is fetched,
|
|
which may be useful for delays, patches, or for read-sensitive I/O ports. KIL
|
|
halts the CPU, the data bus will be set to #$FF, KIL can be suspended by
|
|
/RESET signal (not sure if also by /IRQ or /NMI ???).<BR>
|
|
<BR>
|
|
<B>Unstable Illegal Opcodes</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 8B nn nz---- 2 XAA #nn ((2)) TXA+AND A=X AND nn
|
|
AB nn nz---- 2 LAX #nn ((2)) LDA+TAX A,X=nn
|
|
BF nn nn nz---- 4* LAX nnnn,X LDA+LDX A,X=[nnnn+X]
|
|
93 nn ------ 6 AHX (nn),Y ((1)) [WORD[nn]+Y] = A AND X AND H
|
|
9F nn nn ------ 5 AHX nnnn,Y ((1)) [nnnn+Y] = A AND X AND H
|
|
9C nn nn ------ 5 SHY nnnn,X ((1)) [nnnn+X] = Y AND H
|
|
9E nn nn ------ 5 SHX nnnn,Y ((1)) [nnnn+Y] = X AND H
|
|
9B nn nn ------ 5 TAS nnnn,Y ((1)) STA+TXS S=A AND X // [nnnn+Y]=S AND H
|
|
</TD></TR></TABLE>note to XAA: DO NOT USE!!! Highly unstable!!!<BR>
|
|
note to LAX: DO NOT USE!!! On my C128, this opcode is stable, but on my C64-II<BR>
|
|
it loses bits so that the operation looks like this: ORA #? AND #{imm} TAX.<BR>
|
|
note to AXS: performs CMP and DEX at the same time, so that the MINUS sets<BR>
|
|
the flag like CMP, not SBC.<BR>
|
|
Combinations of STA/STX/STY:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> AHX {adr} = stores A&X&H into {adr}
|
|
SHX {adr} = stores X&H into {adr}
|
|
SHY {adr} = stores Y&H into {adr}
|
|
</TD></TR></TABLE>note: sometimes the &H drops off. Also page boundary crossing will not work as<BR>
|
|
expected (the bank where the value is stored may be equal to the value stored).<BR>
|
|
["H" probably meant to be the MSB aka Highbyte of the 16bit memory address?]<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuassemblerdirectivessyntax"></A><FONT SIZE=+2> CPU Assembler Directives/Syntax</FONT></TD></TR></TABLE><BR>
|
|
Below are some common 65XX assembler directives, and the corresponding
|
|
expressions in 80XX-style language.<BR>
|
|
<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE><B> 65XX-style 80XX-style Expl.</B>
|
|
.native .nocash select native or nocash syntax
|
|
*=$c100 org 0c100h sets the assumed origin in memory
|
|
*=*+8 org $+8 increments origin, does NOT produce data
|
|
label label: sets a label equal to the current address
|
|
label=$dc00 label equ 0dc00h assigns a value or address to label
|
|
.by $00 db 00h defines a (list of) byte(s) in memory
|
|
.byt $00 defb 00h same as .by and db
|
|
.wd $0000 dw 0000h defines a (list of) word(s) in memory
|
|
.end end indicates end of source code file
|
|
|nn [|nn] force 16bit "00NN" instead 8bit "NN"
|
|
#<nnnn nnnn AND 0FFh isolate lower 8bits of 16bit value
|
|
#>nnnn nnnn DIV 100h isolate upper 8bits of 16bit value
|
|
N/A (?) fast label ensure relative jump without page crossing
|
|
N/A (?) slow label ensure relative jump with page crossing
|
|
</TD></TR></TABLE><BR>
|
|
<B>Special Directives</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> .65xx Select 6502 Instruction Set
|
|
.nes Create NES ROM-Image with .NES extension
|
|
.c64_prg Create C64 file with .PRG extension/stub/fixed entry
|
|
.c64_p00 Create C64 file with .P00 extension/stub/fixed entry/header
|
|
.vic20_prg Create VIC20/C64 file with .PRG extension/stub/relocated entry
|
|
end entry End of Source, the parameter specifies the entrypoint
|
|
</TD></TR></TABLE>The C64 files contain Basic Stub "10 SYS<entry>" with default ORG 80Eh.<BR>
|
|
<BR>
|
|
<B>VIC20 Stub</B><BR>
|
|
The VIC20 Stub is "10 SYSPEEK(44)*256+<entry>" with default ORG 1218h, this
|
|
relocates the entryoint relative to the LOAD address (for C64: 818h, for
|
|
VIC20: 1018h (Unexpanded), 0418h (3K Expanded), 1218h (8K and more
|
|
Expansion). It does NOT relocate absolute addresses in the program, if the
|
|
program wishes to run at a specific memory location, then it must de-relocate
|
|
itself from the LOAD address to the desired address.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuglitches"></A><FONT SIZE=+2> CPU Glitches</FONT></TD></TR></TABLE><BR>
|
|
<B>Dummy Read Cycles at Page-Wraps</B><BR>
|
|
Dummy reads occur when reads from [nnnn+X] or [nnnn+Y] or [WORD[nn]+Y] are
|
|
crossing page boundaries, this applies only to raw read-opcodes, not for
|
|
write or read-and-modify opcodes (ie. only for opcodes that include an extra
|
|
clock cycle on page boundaries, such as LDA, CMP, etc.)<BR>
|
|
For above reads, the CPU adds the index register to the lower 8bits of the
|
|
16bit memory address, and does then read from the resulting memory address,
|
|
if the addition caused a carry-out, then an extra clock cycle is used to
|
|
increment the upper 8bits of the address, and to read from the correct memory
|
|
location. For example, a read from [1280h+X] with X=C0h produces a dummy read
|
|
from [1240h], followed by the actual read from [1340h].<BR>
|
|
Dummy reads cause no problems with normal ROM or RAM, but may cause problems
|
|
with read-sensitive I/O ports (eg. IRQ flags that are automatically cleared
|
|
after reading, or data-registers that are automatically incrementing
|
|
associated memory pointers, etc.)<BR>
|
|
<BR>
|
|
<B>Dummy Write Cycles in Read-Modify-Opcodes</B><BR>
|
|
Dummy writes occur in all read-modify opcodes, ie. all INC, DEC, Shift,
|
|
Rotate opcodes with memory operands. The opcodes consist of three memory
|
|
accesses: read original value, write dummy value, write result value.<BR>
|
|
Dummy writes cause no problems with normal RAM, but may cause problems (or
|
|
may be useful) with write-sensitive I/O ports (eg. IRQ flags that are cleared
|
|
by writing certain values, or data-registers that are automatically
|
|
incrementing associated memory pointers, etc.)<BR>
|
|
On the C64 and C16, the written dummy value appears to be equal to the
|
|
original value, a couple of programs are using this to acknowledge IRQs.<BR>
|
|
On the NES, the dummy value appears to be equal to the result value, though
|
|
more or less unstable ANDed with a random number. Presumably 00h is output
|
|
during the first half of the write cycle, and the result only during the
|
|
second half, not leaving enough time to raise all bits from LOW to high.
|
|
Also, dummy writes to [2007h] aren't always recognized (ie. the VRAM address
|
|
register isn't always incremented twice), presumably because the PPU isn't
|
|
fast enough to realize two write-signals immediately after each other, that
|
|
maybe because it is attempting to synchronize CPU bus writes with the PPU
|
|
bus.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cputhe65xxfamily"></A><FONT SIZE=+2> CPU The 65XX Family</FONT></TD></TR></TABLE><BR>
|
|
Different versions of the 6502:<BR>
|
|
<BR>
|
|
All of these processors are the same concerning the software-side:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 6501 Some sort of 6502 prototype
|
|
6502 Used in the CBM floppies and some other 8 bit computers.
|
|
6507 Used in Atari 2600, 28pins (only 13 address lines, no /IRQ, no /NMI).
|
|
6510 Used in C64, with built-in 6bit I/O port.
|
|
7501 Used in C16,C116,Plus/4, with built-in 7bit I/O Port, without /NMI pin.
|
|
8500 Used in C64-II, with different pin-outs.
|
|
8501 Same as 7501
|
|
8502 Used in C128s.
|
|
</TD></TR></TABLE><BR>
|
|
Some processors of the family which are not 100% compatible:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 65C02 Extension of the 6502
|
|
65SC02 Small version of the 65C02 which lost a few opcodes again.
|
|
65CE02 Extension of the 65C02, used in the C65.
|
|
65816 Extended 6502 with new opcodes and 16 bit operation modes.
|
|
2A03 Nintendo NES/Famicom, modified 6502 with built-in sound controller.
|
|
</TD></TR></TABLE><BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpulocalusage"></A><FONT SIZE=+2> CPU Local Usage</FONT></TD></TR></TABLE><BR>
|
|
<B>Atari 2600 - CPU 6507</B><BR>
|
|
The 6507 is a 6502-compatible CPU squeezed into a DIL-28 package, it's having
|
|
only 8K address space, and doesn't have any IRQ or NMI inputs.<BR>
|
|
Clocked at 1.193182 MHz (NTSC), 1.182298 MHz (PAL).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="hardwaresoldering"></A><FONT SIZE=+2> Hardware / Soldering</FONT></TD></TR></TABLE><BR>
|
|
<B>Hardware Tuning</B><BR>
|
|
<A HREF="#nocashsramcircuit">Nocash SRAM Circuit</A><BR>
|
|
<A HREF="#compositevideoandaudioout">Composite Video and Audio Out</A><BR>
|
|
<A HREF="#usingapcpowersupply">Using a PC Power Supply</A><BR>
|
|
<BR>
|
|
<B>Cartridge Slot and Controller Ports</B><BR>
|
|
<A HREF="#controllersexternalportpinouts">Controllers: External Port Pin-Outs</A><BR>
|
|
<A HREF="#cartpinouts">Cart Pin-Outs</A><BR>
|
|
<BR>
|
|
<B>Mainboard - CPU, PIA, TIA</B><BR>
|
|
<A HREF="#chipsetpinouts">Chipset Pin-Outs</A><BR>
|
|
<BR>
|
|
<B>Other Connectors</B><BR>
|
|
- TV: One Cinch Socket (Video/Audio TV Signal) ;doesn't work with all RF cables<BR>
|
|
- Power: 9V DC, 500mA (internally converted to 5V DC)<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="nocashsramcircuit"></A><FONT SIZE=+2> Nocash SRAM Circuit</FONT></TD></TR></TABLE><BR>
|
|
<B>Nocash SRAM Circuit</B><BR>
|
|
This circuit has been developed while testing no$2k6, it wired directly to
|
|
the Atari mainboard, and allows to upload ROM-images from PC to Atari via
|
|
function in no$2k6 utility menu. Features:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> - one-directional 4bit highspeed upload (when joystick is not moved)
|
|
- bi-directional 1bit transmission for upload/download/debug terminal
|
|
- works with external carts (if parallel cable disconnected or all high)
|
|
- upload with automatic reset (autostart)
|
|
- works with any older/newer one/two-directional PC parallel port
|
|
- supports almost all existing cartridge types (except eight games)
|
|
</TD></TR></TABLE>Only a few exotic cartridges (eight games) are not supported: JSR banking
|
|
(Decathln), 256 bytes RAM expansion (Mtnking, Omegarac, Tunlrunr), Port
|
|
FFEX Nx2K banking (Bnj, Burgtime, He_man), and the sequential memory
|
|
controller (Pitfall2).<BR>
|
|
<BR>
|
|
<B>Step 1 - Basic Connection (raw 1K,2K,4K unbanked ROM) (for 348 games)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> _____________ _____________
|
|
D0-7 --|D0-7 | D0-7 --|D0-7 |
|
|
A0-6,8-10 --|A06,8-10 | A0-6,8-10 --|A0-6,8-10 |
|
|
XA7,11 --|A7,11 | XA7,11-14 --|A7,11-14 |
|
|
VCC --|A12-15 EPROM | /WRS --|/WE SRAM |
|
|
/MREQ --|/CS 64Kx8 | /MREQ --|/CS 32Kx8 |
|
|
/PROM.DTA3 --|/OE 27C512 | /SRAM.DTA2 --|/OE 62C256 |
|
|
|_____________| |_____________|
|
|
</TD></TR></TABLE><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> XA7 --------- A7 /RES.DTA4 ---|<|--- /RES,TP2,C27(+)
|
|
XA11 --------- A11 /PROM.DTA3 --[10K]-- VCC
|
|
R/W --------- /WRS /SRAM.DTA2 --[10K]-- VCC
|
|
LPT.DTA0 --------- SWCHB.5,PIA.18 CART.DTA5 --[10K]-- VCC
|
|
LPT.DTA1 --------- SWCHB.4,PIA.19 XA12 --[10K]-- VCC
|
|
LPT.BUSY --------- SWCHB.2,PIA.22 XA13 --[10K]-- VCC
|
|
LPT./STB --------- SWCHA.0,PIA.8 XA14 --[10K]-- VCC
|
|
LPT./AUTOLF --------- SWCHA.2,PIA.10 ____
|
|
LPT./INIT --------- SWCHA.4,PIA.12 A12 --|AND \__ CS,SLOT.18
|
|
LPT./SELECT --------- SWCHA.6,PIA.14 CART.DTA5 --|____/
|
|
LPT.GND --------- GND A12 --|NAND\__ /MREQ
|
|
CS,SLOT.18 --/cut/-- A12 PHI2 --|____/
|
|
</TD></TR></TABLE><BR>
|
|
<B>Step 2 - Port 3Fh (Nx2K ROM) (for 6 games & control bits for next step)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> ____ _______
|
|
A11 --/cut/--- XA11 A6 --| |-------------|LE |
|
|
GND ---------- 1K A7 --|NOR | D0 --|D0 Q0|-|<|- XA11
|
|
LPT.DTA6 ----- 3F A12 --| | D1 --|D1 Q1|-|<|- XA12
|
|
____ R/W --| | D2 --|D2 Q2|-|<|- XA13
|
|
3F ___|INV \_____________| | D3 --|D3 Q3|-|<|- XA14
|
|
|____/ /3F |____| D4 --|D4 Q4|-- 1K
|
|
A11 ---|NOR | ____ D5 --|D5 Q5|-- 4K
|
|
3F ---| |__|INV \--|<|--XA11 D6 --|D6 Q6|-- /16K
|
|
1K ---| | |____/ ____ D7 --|D7 Q7|-- /32K
|
|
GND ---| | 3F --|AND \_______|/OE |
|
|
GND ---|____| A11 --|____/ |_______| 74373
|
|
XA11 --[10K]-- VCC XA10 --[10K]-- VCC 1K --[10K]-- VCC
|
|
</TD></TR></TABLE><BR>
|
|
<B>Step 3 - Port FFFXh (Nx4K ROM) (for ca. 160 games)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> ____ ____ _________
|
|
PHI2 -| | A2 -----|NAND\_ ____ ____ 4K -|/CE1 /OE1|-- XRAM
|
|
A5 ---| | /32K ---|____/ |XOR \_________| | 3F -|/CE2 /OE2|-- GND
|
|
A6 ---|NAND| A1 -----|NAND\_|____/ /GOODA2 | |______|CLK RES|-- GND
|
|
A7 ---| | 16K ----|____/ _______|NOR | | 74173 |
|
|
A8 ---| | A2 -----|NAND\_ ____ GND | | A0 -|D0 Q0|-|<|-XA12
|
|
A9 ---| | 16K32K -|____/ |XOR \_________| | A1 -|D1 Q1|-|<|-XA13
|
|
A10 --| |_ A3 ------------|____/ /GOODA3 | | A2 -|D2 Q2|-|<|-XA14
|
|
A11 --|____| | GND --- XRAM ________________| | NC -|D3 Q3|-- NC
|
|
____ |______________| ____ /GOODFF | | |_________|
|
|
/16K -|XOR \___ ___|INV \_________| | /16K --|XOR \__ 16K
|
|
/32K -|____/ 16K32K A4 |____/ /GOODA4 |____| VCC --|____/
|
|
</TD></TR></TABLE><BR>
|
|
<B>Step 4 - XRAM (128 Bytes Expansion RAM) (for 17 games) (and Write Protect)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> ____ ____
|
|
A8 ---| |-- XRAM GND --/cut/-- XRAM XRAM -|OR \__ XA7
|
|
A9 ---|NOR | A7 --/cut/-- XA7 A7 --|____/
|
|
A10 ---| | R/W --/cut/-- /WRS ____ R/W --|OR \__ /WRS
|
|
A11 ---| | /XRAM.DTA7 -----------------|AND \_______|____/
|
|
/XRAM.DTA7 ---|____| /3F -----------------|____/ WPROT
|
|
</TD></TR></TABLE><BR>
|
|
<B>Step 5 - Port FFXXh (Nx1K ROM) (for 13 games)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> __________ ____
|
|
A0..2 ---|D0-2 Q0-2|--- XA10..12 A10 --/cut/-- XA10 1K --|OR \-|<|-XA10
|
|
A12 -----|D3 Q3|--- NC GND --/cut/-- 1K A10 --|____/
|
|
A3 ------|WA0 RA0|--- A10 ____ 3F __|INV \-|<|- 1K
|
|
A4 ------|WA1 RA1|--- A11 ____ _______/AND |--- A10 |____/
|
|
/GOODFF -|/WR /RD|________/OR | \____|--- A11 1K __|INV \_____ /1K
|
|
|__________| 74170 \____|__/1K |____/
|
|
</TD></TR></TABLE><BR>
|
|
<B>Notes</B><BR>
|
|
The Eprom socket can be soldered directly on top of the SRAM (only Pins 1,
|
|
2, 22, 26, and 27 need different connection).<BR>
|
|
Implement the separate steps in incrementing order, steps 2 and up are
|
|
optional, the device should be fully functional after completion of each
|
|
step, do not attempt to implement all steps at once, establish 1-2 days
|
|
per step.<BR>
|
|
<BR>
|
|
<B>Parts List</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 1 27C512 EPROM (or EEPROM, or FLASH, or other size, min 1KByte)
|
|
1 62C256 Static RAM (32KBytes or bigger)
|
|
1 74LS04 Hex Inverter
|
|
1 74LS08 Quad 2-input AND gate
|
|
1 74LS30 Single 8-input NAND gate
|
|
1 74LS32 Quad 2-input OR gate
|
|
1 74LS86 Quad 2-input XOR gate
|
|
1 74LS170 4x4 Register File open collector
|
|
1 74LS173 4-bit 3-state flip-flop with clock enable
|
|
2 74LS260 Dual 5-input NOR gate
|
|
1 74LS374 8-bit 3-state flip-flop
|
|
9 10K Ohm Resistors
|
|
11 1N4148 diodes (for /Reset signal, and ANDed "XAnn" and "1K" outputs)
|
|
1 Centronics socket 36pin female (and standard printer cable)
|
|
</TD></TR></TABLE>Plus socket(s) for EPROM (and any other chips), 100nF capacitors for all
|
|
chips, wire, board, solder, tools, eprom burner.<BR>
|
|
Caution: 74LS260 outputs are at Pin 5 & 6 (unlike some internet-specs say)<BR>
|
|
<BR>
|
|
<B>BIOS EPROM</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 0000 20 4A FC 9D FC 34 20 4C FC FF FC 26 20 25 FD 85
|
|
0010 85 20 25 FD 85 86 A9 00 85 80 A9 F0 85 81 20 87
|
|
0020 00 20 3F FC 4C 30 FC 20 87 00 20 3F FC 4C 30 FC
|
|
0030 20 4A FC D1 FC 2E 20 4C FC 25 FD 27 4C 87 00 A5
|
|
0040 82 20 FF FC A5 83 20 FF FC 60 A0 87 20 6C FC 85
|
|
0050 80 20 6C FC 85 81 20 6C FC 85 84 98 AA A0 00 B1
|
|
0060 80 95 00 C8 E8 C4 84 D0 F6 8A A8 60 BA F6 03 D0
|
|
0070 02 F6 04 A1 03 60 A0 00 84 80 20 AE 00 85 3F 20
|
|
0080 AE 00 85 81 0A F0 15 20 AE 00 91 80 18 65 82 85
|
|
0090 82 A9 00 65 83 85 83 C8 D0 ED F0 DE 60 20 BB 00
|
|
00A0 A6 85 DD 00 FF A0 00 B1 80 48 20 BB 00 68 18 65
|
|
00B0 82 85 82 A9 00 65 83 85 83 E6 80 D0 E3 E6 81 D0
|
|
00C0 DF A9 F0 85 81 A5 85 E6 85 C5 86 D0 D3 20 BB 00
|
|
00D0 60 20 B5 00 85 3F 20 B5 00 A2 58 86 49 8D 97 00
|
|
00E0 CD 00 FF A9 0F 85 3F A9 FF 8D 97 02 8D 80 02 8D
|
|
00F0 82 02 A9 00 85 81 8D 81 02 8D 83 02 6C FC FF 85
|
|
0100 84 A0 04 A9 10 06 84 69 03 8D 82 02 A9 10 2C 82
|
|
0110 02 D0 FB 06 84 69 03 8D 82 02 A9 10 2C 82 02 F0
|
|
0120 FB 88 D0 E1 60 A9 01 85 84 A9 10 2C 82 02 D0 FB
|
|
0130 0A 2D 82 02 C9 20 26 84 A9 10 2C 82 02 F0 FB 0A
|
|
0140 2D 82 02 C9 20 26 84 90 E0 A5 84 60 A9 10 2C 82
|
|
0150 02 D0 FB 0E 80 02 2C 82 02 F0 FB AD 80 02 60 A2
|
|
0160 00 BD 99 FD 20 FF FC E8 BD 99 FD D0 F4 A2 00 20
|
|
0170 25 FD DD AA FD D0 FE E8 E0 08 D0 F3 A9 2B 20 FF
|
|
0180 FC A2 00 A0 2B 20 4C FD DD AA FD F0 02 A0 2D E8
|
|
0190 E0 08 D0 F1 98 20 FF FC 60 4E 4F 24 32 4B 36 20
|
|
01A0 42 49 4F 53 20 56 31 2E 31 00 00 FF 55 AA 0F F0
|
|
01B0 3C C3 20 25 FD 85 3F 20 25 FD CD F7 FF 20 25 FD
|
|
01C0 85 3F 60 78 D8 A9 00 AA 95 00 9A E8 D0 FA A9 0E
|
|
01D0 85 3F A9 04 8D 83 02 A9 AA 8D 81 02 A2 28 86 49
|
|
01E0 20 5F FD 20 B2 FD 20 25 FD C9 31 F0 0B C9 34 F0
|
|
01F0 1A C9 44 F0 25 4C F5 FD A2 00 86 49 20 4A FC 76
|
|
0200 FC 27 20 4C FC 25 FD 27 4C 27 FC 20 4A FC 76 FC
|
|
0210 27 20 4C FC 4C FD 13 4C 27 FC 4C 00 FC FF FF FF
|
|
0220 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
|
.... FF FF FF ............................. FF FF FF
|
|
03F0 FF FF FF FF FF FF FF FF FF FF FF FF C3 FD 00 00
|
|
</TD></TR></TABLE>To be placed to highest memory location, eg. FC00h-FFFFh for 64K chips.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="compositevideoandaudioout"></A><FONT SIZE=+2> Composite Video and Audio Out</FONT></TD></TR></TABLE><BR>
|
|
<B>Composite Video Mod</B><BR>
|
|
This circuit from http://www.console-corner.de/videomod.html uses 5 resistors
|
|
and 1 capacitor. The picture quality is very good, and it's less complicated
|
|
than many other approaches (some of them require potentiometers, non-standard
|
|
resistor values, transistors, chips, or need to disconnect the original RF
|
|
modulator).<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> LUM0'----[3K3]----o----------------o--------VIDEO OUT
|
|
| |
|
|
LUM1'----[2K2]----o 100p
|
|
| |
|
|
LUM2'----[1K]-----o TIA.COLOR---o-----[1K]-----GND
|
|
|
|
|
SYNC'----[330]----o TIA.AUDIO------------AUDIO OUT
|
|
</TD></TR></TABLE>The LUMx' and SYNC' signals are found on the following pins of the 4050-chip:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Type LUM0' LUM1' LUM2' SYNC'
|
|
Atari 2600 4050.Pin2 4050.Pin12 4050.Pin15 4050.Pin4
|
|
Atari 2600A N/A N/A N/A N/A
|
|
Atari Junior 4050.Pin2 4050.Pin10 4050.Pin15 4050.Pin12
|
|
</TD></TR></TABLE>The COLOR, AUDIO, LUMx and SYNC signals are on these TIA (6526) pins:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Type COLOR AUDIO LUM0 LUM1 LUM2 SYNC
|
|
PAL TIA.Pin9 TIA.Pin13 TIA.Pin7 TIA.Pin5 TIA.Pin6 TIA.Pin2
|
|
NTSC TIA.Pin9 TIA.Pin13+12 TIA.Pin8 TIA.Pin5 TIA.Pin7 TIA.Pin2
|
|
</TD></TR></TABLE>Best use the LUMx' and SYNC' signals on the 4050-chip. Some mainboards do not
|
|
include that chip, if it's absent: pick the LUMx and SYNC signals on the
|
|
TIA-chip (you may need to change the resistor values in that case).<BR>
|
|
<BR>
|
|
<B>RF Notes</B><BR>
|
|
Installing the 4 resistors on the 4050 outputs has little (or no) effect on
|
|
RF output, installing the Color-to-GND resistor makes dark RF colors slightly
|
|
darker, installing the capacitor & connecting the video-out cable does reduce
|
|
the quality of the RF output - but it's still working, and you'll no longer
|
|
need it anyways.<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="usingapcpowersupply"></A><FONT SIZE=+2> Using a PC Power Supply</FONT></TD></TR></TABLE><BR>
|
|
When using a PC (or other computer) to develop Atari games it might be
|
|
recommended to connect the console directly to the PC's power supply,
|
|
without having to use the external 9V power supply.<BR>
|
|
<BR>
|
|
<B>Using +5V DC Power Supply</B><BR>
|
|
Connect +5V (red floppy cable) directly to the 7805 voltage regulator's
|
|
5V output (not to the 9V input). Connect GND (black floppy cable) to
|
|
middle 7805 pin (not required if centronics cable is connected). Most of
|
|
the console works fine at 5V, but a few things still need to get
|
|
modified to get it working at raw 5V only:<BR>
|
|
Move the power switch into 5V line (so that 9V are always on, and that 5V
|
|
can be switched on and off). Replace the 750 Ohm LED resistor (R57) by 390
|
|
Ohm, and connect it to 5V instead of 9V. And, most important, connect
|
|
color adjust potientometer (R9) to 5V instead of 6.2V, and re-adjust it so
|
|
that it outputs approximately 3.38V (PAL) at the middle pin.<BR>
|
|
That's it. It's now everything working at 5V internally - and would still
|
|
work alternately with 9V external supply.<BR>
|
|
<BR>
|
|
<B>Using +12V DC Power Supply</B><BR>
|
|
Alternately, +12V (yellow floppy cable) could be connected directly to the
|
|
9V input without any console modifications.<BR>
|
|
Drawbacks would be that the 7805 voltage converter would be producing more
|
|
heat, and that some consoles are using a '3.5mm headphone socket' as power
|
|
input - which would produce a shortcut (and shutdown the PC power supply)
|
|
when inserting/removing the plug.<BR>
|
|
Note: An external 7809 would solve that problems, it'd split the heat to
|
|
the 7809 and 7805, and it'd provide a more or less reliable protection
|
|
against shortcuts (at least for short periodes, the 7809 would get very
|
|
hot if the plug is stuck in 'half inserted' position).<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="chipsetpinouts"></A><FONT SIZE=+2> Chipset Pin-Outs</FONT></TD></TR></TABLE><BR>
|
|
<B>CPU 6507 - Central Processing Unit (cut-down 6502 with only 28 pins)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 25..28 D0..D7
|
|
4,2 VCC,GND
|
|
5..17 A0..A12
|
|
1,3,26 /RES,RDY,R/W
|
|
27,28 PHI0,PHI2
|
|
</TD></TR></TABLE><BR>
|
|
<B>PIA 6532 - (128 bytes RAM, I/O Ports, Timer)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 33..26 D0..D7
|
|
7..2,40 A0..A6
|
|
35 R/W
|
|
25 IRQ (NC)
|
|
36 /RS (A9)
|
|
37 /CS2 (A12)
|
|
38 CS1 (A7)
|
|
39 PHI2
|
|
34 /RES
|
|
8..15 PA0..PA7 (UDLR2, UDLR1)
|
|
1,20 GND,VCC
|
|
16..24 PB7..PB0 (DIF1,DIF0,NC,NC,COLOR,SELECT,RESET)
|
|
</TD></TR></TABLE><BR>
|
|
<B>TIA 6526 - Television Interface Adapter (Video, Audio, Pot/Button Inputs)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 20,23,22,1 VCC,VCC,GND,GND
|
|
14..19,33..34 D0..D7
|
|
32..27 A0..A5
|
|
21,24 /CS1 (A7), /CS2 (A12)
|
|
3,25,4,26,11 RDY,R/W,PHI0,PHI2,OSC
|
|
40..37,36,35 P0..P3 (POT0..3), T0..T1 (BUTTON1,2)
|
|
2,9,10 SYNC, COLOR, CADJ (+3.4V)
|
|
</TD></TR></TABLE>For PAL (6526P):<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 7,5,6 LUM0,LUM1,LUM3
|
|
13,12,8 AUD,PALS,PALI ;AUD is audio AUD0+AUD1 merged on one pin
|
|
</TD></TR></TABLE>For NTSC:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 8,5,7 LUM0,LUM1,LUM2
|
|
13,12,6 AUD0,AUD1,/BLK ;Pin6 exist in 2600 only (not 2600A?)
|
|
</TD></TR></TABLE><BR>
|
|
<B>4050 (non-inverting buffer; used as amplifier or edge-sharpener or so)</B><BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> 3,5,7,9,11,14 INPUT A,B,C,D,E,F
|
|
2,4,6,10,12,15 OUTPUT A,B,C,D,E,F
|
|
1,8,13,16 VCC,GND,NC,NC
|
|
</TD></TR></TABLE>The chip exists in (most) PAL/NTSC consoles, connected like so:<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> Atari 2600 A=LUM0, B=SYNC, C=JOY2, D=JOY1, E=LUM1, F=LUM2
|
|
Atari 2600A N/A N/A N/A N/A N/A N/A
|
|
Atari Junior A=LUM0, B=/RES, C=PALI, D=LUM1, E=SYNC, F=LUM2
|
|
</TD></TR></TABLE>Not sure about the purpose of C=PALI in PAL consoles, and no idea if/how that
|
|
pin is used in NTSC consoles (?)<BR>
|
|
<BR>
|
|
<BR>
|
|
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="links"></A><FONT SIZE=+2> Links</FONT></TD></TR></TABLE><BR>
|
|
<B>AtariAge - Atari 2600 ROMs</B><BR>
|
|
About 500 games (ROM images) for the Atari 2600, about 2MB zipped.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> http://www.atariage.com/system_items.html?SystemID=2600&ItemTypeID=ROM
|
|
</TD></TR></TABLE>The webpage also includes a nice FAQ, very useful schematics, and various
|
|
other info. The separate pages are badly generated bloated html, loading
|
|
VERY slowly, and likely to crash your browser.<BR>
|
|
<BR>
|
|
<B>Stella Programmer's Guide</B><BR>
|
|
Official specs for Atari 2600, TIA and PIA chips (but lacks information
|
|
about CPU and ROM), by Steve Wright 12/03/79, reconstructed by Charles
|
|
Sinnett 6/11/93.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> http://alienbill.com/vgames/guide/docs/stella.html
|
|
</TD></TR></TABLE>This document is a matter of slightly increasing information, each chapter
|
|
repeats the exact information from the previous chapter, and eventually
|
|
reveals some additional details.<BR>
|
|
<BR>
|
|
<B>65xx processor series opcodes</B><BR>
|
|
Very nice summary of documented and undocumented 65XX opcodes.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> http://oxyron.net/graham/opcodes.html
|
|
</TD></TR></TABLE><BR>
|
|
<B>nocash 2K6 specs</B><BR>
|
|
This document (or newer updates), in TXT and HTM format.<BR>
|
|
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><PRE> http://nocash.emubase.de/2k6specs.txt
|
|
http://nocash.emubase.de/2k6specs.htm
|
|
</TD></TR></TABLE>Atari 2600 Programming Specs. Describes TIA and PIA I/O ports, CPU,
|
|
memory, cartridges, joysticks, paddles, etc.<BR>
|
|
<BR>
|
|
</BODY></HTML>
|