Initial commit: C64 project skeleton with oscar64 submodule

This commit is contained in:
ballz
2026-07-17 00:36:14 +02:00
commit cbe5cf6a47
31 changed files with 29332 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+74
View File
@@ -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".)
+56
View File
@@ -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.
+68
View File
@@ -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>