Autore Topic: Esercizio Con Caratteri Su Schermo  (Letto 7209 volte)

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« il: 14 Giugno 2014, 14:48:01 »
 Innanzitutto un saluto a tutti voi di questa comunità.
Mi presento come un nostalgico commodoriano e degli anni che furono per il quale , come suggerisce nickname che vedete qui a fianco non è mai troppo tardi nella vita ed è sempre meglio tardi che mai.
Per cui ho deciso di avventurarmi nello studio degli argomenti che sempre hanno catturato la mia attenzione , fascino e curiosità: primo fra tutti il linguaggio assembly del 6510.
Dopo aver selezionato un pò di bibliografia sull'argomento in .pdf o cartaceo che ho deciso di tener d'occhio e a portata di mano per un successivo studio mi sono imbattuto nel tutorial di assembler di Hex Files.

http://www.oldschool-gaming.com/articles_i...w=c64_hex_files

Ho avuto modo di studiare la prima e la seconda puntata senza alcun problema ma non appena ho iniziato la terza parte di questo,a mio avviso semplice e pratico tutorial, sono incominciati a venirmi i primi dubbi.
Ragion per cui non sapendo più dove andare a sbattere la testa ho deciso di sottoporre alla attenzione di tutti voi il primo esercizio della terza puntata che mi ha lasciato letteralmente "inchiodato".


                                       *= $0900
MAIN                               LDX #$00
MOVELOOP                       LDA $0401,X
                                       STA $0400,X
                                       INX
                                       CPX #$27
                                       BNE MOVELOOP
                                       INC $0427
                                       JMP MAIN

Bene... inizio subito ad esporre a voi quello che mi è parso chiaro e semplice per poi passare in rassegna i miei dubbi e a porvi qualche domanda nella speranza di riuscire a capire il funzionamento e la logica di questo breve listato.
Il programma ha due cicli il primo con la label MAIN il secondo con la label MOVELOOP. Iniziando dalla prima istruzione del primo ciclo il programma per prima cosa azzera il registro X dopodicché inizia il secondo ciclo che al primo giro vede il registro X con valore zero e legge il contenuto della locazione $0401 ( 1025 ) e lo trasferisce nella locazione precedente $0400 ( 1024 ). Fatto ciò il registro X viene incrementato di 1 e il programma salta di nuovo alla label del MOVELOOP e prosegue i vari cicli finquando il valore di X non abbia raggiunto il valore di #$27 ossia di 40 ( che corrisponde alla posizione sullo schermo della prima riga e della colonna 39 ).
In pratica fino a  quando il cursore, diciamo ,arriva alla posizione dell'angolo superiore a destra delo schermo del commodore 64.
Fin qui "dovrei" aver afferrato cosa sta succedendo ma i problemi iniziano per me con l'istruzione  INC $0427.

Quello che mi è parso di capire e di immaginare ( correggetemi se sbaglio ) è che il programma è come se percorresse da sinistra verso destra lo schermo del commodore 64 dalla prima procedendo a scatti ossia andando a leggere cosa contiene la posizione n+1 e scrivendo il valore nella posizione n fino ad arrivare alla posizione del primo carattere della seconda riga del lato sinistro dello schermo, leggere quindi il suo contenuto per poi scrivere nella posizione immediatamente precedente.

Intanto il programma scrive per ogni ciclo i caratteri ASCII del commodore 64 dal valore 0 al valore 254.

Quello che non riesco ad immaginare è cosa fa effettivamente l'istruzione INC $0427 ???

Serve solo per cambiare carattere ASCII ?

Incrementa ad ogni ciclo il valore dell'accumulatore A?

Ad ogni ciclo ad esempio... se inizio dal primo giro... una volta che arrivo a  INC $0427 e il ciclo salta a MAIN cosa ho in  LDA $0401,X ? $0401+ 1 ? oppure $0401 + $0427 + 1 ?

E' proprio qui che mi perdo....

Vorrei tenere d'occhio i valori ,sapere cosa cambia ad ogni ciclo ma non riesco.

In ogni caso per capire cosa sta succedendo sullo schermo vi rimando all'esempio di questo tutorial che segue a quello da me esposto sopra il quale per permettere all'occhio di capire cosa avviene perché aggiunge altre tre istruzioni al listato che già conoscete e rallentando il tutto consentono all'occhio di capire cosa viene scritto a schermo di volta in volta.


                   *= $0900
