Ready64 Forum
Commodore 64 => Programmazione, Grafica e Musica => Topic aperto da: djwiper - 25 Luglio 2004, 11:38:16
-
Se non ricordo male mediante basic si potevano gestire fino a 7 sprites (o forse erano 8?). Ai tempi in cui possedevo un commodore mi pare di aver modificato il famoso listato basic della mongolfiera marchiata C=, presente nel manuale per far si che ne apparissero 7 (o 8?). Ma in linguaggio macchina si possono "muovere" più sprites rispetto a quanti se ne possono gestire con il BASIC, giusto? Dico questo perchè alcuni giochi, tra personaggi e altri oggetti moventi, arrivano tranquillamente ad una ventina di sprites. O forse si utilizza qualche espediente e il numero di sprites rimane fisso a 7 (o 8?)?
Un'altra cosa per evitare di aprire un nuovo topic:
Ma il colore di trasparenza, ossia quello che fa "fondere" lo sprites con il fondo qual'è? Nonostante abbia letto i doc a riguardo non ho ancora capito. Se ho uno sprites: (facciamo finta che row e colums siano correti in numero)
****
*
*
****
qual'è l'equivalente colore del cancelletto?
####
****#
*###
*###
****#
####
Spero di non aver scritto in arabo...
-
Ciao e ben tornato :)
forse si utilizza qualche espediente e il numero di sprites rimane fisso a 7 (o 8?)?
Sia in basic che in LM si possono gestire fino a 8 sprite (limite fisico del chip video).
Tuttavia,gestendo adeguatamente gli interrupt del raster (il fascio di elettroni che disegna lo schermo 50 volte al secondo in un C64 PAL,60 volte al secondo in un C64 NTSC) è possibile "ingannare" il VIC,ottenendo più di 8 sprite in una stessa schermata.
Ad esempio,compila questo sorgente e lancia l'eseguibile con una SYS 49152
* = $c000
SEI
JSR INIT ; inizializza sprites
LDA #< IRQ
STA $0314
LDA #> IRQ
STA $0315 ; setta vettore di interruzione
LDA #$01
STA $D01A
LDA $D011
AND #$7F
STA $D011
LDA #$32
STA $D012 ; abilita prima interruzione del raster
; alla riga 50
CLI
RTS
INIT LDA #$00
STA $FB ; inizializza contatore
LDA #$FF
LDX #$00
STORE STA $02C0,X
INX
CPX #$3F
BNE STORE ; setta la forma degli sprite
LDA #$0B
LDX #$00
POINTER STA $07F8,X
INX
CPX #$08
BNE POINTER ; setta i puntatori agli sprite
LDY #$00
LDX #$00
SETX LDA XCOORD,Y
STA $D000,X
INX
INX
INY
CPY #$08
BNE SETX ; setta coordinata X
LDX #$00
LDA #$40
SETY STA $D001,X
INX
INX
CPX #$10
BNE SETY ; setta coordinata Y
LDA #$00
STA $D010 ; setta coordinata X di pagina 1
LDA #$07
LDX #$00
FILL STA $D027,X
INX
CPX #$08
BNE FILL ; colora gli sprite di giallo
LDA #$FF
STA $D015 ; visualizza gli sprite
RTS
IRQ LDA $91
BPL RESET ; [RUN-STOP] premuto,esci
LDA $D019
STA $D019 ; sblocca il registro per le interruzioni s
; successive
AND #$01
BEQ EXIT ; se interruzione non del raster,esce
LDX $FB
LDA YCOORD,X
STA $D001
STA $D003
STA $D005
STA $D007
STA $D009
STA $D00B
STA $D00D
STA $D00F ; cambia l'ordinata degli sprite
LDA RASTER,X
CPX #$03
BNE CONT
LDX #$FF
CONT INX
STX $FB ; aggiorna/resetta contatore
STA $D012 ; setta la prossima linea di raster
LDA $D011
AND #$7F
STA $D011
JMP $EA31 ; salta alla normale routine di IRQ
EXIT JMP $FEBC ; torna dall'interruzione
RESET JMP $FE66
;*** LINEE DI INTERRUZIONE DEL RASTER ***
RASTER .BYTE $63,$95,$C7,$32
;*** COORDINATE SPRITES ***
XCOORD .BYTE $18,$34,$50,$6C,$88,$A4,$C0,$DC ; X
YCOORD .BYTE $40,$72,$A4,$D6 ; Y
Questa routine sfrutta gli interrupt del raster per visualizzare a schermo 32 sprite in contemporanea. :)
Ma il colore di trasparenza, ossia quello che fa "fondere" lo sprites con il fondo qual'è?
E' il colore del fondo stesso (quello contenuto nella locazione 53281).
P.S.:Se qualcuno ha domande da porre sul listato,non esiti ;)
Bye
-
LDA $D019
STA $D019 ; sblocca il registro per le interruzioni successive
AND #$01
Forse ho capito...
io sono abituato a sbloccare il latch in un altro punto del programma e a controllare in un altro momento se l'interruzione è del raster oppure no... ma è lo stesso anche come fai tu ;)
-
No,non è sbagliato,perchè si vuole sbloccare il registro $D019 per avere altri interrupt,e poi si vede se si è verificato un interrupt del raster.
-
e non ricordo male mediante basic si potevano gestire fino a 7 sprites (o forse erano 8?). Ai tempi in cui possedevo un commodore mi pare di aver modificato il famoso listato basic della mongolfiera marchiata C=, presente nel manuale per far si che ne apparissero 7 (o 8?). Ma in linguaggio macchina si possono "muovere" più sprites rispetto a quanti se ne possono gestire con il BASIC, giusto? Dico questo perchè alcuni giochi, tra personaggi e altri oggetti moventi, arrivano tranquillamente ad una ventina di sprites. O forse si utilizza qualche espediente e il numero di sprites rimane fisso a 7 (o 8?)?
Il Commodore 64 riesce a gestire graficamente 8 Sprites alla volta. Quindi più di 8 allo stesso tempo sullo schermo non se ne possono mostrare.
Con l'evoluzione delle tecniche di programmazione però, è stato creato un nuovo metodo di gestire gli sprite, che si chiama Multiplexing.
Con il multiplexing si possono gestire un numero molto superiore di sprite adottando un semplice trucchetto che consiste nell' "accendere e spegnere" molto velocemente 8 sprites alla volta.
In questo modo, l'occhio umano viene ingannato facendogli credere che sullo schermo siano presenti più di otto oggetti nello stesso tempo, cosa effettivamente non vera :)
Ma il colore di trasparenza, ossia quello che fa "fondere" lo sprites con il fondo qual'è? Nonostante abbia letto i doc a riguardo non ho ancora capito. Se ho uno sprites: (facciamo finta che row e colums siano correti in numero)
In modo multicolor, ogni sprite può utilizzare 4 colori.
I colori li decidi tutti tu, ma con alcune limitazioni.
In particolare, i colori 1 e 2 sono gli stessi per TUTTI gli sprites, vale a dire che se tu cambi il colore 1 o 2, questo cambiamento ha effetto su tutti gli sprites.
Poi c'è il "colore custom" che può essere uno qualsiasi dei 16 che la palette del C64 ti mette a disposizione, e varia da sprite a sprite.
Per imparare non c'è niente di meglio che cominciare a 'smanettare' con uno sprite editor. Prova e persevera, vedrai che dopo un pò ti sarà tutto chiaro.
-
Ad esempio,compila questo sorgente e lancia l'eseguibile con una SYS 49152
Lo farò senz'altro, prima però vorrei approfondire l'argomento sul rasterbeam che mi incuriosisce molto e di cui sono "bianco" allo stato attuale. Una domanda sul sorgente mi permetto di fartela:
JSR INIT ; inizializza sprites
JSR sarebbe l'equivalente x86 di JMP, giusto? Cioè "salta" alla label INIT, la quale
INIT LDA #$00
STA $FB ; inizializza contatore
LDA #$FF
LDX #$00
Dopo aver eseguito i quattro i comandi (LDA, STA, LDA, LDX) che fa?
Non dovrebbe tornare alla linea immediatamente successiva a JSR INIT? Si può omettere l'equivalente x86 RET per il ritorno dal salto non condizionale?
Poi, immediatamente dopo la linea JSR INIT abbiamo
LDA #< IRQ
Non ci arrivo proprio... :( Vuol forse dire "Carica nell'accumulatore A il valore restituito dalla funzione (?) IRQ?" In quel caso la label IRQ sarebbe una funzione che restituisce un valore? Anche così non avrebbe senso poichè l'operatore < e successivamente quello > non riuscirei a spiegarli...
E per quanto riguarda la parte teorica ho finito, passiamo a Roberto :)
Con l'evoluzione delle tecniche di programmazione però, è stato creato un nuovo metodo di gestire gli sprite, che si chiama Multiplexing.
Un pò come accade nei vecchi display LCD "multiplexati" se ho ben capito. Quelli cioè delle calcolatrici a, ad esempio, dieci cifre che invece di tenere settanta segmenti teoricamente accesi o spenti ne "multiplexavano" una piccola parte (di solito quattro-cinque) mediante un oscillatore al quarzo che "ingannava" l'occhio umano? Se fosse così ho capito il funzionamento
Come al solito grazie ragazzi :D
-
più di 8 allo stesso tempo sullo schermo non se ne possono mostrare.
Con l'evoluzione delle tecniche di programmazione però, è stato creato un nuovo metodo di gestire gli sprite, che si chiama Multiplexing.
Con il multiplexing si possono gestire un numero molto superiore di sprite adottando un semplice trucchetto che consiste nell' "accendere e spegnere" molto velocemente 8 sprites alla volta.
In questo modo, l'occhio umano viene ingannato facendogli credere che sullo schermo siano presenti più di otto oggetti nello stesso tempo, cosa effettivamente non vera
Non è un'illusione ottica.
Nel multiplexing gli sprite sullo schermo sono effettivamente più di 8.
Ad esempio,nella routine postata il fascio del raster provoca un'interruzione alle righe 50,99,149,199.
Arrivato a ciascuna di queste righe,viene cambiata l'ordinata degli sprite,in modo che il raster disegni 8 sprite in ciascuna delle 4 porzioni in cui viene diviso il video.
-
Innanzitutto,ho apportato alcune piccole modifiche al sorgente,quindi ti/vi prego di copiare/incollare quello attualmente presente. ;)
Dopo aver eseguito i quattro i comandi (LDA, STA, LDA, LDX) che fa?
Disegna 8 rettangoli,li colora tutti di giallo e ne setta le coordinate di partenza.
Non dovrebbe tornare alla linea immediatamente successiva a JSR INIT? Si può omettere l'equivalente x86 RET per il ritorno dal salto non condizionale?
Esatto,costruisce gli sprite e poi l'esecuzione riprende dall'istruzione successiva alla JSR INIT.
Non ci arrivo proprio... Vuol forse dire "Carica nell'accumulatore A il valore restituito dalla funzione (?) IRQ?" In quel caso la label IRQ sarebbe una funzione che restituisce un valore? Anche così non avrebbe senso poichè l'operatore < e successivamente quello > non riuscirei a spiegarli...
LDA #IRQ "carica nell'accumulatore il byte alto dell'indirizzo di partenza di IRQ".
-
Ciao a tutti,
x Alberto: ah, forse ho capito come hai fatto... io usavo un altro metodo... ma sia come faccio io o come fai te credo sia la stessa cosa, per cui dietrofront! ;)
Evito di rispondere riguardo a domande specifiche sul codice, visto che lo ha postato Alberto e potrei non averne compreso alcune parti (ognuno ha il suo stile di programmazione).
Attenzione a non confondere il multiplexing con la tecnica generica delle interruzioni del raster, sono due cose differenti.
Vediamo un attimo come funge il raster.
Lo schermo, nei sistemi PAL (cioè quelli che usiamo noi), viene aggiornato 50 volte al secondo. Questo aggiornamento viene fatto da un fascio di elettroni, che fa in modo che vengano accesi i pixel opportuni su ciascuna linea di scansione (eccitando i fosfori).
********************* 1a linea
********************* 2a linea
queste linee vengono visualizzate dall'alto verso il basso, e poi il processo ricomincia da capo. Il fascio di elettroni percorre ciascuna linea da sinistra a destra.
Giunto all'ultima linea, il fascio riprende la sua scansione dalla prima in alto.
Il raster è un termine che indica diverse cose:
- lo schermo raster: è lo schermo diviso in linee di scansione.
- il raster (abbreviazione di rasterbeam) = pennello elettronico.
- raster (nel senso di raster interrupt) = interruzione del raster.
Un'interruzione del raster viene generata dal VIC-II quando il rasterbeam si trova in una certa linea di scansione. Nel C64 PAL, le linee di scansione vanno da 0 a 312 (quelle visibili da 50 a 250, le non visibili corrispondono al bordo).
Il registro del raster (in realtà sono due perché l'informazione è a 9 bit, ma tralasciamo questo aspetto) indica la posizione corrente del raster. Inoltre, scrivendo su questo stesso registro, viene impostato il valore al quale avverrà l'interruzione del raster.
Per esempio, se voglio dividere lo schermo in due parti, in modo che in mezzo schermo il bordo sia rosso e nell'altro mezzo bianco, devo generare due interruzioni del raster (una a metà dello schermo - impostando di conseguenza il registro alla opportuna linea di scansione) e una in cima allo schermo (linea di scansione 0).
Analogamente, se voglio rappresentare più di 8 sprite sullo schermo, basta che io generi ad esempio 4 interruzioni del raster, dividendo così lo schermo in quattro file:
************** interruzione 1
8 sprite
...
*************** interruzione 2
8 sprite
***************
ecc...
In questo modo, si spostano gli sprite da una fila all'altra quando avviene l'interruzione. L'interruzione avviene quando gli sprite della fila di sopra sono già stati disegnati... e così posso spostare gli sprite nella fila di sotto (cioè la fila corrispondente alla linea di scansione nella quale è avvenuta l'interruzione corrente) senza che chi guarda se ne accorga.
Il multiplexing consiste nell'alternare UNO STESSO sprite in una stessa "fila" (cioè in corrispondenza delle stesse linee di scansione). Ad esempio, nella zona dalla linea di scansione 50 alla 75, per dire, potrei visualizzare non più di 8 sprite... e le interruzioni del raster, intese nel senso di prima, non mi sarebbero utili.
Ma io dispongo di 50 fotogrammi al secondo... e posso rappresentare lo sprite 1 (per dire) nella posizione x = 50 nel fotogramma 1 e nella posizione X = 120 nel fotogramma 2. In questo modo, pena un po' di sfarfallio, pur avendo un solo sprite riesco a farne vedere due... in corrispondenza delle stesse linee di scansione.
Combinando i due effetti si possono visualizzare anche 50 sprite.
Ovviamente, per fare il multiplexing servono le interruzioni del raster, ma stavolta l'obiettivo è quello di alternare due fotogrammi, non di dividere lo schermo in più parti.
Scusate la sciatteria nel trattare le tematiche, ma se riuscirò a completare il "corso semiserio di assembler" tratterò meglio questi argomenti e porterò degli esempi.
Ciao!
-
Ops :stordita:
-
Per chi fosse interessato,un piccolo esercizio:
come avrete notato,la velocità di ripetizione del cursore risulta accelerata (domanda:perchè?).
Modificate il listato in modo da riportare il blink a velocità normale ;)
Bye
-
Ma io dispongo di 50 fotogrammi al secondo... e posso rappresentare lo sprite 1 (per dire) nella posizione x = 50 nel fotogramma 1 e nella posizione X = 120 nel fotogramma 2. In questo modo, pena un po' di sfarfallio, pur avendo un solo sprite riesco a farne vedere due... in corrispondenza delle stesse linee di scansione.
Però,facendo così l'effetto a schermo è abbastanza schifido:50 hz sono una frequenza video troppo bassa per creare l'effetto di più di 8 sprite su una sola riga di raster.
-
JSR sarebbe l'equivalente x86 di JMP, giusto? Cioè "salta"
No JMP e' JMP in entrambi i processori. Salto incondizionato e senza ritorno.
JSR e' Jump to Subroutine and Return. Si memorizza nello stack l'indirizzo dell'istruzione successiva alla JSR, salta al nuovo indirizzo e appena si incontra RTS ritorna all'inidirizzo memorizzato sullo stack, continuando di fatto dalla istruzione successiva alla JSR.
Leggiti bene il capitolo 5 della guida di rifermento che trovi sul sito, ogni istruzione 6502 e' spiegata per filo e per segno ;)
-
iAN, hai proprio ragione! Piccolo erroe confusionario
Leggerò sicuramente la guida, anze LE guide visto che me ne mancano alcune...
Ritornando al discorso degli sprites credo di averlo capito. Per caso può interessare anche altre macchine, come ad esempio il nintendo (sebbene abbia il chip 6510 come cpu) o il supernintendo? In casi di particolare confusione, alcuni giochi di tali piattaforme rallentano e scompaiono temporaneamente alcuni sprites. Forse è una cosa che non centra proprio nulla?
-
Non è un'illusione ottica.
Nel multiplexing gli sprite sullo schermo sono effettivamente più di 8.
mha, io direi piuttosto che, dato che non ci possono essere piu' di 8 sprites HARDWARE, gli sprites sono sempre 8 ma la temporizzazione fa in modo che il raster non riesca a tornare in cima e ridisegnare lo schermo, facendo vedere che lo sprite e' stato spostato. E' solo e comunque un effetto ottico. Fisicamente di sprite ce ne sono sempre e solo 8.
Arrivato a ciascuna di queste righe,viene cambiata l'ordinata degli sprite
Appunto, spostato, quindi sopra non c'e' piu'. Che poi noi non lo vediamo perche' facciamo in modo che il raster non riesca a ridisegnare la parte sopra, lasciata vuota, e' ben diverso dal dire che gli sprite sono piu' di 8 contemporaneamente ;)
-
nintendo (sebbene abbia il chip 6510 come cpu) o il supernintendo?
Putroppo non so nulla riguardo a NES/SNES a parte il fatto che usano una 65xx come cpu. Spiacente. ;)
-
Sì,è ovvio che gli sprite mappati sullo schermo,in ogni momento,sono sempre e solo (al massimo)8,ma nel caso del programma sopra,quel che si vede a video sono comunque 32 sagome per frame,non 8 che appaiono e scompaiono alternativamente.
-
Sì,è ovvio che gli sprite mappati sullo schermo,in ogni momento,sono sempre e solo (al massimo)8,ma nel caso del programma sopra,quel che si vede a video sono comunque 32 sagome per frame,non 8 che appaiono e scompaiono alternativamente.
Ma e' quello che ho detto anche io: siamo noi da codice che spostiamo gli sprites mentre il raster va in giu', il raster non ha il tempo di far vedere che sopra non ci sono piu'. quando il raster ritorna all'inizio dello schermo si rispostano gli sprites nella prima sezione e cosi' via. Il tutto, effettuato in un frame, non permette di vedere lo spostamento.
-
Nel multiplexing gli sprite sullo schermo sono effettivamente più di 8.
Sì,è ovvio che gli sprite mappati sullo schermo,in ogni momento,sono sempre e solo (al massimo)8,
Ma giochiamo con le parole?
-
Vabbò,tronchiamo qui la polemica (preferisco occupare il mio tempo in maniera migliore ;) )
Bye :ciauz:
-
Vabbò,tronchiamo qui la polemica (preferisco occupare il mio tempo in maniera migliore ;) )
Bye :ciauz:
quale polemica... si stava discutendo sul come funziona il programma :confused:
-
Però,facendo così l'effetto a schermo è abbastanza schifido:50 hz sono una frequenza video troppo bassa per creare l'effetto di più di 8 sprite su una sola riga di raster.
Centinaia e centinaia di bellissime IFLI sono state fatte con questo principio... frizzano ma qual'è il problema? Si guadagna molto: risoluzione doppia e mescolamento dei colori. Analogamente, multiplexando hai sì dello sfarfallamento, ma hai il doppio di quello che avresti senza sfarfallare... sono i soliti compromessi che si hanno lavorando con un computer classico ;)
-
Qua nessuno vuol far polemiche... semplicemente stiamo parlando di alcune tematiche - peraltro, almeno per me, tutt'altro che semplici...
-
Putroppo non so nulla riguardo a NES/SNES a parte il fatto che usano una 65xx come cpu. Spiacente.
Io posso dire solo una cosa (visto che è l'unica che so sul NES! :doh: ): nel NES, che è successivo al C64, prima di scrivere dati sullo schermo il circuito grafico si assicura da solo che il rasterbeam sia nell'area non visibile dello schermo, evitando sfarfallamenti.
Nel C64, invece, ad esempio per fare uno scrolling senza disturbi video, occorre come minimo scrivere:
loop lda $d011
bpl loop
come ci dice il buon vecchio "mapping the 64".
Ciao!
-
Putroppo non so nulla riguardo a NES/SNES a parte il fatto che usano una 65xx come cpu. Spiacente. ;)
Questo vuol dire che il LM del commodore sostanzialmente non differisce molto dal LM del NES/SNES? O si devono utilizzare particolari accorgimenti oltre ai cambiamenti del chip 6502 e 6510a01 montato sul nes?
Scusate il palese off topic
-
Allora,vediamo di capirci,perchè mi sa che sono stato equivocato ;)
@Roberto:
Quando parlo di sprite (visualizzato) sullo schermo,intendo la SAGOMA dello sprite.
Quando parlo di sprite MAPPATO in memoria,intendo gli sprite hardware (cioè quelli in quel momento attivi,quindi soggetti a collisioni,puntati da $07f8-$07ff eccetera).
Comunque ammetto di non essermi spiegato in modo chiarissimo :stordita:
@Ian:
Mi sembra inutile portare avanti una discussione tra noi due,quando entrambi intendiamo le stesse cose,ti pare?
Il post in cui ho detto 'E' ovvio che...' era per farti capire che intendevo dire esattamente quel che hai detto tu,e siccome hai replicato 'Ma è quello che ho detto io...',mi sembrava che la discussione stesse degenerando (inutilmente) in una mezza polemica.
@Marcello:
Non ho mai provato a fare IFLI con il multiplexing,per cui mi attengo a quel che dici tu ;)
La storia della polemica,comunque,era riferita al discorso tra me e Ian CooG,tu non c'entri nulla :mellow:
Ciauz :c64:
-
Non ho mai provato a fare IFLI con il multiplexing,per cui mi attengo a quel che dici tu
L'IFLI e il multiplexing sono due cose diverse... ma in entrambe vi è il concetto di alternare due fotogrammi... tutto qui. Quanto alla polemica, l'avevo intuito che non era diretta a me, mi premeva comunque chiarire e l'ho fatto ;)
Questo vuol dire che il LM del commodore sostanzialmente non differisce molto dal LM del NES/SNES? O si devono utilizzare particolari accorgimenti oltre ai cambiamenti del chip 6502 e 6510a01 montato sul nes?
L'unica differenza fra il 6510 e il 6502 è data dalla gestione della memoria. Nel 6502 non vi sono il registro 0 e 1 (direzione dati e porta di I/O). Il set di istruzioni e l'assembly sono identici per entrambe le macchine.
Per essere precisi, il 6502 del NES non presenta NMI, ma anche questo fatto è di scarso rilievo. Ad esempio io ho studiato l'assembly del 6510 utilizzando anche, fra le altre cose, un tutorial destinato al mondo del NES :)
Ciao!
-
Ciao a tutti,
avrei una curiosita' forse stupida, tipica da coder, anche se io mi sono sempre occupato di musica, o quasi.
Il discorso del multiplexing mi ha sempre interessato all'n-esima potenza, ma il quesito a cui non ho mai trovato una risposta e': dal momento che il C64 puo' visualizzare 8 sprites hardware contemporaneamente, come fa, un esempio eclatante, un gioco come Armalyte a trattare tutti gli sprites come singole entita'?
Mediante l'utilizzo di registri ombra? Questo quesito me lo porto dietro da parecchi anni, e non sono mai riuscito a trovare una risposta :D
Se gli sprite hardware sono 8, e vengono gestiti mediante gli appropriati registri, come vengono trattati gli sprite "software"?
Saluti a tutti
-
Dan Phillips ha pubblicato il suo Multiplexor su lemon
http://www.lemon64.com//forum/viewtopic.php?t=5839 (http://www.lemon64.com//forum/viewtopic.php?t=5839)
A me viene il mal di testa a leggerlo :D
-
Mi arrendo, non ci capiro' mai niente :doh: :confused:
A vederlo cosi' sembra la cosa piu' semplice del mondo... e invece...
-
Mi arrendo, non ci capiro' mai niente :doh: :confused:
A vederlo cosi' sembra la cosa piu' semplice del mondo... e invece...
Gia'... il sorgente e' MOLTO parziale, label che mancano... ho provato a riformattarlo in modo che sia piu' scorrevole da leggere. Io uso un editor dos in modalita' 80x50 (edit del dos va bene)
http://digilander.libero.it/iANCooG/armathing2.asm (http://digilander.libero.it/iANCooG/armathing2.asm)