C64 Bedtime Coding (ITA) – Print AT (#09)

(Article by Phaze101)

Introduzione

Le mie scuse

Ho bisogno di scusarmi con tutti voi per il ritardo nella pubblicazione di questo articolo. Ho saltato la data che avevo pianificato.  Come sempre la vita si è messa in mezzo, soprattutto il lavoro. Ho avuto anche altri impegni che trascuravo da tempo. Il codice di questo articolo era pronto immediatamente dopo l’articolo 8, ma trovare del tempo per commentarlo ha richiesto più di quanto avessi previsto.

Un altro motivo per cui questo articolo ha richiesto più tempo è dovuto alla preparazione del codice, che ha richiesto maggiori ricerche ed è piuttosto lungo.

Per tutti questi motivi, i futuri articoli saranno rilasciati senza programmazione e non tutti i sabati. Tuttavia, quando ci sarà un nuovo articolo in inglese, sarà sempre di sabato. La versione in italiano sarà pubblicata qualche giorno dopo.

Pastebin

Sarete felici di sapere che da oggi il codice è su Pastebin.

Quindi, per quelli che amano il copia e incolla, sappiate che avete anche questa opzione. Potrei anche inserire il codice precedente, dipende dal tempo che avrò a disposizione.

Github

In futuro, potrei anche usare Github dal momento in cui ci saranno da caricare la grafica, i suoni e molto altro, cosa che Pastebin non permette. Senza dubbio è meglio avere tutto in un’unica cartella.

Print At

Dal precedente articolo

Il Commodore 64 non ha un comando Print At (Stampa A) in Basic, ma si può ottenere con metodi diversi.

Nell’articolo 8, abbiamo visto come attraverso l’uso di alcune routine come SetCursor (\$E50C) e PrintString (\$AB1E) siamo stati capaci di dire al computer di stampare una stringa in una posizione precisa. Tuttavia, io ritengo che questa strada sia veramente lenta, anche se eseguita in assembly. Abbiamo quindi bisogno di essere più veloci nella stampa nello schermo.

Per raggiungere il nostro obiettivo, dobbiamo costruire la nostra routinr Print At ed è quello che vi mostrerò in questo articolo.

I concetti del Print At

Sappiamo che lo schermo comincia alla locazione \$0400 di default sul C64. Sappiamo anche che lo schermo è composto da 40 caratteri per 25 linee che possono essere considerati come 40 colonne per 25 righe.

Immaginiamo di voler stampare le famose parole “Phaze 101” intorno alla 13-ma riga e alla 16-ma colonna che rappresentano il centro dello schermo. Per rendere semplici i calcoli, cominceremo a contare le colonne e le righe da 0 e di conseguenza cominceremo a stampare dalla riga 12 e colonna 15.

Per calcolare lo scostamento nel buffer dello schermo, dobbiamo prima moltiplicare 12 per 40 (12 righe per 40 caratteri). Il risultato ci darà la posizione del primo carattere che rappresenta il carattere più a sinistra della colonna (0) nella riga 12 (la 13-ma riga). Per prendere la colonna desiderata, aggiungiamo 15. Alla fine, aggiungiamo il risultato all’ indirizzo di base dello schermo che è \$0400 (1024) e dovremmo avere la posizione di partenza in cui scrivere il primo carattere.

Riassumiamo:

  1. 12 * 40 = 480 ;12 righe per 40 caratteri.
  2. + 15 = 495 ;nella 13-ma riga partiamo dalla colonna 14 e per questo lo sommiamo.
  3. + 1024 = 1519  ;base dello schermo è \$0400 che è 1024 e per questo lo sommiamo.

Se cominciamo a scrivere la nostra stringa nella locazione di memoria 1519, dovremmo leggere “Phaze 101” stampato in mezzo allo schermo.

Addizione e moltiplicazione

È più facile a dirsi che a farsi. Come si può fare l’addizione e la moltiplicazione nel linguaggio di programmazione assembly 6502 quando ogni byte può contenere 256 valori?

Questo tema sarà trattato in futuro in uno specifico articolo, poiché è abbastanza importante, per adesso parliamo solo di numeri.

Per prima cosa andrò a semplificare utilizzando l’addizione dappertutto dove necessita. Poi, come secondo passo, userò 2 byte per calcolare e salvare il nostro risultato. Con 2 byte abbiamo da 0 a 65535 possibili valori.

Possiamo ottenere la moltiplicazione sommando 40 per 12 volte. Noterete che sto utilizzando questo metodo perché non ho spiegato precedentemente le operazioni matematiche in assembly. Ci sono altri modi per farlo, tuttavia, per raggiungere il nostro obiettivo, cioè di stampare nello schermo, questo metodo è più che sufficiente.

Somma dei numeri in Assembly

Per sommare numeri in 6502 assembly dobbiamo introdurre le seguenti istruzioni: CLD, CLC, ADC.

CLD significa Clear Decimal Flag (Pulizia del flag decimale). Utilizziamo questa istruzione per essere sicuri che la CPU non sta utilizzando la modalità decimale. Copriremo questo argomento dettagliatamente in un futuro articolo.

CLC significa Clear Carry Flag (Pulizia del flag di riporto). Prima di cominciare a sommare nel linguaggio assembly del 6502, devi essere sicuro che il Carry Flag di una addizione precedente non venga sommato alla prossima addizione.

ADC significa ADD (somma) con riporto. L’istruzione somma il contenuto della locazione di memoria o un numero in forma immediata nel registro accumulatore. Se il flag di riporto è valorizzato (per esempio dalla precedente addizione) allora il risultato sarà incrementato di 1. Per esempio, quando A è zero e il Carry Flag è vuoto, ADC #\$04 memorizza \$04 nell’accumulatore. Se il Carry Flag è valorizzato allora l’accumulatore conterrà \$05.

Il risultato di ADC è memorizzato nell’accumulatore ed è necessario salvarlo nella memoria utilizzando STA.

Addizione a 8 Bit

Esaminiamo più in profondità il Carry Flag nell’addizione a 8 bit. Nell’esempio che tratteremo, il Carry Flag non è valorizzato.

Il risultato dell’addizione può essere memorizzato in un byte. In questo caso, il Carry Flag è vuoto.

Adesso diamo uno sguardo a qualcosa che valorizzerà il Carry Flag.

Il risultato della precedente addizione non può essere inserito in un byte. La parte del risultato che può essere inserita nell’accumulatore è \$8c che sono i byte meno significativi (lower byte). Il nono bit del risultato che non può essere inserito nell’accumulatore è salvato nel Carry Flag.

Di seguito il codice per l’addizione di un byte dove lasciamo il valore nel Carry Flag.

Dov’è finito il valore di riporto? Beh, il riporto è ancora valorizzato nel Carry Flag e abbiamo bisogno di qualcosa che ci indichi come salvarlo.

 

Addizione a 16 Bit

La soluzione al precedente problema è l’uso di 2 byte e infatti salviamo il Carry Flag nel secondo byte.

Diamo uno sguardo al programma con addizione di numeri a 16 bit. Da notare che questo concetto può essere esteso a 24 bit (3 byte) e numeri a 32 bit (4 byte).

Supponiamo che la locazione di memoria \$00FB contenga \$FF e \$00FC contenga \$0.

Qui abbiamo il programma che effettuerà la somma di \$8D nella locazione di memoria \$00FB è salverà il Carry Flag in \$00FC.

Questo salverà il risultato \$8C in \$FB e \$01\$ in FC che sarà reso un numero a 2 byte o numero a 16 bit.

La parte più importante e degna di nota è che ADC significa somma l’accumulatore e il Carry (riporto). Anche se l’accumulatore è 0, se il Carry Flag è valorizzato allora abbiamo ancora 1.

Torniamo al codice

Ora che conosciamo come addizionare a 16 bit, possiamo tornare indietro al codice del nostro Print At.

Qui abbiamo il codice completo su Pastebin

https://pastebin.com/QQgLYFEX

Routine principale

La main routine chiama 5 subroutines. Quattro di queste 5 subroutines prendono i parametri nei registri. Ho scritto queste routine per favorire anche la scrittura delle vostre personali routine.

La prima è la SetBgBorder, che imposta i colori dello sfondo e del bordo. Il registro X è usato per definire il colore di sfondo e il registro Y è utilizzato per definire il colore del bordo.

La prossima subroutine è la ClearScreen che pulisce lo schermo con il valore contenuto nell’accumulatore che in questo caso è lo spazio.

La prossima è SetCurs. Ha bisogno di un valore Y (linea o numero di riga che parte da 0) dello schermo nel registro Y e il valore X (numero di colonna che parte da 0) nel registro X. In questo caso possiamo passare il numero 12 e la colonna numero 9. Guarderemo questa routine più dettagliatamente in seguito.

La prossima subroutine è la PrintAt. La useremo per indicare dove vogliamo locare la stringa da stampare, passandole i bit meno significativi e bit più significativi rispettivamente dai registri A e Y. Dopo ne sapremo di più.

L’ultima routine è la classica routine di attesa di pressione della barra spaziatrice.

Spiegherò solo le routine SetCurs e la PrintAt, poiché le altre sono state dettagliate nei precedenti articoli.

La subroutine SetCurs

Alla fine della routine troverete tre locazioni di parole (2 byte): Buf1, Buf2 e Buf3. La prima è inizializzata con il valore base dello schermo \$0400. Le altre sono entrambe settate a zero in questo momento.

Ognuno dei tre passi della formula che abbiamo visto precedentemente è una sezione della routine indicata con dei commenti.

Linee dalla 105 alla 114

Questa è la stessa routine di addizione che abbiamo visto prima (linee dalla 105 alla 112), tuttavia facciamo questo ciclo 12 volte e ogni volta sommiamo 40 (\$28). Il risultato dell’addizione è salvato in Buf2 in modalità 16 bit o 2 byte.

Linee dalla 118 alla 125

Nuovamente abbiamo utilizzato l’addizione come somma di numeri di colonna che sono passati dal registro X a Buf2.

Linee dalla 129 alla 137

Stiamo sommando il numero di Buf1 che è il valore di inizio dello schermo con lo scostamento salvato in Buf2 e salveremo il risultato in Buf3.

Buf3 contiene l’indirizzo dello schermo da dove cominciare a scrivere nello schermo.

Subroutine PrintAt

Questa routine è attualmente una routine di copia, cioè copierà il contenuto da una locazione di memoria (dove è contenuta la stringa) in un’altra che è la locazione di memoria dello schermo.

Linee dalla 153 alla 154

Qui stiamo inizializzando l’indirizzo di pagina zero \$00FB e \$00FC con l’indirizzo sorgente che è l’indirizzo della nostra stringa.

Linee dalla 156 alla 159

Qui stiamo inizializzando l’indirizzo di pagina zero \$00FD e \$00FE con l’indirizzo di destinazione che è contenuto in Buf3, cioè da dove inizieremo a scrivere nello schermo. Il valore è ottenuto dal calcolo della precedente chiamata a SetCurs.

Linee dalla 161 alla 169

 

Questo è il codice che copia. Copieremo la stringa nello schermo fino ad incontrare il byte zero. Noterete che la lunghezza massima della stringa è di 256 caratteri.

Qui abbiamo l’output, ricordatevi di inserire SYS 49152 per lanciare il programma.

Il prossimo articolo

È tutto per adesso. Continueremo nel prossimo articolo con la PrintAt avanzata, oltre questo non ho ancora deciso.

Ho in mente 3 argomenti che necessitano di essere dettagliati:

  • Colore
  • Addizione, sottrazione, moltiplicazione, divisione di numeri a 16-bit
  • Numeri casuali

Come sempre, se avete qualche domanda per favore scrivetemi.

Coding is Fun 😊

Phaze 101

Thanks Go To

 

English proofreading: Colin Vella

Translation to Italian: Davide Aldegheri

Italian proofreading: David La Monaca

Other team members: Pinov Vox and John Sherwood

 

Retro Programming Italia

 

You can also read all previous articles on SYS32768.ORG

 

Articolo 8
https://sys64738.org/2019/05/c64-bedtime-coding-ita-stampare-sullo-schermo-08/

Articolo 7
https://sys64738.org/2019/05/c64-bedtime-coding-ita-cancellare-lo-schermo-07/

Articolo 6
https://sys64738.org/2019/04/c64-bedtime-coding-ita-primi-passi-06/

Articolo 5
https://sys64738.org/2019/04/c64-bedtime-coding-ita-il-set-di-istruzioni/

Articolo 4
https://sys64738.org/2019/03/c64-bedtime-coding-ita-modalita-di-indirizzamento-04/

Articolo 3
https://sys64738.org/2019/03/c64-bedtime-coding-ita-i-registri-della-cpu-03/

Articolo 2
https://sys64738.org/2019/03/c64-bedtime-coding-ita-linguaggio-macchina-02/

Articolo 1
https://sys64738.org/2019/03/c64-bedtime-coding-introduzione-e-basi-01/

 

Have your say