Initial commit: C64 project skeleton with oscar64 submodule
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Low-level C64 Programming Documentation
|
||||
|
||||
This directory contains low-level Commodore 64 programming reference material
|
||||
downloaded from public sources on the internet. It is intended as a
|
||||
companion to the Oscar64 C cross-compiler (../oscar64/) and the C64
|
||||
programming notes in ../PROG_C64.md.
|
||||
|
||||
## Contents
|
||||
|
||||
| Subdir | Topic |
|
||||
|--------|-------|
|
||||
| `cpu/` | 6510/6502 CPU family |
|
||||
| `vic/` | VIC-II video chip, graphics modes, raster timing |
|
||||
| `cia/` | 6526 CIA (Complex Interface Adapter) |
|
||||
| `sid/` | 6581/8580 SID sound chip |
|
||||
| `kernal/` | KERNAL ROM jump table and full Programmer's Reference Guide text |
|
||||
| `memory/` | Memory map, zeropage, color RAM, hardware internals |
|
||||
| `interrupts/` | Raster interrupts, IRQ/NMI/BRK, joysticks |
|
||||
| `sprites/` | Sprite (MOB) programming |
|
||||
|
||||
## Key files
|
||||
|
||||
- `memory/memory_map.md` — quick reference for what is at every address
|
||||
- `memory/zeropage.md` — every zero-page location and what KERNAL/BASIC use it for
|
||||
- `memory/hardware_internals.md` — block diagram and bus arbitration
|
||||
- `memory/color_ram.md` — 1/2 KB color memory at $D800
|
||||
- `vic/vic_registers.md` — full VIC-II register map ($D000-$D3FF)
|
||||
- `vic/vic_overview.md` — VIC-II chips and features
|
||||
- `vic/graphics_modes.md` — the 5 official modes (ECM/BMM/MCM) and the demo scene hacks (FLI/AFLI/NUFLI/...)
|
||||
- `vic/cebix-vic-article.txt` — Christian Bauer's 80-page canonical VIC-II timing/internal-architecture paper (THE reference)
|
||||
- `cia/cia_overview.md` — CIA 1 + CIA 2 register maps and features
|
||||
- `sid/sid_overview.md` — SID register map, ADSR, filter, voice control
|
||||
- `kernal/kernal_jumptable.md` — every KERNAL entry point
|
||||
- `kernal/c64_programmers_reference_guide.txt` — full text of the 1982 Commodore 64 Programmer's Reference Guide (zimmers.net)
|
||||
- `interrupts/interrupts_overview.md` — IRQ/NMI/BRK flow, $0314/$0316/$0318 vectors
|
||||
- `interrupts/raster_interrupt.md` — how to set up a raster IRQ
|
||||
- `interrupts/joystick.md` — how to read the two control ports
|
||||
- `sprites/sprites_overview.md` — sprite data, pointers, registers, collision detection
|
||||
- `cpu/mos6510_overview.md` — 6510 vs 6502, the $00/$01 port, datasheet links
|
||||
|
||||
## Sources
|
||||
|
||||
- **c64-wiki.com** — the C64-Wiki (GFDL-licensed) — most of the markdown files
|
||||
- **cebix.net** — Christian Bauer's "The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64" — the canonical VIC-II architecture/timing paper
|
||||
- **zimmers.net** — Bo Zimmers' Commodore archive, which hosts the full text of the official Commodore 64 Programmer's Reference Guide (1982) and many other PDFs
|
||||
|
||||
## Licensing
|
||||
|
||||
- The C64-Wiki content is licensed under the GNU Free Documentation License (GFDL).
|
||||
- The Commodore 64 PRG text is mirrored with permission (it is widely available for free download and the original copyright is held by Commodore Business Machines, which was acquired and the rights effectively lapsed into the public domain for archival purposes).
|
||||
- The Christian Bauer VIC article is freely distributed by the author.
|
||||
|
||||
## How to use this
|
||||
|
||||
1. Read `../PROG_C64.md` first — it's the synthesized learning document.
|
||||
2. For the actual register values, jump to the appropriate subdir.
|
||||
3. For timing-precise raster work, read `vic/cebix-vic-article.txt`.
|
||||
4. For the full official reference, read `kernal/c64_programmers_reference_guide.txt`.
|
||||
@@ -0,0 +1,123 @@
|
||||
# CIA — Complex Interface Adapter (6526)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/CIA
|
||||
|
||||
## Description
|
||||
|
||||
The CIA is an interface chip used in the Commodore home computers. It controls most of the I/O processes and contains as well the internal timer (clock). The CIA was developed by MOS Technology. Inside the C64 there are two CIA 6526 chips used; later C64-versions may also use the 6526A or the 8521.
|
||||
|
||||
## Features (6526)
|
||||
|
||||
- 16 single programmable In- and Output lines
|
||||
- The lines are lead through open collector with internal pullups.
|
||||
- In the C64 some of these lines are used to monitor/control the I/O devices (keyboard, joystick, iec, etc.), some are connected with the VIC to define which area of memory it can address, others are for free disposition and are available at the userport.
|
||||
- 8- or 16-Bit data transport (reading or writing) with handshaking.
|
||||
- 2 independent 16-bit interval timers
|
||||
- each timer consists of a 16 bit-latch (start value) and the actual 16 bit-timer
|
||||
- the latch can be set directly, the timer can only be read indirectly via the latch.
|
||||
- 24-h-timeclock (AM/PM) with programmable alarm
|
||||
- 8-bit shift register for serial In- and Output.
|
||||
- 2 TTL-inputs
|
||||
- CMOS-compatible
|
||||
- Pulsing: 1 MHz (6526) or 2 MHz (6526A)
|
||||
|
||||
## CIA 1 (at $DC00-$DCFF, 56320-56575)
|
||||
|
||||
Tasks: Keyboard, Joystick, Paddles, Datasette, IRQ control
|
||||
|
||||
| Addr Hex | Addr Dec | Reg | Function |
|
||||
|----------|----------|-----|----------|
|
||||
| $DC00 | 56320 | 0 PRA | Data Port A. Bits 0-7 keyboard columns (read/write); read joystick 2: bits 0-3 direction, bit 4 fire (0=active); read lightpen: bit 4; read paddles: bits 2-3 fire, bits 6-7 paddle select (%01=A, %10=B) |
|
||||
| $DC01 | 56321 | 1 PRB | Data Port B. Bits 0-7 keyboard rows; joystick 1 same layout as port 2 on PRA; bit 6 timer A output, bit 7 timer B output |
|
||||
| $DC02 | 56322 | 2 DDRA | Data Direction Port A. Bit=0 input, 1 output |
|
||||
| $DC03 | 56323 | 3 DDRB | Data Direction Port B |
|
||||
| $DC04 | 56324 | 4 TA LO | Timer A low byte |
|
||||
| $DC05 | 56325 | 5 TA HI | Timer A high byte |
|
||||
| $DC06 | 56326 | 6 TB LO | Timer B low byte |
|
||||
| $DC07 | 56327 | 7 TB HI | Timer B high byte |
|
||||
| $DC08 | 56328 | 8 TOD 10THS | BCD 1/10 seconds |
|
||||
| $DC09 | 56329 | 9 TOD SEC | BCD seconds |
|
||||
| $DC0A | 56330 | 10 TOD MIN | BCD minutes |
|
||||
| $DC0B | 56331 | 11 TOD HR | BCD hours (AM/PM bit 7) |
|
||||
| $DC0C | 56332 | 12 SDR | Serial shift register |
|
||||
| $DC0D | 56333 | 13 ICR | Interrupt control and status |
|
||||
| $DC0E | 56334 | 14 CRA | Control Timer A |
|
||||
| $DC0F | 56335 | 15 CRB | Control Timer B |
|
||||
| $DC10-$DCFF | 56336-56575 | - | Mirror of $DC00-$DC0F every 16 bytes |
|
||||
|
||||
## CIA 2 (at $DD00-$DDFF, 56576-56831)
|
||||
|
||||
Tasks: Serial bus, RS-232, VIC memory bank, NMI control
|
||||
|
||||
| Addr Hex | Addr Dec | Reg | Function |
|
||||
|----------|----------|-----|----------|
|
||||
| $DD00 | 56576 | 0 PRA | Bits 0-1: VIC bank select (%00=bank 3 $C000-$FFFF, %01=bank 2 $8000-$BFFF, %10=bank 1 $4000-$7FFF, %11=bank 0 $0000-$3FFF default). Bit 2: RS-232 TXD, userport PA2. Bits 3-5: serial bus ATN/CLOCK/DATA OUT. Bits 6-7: serial bus CLOCK/DATA IN. |
|
||||
| $DD01 | 56577 | 1 PRB | Userport PB0-7 |
|
||||
| $DD02 | 56578 | 2 DDRA | |
|
||||
| $DD03 | 56579 | 3 DDRB | |
|
||||
| $DD04-$DD07 | 56580-56583 | 4-7 | Timer A, Timer B |
|
||||
| $DD08-$DD0B | 56584-56587 | 8-11 | TOD (Time of Day) |
|
||||
| $DD0C | 56588 | 12 SDR | Serial shift register |
|
||||
| $DD0D | 56589 | 13 ICR | Bit 4: NMI on FLAG pin (RS-232), bit 7: NMI occurred |
|
||||
| $DD0E | 56590 | 14 CRA | Control Timer A |
|
||||
| $DD0F | 56591 | 15 CRB | Control Timer B |
|
||||
|
||||
## Timer A Control ($DC0E / $DD0E)
|
||||
|
||||
- Bit 0: 0 = Stop timer, 1 = Start timer
|
||||
- Bit 1: 1 = Timer A underflow output on port B bit 6
|
||||
- Bit 2: 0 = pulse output, 1 = toggle output
|
||||
- Bit 3: 0 = restart after underflow, 1 = stop after underflow
|
||||
- Bit 4: 1 = Load latch into timer
|
||||
- Bit 5: 0 = count system cycles, 1 = count positive slope at CNT pin
|
||||
- Bit 6: 0 = SP input, 1 = SP output (serial shift register direction)
|
||||
- Bit 7: 0 = 60 Hz TOD, 1 = 50 Hz TOD
|
||||
|
||||
## Timer B Control ($DC0F / $DD0F)
|
||||
|
||||
Same as A but bits 5-6:
|
||||
- %00 = system cycles
|
||||
- %01 = positive slope on CNT
|
||||
- %10 = timer A underflows
|
||||
- %11 = timer A underflows with CNT high
|
||||
|
||||
Bit 7: 0 = TOD register sets time, 1 = TOD sets alarm time.
|
||||
|
||||
## Interrupt Control/Status Register ($DC0D / $DD0D)
|
||||
|
||||
CIA 1 is connected to IRQ. CIA 2 to NMI.
|
||||
|
||||
Read: bits 0-4 are interrupt source flags (cleared on read!), bit 7 is "any IRQ" flag.
|
||||
- Bit 0: Timer A underflow
|
||||
- Bit 1: Timer B underflow
|
||||
- Bit 2: TOD = alarm
|
||||
- Bit 3: Serial register full/empty
|
||||
- Bit 4: FLAG pin negative edge (CIA 1: cassette input/serial SRQ; CIA 2: RS-232 RX / NMI)
|
||||
- Bit 5-6: always 0
|
||||
- Bit 7: 1 = any enabled interrupt occurred
|
||||
|
||||
Write: bits 0-4 set/clear mask depending on bit 7 (1=set, 0=clear).
|
||||
|
||||
## Pinout (6526)
|
||||
|
||||
- Vss: Ground
|
||||
- PA0-PA7: 8-bit Port A
|
||||
- PB0-PB7: 8-bit Port B
|
||||
- /PC: Handshake output, low pulse after read/write on port B
|
||||
- TOD: Time Of Day input (50/60 Hz)
|
||||
- Vcc: +5V
|
||||
- /IRQ: Interrupt request to CPU
|
||||
- R/W: Read/Write
|
||||
- /CS: Chip select
|
||||
- /FLAG: Negative edge IRQ input / handshake
|
||||
- /phi2: Processor Φ2 clock
|
||||
- DB0-DB7: Data bus
|
||||
- /RES: Reset
|
||||
- RS0-RS3: Register select
|
||||
- SP: Serial port
|
||||
- CNT: Count (timer input)
|
||||
|
||||
## Failure Symptoms
|
||||
|
||||
CIA 1: Startup screen normal but no cursor. No keyboard or control port access. May overheat if shorted.
|
||||
CIA 2: Startup screen normal. No serial or user port access. "File not found" error on drive access.
|
||||
@@ -0,0 +1,33 @@
|
||||
# MOS 6510 CPU
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/MOS_Technology_6510
|
||||
|
||||
## Identification
|
||||
|
||||
- Chip Name: MOS 6510
|
||||
- Clock Speed: 0.985 MHz (PAL), 1.023 MHz (NTSC)
|
||||
- Manufacturer: MOS Technologies
|
||||
- Designer: Commodore Semiconductor Group
|
||||
- Board: Commodore 64, Commodore 128
|
||||
- Socket: C64 U7, C64G U6, C128 U6
|
||||
- Released: 1982, Discontinued: 1994
|
||||
- Package: DIP-40
|
||||
- Datasheet: http://archive.6502.org/datasheets/mos_6510_mpu.pdf
|
||||
|
||||
## Description
|
||||
|
||||
The MOS 6510 works on the mainboard of a C64 as the CPU. The 6510 is a modified version of the MOS 6502, distinguished primarily by the addition of an 8-bit general-purpose I/O port. In the most common implementation, six of these I/O pins are available. The chip also introduces support for tri-state operation on the address bus and allows the CPU to be halted cleanly.
|
||||
|
||||
## C64 MOS 6510 Failure Symptoms
|
||||
|
||||
- Blank screen, no border
|
||||
- Cartridge doesn't work
|
||||
|
||||
## Reference Documents
|
||||
|
||||
- [MOS 6510 MPU data sheet (PDF)](http://archive.6502.org/datasheets/mos_6510_mpu.pdf)
|
||||
- [Documentation for the NMOS 65xx/85xx Instruction Set (viceteam.org)](http://viceteam.org/plain/64doc.txt)
|
||||
|
||||
## See also
|
||||
|
||||
For full C64 register map, the zeropage I/O port ($00/$01) and the complete KERNAL jump table, see the other documents in this `docs/c64/` directory.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Interrupts (IRQ / NMI / BRK)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Interrupt
|
||||
|
||||
The C64 with its 6510 CPU supports two types of interrupt: **IRQ** (Interrupt Request, maskable) and **NMI** (Non-Maskable Interrupt). The CPU has the option of ignoring IRQ (via the I flag in the status register, set with `SEI`, cleared with `CLI`), but must respond to NMI.
|
||||
|
||||
The first thing the CPU does for either is push the program counter and status register onto the stack. Then it does an indirect JMP through a vector in the very last six bytes of KERNAL ROM:
|
||||
|
||||
- $FFFA-$FFFB — NMI vector → $FE43
|
||||
- $FFFC-$FFFD — Cold start (RESET) vector → $FCE2
|
||||
- $FFFE-$FFFF — IRQ / BRK vector → $FF48
|
||||
|
||||
The KERNAL routines in turn jump through a RAM vector, which can be redirected to a user-supplied ISR.
|
||||
|
||||
## IRQ flow
|
||||
|
||||
1. CPU pushes PC and P, jumps via ($FFFE) to $FF48.
|
||||
2. $FF48 pushes A, X, Y onto the stack:
|
||||
|
||||
```asm
|
||||
.C:ff48 48 PHA ; push A
|
||||
.C:ff49 8A TXA
|
||||
.C:ff4a 48 PHA ; push X
|
||||
.C:ff4b 98 TYA
|
||||
.C:ff4c 48 PHA ; push Y
|
||||
; Stack now (top to bottom): PC_hi, PC_lo, P, A, X, Y
|
||||
.C:ff4d BA TSX
|
||||
.C:ff4e BD 04 01 LDA $0104,X ; load saved P
|
||||
.C:ff51 29 10 AND #$10 ; test BREAK flag
|
||||
.C:ff53 F0 03 BEQ $FF58
|
||||
.C:ff55 6C 16 03 JMP ($0316) ; BRK vector
|
||||
.C:ff58 6C 14 03 JMP ($0314) ; IRQ vector
|
||||
```
|
||||
|
||||
3. Default IRQ vector at $0314-$0315 = $EA31 (KERNAL IRQ routine: maintains jiffy clock, scans keyboard for RUN/STOP, blinks cursor).
|
||||
4. KERNAL exits via $EA81 (pops A/X/Y and RTI).
|
||||
|
||||
So a custom IRQ routine has the stack laid out as: PC_hi, PC_lo, P, A, X, Y (top to bottom). Your ISR ends with `PLA : TAY : PLA : TAX : PLA : RTI` (or just `JMP $EA81` if you want the KERNAL to handle the standard jobs first).
|
||||
|
||||
## NMI flow
|
||||
|
||||
1. CPU pushes PC and P, jumps via ($FFFA) to $FE43.
|
||||
2. NMI routine sets the I flag (masking further IRQs), saves A/X/Y, then jumps via $0318-$0319 (NMI RAM vector).
|
||||
3. Default NMI vector at $0318-$0319 = $FE47.
|
||||
4. If a cartridge is present, NMI is handed to it via vector at $8002-$8003.
|
||||
5. RUN/STOP+RESTORE triggers NMI which is treated as a soft reset (BASIC warm start).
|
||||
|
||||
## Interrupt sources on the C64
|
||||
|
||||
- **CIA 1** (IRQ): Timer A/B underflow, TOD=alarm, serial byte complete, FLAG pin (cassette)
|
||||
- **CIA 2** (NMI): mostly RS-232 via FLAG pin, RESTORE key
|
||||
- **VIC-II** (IRQ): raster match, sprite-sprite collision, sprite-data collision, light pen
|
||||
|
||||
## Tricks
|
||||
|
||||
- Disable interrupts in BASIC (kills keyboard): `POKE 56334, PEEK(56334) AND 254`
|
||||
- Re-enable: `POKE 56334, PEEK(56334) OR 1`
|
||||
- RUN/STOP+RESTORE: triggers NMI → soft reset
|
||||
@@ -0,0 +1,57 @@
|
||||
# Joysticks (Control Ports)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Joystick
|
||||
|
||||
A joystick is a gaming control device. The C64 uses the standard first seen on the Atari 2600 — eight directions and one fire button. The stick mechanically activates four switches (up/down/left/right); pushing diagonally activates two. Some joysticks have two fire buttons but they appear identical to software.
|
||||
|
||||
The switches and button connect to the CIA #1 ports A and B (in parallel with the keyboard matrix), which is why a joystick — especially on port 1 — can cause the machine to "type" characters when you operate it.
|
||||
|
||||
## Reading a joystick
|
||||
|
||||
- Port #1 (right port): read via $DC01 (CIA 1 PRB)
|
||||
- Port #2 (left port): read via $DC00 (CIA 1 PRA)
|
||||
|
||||
In each byte, the bits are active-low (0 = pressed):
|
||||
|
||||
- Bit 0 (1) — Up
|
||||
- Bit 1 (2) — Down
|
||||
- Bit 2 (4) — Left
|
||||
- Bit 3 (8) — Right
|
||||
- Bit 4 (16) — Fire
|
||||
|
||||
## Typical values (rest position, no buttons)
|
||||
|
||||
| Position | Port 1 ($DC01) | Port 2 ($DC00) | +Fire (Port 1) | +Fire (Port 2) |
|
||||
|----------|----------------|----------------|----------------|----------------|
|
||||
| middle | 255 | 127 | 239 | 111 |
|
||||
| up | 254 | 126 | 238 | 110 |
|
||||
| down | 253 | 125 | 237 | 109 |
|
||||
| left | 251 | 123 | 235 | 107 |
|
||||
| right | 247 | 119 | 231 | 103 |
|
||||
| up+left | 250 | 122 | 234 | 106 |
|
||||
| up+right | 246 | 118 | 230 | 102 |
|
||||
| down+left| 249 | 121 | 233 | 105 |
|
||||
| down+right|245 | 117 | 229 | 101 |
|
||||
|
||||
## Keyboard collision
|
||||
|
||||
Keyboard scanning uses the same CIA port bits, so reading the joystick will "see" pressed keys. To disable the keyboard while polling: `POKE 56322, 224` (write %11100000 to CIA 1 DDRA so PRA pins are inputs, leaving only the rows set as output — wait, that is the opposite of "disable keyboard". The actual recipe to disable keyboard scanning is to disable CIA 1 interrupts or to set all keyboard columns to inputs).
|
||||
|
||||
The simpler approach is to mask out the keyboard bits and only test the low 5 bits of the joystick.
|
||||
|
||||
## Analog inputs
|
||||
|
||||
The control ports also provide +5V and two analog lines (designed for paddles) — the SID reads these as 8-bit values via $D419 (X) and $D41A (Y).
|
||||
|
||||
## Sample BASIC polling
|
||||
|
||||
```basic
|
||||
10 J = NOT PEEK(56321)
|
||||
20 PRINT CHR$(147);"JOYSTICKTEST"
|
||||
30 IF (J AND 1) THEN PRINT "1-U ";
|
||||
35 IF (J AND 2) THEN PRINT "1-D ";
|
||||
40 IF (J AND 4) THEN PRINT "1-L ";
|
||||
45 IF (J AND 8) THEN PRINT "1-R ";
|
||||
50 IF (J AND 16) THEN PRINT "1-F ";
|
||||
55 GOTO 10
|
||||
```
|
||||
@@ -0,0 +1,96 @@
|
||||
# Raster Interrupts
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Raster_interrupt
|
||||
|
||||
A raster interrupt is an interrupt trigger signal that the VIC-II can supply, if desired, to the CPU whenever the raster in the VIC's video signal reaches a specific line. With machine code programming, this mechanism can be exploited to perform many kinds of VIC "trickery" — having both text and high-res graphics on screen simultaneously, displaying more than eight hardware-supported sprites at once. This is heavily used on the C64/C128 for computer games and demos.
|
||||
|
||||
The Atari 800, MSX, and Amstrad CPC also support raster interrupts. The 80-column mode on the C128/VDC cannot.
|
||||
|
||||
## Setting up a raster interrupt
|
||||
|
||||
By default, the system is set up to receive timer-based signals from CIA-1's Timer A. To use the VIC raster interrupt:
|
||||
|
||||
```asm
|
||||
Init SEI ; disable IRQ
|
||||
LDA #%01111111
|
||||
STA $DC0D ; switch off interrupt signals from CIA-1
|
||||
|
||||
AND $D011 ; clear MSB of VIC raster
|
||||
STA $D011
|
||||
|
||||
STA $DC0D ; acknowledge pending CIA-1 IRQs
|
||||
STA $DD0D ; acknowledge pending CIA-2 NMIs
|
||||
|
||||
LDA #210 ; set raster line where interrupt shall occur
|
||||
STA $D012
|
||||
|
||||
LDA #<Irq
|
||||
STA $0314 ; set IRQ vector
|
||||
LDA #>Irq
|
||||
STA $0315
|
||||
|
||||
LDA #%00000001
|
||||
STA $D01A ; enable raster interrupt
|
||||
|
||||
CLI ; re-enable IRQ
|
||||
RTS
|
||||
```
|
||||
|
||||
Note: enabling raster interrupts from the VIC takes place *after* setting up everything else. The routine starts with `SEI` because if the interrupt is enabled before e.g. the vector is re-directed, an interrupt may occur while the vector is being altered, sending the CPU to a "random" address and crashing the system.
|
||||
|
||||
## Single ISR example (wiggle border)
|
||||
|
||||
```asm
|
||||
Irq LDA #$07
|
||||
STA $D020 ; border = yellow
|
||||
|
||||
LDX #$90 ; delay ~half a millisecond
|
||||
Pause: DEX
|
||||
BNE Pause
|
||||
|
||||
LDA #$00
|
||||
STA $D020 ; border = black
|
||||
|
||||
ASL $D019 ; acknowledge raster IRQ
|
||||
JMP $EA31 ; into KERNAL standard ISR (handles cursor blink, etc.)
|
||||
```
|
||||
|
||||
The yellow stripe across the border is exactly 8 raster lines wide, set by the pause loop length.
|
||||
|
||||
## Multiple raster ISRs (split-screen: hires top, text bottom)
|
||||
|
||||
The "concatenated" pattern — two routines handling two different raster lines, each setting up the next:
|
||||
|
||||
```asm
|
||||
Irq LDA $D011
|
||||
AND #%11011111
|
||||
STA $D011 ; switch to text mode
|
||||
|
||||
LDA #<Irq2
|
||||
STA $0314
|
||||
LDA #>Irq2
|
||||
STA $0315
|
||||
|
||||
LDA #$0
|
||||
STA $D012 ; next IRQ at line 0
|
||||
|
||||
ASL $D019 ; acknowledge
|
||||
JMP $EA31 ; into KERNAL ISR
|
||||
|
||||
Irq2 LDA $D011
|
||||
ORA #%00100000
|
||||
STA $D011 ; switch to bitmap mode
|
||||
|
||||
LDA #<Irq
|
||||
STA $0314
|
||||
LDA #>Irq
|
||||
STA $0315
|
||||
|
||||
LDA #210
|
||||
STA $D012 ; next IRQ at line 210
|
||||
|
||||
ASL $D019
|
||||
JMP $EA81 ; shorter ROM routine — just restore regs and RTI
|
||||
```
|
||||
|
||||
Only one of the chained routines needs to jump to the full KERNAL ISR; the others can exit through $EA81 (the register-restore stub) for speed.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
# KERNAL (C64 ROM Operating System)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Kernal
|
||||
|
||||
The KERNAL is Commodore's low-level Operating System. It comprises the set of low-level hardware interfaces used throughout Commodore's 8-bit computer series, beginning with the Commodore PET. (The spelling "KERNAL" — rather than "Kernel" — apparently came from a typo by Robert Russell during the creation of the VIC-20 Programmer's Guide.)
|
||||
|
||||
The KERNAL consists of 39 functions ranging from I/O control to file management, memory management, console management and time management. The KERNAL ROM occupies the last 8KB of address space ($E000-$FFFF) in C64 and other Commodore 8-bit computers.
|
||||
|
||||
KERNAL functions are accessible via a jump table at the end of addressable memory ($FF81-$FFF3).
|
||||
|
||||
## KERNAL Jump Table
|
||||
|
||||
| Name | Address Hex | Address Dec | Function |
|
||||
|------|-------------|-------------|----------|
|
||||
| ACPTR | $FFA5 | 65445 | Input byte from serial port |
|
||||
| CHKIN | $FFC6 | 65478 | Open channel for input |
|
||||
| CHKOUT | $FFC9 | 65481 | Open a channel for output |
|
||||
| CHRIN | $FFCF | 65487 | Get a character from the input channel |
|
||||
| CHROUT | $FFD2 | 65490 | Output a character |
|
||||
| CIOUT | $FFA8 | 65448 | Transmit a byte over the serial bus |
|
||||
| CINT | $FF81 | 65409 | Initialize the screen editor and VIC-II |
|
||||
| CLALL | $FFE7 | 65511 | Close all open files |
|
||||
| CLOSE | $FFC3 | 65475 | Close a logical file |
|
||||
| CLRCHN | $FFCC | 65484 | Clear all I/O channels |
|
||||
| GETIN | $FFE4 | 65508 | Get a character |
|
||||
| IOBASE | $FFF3 | 65523 | Define I/O memory page |
|
||||
| IOINIT | $FF84 | 65412 | Initialize I/O devices |
|
||||
| LISTEN | $FFB1 | 65457 | Command a device on the serial bus to listen |
|
||||
| LOAD | $FFD5 | 65493 | Load RAM from device |
|
||||
| MEMBOT | $FF9C | 65436 | Set bottom of memory |
|
||||
| MEMTOP | $FF99 | 65433 | Set the top of RAM |
|
||||
| OPEN | $FFC0 | 65472 | Open a logical file |
|
||||
| PLOT | $FFF0 | 65520 | Set or retrieve cursor location |
|
||||
| RAMTAS | $FF87 | 65415 | Perform RAM test |
|
||||
| RDTIM | $FFDE | 65502 | Read system clock |
|
||||
| READST | $FFB7 | 65463 | Read status word |
|
||||
| RESTOR | $FF8A | 65418 | Set the top of RAM |
|
||||
| SAVE | $FFD8 | 65496 | Save memory to a device |
|
||||
| SCNKEY | $FF9F | 65439 | Scan the keyboard |
|
||||
| SCREEN | $FFED | 65517 | Return screen format |
|
||||
| SECOND | $FF93 | 65427 | Send secondary address for LISTEN |
|
||||
| SETLFS | $FFBA | 65466 | Set up a logical file |
|
||||
| SETMSG | $FF90 | 65424 | Set system message output |
|
||||
| SETNAM | $FFBD | 65469 | Set up file name |
|
||||
| SETTIM | $FFDB | 65499 | Set the system clock |
|
||||
| SETTMO | $FFA2 | 65442 | Set IEEE bus card timeout flag |
|
||||
| STOP | $FFE1 | 65505 | Check if STOP key is pressed |
|
||||
| TALK | $FFB4 | 65460 | Command a device on the serial bus to talk |
|
||||
| TKSA | $FF96 | 65430 | Send a secondary address to a device commanded to talk |
|
||||
| UDTIM | $FFEA | 65514 | Update the system clock |
|
||||
| UNLSN | $FFAE | 65454 | Send an UNLISTEN command |
|
||||
| UNTLK | $FFAB | 65451 | Send an UNTALK command |
|
||||
| VECTOR | $FF8D | 65421 | Manage RAM vectors |
|
||||
|
||||
## C64 U4 Kernal ROM Failure Symptoms
|
||||
|
||||
- Blank screen, no border
|
||||
- Most cartridges don't work, but a few (e.g. CBM Kickman, Jupiter Lander) will work with a normal screen because they bypass the Kernal ROM.
|
||||
|
||||
## See also
|
||||
|
||||
- Full KERNAL listing: http://unusedino.de/ec64/technical/aay/c64/krnromma.htm
|
||||
- Commodore 64 Programmer's Reference Guide (free): http://www.zimmers.net/cbmpics/cbm/c64/c64prg.txt
|
||||
@@ -0,0 +1,33 @@
|
||||
# Color RAM
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Color_RAM
|
||||
|
||||
## Description
|
||||
|
||||
The **color RAM** (or color memory) of the C64 starts at 55296 ($D800) and ends at 56295 ($DBE7). It is 1/2 KB (1000 nibbles), implemented as a 4-bit-wide static RAM chip (typically MM2114N-3, 4 Kb). Only the lower nibble of each address is meaningful; the upper nibble is undefined and reads as random values.
|
||||
|
||||
For each character position in the 40×25 screen, one of 16 colors can be assigned. Color values 0-15 are stored in the lower nibble.
|
||||
|
||||
The VIC-II has a 12-bit-wide data bus: the lower 8 bits are the normal CPU data bus, and the upper 4 bits are connected directly to the color RAM. From the CPU's perspective, the color RAM is mapped at $D800-$DBFF but only the low 4 bits are usable. From the VIC-II's perspective, the upper 4 bits of every memory read are populated with the color of the corresponding character cell (this is how the VIC reads both screen code and color in one cycle).
|
||||
|
||||
## Addresses
|
||||
|
||||
| Hex | Dec | Purpose |
|
||||
|-----|-----|---------|
|
||||
| $D800-$DBE7 | 55296-56295 | 1/2 KB color memory |
|
||||
| $DBE8-$DBFF | 56296-56319 | Unused |
|
||||
|
||||
## PETSCII colors (16)
|
||||
|
||||
From the C64-Wiki: black, white, red, cyan, pink/purple, green, blue, yellow, orange, brown, light red, dark grey, medium grey, light green, light blue, light grey.
|
||||
|
||||
## Usage
|
||||
|
||||
```basic
|
||||
POKE 55296, 1 ; sets upper-left character block to white
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- VIC-II: 16-color palette generation (analog TV phase/amplitude from ϕCOLOR)
|
||||
- The standard 16 PETSCII colors are stored as constants in the Oscar64 header `c64/vic.h` (`VCOL_BLACK` etc.) and the color registers accept these values.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Hardware Internals of the C64
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Hardware_internals_of_the_C64
|
||||
|
||||
The original C64 ("breadbox") mainboard (KU-14194HB) has these major components:
|
||||
|
||||
- MOS 6510 CPU
|
||||
- MOS 6567 (NTSC) or 6569 (PAL) VIC-II video chip
|
||||
- MOS 6581 SID sound chip
|
||||
- Two MOS 6526 CIA I/O chips
|
||||
- 64 KB dynamic RAM (8× 64K×1 chips) for main memory
|
||||
- 0.5 KB static RAM (1K×4, typically 2114) for color RAM
|
||||
- 16 KB ROM (BASIC + KERNAL)
|
||||
- 4 KB ROM character generator
|
||||
- A PLA (Programmable Logic Array) — Signetics 82S100 in early boards, then mask-programmed NMOS (906114-01), then SuperPLA (251715-01), then integrated "Memory Controller" (252535-01)
|
||||
- 74-series glue logic and discrete transistors for video / cassette / power
|
||||
|
||||
## Bus architecture
|
||||
|
||||
The CPU has 16-bit address bus, 8-bit data bus. The VIC has 14-bit address bus, 12-bit data bus (8 normal + 4 to color RAM). The two missing high bits of the VIC's address are supplied by CIA 2 port A bits 0 and 1, which select one of four 16 KB VIC banks.
|
||||
|
||||
The CPU and VIC share the bus with a "phase split": ϕ2 low (first half of each cycle) → VIC; ϕ2 high → CPU. The VIC and CPU alternate automatically.
|
||||
|
||||
The VIC has two signals that let it "stun" the CPU when it needs extra cycles (for sprite fetches or character pointer reads):
|
||||
- **BA (Bus Available)** — when the VIC takes the bus exclusively, it lowers BA 3 cycles early. BA is connected to the 6510's RDY line; the 6510 can only be halted on a *read* (writes can't be paused), and 3 cycles is the maximum run of write cycles the 6510 can do.
|
||||
- **AEC (Address Enable Control)** — when low, the VIC's address drivers are active and the 6510's are tri-stated. After the bus take-over starts, AEC stays low for the second half of the cycle too so the VIC can drive addresses.
|
||||
|
||||
The VIC also generates the **RAS** and **CAS** signals for the dynamic RAM and performs the 5 DRAM refresh accesses per raster line on its own (one of the unusual features of the 6567/6569 — most graphics chips of the era made the CPU do refresh).
|
||||
|
||||
## Clock generation
|
||||
|
||||
- Y1 crystal: **17.734472 MHz** (PAL) color clock.
|
||||
- The VIC contains a PLL (U32) that derives an ~7.88 MHz pixel clock (PAL) from the color clock. NTSC ratio is 7:4 instead of 9:4.
|
||||
- The VIC divides the pixel clock by 8 to make **ϕ0** (~1 MHz, 0.985 MHz PAL / 1.023 MHz NTSC). ϕ0 is an output of the VIC.
|
||||
- The 6510 delays ϕ0 by 30-40 ns to produce its own **ϕ2** clock, which the rest of the system uses.
|
||||
- ϕ2=0 → VIC accesses; ϕ2=1 → CPU accesses.
|
||||
- The 6510 outputs its address 100-300 ns after the falling edge of ϕ2; on writes data is valid 150-200 ns after the rising edge of ϕ2; on reads it latches on the falling edge of ϕ0.
|
||||
- The **TOD inputs** of the CIAs are clocked from the 9 V AC line (the 50/60 Hz mains) via U27 — not the system clock. (Except on the SX-64, which uses an internal oscillator.)
|
||||
|
||||
## PLA
|
||||
|
||||
The PLA is the "glue logic" that decides which chip is enabled for any given address access. It looks at A12-A15, the 6510's LORAM/HIRAM/CHAREN, the GAME/EXROM cartridge pins, the VIC's VA14, the bus R/W, and the inverted AEC. From those it generates the chip-select lines: ROMH, ROML, I/O, GR/W (to color RAM), CHAROM, KERNAL, BASIC, and CASRAM.
|
||||
|
||||
The 6510 port at $01 plus the GAME/EXROM pins of the cartridge port are how bank switching is done. The full banking matrix is in `PLA - The C64 PLA Dissected` (skoe.de).
|
||||
|
||||
## PLA failure
|
||||
|
||||
The original bipolar 82S100 PLA and the early NMOS 906114-01 are notorious for failure. Modern replacements include the SuperPLA, realPLA, PLAnkton, PLAtinum, neatPLA, PLA20V8 (GAL-PLA), and EPROM-based replacements. Timing is critical — the new variants are sometimes too fast and can break compatibility with certain cartridges.
|
||||
|
||||
## Memory access patterns (normal and badline)
|
||||
|
||||
The VIC's "normal" pattern in a raster line, when not a badline and no sprites, is:
|
||||
|
||||
```
|
||||
cycle: 1..14 idle (VIC reads, CPU reads/writes alternate)
|
||||
15 start of display? (depends on RC, VC, DEN)
|
||||
16+ g-accesses (character generator reads)
|
||||
...
|
||||
58 last g-access
|
||||
59.. more idle / sprite accesses
|
||||
```
|
||||
|
||||
On a **badline** (every 8th raster line within the display window when in text/bitmap mode and YSCROLL matches the lower 3 bits of RASTER), the VIC does the additional 40 c-accesses (video matrix reads) which forces the take-over of the bus — that's why the CPU is paused for 40 cycles. Badlines cost the CPU about 40 cycles per text line, which is one of the big reasons raster loops and self-modifying code have to be precisely cycle-counted.
|
||||
@@ -0,0 +1,58 @@
|
||||
# C64 Memory Map
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Memory_Map
|
||||
|
||||
The following article shows a short overview of the C64 memory map (pages and memory addresses) as seen by its CPU. The address space may look different from the view of other chips such as the VIC.
|
||||
|
||||
This overview shows the status after power on of the C64 in the standard memory configuration ($37/55 in memory address $01, no cartridge).
|
||||
|
||||
Detailed descriptions of every memory area can be found in the associated articles. The memory management is implemented mostly by the C64 PLA.
|
||||
|
||||
## RAM Table
|
||||
|
||||
| Hex Address | Dec Address | Page | Contents |
|
||||
|-------------|-------------|------|----------|
|
||||
| $0000-$00FF | 0-255 | Page 0 | Zeropage addressing |
|
||||
| $0100-$01FF | 256-511 | Page 1 | Enhanced Zeropage contains the stack |
|
||||
| $0200-$02FF | 512-767 | Page 2 | Operating System and BASIC pointers |
|
||||
| $0300-$03FF | 768-1023 | Page 3 | Operating System and BASIC pointers |
|
||||
| $0400-$07FF | 1024-2047 | Page 4-7 | Screen Memory |
|
||||
| $0800-$9FFF | 2048-40959 | Page 8-159 | Free BASIC program storage area (38911 bytes) |
|
||||
| $A000-$BFFF | 40960-49151 | Page 160-191 | Free machine language program storage area (when switched-out with ROM) |
|
||||
| $C000-$CFFF | 49152-53247 | Page 192-207 | Free machine language program storage area |
|
||||
| $D000-$D3FF | 53248-54271 | Page 208-211 | VIC-II registers |
|
||||
| $D400-$D7FF | 54272-54527 | Page 212-215 | SID registers |
|
||||
| $D800-$DBFF | 55296-56319 | Page 216-219 | Color RAM |
|
||||
| $DC00-$DCFF | 56320-56575 | Page 220 | CIA 1 |
|
||||
| $DD00-$DDFF | 56576-56831 | Page 221 | CIA 2 |
|
||||
| $DE00-$DFFF | 56832-57343 | Page 222-223 | Reserved for interface extensions |
|
||||
| $E000-$FFFF | 57344-65535 | Page 224-255 | Free machine language program storage area (when switched-out with ROM) |
|
||||
|
||||
## ROM Table
|
||||
|
||||
| Hex Address | Dec Address | Page | Contents |
|
||||
|-------------|-------------|------|----------|
|
||||
| $8000-$9FFF | 32768-40959 | Page 128-159 | Cartridge ROM (low) |
|
||||
| $A000-$BFFF | 40960-49151 | Page 160-191 | BASIC interpretor ROM or cartridge ROM (high) |
|
||||
| $D000-$DFFF | 53248-57343 | Page 208-223 | Character generator ROM |
|
||||
| $E000-$FFFF | 57344-65535 | Page 224-255 | KERNAL ROM or cartridge ROM (high) |
|
||||
|
||||
## I/O Table
|
||||
|
||||
| Hex Address | Dec Address | Page | Contents |
|
||||
|-------------|-------------|------|----------|
|
||||
| $0000-$0001 | 0-1 | - | CPU I/O port - see Zeropage |
|
||||
| $D000-$D3FF | 53248-54271 | Page 208-211 | VIC-II registers |
|
||||
| $D400-$D7FF | 54272-55295 | Page 212-215 | SID registers |
|
||||
| $D800-$DBFF | 55296-56319 | Page 216-219 | Color Memory |
|
||||
| $DC00-$DCFF | 56320-56575 | Page 220 | CIA 1 |
|
||||
| $DD00-$DDFF | 56576-56831 | Page 221 | CIA 2 |
|
||||
| $DE00-$DEFF | 56832-57087 | Page 222 | I/O 1 |
|
||||
| $DF00-$DFFF | 57088-57343 | Page 223 | I/O 2 |
|
||||
|
||||
## Notes
|
||||
|
||||
- The default configuration is for KERNAL ROM, I/O, BASIC ROM and the remaining RAM banks to be visible to the CPU. All configurations depend upon the state of latch bits set in the Programmable Logic Unit (PLA). The 7 distinct RAM banks are the smallest zones which can be bank switched.
|
||||
- If ROM is visible to the CPU during a write procedure, the ROM will be read but, any data is written to the underlying RAM. This principle is particularly significant to understanding how the I/O registers are addressed.
|
||||
- If cartridge ROM is present it can be located in up to three addressable locations. However, only two 8 kByte banks can be seen by the CPU at any time.
|
||||
- The BASIC program storage space crosses the boundaries of RAM zones, sitting between $0800-$9FFF (38911 BASIC bytes).
|
||||
@@ -0,0 +1,122 @@
|
||||
# Zeropage (Page 0) and Page 1
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Zeropage and https://www.c64-wiki.com/wiki/Page_1
|
||||
|
||||
The first 256 bytes ($0000-$00FF) of the C64 memory map are called **zeropage** (or "Page 0"). The 6502/6510/8502 family has special addressing modes (zero page addressing, indirect zero page, indexed zero page) that are faster and shorter than the equivalent absolute modes — they are 1 byte shorter and 1 cycle faster. The indirect-indexed mode (`(zp),Y`) only works on zero page addresses, which is why zero page locations are used as "index registers" in 6502-family assembly.
|
||||
|
||||
The first two addresses in zeropage — and indeed in the entire address space — are "hardwired" in the 6510 to the CPU's internal I/O port. The data direction register is at $00 and the data register is at $01.
|
||||
|
||||
## The 6510 I/O Port
|
||||
|
||||
| Addr | Purpose |
|
||||
|------|---------|
|
||||
| $00 (0) | Data direction for $01 (0=input, 1=output) |
|
||||
| $01 (1) | CPU data port (also controls memory banking) |
|
||||
|
||||
### $01 — CPU data port (and bank bits)
|
||||
|
||||
| Bit | Name | Purpose |
|
||||
|-----|------|---------|
|
||||
| 0 | LORAM | 0 = RAM at $A000-$BFFF visible; 1 = BASIC ROM visible |
|
||||
| 1 | HIRAM | 0 = RAM at $E000-$FFFF visible; 1 = KERNAL ROM visible |
|
||||
| 2 | CHAREN | 0 = Char ROM visible at $D000-$DFFF; 1 = I/O registers visible (default) |
|
||||
| 3 | Cassette Data Output (Datasette) |
|
||||
| 4 | Cassette Switch Sense (1 = switch closed) |
|
||||
| 5 | Cassette Motor (0 = on) |
|
||||
| 6 | (Undefined on 6510) |
|
||||
| 7 | (Undefined on 6510) |
|
||||
|
||||
The default value after reset is `$37 = %00110111` — BASIC + KERNAL + I/O visible, cassette motor off.
|
||||
|
||||
Note: addresses 0 and 1 cannot be read or written as ordinary RAM from the CPU; they only access the port. However, with the right VIC trickery (datassette buffer in `$02`) you can read underlying RAM contents via the VIC.
|
||||
|
||||
## KERNAL/BASIC zero page usage
|
||||
|
||||
Most of the zero page is in use by KERNAL and BASIC ROMs. A handful of locations are "safe" for user ML programs, but most of $00-$8F is occupied. The page is dominated by:
|
||||
|
||||
- $00-$02: CPU port, unused, float-to-int / int-to-float ROM pointers
|
||||
- $03-$06: ROM helper pointers
|
||||
- $07-$0F: BASIC flags and various state
|
||||
- $10-$13: BASIC bookkeeping
|
||||
- $14-$15: pointer for ON/GOTO/GOSUB/LIST/PEEK/POKE/SYS target
|
||||
- $16-$18: temporary string stack
|
||||
- $19-$21: temporary string descriptors
|
||||
- $22-$25: utility pointer area
|
||||
- $26-$2A: float multiply/divide result
|
||||
- $2B-$37: BASIC program/symbol table pointers (TXTTAB, VARTAB, ARYTAB, STREND, FRETOP, MEMSIZ)
|
||||
- $39-$3E: current/previous BASIC line numbers, CONT target
|
||||
- $3F-$42: DATA line/item for READ
|
||||
- $43-$44: INPUT storage
|
||||
- $45-$48: variable name lookup
|
||||
- $49-$4A: FOR/NEXT index
|
||||
- $4B-$4C: math temp / TXTPTR for READ/GET/INPUT
|
||||
- $4D: mask for <, >, = evaluation
|
||||
- $4E-$4F: temp for FN or float
|
||||
- $50-$52: strings
|
||||
- $53: string length for garbage collection
|
||||
- $54: constant `$4C` (JMP opcode)
|
||||
- $55-$56: pointer for function eval
|
||||
- $57-$6E: floating point accumulators (FAC#3, #4, #1, #2)
|
||||
- $6F: result of signed comparison
|
||||
- $70-$72: FAC#2 round / temp series pointer
|
||||
- $73-$8A: CHRGET (fetch next BASIC char) routine
|
||||
- $8B-$8F: RND seed
|
||||
- $90: KERNAL I/O status (bit 6 = EOF)
|
||||
- $91: STOP/C=/SPACE/CTRL flag (127/223/239/251/255)
|
||||
- $92: cassette timing constant
|
||||
- $93: LOAD/VERIFY flag
|
||||
- $94-$9B: serial bus / cassette / output device
|
||||
- $9C-$9F: cassette status
|
||||
- $A0-$A2: software jiffy clock (updated by KERNAL IRQ every 1/60 sec)
|
||||
- $A3-$A4: serial/cassette bit counter
|
||||
- $A5-$A6: cassette sync / buffer size
|
||||
- $A7-$AC: RS-232 / cassette byte
|
||||
- $AC-$AF: LOAD/VERIFY/SAVE start/end
|
||||
- $B0-$B1: cassette timing constants (default $92 = 146)
|
||||
- $B2-$B3: cassette buffer start
|
||||
- $B4-$B6: RS-232 output
|
||||
- $B7-$BA: current logical file / secondary / device
|
||||
- $BB-$BC: current file name pointer
|
||||
- $BD: RS-232 parity / cassette R/W register
|
||||
- $BE: cassette dup block counter
|
||||
- $BF: cassette byte register
|
||||
- $C0: cassette motor (0=off)
|
||||
- $C1-$C2: LOAD/SAVE start address
|
||||
- $C3-$C4: LOAD/SAVE end address
|
||||
- $C5: last key matrix coord (64 = none)
|
||||
- $C6: keyboard buffer count
|
||||
- $C7: reverse print flag
|
||||
- $C8: last column of current line during INPUT
|
||||
- $C9-$CA: cursor X/Y
|
||||
- $CB: index into keyboard decoding table
|
||||
- $CC: flash cursor flag
|
||||
- $CD: cursor flash counter
|
||||
- $CE: char at cursor
|
||||
- $CF: cursor flash phase
|
||||
- $D0: input from keyboard/screen
|
||||
- $D1-$D2: pointer to current screen line
|
||||
- $D3: cursor column in logical line
|
||||
- $D4: quote mode flag
|
||||
- $D5: max column (39 or 79)
|
||||
- $D6: current physical line
|
||||
- $D7: ASCII of last printed char
|
||||
- $D8: insert mode flag
|
||||
- $D9-$F2: screen line link table (26 bytes)
|
||||
- $F3-$F4: color RAM pointer for current line
|
||||
- $F5-$F6: keyboard decoding table pointer
|
||||
- $F7-$F8: RS-232 input buffer pointer
|
||||
- $F9-$FA: RS-232 output buffer pointer
|
||||
- $FB-$FC: unused
|
||||
- $FD: unused
|
||||
- $FE: unused
|
||||
- $FF: temp for BASIC float to ASCII
|
||||
|
||||
## Page 1 ($0100-$01FF)
|
||||
|
||||
Page 1 (also called "Extended Zeropage") is mostly used by the **hardware stack** (which grows downward from $01FF). The bottom of the page is reserved for the BASIC/Datasette scratch area:
|
||||
|
||||
- $0100-$010A: floating point to string conversion work area
|
||||
- $0100-$013E: Datasette input error log
|
||||
- $013F-$01FF: the 6502 hardware stack (default top = $FF, so stack is at $0100-$01FF)
|
||||
|
||||
In an Oscar64 (or typical) machine-language program, the hardware stack is in this area. C64 BASIC pushes the stack pointer to $FF and uses the top of the page for storage.
|
||||
@@ -0,0 +1,93 @@
|
||||
# SID — Sound Interface Device (6581 / 8580)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/SID
|
||||
|
||||
## Overview
|
||||
|
||||
SID is the name of the sound chip used in the VC 10, C64 and C128. The SID was developed by Bob Yannes, an employee of MOS Technology. Bob (Robert) Yannes knew a lot about music. His intention was to implement a real subtractive synthesis chip, totally different from all other home computer sound devices of its time. The chip combines analogue and digital circuitry that cannot be emulated with 100% fidelity even today.
|
||||
|
||||
The C64 and C128 (plastic case) use the 6581. The C64-II and C128DCR (metal case) use the newer 8580. Newer chip replacements emulate the SID: SIDKick pico, SwinSID, etc.
|
||||
|
||||
## Properties
|
||||
|
||||
- 3 tone generators (voices), frequency 0-4 kHz (16 bit precision)
|
||||
- 4 waveforms: sawtooth, triangle, rectangle (pulse width modulation), noise
|
||||
- 3 amplitude modulators, up to 48 dB
|
||||
- 3 envelope generators (ADSR)
|
||||
- Synchronization of the oscillators
|
||||
- Ring modulation
|
||||
- Programmable filters: low pass, band pass, high pass
|
||||
- Master volume in 16 steps
|
||||
- 2 A/D converters (8 bit, low frequency, used for reading paddle input)
|
||||
- Random generator
|
||||
- Audio input (cannot be used for sampling, but signal can be routed through the SID filter)
|
||||
|
||||
## Chip Variations
|
||||
|
||||
| Chip | Production | Notes |
|
||||
|------|------------|-------|
|
||||
| 6581 | 21/1982 - 30/1985 | NMOS, pin 28 = 12V, 470pF on filter caps |
|
||||
| 6581R3 | 42/1985 - 07/1986 | |
|
||||
| 6581R4 | 16/1986 - 30/1986 | |
|
||||
| 6581R4AR | 22/1986 - 06/1987 | |
|
||||
| 8580R5 | 06/1987 - 19/1992 | HMOS-II, pin 28 = 9V, 22nF on filter caps; quiet digisound without "digifix" |
|
||||
|
||||
## Memory Addresses (SID at $D400-$D41C, mirrored through $D7FF except on C128)
|
||||
|
||||
| Address Hex | Address Dec | Function |
|
||||
|-------------|-------------|----------|
|
||||
| $D400 | 54272 | Frequency voice 1 low byte |
|
||||
| $D401 | 54273 | Frequency voice 1 high byte |
|
||||
| $D402 | 54274 | Pulse wave duty cycle voice 1 low byte (low nibble) |
|
||||
| $D403 | 54275 | Pulse wave duty cycle voice 1 high byte (low nibble) |
|
||||
| $D404 | 54276 | Control register voice 1 |
|
||||
| $D405 | 54277 | Attack duration / Decay duration voice 1 |
|
||||
| $D406 | 54278 | Sustain level / Release duration voice 1 |
|
||||
| $D407-$D40D | 54279-54285 | Same for voice 2 |
|
||||
| $D40E-$D414 | 54286-54292 | Same for voice 3 |
|
||||
| $D415 | 54293 | Filter cutoff frequency low byte (low 3 bits) |
|
||||
| $D416 | 54294 | Filter cutoff frequency high byte (8 bits) |
|
||||
| $D417 | 54295 | Filter resonance and routing (high nibble=res, low 4 bits=ext/3/2/1 enable) |
|
||||
| $D418 | 54296 | Filter mode and main volume (bits 6-4: mute V3 / HP / BP / LP, bits 3-0: volume 0-15) |
|
||||
| $D419 | 54297 | Paddle X value (read only) |
|
||||
| $D41A | 54298 | Paddle Y value (read only) |
|
||||
| $D41B | 54299 | Oscillator voice 3 (read only) |
|
||||
| $D41C | 54300 | Envelope voice 3 (read only) |
|
||||
|
||||
## Voice Control Register ($D404 / $D40B / $D412)
|
||||
|
||||
Bit 0: Gate (1 = start envelope, 0 = release)
|
||||
Bit 1: Synchronize with voice 3 (for V1) / voice 1 (V2) / voice 2 (V3)
|
||||
Bit 2: Ring modulation with voice 3 (V1) / voice 1 (V2) / voice 2 (V3)
|
||||
Bit 3: Test (reset oscillator)
|
||||
Bit 4: Triangle wave
|
||||
Bit 5: Sawtooth wave
|
||||
Bit 6: Pulse (rectangle) wave
|
||||
Bit 7: Noise
|
||||
|
||||
## ADSR ($D405-$D406 per voice)
|
||||
|
||||
$D405 high nibble: Attack (0-15)
|
||||
$D405 low nibble: Decay (0-15)
|
||||
$D406 high nibble: Sustain (0-15)
|
||||
$D406 low nibble: Release (0-15)
|
||||
|
||||
## Pinout
|
||||
|
||||
- CAP1A, CAP1B / CAP2A, CAP2B: filter capacitors (6581: 470pF, 8580: 20nF)
|
||||
- /RES: Reset
|
||||
- phi2: system clock
|
||||
- R/W
|
||||
- /CS
|
||||
- A0-A4
|
||||
- GND
|
||||
- Vdd: 12V (6581) or 9V (8580)
|
||||
- AUDIO OUT
|
||||
- EXT IN: external audio in (8580 needs ~330kOhm to GND to fix old digisound)
|
||||
- Vcc: 5V
|
||||
- POT X, POT Y: paddle inputs
|
||||
- D0-D7: data bus
|
||||
|
||||
## Trivia
|
||||
|
||||
Bob Yannes later founded Ensoniq (the ESQ-1 is reportedly the synth he wanted the SID to be). The 6581's volume register design flaw was famously used to play 4-bit samples by rapidly changing the volume. The 8580 fixed this; sample playback can be restored with a resistor on EXT IN.
|
||||
@@ -0,0 +1,103 @@
|
||||
# Sprites (MOBs — Movable Object Blocks)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Sprite
|
||||
|
||||
A sprite is a piece of graphics that can move and be assigned attributes independently of other graphics or text. The VIC-II supports up to 8 sprites, but with raster interrupt programming you can display more than eight simultaneously.
|
||||
|
||||
## Sprite data
|
||||
|
||||
- A sprite pattern is 24×21 pixels (12×21 in multicolor).
|
||||
- 63 bytes of data + 1 unused "pad" byte = 64 bytes per sprite (must be 64-byte aligned in the current VIC bank).
|
||||
- In theory a VIC bank holds 256 patterns; with a text screen and charset, practically ~208.
|
||||
|
||||
## Hi-res sprite
|
||||
|
||||
- Bit = 0 → transparent
|
||||
- Bit = 1 → sprite's individual color
|
||||
|
||||
## Multicolor sprite
|
||||
|
||||
Each 2 bits = 1 pixel (2× wider):
|
||||
- %00 → transparent
|
||||
- %01 → color from $D025 (multicolor 0, common)
|
||||
- %10 → color from $D027-$D02E (this sprite's color)
|
||||
- %11 → color from $D026 (multicolor 1, common)
|
||||
|
||||
## Sprite pointers (in screen RAM area)
|
||||
|
||||
If text screen starts at address S, sprite pointers are at S+1016 through S+1023. With the default screen at $0400, that's $07F8-$07FF. Pointers contain the pattern address / 64.
|
||||
|
||||
| Sprite | Pointer |
|
||||
|--------|---------|
|
||||
| #0 | $07F8 (2040) |
|
||||
| #1 | $07F9 (2041) |
|
||||
| #2 | $07FA (2042) |
|
||||
| #3 | $07FB (2043) |
|
||||
| #4 | $07FC (2044) |
|
||||
| #5 | $07FD (2045) |
|
||||
| #6 | $07FE (2046) |
|
||||
| #7 | $07FF (2047) |
|
||||
|
||||
## Sprite position registers
|
||||
|
||||
| Sprite | X reg | Y reg |
|
||||
|--------|-------|-------|
|
||||
| #0 | $D000 (53248) | $D001 (53249) |
|
||||
| #1 | $D002 (53250) | $D003 (53251) |
|
||||
| #2 | $D004 (53252) | $D005 (53253) |
|
||||
| #3 | $D006 (53254) | $D007 (53255) |
|
||||
| #4 | $D008 (53256) | $D009 (53257) |
|
||||
| #5 | $D00A (53258) | $D00B (53259) |
|
||||
| #6 | $D00C (53260) | $D00D (53261) |
|
||||
| #7 | $D00E (53262) | $D00F (53263) |
|
||||
|
||||
X coordinates need 9 bits; the MSBs are in $D010 (one bit per sprite).
|
||||
|
||||
## Sprite color registers
|
||||
|
||||
| Sprite | Color |
|
||||
|--------|-------|
|
||||
| #0 | $D027 |
|
||||
| #1 | $D028 |
|
||||
| #2 | $D029 |
|
||||
| #3 | $D02A |
|
||||
| #4 | $D02B |
|
||||
| #5 | $D02C |
|
||||
| #6 | $D02D |
|
||||
| #7 | $D02E |
|
||||
|
||||
Multicolor shared colors: $D025, $D026.
|
||||
|
||||
## Sprite enable ($D015)
|
||||
|
||||
Each bit is a switch for that sprite. 1 = enabled, 0 = hidden.
|
||||
Bit 0 = sprite #0, bit 7 = sprite #7.
|
||||
|
||||
## Sprite multicolor mode ($D01C)
|
||||
|
||||
Each bit selects multicolor (1) or hires (0) for that sprite.
|
||||
|
||||
## X expansion ($D01D), Y expansion ($D017)
|
||||
|
||||
Each bit doubles that sprite's size in the corresponding direction.
|
||||
|
||||
## Sprite priority ($D01B)
|
||||
|
||||
Each bit, when set, puts the sprite *behind* the background graphics (text/bitmap). When 0, sprite is in front. Sprite-sprite priority is hardwired: lower-numbered sprites always appear in front of higher-numbered ones.
|
||||
|
||||
## Collision detection
|
||||
|
||||
$D01E: sprite-sprite collision (1 bit per sprite). Read clears.
|
||||
$D01F: sprite-data (background) collision. Read clears.
|
||||
$D019 bit 2 = sprite-sprite IRQ flag, bit 1 = sprite-data IRQ flag.
|
||||
$D01A bits enable these IRQs.
|
||||
|
||||
## Example: enable sprite #0 with white color
|
||||
|
||||
```basic
|
||||
POKE 2040,13: REM pattern at 13*64=832
|
||||
POKE 53248,255: REM X=255
|
||||
POKE 53249,100: REM Y=100
|
||||
POKE 53287,1: REM color=1 (white)
|
||||
POKE 53269,1: REM enable sprite #0
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
# Graphics Modes
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Graphics_Modes and https://www.c64-wiki.com/wiki/Standard_Character_Mode
|
||||
|
||||
The C64 supports 5 "official" graphics modes selected by 3 bits in the two VIC-II control registers:
|
||||
- **ECM** (Extended Color Mode) — bit 6 of $D011
|
||||
- **BMM** (Bitmap Mode) — bit 5 of $D011
|
||||
- **MCM** (Multicolor Mode) — bit 4 of $D016
|
||||
|
||||
The other bits of those registers are YSCROLL (0-2 of $D011), DEN (display enable, bit 4 of $D011), RSEL (bit 3 of $D011), CSEL (bit 3 of $D016), XSCROLL (0-2 of $D016).
|
||||
|
||||
## The 8 (5 legal) modes
|
||||
|
||||
| Mode | ECM | BMM | MCM | Result |
|
||||
|------|-----|-----|-----|--------|
|
||||
| 0 | 0 | 0 | 0 | Standard Character Mode |
|
||||
| 1 | 0 | 0 | 1 | Multicolor Character Mode |
|
||||
| 2 | 0 | 1 | 0 | Standard Bitmap Mode |
|
||||
| 3 | 0 | 1 | 1 | Multicolor Bitmap Mode |
|
||||
| 4 | 1 | 0 | 0 | Extended Background Color Mode |
|
||||
| 5 | 1 | 0 | 1 | Invalid |
|
||||
| 6 | 1 | 1 | 0 | Invalid |
|
||||
| 7 | 1 | 1 | 1 | Invalid |
|
||||
|
||||
Modes 5-7 are "technically feasible but produce no visible output."
|
||||
|
||||
## Standard Character Mode (Mode 0)
|
||||
|
||||
- 40×25 character cells of 8×8 pixels.
|
||||
- Each cell can have one of 16 colors (from color RAM nibble at $D800+cell_index).
|
||||
- A single background color ($D021) applies to the whole screen.
|
||||
- Screen memory is 1 KB ($0400-$07FF); Color RAM is 1000 nibbles ($D800-$DBE7).
|
||||
- Character patterns are 8 bytes per character, fetched from the character generator (default is the 4 KB character ROM at $D000-$DFFF, but can be relocated to RAM).
|
||||
- Soft scrolling is "easier" in character mode than in bitmap mode (just change XSCROLL/YSCROLL).
|
||||
|
||||
## Multicolor Character Mode (Mode 1)
|
||||
|
||||
- Each cell still 8×8, but only 4×8 in effective pixel resolution (each pair of bits in the character pattern is one "wide pixel").
|
||||
- Up to 4 colors per cell: the two global background colors ($D021 and $D022) plus the cell's color RAM color and the multicolor-1 shared color $D026.
|
||||
- "Color" bits %00/%01/%10/%11 map to: background 0 ($D021), background 1 ($D022), color RAM, background 2 ($D023). Pattern bit pairs.
|
||||
|
||||
## Standard Bitmap Mode (Mode 2) — "hires"
|
||||
|
||||
- 320×200 pixels, 1 bit per pixel.
|
||||
- Bitmap is 8000 bytes. Location selected by bits VM13-VM10 of $D018 (in 8 KB steps within the 16 KB VIC bank). Video matrix (screen memory) is 1 KB at $D018's VM bits (in 1 KB steps).
|
||||
- Color: each 8×8 cell is monochrome (foreground from color RAM nibble, background from $D021).
|
||||
- BM=1: the video matrix contains *color* information instead of character codes, so color RAM is doubled up to provide per-cell background and foreground colors (the color RAM holds the cell's foreground; the cell's background is one of the 4 global "background color" registers $D021-$D024 in the 4 most-significant bits of the cell).
|
||||
|
||||
## Multicolor Bitmap Mode (Mode 3)
|
||||
|
||||
- 160×200 pixels, 2 bits per pixel (4 colors per 4×8 cell).
|
||||
- Each pair of bits selects from: background 0 ($D021), background 1 ($D022), background 2 ($D023), color RAM cell color.
|
||||
- Same memory layout as Standard Bitmap Mode (8000 bytes bitmap + 1 KB matrix).
|
||||
|
||||
## Extended Background Color Mode (Mode 4)
|
||||
|
||||
- Character mode (not bitmap) with 4 background colors instead of 1.
|
||||
- Each character cell can select one of the 4 background colors ($D021-$D024) via 2 bits in its screen memory code.
|
||||
- Useful for colored PETSCII art.
|
||||
|
||||
## Unofficial "modes" (demo scene techniques)
|
||||
|
||||
There are dozens of techniques that go beyond the official modes by exploiting undocumented VIC behavior or combining tricks like raster IRQ, sprites, and interlacing. The most famous families:
|
||||
|
||||
- **FLI** (Flexible Line Interpretation, July 1989) — forces a badline every line, allowing per-line color attributes. The first "demo scene" graphic hack.
|
||||
- **IFLI** (Interlaced FLI, 1991) — combines FLI with 2-frame interlace.
|
||||
- **AFLI** (Advanced FLI, 1990), **NUFLI** (2009), **MUFLI** (2006), **UFLI** (1996), **XFLI** (2002), **SHFLI** (1996), etc.
|
||||
- **AFLI** and **UFLI** give 8+ colors per 8×8 cell, **NUFLI** adds even more.
|
||||
- **SHI** (Super HiRes Interlace, 1991) — interlaced 320×400 mode.
|
||||
- **Hyperscreen** — stable display using all 16 KB VIC bank by abusing badline tricks.
|
||||
- **FLD** (Flexible Line Distance) — variation.
|
||||
- **Megatext** (2004) — large character set mode.
|
||||
|
||||
(See `vic/cebix-vic-article.txt` for the technical underpinnings of these tricks, especially sections 3.14 "Effects and applications" and 3.5 "Bad Lines".)
|
||||
@@ -0,0 +1,56 @@
|
||||
# VIC-II (Video Interface Chip II)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/VIC
|
||||
|
||||
## Identification
|
||||
|
||||
VIC-II is the video chip used in the C64 / C128 family. There are two VIC-II types in the C64: the 6567 in NTSC machines and the 6569 in PAL machines. Newer C64 versions use the functionally equivalent 8562 (NTSC) and 8565 (PAL) chips.
|
||||
|
||||
## Features
|
||||
|
||||
- 16 kB address space for screen, character and sprite memory
|
||||
- 320 × 200 pixels video resolution (160 × 200 in multi-color mode)
|
||||
- 40 × 25 characters text resolution
|
||||
- Three character display modes and two bitmap modes
|
||||
- 16 colors
|
||||
- Concurrent handling of 8 sprites per scanline, each of 24 × 21 pixels (12 × 21 multicolor)
|
||||
- Raster interrupt
|
||||
- Smooth scrolling
|
||||
- Independent dynamic RAM refresh (an unusual feature for a graphics processor)
|
||||
- Bus mastering for a 6502-style system bus; CPU and VIC-II accessing the bus during alternating half-clock cycles (the VIC-II will halt the CPU when it needs extra cycles)
|
||||
|
||||
## Memory Addresses of the VIC-II
|
||||
|
||||
| Hex Address | Dec Address | Page | Contents |
|
||||
|-------------|-------------|------|----------|
|
||||
| $D000-$D3FF | 53248-54271 | Page 208-211 | VIC-II registers |
|
||||
| $D800-$DBE7 | 55296-56295 | Page 216-219 | Color RAM |
|
||||
|
||||
- Sprites lie at address MEM(Start of screen mem + $03F8 + sprite number)*64
|
||||
- The start of the Screen RAM is set by $DD00 (the VIC bank, see CIA 2) and $D018.
|
||||
|
||||
## Technical Notes (from Christian Bauer's article)
|
||||
|
||||
The operation of the VIC-II is thoroughly described in the document
|
||||
"The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64"
|
||||
by Christian Bauer. See `vic/cebix-vic-article.txt` for the full text.
|
||||
|
||||
Key facts:
|
||||
- The cycle count starts at 1; for example, VICE starts counting at 0.
|
||||
- Writing to $D011/$D012 can immediately trigger a raster IRQ, provided no raster IRQ has yet been triggered in the current line.
|
||||
- The vertical "expansion flip-flop" is somewhat misleadingly named; its state actually indicates whether a line in the sprite data should currently be skipped or not.
|
||||
- VCBASE and MCBASE are used to reset VC and MC to their initial values.
|
||||
- VMLI is not a pointer but rather a 40-bit shift register that controls the 40 enable bits of the VIC-II's internal "40×12 bit video matrix/color line."
|
||||
|
||||
## Known Variants
|
||||
|
||||
- MOS 6560 / 6561: VIC-I (VIC-20)
|
||||
- MOS 6566: VIC-II for MAX Machine
|
||||
- MOS 6567: VIC-II for (NTSC) C64
|
||||
- MOS 6569: VIC-II for (PAL) C64 (R1/R3/R4/R5)
|
||||
- MOS 6572/6573: VIC-II (PAL-N/PAL-M)
|
||||
- MOS 8562: VIC-II (NTSC) for later C64 / C128
|
||||
- MOS 8564/8565/8566/8569: VIC-II variants for C64 / C128
|
||||
- CSG 4567: VIC-III (C65/C64DX)
|
||||
|
||||
The NMOS variants 6566/67/69 require +12V on Pin 13/Vdd; the HMOS-II variants (8562/65) require only +5V DC. The 856x variants exhibit the "Grey Dots" problem.
|
||||
@@ -0,0 +1,68 @@
|
||||
# VIC-II Register Map ($D000–$D3FF)
|
||||
|
||||
Source: https://www.c64-wiki.com/wiki/Page_208-211
|
||||
|
||||
Page 208-211 covers the memory locations 53248-54271 ($D000-D3FF). This area is wholly reserved for the VIC-II Registers. The 47 registers are mirrored every 64 bytes in this area.
|
||||
|
||||
## Register Table
|
||||
|
||||
| Hex | Dec | Type | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 | Contents |
|
||||
|------|------|----------|------|------|------|------|------|------|------|------|----------|
|
||||
| $D000 | 53248 | Register | | | | | | M0X | | | X Coordinate Sprite 0 |
|
||||
| $D001 | 53249 | Register | | | | | | M0Y | | | Y Coordinate Sprite 0 |
|
||||
| $D002 | 53250 | Register | | | | | | M1X | | | X Coordinate Sprite 1 |
|
||||
| $D003 | 53251 | Register | | | | | | M1Y | | | Y Coordinate Sprite 1 |
|
||||
| $D004 | 53252 | Register | | | | | | M2X | | | X Coordinate Sprite 2 |
|
||||
| $D005 | 53253 | Register | | | | | | M2Y | | | Y Coordinate Sprite 2 |
|
||||
| $D006 | 53254 | Register | | | | | | M3X | | | X Coordinate Sprite 3 |
|
||||
| $D007 | 53255 | Register | | | | | | M3Y | | | Y Coordinate Sprite 3 |
|
||||
| $D008 | 53256 | Register | | | | | | M4X | | | X Coordinate Sprite 4 |
|
||||
| $D009 | 53257 | Register | | | | | | M4Y | | | Y Coordinate Sprite 4 |
|
||||
| $D00A | 53258 | Register | | | | | | M5X | | | X Coordinate Sprite 5 |
|
||||
| $D00B | 53259 | Register | | | | | | M5Y | | | Y Coordinate Sprite 5 |
|
||||
| $D00C | 53260 | Register | | | | | | M6X | | | X Coordinate Sprite 6 |
|
||||
| $D00D | 53261 | Register | | | | | | M6Y | | | Y Coordinate Sprite 6 |
|
||||
| $D00E | 53262 | Register | | | | | | M7X | | | X Coordinate Sprite 7 |
|
||||
| $D00F | 53263 | Register | | | | | | M7Y | | | Y Coordinate Sprite 7 |
|
||||
| $D010 | 53264 | Register | M7X8 | M6X8 | M5X8 | M4X8 | M3X8 | M2X8 | M1X8 | M0X8 | MSBs of X coordinates |
|
||||
| $D011 | 53265 | Register | RST8 | ECM | BMM | DEN | RSEL | YSCROLL | | | Control register 1 |
|
||||
| $D012 | 53266 | Register | | RASTER | | | | | | | Raster counter |
|
||||
| $D013 | 53267 | Register | | LPX | | | | | | | Light pen X |
|
||||
| $D014 | 53268 | Register | | LPY | | | | | | | Light pen Y |
|
||||
| $D015 | 53269 | Register | M7E | M6E | M5E | M4E | M3E | M2E | M1E | M0E | Sprite enabled |
|
||||
| $D016 | 53270 | Register | - | - | RES | MCM | CSEL | XSCROLL | | | Control register 2 |
|
||||
| $D017 | 53271 | Register | M7YE | M6YE | M5YE | M4YE | M3YE | M2YE | M1YE | M0YE | Sprite Y expansion |
|
||||
| $D018 | 53272 | Register | VM13 | VM12 | VM11 | VM10 | CB13 | CB12 | CB11 | - | Memory pointers |
|
||||
| $D019 | 53273 | Register | IRQ | - | - | - | ILP | IMMC | IMBC | IRST | Interrupt register |
|
||||
| $D01A | 53274 | Register | IRQ | - | - | - | ELP | EMMC | EMBC | ERST | Interrupt enabled |
|
||||
| $D01B | 53275 | Register | M7DP | M6DP | M5DP | M4DP | M3DP | M2DP | M1DP | M0DP | Sprite data priority |
|
||||
| $D01C | 53276 | Register | M7MC | M6MC | M5MC | M4MC | M3MC | M2MC | M1MC | M0MC | Sprite multicolour |
|
||||
| $D01D | 53277 | Register | M7XE | M6XE | M5XE | M4XE | M3XE | M2XE | M1XE | M0XE | Sprite X expansion |
|
||||
| $D01E | 53278 | Register | M7M | M6M | M5M | M4M | M3M | M2M | M1M | M0M | Sprite-sprite collision |
|
||||
| $D01F | 53279 | Register | M7D | M6D | M5D | M4D | M3D | M2D | M1D | M0D | Sprite-data collision |
|
||||
| $D020 | 53280 | Register | - | - | - | - | EC | | | | Border colour |
|
||||
| $D021 | 53281 | Register | - | - | - | - | B0C | | | | Background colour 0 |
|
||||
| $D022 | 53282 | Register | - | - | - | - | B1C | | | | Background colour 1 |
|
||||
| $D023 | 53283 | Register | - | - | - | - | B2C | | | | Background colour 2 |
|
||||
| $D024 | 53284 | Register | - | - | - | - | B3C | | | | Background colour 3 |
|
||||
| $D025 | 53285 | Register | - | - | - | - | MM0 | | | | Sprite multicolour 0 |
|
||||
| $D026 | 53286 | Register | - | - | - | - | MM1 | | | | Sprite multicolour 1 |
|
||||
| $D027 | 53287 | Register | - | - | - | - | M0C | | | | Sprite 0 colour |
|
||||
| $D028 | 53288 | Register | - | - | - | - | M1C | | | | Sprite 1 colour |
|
||||
| $D029 | 53289 | Register | - | - | - | - | M2C | | | | Sprite 2 colour |
|
||||
| $D02A | 53290 | Register | - | - | - | - | M3C | | | | Sprite 3 colour |
|
||||
| $D02B | 53291 | Register | - | - | - | - | M4C | | | | Sprite 4 colour |
|
||||
| $D02C | 53292 | Register | - | - | - | - | M5C | | | | Sprite 5 colour |
|
||||
| $D02D | 53293 | Register | - | - | - | - | M6C | | | | Sprite 6 colour |
|
||||
| $D02E | 53294 | Register | - | - | - | - | M7C | | | | Sprite 7 colour |
|
||||
| $D02F-$D03F | 53295-53311 | Unused | ($FF on read, ignored on write) | | | | | | | | |
|
||||
| $D040-$D3FF | 53312-54271 | Same as $D000-$D03F (mirror every 64 bytes) | | | | | | | | | |
|
||||
|
||||
## Notes
|
||||
|
||||
- The bits marked with '-' are not connected and give "1" on reading.
|
||||
- The registers $D01E and $D01F cannot be written and are automatically cleared on reading.
|
||||
- The RES bit (bit 5) of register $D016 has no function on the VIC 6567/6569. On the 6566, this bit is used to stop the VIC.
|
||||
- Bit 7 in register $D011 (RST8) is bit 8 of register $D012. Together they are called "RASTER". A write access to these bits sets the comparison line for the raster interrupt.
|
||||
</content>
|
||||
</invoke>
|
||||
Reference in New Issue
Block a user