MAIN            LDX #$00

 
                    LDA #$FE
RASTER         CMP $D012
                    BNE RASTER


MOVELOOP    LDA $0401,X
                    STA $0400,X
                    INX
                    CPX #$27
                    BNE MOVELOOP
                    INC $0427
                    JMP MAIN

Mi aiutate a capire come tener d'occhio i valori che si muovono ad ogni ciclo?
quindi:

a)  cosa fa effettivamente INC $0427 ???

b) Una volta che arrivo a  INC $0427 e il ciclo salta a MAIN cosa ho in A.

c) che valori vengono caricati ad ogni ciclo nelle locazioni $0401 e $0400 con le istruzioni  LDA $0401,X e STA $0400,X ?

( $0401+ 1 ? oppure $0401 + $0427 + 1 ? oppure niente di tutto ciò? )

d) da quale istruzione del listato sono scritti sullo schermoi caratteri ASCII del commodore 64 che vanno dal valore 0 al valore 254.


Grazie per le vostre dritte...

tsm_carmine

  • Redazione
  • Utente
  • ****
  • Post: 513
  • Gioco Preferito: Krakout
Esercizio Con Caratteri Su Schermo
« Risposta #1 il: 14 Giugno 2014, 17:33:46 »
 Ciao e benvenuto.
Il programmino, come giustamente hai osservato, "percorre" la prima riga di caratteri e copia ogni carattere nella posizione precedente.
In particolare, i caratteri dal secondo all'ultimo della riga vengono copiati nelle posizioni dalla prima alla penultima. Nelle istruzioni LDA / STA del programma, X non arriva mai a puntare all'ultimo carattere, perché quando viene incrementato viene subito confrontato con #$27; se è uguale, non si ha il salto a MOVELOOP.
Ciononostante, il puntamento all'ultimo carattere si ha grazie all'istruzione LDA $0401, X.
Fin qui l'ultimo carattere viene letto ma non scritto. L'istruzione che invece manipola l'ultimo carattere è INC $0427. Il carattere, o per meglio dire, la locazione viene incrementata continuamente in modo che tutto il set di caratteri scorra nella prima riga dello schermo.
Riusciremo a costruire un mondo dove più nessuno osi pronunciare le parole... "lettore floppy"?

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #2 il: 14 Giugno 2014, 20:52:53 »
 tsm_carmine ti ringrazio per la risposta ma mi sento ancora piu' confuso. Evidentemente mi saro' fatto un'idea sbagliata di come funziona il programma.

Non capisco cosa avviene prima nel programma se ad esempio al primo giro di ciclo si passa da destra verso sinistra scorrendo sulla prima riga dello schermo o se si passa da sinistra verso destra.

Quale alternativa tra le due che seguono si verifica?

a)Vedendo il programma in funzione mi verrebbe da pensare che venga prima stampato un carattere ASCII sullo schermo nella ultima posizione a destra ( nella casella n.39 per capirci ) ad esempio il carattere @ poi iniziando il ciclo viene copiato il valore della 39° posizione nella posizione 38 sempre "scorrendo" sulla prima riga e procedendo da destra verso sinistra.
Una volta arrivati alla posizione 0  un nuovo carattere ASCII viene generato sempre nella 39° posizione ed il ciclo riparte  copiando in successione decrescente ( sempre procedendo da destra verso sinistra ) fino ad arrivare alla casella zero.

b) vedendo il listato, invece ,ho l'idea, forse giusta forse errata ,che stiamo procedendo da sinistra verso destra lungo la prima riga perché  cresce di uno in uno il valore che viene caricato nell' accumulatore dall'istruzione LDA $0401,x e cresce da 0 a 39.

Quindi si parte leggendo da $0401 e scrive in $0400 , si legge da $0402 e scrive in $0401 e cosi via ... fino ad arrivare alla posizione  $0427 che corrisponde alla 39 esima casellina.

Questo mi sembrerebbe' piu' realistico leggendo il codice ma quello che mi domando è "se cosi' stanno le cose la prima riga di caratteri e' ancora vuota al primo ciclo ? Quindi non vi sarebbe nessun carattere da copiare e dovremmo aspettare di arrivare fino alla cella 39° per poter pescare il primo carattere generato? ( dall'istruzione INC $0427 )

