Per quanto riguarda il NES (e anche il SNES per lo più), ecco una panoramica di base. Non ho scritto alcun gioco NES, ma ho scritto un emulatore NES (Graybox) e ho fatto un bel po 'di reingegnerizzazione di vecchi carrelli.
Per quanto riguarda il linguaggio di programmazione: sì, era tutto assemblato. Programmare il NES significava lavorare direttamente con interrupt di processo, porte DMA, commutazione di banchi ecc. Fortunatamente, programmare il 6502 (o meglio, il 2A03) è abbastanza semplice [1]:
- ci sono pochi registri: principalmente A, X e Y, gli ultimi due sono utilizzabili solo per indicizzazione e iterazione
- il set di istruzioni è piccolo e per lo più semplice
- poca memoria: la RAM principale è di 2 KB, con un'estensione opzionale da 8 KB alimentata a batteria. Di quei 2 KB, 256 byte sono riservati per lo stack e la pagina 0 (i primi 256 byte) era il punto in cui si desidera archiviare i puntatori e i valori più utilizzati a causa di alcune modalità di indirizzamento speciali
Queste 3 cose insieme creano un ambiente abbastanza facile da memorizzare mentre ci si lavora. Sì, gestisci tu stesso tutta la memoria, ma ciò significa essenzialmente che crei una mappa completa di dove tutto va avanti e quella mappa non è molto grande perché devi solo preoccuparti di 2K, quindi puoi tracciarlo su un pezzo di carta millimetrata. Dovevi pianificare un po 'di più le cose e assegnare staticamente variabili e costanti alle posizioni RAM e ROM (sulla cartuccia).
Diventa un po 'più complicato quando i dati della cartuccia superano i limiti indirizzabili della CPU. Sono 64 KB, di cui i 32 KB inferiori sono impostati in pietra e mappati su tutti i tipi di porte hardware e RAM. È qui che entra in gioco il cambio di banco, il che significa mappare una sezione della ROM nello spazio degli indirizzi di 32 KB (parte di) superiore.
Questo può essere usato nel modo desiderato dal programmatore, ma un esempio potrebbe essere quello di avere un gioco con 3 livelli, con tutti i dati di livello, i metadati e il codice per ogni livello stipati in aree di memoria separate da 8 KB sulla cartuccia. Il livello potrebbe avere callback per es. Inizializzazione, aggiornamento per frame, ecc. "Caricamento" del livello significherebbe mappare quel pezzo di memoria da 8 KB ad es. 0xC000. È quindi possibile specificare che la routine init è sempre a 0xC000, la routine di aggiornamento dei frame è a 0xC200 e i dati di livello iniziano a 0xC800. Il codice principale del gioco contenuto in un altro blocco di memoria controlla quindi i cambiamenti di livello semplicemente scambiando il blocco giusto e saltando agli indirizzi assoluti 0xC000 e 0xC200 nei momenti appropriati.
Dati grafici scritti: i dati dei riquadri del NES sono mappe di pixel 8x8 a 2 bit. Per lo sfondo sono combinati con uno strato da 2 bit a risoluzione 1/4. Questi valori a 4 bit sono stati quindi indicizzati in una tavolozza a 16 voci, con credo che siano disponibili 53 colori unici efficaci. Gli sprite hanno anche usato i dati dei pixel a 2 bit e ogni sprite ha nuovamente specificato il proprio indice di gruppo a 2 bit formando un indice pal a 4 bit. L'immagine BG sullo schermo è una matrice 32x30 di numeri indice di piastrelle.
In sostanza, avendo una tonnellata di ripetizioni e indici in indici è possibile mantenere i dati molto piccoli. I dati di livello venivano spesso memorizzati come barre verticali di indici di riquadri e poiché anche quelle barre verticali venivano riutilizzate, anche quelle venivano indicizzate e archiviate una sola volta sulla cartuccia. Semplici tecniche di compressione dei dati funzionano in modo simile. Ciò ha permesso a Mario 1 di avere 32 KB di dati (con spazio libero) e 8 KB di dati bitmap.
Per quanto riguarda gli ambienti di sviluppo, ho visto alcune foto in cui le persone lavoravano su alcuni computer certificabilmente antichi collegati ai masterizzatori EEPROM per lavoro. Il debug con strumenti non era realmente possibile fino all'età SNES [2]. Questo è il motivo principale per cui molti vecchi giochi hanno bug "ovvi" e perché cose come Gameshark potrebbero fare quello che fanno; la salute del giocatore sarà sempre nella posizione mem X, quindi puoi forzarla a 100 in ogni momento.
Se trovi interessanti queste cose, ti incoraggio a consultare, ad esempio, http://wiki.nesdev.com/w/index.php/Nesdev_Wiki
Ci sono alcuni corsi di programmazione per NES che possono essere trovati anche online.
Spero che questa panoramica semplificata abbia dato un'idea dello sviluppo del gioco degli anni '80.
[1] Relativamente parlando. Inoltre sono di parte mentre scrivevo Graybox stesso in circa l'85% di assemblaggio PowerPC. [2] Vedi la realizzazione dell'articolo FF6: http://www.edge-online.com/features/the-making-of-final-fantasy-vi/