problemkaputt.github.io/pagezero.htm
2021-01-14 23:48:20 -08:00

4648 lines
250 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<HTML><HEAD>
<TITLE>Pagezero Commodore 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>&nbsp;Pagezero</FONT></TD></TR></TABLE><BR>
<B>Specifications</B><BR>
<A HREF="#c64specs">C64 Specs</A><BR>
<A HREF="#vic20specs">VIC20 Specs</A><BR>
<A HREF="#c16plus4specs">C16/PLUS4 Specs</A><BR>
<A HREF="#cpu65xxmicroprocessor">CPU 65XX Microprocessor</A><BR>
<BR>
<B>Links</B><BR>
<A HREF="#links">Links</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64specs"></A><FONT SIZE=+2>&nbsp;C64 Specs</FONT></TD></TR></TABLE><BR>
<B>C64 Overviews</B><BR>
<A HREF="#c64technicaldata">C64 Technical Data</A><BR>
<A HREF="#c64iomap">C64 I/O Map</A><BR>
<A HREF="#c64interruptsandnmis">C64 Interrupts and NMIs</A><BR>
<BR>
<B>C64 I/O Specs</B><BR>
<A HREF="#c64memorybankinganddatasette">C64 Memory Banking and Datasette</A><BR>
<A HREF="#c64videocontroller">C64 Video Controller</A><BR>
<A HREF="#c64soundinterface">C64 Sound Interface</A><BR>
<A HREF="#c64complexinterfaceadapters">C64 Complex Interface Adapters</A><BR>
<BR>
<B>Other</B><BR>
<A HREF="#diskdrive">Disk Drive</A><BR>
<A HREF="#cpu65xxmicroprocessor">CPU 65XX Microprocessor</A><BR>
<A HREF="#z80microprocessorcartridge">Z80 Microprocessor Cartridge</A><BR>
<A HREF="#kernalfunctions">KERNAL Functions</A><BR>
<A HREF="#externalconnectors">External Connectors</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64technicaldata"></A><FONT SIZE=+2>&nbsp;C64 Technical Data</FONT></TD></TR></TABLE><BR>
COMMODORE 64 (C64)<BR>
<BR>
<B>Microprocessor</B><BR>
<TABLE><TR><TD><PRE> 6510A 8bit CPU, 1.02 MHz (NTSC) or 0.98 MHz (PAL), Compatible with 6502
</TD></TR></TABLE><B>Memory</B><BR>
<TABLE><TR><TD><PRE> 64Kbytes RAM (used for both work RAM and video RAM)
16Kbytes KERNAL/BASIC ROM
4Kbytes Character ROM (156 unique chars & many duplicated/inverted chars)
1024x4bit Color RAM
</TD></TR></TABLE><B>Display</B><BR>
<TABLE><TR><TD><PRE> 40x25 Character Text mode, or 320x200 (or 160x200) Pixels Bitmap mode
40x25 Color attributes used for both Text and Bitmap modes
High resolution allows two colors (out of 16) per 8x8 tile
Low resolution allows four colors (out of 16) per 4x8 tile
8 Sprites (each HiRes 24x21 one color, or LowRes 12x21 three colors)
Horizontal and vertical sprite magnification (normal and double size)
Sprite-to-Sprite and Sprite-to-Background collision detection
</TD></TR></TABLE><B>6581 Sound Interface Device</B><BR>
<TABLE><TR><TD><PRE> 3 independent tone generators - each with 9 octaves
Each voice includes programmable ADSR generator (Attack, Decay,
Sustain, Release) and control of sawtooth, triangle, square,
variable pulse and noise waveforms
Full filtering capabilities with low, high and band pass filters
External sound input
</TD></TR></TABLE><B>Keyboard</B><BR>
<TABLE><TR><TD><PRE> 66 Keys, including not more than two (2) cursor keys
</TD></TR></TABLE><B>Connectors</B><BR>
<TABLE><TR><TD><PRE> User port
Serial port (for Printer or Disk drive)
ROM cartridge port
2 Joystick/paddle ports
2 Video ports (Monitor or TV)
C1530 Cassette drive interface port (aka Datasette)
</TD></TR></TABLE><B>Power Supply</B><BR>
<TABLE><TR><TD><PRE> External Supply, +5V DC and 9V AC(!).
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64iomap"></A><FONT SIZE=+2>&nbsp;C64 I/O Map</FONT></TD></TR></TABLE><BR>
<B>CPU On-Chip I/O Port</B><BR>
<TABLE><TR><TD><PRE> 0000 MOS 6510 CPU On-Chip I/O Port Direction
0001 MOS 6510 CPU On-Chip I/O Port Data - Memory and Datasette
</TD></TR></TABLE><B>D000-D02E MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)</B><BR>
<TABLE><TR><TD><PRE> D000 Sprite 0 X Pos
D001 Sprite 0 Y Pos
D002 Sprite 1 X Pos
D003 Sprite 1 Y Pos
D004 Sprite 2 X Pos
D005 Sprite 2 Y Pos
D006 Sprite 3 X Pos
D007 Sprite 3 Y Pos
D008 Sprite 4 X Pos
D009 Sprite 4 Y Pos
D00A Sprite 5 X Pos
D00B Sprite 5 Y Pos
D00C Sprite 6 X Pos
D00D Sprite 6 Y Pos
D00E Sprite 7 X Pos
D00F Sprite 7 Y Pos
D010 Sprites 0-7 X Pos (msb of X coord.)
D011 VIC Control Register (1)
D012 Read Raster / Write Raster Value for Compare IRQ
D013 Lightpen Latch X Pos
D014 Lightpen Latch Y Pos
D015 Sprite display Enable: 1 = Enable
D016 VIC Control Register (2)
D017 Sprites 0-7 Expand 2x Vertical (Y)
D018 VIC Memory Control Register
D019 VIC Interrupt Flag Register
D01A IRQ Mask Register: 1 = Interrupt Enabled
D01B Sprite to Background Display Priority
D01C Sprites 0-7 Multi-Color Mode Select
D01D Sprites 0-7 Expand 2x Horizontal (X)
D01E Sprite to Sprite Collision Detect
D01F Sprite to Background Collision Detect
D020 Border Color
D021 Background Color 0
D022 Background Color 1
D023 Background Color 2
D024 Background Color 3
D025 Sprite Multi-Color Register 0
D026 Sprite Multi-Color Register 1
D027 Sprite 0 Color
D028 Sprite 1 Color
D029 Sprite 2 Color
D02A Sprite 3 Color
D02B Sprite 4 Color
D02C Sprite 5 Color
D02D Sprite 6 Color
D02E Sprite 7 Color
D02F-D03F Not used (always FFh)
D040-D3FF Mirrors of above VIC registers (repeated each 40h bytes)
</TD></TR></TABLE><B>D400-D7FF MOS 6581 SOUND INTERFACE DEVICE (SID)</B><BR>
<TABLE><TR><TD><PRE> D400 Voice 1: Frequency Control - Low-Byte
D401 Voice 1: Frequency Control - High-Byte
D402 Voice 1: Pulse Waveform Width - Low-Byte
D403 Voice 1: Pulse Waveform Width - High-Nybble
D404 Voice 1: Control Register
D405 Envelope Generator 1: Attack / Decay Cycle Control
D406 Envelope Generator 1: Sustain / Release Cycle Control
D407 Voice 2: Frequency Control - Low-Byte
D408 Voice 2: Frequency Control - High-Byte
D409 Voice 2: Pulse Waveform Width - Low-Byte
D40A Voice 2: Pulse Waveform Width - High-Nybble
D40B Voice 2: Control Register
D40C Envelope Generator 2: Attack / Decay Cycle Control
D40D Envelope Generator 2: Sustain / Release Cycle Control
D40E Voice 3: Frequency Control - Low-Byte
D40F Voice 3: Frequency Control - High-Byte
D410 Voice 3: Pulse Waveform Width - Low-Byte
D411 Voice 3: Pulse Waveform Width - High-Nybble
D412 Voice 3: Control Register
D413 Envelope Generator 3: Attack / Decay Cycle Control
D414 Envelope Generator 3: Sustain / Release Cycle Control
D415 Filter Cutoff Frequency: Low-Nybble (Bits 2-0)
D416 Filter Cutoff Frequency: High-Byte
D417 Filter Resonance Control / Voice Input Control
D418 Select Filter Mode and Volume
D419 Analog/Digital Converter Game Paddle 1 (0-255)
D41A Analog/Digital Converter Game Paddle 2 (0-255)
D41B Oscillator 3 Random Number Generator
D41C Envelope Generator 3 Output
D41D-D41F Not used (always 00h)
D420-D7FF Mirrors of above SID registers (repeated each 20h bytes)
</TD></TR></TABLE><B>Color RAM</B><BR>
<TABLE><TR><TD><PRE> D800-DBFF Color RAM (1000 Nybbles, plus 24 unused Nybbles)
</TD></TR></TABLE><B>DC00-DCFF MOS 6526 Complex Interface Adapter (CIA) #1</B><BR>
<TABLE><TR><TD><PRE> DC00 Data Port A (Keyboard, Joystick, Paddles): Game Port 2
DC01 Data Port B (Keyboard, Joystick, Paddles, Lightpen): Game Port 1
DC02 Data Direction Register - Port A
DC03 Data Direction Register - Port B
DC04 Timer A: Low-Byte
DC05 Timer A: High-Byte
DC06 Timer B: Low-Byte
DC07 Timer B: High-Byte
DC08 Time-of-Day Clock: 1/10 Seconds
DC09 Time-of-Day Clock: Seconds
DC0A Time-of-Day Clock: Minutes
DC0B Time-of-Day Clock: Hours + AM/PM Flag (Bit 7)
DC0C Synchronous Serial I/O Data Buffer
DC0D CIA Interrupt Control Register (Read IRQs/Write Mask)
DC0E CIA Control Register A
DC0F CIA Control Register B
DC10-DCFF Mirrors of above CIA1 registers (repeated each 10h bytes)
</TD></TR></TABLE><B>DD00-DDFF MOS 6526 Complex Interface Adapter (CIA) #2</B><BR>
<TABLE><TR><TD><PRE> DD00 Data Port A (Serial Bus, RS-232, VIC Memory Control)
DD01 Data Port B (User Port, RS-232)
DD02 Data Direction Register - Port A
DD03 Data Direction Register - Port B
DD04 Timer A: Low-Byte
DD05 Timer A: High-Byte
DD06 Timer B: Low-Byte
DD07 Timer B: High-Byte
DD08 Time-of-Day Clock: 1/10 Seconds
DD09 Time-of-Day Clock: Seconds
DD0A Time-of-Day Clock: Minutes
DD0B Time-of-Day Clock: Hours + AM/PM Flag (Bit 7)
DD0C Synchronous Serial I/O Data Buffer
DD0D CIA Interrupt Control Register (Read NMIs/Write Mask)
DD0E CIA Control Register A
DD0F CIA Control Register B
DD10-DDFF Mirrors of above CIA2 registers (repeated each 10h bytes)
</TD></TR></TABLE><B>Reserved</B><BR>
<TABLE><TR><TD><PRE> DE00-DEFF Reserved for Future I/O Expansion
DF00-DFFF Reserved for Future I/O Expansion
</TD></TR></TABLE><BR>
The two open I/O slots are for general purpose user I/O, special purpose
I/O cartridges (such as IEEE), and have been tentatively designated for
enabling the Z-80 cartridge (CP/M option) and for interfacing to a
low-cost high-speed disk system.<BR>
<TABLE><TR><TD><PRE> DE00-DEFF Open I/O slot #1 (CP/M Enable) 256 Bytes
DF00-DFFF Open I/O slot #2 (Disk) 256 Bytes
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64interruptsandnmis"></A><FONT SIZE=+2>&nbsp;C64 Interrupts and NMIs</FONT></TD></TR></TABLE><BR>
<B>Possible IRQ (Maskable Interrupt Request) Sources</B><BR>
<TABLE><TR><TD><PRE> Expansion Port &lt;-- /IRQ-pin
VIC &lt;-- Lightpen Trigger
VIC &lt;-- Sprite to Sprite Collision
VIC &lt;-- Sprite to Background Collision
VIC &lt;-- Raster Compare Match
CIA #1 &lt;-- Timer A Interrupt
CIA #1 &lt;-- Timer B Interrupt
CIA #1 &lt;-- TOD Alarm Interrupt
CIA #1 &lt;-- Serial Port Interrupt
CIA #1 &lt;-- FLAG &lt;-- Cassette Read
CIA #1 &lt;-- FLAG &lt;-- Serial Bus SRQ
</TD></TR></TABLE>VIC/CIA registers allow to enable/disable all IRQ sources separately, and
to determine which source(s) have caused the IRQ (except that Cassette
Read and Serial Bus SRQ are sharing the same CIA bits). The CPU can
disable all IRQs by setting the I-flag.<BR>
The CPU shares the same vector, located at [FFFEh], for BRK opcode and for
IRQs. The KERNAL ROM (if it is enabled) pushes the reqisters A,X,Y on
stack, examines the B-flag, and does then redirect to IRQ=[0314h] or
BRK=[0316h].<BR>
<BR>
<B>Possible NMI (Non-Maskable Interrupt) Sources</B><BR>
<TABLE><TR><TD><PRE> Expansion Port &lt;-- /NMI-pin
Memory Controller &lt;-- Trigger/Capaciator &lt;-- Keyboard RESTORE-key
CIA #2 &lt;-- Timer A Interrupt
CIA #2 &lt;-- Timer B Interrupt
CIA #2 &lt;-- TOD Alarm Interrupt
CIA #2 &lt;-- Serial Port Interrupt
CIA #2 &lt;-- FLAG &lt;-- User Port &lt;-- Custom Hardware connected to Pin B
CIA #2 &lt;-- FLAG &lt;-- User Port &lt;-- RS-232 Adapter: Received Data Input
CIA #2 &lt;-- FLAG &lt;-- User Port &lt;-- Centronics Printer Adaper: Busy
</TD></TR></TABLE>CIA registers allow to enable/disable all CIA NMI sources separately, and
to determine which CIA source(s) have caused the NMI (different types of
hardware may be connected to the user port though). The CPU cannot disable
NMIs by setting the I-flag.<BR>
The NMI vector is located at [FFFAh], the KERNAL ROM (if it is enabled)
redirects NMIs to vector [0318h], without pushing any registers.<BR>
The RESTORE-keys trigger/capaciatior prevents switch bounce, the memory
controller issues only a short NMI pulse at the time when the key gets
pressed (this prevents a stuck NMI signal, allowing CIA2 to generate new
NMIs even when the key is kept held down).<BR>
<TABLE><TR><TD><PRE> probably possible to "disable" the RESTORE-key by
a not-acknowledged CIA interrupt signal ???
</TD></TR></TABLE>Caution: Because the RESTORE-key cannot be disabled by software, your
program &lt;must&gt; provide valid NMI vector(s) which must point to a RTI
opcode or other NMI handler, otherwise the C64 crashes when touching the
RESTORE-Key.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64memorybankinganddatasette"></A><FONT SIZE=+2>&nbsp;C64 Memory Banking and Datasette</FONT></TD></TR></TABLE><BR>
<B>0000h - MOS 6510 Data Direction</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
0-7 Direction for Bit 0-7 of Port 0001h (0=Input, 1=Output)
</TD></TR></TABLE>In the C64, this would be usually configured as 2Fh (101111b), so that
Bit 4 is used as input, Bit 0-3,5 as outputs, Bit 6-7 don't care.<BR>
<BR>
<B>0001h - MOS 6510 Micro-Processor On-Chip I/O Port - Memory & Cassette</B><BR>
For Cassette Data Input see Port DC0Dh (CIA #1 Interrupt Control).<BR>
<TABLE><TR><TD><PRE> Bit Expl.
0 /LORAM Signal (*) (0=RAM, 1=BASIC ROM at A000-BFFF)
1 /HIRAM Signal (*) (0=RAM, 1=Kernal ROM at E000-FFFF)
2 /CHAREN Signal (*) (0=Character ROM, 1=I/O at D000-DFFF)
3 Cassette Data Output (Pulse)
4 Cassette Switch Sense (0=Switch Opened, 1=Switch Closed)
(0=play button down)
5 Cassette Motor Control (0=Motor On, 1=Motor Off)
6-7 Not used
</TD></TR></TABLE>(*) In general, Bit 0-3 are following the above specifications, however,
some combinations of these bits (and of some expansion port pins) will
result in special memory modes, see Memory Configurations table below.<BR>
<BR>
<B>Memory Configurations</B><BR>
The table below shows which IO and ROM areas are enabled, depending on the
value (0-3) of the lower two bits of Port 0001h, and on the expansion
ports /GAME and /EXROM pins.<BR>
<TABLE><TR><TD><PRE> Normal Operation 8K Expansion 16K Expansion
Val /game=/exrom=high /game=high,/exrom=low /game=low,/exrom=low
0 RAM RAM IO/C,KERNAL
1 IO/C IO/C IO/RAM
2 IO/C,KERNAL IO/C,KERNAL IO/C,KERNAL,ROMH
3 IO/C,KERNAL,BASIC IO/C,KERNAL,BASIC,ROML IO/C,KERNAL,ROMH,ROML
</TD></TR></TABLE>Note on IO/C (or IO/RAM): Bit 2 of Port 0001h (/CHAREN) selects between
IO-Ports and CHARACTER-ROM (or RAM). Any disabled ROM areas (ie. not
listed in the table) contain RAM.<BR>
<BR>
<B>Memory Map</B><BR>
<TABLE><TR><TD><PRE> Addr Bytes Content
0000 2 IO ;CPU On-chip I/O ports (no RAM here)
0002 254 RAM ;BIOS system data
0100 256 RAM ;CPU Stack
0200 1.5K RAM ;BIOS system data
0800 30K RAM ;Normal BASIC Program space
8000 8K RAM or ROML ;Optional Cartridge ROML space
A000 8K RAM or BASIC or ROMH ;BASIC ROM, or ROMH space
C000 4K RAM ;RAM only
D000 4K RAM or IO or CHAR ;I/O Ports+Colour RAM or CHAR ROM
E000 8K RAM or KERNAL ;KERNAL ROM
</TD></TR></TABLE>Even if ROM is enabled, it is possible to write to underlaying RAM, and
the display controller always reads from RAM - allowing to use the same
memory area for ROM and VRAM.<BR>
<BR>
<B>Expansion ROM Cartridges</B><BR>
Commodore 64 Expansion Cartridges are automatically started if the first nine
bytes of the cartridge ROM at location 8000h contain specific data:<BR>
<TABLE><TR><TD><PRE> 8000h-8001h Cold Start Vector
8002h-8003h Warm Start Vector
8004h-8008h ASCII ID Code "CBM80" with Bit7 set in the first 3 letters
</TD></TR></TABLE><BR>
<B>Ultimax video game console mode (/GAME=LOW,/EXROM=HIGH)</B><BR>
Rarely used memory mode used for Ultimax video games. The upper 60K of
RAM, and all ROM in the C64 are disabled. Ports 0000h and 0001h have no
effect on memory mapping, but may cause problems when attempted to be used
as RAM???.<BR>
<TABLE><TR><TD><PRE> E000-FFFF=ROMH, 8000-9FFF=ROML, D000-DFFF=IO, 0000-0FFF=RAM, other=N/A
</TD></TR></TABLE>The game is started directly by CPU Entrypoint vector at [FFFCh].<BR>
Note that the 2K byte "expansion RAM" for the ULTIMAX, if required, is
accessed out of the COMMODORE 64 and any RAM in the cartridge is ignored.<BR>
<BR>
XXX...Explanation for the bits of $0001:<BR>
<TABLE><TR><TD><PRE> 7 - unused (Flash 8: 0=8MHz/1=1MHz)
6 - unused (C128: ASCII/DIN sense/switch (1=ASCII/0=DIN))
</TD></TR></TABLE>Note to bit 6: This bit is used to select either the ASCII or the DIN
character ROM of a C128. When data direction is set to INPUT, the charset
is selected externally with the ASCII/DIN key.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64videocontroller"></A><FONT SIZE=+2>&nbsp;C64 Video Controller</FONT></TD></TR></TABLE><BR>
MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)<BR>
<BR>
<B>I/O Registers</B><BR>
<A HREF="#c64viccontrolregisters">C64 VIC Control Registers</A><BR>
<A HREF="#c64vicspriteregisters">C64 VIC Sprite Registers</A><BR>
<A HREF="#c64viccolorregisters">C64 VIC Color Registers</A><BR>
<BR>
<B>Display Data</B><BR>
<A HREF="#c64vicbackgrounddisplaymodes">C64 VIC Background Display Modes</A><BR>
<A HREF="#c64vicspritedisplay">C64 VIC Sprite Display</A><BR>
<A HREF="#c64viccharactersets">C64 VIC Character Sets</A><BR>
<BR>
<B>Timings</B><BR>
<A HREF="#c64vicrendering">C64 VIC Rendering</A><BR>
<A HREF="#c64vicdimensionsandtimings">C64 VIC Dimensions and Timings</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64viccontrolregisters"></A><FONT SIZE=+2>&nbsp;C64 VIC Control Registers</FONT></TD></TR></TABLE><BR>
<B>D011h - VIC Control Register 1</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
7 RC8 Raster Compare Bit 8 (See below, Port D012h)
6 ECM Extended Color Text Mode (0=Normal, 1=Extended)
5 BMM Bitmap Mode (0=Text, 1=Bitmap)
4 DEN Display Enable (0=Blank/Border Color, 1=Enable BG/MOB)
3 RSEL Row Select Display Height (0=24 Rows, 1=25 Rows)
0-2 Y0-2 Smooth Scroll Y Position (0-7)
</TD></TR></TABLE><BR>
<B>D016h - VIC Control Register 2</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
6-7 - Unused
5 RES ALWAYS SET THIS BIT TO 0 ! --- Huh, what/why ???
4 MCM Multi-Color Mode (0=Disable, 1=Enable)
3 CSEL Column Select Display Width (0=38 Columns, 1=40 Columns)
0-2 X0-2 Smooth Scroll to X Position (0-7)
</TD></TR></TABLE><BR>
<B>D012h - Raster Register</B><BR>
Reading from RC0-8 returns the current scanline.<BR>
Writing to RC0-8 defines the raster compare IRQ scanline.<BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 RC0-7 Raster Compare/Scanline
</TD></TR></TABLE>For both reading and writing, the most significant bit (RC8) is located
in Bit 7 of Port D011h.<BR>
The visible display window is in range 51-251 (33h-FBh). - That are, 201
lines ???<BR>
When the current raster matches the written value, the raster interrupt
latch is set.<BR>
<BR>
<B>D013h - Lightpen Latch X Position (LPX) (Divided by two)</B><BR>
<B>D014h - Lightpen Latch Y Position (LPY)</B><BR>
The lightpen input latches the current screen position into LPX,LPY on
a low-going edge. The LPX value is cut down to 8bits (that is the usual
9bit X Position divided by two).<BR>
The lightpen latch may be triggered only once per frame, and subsequent
triggers within the same frame will have no effect. To eliminate dirt,
read LPX and LPY for at least 3 frames, and confirm that all are
(approximately) at the same position.<BR>
<BR>
<B>D018h - VIC Memory Control Register</B><BR>
Selects the Video Matrix Base Address in steps of 1024 bytes (400h), and
the Character Base Address in steps of 2048 bytes (800h). In Bitmap
modes Bit 1-2 are ignored, thus using steps of 8192 bytes (2000h).<BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
4-7 VM# Video Matrix Base Address Bit 13-10
1-3 CB# Character Dot-Data Base Address Bit 13-11
0 - Not used
</TD></TR></TABLE>In the C64, Bit 14-15 of Video Matrix/Character Base are controlled by CIA
#2 Data Port A (Port DD00h, Bit 0-1), values 0-3 specify VRAM addresses
CXXXh,8XXXh,4XXXh,0XXXh, in exactly this (reversed) order.<BR>
Caution: Selection of specific Character Base Address redirects to
character ROM:<BR>
<TABLE><TR><TD><PRE> 1000h or 9000h --&gt; 1st half of Character ROM (D000h)
1800h or 9800h --&gt; 2nd half of Character ROM (D800h)
</TD></TR></TABLE>When actually selecting D000h or D800h as Base, charcter ROM is NOT
accessed ??? Instead underlaying RAM ??? When Bitmap memory crosses
1XXXh area, ROM is (NOT) accessed also ???<BR>
VRAM may be located under ROM, and can be displayed even if overlaying
ROM is enabled ???<BR>
<BR>
Note: Color RAM is always located at D800h-DBFFh, regardless of above.<BR>
<BR>
<B>D019h - VIC Interrupt Flag Register</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
7 IRQ Set on Any Enabled VIC IRQ Condition (0=None, 1=IRQ)
4-6 - Not used
3 ILP Lightpen Triggered IRQ Flag (0=None, 1=IRQ)
2 IMMC Sprite to Sprite Collision IRQ Flag (0=None, 1=IRQ)
1 IMBC Sprite to Background Collision IRQ Flag (0=None, 1=IRQ)
0 IRST Raster Compare IRQ Flag (0=None, 1=IRQ)
</TD></TR></TABLE>Reading returns the (latched) interrupt flags. Writing "1" into Bit(s)
0-3 acknowledges (clears) the respective interrupt flag(s).<BR>
<BR>
<B>D01Ah - Interrupt Enable Register</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
4-7 - Not used
3 ELP Lightpen Triggered (0=Disable, 1=Enable)
2 EMMC Sprite to Sprite Collision (0=Disable, 1=Enable)
1 EMBC Sprite to Background Collision (0=Disable, 1=Enable)
0 ERST Raster Compare (0=Disable, 1=Enable)
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64vicspriteregisters"></A><FONT SIZE=+2>&nbsp;C64 VIC Sprite Registers</FONT></TD></TR></TABLE><BR>
<B>D000h,D002h,D004h,D006h,D008h,D00Ah,D00Ch,D00Eh - Sprite 0-7 Position X</B><BR>
Value 24 is the left-most visible pixel (in 40-column mode).<BR>
"X locations 23 to 347 ($17-$157) and Y locations 50 to 249 ($32-$F9) are
visible." Ah yes, this results in a horizontal range of 325 (321 when using
hex-format), and vertical range of 200, undeclared plus/minus parts offscreen
areas ??? Sprites are smoothly moved at 1pix resolution even when using
magnification or lowres/multicolor ???<BR>
<BR>
The PAL dot clock counter operates in range 0..1F7h (63 CPU cycles * 8 dots),
respectively a MOB at value 1F7h appears one pixel left from a MOB at value
0. MOBs at 1F8h..1FFh are not displayed.<BR>
Early NTSC units use range 0..1FFh (64*8), allowing to use values 0..1FFh.<BR>
Most (newer) NTSC units use range 0..207h (65*8), respectively, it is
probably impossible to position MOBs at the next 8 pixels at the left from
position 0.<BR>
<BR>
<BR>
<B>D001h,D003h,D005h,D007h,D009h,D00Bh,D00Dh,D00Fh - Sprite 0-7 Position Y</B><BR>
Value 50 is the first line (in 25-row mode).<BR>
MOB display is activated when the MOB enable bit is set, and the MOB vertical
position setting matches the current raster value, and only if it isn't
already activated. Once when activated, the MOB will be displayed in the next
21 scanlines (or 42 scanlines if magnified), during this time, changes to the
MOB enable bit, or to the MOB vertical position setting have no effect.<BR>
<BR>
<B>D010h - Sprite 0-7 Position X (Upper Bit)</B><BR>
Most significant X position bits for Sprite 0-7 in Bits 0-7 respectively.<BR>
<BR>
<B>D015 - Sprites 0-7 Enable</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#E Sprite 0-7 Enable (0=Hidden, 1=Display)
</TD></TR></TABLE><BR>
<B>D017 - Sprites 0-7 Expand Vertical (Y)</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#YE Sprite 0-7 Expand Y (0=Normal, 1=Magnified by two)
</TD></TR></TABLE><BR>
<B>D01B - Sprites 0-7 to Background Display Priority</B><BR>
Selects the Sprite-to-Background priority of each sprite. Even when
using "Behind BG" priority, sprites still have priority above "Bkgd #0
or multi-color bit pair 01". (???)<BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#DP Sprite 0-7 Priority (0=Above BG, 1=Behind BG) OR VICE-VERSA ???
</TD></TR></TABLE>The VIC first processes the Sprite-to-Sprite priority (that is, Sprite 0
having highest, and Sprite 7 having lowest priority). And then, only (!)
the sprite with highest priority is displayed above/behind background.<BR>
<BR>
<B>D01C - Sprites 0-7 Multi-Color Mode Select</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#MC Sprite 0-7 Multi Color (0=Normal, 1=Multi Color)
</TD></TR></TABLE>Increases the Sprite color depth to 4 colors (2 bits), using
horizontally magnified Low Resolution 12x21 dots.<BR>
<BR>
<B>D01D - Sprites 0-7 Expand Horizontal (X)</B><BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#XE Sprite 0-7 Expand X (0=Normal, 1=Magnified by two)
</TD></TR></TABLE>When combining Expand-X and Multi-Color, the sprite is magnified twice,
each dot is then sized as four normal pixels horizontally.<BR>
<BR>
<B>D01E - Sprite to Sprite Collision Detect (Read Only)</B><BR>
When non-transparent pixels of two (or more) sprites overlap each other,
collision bits for each of these sprites will be set.<BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#M Sprite 0-7 Collision Flag (0=Normal, 1=Collision)
</TD></TR></TABLE>Collisions are detected even if sprites are located offscreen.<BR>
The IMMC IRQ Bit becomes set when this register changes from 00h to a
non-zero value.<BR>
This register is automatically cleared after reading.<BR>
<BR>
<B>D01F - Sprite to Background Collision Detect</B><BR>
When non-transparent pixels of any sprites overlap non-transparent
background pixels, collision bits for any such sprites will be set.<BR>
"For special applications, the display data from the 0-1 multicolor bit
pair also does not cause a collision. This feature permits their use as
background display data without interfering with true MOB collisions."
???<BR>
<TABLE><TR><TD><PRE> Bit Name Expl.
0-7 M#D Sprite 0-7 Collision Flag (0=Normal, 1=Collision)
</TD></TR></TABLE>Offscreen collisions may occur in 38 column mode if overlapping the two
horizontally offscreen hidden columns.<BR>
The IMBC IRQ Bit becomes set when this register changes from 00h to a
non-zero value.<BR>
This register is automatically cleared after reading.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64viccolorregisters"></A><FONT SIZE=+2>&nbsp;C64 VIC Color Registers</FONT></TD></TR></TABLE><BR>
<B>Color Codes</B><BR>
All registers below are 4bit registers, of which the upper 4bits are
unused, the lower 4bits define a color by using the following codes:<BR>
<TABLE><TR><TD><PRE> 0 Black 8 Orange
1 White 9 Brown
2 Red 10 Light red
3 Cyan 11 Dark grey
4 Purple 12 Medium grey
5 Green 13 Light green
6 Blue 14 Light blue
7 Yellow 15 Light grey
</TD></TR></TABLE>Note: In Multi-Color Character Mode, only color codes 0-7 can be used in
Color RAM because Bit 3 of the color nybble is used to select the
resolution.<BR>
<BR>
<B>D020 - Border Color</B><BR>
Also, this color is used when DEN=0.<BR>
<BR>
<B>D021 - Background Color 0</B><BR>
<B>D022 - Background Color 1</B><BR>
<B>D023 - Background Color 2</B><BR>
<B>D024 - Background Color 3</B><BR>
<BR>
<B>D025 - Sprite Multi-Color Register 0</B><BR>
<B>D026 - Sprite Multi-Color Register 1</B><BR>
<BR>
<B>D027-D02E - Sprite 0-7 Colors</B><BR>
<TABLE><TR><TD><PRE> Sprite 0 1 2 3 4 5 6 7
Port D027 D028 D029 D02A D02B D02C D02D D02E
</TD></TR></TABLE><BR>
<B>D800-DBFF - Color RAM 1024 Nybbles</B><BR>
Contains 1000 Color Nybbles for each of the 40x25 background characters,
which are used for all Character Modes and for Multi-Color Bitmap Mode
(but not for Standard Bitmap Mode).<BR>
Note: Additional 24 nybbles exist at the end of the Color RAM, these
might be used for whatever (4bit-) data storage.<BR>
<BR>
<B>Bitmap Color Attributes</B><BR>
In both Standard and Multi-Color Bitmap mode, the 1000 bytes in the
Video Matrix VRAM area are containing color attributes for each of the
40x25 bitmap character regions, the whole 8bit of each byte are used,
allowing to select two 4bit colors.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64vicbackgrounddisplaymodes"></A><FONT SIZE=+2>&nbsp;C64 VIC Background Display Modes</FONT></TD></TR></TABLE><BR>
<B>Mode Selection</B><BR>
Background modes are selected by BMM, MCM, ECM bits in VIC Control
Registers 1 and 2 (Port D011h, D016h):<BR>
<TABLE><TR><TD><PRE> BMM ECM MCM Mode Name
0 0 0 Standard Character Mode
0 0 1 Multi-Color Character Mode
0 1 0 Extended Color Character Mode
0 1 1 Reserved
1 0 0 Standard Bitmap Mode
1 0 1 Multi-Color Bitmap Mode
1 1 0 Reserved
1 1 1 Reserved
</TD></TR></TABLE><BR>
<B>Video Memory</B><BR>
Memory usage in character modes:<BR>
<TABLE><TR><TD><PRE> 2048 Bytes Character Data (256 tiles)
1000 Bytes Video Matrix Data (40x25 tile numbers)
1000 Nybbles Color RAM (40x25 color attributes)
</TD></TR></TABLE>Memory usage in Bitmap modes:<BR>
<TABLE><TR><TD><PRE> 8000 Bytes Character Data (40x25 tiles) - Addressed by CB13
1000 Bytes Video Matrix Data (40x25 color attributes)
1000 Nybbles Color RAM (40x25 color attributes)
</TD></TR></TABLE><BR>
<B>Standard Character Mode (MCM=0, ECM=0, BMM=0)</B><BR>
Normal Resolution 8x8 pixel character, two colors:<BR>
<TABLE><TR><TD><PRE> 0 BG color 0 (Port D021h) (0-15)
1 Color as selected by Nybble (0-15)
</TD></TR></TABLE><BR>
<B>Multi-Color Character Mode (MCM=1, ECM=0, BMM=0)</B><BR>
Nybble MSB=0 : Normal Resolution 8x8 pixel character, two colors:<BR>
<TABLE><TR><TD><PRE> 0 BG color 0 (Port D021h) (0-15)
1 Color as selected by Nybble LSBs (0-7)
</TD></TR></TABLE>Nybble MSB=1 : Low Resolution 4x8 pixel character, four colors:<BR>
<TABLE><TR><TD><PRE> 0 BG color 0 (Port D021h) (0-15)
1 BG color 1 (Port D022h) (0-15)
2 BG color 2 (Port D023h) (0-15)
3 Color as selected by Nybble LSBs (0-7)
</TD></TR></TABLE>XXX Prio<BR>
<BR>
<B>Extended Color Character Mode (MCM=0, ECM=1, BMM=0)</B><BR>
Normal Resolution 8x8 pixel character, two colors with custom BG color:<BR>
<TABLE><TR><TD><PRE> 0 BG Color 0-3 (Port D021h-D024h) (0-15)
1 Color as selected by Nybble (0-15)
</TD></TR></TABLE>In this mode, only character 0-63 can be used (first 512 Bytes of
Character RAM). The two MSBs of the Map Data are used to select one of
the four BG colors.<BR>
<BR>
<B>Standard Bit Map Mode (MCM=0, BMM=1)</B><BR>
Normal Resolution 320x200 pixels, 40x25 tiles of 8x8 pixels of two colors:<BR>
<TABLE><TR><TD><PRE> 0 LSBs of video matrix entry (0-15)
1 MSBs of video matrix entry (0-15)
</TD></TR></TABLE>In this mode, the Color RAM is not used.<BR>
<BR>
<B>Multi-Color Bit Map Mode (MCM=1, BMM=1)</B><BR>
Low Resolution 160x200 pixels, 40x25 tiles of 4x8 pixels of four colors:<BR>
<TABLE><TR><TD><PRE> 0 BG Color 0 (Port D021h) (0-15)
1 MSBs of video matrix entry (0-15)
2 LSBs of video matrix entry (0-15)
3 Video Matrix Color Nybble (0-15)
</TD></TR></TABLE><BR>
-- Special BG Modes --<BR>
<BR>
<B>Reserved Modes (ECM=1, with BMM=1 and/or MCM=1)</B><BR>
In these modes, the picture appears to be always Black (regardless of any
Background or Border color registers, and regardless of VRAM address 3FFFh).<BR>
<BR>
<B>Display Disable (DEN=0)</B><BR>
The DEN bit is checked in scanline 48, if it is been set in that line, at
least for a few clock cycles, then screen matrix fetches will be enabled,
otherwise matrix data will not be fetched (so the CPU will run without
waitstates), and character data will be fetched from VRAM address 3FFFh.<BR>
Furthermore, the DEN bit is checked in scanline 51 in 25-row mode, and in
scanlines 51 through 55 in 24-row mode, if it has been cleared in one or more
of that scanline(s), then the whole picture will be drawn at border color,
neither BG nor MOBs will be displayed.<BR>
Mid-frame changes to the DEN bit have no effect (until the next checks occur<BR>
in lines 48 and up).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64vicspritedisplay"></A><FONT SIZE=+2>&nbsp;C64 VIC Sprite Display</FONT></TD></TR></TABLE><BR>
Up to eight sprites (aka MOBs, Moveable Object Blocks) can be displayed
on the screen.<BR>
<BR>
<B>Standard MOB (M#MC=0)</B><BR>
Normal Resolution, 24x21 pixels, one color:<BR>
<TABLE><TR><TD><PRE> 0 Transparent (-)
1 Sprite Color (Port D027h-D02Eh) (0-15)
</TD></TR></TABLE><BR>
<B>Multi-Color MOB (M#MC=1)</B><BR>
Low Resolution, 12x21 pixels, three colors:<BR>
<TABLE><TR><TD><PRE> 0 Transparent (-)
1 Sprite Multi Color 0 (Port D025h) (0-15)
2 Sprite Color (Port D027h-D02Eh) (0-15)
3 Sprite Multi Color 1 (Port D026h) (0-15)
</TD></TR></TABLE><BR>
<B>MOB Tiles</B><BR>
Each MOB Tile occupies 63 bytes of memory (first 3 bytes for the upper
row, next 3 bytes for the next row, and so on). Tile data can be defined
at any addresses in the 16K VRAM area in steps of 64 bytes (leaving one
unused byte between each MOB tile). Theoretically allowing to define up
to 256 MOB tiles, practically some of the memory will be required for BG
Character Data and Video Matrix though.<BR>
<BR>
<B>MOB Tile Numbers</B><BR>
The eight bytes at the end of the Video Matrix area are used to specify
the MOB Tile Numbers for each MOB. (Ie. the total size of the Video
Matrix is 1024 Bytes, first 1000 bytes used for BG, followed by 16
unused bytes, followed by 8 MOB Tile Numbers at addresses 3F8h-3FFh in
the matrix).<BR>
The 8bit tile numbers are directly addressing MOB Tiles in the 16K VRAM
area, in steps of 64 bytes.<BR>
The MOB Tile Numbers are read from the video matrix at the end of every
raster line.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64viccharactersets"></A><FONT SIZE=+2>&nbsp;C64 VIC Character Sets</FONT></TD></TR></TABLE><BR>
The C64 character sets (fonts) are relative complicated. The BIOS
handles characters by using some kind of uppercase-only ASCII format.
The actual hardware uses either one of two ROM fonts which are both not
using normal ASCII format. Alternately, user defined fonts can be
defined in RAM. The mapping of the native C64 characters is as such:<BR>
<TABLE><TR><TD><PRE><B> CHR ASCII CHARSET ROM CHARSET 1 ROM CHARSET 2</B>
0Xh \\\\\\\\\\\\\\\\ @ABCDEFGHIJKLMNO @abcdefghijklmno
1Xh \\\\\\\\\\\\\\\\ PQRSTUVWXYZ[\]^\ pqrstuvwxyz[\]^\
2Xh !"#$%&'()*+,-./ !"#$%&'()*+,-./ !"#$%&'()*+,-./
3Xh 0123456789:;&lt;=&gt;? 0123456789:;&lt;=&gt;? 0123456789:;&lt;=&gt;?
4Xh @ABCDEFGHIJKLMNO \\\\\\\\\\\\\\\\ \ABCDEFGHIJKLMNO
5Xh PQRSTUVWXYZ[\]^\ \\\\\\\\\\\\\\\\ PQRSTUVWXYZ\\\\\
6Xh \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\
7Xh \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\
</TD></TR></TABLE>Backslashes (\) indicate special ROM graphic symbols, or non-printable
'ASCII' control codes. For both ROM character sets, 80h-FFh are
color-inverted duplicates of 00h-7Fh.<BR>
<BR>
<B>ASCII Characters</B><BR>
The BIOS is processing strings in cutdown 6bit ASCII format; characters
20h-5Fh are 64 normal ASCII punctation marks, numbers, and upppercase-only
letters (with exceptions 5Ch pounds symbol instead backslash, and 5Fh arrow
left symbol instead underscore).<BR>
<BR>
<B>ROM Character Sets</B><BR>
The C64 includes a 4KBytes character set ROM, theoretically offering
space for 512 different characters (practically it contains only 156
unique, not duplicated, and not inverted characters).<BR>
However, 256 characters can be displayed at once, so the ROM is split
into two sets of 256 characters each. Now the video controller doesn't
support invert attributes, so each of these sets is split into 128
normal characters (00h-7Fh), and 128 identical (but color-inverted)
characters (80h-FFh).<BR>
<BR>
<B>C64 and VIC20 Character Sets</B><BR>
The C64 and VIC20 are using the same sets of characters and symbols. The C64
however is using a bold characters (to compensate the higher screen
resolution). On VIC20, the horizontal-line characters 40h/43h are different,
on C64 these chars contain identical bold-lines. And, on the C64, a pixel got
changed in the two inverted "@" symbols.<BR>
<BR>
<B>ROM Character Set 1</B><BR>
Character set 1 contains 126 different characters (two are duplicated
20h=60h, and 40h=43h) which include the above mentioned 64 ASCII
characters (ASCII 40h-5Fh moved to ROM 00h-1Fh though, software can
easily translate this as "ASCII AND 3Fh"), and 62 graphic symbols.<BR>
<BR>
<B>ROM Character Set 2</B><BR>
This character set includes 29 new characters which cannot be found in
set 1. 01h-1Ah are now lowercase. Uppercase characters moved to 41h-5Ah
(by overwriting some graphic symbols), three 3 graphic symbols at 5Fh,
69h, 7Ah have changed. Additionally, 5Eh has been changed equal to E6h
(ie. inverted 66h).<BR>
<BR>
<B>Japanese Kanji Character Set</B><BR>
Set 1 is same as English Set 1, except that the Pound symbol has been
replaced by a Yen symbol. In Set 2, 00h-3Fh are same as Set 1 (uppercase (!)
chars, numbers, punctation marks, and Yen symbol), 40h-7Fh contain Kanji
characters and some line-drawing symbols. In both sets, 80h-FFh are inverted.<BR>
<BR>
<B>RAM Character Set</B><BR>
When defining characters in RAM, up to 256 different characters can be
defined. (Using 80h-FFh for duplicated inverted characters is a
'feature' of the C64 character ROM, the actual display hardware allows
to use 80h-FFh for whatever purpose.)<BR>
<BR>
<B>C64 Memory Addresses</B><BR>
ROM characters can be read out by the CPU at addresses D000h-DFFFh
(requires to disable I/O area temporily which uses same addresses).
However, the display controller uses different addresses to read out ROM
character data:<BR>
<TABLE><TR><TD><PRE> SET CPU Address VIC Addresses
1 D000h-D7FFh 1000h-17FFh or 9000h-97FFh
2 D800h-DFFFh 1800h-1FFFh or 9800h-9FFFh
</TD></TR></TABLE>RAM characters can be stored at any memory addresses (at increments of
800h), except, obviously not at 1000h-1FFFh or 9000h-9FFFh. Also,
Character data must be in the same 16K bank as Video Matrix data.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64vicrendering"></A><FONT SIZE=+2>&nbsp;C64 VIC Rendering</FONT></TD></TR></TABLE><BR>
<B>Internal Registers used for Vertical Rendering</B><BR>
<TABLE><TR><TD><PRE> YY_POS 3bit internal counter (vertical position in current char row)
PIC_ON 1bit internal flag (picture output enable)
BORDER 1bit
CHAR_ADDR 10bit internal screen matrix address (of current char row)
ROW_BUF 40x12bit internal buffer for 8bit tile numbers & 4bit colors
</TD></TR></TABLE>If DEN was set in line 48 then: At the begin of each of the scanlines
48..247: the lower 3bits of the raster value [D012h] and of control register
1 vertical scroll [D011h] are compared against each other, if they match,
then PIC_ON will be set, YY_POS will be reset to zero, and 40 bytes will be
copied from the screen matrix to ROW_BUF through normal 8bit databus (which
halts the CPU for 40 cycles), simultaneous 40 color values are copied from
color ram to ROW_BUF through separate 4bit color-databus (which doesn't cause
additional waitstates).<BR>
If PIC_ON is set: 40 bytes of Tile data are fetched from [ROW_BUF]*8+YY_POS
(this takes place during Phase ? and doesn't cause waitstates), and tile-row
are displayed (unless BORDER is set), and, at the end of the scanline, YY_POS
is incremented, if it overflows then PIC_ON will be reset, and CHAR_ADDR will
be incremented by 40.<BR>
IF PIC_ON is cleared: Tile data is fetched from memory with all 14 address
lines high (ie. from 3FFFh plus the VIC Base address in CIA #2 Data Port A).
If BORDER is off, then color 0 of that tile data is displayed as background
color as usually, but the character color (color ram) is always BLACK. Screen
output with PIC_ON cleared may happen if a 25-row screen is vertically
scrolled, or if software is repeatedly setting the vertical scroll value to a
value different than the current raster value, or if the vertical border is
opened, or if DEN was not set in line 48.<BR>
During vertical blank, CHAR_ADDR is reset to zero.<BR>
<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64vicdimensionsandtimings"></A><FONT SIZE=+2>&nbsp;C64 VIC Dimensions and Timings</FONT></TD></TR></TABLE><BR>
The visible width and height of the screen border is about 3-4 characters,
at the left, right, top, and bottom of the 40x25 character area, the exact
size may depend on the TV set or monitor used.<BR>
<BR>
<TABLE><TR><TD><PRE> Item NTSC PAL
Oscillator 14.318181 MHz 17.734472 MHz
Divider Osc/14 Osc/18
System Clock 1.022727 MHz 0.985248 MHz
Frame Rate ca. 60Hz ca. 50Hz
Scanlines 263 312
Clks/Line 65 63
</TD></TR></TABLE><BR>
More detailed...?<BR>
<TABLE><TR><TD><PRE> NTSC: 6567R5 6A: 64 cycles/line x 262 lines.
NTSC: 6567R8 and newer: 65 cycles/line x 263 lines.
</TD></TR></TABLE><BR>
<B>CPU Waitstates</B><BR>
Each CPU clock cycle is split into one half cycle for Video DMA (Phase 1),
and one half cycle for CPU access (Phase 2).<BR>
Most of the Video DMA takes place during Phase 1, without waitstates:<BR>
40 bytes BG character data per scanline, 8 bytes MOB tile numbers per
scanline, and (for each enabled MOB in that line only) the middle byte of the
MOB character data. Additionally, DRAM Refresh takes place during Phase 1.<BR>
However, some video DMA takes place during Phase 2, with waitstates:<BR>
40 bytes screen/matrix data in the first scanline of each of the 25 character
rows (these scanlines are often referred to as "bad lines" as they leave less
cycles to the CPU, simultaneously the 40 color nybbles are fetched through a
separate 4bit data bus), and (for each enabled MOB in that line only) the 1st
and 3rd byte of the MOB character data.<BR>
Notes: The wait signal is brought low a few cycles in advance, to notify the
CPU that the bus is about to be used for DMA (the CPU is probably halted
immediately on the notification in must cases? in some cases it may to
execute some cycles, until the actual DMA takes place, and/or even some more
cycles if an opcode-cycle doesn't require to use the bus?) typically a 40
bytes BG matrix access results in 3+40 waitstates, a 2 bytes MOB access
results in 3+2 waitstates. For the MOB accesses, the three extra cycles may
overlap with the cycles from the previous MOB (there are 3+2+2 waitstates if
MOB 0 and 1 are used, and 3+2+3+2 if MOB 0 and 7 are used, respectively, the
CPU runs faster with continuously arranged MOBs). MOB data is fetched even
if the MOB isn't visible (positioned in the border area), for vertically
magnified MOBs, data is fetched in all 42 lines (not only each 2nd line).<BR>
<BR>
eventually the CPU may keep<BR>
<BR>
allowing the CPU to<BR>
phase 2 accesses are<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64soundinterface"></A><FONT SIZE=+2>&nbsp;C64 Sound Interface</FONT></TD></TR></TABLE><BR>
MOS 6581 SOUND INTERFACE DEVICE (SID)<BR>
<BR>
<B>D400/D407/D40E - Voice 1/2/3 Frequency Control - Low-Byte</B><BR>
<B>D401/D408/D40F - Voice 1/2/3 Frequency Control - High-Byte</B><BR>
<BR>
<B>D402/D409/D410 - Voice 1/2/3 Pulse Waveform Width - Low-Byte</B><BR>
<B>D403/D40A/D411 - Voice 1/2/3 Pulse Waveform Width - High-Nybble</B><BR>
Defines a 12bit waveform pulse width (the four MSBs of the high-register
are unused).<BR>
<BR>
<B>D404/D40B/D412 - Voice 1/2/3 Control Register</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Select Random Noise Waveform, 1 = On
6 Select Pulse Waveform, 1 = On
5 Select Sawtooth Waveform, 1 = On
4 Select Triangle Waveform, 1 = On
3 Test Bit: 1 = Disable Oscillator 1/1/1
- That is "1/1/1" for all voicechannels ???
2 Ring Modulate Osc. 1/2/3 with Osc. 3/1/2 Output, 1 = On
1 Synchronize Osc. 1/2/3 with Osc. 3/1/2 Frequency, 1 = On
0 Gate Bit: 1 = Start Att,Dec,Sus, 0 = Start Release
</TD></TR></TABLE><BR>
<B>D405/D40C/D413 - Envelope Generator 1/2/3: Attack / Decay Cycle Control</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
4-7 Select Attack Cycle Duration: 0-15
0-3 Select Decay Cycle Duration: 0-15
</TD></TR></TABLE><BR>
<B>D406/D40D/D414 - Envelope Generator 1/2/3: Sustain / Release Cycle Control</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
4-7 Select Sustain Cycle Duration: 0-15
0-3 Select Release Cycle Duration: 0-15
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> ----- Control Registers -----
</TD></TR></TABLE><BR>
<B>D415 - Filter Cutoff Frequency: Low-Nybble (Bits 2-0)</B><BR>
<B>D416 - Filter Cutoff Frequency: High-Byte</B><BR>
<BR>
<B>D417 - Filter Resonance Control / Voice Input Control</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
4-7 Select Filter Resonance: 0-15
3 Filter External Input: 1 = Yes, 0 = No
2 Filter Voice 3 Output: 1 = Yes, 0 = No
1 Filter Voice 2 Output: 1 = Yes, 0 = No
0 Filter Voice 1 Output: 1 = Yes, 0 = No
</TD></TR></TABLE><BR>
<B>D418 - Select Filter Mode and Volume</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Cut-Off Voice 3 Output: 1 = Off, 0 = On
6 Select Filter High-Pass Mode: 1 = On
5 Select Filter Band-Pass Mode: 1 = On
4 Select Filter Low-Pass Mode: 1 = On
0-3 Select Output Volume: 0-15
</TD></TR></TABLE><BR>
<B>D419 - Paddle Analog/Digital Converter X-Axis (0-255)</B><BR>
<B>D41A - Paddle Analog/Digital Converter Y-Axis (0-255)</B><BR>
Before reading analog input, select paddle 1 or 2 (by writing to CIA#1
Data Port A) and perform a "ldy #$80; lop: nop; dey; bpl lop" delay.<BR>
<BR>
<B>D41B - Oscillator 3 Random Number Generator</B><BR>
<B>D41C - Envelope Generator 3 Output</B><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64complexinterfaceadapters"></A><FONT SIZE=+2>&nbsp;C64 Complex Interface Adapters</FONT></TD></TR></TABLE><BR>
DC00-DC0F MOS 6526 Complex Interface Adapter (CIA) #1<BR>
DD00-DD0F MOS 6526 Complex Interface Adapter (CIA) #2<BR>
<BR>
<A HREF="#c64cia1dataportskeyboardjoystick">C64 CIA #1 Data Ports (Keyboard, Joystick)</A><BR>
<A HREF="#c64cia2dataportsserialvicuserport">C64 CIA #2 Data Ports (Serial, VIC, User Port)</A><BR>
<A HREF="#c64cia12timersinterruptandcontrolregisters">C64 CIA #1/#2 Timers, Interrupt, and Control Registers</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64cia1dataportskeyboardjoystick"></A><FONT SIZE=+2>&nbsp;C64 CIA #1 Data Ports (Keyboard, Joystick)</FONT></TD></TR></TABLE><BR>
<B>DC00 - CIA #1 Data Port A (Keyboard, Joystick, Paddles)</B><BR>
<TABLE><TR><TD><PRE> Bit Dir. Expl.
7-0 Out Select Keyboard Column 7-0 (0=Select, 1=Not select)
7-6 Out Select Analog Paddle (01b=Paddle 1, 10b=Paddle 2) ???
5 - Used for Keyboard only (See above, Bit 7-0)
4 In Joystick 2 Fire (0=Pressed, 1=Released)
3 In Joystick 2 Right, Paddle 2 Y-Button (0=Moved/Pressed, 1=Released)
2 In Joystick 2 Left, Paddle 2 X-Button (0=Moved/Pressed, 1=Released)
1 In Joystick 2 Down (0=Moved, 1=Released)
0 In Joystick 2 Up (0=Moved, 1=Released)
</TD></TR></TABLE>Analog paddle input can be read from Port D419h and D41Ah (SID).<BR>
<A HREF="#keyboardmatrix">Keyboard Matrix</A><BR>
<BR>
<B>DC01 - CIA #1 Data Port B (Keyboard, Joystick, Paddles, Lightpen)</B><BR>
<TABLE><TR><TD><PRE> Bit Dir. Expl.
7-0 In Keyboard Row 7-0 Input (0=Pressed, 1=Released)
7 Out Timer B Toggle/Pulse Output (Output from Timer B)
6 Out Timer A Toggle/Pulse Output (Output from Timer A)
5 In Used for Keyboard only (See above, Bit 7-0)
4 In Joystick 1 Fire (or Lightpen) (0=Pressed, 1=Released)
3 In Joystick 1 Right, Paddle 1 Y-Button (0=Moved/Pressed, 1=Released)
2 In Joystick 1 Left, Paddle 1 X-Button (0=Moved/Pressed, 1=Released)
1 In Joystick 1 Down (0=Moved, 1=Released)
0 In Joystick 1 Up (0=Moved, 1=Released)
</TD></TR></TABLE>Lightpen can be plugged to Game Port 1 only, the signal is wired to VIC
and to CIA Port B, software can process lightpens through VIC Ports
D013h/D014h.<BR>
<BR>
<B>Combined Keyboard and Joystick Use</B><BR>
The joystick ports cannot be disabled - use of joysticks will disturb
keyboard input! Joystick 1 signals always produce garbage keystroke,
Joystick 2 signals produce garbage only if keyboard keys are down
simultaneously. Software that wishes to allow to switch between keyboard
and joystick should use code as such:<BR>
<TABLE><TR><TD><PRE> 1) Read joysticks
2) Read keyboard columns
3) Read joysticks again
</TD></TR></TABLE>That procedure should be invoked once per "frame", any received keyboard
signals in Step 2 should be ignored if joystick signals were received in
Step 1 or 3. Ideally, to eliminate problems caused by switch bounce,
keyboard signals should be also ignored if joystick signals were received
in the previous or next frame (in case of next frame: requiring keyboard
handling to be delayed by one frame).<BR>
<BR>
<B>Joystick 1 and 2</B><BR>
The C64 Programmers Reference Guide and C64 Schematics used some odd
confusing declarations for the two joystick ports:<BR>
<TABLE><TR><TD><PRE> 1st Joystick = Joystick A = JOY B = CIA Port A (DC00h) = Port 2
2nd Joystick = Joystick 1 = JOY A = CIA Port B (DC01h) = Port 1
</TD></TR></TABLE>In result, some programmers have choosen to use DC00h (requires stick
plugged into Port 2), others to use DC01h (plugged into Port 1); making it
necessary to re-connect the joystick to the desired socket about every
time when loading a different game.<BR>
Any programs of better quality should work with both ports, regardless of
the current connection. And of course such programs should also provide
keyboard controls (preferably Q,A,O,P and Space) for users whom don't own
a joystick at all.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64cia2dataportsserialvicuserport"></A><FONT SIZE=+2>&nbsp;C64 CIA #2 Data Ports (Serial, VIC, User Port)</FONT></TD></TR></TABLE><BR>
<B>DD00 - CIA #2 Data Port A (Serial Bus, RS-232, VIC Memory Control)</B><BR>
<TABLE><TR><TD><PRE> Bit Dir. Expl.
7 Serial Bus Data Input
6 Serial Bus Clock Pulse Input
5 Serial Bus Data Output
4 Serial Bus Clock Pulse Output
3 Serial Bus ATN Signal Output
2 User / RS-232 Data Output / CNTR "/Strobe"
1-0 Out VIC Memory Bank XOR 3 (Default=3, see VIC Port D018h)
</TD></TR></TABLE><BR>
<B>DD01 - CIA #2 Data Port B (User Port, RS-232)</B><BR>
<TABLE><TR><TD><PRE> Bit Dir. Expl.
7 Out Timer B Toggle/Pulse Output (Output from Timer B)
6 Out Timer A Toggle/Pulse Output (Output from Timer A)
7 User / RS-232 Data Set Ready
6 User / RS-232 Clear to Send
5 User
4 User / RS-232 Carrier Detect
3 User / RS-232 Ring Indicator
2 User / RS-232 Data Terminal Ready
1 User / RS-232 Request to Send
0 User / RS-232 Received Data
</TD></TR></TABLE><BR>
<B>RS-232 Interface</B><BR>
Aside from its native Serial Bus interface, the C64 BIOS also supports
RS-232 protocol, by using CIA#2 Data Port A Bit 2, CIA#2 Port B Bit 0-4,
6-7, and Interrupt Control Register Bit 4.<BR>
The signals are output/input by user port as TTL signals (0V/5V). A RS-232
adapter/cable would be thus required to convert the signals into +/-12V
signals.<BR>
<BR>
<B>Parallel Centronics Printer Port</B><BR>
Original Commodore Printers are connected to the Serial Bus, most other
printers are using parallel ports (some C64 software such like GEOS may
support parallel printers).<BR>
Recommended connection for User port adapter would be CIA#2 Data Port A
Bit 2 (/Strobe), CIA#2 Port B Bit 0-7 (Data), and Interrupt Control
Register Bit 4 (Busy), and the adapter should drag the Auto-LF signal to
ground.<BR>
<BR>
<B>Serial Bus</B><BR>
A printer and up to four disk drives can be connected to the serial bus.
To access a specific device, the computer must enable the ATN signal, and
then send the device number. The specified device should then communicate
with the computer, and all other devices should ignore any data on the
serial bus - until a new ATN signal is send to select a new device.<BR>
Device numbers can range from 00h to 1Fh. The following codes are used by
the Commodore 64 to stand for the CBM devices listed below:<BR>
<TABLE><TR><TD><PRE> 00 Keyboard
01 Datassette(TM)
02 RS-232C device
03 CRT display
04 Serial bus printer
08 Serial bus disk drive unit 1
09 Serial bus disk drive unit 2
0A Serial bus disk drive unit 3
0B Serial bus disk drive unit 4
</TD></TR></TABLE>The KERNAL redirects device numbers 0-3 to internal hardware (as shown in
the table), normally only device numbers 04h-1Fh are used for serial bus.<BR>
BUG: Device number 1Fh is used to deselect devices by UNTLK/UNLSN, it
should never be used to select a device.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c64cia12timersinterruptandcontrolregisters"></A><FONT SIZE=+2>&nbsp;C64 CIA #1/#2 Timers, Interrupt, and Control Registers</FONT></TD></TR></TABLE><BR>
Below registers are mostly the same for CIA#1 and CIA#2, however,
separate registers for each CIA exist, for example each is having 2
Timers, resulting in a total of 4 Timers.<BR>
<BR>
<B>DC02/DD02 - CIA #1/#2 Data Direction Register - Port A</B><BR>
<B>DC03/DD03 - CIA #1/#2 Data Direction Register - Port B</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7-0 Data Direction for Port A/B Bits 7-0 each (0=Input, 1=Output)
</TD></TR></TABLE>When Timer-Output-to-Port-B is enabled in control register below, Bit 6
and/or 7 of Port B are forcefully set to output state regardless of the
direction specified in this register.<BR>
Note: Even when output direction is selected, the port still
receives external LOW signals, reading from the data register
does then return the external inputs ANDed with the local outputs
(for example, Sorcery reads from DC00h while being configured as
output).<BR>
<BR>
<B>DC04/DD04 - CIA #1/#2 Timer A: Low-Byte</B><BR>
<B>DC05/DD05 - CIA #1/#2 Timer A: High-Byte</B><BR>
<B>DC06/DD06 - CIA #1/#2 Timer B: Low-Byte</B><BR>
<B>DC07/DD07 - CIA #1/#2 Timer B: High-Byte</B><BR>
Reading from this register returns the timers current counter value.
Writing initializes the latched prescaler (reload) value. The 16bit
prescaler is copied into the actual counter registers upon any of the
following situations: 1) on timer underflow, 2) on "force load", 3) when
writing to the timer-high-byte while the timer is stopped.<BR>
<BR>
<B>DC08/DD08 - CIA #1/#2 TOD 1/10 Seconds (00h-09h BCD)</B><BR>
<B>DC09/DD09 - CIA #1/#2 TOD Seconds (00h-59h BCD)</B><BR>
<B>DC0A/DD0A - CIA #1/#2 TOD Minutes (00h-59h BCD)</B><BR>
<B>DC0B/DD0B - CIA #1/#2 TOD Hours (12h,01h-11h BCD) + AM/PM Flag (Bit 7)</B><BR>
<TABLE><TR><TD><PRE> Is that eventually 00-11 or actually 12,01-11 Hours ???
</TD></TR></TABLE>The Time-of-Day Clock (TOD) can be operated by 50Hz or 60Hz input, in
either case the clock input should be properly specified in Control
Register A. The TOD input frequency is gained from the 9V AC power
supply, which is itself gained from the wall socket (eg. US 110V/60Hz,
or German 230V/50Hz), the frequency (and accuracy) are thus depending on
the local energy provider.<BR>
When reading Hours, all TOD registers are latched (ie. frozen, but kept
counting in background), until 1/10 Seconds is read.<BR>
When writing Hours, all TOD registers are completely stopped, until 1/10
Seconds is written.<BR>
When "Set Alarm" mode is selected in Control Register B, writing to TOD
registers sets the Alarm-Time rather than the current Clock-Time. (Reading
still returns the current time, Alarm is write-only).<BR>
<BR>
<B>DC0C/DD0C - CIA #1/#2 Synchronous Serial I/O Data Buffer</B><BR>
8bit shift register for serial input/output.<BR>
<BR>
<B>DC0D/DD0D - CIA #1/#2 CIA Interrupt Control Register (Read Flags/Write Mask)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Any enabled interrupt (0=None, 1=Yes) / Set-Clear Flag (0=Clear, 1=Set)
6-5 Not used (always read out as zero)
4 FLAG External IRQ/NMI Input,
CIA #1 - IRQ - Cassette Read, Serial Bus SRQ Input
CIA #2 - NMI - User, RS-232 Received Data Input, CNTR Busy
3 Serial Port Interrupt
2 Time-of-Day Clock Alarm Interrupt
1 Timer B Interrupt
0 Timer A Interrupt
</TD></TR></TABLE>Reading from this register returns interrupt request flags, reading
automatically clears all IRQ flags (including such that are disabled by
interrupt mask), bit 7 indicates whether any enabled interrupts are
present, ie. bit 7 is set if (IRQ_flags AND IRQ_enable)&lt;&gt;0.<BR>
Writing to this register may either set or reset interrupt mask enable
bits, depending on the Set-Clear flag in bit 7 of the written value, any
written "0" bits are kept unaffected, any written "1" bits are set to
the value of bit 7.<BR>
<BR>
<B>DC0E/DD0E - CIA #1/#2 Control Register A</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Time-of-Day Clock Frequency (0=9VAC/60Hz, 1=9VAC/50Hz)
6 Serial Port I/O Mode Output (0=Input, 1=Output)
5 Timer A Counts (0=System 02 Clock, 1=CNT Signals)
4 Timer A Force Load (0=No, 1=Yes)
3 Timer A Run Mode (0=Continuous, 1=One-Shot)
2 Timer A Output-to-Port-B Mode (0=Pulse, 1=Toggle)
1 Timer A Output-to-Port-B Enable (0=Disable, 1=Enable)
0 Timer A Start/Stop (0=Stop, 1=Start)
</TD></TR></TABLE><BR>
<B>DC0F/DD0F - CIA #1/#2 Control Register B</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Time-of-Day Write Mode (0=Set Clock, 1=Set Alarm)
6-5 Timer B Mode Select:
0 = Count System 02 Clock Pulses
1 = Count Positive CNT Transitions
2 = Count Timer A Underflow Pulses
3 = Count Timer A Underflows While CNT Positive
4-0 Same as for above Timer A, but for Timer B respectively.
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20specs"></A><FONT SIZE=+2>&nbsp;VIC20 Specs</FONT></TD></TR></TABLE><BR>
<B>VIC20</B><BR>
<A HREF="#vic20techdata">VIC20 Tech Data</A><BR>
<A HREF="#vic20memoryandiomap">VIC20 Memory and I/O Map</A><BR>
<A HREF="#vic20videoandaudio">VIC20 Video and Audio</A><BR>
<A HREF="#vic20versatileinterfaceadaptersvia1and2">VIC20 Versatile Interface Adapters (VIA 1 and 2)</A><BR>
<A HREF="#vic20pinoutsforinputoutputdevices">VIC20 Pinouts for Input/Output Devices</A><BR>
<BR>
<B>Other</B><BR>
<A HREF="#cpu65xxmicroprocessor">CPU 65XX Microprocessor</A><BR>
<A HREF="#kernalfunctions">KERNAL Functions</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20techdata"></A><FONT SIZE=+2>&nbsp;VIC20 Tech Data</FONT></TD></TR></TABLE><BR>
<B>"PEEK and POKE commands are very effective especially in animation,</B><BR>
<B>and for sophisticated programming such as bouncing a ball."</B><BR>
This fundamentel piece of information has been obtained from:<BR>
Programmers Reference Guide for VIC 20 Personal Computer, compiled from the
experience of Commodore's international programming staffs in more than half
a dozen countries.<BR>
<BR>
<B>VIC-20 Tech Details</B><BR>
<TABLE><TR><TD><PRE> CPU: 6502A, 1.02 MHz (NTSC), 1.11 MHz (PAL)
ROM: 16K Basic/Kernal ROM, 4K Character ROM (2 sets of 256 characters)
RAM: 5K RAM (expandable to 40K RAM max), 1Kx4bit Color RAM
Video: 22x23 tiles, 176x184 pix (1bit HiRes), or 88x184 pix (2bit MultiColor)
Color: 16 Color Palettte, 2 or 4 Colors (Hires/Multi), 1 unique color/tile
Sound: 3x Square Wave, 1x Noise, 1x Volume (shared for all 4 channels)
Ports: One Joystick port, User Port, Expansion Port, Serial Port, Cassette
Keyboard: Matrix with 8x8 Keys, plus Restore Key
</TD></TR></TABLE><BR>
<B>VIC-1001</B><BR>
Japanese VIC20, NTSC based. Modified Kernal and Character ROMs for Kanji.<BR>
<BR>
<B>VC-20</B><BR>
European VIC20, PAL-based, called VC-20 (in germany at least). Changed Kernal
matched to PAL timings.<BR>
<BR>
<B>VIC20CR</B><BR>
Cost Reduced (CR) revision with minor changes. Eight of the 1Kx4bit SRAMs
have been replaced by two 2Kx8bit SRAMs. The Audio output is merged with a
new external Audio input from Expansion Port. The Video signal is directly
output to both Video pins (without any loop/capacitor on either pin).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20memoryandiomap"></A><FONT SIZE=+2>&nbsp;VIC20 Memory and I/O Map</FONT></TD></TR></TABLE><BR>
<B>VIC20 Memory Map</B><BR>
<TABLE><TR><TD><PRE> Addr. Size Expl.
0000h 1K RAM (BIOS,KERNAL,STACK)
0400h 3K Expansion RAM
1000h 4K RAM (3.5K BASIC/USER, 0.5K Screen RAM)
2000h 24K Expansion RAM (or ROM)
8000h 1K Character ROM Uppercase and all Symbols (Normal)
8400h 1K Character ROM Uppercase and all Symbols (Reversed)
8800h 1K Character ROM Upper/lowercase and some Symbols (Normal)
8C00h 1K Character ROM Upper/lowercase and some Symbols (Reversed)
9000h I/O Area (VIC Chip, VIA1, VIA2)
9400h Color RAM (1024x4bit)
9800h Expansion I/O Area 2
9C00h Expansion I/O Area 3
A000h 8K Expansion ROM (or RAM)
C000h 8K BASIC ROM
E000h 8K KERNAL ROM
</TD></TR></TABLE><BR>
<B>VIC20 RAM Expansions</B><BR>
The VIC has three memory expansion areas, one for 3K RAM, and one for 8K..24K
RAM, and one for 8K ROM (or RAM). The built-in 4K RAM are located in the
middle of the first two areas. The following rules apply to RAM:<BR>
<TABLE><TR><TD><PRE> Basic RAM must be located in a continous memory block.
Screen RAM must be located in built-in 4K RAM.
Color RAM address bit9 must match Screen RAM address bit9.
</TD></TR></TABLE>Respectively, to provide as much Basic RAM as possible, the locations of
Basic, Screen, and Color RAM change depending on installed RAM Expansions:<BR>
<TABLE><TR><TD><PRE> Expansion Total RAM Basic RAM Screen RAM Color RAM Basic Space
None 5K 1000h-1DFFh 1E00h-1FFFh 9600h-97FFh 3.5K
3K 8K 0400h-1DFFh 1E00h-1FFFh 9600h-97FFh 6.5K
8K..35K 13K..40K 1200h-7FFFh 1000h-11FFh 9400h-95FFh 11.5K..27.5K
</TD></TR></TABLE>Notes: The 3K area isn't used by Basic when adding 8K RAM (or more). RAM in
the third expansion area at A000h cannnot be used by Basic.<BR>
<BR>
<B>VIC20 ROM Expansion</B><BR>
Expansion ROM is automatically started if the first 9 bytes at A000h contain
specific data:<BR>
<TABLE><TR><TD><PRE> A000h-A001h Cold Start Vector (invoked after RESET with S=FFh, D=0, I=1)
A002h-A003h Warm Start Vector
A004h-A008h ASCII ID Code "A0CBM" with Bit7 set in the last 3 letters
</TD></TR></TABLE><BR>
<B>VIC20 I/O Map</B><BR>
9000h-900Fh - VIC (Video, Sound, Lightpen, Paddles)<BR>
<TABLE><TR><TD><PRE> 9000h Horizontal Screen Origin, and Interlace
9001h Vertical Screen Origin
9002h Horizontal Screen Size, and Screen Base
9003h Vertical Screen Size, Raster, and Character Size
9004h Raster Value
9005h Video Memory Base Addresses
9006h Lightpen Horizontal
9007h Lightpen Vertical
9008h Paddle X Position
9009h Paddle Y Position
900Ah Voice 1 Square/Bass
900Bh Voice 2 Square/Alto
900Ch Voice 3 Square/Soprano
900Dh Voice 4 Noise
900Eh Sound Volume, and Auxiliary Color
900Fh Screen Color, Border Color, and Reverse Mode
</TD></TR></TABLE>9110h-911Fh - VIA1 (NMI, Cas, Joy, Serial, User Port, Restore Key)<BR>
9120h-912Fh - VIA2 (IRQ, Cas, Joy, Serial, Keyboard, 60Hz Jiffy)<BR>
<TABLE><TR><TD><PRE> 91x0h Input/Output Register B (IRB/ORB)
91x1h Input/Output Register A (IRA/ORA)
91x2h Data Direction Register B (DDRB)
91x3h Data Direction Register A (DDRA)
91x4h T1 Low-order Counter/Latch (T1C_L)
91x5h T1 High-order Counter/Latch (T1C_H)
91x6h T1 Low-order Latch (T1L_L)
91x7h T1 High-order Latch (T1L_H)
91x8h T2 Low-Order Latch/Counter (T2C_L)
91x9h T2 High-Order Counter (T2C_H)
91xAh Shift Register (SR)
91xBh Auxiliary Control Register (ACR)
91xCh Peripheral Control Register (PCR)
91xDh Interrupt Flag Register (IFR) (Request/Acknowledge)
91xEh Interrupt Enable Register (IER) (Enable/Disable)
91xFh Input/Output Register A' (IRA'/ORA')
</TD></TR></TABLE><BR>
<B>VIC20 Mirrors</B><BR>
There are no memory mirrors, except in the I/O-0 area at 9000h-93FFh, the
devices are selected as such: VIA1 by A4=1, VIA2 by A5=1, and [probably ?]
VIC by A8=0. Most of the mirrors are selecting more than one device at once.<BR>
<BR>
<B>VIC20 Empty Memory Regions</B><BR>
The following regions are empty (unless used by expansion hardware):<BR>
RAM/ROM Expansion Areas, I/O Expansion Areas, Upper Nybbles in Color RAM, and
locations in Internal I/O Area with A4=0, A5=0, A8=1.<BR>
The Data bus is shared for CPU and Video DMA (one half clock cycle each), so
when the CPU reads from empty memory regions it will receive the value from
the previous DMA transfer (a byte from Screen RAM or Character ROM/RAM during
picture drawing, or garbage DMA fetches somewhere from 101Ch or 181Ch or else
during blanking periods).<BR>
<BR>
<B>Basic/Kernal RAM in First Kilobyte</B><BR>
<A HREF="#kernalfirstkilobyteram0000h03ffh">KERNAL First Kilobyte RAM (0000h-03FFh)</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20videoandaudio"></A><FONT SIZE=+2>&nbsp;VIC20 Video and Audio</FONT></TD></TR></TABLE><BR>
Video Interface Chip (VIC) 6560 (NTSC) or 6561 (PAL)<BR>
<BR>
The VIC20 supports only one video mode, which behaves similiar as the C64's
"Multi-Color Character Mode" (MCM=1, ECM=0, BMM=0), with smaller resolution,
with some color limitiations, and without moveable objects.<BR>
<BR>
- Fully expandable system with a 16K byte address space<BR>
- Screen grid size up to 192 Horizontal by 200 vertical dots<BR>
- Up to 600 locations on TV<BR>
<BR>
<B>9000h Horizontal Screen Origin, and Interlace (NTSC=05h, PAL=0Ch)</B><BR>
<TABLE><TR><TD><PRE> Bit7 Interlace mode (0=Off/Normal, 1=On) (NTSC Only) (PAL: No Effect)
Bit6-0 Left Border width (in FOUR pixel steps)
</TD></TR></TABLE>Interlace reduces the Frame Rate from 60Hz to 30Hz; intended to blend the VIC
picture with a picture from another source.<BR>
<BR>
<B>9001h Vertical Screen Origin (NTSC=19h, PAL=26h)</B><BR>
<TABLE><TR><TD><PRE> Bit0-7 Upper Border Height (in TWO pixel steps)
</TD></TR></TABLE><BR>
<B>9002h Horizontal Screen Size, and Screen Base (96h) (16h for 8K Expansion)</B><BR>
<TABLE><TR><TD><PRE> Bit7 Screen Base A9 (1 = +0200h) (see Port 9005h), and
Color RAM Base A9 (0=9400h, 1=9600h)
Bit6-0 Number of video columns (Default = 22 columns; 176 pixels)
</TD></TR></TABLE>The maximum column setting is 27 or 31 for NTSC, and 34 or 32 for PAL (?).
Attempts to use bigger values are rejected (the maximum setting is used
instead). The maximum settings might exceed the visible area of the TV Set?<BR>
<BR>
<B>9003h Vertical Screen Size, Raster, and Character Size (2Eh or AEh)</B><BR>
<TABLE><TR><TD><PRE> Bit7 Bit 0 of Raster value (Bits 8-1 are in Port 9004h)
Bit6-1 Number of video rows (Default is 23 rows; 184 pixels)
Bit0 Character size (0=Normal 8x8, 1=Large 8x16)
</TD></TR></TABLE>Note: The 8x16 mode allows to access twice as much Character RAM (4K at
1000h-1FFFh), respecticely Screen RAM occupies only half as much memory, and
can be squeezed between CPU Stack and IRQ/NMI verctors (0.25K at 200h-2FFh).<BR>
<BR>
<B>9004h Raster Value (Current Scanline) (Read only)</B><BR>
<TABLE><TR><TD><PRE> Bit7-0 Bits 8-1 of Raster value (Bit 0 is in Port 9004h)
</TD></TR></TABLE>The counter starts at 000h at the begin of the Upper Border area. The current
scanline within the Picture area can be calculated as such:<BR>
<TABLE><TR><TD><PRE> ([9004h]-[9001h]) * 2 + [9003h].Bit7
</TD></TR></TABLE><BR>
<B>9005h Video Memory Base Addresses (F0h) (C0h for 8K Expansion)</B><BR>
Screen memory for 22x23 tiles of 8x8 pixels occupies a bit less than 200h
bytes (0.5K), or about half as much for 8x16 tiles. Character memory for 256
tiles occupies 800h bytes (2K) (8x8 tiles), or 1000h (4K) bytes (8x16 tiles).
The base is NOT required to be aligned to that numbers.<BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 Screen Base A13 (0=ROM, 1=RAM) (Must be RAM, obviously)
6 Screen Base A12 (1 = +1000h)
5 Screen Base A11 (1 = +0800h)
4 Screen Base A10 (1 = +0400h)
- Screen Base A9 (1 = +0200h) (A9 defined in Port 9002h)
3 Character Base A13 (0=ROM, 1=RAM)
2 Character Base A12 (1 = +1000h)
1 Character Base A11 (1 = +0800h)
0 Character Base A10 (1 = +0400h)
</TD></TR></TABLE>The VIC uses a 16K address space, the VIC VA13 address line equals the to
inverted CPU CA15 address line. Table below shows which regions of the 16K
area can (or cannot) be accessed by the VIC chip:<BR>
<TABLE><TR><TD><PRE> CPU VIC Content
0000h-03FFh (see note) 1K Internal RAM
0400h-0FFFh No 3K Expansion RAM
1000h-1FFFh Characters/Screen 4K Internal RAM
8000h-8FFFh Characters 4K Character ROM
9000h-9FFFh No 4K I/O Area
</TD></TR></TABLE>The VIC can access the RAM at 0-3FFh, however, even when Kernal and Basic are
not used, that region is shared with the CPU Zero Page area (000h-0FFh), CPU
Stack (100h-1FFh), and IRQ/BRK/NMI Vectors (314h-319h).<BR>
Expansion RAM (even if installed) cannot be used because the Expansion Port
outputs only the CPUs CA0-CA13 address signals (not the VA0-VA13 signals).<BR>
<BR>
<B>9006h - Light pen Horizontal (00h)</B><BR>
<B>9007h - Light pen Vertical (00h)</B><BR>
<TABLE><TR><TD><PRE> Bit7-0 Light pen position in pixels (00h=upper/left)
</TD></TR></TABLE>"When the scan passes the area where the pen is, a signal is sent to the VIC
chip. When this signal is received, the VIC chip will record the exact
location of the scan in two registers.<BR>
The light pen trigger is connected to pin 6 of the game port. The light pen
trigger input can also be reached from pin 7 of the user port. Note that you
can't use a joystick and a light pen at the same time, because the same line
that is used as the light pen trigger input is used as the joystick fire
button input (you would get false readings).<BR>
The VIC chip constantly keeps track of the scan position on the television in
two registers. When the light pen trigger input is brought low, the VIC
freezes the two registers. You can then read and use this information. After
reading the two registers, the trigger line will be cleared, so that scan
information can be placed again in the two registers."<BR>
<BR>
<B>9008h Paddle X Position (FFh)</B><BR>
<B>9009h Paddle Y Position (FFh)</B><BR>
<TABLE><TR><TD><PRE> Bit7-0 Paddle Input (0-FFh) (A/D converted variable resistance)
</TD></TR></TABLE>Note: Paddle Buttons can be read from VIA1/PortA Bit4, and VIA2/PortB Bit7.<BR>
<BR>
<B>900Ah Voice 1 Square - 3995Hz/NTSC, 4329Hz/PAL (00h) (Bass)</B><BR>
<B>900Bh Voice 2 Square - 7990Hz/NTSC, 8659Hz/PAL (00h) (Alto)</B><BR>
<B>900Ch Voice 3 Square - 15980Hz/NTSC, 17320Hz/PAL (00h) (Soprano)</B><BR>
<B>900Dh Voice 4 Noise - 31960Hz/NTSC, 34640Hz/PAL (00h)</B><BR>
<TABLE><TR><TD><PRE> Bit 7 Sound Enable (0=Off, 1=On)
Bit 6-0 Sound Frequency (0-127); F = Baseclock / (127-X)
</TD></TR></TABLE>Each Voice uses a different Baseclock (see above PAL/NTSC Voice values).<BR>
Not sure what happens on division by zero?<BR>
<BR>
<B>900Eh - Sound Volume and Auxiliary Color (00h)</B><BR>
<TABLE><TR><TD><PRE> Bit 7-4 Auxiliary color (0-15) (Color 3 for Multi-Color tiles)
Bit 3-0 Volume for all Sound channels (0=Off, 15=Loudest)
</TD></TR></TABLE><BR>
<B>900Fh - Screen Color, Border Color, and Reverse Mode (1Bh)</B><BR>
<TABLE><TR><TD><PRE> Bit 7-4 Background/Screen Color (0-15) (Color 0 of all tiles)
Bit 3 Character Reverse Mode (0=Inverted, 1=Normal)
Bit 2-0 Border Color (0-7) (also Color 1 of Multi-Color tiles)
</TD></TR></TABLE><BR>
<B>9400h-97FFh - Color RAM (1024x4bit) (see Port 9002h for used area)</B><BR>
Allows to select Hi-Res or Multi-color mode for each tile, and to assign one
custom color for each tile. The other tile color(s) are defined in I/O Ports,
shared for all tiles.<BR>
<TABLE><TR><TD><PRE> Bit7-4 Not used (returns garbage when reading)
Bit3 Resolution/Depth (0=Hi-Res 8x8, 2 color, 1=Multi-Color 4x8, 4 color)
Bit2-0 Character Color (0-7) (Indepent color for each tile)
</TD></TR></TABLE>Note: Only 506 entries are used at default resolution of 22x23 characters,
the remaining 518 entries can be used as general purpose 4bit RAM.<BR>
<BR>
<B>Hi-Res and Multi-Color Tile Colors</B><BR>
<TABLE><TR><TD><PRE> Hi-Res Multi-Color Color Source
Color 0 Color 0 Screen color (0-15) (Port 900Fh, Bit4-7)
- Color 1 Border color (0-7) (Port 900Fh, Bit0-2)
Color 1 Color 2 Character color (0-7) (Color RAM)
- Color 3 Auxiliary color (0-15) (Port 900Eh, Bit4-7)
</TD></TR></TABLE>Each byte in Character RAM defines one row of a tile. The color of leftmost
pixel for each row is located in the most-significant bit(s).<BR>
<BR>
<B>VIC20 Color Code Table</B><BR>
Screen Color and Auxiliary Color can be in range 0-15.<BR>
Border Color and Charater Colors (Color RAM) can be only 0-7.<BR>
<TABLE><TR><TD><PRE> 0 Black 8 Orange
1 White 9 Light Orange
2 Red 10 Light Red (Pink)
3 Cyan (Green+Blue) 11 Light Cyan
4 Purple (Red+Blue) 12 Light Purple
5 Green 13 Light Green
6 Blue 14 Light Blue
7 Yellow (Green+Red) 15 Light Yellow
</TD></TR></TABLE>Note: On the C64, some of the Light (pastelized) colors have been replaced.<BR>
<BR>
<A HREF="#c64viccharactersets">C64 VIC Character Sets</A><BR>
<BR>
<B>VIC20 Video Timings</B><BR>
<TABLE><TR><TD><PRE> Type NTSC 60Hz PAL 50Hz
Oscillator 14.318181 MHz 17.734472 MHz
Divider Osc/14 Osc/16
System Clock 1.022727 MHz 1.108405 MHz
Visible ???x??? ???x???
Scanlines 261 312
Clks/Line 65 clks 71 clks
Clks/Char 2 clks 2 clks
</TD></TR></TABLE><BR>
<B>Non-blocking Video DMA</B><BR>
The VIC performs two DMA operations for each character row: One read from
Screen/Color RAM (via 12bit databus). And one read from Character RAM/ROM
(via 8bit databus). The bus-frequency is twice the CPUs clock-frequency,
there's one half cycle available to the CPU and DMA each, that allows video
DMA to take place without halting the CPU.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20versatileinterfaceadaptersvia1and2"></A><FONT SIZE=+2>&nbsp;VIC20 Versatile Interface Adapters (VIA 1 and 2)</FONT></TD></TR></TABLE><BR>
9110h-911Fh - 6522 VIA#1 (NMI, Cas, Joy, Serial, User Port, Restore Key)<BR>
9120h-912Fh - 6522 VIA#2 (IRQ, Cas, Joy, Serial, Keyboard, 60Hz Jiffy)<BR>
<A HREF="#versatileinterfaceadapter6522via">Versatile Interface Adapter 6522 (VIA)</A><BR>
<BR>
<B>VIA #1 Port B - 9110h=Data, 9112h=Direction (User Port)</B><BR>
<TABLE><TR><TD><PRE> Bit Pin(s) Purpose/Example
PB0 USR.C RS232 Received data (Sin) (0=Low)
PB1 USR.D RS232 Request to Send (RTS) (0=Low)
PB2 USR.E RS232 Data terminal ready (DTR) (0=Low)
PB3 USR.F RS232 Ring indicator (RI) (0=Low)
PB4 USR.H RS232 Received line signal (DCD) (0=Low)
PB5 USR.J Not used with RS232 (0=Low)
PB6 USR.K RS232 Clear to send (CTS) (0=Low)
PB7 USR.L RS232 Data set ready (DSR) (0=Low)
</TD></TR></TABLE><BR>
<B>VIA #1 Port A - 9111h/911Fh=Data, 9113h=Dir (User Port, Joy, Cas, Serial)</B><BR>
<TABLE><TR><TD><PRE> Bit Pin(s) Purpose/Example
PA0 SIO.4 Serial CLK IN (0=Low)
PA1 SIO.5 Serial DATA IN (0=Low)
PA2 JOY.1/USR.4 Joy S0 Up ;JOY S0,S1,S2,S4 controlled by VIA #1 Port A
PA3 JOY.2/USR.5 Joy S1 Down ;JOY S3: see VIA #2 Port B
PA4 JOY.3/USR.6 Joy S2 Left/Paddle Switch X (0=Low)
PA5 JOY.6/USR.7 Joy S4 Fire/Lightpen (0=Low)
PA6 CAS.6/USR.8 Cassette switch sense (0=Low)
PA7 SIO.3/USR.9 Serial ATN out (1=Low) (Inverted)
</TD></TR></TABLE><BR>
<B>VIA #1 Timers, Shift, Auxiliary, Peripheral, Interrupts (Port 9114h-911Eh)</B><BR>
<TABLE><TR><TD><PRE> Item Pin(s) Purpose/Example
T1 Timer 1
T2 Timer 2
SHFT Shift register
CA1 KEYB Restore key (0=Low=Pressed)
CA2 CAS.3 Cassette motor control (?=On)
CB1 USR.B Interrupt signal for received RS-232 data
CB2 USR.M Transmitted RS-232 data
/INT CPU.6/EXP.W CPU Non Maskable Interrupt (and Expansion Port) (NMI)
</TD></TR></TABLE><BR>
<B>VIA #2 Port B - 9120h=Data, 9122h=Direction (Keyboard, Cas, Joy)</B><BR>
<TABLE><TR><TD><PRE> Bit Pin(s) Purpose/Example
PB0-7 COL.0-7 Keyboard Column scan (0=Low)
PB3 COL.3/CAS.5 Cassette write line (0=Low)
PB7 COL.7/JOY.4 Joy S3 Right/Paddle Switch Y (0=Low)
</TD></TR></TABLE>In Keyboard Matrix, VIC20 COLUMNS equal to C64 ROWS with Bit3,7 exchanged.<BR>
<A HREF="#keyboardmatrix">Keyboard Matrix</A><BR>
<BR>
<B>VIA #2 Port A - 9121h/912Fh=Data, 9123h=Direction (Keyboard)</B><BR>
<TABLE><TR><TD><PRE> Bit Pin(s) Purpose/Example
PA0-7 ROW.0-7 Keyboard Row scan (0=Low)
</TD></TR></TABLE>In Keyboard Matrix, VIC20 ROWS equal to C64 COLUMNS with Bit0,7 exchanged.<BR>
<BR>
<B>VIA #2 Timers, Shift, Auxiliary, Peripheral, Interrupts (Port 9214h-921Eh)</B><BR>
<TABLE><TR><TD><PRE> Item Pin(s) Purpose/Example
T1 Timer 1 (used for 60Hz Jiffy clock interrupt)
T2 Timer 2
SHFT Shift register
CA1 CAS.4 Cassette read line (0=Low)
CA2 SIO.4 Serial CLK OUT (1=Low) (Inverted)
CB1 SIO.1 Serial SRQ IN (0=Low)
CB2 SIO.5 Serial DATA OUT (1=Low) (Inverted)
/INT CPU.4/EXP.19 CPU Interrupt Request (and Expansion Port) (IRQ)
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="vic20pinoutsforinputoutputdevices"></A><FONT SIZE=+2>&nbsp;VIC20 Pinouts for Input/Output Devices</FONT></TD></TR></TABLE><BR>
<B>VIC20 Joystick Port - Game I/O - 9pin DSUB</B><BR>
From left-to-right: Pin 1-5 in upper row, Pin 6-9 in lower row.<BR>
<TABLE><TR><TD><PRE> Pin Control Name Purpose
1 VIA1.PA2 JOY0 Up
2 VIA1.PA3 JOY1 Down
3 VIA1.PA4 JOY2 Left/Paddle Switch X
4 VIA2.PB7 JOY3 Right/Paddle Switch Y
5 VIC.POTY POTY Paddle Position Y
6 VIA1.PA5 JOY4 Fire/Lightpen
7 - 5V +5V (max 100mA)
8 - GND Ground
9 VIC.POTX POTX Paddle Position X
</TD></TR></TABLE><BR>
<B>VIC20 Audio/Video - 5pin DIN</B><BR>
Anti-clockwise, from upper-left to upper-right: Pin 3,5,2,4,1.<BR>
<TABLE><TR><TD><PRE> 1 +5V REG (max 10mA)
2 GND
3 AUDIO
4 VIDEO LOW (VIC20: via 3.9uH & capacitor, VIC20CR: shortcut with Pin 5)
5 VIDEO HIGH (direct output without loop/capacitor, otherwise same as Pin 4)
</TD></TR></TABLE><BR>
<B>VIC20 Serial I/O - 6pin DIN</B><BR>
Anti-clockwise, from upper-left to upper-right: Pin 5,4,3,2,1. Middle: Pin 6.<BR>
<TABLE><TR><TD><PRE> 1 SERIAL SRQ IN
2 GND
3 SERIAL ATN OUT
4 SERIAL CLC IN/OUT
5 SERIAL DATA IN/OUT
6 /RESET (or N.C.)
</TD></TR></TABLE><BR>
<B>VIC20 Cassette/Datasette Port - 12pin Edge (only 6 pins actually used)</B><BR>
From left-to-right: Pin 1-6 in upper row, short-cut with Pin A-F in lower row.<BR>
<TABLE><TR><TD><PRE> A-1 GND
B-2 +5V
C-3 CASSETTE MOTOR (VIA1.CA2) (+9V)
D-4 CASSETTE READ (VIA2.CA1)
E-5 CASSETTE WRITE (VIA2.PB3)
F-6 CASSETTE SWITCH (VIA1.PA6)
</TD></TR></TABLE><BR>
<B>VIC20 User I/O Port - 24pin Edge</B><BR>
From left-to-right: Pin 1-12 in upper row, Pin A-F,H,J-N in lower row.<BR>
<TABLE><TR><TD><PRE> 1 GND Ground A GND Ground
2 5V +5VDC max 100mA B CB1 RS232 Interrupt for Sin
3 /RES /RESET C PB0 RS232 Received data (Sin)
4 PA2 JOY0 Up D PB1 RS232 Request to Send (RTS)
5 PA3 JOY1 Down E PB2 RS232 Data terminal ready (DTR)
6 PA4 JOY2 Left/Paddle Switch X F PB3 RS232 Ring indicator (RI)
7 PA5 JOY4 Fire/Lightpen H PB4 RS232 Received line signal (DCD)
8 PA6 Cassette switch sense J PB5 Not used with RS232
9 PA7 SERIAL ATN OUT K PB6 RS232 Clear to send (CTS)
10 9V 9VAC Phase 1 max 100mA L PB7 RS232 Data set ready (DSR)
11 9V 9VAC Phase 2 max 100mA M CB2 RS232 Transmitted data (Sout)
12 GND Ground N GND Ground
</TD></TR></TABLE><BR>
<B>VIC20 Expansion Port - 48 pin (24/24) female edge connector</B><BR>
From left-to-right: Pin 1-22 in upper row, Pin A-F,H,J-N,P,R-Z in lower row.<BR>
<TABLE><TR><TD><PRE> Pin Name Description
2-9 CD0-7 Data bus Bits 0-7
B-S CA0-13 Address bus Bits 0-13 (upper bits decoded in /IO,/RAM,/BLK)
10-12 /BLK1-3 8K decoded RAM/ROM blocks 1,2,3 at 2000h,4000h,6000h
13 /BLK5 8K decoded ROM block 5 at A000h
14-16 /RAM1-3 1K decoded RAM blocks 1,2,3 at 0400h,0800h,0C00h
T-U /IO2-3 I/O blocks 2,3 (located at 9800h,9C00h) (eg. IEEE adapter)
17 VR/W Read/Write line from VIC chip (high-read, low-write)
18 CR/W Read/Write line from CPU chip (high-read, low-write)
V PHI2 Phase 2 system clock
19 /IRQ 6502 Interrupt Request ("keyboard scan and system clock")
W /NMI 6502 Non Maskable Interrupt (WARMSTART, RUN/STOP-RESTORE)
X /RESET 6502 RESET pin
21 +5V Supply
1,22,A,Z GND System ground
20 (NC) Not connected
Y SNDIN Not connected (VIC20), or Audio In (VIC20CR)
</TD></TR></TABLE>"Memory expansion will normally use the VR/W signal. Other devices may need
the CR/W signal." -- Is that correct... or vice-versa ?<BR>
<BR>
<B>Power Supply Input</B><BR>
VIC20: 2pin; 9VAC<BR>
VIC20CR: 7pin; 9VAC and +5VDC (same as in C64)<BR>
Internally, all mainboards are running at raw 5VDC, the other voltages are
used only to increase the room temperature, and for external hardware:
Cassette Motor (9VDC), and User Port (9VAC).<BR>
<BR>
<B>VIC20 Pin Configuration 6560 - 40pin</B><BR>
<TABLE><TR><TD><PRE> 1 N.C.
2 COMP COLOR
3 SYNC & LUMINANCE
4 R/W
5-16 DB11-0
17,18 POTX,POTY
19 SOUND OUT
20 GND
21-34 A0-13 (Note: A13 is gained from /BLK4 signal)
35,36 P01,P02 Clock Out, NTSC: X/14 = 1.02MHz, PAL: X/16 = 1.11MHz
37 LPEN
38,39 X02,X01 Clock In, NTSC: 14318181Hz, PAL:17734472Hz
40 VCC 5VDC
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4specs"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Specs</FONT></TD></TR></TABLE><BR>
<A HREF="#c16plus4techdata">C16/PLUS4 Tech Data</A><BR>
<A HREF="#c16plus4memoryandiomap">C16/PLUS4 Memory and I/O Map</A><BR>
<A HREF="#c16plus4keyboardjoystickcassetteserialsounduserport">C16/PLUS4 Keyboard, Joystick, Cassette, Serial, Sound, User Port</A><BR>
<A HREF="#c16plus4interruptsrasterandtimers">C16/PLUS4 Interrupts (Raster and Timers)</A><BR>
<A HREF="#c16plus4memorycontrolcpuandvideo">C16/PLUS4 Memory Control (CPU and Video)</A><BR>
<A HREF="#c16plus4videocontrol">C16/PLUS4 Video - Control</A><BR>
<A HREF="#c16plus4videocursorandcolor">C16/PLUS4 Video - Cursor and Color</A><BR>
<A HREF="#c16plus4videorendering">C16/PLUS4 Video - Rendering</A><BR>
<A HREF="#c16plus4videomodes">C16/PLUS4 Video Modes</A><BR>
<A HREF="#c16plus4dimensionsandtimings">C16/PLUS4 Dimensions and Timings</A><BR>
<A HREF="#c16plus4pinouts">C16/PLUS4 Pin-Outs</A><BR>
<BR>
<B>Other</B><BR>
<A HREF="#diskdrive">Disk Drive</A><BR>
<A HREF="#cpu65xxmicroprocessor">CPU 65XX Microprocessor</A><BR>
<A HREF="#kernalfunctions">KERNAL Functions</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4techdata"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Tech Data</FONT></TD></TR></TABLE><BR>
<B>C16</B><BR>
<TABLE><TR><TD><PRE> CPU 7501/8501 - 6502 compatible with on-chip 7bit I/O Port
16K DRAM (3FFEh bytes can be used) (shared as WRAM and VRAM)
32K ROM (BASIC V3.5, separate KERNALs for PAL-B and NTSC-M)
TED (Text Editing Device) for Video, Sound, Timers, Keyboard
Four cursor keys (unfortunately arranged all in one row)
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> Character graphics, high resolution graphics, Enhanced Colour Mode and
reverse characters
Multicolour graphics (4x8 character or graphics cells)
Writable horizontal and vertical sync counters
Horizontal raster position register
Same chip for both NTSC-M and PAL-B
1.NTSC: 14318181/16 Hz
NTSC = 0.894886 MHz (single), or 1.789773 MHz (twice)
2.PAL: 17734472/20 Hz
PAL = 0.886724 MHz (single), or 1.773447 MHz (twice)
Double clock mode for faster operation
</TD></TR></TABLE><BR>
<BR>
<B>C116</B><BR>
Same as C16, slightly re-arranged mainboard. Equipped with a cheaper
short-way flat keyboard, without shift-lock key, however it's having the four
cursor keys re-arranged in compass directions.<BR>
<BR>
<B>Plus/4</B><BR>
Expanded C16, with 64K DRAM (about 61K can be used), additional 32K on-board
Function ROM (3-plus-1 word processor), User Port with RS232 interface and
8bit parallel port, changed connection for Cassette Sense. Lacks 5VDC outputs
on Serial and Audio/Video Ports. Different Power supply input (9VAC and
5VDC).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4memoryandiomap"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Memory and I/O Map</FONT></TD></TR></TABLE><BR>
<B>C16 and Plus/4 Memory Map</B><BR>
<TABLE><TR><TD><PRE> 0000h-0001h I/O CPU 7501/8501 On-chip I/O Port
0002h-7FFFh RAM
8000h-BFFFh RAM or LO ROM (Basic, Function LO, Cart 1 LO, Cart 2 LO)
C000h-FBFFh RAM or HI ROM (Kernal, Function HI, Cart 1 HI, Cart 2 HI)
FC00h-FCFFh RAM or HI ROM (Kernal)
FD00h-FF3Fh I/O Area
FF40h-FFFFh RAM or HI ROM (Kernal, Function HI, Cart 1 HI, Cart 2 HI)
</TD></TR></TABLE>The C16 and C116 contain only 16K built-in RAM which is mirrored across the
whole 64K address space (the mirrors cannot be disabled, so expansion RAM
cannot be installed), the full 16K can be accessed at 0002h-4001h (that
includes mirrors of the two hidden bytes at 0000h-0001h).<BR>
Further RAM at 4000h-FFFFh built-in in Plus/4 only.<BR>
<BR>
<B>Character Set in Kernal ROM</B><BR>
<TABLE><TR><TD><PRE> D000h-D7FFh 256 non-inverted tiles
</TD></TR></TABLE><BR>
<B>Kernal FC00h-FCFFh (Banking Routines)</B><BR>
<TABLE><TR><TD><PRE> FCF1h-FCF3h Jump to interrupt routine for cartridge
FCF4h-FCF6h Jump to cartridge reenable routine
FCF7h-FCF9h Jump to long fetch routine
FCFAh-FCFCh Jump to long jump routine
FCFDh-FCFFh Jump to long interrupt routine
</TD></TR></TABLE>Memory at FC00h-FCFFh is always Kernal ROM (or RAM), Function ROM or
Cartridge ROM is disabled in this region.<BR>
<BR>
<B>I/O Map</B><BR>
7501/8501 CPU On-chip I/O Registers<BR>
<TABLE><TR><TD><PRE> 0000h - CPU 7501/8501 On-Chip I/O Port Direction
0001h - CPU 7501/8501 On-Chip I/O Port Data (Cassette, Serial, User Port)
</TD></TR></TABLE>7700 Decoded I/O Addresses<BR>
<TABLE><TR><TD><PRE> FD00h-FD0Fh - User Port RS232 Controller 6551A (Plus/4 Only - Not C16/C116)
FD10h-FD1Fh - Cassette Sense / User Port 8bit Parallel I/O
FD30h-FD3Fh - 6529B Keyboard Column Output Latch
FDD0h-FDDFh - ROM Bank Latch
</TD></TR></TABLE>7360/8360 TED I/O Registers<BR>
<TABLE><TR><TD><PRE> FF00h - Timer 1 Counter/Reload LSB
FF01h - Timer 1 Counter/Reload MSB
FF02h - Timer 2 Counter LSB
FF03h - Timer 2 Counter MSB
FF04h - Timer 3 Counter LSB
FF05h - Timer 3 Counter MSB
FF06h - Video Control Register 1
FF07h - Video Control Register 2
FF08h - Keyboard / Joystick Latch
FF09h - Interrupt request register
FF0Ah - Interrupt mask register
FF0Bh - Raster interrupt register
FF0Ch - Hardware-cursor position MSB (2bit) (Bit7-2 unused)
FF0Dh - Hardware-cursor position LSB (8bit)
FF0Eh - Sound 1 Frequency LSB (8bit)
FF0Fh - Sound 2 Frequency LSB (8bit)
FF10h - Sound 1 (or 2 ?) Frequency MSB (2bit) (Bit7-2 unused)
FF11h - Sound control register
FF12h - Bitmap/Character Memory Control and Sound 2 Frequency MSB
FF13h - System Clock and Character Memory Control
FF14h - Screen/Color Memory Control
FF15h - Background Color 0
FF16h - Background Color 1
FF17h - Background Color 2
FF18h - Background Color 3
FF19h - Border Color
FF1Ah - Current Character Position MSB (2bit) (Bit7-2 unused)
FF1Bh - Current Character Position LSB (8bit)
FF1Ch - Current Scanline MSB (1bit) (Bit7-1 unused)
FF1Dh - Current Scanline LSB (8bit)
FF1Eh - Actual position of horizontal scanning. R/W!.
FF1Fh - Flashing Counter and Character Scanline Index
</TD></TR></TABLE>7360/8360 TED Strobe Outputs<BR>
<TABLE><TR><TD><PRE> FF3Eh - CPU/Screen/Color ROM Enable
FF3Fh - CPU/Screen/Color RAM Enable
</TD></TR></TABLE><BR>
<B>FD20h-FD2Fh, FD40h-FDCFh, FDE0h-FEFFh, FF20h-FF3Dh</B><BR>
Unused portions of the I/O Area. Known fragments are: FD20h-FD2Fh accessed by
the kernal power-up routines, but nothing inside the PLUS/4 or C16 is at this
address. FDE0h-FEFFh for Disk DMA. FF20h-FF3Dh contains RAM/HI-ROM.<BR>
<BR>
<B>Expansion ROM Header</B><BR>
<TABLE><TR><TD><PRE> 8000h-8002h Entrypoint (started by JSR 8000h)
8003h-8005h Another Entrypoint, not used by BIOS (?)
8006h Desired Entry Time (00h=Never, 01h=Immediately, 02h..FFh=Later)
8007h-8009h ASCII ID "CBM"
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4keyboardjoystickcassetteserialsounduserport"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Keyboard, Joystick, Cassette, Serial, Sound, User Port</FONT></TD></TR></TABLE><BR>
<B>FD30h-FD3Fh - 6529B Keyboard Column Output Latch</B><BR>
The lower 4 address bits are don't care, normally FD30h is used.<BR>
<TABLE><TR><TD><PRE> 7-0 Keyboard Column 7-0 Selection (0=Select, 1=Deselect)
</TD></TR></TABLE>The 6529B chips appears to be bi-directional, so reading from this port does
(probably?) usually receive the state of the outputs, however, if two keys
are pressed in the same row, then one column output may appear on two column
inputs.<BR>
<BR>
<B>FF08h - Keyboard/Joystick Strobe (W) and Row Input Latch (R)</B><BR>
Write: Output unlatched Joystick column & strobe keyboard/joystick row latch.<BR>
<TABLE><TR><TD><PRE> 7-3 Not used
2 Joystick 1 (0=Select, 1=Deselect)
1 Joystick 2 (0=Select, 1=Deselect)
0 Not used
</TD></TR></TABLE>Read: Latched keyboard/joystick row input (latched at time of above write)<BR>
<TABLE><TR><TD><PRE> 7-0 State of Row 7-0 for any selected columns (0=Pressed, 1=Released)
7 Joystick 2 Fire (0=Pressed, 1=Released)
6 Joystick 1 Fire (0=Pressed, 1=Released)
3 Joystick 1/2 Right (0=Moved, 1=Released)
2 Joystick 1/2 Left (0=Moved, 1=Released)
1 Joystick 1/2 Down (0=Moved, 1=Released)
0 Joystick 1/2 Up (0=Moved, 1=Released)
</TD></TR></TABLE>Flowchart: Output latched keyboard column to FD30h, then output unlatched
joystick column to FF08h, then read latched row input from FF08h.<BR>
The Keyboard Matrix is almost same as on C64, a couple of keys have been
reassigned, mainly because the C16 has four (instead two) cursor keys.<BR>
<A HREF="#keyboardmatrix">Keyboard Matrix</A><BR>
<BR>
<B>0000h - CPU 7501/8501 On-Chip I/O Port Direction</B><BR>
Selects Data Direction for Register 0001h. Should be always ??h.<BR>
<BR>
<B>0001h - CPU 7501/8501 On-Chip I/O Port Data (Cassette, Serial, User Port)</B><BR>
<TABLE><TR><TD><PRE> Bit Dir Expl.
7 In Serial Data In (and PLUS/4: Cas Sense) (0=Low, 1=High)
6 In Serial Clock In (0=Low, 1=High)
5 - Not used (no pin-out on 7501/8501) (N/A)
4 In Cassette Read (0=Low, 1=High)
3 Out Cassette Motor (0=9VDC, 1=Off) (Inverted)
2 Out Serial ATN Out (and PLUS/4: User Port) (0=High, 1=Low) (Inverted)
1 Out Serial Clock Out, Cassette Write (0=High, 1=Low) (Inverted)
0 Out Serial Data Out (0=High, 1=Low) (Inverted)
</TD></TR></TABLE>Switch Serial Clock/Data Outputs HIGH before reading Clock/Data Inputs.<BR>
<BR>
<B>FD10h-FD1Fh - Cassette Sense / User Port 8bit Parallel I/O</B><BR>
<TABLE><TR><TD><PRE> 7-0 User Port 6529B, 8bit Parallel I/O (PLUS/4 Only)
2 Cassette Sense In (C16 and C116 Only)
</TD></TR></TABLE>Note: On the PLUS/4, the Cassette Sense signal has moved to Port 0001h/Bit7,
exchanging the J8,J9 jumpers switches the Plus/4 to C16 compatible mode.<BR>
<BR>
<B>FD00h-FD0Fh - User Port RS232 Controller 6551A (Plus/4 Only - Not C16/C116)</B><BR>
The Plus/4 contains a built-in ACIA 6551A RS232 Controller (unlike C64 and
VIC20 which require external controller). To use RS232, one still requires a
User Port to DSUB adapter; with TTL to RS232 voltage conversion. The downside
is that the FD00h-FD0Fh cannot control the associated User Port pins directly
as general purpose parallel I/O pins.<BR>
<BR>
<B>FF0Eh - Sound 1 Frequency LSB (8bit)</B><BR>
<B>FF0Fh - Sound 2 Frequency LSB (8bit)</B><BR>
<B>FF10h - Sound 1 (or 2 ?) Frequency MSB (2bit) (Bit7-2 unused)</B><BR>
<B>FF12h - Sound 2 (or 1 ?) Frequency MSB (2bit) (Bit7-2 see Memory Control)</B><BR>
The soundregister-value can be calculated as<BR>
<TABLE><TR><TD><PRE> reg=1024-(111860.781/frq[Hz]) (NTSC)
reg=1024-(111840.45 /frq[Hz]) (PAL)
</TD></TR></TABLE><BR>
<B>FF11h - Sound control register</B><BR>
<TABLE><TR><TD><PRE> Bit7 D/A mode. See below for more.
Bit6 Sound #2 noise on/off. If You set both, the square will sound.
Bit5 Sound #2 squarewave on/off.
Bit4 Sound #1 squarewave on/off.
Bit0-3 Volume. Maximum value is 8. //OR:// 0=Off, F=Highest
</TD></TR></TABLE>To play samples, the TED can switch the sound generators to constant level<BR>
outputs. D/A is then done by changing the volume register setting. Each<BR>
generator can generate frequencies from 100Hz to 23kHz.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4interruptsrasterandtimers"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Interrupts (Raster and Timers)</FONT></TD></TR></TABLE><BR>
/IRQ Sources: Raster, and 3 Timers<BR>
/NMI Sources: None (the 7501/8501 CPU doesn't have a /NMI input)<BR>
/RES Sources: Power up, and Reset Button<BR>
<BR>
<B>FF09h - Interrupt request register</B><BR>
<TABLE><TR><TD><PRE> Bit7 Set on Any-Enabled-IRQ Condition (0=None, 1=IRQ)
Bit6 Timer 3 Interrupt Request (0=None, 1=IRQ / Acknowledge)
Bit5 Unused
Bit4 Timer 2 Interrupt Request (0=None, 1=IRQ / Acknowledge)
Bit3 Timer 1 Interrupt Request (0=None, 1=IRQ / Acknowledge)
Bit2 Lightpen Interrupt Request (Not implemented?)
Bit1 Raster Interrupt Request (0=None, 1=IRQ / Acknowledge)
Bit0 Unused
</TD></TR></TABLE>Reading returns the (latched) interrupt flags. Writing "1" into Bit(s) 6,4-1
acknowledges (clears) the respective interrupt flag(s).<BR>
<BR>
<B>FF0Ah - Interrupt mask register</B><BR>
<TABLE><TR><TD><PRE> Bit7 Unused
Bit6 Timer 3 Interrupt (0=Disable, 1=Enable)
Bit5 Unused
Bit4 Timer 2 Interrupt (0=Disable, 1=Enable)
Bit3 Timer 1 Interrupt (0=Disable, 1=Enable)
Bit2 Lightpen Interrupt (Not implemented?)
Bit1 Raster Interrupt (0=Disable, 1=Enable)
Bit0 High bit of Raster FF0Bh (see there)
</TD></TR></TABLE><BR>
<B>FF0Bh - Raster interrupt register</B><BR>
Lower 8bit of the Raster Interrupt value (the upper bit is in Port FF0Ah), a
Raster interrupt is requested when this value matches the current scanline
number.<BR>
On the C16, picture rendering starts at line 000h, however, in 25-row mode,
the first 3 scanlines are masked (in 24-row mode, first 7 lines are masked).<BR>
There are also several registers to read (and modify) the current scanline
number, as well as other horizontal/vertical position registers, see
Rendering chapter.<BR>
<BR>
<B>FF00h - Timer 1 Counter/Reload LSB</B><BR>
<B>FF01h - Timer 1 Counter/Reload MSB</B><BR>
<B>FF02h - Timer 2 Counter LSB</B><BR>
<B>FF03h - Timer 2 Counter MSB</B><BR>
<B>FF04h - Timer 3 Counter LSB</B><BR>
<B>FF05h - Timer 3 Counter MSB</B><BR>
All counters are decremented at single clock speed (NTSC=0.894886MHz,
PAL=0.886724MHz). Interrupts are requested on underflow, and Timer 1 is
restarted at the written (reload) value, Timer 2 and 3 are restarted at
FFFFh.<BR>
No idea if the timers are temporarily stopped/frozen when writing/reading to
LSB registers, and re-activated on MSB register access?<BR>
<BR>
<B>Reset on Power up / Reset Button</B><BR>
Resets the CPU (program counter), the ROM Bank Latch (to Basic/Kernal), the
Plus/4's RS232 controller, and whatever external hardware which is connected
to the /Reset signal.<BR>
The RAM isn't cleared on reset. And the TED doesn't seem to have a Reset
input - so either RAM or ROM may be enabled - even on power-up!?! Maybe the
TED triggers reads from the Reset vector to enable ROM...?<BR>
The key-combination RESET+STOP enters the built-in machine language monitor,
very nice idea, but taking into account that RESET destroys the current
program counter setting, this is by far the worst debugging solution that I
could think off.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4memorycontrolcpuandvideo"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Memory Control (CPU and Video)</FONT></TD></TR></TABLE><BR>
<B>FF12h - Bitmap/Character Memory Control and Sound 2 Frequency MSB</B><BR>
<TABLE><TR><TD><PRE> Bit7-6 Unused
Bit5-3 Bitmap Base Address (in 8K steps) (ROM/RAM see FF12h.Bit2)
Bit2 Character/Bitmap ROM/RAM (0=RAM, 1=ROM) (Address see FF13h.Bit7-2)
Bit1-0 Sound 2 Frequency MSB (see Sound chapter)
</TD></TR></TABLE><BR>
<B>FF13h - System Clock and Character Memory Control</B><BR>
<TABLE><TR><TD><PRE> Bit7-2 Character Base Address (in 1K steps) (ROM/RAM see FF12h.Bit2)
Bit1 Force single clock mode
Bit0-??-Memory State READ ONLY (0=RAM, 1=ROM) (change via FF3Eh/FF3Fh)
Bit0-??-Status of Clock
</TD></TR></TABLE><BR>
<B>FF14h - Screen/Color Memory Control</B><BR>
<TABLE><TR><TD><PRE> Bit7-3 Video-ram Base Address (in 2K steps) (ROM/RAM see FF3Eh/FF3Fh)
Bit2-0 Unused
</TD></TR></TABLE>Used for both Color and Screen memory: 1K Color memory, followed by 1K Screen
(Matrix) memory.<BR>
<BR>
<B>FF3Eh - CPU/Screen/Color ROM Enable</B><BR>
<B>FF3Fh - CPU/Screen/Color RAM Enable</B><BR>
Not sure if this actually affects Screen/Color, probably that is always RAM ?<BR>
Write any value to these addresses to select ROM/RAM at 8000h-FFFFh.<BR>
All ROM is write-through, the CPU can write to underlaying RAM, even if ROM
is enabled.<BR>
See FF13h.0, and FF14h, and FDD0h-FDDFh.<BR>
<TABLE><TR><TD><PRE> Port Write Read RAM Read ROM
FF3E ROM SELECT ? HI ROM
FF3F RAM SELECT ? HI ROM
</TD></TR></TABLE><BR>
<B>FDD0h-FDDFh - ROM Bank Latch</B><BR>
The written data value (D0-D7) is ignored, instead the lower 4 address bits
are decoded. As such, this port is write only.<BR>
<TABLE><TR><TD><PRE> A3-A2 HI-ROM C000h-FFFFh Select (0=Kernal, 1=FuncHI, 2=Cart1Hi, 3=Cart2Hi)
A1-A0 LO-ROM 8000h-BFFFh Select (0=Basic, 1=FuncLO, 2=Cart1LO, 3=Cart2LO)
</TD></TR></TABLE>On-board Function ROM included on Plus/4 only (not C16 and C116).<BR>
Memory at FC00h-FCFFh is always Kernal ROM (or RAM).<BR>
The region at FD00h-FD3Fh is used for I/O.<BR>
For ROM/RAM selection see FF12h.Bit2 (Character/Bitmap), and FF3Eh/FF3Fh
(CPU/Screen/Color).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4videocontrol"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Video - Control</FONT></TD></TR></TABLE><BR>
<B>FF06h - Video Control Register 1</B><BR>
<TABLE><TR><TD><PRE> Bit7 TEST Internal TED Test (Should be always 0)
Bit6 ECM Enhanced color mode (0=Normal, 1=Extended)
Bit5 BMM Bitmap mode (0=Text, 1=Bitmap)
Bit4 DEN Display Enable (0=Blank/Border Color, 1=Display Enable)
Bit3 RSEL 24/25 rows screen (0=24 Rows, 1=25 Rows)
Bit2-0 Y2-0 Vertical smooth-scrolling
</TD></TR></TABLE><BR>
<B>FF07h - Video Control Register 2</B><BR>
<TABLE><TR><TD><PRE> Bit7 Reverse Mode (0=Reverse/128 Chars, 1=No Reverse/256 Chars)
If 0, higmost char-bit tells if char should appear in inverse.
Bit6 NTSC Select Video Format (0=PAL, 1=NTSC) (Don't change!)
Bit5 RES TED stop. If set, the TED stops it's counters and
screen-generating, only single clock and refresh
cycles remain. PROJECT 64: Flashing (0=Yes, 1=No)
Bit4 MCM Multicolor mode (0=Normal, 1=Multicolor)
Bit3 CSEL 40/38 columns screen (0=38 Columns, 1=40 Columns)
Bit2-0 X2-0 Horizontal smooth-scrolling
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4videocursorandcolor"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Video - Cursor and Color</FONT></TD></TR></TABLE><BR>
<B>FF0Ch - Hardware-cursor position MSB (2bit) (Bit7-2 unused)</B><BR>
<B>FF0Dh - Hardware-cursor position LSB (8bit)</B><BR>
Beyond 1000 the cursor is not seeable.<BR>
The shape/size/height and appearance (maybe different color, blinking, and/or
inversion) of the cursor are unknown?<BR>
<BR>
<B>FF15h - Background Color 0</B><BR>
<B>FF16h - Background Color 1</B><BR>
<B>FF17h - Background Color 2</B><BR>
<B>FF18h - Background Color 3</B><BR>
<B>FF19h - Border Color</B><BR>
<TABLE><TR><TD><PRE> Bit7 Not used
Bit6-4 Luminance (Not used for Color Black)
Bit3-0 Color
</TD></TR></TABLE><BR>
The Color codes are unknown? Probably different as on C64, as luminance has
moved to separate bitfield.<BR>
The luminance setting is ignored for Color Black.<BR>
There are 121 different color/luminance combinations.<BR>
<BR>
Base colours<BR>
<TABLE><TR><TD><PRE> 0 ------ Black 8 RRG--- Orange
1 R-G-B- White 9 R-g--- Brown
2 RR---- Red 10 R-GG-- Yellow-Green
3 --GGBB Cyan 11 RR--B- Pink
4 RR--BB Purple 12 --G-BB Blue-Green
5 --GG-- Green 13 R---BB Light Blue
6 ----BB Blue 14 --g-B- Dark Blue
7 RRGG-- Yellow 15 GG--B- Light Green
</TD></TR></TABLE>Color names taken from the Plus/4 users manual. The RGB values are raw
guesswork - assuming 30 degree steps on a 360 degrees color wheel, Color 9
assumed to be low-intensity color 8, and color 12 and 14 to be opposites of 8
and 9 - no idea if real C16s work like that?<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4videorendering"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Video - Rendering</FONT></TD></TR></TABLE><BR>
Below registers are used internally during rendering. Programs normally do
need to use or initialize that registers. However, reading or modifying them
may be useful for synchronization and effects.<BR>
<BR>
<B>FF1Ah - Current Character Position MSB (2bit) (Bit7-2 unused)</B><BR>
<B>FF1Bh - Current Character Position LSB (8bit)</B><BR>
Actual character-position. TED counts the characters that it had fetched and
put out to the screen. The number is increasing by 40 after every
characterline (8 rasterlines).<BR>
<BR>
<B>FF1Ch - Current Scanline MSB (1bit) (Bit7-1 unused)</B><BR>
<B>FF1Dh - Current Scanline LSB (8bit)</B><BR>
Actual position of vertical scanning. Read/Writeable!<BR>
There's also a Raster Interrupt register, see Interrupt chapter.<BR>
On the C16, picture rendering starts at line 000h, however, in 25-row mode,
the first 3 scanlines are masked (in 24-row mode, first 7 lines are masked).<BR>
<BR>
<B>FF1Eh - Actual position of horizontal scanning. R/W!.</B><BR>
Lowmost bit is unused. It contains the TED's internal counter's highmost 8
bits. So, it increases 4 with every character. When writing, it seems to put
the value to a functionally different register (writing back a reading value
in right time affects the screen).<BR>
<BR>
<B>FF1Fh - Flashing Counter and Character Scanline Index</B><BR>
<TABLE><TR><TD><PRE> Bit7 Unused
Bit6-3 Flashing counter. It's value increases with every
frame, and TED fits it's flashing feature to this
register's reaching to 15.
Bit2-0 Actual vertical scanning-line in a character-row (R/W!)
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4videomodes"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Video Modes</FONT></TD></TR></TABLE><BR>
Video Information<BR>
Abilities mostly parallel those of the uniquitous VIC-II video IC in the C64.<BR>
TED does not contain sprite support. The TED can display 121 different
colors. Other features include a hardware cursor, hardware text blinking, and
hardware inverse character support.<BR>
<BR>
<B>Character/Text modes 40x25 characters (BMM=0):</B><BR>
<TABLE><TR><TD><PRE> 1K color memory (1st 400h bytes of Color/Screen memory)
bit7 Flashing (Hires Text Mode only)
bit6-4 Luminance (Not used for Color Black)
bit3 Multicolor (Multicolor Text Mode only)
bit3-0 Color (Only Bit2-0 in Multicolor Text Mode)
1K screen memory (2nd 400h bytes of Color/Screen memory)
bit7 Inversion (Hires Text Mode, with FF07h/Bit7=0 only)
bit7-6 Extended BG Color (Extended Text Mode only)
bit7-0 Tile number 0-255 (max 127 or 63 for Inversion / Extended BG)
2K character memory (800h bytes) (for 256 tiles)
</TD></TR></TABLE>High-Resolution Characters, fixed BG color<BR>
<TABLE><TR><TD><PRE> 0 Background color 0 (Port FF15h)
1 Color Memory (with Flashing Bit in Bit7)
</TD></TR></TABLE>Extended Color Characters, 64 Tiles, selectable 4 BG Colors (ECM=1)<BR>
<TABLE><TR><TD><PRE> 0 Background color 0-3 (Port FF15h-FF18h) select by upper 2bit of tileno
1 Color Memory (Bit7 probably unused?)
</TD></TR></TABLE>Multicolor Characters (MCM=1) with 0-1 colors (Hires) or 0-3 (Multicolor):<BR>
<TABLE><TR><TD><PRE> 0 0 Background color 0 (Port FF15h)
- 1 Background color 1 (Port FF16h)
- 2 Background color 2 (Port FF17h)
1 3 Color Memory (Bit3 selects Hires (0) or Color (1) tile-mode)
(Multicolor mode uses only 6 bits for color/luminance)
(Bit7 in Color Memory probably unused?)
</TD></TR></TABLE><BR>
<B>Bitmap modes (BMM=1):</B><BR>
<TABLE><TR><TD><PRE> 1K intensity memory (1st 400h bytes of Color/Screen memory)
bit7 Not used
bit6-4 Luminance MSB (Not used for Color Black)
bit3 Not used
bit2-0 Luminance LSB (Not used for Color Black)
1K color memory (2nd 400h bytes of Color/Screen memory)
bit7-4 Color MSB
bit3-0 Color LSB
8K bitmap (2000h bytes) (consisting of 40x25 tiles)
</TD></TR></TABLE>In 320x200 Hires bitmap mode (MCM=0), colors are:<BR>
<TABLE><TR><TD><PRE> 0 Color LSB with Luminance MSB
1 Color MSB with Luminance LSB
</TD></TR></TABLE>In 160x200 Multicolor bitmap mode (MCM=1), colors are:<BR>
<TABLE><TR><TD><PRE> 0 Background color 0 (Port FF15h)
1 Color LSB with Luminance MSB
2 Color MSB with Luminance LSB
3 Background color 1 (Port FF16h)
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4dimensionsandtimings"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Dimensions and Timings</FONT></TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> Item NTSC PAL
Oscillator 14.318181 MHz 17.734472 MHz
Divider Osc/16 Osc/20
Single Clock 0.894886 MHz 0.886724 MHz
Twice Clock 1.789773 MHz 1.773447 MHz
Frame Rate 60Hz 50Hz
Scanlines 262 312
Clks/Line 57 single clks 57 single clks
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> Dot clock = 8 times processor clock
Two blocked DMA fetches per character line
Writable horizontal and vertical sync counters
Horizontal raster position register
</TD></TR></TABLE><BR>
<B>CPU Clock</B><BR>
The TED also generates the clock signal for the 7501/8501 microprocessor. The
clock is not constant, as it switches from from 885 kHz and twice that speed,
1.773 Mhz. The speed depends on TED's current task. It generates the slower
clock signal when refreshing DRAM or fetching data for the video screen.
Otherwise, the high clock signal is generated.<BR>
The user can disable fast clock generation via a register. The end result is
a machine that operates at approximately 1 MHz, as the CPU runs in slow mode
while the screen is displayed, and operates in fast mode when the TED starts
drawing the top and bottom borders.<BR>
<BR>
<B>PAL/NTSC</B><BR>
The TED chip can be configured to PAL or NTSC signals in Video Control
Register 2, there is no way to detect a PAL or NTSC mainboard, so the
initialization is handled by separate PAL and NTSC BIOS versions.<BR>
Attempts to change the setting will result in faulty color output, changed
oscillator divider (resulting in overclocked/underclocked hardware), and
changed number of scanlines (this will NOT toggle between 50Hz/60Hz mode, due
to the different oscillator).<BR>
<BR>
<B>Raster</B><BR>
For the serious video programmer, raster interrupts are implemented as on the
VIC-II. However, the 0 line of the register corresponds to the first line of
the character screen area, not the top of the border. In addition, the
current raster line can be read from TED registers. You can modify the
counter as well. Doing so will most likely affect the screen display. As a
bonus, the horizontal location of the raster can be read and modified in the
same way.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="c16plus4pinouts"></A><FONT SIZE=+2>&nbsp;C16/PLUS4 Pin-Outs</FONT></TD></TR></TABLE><BR>
<B>C16/PLUS4 Serial - Female 6pin DIN</B><BR>
<TABLE><TR><TD><PRE> 1 C16/C116: 5VDC via 330 Ohm - PLUS/4: N.C.
2 GND
3 ATN OUT
4 CLK IN/OUT
5 DATA IN/OUT
6 /RESET OUT
</TD></TR></TABLE>Note: In other CBM computers, Pin 1 is used as SRQ IN, the C16/PLUS4 doesn't
have this.<BR>
<BR>
<B>C16/PLUS4 Joystick Ports - 2 x Female 8pin Mini DIN</B><BR>
Not sure if one of the inputs can be used to connect a Lightpen?<BR>
<TABLE><TR><TD><PRE> 1 JOY0 Up (TED K0 Input)
2 JOY1 Down (TED K1 Input)
3 JOY2 Left (TED K2 Input)
4 JOY3 Right (TED K3 Input)
5 5VDC
6 BINA Fire (TED K6 or K7 Input)
7 GND
8 SELECT (Amplified CPU databus D1 or D2 signal)
</TD></TR></TABLE>Whereas, Commodores typical confusing assignments for two joysticks are:<BR>
<TABLE><TR><TD><PRE> SELECT C16 C116 PLUS/4 BINA BASIC
D1=LOW JOY2 JOY1/JOYB JOY1 K7 JOY(2)
D2=LOW JOY1 JOY0/JOYA JOY0 K6 JOY(1)
</TD></TR></TABLE>For normal 9pin DSUB joysticks, connect directions and buttons accordingly,
and connect the Mini DIN's SELECT signal to DSUB's GND pin. Leave all other
pins unconnected.<BR>
<BR>
<B>Cassette - Female 7pin Mini-DIN</B><BR>
<TABLE><TR><TD><PRE> 1 GND
2 5VDC
3 MOTOR (9VDC)
4 CAS RD
5 CAS WRT
6 SENSE
7 GND
</TD></TR></TABLE><BR>
<B>Audio/Video - Female 8pin DIN</B><BR>
<TABLE><TR><TD><PRE> 1 LUM
2 GND
3 AUDIO OUT
4 COMP
5 EXT AUDIO IN
6 COLOR
7 N.C.
8 C16/C116: 5VDC - PLUS4: N.C.
</TD></TR></TABLE><BR>
<B>Expansion Port - 50pin Female Edge</B><BR>
<TABLE><TR><TD><PRE> Y-F A0-A15
21-14 D0-D7
4,5,C /IRQ, R/W, /RESET
B,6,7,8 C1 LOW, C1 HIGH, C2 LOW, C2 HIGH
9,10 /CS1, /CS0
11,12,13 /CAS, MUX, BA
D,E,24,22 /RAS, Phi0, Phi2, AEC
2,3 5VDC
I,A,CC,25 GND
AA,BB N.C.
Z N.C. (RAMEN ?)
23 EXT AUDIO IN
</TD></TR></TABLE><BR>
<B>User Port - PLUS/4 Only - Not C16/C116 - 24pin Male Edge</B><BR>
<TABLE><TR><TD><PRE> M,E,D,B8?,H,L,C 6551A TxD,DTR,RTS,RxC,DCD,DSR,RxD
1,12,A,N GND
2 5VDC
10,11 9VAC1, 9VAC2
9 SIO ATN
3 /RESET (OUT)
F,J,7,6,5,4,K,B8? 6529B P7-P0
</TD></TR></TABLE><BR>
<B>Power Supply Input</B><BR>
C16/C116: +9VDC<BR>
PLUS/4: Female 4pin "Square-DIN-Style" with 9VAC and +5.2VDC<BR>
Internally, all mainboards are running at raw 5VDC, the other voltages are
used only to increase the room temperature, and for external hardware:
Cassette Motor (9VDC), and User Port (9VAC).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="keyboardmatrix"></A><FONT SIZE=+2>&nbsp;Keyboard Matrix</FONT></TD></TR></TABLE><BR>
Note: On C64 and VIC20, Row and Column are bi-directional, conventionally
Column=Output and Row=Input are used, but some programs are using the
opposite directions. The C16 and Plus/4 are always using Col=Out, Row=In.<BR>
<BR>
<B>C64 Keyboard Matrix</B><BR>
The keyboard is arranged in form of a 8x8 matrix, a column must be
selected by writing to CIA#1 Data Port A, the Row 0-7 data can be read
from CIA#1 Data Port B as Bit 0-7:<BR>
<TABLE><TR><TD><PRE> Bit Col0 Col1 Col2 Col3 Col4 Col5 Col6 Col7
Row0 DEL "3" "5" "7" "9" "+" PND "1"
Row1 RET "W" "R" "Y" "I" "P" "*" &lt;--
Row2 RIGHT "A" "D" "G" "J" "L" ";" CTRL
Row3 F7 "4" "6" "8" "0" "-" HOME "2"
Row4 F1 "Z" "C" "B" "M" "." RSHIFT SPC
Row5 F3 "S" "F" "H" "K" ":" "=" &lt;C=&gt;
Row6 F5 "E" "T" "U" "O" "@" "^" "Q"
Row7 DOWN LSHIFT "X" "V" "N" "," "/" STOP
</TD></TR></TABLE>For I/O details see Complex Interface Adapter CIA#1 chapter. The default
keyboard translation table is located at address EB81h in KERNAL ROM.<BR>
<BR>
<B>C16 and Plus/4 Keyboard Matrix</B><BR>
Almost same as on C64, only 10 keys are reassigned, mainly cursor related:<BR>
<TABLE><TR><TD><PRE> C64 "-" "+" POUND HOME DOWN RIGHT RSHIFT &lt;-- "^" "@"
C16 UP DOWN LEFT RIGHT "@" POUND ESC? HOME "+" "-"
</TD></TR></TABLE>Also, function keys F1,F3,F5,F7 have been renamed to F1,F2,F3,HELP(F8).<BR>
And, the C16 doesn't have a RESTORE key, instead it's having a RESET button.<BR>
<BR>
<B>VIC20 Keyboard Matrix</B><BR>
VIC20 COLUMNS equal to C64 ROWS with Bit3,7 exchanged.<BR>
VIC20 ROWS equal to C64 COLUMNS with Bit0,7 exchanged.<BR>
<BR>
<B>C64 Keyboard Layout</B><BR>
<TABLE><TR><TD><PRE> &lt;-- 1! 2" 3# 4$ 5% 6& 7' 8( 9) 0 + - PND HOME DEL F1
CTRL Q W E R T Y U I O P @ * ^ RESTORE F3
STP SHL A S D F G H J K L :[ ;] = [RETURN] F5
C= SHIFT Z X C V B N M ,&lt; .&gt; /? SHIFT U/D L/R F7
[ _ _ _ _ _ SPACE _ _ _ _ _]
</TD></TR></TABLE><BR>
<B>C128 Keyboard Layout</B><BR>
<TABLE><TR><TD><PRE> ESC TAB ALT CAPS HLP LF 40 SCR UP DOWN LFT RGT F1 F3 F5 F7
&lt;-- 1! 2" 3# 4$ 5% 6& 7' 8( 9) 0 + - PND HOME DEL 7 8 9 +
CTRL Q W E R T Y U I O P @ * ^ RESTORE 4 5 6 -
STP SHL A S D F G H J K L :[ ;] = [RETURN] 1 2 3 EN-
C= SHIFT Z X C V B N M ,&lt; .&gt; /? SHIFT U/D L/R [-0-] . TER
[ _ _ _ _ _ SPACE _ _ _ _ _]
</TD></TR></TABLE><BR>
<B>C16 (66 type-writer keys; 3xSHIFT; cursor keys L/R/U/D in upper row)</B><BR>
<TABLE><TR><TD><PRE> ESC 1 2 3 4 5 6 7 8 9 0 L R U D DEL F1
CTRL Q W E R T Y U I O P @ + - HOME F2
RN SL A S D F G H J K L ; : * RETRN F3
C= SHF Z X C V B N M , . / SHF $ = HELP
[------SPACE------]
</TD></TR></TABLE><BR>
<B>C116 (65 flat-short-way keys; 2xSHIFT)</B><BR>
<TABLE><TR><TD><PRE> F1 F2 F3 HELP HOME? DEL?
ESC 1 2 3 4 5 6 7 8 9 0 + - *
CTRL Q W E R T Y U I O P @ RET
RUN $ A S D F G H J K L [ ] = _|_
C= SHF Z X C V B N M , . / SHF |
[------SPACE------]
</TD></TR></TABLE><BR>
<B>Plus/4 (67 type-writer keys, 3xSHIFT, 2xCTRL)</B><BR>
<TABLE><TR><TD><PRE> F1 F2 F3 HELP &lt;-- reset button (side)
ESC 1 2 3 4 5 6 7 8 9 0 + - = HOME DEL
CTRL Q W E R T Y U I O P @ PND * CTRL
RN SL A S D F G H J K L [ ] RETURN
C= SHF Z X C V B N M , . / SHF _|_
[-----SPACE-----] |
</TD></TR></TABLE><BR>
<B>The SHIFT LOCK Key (SHL)</B><BR>
The C64 has three SHIFT keys (two normal SHIFT keys, and one SHIFT LOCK
key). Left Shift and Shift Lock share the same entry in the keyboard
matrix. The shift lock key is having a mechanical locking/unlocking function
(similar like a ball-pen, it remains down when pressed once, and remains up
when pressed another time).<BR>
<BR>
<B>The RESTORE Key</B><BR>
The Restore key is not part of the keyboard matrix, instead it is connected
to the CPUs NMI signal, producing a non-maskable interrupt when pressed. On
C64 it goes directly to the NMI line (and cannot be disabled), on VIC20 it is
connected to VIA1 (allowing to enable/disable the NMI). Software should
include a dummy NMI handler to prevent crashes when touching this key. For
details see Interrupt chapter.<BR>
<BR>
<B>Description of other special C64 keys...</B><BR>
<TABLE><TR><TD><PRE> Key Full name Normal use Shifted use
HOME CLR/HOME Move cursor to 0,0 Move to 0,0 and clear screen
DEL INST/DEL Backspace Insert one SPACE not moving cursor
STP RUN/STOP Stop/Break Start Cassette Loading (LOAD+RUN)
C= COMMODORE Keycombinations... Toggle Character Set 1 and 2
U/D CRSR Cursor Down Cursor Up
L/R CRSR Cursor Right Cursor Left
F1/F2 FUNCTION F1 F2
F3/F4 FUNCTION F3 F4
F5/F6 FUNCTION F5 F6
F7/F8 FUNCTION F7 F8
</TD></TR></TABLE>The "&lt;--" key displays the 'arrow left' symbol. The "PND" key
displays the 'pound' symbol, chr(5Ch), which is the backslash on
computers with real ASCII character set.<BR>
The RESTORE+STOP key combination produces a warmboot ???<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalfunctions"></A><FONT SIZE=+2>&nbsp;KERNAL Functions</FONT></TD></TR></TABLE><BR>
<B>KERNAL Functions (C64: FF81h-FFF5h, VIC20: FF8Ah-FFF5h)</B><BR>
<A HREF="#kernalloadsavefunctions">KERNAL Load/Save Functions</A><BR>
<A HREF="#kernalgeneralfileinputoutput">KERNAL General File Input/Output</A><BR>
<A HREF="#kernalserialbuslowlevelfunctions">KERNAL Serial Bus Low Level Functions</A><BR>
<A HREF="#kernalsystemcontrol">KERNAL System Control</A><BR>
<A HREF="#kernalerrorhandling">KERNAL Error Handling</A><BR>
<BR>
<B>KERNAL Memory (0000h-03FFh)</B><BR>
<A HREF="#kernalfirstkilobyteram0000h03ffh">KERNAL First Kilobyte RAM (0000h-03FFh)</A><BR>
<BR>
<B>KERNAL POWER-UP ACTIVITIES</B><BR>
<TABLE><TR><TD><PRE> The KERNAL then checks for the presence of an autostart ROM cartridge
at location C64:8000h, VIC20:A000h. If this is present, normal
initialization is suspended, and control is transferred to the car-
tridge code.
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalloadsavefunctions"></A><FONT SIZE=+2>&nbsp;KERNAL Load/Save Functions</FONT></TD></TR></TABLE><BR>
<B>FFBA - SETLFS - Set up a logical file</B><BR>
In: A=file_number, X=device_number (0-1Fh), Y=secondary address/channel<BR>
Out: N/A<BR>
<TABLE><TR><TD><PRE> The following codes are used by the Commodore 64 to stand for the
CBM devices listed below:
ADDRESS DEVICE
0 Keyboard
1 Datassette(TM)
2 RS-232C device
3 CRT display
4 Serial bus printer
8 CBM serial bus disk drive
Device numbers 4 or greater automatically refer to devices on the
serial bus.
A command to the device is sent as a secondary address on the serial
bus after the device number is sent during the serial attention
handshaking sequence. If no secondary address is to be sent, the Y index
register should be set to 255.
</TD></TR></TABLE><BR>
<B>FFBD - SETNAM - Set file name</B><BR>
Used to prepare address & length of filename for OPEN, LOAD, SAVE functions.<BR>
In: A=Length (0=None), Y:X=Address (if length nonzero) - Out: N/A<BR>
<BR>
<B>FFD5 - LOAD - Load RAM from device</B><BR>
Use SETLFS and SETNAM to prepare additional parameters before LOAD.<BR>
The Secondary Address parameter (SA) is misused to select the target
address in memory, either the address in Y:X registers, or the original
file address stored in file header.<BR>
In: A (0=Load, 1=Verify), SA (0=Load to Y:X, 1=Load to Header Address)<BR>
Out: A=???, Y:X=End Address of file<BR>
Error returns: 0,4,5,8,9, READST<BR>
<BR>
<B>FFD8 - SAVE - Save memory to a device</B><BR>
Use SETLFS and SETNAM to prepare additional parameters before SAVE.<BR>
In: WORD[A]=Start Address, Y:X=End Address<BR>
Note: The A-register must point to a 16bit value in page zero.<BR>
Error returns: 5,8,9, READST<BR>
<TABLE><TR><TD><PRE> Registers affected: A, X, Y
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalgeneralfileinputoutput"></A><FONT SIZE=+2>&nbsp;KERNAL General File Input/Output</FONT></TD></TR></TABLE><BR>
<B>FFC0 - OPEN - Open a logical file</B><BR>
Use SETLFS and SETNAM to prepare the parameters before using OPEN.<BR>
In: N/A - Out: A,X,Y=Destroyed<BR>
Error returns: 1,2,4,5,6,240, READST<BR>
<BR>
<B>FFC6 - CHKIN - Select handle for CHRIN/GETIN</B><BR>
Use OPEN to initialize the file_handle before use.<BR>
This function automatically invokes TALK and TKSA.<BR>
In: X=file_handle - Out: A,X=Destroyed<BR>
<BR>
<B>FFC9 - CHKOUT - Select handle for CHROUT</B><BR>
Use OPEN to initialize the file_handle before use.<BR>
This function automatically invokes LISTEN and SECOND.<BR>
In: X=file_handle - Out: A,X=Destroyed<BR>
<BR>
<B>FFE4 - GETIN - Get a character</B><BR>
In: N/A - Out: A=Data, X,Y=Destroyed<BR>
<TABLE><TR><TD><PRE> Preparatory routines: CHKIN, OPEN
Error returns: See READST
Description: If the channel is the keyboard, this subroutine removes
one character from the keyboard queue and returns it as an ASCII value in
the accumulator. If the queue is empty, the value returned in the
accumulator will be zero. Characters are put into the queue automatically
by an interrupt driven keyboard scan routine which calls the SCNKEY
routine. The keyboard buffer can hold up to ten characters. After the
buffer is filled, additional characters are ignored until at least one
character has been removed from the queue.
If the channel is RS-232, then
only the A register is used and a single character is returned. See
READST to check validity. If the channel is serial, cassette, or screen,
call BASIN routine.
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> How to Use:
1) Call this routine using a JSR instruction.
2) Check for a zero in the accumulator (empty buffer).
3) Process the data.
EXAMPLE:
;WAIT FOR A CHARACTER
WAIT JSR GETIN
CMP #0
BEQ WAIT
</TD></TR></TABLE><BR>
<B>FFCF - CHRIN - Get a character from the input channel</B><BR>
Use OPEN and CHKIN to initialize and select the channel.<BR>
XXX behaves special when reading from keyboard ???<BR>
In: N/A - Out: A=Data, X=Destroyed<BR>
Error returns: 0 (See READST)<BR>
<BR>
<B>FFD2 - CHROUT - Output a character</B><BR>
Use OPEN and CHKOUT to initialize and select the channel.<BR>
In: A=Data - Out: A=Destroyed<BR>
Error returns: 0 (See READST)<BR>
<BR>
<TABLE><TR><TD><PRE> +-----------------------------------------------------------------------+
| NOTE: Care must be taken when using this routine to send data to a |
| specific serial device since data will be sent to all open output |
| channels on the bus. Unless this is desired, all open output channels |
| on the serial bus other than the intended destination channel must be |
| closed by a call to the KERNAL CLRCHN routine. |
+-----------------------------------------------------------------------+
</TD></TR></TABLE><BR>
<B>FFCC - CLRCHN - Clear I/O channels</B><BR>
In: N/A - Out: A,X=Destroyed<BR>
<TABLE><TR><TD><PRE> Description: This routine is called to clear all open channels and re-
store the I/O channels to their original default values. It is usually
called after opening other I/O channels (like a tape or disk drive) and
using them for input/output operations. The default input device is 0
(keyboard). The default output device is 3 (the Commodore 64 screen).
If one of the channels to be closed is to the serial port, an UNTALK
signal is sent first to clear the input channel or an UNLISTEN is sent to
clear the output channel. By not calling this routine (and leaving lis-
tener(s) active on the serial bus) several devices can receive the same
data from the Commodore 64 at the same time. One way to take advantage
of this would be to command the printer to TALK and the disk to LISTEN.
This would allow direct printing of a disk file.
This routine is automatically called when the KERNAL CLALL routine is
executed.
</TD></TR></TABLE><BR>
<B>FFC3 - CLOSE - Close a logical file</B><BR>
In: A=file handle - Out: A,X,Y=Destroyed<BR>
Error returns: 0,240 (See READST)<BR>
<TABLE><TR><TD><PRE> Description: This routine is used to close a logical file after all I/O
operations have been completed on that file. This routine is called after
the accumulator is loaded with the logical file number to be closed (the
same number used when the file was opened using the OPEN routine).
</TD></TR></TABLE><BR>
<B>FFE7 - CLALL - Close all files</B><BR>
In: N/A - Out: A,X=Destroyed<BR>
<TABLE><TR><TD><PRE> Description: This routine closes all open files. When this routine is
called, the pointers into the open file table are reset, closing all
files. Also, the CLRCHN routine is automatically called to reset the I/O
channels.
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalserialbuslowlevelfunctions"></A><FONT SIZE=+2>&nbsp;KERNAL Serial Bus Low Level Functions</FONT></TD></TR></TABLE><BR>
Receive Functions: TALK, TKSA, ACPTR, UNTLK<BR>
Send Functions: LISTEN, SECOND, CIOUT, UNLSN<BR>
<BR>
<B>FFA5 - ACPTR - Get data from the serial bus</B><BR>
Prepare by TALK and TKSA before use.<BR>
In: N/A - Out: A=Received Data, X=Destroyed.<BR>
Error returns: See READST<BR>
<BR>
<B>FFA8 - CIOUT - Transmit a byte over the serial bus</B><BR>
Prepare by LISTEN and SECOND and TKSA before use.<BR>
In: A=Data - Out: N/A<BR>
Error returns: See READST<BR>
<BR>
<TABLE><TR><TD><PRE> This routine always buffers one character. (The routine holds the previous
character to be sent back.) So when a call to the UNLSN routine is made to
end the data transmission, the buffered character is sent with an End Or
Identify (EOI) set. Then the UNLSN command is sent to the device.
</TD></TR></TABLE><BR>
<B>FFB1 - LISTEN - Command a device on the serial bus to receive data</B><BR>
<TABLE><TR><TD><PRE> In: A=Device Number (0-1Fh)
Error returns: See READST
Registers affected: A
</TD></TR></TABLE>LISTEN will OR the number bit by bit to convert to a listen address, then
transmits this data as a command on the serial bus.<BR>
The specified device will then go into listen mode, and be ready to accept
information.<BR>
<BR>
<B>FF93 - SECOND - Send secondary address for LISTEN</B><BR>
<TABLE><TR><TD><PRE> Communication registers: A
Preparatory routines: LISTEN
Error returns: See READST
Registers affected: A
Description: This routine is used to send a secondary address to an
I/O device after a call to the LISTEN routine is made, and the device is
commanded to LISTEN. The routine can NOT be used to send a secondary
address after a call to the TALK routine.
A secondary address is usually used to give setup information to a
device before I/O operations begin.
When a secondary address is to be sent to a device on the serial bus,
the address must first be ORed with $60.
</TD></TR></TABLE><BR>
<B>FFAE - UNLSN - Send an UNLISTEN command on serial bus</B><BR>
<TABLE><TR><TD><PRE> In: N/A - Out: A=Destroyed
Error returns: See READST
</TD></TR></TABLE>Commands all devices on the serial bus to stop receiving data. Only devices
previously commanded to listen are affected.<BR>
<BR>
<B>FFBA - TALK - Command a device on the serial bus to TALK</B><BR>
In: A=Device number (0-1Fh) - Out: A=Destroyed<BR>
Error returns: See READST<BR>
<BR>
<B>FF96 - TKSA - Send a secondary address to a device commanded to TALK</B><BR>
Use TALK to send the device number before using TKSA.<BR>
TKSA is required if the device does use secondary address.<BR>
In: A=Secondary Address (0..1Fh), eg. disk channel_number - Out: A=Destroyed<BR>
Error returns: See READST<BR>
<BR>
<B>FFAB - UNTLK - Send an UNTALK command on serial bus</B><BR>
<TABLE><TR><TD><PRE> In: N/A - Out: A=Destroyed
Error returns: See READST
</TD></TR></TABLE>All devices previously set to TALK will stop sending data when this command
is received.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalsystemcontrol"></A><FONT SIZE=+2>&nbsp;KERNAL System Control</FONT></TD></TR></TABLE><BR>
<B>FF81 - CINT - Initialize screen editor & 6567 video chip</B><BR>
C64 Only - Not supported by VIC20 !!!<BR>
In: N/A - Out: A,X,Y=Destroyed<BR>
<TABLE><TR><TD><PRE> Description: This routine sets up the 6567 video controller chip in the
Commodore 64 for normal operation. The KERNAL screen editor is also
initialized. This routine should be called by a Commodore 64 program
cartridge.
</TD></TR></TABLE><BR>
<B>FF84 - IOINIT - Initialize I/O devices</B><BR>
C64 Only - Not supported by VIC20 !!!<BR>
In: N/A - Out: A,X,Y=Destroyed<BR>
<TABLE><TR><TD><PRE> Description: This routine initializes all input/output devices and
routines. It is normally called as part of the initialization procedure
of a Commodore 64 program cartridge.
</TD></TR></TABLE><BR>
<B>FF87 - RAMTAS - Perform RAM test</B><BR>
C64 Only - Not supported by VIC20 !!!<BR>
In: N/A - Out: A,X,Y = Destroyed, TwoSecondsOfYourLife = Wasted.<BR>
<TABLE><TR><TD><PRE> Description: This routine is used to test RAM and set the top and
bottom of memory pointers accordingly. It also clears locations $0000 to
$0101 and $0200 to $03FF. It also allocates the cassette buffer, and sets
the screen base to $0400. Normally, this routine is called as part of the
initialization process of a Commodore 64 program cartridge.
</TD></TR></TABLE><BR>
<B>FF8A - RESTOR - Restore default system and interrupt vectors</B><BR>
In: N/A - Out: A,X,Y=Destroyed<BR>
<TABLE><TR><TD><PRE> Description: This routine restores the default values of all system
vectors used in KERNAL and BASIC routines and interrupts. (See the Memory
Map for the default vector contents). The VECTOR routine is used
to read and alter individual system vectors.
</TD></TR></TABLE><BR>
<B>FF8D - VECTOR - Copy KERNAL vectors [0314h-0333h] to/from Buffer [Y:X]</B><BR>
<TABLE><TR><TD><PRE> Get: In: Cy=1, Y:X=Target Address - Out: A,X,Y=Destroyed
Set: In: Cy=0, Y:X=Source Address - Out: A,X,Y=Destroyed
</TD></TR></TABLE>BUG: Programmers Reference suggests using a 26 bytes buffer, all C64/VIC20
Kernal versions actually require 32 bytes (20h) buffer.<BR>
<BR>
<B>FF9C - MEMBOT - Get or Set bottom of RAM</B><BR>
<TABLE><TR><TD><PRE> Set: In: Cy=0, Y:X=Address
Get: In: Cy=1 - Out: Y:X=Address (usually 800h on C64)
</TD></TR></TABLE><BR>
<B>FF99 - MEMTOP - Get or Set the top of RAM</B><BR>
<TABLE><TR><TD><PRE> Set: In: Cy=0, Y:X=Address
Get: In: Cy=1 - Out: Y:X=Address (usually A000h on C64)
</TD></TR></TABLE><BR>
<B>FF9F - SCNKEY - Scan the keyboard</B><BR>
Preparatory routines: IOINIT<BR>
<TABLE><TR><TD><PRE> In: N/A - Out: A,X,Y=Destroyed
</TD></TR></TABLE>Scans the keyboard, if a key is down, its ASCII value is placed in the
keyboard queue, which can be then read by GETIN.<BR>
SCNKEY is normally automatically called by the interrupt handler.<BR>
<BR>
<B>FFED - SCREEN - Get Computers Screen Format</B><BR>
<TABLE><TR><TD><PRE> Out: X=Width, Y=Height (40x25 for C64/C16, 22x23 for VIC20)
</TD></TR></TABLE><BR>
<B>FFF0 - PLOT - Get or Set Cursor Location</B><BR>
<TABLE><TR><TD><PRE> Set: In: Cy=0, X=0..24, Y=0..39 - Out: A=Destroyed
Get: In: Cy=1 - Out: X=0..24, Y=0..39
</TD></TR></TABLE>Note that the X-register has been choosen to specify the Y-position.<BR>
<BR>
<B>FFF3 - IOBASE - Get Computers I/O Base Address</B><BR>
Out: Y:X=Address (C64: DC00h, CIA#1) (VIC20: 9110h, VIA#1) (C16: FD00h, ACIA)<BR>
<BR>
<B>FFDB - SETTIM - Set the system clock</B><BR>
In: Y:X:A=Time in 1/60 seconds (jiffies) - Out: N/A<BR>
<BR>
<B>FFDE - RDTIM - Read system clock</B><BR>
<TABLE><TR><TD><PRE> In: N/A - Out: Y:X:A=Time in 1/60 seconds (jiffies)
The clock range is 24 hours, 0..5183999 (0..4F19FFh) jiffies,
and starts over at zero when exceeding that range.
</TD></TR></TABLE>Note: The clock is NOT battery buffered, it is reset to zero on power up.<BR>
BUG: Programmers Guide incorrectly specified A:X:Y ordering for RDTIM/SETTIM.<BR>
The clock is incremented by CIA1 only 20x per second ??? Or is that 3x
CPU-clock ??? Inaccuracy with PAL/NTSC oscillators which are both not
exact 1MHZ ???<BR>
<BR>
<B>FFEA - UDTIM - Update the system clock</B><BR>
Increments the system clock by 1 jiffie (=1/60 seconds).<BR>
This function is usually called by the KERNALs interrupt handler.<BR>
In: N/A - Out: A,X=Destroyed<BR>
<BR>
<B>FFA2 - SETTMO - Set IEEE bus card timeout flag</B><BR>
<TABLE><TR><TD><PRE> In: A.Bit7 Timeout Flag (0=Set/Enable, 1=Reset/Disable) - Out: Same
</TD></TR></TABLE>NOTE: This routine is used ONLY with an IEEE add-on card!<BR>
<TABLE><TR><TD><PRE> Description: When the timeout flag is set, the Kernal will wait for a
device on the IEEE port for 64 milliseconds. If the device does not
respond to the Data Address Valid (DAV) signal within that time then the
Kernal will recognize an error condition and leave the handshake sequence.
</TD></TR></TABLE>NOTE: The Commodore 64 uses the timeout feature to communicate that a disk
file is not found on an attempt to OPEN a file only with an IEEE card.<BR>
<BR>
<B>FFE1 - STOP - Check if &lt;STOP&gt; key is pressed</B><BR>
<TABLE><TR><TD><PRE> In: N/A - Out: A,X=Destroyed, Zeroflag=STOP Flag
</TD></TR></TABLE>If the &lt;STOP&gt; key on the keyboard was pressed during a UDTIM call, this call
returns the Z flag set. In addition, the channels will be reset to default
values.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalerrorhandling"></A><FONT SIZE=+2>&nbsp;KERNAL Error Handling</FONT></TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> ERROR RETURNS: A return from a KERNAL routine with the CARRY set
indicates that an error was encountered in processing. The accumulator
will contain the number of the error.
NOTE: Some KERNAL I/O routines do not use these codes for error
messages. Instead, errors are identified using the KERNAL READST
routine.
</TD></TR></TABLE>Additionally, disk drives provide additional error information by reading
from the drives error channel (see Disk chapter for more info).<BR>
<BR>
<B>Error codes in Accumulator (A-Register)</B><BR>
<TABLE><TR><TD><PRE> If an error occurs during a KERNAL routine, the carry bit is set,
and the number of the error message is returned in the accumulator.
Num Expl.
0 Routine terminated by the &lt;STOP&gt; key
1 Too many open files
2 File already open
3 File not open
4 File not found
5 Device not present
6 File is not an input file
7 File is not an output file
8 File name is missing
9 Illegal device number
240 Top-of-memory change RS-232 buffer allocation/deallocation
</TD></TR></TABLE><BR>
<B>FFB7 - READST - Read Status Word of Serial Bus and Cassette operations</B><BR>
In: N/A - Out: A, Bit 0-7 (0=Okay, 1=Error) (See table)<BR>
<TABLE><TR><TD><PRE> Bit Expl.
0 Serial Bus: Time out write
1 Serial Bus: Time out read
2 Cassette: Short Block
3 Cassette: Long Block
4 Cassette: Any mismatch/Unrecoverable read error
5 Cassette: Checksum error
6 Cassette: End of file, Serial Bus: EOI line (End Or Identify)
7 Cassette: End of tape, Serial Bus: Device not present
</TD></TR></TABLE><BR>
<B>FF90 - SETMSG - Enable/Disable Screen Output of Control & Error Messages</B><BR>
<TABLE><TR><TD><PRE> Communication registers: A
Registers affected: A
Bit7 0=Disable, 1=Enable Control Messages (eg. PRESS PLAY ON CASSETTE)
Bit6 0=Disable, 1=Enable Error Messages (eg. FILE NOT FOUND)
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="kernalfirstkilobyteram0000h03ffh"></A><FONT SIZE=+2>&nbsp;KERNAL First Kilobyte RAM (0000h-03FFh)</FONT></TD></TR></TABLE><BR>
Below describes the C64/VIC20 operating system usage of the first kilobyte of
RAM. Caution: The C16 uses different addresses.<BR>
Fixed assignments are 0100h-01FFh (CPU stack), and 0314h-0319h (IRQ/BRK/NMI
vectors). The other memory can be used for whatever purpose by Non-OS-based
programs.<BR>
<BR>
<TABLE><TR><TD><PRE> Address Name Expl.
0000h D6510 C64: 6510 On-Chip Data-Direction Register
0001h R6510 C64: 6510 On-Chip Data-Input/Output Register
0002h C64: Unused
</TD></TR></TABLE><B>BASIC Working Storage (0000h-008Fh)</B><BR>
<TABLE><TR><TD><PRE> 0000h VIC20: USR Function JMP Opcode (4Ch) (C64: see 0310h)
0001h-0002h VIC20: USR Function Vector (MSB,LSB) (C64: see 0311h)
0003h-0004h ADRAY1 Jump Vector: Convert Float--Integer
0005h-0006h ADRAY2 Jump Vector: Convert Integer--Float
0007h CHARAC Search Character
0008h ENDCHR Flag: Scan for Quote at End of String
0009h TRMPOS Screen Column From Last TAB
000Ah VERCK Flag: 0=Load, 1=Verify
000Bh COUNT Input Buffer Pointer / Number of Subscripts
000Ch DIMFLG Flag: Default Array DIMension
000Dh VALTYP Data Type: FFh=String, 00h=Numeric
000Eh INTFLG Data Type: 80h=Integer, 00h=Float
000Fh GARBFL Flag: DATA scan/LIST quote/Garbage Coll
0010h SUBFLG Flag: Subscript Ref / User FNx Function Call
0011h INPFLG Flag: 00h=INPUT, 40h=GET, 98h=READ
0012h TANSGN Flag: ATN/TAN sign / Comparison Result
0013h Flag: INPUT Prompt
0014h-0015h LINNUM Temp: Integer Value (see Float conversion 0003h,0005h)
0016h TEMPPT Pointer Temporary String Stack
0017h-0018h LASTPT Last Temp String Address
0019h-0021h TEMPST Stack for Temporary Strings
0022h-0025h INDEX Utility Pointer Area (0022h: INDEX1, 0024h: INDEX2)
0026h-002Ah RESHO Floating-Point Product of Multiply
002Bh-002Ch TXTTAB Pointer: Start of BASIC Program
002Dh-002Eh VARTAB Pointer: Start of BASIC Variables (End of Basic program)
002Fh-0030h ARYTAB Pointer: Start of BASIC Arrays (End of Variables)
0031h-0032h STREND Pointer: Start of free memory (End of Arrays+1)
0033h-0034h FRETOP Pointer: Bottom of String Storage (End of Free memory)
0035h-0036h FRESPC Utility String Pointer
0037h-0038h MEMSIZ Pointer: Highest Address Used by BASIC (End of Strings)
0039h-003Ah CURLIN Current BASIC Line Number
003Bh-003Ch OLDLIN Previous BASIC Line Number
003Dh-003Eh OLDTXT Pointer: BASIC Statement for CONT
003Fh-0040h DATLIN Current DATA Line Number
0041h-0042h DATPTR Pointer: Current DATA Item Address
0043h-0044h INPPTR Vector: INPUT Routine
0045h-0046h VARNAM Current BASIC Variable Name
0047h-0048h VARPNT Current BASIC Variable Address (Pointer)
0049h-004Ah FORPNT Pointer: Index Variable for FOR/NEXT
<B> 004Bh-0060h Temp Pointer / Data Area</B>
004Bh-004Ch VARTXT Temporary storage for TXTPTR during READ, INPUT, GET
004Dh OPMASK Mask used during FRMEVL / Comparison symbol accumulator
004Eh-0052h TEMPF3 Temporary storage for FLPT value.
0053h FOUR6 Length of String Variable during Garbage collection.
0054h-0056h JMPER Jump Vector used in Function Evaluation (4Ch, LSB, MSB)
0057h-005Bh TEMPF1 Temporary storage for FLPT value.
005Ch-0060h TEMPF2 Temporary storage for FLPT value.
</TD></TR></TABLE><B>.................</B><BR>
<TABLE><TR><TD><PRE> 0061h-0066h FAC Floating-Point Accumulator 1 (Exp,4-Byte Mantissa,Sign)
0067h SGNFLG Pointer: Series Evaluation Constant
0068h BITS Floating-Point Accumulator 1 (Overflow Digit)
0069h-006Eh ARG Floating-Point Accumulator 2 (Exp,4-Byte Mantissa,Sign)
006Fh ARISGN Sign Comparison Result: Accumulator 1 vs 2
0070h FACOV Floating-Point Accumulator 1 (Low-Order, Rounding)
0071h-0072h FBUFPT Pointer: Cassette Buffer
0073h-0078h CHRGET Subroutine: Get Next Byte of BASIC Text
0079h CHRGOT Subroutine: Entry to Get Same Byte of Text Again
007Ah-007Bh TXTPTR Pointer: Current Byte of BASIC Text
007Ch-008A Subroutine: Rest of the CHRGET/CHRGOT Subroutines
008Bh-008Fh RNDX Floating RND Function Seed Value
</TD></TR></TABLE><B>KERNAL Working Storage (0090h-00FFh)</B><BR>
<TABLE><TR><TD><PRE> 0090h STATUS Kernal I/O Status Word: ST
0091h STKEY Flag: STOP key / RVS key
0092h SVXT Timing Constant for Tape
0093h VERCK Flag: 0=Load, 1=Verify
0094h C3PO Flag: Serial Bus-Output Character Buffered
0095h BSOUR Buffered Character for Serial Bus
0096h SYNO Cassette Sync No. / Tape EOT received
0097h Temp Data Area / Register save
0098h LDTND Number of Open Files / Index to File Table
0099h DFLTN Default Input Device (normally 0=Keyboard)
009Ah DFLTO Default Output (CMD) Device (normally 3=Screen)
009Bh PRTY Tape Character Parity
009Ch DPSW Flag: Tape Byte-Received
009Dh MSGFLG Flag: 80h=Direct Mode, 00h=Program RUN
009Eh PTR1 Tape Pass 1 Error Log
009Fh PTR2 Tape Pass 2 Error Log
00A0h-00A2h TIME 60Hz Real-Time Jiffy Clock (approx) 1/60 Sec
00A3h-00A4h Temp Data Area
00A5h CNTDN Cassette Sync Countdown
00A6h BUFPNT Pointer: Tape I/O Buffer
00A7h INBIT RS-232 Input Bits / Cassette Temp
00A8h BITCI RS-232 Input Bit Count / Cassette Temp
00A9h RINONE RS-232 Flag: Check for Start Bit
00AAh RIDATA RS-232 Input Byte Buffer/Cassette Temp
00ABh RIPRTY RS-232 Input Parity / Cassette Short Cnt
00ACh-00ADh SAL Pointer: Tape Buffer / Screen Scrolling
00AEh-00AFh EAL Tape End Addresses/End of Program
00B0h-00B1h CMP0 Tape Timing Constants
00B2h-00B3h TAPE1 Pointer: Start of Tape Buffer
00B4h BITTS RS-232 Out Bit Count / Cassette Temp
00B5h NXTBIT RS-232 Next Bit to Send/ Tape EOT Flag
00B6h RODATA RS-232 Out Byte Buffer
00B7h FNLEN Length of Current File Name
00B8h LA Current Logical File Number
00B9h SA Current Secondary Address
00BAh FA Current Device Number
00BBh-00BCh FNADR Pointer: Current File Name
00BDh ROPRTY RS-232 Out Parity / Cassette Temp
00BEh FSBLK Cassette Read / Write Block Count
00BFh MYCH Serial Word Buffer
00C0h CAS1 Tape Motor Interlock
00C1h-00C2h STAL I/O Start Address (VIC20:8000h, C64:A000h) (both wrong?)
00C3h-00C4h MEMUSS Tape Load Temps / VIC20: KERNAL setup pointer
00C5h LSTX Current Key Pressed (40h=None) (0-3Fh=Key Number)
The Key Numbers differ on C64/VIC20. If more than 1 key
is down, the key with the highest number shows up here.
Not used for special keys like SHIFT, CTRL, etc.
00C6h NDX Number of Chars in Keyboard Buffer (see also: 0277h)
00C7h RVS Flag: Reverse Chars (01h=On/Yes, 00h=Off/Not Used)
00C8h INDX Pointer: End of Logical Line for INPUT
00C9h-00CAh LXSP Cursor X,Y Position at Start of INPUT
00CBh SFDX C64: Flag: Print Shifted Chars.
00CBh VIC20: Current key pressed (same as 00C5h)
00CCh BLNSW Cursor Blink enable (0=Flash Cursor) (copy of 00C6h)
00CDh BLNCT Timer: Countdown to Toggle Cursor
00CEh GDBLN Character Under Cursor
00CFh BLNON Flag: Last Cursor Blink On/Off
00D0h CRSW Flag: INPUT or GET from Keyboard / from screen
00D1h-00D2h PNT Pointer: Cursor Current Screen Line Address
00D3h PNTR Cursor Column on Current Line
00D4h QTSW Flag: Editor in Quote Mode (00h=No/Direct Cursor)
00D5h LNMX Screen Line Length, screen_width*(1..4)-1
00D6h TBLX Current Cursor Line Number (see also: 00D1h-00D2h,00D3h)
00D7h Temp Data Area, last inkey/checksum/buffer
00D8h INSRT Insert Mode (00h=Disable, NNh=Number of spaces left)
00D9h-00F2h LDTB1 Screen Line Link Table / Editor Temps
00F3h-00F4h USER Pointer: Current Screen Color RAM location
00F5h-00F6h KEYTAB Pointer: Current Keyboard Decode Table (Norm,Shift,etc.)
00F7h-00F8h RIBUF RS-232 Input Rcv Buffer Pointer
00F9h-00FAh ROBUF RS-232 Output Tx Buffer Pointer
00FBh-00FEh FREKZP User Program Zero-Page Space (not used by BASIC/KERNAL)
00FFh BASZPT BASIC Temp Data Area
</TD></TR></TABLE><B>BASIC & KERNAL Stack (0100h-01FFh)</B><BR>
<TABLE><TR><TD><PRE> 0100h-01FFh Micro-Processor System Stack Area
0100h-010Ah Floating to String Work Area
0100h-013Eh BAD Tape Error Log
</TD></TR></TABLE><B>BASIC & KERNAL Working Storage (0200h-033Bh)</B><BR>
<TABLE><TR><TD><PRE> 0200h-0258h BUF System INPUT Buffer
0259h-0262h LAT KERNAL Table: Active OPEN Logical File Numbers
0263h-026Ch FAT KERNAL Table: Device Number for each File
026Dh-0276h SAT KERNAL Table: Secondary Address for each File
0277h-0280h KEYD Keyboard Buffer Queue (see also: 00C6h,0289h)
0281h-0282h MEMSTR Pointer: Bottom of Memory for Operating System
0283h-0284h MEMSIZ Pointer: Top of Memory for Operating System
0285h TIMOUT Flag: Kernal Variable for IEEE or Serial Timeout
0286h COLOR Current Character Color Code
0287h GDCOL Background Color Under Cursor
0288h HIBASE Start of Screen Memory (MSB=Page)
0289h XMAX Size of Keyboard Buffer (max 0Ah, see also: 0277h,0289h)
028Ah RPTFLG Flag: Key Repeat (00h=Cursor Keys, 80h=All keys)
028Bh KOUNT Key Repeat Speed Counter
028Ch DELAY Key Repeat Delay Counter
028Dh SHFLAG Keyboard Flags (Bit0=Shift, Bit1=Commodore, Bit2=Ctrl)
028Eh LSTSHF Last Keyboard Shift Pattern
028Fh-0290h KEYLOG Vector: Keyboard Table Setup / Decode Logic
0291h MODE Flag: SHIFT+COMMODORE Case Switch (0=Enable,80h=Disable)
0292h AUTODN Flag: Auto Scroll Down (0=On, other=Off)
0293h M51CTR RS-232: 6551 Control Register Image
0294h MS1CDR RS-232: 6551 Command Register Image
0295h-0296h M51AJB RS-232 Non-Standard BPS (Time/2-100) USA
0297h RSSTAT RS-232: 6551 Status Register Image
0298h BITNUM RS-232 Number of bits left to send
0299h-029Ah BAUDOF RS-232 Baud Rate: Full Bit Time (us)
029Bh RIDBE RS-232 Index to Input Buffer End
029Ch RIDBS RS-232 Start of Input Buffer (Page)
029Dh RODBS RS-232 Start of Output Buffer (Page)
029Eh RODBE RS-232 Index to Output Buffer End
029Fh-02A0h IRQTMP Holds IRQ Vector During Tape I/O
02A1h-02FFh VIC20: Program indirects
02A1h ENABL C64: RS-232 Enables
02A2h C64: TOD Sense During Cassette I/O
02A3h C64: Temp Storage For Cassette Read
02A4h C64: Temp D1 IRQ Indicator For Cassette Read
02A5h C64: Temp For Line Index
02A6h C64: PAL/NTSC Flag, 0= NTSC, 1 = PAL
02A7h-02FFh C64: Unused
0300h-0301h IERROR Vector: Print BASIC Error Message
0302h-0303h IMAIN Vector: BASIC Warm Start
0304h-0305h ICRNCH Vector: Tokenize BASIC Text (Crunch)
0306h-0307h IQPLOP Vector: BASIC Text LIST (Print Tokens)
0308h-0309h IGONE Vector: BASIC Char. Dispatch / Start new Basic code link
030Ah-030Bh IEVAL Vector: BASIC Token Evaluation / arithmetic element link
030Ch-030Fh SxREG Storage for 6502 Registers A,X,Y,P
0310h-0313h VIC20: Unused ?
0310h USRPOK C64: USR Function JMP Opcode (4Ch) (VIC20: see 0000h)
0311h-0312h USRADD C64: USR Function Vector (LSB,MSB) (VIC20: see 0001h)
0313h C64: Unused
0314h-0315h CINV CPU IRQ Vector (redirected IRQ with A,X,Y pushed)
0316h-0317h CBINV CPU BRK Vector (redirected BRK with A,X,Y pushed)
0318h-0319h NMINV CPU NMI Vector (redirected NMI without anything pushed)
031Ah-031Bh IOPEN KERNAL OPEN Vector
031Ch-031Dh ICLOSE KERNAL CLOSE Vector
031Eh-031Fh ICHKIN KERNAL CHKIN Vector
0320h-0321h ICKOUT KERNAL CHKOUT Vector
0322h-0323h ICLRCH KERNAL CLRCHN Vector
0324h-0325h IBASIN KERNAL CHRIN Vector
0326h-0327h IBSOUT KERNAL CHROUT Vector
0328h-0329h ISTOP KERNAL STOP Vector
032Ah-032Bh IGETIN KERNAL GETIN Vector
032Ch-032Dh ICLALL KERNAL CLALL Vector
032Eh-032Fh USRCMD User-Defined Vector
0330h-0331h ILOAD KERNAL LOAD Vector
0332h-0333h ISAVE KERNAL SAVE Vector
0334h-033Bh Unused
</TD></TR></TABLE><B>Tape Buffer Working Storage (033Ch-03FFh)</B><BR>
<TABLE><TR><TD><PRE> 033Ch-03FBh TBUFFR Tape I/O Buffer (General purpose RAM when CAS not used)
03FCh-03FFh Unused
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="versatileinterfaceadapter6522via"></A><FONT SIZE=+2>&nbsp;Versatile Interface Adapter 6522 (VIA)</FONT></TD></TR></TABLE><BR>
<B>00h - Input/Output Register B (IRB/ORB) (PB7..PB0)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7-0 Input/Output lines PB7..PB0 (0=Low, 1=High)
</TD></TR></TABLE>Writing always sets the ORB output latch (even in input mode).<BR>
Reading unlatched-inputs returns current state of PB pins.<BR>
Reading latched-inputs returns state of PB pins at most recent CB1 edge.<BR>
Reading outputs will directly return ORB settings, regardless of PB pins
and/or latching (unlike as for Register A below).<BR>
Reading/writing IRB/ORB acknowledges CB1 Edge IRQ, and (in Non-independend
mode) also acknowledges CB2 Edge IRQ.<BR>
<BR>
<B>01h - Input/Output Register A (IRA/ORA) (PA7..PA0)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7-0 Input/Output lines PA7..PA0 (0=Low, 1=High)
</TD></TR></TABLE>Writing always sets the ORA output latch (even in input mode).<BR>
Reading unlatched-inputs returns current state of PA pins.<BR>
Reading latched-inputs returns state of PA pins at most recent CA1 edge.<BR>
In output mode, reading/latching data from PA pins will most likely represent
to ORA data - but may be forcefully pulled high/low by external hardware
(unlike as for Register B above).<BR>
Reading/writing IRA/ORA acknowledges CA1 Edge IRQ, and (in Non-independend
mode) also acknowledges CA2 Edge IRQ.<BR>
<BR>
<B>02h - Data Direction Register B (DDRB)</B><BR>
<B>03h - Data Direction Register A (DDRA)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7-0 Direction for Data Port Bits 7-0 (0=Input, 1=Output)
</TD></TR></TABLE><BR>
<B>04h - T1 Low-order Counter/Latch (T1C_L)</B><BR>
<B>05h - T1 High-order Counter/Latch (T1C_H)</B><BR>
<B>06h - T1 Low-order Latch (T1L_L)</B><BR>
<B>07h - T1 High-order Latch (T1L_H)</B><BR>
<TABLE><TR><TD><PRE> Reading port 04h/05h returns the upper/lower T1 counter value.
Reading port 06h/07h returns the lower/upper T1 latch value.
Reading port 04h resets the T1 interrupt flag (IFR.6).
Writing port 04h/05h or 06h/07h sets lower/upper bits of the T1 &lt;latch&gt;.
Writing port 05h copies the 16bit T1 latch to the 16bit T1 counter.
Writing port 05h/07h resets the T1 interrupt flag (IFR.6).
</TD></TR></TABLE>T1 is a 16bit counter decremented at system clock rate. An interrupt is
generated upon underflow. It can be used in one-shot mode, or in continous
mode (using the latch as reload value upon underflows). Additionally, it can
be configured to toggle the PB7 output upon underflow.<BR>
<BR>
<B>08h - T2 Low-Order Latch/Counter (T2C_L)</B><BR>
<B>09h - T2 High-Order Counter (T2C_H)</B><BR>
<TABLE><TR><TD><PRE> Writing to 08h sets the T2 low-order &lt;latch&gt;.
Writing to 09h sets the T2 high-order &lt;counter&gt;.
Writing to 09h also copies lower-order latch to low-order counter.
Writing to 09h additionally resets the T2 interrupt flag (IFR.5).
Reading from 08h/09h returns the low/high-order T2 counter value.
Reading from 08h additionally resets the T2 interrupt flag (IFR.5).
</TD></TR></TABLE>T2 is a one-shot 16bit counter, decremented either at System 02 clock rate,
or by negative pulses on PB6 pin. An interrupt is generated upon underflow.
T2 can be also used as 8bit prescaler for the Shift register (in that case,
the low-order latch is used as 8bit reload value after each bit transfer).<BR>
<BR>
<B>0Ah - 8bit Shift Register (SR)</B><BR>
<TABLE><TR><TD><PRE> Reading/writing SR resets the shift counter, and, in most shift modes,
starts the transfer and generates an interrupt once the shift counter
reaches a value of eight.
</TD></TR></TABLE>Serial data is shifted in or out to the left, in case of serial output
the register is in fact just rotated to the left, causing the initial
content to be restored after 8 shift operations.<BR>
Data is input/output at CB2 line, the shift clock is input/output at CB1 line.<BR>
Transfer direction, internal clock rate, or external clock selection can be
programmed in Auxiliary Control Register.<BR>
<BR>
<B>0Bh - Auxiliary Control Register (ACR)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7 T1 Toggle PB7 Output (0=Disable, 1=Invert PB7 upon underflow)
6 T1 Continous Mode (0=One-Shot, 1=Restart upon underflow)
5 T2 Clock Source (0=System clock, 1=PB6 negative edge)
4 Shift Register Direction (0=Shift In, 1=Shift Out)
3-2 Shift Register Mode (0-3, see below)
1 PB Latching Enable (0=Disable, 1=Latch PB on CB1 Interrupt Flag)
0 PA Latching Enable (0=Disable, 1=Latch PA on CA1 Interrupt Flag)
</TD></TR></TABLE>Shift Register Modes:<BR>
<TABLE><TR><TD><PRE> 0=Free-Run (when Bit4=1), or Disabled (when Bit4=0)
1=Shift at System 02 Clock rate divided by (2+T2C_L)
2=Shift at System 02 Clock rate divided by 2
3=Shift at external CB1 clock rate
</TD></TR></TABLE>In mode Free-Run/Disabled mode, data is shifted in at CB1 rate, or shifted
out at T2 rate (by repeatedly outputting 8bit SR data), in either case no
interrupts are generated when completing 8bits of data.<BR>
<BR>
<B>0Ch - Peripheral Control Register (PCR)</B><BR>
<TABLE><TR><TD><PRE> Bit Expl.
7-5 CB2 Input/Output Control (0-7, see below)
4 CB1 Input Control (0-1, see below)
3-1 CA2 Input/Output Control (0-7, see below)
0 CA1 Input Control (0-1, see below)
</TD></TR></TABLE>CB2 and CA2 Control (referred as CX2, with corresponding CX1,PX respectively)<BR>
<TABLE><TR><TD><PRE> 0 (In) Interrupt on negative CX2 edge, Acknowldge by read/write Port PX
1 (In) Interrupt on negative CX2 edge, Independent (without ack via PX)
2 (In) Interrupt on positive CX2 edge, Acknowldge by read/write Port PX
3 (In) Interrupt on positive CX2 edge, Independent (without ack via PX)
4 (Out) Handshake (CX2=LOW on write Port B, CX2=HIGH on active CX1 edge)
5 (Out) Pulse (CX2=LOW for 1 cycle on write to Port PX)
6 (Out) Manual (CX2=LOW)
7 (Out) Manual (CX2=HIGH)
</TD></TR></TABLE>CB1 and CA1 Control (referred as CX1, with corresponding PX respectively)<BR>
<TABLE><TR><TD><PRE> 0 (In) Interrupt on negative CX1 edge, Acknowldge by read/write Port PX
1 (In) Interrupt on positive CX1 edge, Acknowldge by read/write Port PX
</TD></TR></TABLE><BR>
<B>0Dh - Interrupt Flag Register (IFR) (Request/Acknowledge)</B><BR>
<B>0Eh - Interrupt Enable Register (IER) (Enable/Disable)</B><BR>
<TABLE><TR><TD><PRE> Bit Set by Cleared by
0 CA2 Active edge Read or write ORA (except in Independed mode)
1 CA1 Active edge Read or write ORA
2 Completed 8 shifts Read or write SR
3 CB2 Active edge Read or write ORB (except in Independed mode)
4 CB1 Active edge Read or write ORB
5 T2 Underflow Read T2 low or write T2 high
6 T1 Underflow Read T1 low or write T1 high
7 Any enabled interrupt Cleared only when (IER AND IFR AND 7Fh)=00h
</TD></TR></TABLE>Accessing Interrupt Flag Register:<BR>
<TABLE><TR><TD><PRE> Write IFR 0-6 Interrupt Acknowledge (0=Keep, 1=Set to Zero)
Write IFR 7 No function (Don't care)
Read IFR 0-6 Interrupt Request Flags (0=None, 1=Interrupt Request)
Read IFR 7 Interrupt signal, set when IER AND IFR AND 7Fh is nonzero
</TD></TR></TABLE>Accessing Interrupt Enable Register:<BR>
<TABLE><TR><TD><PRE> Write/IER 0-6 Select Interrupt Enable Bits (0=Keep, 1=Set to Bit7)
Write/IER 7 New Value for Selected IER Bits (0=Disable, 1=Enable)
Read/IER 0-6 Current Value of IER Bits 0-6 (0=Disabled, 1=Enabled)
Read/IER 7 Not used (Always 1)
</TD></TR></TABLE>Writing a "1" into IER Bit 0-6 sets the respective bit to the value in IER 7.<BR>
Writing a "1" into IFR Bit 0-6 sets the respective bit to zero (the IFR bits
can be also cleared by circumstances described in the right column).<BR>
<BR>
<B>0Fh - Input/Output Register A' (IRA'/ORA')</B><BR>
Same as Register 01h, except no CA1/CA2 handshake.<BR>
<BR>
<B>Summary of Input/Output Pins</B><BR>
The VIA includes 16 general purpose pins, 4 control pins, and 1 interrupt pin.<BR>
<TABLE><TR><TD><PRE> Pin(s) Dir Purpose
PA0-7 I/O Eight general purpose I/O pins
PB0-7 I/O Eight general purpose I/O pins
PB6 In Optionally used as Timer T2 clock source (negative edge)
PB7 Out Optionally toggled on each T1 Timer underflow
CA1/CB1 In Edge triggered IRQ (with optional Port A/B latching)
CA2/CB2 In Edge triggered IRQ (with optional Port A/B Acknowledge)
CA1/CB1 In Port A/B handshake input
CA2/CB2 Out Fixed High/Low, or Port A/B Handshake output
CB1/CB2 I/O Shift-Register clock/data
IRQ Out Interrupt signal send to CPU's /IRQ or /NMI input
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskdrive"></A><FONT SIZE=+2>&nbsp;Disk Drive</FONT></TD></TR></TABLE><BR>
"Welcome to the fastest, easiest, and most efficient filing system
available for your Commodore 64 or VIC 20 computer, your 1541 DISK DRIVE."<BR>
<BR>
<A HREF="#disktechdetails">Disk Tech Details</A><BR>
<A HREF="#diskaccessingthedrive">Disk Accessing the Drive</A><BR>
<A HREF="#diskcommandanderrorchannel">Disk Command and Error Channel</A><BR>
<A HREF="#diskdatachannelsfiletypes">Disk Data Channels & File Types</A><BR>
<A HREF="#diskprogrammingthediskcontroller">Disk Programming the Disk Controller</A><BR>
<A HREF="#diskformat">Disk Format</A><BR>
<A HREF="#diskandfileimages">Disk and File Images</A><BR>
<A HREF="#diskmemorymapandioports">Disk Memory Map and I/O Ports</A><BR>
<A HREF="#diskconfiguration">Disk Configuration</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="disktechdetails"></A><FONT SIZE=+2>&nbsp;Disk Tech Details</FONT></TD></TR></TABLE><BR>
<B>1541 Disk Drive</B><BR>
<TABLE><TR><TD><PRE> CPU 6502 ???MHz, 16K ROM, 2K RAM, two 6522 I/O and timer chips
Read/Write Speed ??? Serial Bus Rate ???
Two serial bus sockets (one towards computer, other for further devices)
Power Supply: 100-240V AC, 25 Watts (internally using +5V and +12V)
Height 97 mm, Width 200 mm, Depth 374 mm, Weight 16 tons
Diskettes: Standard mini 5 1/4", Single Sided (SS), Single Density (SD)
Formatting: 35 Tracks, 17-21 sectors per track, 256 bytes per sector
Total Capacity: 174848 bytes (683 blocks, 256 bytes each)
Free Space: 168656 bytes (664 blocks, 256-2 bytes each)
Directory: 144 files per diskette, 16 characters per filename (19 blocks)
</TD></TR></TABLE><BR>
The 1541 disk drive is actually a complete computer with CPU, ROM, and
RAM. The drive is connected to the computer via serial bus. Commodore
describes that overcomplicated circuitry as "intelligent". That is true in
so far that all filesystem is handled by the drive, without occupying ROM
or RAM areas in the computers memory map.<BR>
<BR>
The downside is that the computers BASIC operating system doesn't know
anything about disk drives (it just knows that it talks to something on
the serial bus), LOAD and SAVE commands are barely working. But issuing
DIR, DELETE, or RENAME commands, or viewing disk error messages works only
when using some odd workarounds.<BR>
<BR>
<B>Using Double Sided (DS) Disks</B><BR>
Even though the 1541 disk drive is having only one head, double sided
diskettes can be used, simply turn over the disk to use the other side.
However, you will need to cut a new write protect notch at the right side
of the disk (which becomes left when turned over).<BR>
The disk is write-protected when the notch at left side is closed (eg.
covered by tape). Of course, because the drive is software controlled,
software may easily ignore the write-protect signal.<BR>
Note: The drive doesn't use the index hole, so you don't need to cut that,
too.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskaccessingthedrive"></A><FONT SIZE=+2>&nbsp;Disk Accessing the Drive</FONT></TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> LOAD "*",8 ;load first file on disk (or recently accessed file)
LOAD "FILENAME",8 ;load a specific file by name
LOAD "FILENAME",8:RUN ;load and start a file
LOAD "$",8:LIST ;load and view the directory
LOAD "$0:FILE*",8:LIST ;load and view specific names in the directory
SAVE "FILENAME",8 ;save a file to disk
SAVE "@0:FILENAME",8 ;save a file to disk and delete old file of same name
VERIFY "FILENAME",8 ;compare specified file with program in memory
</TD></TR></TABLE><BR>
<B>Notes</B><BR>
The drive supports standard wildcards ("*" and "?"). Commodore has also
manufactured a dual disk drive (two drives in one case, numbered drive 0
and 1). For 1541, always specify drive "0" in the "$0:" and "@0:"
expressions. When loaded to a different memory location, internal pointers
may get changed automatically inside of the program, in that case VERIFY
would produce an error.<BR>
<BR>
<B>DOS Support Program</B><BR>
A program called DOS Support should be shipped along with the disk drive.<BR>
The following abbreviations can be used if DOS Support has been loaded:<BR>
<TABLE><TR><TD><PRE> /filename load a program from disk
&gt; or @ read and display error channel
&gt;$ or @$ read and display directory
&gt;cmd or @cmd send command to drive
</TD></TR></TABLE><BR>
<B>BASIC Instructions used to access the Disk Drive</B><BR>
<TABLE><TR><TD><PRE> LOAD file_name, device_number [,command_number]
SAVE file_name, device_number [,command_number]
VERIFY file_name, device_number
OPEN file_number, device_number, channel_number [,file_name]
PRINT# file_number, variable list
INPUT# file_number, variable list
GET# file_number, variable list
CLOSE file_number
STATUS, CHR$, ASC
</TD></TR></TABLE><BR>
<B>KERNAL Functions used to access the Disk Drive</B><BR>
<TABLE><TR><TD><PRE> Addr Name Expl.
FFBA SETLFS Set logical/physical/secondary address (fileno,device,channel)
FFBD SETNAM Set length and address of filename
FFC0 OPEN Open a file (parameters must be prepared by SETLFS/SETNAM)
FFC3 CLOSE Close a file
FFC6 CHKIN Select file_number for CHRIN
FFC9 CHKOUT Select file_number for CHROUT
FFCC CLRCHN Clear all channels (undoes or terminates CHKIN/CHKOUT ???)
FFCF CHRIN Read a byte from the file being selected by CHKIN
FFD2 CHROUT Write a byte to the file being selected by CHKOUT
</TD></TR></TABLE><BR>
Whereas,<BR>
<TABLE><TR><TD><PRE> device_number values 8-11 for 1st-4th attached drive unit (usually 8)
drive_number always 0 for normal drives, value 0-1 for dual drives
file_number file handle in computer (use any value 1-127)
channel_number file handle in drive (0-1 reserved, 2-14 data, 15 cmd/err)
file_name ASCII filename (misused to contain parameters in some cases)
command_number
</TD></TR></TABLE><BR>
<B>Using PRINT#</B><BR>
Note that PRINT always produces text output (any numeric parameters are
converted into strings), if you want to send a binary number as such then
you must specify it as CHR$(nn) to avoid that conversion. PRINT inserts
unwanted spaces between parameters in some cases, or lacks to insert
spaces or commas in other cases, and PRINT appends CR, chr$(0Dh), at the
end of the statement (unless it was terminated by comma or semicolon).<BR>
In short, PRINT works much unpredictable - PRINT your data to the screen
instead of to the drive to see how it comes out.<BR>
<BR>
<TABLE><TR><TD><PRE> When using the PRINT# statement, if you use commas (,) to separate
items on the line, the items will be separated by some blank spaces,
as if it were being formatted for the screen. Semicolons (;) don't
result in any extra spaces.
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> Numeric data written in the file takes the form of a string, as if the
STR$ function had been performed on it before writing it out. The
first character will be a blank space if the number is positive, and a
minus sign (-) if the number is negative. Then comes the number, and
the last character is the cursor right character.
</TD></TR></TABLE><BR>
<B>Using INPUT#, GET#, and STATUS</B><BR>
INPUT# receives strings, any commas or carriage returns (CR) in the file
are treated as string end. GET# receives single characters, commas and CRs
can be read as such, note that binary data comes out as CHR$(nn), the
binary value can be retrieved by ASC function. The ST or STATUS system
variable can be used to detect the end of the file.<BR>
<BR>
<B>Using CLOSE</B><BR>
It is extremely important that you properly CLOSE files once you are<BR>
finished using them. Closing the file causes DOS to properly allocate<BR>
blocks in the BAM and to finish the entry in the directory. If you<BR>
don't CLOSE the file, all your data will be lost!<BR>
<BR>
You should also be careful not to CLOSE the error channel (channel<BR>
15) before CLOSEing your data channels. The error channel should be<BR>
OPENed first and CLOSEd last of all your files! That will keep your<BR>
programs out of trouble.<BR>
<BR>
If you close the error channel while other files are OPEN, the disk<BR>
drive will close them for you, but BASIC will still think they are<BR>
open (unless you CLOSE them properly), let you to try to write to them.<BR>
<BR>
NOTE: If your BASIC program leads you into an error condition, all<BR>
files are CLOSEd in BASIC, without CLOSEing them on your disk drive!<BR>
This is a very dangerous condition. You should immediately type the<BR>
statement OPEN 15, 8, 15, "I". This will re-initialize your drive and<BR>
make all your files safe.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskcommandanderrorchannel"></A><FONT SIZE=+2>&nbsp;Disk Command and Error Channel</FONT></TD></TR></TABLE><BR>
Channel 15 is used as command and error channel, allowing to send commands
to the disk drive, and, in the other direction, to receive status
information.<BR>
<BR>
<B>OPEN / Filename</B><BR>
Like data channels, the channel must be opened before using it, but a
filename is not required. The filename field may be left out, or it may
contain a command (allowing to send the first command directly along with
the OPEN function).<BR>
<BR>
<B>Command Format</B><BR>
All commands are to be sent as ASCII text string, terminated by CR:<BR>
<TABLE><TR><TD><PRE> "COMMAND:parameters",0dh
"SPECIAL-COMMAND:parameters",0dh
</TD></TR></TABLE>Commands can be abbreviated by using the first character of each word, ie.<BR>
<TABLE><TR><TD><PRE> "C:parameters",0dh
"S-C:parameters",0dh
</TD></TR></TABLE>Some commands, have more than one parameter, separated by commas or spaces
or other characters (depending on the command).<BR>
Numeric parameters must be sent as decimal text string, ie. the value 80h
(128 decimal) takes up three characters: "1", "2", "8". The only exception
are the "MEMORY-" commands and the "POSITION" command which are using
binary parameters.<BR>
<BR>
<BR>
PRINT#15,<BR>
<BR>
<TABLE><TR><TD><PRE> "NEW:name,id" format the entire disk, and set disk name and 2 chars ID
"NEW:name" clears the directory without re-formatting the whole disk
"COPY:newfile=oldfile" copy a file (source and dest both on same disk)
"COPY:newfile=f1,f2,f3,f4" copy max 4 files into 1 file
"RENAME:newname=oldname" rename a file
"SCRATCH:name" delete a file (may use wildcards)
"INITIALIZE" closes any open files and reboots the drive
"VALIDATE" defragments the disk (do not use with random files)
"DUPLICATE" reserved for dual drives (1:1 copy of a whole disk)
</TD></TR></TABLE><BR>
<BR>
<B>General Disk Managment Commands</B><BR>
<TABLE><TR><TD><PRE> NEW "N
COPY "C:new file=:original file
RENAME "R:new name=old name"
SCRATCH "S:file name"
INITIALIZE "I
VALIDATE "V
DUPLICATE not for single drives
C64/default speed "UI+"
VIC 20 speed "UI-"
</TD></TR></TABLE><B>Special Random File Commands</B><BR>
<TABLE><TR><TD><PRE> BLOCK-ALLOCATE "B-A: drive track block"
BLOCK-FREE "B-F: drive track block"
BLOCK-READ "B-R: channel drive track block"
BLOCK-WRITE "B-W: channel drive track block"
BLOCK-EXECUTE "B-E: channel drive track block"
BUFFER-POINTER "B-P: channel position"
USER1 (UA) (READ) "U1: channel drive track block"
USER2 (UB) (WRITE) "U2: channel drive track block"
</TD></TR></TABLE><B>Special Relative File Command</B><BR>
<TABLE><TR><TD><PRE> POSITION "P", channel+96, record_lsb, record_msb [,position]
</TD></TR></TABLE><B>Disk Controller Commands</B><BR>
<TABLE><TR><TD><PRE> MEMORY-READ "M-R", address_lsb, address_msb
MEMORY-WRITE "M-W", address_lsb, address_msb, length, data[length]
MEMORY-EXECUTE "M-E", address_lsb, address_msb
USER Commands "Un"
</TD></TR></TABLE><BR>
<TABLE><TR><TD><PRE> U3 or UC jump to 0500h
U4 or UD jump to 0503h
U5 or UE jump to 0506h
U6 or UF jump to 0509h
U7 or UG jump to 050Ch
U8 or UH jump to 050Fh
U; or UJ jump to [FFFC] power-up vector
</TD></TR></TABLE><BR>
<B>Error Channel Format</B><BR>
NN is the error number (to be interpreted by software), NAME is the error
name (to be output to screen if wanted), TR and BL usually specify the
track and block number where the error has occured.<BR>
<TABLE><TR><TD><PRE> "NN,NAME,TR,BL",0dh
</TD></TR></TABLE>NN, TR, and BL are numbers in two-digit string format. The items are
separated by commas, and the error message is terminated by CR, chr(0dh).<BR>
After the error message has been received, the error channel gets cleared
(ie. reset to 00/OK) automatically.<BR>
<BR>
<B>Description of DOS Error Messages</B><BR>
<TABLE><TR><TD><PRE> 00 OK - No error.
01 NAME??? - No error. Response to SCRATCH (TR=number of files deleted)
02-19 N/A - No error. Reserved for status messages (should be ignored)
20 READ ERROR - Block header not found
21 READ ERROR - No sync mark found on track
22 READ ERROR - Data block not present
23 READ ERROR - Checksum error in data block
24 READ ERROR - Byte decoding error
25 WRITE ERROR - Write-verify error
26 WRITE PROTECT ON - Attempt to write with closed write-protect notch
27 READ ERROR - Checksum error in header
28 WRITE ERROR - No sync mark found after written data block
29 DISK ID MISMATCH - Unformatted disk or bad header
30 SYNTAX ERROR - Invalid command parameters
31 SYNTAX ERROR - Unrecognized command
32 SYNTAX ERROR - Command/parameters longer than 58 characters
33 SYNTAX ERROR - Wildcards used in OPEN/SAVE command
34 SYNTAX ERROR - Missing filename in command string
39 SYNTAX ERROR - Unrecognized command. "Command file not found" ???
50 RECORD NOT PRESENT - Reading past the last record.
Positioning to a record beyond end of file in a relative file. If the
intent is to expand the file by adding the new record (with a PRINT#
command), the error message may be ignored. INPUT or GET should not be
attempted after this error is detected without first repositioning.
51 OVERFLOW IN RECORD - Writing exceeds record boundary.
52 FILE TOO LARGE - Record position in relative file exceeds disk space
60 WRITE FILE OPEN - Tried to open a file for read while open for write
61 FILE NOT OPEN - Tried to access a file that is not open
62 FILE NOT FOUND - The requested file does not exist
63 FILE EXISTS - The filename of the file being created already exists
64 FILE TYPE MISMATCH - File type does not match file type in directory
65 NO BLOCK - B-A command fail (TR,BL=next free block, 00,00=None)
66 ILLEGAL TRACK AND SECTOR - Illegal track or block number
67 ILLEGAL SYSTEM T OR S - Illegal system track or block
70 NO CHANNEL - Too many channels used, or requested channel not free
71 DIRECTORY ERROR - BAM messed up (on floppy disk, or in drive RAM)
72 DISK FULL - Disk or directory full. Close requires 2 free blocks
73 CBM DOS V2.6 1541 - Power-up message (note that 73 is also used below)
73 DOS MISMATCH - DOS2.X cannot &lt;write&gt; to old DOS1-formatted disks
74 DRIVE NOT READY - Disk missing
</TD></TR></TABLE>CHR(0-255) -- Binary data returned after MEMORY-READ command<BR>
<BR>
<B>Retrieving Error Messages in BASIC</B><BR>
Because the BASIC operating system doesn't explicitely support disk
drives, it will usually come up with a meaningless "FILE NOT FOUND"
message even if the error was actually caused by an unformatted disk.<BR>
A small program is required to receive more detailed error information:<BR>
<TABLE><TR><TD><PRE> 10 OPEN 1, 8, 15 ;open the error channel
20 INPUT# 1, A, B$, T, B ;read error_code, error_name, track, block
30 PRINT A, B$, T, B ;display it
RUN ;start (INPUT works only with line numbers)
</TD></TR></TABLE>The error_name parameter contains a text string (equivalent to error_code
information, but more convinient for human users). The other three
parameters always contain numbers and can be interpreted by software.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskdatachannelsfiletypes"></A><FONT SIZE=+2>&nbsp;Disk Data Channels & File Types</FONT></TD></TR></TABLE><BR>
The channel# is a data channel, number 2 through 14.<BR>
A maximum of five sequential files may be opened at one time to the DOS.
Direct access channels (what is a direct access channel???) may have six
opened files. (Does that mean 5 PLUS 6 data channels in total???)<BR>
<BR>
<B>Sequential Files</B><BR>
Sequential files consist of one or more data blocks, each block contains
254 bytes data, and a pointer to position of the next block. That format
makes it necessary to read through all previous blocks to find the
position of the last block.<BR>
Sequential files are accessed by opening a data channel, with the
following expression in the file_name field:<BR>
<TABLE><TR><TD><PRE> OPEN file_name_field: "[@]0:filename[,file_type,direction]"
</TD></TR></TABLE>The leading "@" optionally indicates to overwrite an existing file of same
name. The "0:" should always precede the filename or the drive will only
allow to use two buffers. The filename may contain wildcards (opening the
first matching file when reading). Sequential file types are:<BR>
<TABLE><TR><TD><PRE> PRG or P - Sequential Program (with BASIC tokens, used for LOAD/SAVE)
SEQ or S - Sequential Data File (typically containing ASCII text data)
USR or U - Sequential User File (unspecified content)
</TD></TR></TABLE>Direction may be READ or R for input, WRITE or W for output. Type and
direction may be left out when opening an existing file for reading.<BR>
Specifying "$" as filename opens the directory (read-only), reading
directory data comes out as BASIC program, filesizes encoded in the
linenumber fields.<BR>
<BR>
<B>Relative Files</B><BR>
The data blocks in relative files have exactly the same format as
sequential files, the filesystem additionally creates 'side sectors' which
contain a list of all data blocks used in the file, allowing it to find a
specific data block on disk without having to read all previous data
blocks.<BR>
When a Relative file is first to be used, the OPEN statement will create
that file; after that, the same file will be used. The replace option
(with the @ sign) does not erase and re-create the file. The file can be
expanded, read, and written into.<BR>
<TABLE><TR><TD><PRE> OPEN file_name_field: "filename,L,", record_length
</TD></TR></TABLE>Filetype (REL or L) and record size may be left out when opening an
existing file. Note that record_length is a binary value (not a text
string).<BR>
Relative files are split into records, the record size may be 1..254 bytes
and is defined when creating the file, there may be up to 65535 records in
each file, records may overlap from one data block into the next. However,
data may NOT overlap from one record into the next; in order to read or
write, you must, before any operation, use the POSITION command to move
the file pointer to the correct record position.<BR>
<TABLE><TR><TD><PRE> "P", channel+96, record_lsb, record_msb [,character_position]
</TD></TR></TABLE>The POSITION command changes the file pointer, but does NOT write anything
to, or read anything from the file. Moving the file pointer beyond the end
of the file produces a RECORD NOT PRESENT error, you should check for that
message (in order to remove it from the error channel), but you may ignore
it if you want to expand the file; writing to the data channel will expand
the filesize by appending new record(s) up to the specified record number.<BR>
<TABLE><TR><TD><PRE> character_position specifies the address (1..size) inside of the record.
If it is not specified, character_position defaults to 1.
HOW does that separate between ending chr(0dh) and character_pos ???
Include the character_position number, when adding fields. WHY ???
</TD></TR></TABLE><BR>
<B>Random Files</B><BR>
Random files consist of raw sectors, marked as allocated in the BAM.
Unlike real files, a random "file" does not include any filename or
directory entry. Accessing a random file requires two channels: the
command channel (15), and a data channel (2..14).<BR>
Caution: Because there is no directory entry, executing the VALIDATE
command will deallocate any blocks used by random files (assuming that
these blocks have been allocated by mistake).<BR>
<TABLE><TR><TD><PRE> OPEN file_name_field: "\[n]"
</TD></TR></TABLE>For the data channel "\" or "\n" should be specified as filename (either
using any buffer, or selecting a specific buffer eg. "\2"). Note: The
backslash, chr(5Ch), will appear as pound sign on the C64 keyboard and in
the C64 charset.<BR>
<TABLE><TR><TD><PRE> PRINT# cmd_file_number, "BLOCK-ALLOCATE:drive track block"
PRINT# cmd_file_number, "BLOCK-FREE: drive track block"
</TD></TR></TABLE>Use BLOCK-ALLOCATE to mark a specific track/sector as used in the BAM. The
allocation will fail if the block is already in use, the error channel does
then return "65,NO BLOCK,TR,BL". Whereas, &lt;TR,BL&gt; will indicate the next
higher unused sector, if any, or &lt;00,00&gt; if there's none. The BLOCK-FREE
command can be used to de-allocate a block.<BR>
<TABLE><TR><TD><PRE> PRINT# cmd_file_number, "BLOCK-READ: data_channel drive track block"
PRINT# cmd_file_number, "U1: data_channel drive track block"
</TD></TR></TABLE>The BLOCK-READ command reads up to 256 characters, but stops reading when
the buffer-pointer stored with the block says that block is finished. The
USER1 command (U1 or UA) performs the BLOCK-READ operation, but first
forces the pointer to 255 in order to read the entire block of data from
the disk.<BR>
<TABLE><TR><TD><PRE> PRINT# cmd_file_number, "BLOCK-WRITE: data_channel drive track block"
PRINT# cmd_file_number, "U2: data_channel drive track block"
</TD></TR></TABLE>The BLOCK-WRITE command writes the contents of the buffer to the block on
the disk along with the value of the buffer-pointer. The USER2 command (U2
or UB) writes the buffer without disturbing the buffer-pointer value
already stored on that block of the diskette. Note that you must fill or
modify the buffer through data channel &lt;before&gt; issuing BLOCK-WRITE or
USER2 through command channel.<BR>
<TABLE><TR><TD><PRE> PRINT# cmd_file_number, "BUFFER-POINTER:data_channel location"
</TD></TR></TABLE>The BUFFER-POINTER command moves the read/write pointer to the specified
address (0..255) in the buffer of the file, reading/writing to the data
channel does then access that address (and up).<BR>
<TABLE><TR><TD><PRE> !! When the data is being put into the buffer, a pointer in the DOS keeps
!! track of how many characters there are, when you perform the BLOCK-WRITE
!! operation, that pointer is recorded on the disk (WHAT WHERE HOW ???).
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskprogrammingthediskcontroller"></A><FONT SIZE=+2>&nbsp;Disk Programming the Disk Controller</FONT></TD></TR></TABLE><BR>
BLOCK-EXECUTE<BR>
This command will load a block from the diskette containing a machine<BR>
language routine, and begin executing it at location 0 in the buffer<BR>
until a RTS (ReTurn from Subroutine) command is encountered.<BR>
<TABLE><TR><TD><PRE> FORMAT FOR BLOCK-EXECUTE:
PRINT#file#, "B-E: data_channel drive track block"
</TD></TR></TABLE><BR>
MEMORY-READ<BR>
There is 16K of ROM in the disk drive as well as 2K of RAM. You can<BR>
get direct access to these, or to the buffers that the DOS has set up<BR>
in the RAM, by using the MEMORY commands. MEMORY-READ allows you to<BR>
select which byte to read, through the error channel.<BR>
<TABLE><TR><TD><PRE> MEMORY-READ:
PRINT#file#, "M-R",addr_lsb,addr_msb
</TD></TR></TABLE>The next byte read using the GET# statement through channel# 15, the<BR>
error channel, will be from that address in the disk controller's<BR>
memory, and successive bytes will be from successive memory locations.<BR>
Any INPUT# to the error channel will give peculiar results when you're<BR>
using this command. This can be cleared up by any other command to<BR>
the disk (aside from a memory command).<BR>
<BR>
MEMORY-WRITE<BR>
The MEMORY-WRITE command allows you to write up to 34 bytes at a time<BR>
into the disk controller's memory.<BR>
<TABLE><TR><TD><PRE> MEMORY-WRITE:
PRINT#file#, "M-W", addr_lsb, addr_msb, len, data[len]
</TD></TR></TABLE><BR>
MEMORY-EXECUTE and USER COMMANDS<BR>
Any routine in the DOS memory, RAM or ROM, can be executed with the<BR>
MEMORY-EXECUTE command.<BR>
<TABLE><TR><TD><PRE> "M-E", addr_lsb, addr_msb ;jump to addr Any address in RAM or ROM
"U3" or "UC" ;jump to 500h Buffer 2, Index 00h
"U4" or "UD" ;jump to 503h Buffer 2, Index 03h
"U5" or "UE" ;jump to 506h Buffer 2, Index 06h
"U6" or "UF" ;jump to 509h Buffer 2, Index 09h
"U7" or "UG" ;jump to 50Ch Buffer 2, Index 0Ch
"U8" or "UH" ;jump to 50Fh Buffer 2, Index 0Fh
"U;" or "UJ" ;jump to [FFFC] Power-up vector
</TD></TR></TABLE><BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskformat"></A><FONT SIZE=+2>&nbsp;Disk Format</FONT></TD></TR></TABLE><BR>
<B>Block Distribution by Track</B><BR>
The disks are having 35 tracks (1-35), track 1 is at the outer rim, track 35 is
at the center hub, track 18 contains the directory. The number of blocks per
track decreases towards inner tracks:<BR>
<TABLE><TR><TD><PRE> Track Numbers Block Numbers Total Size (Tracks * Blocks)
1..17 0..20 17*21=357
18..24 0..18 7*19=133
25..30 0..17 6*18=108
31..35 0..16 5*17=85
</TD></TR></TABLE>There's a total of 683 blocks (sectors) of 256 bytes on the disk.<BR>
However, all 19 blocks in Track 18 are used for the directory, so that
only 664 blocks are free for data. And, the first two bytes in each sector
are used by the filesytem, leaving only 254 bytes to the user.<BR>
Note: The DOS (disk operating system) fills up the diskette from the
center outward, ie. starting at track 35.<BR>
<BR>
<B>1540/1541 Block Availability Map (BAM) Format (Track 18, Sector 0)</B><BR>
<TABLE><TR><TD><PRE> Index Expl.
00,01 Track and sector of first directory block (18,01)
02 ASCII character "A" indicating 4040 format (41h)
03 Null flag for future DOS use. (00h)
04-8F Bit map of available blocks for tracks 1-35
</TD></TR></TABLE>Each bit represents one block, 1 = available block, 0 = block not available.<BR>
BAM contains space for 1120 blocks ??? Are blocks on track 18 included ???<BR>
Is that 4 bytes per track ???<BR>
<BR>
<B>1540/1541 Directory Header (Track 18, Sector 0)</B><BR>
<TABLE><TR><TD><PRE> Index Expl.
90-A1 144-161 Disk name 18 characters padded with shifted spaces
A2-A3 162-163 Disk ID two characters
A4 164 Shifted space (A0h)
A5-A6 165,166 DOS version "2" and format type "A" (32h,41h)
A6-A7 Shifted spaces (A0h,A0h)
AB-FF Nulls, not used (00h filled)
</TD></TR></TABLE>Index A6 used twice ??? Index A8-AA unspecified ???<BR>
Note: ASCII characters may appear in locations 180 thru 191 on some
diskettes.<BR>
<BR>
<B>Directory Format (Track 18, Sectors 1..18)</B><BR>
The directory consists of 144 file entries (stored in 18 sectors of 8 entries
each).<BR>
<TABLE><TR><TD><PRE> Index Expl.
00,01 Track and sector of next directory block
02-1F File entry 1
22-3F File entry 2
42-5F File entry 3
62-7F File entry 4
82-9F File entry 5
A2-BF File entry 6
C2-DF File entry 7
E2-FF File entry 8
</TD></TR></TABLE>Note that there are two unused bytes between each file entry.<BR>
<BR>
<B>Structure of single Directory Entry</B><BR>
<TABLE><TR><TD><PRE> Index Expl.
00 128+type
File type OR'ed with 80h to indicate properly closed file.
Types: 0=DELeted, 1=SEQuential, 2=PROGram, 3=USER, 4=RELative
01,02 Track and sector of 1st data block.
03-12 File name 16 characters padded with shifted spaces (=A0h).
??? Relative file only: track and sector for first side sector block.
??? Relative file only: Record size.
13-1B Unused (zero filled).
??? Track and sector of replacement file when OPEN@ is in effect.
1C-1D Number of blocks in file: low byte, high byte.
</TD></TR></TABLE><BR>
<B>Sequential Format</B><BR>
<TABLE><TR><TD><PRE> 00,01 Track and sector of next sequential data block.
02-FF 254 bytes of data with carriage returns as record terminators.
</TD></TR></TABLE><BR>
<B>Program File Format</B><BR>
<TABLE><TR><TD><PRE> 00,01 Track and sector of next block in program file.
02-FF 254 bytes of program info stored in CBM memory format (with key
words tokenized). End of file is marked by three zero bytes.
</TD></TR></TABLE><BR>
<B>Random File Format</B><BR>
<TABLE><TR><TD><PRE> 00-FF Data
</TD></TR></TABLE>Random files consist of blocks marked as used in the BAM, and the full 256
bytes of each block can be used for data. These "files" do not have a
filename or directory entry.<BR>
<BR>
<B>Relative File Format</B><BR>
Side Sector Block(s):<BR>
<TABLE><TR><TD><PRE> 00,01 Track and block of next side sector block.
02 Side sector number. (0-5)
03 Record length.
04-0F Track and block of side sector number 0-5.
10-FF Track and block pointers to 120 data blocks.
</TD></TR></TABLE>Data Block(s):<BR>
<TABLE><TR><TD><PRE> 00,01 Track and block of next data block.
02-FF 254 bytes of data.
</TD></TR></TABLE>Empty records contain FFh in the first byte followed by 00h to the end of
the record. Partially filled records are padded with nulls (00h).<BR>
A blank disk provides space for 664 data blocks (plus 6 side sectors), so
that the last some entries in the last side sector are typically not used.<BR>
<BR>
<B>1540/1541 Format: Expanded View of a Single Sector</B><BR>
Each sector consists of a header, followed by the actual data field, each with
separate leading SYNC signal, and ending GAP space.<BR>
<TABLE><TR><TD><PRE> Header: SYNC, 08, ID1, ID2, TRK, BLK, CHKSUM, GAP1
Data Field: SYNC, 07, DATA[256], CHKSUM, GAP
</TD></TR></TABLE>Note: The drive doesn't include a Index Hole LED, the first sector will be thus
positioned anywhere on the track.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskandfileimages"></A><FONT SIZE=+2>&nbsp;Disk and File Images</FONT></TD></TR></TABLE><BR>
.PRG .P00 .LNX .SDA .SFX .D64<BR>
<BR>
The following are common file formats used by C64 emulators.<BR>
The VIC20 uses the same extensions, same Basic Tokens, and same cassette and
disk formats.<BR>
<BR>
<B>Program Files (Extension .PRG)</B><BR>
Contains the original load address in first two bytes, followed by the actual
program or data (which is usually loaded to the computers MEMBOT+1 address,
NOT to the original address in the file).<BR>
<TABLE><TR><TD><PRE> - Original 16bit memory address (typically MEMBOT+1)
- BASIC line(s)
- Two zero bytes (End of BASIC program)
- Binary data (eg. machine code) (if any)
</TD></TR></TABLE>Each BASIC line:<BR>
<TABLE><TR><TD><PRE> - 16bit pointer to next line (in respect to original load address)
- 16bit line number
- BASIC expressions (consisting of tokens and ascii text)
- One zero byte (End of line)
</TD></TR></TABLE>Typical values for MEMBOT+1 are: 801h (C64), and 401h, 1001h, or 1201h
(VIC20; depending on amount of installed RAM).<BR>
<BR>
<B>Self-Extracting C64 files (.LNX .SDA .SFX)</B><BR>
These are just normal .PRG files with uncommon extensions. The extension
is meant to indicate that the file will self-extract itself after it has
been loaded into the C64 (or emulator). Respectively, you will need a
blank disk (or disk image) to store the extracted file(s).<BR>
<BR>
<B>"Encapsulated" C64 File Images (Typically with extension .P00)</B><BR>
C64 File Images contain the actual C64 file data, plus additional
information from the C64 disks directory, that info is parts of stored in
the images filename/extension, and parts of in a 26 bytes header. The
images filename and extension should be:<BR>
<TABLE><TR><TD><PRE> &lt;FILENAME&gt;.&lt;T&gt;&lt;NN&gt;
</TD></TR></TABLE>&lt;FILENAME&gt; may be up to 8 characters long, and may contain letters "A"-"Z"
and numbers "0"-"9" only, ideally this name would be composed of the the
first some characters of the original 16 char C64 filename - in practice
there's often little or no relationship, making it almost impossible to
find a C64-Image by C64-Filename.<BR>
&lt;T&gt; indicates the file type:<BR>
<TABLE><TR><TD><PRE> P - Program file (PRG)
S - Sequential file (SEQ)
U - User file (USR)
D - Deleted file (DEL)
R - Relative file (REL)
</TD></TR></TABLE>&lt;NN&gt; may be a number in range "00"-"99", allowing to use the same
&lt;FILENAME&gt; for different files. Note that the number "64" should be
avoided for 'deleted' files because the extension ".D64" is also used for
C64 disk images.<BR>
The first 26 bytes of the image contain the image header:<BR>
<TABLE><TR><TD><PRE> Index Size Expl.
00h 07h+1 Image ID "C64File", ended by 00h
08h 10h+1 Original 16 character C64 Filename, padded with 00h
19h 01h Record size for REL files (00h for other files)
1ah ... Original file image with load address (same as .PRG file)
</TD></TR></TABLE>Data blocks are 254 bytes each, excluding the track/block bytes stored on
C64 disks???<BR>
Relative files are assumed to be stored one data block after another, the
C64s "side sectors" are thus not required and are not included in the
file???<BR>
<BR>
<B>C64 Disk Images (Extension .D64)</B><BR>
Contains a raw disk image, including for the BAM and directory in the
middle of the disk/image, but without any image header or disk formatting
information. The filesize is 174848 bytes, for 683 blocks, of 256 bytes
each.<BR>
The images may contain so-called "random files", but the image format is
not suitable for copy protected disks - which may contain unformatted
tracks, may use reversed sector numbers, may use different number of bytes
per block, etc.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskmemorymapandioports"></A><FONT SIZE=+2>&nbsp;Disk Memory Map and I/O Ports</FONT></TD></TR></TABLE><BR>
<B>Memory Map</B><BR>
<TABLE><TR><TD><PRE> 0000-07FF Work RAM (2 KBytes)
0800-17FF Not used
1800-180F I/O - VIA#1 (serial data & control)
1810-1BFF Not used
1C00-1C0F I/O - VIA#2 (drive data & control)
1C10-BFFF Not used
C000-FFFF Disk ROM (16 KBytes)
</TD></TR></TABLE><BR>
<B>Work RAM</B><BR>
<TABLE><TR><TD><PRE> 0000-0103 System Area
0104-01FF Stack Area
0200-02FF System Area
0300-03FF Buffer 0
0400-04FF Buffer 1
0500-05FF Buffer 2
0600-06FF Buffer 3
0700-07FF Buffer 4
</TD></TR></TABLE><BR>
<B>1800h-180Fh - VIA 1: 6522, port for serial bus</B><BR>
<TABLE><TR><TD><PRE> PB 7, CB2: ATN IN
PB 6,5: Device address preset switches
PB 4: ATN acknowledge OUT
PB 3: CLOCK OUT
PB 2: CLOCK IN
PB 1: DATA OUT
PB 0: DATA IN
</TD></TR></TABLE><BR>
<B>1C00h-1C0Fh - VIA 2: 6522, port for motor and read/write head control</B><BR>
<TABLE><TR><TD><PRE> PA data to and from read/write head
PB 7: SYNC IN
PB 6,5: Bit rate D1 and D0
PB 4: WPS - Write Protect Sense (1 = On)
PB 3: ACT - LED on drive
PB 2: MTR - drive motor
PB 0,1: step motor for head movement
CA 1: Byte ready
CA 2: SOE - Set Overflow Enable for 6502
CA 3: (CA three?) read/write
</TD></TR></TABLE><BR>
<A HREF="#versatileinterfaceadapter6522via">Versatile Interface Adapter 6522 (VIA)</A><BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="diskconfiguration"></A><FONT SIZE=+2>&nbsp;Disk Configuration</FONT></TD></TR></TABLE><BR>
<B>Changing the Disk Drive Device Number</B><BR>
When turned on, the drive checks its jumper settings to determine its
device number (usually 8), and does then store the device number in RAM.
If you have two drives with the same device number, disconnect one drive,
enter the following expression to change the device number of the
connected drive from X to Y, eg. 8 to 9, and then re-connect the other
drive.<BR>
<TABLE><TR><TD><PRE> open 1,x,15:print#1,"m-w" chr$(119) chr$(0) chr$(2) chr$(y+32) chr$(y+64)
</TD></TR></TABLE>For a permanent change, cut the jumpers on the drives mainboard:<BR>
<TABLE><TR><TD><PRE> Device Jumper A/1 Jumper B/2
8 Don't cut Don't cut (default)
9 Cut Don't cut
10 Don't cut Cut
11 Cut Cut
</TD></TR></TABLE>Jumpers are labeled A,B in some drives, or 1,2 in others (btw. not J1,J2).<BR>
<BR>
<B>Changing the Drive Speed for VIC 20 or Commodore 64</B><BR>
The drive works with both VIC 20 and C64 computers. However, the
transmission rate from drive to computer is different. When the drive is
switched on it is set to C64 speed, but can be changed by UI or U9 command:<BR>
<TABLE><TR><TD><PRE> OPEN 1,8,15,"UI-":CLOSE 1 ;VIC 20 speed
OPEN 1,8,15,"UI+":CLOSE 1 ;Commodore 64 speed (default)
</TD></TR></TABLE>The actual speed(s) are unknown???<BR>
There is no jumper for permanent change???<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpu65xxmicroprocessor"></A><FONT SIZE=+2>&nbsp;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>&nbsp;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><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><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=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 &lt;through&gt; 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>&nbsp;CPU Memory Addressing</FONT></TD></TR></TABLE><BR>
<B>Opcode Addressing Modes</B><BR>
<TABLE><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&gt;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&gt;FFh if possible.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpumemoryandregistertransfers"></A><FONT SIZE=+2>&nbsp;CPU Memory and Register Transfers</FONT></TD></TR></TABLE><BR>
<B>Register to Register Transfer</B><BR>
<TABLE><TR><TD><PRE> A8 nz---- 2 TAY Transfer Accumulator to Y Y=A
AA nz---- 2 TAX Transfer Accumulator to X X=A
BA nz---- 2 TSX Transfer Stack pointer to X X=S
98 nz---- 2 TYA Transfer Y to Accumulator A=Y
8A nz---- 2 TXA Transfer X to Accumulator A=X
9A ------ 2 TXS Transfer X to Stack pointer S=X
</TD></TR></TABLE>Nocash syntax: MOV dest,source (eg. MOV Y,A = TAY).<BR>
<BR>
<B>Load Register from Memory</B><BR>
<TABLE><TR><TD><PRE> A9 nn nz---- 2 LDA #nn Load A with Immediate A=nn
A5 nn nz---- 3 LDA nn Load A with Zero Page A=[nn]
B5 nn nz---- 4 LDA nn,X Load A with Zero Page,X A=[nn+X]
AD nn nn nz---- 4 LDA nnnn Load A with Absolute A=[nnnn]
BD nn nn nz---- 4* LDA nnnn,X Load A with Absolute,X A=[nnnn+X]
B9 nn nn nz---- 4* LDA nnnn,Y Load A with Absolute,Y A=[nnnn+Y]
A1 nn nz---- 6 LDA (nn,X) Load A with (Indirect,X) A=[WORD[nn+X]]
B1 nn nz---- 5* LDA (nn),Y Load A with (Indirect),Y A=[WORD[nn]+Y]
A2 nn nz---- 2 LDX #nn Load X with Immediate X=nn
A6 nn nz---- 3 LDX nn Load X with Zero Page X=[nn]
B6 nn nz---- 4 LDX nn,Y Load X with Zero Page,Y X=[nn+Y]
AE nn nn nz---- 4 LDX nnnn Load X with Absolute X=[nnnn]
BE nn nn nz---- 4* LDX nnnn,Y Load X with Absolute,Y X=[nnnn+Y]
A0 nn nz---- 2 LDY #nn Load Y with Immediate Y=nn
A4 nn nz---- 3 LDY nn Load Y with Zero Page Y=[nn]
B4 nn nz---- 4 LDY nn,X Load Y with Zero Page,X Y=[nn+X]
AC nn nn nz---- 4 LDY nnnn Load Y with Absolute Y=[nnnn]
BC nn nn nz---- 4* LDY nnnn,X Load Y with Absolute,X Y=[nnnn+X]
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
Nocash syntax: MOV reg,op (MOV Y,12h; MOV X,[12h+Y]; MOV A,[[NN]+Y]; etc.)<BR>
<BR>
<B>Store Register in Memory</B><BR>
<TABLE><TR><TD><PRE> 85 nn ------ 3 STA nn Store A in Zero Page [nn]=A
95 nn ------ 4 STA nn,X Store A in Zero Page,X [nn+X]=A
8D nn nn ------ 4 STA nnnn Store A in Absolute [nnnn]=A
9D nn nn ------ 5 STA nnnn,X Store A in Absolute,X [nnnn+X]=A
99 nn nn ------ 5 STA nnnn,Y Store A in Absolute,Y [nnnn+Y]=A
81 nn ------ 6 STA (nn,X) Store A in (Indirect,X) [[nn+x]]=A
91 nn ------ 6 STA (nn),Y Store A in (Indirect),Y [[nn]+y]=A
86 nn ------ 3 STX nn Store X in Zero Page [nn]=X
96 nn ------ 4 STX nn,Y Store X in Zero Page,Y [nn+Y]=X
8E nn nn ------ 4 STX nnnn Store X in Absolute [nnnn]=X
84 nn ------ 3 STY nn Store Y in Zero Page [nn]=Y
94 nn ------ 4 STY nn,X Store Y in Zero Page,X [nn+X]=Y
8C nn nn ------ 4 STY nnnn Store Y in Absolute [nnnn]=Y
</TD></TR></TABLE>Nocash syntax: MOV op,reg (MOV [12h],A; MOV [12h+Y],X; MOV [[NN]+Y],A; etc.)<BR>
<BR>
<B>Push/Pull</B><BR>
<TABLE><TR><TD><PRE> 48 ------ 3 PHA Push accumulator on stack [S]=A
08 ------ 3 PHP Push processor status on stack [S]=P
68 nz---- 4 PLA Pull accumulator from stack A=[S]
28 nzcidv 4 PLP Pull processor status from stack P=[S]
</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>
Nocash syntax: PUSH A; PUSH P; POP A; POP P.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpuarithmeticlogicaloperations"></A><FONT SIZE=+2>&nbsp;CPU Arithmetic/Logical Operations</FONT></TD></TR></TABLE><BR>
<B>Add memory to accumulator with carry</B><BR>
<TABLE><TR><TD><PRE> 69 nn nzc--v 2 ADC #nn Add Immediate A=A+C+nn
65 nn nzc--v 3 ADC nn Add Zero Page A=A+C+[nn]
75 nn nzc--v 4 ADC nn,X Add Zero Page,X A=A+C+[nn+X]
6D nn nn nzc--v 4 ADC nnnn Add Absolute A=A+C+[nnnn]
7D nn nn nzc--v 4* ADC nnnn,X Add Absolute,X A=A+C+[nnnn+X]
79 nn nn nzc--v 4* ADC nnnn,Y Add Absolute,Y A=A+C+[nnnn+Y]
61 nn nzc--v 6 ADC (nn,X) Add (Indirect,X) A=A+C+[[nn+X]]
71 nn nzc--v 5* ADC (nn),Y Add (Indirect),Y A=A+C+[[nn]+Y]
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
Nocash syntax: ADC A,op (ADC A,12h; ADC A,[12h+X]; ADC A,[[NN]+Y]; etc.)<BR>
<BR>
<B>Subtract memory from accumulator with borrow</B><BR>
<TABLE><TR><TD><PRE> E9 nn nzc--v 2 SBC #nn Subtract Immediate A=A+C-1-nn
E5 nn nzc--v 3 SBC nn Subtract Zero Page A=A+C-1-[nn]
F5 nn nzc--v 4 SBC nn,X Subtract Zero Page,X A=A+C-1-[nn+X]
ED nn nn nzc--v 4 SBC nnnn Subtract Absolute A=A+C-1-[nnnn]
FD nn nn nzc--v 4* SBC nnnn,X Subtract Absolute,X A=A+C-1-[nnnn+X]
F9 nn nn nzc--v 4* SBC nnnn,Y Subtract Absolute,Y A=A+C-1-[nnnn+Y]
E1 nn nzc--v 6 SBC (nn,X) Subtract (Indirect,X) A=A+C-1-[[nn+X]]
F1 nn nzc--v 5* SBC (nn),Y Subtract (Indirect),Y A=A+C-1-[[nn]+Y]
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
Nocash syntax: SBC A,op (SBC A,12h; SBC A,[12h+X]; SBC A,[[NN]+Y]; etc.)<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><TR><TD><PRE> 29 nn nz---- 2 AND #nn AND Immediate A=A AND nn
25 nn nz---- 3 AND nn AND Zero Page A=A AND [nn]
35 nn nz---- 4 AND nn,X AND Zero Page,X A=A AND [nn+X]
2D nn nn nz---- 4 AND nnnn AND Absolute A=A AND [nnnn]
3D nn nn nz---- 4* AND nnnn,X AND Absolute,X A=A AND [nnnn+X]
39 nn nn nz---- 4* AND nnnn,Y AND Absolute,Y A=A AND [nnnn+Y]
21 nn nz---- 6 AND (nn,X) AND (Indirect,X) A=A AND [[nn+X]]
31 nn nz---- 5* AND (nn),Y AND (Indirect),Y A=A AND [[nn]+Y]
</TD></TR></TABLE>Nocash syntax: AND A,op (AND A,12h; AND A,[12h+X]; AND A,[[NN]+Y]; etc.)<BR>
* Add one cycle if indexing crosses a page boundary.<BR>
<BR>
<B>Exclusive-OR memory with accumulator</B><BR>
<TABLE><TR><TD><PRE> 49 nn nz---- 2 EOR #nn XOR Immediate A=A XOR nn
45 nn nz---- 3 EOR nn XOR Zero Page A=A XOR [nn]
55 nn nz---- 4 EOR nn,X XOR Zero Page,X A=A XOR [nn+X]
4D nn nn nz---- 4 EOR nnnn XOR Absolute A=A XOR [nnnn]
5D nn nn nz---- 4* EOR nnnn,X XOR Absolute,X A=A XOR [nnnn+X]
59 nn nn nz---- 4* EOR nnnn,Y XOR Absolute,Y A=A XOR [nnnn+Y]
41 nn nz---- 6 EOR (nn,X) XOR (Indirect,X) A=A XOR [[nn+X]]
51 nn nz---- 5* EOR (nn),Y XOR (Indirect),Y A=A XOR [[nn]+Y]
</TD></TR></TABLE>Nocash syntax: XOR A,op (XOR A,12h; XOR A,[12h+X]; XOR A,[[NN]+Y]; etc.)<BR>
* Add one cycle if indexing crosses a page boundary.<BR>
<BR>
<B>Logical OR memory with accumulator</B><BR>
<TABLE><TR><TD><PRE> 09 nn nz---- 2 ORA #nn OR Immediate A=A OR nn
05 nn nz---- 3 ORA nn OR Zero Page A=A OR [nn]
15 nn nz---- 4 ORA nn,X OR Zero Page,X A=A OR [nn+X]
0D nn nn nz---- 4 ORA nnnn OR Absolute A=A OR [nnnn]
1D nn nn nz---- 4* ORA nnnn,X OR Absolute,X A=A OR [nnnn+X]
19 nn nn nz---- 4* ORA nnnn,Y OR Absolute,Y A=A OR [nnnn+Y]
01 nn nz---- 6 ORA (nn,X) OR (Indirect,X) A=A OR [[nn+X]]
11 nn nz---- 5* ORA (nn),Y OR (Indirect),Y A=A OR [[nn]+Y]
</TD></TR></TABLE>Nocash syntax: OR A,op (OR A,12h; OR A,[12h+X]; OR A,[[NN]+Y]; etc.)<BR>
* Add one cycle if indexing crosses a page boundary.<BR>
<BR>
<B>Compare</B><BR>
<TABLE><TR><TD><PRE> C9 nn nzc--- 2 CMP #nn Compare A with Immediate A-nn
C5 nn nzc--- 3 CMP nn Compare A with Zero Page A-[nn]
D5 nn nzc--- 4 CMP nn,X Compare A with Zero Page,X A-[nn+X]
CD nn nn nzc--- 4 CMP nnnn Compare A with Absolute A-[nnnn]
DD nn nn nzc--- 4* CMP nnnn,X Compare A with Absolute,X A-[nnnn+X]
D9 nn nn nzc--- 4* CMP nnnn,Y Compare A with Absolute,Y A-[nnnn+Y]
C1 nn nzc--- 6 CMP (nn,X) Compare A with (Indirect,X) A-[[nn+X]]
D1 nn nzc--- 5* CMP (nn),Y Compare A with (Indirect),Y A-[[nn]+Y]
E0 nn nzc--- 2 CPX #nn Compare X with Immediate X-nn
E4 nn nzc--- 3 CPX nn Compare X with Zero Page X-[nn]
EC nn nn nzc--- 4 CPX nnnn Compare X with Absolute X-[nnnn]
C0 nn nzc--- 2 CPY #nn Compare Y with Immediate Y-nn
C4 nn nzc--- 3 CPY nn Compare Y with Zero Page Y-[nn]
CC nn nn nzc--- 4 CPY nnnn Compare Y with Absolute Y-[nnnn]
</TD></TR></TABLE>* Add one cycle if indexing crosses a page boundary.<BR>
Nocash syntax: CMP reg,op (CMP X,12h; CMP A,[12h+X]; CMP A,[[NN]+Y]; etc.)<BR>
Note: Compared with normal 80x86 and Z80 CPUs, resulting Carry Flag is
reversed.<BR>
<BR>
<B>Bit Test</B><BR>
<TABLE><TR><TD><PRE> 24 nn xz---x 3 BIT nn Bit Test A AND [nn], N=[nn].7, V=[nn].6
2C nn nn xz---x 4 BIT nnnn Bit Test A AND [..], N=[..].7, V=[..].6
</TD></TR></TABLE>Nocash syntax: TEST A,op (TEST A,[12h]; TEST A,[1234h]; etc.)<BR>
<BR>
<B>Increment by one</B><BR>
<TABLE><TR><TD><PRE> E6 nn nz---- 5 INC nn Increment Zero Page [nn]=[nn]+1
F6 nn nz---- 6 INC nn,X Increment Zero Page,X [nn+X]=[nn+X]+1
EE nn nn nz---- 6 INC nnnn Increment Absolute [nnnn]=[nnnn]+1
FE nn nn nz---- 7 INC nnnn,X Increment Absolute,X [nnnn+X]=[nnnn+X]+1
E8 nz---- 2 INX Increment X X=X+1
C8 nz---- 2 INY Increment Y Y=Y+1
</TD></TR></TABLE>Nocash syntax: INC op/reg (INC [12h]; INC [1234h+X]; INC Y; etc.)<BR>
<BR>
<B>Decrement by one</B><BR>
<TABLE><TR><TD><PRE> C6 nn nz---- 5 DEC nn Decrement Zero Page [nn]=[nn]-1
D6 nn nz---- 6 DEC nn,X Decrement Zero Page,X [nn+X]=[nn+X]-1
CE nn nn nz---- 6 DEC nnnn Decrement Absolute [nnnn]=[nnnn]-1
DE nn nn nz---- 7 DEC nnnn,X Decrement Absolute,X [nnnn+X]=[nnnn+X]-1
CA nz---- 2 DEX Decrement X X=X-1
88 nz---- 2 DEY Decrement Y Y=Y-1
</TD></TR></TABLE>Nocash syntax: DEC op/reg (DEC [12h]; DEC [1234h+X]; DEC Y; etc.)<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="cpurotateandshiftinstructions"></A><FONT SIZE=+2>&nbsp;CPU Rotate and Shift Instructions</FONT></TD></TR></TABLE><BR>
<B>Shift Left</B><BR>
<TABLE><TR><TD><PRE> 0A nzc--- 2 ASL A Shift Left Accumulator SHL A
06 nn nzc--- 5 ASL nn Shift Left Zero Page SHL [nn]
16 nn nzc--- 6 ASL nn,X Shift Left Zero Page,X SHL [nn+X]
0E nn nn nzc--- 6 ASL nnnn Shift Left Absolute SHL [nnnn]
1E nn nn nzc--- 7 ASL nnnn,X Shift Left Absolute,X SHL [nnnn+X]
</TD></TR></TABLE>Nocash syntax: SHL op/reg (SHL A; SHL [12h]; SHL [1234h+X]; etc.)<BR>
<BR>
<B>Shift Right</B><BR>
<TABLE><TR><TD><PRE> 4A 0zc--- 2 LSR A Shift Right Accumulator SHR A
46 nn 0zc--- 5 LSR nn Shift Right Zero Page SHR [nn]
56 nn 0zc--- 6 LSR nn,X Shift Right Zero Page,X SHR [nn+X]
4E nn nn 0zc--- 6 LSR nnnn Shift Right Absolute SHR [nnnn]
5E nn nn 0zc--- 7 LSR nnnn,X Shift Right Absolute,X SHR [nnnn+X]
</TD></TR></TABLE>Nocash syntax: SHR op/reg (SHR A; SHR [12h]; SHR [1234h+X]; etc.)<BR>
<BR>
<B>Rotate Left through Carry</B><BR>
<TABLE><TR><TD><PRE> 2A nzc--- 2 ROL A Rotate Left Accumulator RCL A
26 nn nzc--- 5 ROL nn Rotate Left Zero Page RCL [nn]
36 nn nzc--- 6 ROL nn,X Rotate Left Zero Page,X RCL [nn+X]
2E nn nn nzc--- 6 ROL nnnn Rotate Left Absolute RCL [nnnn]
3E nn nn nzc--- 7 ROL nnnn,X Rotate Left Absolute,X RCL [nnnn+X]
</TD></TR></TABLE>Nocash syntax: RCL op/reg (RCL A; RCL [12h]; RCL [1234h+X]; etc.)<BR>
<BR>
<B>Rotate Right through Carry</B><BR>
<TABLE><TR><TD><PRE> 6A nzc--- 2 ROR A Rotate Right Accumulator RCR A
66 nn nzc--- 5 ROR nn Rotate Right Zero Page RCR [nn]
76 nn nzc--- 6 ROR nn,X Rotate Right Zero Page,X RCR [nn+X]
6E nn nn nzc--- 6 ROR nnnn Rotate Right Absolute RCR [nnnn]
7E nn nn nzc--- 7 ROR nnnn,X Rotate Right Absolute,X RCR [nnnn+X]
</TD></TR></TABLE>Nocash syntax: RCR op/reg (RCR A; RCR [12h]; RCR [1234h+X]; etc.)<BR>
<BR>
Notes:<BR>
ROR instruction is available on MCS650X microprocessors after June, 1976.<BR>
ROL and ROL 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>&nbsp;CPU Jump and Control Instructions</FONT></TD></TR></TABLE><BR>
<B>Normal Jumps</B><BR>
<TABLE><TR><TD><PRE> 4C nn nn ------ 3 JMP nnnn Jump Absolute PC=nnnn
6C nn nn ------ 5 JMP (nnnn) Jump Indirect PC=WORD[nnnn]
20 nn nn ------ 6 JSR nnnn Jump and Save Return Addr. [S]=PC+2,PC=nnnn
40 nzcidv 6 RTI Return from BRK/IRQ/NMI P=[S], PC=[S]
60 ------ 6 RTS Return from Subroutine PC=[S]+1
</TD></TR></TABLE>Nocash syntax: JMP nnnn; JMP [nnnn]; CALL nnnn (=JSR); RETI; RET (=RTS).<BR>
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 (Branch on condition, to PC=PC+/-nn)</B><BR>
<TABLE><TR><TD><PRE> 10 dd ------ 2** BPL/JNS disp ;N=0 (plus/positive)
30 dd ------ 2** BMI/JS disp ;N=1 (minus/negative/signed)
50 dd ------ 2** BVC/JNO disp ;V=0 (no overflow)
70 dd ------ 2** BVS/JO disp ;V=1 (overflow)
90 dd ------ 2** BCC/BLT/JNC/JB disp ;C=0 (less/below/no carry)
B0 dd ------ 2** BCS/BGE/JC/JAE disp ;C=1 (above/greater/equal/carry)
D0 dd ------ 2** BNE/BZC/JNZ/JNE disp ;Z=0 (not zero/not equal)
F0 dd ------ 2** BEQ/BZS/JZ/JE disp ;Z=1 (zero/equal)
</TD></TR></TABLE>Nocash syntax: Jxx nnnn; Native syntax: Bxx nnnn.<BR>
** 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><TR><TD><PRE> 00 ---1-- 7 BRK Force Break B=1 [S]=PC+1,[S]=P,I=1,PC=[FFFE]
-- ---1-- ?? /IRQ Interrupt B=0 [S]=PC,[S]=P,I=1,PC=[FFFE]
-- ---1-- ?? /NMI NMI B=0 [S]=PC,[S]=P,I=1,PC=[FFFA]
-- ---1-- T+6 /RESET Reset PC=[FFFC],I=1
</TD></TR></TABLE>Notes: IRQs can be disabled by setting the I-flag, a BRK command, a NMI,
and a /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><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><TR><TD><PRE> 18 --0--- 2 CLC Clear carry flag C=0
58 ---0-- 2 CLI Clear interrupt disable bit I=0
D8 ----0- 2 CLD Clear decimal mode D=0
B8 -----0 2 CLV Clear overflow flag V=0
38 --1--- 2 SEC Set carry flag C=1
78 ---1-- 2 SEI Set interrupt disable bit I=1
F8 ----1- 2 SED Set decimal mode D=1
</TD></TR></TABLE>Nocash Syntax: CLC; EI (=CLI); CLD, CLV; STC; DI (=STI); STD.<BR>
<BR>
<B>No Operation</B><BR>
<TABLE><TR><TD><PRE> EA ------ 2 NOP No operation 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>&nbsp;CPU Illegal Opcodes</FONT></TD></TR></TABLE><BR>
<B>SAX and LAX</B><BR>
<TABLE><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><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><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><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><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, 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><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><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>&nbsp;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><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"
#&lt;nnnn nnnn AND 0FFh isolate lower 8bits of 16bit value
#&gt;nnnn nnnn DIV 100h isolate upper 8bits of 16bit value
</TD></TR></TABLE><BR>
<B>Special Directives</B><BR>
<TABLE><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&lt;entry&gt;" with default ORG 80Eh.<BR>
<BR>
<B>VIC20 Stub</B><BR>
The VIC20 Stub is "10 SYSPEEK(44)*256+&lt;entry&gt;" 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>&nbsp;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
accociated 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 accociated 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>&nbsp;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><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><TR><TD><PRE> 65C02 Extension of the 6502, used in the C16, C116 and the Plus/4 computers?
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>&nbsp;CPU Local Usage</FONT></TD></TR></TABLE><BR>
<B>C64</B><BR>
6510A 8bit CPU, 1.02 MHz (NTSC) or 0.98 MHz (PAL), compatible with 6502, with
built-in I/O Ports at addresses 0000h and 0001h.<BR>
Video DMA to Character Memory takes place without waitstates, however, DMA to
Matrix memory (in each 8th scanline), and DMA to Sprite memory (if any)
stalls the CPU. For more info see<BR>
<A HREF="#c64vicdimensionsandtimings">C64 VIC Dimensions and Timings</A><BR>
<BR>
<B>VIC20</B><BR>
CPU: 6502A, 1.02 MHz (NTSC), 1.11 MHz (PAL).<BR>
Because of the low resolution/dot clock, all Video DMA takes place in Phase
1, without any CPU waitstates.<BR>
<BR>
<B>C16/Plus4</B><BR>
CPU: 7501/8501, single-speed clock 0.894886 MHz (NTSC), 0.886724 MHz (PAL).<BR>
6502 compatible with on-chip 7bit I/O Port, with double-speed mode, without
NMI input.<BR>
In single-speed mode, the CPU is clocked in Phase 2 only, most video DMA and
DRAM refresh take place without waitstates during Phase 1. However, 80 bytes
screen/color data must be fetched for each character row, which is probably
done in phase 2 (unless it is squeezed into hblank periods of previous
lines?).<BR>
In twice-speed mode, CPU is clocked in both phases, theoretically running at
more than than 1.7MHz, because of the Phase 1 Video DMA the full speed is
achieved only in Hblank & Vblank periods, minus whatever (?) cycles spent on
DRAM refresh.<BR>
<BR>
<B>Disk Drive</B><BR>
Uses the 6502, too. Clock frequency is unknown.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="z80microprocessorcartridge"></A><FONT SIZE=+2>&nbsp;Z80 Microprocessor Cartridge</FONT></TD></TR></TABLE><BR>
<B>Z80 Cartridge</B><BR>
Optionally, the C64 can be upgraded by an external Z80 CPU cartridge,
the clock frequency of this CPU is unknown???. Even when the Z80
cartridge is connected, the C64 still operates in 6510 mode as usually,
but programs may now freely switch back and forth between 6510 and Z80
modes, however, as both CPUs need to access the data/addressbus, both
cannot be operated simultaneously.<BR>
Both 6510 and Z80 are accessing the same RAM (and ROM, and I/O ???)
being built-in into the C64, as each CPU expects special data at address
0000h, all memory has been 'shifted' by 1000h bytes. The Z80 addresses
0000h-EFFFh refer to 1000h-FFFFh of normal C64 memory, and Z80
F000h-FFFFh wraps to 0000h-0FFFh of C64 memory.<BR>
<BR>
<B>CPU Mode Switching</B><BR>
The example code below illustrates switching to Z80 mode, executing a
simple 'program' in Z80 mode, and switching back to 6510 mode. First,
write the following opcodes into memory at C64-addresses 1000h and up,
ie. Z80 addresses 0000h and up.<BR>
<TABLE><TR><TD><PRE> C64 Z80 Opcode Disassembled Comment
1000 0000 00 nop ;\the Commodore Z80 needs three NOPs
1001 0001 00 nop ; to stabilize after mode switching
1002 0002 00 nop ;/
1003 0003 21 02 F5 ld hl,0F502h ;\the actual Z80 'program' increment
1006 0006 34 inc (hl) ;/a byte in VRAM (C64 address=0502h)
1007 0007 3E 01 ld a,01h ;\turn off Z80 again by I/O port
1009 0009 32 00 CE ld (0CE00h),a ;/(C64 address=DE00h)
100C 000C 00 nop ;\
100D 000D 00 nop ; again three NOPs to 'destabilize'
100E 000E 00 nop ;/
100F 000F C3 jp 0000h ;-Huh? Should never execute this...
</TD></TR></TABLE>Now execute the following BASIC program from inside of C64 mode:<BR>
<TABLE><TR><TD><PRE> 10 poke 56333,127 :rem [DC0Dh]=7Fh, turn off 6510 irq's
20 poke 56832,00 :rem [DE00h]=00h, turn on z80 card & execute Z80 code
30 poke 56333,129 :rem [DC0Dh]=81h, turn on 6510 irq's when z80 done
</TD></TR></TABLE>Interrupts should be disabled during mode switching, but might be
enabled while operating in Z80 mode, provided that Z80 /IRQ and /NMI
lines are connected ???<BR>
When switching to Z80 mode, the Z80-CPU is apparently reset (and starts
at Z80-address 0000h, of course RAM is not reset, so the Z80 may
re-initialize itself from code and data stored in RAM).<BR>
When switching to 6510 mode, the 6510 CPU is NOT reset, and just
continues where it had stopped before switching to Z80 mode ???<BR>
<BR>
<B>Commodore CP/M</B><BR>
The Z80 cartridge is mainly intended for use with CP/M software, thus
sometimes referred to as CP/M cartridge, even though it contains a raw
CPU without any BIOS or operating system ROM.<BR>
The cartridge should be usually delivered together with a Commodore CP/M
disk. To start CP/M, turn on the computer, and load and start CP/M (all
still from inside of normal C64 mode). The C64 provides 52K contiguous
bytes of RAM for use in CP/M mode (of which 4K are used by the CP/M
operating system, and 48K are free for CP/M software???).<BR>
Note: CP/M is a text based disk operating system (with similar appearance as
MS DOS) which is used on many different Z80 computers.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="externalconnectors"></A><FONT SIZE=+2>&nbsp;External Connectors</FONT></TD></TR></TABLE><BR>
<B>Joystick Ports - 2x SUB-D 9pin Male</B><BR>
The C64 has two "Control Ports", a digitial joystick or paddle can be
connected to each Port 1 and Port 2. Also, a lightpen can be connected to
Port 1.<BR>
<TABLE><TR><TD><PRE> Pin Name Expl.
1 Switch 0 Joystick Up
2 Switch 1 Joystick Down
3 Switch 2 Joystick Left, or Paddle X-Button
4 Switch 3 Joystick Right, or Paddle Y-Button
5 POTY Paddle Y-Axis
6 Switch 4 Joystick Fire, or Lightpen (Port 1 only)
7 +5V Power Supply (max 50mA)
8 GND Ground
9 POTX Paddle X-Axis
</TD></TR></TABLE>Pin 1-5 in upper row, Pin 6-9 in lower row, from left to right each.<BR>
Note that Port 1 is CIA Port B, and Port 2 is CIA Port A (!).
Respectively, it is everyones bet which port is to be treated as
the "first" port, many games expect the joystick to be connected to
Port 2 (CIA Port A), other games expect it at Port 1 (CIA Port
B), and some of the better games work with either port.<BR>
See also:<BR>
<A HREF="#joystickycable">Joystick Y-Cable</A><BR>
<BR>
<B>Cartridge Expansion Slot - 44 Pins Female</B><BR>
<TABLE><TR><TD><PRE> Pin Expl. Pin Expl. Pin Expl. Pin Expl.
1 GND 12 BA A GND N A9
2 +5V 13 /DMA B /ROMH P A8
3 +5V 14 D7 C /RESET R A7
4 /IRQ 15 D6 D /NMI S A6
5 R/W 16 D5 E 02 T A5
6 Dot Clock 17 D4 F A15 U A4
7 I/O1 18 D3 H A14 V A3
8 /GAME 19 D2 J A13 W A2
9 /EXROM 20 D1 K A12 X A1
10 I/O2 21 D0 L A11 Y A0
11 /ROML 22 GND M A10 Z GND
</TD></TR></TABLE>Pin 1-22 in upper row, A-F,H,J-N,P,R-Z in lower row, from right to left each!<BR>
<BR>
<B>TV Output - Cinch Female</B><BR>
Outputs TV Signals (video and sound), channel switch may select between
two channels ???<BR>
<BR>
<B>Audio/Video (6 or 8 Pin, DIN, Female)</B><BR>
<TABLE><TR><TD><PRE> Pin Expl. ++ ++
1 Luminance / +-+ \
2 GND + 8 7 +
3 Audio Out | 3 6 1 |
4 Video Out + 5 4 +
5 Audio In \ 2 /
6 Chrominance +---+
(7) N.C.
(8) +5V DC
</TD></TR></TABLE><BR>
<B>Serial I/O (6 Pin, DIN, Female)</B><BR>
<TABLE><TR><TD><PRE> Pin Expl. ++ ++
1 Serial /SRQ In / +-+ \
2 GND + 5 1 +
3 Serial ATN Out | 6 |
4 Serial CLK In/Out + 4 2 +
5 Serial Data In/Out \ 3 /
6 /RESET +---+
</TD></TR></TABLE>A printer, up to five disk drives, and other hardware can be
(simultaneously) connected to the Serial I/O Port. Each peripheral should
include two identical serial sockets, either one connected to the C64 (or
previous device), the other one connected to the next device (if any).<BR>
<BR>
<B>Cassette - 12 Pins Male (actually 6 pins duplicated)</B><BR>
<TABLE><TR><TD><PRE> Pin Expl.
A-1 GND
B-2 +5V DC
C-3 Cassette Motor (WHAT=On ???) (+9V UNREG DC ?)
D-4 Cassette Read
E-5 Cassette Write
F-6 Cassette Sense (Switch PLAY Pressed ???, WHAT=Yes ???)
</TD></TR></TABLE>Pin 1-6 in upper row, Pin A-F in lower row, from left to right each.<BR>
<BR>
<B>User I/O (User Port) - 24 Pins Male</B><BR>
<TABLE><TR><TD><PRE> Pin Expl. Pin Expl.
1 GND A GND
2 +5V DC (max 100 mA) B /FLAG2
3 /RESET C PB0
4 CNT1 D PB1
5 SP1 E PB2
6 CNT2 F PB3
7 SP2 H PB4
8 /PC2 J PB5
9 SER. ATN OUT K PB6
10 9V AC1 (max 100 mA) L PB7
11 9V AC2 (max 100 mA) M PA2
12 GND N GND
</TD></TR></TABLE>Pin 1-12 in upper row, A-F,H,J-N in lower row, from left to right each.<BR>
<BR>
<B>Power Supply (7 Pin, DIN, Female)</B><BR>
<TABLE><TR><TD><PRE> Pin Expl. ++ ++
1 GND / +-+ \
2 GND (or N.C.) + 7 6 +
3 GND | 3 1 |
4 +5V DC + 5 4 +
5 +5V DC \ 2 /
6 +/-9V AC1 +---+
7 +/-9V AC2
</TD></TR></TABLE>Most of the computer circuit is operated at +5V DC. The 9V AC voltage is
internally converted into +9V UNREG (for cassette motor), and into +9V
or +12V DC (for sound chip, voltage depends on type of chip used). Also,
9V AC are output to the user port. And, the 9V AC1 frequency (typically
50Hz or 60Hz, depending on wall socket) is used to feed to time of day
clock.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="transmitfunction"></A><FONT SIZE=+2>&nbsp;Transmit Function</FONT></TD></TR></TABLE><BR>
The Xmit function allows to upload a .PRG or .P00 file from no$c64
(utility menu) to real C64. The required circuit consists of a
parallel/printer cable connected to the user port signals, and a boot
EPROM connected to the C64 expansion port signals. The feature has been
very useful and comfortable when making and testing no$c64, and might be
of some use for other programmers, at least if owning an eprom burner.<BR>
<BR>
<B>Features / Performance / Requirements</B><BR>
All transfer takes place automatically, there's no need to reset the C64
manually, nor to type LOAD or RUN. Transmission time should be max 3
seconds (for big 50K files). The circuit works with any parallel/printer
port (both older one-directional, and newer bi-directonal ports).
Transmission should work stable regardless of the PCs CPU speed, and even
with multitasking operating systems. Windows NT and worse reportedly
prevent to access the parallel port unless when installing a special
driver to unlock the port (eg. Giveio, Totalio, Userport).<BR>
<BR>
<B>Transmit Circuit</B><BR>
The schematic shows the connection and pin numbers for the User port,
Expansion Port, Eprom, and Printer port (USR, EXP, ROM, PRN). The circuit
can be connected externally (to user/expansion port). Or inside of the C64
(circuit soldered directly to the mainboard, with Centronics socket
installed in computers case, the EPROM socket can be 'stacked' on top of
the BIOS ROM with 1:1 connection for most pins). The external solution
would require a lot of messy/special cables, the internal solution works
with a standard printer cable.<BR>
<TABLE><TR><TD><PRE> Name Pin Pin Name
PA2 USR.M ----------------- PRN.1 /STROBE
PB0-7 USR.C-L ----------------- PRN.2-9 DATA0-7
FLAG USR.B ----------------- PRN.11 BUSY
GND USR.A,N ----------------- PRN.19-24 GND
GND USR.A,N ----------------- PRN.14 /AUTOLF
/INTRES EXP.C ----------------- PRN.16/31 /INIT
/EXROM EXP.9 ---|&gt;|---+---+--- PRN.17/36 /SELECT
+5VDC EXP.2 --[3K3]--' '--- ROM.20 /CS
/ROML EXP.11 ----------------- ROM.22 /OE
GND EXP.1 ----------------- ROM.14 GND
+5VDC EXP.2 ----------------- ROM.1,26-28 A13-15,VCC
D0-7 EXP.21-14 ----------------- ROM.11-13,15-19 D0-7
A0-12 EXP.Y-K ----------------- ROM.10-3,25,24,21,23,2 A0-12
</TD></TR></TABLE>The diode (1N4148) and resistor (3.3KOhm) used for compatibility with
other expansion cartridges only, you can leave out the diode & resistor,
and connect /EXROM directly to /SELECT. The grounded /AUTOLF signal used
for compatibility with "geocab" parallel printer port adapter only. Use
PRN pins 16,17 for DSUB 25pins plug or pins 31,36 for Centronics 36pins
plug.<BR>
<BR>
<B>Boot EPROM</B><BR>
Here's the hex-dump, type up the bytes, or copy/paste in windows version,
and use whatever preferred method to get the hex values into binary
format.<BR>
<TABLE><TR><TD><PRE> 1E 81 00 00 C3 C2 CD 38 30 A9 1B 8D 11 D0 A9 08
8D 16 D0 A9 04 09 10 8D 18 D0 A9 03 8D 00 DD A9
00 8D 15 D0 A9 00 A9 02 8D 20 D0 8D 21 D0 A9 01
A2 00 9D 00 D8 9D 00 D9 9D 00 DA 9D 00 DB E8 D0
F1 A9 20 A2 00 9D 00 04 9D 00 05 9D 00 06 9D 00
07 E8 D0 F1 A9 00 85 0C 85 0D 60 48 C9 0D D0 07
A9 00 85 0C 4C 95 80 C9 0A D0 05 E6 0D 4C 95 80
A9 00 85 0B A5 0D 0A 0A 65 0D 0A 0A 26 0B 0A 26
0B 65 0C 85 0A A9 04 65 0B 85 0B 68 48 29 3F A2
00 81 0A E6 0C 68 60 68 85 08 68 85 09 E6 08 D0
02 E6 09 A2 00 A1 08 E6 08 D0 02 E6 09 C9 00 F0
06 20 5B 80 4C A3 80 6C 08 00 A9 3B 8D 02 DD A9
00 8D 03 DD 60 A9 04 2C 00 DD D0 FB AE 01 DD 2C
00 DD F0 FB 8A 60 A0 00 A9 04 2C 00 DD D0 FB AD
01 DD 91 02 C8 A9 04 2C 00 DD F0 FB AD 01 DD 91
02 C8 D0 E4 E6 03 60 A9 00 A8 99 02 00 99 00 02
99 00 03 C8 D0 F4 A9 3C 85 B2 A9 03 85 B3 A9 A0
8D 84 02 A9 08 8D 82 02 A9 04 8D 88 02 60 A9 E7
85 01 A9 2F 85 00 A2 00 8E 16 D0 20 A3 FD 20 F7
80 20 15 FD 20 5B FF 58 4C 3B 81 20 53 E4 20 BF
E3 20 22 E4 A2 FB 9A D0 00 A2 80 4C 4E 81 8A 20
87 81 86 2D 84 2E A9 76 A0 A3 20 1E AB 20 59 A6
20 33 A5 A9 04 85 C6 A2 09 BD 7D 81 9D 77 02 CA
10 F7 A9 A4 48 A9 7F 48 A9 04 4C 7B 02 52 55 4E
0D 2C 00 DD F0 FB 60 08 78 20 BA 80 A9 05 8D 20
D0 20 C5 80 85 02 20 C5 80 85 03 20 C5 80 85 04
20 C5 80 85 05 20 C5 80 85 06 20 C5 80 85 07 A9
00 8D 20 D0 20 D6 80 C6 05 D0 F9 A9 04 2C 00 DD
D0 FB A9 0F 8D 20 D0 A6 02 A4 03 28 60
</TD></TR></TABLE>Keep in mind to specify the correct target address when burning the EPROM,
eg. when using a 27C512 chip (64KBytes) with A13-15 connected HIGH, use
E000h as target address.<BR>
<BR>
<B>Notes</B><BR>
The circuit currently provides one-way communication from PC to C64 only,
no$c64 sends data blindly without receiving checksum or status
information, it'll be thus always report "Okay" even if the C64 is
disconnected or switched off.<BR>
The C64 can be kept used as normal with disk and cassette programs,
provided that the /SELECT and /INIT signals are HIGH (default setting
after transmission, however, the PCs BIOS/OS may mess around with that
signals when (re-)booting the computer, simply disconnect the parallel
cable in case of problems).<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="joystickycable"></A><FONT SIZE=+2>&nbsp;Joystick Y-Cable</FONT></TD></TR></TABLE><BR>
Because of unclear programming specs, many C64 games are working only with
joystick port 1, or only with joystick port 2, making it necessary to
re-connect the joystick to appropriate port about each time when loading a
new game.<BR>
Unlike normal Y-cables (which split one port into two ports), the nocash
C64 Y-cable turns it the other way around and forcefully solves the
problem by merging both ports into a single port.<BR>
The circuit consists of some wires, plugs/sockets, and 10 diodes (eg.
1N4148). Use two diodes for each of the 5 switches (directions and
button), connected as such:<BR>
<TABLE><TR><TD><PRE> C64 Port 1 ----|&gt;|----+---- Joystick Switch
C64 Port 2 ----|&gt;|---/
C64 Ground ---------------- Joystick Ground
</TD></TR></TABLE>The diodes ring is to be pointing to the joystick-side. Diodes used to
keep the keyboard working when joystick is not moved. Both (two) diodes
are required because some programs (eg. Bruce Lee) use reversed
input/output direction for keyboard row/column ports.<BR>
The single joystick will act as if two joysticks are moved simultaneously
into same direction. This works okay with most programs, but may confuse a
few games, eg. Zaxxon produces some odd blinking when moved right.<BR>
<BR>
<BR>
<TABLE WIDTH=100%><TR bgcolor="#cccccc"><TD><A NAME="links"></A><FONT SIZE=+2>&nbsp;Links</FONT></TD></TR></TABLE><BR>
<B>This Document in TXT and HTM Format</B><BR>
http://nocash.emubase.de/c64.htm - homepage of no$c64 emulator/debugger<BR>
http://nocash.emubase.de/pagezero.htm - specs in HTM format<BR>
http://nocash.emubase.de/pagezero.txt - specs in TXT format<BR>
<BR>
<B>Project 64</B><BR>
http://project64.c64.org/archive.htm<BR>
Books and manuals converted into in plain clean raw ascii text format. The
file C64PRG10.TXT has been essential when making no$c64 emulation and
documentation. Also, 1541D10A.TXT and 154MAP10.TXT gave important info on the
disk drive, and PLUS4M~1.TXT provided some valuable & rare info on C16.<BR>
<BR>
<B>funet.fi</B><BR>
http://www.funet.fi/pub/cbm/<BR>
Great collection of C64, VIC20, and PLUS4 related things in various
categories, especially the schemactic sections have been very helpful when
making no$c64.<BR>
<BR>
<B>Grahams 65xx processor series opcodes</B><BR>
http://oxyron.net/graham/opcodes.html<BR>
Info on documented and undocumented 6502 opcodes, the undocumented part is
great, but the documented part lacks some fundamental details.<BR>
<BR>
<B>C=Hacking Magazine</B><BR>
http://www.ffd2.com/fridge/chacking/<BR>
Many thanks for articles Talking to TED, and Opening the Borders.<BR>
<BR>
<B>C64 Games</B><BR>
http://arnold.c64.org/<BR>
<BR>
</BODY></HTML>