In effetti se m potreste dare una idea di cosa avviene in uno o due cicli forse stanotte riuscirò a dormire tranquillo.

Dove sto sbagliando? Quale pezzo mi manca per capire a dovere il listato?


Grazie

Elder0010

  • Utente
  • **
  • Post: 75
    • http://csdb.dk/scener/?id=22731
  • Gioco Preferito: Rampage
Esercizio Con Caratteri Su Schermo
« Risposta #3 il: 15 Giugno 2014, 23:41:55 »
 Ti ho riscritto il codice commentando un po', magari ora ti è piu chiaro.

Ricorda che:
$0400 è la memoria schermo "di default"
$d012 è uno dei registri piu' importanti di tutta la baracca :D quando lo leggi ti restituisce la posizione del raster beam, che va dall'alto dello schermo verso il basso. in questo esempio il suo valore viene usato per sincronizzare la routine di movimento dei caratteri con il refresh dello schermo.

Codice: [Seleziona]
main:
  
  //carico il valore 0
  //dentro il registro x
  ldx #0

  //carico il valore #$fe
  //dentro l'accumulatore
  lda #$fe
raster:
  cmp $d012 //finchè il raster non raggiunge la linea $fe
  bne raster      //(in pratica un paio di px dall'inizio del bordo inferiore)
     //rimango in attesa: questo serve per fare in modo che il loop inferiore
     //avvenga una sola volta per frame.
     //se non facessi così, l'effetto andrebbe "fuori sincrono"
     //rispetto al refresh dello schermo.

  //copio ogni carattere della riga indietro di uno
  //quindi:
  //FRAME 0: ABCDEFGHIJKLMNO
  //FRAME 1: BCDEFGHIJKLMNO  <-tutti i chars sono spostati di uno
moveloop:
  lda $0401,x
  sta $0400,x
  inx
  cpx #$27
  bne moveloop

  inc $0427         //incremento di 1 il valore di $0427
     //che corrisponde all'ultimo carattere della prima riga
     //dello schermo. se ad es al frame 0 in fondo a dx cè A (valore 1)
     //al prox frame ci sarà B (valore 2)

     //questo giochino serve solo per inserire nuovi caratteri a dx,
     //che verranno copiati verso sx di uno al prox frame.
     //si tratta in pratica di uno scrolltext "alla buona";)

  jmp main         //jump back: il loop attenderà un frame per via della cmp $d012
     //e farà un altro giro di copia e incremento del carattere in fondo
     //a dx della prima riga

Nota: per motivi di ordine, sarebbe molto meglio mettere quella ldx #0 vicino al loop che utilizza x, per cui
Codice: [Seleziona]
 ldx #0
moveloop:
  lda $0401,x
  sta $0400,x
  inx
  cpx #$27
  bne moveloop
lda #0 sta $d020 sta $d021

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #4 il: 16 Giugno 2014, 00:05:37 »
 Grazie Elder0010,

apprezzo moltissimo la tua spiegazione.

Ma mi confermi che al primo giro di ciclo procedendo da sinistra verso destra da $0400 in poi fino ad arrivare a $0427 non ci sono ancora caratteri da copiare perché lo schermo non e' stato ancora scritto? Ed il primo carattere da leggere e copiare nella posizione precedente lo avremo solamente una volta arrivati alla posizione 39° dove viene generato il primo carattere ASCII di tutta la serie?
 

COMMODORO

  • Utente
  • **
  • Post: 160
  • Gioco Preferito: Bomberman C64
Esercizio Con Caratteri Su Schermo
« Risposta #5 il: 16 Giugno 2014, 01:39:54 »
 In realtà se non viene cancellato lo schermo prima di far partire il programma vedremo alla fine del primo ciclo già i caratteri eventualmente presenti sulla prima riga spostati tutti di una colonna a sinistra...
 Se lo schermo verrà cancellato prima del run o con un comando all'interno del programma dovremmo vedere alla fine del primo ciclo già qualcosa sulla 40a posizione della prima riga perché il suo contenuto viene incrementato prima che il programma torni al 'main'.
Cioé vengono copiate tutte le posizioni dalla 2a alla 40a ( che é ancora 'vuota') ma prima che finisca il ciclo il suo valore viene incrementato e poi il ciclo reinizia.
Spero di non aver scritto fesserie, ciao!

