Initial commit: C64 project skeleton with oscar64 submodule
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user