La mappa di memoria del C/64

Programmare il C/64 era complicato per diverse ragioni:

  1. Il Basic V2 era troppo lento per scrivere giochi effettivi
  2. La maggior parte delle feature richiedevano di scrivere direttamente su celle di memoria mappate sui chip audio e video, spesso cambiando singoli bit.
  3. La mappa di memoria del C/64 era abbastanza complessa


Mappa di memoria dal C64Wiki

Premessa: il MOS 6502 non ha istruzioni di I/O dedicate, anche se aveva linee di I/O molto complesse da gestire (vedi le locazioni $00 e $01 del C/64 che per es pilotano il nastro e l’I/O).

Commodore penso’ di  mappare i registri I/O dei chip del C/64 direttamente sulla RAM. Questo semplificava anche la scrittura del software, solo che… gli altri microcomputer (es Vic20 o C/16) non avevano cosi’ tanta memoria… e quindi non era un problema mappare questi registri nello spazio di indirizzamento da 64Kb, ne’ mappare le ROM. Per prendere anche una architettura diversa,  lo ZX Spectrum  aveva “solo” 48Kb RAM e teneva la ROM in quello che restava (16Kb)

Il C/64 veniva fornito con un quantitativo di RAM enorme, che riempiva tutto lo spazio di indirizzamento del 6502,: si trattava di una scommessa fatta (e vinta) da Commodore che confidava sulla riduzione dei costi dei chip di memoria RAM statica.

Per cui la ROM era “mappata” sullo spazio di indirizzamento del 6502, e quindi la ROM del BASIC e de Kernal poteva essere “rimpiazzata” dalla RAM sottostante (Bank Switching).

Tutto questo era gestito attraverso la locazione $01, che pilotava un chip chiamato Programmable Logic Array  (PLA, peraltro uno dei chip custom del C/64).

In particolare ecco la semantica della locazione $01:

Bit 0 - LORAM: Configures RAM or ROM at $A000-$BFFF
Bit 1 - HIRAM: Configures RAM or ROM at $E000-$FFFF
Bit 2 - CHAREN: Configures I/O or ROM at $D000-$DFFF
Bit 3 - Cassette Data Output Line (Datasette)
Bit 4 - Cassette Switch Sense; 1 = Switch Closed
Bit 5 - Cassette Motor Control; 0 = On, 1 = Off
Bit 6 - Undefined
Bit 7 - Undefined

I 4Kb in $D000-DFFF hanno un triplo bank switching: in questi 4KB trovate sia la maggior parte dei registri di I/O,  la ROM dei caratteri e ALTRI 4 Kb di VERA RAM.

Peccato che per accedere alla RAM in $D000 si deve per forza disattivare anche il Kernal in $E000-$FFFF e quindi il suo utilizzo non risulta agevolissimo (questo schema mostra tutte le configurazioni).
Rinunciare al Kernal non e’ agevole perche’ gli interrupt (mascherabili (IRQ) e non (NMI)) hanno bisogno delle routine di gestione, e queste stanno proprio nel Kernal.

La CHAR ROM e’ “posizionata” in $D000 solo ad uso e consumo del 6502: il VIC-II usa un modo completamente diverso per indirizzare la memoria perche’ puo’ indirizzare solo 16k di RAM alla volta.  Siccome 16×4 fa 64, ci sono solo 4 “banchi” in cui e’ segmentata la memoria per il VIC-II e bastano due bit per dirgli che banco “guardare”.

In due di queste quattro modalita’ la CHAR ROM e’ visibile al VICII, e non c’e’ bisogno di mapparla nello spazio di indirizzamento del C/64. La CHAR ROM e’ accessibile in $D000 nel caso serva ai programmi applicativi, per es per “copiarla” in memoria e fare solo piccole modifiche.

Un bel caos giusto?

Infine di DEFAULT, la memoria video del C/64 per la modalita’ caratteri e’ rilocata in $0400 (dec 1024) per 1000 byte (=40×25).

Le cartucce

Le cartucce (CART ROM) possono mappare fino a tre aree per un totale di 3×8=24Kb,ma devono di norma coprire l’area da $8000 perche’ al BOOT il kernal cerca li’ la signature che scatena il lancio per consentire alla cartuccia di partire. In particolare in $8004–$8008 deve esserci la stringa “CBM80” che fa si’ che il Kernal faccia un salto indiretto all’indirizzo posto in $8000-8001.

 

Ciliegina sulla torta, non trovate proprio tutti gli I/O in $D000-DFFF, perche’ alcune sono sulle locazioni $00- $01 e alcune si trovano sul registro SID (!) per es il potenziometro per alcuni dispositivi come i paddle gioco.