Elder0010

  • Utente
  • **
  • Post: 75
    • http://csdb.dk/scener/?id=22731
  • Gioco Preferito: Rampage
Esercizio Con Caratteri Su Schermo
« Risposta #6 il: 16 Giugno 2014, 14:34:45 »
 Allora, "non ci sono caratteri da copiare" non è un affermazione totalmente corretta.

Il ciclo effettua la copia sempre e comunque. I valori vengono sempre "shiftati", gli spazi vuoti non devono confonderti. Sono caratteri anche loro, solo che semplicemente corrispondono al carattere vuoto (lo spazio).

Quindi la prima volta non hai un feedack "visivo" di quello che succede, ma la copia avviene regolarmente.

Inoltre, ricorda che andando a colpi di inc $0427, i valori assunti dalla locazione $0427 andranno da 0 a $ff (che è 255, e NON 254..).

Tieni presente che:

se $0427 = $0 e esegui inc $0427 -> $0427 = $1
se $0427 = $1 e esegui inc $0427 -> $0427 = $2
...
se $0427 = $23 e esegui inc $0427 -> $0427 = $24
..
se $0427 = $37 e esegui inc $0427 -> $0427 = $38

e cosi via… fino al caso limite
se $0427 = $ff e esegui inc $0427 -> $0427 = $0

quindi da $ff si torna a ZERO! I registri possono contenere valori a OTTO bit. Don't forget :)

Quando questa routine ti sarà chiara, posta sul forum che ti spiego come funziona la sincronia con il refresh dello schermo in dettaglio.

:D
 
lda #0 sta $d020 sta $d021

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #7 il: 17 Giugno 2014, 00:08:08 »
Citazione da: "Elder0010"
Allora, "non ci sono caratteri da copiare" non è un affermazione totalmente corretta.

Il ciclo effettua la copia sempre e comunque. I valori vengono sempre "shiftati", gli spazi vuoti non devono confonderti. Sono caratteri anche loro, solo che semplicemente corrispondono al carattere vuoto (lo spazio).

Quindi la prima volta non hai un feedack "visivo" di quello che succede, ma la copia avviene regolarmente.

Inoltre, ricorda che andando a colpi di inc $0427, i valori assunti dalla locazione $0427 andranno da 0 a $ff (che è 255, e NON 254..).

Tieni presente che:

se $0427 = $0 e esegui inc $0427 -> $0427 = $1
se $0427 = $1 e esegui inc $0427 -> $0427 = $2
...
se $0427 = $23 e esegui inc $0427 -> $0427 = $24
..
se $0427 = $37 e esegui inc $0427 -> $0427 = $38

e cosi via… fino al caso limite
se $0427 = $ff e esegui inc $0427 -> $0427 = $0

quindi da $ff si torna a ZERO! I registri possono contenere valori a OTTO bit. Don't forget :)

Quando questa routine ti sarà chiara, posta sul forum che ti spiego come funziona la sincronia con il refresh dello schermo in dettaglio.

:D
Elder0010 grazie per le spiegazioni molto dettagliate ora mi risulta tutto molto più chiaro e rimango tutto orecchie per quant'altro vorrai dirmi...

 

Elder0010

  • Utente
  • **
  • Post: 75
    • http://csdb.dk/scener/?id=22731
  • Gioco Preferito: Rampage
Esercizio Con Caratteri Su Schermo
« Risposta #8 il: 18 Giugno 2014, 00:47:18 »
 ottimo :) continua a studiare e se hai domande posta allora! spendi un altro po di tempo su queste semplici routine di base che ti fanno entrare nella giusta mentalità!
lda #0 sta $d020 sta $d021

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #9 il: 20 Giugno 2014, 01:05:59 »
 
Citazione da: "Elder0010"
ottimo :) continua a studiare e se hai domande posta allora! spendi un altro po di tempo su queste semplici routine di base che ti fanno entrare nella giusta mentalità!
Bene Elder0010!
Mi sembra di aver afferrato i concetti di funzionamento di questo programmino e per verificare se ho ben compreso il tutto ho provato a svolgere l'esercizio proposto dall'autore alla fine della terza lezione di questo tutorial che sto seguendo:

http://www.oldschool-gaming.com/view_artic...c64_hex_files_3

L'autore chiede infatti di provare a scrivere lo stesso programmino ma usando un'altra locazione dalla quale attingere i caratteri da stampare a schermo e quindi dalla locazione $E460 e di stampare poi i caratteri a partire dalla seconda riga.

Per cui ho scritto:

Codice: [Seleziona]
                 * = $0900
                  ldy #$00;
main              ldx #$00
                  lda #$fe  
raster            cmp $d012
                  bne raster
move_loop         lda $0429,x
                  sta $0428,x  
                  inx
                  cpx #$27
                  bne move_loop
                  lda $a1ff,y
                  sta $044f
                  iny  
                  jmp main  






per cui se mi confermi il tutto ... felice ... passero' a studare la quarta lezione ( the 4th istallment )

Elder0010

  • Utente
  • **
  • Post: 75
    • http://csdb.dk/scener/?id=22731
  • Gioco Preferito: Rampage
Esercizio Con Caratteri Su Schermo
« Risposta #10 il: 21 Giugno 2014, 09:21:21 »
 Non è quello che vedo nel codice, stai leggendo da $a1ff+y anzichè $e460+y

infatti:

Codice: [Seleziona]
lda $a1ff,y
sta $044f
lda #0 sta $d020 sta $d021

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #11 il: 21 Giugno 2014, 14:14:31 »
 Ciao Elder0010,

mi devi perdonare ma forse ho mancato di specificare un passaggio:

nel primo esempio del thread si è semplicemente letto i caratteri, di volta in volta generati e successivamente stampati sullo schermo, semplicemente andando leggendo il valore della locazione $0427 il cui contenuto ad ogni ciclo veniva incrementato di una unità.

Il secondo esercizio dell' 3° lezione: http://www.oldschool-gaming.com/view_artic...c64_hex_files_3

E qui riporto il codice:
Codice: [Seleziona]




                                 * = $0900
                                 ldy #$00
main                             ldx #$00
                                 lda #$fe
raster                           cmp $d012
                                 bne raster
move_loop                        lda $0401,x
                                 sta $0400,x
                                 inx
                                 cpx #$27
                                 bne move_loop
                                 lda $a1ff,y
                                 sta $0427
                                 iny
                                 jmp main






propone un ulteriore esempio dove i caratteri da stampare sullo schermo invece che di essere letti locazione 39° vengono letti dalla locazione $A1FF.
La locazione $A1FF,specifica il tutorial, è la locazione in cui il C64 legge alcuni dei suoi errori. Per cui invece che di avere a schermo i caratteri ASCII da 0 a 255 vedremo alternarsi sullo schermo uno scroll composto da messaggi di errore.

E siccome non abbiamo modificato la riga il tutto avviene sempre sulla prima riga dello schermo.

Con il mio ultimo programmino ho semplicemente svolto l'esercizio proposto dall'autore del tutorial di stampare il tutto, non sulla prima riga dello schermo masulla seconda riga e di leggere "cosa stampare" non dalla locazione  $A1FF ( contenente messaggi di errore ) ma dalla locazione $E460.

E da qui il mio programmino:

Codice: [Seleziona]

                  * = $0900
                  ldy #$00;
main              ldx #$00
                  lda #$fe  
raster            cmp $d012
                  bne raster
move_loop         lda $0429,x
                  sta $0428,x  
                  inx
                  cpx #$27
                  bne move_loop
                  lda $a1ff,y
                  sta $044f
                  iny  
                  jmp main  






Correggimi se sbaglio....

Elder0010

  • Utente
  • **
  • Post: 75
    • http://csdb.dk/scener/?id=22731
  • Gioco Preferito: Rampage
Esercizio Con Caratteri Su Schermo
« Risposta #12 il: 21 Giugno 2014, 20:15:46 »
 ora ho capito :)
non l'ho provato ma mi sembra giusto, ovviamente stai facendo le prove compilando vero?
lda #0 sta $d020 sta $d021

NeVERTooL8

  • Neo-iscritto
  • *
  • Post: 8
  • Gioco Preferito: Comic Bakery
Esercizio Con Caratteri Su Schermo
« Risposta #13 il: 22 Giugno 2014, 23:01:06 »
 Ciao! Compilando a me sembrerebbe corretto  ma se potessi dare un'occhiata tu compilando l'ultimo sorgente di codice starei più tranquillo e sicuro che il tutto sia corretto.