Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
06-07-2015, 07:01 PM
(Questo messaggio è stato modificato l'ultima volta il: 27-01-2023, 02:23 PM da Bonnox.)
[br]
---
Guida:
Buongiorno
Oggi vi fornirò le basi di questo fantastico mondo, per arrivare a nozioni più importanti (come corposità), utili a comprendere gli argomenti più difficili, di cui parlano i professionisti.
- Comprendere il funzionamento di files e sistemi di numerazione (breve)
#fatta
Mi dispiace, dobbiamo partire con un po' di matematica, ovvero con i sistemi di numerazione. Se li conoscete già potete saltare questa parte.
Noi umani solitamente contiamo usando le mani, perciò arriviamo fino a 10. Stiamo dunque inconsapevolmente utilizzando il sistema decimale della notazione posizionale. Che accidenti significa? Semplicemente ogni posizione nel numero ha un significato diverso, ovvero, per esempio, tra 1, 11 e 111 c'è una bella differenza! Questa differenza è un'esponenziale di 10, ovvero, per ogni posizione che aggiungo, il numero aumenta di 10 volte. Inoltre, i numeri si possono esprimere, in forma completa, come somma dei contributi delle singole posizioni:
ad esempio il numero 619 si può vedere come 6*10^2 + 1*10^1 + 9*10^0.
Nei sistemi esadecimale e binario funziona tutto allo stesso modo, solo che il numero di cifre è diverso, ovvero 16 (0 1 2 3 4 5 6 7 8 9 A B C D E F) e 2 (0 1).
Per convertire da qualsiasi sistema al decimale si fa come sopra. Come esempio userò il famoso numero 80C:
8*16^2 + 0*16^1 + 12*10^0 (C vale 12) = 2060.
Più complicato convertire dal decimale ad un altro sistema.
Dovete ripetere i passaggi:
- dividete il numero da convertire per la base (esempio 16)
- segnatevi il resto della divisione
- ora il numero da dividere diventa la parte intera della divisione precedente.
finchè arrivate ad un punto in cui andate avanti all'infinito.
il numero è la lettura, dall'ultimo, di tutti i resti.
[attachment=278]
l'esempio mostra la conversionde di 23 in base 2, ovvero 10111.
Ora che avete imparato a convertire tra i sistemi, dimenticatelo pure se non dovete studiare informatica e usate la calcolatrice! [emoji14]
Un computer dispone di dispositivi di calcolo e memorizzazione. Questi contengono un'immenso numero di elementi fisici minimi che possono assumere 2 posizioni: acceso e spento (o magnetizzato e smagnetizzato, a seconda della tecnologia). Questi si chiamano Bit, dall'inglese BInary digiT. Ecco spiegato il perchè del sistema binario. Tuttavia operare sui bit non è conveniente, perciò sono raggruppati a gruppi di 8 in elementi logici minimi, detty Byte. Dunque un byte può assumere 2^7+ 2^6 + 2^5 + 2^4 + 2^3 +2^1 +2^0 =256 valori, partendo da 0 e arrivando a 255 (o FF).
ah, una nota: precisate sempre in che sistema state scrivendo, altrimenti ci potrebbero essere disastrose incomprensioni!
ci sono varie notazioni per fare ciò.
- PREFISSE:
- SUFFISSE:
- HEX:
- DEC:
- d
- # (dipende dalla piattaforma usata, in quanto va in conflitto con un altro, io di solito lo uso per numeri a tre cifre)
- BIN:
Ogni singolo file ("archivio") sul computer è composto da un numero più o meno grande di byte. Ora prendete una ROM di pokemon (legalmente estratta dalla cartuccia  ): vedrete che è grande 16.777.216 bytes. Per convenienza, si raggruppano 1024 Bytes in un KiloByte, 1024 Kilobytes in un Megabyte, e così via. ( approfondimento) Così la ROM di pokemon pesa 16 MB.
Ovviamente su un computer normale non si può aprire tale file, bisogna installare i programmi adatti.
- Formato GBA e HEX editor (lunga)
Ed è qui che siamo giunti, con i nostri programmi d'esempio VBA e AMAP. Entrambi riconoscono il formato GBA, un tipo di file binario che nè W1nd0ws nè Linux saprebbero riconoscere. Cos'è un file binario? Semplicemente un file riempito di comunissimi dati binari. I dati si dicono binari perchè sono rappresentati nel loro "modo naturale". Questo significa che solo il programma/hardware per cui sono stati sviluppati saprà leggerlo. Possiamo vedere questo concetto cercando di aprire un'immagine con il blocco note: vedremo un ammasso di cose senza senso, perchè semplicemente esso cerca di interpretare l'immagine come se fosse fatta da dati del "suo" tipo (ovvero il testo). Questo forse vi farà ricordare cosa dissero i maestri di gen I, ovvero che pokemon rosso interpretava come pokemon dati di tutt'altro tipo, generando così le cose glitchate. Oggi una cosa del genere sarebbe inammissibile e il programma vittima di questo errore verrebbe arrestato quanto prima.
Eravamo rimasti al nostro file binario GBA. Questo file è molto simile ai comunissimi "exe" di windows, con l'unica differenza che sono concepiti per due sistemi differenti. Entrambi i tipi di file infatti contengono al proprio interno le effettive istruzioni da eseguire, i dati e alcune cose aggiuntive.
Sia VBA che AMAP possono comprendere il formato GBA, ma ci sono delle differenze. Mentre il primo può capire "tutta" la ROM, si limita a leggerla (infatti non saprebbe cosa modificare); AMAP, d'altro canto, può anche scrivere sulla ROM, ma è specializzato solo su alcune sezioni di essa, perchè ne Può capire solo alcuni pezzi. Sono 2 programmi complementari e opposti.
Ecco come funzionano (in parole povere):
-VBA: legge una alla volta le istruzioni incluse nel file, e si comporta esattamente come se fosse un GBA vero, solo che al posto di accedere direttamente alle risorse hardware deve chiedere il permesso al sistema operativo (  )
-AMAP: legge solamente i bytes che rappresentano il "tipo naturale" delle mappe, ed è anche in grado di modificarli.
ed ecco che giungiamo al nostro esempio pratico con... L'HEX EDITOR!! (finalmente!)
Cos'è questo strumento che affascina ma al contempo spaventa? Si tratta di un semplicissimo programma per aprire QUALSIASI file. Ma come, direte voi, come fa quel programma ad aprire files che non conosce? Eh eh, mio caro ragazzo, l'hex editor è subdolo: non cerca di interpretare i dati che legge. Per questo riesce ad aprire tutto, si limita a mostrare il contenuto "grezzo" (raw) del file, ovvero i suoi bytes! Perciò è L'utente che deve capire cosa sta leggendo/modificando.
Ora impareremo a familiarizzare con questo strano personaggio (sarà una parte lunghetta, mettetevi comodi)
OT
(beati voi... io devo familiarizzare con una robot dotata di intelligenza artificiale quantistica ma impazzita che si diverte a veder soffrire gli uomini.... ma spesso le sue "sono battute".
ehm, mi sa che in tutto il forum l'unico che può capire è Mew2... e forse andrea...)
e poi ci applicheremo a alcuni casi concreti.
Quale editor usare? Io personalmente utilizzo XVI 32 perchè mi trovo bene con quello, ma ce ne sono molti altri. Ad esempio è diffuso HxD (che talvolta uso), ma per noi hacker di pokemon potrebbe essere interessante usare anche thingy 32 e windhex 32. Ognuno ha i suoi punti di forza.
Ma prima una piccola parentesi sui caratteri. Quando i nostri byte sono interpretati come "tipo testo", i programmi si affidano a uno standard internazionale, per poter garantire la reciproca compatibilità. Gli standard normali usati da noi sono ASCII (ormai superato, era presente nei primi computer che fossero qualcosa di più che una calcolatrice  ) e la sua estensione LATIN 7, ma ora si usa l'UNICODE, che è quello grazie a cui tutti noi possiamo fare le faccine su wozzap. Quali sono le differenze tra i diversi sistemi? soltanto una: il numero di bit usato per la codifica. Abbiamo 7, 8 e 16 bit , per un totale di (ballando con le stelle ) 128, 256, 65535 caratteri.
Prima di procedere vi devo avvertire che la n1ntendo ha avuto la "brillante" idea di sovvertire l'ordine naturale delle cose, creando set di carattere proprietari per i propri giochi. Quello per pokemon è reperibile su bulbapedia. Questo significa,come è già stato detto in passato, che ad ogni singolo byte corrisponde un solo carattere. Ance se con un hex editor, una volta caricati i nuovi caratteri, vedremo il cambiamento su tutti i byte, questa corrispondenza nel gioco vale soltanto se i dati sono rappresentati nel tipo di testo, e questo lo decide il software.
Torniamo a noi. Avete preso i 4 hex editor elencati in precedenza? Bene, potete già buttarne via 2, e vi spiego il motivo, anche se è del tutto soggettivo.
Per spiegare senza complicare troppo il testo vi descriverò direttamente ogni programma.
-XVI mi piace perchè ha una bella interfaccia, ha il pregio non da poco di poter ridimensionare la visuale,e ha un simbolo per rappresentare il carattere 08 diverso dagli altri (actually, usa il set DOS), anche se ogni tanto il mio PC si bugga, per cui nello screen sotto non potete vederlo. Più avanti capirete perchè questa cosa del carattere 8 è così importante. Di contro ha che è difficile incollare i bytes sovrascrivendoli alla ROM, ci sono riuscito solo una volta per caso e poi basta. E' necessario evitare di aumentare le dimensioni della ROM perchè altrimenti non viene letta correttamente dal VBA, e si glitcha tutta.
- HXD : è pieno zeppo di funzioni.
- Thingy 32: non lo trovo molto pratico, anzi mi risulta piuttosto scomodo da usare come normale strumento di hacking, questo perchè è stato concepito per uno scopo preciso: le traduzioni. Nella seconda esperienza vedremo di più. A questo punto l'unico merito che possiamo dargli per non screditarlo è che se lo scaricate dai siti di pokemon, avrete inclusa una tabella dei caratteri già pronta. Ma eccola qua:
[attachment=279] (dovrete rinominare l'estensione in "TBL")
- Windhex 32: anche questo non è comodissimo per l'hacking, ma di sicuro di più del precedente. Pregio di questo programma è che potete caricare la tabella di thingy. Scorrendo le funzioni si nota subito che anche lui è stato creato per modificare i testi dell ROM.
voi usate quello che vi sembra più comodo, vi aiuterà a concentrarvi (actually, a non distrarvi  ).
Ok, mentre scrivevo ho scoperto 2 funzioni per i programmi "di punta": XVI permette una tabella dei caratteri (woo!) anche se bisogna farsela a mano (ecco la mia fatta in 4 minuti. ha solo le lettere. da rinominare in "XCT": [attachment=280]); mentre Hxd permette pure lui di cambiare il numero di caratteri in una riga (funzione che trovo comodissima e che dopo vedrete all'opera).
finalmente dopo tante chiacchere (ciò che io chiamo "la teoria degli esercizi"  ) ecco come usare un hex editor.
[attachment=281]
innanzitutto usate i comandi nel riquadro rosso per aprire la ROM.
nel riquandro a sinistra ci sono i byte che compongono la nostra ROM, mentre a destra la loro conversione nel sistema di caratteri corrente. Nell'immagine, XVI usa il DOS charset (anche se non si vede perchè ogni tanto si bugga, ma forse è il mio PC scrauso), mentre windhex il set di pokemon. A sinistra trovate anche l'offset. Offset, dall'inglese "scostamento", significa "quanto in là" siamo dall'inizio del file. In pratica è l'ordinale dei byte, ovvero la loro posizione dentro il file. Per praticità di default è visualizzato in esadecimale.
Esperienza 1)
modifica dati binari
- Recatevi all'offset 3E6E50h. Per farlo, usate la scorciatoia da tastiera CTRL+G (è uguale per tutti). a seconda di come è fatto il programma, avrete finestre di dialogo differenti.
[attachment=282]
dopo esserci spostati, troveremo dei byte che devono essere interpretati in qualche modo. per fare questo dovremo spostarli in un nuovo file per poterli analizzare meglio. D'ora in avanti mi riferirò a XVI, ma il procedimento non è molto dissimile dagli altri programmi. Edit > block n chars > 420d. Edit > clipboard > copy. File > new. Edit > clipboard > paste. Aumentate il numero di colonne fino a 28. Riconoscete la forma? Forse un'immagine vi può aiutare:
Esatto, si tratta della mappa città.
modificate qualche byte a caso posizionandovi direttamente sul byte a sinistra, e assicuratevi di essere in modalità OVERWRITE, non INSERT. Esiste un tasto della tastiera per fare ciò, ma io ho un portatile dunque è diverso per tutti, non posso dirvi dov'è. Oh, io ve lo dico lo stesso. per gli HP è sullo 0 del tastierino munerico, ma dovete premere FN.
Una volta provato a modificare qualche byte a caso, ricordatevi che non potete superare il valore 57h. Il motivo di ciò è spiegato nella mia guida, ma forse al momento è troppo complicata.
Quando siete soddisfatti delle vostre modifiche, copiate tutti i 420 bytes e INCOLLATELI nella ROM. Con XVI è un parto, per cui usero Hxd. Recatevi ancora all'offset 3E6E50h con ctrl+g e incollate i bytes premendo CTRL+B.
Slavate e aprite la ROM con l'emulatore. Andate a vedere la mappa città. Cambia qualcosa? Se avete fatto giusto, ora le città dovrebbero essere diverse.
Congratulazioni, avete appena fatto dell'HEX-HACKING!
Le possibilità di questi metodi avanzati sono infinite; entro i limiti tecnici del GBA, ovviamente. Il problema è che non è proprio semplice applicarlo, ma ora potete benissimo comprendere quelle che vedrete postare dai più esperti.
Esperienza 2)
cambiare i testi
Con questo metodo (per l'altro guardate la guida di emme97) a mio parere si fa leggermente prima
Esso si basa sullo scopo per il quale sono stati creati alcuni hex editor: scrivere.
Dopo aver acquisito dimestichezza con l'hex editor grazie all'esperienza 1 si può cominciare a fare sul serio 
L'obiettivo sarà la traduzione di una Stringa di testo presente nel gioco.
Iniziamo in modo "soft" predisponendo gli attrezzi del lavoro: lanciamo l'hex editor, apriamo la nostra ROM, e carichiamo la tabella dei caratteri: la procedura dipende dal programma. Su XVI è search>character conversion, su windhex è file>open table file. /!\ Attenzione! Sembra che XVI sostituisca fisicamente i bytes, quindi fate una copia di sicurezza prima di procedere!
Il prossimo passo è di ricavare l'offset ("scostamento" dall'inizio del file) del nostro testo. Per fare ciò avviate la funzione di ricerca (di solito è nei menu edit o search, ma ora dovreste sapere dove si trova), e scegliete di cercare una stringa di caratteri, quelli della nostra table. Inserite il testo che volete cercare. Ecco un esempio.
Attenzione, il testo deve combaciare esattamente! Motivo per cui è meglio non mettere le iniziali, dato che potrebbero essere maiuscole. Abbiamo il risultato, che è all'offset 1C6D78h (il testo parte da "Hi!").
Ora dobbiamo cercarne il puntatore Che significa? Quando il gioco è stato creato ("compilato") i programmi degli sviluppatori hanno separato le istruzioni dai dati, perciò in mezzo alle istruzioni della intro c'è una referenza al dato del testo. Il puntatore è semplicemente un valore (capiremo meglio questo aspetto nel prossimo capitolo) che indica al GBA dove andare a trovare un dato (o anche un'istruzione, volendo).
Per il momento prendete per buono quanto segue.
- Per ricavare il puntatore dell'offset, scriviamo XX XX XX 08.
- Prendiamo i byte del nostro offset e invertiamoli di ordine (da 1C 6D 78 a 78 6D 1C)
- Sostituiamoli alle X: 786D1C08.
Ora che abbiamo il puntatore dobbiamo cercarlo nella ROM, dunque ancora la funzionalità di ricerca, ma stavolta ditegli di cercare un valore hex. Potrebbe essere comodo flaggare l'eventuale opzione "cerca dall'inizio dal file".
Sarebbe meglio trovare solo 1 o pochi risultati, perchè se presumiamo che il dato venga usato solo una volta in tutto il gioco, trovarne tante referenze significa che c'è qualquadra che non cosa. Segnamoci questo risultato da qualche parte.hr
Il nostro prossimo passo sarà di scrivere il testo effettivo.
Posizioniamoci in uno spazio libero con ctrl+g (il grande oceano sconfinato di spazio libero su rubino parte da circa 6B1000h e termina a CFFFFF, per ripartire da EAE300h fino alla fine; su rosso fuoco con una rapida ricerca di FSF trovo 71A23C, ma non sono pratico di tale rom, dunque prestate attenzione)
Iniziamo a scrivere il nostro testo con la tabella dei caratteri di pokemon (dovrebbe essere selezionata quando la caricate, altrimenti selezionatela. (Per windhex File > swap table file).
Secondo me questo metodo di lavoro è molto più veloce e fluido, l'unico piccolo inconveniente rispetto a XSE è che non abbiamo la giusta sensazione dello spazio occupato nella riga. Per questo il metodo da il massimo per testi piccoli, ad esempio per tradurre gli strumenti/mosse/chicchessia. A parte che comunque è possibile inserire l'accapo con il byte 0xFA e il paragrafo con 0xFB (e che potete ridimensionare la finestra del programa a una trentina di byte per simulare una riga) questo metodo è più diretto per inserire le sequenze di escape, che su XSE richiedono particolari sequenze di caratteri. Cosa sono? Nei linguaggi di programmazione, sono delle sequenze di caratteri che quando vengono lette dal computer, fanno qualcosa di particolare. Ad esempio l'accapo è una di esse. Quando il programma che legge il testo da scrivere trova la sequenza di accapo ("\n" in molti linguaggi di programmazione, ecco perchè su XSE per andare a capo si usa "\n"), parte una funzione corrispondente, che esegue l'accapo. Ovviamente le sequenze di escape del GBA sono completamente diverse da quelle dei computer. Potete averne un'idea consultando la stessa pagina di bulbapedia fornita prima. L'unica che dovrete assolutamente ricorare è 0xFF che segna la fine di un testo (un po' come 0xFE segna la fine dei movimenti). Altre invece sono carine curiose, come quella per colorare il testo (ma tanto vedremo nel terzo capitolo un modo superiore) o mostrare le variabili come il nome del rivale.
Una volta soddisfatti del testo, dobbiamo farlo usare dal gioco, sostituendo il puntatore del testo vecchio con quello nuovo. Ricaviamo ancora l'offset seguendo i passaggi, così nel mio esempio diventa 10007008h.
Andiamo al posto che vi siete segnati prima (il puntatore del testo vecchio) e sostituite i byte con il nuovo vaore appena calcolato! Ora non resta che provare la modifica:
FINE!
Esperienza 3)
Tabelle
Questa è l'ultima sezione del capitolo, dopodichè, se completata con successo, potrete definirvi competenti nel''hex editor, ve ne do il permesso.
Ovviamente dato che sono pigro useremo un esempio già scoperto
Non c'è molta difficoltà in più, anzi; serve solo molta attenzione a non combinare casini.
Questa esperienza sarà un po' meno pratica ma più descrittiva.
Bene, recatevi con una ROM di rubino (sempre la solita asd) a 3E73C4h.
aggiustate la vista delle colonne per una visione confortevole della tabella.
se tutto è corretto, dovreste avere qualcosa del genere:
http://postimg.org/image/jjrtfo3kz/
Come funzionano le tabelle?
Quando i casi da gestire per una situazione sono molti, nei linguaggi di brogrammazione di alto livello si usa il costrutto switch (o l'istruzione case, a seconda del linkuaggio), che permette di elencare velocemente tutte le possibilità.
Per farla breve, Anche le tabelle di pokemon sono un segno dello switch. Di solito prima di accedervi è stato ottenuto un valore, chiamato indice, che indica quale elemento deve essere letto. Dato che le voci sono tutte lunghe uguali, è facile risalire all'offset del nostro dato. Il GBA scorre tutta la tabella finchè non trova il valore corretto, oppure calcola subito l'offset.
Prima di modificare le cose alla cieca è meglio studiare approfonditamente la tabella e capire cosa rappresenta. Nel caso di esempio rappresenta i valori delle città.
ogni voce è costituita dalla stessa struttura:
- Coordinate
- Dimensioni
- Puntatore al nome
Per maggiori informazioni vi rimando alla guida ufficiale (che siccome non ho mai tempo di riscrivere è ancora in R&D ^_^" )
Se i valori binari occupassero in totale un numero di byte "strano", la tabella avrebbe dei byte di riempimento ("filler") o anche allineamento ("padding"), che di solito sono 0x00 o 0xFF.
Dunque se noi volessimo alterare i dati all'interno potemmo farlo comunemente, come se stessimo modificando normali dati binari. Bisogna però sempre ricordare le solite regole, ovvero MAI AGGIUNGERE BYTES ALLA ROMA e RICORDARSI LA STRUTTURA DELLA TABELLA.
E se si volesse aumentarne le dimensioni? Bisogna ripuntarla. Il procedimento non è dissimile da quello che abbiamo fatto per il testo. Andate all'inizio di una tabella (dovete esserne certi però che sia davvero l'inizio) e ottenetene il puntatore, ribaltando i bytes e aggiungendo 08. Cercate tale valore nella ROM e sostituite le occorrenze (con cautela se sono molte) con il nuovo punntatore, che punterà allo spazio libero. Poi copiate la vostra tabella e incollatela nello spazio libero e aumentatela. Ricordate che di solito le dimensioni massime sono di 255 o 65535 voci, ma più spesso 255. Dovete vedere quanti byte è grande l'indice; solo che a volte non è immediato e serve l'asm.
FINE!
Alla fine ciò che noi facciamo coi programmi non è altro che un'operazione molto simile a questa, soltanto (molto) semplificata e (fortunatamente) automatizzata. Infatti i programmi, specialmente quelli più user friendly come advance map, compiono spesso "di nascosto" queste operazioni di repoint, e a volte non è proprio poca roba.
Tuttavia questa pratica sarebbe abominevole davanti agli occhi di un programmatore, in quanto stiamo "Pacioccando sul compilato", citando un importante membro di un altro forum (non di pokemon state tranquilli). Ci riesce bene perché fortunatamente la struttura della ROM e del GBA si presta a questo tipo di modifiche.
E adesso arriva il bello. Fino a poco tempo fa c'era l'hacking tradizionale, che consisteva nel cambiare qualche mappa, mettere gli script e il gioco era fatto; poi vabbè è arrivato andrea e ha portato con se un uragano di novità (insieme ad un file idb che il popolo vorrebbe!!!  ) Perchè ho fatto questa distinzione "Avanti Andrea" e "Dopo Andrea" ( ok adesso mi sembra di essere blasfemo lol) ? Semplice. Andrea non si limita a modificare i dati di una ROM, ma ne modifica anche le istruzioni
Noi fino ad adesso, con i programmi tipo AMAP, abbiamo semplicemente modificato i dati di un programma GBA, e ci è sempre bastato. Abbiamo alterato solamente i più superficiali strati di un sistema software costruito su misura, "ad arte", per l'hardware su cui avrebbe dovuto essere eseguito, senza nemmeno scalfire ciò che sta sotto, ai livelli inferiori. Ora con l'ASM stiamo scendendo man mano nei più reconditi meandri dell'engine... Mentre i nostri colleghi di prima generazione sono addirittura un passo avanti a noi con il disassembly completo... Ma queste fantasticherie del professor De Nuvolis le lasciamo per dopo, mentre ora è il momento de
- L'architettura del GBA e la sua relazione con il WBTO (breve)
Questa parte sarà più corta della precedente, ma è un passaggio obbligato.
Il GBA, in quanto macchina di Von Newmann, è paragonabile ad un PC.
Esso è dotato di:
- Un processore (  )
- Una memoria ad accesso casuale
- Memoria di massa
- Dispositivi di input/output
Il processore è il "cuore" di un computer. Si occuppa di fare tutti i calcoli richiesti dal software e di "mandare avanti la vita della macchina", se mi passate l'analogia.
La memoria ad accesso casuale (RAM per gli amici) è una memoria molto veloce che immagazzina temporaneamente i dati che devono essere elaborati. Si cancella allo spegnimento.
La aemoria di massa, in questo caso la cartuccia del gioco (Read Only Memory). Contiene tutte le istruzioni che devono essere eseguite e i relativi dati.
Infine, come output abbiamo l'altoparlante, lo schermo, mentre per input c'è i tasti, la presa per il cavo.
La particolarità del GBA è che tutto viene rappresentato sotto forma di "memoria". Per comprendere meglio il concetto, aprite una qualsiasi ROM con il VBA. Andate su Tools > memory viewer. Ora vedrete una distesa continua e sterminata di bytes. Ogni memoria reale viene mappata come parte di un'unica area di memoria contigua, ed è possibile accedere indifferentemente a qualsiasi memoria con le medesime procedure. Il menù a tendina a sinistra per il momento è la parte più importante da osservare. Esso infatti è un selettore di tutte le memorie del GBA. Ogni memoria ha un codice di identificazione.
- 00: Bios. E' una memoria importantissima in informatica, nonostante a noi per il momento non serva a molto. Contiene le "istruzioni di base" di una macchina. Se mi passate il paragone con il mondo animale, potremmo dire che è l'istinto.
- 02: WRAM. La vera RAM, contiene tutti i dati in attesa di essere elaborati.
- 03: IRAM: RAM Interna. Sta all'interno del processore. E' molto più piccola dell'altra, ma è dannatamente più veloce.
- 04: Registri Input/Output. Questa minuscola sezione è veramente ostica, e serve per controllare tutte le periferiche del GBA. Sul GBATek è presente una descrizione dettagliata
- 05 Palette. Le palette da utilizzare per dipingere la scena. Non è modificabile, ma viene costantemente aggiornata prendendo i dati da un'altra area di memoria.
- 06 VRAM: Memoria video. contiene i tiles e le mappe dei BG (gli "strati" di visualizzazione)
- 07 OAM: contiene gli attributi degli oggetti. Per maggiori informazioni vi rimando alla guida di Feanor.
- 08 ROM: Qua c'è la nostra immagine del gioco. Ovviamente non è modificabile. Per accedere a dati di ROM di dimensioni maggiori di 16 MB (e inferiori a 32) si utilizza il prefisso 09.
Vi starete chiedendo il perchè di tutta questa cosa, ed è presto detto. Innanzitutto serve per l'asm, e poi per comprendere meglio il comando WBTO, nonchè l'hex hacking in generale.
Se vi ricordate, prima vi ho detto di aggiungere uno 08 al puntatore di un testo. Quello 08 significava la ROM! La struttura del GBA è versatile, e uno così può accedere in maniera trasparente a qualsiasi memoria, semplicemente mettendo il giusto prefisso prima dell'offset desiderato! Così si spiega anche la massiccia presenza di 08 nelle tabelle, in quanto si riferiscono a dati che stanno sulla ROM.
Ed ecco perchè preferisco XVI: avendo i caratteri DOS, lo 08 è un carattere dalla forma particolare e subito identificabile, che si traduce in comodità nella lettura/modifica di tabelle.
Da notare la coincidenza di scrivere 0x per denotare un numero esadecimale e l'utilizzo di uno 0 seguito dal numero della memoria. Fuori dal nostro ambiente non lo sapranno mai, ma è convenzione che se si scrive un valore del GBA, con memoria e offset (32 bit), è esadecimale. Dunque i valori 083E6E50 e 0x3E6E50 in teoria sono equivalenti, ma bisogna vedere quale è la convenzione utilizzata.
Ma ora, finita la teoria, facciamo qualche esempio di WBTO. Esso sta per WriteByteToOffset, ovvero scrive un byte all'offset specificato. Se il numero di byte da scrivere è maggiore di una manciata, conviene usare l'asm in quanto occupa meno spazio ed è più veloce (anche se noi potremmo non percepire la differenza).
ecco la sintassi generale:
writebytetooffset 0xXX, 0xYYYYYYYY
dove XX è il byte da scrivere, YYYYYYYY è il dove scriverlo.
Cambiare il genere del giocatore:
è stata pubblicata una guida per fare ciò, ma il metodo WBTO è applicabile solo a rubino. Essenzialmente dovete settare a 0 o 1 il byte a 02024EAC.
cambiare colore del testo
A partire da 0202EEC8 c'è la replica delle palette. Secondo l'enciclopedia,
Citazione:Nella computer grafica la tavolozza, anche chiamata palette (sinonimo mutuato dalla lingua inglese), è una lista di colori scelti nell'insieme di tutti quelli disponibili. Ogni colore della tavolozza è associato ad un indice, cioè ad un ordinale che identifica il colore nella tavolozza stessa (è possibile comunque che lo stesso colore si ripeta con indici diversi). La rappresentazione dei pixel di un'immagine attraverso indici nella tavolozza permette un drastico risparmio memoria e tempo computazionale rispetto ad altre tecniche, ma limita la gamma di colori utilizzabili a quelli presenti nella tavolozza. Questi ultimi possono essere fissi, se determinati, ad esempio, dall'hardware utilizzato, oppure modificabili a seconda della fattispecie di un'immagine. Per sfruttare al meglio le caratteristiche della tecnica digitale il numero di elementi in una tavolozza è generalmente una potenza di due e raramente supera i 28 = 256 colori. Quando è necessario un numero di colori ancora maggiore – è questo il caso di tutte le rappresentazioni fotografiche o realistiche – le tavolozze non vengono usate; il colore è allora codificato direttamente nelle componenti cromatiche secondo il modello adoperato.
Talvolta qualcuno usa il termine "palette" al posto di "colore".... E ovviamente non va bene.
Ah-ehm, dicevamo. Il testo usa la sedicesima palette, e dato che ogni palette occupa 32 bytes, dobbiamo scendere di 32 righe nel VBA memory viewer. Se avete fatto giusto, dovreste trovare 0202F0A8. Scriviamo qualche byte (Usate pure i programmi RGB to GBA per calcolare il colore, oppure l'editor palette di advance map), e così potremo usare qualsiasi colore che il GBA può visualizzare!
cambiare il nome del box
i nomi dei box sono collocati a 020383E4. potete seguire la tabella dei caratteri di bulbapedia e cambiare il testo con dei wbto.
se troverò altri esempi li aggiungerò.
- Rapporto diretto con l'hardware: Assembly (media)
Ed eccoci alla parte più importante del tutorial, al boss finale. Data l'importanza dell'argomento, spero di essere all'altezza.
Spesso abbreviato in ASM, è quanto di più vicino al linguaggio macchina l'uomo possa comprendere senza diventare pazzo. Infatti il linguaggio macchina è fatto dai cosiddetti codici operativi, ovvero dei byte che vengono letti dal processore, ed ognuno ha un preciso significato come istruzione. La sua particolarità rispetto agli altri linguaggi di programmazione è che c'è una corrispondenza 1:1 tra istruzioni scritte e istruzioni reali della macchina. Significa che per ogni istruzione scritta/letta da noi esiste un singolo codice operativo, e questa cosa si esprime dicendo che "esiste una sostituzione mnemonica tra istruzione della macchina e parola chiave del linguaggio". L'assembly, come avrete intuito, è un linguaggio a basso livello, per cui non è dotato di tutti i meccanismi di sicurezza che di solito abbiamo. Siamo solo noi e l'hardware. In altre parole, siamo i padroni totali, ma dobbiamo anche prenderne le responsabilità.
nota:
In questa breve esposizione cercherò di informarvi su come creare routine da eseguire in, per così dire, maniera diretta (vano tentativo di tradurre "straightforward"), ovvero di tali funzioni che vengono chiamate da un livello superiore (lo script), sono eseguite per la loro integrità, e ritornano un risultato. Per semplicità d'esposizione non tratterò delle routine inserite in altre routine esistenti, perchè nonostante come difficoltà concettuale non siano molto più complicate, la loro ricerca e successiva applicazione può variare sensibilmente da caso a caso; inoltre esce leggermente dallo scopo di questo testo. Spero di non avervi spaventato/annoiato con questa breve introduzione.
Cominciamo con il fornire qualche link utile
presentazione del processore
manuale del processore - parte 1 (anche se "nessuno legge mai i manuali")
manuale del processore - parte 2
manuale del processore - parte 3 (consigliata)
altri manuali
tavola di riepilogo (consigliata)
Prima di elencare i comandi è necessario comprendere appieno la struttura della CPU (processore), altrimenti rischia di essere soltanto una sterile esposizione.
La CPU è composta da varie parti; a grandi linee troviamo l'ALU, unità che esegue le operazioni, la CU, unità di controllo, e i BUS (collegamenti elettrici) che trasferiscono i dati. Esiste poi un minuscolo pezzo di memoria (non è l'IRAM di prima) che è sufficiente a contenere giusto i dati che servono per la corrente operazione. Tali spazi di memoria sono i registri. I registri possono essere paragonati a delle variabili, ovvero dei contenitori di informazioni. Pensate ad una tazza piena di riso: noi possiamo mettere dentro tutti i chicchi di riso che vogliamo, ovviamente finchè non tracima (operazione da evitare come la peste nella programmazione), oppure possiamo svuotarne il contenuto, o anche solo contare quanti chicchi contiene in un certo momento. I registri del GBA sono lunghi 32 bit, ovvero possono contenere dati fino a FFFFFFFFh.
Ecco i registri:
- PC: Program Counter: contiene l'indirizzo della prossima istruzione. Non bisognerebbe mai alterarlo manualmente.
- R0-R12: contengono le nostre variabili
- LR: Link Register. Nell'architettura x86 non esiste, ma qua (architettura ARM) serve per contenere l'indirizzo a cui ritornare dopo l'esecuzione della funzione corrente. Non è possibile pensare di eseguire tutte le operazioni una dietro l'altra, in quanto occorre fare una separazione logica dei vari compiti da eseguire. Per questo ogni programma (quindi anche pokemon) è suddiviso in funzioni, ovvero dei pezzetti di codice che fanno solo una cosa. Quando le funzioni vengono chiamate, si dà loro dei dati, detti parametri, che useranno per fare il loro compito. Ad esempio, in un linguaggio di alto livello, possiamo scrivere "sqrt(2);" per chiamare la funzione della radice quadrata, con parametro (o argomento, per noi va bene utilizzare le 2 parole come sinonimi) che vale 2. Ecco, il link register viene aggiornato tutte le volte che viene chiamata una funzione, e contiene l'offset dell'istruzione successiva, allo stesso livello di profondità dell'istruzione chiamante.
- SP: Stack Pointer: Noi non useremo nemmeno tale registro, ma è importante sapere cos'è. Contiene l'offset dell'ultimo valore dello stack. Cosa è lo stack? Significa "pila". Contiene tutti i dati temporanei accantonati per qualche motivo. Perchè bisogna accantonare i dati? Perchè se io chiamo una sotto-funzione, essa avrà bisogno, come ogni funzione di qualsiasi livello, dei registri per compiere le sue operazioni. Ma i registri erano in uso anche dalla funzione precedente; per questo dobbiamo svuotarli, e ne riversiamo il contenuto nello stack. Fatto ciò la funzione corrente potrà usare liberamente i registri. Finita la sua esecuzione si salva un eventuale valore di ritorno (il risultato della funzione, ovvero nel caso di sqrt(2) è 1.41421356237) in un registro e si ripristinano gli altri, in modo che l'esecuzione del programma possa continuare.
Una piccola premessa: il processore ha 2 moalità operative: si chiamano arm e thumb, e saranno nominate varie volte in seguito. ecco le principali differenze: arm utilizza 32 bit per istruzione, mentre thumb 16. thumb è più veloce (credo di ricordare 1,6 volte) ma ha alcune limitazioni nelle operazioni consentite(sono poche e non condizionali). ogni istruzione thumb ha un corrispettivo arm. Il GBA sa in quale modo operare grazie a un registro di un bit, se 0 ARM, se 1 thumb.
ecco perchè quando facciamo il famoso comando callasm su script dobbiamo aggiungere 1 all'offset, serve per innalzare a 1 il livello del registro del modo operativo!
Vi indico alcuni comandi. Non spaventatevi se vi sembrano pochi rispetto allo scripting, dopotutto è linguaggio macchina, e tra l'altro RISC.
va beh, si trovano pure nella thumbref ^_^" Se mai li spiego un pochino con parole mie- ADD/MUL/SUB
operazioni matematiche somma moltiplicazione sottrazione. cioè fatemi capire volete rifare le elementari? Secondo me, per queste operazioni la documentazione basta e avanza. Ricordatevi solo che Rd significa registro di destinazione mentre Rm e Rn sono gli operandi dell'operazione.
- B/BL/BX servono per eseguire dei salti. I salti permettono di alterare il normale flusso di esecuzione del programma, ma per routine semplici non sono necessari. Di solito si usano quando si testa una condizione e si vuole un comportamento diverso a seconda dei casi. Se avete capito bene i goto negli script, non avrete problemi. La differenza tra i tre è che B salta e basta, BL salta e "si ricorda" il punto del salto e poi ritorna, BX salta e cambia modo operativo, a seconda dell'ultimo bir del valore.
E' possibile aggiungere delle condizioni all'istruzione B.- BEQ signifca salta se uguale (branch equal)
- BNE Branch not equal
- BGE Greater or equal
- BLT Less than
- BGT Greater than
- BLE Less than or equal
I salti condizionali sono molto usati con l'istruzione CMP.
- CMP paragona. può paragonare un registro ad un byte, o 2 registri e mette il risultato nel PSW. subito dopo asrebbe utile eseguire un salto. altrimenti è un'operazione sprecata. Questo è l'unico modo di eseguire istruzioni condizionali in modalità thumb
- LDR/LDRB/LDRH/MOV Serve per caricare un registro con dei dati. Esistono varie opzioni, come un valore immediato; un valore letto dall'indirizzamento indiretto; un valore ottenuto mediante operazioni, ecc. La differenza sostanziale tra i tre sta in cosa caricano: LDR 32 bit, LDRH 16 bit (H sta per Half) , LDRB 8 bit (B sta per Byte). MOV invece inizializza un registro con un byte.
- LSL/LSR serve per shiftare i bytes a destra o a sinistra. approfondimento sullo shift:
questa operazione è utile quando si vuole moltiplicare per potenze di 2. infatti si può moltiplicare di 2^n un numero spostando verso sinistra n volte i bytes. Per dividere shiftiamo verso destra.
esempio:
5d
0101b
shiftiamo di 1
1010b
10d
esempio
50d
110010b
shiftiamo di 1
011001b
25d
per favore ditemi se non sono stato chiaro
- STR/STRB/STRH Questi invece fanno l'operazione inversa del LDR, ovvero "stoccano" il dato da qualche parte. Anche qui Vi sono molte opzioni, ma è meglio visionarle sulla guida, in quanto in questa sede appesantirebbe la lettura.
- POP/PUSH servono all'inizio e alla fine della nostra funzione ASM (non in tutti i casi, solo nelle sotto-funzioni) per accatastare sulla pila i contenuti dei registri che ci serviranno per compiere le operazioni. E' buona cosa ricordarsi di andare a riprendere le informazioni e rimetterle alloro posto una volta terminata la routine.
E' importante ricordare che per iniziare una sotto-funzione (quelle trattate in questa guida) su usa PUSH LR (più eventuali registri usati) e per terminarla si deve fare POP PC. Questo perchè quando eseguiamo un salto il Link Register assume il valore dell'offset dell'istruzione successiva a quella del salto. ovvero, per chi usa un IDE, "step over". ovvero, per i comuni umani, considera la funzione chiamata dal salto come una singola istruzione, e dunque l'istruzione seguente non è la prima che si incontra dopo aver seguito il salto, ma quella effettivamente successiva nel file (rimane allo stesso livello di profondità delle sotto-funzioni). Una volta accantonato il LR e compiuta la routine, dobbiamo tornare indietro. Come? Facile. Poppando (ok, doppiosenso, scusate) il LR otteniamo il punto dove continua la nostra ROM, ma per andarci dobbiamo metterlo nel Program Counter!
Notazione:
[x] indica ciò che si trova all'indirizzo X della memoria del GBA
<< o >> byte shifting
Finalmente un po' di esempi. Saranno commentati il più possibile (al limite dell'offesa all'intelligenza umana, s'intende  )
esempio di livello facile
Citazione:.align 2 // direttive al compilatore. vanno SEMPRE messe.
.thumb // Nessuna eccezione. (dato che non useremo mai ARM)
PUSH {r0-r1, LR} // dichiariamo i registri che ci servono
LDR R0, = 0xOFFSET
MOV R1, #VAL // mi preparo alla scrittura di un byte
STRB R1, [R0] // scrivo effettivamente il byte
POP {r0-r1, pc} // ripristino i registri
questa routine fa la stessa cosa di un WriteByteToOffset. Scrive un byte dove vogliamo
esempio di livello medio
per maggiori informazioni vi rimando alla pagina di spiegazione
Citazione:.align 2
.thumb
.main: // Un nome per riferirsi ad un punto preciso del codice. Di solito si usa per i salti. Qui non è servito.
push {r0-r1, lr} // dichiariamo i registri che ci servono
ldr r0, .POINTER // uno dei modi di caricare un dato
ldr r0, [r0] // sovrascrivo r0 con ciò che c'è all'offset indicato da r0
add r0, r0, #0x8 //ottengo l'offset del genere del giocatore (r0=r0+8)
mov r1, #0x1 //mi preparo a cambiarlo
strb r1, [r0, #0x0] // lo cambio effettivamente
pop {r0-r1, pc} // termino
.align 2 // necessario per non far crashare il tutto.
.POINTER: // ecco un utilizzo degli identificatori. solo che main non veniva mai usato.
.word 0x0300500C
esempio sempre di livello medio (ma più alto) sotto gentile concessione di andrea.
Provatela su una ROM di rubino.. avrete una simpatica sorpresa!
Citazione:.THUMB
.ALIGN 2
PUSH {LR}
LDR R0, = 0x08393250 @tile nella ROM
LDR R1, = 0x06008000 @offset tile BG0
SWI 0x12
LDR R0, = 0x083939EC @raw nella ROM
LDR R1, = 0x0600F800 @offset raw BG0
SWI 0x12
LDR R0, = 0x08393210 @palette nella ROM
LDR R1, = 0x0202F088 @offset palette
MOV R2, #16 @grandezza da copiare diviso 2
SWI 0xB
LDR R1, = 0x0202EC88 @offset palette fadescreen
SWI 0xB // a questo punto devo spiegare cos'è
POP {PC}
si è reso necessario spiegare cosa sia SWI. è l'acronimo di SoftWare Interrupt e consiste nell'eseguire alcune funzioni che stanno nel Bios del GBA. il suo utilizzo è simile agli script, quando usiamo un comando che vuole un numero d'indice.
Lo 0x12 decomprime i dati, mentre il lo 0xB copia una sequenza di bytes.
ok, giusto per completezza metto una mia routine di cui non avevo pubblicato il sorgente nella relativa discussione.
non è molto difficile se avete capito bene gli esempi precedenti, anche se direi che è di un livello intermedio alto. più che altro per le ore sudate a trovare dove iniettarla XD mentre su PC (o andrea) queste se le mangiano a colazione ahah
Citazione:.THUMB
.ALIGN 2
PUSH {R1,LR}
LDR R1, =0x00000008
MUL R0, R1
LDR R1, = 0x08740000
ADD R0, R0, R1
ADD R0, R0, #04
LDR R0, [R0]
POP {R1, PC}
si può notare fin da subito l'anomalo utilizzo del registro 0. Innanzitutto va chiarito che non è necessario pushare i registi a partire dal più basso, ma è una convenzione. In questo caso però r0 andava lasciato perchè contiene il valore di ritorno della funzione. (Dunque sarebbe diel tipo non coperto dalla guida, ma vabbè). Il suo scopo è scorrere una tabella e ritornare un valore letto. Avevo scoperto che in realtà il codice usato dal compilatore della GF per leggere una tabella è più elegante del mio (che non prevede eccezioni: o l'indice è corretto o ti arrangi - stile missingNO), ma se uno si crea la tabella con tutte le 255 voci è a posto. E per la cronaca, avevo sposato la tabella a 740000h.
ah, per fare una dimostrazione completa avrei potuto sostituire MUL 8 con LSL 3, che è un'operazione mooolto più veloce per il processore (solo che noi non lo percepiamo perchè siamo lenti) Per compilare e inserire una routine esistente esistono già guide (o di feanor o andrea, non ricordo esattamente)
grazie per aver seguito!
vi chiedo sempre utili feedback, in particolare se ci sono delle parti spiegate troppo sinteticamente per essere ben comprese.
FIRMA (intanto che ivan rimette lo spazio dedicato)
Guida di cui vado più fiero: Mega-Huge Bonnox' guide
Il mio nuovo motto: don't ask for ETAs!
(RIP immagine firma cancellata dai server)
"L'uomo è ancora il più straordinario dei computer"
-
citazione famosa, qualcuno di importante nella storia, forse Churchill boh
pezzo di firma prevalentemente riguardo il fangirling su Doctor who, di cui ora mi mezzo vergogno ma che alla fine per qualche motivo non riesco a cancellare, come se fossi ancorato alle origini.
In fondo contiene anche un primordiale tentativo di ravvedimento, processo che si conclude con l'introduzione del presente spoiler.
*immagine di congiunzione tra mass effect e doctor who della segretaria samantha traynor con in mano lo spazzolino sonico*
Ho un T.A.R.D.I.S. modello 40 ma non so usarlo.
Ehm, in realtà non è mio. L'ho "preso in prestito". Presa. E' una donna, già.
Vuoi fare un giro? Ovunque e Dovunque; tutto il tempo e lo spazio; ciò che è stato e che sarà. Da dove vuoi cominciare?
People assume that time is a strict progression of cause to effect, but *actually* from a non-linear, non-subjective viewpoint - it's more like a big ball made of wibbly wobbly... time-y wimey... stuff.
Prima di fare le fangirl in preda agli ormoni informatevi sulla fisica!
 Mi Piace Ricevuti:  |
...Splash, Stygian, Mew2, Earl Undefined, 80C, Valley, bonzi, eMMe97, Drk090, Шахтар, Flygon, PokemonHack, Carl_J90, IceTrainer, Blakeishitta, MasterNinja98, Explosion100 like this post
|
Messaggi: 2,222
Discussioni: 98
Registrato: 29-12-2014
Reputazione:
17
Molto interessante questo inizio , specie per gente che come me da un po' di tempo si sta dando alla comprensione dell'hacking avanzato, mi raccomando, continuala!
 Mi Piace Ricevuti:  |
|
Messaggi: 82
Discussioni: 17
Registrato: 17-05-2015
Reputazione:
4
Complimenti, bella guida!
É la prima che trovo in italiano che spiega le basi di questi argomenti!
 Mi Piace Ricevuti:  |
|
Messaggi: 1,832
Discussioni: 159
Registrato: 09-10-2014
Reputazione:
45
@ Bonnox il "Livello Facile" non presenta alcun contenuto nello spoiler.
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
17-07-2015, 06:13 PM
(Questo messaggio è stato modificato l'ultima volta il: 22-10-2016, 11:58 AM da Bonnox.)
(17-07-2015, 05:51 PM)eMMe97 Ha scritto: @Bonnox il "Livello Facile" non presenta alcun contenuto nello spoiler.
infatti ho tolto solo adesso gli avvisi di incompletezza. :p
comunque sono contento di ricevere feedback positivi
FIRMA (intanto che ivan rimette lo spazio dedicato)
Guida di cui vado più fiero: Mega-Huge Bonnox' guide
Il mio nuovo motto: don't ask for ETAs!
(RIP immagine firma cancellata dai server)
"L'uomo è ancora il più straordinario dei computer"
-
citazione famosa, qualcuno di importante nella storia, forse Churchill boh
pezzo di firma prevalentemente riguardo il fangirling su Doctor who, di cui ora mi mezzo vergogno ma che alla fine per qualche motivo non riesco a cancellare, come se fossi ancorato alle origini.
In fondo contiene anche un primordiale tentativo di ravvedimento, processo che si conclude con l'introduzione del presente spoiler.
*immagine di congiunzione tra mass effect e doctor who della segretaria samantha traynor con in mano lo spazzolino sonico*
Ho un T.A.R.D.I.S. modello 40 ma non so usarlo.
Ehm, in realtà non è mio. L'ho "preso in prestito". Presa. E' una donna, già.
Vuoi fare un giro? Ovunque e Dovunque; tutto il tempo e lo spazio; ciò che è stato e che sarà. Da dove vuoi cominciare?
People assume that time is a strict progression of cause to effect, but *actually* from a non-linear, non-subjective viewpoint - it's more like a big ball made of wibbly wobbly... time-y wimey... stuff.
Prima di fare le fangirl in preda agli ormoni informatevi sulla fisica!
 Mi Piace Ricevuti:  |
|
Messaggi: 1,832
Discussioni: 159
Registrato: 09-10-2014
Reputazione:
45
Ovvio, ci voleva una guida ASM che spiegasse bene tutte le basi!
 Mi Piace Ricevuti:  |
|
Messaggi: 551
Discussioni: 28
Registrato: 01-04-2015
Reputazione:
7
@ Bonnox bellissima guida, veramente complimenti!
E comunque la citazione di "nessuno legge mai i manuali" l'hai presa secondo me dal cartone animato "Due fantagenitori". Giusto?
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
04-12-2015, 04:48 PM
(Questo messaggio è stato modificato l'ultima volta il: 04-12-2015, 04:51 PM da Bonnox.)
(04-12-2015, 03:35 PM)PokemonHack Ha scritto: @Bonnox bellissima guida, veramente complimenti!
E comunque la citazione di "nessuno legge mai i manuali" l'hai presa secondo me dal cartone animato "Due fantagenitori". Giusto? Ti ringrazio molto, sono felice che sia utile.
Si, hai indovinato ahaha
Anche se dovrei "sciacquare i panni in Arno" rimuovendo un po' di errori stilistici (come appunto le millemila divagazioni)
Sto pensando di aggiungere un altro esempio di asm, niente di che, però credo sia utile. Ma prima bisogna farlo [emoji14] [emoji28]
inviato dal mio C5303 utilizzando SchifoTalk
FIRMA (intanto che ivan rimette lo spazio dedicato)
Guida di cui vado più fiero: Mega-Huge Bonnox' guide
Il mio nuovo motto: don't ask for ETAs!
(RIP immagine firma cancellata dai server)
"L'uomo è ancora il più straordinario dei computer"
-
citazione famosa, qualcuno di importante nella storia, forse Churchill boh
pezzo di firma prevalentemente riguardo il fangirling su Doctor who, di cui ora mi mezzo vergogno ma che alla fine per qualche motivo non riesco a cancellare, come se fossi ancorato alle origini.
In fondo contiene anche un primordiale tentativo di ravvedimento, processo che si conclude con l'introduzione del presente spoiler.
*immagine di congiunzione tra mass effect e doctor who della segretaria samantha traynor con in mano lo spazzolino sonico*
Ho un T.A.R.D.I.S. modello 40 ma non so usarlo.
Ehm, in realtà non è mio. L'ho "preso in prestito". Presa. E' una donna, già.
Vuoi fare un giro? Ovunque e Dovunque; tutto il tempo e lo spazio; ciò che è stato e che sarà. Da dove vuoi cominciare?
People assume that time is a strict progression of cause to effect, but *actually* from a non-linear, non-subjective viewpoint - it's more like a big ball made of wibbly wobbly... time-y wimey... stuff.
Prima di fare le fangirl in preda agli ormoni informatevi sulla fisica!
 Mi Piace Ricevuti:  |
PokemonHack likes this post
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
30-01-2016, 11:40 PM
(Questo messaggio è stato modificato l'ultima volta il: 30-01-2016, 11:41 PM da Bonnox.)
ho corretto un paio di frasi (ma ci sarebbe ancora molto da fare)
in futuro la amplierò con materiale tratto dalle ben più corpose aule.
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
20-07-2016, 12:17 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:06 PM da Bonnox.)
e niente, nell'attesa di ampliare la guida raccolgo qui le lezioni per la vostra e mia comodità. nota: non fornisco supporto per le suddette al di fuori della sezione di competenza.
PARTE 1 (purtroppo il sito taglia i messaggi troppo lunghi :v :c)
avvertimento: alcuni post saranno giganteschi perchè non ho potuto usare gli spoiler per questioni di impaginazione :c
LEZIONE 0 (INTRO)
DragonType eMMe9"
Hai la sfortuna di essere capitato nella mia prima aula!
Siccome non ho ancora ben definito un'introduzione vorrei chiedervi se vi sentivate di saltare qualche parte che magari conoscevate già, per andare più veloce; anche perchè da quanto ho visto siete comunque ad un certo livello, non so se avrete voglia di sentirvi parlare ancora dei byte e dei puntatori! XD
Innanzitutto vi comunico il materiale essenziale:
- ROM AXVE e BPRE
- VBA
-Hex editor
- VBA SDL-H
- Assemblatore
- Referenza
- Documentazione (anche troppo approfondita)
Sui primi due non penso ci siano problemi. Sono facilmente reperibili in commercio
Il VBA-SDL-H è una versione modificata che permette di fare cose avanzate per gli hacker, ed è quello che useremo più spesso. Funziona da linea di comando.
L'Asemblatore è un programma che permette di passare dal linguaggio al file binario effettivo.
dite se possiamo proseguire
(non è detto che arrivino messaggi così spesso eh, disabituatevi [emoji14] )
ah, mi manca il segnalino in alto, ho dovuto usare "scripting" :(
Ciao, innanzitutto chiedo scusa a tipo drago per aver cercato di forzare i tempi. Dopotutto siamo qui per imparare, bisogna aver fugato ogni dubbio! ;)
Ops, mi sono dimenticato di dirvi che nel materiale serve anche (OVVIAMENTE) un hex editor: quello che volete, ce n'è una svalangata tra cui scegliere, ergo usate quello con cui siete più comodi. I toolz servono per facilitare il lavoro, non per litigarci contro (e vi posso garantire che è infernale non andare d'accordo col programma in uso). Sicuramente emme97 sarà ben fornito, mentre a drago consiglio di dare un' occhiata ai seguenti 3, poi sceglierà lui : HxD, XVI 32, windhex 32.
Magari mi segno di non dimenticarlo la prossima volta (dopotutto ho appena iniziato, un po' di comprensione) ^_^"
Bene da ora in poi userò un tono serio, se ci riesco.
Inizio facendo un paio di considerazioni.
Innalzo il tempo di risposta dai 5 giorni canonici a 8 (ma potrebbero essere anche di più). Ovviamente questo vale solo per lo svolgimento di un compito, perché gli altri post non richiedono grandi capacità o applicazione, e anche perché immagino sarete incollati al pannello di controllo per vedere se ho risposto, dunque non c'è neanche bisogno di fissare una scadenza per il resto dei messaggi. Questa modifica semplicemente per il fatto che questa è roba di una certa levatura, a volte anche difficile. Potrà sembrare strano, ma come il mapping anche l'asm richiede tanto tempo... Per la creatività :v O.o no ok magari non è la migliore scelta lessicale, fatto sta che ci può davvero volere del tempo. Dunque avremo orari... flessibili. Fortunati voi che siete in vacanza.
Allora la mia idea, prescindendo dagli argomenti trattati, era di preferire un post grosso diviso in più parti, in modo da poter analizzare con calma ogni singolo aspetto. Non disdegno la tecnica "mordi e fuggi", ma in questo caso non potrebbe essere applicata per svariati motivi. Magari negli altri casi, come spiegare i comandi di XSE un po' per volta, può funzionare (drago perdonami se ho detto qualcosa che ti urta), ma non qui.
Se siete d'accordo posso iniziare, dopo questa breve presentazione, con la vera lezione.
Mi dispiace solo che abbiate interpretato male la mia prima fase. Uno l'ha presa come "prima impara questi prerequisiti", l'altro come "dimmi tutti i comandi che sai usare". Ragazzi tranquilli che non vi mangia nessuno! Anzi, si può anche essere informali, se favorisce l'obiettivo! Del resto programmare è a suo modo un'arte, dunque serve un ambiente ottimale. La mia era solo una domanda volta a cercare di risparmiare tempo ed energie, non certo un obbligo.
Detto questo ci vediamo la prossima volta :)
Saluti
(spero non sia sembrato "kattivo", non voglio essere cattivo se non c'è motivo)
(e, plis, aiutatemi a guarire dalla mania delle parentesi. Siete autorizzati a mandarmi un messaggio se metto troppe parentesi)
Okay DragonType eMMe97 , let's get this show started.
LEZIONE 1
scusate se non è molto bello da vedere.
Devo fare una piccola premessa per permettere a drago di recuperare terreno: Terminologia
- Bit
Elemento che può assumere 2 stati (configurazioni) diverse. Rappresenta le 2 cifre del sistema binario (0 e 1). È l'unità fisica minima nell'informazione.
- Byte:
È l'unità logica fondamentale, composta da un gruppo di 8 bit su un supporto (cd, hard disk, radio frequenze...) Può dunque assumere un massimo di 2^8 = 256 stati diversi. Nel nostro sistema decimale si parte da 0 e si arriva a 255. In binario è 11111111b. In esadecimale corrisponde a 0xFF.
- Offset:
letteralmente "scostamento", indica lo spostamento di un byte relativamente all'origine del file. Noi fortunatamente consideriamo sempre tale origine come il primo byte della ROM, dunque indirizzo 0 (ricordo che in informatica si inizia sempre a contare da 0), ma non è raro il caso di dover iniziare a contare a partire da un altro valore. Ad esempio per hacking di altre console (il caso più vicino a noi è GB) si divide la rom in varie parti; ognuna determina una diversa origine del valore dell'offset.
- Puntatore: generalmente in informatica è un valore (sarebbe meglio dire variabile, probabilmente sai cos'è visto che hai un corso di scripting) che indica, quindi "punta", un'area della memoria della macchina. Generalmente nei computer indica la RAM, ovvero la memoria temporanea che contiene i dati in attesa di essere elaborati. Mentre noi avremo quasi sempre a che fare con puntatori alla ROM, che è la memoria di sola lettura in cui risiede il gioco (che actually è da considerarsi il sistema operativo del GBA, ma se mai lo spiegherò più avanti).
Come avrete capito in questa prima parte lavoreremo sui byte; nonostante ahimè sia un lavoro noioso secondo me è più facile da comprendere di altro.
Ogni file sul nostro computer è composto da una serie più o meno lunga di bytes. Come avrete avuto modo di notare, la rom occupa esattamente 16 MB, il che è veramente poco, se non fosse che risale al 2002 e per giunta è per una piattaforma mobile.
All'interno del file ci sono, stipati insieme, tutte le istruzioni del programma e tutti i dati che servono a far funzionare correttamente il tutto. Le istruzioni sono ciò che vedremo con l'Assembly, il linguaggio macchina sostanzialmente, ovvero tutte le istruzioni che il GameBoy esegue una volta caricato il gioco, come ad esempio "fai questo suono", "memorizza tale variabile", “visualizza l’immagine”, eccetera. I dati invece sono informazioni conservate nella rom con un preciso formato. Ad esempio sono dati le musiche, le mappe, i pokemon degli allenatori, i testi dei messaggi… tutto quello che viene modificato dai programmi è un dato. Ma noi dobbiamo imparare a farlo anche senza programmi. I dati vengono letti solo quando necessario e caricati a blocchi nella ram, che anche se piccola è molto veloce, in quanto le continue operazioni di lettura rallenterebbero il programma. Infatti la memoria centrale (altro nome della ram secondo Von Newmann) è sì più piccola, ma anche molto più veloce della memoria di massa. Si parla di tempi dell'ordine dei nanosecondi per accedere a un dato, contro i vari millisecondi della rom...
Bene, eccoci alla vera lezione. Mi scuso se sarà un po’ monotona, ma è importante. Come diceva un mio professore, “il brutto delle cose facili è che vanno sapute perfettamente”.
Aprite un hex editor. Esso è un software che ci permette di visionare e modificare i bytes di un file. Ecco come si presenta uno di essi una volta aperto:
Iniziamo caricando un nuovo file. Consiglio un file che non vi serve più, dato che andremo a pasticciare :D
Normalmente troveremo tre colonne: una indica l’offset dall’inizio del file, quella centrale visualizza tutti i byte, e l’ultima colonna ci indica gentilmente la loro rappresentazione testuale. Che non potrebbe fregarci di meno. L’unico utilizzo che può avere per noi tale parte è per “rincuorarci”, ovvero trovare un piccolo conforto in caratteri familiari di fronte all’agonia della vista dei byes. Ok, dovrò andare a fare il drammaturgo :)
Posizionate il cursore sulla colonna a destra, e iniziate a scrivere cose a caso sul file cavia. Notate che c’è una corrispondenza a sinistra con ciò che scrivete?
Ora vorrei che vi prendeste un attimo di tempo per fare una cosa. Iniziate a scrivete tutte le lettere dell’alfabeto, dalla a alla z, minuscole e maiuscole, e poi i numeri. Cosa notate? I byte a destra assumono precisi valori. Signori, vi presento l’ASCII. Questo è uno standard americano di comunicazione abbastanza datato, ma è la base dei più recenti. Ora prendiamo confidenza con le funzionalità. Non so il vostro percorso del menu a tendina, ma esiste una scorciatoia universale: CTRL+F. aprirà una finestra chiamata ricerca. Qua ci mettete del testo che volete venga cercato all’interno di un file. Se state usando una rom di pokemon non avrete fortuna, perciò cambiate subito file. Dopo aver avviato la ricerca si posizionerà il cursore sulla prima occorrenza; per cercare ancora premete F3. Oppure create una lista di risultati, che è più comoda:
Fate la stessa cosa con le stringhe esadecimali. Cercate una stringa, stavolta corta, per aumentare le probabilità di successo.
Ricordate che anche se in generale sono simili, ogni hex editor ha proprie funzioni aggiuntive che vale la pena provare e sfruttare.
Ad esempio poco fa avete visto in azione una delle caratteristiche che mi piacciono di windhex. Peccato che sia un po’ scomodo da usare “quotidianamente”.
Ora vorrei concentrarmi su una cosa molto importante, ovvero la ricerca dei puntatori. Come accennato prima sono dei valori che indicano una posizione all’interno della memoria del GBA. Ipoteticamente, ogni byte potrebbe avere il suo puntatore, basta costruirlo. Nella realtà però non è così perché si indica soltanto il primo byte di qualcosa, quelli seguenti sono referenziati tramite un indice di scostamento rispetto al puntatore (l’origine di cui parlavo prima). Considerate questo esempio:
“QUEL FEZ SGHEMBO COPRE DAVANTI”
non preoccupatevi, è soltanto un pangramma. Volevo mettere quello degli ioni che era l’unico che ricordavo a memoria, ma nell’aprire wikipedia ed aver visto una citazione al mio telefilm preferito… beh… <3<3 giustamente dovevo metterla, concedetemelo. Analizziamo ora la frase:
[Q][U][E][L][ ][F][E][Z][ ][S.][G][H][E][M] [O][ ][C][O][P][R][E][ ][D][A][V][A][N][T][I.]
Abbiamo un indice che identifica ogni lettera:
[00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29]
Se volessimo accedere ad una lettera, non dovremmo fare altro che sommare l’indice all’offset del primo carattere, così:
Codice: *byte[] carattere;
carattere[i]=&frase[0]+i
ovvero, in un linguaggio più umano (perdonate la sintassi C e lo stile matematico della definizione (ci mancavano solo il “per ogni” e “tale che” :asd: )), significa che ogni lettera all’indice i di un testo ha un offset totale pari all’offset del primo carattere più il suo offset relativo, appunto l’indice i. capiamo meglio con un’immagine:
In questo esempio possiamo vedere che l’offset del primo carattere è 9D3CE4h, e se voglio l’indice del carattere z devo sommare l’i di z, ovvero 7.
Spero sia chiaro, altrimenti non fatevi scrupoli a chiedere.
Ora vediamo quali sono i passaggi per ottenere un puntatore. Per il momento ci saranno dei punti poco chiari, ma nelle prossime lezioni saranno rivelati.
Dato un offset lungo 3 byte, il suo puntatore è:
- scrivere XX XX XX 08;
- invertire l’ordine dei 3 byte (quello in mezzo ovviamente resta in mezzo)
- sostituire i nuovi byte alle X.
Ecco l’esempio per 9D3CE4:
- scrivo XX XX XX 08;
- ribalto i bytes: E4, 3C, 9D.
- sostituisco: E43C9D08.
Questo è il puntatore come se fosse stato inserito nella ROM originale.
Avete voglia di ricavare qualche puntatore, così giusto per esercizio?
Ricavate i puntatori dei seguenti offset:
- 3E6E50
- FB328
- E00000
Spero lo abbiate fatto, perché alla fine della lezione vi servirà.
Bene, eccoci alla prima su due cose pratiche. Recatevi all’offset 3E6E50. Come fare? Non so quale sia il vostro menu a tendina, ma sicuramente potete fare CTRL+G.
Inserite l’offset come faccio io e dovreste avere il seguente risultato;
Questo è un dato binario. Significa che è un dato rappresentato nel suo tipo (formato) naturale. ne consegue che solo chi sa leggere quel tipo di dato potrà comprenderne il significato. Fate una prova: aprite un’immagine con il blocco note. Cosa esce? Caratteri incomprensibili, perché il blocco note non sa leggere le immagini, lui poverino cerca solo il suo formato di dati (il testo) nell’immagine. Se provate ad aprire file prodotti da un’applicazione professionale, come ad esempio qualcosa di autodesk o adobe, con un programma totalmente diverso, come ad esempio VLC, sarete fermati da un errore di incompatibilità. I programmi si aspettano certe cose nel file che aprono, e se non le trovano prevengono potenziali (anzi, sicuri) catastrofici errori dicendo di non poter aprire il file. Che poi VLC sia zelante e Windows media player invece un piagnucolone sono dettagli…
Dunque dicevo, ciò che troviamo sulla rom deve essere interpretato come il tipo di dati giusto per produrre un output coerente per l’utente. Altrimenti si verifica la stessa cosa di missingno, e mi pare di ricordare che anche a emme sia capitata: che il gioco interpreti certe cose come altre. Secondo pokemon rosso laggiù ci doveva essere il verso di un pokemon, mentre invece c’erano dati di chissà cosa… ecco da dove nasce l’inquietante verso di ? (“female”, nel caso in cui il carattere ALT+12 non venisse letto dal forum). Ed ecco perché sembra non finire mai: interpretando tali dati come suono, i byte che indicano la fine del suono non vengono raggiunti in tempi ragionevoli. Stesso discorso dicasi per la lunga lista di evoluzioni di certi pokemon glitch: non si trovava una sequenza di byte terminatrice. A noi invece il massimo che possa capitare è vedere qualche carattere giapponese al posto di un messaggio, perché magari sbagliamo a mettere l’offset, confondendolo con il puntatore; questo perché la nostra rom è dannatamente più stabile.
Come modificare tali dati binari allora? Dobbiamo innanzitutto scoprire cosa rappresentano. Io lo so già perché riciclo gli esempi per la non sbatta
Dobbiamo copiare i byte in un nuovo file per poterli analizzare meglio.
In realtà mi sono accorto solo ora che il dato binario è word-aligned (allineato di ogni 4 byte), dunque non serve ciò che sta sotto. Che sbadato :|
Procedura per XVI:
- Posizionatevi sul punto da copiare
- Edit>block n chars
- 420d
- Edit>clipboard>copy
- Nuovo file clickando sull’iconcina del foglio
- Edit>clipboard>paste
[ ![[Immagine: attachment.php?aid=237]](http://pokehack.altervista.org/attachment.php?aid=237) ]
Sicuramente ve lo aspettavate, conoscendomi :D chiedo nuovamente scusa a fiammy per aver tralasciato dall’immagine il suo posticino di meditazione quotidiana :D
Bene, ora che sappiamo cosa è analizziamo il formato: sembra che ogni valore del byte corrisponda a una città (SHISH, A GINIUS!). è importante però notare una cosa: il valore 58h indica il vuoto. Anzi, qualunque valore al di sopra di 58h indica vuoto.
Il vostro compito è di modificare (tramite hex editor, ovviamente) la worldmap, reinserirla nella rom e farmi vedere il risultato.
Perché l’abbiamo estratta? Perché è più semplice da riconoscere: come avete potuto notare, nella rom è “sfasata”, non si capisce bene cosa sia. E poi potete vedere subito se per sbaglio aggiungete dei byte. Controllate sempre di essere in modalità OVERWRITE! Non credo di dover spiegare a gente come voi perché non bisogna aggiungere byte alla rom, vero? Ok, ve lo dico con parole povere: inserendo bytes spostate altra roba, che dunque non è più al suo posto, e non viene letta correttamente. Finchè si tratta di dati si può soprassedere (immagini, testi e suoni glitchati), ma se sono istruzioni, la cosa si fa grave...
Per compito i 4 angoli della tabella devono contenere una città. Questo è un compito per farvi imparare a contare (? Asd). Si, perché avrete notato che i dati sono tutti immagazzinati in fila indiana, non ci sono righe o colonne. La presenza di righe e colonne è dedotta dal software, mediante un semplice procedimento.
- So le coordinate X e Y del dato della tabelle che devo leggere.
- Moltiplico la Y per il numero di elementi di una riga
- Sommo X al precedente risultato
- Sommo l’offset del primo elemento della tabella al precedente risultato.
Come funzionano questi passaggi? Facciamo un esempio passo-passo.
Supponiamo di avere all’inizio di un file una talebba di 9 elementi, così:
A B C
D E F
G H I
Ma ovviamente nella memoria essa è contenuta linearmente: [[(A), (B), (.C)],[(D), (E), (F)],[(G), (H), (I)]] . Come facciamo ad accedere ad un elemento? Dobbiamo indicizzarla.
Mettiamo di voler accedere alla posizione centrale, di indice 1,1 (si parte a contare da 0).
- Moltiplico y*la larghezza: 1*3=3
- Sommo la x: 3+1=4
- Sommo l’offset di inizio della tabella: 4+0=4
Dunque prendiamo il valore alla posizione 4: A, B, C, D, E.
Tutto questo casino per cosa? Per sapere cosa state modificando. Se siete sulla ROM vi perderete in fretta, per cui bisogna sempre contare prima di scrivere qualcosa.
Ma tanto già so che voi avrete estratto la worldmap e ridimensionato la finestra del programma per avere esattamente 28 colonne, vero? Sempre che il vostro hex editor permetta ciò. A questo punto il compito diventa una bazzecola.
Chi lavora su fire red può fare il compito su fire red, per questa volta. L’offset è 3F2500h.
Ora proviamo a fare una cosa più complicata. Vi giuro che è l’ultima per oggi. Mi serve perché contiene una cosa che da grattacapi ad alcuni utenti, ma immagino che per voi non sarà un problema.
Spostiamo la worldmap. Cosa? Eh, dai, su, non ho mica detto di spostare una regione intera, è solo una cartina! Mica siamo dei titani, solo dei geografi! :D
Ecco il procedimento. Vorrei lo faceste per compito.
Per poter proseguire, dovete aver fatto il mini esercizio sui puntatori.
Soluzione:
- 506E3E08
- 28B30F08
- 0000E008
Prendete il primo. Aprite la rom e cercate una stringa esadecimale. Scrivete il puntatore. Se tutto è corretto dovreste averlo trovato una sola volta (se di più o avete usato rosso fuoco e allora non so, oppure c’è qualcosa di sbagliato, nel caso chiedete pure). Si trova a FB328h.
Sostituitelo. Con cosa? Ma con quello che volete voi. Ad esempio provate un offset a caso. Scrivete byte a caso. Aprite la mappa città e vedete che succede. Il gioco interpreta come mappa città dati che mappa città non sono. complimenti, avete buggato la rom! Ora invece torniamo indietro. Mettete il puntatore di questo valore: 720000h. se la rom è vergine, dovrebbe esserci spazio laggiù. Il puntatore è: 00-00-72-08. Ora, come prima, copiate la vostra wolrdmap in tale punto. Modificate valori della worldmap a caso per avere la garanzia che il gioco non prenda dati da quella originale. Se tutto va bene, cancellate quella originale, scrivendo 420d volte 00h o FFh.
La prossima volta, se volete, facciamo i testi, oppure se siete stufi di ‘sta roba passiamo in fretta al WBTO!
Bye!
avete sottoscritto la discussione? così non dobbiamo tutte le volte taggarci (voi non taggatemi comunque perchè essendo l'autore vedo subito se qualcuno ha scritto)
In questa lezione completiamo l'argomento hex editor e lo applichiamo alla struttura del GBA.
Non fate caso a segni strani, come detto è la prima stesura, non è perfetta.
---
#PARTE 1
LEZIONE 1.2
Se ricordate, l'altra volta ho detto che per visualizzare i caratteri sono utilizzati gli standard di comunicazione, in cui ad ogni byte corrisponde un carattere ben preciso.
Ovviamente in GF hanno avuto la brillante idea (si fa per dire...) di alterare l'ordine naturale delle cose sostituendo tutti i caratteri con dei nuovi. Il funzionamento è il medesimo, ma i giochi adottano un set di caratteri diverso, come si suol dire. Questi possono essere trovati sull'enciclopedia [ http://bulbapedia.bulbagarden.net/wiki/C...ration_III] dove sono descritti in maniera molto dettagliata. Noterete che ci sono alcuni valori strani: sono le sequenze di escape, ovvero i caratteri di controllo. Questi sono speciali caratteri, presenti in ogni sistema operativo, che hanno particolari compiti. La procedura che si occupa della scrittura del testo riconosce il carattere speciale e si comporta di conseguenza. Ora mentre sto scrivendo questo testo non ho sotto mano il documento, ma ogni singolo byte è ampiamente documentato. Ad esempio con essi potete cambiare colore, oppure fare una pausa, o usare il grassetto. Sono tecniche utili per la regia ;) Anche nel computer normale ci sono le sequenze di escspe: a capo è un esempio.
Tutte le volte che usate una sequenza mnemonica in xse, come ad esempio "LASTRESULT" o "RS_cyan" (non son sicuro che la seconda sia corretta così com'è, ma avete capito a cosa mi riferisco) lui sostituisce nella ROM una particolare sequenza di caratteri al posto della parola chiave. Nel nostro caso al posto del colore metterà il byte che indica il cambio di colore, e poi il byte del colore [# non avendo sotto mano la pagina di bulba è il massimo che posso dirvi a riguardo]. E se volete inserire in XSE altre sequenze di escape? C'è il comando "\h", mi pare, ma non sono sicuro. Comunque dovete inserire un "\h" (o quello che è) per ogni singolo byte che compone la nostra sequenza di controllo. Noioso, vero? Ecco perchè a volte preferisco usare l'hex editor. Ovviamente non dovrete usarlo sempre, anzi riconosco che usare XSE è più comodo, ma sapere come fare è sempre meglio; forse vi capiterà qualche caso in cui vi servià.
Per svolgere correttamente questa attività dovrete avere una tabella dei caratteri, che essenzialmente è un file che dice all'hex editor quali sono le corrispondenze tra i caratteri "normali" (ASCII) e "quelli pokemon" . Io vi passo quella che si trova insieme a thingy 32 (un hex editor sviluppato principalmente per le traduzioni) e quella (incompleta) che ho fatto io per xvi in un momento di noia [attachment=279] [attachment=280]. Da rinominare in "TBL" e "XCT".
Come si usano? Ogni programma ha le sue beghe, dunque bisognerà stare attenti. Comincio col dire che su HxD neanche c'è questa possibilità, oppure sono stordito io che non l'ho vista. Rimangono windhex e thingy che si comportano in modo piuttosto simile, mentre xvi, come vedrete tra poco, fa una "cassanata".
Dunque è giunto il momento di aprire rom e tabella. Solitamente i comandi stanno nel menu file. Windhex legge la tabella di thingy. Una volta completato dovreste vedere che i caratteri a destra sono cambiati. Il programma sta sostituendo i byte della ROM con i caratteri indicati da noi. Ora, finalmente, potete provare a sbizzarrirvi con la ricerca di testo, in quanto ci sono un mucchio di parole di senso compiuto! E se provate a scrivere con le normali lettere della tastiera, queste vengono automaticamente tradotte nel formato corretto, mentre a noi appariranno come lettere normali!
[attachment=308]
Bisogna ricordare, però, che il programma è stupido, e non sa quali byte sono effettivamente testo e quali no, perciò li sostituisce tutti. Per superare questo inconveniente basta cambiare la tabella in uso, tornando ad ASCII, o quello che è un uso dal vostro programma. Di solito tale comando sta o in file o in modifica. (in windhex File>Swap table file)
Ora arriviamo al problema XVI: purtroppo non riesce ad astrarre i caratteri, perciò la soluzione che adotta è sostituirli fisicamente nella vista di sinistra! [emoji33] Se salvate vi ritroverete una ROM sicuramente corrotta! NON SALVATE LA ROM DOPO AVER APPLICATO LA SOSTITUZIONE CON XVI!
Ora impareremo a cambiare il testo direttamente con l'hex editor. Come funziona questo metodo? Se sapete trovare e modificare i puntatori lo applicate alla svelta.
- Individuate il testo da modificare con la ricerca di stringa, di testo stavolta
- ricavatene il puntatore
- cercate il puntatore dall'inizio della ROM. Meglio se pochi (1) risultati, perchè significa che la risorsa è usata una sola volta. Nel caso del testo dovrebbe essere così. Segnate l'offset.
- andate in spazio libero (createne il puntatore) e scrivete! Bisogna però stare attenti alla larghezza, in quanto finora tutti gli hex editor adottano larghezza fissa delle colonne. In Certi casi torna utile, ma non in questo. Indicativamente, in minuscolo potete scrivere 30 lettere.
- andate al primo offset segnato. Contiene il puntatore al vostro testo. Dovrete sostituirlo con il puntatore al nuovo testo.
Se conoscete un hex editor migliore di quelli elencati in questo corso (windhex, XVI, HxD) per favore segnalatelo.
Come potete notare non ci siamo spostati neanche per un attimo dal programma corrente, quindi, se il testo è favorevole da scrivere, questo consente di risparmiare un po' di tempo rispetto ad altri metodi [# so che emme97 mi odierà per questo [emoji8] ].
Come vedremo nelle ultime lezioni, disporre dei testi di una ROM è essenziale per iniziare piuttosto agevolmente alcune particolari ricerche di ASM.
Come compito modificate un testo come volete. (tanto poi fatto uno fatti tutti)
---
#PARTE 2
LEZIONE 2
I moderni calcolatori sono costruiti secondo l'architettura di Von Neumann (in opposizione a quella di Turing che non è da meno, ma con i moderni dispositivi è inefficiente e poco gestibile, anche se ha grande rilevanza teorica).
Questo significa che Il cuore del dispositivo è la memoria centrale (nome rigoroso per RAM, ovvero la memoria temporanea in cui stanno i dati che devono essere elaborati). Tutte le componenti del dispositivo comunicano con la memoria centrale e con il processore. https://www.google.it/search?q=architett...on+neumann&biw=1366&bih=661&source=lnms&tbm=isch&sa=X&sqi=2&ved=0CAYQ_AUoAWoVChMIn_aVvp6pxwIVLjnbCh1X9Ay9
Anche il GBA funziona secondo questo schema. Apriamo il VBA normale e andiamo nel menu a tendona "tools" e apriamo tutto da "io viewer" a "tile viewer". Cosa è tutto questo macello? Sono le varie parti del GBA, servono per "dissezionare" il gioco e ricavarne le modifiche. Ora possiamo chiuderle tutte tranne una, il memory viewer. Essenzialmente tutte quelle finestre possono essere ricondotte al memory viewer, in quanto il contenuto di ciascuna è solo una forma comprensibile di ciò che sta nella memoria. Con il memory viewer avete accesso a tutte le macro aree della memoria del GBA (spiegate tra poco)
Come vedrete, ci sono dei buchi. Questo non significa che la memoria del GBA abbia dei buchi (è piena di tarli!) oppure sia davvero grande 09000000h, che è più di 100 MB! Semplicemente lei fisicamente sarà come sarà, ma viene "mappata" logicamente secondo tali indirizzi. Questo procedimento è un'astrazione dall'ambiente fisico, e grazie ad essa è possibile manipolare indipendentemente qualsiasi settore.
Ed ecco spiegato il motivo del mettere lo 08 al puntatore. Ogni puntatore visto fino ad ora si riferiva alla ROM, perciò si metteva per forza il byte 08. Ora sostituite il passo "metto 08 al puntatore" con "metto il numero della memoria che voglio usare".
Tutto ciò trova un'applicazione pratica: il WBTO.
Questo comando degli script permette di scrivere un byte in una locazione di memoria di quelle elencate prima.
Non si può veramente "insegnare il WBTO", a parte perchè l'ho appena fatto nel periodo precedente (si, la frase precedente è "insegnare il WBTO"), ma soprattutto perchè questo comando presuppone che ci sia uno studio dietro la sua applicazione, in modo da ottenere l'effetto ricercato. Ok, posso dirvi cosa dovrete scrivere nella memoria per ottenere qualcosa, ma allora l'insegnamento si riduce a una semplice elencazione di valori, cosa che potete trovare benissimo per il WEB (e quelli di forumcommunity ne sanno qualcosa, vero?). Qui vi spiego COME funzionano gli offset di memoria, in modo che possiate sviluppare il vostro atteggiamento critico verso la realtà (mi sembra filosofia :asd: ) che vi porterà a fare le vostre nuove scoperte. Se poi unite questo al potente strumento che è la documentazione degli offset scoperti (cui vi consiglio di partecipare all'ampliamento) allora sarete un'arma dal grande potenziale. Tutta questa manfrina poetica per dire cosa? Per introdurre la
(BREVE) SPIEGAZIONE SU COME FUNZIONA LA MEMORIA
- 08 : La nostra ROM.
- 09 : Per accedere alla ROM dai 16 MB a 32 (il massimo) si usa questo prefisso. l'offset è quello che sarebbe con l'origine relativa in 08FFFFFF (quello che avevamo detto la scorsa volta sugli scostamenti torna molto utile).
- 07 : è una memoria piccolissima che contiene le informazioni sugli oggetti. un oggetto può essere qualunque cosa, da un people di advance map a un elemento dell'interfaccia grafica. Trovate maggiori informazioni nelle guide di andera/feanor.
- 00 : BIOS di sistema. è una cosa che tutti i computer hanno, e contiene "l'essenza della vita", ovvero, più seriamente, tutto ciò che serve a far funzionare il computer a livello basilare (del tipo accendersi, rispondere ai tasti, ecc). Non a caso l'acronimo sta per Basic Input/Output System. Noi potremo trarre vantaggio dal BIOS con l'ASM, in quanto potremo usare alcune funzioni non proprio elementari contenute in esso: ad esempio la decompressione dei dati, oppure funzioni matematiche come il seno. Già, non sembrano molto essenziali per far funzionare una macchina, ma probabilmente sono state inserite perchè di frequente uso nei giochi.
- 02 : WRAM, La memoria temporanea che hanno tutti i computer. Qua abbiamo la bellezza di 256 KB di RAM.
- 03 : Con questo codice ci si riferisce all'IRAM, ovvero una memoria interna (come suggerisce l'iniziale) al processore. è molto più veloce di quella normale, ma è grande solo 32 KB. Meglio non utilizzarla per i nostri scopi.
- 05 : Contiene le palette da utilizzare. contiene 16 palette per un totale di 256 colori. Non è modificabile, perchè viene costantemente aggiornata prendendo i dati dall'indirizzo 0202EEC8
- 04 : Questa locazione si chiama registri di Input/Output. è un minuscolo settore in cui ci stanno i valori interni del GBA per utilizzare le periferiche.
- 06 : VRAM. Questa è la memoria Video da 96 KB. Il suo contenuto è grezzo, per visionarla in forma comprensibile si usano il tile viewer e il map viewer. Le map essenialmente sono ciò che forma l'immagine da visualizzare: Sono dei riferimenti ai tiles. Ci possono essere fino a 4 strati, chiamati BG, in un gioco GBA. In pokemon il BG0 è utilizzato principalmente per l'interfaccia. Gli altri variano a seconda del contesto, ma durante l'overworld sono usati tutti e 3 per le varie altezze dei blocchi. Ad esempio il tetto delle case è nel BG1.
L'elemento minimo che costituisce la tilemap (quella cosa che compone il BG e si edita con cyclone e NTME) è formato da due bytes. Il primo indica il numero del tile da prendere, mentre il secondo bytes viene diviso in 2. I primi 4 bit indicano la palette scelta tra le 16 disponibili. I secondi 4 indicano la "base" dei tiles, ovvero la "pagina" di 256 tiles da scegliere; se ci pensate un attimo queste informazioni sembrano messe in ordine innaturale rispetto a come ci verrebbe da pensare; infatti vanno invertiti, sempre per la storia del little endian che se bazzicate in R&D avrete sicuramente incontrato (cercate "ordine dei byte" su Wikipedia), per cui effettivamente il GBA legge pagina, palette e numero del tile, ovvero qualcosa di più comodo per noi (dunque per chi proggettava il GBA). So che tutto questo non è un concetto molto semplice, magari ne riparleremo più avanti, con l'asm.
Ricordate comunque che per ogni esigenza di consultazione tecnica esistono i siti internet:
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm (facile)
http://problemkaputt.de/gbatek.htm (difficile)
Ora che sapete un po' meglio come funziona la mappatura della memoria, vi mancano gli offset. In questo forum io mi sto battendo per avere una raccolta ordinata di tutti gli offset, ma l'idea sembra non riscuotere successo. Comunque se volete sono qui
http://pokehack.altervista.org/showthread.php?tid=1754
http://pokehack.altervista.org/showthread.php?tid=2012&highlight=buffer
poi boh...
Altrimenti potete sempre bazzicare in altri fori e gozzovigliare un po' (e magari venire a riportarmi cosa scoprite). Io di sicuro prima o poi farò passare tutte le discussioni della macroarea apprendimento e ne coglierò ogni offset. Noiosissimo, lo so.
ecco una dettagliata spiegazione di ogni singolo freakin' registro:
Ecco ora qualche esempio di WBTO:
difficoltà facile:
hmm, non mi garba molto il colore dell'erba del percorso 101. Aspetta che chiamo il giardiniere...
Codice: #org @start
writebytetooffset 0x19 0x0202ef22
writebytetooffset 0x29 0x0202ef23
end
et voilà, ora è diventata di un bel rosso sangue!
Spiegazione: sostituisco il qattordicesimo colore della terza palette.
difficoltà media:
Recentemente sono riuscito ad implementare una feature che per l'utente non ha rilevanza, ma può tornare utile a noi sviluppattori. Si tratta di dirottare i dati delle tabelle nella RAM. Come mai fare una cosa che "a orecchio" sembra complicata? Perchè può capitare di arrivare a 255 elementi di una tabella indicizzata con un byte e dunque non poterne più inserire nessuno, a meno di avventurarsi nell'asm per cambiare il modo con cui vengono trovati gli elementi. Ma basta con le chiacchiere e passiamo ai fatti: Sono riuscito a dirottare in RAM i multichoice. Come ben sapete [#dragontype lo saprà al meglio] i multichoice sono circa 80, ma possono essere al massimo 255, perchè in XSE viene detto chiaramente che l'ID occupa un byte. E se li finiamo? Semplicemente diciamo al GBA di andare a trovare i testi in RAM, così se ne possono mettere quanti si vuole! Dovrete sacrificarne alcuni, ma ne avrete infiniti! Quanti ne servono? dipende da voi, uno per ogni numero di scelte. Significa uno per una scelta, uno per due scelte, uno per tre scelte, e così via, fino al numero che volete. Il massimo che si può fare senza corrompere il gioco è 9. gli ultimi 9 multichoice si riferiranno agli ultimi 9 puntatori dei boxset (per approfondimenti vi rimando al topic ufficiale del multichoice), i quali punteranno alla RAM. Per poter utilizzare la tecnica negli script occorrerà fare un wbto nell'area designata, con i caratteri che abbiamo visto la volta scorsa, e successivamente chiamare il multichoice.
Esempio di script funzionante (ovviamente servirebbe anche la modifica del MC da fare sulle vostre ROM):
Codice: #org @start
writebytetooffset 0xBB 0x2000000
writebytetooffset 0xFF 0x2000001
writebytetooffset 0xBC 0x2000002
writebytetooffset 0xBD 0x2000003
writebytetooffset 0xFF 0x2000004
writebytetooffset 0xBE 0x2000005
writebytetooffset 0xBF 0x2000006
writebytetooffset 0xFF 0x2000007
msgbox @string1 MSG_FACE //"PROF. BIRCH spends days in his LAB..."
multichoice 0x0 0x0 0x0 0x0
ho dovuto metere un testo se no non rimaneva fermo il riquadro. L'effetto è [attachment=309], non contate il fatto che ci sono solo 2 testi invece di 3, era una prova.
Spiegazione: A parte la modifica al multichoice che non è mostrata, ho semplicemente scritto del testo nella RAM, che viene letto correttamente dal programma multichoice.
compiti? Boh, non saprei, ci possono essere mille utilizzi differenti, a seconda della situazione! noi in un contesto come questo non abbiamo nemmeno delle occasioni, degli stimoli ad usarlo, in quanto operiamo (si presume) su ROM pulite, perciò non abbiamo le necessità che scaturiscono da un progetto reale. inoltre qua siamo liberi di fare ciò che ci sentiamo, senza vincoli (non come in altre lezioni). Dunque facciamo così: a scelta tra
1) o fate qualcosa di vostro con il WBTO (tipo cambio palette, operazione sui dati, ecc),
oppure
2)mi spiegate il funzionamento di uno dei "codici da inserire nelle ak rum" (sarebbero i WBTO) che trovate su forumcommunity internet.
Così avete la scelta tra un compito più pratico e uno più teorico.
Ovviamente qualcosa di facile per il momento.
Consigli: per fare il primo, pensate al vostro obiettivo, poi scovatene l'offset. come funziona l'obiettivo? Se voglio ottenere questo, cosa devo mettere? Per fare il secondo compito cercate l'offset indicato dal comando, e andate a vedere in quale memoria (e in quale settore in alcuni casi) risiede. pensate a cosa fa tale locazione e come si comporta con il nuovo byte.
Preparatevi, la prossima lezione sarà corposa, è la prima dell'ASM, e voglio iniziare le cose per bene! Meglio avere chiari fin da sunito i punti salienti/prerequisiti, per poi non rischiare di perdere tempo in seguito.
Se avete dubbi come sempre non esitate a chiedere, ciao
---
mi scuso se il testo possa apparire "brutto" (mancanza di formattazione, ecc..), in quanto è la mia prima stesura, per questo, solo a voi, offro un "periodo di supporto gratuito" della durata di un mese dalla data di pubblicazione della lezione, in cui potrete chiedermi, via messaggio, tutto quello che vorrete riguardo alla lezione.
ESERCIZI 2
spiegazione WBTO textbox trasparente:
con i byte da 4000040 a 4000046 definisco le coordinate delle finestre.
ecco la spiegazione dei byte. I registri sono complicati da manovrare perchè è tutto a livello di singoli bit.
Citazione:Addresses: 0x4000040 - 0x400004A - Windowing Registers
Address: 0x4000040 - REG_WIN0H (Window 0 X Coordinates) (Write Only)
Address: 0x4000042 - REG_WIN1H (Window 1 X Coordinates)(Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0
L L L L L L L L R R R R R R R R
0-7 ® = X coordinate for the rightmost side of the window
8-F (L) = X coordinate for the leftmost side of the window
Address: 0x4000044 - REG_WIN0V (Window 0 Y Coordinates) (Write Only)
Address: 0x4000046 - REG_WIN1V (Window 1 Y Coordinates)(Write Only)
F E D C B A 9 8 7 6 5 4 3 2 1 0
T T T T T T T T B B B B B B B B
0-7 (B) = Y coordinate for the bottom of the window
8-F (T) = Y coordinate for the top of the window
poi però modificando la dimensione delle finestre si creano dei problemi. Infatti quegli sveglioni GF hanno messo TUTTO dentro la finestra 0, che io invece uso per il messaggio. per questo ciò che sta fuori non è visibile. Dobbiamo quindi abilitare la visualizzazione della finestra 1 con questi bit:
Citazione:Address: 0x4000048 - REG_WININ (Inside Window Settings)
F E D C B A 9 8 7 6 5 4 3 2 1 0
X X T S R Q P O X X L K J I H G
0 (G) = BG0 in win0
1 (H) = BG1 in win0
2 (I) = BG2 in win0
3 (J) = BG3 in win0
4 (K) = Sprites in win0
5 (L) = Blends in win0
8 (O) = BG0 in win1
9 (P) = BG1 in win1
A (Q) = BG2 in win1
B ® = BG3 in win1
C (S) = Sprites in win1
D (T) = Blends in win1
Address: 0x400004A - REG_WINOUT (Outside Window and Sprite Window)
F E D C B A 9 8 7 6 5 4 3 2 1 0
X X T S R Q P O X X L K J I H G
0 (G) = BG0 outside
1 (H) = BG1 outside
2 (I) = BG2 outside
3 (J) = BG3 outside
4 (K) = Sprites outside
5 (L) = Blends outside
8 (O) = BG0 in sprite win
9 (P) = BG1 in sprite win
A (Q) = BG2 in sprite win
B ® = BG3 in sprite win
C (S) = Sprites in sprite win
D (T) = Blends in sprite win
"giocando" con questi bit permette di far scomparire i livelli del GBA, e a volte crea un effetto anche grottesco (del tipo le case che spariscono)
ora dobbiamo applicare il blending.
Citazione:Address: 0x4000050 - REG_BLDMOD
F E D C B A 9 8 7 6 5 4 3 2 1 0
X X T S R Q P O M M L K J I H G
0 (G) = Blend BG0 (source)
1 (H) = Blend Bg1 (source)
2 (I) = Blend BG2 (source)
3 (J) = Blend BG3 (source)
4 (K) = Blend sprites (source)
5 (L) = Blend backdrop (source)
6-7 (M) = Blend Mode
There are four different modes:
00: All effects off
01: alpha blend
10: lighten (fade to white)
11: darken (fade to black)
8 (O) = Blend BG0 (target)
9 (P) = Blend BG1 (target)
A (Q) = Blend BG2 (target)
B ® = Blend BG3 (target)
C (S) = Blend sprites (target)
D (T) = Blend backdrop (target)
ho aggiunto i link a gba tek e a un sito più facile da comprendere per chi è alle prime armi (io l'ho letto settimana scorsa e da lì mi sono scaturite varie idee, tra cui questa)
Dragon riesci a fare qualcosa o hai dei problemi? Ricorda che Sono qua per (cercare di) risolverli! ;)
Comunque non ho ancora stabilito delle precise politiche di gestione dell'aula, diciamo che questa volta vi è andata bene. Vorrà dire che se non riesci dovrai postare doppi compiti la prossima volta.
Inizio a scrivere la prossima lezione, ma ci metterò un po' perché non èche sia proprio piccola.
La prossima lezione sarà una introduzione alla programmazione. Non in uno specifico linguaggio, ma più in generale. Questo perché asm è essenzialmente programmazione , e, citando il collega fuji97, se non la sai siete nei guai.
Se però sapete già programmare possiamo saltare quella parte, così i miei Manzoniani 25 lettori (quasi al quadrato XD) hanno qualcosa di interessante XD
Ovviamente dovete deciderlo voi se vi serve, non il pubblico.
A dragon lo consiglio, se non altro perché è giovane e potrebbe non aver fatto tale argomento a scuola, ed è importante per la buona riuscita del corso. Puoi anche sapere tutti i comandi a memoria ma se non li sai applicare non fai niente :v
Ho deciso di pubblicare comunque qualcosa sennò "morite di fame"
LEZIONE 3.1
oggi parliamo di:
INTRODUZIONE ALLA PROGRAMMAZIONE
Siccome questo è un argomento troppo importante per essere saltato, vi tocca. Senza di esso potreste avere varie difficoltà in seguito, perciò ho deciso di affrontarlo una volta per tutte. Inoltre è un requisito nel caso in cui voleste imparare un linguaggio di programmazione ad oggetti (come il Ruby, usato in rpg).
___
Ogni giorno ci troviamo a dover risolvere dei problemi. Ad esempio scegliere cosa fare da mangiare o montare un mobile sono alcuni dei problemi quotidiani. La maggior parte di essi sono risolti istintivamente da noi; non necessariamente nel senso che usiamo l'istinto, ma che non ci riflettiamo più di tanto perché viene automatico. mentre se il problema è più difficile (montare il mobile) dobbiamo seguire le istruzioni che ci vengono fornite. anche i computer vengono utilizzati per risolvere problemi. Una volta erano prevalentemente di tipo matematico (i primi computer erano solo enormi calcolatori), mentre oggi si utilizzano per qualsiasi scopo: esempio previsioni del tempo, controllo di una centrale atomica, realizzazione di grafica. I computer però non ragionano da soli, serve qualcuno che li "istruisca" per fare tutte queste cose utili, ovvero il programmatore. Ebbene, c'è una similitudine tra il computer e noi che montiamo un mobile: seguiamo delle istruzioni scritte da altri. Questo insieme di istruzioni viene chiamato algoritmo. Si potrebbe scendere nei dettagli sulle proprietà degli algoritmi, ma dovrei andare a riprendere gli appunti di tanti anni fa(magari posso farlo per le prossime lezioni). Perciò per il momento ci concentriamo sul capire bene come funzionano questi algoritmi. Ne incontriamo a bizzeffe ogni giorno, il mondo ne è pieno. Sostanzialmente, ad ogni problema risolvibile è possibile associare un algoritmo risolutivo. Un algoritmo è una sequenza di passi (istruzioni) da eseguire per risolvere un problema.
Ad esempio per preparare la pasta ci sono dei passi (accendi il Gas, metti l'acqua, ecc) che il cuoco esegue. Anche se può sembrare naturale, in realtà una qualsiasi azione è il frutto di ben precise "istruzioni", eseguite in sequenza dal nostro cervello.
Un altro esempio di algoritmo lo avevamo visto le volte scorse, quando vi avevo detto come ricavare un puntatore o indicizzare una tabella.
la programmazione è l'"arte" di istruire i computer. per farlo serve elaborare un algoritmo che risolve il problema. in questo corso non risolveremo problemi di tipo strano, come la costruzione di un mobile o la preparazione di una pietanza, ma agli inizi saranno prevalentemente di tipo matematico per prendere confidenza, e poi sposteremo il campo verso la piattaforma GBA.
Un esempio di problema potrebbe essere: determinare il massimo tra una serie di numeri.
adesso compirò quella "brutta cosa" che è copiare wikipedia (perchè non voglio scavare nei quaderni lol) per informarvi sulle proprietà degli algoritmi per aiutarvi a capire il tipo di procedimento necessario;
- i passi costituenti devono essere "elementari", ovvero non ulteriormente scomponibili (atomicità)
- i passi costituenti devono essere interpretabili in modo diretto e univoco dall'esecutore, sia esso umano o artificiale (non ambiguità)
- l'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di dati in ingresso (finitezza)
- l'esecuzione deve avere termine dopo un tempo finito (terminazione)
- l'esecuzione deve portare a un risultato univoco (effettività).
In generale non esiste una sola soluzione ad un dato
problema; le soluzioni potrebbero essere numerose. La programmazione consiste proprio nel trovare la strada più efficiente che conduce alla soluzione del problema in oggetto. Ecco perchè programmatori diversi possono dare diverse soluzioni (magari corrispondenti a diverse visioni del problema), anche se entrambe corrette.
"Ho capito, ma come faccio a risolvere un problema?" bisogna precisare che non esiste una "ricetta" universalmente valida, ma ci sono dei paletti che definiscono in generale un percorso da seguire per semplificare l'approccio.
Per risolvere un problema innanzitutto bisogna "prenderlo" e analizzarlo. La prima cosa da fare è stabilire cosa richiede la soluzione (output) e cosa dobbiamo conoscere in principio per poter risolverlo (input). Prendo l'esempio del massimo: cosa devo fornire al programma e cosa deve "buttar fuori"? Devo inserire alcuni numeri, e devo ricevere ancora un numero (non è detto che si utilizzino sempre solo i numeri per operare, si può anche operare sul testo, sulle immagini, ecc, così come il programma potrebbe dare quelle cose come soluzione)
Poi esistono due diversi approcci, entrambi validi, per analizzare il problema e iniziare a determinare una soluzione. il secondo è sconsigliato ai Principianti.
Top-down e Bottom-up; Come suggerisce il nome, i due sono opposti.
Nel modello top-down si formula inizialmente una visione generale del sistema, ovvero se ne descrive la finalità principale senza scendere nel dettaglio delle sue parti. Ogni parte del sistema è successivamente rifinita aggiungendo maggiori dettagli della progettazione. Ogni nuova parte così ottenuta può quindi essere nuovamente rifinita, specificando ulteriori dettagli, finché la specifica completa è sufficientemente dettagliata da validare il modello. Il modello top-down è spesso progettato con l'ausilio di "scatole nere" che semplificano il riempimento ma non consentono di capirne il meccanismo elementare.
In contrasto con il modello top-down c'è la progettazione bottom-up, nella quale parti individuali del sistema sono specificate in dettaglio, e poi connesse tra loro in modo da formare componenti più grandi, a loro volta interconnesse fino a realizzare un sistema completo. Le strategie basate sul flusso informativo bottom-up sembrano potenzialmente necessarie e sufficienti, poiché basate sulla conoscenza di tutte le variabili in grado di condizionare gli elementi del sistema.
Ricapitolando le differenze ma senza scendere troppo nei dettagli tecnici, abbiamo che
La programmazione top-down è uno stile di programmazione in cui la progettazione inizia specificando parti complesse e suddividendole successivamente in parti più piccole (divide et impera). Eventualmente, i componenti sono specificati quanto basta per la codifica ed il programma viene anche scritto.
Il bottom up prende corpo dal punto di partenza (bottom) ovvero dalla situazione iniziale; considera l'obiettivo finale, induce a costruire un percorso sequenziale organizzato in passaggi successivi in cui l'ancoraggio tra traguardi intermedi e obiettivo finale è generalmente ricercato in modo intuitivo (euristico).
come compito potreste descrivermi nel linguaggio a voi più naturale (es: italiano scritto) la risoluzione di un paio di problemi. (non copiatevi)
nella lezione successiva vedremo di formalizzare le vostre soluzioni con opportuni metodi e iniziare la programmazione.
[b]facile: dati 3 numeri, determinare il maggiore (SUGGERIMENTO: chiamate i numeri in qualche modo, come ad esempio A,B,C. vi aiuterà nello stabilire le condizioni delle "sentenze")
facile: calcola l'area di un n-agono (figura geometrica regolare con n lati) (n a scelta dell'utente) (SUGGERIMENTO: vai a rivedere le formule)
facile/medio (dipende dal livello di formalismo del linguaggio usato): fornire i primi 40 multipli di 13 (SUGGERIMENTO: dovrete contare le volte...)
medio: calcolare i coefficienti reali dell'equazione ax^2+bx+c=k (SUGGERIMENTO: torna comodo un linguaggio matematico)
ops, mi rendo conto che dragontype potrebbe non aver ancora affrontato questo argomento a scuola. se non l'hai fatto ti do un problema diverso, sii sincero.
ciao
vi taggo perchè immagino abbiate perso la speranza ahah
.
LEZIONE 3.2
(sarà unita alla precedente)
DIAGRAMMI DI FLUSSO
Per gli amici "schemi a blocchi", i diagrammi di flusso servono per rappresentare graficamente un algoritmo (sequenza di passi elementari con alcune proprietà già viste da seguire per risolvere un problema).
Di norma vengono introdotti parallelamente agli algoritmi, ad essi profondamente legati, in quanto sono la loro rappresentazione in un linguaggio formale
Esistono 2 grandi tipologie di diagrammi di flusso: non strutturati e strutturati. Noi non tratteremo i primi, in quanto non di interesse per fare programmazione. Tuttavia tra i due non ci sono grosse differenze tali da implicare grossi cambiamenti nello studio e negli esercizi, ma riveste grande importanza quando bisogna applicare il risultato su un calcolatore: semplicemente, quelli non strutturati non sono riproducibili su un computer! Inoltre abituano male alla programmazione, facendo uso di tecniche errate; Perciò vi farò un favore per la vostra crescita personale, e non ve li spiegherò nemmeno.
Cominciamo :)
ogni schema a blocchi è composto da blocchi connessi mediante frecce. l'esecutore segue il percorso indicato dalla freccia ed esegue le istruzioni riportate.
ogni schema inizia e si conclude con due blocchi speciali, chiamati I (inizio) e F (fine). di norma sono rotondi (la notazione uitlizzata è ininfluente, ma bisogna mettersi d'accordo a priori).
Questo che segue è un esempio di utilizzo dei due blocchi in uno schema stupido, inutile, che non fa niente. Ma una proprietà ce l'ha: essenzialmente è la base di ogni programma: deve avere esattamente un inizio e una o più fini. (ci sono dispute teoriche altolocate che non ci interessano sulle varie proprietà algoritmiche)
[attachment=382]
introduciamo un altro blocco: il blocco operativo. questo blocco è di forma rettangolare, e viene usato per impartire istruzioni all'esecutore. Un esempio di istruzioni può essere "accendi il gas", "metti il bullone X nel foro Y del pianale", ecc. Devono perciò essere interpretabili ed eseguibili dal lettore. Noi purtroppo però ci occuperemo soltanto di problemi matematici, che sono quelli che rendono meglio con gli schemi a blocchi. Un concetto importantissimo per questo blocco sono le variabili: per farla semplice, si tratta di una sorta di "contenitori" nella memoria del computer, che possiamo usare come vogliamo per conservare le informazioni (temporanee) che ci servono.
Ad esempio, se mi chiedono di contare fino a 100, inizio dicendo "1", "2", "3" .... ovvero sto usando un po' della mia memoria a breve termine per conservare l'informazione del numero cui sono arrivato a contare.
Ma ciancio alle bande, ecco un piccolo esempio di blocco di istruzioni quadrato.
[attachment=383]
come potete intuire, questi blocchi in serie sono le istruzioni per calcolare l'area di un trapezio! ^^ abbiamo assegnato a 3 variabili B, b e h i valori base maggiore, base minore e altezza, che poi abbiamo usato nel calcolo dell'area. notare che ho omesso il verso delle frecce, in quanto ovvio.
tutti quei quadrati in serie si dice che formano una struttura di sequenza.
la sequenza è un insieme di blocchi di tipo operativo.
[attachment=384]
qui vedete come un insieme di rettangoli possa essere schematizzato in un solo grande rettangolo, in quanto la loro natura è la medesima. ma attenzione, non significa che spariscano, semplicemente facciamo uno "zoom-out" di un livello di generalizzazione, e i dettagli implementativi si perdono. potremmo sostituire i puntini con un generico "Area_Trapezio", nome che rachiude in sè tutti e soli i comandi scritti a sinistra.
gli schemi a blocchi strutturati si compongono soltanto di strutture. ogni struttura è una generalizzazione di blocchi dello stesso tipo. ad esempio, poco sopra, abbiamo visto la sequenza. ne rimangono 2.
un altro blocco è il parallelogramma: dentro di esso si mettono gli input/output, ovvero le cose che l'utente scrive (immette nel calcolatore) o il computer gli dice.
è talmente banale che unirò l'esempio con quelli successivi.
il nuovo tipo di blocco è il rombo: esso permette di fare delle scelte. se durante la nostra soluzione del problema dobbiamo fare cose diverse in base alle circostanze, useremo il blocco rombo. al suo interno si mette una condizione[i] che dovrà essere [i]valutata. se è vera, si prenderà la strada del Vero, se è falsa si prenderà la strada del Falso.
esempietto:
[attachment=387]
Analizziamo questo nuovo schema, che ci propone molto spunti di riflessione.
Innanzitutto diciamo quale e il suo scopo generale. Serve per dimostrare l'uso dei blocchi di input /output: chiede una frase (la password), la riceve, la confronta e a seconda che sia Uguale o meno a quella desiderata fa cose diverse.
Vi invito a notare le " che circondano la frase. I computer sono esseri molto precisi, non gli piacciono le.cose pressappoco. Perciò dovete specificare esattamente ciò che deve essere scritto, e la maggior parte dei linguaggi usa proprio ". Poi vediamo questo accesso, ma cos'è? È anche lui una variabile, ma il suo cassetto (nella distesa di armadi che rappresenta la RAM) è piccolo, perciò non è adatto a contenere interi o reali (i tipi che abbiamo utilizzato nel trapezio), ma ha posto solo per un particolare tipo di valore, che può assumere soltanto due stati : vero o falso (come un interruttore, una bandierina del guardalinee, una flag nello scripting - actually è la flag che deriva da qui). Questo tipo di valore si chiama booleano, da George Boole, un matematico che ha fatto... Cose Che non ci interessano per il momento. Inoltre è possibile avere variabili che conservano i singoli caratteri (comunemente rappresentanti da un byte); o anche frasi intere, come quella del disegno: il tipo di quelle variabili si chiama Stringa. Una stringa è un insieme contiguo di caratteri terminata da un byte con valore particolare. Generalmente in informatica le stringhe sono null-terminated, ovvero finiscono per 0x00, mentre quei geniacci fella game freak, come saprete, hanno sovvertito l'ordine naturale delle cose, perciò le loro stringhe sono FF-terminated.
Successivamente c'è la parte più importante dell'esempio, ovvero la scelta. Ciò che sta dentro il rombo deve necessariamente poter essere valutato come vero o falso. E poi l'esecuzione continuerà nel ramo corrispondente. Non è necessario avere sempre entrambi i rami, il tutto dipende dalla necessità. Notare nuovamente le ", in quanto una stringa (frase) deve essere precisamente delimitata, altrimenti come possiamo confrontare una cosa non ben definita? (negazione di una proprietà degli algoritmi)
Altra cosa molto importante è il simbolo "==", non fatevi spaventare non è niente di oscuro. Semplicemente significa "Uguale". E allora perché non usiamo il classico "="? Perché quest'ultimo in realtà non significa "Uguale", anche se con l'abitudine si dice ormai così; significa "assegno alla variabile a sinistra il valore a destra". E siccome non possono esserci due operatori uguali (come si distinguerebbero?), è stato inventato quello. In realtà si potrebbe anche utilizzare "=", ma solo se prima ci si è messi d'accordo che soltanto dentro il rombo = significa uguaglianza e non assegnamento.
Finite le operazioni da eseguire durante la selezione (questo il nome formale dellla struttura di scelta), si ritorna allo stesso punto di prima, solo un passo dopo. Notate come le frecce convergano nello stesso punto, in linea con l'apertura del rombo, e da cui le frecce diventano una sola che Prosegue nel programma.
Eseguiamo ancora una volta l'operazione di zoom out, e vediamo gli elementi principali che costituiscono il programma.
[attachment=388]
Abbiamo una struttura sequenza seguita da una selezione, che ovviamente porta ad altre sotto sequenze.
Abbiamo visto due strutture che hanno il loro blocco, e un blocco che non ha una sua struttura personale. Quale combinazione manca? La terza struttura fondamentale che non ha il suo blocco!
L'ultima struttura infatti non introduce un nuovo blocco, ma fa uso di tutti i tipi di blocchi visti finora, ed è forse la più potente per quanto riguarda la risoluzione dei problemi. Prima di gettarsi nelle definizioni, considerate questo esempio.
Devo sommare Tra loro i numeri dispari da 1 a 10. Posso benissimo fare tanti cubetti in cui assegno una variabile e la sommo. Oppure posso usare una Strada più comoda. Infatti, se i numeri da sommare fossero stati 100 o anche 1000, non avremmo più finito. Dunque ci serve un modo per ripetere le stesse operazioni più e più volte. Ebbene quest esiste e si chiama ciclo, realizzato tramite la struttura dell' iterazione. non ha niente di difficile, basta stare attenti a come è fatta.
si compone di:
- la condizione di permanenza (nel ciclo)
- il corpo delle istruzioni
- il rimando ad un altro punto del diagramma
sembra strano? in realtà noi la applichiamo tutti i giorni, inconsapevolmente!
perdonatemi questo esempio. Quando preparate la pasta seguite varie istruzioni: mettete l'acqua, mettete il sale, ecc, una normale sequenza. poi però dovrete aspettare che la pasta sia cotta. Allora dopo un po' assaggiate. se è pronta, proseguite, altrimenti tornate indietro e rifate i passaggi.
identifichiamo le componenti:
- condizione di permanenza: la pasta è cotta?
- corpo delle istruzioni: aspetta; assaggia.
- rimando: se non è cotta, rifai le azioni
ed ecco finalmente come si presenta una risoluzione con ciclo:
http://pokehack.altervista.org/attachment.php?aid=389
(il "i è dispari" lo guarderemo più avanti)
sono possibili 2 metodi risolutivi, a seconda di quando viene valutata la condizione di permanenza. la differenza è che nel primo le istruzioni vengono eseguite almeno una volta, mentre nell'altro questo comportamento non è garantito a priori.
abbiamo quasi finito, mancano un paio di precisazioni. Abbiamo usato le frecce per indicare le direzioni da seguire. ciò non significa che possiamo andare dove vogliamo: ogni struttura ha le sue regole di funzionamento, e soprattutto, cosa più importante, non si può uscire dalla struttura in cui si è. ecco perchè vi ho stufato tanto prima (e lo farò ancora un'ultima volta) indicandovi le zone di competenza di ciascuna. ad esempio, quella che è più comune sbagliare, è l'iterazione. la freccia può, nel primo caso (controllo alla fine), entrare soltanto nella sequenza precedente (se non esiste una sequenza se ne fa una nulla fittizia), non inserirsi in altre strutture! mentre per il secondo tipo di iterazione (controllo all'inizio), la freccia può solo tornare al rombo della condizione di permanenza.
è anche possiblie, qualora si renda necessario, utilizzare più strutture dentro altre: questo processo si chiama annidamento; e in effetti lh'o usato nell'ultimo disegno: ho messo un rombo dentro un altro rombo. questa cosa si può fare anche all'infinito, finchè non viola le proprietà degli algoritmi.
ed ecco infine la tabella riassuntiva
http://pokehack.altervista.org/attachment.php?aid=390
per concludere veramente, vi dico che il teorema di jacopini-bohm dice che ogni problema può essere risolto soltanto con l'uso di sequenza, selezione e iterazione, perciò mettetevi tranquilli e pensate ad un modo per risolvere il problema, che ci sarà sicuramente, e non fate dipanare frecce ovunque intorno all'universo.
per il momento metabolizzate bene questo, che non è poca roba, la prossima volta vedremo qualche esercizio!
ci vediamo ;)
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere
FIRMA (intanto che ivan rimette lo spazio dedicato)
Guida di cui vado più fiero: Mega-Huge Bonnox' guide
Il mio nuovo motto: don't ask for ETAs!
(RIP immagine firma cancellata dai server)
"L'uomo è ancora il più straordinario dei computer"
-
citazione famosa, qualcuno di importante nella storia, forse Churchill boh
pezzo di firma prevalentemente riguardo il fangirling su Doctor who, di cui ora mi mezzo vergogno ma che alla fine per qualche motivo non riesco a cancellare, come se fossi ancorato alle origini.
In fondo contiene anche un primordiale tentativo di ravvedimento, processo che si conclude con l'introduzione del presente spoiler.
*immagine di congiunzione tra mass effect e doctor who della segretaria samantha traynor con in mano lo spazzolino sonico*
Ho un T.A.R.D.I.S. modello 40 ma non so usarlo.
Ehm, in realtà non è mio. L'ho "preso in prestito". Presa. E' una donna, già.
Vuoi fare un giro? Ovunque e Dovunque; tutto il tempo e lo spazio; ciò che è stato e che sarà. Da dove vuoi cominciare?
People assume that time is a strict progression of cause to effect, but *actually* from a non-linear, non-subjective viewpoint - it's more like a big ball made of wibbly wobbly... time-y wimey... stuff.
Prima di fare le fangirl in preda agli ormoni informatevi sulla fisica!
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
20-07-2016, 01:23 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:07 PM da Bonnox.)
ESERCIZI 3.2
facciamo qualche esercizio!^^
chiedo scusa, ma in realtà mi sono dimenticato di inserire alcuni concetti nella precedente lezione, ma va bene anche così, in quanto era già molto lunga, poi possono benissimo essere scambiati per la "teoria degli eserzizi"!
- Funzioni
è un particolare costrutto sintattico, in qualche linguaggio di programmazione, che permette di raggruppare, all'interno di programma, una sequenza di istruzioni in un unico blocco di istruzioni espletando così una determinata e in generale più complessa operazione, azione o elaborazione sui dati del programma stesso in modo tale che a partire da determinati input restituisca determinati output.
(grazie wikipedia, scusate ma non sarei riuscito ad esprimerlo così bene)
in alcuni linguaggi le funzioni assumono nomi diversi
(se siete interessati...)
in pascal le funzioni senza valore di ritorno si chiamano procedure
in assembly si chiamano routine
nei linguaggi ad oggetti si chiamano metodi
- Valore di ritorno
quando una funzione termina, restituisce un valore al blocco invocante. Questo può essere di qualunque tipo di dato, ovvero intero, reale, booleano, intero corto, intero lungo, carattere, e anche quelli definiti da voi. tuttavia questo comportamento non è obbligatorio, se il contesto non lo richiede. dopotutto, se avete fatto matematica a livelli non bassi, avrete visto le funzioni, come relazioni che associano agli elementi di un insieme al più un elemento di un altro insieme. Lo stesso in informatica.
ciò che nella lezione precedente abbiamo racchiuso in un unico blocco più grosso potrebbe benissimo essere racchiuso in una funzione; riconducendoci agli esempi, "area_trapezio" e "is_odd_number" sono anch'esse funzioni; la prima non ritorna nulla (si dice che è di tipo void) la seconda ritorna un booleano
- Vettori (array in inglese)
la definizione è molto semplice, ma sono uno strumento importantissimo: un vettore è una sequenza di dati dello stesso tipo in memoria.
(con sequenza intendo elementi contigui, tenetelo bene a mente)
ad esempio una stringa di testo è un vettore di tipo carattere:
"Ciao mondo" è rappresentato in memoria:
[...] [C] [i,] [a] [o] [ ] [m] [o] [n] [d] [o] [...]
(la i è brutta perchè ho dovuto ingannare il formattatore, altrimenti me la considerava italic)
i puntini all'inizio e alla fine sono quella notazione in grammatica per dire "c'è dell'altro".
questa è la rappresentazione generica di un vettore:
![[Immagine: Array+in+Java+Comparision.gif]](http://2.bp.blogspot.com/-v-dkON4gwhQ/U4cw77VA-2I/AAAAAAAABkI/RL1x8PGgt-U/s1600/Array+in+Java+Comparision.gif)
un elemento di un vettore può contenere a sua volta un vettore. in Questo caso rprende il nome di matrice. un esempio di matrice è una mappa di tiles, in cui le "colonne" sono elementi delle "righe" (o viceversa a seconda dell'implementazione)
realizzazione:
![[Immagine: array-2d.png]](http://ycpcs.github.io/cs201-summer2014/notes/figures/array-2d.png)
e considerando una matrice 3x3, ogni elemento è:
![[Immagine: Image377.gif]](http://www.math.it/formulario/images/determinanti/Image377.gif)
abbiamo finito per ora! ~
in questi esercizi simulerò i passaggi risolutivi che uno dovrebbe seguire.
sono 5 esercizi sugli algoritmi (schemi a blocchi) perchè non posso allegare più immagini di così.
Per i disegni così belli ho usato un programma chiamato Algobuild
1) dato un numero, stampa (o ritorna) il fattoriale
il fattoriale di un mumero è il prodotto dei numeri da 1 al numero stesso.
ad esempio, se il numero è 5, il fattoriale è 5*4*3*2*1=120
input: un numero
output: un numero
strategia risolutiva: dobbiamo avere un valore temporaneo che sarà il risultato
dobbiamo anche moltiplicare il risultato delle moltiplicazioni precedenti per qualcosa di nuovo; ci fermeremo quando il fattore raggiunge 1.
[attachment=393]
2) dati n numeri (uno alla volta), calcolare la media
input:
- un numero che indicala quantità di numeri da processare
- tanti numeri (da processare uno alla volta)
output
la media di tutti
strategia risolutiva: ogni volta che l'utente inserisce un numero,dovremo aggiornare la somma. calcoleremo la media alla fine dell'inserimento (totale/numero di elementi)
[attachment=395]
3) soluzione equazione di secondo grado
un'equazione del tipo ax^2+bx+c=0 ha soluzione
x1= -b+sqrt(b^2-4*a*c))/2*a
x2= -b+sqrt(b^2-4*a*c))/2*a
chiederemo i coefficienti a, b, c e verificheremo che il discriminante non sia negativo (non si può fare la radice quadrata di un numero negativo! :p), poi applicheremo la formula
[attachment=396]
4) data una stringa, invertirla
input: un vettore
output: un vettore
strategia risolutiva: inizio a riempire il nuovo vettore partendo dall'ultima posizione
dell'altro
[attachment=397]
5) dato un vettore, calcolare la moda (il valore più ricorrente)
input: un vettore
output: un numero
strategia risolutiva:
creo una tabella (detta matrice, ovvero un vettore di vettori) in cui memorizzo ogni valore e le sue occorrenze. scorro il vettore dato e "popolo" la tabella. ogni volta che trovo un valore lo aggiungo al contatore. alla fine scorro l'intera tabella per trovare il valore con più occorrenze.
la tabella è grande esattamente quanto il vettore (x2 ovviamente), e non è il massimo dell'ottimizzazione.
si potrebbe fare in varie altre maniere, di cui sicuramente una meno esosa di risorse, ma al momento non ho tempo per pensarci troppo :p
[attachment=398]
(scusate se ci sono un paio di piccoli errori (non nell'algoritmo), ma sinceramente non ho voglia di rifare tutto)
ora, compiti! ~
avete max 10/12 giorni di tempo
- dato un numero, stabilire se è pari o dispari
suggerimento: un numero è pari quando è divisibile per 2. cosa vuol dire essere divisibile per due?
per fare questo ci sono almeno 3 possibili strade (proprietà degli algoritmi)
- dati 2 vettori, produrne un terzo con la loro somma (somma "termine a termine" delle componenti)
- dati 2 vettori, concatenarli ("attaccarli")
suggerimento: creare un nuovo vettore, ovviamente più grande, in cui si mettono gli altri
- dati n numeri inseriti dall'utente, stabilire il maggiore
- dati i 3 lati di un triangolo, classificarlo (scaleno, isoscele, equilatero)
suggerimento: bisogna sapere come sono i lati tra di loro (in lunghezza)
e per oggi è utto!
la prossima volta, finalmente ASM!
BUONE FESTE E BUON HACKING! 
.
LEZIONE 4
ASM
#integrare con jpan
Eccoci alla parte che forse vi interessa maggiormente! Se avete capito bene l'ultima lezione non dovreste avere grossi problemi.
Spesso abbreviato in ASM, è quanto di più vicino al linguaggio macchina l'uomo possa comprendere senza diventare pazzo. Infatti il linguaggio macchina è fatto dai cosiddetti codici operativi, ovvero dei byte che vengono letti dal processore, ed ognuno ha un preciso significato come istruzione. La sua particolarità rispetto agli altri linguaggi di programmazione è che c'è una corrispondenza 1:1 tra istruzioni scritte e istruzioni reali della macchina. Significa che per ogni istruzione scritta/letta da noi esiste un singolo codice operativo, e questa cosa si esprime dicendo che "esiste una sostituzione mnemonica tra istruzione della macchina e parola chiave del linguaggio". L'assembly, come avrete intuito, è un linguaggio a basso livello, per cui non è dotato di tutti i meccanismi di sicurezza che di solito abbiamo. Siamo solo noi e l'hardware. In altre parole, siamo i padroni totali, ma dobbiamo anche prenderne le responsabilità.
Prima però bisogna capire come funziona il processore.
Esso è responsabile dell'esecuzione fisica del gioco, svolge i calcoli necessari e controlla le periferiche (tutta roba trovabile su wikipedia).
La CPU è composta da varie parti; a grandi linee troviamo l'ALU, unità che esegue le operazioni via hardware (i circuiti elettronici elaborano i byte), la CU, unità di controllo, e i BUS (collegamenti elettrici) che trasferiscono i dati. Esiste poi un minuscolo settore di memoria che è sufficiente a contenere giusto i dati che servono per la corrente operazione. Tale spazio prende il nome di registri (da non confondere con i registri I/O tipici del GBA). I registri possono essere paragonati a delle variabili, ovvero dei contenitori di informazioni. Pensate ad una tazza piena di riso: noi possiamo mettere dentro tutti i chicchi di riso che vogliamo, ovviamente finchè non tracima, oppure possiamo svuotarne il contenuto, o anche solo contare quanti chicchi contiene in un certo momento (perdonatemi il brutto esempio, copiato da qualcuno su internet). I registri del GBA sono lunghi 32 bit, ovvero possono contenere dati fino a FFFFFFFFh, da cui si suol dire che il GBA è una macchina a 32 bit (come i computer fino a qualche anno fa).
Il processore funziona secondo uno schema fisso sempre uguale: - reperimento delle istruzioni (fetch)
- decodifica delle istruzioni (decode)
- esecuzione delle istruzioni (execute)
Questo processo si chiama pipeline, termine con cui si identificano le condutture petrolifere, proprio perchè il processo (scusate la ripetizione) è costante come il flusso di liquido. Le fasi vengono tutte svolte tramite dei circuiti dedicati ad ogni singolo compito, residenti un po' ovunque nella console (per la prima fase intervengono i bus sulla scheda madre e sulla cartuccia di gioco, le alte due invece vengono eseguite all'interno del processore). Questa pipeline a 3 stadi è tra le più semplici, e ad ogni istante ci sono 3 differenti istruzioni che stanno subendo un passo diverso tra quelli possibili (ovviamente in ordine). La più semplice ovviamente è quella che fa le operazioni una alla volta. Giusto per curiosità, i processori desktop hanno pipeline con addirittura decine di passi! (il pentium 4 una quarantina, perchè doveva essere il più veloce processore single core)
Prima di tuffarci a capofitto nelle istruzioni, bisogna spendere ancora qualche parola sullo specifico processore con cui lavoreremo: l'ARM7TDMI.
Il processore del GBA adotta l'architettura RISC, dunque è piuttosto semplice. RISC vuol dire Reduced Instruction Set Computer, ovvero elaboratore con set di istruzioni ridotto; modello che si contrappone ai CISC (Complex Instruction Set Computer), di uso tipico nei computer. L'e due architetture sono opposte; la seconda presenta molte istruzioni elementari utilizzabili, mentre la prima, per ridurre la complessità in ambienti critici, come una console portatile, offre soltanto lo stretto indispensabile in termini di operazioni effettuabili a livello di codice macchina. Ma proprio questo gli conferisce consumi energetici ridotti (io a volte arrivavo a 10 ore col GBA!!! [emoji15]); è anche stato usato in diversi vecchi dispositivi come l'ipod touch 1G.
Semplice fino a un certo punto; ci sono comunque un sacco di aspetti da tenere conto, anche tralasciando la realizzazione fisica (per quello c'è il noiosissimo libro facoltativo linkato all'inizio, ne sconsiglio vivamente la lettura se non siete bravi in elettronica (io tre quarti delle cose manco le so leggere asd)).
REGISTRI:
- R0-R12: registri general purpose, possono essere usati per contenere qualunque dato
- R13: Stack Pointer. usato per tenere traccia dell'ultimaposozione dello stack
- R14: Link Register, contiene l'indirizzo di ritorno della funzione
- R15: Program counter, indica la prossima istruzione da fetchare.
- CPSR: Current Program Status Register è il nome del PSW, un registro interno che raccoglie informazioni come lo stato dell'ultima operazione.
#spiegare bene cosa sono SP e LR nella prossima revisione
parte tradotta direttamente dalla documentazione:
L'ARM7TDMI ha due "modalità operative", ovvero può lavorare con due diversi set di istruzioni
- ARM, set di istruzioni a 32 bit
- Thumb, set di istruzioni a 16 bit
Il set thumb è un sotto-set dell'ARM, ogni sua istruzione ha una corrispondenza nel set esteso, che svolge lo stesso compito. La cosa forte è che entrambe le modalità condividono gli stessi registri, permettendo una forte collaborazione tra le due, consentendo di ottimizzare sia lo spazio occupato sia le prestazioni.
Infatti durante l'esecuzione, ogni istruzione a 16 bit viene "decompressa" nel suo equivalente a 32 bit, permettendo di sfruttare appieno le capacità della macchina.
Thumb ha tutti i vantaggi di un "cuore" a 32 bit:
- indirizzamento a 32 bit (significa che potrete trattare memoria fino a 4 GB, ma siccome come sapete il GBA si ferma a 0E-000000, avrete comunque tutto il range disponibile)
- registri a 32 bit
- operazioni a 32 bit
- trasferimento di memoria a 32 bit
il codice thumb occupa tipicamente il 65% del corrispettivo ARM, e fornisce il 160% delle prestazioni, se letto da una memoria a 16 bit. La ROM guarda caso ha un sistema di trasferimento a 16 bit, ecco spiegato il motivo per cui i giochi sono principalmente compilati in questa modalità. Tuttavia, se eseguito in uno spazio a 32 bit (ad esempio dalla RAM), la superiorità del codice thumb scema. Infatti sono fatte in ARM e residenti in RAM le routine di gestione degli interrupt, che noi non vedremo.
Il core del processore usa il primo bit del program counter per determinare cosa mettere in un altro registro interno, che serve per stabilire il set di istruzioni da usare (ecco spiegato l'arcano mistero del +1 nel callasm  ).
Il processore supporta sia la modalità di storage dei dati big endian che little endian.
ma siccome devono complicarci le cose (-.-") il default è little endian, in quanto di più veloce processamento (ha a che fare con la realizazione fisica dei circuiti dediti ai calcoli).
I precedenti termini si riferiscono a come le informazioni vengono scritte nella memoria. Big endian memorizza le informazioni a partire dal MSB (most significant bit), mentre little endian dal LSB (least significant bit).
Durante la modalità thumb, i registri alti (8-15) non sono immediatamente accessibili con le operazioni elementari. Se non possiamo farne a meno come deposito temporaneo di informazioi, possiamo usare alcune istruzioni per copiarvi il contenuto dei registri bassi (0-7), o anche nell'altro senso.
ogni istruzione può essere eseguita condizionalmente in modalità ARM, mentre lpunica istruzione condizionale in modalità thumb è il salto.
fine parte tradotta
Dopo questa estenuante introduzione penso che siamo pronti per vedere i veri comandi! ~
NOTA: non vi insegnerò la sintassi, a parte un caso che vedremo (#word align4 per ldr), perchè è noiosa e fine a se stessa, e potete trovarla nella documentazione. Reputo molto più istruttivo prima comprendere bene effettivamente cosa fanno i vari comandi.
- ADD/MUL/SUB
operazioni matematiche come somma, moltiplicazione, sottrazione.
di solito si scrive il comando seguito da 3 registri: registro destinazione del risultato, registro operando 1, registro operando 2. oppure si usa un immediato (un piccolo valore scritto direttamente nel codice, senza dover sprecare un registro)
- B/BL/BX servono per eseguire dei salti nel codice. I salti permettono di alterare il normale flusso di esecuzione del programma, ma per routine semplici non sono necessari. Di solito si usano quando si testa una condizione e si vuole un comportamento diverso a seconda dei casi. Se avete capito bene i goto negli script, non avrete problemi. La differenza tra i tre è che B salta e basta, BL salta e copia il PC nel LR per un facile ritorno, BX salta e cambia modo operativo, a seconda dell'ultimo bit del valore.
E' possibile aggiungere delle condizioni all'istruzione B.-
B + qualcosa significa salta se:
- BEQ uguale (equal)
- BNE diverso (not equal)
- BLT minore (Less than)
- BGT maggiore (Greater than)
- BLE minore o uguale (Less than or equal)
- BGE maggiore o uguale (Greater than or equal)
#PRENDERE DA TONC E CREDITARE
I salti condizionali sono molto usati con l'istruzione CMP.
le varianti condizionali si basano sul CPSR, perciò sono utili solamente se seguono un'istruzione CMP. potreste comunque usarle quando volete (come ogni istruzione del resto), ma non avrebbe molto senso.
- CMP paragona. può paragonare un registro ad un byte, o 2 registri tra loro e mette il risultato nel PSW (CPSR), subito dopo sarebbe utile eseguire un salto. altrimenti è un'operazione sprecata. Questo è l'unico modo di eseguire istruzioni condizionali in modalità thumb
- LDR/LDRB/LDRH/MOV Serve per caricare un registro con dei dati. Esistono varie opzioni, come un valore immediato; un valore letto dall'indirizzamento indiretto; un valore ottenuto mediante operazioni, ecc. La differenza sostanziale tra i tre sta in cosa caricano: LDR 32 bit, LDRH 16 bit (H sta per Half) , LDRB 8 bit (B sta per Byte). MOV invece inizializza un registro con un byte presente nelostesso codice operativo.
- LSL/LSR serve per shiftare i bytes a destra o a sinistra. approfondimento sullo shift:
questa operazione è utile quando si vuole moltiplicare per potenze di 2. infatti si può moltiplicare di 2^n un numero spostando verso sinistra n volte i bytes. Per dividere shiftiamo verso destra.
esempio:
5d
0101b
shiftiamo di 1
1010b
10d
esempio
50d
110010b
shiftiamo di 1
011001b
25d
# revisione ^
- NEG nega il contenuto di un registro, bit per bit.
- STR/STRB/STRH Questi invece fanno l'operazione inversa del LDR, ovvero "stoccano" (da store) il dato da qualche parte. Anche qui Vi sono molte opzioni, ma è meglio visionarle sulla guida, in quanto in questa sede appesantirebbe la lettura.
- POP/PUSH servono all'inizio e alla fine della nostra funzione ASM (non in tutti i casi, solo nelle sotto-funzioni) per accatastare sulla pila i contenuti dei registri che ci serviranno per compiere le operazioni. E' buona cosa ricordarsi di andare a riprendere le informazioni e rimetterle alloro posto una volta terminata la routine.
E' importante ricordare che per iniziare una sotto-funzione (quelle trattate in questa guida) su usa PUSH LR (più eventuali registri usati) e per terminarla si deve fare POP PC. Questo perchè quando eseguiamo un salto il Link Register assume il valore dell'offset dell'istruzione successiva a quella del salto. ovvero, per chi usa un IDE, "step over". ovvero, per i comuni umani, considera la funzione chiamata dal salto come una singola istruzione, e dunque l'istruzione seguente non è la prima che si incontra dopo aver seguito il salto, ma quella effettivamente successiva nel file (rimane allo stesso livello di profondità delle sotto-funzioni). Una volta accantonato il LR e compiuta la routine, dobbiamo tornare indietro. Come? Facile. Poppando (ok, doppiosenso, scusate) il LR otteniamo il punto dove continua la nostra ROM, ma per andarci dobbiamo metterlo nel Program Counter!
#aggiungere tutti i comandi
#da qualche parte metttere endianess
vi è andata bene che non vi do compiti, prossima volta esercizi, vediamo qualcosa in azione!
#revisionare tutto
Ciao e benvenuti nella mia aula!
Vi prego di portare pazienza, in quanto devo sistemare per bene i testi; questo messaggio era per dirvi che "so che ci siete"!
LEZIONE 0 - INTRO
Innanzitutto vi comunico il materiale essenziale:
Facoltativo (ma consigliato): - Documentazione ufficiale ("approfondimento"):
Il VBA-SDL-H è una versione modificata del VBA che permette di fare cose avanzate per gli hacker, ed è quello che useremo più spesso, in quanto torna molto utile come debugger e disassemblatore. Funziona da linea di comando, ma come vedrete non è molto difficile da usare.
L'Asemblatore è un programma che permette di passare dal nostro linguaggio ASM al file binario effettivo (codice eseguibile dal GBA)
Per quanto riguarda l'Hex editor cìè un piccolo discorso da fare: Esso sarà il nostro "migliore amico", perciò bisogna sceglierlo bene. quello che volete, ce n'è una svalangata tra cui scegliere, ergo usate quello con cui siete più comodi. I toolz servono per facilitare il lavoro, non per litigarci contro (e vi posso garantire che è infernale non andare d'accordo col programma in uso). Io attualmente uso questi 3 in accoppiata: XVI32, HxD, WindHex, ma non vuol dire che dobbiate farlo anche voi. Più avanti vi illustrerò brevemente ciascuno di wuesti tre.
Ora faccio un paio di considerazioni.
Innalzo il tempo di risposta dai 5 giorni canonici a 8/10 (ma potrebbero essere anche di più). Ovviamente questo vale solo per lo svolgimento di un compito, perché gli altri post non richiedono grandi capacità o applicazione, e anche perché immagino sarete incollati al pannello di controllo per vedere se ho risposto, dunque non c'è neanche bisogno di fissare una scadenza per il resto dei messaggi. Questa modifica semplicemente per il fatto che questa è roba di una certa levatura, a volte anche difficile. Potrà sembrare strano, ma come il mapping anche l'asm richiede tanto tempo... Per la creatività! Pacman Confused no ok magari non è la migliore scelta lessicale, fatto sta che ci può davvero volere del tempo. Dunque avremo orari... flessibili.
A proposito, vi consiglio di stootscrivere la discussione clickando sul link in fondo alla pagina, oppure la stella di SchifoTalk  così non dovremo più taggarci come dei matti (avendo sottoscritto, voi vedrete che ci sono nuovi post dal pannello di controllo, io pure perchè sono l'autore)
Allora la mia idea, prescindendo dagli argomenti trattati, era di preferire un post grosso diviso in più parti, in modo da poter analizzare con calma ogni singolo aspetto. Non disdegno la tecnica "mordi e fuggi", ma in questo caso non potrebbe essere applicata per svariati motivi. Magari negli altri casi, come spiegare i comandi di XSE un po' per volta, può funzionare, ma non qui.
Se alcuni concetti esposti in questo messaggio non vi saranno subito chiari non preoccupatevi, li riprenderemo ~
Detto questo ci vediamo la prossima volta Smile
Saluti
(spero non sia sembrato "kattivo", non voglio essere cattivo se non c'è motivo)
(e, plis, aiutatemi a guarire dalla mania delle parentesi. Siete autorizzati a mandarmi un messaggio se metto troppe parentesi)
let's get it started.
LEZIONE 1
BIT? BYTE?
IL LINGUAGGIO BINARIO
Devo fare una piccola premessa con la Terminologia. se la sapete potere pure saltare (Do per scontato che sappiate i sistemi di numerazione). - Bit
Elemento che ha origini agli albori dell'informatica. E' un elemento che può assumere 2 stati (configurazioni) diverse. Solitamente sono HIGH e LOW (con riferimento ai valori della tensione in un circuito) Per estensione, rappresenta le 2 cifre del sistema binario (0 e 1). È l'unità fisica minima nell'informazione.
- Byte:
È l'unità logica fondamentale, composta da un gruppo di 8 bit su un supporto (cd, hard disk, radio frequenze...) Può dunque assumere un massimo di 2^8 = 256 stati diversi. Nel nostro sistema decimale si parte da 0 e si arriva a 255. In binario è 11111111b. In esadecimale corrisponde a 0xFF.
- Offset:
letteralmente "scostamento", indica lo spostamento di un preciso byte relativamente all'origine del file. Noi fortunatamente consideriamo sempre tale origine come il primo byte della ROM, dunque indirizzo 0 (ricordo che in informatica si inizia sempre a contare da 0), ma non è raro il caso di dover iniziare a contare a partire da un altro valore. Ad esempio per hacking di altre console (il caso più vicino a noi è GB) si divide la rom in varie parti; ognuna determina una diversa origine del valore dell'offset.
- Puntatore:
generalmente in informatica è un valore (sarebbe meglio dire variabile) che indica, quindi si dice "punta", un'area della memoria della macchina. Generalmente nei computer indica la RAM, ovvero la memoria temporanea che contiene i dati in attesa di essere elaborati; Mentre noi avremo quasi sempre a che fare con puntatori alla ROM, che è la memoria di sola lettura in cui risiede il gioco (che actually è da considerarsi il sistema operativo del GBA, ma forse lo vedremo meglio più avanti).
Come avrete capito in questa prima parte lavoreremo sui byte; nonostante ahimè sia un lavoro noioso secondo me è più facile da comprendere di altro.
Ogni file sul nostro computer è composto da una serie più o meno lunga di bytes. Come avrete avuto modo di notare, la rom occupa esattamente 16 MB, il che è veramente poco, se non fosse che risale al 2002 e per giunta è per una piattaforma mobile.
All'interno del file ci sono, stipati insieme, tutte le istruzioni del programma e tutti i dati che servono a far funzionare correttamente il tutto. Le istruzioni sono ciò che vedremo con l'Assembly, il linguaggio macchina sostanzialmente, ovvero tutte le istruzioni che il GameBoy esegue una volta caricato il gioco, come ad esempio "fai questo suono", "memorizza tale variabile", “visualizza l’immagine”, "muovi la pokeball", eccetera. I dati invece sono informazioni conservate nella rom con un preciso formato. Ad esempio sono dati le musiche, le mappe, i pokemon degli allenatori, i testi dei messaggi… tutto quello che viene modificato dai programmi è un dato. Ma noi dobbiamo imparare a farlo anche senza programmi. I dati vengono letti solo quando necessario e caricati a blocchi nella ram, che anche se piccola è molto veloce, in quanto le continue operazioni di lettura rallenterebbero il programma. Infatti la memoria centrale (altro nome della ram secondo Von Newmann) è sì più piccola, ma anche molto più veloce della memoria di massa. Si parla di tempi dell'ordine dei nanosecondi per accedere a un dato, contro i vari millisecondi della rom.
E' importante chiarire il fatto che in sè non esisterebbe la distinzione tra istruzioni e dati. I dati infatti possono essere anche erroneamente interpretati come istruzioni (vedasi i vari glitch di pokemon red), e se per noi è un fastidio, per la macchina non cambia assolutamente nulla. Vederemo più avanti come questo sia possibile.
Bene, eccoci alla vera lezione. Mi scuso se sarà un po’ monotona, ma è importante. Come diceva un mio professore, “il brutto delle cose facili è che vanno sapute perfettamente”.
Aprite un hex editor. Esso è un software che ci permette di visionare e modificare i bytes di un file. Ecco come si presentano alcuni di essi una volta aperti:
http://pokehack.altervista.org/attachment.php?aid=297
Iniziamo caricando un nuovo file. Consiglio un file che non vi serve più, dato che andremo a pasticciare e a rovinare
Normalmente troveremo tre colonne: la prima indica l’offset dall'inizio del file, quella centrale visualizza tutti i byte, e l’ultima colonna ci indica gentilmente la loro rappresentazione testuale, cosa di cui non potrebbe fregarci di meno, dato che per noi è inutile. L’unico utilizzo che può avere per noi tale parte è per “rincuorarci”, ovvero trovare un piccolo conforto in caratteri familiari di fronte all'agonia della vista dei bytes. Ok, dovrò andare a fare il drammaturgo 
Posizionate il cursore sulla colonna a destra, e iniziate a scrivere cose a caso sul file cavia. Notate che c’è una corrispondenza a sinistra con ciò che scrivete?
Ora vorrei che vi prendeste un attimo di tempo per fare una cosa. Iniziate a scrivete tutte le lettere dell'alfabeto, dalla a alla z, minuscole e maiuscole, e poi i numeri. Cosa notate? I byte a destra assumono precisi valori. Signori, vi presento l’ASCII. Questo è uno standard americano di comunicazione abbastanza datato, ma è la base dei più recenti. In pratica assegna ad ognuno dei valori ottenibili da 7 bit a un carattere o simbolo. La tabella attualmente diffusa è quella di MS-DOS, mentre una volta c'erano discrepanze a seconda del sistema operativo.
Ora prendiamo confidenza con le funzionalità del'H.E.. Non so il vostro percorso del menu a tendina, ma esiste una scorciatoia praticamente universale che tutti implementano: CTRL+F. Si aprirà una finestra chiamata ricerca. Qua ci mettete del testo che volete venga cercato all’interno di un file. Se state usando una rom di pokemon non avrete fortuna, perciò cambiate subito file. Potete scegliere un documento di office di quelli vecchi (.doc e non .docx ). Dopo aver avviato la ricerca il cursore si posizionerà sulla prima occorrenza; per cercare ancora premete F3. Oppure create una lista di risultati, che è più comoda:
http://pokehack.altervista.org/attachment.php?aid=298
Fate la stessa cosa con le stringhe esadecimali. Cercate una stringa, stavolta corta, per aumentare le probabilità di successo.
Ricordate che anche se in generale sono simili, ogni hex editor ha proprie funzioni aggiuntive che vale la pena provare e sfruttare.
Ad esempio poco fa avete visto in azione una delle caratteristiche che mi piacciono di windhex. Peccato che sia un po’ scomodo da usare “quotidianamente”.
[attachment=415]
[attachment=416]
Ora vorrei concentrarmi su una cosa molto importante, ovvero la ricerca dei puntatori. Come accennato prima sono dei valori che indicano una posizione all’interno della memoria del GBA. Ipoteticamente, ogni byte potrebbe avere il suo puntatore, basta costruirlo. Nella realtà però non è così perché si indica soltanto il primo byte di qualcosa (la cosiddetta "risorsa": un'immagine, un testo, ecc.), quelli seguenti sono referenziati tramite un indice di scostamento rispetto al puntatore (l’origine di cui parlavo prima). Considerate questo esempio:
“QUEL FEZ SGHEMBO COPRE DAVANTI”
non preoccupatevi, è soltanto un pangramma. Volevo mettere quello degli ioni che era l’unico che ricordavo a memoria, ma nell’aprire wikipedia ed aver visto una citazione al mio telefilm preferito… beh… <3 giustamente dovevo metterla, concedetemelo. Analizziamo ora la frase:
[Q][U][E][L][ ][F][E][Z][ ][S.][G][H][E][M][B.][O][ ][C][O][P][R][E][ ][D][A][V][A][N][T][I.]
(il "." è per imbrogliare il parser myBB)
Abbiamo un indice che identifica ogni lettera:
[00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29]
Se volessimo accedere ad una lettera, non dovremmo fare altro che sommare l’indice all’offset del primo carattere, così:
Codice: *byte[] carattere;
carattere[i]=&frase[0]+i
ovvero, in un linguaggio più umano (perdonate la sintassi C e lo stile matematico della definizione), significa che ogni lettera all'indice i di un testo ha un offset totale pari all'offset del primo carattere più il suo offset relativo, appunto l’indice i. capiamo meglio con un’immagine:
http://pokehack.altervista.org/attachment.php?aid=300
In questo esempio possiamo vedere che l’offset del primo carattere è 9D3CE4h, e se voglio l’indice del carattere z devo sommare l’i di z, ovvero 7.
Spero sia chiaro, altrimenti non fatevi scrupoli a chiedere.
Ora vediamo quali sono i passaggi per ottenere un puntatore. Per il momento ci saranno dei punti poco chiari, ma nelle prossime lezioni saranno rivelati.
Dato un offset lungo 3 byte, il suo puntatore è: - scrivere XX XX XX 08;
- invertire l’ordine dei 3 byte (quello in mezzo ovviamente resta in mezzo)
- sostituire i nuovi byte alle X.
Ecco l’esempio per 9D3CE4: - scrivo XX XX XX 08;
- ribalto i bytes: E4, 3C, 9D.
- sostituisco: E43C9D08.
Questo è il puntatore come se fosse stato inserito nella ROM originale. Ora basta metterlo nel posto giusto e il gioco potrà usare il nuovo testo, e nessuno si accorgerà della modifica!
Avete voglia di ricavare qualche puntatore, così giusto per esercizio?
Ricavate i puntatori dei seguenti offset:
Spero lo abbiate fatto, perché alla fine della lezione vi servirà.
Bene, eccoci alla prima su due cose pratiche. Recatevi all’offset 3E6E50. Come fare? Non so quale sia il vostro menu a tendina, ma sicuramente potete fare CTRL+G.
Inserite l’offset come faccio io e dovreste avere il seguente risultato;
http://pokehack.altervista.org/attachment.php?aid=301
Questo è un dato binario. Significa che è un dato rappresentato nel suo tipo (formato) naturale. ne consegue che solo chi sa leggere quel tipo di dato potrà comprenderne il significato. Fate una prova: aprite un’immagine con il blocco note. Cosa esce? Caratteri incomprensibili, perché il blocco note non sa leggere le immagini, lui poverino cerca solo il suo formato di dati (il testo) nell’immagine. Se provate ad aprire file prodotti da un'altra applicazione, come ad esempio qualcosa di autodesk o adobe, con un programma totalmente diverso, come ad esempio VLC, sarete fermati da un errore di incompatibilità. I programmi si aspettano certe cose nel file che aprono, e se non le trovano prevengono potenziali (anzi, sicuri) catastrofici errori dicendo di non poter aprire il file. Che poi VLC sia zelante e apre tutto mentre Windows media player invece schizzinoso sono dettagli…
Dunque dicevo, ciò che troviamo sulla rom deve essere interpretato come il tipo di dati giusto per produrre un output coerente per l’utente. Altrimenti si verifica la stessa cosa di missingno: Secondo pokemon rosso laggiù ci doveva essere il verso di un pokemon, mentre invece c’erano dati di chissà cosa… ecco da dove nasce l’inquietante verso di ♀ (“female”). Ed ecco perché sembra non finire mai: interpretando tali dati come suono, i byte che indicano la fine del suono non vengono raggiunti in tempi ragionevoli. Stesso discorso dicasi per la lunga lista di evoluzioni di certi pokemon glitch: non si trova una sequenza di byte terminatrice. A noi invece il massimo che possa capitare è vedere qualche carattere giapponese in un messaggio (mai capitato durante il corso di XSE?), perché magari sbagliamo a mettere l’offset, confondendolo con il puntatore; questo perché la nostra rom è dannatamente più stabile.
Come modificare tali dati binari allora? Dobbiamo innanzitutto scoprire cosa rappresentano. Io lo so già perché riciclo gli esempi per la non sbatta. non è vero: in futuro aggiungerò un esempio tratto da advance map
Dobbiamo copiare i byte in un nuovo file per poterli analizzare meglio.
EDIT: In realtà mi sono accorto solo ora che il dato binario è word-aligned (allineato per 4 byte), dunque non serve ciò che sta sotto. Che sbadato :|
Tuttavia anche se stavolta non serve è utile sapere come si fa, perciò dategli un'occhiata lo stesso.
Procedura per XVI:
Modo 1: - Copiate una sequenza di byte da un programma (browser? andrea <3 )
- posizionatevi nel punto in cui incollare
- Edit > overwrite string
- selezionate hex
- incollate e confermate
Modo 2 - assicuratevi di essere in modalità overwrite
- Posizionatevi sul punto da copiare
- Edit>block n chars
- inserite la lunghezza da copiare
- Edit>clipboard>copy
- posizionatevi nel punto in cui incollare
- Edit > block copy/overwrite (CTRL+W)
Spiegazione per HxD:
Sostanzialmente uguale a prima, ma l'ultimo passaggio è CTRL+B
Sicuramente ve lo aspettavate, conoscendomi  chiedo nuovamente scusa a fiammy per aver tralasciato dall’immagine il suo posticino di meditazione quotidiana
Bene, ora che sappiamo cosa è analizziamo il formato: sembra che ogni valore del byte corrisponda a una città (SHISH, A GINIUS!). è importante però notare una cosa: il valore 58h indica il vuoto. Anzi, qualunque valore al di sopra di 58h indica vuoto.
Il vostro compito è di modificare (tramite hex editor, ovviamente) la worldmap e farmi vedere il risultato.
Perché l’abbiamo estratta? Perché è più semplice da riconoscere: come avete potuto notare, nella rom è “sfasata”, non si capisce bene cosa sia.
E poi potete vedere subito se per sbaglio aggiungete dei byte. Controllate sempre di essere in modalità OVERWRITE! Inserendo bytes spostate altra roba, che dunque non è più al suo posto, e non verrà letta correttamente. Finchè si tratta di dati si può soprassedere (immagini, testi e suoni glitchati), ma se sono istruzioni, la cosa si fa grave...
CONSIGLIO: fate spesso backup.
Per compito i 4 angoli della tabella devono contenere una città a scelta. Questo è un compito per farvi imparare a contare (? Asd). Si, perché avrete notato che i dati sono tutti immagazzinati in fila indiana, non ci sono righe o colonne. La presenza di righe e colonne è dedotta dal software, mediante un semplice procedimento.
- So le coordinate X e Y del dato della tabelle che devo leggere.
- Moltiplico la Y per il numero di elementi di una riga
- Sommo X al precedente risultato
- Sommo l’offset del primo elemento della tabella al precedente risultato.
Come funzionano questi passaggi? Facciamo un esempio passo-passo.
Supponiamo di avere all’inizio di un file una talebba di 9 elementi, così:
A B C
D E F
G H I
Ma ovviamente nella memoria essa è contenuta linearmente: [[(A), (B), (.C)],[(D), (E), (F)],[(G), (H), (I)]] . Come facciamo ad accedere ad un elemento? Dobbiamo indicizzarla.
Mettiamo di voler accedere alla posizione centrale, di indice 1,1 (si parte a contare da 0).
- Moltiplico y*la larghezza: 1*3=3
- Sommo la x: 3+1=4
- Sommo l’offset di inizio della tabella: 4+0=4
Dunque prendiamo il valore alla posizione 4: A, B, C, D, E.
Tutto questo casino per cosa? Per sapere cosa state modificando. Se siete sulla ROM vi perderete in fretta, per cui bisogna sempre contare prima di scrivere qualcosa.
Ma tanto già so che voi avrete estratto la worldmap e ridimensionato la finestra del programma per avere esattamente 28 colonne, vero? Sempre che il vostro hex editor permetta ciò. A questo punto il compito diventa una bazzecola.
Chi lavora su fire red può fare il compito su fire red, per questa volta. L’offset è 3F2500h.
Ora proviamo a fare una cosa più complicata. Vi giuro che è l’ultima per oggi. Mi serve perché contiene una cosa che da grattacapi ad alcuni utenti, ma immagino che per voi non sarà un problema.
Spostiamo la worldmap.
Cosa? Eh, dai, su, non ho mica detto di spostare una regione intera, è solo una cartina! Mica siamo dei titani, solo dei geografi!  ok pessima Ecco il procedimento passo per passo. Vorrei lo faceste per compito.
Per poter proseguire, dovete aver fatto il mini esercizio sui puntatori.
Soluzione:
- 506E3E08
- 28B30F08
- 0000E008
Prendete l'offset della worldmap. Aprite la rom e cercate una stringa esadecimale. Scrivete il puntatore. Se tutto è corretto dovreste averlo trovato una sola volta (se di più o avete usato rosso fuoco e allora non so, oppure c’è qualcosa di sbagliato, nel caso chiedete pure). Si trova a FB328h per ruby.
Sostituitelo. Con cosa? Ma con quello che volete voi. Ad esempio provate un offset a caso. Scrivete davvero byte a caso, è istruttivo. Aprite la mappa città nel gioco e vedete che succede. Il gioco interpreta come mappa città dati che mappa città non sono. Complimenti, avete buggato la rom! Tranquilli, è riparabilissimo, basta fare l'operazione inversa! Ora invece torniamo indietro. Mettete il puntatore di questo valore: 720000h. se la rom è vergine, dovrebbe esserci spazio laggiù. Il puntatore è: 00-00-72-08. Ora, come prima, copiate la vostra wolrdmap in tale punto. Modificate valori della worldmap a caso per avere la garanzia che il gioco non prenda dati da quella originale. Se tutto va bene, cancellate quella originale, scrivendo 420d volte 00h o FFh (o qualsiasi cosa, ma questi due valori sono molto più "convenzionali").
Bye!
LEZIONE 1.2
Se ricordate, l'altra volta ho detto che per visualizzare i caratteri sono utilizzati gli standard di comunicazione, in cui ad ogni byte corrisponde un carattere ben preciso.
Ovviamente in GF hanno avuto la brillante idea (si fa per dire...) di alterare l'ordine naturale delle cose sostituendo tutti i caratteri con dei nuovi. Il funzionamento è il medesimo, ma i giochi adottano un set di caratteri diverso, come si suol dire. Questi possono essere trovati sull'enciclopedia [ http://bulbapedia.bulbagarden.net/wiki/C...ration_III] dove sono descritti in maniera molto dettagliata. Noterete che ci sono alcuni valori strani: sono le sequenze di escape, ovvero i caratteri di controllo. Questi sono speciali caratteri, presenti in ogni sistema operativo, che hanno particolari compiti. La procedura che si occupa della scrittura del testo riconosce il carattere speciale e si comporta di conseguenza. Ora mentre sto scrivendo questo testo non ho sotto mano il documento, ma ogni singolo byte è ampiamente documentato. Ad esempio con essi potete cambiare colore, oppure fare una pausa, o usare il grassetto. Sono tecniche utili per la regia  Anche nel computer normale ci sono le sequenze di escspe: a capo è un esempio.
Tutte le volte che usate una sequenza mnemonica in xse, come ad esempio "LASTRESULT" o "RS_cyan" (non son sicuro che la seconda sia corretta così com'è, ma avete capito a cosa mi riferisco) lui sostituisce nella ROM una particolare sequenza di caratteri al posto della parola chiave. Nel nostro caso al posto del colore metterà il byte che indica il cambio di colore, e poi il byte del colore [# non avendo sotto mano la pagina di bulba è il massimo che posso dirvi a riguardo]. E se volete inserire in XSE altre sequenze di escape? C'è il comando "\h", mi pare, ma non sono sicuro. Comunque dovete inserire un "\h" (o quello che è) per ogni singolo byte che compone la nostra sequenza di controllo. Noioso, vero? Ecco perchè a volte preferisco usare l'hex editor. Ovviamente non dovrete usarlo sempre, anzi riconosco che usare XSE è più comodo, ma sapere come fare è sempre meglio; forse vi capiterà qualche caso in cui vi servià.
Per svolgere correttamente questa attività dovrete avere una tabella dei caratteri, che essenzialmente è un file che dice all'hex editor quali sono le corrispondenze tra i caratteri "normali" (ASCII) e "quelli pokemon" . Io vi passo quella che si trova insieme a thingy 32 (un hex editor sviluppato principalmente per le traduzioni) e quella (incompleta) che ho fatto io per xvi in un momento di noia
http://pokehack.altervista.org/attachment.php?aid=279
http://pokehack.altervista.org/attachment.php?aid=280
Da rinominare in "TBL" e "XCT".
Come si usano? Ogni programma ha le sue beghe, dunque bisognerà stare attenti. Comincio col dire che su HxD neanche c'è questa possibilità, oppure sono stordito io che non l'ho vista. Rimangono windhex e thingy che si comportano in modo piuttosto simile, mentre xvi, come vedrete tra poco, fa una "cassanata".
Dunque è giunto il momento di aprire rom e tabella. Solitamente i comandi stanno nel menu file. Windhex legge la tabella di thingy. Una volta completato dovreste vedere che i caratteri a destra sono cambiati. Il programma sta sostituendo i byte della ROM con i caratteri indicati da noi. Ora, finalmente, potete provare a sbizzarrirvi con la ricerca di testo, in quanto ci sono un mucchio di parole di senso compiuto! E se provate a scrivere con le normali lettere della tastiera, queste vengono automaticamente tradotte nel formato corretto, mentre a noi appariranno come lettere normali!
http://pokehack.altervista.org/attachment.php?aid=308
Bisogna ricordare, però, che il programma è stupido, e non sa quali byte sono effettivamente testo e quali no, perciò li sostituisce tutti. Per superare questo inconveniente basta cambiare la tabella in uso, tornando ad ASCII, o quello che è un uso dal vostro programma. Di solito tale comando sta o in file o in modifica. (in windhex File>Swap table file)
Ora arriviamo al problema XVI: purtroppo non riesce ad astrarre i caratteri, perciò la soluzione che adotta è sostituirli fisicamente nella vista di sinistra! [emoji33] Se salvate vi ritroverete una ROM sicuramente corrotta! NON SALVATE LA ROM DOPO AVER APPLICATO LA SOSTITUZIONE CON XVI!
Ora impareremo a cambiare il testo direttamente con l'hex editor. Come funziona questo metodo? Se sapete trovare e modificare i puntatori lo applicate alla svelta.
- Individuate il testo da modificare con la ricerca di stringa, di testo stavolta
- ricavatene il puntatore
- cercate il puntatore dall'inizio della ROM. Meglio se pochi (1) risultati, perchè significa che la risorsa è usata una sola volta. Nel caso del testo dovrebbe essere così. Segnate l'offset.
- andate in spazio libero (createne il puntatore) e scrivete! Bisogna però stare attenti alla larghezza, in quanto finora tutti gli hex editor adottano larghezza fissa delle colonne. In Certi casi torna utile, ma non in questo. Indicativamente, in minuscolo potete scrivere 30 lettere.
- andate al primo offset segnato. Contiene il puntatore al vostro testo. Dovrete sostituirlo con il puntatore al nuovo testo.
Se conoscete un hex editor migliore di quelli elencati in questo corso (windhex, XVI, HxD) per favore segnalatelo.
Come potete notare non ci siamo spostati neanche per un attimo dal programma corrente, quindi, se il testo è favorevole da scrivere, questo consente di risparmiare un po' di tempo rispetto ad altri metodi.
Come vedremo nelle ultime lezioni, disporre dei testi di una ROM è essenziale per iniziare piuttosto agevolmente alcune particolari ricerche di ASM.
Come compito modificate un testo come volete. (tanto poi fatto uno fatti tutti)
---
#PARTE 2
LEZIONE 2
I moderni calcolatori sono costruiti secondo l'architettura di Von Neumann (in opposizione a quella di Turing che non è da meno, ma con i moderni dispositivi è inefficiente e poco gestibile, anche se ha grande rilevanza teorica).
Questo significa che Il cuore del dispositivo è la memoria centrale (nome rigoroso per RAM, ovvero la memoria temporanea in cui stanno i dati che devono essere elaborati). Tutte le componenti del dispositivo comunicano con la memoria centrale e con il processore. https://www.google.it/search?q=architett...on+neumann&biw=1366&bih=661&source=lnms&tbm=isch&sa=X&sqi=2&ved=0CAYQ_AUoAWoVChMIn_aVvp6pxwIVLjnbCh1X9Ay9
Anche il GBA funziona secondo questo schema. Apriamo il VBA normale e andiamo nel menu a tendona "tools" e apriamo tutto da "io viewer" a "tile viewer". Cosa è tutto questo macello? Sono le varie parti del GBA, servono per "dissezionare" il gioco e ricavarne le modifiche. Ora possiamo chiuderle tutte tranne una, il memory viewer. Essenzialmente tutte quelle finestre possono essere ricondotte al memory viewer, in quanto il contenuto di ciascuna è solo una forma comprensibile di ciò che sta nella memoria. Con il memory viewer avete accesso a tutte le macro aree della memoria del GBA (spiegate tra poco)
Come vedrete, ci sono dei buchi. Questo non significa che la memoria del GBA abbia dei buchi (è piena di tarli!) oppure sia davvero grande 09000000h, che è più di 100 MB! Semplicemente lei fisicamente sarà come sarà, ma viene "mappata" logicamente secondo tali indirizzi. Questo procedimento è un'astrazione dall'ambiente fisico, e grazie ad essa è possibile manipolare indipendentemente qualsiasi settore.
Ed ecco spiegato il motivo del mettere lo 08 al puntatore. Ogni puntatore visto fino ad ora si riferiva alla ROM, perciò si metteva per forza il byte 08. Ora sostituite il passo "metto 08 al puntatore" con "metto il numero della memoria che voglio usare".
Tutto ciò trova un'applicazione pratica: il WBTO.
Questo comando degli script permette di scrivere un byte in una locazione di memoria di quelle elencate prima.
Non si può veramente "insegnare il WBTO", a parte perchè l'ho appena fatto nel periodo precedente (si, la frase precedente è "insegnare il WBTO"), ma soprattutto perchè questo comando presuppone che ci sia uno studio dietro la sua applicazione, in modo da ottenere l'effetto ricercato. Ok, posso dirvi cosa dovrete scrivere nella memoria per ottenere qualcosa, ma allora l'insegnamento si riduce a una semplice elencazione di valori, cosa che potete trovare benissimo per il WEB (e quelli di forumcommunity ne sanno qualcosa, vero?). Qui vi spiego COME funzionano gli offset di memoria, in modo che possiate sviluppare il vostro atteggiamento critico verso la realtà (mi sembra filosofia  ) che vi porterà a fare le vostre nuove scoperte. Se poi unite questo al potente strumento che è la documentazione degli offset scoperti (cui vi consiglio di partecipare all'ampliamento) allora sarete un'arma dal grande potenziale. Tutta questa manfrina poetica per dire cosa? Per introdurre la
(BREVE) SPIEGAZIONE SU COME FUNZIONA LA MEMORIA
- 08 : La nostra ROM.
- 09 : Per accedere alla ROM dai 16 MB a 32 (il massimo) si usa questo prefisso. l'offset è quello che sarebbe con l'origine relativa in 08FFFFFF (quello che avevamo detto la scorsa volta sugli scostamenti torna molto utile).
- 07 : è una memoria piccolissima che contiene le informazioni sugli oggetti. un oggetto può essere qualunque cosa, da un people di advance map a un elemento dell'interfaccia grafica. Trovate maggiori informazioni nelle guide di andera/feanor.
- 00 : BIOS di sistema. è una cosa che tutti i computer hanno, e contiene "l'essenza della vita", ovvero, più seriamente, tutto ciò che serve a far funzionare il computer a livello basilare (del tipo accendersi, rispondere ai tasti, ecc). Non a caso l'acronimo sta per Basic Input/Output System. Noi potremo trarre vantaggio dal BIOS con l'ASM, in quanto potremo usare alcune funzioni non proprio elementari contenute in esso: ad esempio la decompressione dei dati, oppure funzioni matematiche come il seno. Già, non sembrano molto essenziali per far funzionare una macchina, ma probabilmente sono state inserite perchè di frequente uso nei giochi.
- 0E : SRAM, ovvero il salvataggio.
- 02 : WRAM, La memoria temporanea che hanno tutti i computer. Qua abbiamo la bellezza di 256 KB di RAM.
- 03 : Con questo codice ci si riferisce all'IRAM, ovvero una memoria interna (come suggerisce l'iniziale) al processore. è molto più veloce di quella normale, ma è grande solo 32 KB. Meglio non utilizzarla per i nostri scopi.
- 05 : Contiene le palette da utilizzare. contiene 16 palette per un totale di 256 colori. Non è modificabile, perchè viene costantemente aggiornata prendendo i dati dall'indirizzo 0202EEC8
- 04 : Questa locazione si chiama registri di Input/Output. è un minuscolo settore in cui ci stanno i valori interni del GBA per utilizzare le periferiche.
- 06 : VRAM. Questa è la memoria Video da 96 KB. Il suo contenuto è grezzo, per visionarla in forma comprensibile si usano il tile viewer e il map viewer. Le map essenialmente sono ciò che forma l'immagine da visualizzare: Sono dei riferimenti ai tiles. Ci possono essere fino a 4 strati, chiamati BG, in un gioco GBA. In pokemon il BG0 è utilizzato principalmente per l'interfaccia. Gli altri variano a seconda del contesto, ma durante l'overworld sono usati tutti e 3 per le varie altezze dei blocchi. Ad esempio il tetto delle case è nel BG1.
L'elemento minimo che costituisce la tilemap (quella cosa che compone il BG e si edita con cyclone e NTME) è formato da due bytes. Il primo indica il numero del tile da prendere, mentre il secondo bytes viene diviso in 2. I primi 4 bit indicano la palette scelta tra le 16 disponibili. I secondi 4 indicano la "base" dei tiles, ovvero la "pagina" di 256 tiles da scegliere; se ci pensate un attimo queste informazioni sembrano messe in ordine innaturale rispetto a come ci verrebbe da pensare; infatti vanno invertiti, sempre per la storia del little endian che se bazzicate in R&D avrete sicuramente incontrato (cercate "ordine dei byte" su Wikipedia), per cui effettivamente il GBA legge pagina, palette e numero del tile, ovvero qualcosa di più comodo per noi (dunque per chi proggettava il GBA). So che tutto questo non è un concetto molto semplice, magari ne riparleremo più avanti, con l'asm.
Ricordate comunque che per ogni esigenza di consultazione tecnica esistono i siti internet:
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm (facile)
http://problemkaputt.de/gbatek.htm (difficile)
Ora che sapete un po' meglio come funziona la mappatura della memoria, vi mancano gli offset. In questo forum io mi sto battendo per avere una raccolta ordinata di tutti gli offset, ma l'idea sembra non riscuotere successo. Comunque se volete sono qui
http://pokehack.altervista.org/showthread.php?tid=1754
http://pokehack.altervista.org/showthread.php?tid=2012
poi boh...
Altrimenti potete sempre bazzicare in altri fori e gozzovigliare un po' (e magari venire a riportarmi cosa scoprite). Io di sicuro prima o poi farò passare tutte le discussioni della macroarea apprendimento e ne coglierò ogni offset. Noiosissimo, lo so.
ecco una dettagliata spiegazione di ogni singolo freakin' registro:
Ecco ora qualche esempio di WBTO:
difficoltà facile:
hmm, non mi garba molto il colore dell'erba del percorso 101. Aspetta che chiamo il giardiniere...
Codice: #org @start
writebytetooffset 0x19 0x0202ef22
writebytetooffset 0x29 0x0202ef23
end
et voilà, ora è diventata di un bel rosso sangue!
Spiegazione: sostituisco il qattordicesimo colore della terza palette.
difficoltà media:
Recentemente sono riuscito ad implementare una feature che per l'utente non ha rilevanza, ma può tornare utile a noi sviluppattori. Si tratta di dirottare i dati delle tabelle nella RAM. Come mai fare una cosa che "a orecchio" sembra complicata? Perchè può capitare di arrivare a 255 elementi di una tabella indicizzata con un byte e dunque non poterne più inserire nessuno, a meno di avventurarsi nell'asm per cambiare il modo con cui vengono trovati gli elementi. Ma basta con le chiacchiere e passiamo ai fatti: Sono riuscito a dirottare in RAM i multichoice. Come ben sapete i multichoice sono circa 80, ma possono essere al massimo 255, perchè in XSE viene detto chiaramente che l'ID occupa un byte. E se li finiamo? Semplicemente diciamo al GBA di andare a trovare i testi in RAM, così se ne possono mettere quanti si vuole! Dovrete sacrificarne alcuni, ma ne avrete infiniti! Quanti ne servono? dipende da voi, uno per ogni numero di scelte. Significa uno per una scelta, uno per due scelte, uno per tre scelte, e così via, fino al numero che volete. Il massimo che si può fare senza corrompere il gioco è 9. gli ultimi 9 multichoice si riferiranno agli ultimi 9 puntatori dei boxset (per approfondimenti vi rimando al topic ufficiale del multichoice), i quali punteranno alla RAM. Per poter utilizzare la tecnica negli script occorrerà fare un wbto nell'area designata, con i caratteri che abbiamo visto la volta scorsa, e successivamente chiamare il multichoice.
Esempio di script funzionante (ovviamente servirebbe anche la modifica del MC da fare sulle vostre ROM):
Codice: #org @start
writebytetooffset 0xBB 0x2000000
writebytetooffset 0xFF 0x2000001
writebytetooffset 0xBC 0x2000002
writebytetooffset 0xBD 0x2000003
writebytetooffset 0xFF 0x2000004
writebytetooffset 0xBE 0x2000005
writebytetooffset 0xBF 0x2000006
writebytetooffset 0xFF 0x2000007
msgbox @string1 MSG_FACE //"PROF. BIRCH spends days in his LAB..."
multichoice 0x0 0x0 0x0 0x0
ho dovuto metere un testo se no non rimaneva fermo il riquadro. L'effetto è
http://pokehack.altervista.org/attachment.php?aid=309, non contate il fatto che ci sono solo 2 testi invece di 3, era una prova. (inoltre, finchè non sistemerò bene i testi, guardate qui per come realizzarlo: http://pokehack.altervista.org/showthread.php?tid=2795)
Spiegazione: A parte la modifica al multichoice che non è mostrata, ho semplicemente scritto del testo nella RAM, che viene letto correttamente dal programma multichoice.
compiti? Boh, non saprei, ci possono essere mille utilizzi differenti, a seconda della situazione! noi in un contesto come questo non abbiamo nemmeno delle occasioni, degli stimoli ad usarlo, in quanto operiamo (si presume) su ROM pulite, perciò non abbiamo le necessità che scaturiscono da un progetto reale. inoltre qua siamo liberi di fare ciò che ci sentiamo, senza vincoli (non come in altre lezioni). Dunque facciamo così: a scelta tra
1) o fate qualcosa di vostro con il WBTO (tipo cambio palette, operazione sui dati, ecc),
oppure
2)mi spiegate il funzionamento di uno dei "codici da inserire nelle ak rum" (sarebbero i WBTO) che trovate su forumcommunity internet.
Così avete la scelta tra un compito più pratico e uno più teorico.
Ovviamente qualcosa di facile per il momento.
Consigli: per fare il primo, pensate al vostro obiettivo, poi scovatene l'offset. come funziona l'obiettivo? Se voglio ottenere questo, cosa devo mettere?
Per fare il secondo compito cercate l'offset indicato dal comando, e andate a vedere in quale memoria (e in quale settore in alcuni casi) risiede. pensate a cosa fa tale locazione e come si comporta con il nuovo byte.
Preparatevi, le prossime lezioni saranno corpose!
Se avete dubbi come sempre non esitate a chiedere, ciao
stavolta avete tempo una settimana.
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere
FIRMA (intanto che ivan rimette lo spazio dedicato)
Guida di cui vado più fiero: Mega-Huge Bonnox' guide
Il mio nuovo motto: don't ask for ETAs!
(RIP immagine firma cancellata dai server)
"L'uomo è ancora il più straordinario dei computer"
-
citazione famosa, qualcuno di importante nella storia, forse Churchill boh
pezzo di firma prevalentemente riguardo il fangirling su Doctor who, di cui ora mi mezzo vergogno ma che alla fine per qualche motivo non riesco a cancellare, come se fossi ancorato alle origini.
In fondo contiene anche un primordiale tentativo di ravvedimento, processo che si conclude con l'introduzione del presente spoiler.
*immagine di congiunzione tra mass effect e doctor who della segretaria samantha traynor con in mano lo spazzolino sonico*
Ho un T.A.R.D.I.S. modello 40 ma non so usarlo.
Ehm, in realtà non è mio. L'ho "preso in prestito". Presa. E' una donna, già.
Vuoi fare un giro? Ovunque e Dovunque; tutto il tempo e lo spazio; ciò che è stato e che sarà. Da dove vuoi cominciare?
People assume that time is a strict progression of cause to effect, but *actually* from a non-linear, non-subjective viewpoint - it's more like a big ball made of wibbly wobbly... time-y wimey... stuff.
Prima di fare le fangirl in preda agli ormoni informatevi sulla fisica!
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
20-07-2016, 02:41 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:11 PM da Bonnox.)
lezione 3.1 1602005
# ho per il momento deciso di saltare la lezione 2-esercizi, perchè devo migliorarla, e siccome ci vuole tempo (che non ho), ho deciso di mettere questa che era quasi pronta.
.
LEZIONE 3.1
DA UN PROBLEMA ALLA SOLUZIONE:
INTRODUZIONE ALLA PROGRAMMAZIONE
Siccome questo è un argomento troppo importante per essere saltato, vi tocca. Senza di esso potreste avere varie difficoltà in seguito, perciò ho deciso di affrontarlo una volta per tutte. Inoltre è un requisito nel caso in cui voleste imparare un linguaggio di programmazione ad oggetti (come il Ruby, usato in rpg).
___
Ogni giorno ci troviamo a dover risolvere dei problemi. Ad esempio scegliere cosa fare da mangiare o montare un mobile sono alcuni dei problemi quotidiani. La maggior parte di essi sono risolti istintivamente da noi; non necessariamente nel senso che usiamo l'istinto, ma che non ci riflettiamo più di tanto perché viene automatico. mentre se il problema è più difficile (montare il mobile) dobbiamo seguire le istruzioni che ci vengono fornite. anche i computer vengono utilizzati per risolvere problemi. Una volta erano prevalentemente di tipo matematico (i primi computer erano solo enormi calcolatori), mentre oggi si utilizzano per qualsiasi scopo: esempio previsioni del tempo, controllo di una centrale atomica, realizzazione di grafica. I computer però non ragionano da soli, serve qualcuno che li "istruisca" per fare tutte queste cose utili, ovvero il programmatore. Ebbene, c'è una similitudine tra il computer e noi che montiamo un mobile: seguiamo delle istruzioni scritte da altri. Questo insieme di istruzioni viene chiamato algoritmo. Si potrebbe scendere nei dettagli sulle proprietà degli algoritmi, ma dovrei andare a riprendere gli appunti di tanti anni fa(magari posso farlo per le prossime lezioni). Perciò per il momento ci concentriamo sul capire bene come funzionano questi algoritmi. Ne incontriamo a bizzeffe ogni giorno, il mondo ne è pieno. Sostanzialmente, ad ogni problema risolvibile è possibile associare un algoritmo risolutivo. Un algoritmo è una sequenza di passi (istruzioni) da eseguire per risolvere un problema.
Ad esempio per preparare la pasta ci sono dei passi (accendi il Gas, metti l'acqua, ecc) che il cuoco esegue. Anche se può sembrare naturale, in realtà una qualsiasi azione è il frutto di ben precise "istruzioni", eseguite in sequenza dal nostro cervello.
Un altro esempio di algoritmo lo avevamo visto le volte scorse, quando vi avevo detto come ricavare un puntatore o indicizzare una tabella.
la programmazione è l'"arte" di istruire i computer. per farlo serve elaborare un algoritmo che risolve il problema. in questo corso non risolveremo problemi di tipo strano, come la costruzione di un mobile o la preparazione di una pietanza, ma agli inizi saranno prevalentemente di tipo matematico per prendere confidenza, e poi sposteremo il campo verso la piattaforma GBA.
Un esempio di problema potrebbe essere: determinare il massimo tra una serie di numeri.
adesso compirò quella "brutta cosa" che è copiare wikipedia (perchè non voglio scavare nei quaderni lol) per informarvi sulle proprietà degli algoritmi per aiutarvi a capire il tipo di procedimento necessario;
- i passi costituenti devono essere "elementari", ovvero non ulteriormente scomponibili (atomicità)
- i passi costituenti devono essere interpretabili in modo diretto e univoco dall'esecutore, sia esso umano o artificiale (non ambiguità)
- l'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di dati in ingresso (finitezza)
- l'esecuzione deve avere termine dopo un tempo finito (terminazione)
- l'esecuzione deve portare a un risultato univoco (effettività).
In generale non esiste una sola soluzione ad un dato problema; le soluzioni potrebbero essere numerose. La programmazione consiste proprio nel trovare la strada più efficiente che conduce alla soluzione del problema in oggetto. Ecco perchè programmatori diversi possono dare diverse soluzioni (magari corrispondenti a diverse visioni del problema), anche se entrambe corrette.
"Ho capito, ma come faccio a risolvere un problema?" bisogna precisare che non esiste una "ricetta" universalmente valida, ma ci sono dei paletti che definiscono in generale un percorso da seguire per semplificare l'approccio.
Per risolvere un problema innanzitutto bisogna "prenderlo" e analizzarlo. La prima cosa da fare è stabilire cosa richiede la soluzione (output) e cosa dobbiamo conoscere in principio per poter risolverlo (input). Prendo l'esempio del massimo: cosa devo fornire al programma e cosa deve "buttar fuori"? Devo inserire alcuni numeri, e devo ricevere ancora un numero (non è detto che si utilizzino sempre solo i numeri per operare, si può anche operare sul testo, sulle immagini, ecc, così come il programma potrebbe dare quelle cose come soluzione)
Poi esistono due diversi approcci, entrambi validi, per analizzare il problema e iniziare a determinare una soluzione. il secondo è sconsigliato ai Principianti.
Top-down e Bottom-up; Come suggerisce il nome, i due sono opposti.
Nel modello top-down si formula inizialmente una visione generale del sistema, ovvero se ne descrive la finalità principale senza scendere nel dettaglio delle sue parti. Ogni parte del sistema è successivamente rifinita aggiungendo maggiori dettagli della progettazione. Ogni nuova parte così ottenuta può quindi essere nuovamente rifinita, specificando ulteriori dettagli, finché la specifica completa è sufficientemente dettagliata da validare il modello. Il modello top-down è spesso progettato con l'ausilio di "scatole nere" che semplificano il riempimento ma non consentono di capirne il meccanismo elementare.
In contrasto con il modello top-down c'è la progettazione bottom-up, nella quale parti individuali del sistema sono specificate in dettaglio, e poi connesse tra loro in modo da formare componenti più grandi, a loro volta interconnesse fino a realizzare un sistema completo. Le strategie basate sul flusso informativo bottom-up sembrano potenzialmente necessarie e sufficienti, poiché basate sulla conoscenza di tutte le variabili in grado di condizionare gli elementi del sistema.
Ricapitolando le differenze ma senza scendere troppo nei dettagli tecnici, abbiamo che
La programmazione top-down è uno stile di programmazione in cui la progettazione inizia specificando parti complesse e suddividendole successivamente in parti più piccole (divide et impera). Eventualmente, i componenti sono specificati quanto basta per la codifica ed il programma viene anche scritto.
Il bottom up prende corpo dal punto di partenza (bottom) ovvero dalla situazione iniziale; considera l'obiettivo finale, induce a costruire un percorso sequenziale organizzato in passaggi successivi in cui l'ancoraggio tra traguardi intermedi e obiettivo finale è generalmente ricercato in modo intuitivo (euristico).
come compito potreste descrivermi nel linguaggio a voi più naturale (es: italiano scritto) la risoluzione di un paio di problemi. (non copiatevi)
nella lezione successiva vedremo di formalizzare le vostre soluzioni con opportuni metodi e iniziare la programmazione.
facile: dati 3 numeri, determinare il maggiore (SUGGERIMENTO: chiamate i numeri in qualche modo, come ad esempio A,B,C. vi aiuterà nello stabilire le condizioni delle "sentenze")
facile: calcola l'area di un n-agono (figura geometrica regolare con n lati) (n a scelta dell'utente) (SUGGERIMENTO: vai a rivedere le formule)
facile/medio (dipende dal livello di formalismo del linguaggio usato): fornire i primi 40 multipli di 13 (SUGGERIMENTO: dovrete contare le volte...)
medio: calcolare le soluzioni reali dell'equazione ax^2+bx+c=k (SUGGERIMENTO: torna comodo un linguaggio matematico)
(in caso non abbiate ancora affrontato l'argomento a scuola, potete saltarlo)
ciao
lezione 3.2 160215
# AS: blake finisci i compiti rimanenti
.
LEZIONE 3.2
(sarà unita alla precedente)
DIAGRAMMI DI FLUSSO
Per gli amici (impropriamente) "schemi a blocchi", i diagrammi di flusso servono per rappresentare graficamente un algoritmo (sequenza di passi elementari, con alcune proprietà già viste, da seguire per risolvere un problema).
Di norma vengono introdotti parallelamente agli algoritmi, ad essi profondamente legati, in quanto sono la loro rappresentazione in un linguaggio formale
Esistono 2 grandi tipologie di diagrammi di flusso: non strutturati e strutturati. Noi non tratteremo i primi, in quanto non di interesse per fare programmazione. Tuttavia tra i due non ci sono grosse differenze tali da implicare grossi cambiamenti nello studio e negli esercizi, ma riveste grande importanza quando bisogna applicare il risultato su un calcolatore: semplicemente, quelli non strutturati non sono riproducibili su un computer. Inoltre abituano male alla programmazione, facendo uso di tecniche errate; Perciò vi farò un favore per la vostra crescita personale, e non ve li spiegherò nemmeno.
Cominciamo
ogni schema a blocchi è composto da blocchi connessi mediante frecce. l'esecutore segue il percorso indicato dalla freccia ed esegue le istruzioni riportate all'interno dei blocchi.
ogni schema inizia e si conclude con due blocchi speciali, chiamati I (inizio) e F (fine). di norma sono rotondi (la notazione utilizzata è ininfluente, c'è chi li fa trapezoidali, molto brutti da vedere, ma bisogna mettersi d'accordo a priori).
Questo che segue è un esempio di utilizzo dei due blocchi in uno schema stupido, inutile, che non fa niente. Ma una proprietà ce l'ha: essenzialmente è la base di ogni programma: deve avere esattamente un inizio e una o più fini. (ci sono dispute teoriche altolocate che non ci interessano sulle varie proprietà algoritmiche)
http://pokehack.altervista.org/attachment.php?aid=382
introduciamo un altro blocco: il blocco operativo. questo blocco è di forma rettangolare, e viene usato per impartire istruzioni all'esecutore. Un esempio di istruzioni può essere "accendi il gas", "metti il bullone X nel foro Y del pianale", ecc. Devono perciò essere interpretabili ed eseguibili dal lettore. Noi purtroppo però ci occuperemo soltanto di problemi matematici, che sono quelli che rappresentabili meglio con gli schemi a blocchi. Un concetto importantissimo per questo blocco sono le variabili: per farla semplice, si tratta di una sorta di "contenitori" nella memoria del computer, che possiamo usare come vogliamo per conservare le informazioni (temporanee) che ci servono.
Ad esempio, se mi chiedono di contare fino a 100, inizio dicendo "1", "2", "3" .... ovvero sto usando un po' della mia memoria a breve termine per conservare l'informazione del numero cui sono arrivato a contare.
Ma ciancio alle bande, ecco un piccolo esempio di blocco di istruzioni quadrato.
http://pokehack.altervista.org/attachment.php?aid=383
come potete intuire, questi blocchi in serie sono le istruzioni per calcolare l'area di un trapezio! Abbiamo assegnato a 3 variabili B, b e h i valori base maggiore, base minore e altezza, che poi abbiamo usato nel calcolo dell'area. notare che ho omesso il verso delle frecce, in quanto ovvio (verso il basso).
tutti quei quadrati in serie si dice che formano una struttura di sequenza.
La sequenza è un insieme di blocchi contigui di tipo operativo.
http://pokehack.altervista.org/attachment.php?aid=384
qui vedete come un insieme di rettangoli possa essere schematizzato in un solo grande rettangolo, in quanto la loro natura è la medesima. ma attenzione, non significa che spariscano, semplicemente facciamo uno "zoom-out" di un livello di generalizzazione, e i dettagli implementativi si perdono. potremmo sostituire i puntini con un generico "Area_Trapezio", nome che racchiude in sè tutti e soli i comandi scritti a sinistra.
Gli schemi a blocchi strutturati si compongono soltanto di strutture. ogni struttura è una generalizzazione di blocchi dello stesso tipo. ad esempio, poco sopra, abbiamo visto la sequenza. ne rimangono 2.
Un altro tipo di blocco è il parallelogramma: dentro di esso si mettono gli input/output, ovvero le cose che l'utente scrive (immette nel calcolatore) o il computer gli dice (verso opposto).
è talmente banale che unirò l'esempio con quelli successivi.
Il nuovo tipo di blocco per questo paragrafo è il rombo: esso permette di fare delle scelte. se durante la nostra soluzione del problema dobbiamo fare cose diverse in base alle circostanze, useremo il blocco rombo. al suo interno si mette una condizione[i] che dovrà essere [i]valutata. se è vera, si prenderà la strada del Vero, se è falsa si prenderà la strada del Falso.
esempietto:
http://pokehack.altervista.org/attachment.php?aid=387
Analizziamo questo nuovo schema, che ci propone molto spunti di riflessione.
Innanzitutto diciamo quale sia il suo scopo generale. Serve per dimostrare l'uso dei blocchi di input /output: chiede una frase (la password), la riceve, la confronta e a seconda che sia Uguale o meno a quella desiderata fa cose diverse.
Vi invito a notare le " che circondano la frase. I computer sono esseri molto precisi, non amano le cose pressappoco. Perciò dovete specificare esattamente ciò che deve essere scritto, e la maggior parte dei linguaggi usa proprio ". Poi vediamo questo "accesso", ma cos'è? È anche lui una variabile, ma il suo cassetto (nella distesa di armadi che rappresenta la RAM) è piccolo, perciò non è adatto a contenere interi o reali (i tipi che abbiamo utilizzato nel trapezio), ma ha posto solo per un particolare tipo di valore, che può assumere soltanto due stati: vero o falso (come un interruttore, una bandierina del guardalinee, una flag nello scripting - actually è la flag che deriva da qui). Questo tipo di valore si chiama booleano, da George Boole, un matematico che ha fatto... Cose Che non ci interessano per il momento. Inoltre è possibile avere variabili che conservano i singoli caratteri (comunemente rappresentanti da un byte); o anche frasi intere, come quella del disegno: il tipo di queste variabili si chiama Stringa. Una stringa è un insieme contiguo di caratteri terminata da un byte con valore particolare. Generalmente in informatica le stringhe sono null-terminated, ovvero finiscono per 0x00, mentre quei geniacci della game freak, come saprete, hanno sovvertito l'ordine naturale delle cose, perciò le loro stringhe sono FF-terminated.
Successivamente c'è la parte più importante dell'esempio, ovvero la scelta. Ciò che sta dentro il rombo deve necessariamente poter essere valutato come vero o falso. E poi l'esecuzione continuerà nel ramo corrispondente. Non è necessario avere sempre entrambi i rami, il tutto dipende dalla necessità. Notare nuovamente le ", in quanto una stringa (frase) deve essere precisamente delimitata, altrimenti come possiamo confrontare una cosa non ben definita? (negazione di una proprietà degli algoritmi)
Altra cosa molto importante è il simbolo "==", non fatevi spaventare, non è niente di oscuro. Semplicemente significa "Uguale". E allora perché non usiamo il classico "="? Perché quest'ultimo in realtà non significa "Uguale", anche se con l'abitudine si dice ormai così; in realtà significa "assegno alla variabile a sinistra il valore a destra". E siccome non possono esserci due operatori identici (come si distinguerebbero?), è stato inventato quello. In realtà si potrebbe anche utilizzare "=", ma solo se prima ci si è messi d'accordo che soltanto dentro il rombo "=" significa "uguaglianza" (operatore logico) e non "assegnamento" (istruzione).
Finite le operazioni da eseguire durante la selezione (questo il nome formale della struttura di scelta), si ritorna allo stesso punto di prima, solo un passo dopo. Notate come le frecce convergano nello stesso punto, in linea con l'apertura del rombo, e da cui le frecce diventano una sola che Prosegue nel programma.
Eseguiamo ancora una volta l'operazione di zoom out, e vediamo gli elementi principali che costituiscono il programma.
http://pokehack.altervista.org/attachment.php?aid=388
Abbiamo una struttura sequenza seguita da una selezione, che ovviamente porta ad altre sotto sequenze.
Abbiamo visto due strutture che hanno il loro blocco caratteristico (sequenza e selezione), e un blocco che non ha una sua struttura personale (parallelogramma, anche se è possibile farlo rientrare nella sequenza). Quale combinazione manca? La terza struttura fondamentale che non ha il suo blocco!
L'ultima struttura infatti non introduce un nuovo blocco, ma fa uso di tutti i tipi di blocchi visti finora, ed è forse la più potente per quanto riguarda la risoluzione dei problemi. Prima di gettarsi nelle definizioni, considerate questo esempio.
Devo sommare Tra loro i numeri dispari da 1 a 10. Posso benissimo fare tanti cubetti in cui assegno una variabile e la sommo. Oppure posso usare una Strada più comoda. Infatti, se i numeri da sommare fossero stati 100 o anche 1000, non avremmo più finito di scrivere a mano tutti i numeri. Dunque ci serve un modo per ripetere le stesse operazioni più e più volte. Dobbiamo trovare un modo di evitare le ripetizioni. Ebbene questo esiste e si chiama ciclo, realizzato tramite la struttura dell' iterazione. Non ha niente di difficile, basta stare attenti a come è fatta.
si compone di:
- la condizione di permanenza nel ciclo
- il corpo delle istruzioni
- il rimando ad un altro punto del diagramma
sembra strano? In realtà noi la applichiamo tutti i giorni, inconsapevolmente!
Perdonatemi questo esempio. Quando preparate la pasta seguite varie istruzioni: mettete l'acqua, mettete il sale, ecc, una normale sequenza. Poi però dovrete aspettare che la pasta sia cotta. Allora dopo un po' assaggiate. se è pronta, proseguite, altrimenti tornate indietro e rifate i passaggi.
identifichiamo le componenti:
- condizione di permanenza: la pasta è cotta?
- corpo delle istruzioni: aspetta; assaggia.
- rimando: se non è cotta, rifai le azioni
ed ecco finalmente come si presenta una risoluzione con ciclo (due possibilità diverse ma equivalenti):
http://pokehack.altervista.org/attachment.php?aid=389
(il "i è dispari" lo guarderemo più avanti)
sono possibili 2 metodi risolutivi, a seconda di quando viene valutata la condizione di permanenza, se all'inizio o alla fine del ciclo. La differenza è che nel primo le istruzioni vengono eseguite almeno una volta, mentre nell'altro questo comportamento non è garantito a priori. Sta al programmatore scegliere di volta in volta la struttura più adatta.
abbiamo quasi finito, mancano un paio di precisazioni. Abbiamo usato le frecce per indicare le direzioni da seguire. ciò non significa che possiamo andare dove vogliamo: ogni struttura ha le sue regole di funzionamento, e soprattutto, cosa più importante, non si può uscire dalla struttura in cui si è. Ecco perchè vi ho stufato tanto prima (e lo farò ancora un'ultima volta) indicandovi le zone di competenza di ciascuna. Ad esempio quella che è più comune sbagliare è l'iterazione. La freccia può, nel primo caso (controllo alla fine), entrare soltanto nella sequenza precedente (se non esiste una sequenza se ne fa una fittizia "nulla", ovvero di dimensione 0), non inserirsi in altre strutture! mentre per il secondo tipo di iterazione (controllo all'inizio), la freccia può solo tornare al rombo della condizione di permanenza.
è anche possibile, qualora si renda necessario, utilizzare più strutture dentro altre: questo processo si chiama annidamento; e in effetti l'ho usato nell'ultimo disegno: ho messo un rombo dentro un altro rombo. questa cosa si può fare anche all'infinito, finchè non viola le proprietà degli algoritmi.
ed ecco infine la tabella riassuntiva
http://pokehack.altervista.org/attachment.php?aid=390
per concludere veramente, vi dico che il teorema di jacopini-bohm dice che ogni problema può essere risolto soltanto con l'uso di sequenza, selezione e iterazione, perciò mettetevi tranquilli e pensate ad un modo per risolvere il problema, che ci sarà sicuramente, e non fate dipanare frecce ovunque intorno all'universo.
Per il momento metabolizzate bene questo, che non è poca roba, la prossima volta vedremo qualche esercizio! (potete però cominciare già a pensare a qualche algoritmo per allenarvi, nel buio della vostra cameretta)
ci vediamo
esercizi 3.1 160217
ESERCIZI 3.1
facciamo qualche esercizio!^^
teoria necessaria per svolgere al meglio gli esercizi:
- Funzioni
è un particolare costrutto sintattico, in qualche linguaggio di programmazione, che permette di raggruppare, all'interno di programma, una sequenza di istruzioni in un unico blocco di istruzioni espletando così una determinata e in generale più complessa operazione, azione o elaborazione sui dati del programma stesso in modo tale che a partire da determinati input restituisca determinati output.
(grazie wikipedia, scusate ma non sarei riuscito ad esprimerlo così bene con parole mie)
in alcuni linguaggi le funzioni assumono nomi diversi
(se siete interessati...)
in pascal le funzioni senza valore di ritorno si chiamano procedure
in assembly si chiamano routine
nei linguaggi ad oggetti si chiamano metodi
"i è dispari" (o pari non ricordo) dell'altra volta era una funzione che ritornava o VERO o FALSO. le funzioni si usano anche per scrivere di meno, in quanto raggruppano molte istruzioni in una sola.
- Valore di ritorno
quando una funzione termina, restituisce un valore al blocco invocante. Questo può essere di qualunque tipo di dato, ovvero intero, reale, booleano, intero corto, intero lungo, carattere, e anche quelli definiti da voi. tuttavia questo comportamento non è obbligatorio, se il contesto non lo richiede. dopotutto, se avete fatto matematica a livelli non bassi (diciamo che una seconda superiore va bene), avrete visto le funzioni, come relazioni che associano agli elementi di un insieme, al più un elemento di un altro insieme. Lo stesso in informatica.
ciò che nella lezione precedente abbiamo racchiuso in un unico blocco più grosso potrebbe benissimo essere racchiuso in una funzione; riconducendoci agli esempi, "area_trapezio" e "is_odd_number" sono anch'esse funzioni; la prima non ritorna nulla (si dice che è di tipo void) la seconda ritorna un booleano
- Vettori (array in inglese)
la definizione è molto semplice, ma sono uno strumento importantissimo: un vettore è una sequenza di dati dello stesso tipo in memoria.
(con sequenza intendo elementi contigui, tenetelo bene a mente)
ad esempio una stringa di testo è un vettore di tipo carattere:
"Ciao mondo" è rappresentato in memoria:
[...] [C] [i,] [a] [o] [ ] [m] [o] [n] [d] [o] [...]
(la i è brutta perchè ho dovuto ingannare il formattatore, altrimenti me la considerava italic)
i puntini all'inizio e alla fine sono quella notazione in grammatica per dire "c'è dell'altro".
questa è la rappresentazione generica di un vettore:
![[Immagine: Array+in+Java+Comparision.gif]](http://2.bp.blogspot.com/-v-dkON4gwhQ/U4cw77VA-2I/AAAAAAAABkI/RL1x8PGgt-U/s1600/Array+in+Java+Comparision.gif)
un elemento di un vettore può contenere a sua volta un vettore. in Questo caso prende il nome di matrice. un esempio di matrice è una mappa di tiles, in cui le "colonne" sono elementi delle "righe" (o viceversa a seconda dell'implementazione)
realizzazione:
![[Immagine: array-2d.png]](http://ycpcs.github.io/cs201-summer2014/notes/figures/array-2d.png)
e considerando una matrice 3x3, ogni elemento è:
![[Immagine: Image377.gif]](http://www.math.it/formulario/images/determinanti/Image377.gif)
abbiamo finito per ora! ~
in questi esercizi simulerò i passaggi risolutivi che uno dovrebbe seguire.
sono 5 esercizi sugli algoritmi (schemi a blocchi) perchè non posso allegare più immagini di così.
Per i disegni così belli ho usato un programma chiamato Algobuild
1) dato un numero, stampa (o ritorna) il fattoriale
il fattoriale di un mumero è il prodotto dei numeri da 1 al numero stesso.
ad esempio, se il numero è 5, il fattoriale è 5*4*3*2*1=120
input: un numero
output: un numero
strategia risolutiva: dobbiamo avere un valore temporaneo che sarà il risultato
dobbiamo anche moltiplicare il risultato delle moltiplicazioni precedenti per qualcosa di nuovo; ci fermeremo quando il fattore raggiunge 1.
http://pokehack.altervista.org/attachment.php?aid=393
2) dati n numeri (uno alla volta), calcolare la media
input:
- un numero che indicala quantità di numeri da processare
- tanti numeri (da processare uno alla volta)
output
la media di tutti
strategia risolutiva: ogni volta che l'utente inserisce un numero,dovremo aggiornare la somma. calcoleremo la media alla fine dell'inserimento (totale/numero di elementi)
http://pokehack.altervista.org/attachment.php?aid=395
3) soluzione equazione di secondo grado
un'equazione del tipo ax^2+bx+c=0 ha soluzione
x1= -b+sqrt(b^2-4*a*c))/2*a
x2= -b+sqrt(b^2-4*a*c))/2*a
chiederemo i coefficienti a, b, c e verificheremo che il discriminante non sia negativo (non si può fare la radice quadrata di un numero negativo! :p), poi applicheremo la formula
http://pokehack.altervista.org/attachment.php?aid=396
4) data una stringa, invertirla
input: un vettore
output: un vettore
strategia risolutiva: inizio a riempire il nuovo vettore partendo dall'ultima posizione
dell'altro
http://pokehack.altervista.org/attachment.php?aid=397
5) dato un vettore, calcolare la moda (il valore più ricorrente)
input: un vettore
output: un numero
strategia risolutiva:
creo una tabella (detta matrice, ovvero un vettore di vettori) in cui memorizzo ogni valore e le sue occorrenze. scorro il vettore dato e "popolo" la tabella. ogni volta che trovo un valore lo aggiungo al contatore. alla fine scorro l'intera tabella per trovare il valore con più occorrenze.
la tabella è grande esattamente quanto il vettore (x2 ovviamente), e non è il massimo dell'ottimizzazione.
si potrebbe fare in varie altre maniere, di cui sicuramente una meno esosa di risorse, ma al momento non ho tempo per pensarci troppo :p
http://pokehack.altervista.org/attachment.php?aid=398
(scusate se ci sono un paio di piccoli errori nel disegno, ma sinceramente non ho voglia di rifare tutto)
ora, compiti (per il momento chiedo di mandarli via MP per evitare che i furbi copino)! ~
avete max 10/12 giorni di tempo
- dato un numero, stabilire se è pari o dispari
suggerimento: un numero è pari quando è divisibile per 2. cosa vuol dire essere divisibile per due?
per fare questo ci sono almeno 3 possibili strade (proprietà degli algoritmi)
- dati 2 vettori, produrne un terzo con la loro somma (somma "termine a termine" delle componenti)
- dati 2 vettori, concatenarli ("attaccarli")
suggerimento: creare un nuovo vettore, ovviamente più grande, in cui si mettono gli altri
- dati n numeri inseriti dall'utente n anche scelto dall'utente), stabilire il maggiore
- dati i 3 lati di un triangolo, classificarlo (scaleno, isoscele, equilatero)
suggerimento: bisogna sapere come sono i lati tra di loro (in lunghezza)
e per oggi è utto!
la prossima volta, finalmente ASM!
lezione 4 160223
.
LEZIONE 4
ASM
#integrare con jpan
Eccoci alla parte che forse vi interessa maggiormente! Se avete capito bene l'ultima lezione non dovreste avere grossi problemi.
Spesso abbreviato in ASM, è quanto di più vicino al linguaggio macchina l'uomo possa comprendere senza diventare pazzo. Infatti il linguaggio macchina è fatto dai cosiddetti codici operativi, ovvero dei byte che vengono letti dal processore, ed ognuno ha un preciso significato come istruzione. La sua particolarità rispetto agli altri linguaggi di programmazione è che c'è una corrispondenza 1:1 tra istruzioni scritte e istruzioni reali della macchina. Significa che per ogni istruzione scritta/letta da noi esiste un singolo codice operativo, e questa cosa si esprime dicendo che "esiste una sostituzione mnemonica tra istruzione della macchina e parola chiave del linguaggio" L'assembli infatti è stato inventato per risparmiare la fatica di programmare i calcolatori inserendo nella loro memoria direttamente il codice macchina, costituito da zeri e uni (potete vederli nelle guide linkate all'inizio). #spiegare meglio, aggiustare la frase, introdurre i primi calcolatori elettronici
L'assembly, come avrete intuito, è un linguaggio a basso livello, per cui non è dotato di tutti i meccanismi di sicurezza che di solito abbiamo con la programmazione. Siamo solo noi e l'hardware. In altre parole, siamo i padroni totali, ma dobbiamo anche prenderne le responsabilità (come dicevano in un film).
Prima però bisogna capire come funziona il processore.
Esso è responsabile dell'esecuzione fisica del gioco, svolge i calcoli necessari e controlla le periferiche (tutta roba trovabile su wikipedia).
La CPU è composta da varie parti; a grandi linee troviamo l'ALU, unità che esegue le operazioni via hardware (i circuiti elettronici elaborano i byte), la CU, unità di controllo, e i BUS (collegamenti elettrici) che trasferiscono i dati. Esiste poi un minuscolo settore di memoria che è sufficiente a contenere giusto i dati che servono per la corrente operazione. Tale spazio prende il nome di registri (da non confondere con i registri I/O tipici del GBA). I registri possono essere paragonati a delle variabili, ovvero dei contenitori di informazioni. Pensate ad una tazza piena di riso: noi possiamo mettere dentro tutti i chicchi di riso che vogliamo, ovviamente finchè non tracima, oppure possiamo svuotarne il contenuto, o anche solo contare quanti chicchi contiene in un certo momento (perdonatemi il brutto esempio, copiato da qualcuno su internet). I registri del GBA sono lunghi 32 bit, ovvero possono contenere dati fino a FFFFFFFFh, da cui si suol dire che il GBA è una macchina a 32 bit (come i computer fino a qualche anno fa).
Il processore funziona secondo uno schema fisso sempre uguale: - reperimento delle istruzioni (fetch)
- decodifica delle istruzioni (decode)
- esecuzione delle istruzioni (execute)
Questo processo si chiama pipeline, termine con cui si identificano le condutture petrolifere, proprio perchè il processo (scusate la ripetizione) è costante come il flusso di liquido. Le fasi vengono tutte svolte tramite dei circuiti dedicati ad ogni singolo compito, residenti un po' ovunque nella console (per la prima fase intervengono i bus sulla scheda madre e sulla cartuccia di gioco, le alte due invece vengono eseguite all'interno del processore). Questa pipeline a 3 stadi è tra le più semplici, e ad ogni istante ci sono 3 differenti istruzioni che stanno subendo un passo diverso tra quelli possibili (ovviamente in ordine). La più semplice ovviamente è quella che fa le operazioni una alla volta. Giusto per curiosità, i processori desktop hanno pipeline con addirittura decine di passi! (il pentium 4 una quarantina, perchè doveva essere il più veloce processore single core)
Prima di tuffarci a capofitto nelle istruzioni, bisogna spendere ancora qualche parola sullo specifico processore con cui lavoreremo: l'ARM7TDMI.
Il processore del GBA adotta l'architettura RISC, dunque è piuttosto semplice. RISC vuol dire Reduced Instruction Set Computer, ovvero elaboratore con set di istruzioni ridotto; modello che si contrappone ai CISC (Complex Instruction Set Computer), di uso tipico nei computer. L'e due architetture sono opposte; la seconda presenta molte istruzioni elementari utilizzabili, mentre la prima, per ridurre la complessità in ambienti critici, come una console portatile, offre soltanto lo stretto indispensabile in termini di operazioni effettuabili a livello di codice macchina. Ma proprio questo gli conferisce consumi energetici ridotti (io a volte arrivavo a 10 ore col GBA!!! [emoji15]); è anche stato usato in diversi vecchi dispositivi come l'ipod touch 1G.
Semplice fino a un certo punto; ci sono comunque un sacco di aspetti da tenere conto, anche tralasciando la realizzazione fisica (per quello c'è il noiosissimo libro facoltativo linkato all'inizio, ne sconsiglio vivamente la lettura se non siete bravi in elettronica (io tre quarti delle cose manco le so leggere asd)).
REGISTRI:
- R0-R12: registri general purpose, possono essere usati per contenere qualunque dato
- R13: Stack Pointer. usato per tenere traccia dell'ultima posozione dello stack
- R14: Link Register, contiene l'indirizzo di ritorno della funzione
- R15: Program counter, indica la prossima istruzione da fetchare.
- CPSR: Current Program Status Register è il nome del PSW, un registro interno che raccoglie informazioni come lo stato dell'ultima operazione.
#spiegare bene cosa sono SP e LR nella prossima revisione
parte tradotta direttamente dalla documentazione:
L'ARM7TDMI ha due "modalità operative", ovvero può lavorare con due diversi set di istruzioni
- ARM, set di istruzioni a 32 bit
- Thumb, set di istruzioni a 16 bit
Il set thumb è un sotto-set dell'ARM, ogni sua istruzione ha una corrispondenza nel set esteso, che svolge lo stesso compito. La cosa forte è che entrambe le modalità condividono gli stessi registri, permettendo una forte collaborazione tra le due, consentendo di ottimizzare sia lo spazio occupato sia le prestazioni.
Infatti durante l'esecuzione, ogni istruzione a 16 bit viene "decompressa" nel suo equivalente a 32 bit, permettendo di sfruttare appieno le capacità della macchina.
Thumb ha tutti i vantaggi di un "cuore" a 32 bit:
- indirizzamento a 32 bit (significa che potrete trattare memoria fino a 4 GB, ma siccome come sapete il GBA si ferma a 0E-000000, avrete comunque tutto il range disponibile)
- registri a 32 bit
- operazioni a 32 bit
- trasferimento di memoria a 32 bit
il codice thumb occupa tipicamente il 65% del corrispettivo ARM, e fornisce il 160% delle prestazioni, se letto da una memoria a 16 bit. La ROM guarda caso ha un sistema di trasferimento a 16 bit, ecco spiegato il motivo per cui i giochi sono principalmente compilati in questa modalità. Tuttavia, se eseguito in uno spazio a 32 bit (ad esempio dalla RAM), la superiorità del codice thumb scema. Infatti sono fatte in ARM e residenti in RAM le routine di gestione degli interrupt, che noi non vedremo.
Il core del processore usa il primo bit del program counter per determinare cosa mettere in un altro registro interno, che serve per stabilire il set di istruzioni da usare (ecco spiegato l'arcano mistero del +1 nel callasm  ).
Il processore supporta sia la modalità di storage dei dati big endian che little endian.
ma siccome devono complicarci le cose (-.-") il default è little endian, in quanto di più veloce processamento (ha a che fare con la realizazione fisica dei circuiti dediti ai calcoli).
I precedenti termini si riferiscono a come le informazioni vengono scritte nella memoria. Big endian memorizza le informazioni a partire dal MSB (most significant bit), mentre little endian dal LSB (least significant bit).
Durante la modalità thumb, i registri alti (8-15) non sono immediatamente accessibili con le operazioni elementari. Se non possiamo farne a meno come deposito temporaneo di informazioni, possiamo usare alcune istruzioni per copiarvi il contenuto dei registri bassi (0-7), o anche copiare il loro contenuto nei registri bassi, ovvero nell'altro senso.
ogni istruzione può essere eseguita condizionalmente in modalità ARM, mentre l'unica istruzione condizionale in modalità thumb è il salto.
fine parte tradotta
Dopo questa estenuante introduzione penso che siamo pronti per vedere i veri comandi! ~
NOTA: non vi insegnerò la sintassi, a parte un caso che vedremo, perchè è noiosa e fine a se stessa, e potete trovarla nella documentazione. Reputo molto più istruttivo prima comprendere bene effettivamente cosa fanno i vari comandi.
ISTRUZIONI ARITMETICHE- ADD/MUL/SUB
operazioni matematiche come somma, moltiplicazione, sottrazione.
di solito si scrive il comando seguito da 3 registri: registro destinazione del risultato, registro operando 1, registro operando 2. oppure si usa un immediato (un piccolo valore scritto direttamente nel codice, senza dover sprecare un registro)
ISTRUZIONI LOGICHE- AND fa l'and bit a bit di due registri #spiegare
- EOR fa l'Esclusive Or (XOR) dei bit di due registri #spiegare
- LSL/LSR serve per shiftare i bytes a destra o a sinistra. approfondimento sullo shift:
questa operazione è utile quando si vuole moltiplicare per potenze di 2. infatti si può moltiplicare di 2^n un numero spostando verso sinistra n volte i bytes. Per dividere shiftiamo verso destra.
esempio:
5d
0101b
shiftiamo di 1
1010b
10d
esempio
50d
110010b
shiftiamo di 1
011001b
25d
# revisione ^
- NEG nega il contenuto di un registro, bit per bit, ma attenzione, farà "0-valore", dunque il risultato sarà avanti di 1 rispetto a quello che ci aspetteremmo!
- ORR fa l'or dei registri, bit a bit. #spiegare
ISTRUZIONI PER IL CONTROLLO DEL FLUSSO- B/BL/BX servono per eseguire dei salti nel codice. I salti permettono di alterare il normale flusso di esecuzione del programma, ma per routine semplici non sono necessari. Di solito si usano quando si testa una condizione e si vuole un comportamento diverso a seconda dei casi. Se avete capito bene i goto negli script, non avrete problemi. La differenza tra i tre è che B salta e basta, BL salta e copia il PC nel LR per un facile ritorno, BX salta e cambia modo operativo, a seconda dell'ultimo bit del valore.
E' possibile aggiungere delle condizioni all'istruzione B.-
B + qualcosa significa salta se:
- EQ equal
- NE not equal
- CS Carry Set
- CC Carry clear
- HS unsigned higer or same
- LO Unsigned Lower
- MI Minus/negative
- PL Plus/Positive or Zero
- VS Overflow
- VC No Overflow
- HI unsigned higher
- LS Unsigned Lower or Same
- GE Signed Greater Than or Equal
- LT Less than
- GT Signed Greater than
- LE Signed less than or equal
- GE Greater than or equal
- AL Always
- NE Never
#spiegare alcuni, tradure, c2
notiamo che gli ultimi 2 sono praticamente inutili.
I salti condizionali sono molto usati con l'istruzione CMP.
le varianti condizionali si basano sul CPSR, perciò sono utili solamente se seguono un'istruzione CMP. potreste comunque usarle quando volete (come ogni istruzione del resto), ma non avrebbe molto senso.
- BKPT breakpoint, serve per interrompere l'esecuzione del programma a scopi di debugging.
- CMP paragona. può paragonare un registro ad un byte, o 2 registri tra loro e mette il risultato nel PSW (CPSR), subito dopo sarebbe utile eseguire un salto. altrimenti è un'operazione sprecata. Questo è l'unico modo di eseguire istruzioni condizionali in modalità thumb
ISTRUZIONI PER OPERAZIONI SULLA MEMORIA
(#cancellare: prima era miste)
- LDR/LDRB/LDRH/MOV Serve per caricare un registro con dei dati. Esistono varie opzioni, come un valore immediato; un valore letto dall'indirizzamento indiretto; un valore ottenuto mediante operazioni, ecc. La differenza sostanziale tra i tre sta in cosa caricano: LDR 32 bit, LDRH 16 bit (H sta per Half) , LDRB 8 bit (B sta per Byte). MOV invece inizializza un registro con un byte presente nelostesso codice operativo.
- STR/STRB/STRH Questi invece fanno l'operazione inversa del LDR, ovvero "stoccano" (da store) il dato da qualche parte. Anche qui Vi sono molte opzioni, ma è meglio visionarle sulla guida, in quanto in questa sede appesantirebbe la lettura.
- POP/PUSH servono all'inizio e alla fine della nostra funzione ASM (non in tutti i casi, solo nelle sotto-funzioni - dunque praticamente sempre) per accatastare sulla pila i contenuti dei registri che ci serviranno per compiere le operazioni. E' buona cosa ricordarsi di andare a riprendere le informazioni e rimetterle alloro posto una volta terminata la routine.
E' importante ricordare che per iniziare una sotto-funzione (quelle trattate in questa guida) su usa PUSH LR (più eventuali registri usati) e per terminarla si deve fare POP PC. Questo perchè quando eseguiamo un salto il Link Register assume il valore dell'offset dell'istruzione successiva a quella del salto. ovvero, per chi usa un IDE, "step over". ovvero, per i comuni umani, considera la funzione chiamata dal salto come una singola istruzione, e dunque l'istruzione seguente non è la prima che si incontra dopo aver seguito il salto, ma quella effettivamente successiva nel file (rimane allo stesso livello di profondità delle sotto-funzioni). Una volta accantonato il LR e compiuta la routine, dobbiamo tornare indietro. Come? Facile. Poppando (ok, doppiosenso, scusate) il LR otteniamo il punto dove continua la nostra ROM, ma per andarci dobbiamo metterlo nel Program Counter!
#da qualche parte metttere endianess
vi è andata bene che non vi do compiti, prossima volta esercizi, vediamo qualcosa in azione!
#revisionare tutto
esercizi 4 160226
spero di non avervi disturbato e che non vi dispiaccia se ho deciso di fondere le aule, è per una gestione meno incasinata! (avere altro disordine è l'ultima cosa che voglio)
questa lexione va in onda in edizione ridottaa causa della grande richiesta che ne ha accorciato i tempi di sviluppo! perciò avrete un paio di esempi in meno (posso passarveli comunque quando saranno pronti), ma alla fine per quelli bravi come voi non è che facessero una grande differenza.
ESERCIZI 4
ASM BASE
in questa sede trasporremo in ASM gli algoritmi visti nelle precedenti lezioni, con lo scopo di abituarci alla sintassi ^^
ho preso alcuni degli esercizi della volta scorsa, in modo da poter riflettere sulle differenze, più alcuni presi da internet sul C, o inventati da me ^^
innanzitutto se avete dei dubbi sulla sintassi consultate pure il PDF che vi ho fato scaricare all'inizio.
esso ha 3 aree: una zona in cui viene presentato il comando in modo molto sintetico, una che illustra la sintassi di ogni variante di ogni comando, e una che mostra come sono fisicamente realizzati gli opcodes. Ora vi esporrò brevemente i punti salienti della sintassi.
(NB: per alleggerire la grafica della pagina non ho quasi mai usato i tag quote o code, ma ho lasciato una riga vuota prima e dopo ogni blocco che ne avrebbe fatto uso)
- [RX] indica di indirizzare l'operazione all'offset di memoria contenuto nel registro.
dunque, l'istruzione
LDR RX, [RY]
caricherà in RX i 4 byte presenti all'indirizzo di memoria contenuto in RY.
[RX, RY]
oppure
[RX, #valore]
significa indirizzare l'operazione all'indirizzo contenuto da RX + RY (o valore)
.
- le etichette servono per distinguere parti di programma, come le funzioni, e servono come destinazione dei salti. per dichiarare un'etichetta basta metterne il nome seguito da due punti, così:
main:
.
- quando iniziate una routine ricordatevi SEMPRE di allinearla. per farlo si usa:
.align X, 0xY, 0xZ
questa è una direttiva al compilatore, ovvero delle istruzioni che noi gli diamo per informarlo di qualcosa prima di procedere a compilare. le direttive iniziano con il punto. in particolare align indica di allineare il compilato a partire da 2^X byte, riempiendo lo spazio intermedio con il byte Y, fino ad un massimo di Z byte, altrimenti il processo verrà saltato. gli ultimi due parametri sono opzionali.
#mostrare esempio sulfile vero, anche ascii
L'align è anche usato sui dati, in quanto se non fossero allineati (specialmente le strutture), sarebbe un casino assicurato nella gestione della memoria. Inoltre alcuni opcodes, se avete letto la documentazione, hanno un offset di reperimento delle informazioni che va a blocchi di 4 byte.
Dunque la pratica, abbastanza diffusa qua da noi, di usare
LDR RX, .pointer
[...]
.align 2
.pointer:
.word 0xqualcosa
nasce dal fatto che l'istruzione LDR ha nei suoi campi (a livello fisico) un valore che indica "quante word in là" andare a prendere il dato. (ricordando che una word è lunga 4 bytes, e 2^2 fa 4)
tuttavia questa pratica ha uno o due elementi non completamente corretti.
innanzitutto si sta usando le direttive come semplici etichette, e questo potrebbe dare problemi in compilazione.
dunque potreste sostituire con
LDR RX, valore
[...]
.align 2
valore: .word 0xqualcosa
se proprio non voleste niente sotto, un'altra soluzione è
LDR RX, =0xqualcosa
in questo modo caricherete subito il valore.
oppure potreste anche fare di meglio. quest'ultimo metodo è parecchio scomodo, in quanto incline agli errori e non centralizzato (se usate un valore molte volte e ad un tratto lo volete sostituire, dovrete cercarlo per tutto il sorgente).
leggendo la guida dell'assemblatoreho scoperto questa nuova direttiva chiamata "equ". svolge un compito simile al #define del C, ovvero sostituisce tutte le occorrenze di un valore nel testo, gestendo automaticamente la questione degli allineamenti. in questo modo scriverete una sola volta il valore, ma potrete usarlo sempre, unendo così i vantaggi dei due metodi (centralizzazione del valore e praticità). ecco un esempio:
.equ alias, 0xqualcosa
LDR RX, =alias
dove alias è una qualunque parola inventata da noi. la direttiva può essere inserita ovunque nel sorgente, perciò prestate attenzione, anche se vi potrebbe sembrare un vantaggio, in realtà contribuisce a rendere meno leggibile il codice. Sarà bene adottare un proprio stile, ovvero decidere se mettere tutte le dichiarazioni di costanti all'inizio o alla fine del file (personalmente ritengo che dichiarare una costante al momento dell'uso renda poco leggibile il codice).
un'altra direttiva è .include, che unisce un file in quello corrente, a compile-time:
supponete di aver creato un file con delle funzioni che usate spesso. potrete "includere" il file nel vostro nuovo sorgente (di solito i file di sorgente assembly si chiamano *.ASM o *.S ) in modo da poterle usare senza doverle riscrivere. è una tecnica molto comoda, in quanto consente di risparmiare tempo. la sintassi è questa:
.include "path"
dove path è il percorso al vostro file. le virgolette vanno messe.
.
- per inserire un immediato, si usa #
un immediato è un valore da usare nell'operazione, inserito nell'istruzione stessa, al posto di usare un registro. in genere se avete valori, conosciuti prima dell'esecuzione, inferiori o uguali a 255 si possono tranquillamente mettere come immediati.
esempio:
MOV R1, #0
.
- potete inserire un commento con la chiocciola, e quel'intera riga, a partire dal carattere chiocciola, non verrà considerata durante la compilazione. esempio:
LDR R0, 0x083E6E50 @carico l'offset
consiglio di inserire sempre qualche commento, anche se all'inizio possa sembrare inutile, perchè potrebbe capitarvi di non riuscire a capire il vostro stesso codice! questo perchè è complicato, e se non lo guardate per un po' vi dimenticherete. Poi se lo dovrete far leggere ad altri è ancora più "moralmente obbligatorio": è un vero atto di cortesia!
ed ecco alcuni swi che potrebbero tornarvi utili (#se leggete "dsi" o "nds" per favore ignoratelo):
Codice: SWI 06h - Div
Signed Division, r0/r1.
r0 signed 32bit Number
r1 signed 32bit Denom
Return:
r0 Number DIV Denom ;signed
r1 Number MOD Denom ;signed
r3 ABS (Number DIV Denom) ;unsigned
For example, incoming -1234, 10 should return -123, -4, +123.
The function usually gets caught in an endless loop upon division by zero.
SWI 08h - Sqrt
Calculate square root.
r0 unsigned 32bit number
Return:
r0 unsigned 16bit number
The result is an integer value, so Sqrt(2) would return 1, to avoid this inaccuracy, shift left incoming number by 2*N as much as possible (the result is then shifted left by 1*N). Ie. Sqrt(2 shl 30) would return 1.41421 shl 15.
SWI 09h - ArcTan
Calculates the arc tangent.
r0 Tan, 16bit (1bit sign, 1bit integral part, 14bit decimal part)
Return:
r0 "-PI/2<THETA/<PI/2" in a range of C000h-4000h.
Note: there is a problem in accuracy with "THETA<-PI/4, PI/4<THETA".
LZ77UnCompReadNormalWrite8bit (Wram) - SWI 11h
LZ77UnCompReadNormalWrite16bit (Vram) - SWI 12h
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits. For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
CAUTION: Writing 16bit units to [dest-1] instead of 8bit units to [dest] means the reading from [dest-1] won't work, ie. the "Vram" function works only with disp=001h..FFFh, but not with disp=000h.
If the size of the compressed data is not a multiple of 4, please adjust it as much as possible by padding with 0. Align the source address to a 4-Byte boundary.
r0 Source address, pointing to data as such:
Data header (32bit)
Bit 0-3 Reserved
Bit 4-7 Compressed type (must be 1 for LZ77)
Bit 8-31 Size of decompressed data
Repeat below. Each Flag Byte followed by eight Blocks.
Flag data (8bit)
Bit 0-7 Type Flags for next 8 Blocks, MSB first
Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
Bit 0-7 One data byte to be copied to dest
Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
Bit 0-3 Disp MSBs
Bit 4-7 Number of bytes to copy (minus 3)
Bit 8-15 Disp LSBs
r1 Destination address
r2 Callback parameter ;\for NDS/DSi "ReadByCallback" variants only
r3 Callback structure ;/(see Callback notes below)
Return: No return value.
SWI 0Ch - CpuFastSet
Memory copy/fill in units of 32 bytes. Memcopy is implemented as repeated LDMIA/STMIA [Rb]!,r2-r9 instructions. Memfill as single LDR followed by repeated STMIA [Rb]!,r2-r9.
After processing all 32-byte-blocks, the NDS/DSi additonally processes the remaining words as 4-byte blocks. BUG: The NDS/DSi uses the fast 32-byte-block processing only for the first N bytes (not for the first N words), so only the first quarter of the memory block is FAST, the remaining three quarters are SLOWLY copied word-by-word.
The length is specifed as wordcount, ie. the number of bytes divided by 4.
On the GBA, the length should be a multiple of 8 words (32 bytes) (otherwise the GBA is forcefully rounding-up the length). On NDS/DSi, the length may be any number of words (4 bytes).
r0 Source address (must be aligned by 4)
r1 Destination address (must be aligned by 4)
r2 Length/Mode
Bit 0-20 Wordcount (GBA: rounded-up to multiple of 8 words)
Bit 24 Fixed Source Address (0=Copy, 1=Fill by WORD[r0])
Return: No return value, Data written to destination address.
SWI 0Bh - CpuSet
Memory copy/fill in units of 4 bytes or 2 bytes. Memcopy is implemented as repeated LDMIA/STMIA [Rb]!,r3 or LDRH/STRH r3,[r0,r5] instructions. Memfill as single LDMIA or LDRH followed by repeated STMIA [Rb]!,r3 or STRH r3,[r0,r5].
The length must be a multiple of 4 bytes (32bit mode) or 2 bytes (16bit mode). The (half)wordcount in r2 must be length/4 (32bit mode) or length/2 (16bit mode), ie. length in word/halfword units rather than byte units.
r0 Source address (must be aligned by 4 for 32bit, by 2 for 16bit)
r1 Destination address (must be aligned by 4 for 32bit, by 2 for 16bit)
r2 Length/Mode
Bit 0-20 Wordcount (for 32bit), or Halfwordcount (for 16bit)
Bit 24 Fixed Source Address (0=Copy, 1=Fill by {HALF}WORD[r0])
Bit 26 Datasize (0=16bit, 1=32bit)
Return: No return value, Data written to destination address.
Note: On GBA, NDS7 and DSi7, these two functions will silently reject to do anything if the source start or end addresses are reaching into the BIOS area. The NDS9 and DSi9 don't have such read-proctections.
SWI 05h - VBlankIntrWait ;DSi7/DSi9=bugged?
Continues to wait in Halt status until a new V-Blank interrupt occurs.
The function sets r0=1 and r1=1 (plus r2=0 on DSi7) and does then execute IntrWait (SWI 04h), see IntrWait for details.
No parameters, no return value.
noi (io) negli esercizi useremo l'indirizzo 02000000 come scambio di informazioni tra script e routine; potrete facilmente cambiarlo.
ESERCIZIO: dato un numero, stampa (o ritorna) il fattoriale
Codice: .THUMB
.ALIGN 2, 0x0
@; RO: OFFSET MEM
@; R1: VALORE
@; R2: DECREMENTO
PUSH {R0-R4,LR}
MOV R0, #1 @;INIZIALIZZO REGISTRO: 2000000
LSL R0, #0X19
LDRH R1, [R0] @; LEGGO VALORE INPUT
MOV R2, R1
fattoriale_ciclo_calcolo:
SUB R2, R2, #1 @; ALGORITMO ITERATIVO DEL FATTORIALE
MUL R1, R2
CMP R2, #1
BHI fattoriale_ciclo_calcolo
STR R1, [R0] @;FORNISCO IL RISULTATO
POP {R0-R4,PC}
tutto quello che abbiamo fatto è stato inizializzare i valori ed eseguire un semplice ciclo in cui moltiplichiamo il numero per sè stesso.
ESERCIZIO: dati n numeri, calcolare la media
avvertenza: ho usato il byte a 200000 per indicare il numero di elementi, che ho messo in un vettore (per complicare un pochino le cose, se no non c'è gusto XD - no scherzo in realtà perchè così avete già in mente come trattare gli altri problemi complicati sui vettori) che compare subito dopo (a pensarci bene in Pascal le stringhe di testo sono vettori di 255 elementi in cui lo 0-esimo indica la lunghezza totale... ma questa è un'altra storia, mi è venuta la coincidenza per caso! )
ecco, ogni tanto provate a fare un riassunto del contenuto dei registri, come ho fato io due volte qua sotto (le righe lunghe), così da non confondervi!
(consiglio di usare programmers notepad per avere la sintassi colorata)
Codice: .thumb
.align 2, 0x0
.equ scambio, 0x2000000
push {r0-r4, lr}
@; r0: accesso vettore, r1: numero elementi r2: somma temporanea r3: elemento letto corrente r4: indice del vettore
inizializzazione:
mov r2, #0
mov r4, #0
ldr r1, =scambio
mov r0, r1 @; copio
ldrb r1, [r1] @; leggo il numero di elementi
add r0, r0, #1 @; mi posiziono sul vettore
ciclo:
ldrb r3, [r0, r4] @; accesso tramite indicizzazione
add r2, r2, r3
add r4, r4, #1
cmp r1, r4
bhi ciclo
@; r0: somma temporanea r1: numero elementi r2: / r3: / r4: memorizzazione
mov r4, r0 @; preparo la divisione
sub r4, r4, #1
mov r0, r2
mov r2, #0
mov r3, #0
swi 0x6
strb r3, [r4] @; comunicazione del risultato
fine:
pop {r0-r4, pc}
notate che per entrambi gli esempi ho scelto di memorizzare il risultato nella memoria RAM per semplicità. Se però le funzioni fossero state inserite in un contesto più ampio, sarebbe stato preferibile usare un valore di ritorno. come si fa? bisogna semplicemente non pushare un (o più) registro, che useremo per contenere il risultato. un esempio di questa tecnica è lo SWI, come abbiamo visto nella divisione, che ritorna qualcosa nei registri. ma noi come possiamo?
generalizzando,
Codice: PUSH {RY-RZ, LR}
@ fai qualcosa
MOV RX, XXX @ memorizza in qualche modo il risultato
POP {RY-RZ,PC}
con, generalmente, X < Y < Z (numeri sempre a vostra scelta, ma meglio se sensata)
in questo modo RX sarà in comune sia alla funzione corrente che a quella chiamante. poi quello che la chiamante farà non è affar della corrente.
nella seconda tipologia di esercizi userò il valore di ritorno, dunque attenti!
#sposare su programmazione
una funzione si dice ricorsiva se durante l'esecuzione chiama sè stessa o chiama una funzione che chiama sè stessa. equivalentemente, in matematica, una funzione è ricorsiva se è definita in termini di sè stessa.
è importante che esista una condizione di base che permette di non chiamare la funzione, altrimenti si genererebbe un ciclo infinito.
pensiamo al fattoriale di n, ovvero la produttoria di numeri che vanno da 1 a n.
è possibile usare l'algoritmo iterativo (anzi c'è un teorema che dice che qualunque problema è risolvibile tramite le strutture fonfamentali), oppure quello ricorsivo.
in questo caso, il fattoriale di n (scritto n!) possiamo vederlo come n*(n-1)!.
[attachment=441]
è proprio la condizione di base che ci permette di uscire dal calcolo.
Che succede se finite i registri come variabili?
abbiamo essenzialmente tre alternative: usare la memoria, lo stack o i registri alti.
per usare la memoria non ci vuole molto, basta scrivere sulla 02 qualche valore da andare a prendere dopo. ovviamente però non dovrete dimenticare dove avete messo i dati! per questo è meglio organizzare la cosa come un vettore di int (il tipo di grandezza massima) allineato, e il cui indirizzo è mantenuto in un rgistro. ora, con semplici immediati (ricordate equ), potrete accedere a qualsiasi cosa vogliate (dubito che abbiate più di 255 variabili), tramite l'indirizzamento scostato (quello con il [RX, #numero]).
la seconda alternativa invece è più integrata nel sistema, ma più delicata.
infatti potrete pushare (accatastare) sullo stack un qualsiasi valore, caricare il nuovo dato in un registro, fare l'operazione e poi poppare (togliere) il valore. RICORDATE CHE ALL'INIZIO E ALLA FINE DEL PROGRAMMA ASM LO STACK DEVE ESSERE NELLO STESSO STATO! ovvero, POPPATE SEMPRE CIO' CHE PUSHATE!
questo perchè altrimenti il programma esterno (la ROM) si ritroverà dati non coerenti e anrà in crash (nel migliore dei casi sarà tutto glitchato)
Poi voi in mezzo alla vostra pila personale potrete fare tutte le vostre porcherie (so che le farete, anche se dovrebbe essere vietato da un'autorità universale), come ad esempio prendere un valore dal mezzo (se lo fate con una pila di piatti vedete che vi succede... XD)... l'importante però è che alla fine della vostra funzione lo stack sia come l'avete trovato.
la terza soluzione, che è un po' scontata, prevede di utilizzare i registri da 8 a 12. il problema è che pochissimi opcodes li trattano, perciò sono scomodi. e comunque dovrete depositarne il contenuto con uno dei metodi di prima ^^".
ora c'è una nuova tipologia di esercizio: io vi darò una funzione, e dovrete rispondere cosa fanno. le prime sono di esempio.
1)
avete due files, quello del programma e quello di utility.
Codice: .thumb
.equ input, 0x2000000
.ascii "inizio programma" @; scrive sul file binario
.align 4, 0x0
PUSH {R0-R4, LR}
main:
LDR R2, =input
LDR R4, [R2]
MOV R0, R4
MOV R1, #4
BL utility_main
CMP R0, #0
BNE no
MOV R0, R4 @; riprendo il dato parcheggiato
MOV R1, #100
BL utility_main
CMP R0, #0
BNE si
MOV R0, R4
MOV R1, #25
LSL R1, #4
BL utility_main
CMP R0, #0
BNE no
si:
MOV R0, #1
LDR R2, =input
STRB R0, [R2]
b return
no:
MOV R0, #0
LDR R2, =input
STRB R0, [R2]
return:
POP {R0-R4, PC}
.include "lib/utility.s" @; entro in una cartella per prendere l'utility
@; l'ho messo in fondo perchè il compilatore non ha capacità di riconoscere il programma prinicipale, compila solo
@; nell'ordine in cui trova il codice, perciò così abbiamo subito il nostro programma all'inizio del file binario
@; (utile per fare eventualmente un callasm); mentre le librerie non ci interessano e rimarranno confinate in fondo.
Codice: .THUMB
.ALIGN 4, 0xFF
utility_main:
PUSH {R2-R6,LR}
MOV R2, #0
MOV R3, #0
MOV R5, R0
MOV R4, R1
SWI #0X6
CMP R1, R4
BHI utility_correggi
B utility_fine
utility_correggi:
NEG R1, R1
SUB R1, R1, #1
utility_fine:
MOV R0, R1
POP {R2-R6,PC}
innanzitutto scopriamo cosa fa l'utiliti. R0 e R1 sono parametri, in quanto usati senza essere pushati. notiamo inoltre che usa lo swi del div, dunque sarà qualcosa attinente alla divisione. noi sappiamo l'output del div, e vediamo che la routine è interessata al R1, ovvero il modulo. anzi, la funzione ritorna proprio quello in R0. ma cos'è quel pezzo prima della fine? se il modulo è maggiore del denominatore (#per una questione che mi son dimenticato di spiegare, si chiama "complemento a due", se volete cercarla su internet o se no mandatemi un messaggio), significa che il numero è necessariamente negativo, dunque lo nega e sottrae 1, ovvero ottiene lo stesso numero positivo.
dunque la routine restituisce il valore assoluto del modulo tra R0 e R1.
cosa fa il file principale?
-controlla se un numero è divisibile per 4
--se non è divisibile restituisce 0
--altrimenti
---controlla se è divisibile per 100
----se no, restituisce 1
----altrimenti
-----controlla se è divisibile per 400 (25*2^4)
-----restituisce la stessa verità del'ultimo controllo.
questo è palesemente l'algoritmo di controllo della bisestilità di un anno.
(la comunicazione con l'esterno avviene tramite RAM e non tramite ritorno perchè è stata pensata per essere usata in uno script)
consiglio: usate le librerie, aiuteranno a scrivere molto meno!
in particolare, potreste fare dei "wrapper" per le funzioni swi, come la precedente, dato che fanno spesso e volentieri macello con i registri, potreste trovarvi in difficoltà. dunque con una routine come questa annullerete l'effetto caos e anzi ritornerete in modo elegante ciò che vi serve.
#calcolatrice
compito
vi consiglio di trovare prima una soluzione con gli schemi a blocchi. e dato che non sono necessarie molte variabili, vi consiglio anzi di tradurre 1:1 le singole strutture in blocchi di codice assemly (ad esempio tutte le sequenze in una sequenza asm), e poi di etichettarli. così potrete facilmente creare il controllo del flusso di esecuzione.
- verificare se un vettore è ordinato
- verificare se un vettore contiene elementi tutti uguali
- bonus: compattare un vettore (eliminare i valori duplicati e quelli pari a 0)
consigli:
- inutile dire che i cicli saranno d'importanza fondamentale.
- non avete limitazioni oltre alle richieste. (a buon intenditor... vabbè ve la spiego: non vi ho detto di che tipo è il vettore, dunque sceglietene uno comodo... vabbè ve lo dico ancora: di sicuro non sarà il tipo booleano o short, ma un tipo che sfrutta appieno la tecnologia del processore...)
- per l'ultimo, prima create una funzione per individuare gli zeri e scorrere a "sinistra" (nella memoria) tutte le celle successive. poi create una funzione che itera su tutto l'array in cerca di valori duplicati, che verranno "marcati" con degli 0. poi fate ripassare la funzione di eliminazione degli zeri.
è vero, questo algoritmo non è il massimo dell'efficienza (anzi è il male in persona), ma sicuramente è molto intuitivo, dunque di facile realizzazione.
è possibile utilizzare sia l'algoritmo iterativo che ricorsivo, dunque buona fortuna! ^^
#intersezione di 2 vett IN C
cosa fanno queste routine?
1)
Codice: .thumb
.align 2, 0xFF
.equ input, 0x2000000
main:
Push {r0-r4, lr}
ldr r1, =input
ldr r0, [r1]
bl func
str r0, [r1]
pop {r0-r4, pc}
func:
push {r1-r4, lr}
cmp r0, #1
beq return
cmp r0, #0
beq return
mov r1, r0
sub r0, #1
bl func
mul r0, r1
return:
pop {r1-r4, pc}
#fare: palindromo/-
anche per stavolta mandatemi i compiti via MP, più avanti studierò un sistema per evitare che gli "esterni" "riciclino" i vostri compiti (perchè do per scontato che non vi copiate tra voi  ).
#nel caso non vi basti, c'è pure il documento di jpan su pc ~
crediti: gbatek, tonc
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere e guarda notepad
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
20-07-2016, 04:52 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:11 PM da Bonnox.)
patch 160319
ciao! questo è una patch aggiornamento flash per spiegarvi alcune operazioni poco chiare prima.
LE ISTRUZIONI LOGICHE
Sono delle operazioni che si ritrovano anche nella logica, una branca della matematica. In questo caso le operazioni sono le stesse, ma si svolgeranno sui nostri registri.
innanzitutto chiariamo che se un'istruzione è "bit a bit" vuol dire che viene eseguita separatamente per ciascun bit del registro, a prescindere dunque dal suo valore ottenuto considerando i suoi 32 bit come un numero unico.
Queste sono le istruzioni che possiamo fare col GBA. le altre possono essere ricavate da queste, precisamente dalle prime 3.
AND
questa operazione restituisce il valore 1 solo se tutti gli ingressi sono a 1, 0 altrimenti. Il nome and (in inglese "e") deriva dal fatto appunto di pronunciare "se il primo ingresso vale 1 e il secondo ingresso vale 1...", in quanto il processore manipola al massimo due registri alla volta.
OR
questa operazione restituisce 1 se almeno un ingresso vale 1. se nessun ingresso vale 1, restituisce 0.
questa operazione è l'esatto contrario della and. or in inglese significa "o", dato che restituisce 1 se il primo ingresso o il secondo ingresso vale 1.
NOT
questa operazione restituisce il contrario dell'ingresso (da cui il nome che significa "negare"), ovvero restituisce 1 se l'ingresso vale 0 e viceversa
XOR
significa "exclusive or", ovvero or esclusivo. questa operazione restituisce 1 se solo un ingresso vale 1.
possiamo riassumere il tutto con un'immagine che si chiama "tabella di verità", in cui sulle colonne ci sono gli ingressi e l'uscita, e sulle righe i loro valori (lasciate pure stare quegli strani oggetti rotondi):
per vedere qualche esempio vi basta usare la calcolatrice sul computer e smanettare un po'
BREVE COMPITO:
fatemi (via MP) la tabella di verità delle operazioni NAND e NOR, sapendo che significano "not and" e "not or"
Bye
Ciao , benvenuti nella mia aula!
Questo corso si prepone lo scopo di far comprendere i fondamenti del funzionamento più interno del nostro amato Game Boy Advance, per poter, con la pratica, diventare capaci di alterare anche in modo profondo i nostri giochi! ^^
LEZIONE 0
INTRO
Innanzitutto vi comunico il materiale essenziale:
- Emulatore normale e ROM AXVE/BPRE (facilmente reperibili in commercio). sapete che preferisco rubino perciò farò più esempi con quella ROM, ma è indipendente quale scegliete.
- Hex editor (spiegato sotto)
- VBA SDL-H
- Assemblatore
- Referenza (quick guide)
Questo invece è Facoltativo (ma consigliato): - Documentazione ufficiale ("approfondimento"):
(ovviamente non è necessario che leggiate subito quei documenti, anzi, probabilmente non ci capirete niente)
cominciamo spiegando di cosa si tratta tutto quel materiale:
Il VBA-SDL-H è una versione modificata del VBA che permette di fare cose avanzate per gli hacker, ed è quello che useremo più spesso durante le ricerche, in quanto torna molto utile come debugger e disassemblatore. Funziona da linea di comando, ma come vedrete non è molto difficile da usare.
L'Asemblatore è un programma che permette di passare dal nostro linguaggio ASM al file binario effettivo (codice eseguibile dal GBA)
Per quanto riguarda l'Hex editor c'è un piccolo discorso da fare. Come alcuni di voi forse già sapranno, è un programma che permette di visualizzare il contenuto a basso livello di un file. Esso sarà il nostro "migliore amico", perciò bisogna sceglierlo bene: quello che volete, su internet ce n'è una svalangata tra cui scegliere (actually sto pensando di farne uno anche io, ma le tempistiche saranno MOLTO lunghe), ergo usate quello con cui siete più comodi. I toolz servono per facilitare il lavoro, non per litigarci contro (e vi posso garantire che è infernale non andare d'accordo col programma in uso, mi è successo). Io attualmente uso questi 3 in accoppiata: XVI32, HxD, WindHex, ma non vuol dire che dobbiate farlo anche voi. Più avanti vi illustrerò brevemente ciascuno di questi tre.
Ora faccio un paio di considerazioni.
Innalzo il tempo di risposta dai 5 giorni canonici a 8/10 (ma potrebbero essere anche di più). Ovviamente questo vale solo per lo svolgimento di un compito, perché gli altri post non richiedono grandi capacità o applicazione, e anche perché immagino sarete incollati al pannello di controllo per vedere se ho risposto (fine autocelebrazione time, rimosso la frase  ), dunque non c'è neanche bisogno di fissare una scadenza per il resto dei messaggi. Questa modifica semplicemente per il fatto che questa è roba di una certa levatura, a volte anche difficile. Potrà sembrare strano, ma come il mapping, anche l'asm richiede tanto tempo... Per la creatività! Pacman Confused no ok magari non è la migliore scelta lessicale (dubito che interagire con i computer a basso lvello sia divertente - # per capogalassia: tra i primi programmatori c'è una donna ^^), fatto sta che ci può davvero volere del tempo perchè potrebbe essere impegnativo. Dunque avremo orari... flessibili.
A proposito, vi consiglio di sottoscrivere la discussione clickando sul link in fondo alla pagina, oppure la stella di SchifoTalk  così non dovremo più taggarci come dei matti: avendo sottoscritto, voi vedrete che ci sono nuovi post dal pannello di controllo; io pure perchè sono l'autore.
Allora la mia idea, prescindendo dagli argomenti trattati, era di preferire un post grosso diviso in più parti, in modo da poter analizzare con calma ogni singolo aspetto. Non disdegno la tecnica "mordi e fuggi", ma in questo caso non potrebbe essere applicata per svariati motivi. Magari negli altri casi, come spiegare i comandi di XSE un po' per volta, può funzionare, ma non qui.
Se alcuni concetti esposti in questo messaggio non vi saranno subito chiari non preoccupatevi, li riprenderemo ~
Detto questo ci vediamo la prossima volta Smile
Saluti
#
ho fatto un'errore, riscarica la quick guide, ho messo un'altro link, quello di prima non andava troppo bene (mi scuso per l'inconveniente)
tranquilli, li vederemo insieme, per gradi. ho semplicemente fatto scaricare tutto all'inizio, anche ciò che servirà più avanti!
let's get it started.
LEZIONE 1
I MATTONCINI DELLA ROM:
IL LINGUAGGIO BINARIO
Prima di cominciare veramente dovrete conoscere il significato di questi termini (ovviamente se li conoscete già potete saltare). Come prerequisito chiedo che sappiate i sistemi di numerazione (cosa sono, come si scrivono, come si passa da uno all'altro), ma non serve che me li esponiate.
Attenzione alla notazione: è universale mettere un "0x" prefisso ai numeri esadecimali (in base 16), poi io ogni tanto metto una "d" o una "b" o una "h" suffisse per decimale, binario, esadecimale. Poi vabbè, potremmo seguire qualsiasi standard...
#copia da guida notazione- Bit
Elemento che ha origini agli albori dell'informatica. E' un elemento che può assumere 2 stati diversi. Solitamente sono HIGH e LOW, nati dai valori della tensione in un circuito, nei primi calcolatori elettronici. Per estensione, rappresenta le 2 cifre del sistema binario (0 e 1). È l'unità fisica minima nell'informatica.
- Byte:
È l'unità logica fondamentale, composta da un gruppo di 8 bit su un qualunque supporto di memorizzazione (cd, hard disk, radio frequenze...) Se facciamo la combinazione di tutti i suoi termini, vediamo che può assumere 2^8 = 256 stati diversi. Nel nostro sistema decimale si parte da 0 e si arriva a 255. In binario si parte da 00000000b e si arriva a 11111111b. In esadecimale, la base che useremo più spesso, quei valori si scrivono 0x0 e 0xFF.
Perchè un byte si rappresenta in esadecimale? perchè è il modo più veloce, in quanto ha solo 2 cifre, e ciascuna rappresenta separatamente 4 degli 8 bit, cosa che non avviene in base 10.
- Offset:
letteralmente "scostamento" in inglese, indica lo spostamento di un preciso byte relativamente a un'origine. Noi fortunatamente consideriamo sempre tale origine come il primo byte della ROM, dunque indirizzo 0 (ricordo che in informatica si inizia sempre a contare da 0), il chè semplifica i conti; ma non è raro il caso di dover iniziare a contare a partire da un altro valore: ad esempio per hacking di altre console, principalmente nintendo (il caso più vicino a noi è il GB) si divide la ROM in varie parti di uguale grandezza, e ognuna determina una diversa origine del valore dell'offset.
- Puntatore:
generalmente in informatica è un valore che indica, da cui l'usanza di dire "punta", un'area della memoria della macchina. Generalmente nei computer indica la RAM, ovvero la memoria temporanea che contiene i dati in attesa di essere elaborati; Mentre noi avremo quasi sempre a che fare con puntatori alla ROM, che è la memoria di sola lettura in cui risiede il gioco.
Come avrete capito in questa prima parte lavoreremo sui byte; nonostante ahimè sia un lavoro noioso secondo me è più facile da comprendere rispetto ad altro.
Ogni file sul nostro computer è composto da una serie più o meno lunga di bytes. Come avrete avuto modo di notare usando il PC, la rom occupa esattamente 16 MB, il che è veramente poco, ma dobbiamo considerare che risale al 2002 e per giunta è per una piattaforma mobile.
All'interno del file ci sono, stipati insieme, tutto il codice del programma e tutti i dati che servono a far funzionare correttamente il tutto. Il codice (chiamato anche linguaggio macchina) è ciò che vedremo con l'Assembly, ovvero tutte le istruzioni che il GameBoy esegue una volta caricato il gioco, come ad esempio "fai questo suono", "memorizza tale valore", “visualizza l’immagine”, "muovi la pokeball", eccetera. I dati invece sono informazioni conservate nella ROM con un preciso formato. Ad esempio sono dati le musiche, le mappe, i pokemon degli allenatori, i testi dei messaggi… tutto quello che viene modificato dai programmi è un dato. Ma noi dobbiamo imparare a farlo anche senza programmi. I dati vengono letti solo quando necessario e caricati a blocchi nella ram, che anche se piccola è molto veloce, per non rallentare il gioco. Infatti la memoria centrale (altro nome della ram secondo Von Newmann) è sì più piccola, ma anche molto più veloce della memoria di massa (ROM). Si parla di tempi dell'ordine dei nanosecondi per accedere a un dato, contro i vari millisecondi della rom.
E' importante chiarire il fatto che in sè non esisterebbe la distinzione tra istruzioni e dati. I dati infatti possono essere anche erroneamente interpretati come istruzioni (vedasi i vari glitch di pokemon red), e se per noi è un fastidio (lo è quasi sempre), per la macchina non cambia assolutamente nulla.
Bene, eccoci alla vera lezione. Mi scuso se sarà un po’ monotona, ma è importante. Come diceva un mio professore, “il brutto delle cose facili è che vanno sapute perfettamente”.
Aprite un hex editor. Esso è un software che ci permette di visionare e modificare i bytes di un file. Ecco come si presentano alcuni di essi una volta aperti:
http://pokehack.altervista.org/attachment.php?aid=297
Iniziamo caricando un nuovo file. Consiglio un file che non vi serve più (ad esempio potete creare un nuovo documento di testo da usare come cavia con il tasto destro), dato che andremo a pasticciare e a rovinare
Normalmente troveremo tre colonne: la prima indica l’offset in cui ci troviamo, quella centrale visualizza tutti i byte, e l’ultima colonna ci indica gentilmente la loro rappresentazione testuale, cosa di cui non potrebbe fregarci di meno, dato che per noi è inutile. L’unico utilizzo che può avere per noi tale parte è per “rincuorarci”, ovvero trovare un piccolo conforto in caratteri familiari di fronte all'agonia della vista dei bytes. Ok, dovrò andare a fare il drammaturgo  Posizionate il cursore e clickate sulla colonna a destra, e iniziate a scrivere cose a caso sul file cavia. Notate che c’è una corrispondenza a sinistra con ciò che scrivete?
Ora vorrei che vi prendeste un attimo di tempo per fare una cosa. Iniziate a scrivete tutte le lettere dell'alfabeto, dalla a alla z, minuscole e maiuscole, e poi anche i numeri. Cosa notate? I byte a destra assumono precisi valori. Signori, questo è l’ASCII. Questo è uno standard americano di comunicazione abbastanza datato, ma è usato come base dei più recenti (ad esempio le emoticon di wozzap). In pratica assegna ad ognuno dei valori ottenibili da 7 bit a un carattere o simbolo. La tabella attualmente diffusa è quella di MS-DOS, mentre una volta c'erano discrepanze a seconda del sistema operativo.
Ora prendiamo confidenza con le funzionalità del'H.E.. Non so il percorso da seguire con il vostro, ma esiste una scorciatoia praticamente universale che tutti implementano: CTRL+F. Si aprirà una finestra chiamata ricerca. Qua ci mettete del testo che volete venga cercato all'interno di un file. Se state usando una rom di pokemon non avrete fortuna, perciò cambiate subito file. Potete ad esempio scegliere un documento di office di quelli vecchi (.doc e non .docx ). Dopo aver avviato la ricerca il cursore si posizionerà sulla prima occorrenza; per cercare ancora premete F3. Oppure create una lista di risultati, che è più comoda:
http://pokehack.altervista.org/attachment.php?aid=298
Ricordate che anche se in generale sono simili, ogni hex editor ha proprie funzioni aggiuntive che vale la pena provare e sfruttare (la mia ultima idea sarebbe quella di crearne uno mio, ma vabbè richiederebbe un tempo veramente ENORME :c )
Ad esempio poco fa, con la lista dei risultati, avete visto in azione una delle caratteristiche che più mi piacciono di windhex. Peccato che lui sia un po’ scomodo da usare “quotidianamente”.
http://pokehack.altervista.org/attachment.php?aid=415
http://pokehack.altervista.org/attachment.php?aid=416
Ora vorrei concentrarmi su una cosa molto importante, ovvero la ricerca dei puntatori. Come accennato prima sono dei valori che indicano una posizione all’interno della memoria del GBA. Ipoteticamente, ogni byte potrebbe avere il suo puntatore, basta costruirlo. Nella realtà però non è così perché si indica soltanto il primo byte di qualcosa (la cosiddetta "risorsa": un'immagine, un testo, ecc.), quelli seguenti sono referenziati tramite un indice di scostamento rispetto al puntatore (l’origine di cui parlavo prima). Considerate questo esempio:
“QUEL FEZ SGHEMBO COPRE DAVANTI”
non preoccupatevi, è soltanto un pangramma. Volevo mettere quello degli ioni o quello della volpe, ma nell’aprire wikipedia ed aver visto una citazione al mio telefilm preferito… beh… <3 giustamente dovevo metterla, concedetemelo.
Analizziamo ora la frase:
[Q][U][E][L][ ][F][E][Z][ ][S.][G][H][E][M][B.][O][ ][C][O][P][R][E][ ][D][A][V][A][N][T][I.]
(il "." è per imbrogliare il forum che altrimenti mi mette italic o bold)
Abbiamo un indice che identifica ogni lettera:
[00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29]
Se volessimo accedere ad una lettera, non dovremmo fare altro che sommare l’indice all’offset del primo carattere.
capiamo meglio con un’immagine:
http://pokehack.altervista.org/attachment.php?aid=300
In questo esempio possiamo vedere che l’offset del primo carattere è 9D3CE4h, e se voglio l’indice del carattere z devo sommare l’indice di z, ovvero 7.
Spero sia chiaro, altrimenti non fatevi scrupoli a chiedere.
Ora vediamo quali sono i passaggi per ottenere un puntatore. Per il momento ci saranno dei punti poco chiari, ma nelle prossime lezioni saranno rivelati.
Dato un offset lungo 3 byte, il suo puntatore è: - scrivere XX XX XX 08;
- invertire l’ordine dei 3 byte (quello in mezzo ovviamente resta in mezzo)
- sostituire i nuovi byte alle X.
Ecco l’esempio per 9D3CE4: - scrivo XX XX XX 08;
- ribalto i bytes: E4, 3C, 9D.
- sostituisco: E43C9D08.
Questo è il puntatore come se fosse stato inserito nella ROM originale. Ora basta metterlo nel posto giusto e il gioco potrà usare il nuovo testo, e nessuno si accorgerà della modifica! Questo è ciò che fa, a volte sbagliando, a-text.
Avete voglia di ricavare qualche puntatore, così giusto per esercizio? è proprio una sciocchezza, si fa in meno di 5 minuti.
Ricavate i puntatori dei seguenti offset:
Spero lo abbiate fatto, perché alla fine della lezione vi servirà.
Bene, eccoci alla prima su due cose pratiche. Recatevi all’offset 3E6E50 di rubino. Come fare? Non so quale sia il vostro menu a tendina, ma sicuramente potete fare CTRL+G, tutti gli hex editor hanno questa scorciatoia.
Inserite l’offset come faccio io e dovreste avere il seguente risultato;
http://pokehack.altervista.org/attachment.php?aid=301
Questo è un dato binario. Significa che è un dato rappresentato nel suo tipo (formato) naturale. ne consegue che solo chi sa leggere quel tipo di dato potrà comprenderne il significato. Fate una prova: aprite un’immagine con il blocco note. Cosa esce? Caratteri incomprensibili, perché il blocco note non sa leggere le immagini, lui poverino cerca solo il suo formato di dati (il testo) nell’immagine. Se provate ad aprire file prodotti da un'altra applicazione con un programma totalmente diverso, sarete fermati da un errore di incompatibilità. I programmi si aspettano certe cose nel file che aprono, e se non le trovano prevengono potenziali (anzi, sicuri) catastrofici errori dicendo di non poter aprire il file. Che poi VLC sia zelante e apre tutti i formati dell'universo in tha worldz forevah and evah mentre Windows media player invece è una checca schizzinoso sono dettagli… L'importante è che non cerchiate di fargli aprire un documento, ma un video! Dunque dicevo, ciò che troviamo sulla rom deve essere interpretato come il tipo di dati giusto per produrre un output coerente per l’utente. Altrimenti si verifica la stessa cosa di missingno: Secondo pokemon rosso laggiù ci doveva essere il verso di un pokemon, mentre invece c’erano altri dati… ecco da dove nasce l’inquietante verso di ♀ (“female”). Ed ecco perché sembra non finire mai: interpretando tali dati come suono, i byte che indicano la fine del suono non vengono raggiunti in tempi ragionevoli. A noi invece il massimo che possa capitare è vedere qualche carattere giapponese in un messaggio (mai capitato durante il corso di XSE?), perché magari sbagliamo a mettere l’offset, confondendolo con il puntatore o il testo; questo perché una ROM del GBA è dannatamente più comoda da modificare rispetto al GB.
Come modificare tali dati binari allora? Dobbiamo innanzitutto scoprire cosa rappresentano. Io lo so già perché riciclo gli esempi per la non sbatta. non è vero: in futuro aggiungerò un esempio tratto da advance map
Dobbiamo copiare i byte in un nuovo file per poterli analizzare meglio.
EDIT: In realtà mi sono accorto solo ora che il dato binario è word-aligned (allineato ogni 4 byte), dunque non serve ciò che sta sotto, nello spoiler. Che sbadato :|
Tuttavia anche se stavolta non serve è utile sapere come si fa, perciò dategli un'occhiata lo stesso.
Procedura per XVI:
Modo 1: - Copiate una sequenza di byte da qualche parte (una rotine di andrea? <3 )
- posizionatevi nel punto in cui incollare
- Edit > overwrite string
- selezionate hex
- incollate e confermate
Modo 2 - assicuratevi di essere in modalità overwrite
- Posizionatevi sul punto da copiare di un file già esistente
- Edit>block n chars
- inserite la lunghezza da copiare
- Edit>clipboard>copy
- posizionatevi nel punto in cui incollare
- Edit > block copy/overwrite (CTRL+W)
#(se non funziona vi prego di comuinicarmelo)
Spiegazione per HxD:
selezionate il testo e copiatelo con CTRL+C. Posizionatevi sulla destinazione e fate CTRL+B. fine :|
aprire immagine:
Sicuramente ve lo aspettavate, conoscendomi  chiedo nuovamente scusa a fiammy per aver dimenticato di colorare il suo posticino di meditazione quotidiana
Bene, ora che sappiamo cosa è analizziamo il formato: sembra che ogni valore del byte corrisponda a una città (SHISH, A GINIUS!). è importante però notare una cosa: il valore 58h indica il vuoto. Anzi, qualunque valore al di sopra di 58h indica vuoto.
Il vostro compito è di modificare (tramite hex editor, ovviamente) la worldmap e farmi vedere il risultato.
Perché l’abbiamo estratta? non l'abbiamo estratta perchè ero nabbo e non mi ero accorto che era già allineata :| Perché è più semplice da riconoscere: come avete potuto notare, nella rom è “sfasata”, non si capisce bene cosa sia.
invece il secondo motivo potrebbe essere valido: potete vedere subito se per sbaglio aggiungete dei byte. Controllate sempre di essere in modalità OVERWRITE! Inserendo bytes spostate altra roba, che dunque non è più al suo posto, e non verrà letta correttamente. Finchè si tratta di dati si può soprassedere (immagini, testi e suoni glitchati), ma se sono istruzioni, la cosa si fa grave...
CONSIGLIO: fate spesso backup. vi torneranno MOLTO utili, soprattutto le prime volte che sperimentate qualcosa di nuovo.
Per compito i 4 angoli della tabella devono contenere una città a vostra scelta, in più invertite albanova e solarosa. Questo è un compito per farvi imparare a contare (? Asd). Si, perché avrete notato che i dati sono tutti immagazzinati in fila indiana, non ci sono righe o colonne. La presenza di righe e colonne è dedotta dal software, mediante un semplice procedimento:
- So le coordinate X e Y del dato della tabelle che devo leggere.
- Moltiplico la Y per il numero di elementi di una riga
- Sommo X al precedente risultato
- Sommo l’offset del primo elemento della tabella al precedente risultato.
Come funzionano questi passaggi? Facciamo un esempio passo-passo.
Supponiamo di avere all’inizio di un file una talebba di 9 elementi, così:
A B C
D E F
G H I
Ma ovviamente nella memoria essa è contenuta linearmente: [[(A), (B), (.C)],[(D), (E), (F)],[(G), (H), (I)]] . Come facciamo ad accedere ad un elemento? Dobbiamo indicizzarla.
Mettiamo di voler accedere alla posizione centrale, di indice 1,1 (si parte a contare da 0).
- Moltiplico y*la larghezza: 1*3=3
- Sommo la x: 3+1=4
- Sommo l’offset di inizio della tabella: 4+0=4
Dunque prendiamo il valore alla posizione 4. Contiamo insieme (scusate se vi sembro Dora l'esploratrice >.<  ):
0-A,
1-B,
2-C,
3-D,
4-E.
Tutto questo casino per cosa? Per sapere cosa state modificando. Se siete sulla ROM vi perderete in fretta, per cui bisogna sempre contare prima di scrivere qualcosa.
Ma tanto già so che voi avrete estratto la worldmap e ridimensionato la finestra del programma per avere esattamente 28 colonne, vero? Sempre che il vostro hex editor permetta ciò. A questo punto il compito diventa una bazzecola.
Chi lavora su fire red può fare il compito su fire red, per questa volta. L’offset è 3F2500h.
Ora proviamo a fare una cosa più complicata. Vi giuro che è l’ultima per oggi. Mi serve perché contiene una cosa che da grattacapi ad alcuni utenti, ed è molto importante capirla.
Spostiamo la worldmap.
Cosa? Eh, dai, su, non ho mica detto di spostare una regione intera, è solo una cartina! Mica siamo dei titani, solo dei geografi!  ok pessima citazione della mitologia greca  Ecco il procedimento passo per passo. Vorrei lo faceste per compito.
Per poter proseguire, dovete aver fatto il mini esercizio sui puntatori, la cui Soluzione è (non guardate prima di aver almeno tentato, se siete onesti - e poi potete chiedermi se avete dei dubbi):
- 506E3E08
- 28B30F08
- 0000E008
Prendete l'offset della worldmap. Aprite la ROM con l'hex editor e cercate una stringa esadecimale. Scrivete il puntatore. Se tutto è corretto dovreste averlo trovato una sola volta (se di più o avete usato rosso fuoco e allora non so, oppure c’è qualcosa di sbagliato, nel caso chiedete pure). Si trova a FB328h per ruby.
Sostituitelo. Con cosa? Ma con quello che volete voi. Ad esempio provate un offset a caso. Scrivete davvero 3 (TRE!) byte a caso, è un procedimento istruttivo. Poi aprite la mappa città nel gioco e vedete che succede. Il gioco interpreta come mappa città dati che mappa città non sono. Complimenti, avete buggato la ROM! Tranquilli, è riparabilissimo, basta fare l'operazione inversa! Ora torniamo indietro. Mettete il puntatore di questo valore: 720000h. se la rom è vergine, dovrebbe esserci spazio laggiù. Ora, come prima, copiate la vostra wolrdmap in tale punto. Modificate valori della worldmap che vi ho chiesto. Se tutto va bene, cancellate quella originale, scrivendo 420d volte 00h o FFh (o qualsiasi cosa, ma questi due valori sono molto più "convenzionali").
Se avete qualsiasi cosa da dire, non abbiate paura!
Bye!
.
LEZIONE 1.2
IMPARIAMO A SCRIVERE?!
Se ricordate, l'altra volta ho detto che per visualizzare i caratteri sono utilizzati gli standard di comunicazione, in cui ad ogni byte corrisponde un carattere ben preciso.
Ovviamente in GF hanno avuto la brillante idea (si fa per dire...) di alterare l'ordine naturale delle cose sostituendo tutti i caratteri con dei nuovi. Il funzionamento è il medesimo, ma i giochi adottano un set di caratteri diverso, come si suol dire. Questi possono essere trovati sull'enciclopedia ( http://bulbapedia.bulbagarden.net/wiki/C...ration_III) dove sono descritti in maniera molto dettagliata. Noterete che ci sono alcuni valori strani: sono le sequenze di escape, ovvero i caratteri di controllo. Questi sono speciali caratteri, presenti in ogni sistema operativo, che hanno particolari compiti. Il sottoprogramma che si occupa della scrittura del testo riconosce il carattere speciale e si comporta di conseguenza. Ora mentre sto scrivendo questo testo non ho sotto mano il documento, ma ogni singolo byte è ampiamente documentato. Ad esempio con essi potete cambiare colore, oppure fare una pausa, o usare il grassetto. Sono tecniche utili per la regia  Anche nel computer normale ci sono le sequenze di escspe: a capo è un esempio.
Tutte le volte che usate una sequenza mnemonica in xse, come ad esempio "LASTRESULT" o "RS_cyan" (non son sicuro che la seconda sia corretta così com'è, ma avete capito a cosa mi riferisco) lui sostituisce nella ROM una particolare sequenza di caratteri al posto della parola chiave. Nel nostro caso al posto del colore metterà il byte che indica il cambio di colore, e poi il byte del colore. E se volete inserire in XSE altre sequenze di escape? C'è il comando "\h", ma Comunque dovete inserire un "\h" per ogni singolo byte che compone la nostra sequenza di controllo. Noioso, vero? Ecco perchè a volte preferisco usare l'hex editor. Ovviamente non dovrete usarlo sempre, anzi riconosco che usare XSE è più comodo, ma sapere come fare è sempre meglio; forse vi capiterà qualche caso in cui vi servià.
Per svolgere correttamente questa attività dovrete avere una tabella dei caratteri, che essenzialmente è un file che dice all'hex editor quali sono le corrispondenze tra i caratteri "normali" (ASCII) e "quelli pokemon" . Io vi passo quella che si trova insieme a thingy 32 (un hex editor sviluppato principalmente per le traduzioni) e quella (incompleta) che ho fatto io per xvi in un momento di noia
http://pokehack.altervista.org/attachment.php?aid=279
http://pokehack.altervista.org/attachment.php?aid=280
Da rinominare in estensioni "TBL" e "XCT".
Come si usano? Ogni programma ha le sue beghe, dunque bisognerà stare attenti. Comincio col dire che su HxD neanche c'è questa possibilità, oppure sono stordito io che non l'ho vista. Rimangono windhex e thingy che si comportano in modo piuttosto simile, mentre xvi, come vedrete tra poco, fa una "cassanata".
Dunque è giunto il momento di aprire rom e tabella. Solitamente i comandi stanno nel menu file. Windhex legge la tabella di thingy. Una volta completato dovreste vedere che i caratteri a destra sono cambiati. Il programma sta sostituendo i byte della ROM con i caratteri indicati da noi. Ora, finalmente, potete provare a sbizzarrirvi con la ricerca di testo, in quanto ci sono un mucchio di parole di senso compiuto! E se provate a scrivere con le normali lettere della tastiera, queste vengono automaticamente tradotte nel formato corretto, mentre a noi appariranno come lettere normali!
http://pokehack.altervista.org/attachment.php?aid=308
Bisogna ricordare, però, che il programma è stupido, e non sa quali byte sono effettivamente testo e quali no, perciò li sostituisce tutti. Per superare questo inconveniente basta cambiare la tabella in uso, tornando ad ASCII, o quello che è un uso dal vostro programma. Di solito tale comando sta o in file o in modifica. (in windhex File>Swap table file)
Ora arriviamo al problema XVI: purtroppo non riesce ad astrarre i caratteri, perciò la soluzione che adotta è sostituirli fisicamente nella vista di sinistra! [emoji33] Se salvate vi ritroverete una ROM sicuramente corrotta! NON SALVATE LA ROM DOPO AVER APPLICATO LA SOSTITUZIONE CON XVI!
Ora impareremo a cambiare il testo direttamente con l'hex editor. Come funziona questo metodo? Se sapete trovare e modificare i puntatori lo applicate alla svelta.
- Individuate il testo da modificare con la ricerca di stringa, di testo stavolta
- ricavatene il puntatore
- cercate il puntatore dall'inizio della ROM. Meglio se pochi (1) risultati, perchè significa che la risorsa è usata una sola volta. Nel caso del testo dovrebbe essere così. Segnate l'offset.
- andate in spazio libero (createne il puntatore) e scrivete! Bisogna però stare attenti alla larghezza, in quanto finora tutti gli hex editor adottano larghezza fissa delle colonne. In Certi casi torna utile, ma non in questo. Indicativamente, in minuscolo potete scrivere 30 lettere.
- andate al primo offset segnato. Contiene il puntatore al vostro testo. Dovrete sostituirlo con il puntatore al nuovo testo.
Se conoscete un hex editor migliore di quelli elencati in questo corso (windhex, XVI, HxD) per favore segnalatelo.
Come potete notare non ci siamo spostati neanche per un attimo dal programma corrente, quindi, se il testo è favorevole da scrivere, questo consente di risparmiare un po' di tempo rispetto ad altri metodi.
Come vedremo nelle ultime lezioni, disporre dei testi di una ROM è essenziale per iniziare piuttosto agevolmente alcune particolari ricerche di ASM.
Come compito modificate un testo come volete. (tanto poi fatto uno fatti tutti)
---
#PARTE 2
LEZIONE 2
UNA LENTE D'INGRANDIMENTO SUL GBA
#CAMBIAcolore
I moderni calcolatori sono costruiti secondo l'architettura di Von Neumann (in opposizione a quella di Turing che non è da meno, ma con i moderni dispositivi è inefficiente e poco gestibile, anche se ha grande rilevanza teorica).
Questo significa che Il cuore del dispositivo è la memoria centrale (nome rigoroso per RAM, ovvero la memoria temporanea in cui stanno i dati che devono essere elaborati). Tutte le componenti del dispositivo comunicano con la memoria centrale e con il processore. https://www.google.it/search?q=architett...on+neumann&biw=1366&bih=661&source=lnms&tbm=isch&sa=X&sqi=2&ved=0CAYQ_AUoAWoVChMIn_aVvp6pxwIVLjnbCh1X9Ay9
Anche il GBA funziona secondo questo schema. Apriamo il VBA normale e andiamo nel menu a tendona "tools" e apriamo tutto da "io viewer" a "tile viewer". Cosa è tutto questo macello? Sono le varie parti del GBA, servono per "dissezionare" il gioco e ricavarne le modifiche. Ora possiamo chiuderle tutte tranne una, il memory viewer. Essenzialmente tutte quelle finestre possono essere ricondotte al memory viewer, in quanto il contenuto di ciascuna è solo una forma comprensibile di ciò che sta nella memoria. Con il memory viewer avete accesso a tutte le macro aree della memoria del GBA (spiegate tra poco)
Come vedrete, ci sono dei buchi. Questo non significa che la memoria del GBA abbia dei buchi (è piena di tarli!) oppure sia davvero grande 09000000h, che è più di 100 MB! Semplicemente lei fisicamente sarà come sarà, ma viene "mappata" logicamente secondo tali indirizzi. Questo procedimento è un'astrazione dall'ambiente fisico, e grazie ad essa è possibile manipolare indipendentemente qualsiasi settore.
Tutto ciò trova un'applicazione pratica: il WBTO.
Questo comando degli script permette di scrivere un byte in una locazione di memoria di quelle elencate prima.
Non si può veramente "insegnare il WBTO", a parte perchè l'ho appena fatto nel periodo precedente (si, la frase precedente è "insegnare il WBTO"), ma soprattutto perchè questo comando presuppone che ci sia uno studio dietro la sua applicazione, in modo da ottenere l'effetto ricercato. Ok, posso dirvi cosa dovrete scrivere nella memoria per ottenere qualcosa, ma allora l'insegnamento si riduce a una semplice elencazione di valori, cosa che potete trovare benissimo per il WEB (e quelli di forumcommunity ne sanno qualcosa, vero?). Qui vi spiego COME funzionano gli offset di memoria, in modo che possiate sviluppare il vostro atteggiamento critico verso la realtà (mi sembra filosofia  ) che vi porterà a fare le vostre nuove scoperte. Se poi unite questo al potente strumento che è la documentazione degli offset scoperti (cui vi consiglio di partecipare all'ampliamento) allora sarete un'arma dal grande potenziale. Tutta questa manfrina poetica per dire cosa? Per introdurre la
SPIEGAZIONE SU COME FUNZIONA LA MEMORIA
#Todo prendi da tonc
- 08 : La nostra ROM. Ed ecco spiegato il motivo del mettere lo 08 al puntatore. Ogni puntatore visto fino ad ora si riferiva alla ROM, perciò si metteva per forza il byte 08. Ora sostituite il passo "metto 08 al puntatore" con "metto il numero della memoria che voglio usare".
- 09 : Per accedere alla ROM dai 16 MB a 32 (il massimo) si usa questo prefisso. l'offset è quello che sarebbe con l'origine relativa in 08FFFFFF (quello che avevamo detto la scorsa volta sugli scostamenti torna molto utile).
- 07 : è una memoria piccolissima che contiene le informazioni sugli oggetti. un oggetto può essere qualunque cosa, da un people di advance map a un elemento dell'interfaccia grafica. Trovate maggiori informazioni nelle guide di andera/feanor.
- 00 : BIOS di sistema. è una cosa che tutti i computer hanno, e contiene "l'essenza della vita", ovvero, più seriamente, tutto ciò che serve a far funzionare il computer a livello basilare (del tipo accendersi, rispondere ai tasti, ecc). Non a caso l'acronimo sta per Basic Input/Output System. Noi potremo trarre vantaggio dal BIOS con l'ASM, in quanto potremo usare alcune funzioni non proprio elementari contenute in esso: ad esempio la decompressione dei dati, oppure funzioni matematiche come il seno. Già, non sembrano molto essenziali per far funzionare una macchina, ma probabilmente sono state inserite perchè di frequente uso nei giochi.
- 0E : SRAM, ovvero il salvataggio.
- 02 : WRAM, La memoria temporanea che hanno tutti i computer. Qua abbiamo la bellezza di 256 KB di RAM.
- 03 : Con questo codice ci si riferisce all'IRAM, ovvero una memoria interna (come suggerisce l'iniziale) al processore. è molto più veloce di quella normale, ma è grande solo 32 KB. Meglio non utilizzarla per i nostri scopi, rischieremmo solo di fare dei casini.
- 05 : Contiene le palette da utilizzare. contiene 16 palette per un totale di 256 colori. Non è modificabile, perchè viene costantemente aggiornata prendendo i dati dall'indirizzo 0202EEC8 (ROM AXVE)
- 04 : Questa locazione si chiama registri di Input/Output. è un minuscolo settore in cui ci stanno i valori interni del GBA per utilizzare le periferiche.
- 06 : VRAM. Questa è la memoria Video da 96 KB. Il suo contenuto è grezzo, per visionarla in forma comprensibile si usano il tile viewer e il map viewer. Le map essenialmente sono ciò che forma l'immagine da visualizzare: Sono dei riferimenti ai tiles. Ci possono essere fino a 4 strati, chiamati BG, in un gioco GBA. In pokemon il BG0 è utilizzato principalmente per l'interfaccia. Gli altri variano a seconda del contesto, ma durante l'overworld sono usati tutti e 3 per le varie altezze dei blocchi. Ad esempio il tetto delle case è nel BG1.
L'elemento minimo che costituisce la tilemap (quella cosa che compone il BG e si edita con cyclone e NTME) è formato da due bytes. Il primo indica il numero del tile da prendere, mentre il secondo bytes viene diviso in 2. I primi 4 bit indicano la palette scelta tra le 16 disponibili. I secondi 4 indicano la "base" dei tiles, ovvero la "pagina" di 256 tiles da scegliere; se ci pensate un attimo queste informazioni sembrano messe in ordine innaturale rispetto a come ci verrebbe da pensare; infatti vanno invertiti, sempre per la storia del little endian che se bazzicate in R&D avrete sicuramente incontrato (cercate "ordine dei byte" su Wikipedia), per cui effettivamente il GBA legge pagina, palette e numero del tile, ovvero qualcosa di più comodo per noi (dunque per chi proggettava il GBA). So che tutto questo non è un concetto molto semplice, magari ne riparleremo più avanti, con l'asm.
Ricordate comunque che per ogni esigenza di consultazione tecnica esistono i siti internet:
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm (facile)
http://problemkaputt.de/gbatek.htm (difficile)
Ora che sapete un po' meglio come funziona la mappatura della memoria, vi mancano gli offset. In questo forum io mi sto battendo per avere una raccolta ordinata di tutti gli offset, ma l'idea sembra non riscuotere successo. Comunque se volete sono qui
http://pokehack.altervista.org/showthread.php?tid=1754
http://pokehack.altervista.org/showthread.php?tid=2012
poi boh...
Altrimenti potete sempre bazzicare in altri fori e gozzovigliare un po' (e magari venire a riportarmi cosa scoprite). Io di sicuro prima o poi farò passare tutte le discussioni della macroarea apprendimento e ne coglierò ogni offset. Noiosissimo, lo so.
ecco una dettagliata spiegazione di ogni singolo freakin' registro:
Ecco ora qualche esempio di WBTO:
difficoltà facile:
hmm, non mi garba molto il colore dell'erba del percorso 101. Aspetta che chiamo il giardiniere...
Codice: #org @start
writebytetooffset 0x19 0x0202ef22
writebytetooffset 0x29 0x0202ef23
end
et voilà, ora è diventata di un bel rosso sangue!
Spiegazione: sostituisco il qattordicesimo colore della terza palette.
difficoltà media:
Recentemente sono riuscito ad implementare una feature che per l'utente non ha rilevanza, ma può tornare utile a noi sviluppattori. Si tratta di dirottare i dati delle tabelle nella RAM. Come mai fare una cosa che "a orecchio" sembra complicata? Perchè può capitare di arrivare a 255 elementi di una tabella indicizzata con un byte e dunque non poterne più inserire nessuno, a meno di avventurarsi nell'asm per cambiare il modo con cui vengono trovati gli elementi. Ma basta con le chiacchiere e passiamo ai fatti: Sono riuscito a dirottare in RAM i multichoice. Come ben sapete i multichoice sono circa 80, ma possono essere al massimo 255, perchè in XSE viene detto chiaramente che l'ID occupa un byte. E se li finiamo? Semplicemente diciamo al GBA di andare a trovare i testi in RAM, così se ne possono mettere quanti si vuole! Dovrete sacrificarne alcuni, ma ne avrete infiniti! Quanti ne servono? dipende da voi, uno per ogni numero di scelte. Significa uno per una scelta, uno per due scelte, uno per tre scelte, e così via, fino al numero che volete. Il massimo che si può fare senza corrompere il gioco è 9. gli ultimi 9 multichoice si riferiranno agli ultimi 9 puntatori dei boxset (per approfondimenti vi rimando al topic ufficiale del multichoice), i quali punteranno alla RAM. Per poter utilizzare la tecnica negli script occorrerà fare un wbto nell'area designata, con i caratteri che abbiamo visto la volta scorsa, e successivamente chiamare il multichoice.
Esempio di script funzionante (ovviamente servirebbe anche la modifica del MC da fare sulle vostre ROM):
Codice: #org @start
writebytetooffset 0xBB 0x2000000
writebytetooffset 0xFF 0x2000001
writebytetooffset 0xBC 0x2000002
writebytetooffset 0xBD 0x2000003
writebytetooffset 0xFF 0x2000004
writebytetooffset 0xBE 0x2000005
writebytetooffset 0xBF 0x2000006
writebytetooffset 0xFF 0x2000007
msgbox @string1 MSG_FACE //"PROF. BIRCH spends days in his LAB..."
multichoice 0x0 0x0 0x0 0x0
ho dovuto metere un testo se no non rimaneva fermo il riquadro. L'effetto è
http://pokehack.altervista.org/attachment.php?aid=309, non contate il fatto che ci sono solo 2 testi invece di 3, era una prova. (inoltre, finchè non sistemerò bene i testi, guardate qui per come realizzarlo: http://pokehack.altervista.org/showthread.php?tid=2795)
Spiegazione: A parte la modifica al multichoice che non è mostrata, ho semplicemente scritto del testo nella RAM, che viene letto correttamente dal programma multichoice.
compiti? Boh, non saprei, ci possono essere mille utilizzi differenti, a seconda della situazione! noi in un contesto come questo non abbiamo nemmeno delle occasioni, degli stimoli ad usarlo, in quanto operiamo (si presume) su ROM pulite, perciò non abbiamo le necessità che scaturiscono da un progetto reale. inoltre qua siamo liberi di fare ciò che ci sentiamo, senza vincoli (non come in altre lezioni). Dunque facciamo così: a scelta tra
1) o fate qualcosa di vostro con il WBTO (tipo cambio palette, operazione sui dati, ecc),
oppure
2)mi spiegate il funzionamento di uno dei "codici da inserire nelle ak rum" (sarebbero i WBTO) che trovate su forumcommunity internet.
Così avete la scelta tra un compito più pratico e uno più teorico.
Ovviamente qualcosa di facile per il momento.
Consigli: per fare il primo, pensate al vostro obiettivo, poi scovatene l'offset. come funziona l'obiettivo? Se voglio ottenere questo, cosa devo mettere?
Per fare il secondo compito cercate l'offset indicato dal comando, e andate a vedere in quale memoria (e in quale settore in alcuni casi) risiede. pensate a cosa fa tale locazione e come si comporta con il nuovo byte.
Preparatevi, le prossime lezioni saranno corpose!
Se avete dubbi come sempre non esitate a chiedere, ciao
stavolta avete tempo una settimana.
ecco dopo molto tempo la vostra lezione! dopo questa staccherò per un po', ma potrete comunque pormi domande.
mi raccomando come al solito leggete attentamente tutto e ponderate ogni frase, il programma è enorme e sono costretto a fare grandi tagli, ciò che esprimo in una frase in realtà potrebbe essere uno spunto d'approfondimento per intere pagine
.
LEZIONE 3.1
DA UN PROBLEMA ALLA SOLUZIONE:
INTRODUZIONE ALLA PROGRAMMAZIONE
Siccome questo è un argomento troppo importante per essere saltato, vi tocca. Senza di esso potreste avere varie difficoltà in seguito, perciò ho deciso di affrontarlo una volta per tutte. Inoltre è un requisito nel caso in cui voleste imparare un linguaggio di programmazione ad oggetti (come il Ruby, usato in rpg).
___
Ogni giorno ci troviamo a dover risolvere dei problemi. Ad esempio scegliere cosa fare da mangiare o montare un mobile sono alcuni dei problemi quotidiani. La maggior parte di essi sono risolti istintivamente da noi; non necessariamente nel senso che usiamo l'istinto, ma che non ci riflettiamo più di tanto perché viene spontaneo. Mentre se il problema è più difficile (montare il mobile) dobbiamo seguire le istruzioni che ci vengono fornite. Anche i computer vengono utilizzati per risolvere problemi, infatti è il loro scopo principale (a parte giocare e visitare pokehack e i socialnetwork :p) Una volta erano prevalentemente di tipo matematico (i primi computer erano solo enormi calcolatori), mentre oggi si utilizzano per qualsiasi scopo: esempio previsioni del tempo, controllo di una centrale atomica, realizzazione di grafica. I computer però non ragionano da soli, serve qualcuno che li "istruisca" per fare tutte queste cose utili, ovvero il programmatore. Ebbene, c'è una similitudine tra il computer e noi che montiamo un mobile: seguiamo delle istruzioni scritte da altri. Questo insieme di istruzioni viene chiamato algoritmo. Si potrebbe scendere nei dettagli sulle proprietà degli algoritmi, ma dovrei andare a riprendere gli appunti di tanti anni fa(magari posso farlo per le prossime lezioni). Perciò per il momento ci concentriamo sul capire bene come funzionano questi algoritmi. Ne incontriamo a bizzeffe ogni giorno, il mondo ne è pieno. Sostanzialmente, ad ogni problema risolvibile è possibile associare un algoritmo risolutivo. Un algoritmo è una sequenza di passi (istruzioni) da eseguire per risolvere un problema.
Ad esempio per preparare la pasta ci sono dei passi che il cuoco esegue: accendi il Gas, metti l'acqua, ecc. Anche se può sembrare naturale, in realtà una qualsiasi azione è il frutto di ben precise "istruzioni", eseguite in sequenza dal nostro cervello.
Un altro esempio di algoritmo molto semplice lo avevamo visto le volte scorse, quando vi avevo detto come ricavare un puntatore o indicizzare una tabella.
La programmazione è l'"arte" di istruire i computer. per farlo serve elaborare un algoritmo che risolve il problema. in questo corso non risolveremo problemi di tipo strano, come la costruzione di un mobile o la preparazione di una pietanza; agli inizi saranno prevalentemente di tipo matematico per prendere confidenza con le strutture necessarie, e poi sposteremo il campo verso la piattaforma GBA e i pokimunz.
Un esempio di problema che vi potrei dare di compito: determinare il massimo tra una serie di numeri.
Un esempio di problema che potreste ritrovarvi a risolvere durante l'hacking: eliminare un pokemon esausto dalla squadra.
Adesso compirò quella "brutta cosa" che è copiare wikipedia (perchè non voglio scavare nei quaderni lol) per informarvi sulle proprietà degli algoritmi per aiutarvi a capire il tipo di procedimento necessario:
- I passi costituenti devono essere "elementari", ovvero non ulteriormente scomponibili (atomicità)
- I passi costituenti devono essere interpretabili in modo diretto e univoco dall'esecutore, sia esso umano o artificiale (non ambiguità)
- L'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di dati in ingresso (finitezza)
- L'esecuzione deve avere termine dopo un tempo finito (terminazione)
- L'esecuzione deve portare a un risultato univoco (effettività).
In generale non esiste una sola soluzione ad un dato problema; le soluzioni potrebbero essere numerose. La programmazione consiste proprio nel trovare la strada più efficiente che conduce alla soluzione del problema in oggetto. Ecco perchè programmatori diversi possono dare diverse soluzioni (magari corrispondenti a diverse visioni del problema), anche se entrambe corrette.
"Ho capito, ma come faccio a risolvere un problema?" bisogna precisare che non esiste una "ricetta" universalmente valida, ma ci sono dei paletti che definiscono in generale un percorso da seguire per semplificare l'approccio.
Per risolvere un problema innanzitutto bisogna "prenderlo" e analizzarlo. La prima cosa da fare è stabilire cosa richiede la soluzione (output) e cosa dobbiamo conoscere in principio per poter risolverlo (input). Prendo l'esempio del massimo: cosa devo fornire al programma e cosa deve "buttar fuori"? Devo inserire alcuni numeri, e devo ricevere ancora un numero (non è detto che si utilizzino sempre solo i numeri per operare, si può anche operare sul testo, sulle immagini, sui pokemon, ecc, così come il programma potrebbe dare quelle cose come soluzione)
Poi esistono due diversi approcci, entrambi validi, per analizzare il problema e iniziare a determinare una soluzione. Il secondo è sconsigliato ai Principianti.
Top-down e Bottom-up; Come suggerisce il nome, i due sono opposti.
Nel modello top-down si formula inizialmente una visione generale del sistema, ovvero se ne descrive la finalità principale senza scendere nel dettaglio delle sue parti. Ogni parte del sistema è successivamente rifinita aggiungendo maggiori dettagli della progettazione. Ogni nuova parte così ottenuta può quindi essere nuovamente rifinita, specificando ulteriori dettagli, finché la specifica completa è sufficientemente dettagliata da validare il modello. Il modello top-down è spesso progettato con l'ausilio di "scatole nere" che semplificano il riempimento ma non consentono di capirne il meccanismo elementare.
In contrasto con il modello top-down c'è la progettazione bottom-up, nella quale parti individuali del sistema sono specificate in dettaglio, e poi connesse tra loro in modo da formare componenti più grandi, a loro volta interconnesse fino a realizzare un sistema completo. Le strategie basate sul flusso informativo bottom-up sembrano potenzialmente necessarie e sufficienti, poiché basate sulla conoscenza di tutte le variabili in grado di condizionare gli elementi del sistema.
Ricapitolando le differenze ma senza scendere troppo nei dettagli tecnici, abbiamo che:
La programmazione top-down è uno stile di programmazione in cui la progettazione inizia specificando parti complesse e suddividendole successivamente in parti più piccole (divide et impera). Eventualmente, i componenti sono specificati quanto basta per la codifica ed il programma viene anche scritto.
Il bottom up prende corpo dal punto di partenza (bottom) ovvero dalla situazione iniziale; considera l'obiettivo finale, induce a costruire un percorso sequenziale organizzato in passaggi successivi in cui l'ancoraggio tra traguardi intermedi e obiettivo finale è generalmente ricercato in modo intuitivo (euristico).
Come compito potreste descrivermi nel linguaggio a voi più naturale (es: italiano scritto) la risoluzione di un paio di problemi. (non copiatevi)
nella lezione successiva vedremo di formalizzare le vostre soluzioni con opportuni metodi e iniziare la programmazione.
ESEMPIO: dati 3 numeri, determinare il maggiore
(suggerimento: chiamate i numeri in qualche modo, come ad esempio A,B,C. vi aiuterà nello stabilire le condizioni delle "sentenze")
- chiedo all'utente i valori dei 3 numeri, uno per volta
- li confronto due a due (posso compiere solo operazioni basilari)
- quello che "vince più volte" è sicuramente il maggiore.
COMPITO:
facile: Calcola l'area di un n-agono (figura geometrica regolare con n lati) (n a scelta dell'utente) (SUGGERIMENTO: vai a rivedere le formule)
facile/medio (ma dipende dal livello di formalismo del linguaggio usato): fornire i primi 40 multipli di 13 (SUGGERIMENTO: dovrete contare le volte...)
facile/medio: Dati due numeri effettuare il loro prodotto usando solo l’operazione somma
medio: Calcolare le soluzioni reali dell'equazione ax^2+bx+c=k (SUGGERIMENTO: torna comodo un linguaggio matematico)
(in caso non abbiate ancora affrontato l'argomento a scuola, potete saltarlo)
changelog:
- 160613: liste, maiuscole, interpunzione, sistemazione alcune frasi sconnesse, sbianchettato una frasi
- prima: boh
ciao
# quando metti le funzioni aggiungi questo
You can think of a procedure like a spy who leaves with a secret plan, acquires
resources, performs the task, covers his or her tracks, and then returns to the point
of origin with the desired result. Nothing else should be perturbed once the mission
is complete. Moreover, a spy operates on only a “need to know” basis, so the spy
can’t make assumptions about his employer
prova
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere e guarda notepad
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
20-07-2016, 06:26 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:11 PM da Bonnox.)
e questa è la famosa guida sulla grafica che ho tanto promesso in giro e spero faccia la gioia di molti.
ovviamente non mi ssumo alcuna responsabilità, è incompleta e nessuna aul al'ha mai vista finora.
LEZIONE 2.1
VOLARE, OH, CANTARE, OH OH OH OH. NEL 0x7C00, DIPINTO DI 0x7C00
-
LA GRAFICA
okokok scusate la canzoncina idiota, forse dalla prossima volta la cambierò.
questa sarà probabilmente la lezione più corposa di tutte, perciò preparatevi!
Ciò che vedremo oggi non riguarda propriamente nè il WBTO nè l'ASM, ma fa comunque parte della conoscenza basilare sul GBA che uno deve avere quando modifica i giochi di pokemon. E poi è sempre roba sui byte 
Ci tengo a farlo perchè ho visto che nei forum regna sovrana molta confusione, per cui speravo di fugare ogni dubbio.
Oggi parliamo di grafica. Quella cosa che gli utenti finali vedono e usano per giudicare, ma che fa sempre imbestialire i programmatori perchè è complicata ed è soltanto un "accessorio" alla struttura del suo programma.
Volevo fare un'introduzione un po' più profonda ma va bene anche così, passiamo senza indugi alla lezione! # scusate ancora se la formattazione non è delle migliori, è la prima volta che scrivo queste cose, mi concentro prima sui contenuti
prima di iniziare una nota importantissima: oggi parleremo in detaglio della memoria 06, ma fate attenzione ad una cosa: non potete scrivere sulla memoria 06 un solo byte alla volta. Se lo fate, quel byte e anche il suo vicino assumeranno lo stesso valore. Per sopravvivere, dovrete (con l'ASM o un linguaggio di alto livello come il C o il Pascal che forse alcuni di voi conoscono) leggere ciò che c'è attualmente in un frammento di 2 o 4 bytes, sostituire il byte voluto, dopodichè rimetterlo.
i colori sono quelle cose formate da onde elettromagnetiche che captano i nostri occhi (trovate una descrizione più migliore su wikipedia).
Il GBA possiede la capacità di mostrare ben 32768 colori. Un colore in formato "grezzo" è composto da 2 byte così ripartiti:
il primo bit deve essere sempre 0. Se dovesse essere 1, sarebbe un colore non consentito: Sul VBA viene renderizzato con quel bruttino fuchsia schocking, mentre non ho mai provato a vedere come sia su hardware.
seguono 3 gruppi di 5 bit: ogni gruppo rappresenta un valore da 0 a 31 per ciascuno dei 3 colori primari (blue, green, red). Cambiando questo valore, il colore sarà più chiaro o più scuro relativamente a quel canale.
Facendo dei semplici conti, viene fuori, ad esempio, che il bianco è 0x7FFF e il nero è 0x0000 (che scoperta). Provate per compito a costruire i seguenti colori, vi aiuterà a diventare pratici nel maneggiare i bit:
- rosso a 20, verde e blu a 5
- verde a 20, rosso e blu a 5
- blu a 20, rosso e verde a 5
per i colori abbiamo finito.
il GBA ha varie modalità di funzionamento grafico, e alcune di queste sono le modalità bitmap, considerate più semplici da capire.
Cos'è un bitmap? è una matrice a due dimensioni ("map") che contiene i colori ("bit"). Come su programmi grafici al computer (esempio paint), ad ogni casella della tabella corrisponde un colore, salvato come abbiamo visto precedentemente.
okkei, ma come funziona esattamente? Ci sono 3 modalità bitmap, la 3, 4 e 5. Per attivarle dovrete scrivere tale valore nel registro DISPCNT, con WBTO, ASM oppure con l'IO viewer del vostro emulatore (sul VBA è nel menu tools). Dopodichè, tenendo conto di alcuni dettagli spiegati in seguito, vi basterà scrivere sulla memoria grafica i colori che volete, all'indirizzo corretto, ovviamente. Per calcolare l'indirizzo, tenete conto di quanto detto in precedenza sugli offset e le tabelle, e ricordate che la risoluzione del GBA è di 240x160 pixel.
Tabella riassuntiva delle modalità.
mode | width | height | bpp | size | page-flip
|
3 | 240 | 160 | 16 | 1x 12C00h | No
|
4 | 240 | 160 | 8 | 2x 9600h | Yes
|
5 | 160 | 128 | 16 | 2x A000h | Yes
|
Cosa significano quei due termini nuovi?
BPP significa "bit per pixel". La traduzione è inutile, ma sappiate che più è alto questo numero, più colori potrà avere il vostro pixel. un valore molto comune nei giochi pokemon è 4. Il massimo valore del GBA è 16 (che però è come se fosse 15, vedi sopra). Il primo game boy aveva 2 BPP. (ricordi d'infanzia...)
Page flipping si riferisce a una tecnica usata nella computer grafica. Se voi modificate la bitmap mentre l'hardware del GBA sta disegnando a schermo ciò che è contenuto nella memoria (cosa molto probabile perchè entrambi i processi richiedono parecchio tempo), avrete un fastidioso effetto "flickering", tipo sfarfallio. La soluzione è avere due immagini separate, così mentre una è visualizzata, potete disegnare sull'altra indisturbati e non causerete nessun orrore visivo. Quando avete finito di disegnare l'altra immagine, "voltate pagina" (da cui il nome) che deve essere visualizzata.
Per cambiare pagina, scrivete 1 o 0 sul bit 4 del registro DISPCNT. La seconda pagina si trova all'indirizzo 0x600A000. Ovviamente la modalità 3 non dispone della seconda pagina perchè occupa troppo spazio! :p
Bene, eccoci ad uno degli argomenti più importanti, nonchè tra i più controversi.
Avrete notato come nella tabella dei modi grafici abbia usato la scrittura 8bpp, quando prima avevo appena finito di dire che i colori sono composti da 16 bit. Come si spiega questo fatto? Ovviamente con le palette, dato che è l'argomento corrente, lol.
Come ho spesso detto, le console portatili intorno agli anni 2000 (e le fisse venti anni prima...) erano molto costose da realizzare, perchè la tecnologia non era così avanzata, perciò bisognava trovare ogni modo possibile per ridurre le dimensioni dei dati. Uno di questi sono le palette, l'altro le tilemap (che vedremo dopo).
Questi due metodi nascono dall'osservazione che gli elementi di un gioco presentano rappresentazioni grafiche molto ripetute. Che significa? Prendiamo ad esempio questa immagine di un personaggio Nintendo, e noteremo che presenta pochi colori.
Dopotutto, chi è che va in giro con un vestito a macchie colorate, come i quadri del 900? un colore per la camicia e uno per i pantaloni, semplice. Poi la nostra pelle presenta più o meno la stessa tonalità ovunque. Oggetti di un solo, o comunque pochi materiali, tendono ad avere pochi colori diversi. Perchè allora non realizziamo un "dizionario" di colori? La palette fa questo: raggruppa un insieme di colori, che poi vengono utilizzati da chi disegna. Pensatela come ad una tavolozza di un pittore (credo che significhi pproprio quello in inglese), da cui attinge nel dipingere. Le bitmap indicizzate fanno lo stesso. invece di avere il dato in forma estesa (i 16 bit che indicano un colore), utilizzano solo 2, 4, o 8 bit. Così lo spazio occupato è 1/8, 1/4 o 1/2 dell'originale. Più l'immagine è ripetitiva, meno colori servono, più spazio si risparmia. Ecco perchè a spriting vi insegnano (lo fanno?) quelle tecniche strane di accostare i colori e robe di disposizioni a scacchiera per dare l'illusione di un colore intermedio che non esiste.
Dunque come sarà fatto il dato? Sicuramente sarà diverso. Facciamo un piccolo esempio.
Consideriamo un bitmap di 4x4 pixel per semplicità, due bianchi e due neri.
0x0000 0x7FFF
0x7FFF 0x0000
questa sarebbe la rapppresentazione in modalità a 16 bpp (ricordate che una volta caricati nella memoria, le righe e le colonne scompariranno, saranno tutti in fila indiana).
Fingiamo di essere nella modalità a 8 bpp, e che il nero e il bianco siano i primi due colori della nostra palette. Come risulterà la bitmap? Costruiamola insieme.
Abbiamo 8 bit per ciascun pixel , e i pixel sono 4 -> 32 bit, ma 8 bit fanno un byte = 4 byte
0x?? 0x??
0x?? 0x??
E già abbiamo dimezzato la dimensione.
Ora, come è fatta la palette? Nel GBA ci sono 2 tipi di palette: palette normale e superpalette. quella normale ha 16 colori (4 bit), la superpalette 256 (8 bit). I colori sono semplicemente disposti uno dopo l'altro, come a formare una bitmap di una riga sola (16x1 o 256x1, ma sul palette viewer del VBA sono 16x16). In altri sistemi (tipo GIMP) è altamente probabile che il formato di memorizzazione sia leggermente più complicato, dunque non fate assunzioni. siccome abbiamo detto che i colori nero e bianco sono i primi due (potevano essere il quindicesimo e il quarantottesimo), sostituiremo i byte con l'idice del colore, ovver uno 0 e un 1 (oppure un 14 e un 47, rispettivamente per l'altro esempio).
0x00 0x01
0x01 0x00
E se avessimo a disposizione solo 16 colori? In tal caso avremmo un bpp di 4. Dobbiamo perciò accostare "entità" da 4 bit per ciascun pixel.
entità nero - entità bianco
entità bianco - entità nero
ricordandoci che "entitànero" è "0000b" e "entità bianco" è "0001b", componiamo la bitmap:
0000b 0001b
0001b 0000b
mettiamo insieme i byte:
0x01
0x10
vedete la comodità delle basi a potenza di 2? posso letteralmente giocare a scomporre e ricomporre pezzi di numeri. 0001b e 0000b concatenati fanno 00010000, che in esadecimale è 1 e 0, ovvero 10!
So che sembra una cosa arcana, ma qui sopra, in due byte (01 e 10), ci sono 4 pixel: due per ogni byte. il pixel di coordinate (0,0), ovvero quell in alto a sinistra, occupa i primi 4 bit del primo byte; il secondo pixel occupa i second 4 bit del primo byte; il terzo pixel occupa i primi 4 bit del secondo byte; e così via. I tiles, che vedremo dopo, in pokemon sono memorizzati in questo modo, ovvero a 16 colori.
vedete come esempio il link in versione "palettizzata" a 4BPP
Per compito provate a rappresentare la bitmap a 2 e 1 BPP, sempre supponendo che il nero e il bianco siano i primi 2 colori della palette. Inoltre, quanto risparmierei se usassi 1 BPP rispetto al full bitmap? Con forumula (via Messaggio Privato).
In conclusione, lo ripeto per essere chiaro: la palette (guardate bene come si scrive: è un termine inglese, con una elle e due ti) è un insieme di colori, scelti tra tutti quelli disponibili (32768). Fate come Bart dei simpson che lo scrive un po' di volte alla lavagna, e andate a spargere la buona novella a quelli che storpiano il nome o lo usno per altri significati.
una nota: il colore 0 di ogni palette (che sia di 16 o 256 colori) è usato per la trasparenza. dunque qualsiasi pixel che ha quel colore non verrrà mostrato.
- IL MAGICO MONDO DELLE MATTONELLE
Benvenuti nella seconda e più potente alternativa per comprimere le immagini. Sarà leggermente confusionante all'inizio, ma se leggete piano ragionandoci su sopravvivrete!
Le palette, come abbiamo visto, servono per comprimere i colori, ma possiamo fare di più, ovvero comprimere anche le immagini (io in questo tutorial continuo a usare la parola "comprimere", ma badate bene di non confonderla con la vera compressione a livello di file e byte, la famosa LZ77. Quest'ultima è "lossless", ovvero sfrutta degli algoritmi (tipo zip) per ridurre la diensione in byte dei nostri dati. invece le palette e le mattonelle sono compressioni "lossy", ovvero con perdita di informazioni, e conseguentemente qualità (tipo mp3)).
Cercate sempre di utilizzare le modalità a mattonelle piuttosto che bitmap. Ci sono svariati motivi: sono implementate nell'hardware (perciò non dovrete faticare a fare calcoli per renderizzare le cose), sono dannatamente più veloci, per il motivo precedente, occupano parecchio spazio in meno, sono stratificati, e dulcis in fundo, si possono applicare vari effetti carini (come la mia implementazione della textbox trasparente con il blending; e lo scrolling, pesantemente usato dagli RPG come pokemon).
come si fa? In certi giochi, tipo gli RPG, i platformer, e così via, le ambientazioni sono spesso molto ripetitive. Considerate ad esempio la seguente immagine:
Questa immagine è molto grande, 512x256, e se la facessimo in 256 colori, occuperebbe la bellezza di 131 KB, Che è una volta e mezza ciò che abbiamo a disposizione. Fortunatamente però notiamo che ci sono parecchi "pezzi" ripetuti. Inoltre, sembra quasi che l'immagine sia divisa in aree da 16x16 pixels. Questi sono i tiles. Grazie ai tiles (mattonelle) possiamo costruire immagini molto grandi, purchè ripetitive. Abbiamo a disposizione una tavolozza di tiles, chiamata tile set. E continuando nello stesso modo della palette, in cui un'immagine era formata dagli indici dei colori, adesso l'immagine sarà formata dagli indici della collezione di piastrelle. Così, invece di usare 512*256 entità colore, utilizzeremo (512/16)*(256/16) entità piastrelle. Considerando che i tiles stessi usano le palette (a 16 o 256 colori), il risparmio può essere veramente abissale.
guardiamo come il tileset (a sinistra) viene utilizzato per formare la mappa (a destra):
Ecco come funzionano le tilemaps. Non si definisce l'intera immagine, ma gruppi di pixel messi insieme in piastrelle e si descrive l'immagine in termini di quei gruppi.
Le piastrelle uniche sono nel tileset, che può (e di solito è) essere più grande della tilemap. La dimensione del tileset può variare: se il bitmap è molto variabile, probabilmente avrete molte piastrelle uniche; inoltre, se il disegno è ben allineato (ovvero gli elementi "fittano" una griglia grande quanto la dimensione dei tiles), il tileset sarà più piccolo.
Ora che abbiamo visto la teoria, passiamo alla pratica.
Ci possono essere fino a 4 strati ("BG" sull'emulatore), e i giochi pokemon li usano tutti. La dimensione dei background si cambia con gli opportuni registri e varia da 128x128 pixel fino a 1024x1024. I tiles sono grandi 8x8 pixel. Su advance map infatti potete unire 4 tiles per fare un "blocco".
Ora viene la parte più difficile, state attenti.
Dovete prestare attenzione alla struttura della VRAM, altrimenti potreste avere delle spiacevoli sorprese. Mi aiuto con una tabella.
Memory
| 0600:0000 | 0600:4000
| 0600:8000 | 0600:C000
|
Tileset
| 0 | 1 | 2 | 3
|
Tilemap
| 0 | … | 7 | 8 | … | 15
| 16 | … | 23 | 24 | … | 31
|
Notiamo che i primi 64 KB di VRAM sono destinati ai BG, mentre i rimanenti 32 KB sono dedicati agli sprite, che non vedremo perchè sono simili e più semplici.
Sono disponibili 4 settori in cui collocare i nostri diversi tiles, l'idea è che ogni settore contiene tiles per ciascun layer. Le tilmao invece possono essere collocate in ciascuno degli slot grandi 800h bytes.
Compito: sapendo che ogni "mattone" di tilemap è grande 2 bytes, quale è la grandezza in blocchi di una tilemap che occupa 800h bytes?
Non è per niente difficile: si tratta sempre potenze di 2... :p Tilemap più grandi occupano più slot, ovviamente.
Se aprite una ROM pokemon noterete una cosa strana, ovvero che le tilemap sono tutte in fondo, probabilmente per lasciare uno spazio contiguo più grande possibile per i tiles (dovrebbe semplificare gli algoritmi dell'engine). E niente, è una cosa perfettamente legittima, solo volevo farvela notare.
C'è un problema: sia i tileset che le tilemap condividono la stessa memoria. Per cui agli inesperti potrebbe capitare che per errore i tiles e le mappe si sovrappongano, generando brutti glitch grafici. un esempio potete trovarlo nella sezione domande,
#chiedere a blake se postare
Detto questo, dovete sempre fare attenzione a cosa succede a basso livello nell'hardware (anche se emulato), non solo nei mondi fantastici e idilliaci degli editor di tilemap (cyclone, NTME)...
Dopo tutte queste raccomandazioni, vi informo che per cambiare l'offset della tilemap di un determinato BG bisogna settare i bit 8-12 del registro BGiCNT, dove i è il numero del vostro BG.
Per concludere vi lascio alcune informazioni sparse.
i registri BGiHOFS e BGiVOFS comandano lo scrolling, ma attenzione, sono read-only! Inoltre non rappresentano la posizione della mappa sullo schermo, ma la posizione dello schermo sulla mappa. E' una sottile differenza, un segno meno che cambia tutto:
I bit 2-3 dei BGiCNT servono per scegliere quale dei 4 settori di tiles usare come "base". Questo vuol dire che se nella tilemap c'è un indice di un tile, questo verrà preso partendo a contare da uno dei quattro offset dei settori.
I bit 14-15 regolano la dimensione:
00: 32x32
01: 64x32
10: 32x64
11: 64x64
in unità di tiles.
Anatomia di una "entry" di tilemap (nel caso i programmi "automagici" falliscano):
F E D C | B | A | 9 8 7 6 5 4 3 2 1 0
|
PB
| VF
| HF
| TID
|
TID: tile Identification, ovvero l'indice del tile. Sarà rappresentato sullo scgermo il tile con quel numero, a partire dalla base (i settori) scelta. Tuttavia, se usate la base 3, non potrete sconfinare nella memoria riservata agli sprite.
HF : Horizontal flipping. Sì, potete anche ribaltare i tiles. Come vedete, le modalità tiled sono molto potenti.
VF : Vertical Flip
PB : Palette Bank. ovvero, quale palette avrà il tile. Non ha significato se il BG è a 256 colori ("ficiur" settabile con l'apposito registro CNT)
L'ultimo lascito che vi faccio è un piccolo avvertimento, anche se in pokemon non si verifica. Se usate tilemap più grandi di 32x32 (almeno nell'overworld in pokemon non vengono usate, per questo non si verifica), dovete stare attenti all'ordinamento: purtroppo è presente una limitazione, che fa si che le "entry" di tilemap non siano disposte veramente come una tabella, ma sono come spezzettate in sotto mappe di 32x32, e accostate. Mi spiego meglio con un'immagine.
Dunque, dovrete fare fino a 4 mappe separate. Io personalmente non ho mai dovuto fare mappe così grandi, perciò non saprei se i programmi tengono in considerazione questo aspetto. comunque nei pokemon è una cosa rara, e dubito ne avrete bisogno voi stessi.
Ultima cosa davvero prima di chiudere: se volete abbreviare i tempi di sviluppo, usate usenti (assonanza wow)! ha un esportatore (disponibile anche stand-alone) che è un "life saviour" ! Comprime, genera file .h, .s, palette, tilemap, praticamente è insostituibile!
#compito: tilemap , tiles, palette, 4x4
4 frecce che puntano da diafonale al centro nei 4 esterni x flipping
4 pallini colorati uguali nei 4 centrali per palette
il resto vuoto
CIAONE!
Ciao e benvenuti nella mia aula!
Questo corso si prefigge lo scopo di far comprendere i fondamenti del funzionamento più interno del nostro amato Game Boy Advance, per poter, con la pratica, diventare capaci di alterare anche in modo profondo i nostri giochi! ^^
Vi chiedo di non scoraggiarvi se all'inizio le cose non vi verranno subito. In tal caso bisogna andare a fare un giro per distrarsi, fare un respiro profondo, rileggere attentamente, e nel caso il problema persistesse, consultare il dottore me, che sono qui apposta.
Vi avviso subito che non sono argomenti facili, ma se non avete fretta riuscirete a dominarli.
LEZIONE 0
INTRO
Innanzitutto vi comunico il materiale essenziale:
- Emulatore normale e ROM (facilmente reperibili in commercio). Sapete che preferisco rubino perciò farò più esempi con quella ROM, ma è indipendente quale scegliete, l'importante è essere comodi a lavorarci su.
- Hex editor (spiegato sotto)
- VBA SDL-H
- Assemblatore
- Referenza (quick guide)
Questo invece è Facoltativo: - Documentazione ufficiale ("approfondimento"):
ovviamente non è necessario che leggiate subito quei documenti, anzi, probabilmente non ci capirete niente le prime volte. Li vedremo insieme, a suo tempo.
cominciamo spiegando di cosa si tratta tutto quel materiale:
Il VBA-SDL-H è una versione modificata del VBA che permette di fare cose avanzate per gli hacker, ed è quello che useremo più spesso durante le ricerche, in quanto torna molto utile come debugger e disassemblatore. Funziona da linea di comando, ma come vedrete non è molto difficile da usare.
L'Asemblatore è un programma che permette di passare dal nostro linguaggio ASM al file binario effettivo (codice eseguibile dal GBA).
Entrambi i tool saranno spiegati in dettaglio più avanti.
Per quanto riguarda l'Hex editor c'è un piccolo discorso da fare. Come alcuni di voi forse già sapranno, è un programma che permette di visualizzare il contenuto a basso livello di un file. Esso sarà il nostro "migliore amico", perciò bisogna sceglierlo bene: quello che volete, su internet ce n'è una svalangata tra cui scegliere (actually sto pensando di farne uno anche io, ma le tempistiche saranno MOLTO lunghe), ergo usate quello con cui siete più comodi. I toolz servono per facilitare il lavoro, non per litigarci contro (e vi posso garantire che è infernale non andare d'accordo col programma in uso, mi è successo). Io attualmente uso questi 3 in accoppiata: XVI32, HxD, WindHex, ma non vuol dire che dobbiate farlo anche voi. Per gli utenti Linux invece di gratuito c'è Bless (non possiedo mac dunque non posso consigliarvi in tal caso).
Più avanti vi illustrerò brevemente ciascuno di questi tre.
Ora faccio un paio di considerazioni.
Innalzo il tempo di risposta dai 5 giorni canonici a 8/10 (ma potrebbero essere anche di più). Ovviamente questo vale solo per lo svolgimento di un compito, perché gli altri post non richiedono grandi capacità o applicazione, perchè si limitano ad esporre dei concetti che possono essere interiorizzati in un paio di giorni. Dunque non c'è neanche bisogno di fissare una scadenza per il resto dei messaggi. Questa modifica semplicemente per il fatto che questa è roba di una certa levatura, a volte anche difficile. Potrà sembrare strano, ma come il mapping, anche l'asm richiede tanto tempo... Per la creatività! Pacman Confused no ok magari non è la migliore scelta lessicale, fatto sta che ci può davvero volere del tempo perchè potrebbe essere impegnativo. Dunque avremo orari... flessibili.
A proposito, vi consiglio di sottoscrivere la discussione clickando sul link in fondo alla pagina, oppure la stella di SchifoTalk  così non dovremo più taggarci come dei matti ( anche perché immagino sarete incollati al pannello di controllo per vedere se ho risposto. ok fine autocelebrazione time  ) : avendo sottoscritto, voi vedrete che ci sono nuovi post dal pannello di controllo; io pure perchè sono l'autore.
Allora la mia idea, prescindendo dagli argomenti trattati, era di preferire un post grosso diviso in più parti, in modo da poter analizzare con calma ogni singolo aspetto. Non disdegno la tecnica "mordi e fuggi", ma in questo caso non potrebbe essere applicata per svariati motivi. Magari negli altri casi, come spiegare i comandi di XSE un po' per volta, può funzionare, ma non qui.
Se alcuni concetti esposti in questo messaggio non vi saranno subito chiari non preoccupatevi, li riprenderemo ~
Detto questo ci vediamo la prossima volta, rispondete quando siete pronti per continuare. Smile
Siete autorizzati a mandarmi un (1) messaggio nel malaugurato caso in cui, per qualche motivo, mi dimenticassi di rispondere con una lezione entro una settimana dall'ultimo di voi.
Saluti
#link vba sdl RH
Porgo tutta la mia solidarietà alle popolazioni colpite dal terremoto, al di fuori di questo contesto della school.
wow, sembra quasi che lo faccia apposta a postare a ridosso di festività...
Comunque ecco questa lezione... da paura (o tenebrosa, o spettrale come volete)
let's get it started.
LEZIONE 1
I MATTONCINI DELLA ROM:
IL LINGUAGGIO BINARIO
Purtroppo, come ho già detto, questo corso deve coprire grandi quantità di informazioni. Prima di cominciare, dovrete quindi conoscere il significato di alcuni termini e concetti (ovviamente se li conoscete già potete saltare). Una volta chiedevo come prerequisito la conoscenza di una cosa chiamata "sistemi di numerazione", ma a scanso di equivoci, e per completezza, riporto comunque le nozioni basilari, alla "quick and dirty" (tranquilli che pure loro riescono ad avere argomenti difficili. Uno lo vedremo forse).
Per la vostra gioia, partiamo con un po' di matematica.
Noi umani solitamente contiamo usando le mani, perciò arriviamo fino a 10. Stiamo dunque inconsapevolmente utilizzando la base decimale della notazione posizionale. Che accidenti significa? Semplicemente ogni posizione nel numero ha un significato diverso, ovvero, per esempio, tra 1, 11 e 111 c'è una bella differenza! Questa differenza è un'esponenziale di 10, ovvero, per ogni posizione che aggiungo, il numero aumenta di 10 volte. Inoltre, i numeri si possono esprimere, in forma completa, come somma dei contributi delle singole posizioni:
ad esempio il numero 619 si può vedere come 6*10^2 + 1*10^1 + 9*10^0.
Mentre invece gli antichi romani dovevano fare 500+100+10+10-1, dato che poverini avevano la notazione additiva.
Esistono poi, oltre alle notazioni, le basi. Ovvero il valore del peso di ciascuna cifra. Quando scriviamo numeri "normali" è 10. In informatica si usano molto anche il 2 e il 16. Il binario ha come cifre solo 0 e 1, mentre l'esadecimale ne ha ben 16, ovvero 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.
In generale, Per convertire da qualsiasi basa alla decimale si fa come sopra. Come esempio userò il famoso numero 80C, da esadecimale a decimale:
8*16^2 + 0*16^1 + 12*10^0 (C vale 12) = 2060.
Invece per convertire da decimale ad un altra base Dovete ripetere i passaggi:
- dividete il numero da convertire per la base (esempio 16)
- segnatevi il resto della divisione
- ora il numero da dividere diventa la parte intera della divisione precedente.
e smettete quando arrivate ad un punto in cui andate avanti all'infinito.
http://pokehack.altervista.org/attachmen...mbnail=278
l'esempio mostra la conversionde di 23 in base 2, ovvero 10111.
Una nota: precisate sempre in che sistema state scrivendo quando si parla di numeri, altrimenti ci potrebbero essere disastrose incomprensioni!
è universale mettere un "0x" prefisso ai numeri esadecimali, poi ci sono comunque degli standard... Ecco quelli che io sicuramente "capisco":
- PREFISSE:
- SUFFISSE:
- HEX:
- DEC:
- d
- # (dipende dalla piattaforma usata, in quanto va in conflitto con un altro, io di solito lo uso per numeri a tre cifre)
- BIN:
Per finire con i prerequisiti, diamo alcune semplici definizioni:
- Bit
Elemento che ha origini agli albori dell'informatica. E' un elemento che può assumere 2 stati diversi. Solitamente sono acceso e spento, nati dai valori della tensione in un circuito nei primi calcolatori elettronici, ma il nome cambia a seconda della tecnologia utilizzata (magnetica, ottica, quantistica). Bit è dunque la contrazione dell'inglese BInary digiT. Si rappresenta con le 2 cifre del sistema binario (0 e 1). È l'unità fisica minima nell'informatica.
- Byte:
È l'unità logica fondamentale, composta da un gruppo di 8 bit su un qualunque supporto di memorizzazione (cd, hard disk, radio frequenze...) Se facciamo la combinazione di tutti i suoi termini, vediamo che può assumere 2^8 = 256 stati diversi. Nel nostro sistema decimale si parte da 0 e si arriva a 255. In binario si parte da 00000000b e si arriva a 11111111b. In esadecimale, la base che useremo più spesso, quei valori si scrivono 0x0 e 0xFF.
Perchè un byte si rappresenta in esadecimale? perchè è il modo più veloce, in quanto ha solo 2 cifre, e ciascuna rappresenta separatamente 4 degli 8 bit, cosa che non avviene in base 10.
- Offset:
letteralmente "scostamento" in inglese, indica lo spostamento di un preciso byte relativamente a un'origine. Noi fortunatamente consideriamo sempre tale origine come il primo byte della ROM, dunque indirizzo 0 (ricordo che in informatica si inizia sempre a contare da 0), il chè semplifica i conti; ma non è raro il caso di dover iniziare a contare a partire da un altro valore: ad esempio per hacking di altre console, principalmente nintendo (il caso più vicino a noi è il GB) si divide la ROM in varie parti di uguale grandezza, e ognuna determina una diversa origine del valore dell'offset.
- Puntatore:
generalmente in informatica è un valore che indica, da cui l'usanza di dire "punta", un'area della memoria della macchina. Generalmente nei computer indica la RAM, ovvero la memoria temporanea che contiene i dati in attesa di essere elaborati; Mentre noi avremo quasi sempre a che fare con puntatori alla ROM, che è la memoria di sola lettura in cui risiede il gioco.
Come avrete capito in questa prima parte lavoreremo sui byte; nonostante ahimè sia un lavoro noioso secondo me è più facile da comprendere rispetto ad altro.
Ogni file sul nostro computer è composto da una serie più o meno lunga di bytes. Come avrete avuto modo di notare usando il PC, la rom occupa esattamente 16 MB, il che è veramente poco, ma dobbiamo considerare che risale al 2002 e per giunta è per una piattaforma mobile.
All'interno di ogni programma informatico (tra cui il gioco) ci sono, stipati insieme, due elementi: Istruzioni e Dati. La loro presenza dovrebbe far funzionare correttamente il tutto. Le istruzioni sono ciò che vedremo con l'Assembly, ovvero il "codice" che il GameBoy esegue una volta caricato il gioco, come ad esempio "fai questo suono", "memorizza tale valore", “visualizza l’immagine”, "muovi la pokeball", eccetera. I dati invece sono informazioni conservate nella ROM con un preciso formato, ma da soli non basterebbero a dar vita al gioco. In realtà come già detto Servono tutti e due, ma se uno ha solo i dati non fa nulla, mentre se ha solo le istruzioni qualcosa di minimo fa - vedasi pokemon essentials. Le prime versioni avevano pochissimi dati, però funzionava. Ad esempio sono dati le musiche, le mappe, i pokemon degli allenatori, i testi dei messaggi…
Tutto ciò che non rappresenta il comportamento del sistema è un dato. Coincidenza, tutto quello che viene modificato dai programmi è un dato. Advance map modifica i dati. Ricordatevelo.
In questa sezione imparariamo a farlo anche senza programmi, non perchè io sia cattivo o cosa, ma in alcune occasioni può tornare utile. Comunque tranquilli, una volta imparato non dovreste più averne molto bisogno, ma sempre meglio sapere come fare.
E' altresì importante chiarire il fatto che di per sè non esisterebbe la distinzione tra istruzioni e dati. Infatti, sia le istruzioni che i dati sono rappresentati sotto forma di bit e byte. I dati possono essere anche erroneamente interpretati come istruzioni, ma anche viceversa (vedasi i vari glitch di pokemon red), e se per noi è un fastidio in quanto tutto va male, per la macchina in realtà non cambia assolutamente nulla. Sta al creatore controllare che il suo gioco non si comporti in modo errato. Sul computer questo invece non succedde quasi più da quando esistono sistemi operativi solidi, ma nel caso dovesse accadere probabilmente c'è un virus nel computer.
Bene, eccoci alla vera lezione. Mi scuso se sarà un po’ monotona, ma è importante. Come diceva un mio professore, “il brutto delle cose facili è che vanno sapute perfettamente”.
In questa lezione faremo una partenza soft con l'hex editor, giusto per prenderci la mano.
Aprite un hex editor. L'Hex editor è un software che ci permette di visionare e modificare i bytes di un file. Ecco come si presentano alcuni di essi una volta aperti:
http://pokehack.altervista.org/attachment.php?aid=297
Iniziamo caricando un nuovo file. Consiglio un file che non vi serve più (ad esempio potete creare un nuovo documento di testo da usare come cavia), dato che andremo a pasticciare e a rovinare
Normalmente troveremo tre colonne: la prima, piccola, indica l’offset in cui ci troviamo, quella centrale visualizza tutti i byte, e l’ultima colonna ci indica gentilmente la loro rappresentazione testuale, cosa di cui non potrebbe fregarci di meno, dato che per noi è inutile. L’unico utilizzo che può avere per noi tale parte è per “rincuorarci”, ovvero trovare un piccolo conforto in caratteri familiari di fronte all'agonia della prima vista dei bytes. Ok, dovrò andare a fare il drammaturgo  Posizionate il cursore e clickate sulla colonna a destra, e iniziate a scrivere cose a caso sul file cavia. Notate che c’è una corrispondenza a sinistra con ciò che scrivete?
Ora vorrei che vi prendeste un attimo di tempo per fare una cosa. Iniziate a scrivete tutte le lettere dell'alfabeto, dalla a alla z, minuscole e maiuscole, e poi anche i numeri. Cosa notate? I byte a destra assumono precisi valori. Signori, questo è l’ASCII. Questo è uno standard americano di comunicazione abbastanza datato, ma è usato come base dei più recenti (ad esempio le emoticon di wozzap). In pratica assegna ad ognuno dei valori ottenibili da 7 bit a un carattere o simbolo. La tabella attualmente diffusa è quella di MS-DOS, mentre tanto tempo fa c'erano discrepanze a seconda del sistema operativo.
Ora prendiamo confidenza con le funzionalità del'H.E.. Non so il percorso del mouse da seguire con il vostro, ma esiste una scorciatoia praticamente universale che tutti implementano: CTRL+F. Si aprirà una finestra chiamata ricerca. Qua ci mettete del testo che volete venga cercato all'interno di un file. Se state usando una rom di pokemon non avrete fortuna, perciò cambiate subito file. Potete ad esempio scegliere un documento di office di quelli vecchi (.doc e non .docx ). Dopo aver avviato la ricerca il cursore si posizionerà sulla prima occorrenza; per cercare ancora premete F3. Oppure create una lista di risultati, che è più comoda:
http://pokehack.altervista.org/attachment.php?aid=298
Ricordate che anche se in generale sono simili, ogni hex editor ha proprie funzioni aggiuntive che vale la pena provare e sfruttare (la mia ultima idea sarebbe quella di crearne uno mio, ma vabbè richiederebbe un tempo veramente ENORME :c )
Ad esempio poco fa, con la lista dei risultati, avete visto in azione una delle caratteristiche che più mi piacciono di windhex. Peccato che lui sia un po’ scomodo da usare “quotidianamente”.
http://pokehack.altervista.org/attachment.php?aid=415
http://pokehack.altervista.org/attachment.php?aid=416
Ora vorrei concentrarmi su una cosa molto importante che tornerà sempre utile, ovvero la ricerca dei puntatori. Come accennato prima, sono dei valori che indicano una posizione all’interno della memoria del GBA, che vedremo in dettaglio in futuro. Ipoteticamente, ogni byte potrebbe avere il suo puntatore, basta costruirlo. Nella realtà però non è così perché si indica soltanto il primo byte di qualcosa (la cosiddetta "risorsa" del gioco, come un'immagine, un testo, ecc... Insomma un dato), mentre quelli seguenti sono referenziati tramite un indice di scostamento rispetto al puntatore (l’origine di cui parlavo prima).
Considerate questo esempio:
“Quel fez sghembo copre davanti”
non preoccupatevi, è soltanto un pangramma. Volevo mettere quello degli ioni o quello della volpe, ma nell’aprire wikipedia ed aver visto una citazione al mio telefilm preferito… beh… <3 giustamente dovevo metterla, concedetemelo.
Analizziamo ora la frase:
[ Q ][ U ][ E ][ L ][ ][ F ][ E ][ Z ][ ][ S ][ G ][ H ][ E ][ M ][ B ][ O ][ ][ C ][ O ][ P ][ R ][ E ][ ][ D ][ A ][ V ][ A ][ N ][ T ][ I ]
Abbiamo un indice che identifica ogni lettera:
[00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29]
Se contate, le due righe hanno lo stesso numero di caratteri.
Se volessimo accedere ad una lettera, non dovremmo fare altro che sommare l’indice all’offset del primo carattere.
capiamo meglio con un’immagine:
http://pokehack.altervista.org/attachment.php?aid=300
In questo esempio possiamo vedere che l’offset del primo carattere è 9D3CE4h, e se voglio l’indice del carattere z devo sommare l’indice di z, ovvero 7.
Spero sia chiaro, altrimenti non fatevi scrupoli a chiedere.
Ora vediamo quali sono i passaggi per ottenere un puntatore. Per il momento ci saranno dei punti poco chiari, ma nelle prossime lezioni saranno rivelati.
Dato un offset lungo 3 byte, il suo puntatore è: - scrivere XX XX XX 08;
- invertire l’ordine dei 3 byte (quello in mezzo ovviamente resta in mezzo)
- sostituire i nuovi byte alle X, in ordine.
Ecco l’esempio per 9D3CE4: - scrivo XX XX XX 08;
- ribalto i bytes: E4, 3C, 9D.
- sostituisco: E43C9D08.
Questo è il puntatore come se fosse stato inserito nella ROM originale. Ora basta metterlo nel posto giusto e il gioco potrà usare il nuovo testo, e nessuno si accorgerà della modifica! Questo è ciò che fa, a volte sbagliando, a-text.
Avete voglia di ricavare qualche puntatore, così giusto per esercizio? è proprio una sciocchezza, si fa in meno di 2 minuti, ma serve a molto.
Ricavate i puntatori dei seguenti offset:
Spero lo abbiate fatto, perché alla fine della lezione vi servirà.
Bene, eccoci finalmente alla vera pratica. Recatevi all’offset 3E6E50 di ruby. Come fare? Non so quale sia il vostro menu a tendina, ma sicuramente potete fare CTRL+G, tutti gli hex editor hanno questa scorciatoia.
Inserite l’offset come faccio io e dovreste avere il seguente risultato;
http://pokehack.altervista.org/attachment.php?aid=301
Questo è un dato binario. Significa che è un dato rappresentato nel suo tipo (formato) naturale. ne consegue che solo chi sa leggere quel tipo di dato potrà comprenderne il significato. Fate una prova: aprite un’immagine con il blocco note. Cosa esce? Caratteri incomprensibili, perché il blocco note non sa leggere le immagini, lui poverino cerca solo il suo formato di dati (il testo) nell’immagine. Se provate ad aprire file prodotti da un'altra applicazione con un programma totalmente diverso, sarete fermati da un errore di incompatibilità. I programmi si aspettano certe cose nel file che aprono, e se non le trovano prevengono potenziali (anzi, sicuri) catastrofici errori dicendo di non poter aprire il file. Che poi VLC sia zelante e apre tutti i formati dell'universo in tha worldz forevah and evah mentre Windows media player invece è una checca schizzinoso sono dettagli… L'importante è che non cerchiate di fargli aprire un documento, ma un video! Dunque dicevo, ciò che troviamo sulla rom deve essere interpretato come il tipo di dati giusto per produrre un output coerente per l’utente. Altrimenti si verifica la stessa cosa di missingno: Secondo pokemon rosso laggiù ci doveva essere il verso di un pokemon, mentre invece c’erano altri dati… ecco da dove nasce l’inquietante verso di ♀ (“female”). Ed ecco perché sembra non finire mai: interpretando tali dati come suono, i byte che indicano la fine del suono non vengono raggiunti in tempi ragionevoli. A noi invece il massimo che possa capitare è vedere qualche carattere giapponese in un messaggio (mai capitato durante il corso di XSE?), perché magari sbagliamo a mettere l’offset, confondendolo con il puntatore o il testo; questo perché una ROM del GBA è dannatamente più comoda da modificare rispetto al GB.
Come modificare tali dati binari allora? Dobbiamo innanzitutto scoprire cosa rappresentano. Io lo so già perché riciclo gli esempi per la non sbatta.
Non è questo il caso, ma se vi capitasse che i dati non siano word aligned, ovvero allineati ogni 4 byte, ovvero ad un offet non terminante per 0,4,8,C (visto che belli i criteri di divisibilità in base 16??), è necessario copiare i byte in un nuovo file per poterli analizzare meglio.
Tuttavia anche se stavolta non serve è utile sapere come si fa, perciò dategli un'occhiata lo stesso.
Procedura per XVI:
Modo 1 (ATTENZIONE NON USARE AL MOMENTO):- Copiate una sequenza di byte da qualche parte (una rotine di andrea? <3 )
- posizionatevi nel punto in cui incollare
- Edit > overwrite string
- selezionate hex
- incollate e confermate
- assicuratevi di essere in modalità overwrite
- Posizionatevi sul punto da copiare di un file già esistente
- Edit>block n chars
- inserite la lunghezza da copiare
- Edit>clipboard>copy
- posizionatevi nel punto in cui incollare (di un nuovo file)
- Edit > block copy/overwrite (CTRL+W)
#(se non funziona vi prego di comuinicarmelo)
Spiegazione per HxD:
selezionate il testo e copiatelo con CTRL+C. Posizionatevi sulla destinazione e fate CTRL+B. fine :|
http://pokehack.altervista.org/attachment.php?aid=237
Sicuramente ve lo aspettavate, conoscendomi  chiedo nuovamente scusa a fiammy per aver dimenticato di colorare il suo posticino di meditazione quotidiana
Bene, ora che sappiamo cosa è analizziamo il formato: sembra che ogni valore del byte corrisponda a una città (A GINIUS!). è importante però notare una cosa: il valore 57h indica il vuoto. Anzi, empiricamente possiamo notare che qualunque valore al di sopra di 57h indica vuoto.
Il vostro compito è di modificare (tramite hex editor, ovviamente) la worldmap e farmi vedere il risultato.
Una volta un alunno passato mi ha posto una domanda arguta, vi lascio qualche riga vuota per farvela formulare anche a voi.
-
-
-
-
-
La domanda era se è possibile mettere più di 56h città. La risposta, mio caro ragazzo, è che sì, è possibile, ma non con l'hex editor. Noi con l'hex editor abbiamo modificato i dati, ma le istruzioni impongono un numero massimo di città. Capite bene che la vera potenza sta nell'ASM, l'hex editor è solo il canale di sfogo di questa.
Vi do un cosniglio: anche se la tentazione di non farlo è forte, conviene sempre spostare il vostro dato in un nuovo file. Infatti potete vedere subito se per sbaglio aggiungete dei byte. Controllate sempre di essere in modalità OVERWRITE! Inserendo bytes spostate altra roba che viene dopo, che dunque non è più al suo posto, e non verrà letta correttamente. Finchè si tratta di dati si può soprassedere (immagini, testi e suoni glitchati senza sapere da dove vengano), ma se sono istruzioni, la cosa si fa grave: non va mai bene, e alla peggio ci crasha la ROM...
Inoltre, fate spesso backup. vi torneranno MOLTO utili, soprattutto le prime volte che sperimentate qualcosa di nuovo, dato che sono più alte le probabilità che qualcosa vada storto.
Per compito i 4 angoli della tabella devono contenere una città a vostra scelta, in più invertite albanova e solarosa. Chi lavora su fire red può fare il compito su fire red, per questa volta. L’offset è 3F2500h.
Questo è un compito per farvi imparare a contare (? Asd). Si, perché avrete notato che i dati sono tutti immagazzinati in fila indiana, non ci sono righe o colonne. La presenza di righe e colonne è dedotta dal software, mediante un semplice procedimento:
- So le coordinate X e Y del dato della tabelle che devo leggere.
- Moltiplico la Y per il numero di elementi di una riga
- Sommo X al precedente risultato
- Sommo l’offset del primo elemento della tabella al precedente risultato.
Come funzionano questi passaggi? Facciamo un esempio passo-passo.
Supponiamo di avere all’inizio di un file una talebba di 9 elementi, così:
A B C
D E F
G H I
Ma ovviamente nella memoria essa è contenuta in linea retta: [[(A), (B), (.C)],[(D), (E), (F)],[(G), (H), (I)]] . Come facciamo ad accedere ad un elemento? Dobbiamo indicizzarla.
Mettiamo di voler accedere alla posizione centrale E, di indice 1,1 (si parte a contare da 0).
- Moltiplico y*la larghezza: 1*3=3
- Sommo la x: 3+1=4
- Sommo l’offset di inizio della tabella: 4+0=4
Dunque prendiamo il valore alla posizione 4. Contiamo insieme (scusate se vi sembro Dora l'esploratrice >.<  ):
0-A,
1-B,
2-C,
3-D,
4-E.
Tutto questo casino per cosa? Per sapere cosa state modificando. Se siete sulla ROM vi perderete in fretta, per cui bisogna sempre contare prima di scrivere qualcosa.
Ma tanto già so che voi avrete ridimensionato la finestra del programma per avere esattamente 28 colonne, vero? Sempre che il vostro hex editor permetta ciò. A questo punto il compito diventa una bazzecola.
Ora proviamo a fare una cosa più complicata. Vi giuro che è l’ultima per oggi.
Spostiamo la worldmap.
Cosa? Eh, dai, su, non ho mica detto di spostare una regione intera, è solo una cartina! Mica siamo dei titani, solo dei geografi!  ok pessima citazione della mitologia greca Ecco il procedimento passo per passo. Vorrei lo faceste per compito.
Per poter proseguire, dovete aver fatto il mini esercizio sui puntatori, la cui Soluzione è (non guardate prima di aver almeno tentato):
- 506E3E08
- 28B30F08
- 0000E008
Prendete l'offset della worldmap. Aprite la ROM con l'hex editor e cercate una stringa esadecimale. Scrivete il puntatore. Se tutto è corretto dovreste averlo trovato una sola volta (se di più o avete usato rosso fuoco e allora non so, oppure c’è qualcosa di sbagliato, nel caso chiedete pure). Si trova a FB328h per ruby.
Sostituitelo. Con cosa? Ma con quello che volete voi. Ad esempio provate un offset a caso. Scrivete davvero 3 (TRE!) byte a caso, è un procedimento istruttivo. Poi aprite la mappa città nel gioco e vedete che succede. Il gioco interpreta come mappa città dati che mappa città non sono. Complimenti, avete buggato la ROM! Tranquilli, è riparabilissimo, basta fare l'operazione inversa! Ora torniamo indietro. Mettete il puntatore di questo valore: 720000h. se la rom è vergine, dovrebbe esserci spazio laggiù. Ora, copiate la vostra wolrdmap in tale punto. Modificate valori della worldmap che vi ho chiesto. Se tutto va bene, cancellate quella originale, scrivendo 420d volte 00h o FFh (o qualsiasi cosa, ma questi due valori sono molto più "convenzionali").
Per concludere, vi lascio un piccolo esempio che riassume al meglio cosa significhi l'hex editing.
- Aprite advance map, una ROM qualsiasi e una mappa qualsiasi.
- prendete un tile qualsiasi e mettetelo nella prima casella della mappa, in alto a sinistra, e ricordatevi il numero, che compare nella barra di stato in basso.
- salvate
- aprite windhex, e usate la funzione compare files.
- mettete la rom che avete appena usato come cavia e una pulita.
- se fate compare, vi dirà 2 byte sono cambiati.
- andate a vedere tali byte, ad esempio io che ho usato albanova ho "2913B4" e noterete che i numeri coincidono, più o meno, con il vostro tile. Più o meno perchè innanzitutto sono "girati", e poi perchè c'è un 4 aggiuntivo. Il 4 io stesso non so cosa sia, forse sarà stato deciso dalle istruzioni. Il perchè è girato lo vedremo un'altra volta. Però sono loro. Per fare una prova, tornate in advance map, e selezionate la scheda "vista header", e premete CTRL+H, per aprire la vista "professionale". Se tutto è andato bene, dovreste vedere tale numero sotto il riquadro "dati mappa" e "offset mappa".
Cosa è successo?
Abbiamo visto cosa succede nella realtà quando usiamo un programma automagico. Ora io non voglio dirvi di buttare advance map e usare per sempre l'hex editor, ma farvi capire la mole di lavoro fanno questi programmi per voi. E pensate che se si aumentano le dimensioni il programma deve anche trovare dello spazio libero per inserire la nuova mappa più grande. Vi ho fatto fare questo perchè prima o poi si rivelerà necessario, ad esempio talvolta si "bruciano" le mappe, e con un po' di fortuna potete recuperarle.
Inoltre è sempre importante almeno sapere nella teoria cosa fanno a basso livello i programmi di automazione che si usano, questo vale in ogni campo dell'informatica.
Se avete qualsiasi cosa da dire, non abbiate paura!
Bye!
LEZIONE 1.2
IMPARIAMO A SCRIVERE?!
Se ricordate, l'altra volta ho detto che per visualizzare i caratteri sono utilizzati gli standard di comunicazione, in cui ad ogni byte corrisponde un carattere ben preciso.
Ovviamente in GF hanno avuto la brillante idea (si fa per dire... Anche se probabilmente l'hanno fatto per rendere più difficili le operazioni dei cheater) di alterare l'ordine naturale delle cose sostituendo tutti i caratteri con dei nuovi. Il funzionamento è il medesimo, ma i giochi adottano un set di caratteri diverso, come si suol dire. Questi possono essere trovati sull'enciclopedia ( http://bulbapedia.bulbagarden.net/wiki/C...ration_III) dove sono descritti in maniera molto dettagliata. Noterete che ci sono alcuni valori strani: sono le sequenze di escape, ovvero i caratteri di controllo. Questi sono speciali caratteri, presenti in ogni sistema operativo, che hanno particolari compiti. Il programma che si occupa della scrittura del testo riconosce il carattere speciale e si comporta di conseguenza. Al link menzionato prima ogni singolo byte è ampiamente documentato. Ovviamente, come al solito, non è necessario impararli a memoria tutti, ma basta "saperli leggere" per poterli consultare in caso di bisogno. Chiedetemi pure se non capite qualcosa. Ad esempio con essi potete cambiare colore, oppure fare una pausa, o usare il grassetto. Sono tecniche molto utili per la regia 
Anche nel computer normale ci sono le sequenze di escape: l'accapo è un esempio.
Tutte le volte che usate una sequenza mnemonica in xse, come ad esempio "LASTRESULT" o "RS_cyan" (non son sicuro che la seconda sia corretta così com'è, ma avete capito a cosa mi riferisco) lui sostituisce nella ROM una particolare sequenza di caratteri al posto della parola chiave. Nel nostro caso al posto del colore metterà il byte che indica il cambio di colore, e poi il byte del colore. E se volete inserire in XSE altre sequenze di escape? C'è il comando "\h", ma Comunque dovete inserire un "\h" per ogni singolo byte che compone la nostra sequenza di controllo. Noioso, vero? Ecco perchè a volte preferisco usare l'hex editor. Ovviamente non dovrete usarlo sempre, anzi riconosco che usare XSE è più comodo, ma sapere come fare è sempre meglio; forse vi capiterà anche qualche caso in cui vi servirà.
Per svolgere correttamente questa attività dovrete avere una tabella dei caratteri, che essenzialmente è un file che dice all'hex editor quali sono le corrispondenze tra i caratteri "normali" (ASCII) e "quelli pokemon" . Io vi passo quella che si trova insieme a thingy 32, un hex editor sviluppato principalmente per le traduzioni, e quella incompleta che ho fatto io per xvi in un momento di noia.
http://pokehack.altervista.org/attachment.php?aid=279
http://pokehack.altervista.org/attachment.php?aid=280
Da rinominare l'estensione in "TBL" e "XCT".
Come si usano? Ogni programma ha i suoi problemi, dunque bisognerà stare attenti. Comincio col dire che su HxD neanche c'è questa possibilità, oppure sono stordito io che non l'ho vista. Rimangono windhex e thingy che si comportano in modo piuttosto simile, mentre xvi, come vedrete tra poco, fa una "cassanata".
Dunque è giunto il momento di aprire rom e tabella. Solitamente i comandi stanno nel menu file. Windhex legge la tabella di thingy. Una volta completato dovreste vedere che i caratteri a destra sono cambiati. Il programma sta sostituendo i byte della ROM con i caratteri indicati da noi. Ora, finalmente, potete provare a sbizzarrirvi con la ricerca di testo, in quanto ci sono un mucchio di parole di senso compiuto! E se provate a scrivere con le normali lettere della tastiera, queste vengono automaticamente tradotte nel formato corretto, mentre a noi appariranno come lettere normali!
http://pokehack.altervista.org/attachment.php?aid=308
Bisogna ricordare, però, che il programma è stupido, e non sa quali byte sono effettivamente testo e quali no, perciò li sostituisce tutti. Per superare questo inconveniente basta cambiare la tabella in uso, ritornando ad ASCII, o quello che è un uso dal vostro programma. Di solito tale comando sta o in file o in modifica. (in windhex File>Swap table file)
Ora arriviamo al problema XVI: purtroppo non riesce ad astrarre i caratteri, perciò la soluzione che adotta è sostituirli fisicamente nella vista di sinistra! [emoji33] Se salvate vi ritroverete una ROM sicuramente corrotta! NON SALVATE LA ROM DOPO AVER APPLICATO LA SOSTITUZIONE CON XVI! L'unico modo è avere una ROM "cavia" (una delle tante ahah) che userete per vedere come saranno i caratteri tradotti, che riporterete nella ROM originale. Già, è molto più comodo usare windhex.
Ora impareremo a cambiare il testo direttamente con l'hex editor. Come funziona questo metodo? Se sapete trovare e modificare i puntatori lo applicate alla svelta. - Individuate il testo da modificare con la ricerca di stringa, di testo stavolta
- Ricavatene il puntatore
- Cercate il puntatore dall'inizio della ROM. Meglio se pochi (1) risultati, perchè significa che la risorsa è usata una sola volta. Nel caso del testo dovrebbe essere così. Segnate l'offset.
- Andate in spazio libero (createne il puntatore) e scrivete! Bisogna però stare attenti alla larghezza, in quanto finora tutti gli hex editor adottano larghezza fissa delle colonne. In Certi casi torna utile, ma non in questo. Indicativamente, in minuscolo potete scrivere 30 lettere.
- Andate al primo offset segnato. Contiene il puntatore al vostro testo. Dovrete sostituirlo con il puntatore al nuovo testo.
Se conoscete un hex editor migliore di quelli elencati in questo corso (windhex, XVI, HxD) per favore segnalatelo.
Come potete notare non ci siamo spostati neanche per un attimo dal programma corrente, quindi, se il testo è favorevole da scrivere, questo consente di risparmiare un po' di tempo rispetto ad altri metodi.
Come vedremo nelle ultime lezioni, disporre dei testi di una ROM è essenziale per iniziare piuttosto agevolmente alcune particolari ricerche di ASM.
Come compito modificate un testo come volete. (tanto poi fatto uno fatti tutti)
Lo so che stavolta era breve, ma d'altronde siamo in regime di festività : p
auguri (emoticon dell'albero di natale)
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere e guarda notepad
Messaggi: 1,096
Discussioni: 81
Registrato: 22-08-2015
Reputazione:
11
Leggo e scopro che la grafica del mio PC è comparabile con quella del GBA
GBA: 16bpp
IL MIO PC: 32 bpp (che bellooo mi gira GTA6 YEEH)
Comunque bravo @ Bonnox , quando avrò un voglia di leggerla tutta quanta la discussione mi preparo un piatto di arachidi salate e un po' d'acqua e inizio ad assorbire il sapere a imparare per bene sta cosa brutta chiamata Assembly.
Grazie mille! ^^
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
12-01-2017, 06:49 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:10 PM da Bonnox.)
.
LEZIONE 2
UNA LENTE D'INGRANDIMENTO SUL GBA
#TODO ASSOLUTAMNTE: per la prox miglioria prendi le spiegazioni da http://www .pokehack.altervista.org/showthread.php?tid=3715&pid=58009#pid58009
post 60 e 62
I moderni calcolatori sono costruiti secondo l'architettura di Von Neumann, in opposizione a quella di Turing che ha grande rilevanza teorica, ma con i moderni dispositivi è inefficiente e poco gestibile.
Spiegando brevemente, Questo significa che Il cuore del dispositivo è la memoria centrale (nome rigoroso per RAM, ovvero la memoria temporanea in cui stanno i dati che devono essere elaborati). Tutte le componenti del dispositivo comunicano con la memoria centrale e con il processore.
Anche il GBA funziona secondo questo schema. Apriamo il VBA normale e andiamo nel menu a tendona "tools" e apriamo tutto da "io viewer" a "tile viewer". Cosa è tutto questo macello? Sono le varie parti del GBA, servono per "dissezionare" il gioco e ricavarne il funzionamento. Ora possiamo chiuderle tutte tranne una, il memory viewer. Essenzialmente tutte quelle finestre possono essere ricondotte al memory viewer, in quanto il contenuto di ciascuna è solo una forma comprensibile di ciò che sta nella memoria. Con il memory viewer avete accesso a tutte le macro aree della memoria del GBA (spiegate tra poco)
Come vedrete, ci sono dei buchi. Questo non significa che la memoria del GBA abbia dei buchi (è piena di tarli? ovviamente no) oppure sia davvero grande come i numeri che vedrete, che sono centinaia di MB! Semplicemente lei fisicamente sarà come sarà, è compito di chi studia elettronica vederlo, ma viene "mappata" logicamente secondo gli indirizzi che vedremo. Questo procedimento è un'astrazione dall'ambiente fisico, e grazie ad essa è possibile manipolare indipendentemente qualsiasi settore.
Tutto ciò trova un'applicazione pratica: il WBTO.
Questo comando degli script permette di scrivere un byte in una locazione di memoria a nostra scelta.
Non si può veramente "insegnare il WBTO", a parte perchè l'ho appena fatto nel periodo precedente (si, la frase precedente in grassetto è "insegnare il WBTO"), ma soprattutto perchè questo comando presuppone che ci sia uno studio dietro la sua applicazione, in modo da ottenere l'effetto ricercato. Ok, posso dirvi cosa dovrete scrivere nella memoria per ottenere qualcosa, ma allora l'insegnamento si riduce a una semplice elencazione di valori, cosa che potete trovare benissimo per il WEB (e quelli di forumcommunity ne sanno qualcosa, vero?). Qui vi spiego COME funzionano gli offset di memoria, in modo che possiate sviluppare il vostro atteggiamento critico verso la realtà (mi sembra filosofia  ) che vi porterà a fare le vostre nuove scoperte. Se poi unite questo al potente strumento che è la documentazione degli offset scoperti allora sarete un'arma dal grande potenziale. Tutta questa manfrina poetica per dire cosa? Per introdurre la
SPIEGAZIONE SU COME FUNZIONA LA MEMORIA
#Todo prendi da tonc
in questa sezione spiegherò brevemente lo scopo di ciascuna delle memorie del GBA.
I numeri a 2 cifre riprtati di seguito sono da mettere davanti all'offset, che in totale dovrà avere 8 cifre (32 bit). - 08 : La nostra ROM. Il GBA legge da questa memoria il gioco. E' una delle più lente della lista. Ed ecco spiegato il motivo del mettere lo 08 al puntatore. Ogni puntatore visto fino ad ora si riferiva alla ROM, perciò si metteva per forza il byte 08. Ora nella guida su come costruire un puntatore, sostituite il passo "metto 08 al puntatore" con "metto il numero della memoria che voglio usare".
- 09 : Per accedere alla ROM estesa, che va dai 16 MB ai 32 (il massimo) si usa questo prefisso. l'offset che il GBA vuole è quello che sarebbe aprendo la ROM con l'hex editor con l'origine relativa in 01000000, come se fosse una sorta di bank 2. Siamo fortunati, il primo game boy aveva un bank ogni 64 KB! Quello che avevamo detto la scorsa volta sugli scostamenti torna molto utile. In pratica serve solo a chi ha tantissimi dati e ha finito lo spazio delle ROM originali.
- 07 : è una memoria piccolissima che contiene le informazioni sugli oggetti. un oggetto può essere qualunque cosa, da un people a un mugshot, a un elemento dell'interfaccia grafica. Essenzialmente sono comunque degli sprite. Trovate alcune informazioni nelle varie guide del forum.
- 00 : BIOS di sistema. è una cosa che tutti i computer hanno, e contiene "l'essenza della vita", ovvero, più praticamente, tutto ciò che serve a far funzionare il computer a livello basilare (del tipo accendersi, rispondere ai tasti, ecc). Non a caso l'acronimo sta per Basic Input/Output System. La scritta "game boy advance" quando si accende è opera sua. Noi potremo trarre vantaggio dal BIOS con l'ASM, in quanto potremo usare alcune funzioni non proprio elementari contenute in esso: ad esempio la decompressione dei dati, oppure funzioni matematiche trigonometriche, che si vedono al triennio delle superiori. Già, non sembrano molto essenziali per far funzionare una macchina, ma probabilmente sono state inserite perchè di frequente uso nei giochi. Infatti per questo sono molto più veloci rispetto a quanto potremmo fare noi "artigianalmente".
- 0E : SRAM, ovvero il salvataggio. Non è una memoria veloce.
- 02 : WRAM, La memoria temporanea che hanno tutti i computer. Qua abbiamo la bellezza di 256 KB di RAM. E' una memoria veloce, sicuramente più della ROM, ma sta a metà classifica.
- 03 : Con questo codice ci si riferisce all'IRAM, ovvero una memoria interna (come suggerisce l'iniziale) al processore. E' la più veloce di tutte, ma è grande solo 32 KB. Meglio non utilizzarla per i nostri scopi, in quanto è già utilizzata da alcune cose necessarie al funzionamento corretto del sistema, e pasticciandoci rischieremmo solo di fare dei casini e crashare il gioco.
- 05 : Contiene le palette da utilizzare. contiene 16 palette per un totale di 256 colori. Agli atti pratici on è modificabile, perchè in pokemon viene costantemente aggiornata prendendo i dati dall'indirizzo 0202EEC8 (ROM AXVE, per altre ROM sicuramente c'è scritto su pokecommunity), che i programmatori del gioco hanno deciso di usare come deposito temporaneo.
- 04 : Questa locazione si chiama registri di Input/Output. è un minuscolo settore in cui ci stanno i valori interni del GBA per utilizzare le periferiche, come il suono, la porta dati, o il display stesso.
- 06 : VRAM. Questa è la memoria Video da 96 KB. Il suo contenuto è grezzo, per visionarla in forma comprensibile si usano il tile viewer e il map viewer. Le map essenialmente sono ciò che forma l'immagine da visualizzare: Sono dei riferimenti ai tiles. Ci possono essere fino a 4 strati, chiamati BG, probabilmente per background. In pokemon il BG0 è utilizzato principalmente per l'interfaccia. Gli altri variano a seconda del contesto, ma durante l'overworld sono usati tutti e 3 per le varie altezze dei blocchi. Ad esempio il tetto delle case è nel BG1.
Ricordate comunque che per ogni esigenza di consultazione tecnica esistono i siti internet (maggiormente comprensibili man mano vi farò più lezioni):
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm (intermedio)
http://problemkaputt.de/gbatek.htm (difficile)
Il secondo è prevalentemente una referenza: se uno non si ricorda a memoria una cosa va e la trova, il primo spiega un po' di più.
Ora che sapete un po' meglio come funziona la mappatura della memoria, vi mancano gli offset. In questo forum io mi sto battendo per avere una raccolta ordinata di tutti gli offset, ma l'idea sembra non riscuotere successo. Comunque se volete alcuni sono qui
http://pokehack.altervista.org/showthread.php?tid=1754
http://pokehack.altervista.org/showthread.php?tid=2012
poi boh...
Altrimenti potete sempre bazzicare in altri fori e gozzovigliare un po' (e magari venire a riportarmi cosa scoprite). Io di sicuro prima o poi farò passare tutte le discussioni della macroarea apprendimento e ne coglierò ogni offset. Noiosissimo, lo so.
se volete, potete usare i 2 link sopra per giocherellare con i registri.
Ecco ora qualche esempio di WBTO:
difficoltà facile:
hmm, non mi garba molto il colore dell'erba del percorso 101. Aspetta che chiamo il giardiniere...
Codice: #org @start
writebytetooffset 0x19 0x0202ef22
writebytetooffset 0x29 0x0202ef23
end
et voilà, ora è diventata di un bel rosso sangue! ( DICHIARAZIONE DI NON RESPONSABILITA': non voglio promuovere la violenza, ciò che faccio io è solo a scopo didattico)
Spiegazione: sostituisco il qattordicesimo colore della terza palette.
difficoltà media:
Recentemente sono riuscito ad implementare una feature che per l'utente non ha rilevanza, ma può tornare utile a noi sviluppattori. Si tratta di dirottare i dati delle tabelle nella RAM. Come mai fare una cosa che a orecchio sembra complicata? Perchè può capitare di "finire lo spazio", ovvero arrivare a 255 elementi di una tabella indicizzata con un byte e dunque non poterne più inserire nessun'altro, a meno di avventurarsi nell'asm per cambiare il modo con cui vengono trovati gli elementi. Ma basta con le chiacchiere e passiamo ai fatti: Sono riuscito a dirottare in RAM i multichoice; Ovviamente è possibile farlo con tutto, ma mi piaceva farlo con questi. Come ben sapete i multichoice su rubino sono circa 80, ma possono essere al massimo 255, perchè in XSE viene detto chiaramente che l'ID occupa un byte. E se li finiamo? Semplicemente diciamo al GBA di andare a trovare i testi in RAM, così se ne possono mettere quanti si vuole! Dovrete sacrificarne alcuni, ma ne avrete infiniti! Quanti ne servono? dipende da voi, uno per ogni numero di scelte. Significa uno per il multichoice da una scelta, uno per il multichoice da due scelte, uno per tre scelte, e così via, fino al numero che volete. Il massimo che si può fare senza far crashare il gioco è 9. Gli ultimi 9 multichoice si riferiranno agli ultimi 9 puntatori dei boxset (per approfondimenti vi rimando al topic ufficiale del multichoice, ci dev'essere pure una mia guida), i quali punteranno alla RAM. Per poter utilizzare la tecnica negli script occorrerà fare un WBTO nell'area designata, con i caratteri che abbiamo visto la volta scorsa per comporre il testo, e successivamente chiamare il multichoice.
Esempio di script funzionante, se avete già la modifica del MC sulle vostre ROM.
Codice: #org @start
writebytetooffset 0xBB 0x2000000
writebytetooffset 0xFF 0x2000001
writebytetooffset 0xBC 0x2000002
writebytetooffset 0xBD 0x2000003
writebytetooffset 0xFF 0x2000004
writebytetooffset 0xBE 0x2000005
writebytetooffset 0xBF 0x2000006
writebytetooffset 0xFF 0x2000007
msgbox @string1 MSG_FACE //"PROF. BIRCH spends days in his LAB..."
multichoice 0x0 0x0 0x0 0x0
ho dovuto metere un testo se no non rimaneva fermo il riquadro. Bah, dettagli per scripter.
L'effetto è
http://pokehack.altervista.org/attachment.php?aid=309, non contate il fatto che ci sono solo 2 testi invece di 3, era una prova. Il concetto che rimane è il poter cambiare i dati del gioco durante la sua esecuzione. Questo trucchetto sarebbe quasi un virus, sui computer. Ma noi dobbiamo essere pronti a fare di tutto, in nome dell'efficienza.
inoltre, finchè non sistemerò bene i testi, guardate qui per la guida di cui parlavo prima su come realizzarlo: http://pokehack.altervista.org/showthread.php?tid=2795
Spiegazione: A parte la modifica al multichoice che non è mostrata, ho semplicemente scritto del testo nella RAM, che viene letto correttamente dal programma multichoice.
compiti? Boh, non saprei, ci possono essere mille utilizzi differenti, a seconda della situazione! noi in un contesto come questo non abbiamo nemmeno delle occasioni, degli stimoli ad usarlo, in quanto operiamo (si presume) su ROM pulite, perciò non abbiamo le necessità che scaturiscono da un progetto reale. inoltre qua siamo liberi di fare ciò che ci sentiamo, senza vincoli (non come in altre lezioni). Dunque, per non saper né leggere né scrivere, provate a fare qualcosa con il WBTO, quello che vi sentite, e spiegatemi come l'avete trovato, e cosa fa.
In seconda battuta spiegatemi questo:
Codice: writebytetooffset 0xAE 0x3004360
Consigli: per fare il primo, pensate al vostro obiettivo, poi scovatene l'offset. come funziona l'obiettivo? Se voglio ottenere questo, cosa devo mettere?
Per fare il secondo compito cercate l'offset indicato dal comando, e andate a vedere in quale memoria (e in quale settore in alcuni casi) risiede. pensate a cosa fa tale locazione e come si comporta con il nuovo byte. Se non riuscite a capire cosa sia, riconsiderate tutto quanto visto finora 
Ah, facciamo che se volete cambiare le palette lo fate per un'altra ROM? Sennò sapete già l'offsset. Tanto è facile, basta cercare i colori che il VBA vi dice.
Se avete dubbi come sempre non esitatee achiedere, ciao
-170111
piccoli cambiamenti alle frasi per spiegare meglio, rimozione link google a von newmann e altri contenuti poco contribuenti
liste invece di -
rimosso spiegazione semidettagliata sulle tilemap, e collegamento a little endian #reinserire
rimosso link doppio a cowbyte e "freakin'" inteso come parolaccia
aggiunto disclaimer a erba rosso sangue
soppressa alternativa, sostituita da piccola domanda. parte rimossa: "2) mi spiegate il funzionamento di uno dei "codici da inserire nelle ak rum" (sarebbero i WBTO) che trovate su forumcommunity internet."
corretto la descrizione della memoria 09
-Prima: ?
Salve per non farvi ammuffire oggi vi porto una veloce lezione 2.1 che avevo scritto in passato ma andò persa dopo l'attacco al forum, e una guida sulla grafica, sicuramente perfettibile, ma che funge da introduzione abbondante in questo mondo. Siccome è la prima stesura, vi invito a leggerla attentamente e soffermarvi sul capire ogni singolo nuovo concetto (sono tanti), in quanto non è molto "user friendly" ("noob friendly").
Ah lo stesso dicasi per la prima parte. E' corta e densa.
ESERCIZI 2.1
I REGISTRI
Questo è il miglior esempio di applicazione del WBTO.
La memoria 4 del GBA viene chiamata "registri di I/O". IO sta per input/output, ovvero ingresso e uscita, l'interazione tra uomo e macchina.
Cos'è un registro? Una piccola zona di memoria che svolge funzioni "a basso livello" (mia definizione improvvisata). Con basso livello intendo che in informatica registri sono usati per configurare il comportamento delle periferiche. Magari in realtà sono dei circuiti elettronici, ma al programmatore appaiono come vere e proprie celle di memoria in cui scrivere, grazie ad una astrazione effettuata dall'architettura.
Questa tecnica si chiama "I/O mappato in memoria" (memory mapped), che consiste appunto nello scrivere a particolari valori in particolari indirizzi per comandare l'hardware.
Nei giochi pokemon alcuni registri sono inaccessibili, nel senso che vengono aggiornati ogni frame, mentre altri possono essere manipolati.
In teoria dovrei presentarvi questi esempi alla fine, in quanto i registri si riferiscono a TUTTO. Qualsiasi aspetto del GBA può essere controllato da essi, tranne l'illuminazione e il volume. Ma è una cosa troppo importante per essere lasciata in fondo. Non capirete tutto subito, ma gradualmente, però almeno avete già le basi.
Una documentazione molto estesa dei registri può essere trovata ai link nella lezione 0.
Ora semplici esempi di WBTO sui registri.
1) http://pokehack.altervista.org/showthread.php?tid=2320
2) in reperimento...
LEZIONE 2.2
VOLARE, OH, CANTARE, OH OH OH OH. NEL 0x7C00, DIPINTO DI 0x7C00
LA GRAFICA
okokok scusate la canzoncina idiota, forse dalla prossima volta la cambierò.
questa sarà probabilmente la lezione più corposa di tutte, perciò preparatevi!
Ciò che vedremo oggi non riguarda propriamente nè il WBTO nè l'ASM, ma fa comunque parte della conoscenza basilare sul GBA che uno deve avere quando modifica i giochi di pokemon. E poi è sempre roba sui byte 
Ci tengo a farlo perchè ho visto che nei forum regna sovrana molta confusione, per cui speravo di fugare ogni dubbio.
Oggi parliamo di grafica. Quella cosa che gli utenti finali vedono e usano per giudicare, ma che fa sempre imbestialire i programmatori perchè è complicata ed è soltanto un "accessorio" alla struttura del suo programma.
Volevo fare un'introduzione un po' più profonda ma va bene anche così, passiamo senza indugi alla lezione! # scusate ancora se la formattazione non è delle migliori, è la prima volta che scrivo queste cose, mi concentro prima sui contenuti
prima di iniziare una nota importantissima: oggi parleremo in detaglio della memoria 06, ma fate attenzione ad una cosa: non potete scrivere sulla memoria 06 un solo byte alla volta. Se lo fate, quel byte e anche il suo vicino assumeranno lo stesso valore. Per sopravvivere, dovrete (con l'ASM o un linguaggio di alto livello come il C o il Pascal che forse alcuni di voi conoscono) leggere ciò che c'è attualmente in un frammento di 2 o 4 bytes, sostituire il byte voluto, dopodichè rimetterlo.
i colori sono quelle cose formate da onde elettromagnetiche che captano i nostri occhi (trovate una descrizione più migliore su wikipedia).
Il GBA possiede la capacità di mostrare ben 32768 colori. Un colore in formato "grezzo" è composto da 2 byte così ripartiti:
il primo bit deve essere sempre 0. Se dovesse essere 1, sarebbe un colore non consentito: ogni emulatore ha il suo comportamento, ad esempio credo che il VBA lo ignori semplicemente, mentre non ho mai provato a vedere come sia su hardware.
seguono 3 gruppi di 5 bit: ogni gruppo rappresenta un valore da 0 a 31 per ciascuno dei 3 colori primari (blue, green, red). Cambiando questo valore, il colore sarà più chiaro o più scuro relativamente a quel canale.
Facendo dei semplici conti, viene fuori, ad esempio, che il bianco è 0x7FFF e il nero è 0x0000 (che scoperta). Provate per compito a costruire i seguenti colori, vi aiuterà a diventare pratici nel maneggiare i bit:
- rosso a 20, verde e blu a 5
- verde a 20, rosso e blu a 5
- blu a 20, rosso e verde a 5
per i colori abbiamo finito.
il GBA ha varie modalità di funzionamento grafico, e alcune di queste sono le modalità bitmap, considerate più semplici da capire.
Cos'è un bitmap? è una matrice a due dimensioni ("map") che contiene i colori ("bit"). Come su programmi grafici al computer (esempio paint), ad ogni casella della tabella corrisponde un colore, salvato come abbiamo visto precedentemente.
okkei, ma come funziona esattamente? Ci sono 3 modalità bitmap, la 3, 4 e 5. Per attivarle dovrete scrivere tale valore nel registro DISPCNT, con WBTO, ASM oppure con l'IO viewer del vostro emulatore (sul VBA è nel menu tools). Dopodichè, tenendo conto di alcuni dettagli spiegati in seguito, vi basterà scrivere sulla memoria grafica i colori che volete, all'indirizzo corretto, ovviamente. Per calcolare l'indirizzo, tenete conto di quanto detto in precedenza sugli offset e le tabelle, e ricordate che la risoluzione del GBA è di 240x160 pixel.
Tabella riassuntiva delle modalità.
mode | width | height | bpp | size | page-flip
|
3 | 240 | 160 | 16 | 1x 12C00h | No
|
4 | 240 | 160 | 8 | 2x 9600h | Yes
|
5 | 160 | 128 | 16 | 2x A000h | Yes
|
Cosa significano quei due termini nuovi?
BPP significa "bit per pixel". La traduzione è inutile, ma sappiate che più è alto questo numero, più colori potrà avere il vostro pixel. un valore molto comune nei giochi pokemon è 4. Il massimo valore del GBA è 16 (che però è come se fosse 15, vedi sopra). Il primo game boy aveva 2 BPP. (ricordi d'infanzia...)
Page flipping si riferisce a una tecnica usata nella computer grafica. Se voi modificate la bitmap mentre l'hardware del GBA sta disegnando a schermo ciò che è contenuto nella memoria (cosa molto probabile perchè entrambi i processi richiedono parecchio tempo), avrete un fastidioso effetto "flickering", tipo sfarfallio. La soluzione è avere due immagini separate, così mentre una è visualizzata, potete disegnare sull'altra indisturbati e non causerete nessun orrore visivo. Quando avete finito di disegnare l'altra immagine, "voltate pagina" (da cui il nome) che deve essere visualizzata.
Per cambiare pagina, scrivete 1 o 0 sul bit 4 del registro DISPCNT. La seconda pagina si trova all'indirizzo 0x600A000. Ovviamente la modalità 3 non dispone della seconda pagina perchè occupa troppo spazio! :p
Bene, eccoci ad uno degli argomenti più importanti, nonchè tra i più controversi.
Avrete notato come nella tabella dei modi grafici abbia usato la scrittura 8bpp, quando prima avevo appena finito di dire che i colori sono composti da 16 bit. Come si spiega questo fatto? Ovviamente con le palette, dato che è l'argomento corrente, lol.
Come ho spesso detto, le console portatili intorno agli anni 2000 (e le fisse venti anni prima...) erano molto costose da realizzare, perchè la tecnologia non era così avanzata, perciò bisognava trovare ogni modo possibile per ridurre le dimensioni dei dati. Uno di questi sono le palette, l'altro le tilemap (che vedremo dopo).
Questi due metodi nascono dall'osservazione che gli elementi di un gioco presentano rappresentazioni grafiche molto ripetute. Che significa? Prendiamo ad esempio questa immagine di un personaggio Nintendo, e noteremo che presenta pochi colori.
Dopotutto, chi è che va in giro con un vestito a macchie colorate, come i quadri del 900? (a parte Mia Ceran in una puntata di mai dire niùs) un colore per la camicia e uno per i pantaloni, semplice. Poi la nostra pelle presenta più o meno la stessa tonalità ovunque. Oggetti di un solo, o comunque pochi materiali, tendono ad avere pochi colori diversi. Perchè allora non realizziamo un "dizionario" di colori? La palette fa questo: raggruppa un insieme di colori, che poi vengono utilizzati da chi disegna. Pensatela come ad una tavolozza di un pittore (credo che significhi pproprio quello in inglese), da cui attinge nel dipingere. Le bitmap indicizzate fanno lo stesso. invece di avere il dato in forma estesa (i 16 bit che indicano un colore), utilizzano solo 2, 4, o 8 bit. Così lo spazio occupato è 1/8, 1/4 o 1/2 dell'originale. Più l'immagine è ripetitiva, meno colori servono, più spazio si risparmia. Ecco perchè a spriting vi insegnano (lo fanno?) quelle tecniche strane di accostare i colori e robe di disposizioni a scacchiera per dare l'illusione di un colore intermedio che non esiste.
Dunque come sarà fatto il dato? Sicuramente sarà diverso. Facciamo un piccolo esempio.
Consideriamo un bitmap di 4x4 pixel per semplicità, due bianchi e due neri.
0x0000 0x7FFF
0x7FFF 0x0000
questa sarebbe la rapppresentazione in modalità a 16 bpp (ricordate che una volta caricati nella memoria, le righe e le colonne scompariranno, saranno tutti in fila indiana).
Fingiamo di essere nella modalità a 8 bpp, e che il nero e il bianco siano i primi due colori della nostra palette. Come risulterà la bitmap? Costruiamola insieme.
Abbiamo 8 bit per ciascun pixel , e i pixel sono 4 -> 32 bit, ma 8 bit fanno un byte = 4 byte
0x?? 0x??
0x?? 0x??
E già abbiamo dimezzato la dimensione.
Ora, come è fatta la palette? Nel GBA ci sono 2 tipi di palette: palette normale e superpalette. quella normale ha 16 colori (4 bit), la superpalette 256 (8 bit). I colori sono semplicemente disposti uno dopo l'altro, come a formare una bitmap di una riga sola (16x1 o 256x1, ma sul palette viewer del VBA sono 16x16). In altri sistemi (tipo GIMP) è altamente probabile che il formato di memorizzazione sia leggermente più complicato, dunque non fate assunzioni. siccome abbiamo detto che i colori nero e bianco sono i primi due (potevano essere il quindicesimo e il quarantottesimo), sostituiremo i byte con l'idice del colore, ovver uno 0 e un 1 (oppure un 14 e un 47, rispettivamente per l'altro esempio).
0x00 0x01
0x01 0x00
E se avessimo a disposizione solo 16 colori? In tal caso avremmo un bpp di 4. Dobbiamo perciò accostare "entità" da 4 bit per ciascun pixel.
entità nero - entità bianco
entità bianco - entità nero
ricordandoci che "entitànero" è "0000b" e "entità bianco" è "0001b", componiamo la bitmap:
0000b 0001b
0001b 0000b
mettiamo insieme i byte:
0x01
0x10
vedete la comodità delle basi a potenza di 2? posso letteralmente giocare a scomporre e ricomporre pezzi di numeri. 0001b e 0000b concatenati fanno 00010000, che in esadecimale è 1 e 0, ovvero 10!
So che sembra una cosa arcana, ma qui sopra, in due byte (01 e 10), ci sono 4 pixel: due per ogni byte. il pixel di coordinate (0,0), ovvero quell in alto a sinistra, occupa i primi 4 bit del primo byte; il secondo pixel occupa i second 4 bit del primo byte; il terzo pixel occupa i primi 4 bit del secondo byte; e così via. I tiles, che vedremo dopo, in pokemon sono memorizzati in questo modo, ovvero a 16 colori.
vedete come esempio il link in versione "palettizzata" a 4BPP
Per compito provate a rappresentare la bitmap a 2 e 1 BPP, sempre supponendo che il nero e il bianco siano i primi 2 colori della palette. Inoltre, quanto risparmierei se usassi 1 BPP rispetto al full bitmap? Con forumula (via Messaggio Privato).
In conclusione, lo ripeto per essere chiaro: la palette (guardate bene come si scrive: è un termine inglese, con una elle e due ti) è un insieme di colori, scelti tra tutti quelli disponibili (32768). Fate come Bart dei simpson che lo scrive un po' di volte alla lavagna, e andate a spargere la buona novella a quelli che storpiano il nome o lo usno per altri significati.
una nota: il colore 0 di ogni palette (che sia di 16 o 256 colori) è usato per la trasparenza. dunque qualsiasi pixel che ha quel colore non verrrà mostrato.
- IL MAGICO MONDO DELLE MATTONELLE
Benvenuti nella seconda e più potente alternativa per comprimere le immagini. Sarà leggermente confusionante all'inizio, ma se leggete piano ragionandoci su sopravvivrete!
Le palette, come abbiamo visto, servono per comprimere i colori, ma possiamo fare di più, ovvero comprimere anche le immagini (io in questo tutorial continuo a usare la parola "comprimere", ma badate bene di non confonderla con la vera compressione a livello di file e byte, la famosa LZ77. Quest'ultima è "lossless", ovvero sfrutta degli algoritmi (tipo zip) per ridurre la diensione in byte dei nostri dati. invece le palette e le mattonelle sono compressioni "lossy", ovvero con perdita di informazioni, e conseguentemente qualità (tipo mp3)).
Cercate sempre di utilizzare le modalità a mattonelle piuttosto che bitmap. Ci sono svariati motivi: sono implementate nell'hardware (perciò non dovrete faticare a fare calcoli per renderizzare le cose), sono dannatamente più veloci, per il motivo precedente, occupano parecchio spazio in meno, sono stratificati, e dulcis in fundo, si possono applicare vari effetti carini (come la mia implementazione della textbox trasparente con il blending; e lo scrolling, pesantemente usato dagli RPG come pokemon).
come si fa? In certi giochi, tipo gli RPG, i platformer, e così via, le ambientazioni sono spesso molto ripetitive. Considerate ad esempio la seguente immagine:
Questa immagine è molto grande, 512x256, e se la facessimo in 256 colori, occuperebbe la bellezza di 131 KB, Che è una volta e mezza ciò che abbiamo a disposizione. Fortunatamente però notiamo che ci sono parecchi "pezzi" ripetuti. Inoltre, sembra quasi che l'immagine sia divisa in aree da 16x16 pixels. Questi sono i tiles. Grazie ai tiles (mattonelle) possiamo costruire immagini molto grandi, purchè ripetitive. Abbiamo a disposizione una tavolozza di tiles, chiamata tile set. E continuando nello stesso modo della palette, in cui un'immagine era formata dagli indici dei colori, adesso l'immagine sarà formata dagli indici della collezione di piastrelle. Così, invece di usare 512*256 entità colore, utilizzeremo (512/16)*(256/16) entità piastrelle. Considerando che i tiles stessi usano le palette (a 16 o 256 colori), il risparmio può essere veramente abissale.
guardiamo come il tileset (a sinistra) viene utilizzato per formare la mappa (a destra):
Ecco come funzionano le tilemaps. Non si definisce l'intera immagine, ma gruppi di pixel messi insieme in piastrelle e si descrive l'immagine in termini di quei gruppi.
Le piastrelle uniche sono nel tileset, che può (e di solito è) essere più grande della tilemap. La dimensione del tileset può variare: se il bitmap è molto variabile, probabilmente avrete molte piastrelle uniche; inoltre, se il disegno è ben allineato (ovvero gli elementi "fittano" una griglia grande quanto la dimensione dei tiles), il tileset sarà più piccolo.
Ora che abbiamo visto la teoria, passiamo alla pratica.
Ci possono essere fino a 4 strati ("BG" sull'emulatore), e i giochi pokemon li usano tutti. La dimensione dei background si cambia con gli opportuni registri e varia da 128x128 pixel fino a 1024x1024. I tiles sono grandi 8x8 pixel. Su advance map infatti potete unire 4 tiles per fare un "blocco".
Ora viene la parte più difficile, state attenti.
Dovete prestare attenzione alla struttura della VRAM, altrimenti potreste avere delle spiacevoli sorprese. Mi aiuto con una tabella.
Memory
| 0600:0000 | 0600:4000
| 0600:8000 | 0600:C000
|
Tileset
| 0 | 1 | 2 | 3
|
Tilemap
| 0 | … | 7 | 8 | … | 15
| 16 | … | 23 | 24 | … | 31
|
Notiamo che i primi 64 KB di VRAM sono destinati ai BG, mentre i rimanenti 32 KB sono dedicati agli sprite, che non vedremo perchè sono simili e più semplici.
Sono disponibili 4 settori in cui collocare i nostri diversi tiles, l'idea è che ogni settore contiene tiles per ciascun layer. Le tilmao invece possono essere collocate in ciascuno degli slot grandi 800h bytes.
Compito: sapendo che ogni "mattone" di tilemap è grande 2 bytes, quale è la grandezza in blocchi di una tilemap che occupa 800h bytes?
Non è per niente difficile: si tratta sempre potenze di 2... :p Tilemap più grandi occupano più slot, ovviamente.
Se aprite una ROM pokemon noterete una cosa strana, ovvero che le tilemap sono tutte in fondo, probabilmente per lasciare uno spazio contiguo più grande possibile per i tiles (dovrebbe semplificare gli algoritmi dell'engine). E niente, è una cosa perfettamente legittima, solo volevo farvela notare.
C'è un problema: sia i tileset che le tilemap condividono la stessa memoria. Per cui agli inesperti potrebbe capitare che per errore i tiles e le mappe si sovrappongano, generando brutti glitch grafici. un esempio potete trovarlo nella sezione domande,
#chiedere a blake se postare
Detto questo, dovete sempre fare attenzione a cosa succede a basso livello nell'hardware (anche se emulato), non solo nei mondi fantastici e idilliaci degli editor di tilemap (cyclone, NTME)...
Dopo tutte queste raccomandazioni, vi informo che per cambiare l'offset della tilemap di un determinato BG bisogna settare i bit 8-12 del registro BGiCNT, dove i è il numero del vostro BG.
Per concludere vi lascio alcune informazioni sparse. - i registri BGiHOFS e BGiVOFS comandano lo scrolling, ma attenzione, sono read-only! Inoltre non rappresentano la posizione della mappa sullo schermo, ma la posizione dello schermo sulla mappa. E' una sottile differenza, un segno meno che cambia tutto:
- I bit 2-3 dei BGiCNT servono per scegliere quale dei 4 settori di tiles usare come "base". Questo vuol dire che se nella tilemap c'è un indice di un tile, questo verrà preso partendo a contare da uno dei quattro offset dei settori.
- I bit 14-15 regolano la dimensione:
00: 32x32
01: 64x32
10: 32x64
11: 64x64
in unità di tiles.
- Anatomia di una "entry" di tilemap (nel caso i programmi "automagici" falliscano):
F E D C | B | A | 9 8 7 6 5 4 3 2 1 0
|
PB
| VF
| HF
| TID
|
TID: tile Identification, ovvero l'indice del tile. Sarà rappresentato sullo scgermo il tile con quel numero, a partire dalla base (i settori) scelta. Tuttavia, se usate la base 3, non potrete sconfinare nella memoria riservata agli sprite.
HF : Horizontal flipping. Sì, potete anche ribaltare i tiles. Come vedete, le modalità tiled sono molto potenti.
VF : Vertical Flip
PB : Palette Bank. ovvero, quale palette avrà il tile. Non ha significato se il BG è a 256 colori ("ficiur" settabile con l'apposito registro CNT)
- L'ultimo lascito che vi faccio è un piccolo avvertimento, anche se in pokemon non si verifica. Se usate tilemap più grandi di 32x32 (almeno nell'overworld in pokemon non vengono usate, per questo non si verifica), dovete stare attenti all'ordinamento: purtroppo è presente una limitazione, che fa si che le "entry" di tilemap non siano disposte veramente come una tabella, ma sono come spezzettate in sotto mappe di 32x32, e accostate. Mi spiego meglio con un'immagine.
Dunque, dovrete fare fino a 4 mappe separate. Io personalmente non ho mai dovuto fare mappe così grandi, perciò non saprei se i programmi tengono in considerazione questo aspetto. comunque nei pokemon è una cosa rara, e dubito ne avrete bisogno voi stessi.
- Ultima cosa davvero prima di chiudere: se volete abbreviare i tempi di sviluppo, usate usenti (assonanza wow)! ha un esportatore (disponibile anche stand-alone) che è un "life saviour" ! Comprime, genera file .h, .s, palette, tilemap, praticamente è insostituibile!
siete fortunati che non vi do il compito perchè non ho tempo di prepararlo!
CIAONE!
(adesso per un mese basta eh)
- 160720 prima stesura
- 170303 fuchsia, typo, grassetto, 2.1>2.2, battuta Mia, lista puntata info fine
#COMPITOOOOO: tilemap , tiles, palette, 4x4
4 frecce che puntano da diafonale al centro nei 4 esterni x flipping
4 pallini colorati uguali nei 4 centrali per palette
il resto vuoto
Ciao e benvenuto nella mia aula!
Questo corso si prefigge lo scopo di far comprendere i fondamenti del funzionamento più interno del nostro amato Game Boy Advance, per poter, con la pratica, diventare capaci di alterare i nostri giochi! ^^
Vi chiedo di non scoraggiarvi se all'inizio le cose non vi verranno subito. In tal caso bisogna andare a fare un giro per distrarsi, fare un respiro profondo, rileggere attentamente, e nel caso il problema persistesse, consultare il dottore me, che sono qui apposta.
Vi avviso subito che non sono argomenti facili, ma se non avete fretta riuscirete a dominarli.
LEZIONE 0
INTRO
Innanzitutto vi comunico il materiale essenziale:
- Emulatore normale e ROM (facilmente reperibili in commercio). Sapete che preferisco rubino perciò farò più esempi con quella ROM, ma è indipendente quale scegliete, l'importante è essere comodi a lavorarci su.
- Hex editor (spiegato sotto)
- VBA SDL-H
- Assemblatore
- Referenza (quick guide)
Questo invece è Facoltativo:
- Documentazione ufficiale ("approfondimento"):
ovviamente non è necessario che leggiate subito quei documenti, anzi, probabilmente non ci capirete niente le prime volte. Li vedremo insieme, a suo tempo.
cominciamo spiegando di cosa si tratta tutto quel materiale:
Il VBA-SDL-H è una versione modificata del VBA che permette di fare cose avanzate per gli hacker, ed è quello che useremo più spesso durante le ricerche, in quanto torna molto utile come debugger e disassemblatore. Funziona da linea di comando, ma come vedrete non è molto difficile da usare.
L'Asemblatore è un programma che permette di passare dal nostro linguaggio ASM al file binario effettivo (codice eseguibile dal GBA).
Entrambi i tool saranno spiegati in dettaglio più avanti.
Per quanto riguarda l'Hex editor c'è un piccolo discorso da fare. Come alcuni di voi forse già sapranno, è un programma che permette di visualizzare il contenuto a basso livello di un file. Esso sarà il nostro "migliore amico", perciò bisogna sceglierlo bene: quello che volete, su internet ce n'è una svalangata tra cui scegliere (actually sto pensando di farne uno anche io, ma le tempistiche saranno MOLTO lunghe), ergo usate quello con cui siete più comodi. I toolz servono per facilitare il lavoro, non per litigarci contro (e vi posso garantire che è infernale non andare d'accordo col programma in uso, mi è successo). Io attualmente uso questi 3 in accoppiata: XVI32, HxD, WindHex, ma non vuol dire che dobbiate farlo anche voi. Per gli utenti Linux invece di gratuito c'è Bless. Non possiedo mac dunque non posso consigliarvi in tal caso.
Più avanti vi illustrerò brevemente ciascuno di questi tre per permettervi di fare una scelta più oculata. Non serve ora.
Ora faccio un paio di considerazioni.
Innalzo il tempo di risposta dai 5 giorni canonici a 8/10 (ma potrebbero essere anche di più). Ovviamente questo vale solo per lo svolgimento di un compito, perché gli altri post non richiedono grandi capacità o applicazione, perchè si limitano ad esporre dei concetti che possono essere interiorizzati in un paio di giorni. Dunque non c'è neanche bisogno di fissare una scadenza per il resto dei messaggi. Questa modifica semplicemente per il fatto che questa è roba di una certa levatura, a volte anche difficile. Potrà sembrare strano, ma come il mapping, anche l'asm richiede tanto tempo... Per la creatività! Pacman Confused no ok magari non è la migliore scelta lessicale, fatto sta che ci può davvero volere del tempo perchè potrebbe essere impegnativo. Dunque avremo orari... flessibili.
A proposito, vi consiglio di sottoscrivere la discussione clickando sul link in fondo alla pagina, oppure la stella di SchifoTalk  così non dovremo più taggarci come dei matti ( anche perché immagino sarete incollati al pannello di controllo per vedere se ho risposto. ok fine autocelebrazione time  ) : avendo sottoscritto, voi vedrete che ci sono nuovi post dal pannello di controllo; io pure perchè sono l'autore.
Allora la mia idea, prescindendo dagli argomenti trattati, era di preferire un post grosso diviso in più parti, in modo da poter analizzare con calma ogni singolo aspetto. Non disdegno la tecnica "mordi e fuggi", ma in questo caso non potrebbe essere applicata per svariati motivi. Magari negli altri casi, come spiegare i comandi di XSE un po' per volta, può funzionare, ma non qui.
Se alcuni concetti esposti in questo messaggio non vi saranno subito chiari non preoccupatevi, li riprenderemo ~
Detto questo ci vediamo la prossima volta, rispondete quando siete pronti per continuare. Smile
nel malaugurato caso in cui, per qualche motivo, non possa rispondere, Siete autorizzati a mandarmi un (1) messaggio privato per ogni settimana passata.
Saluti
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere e guarda notepad
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
08-10-2017, 04:36 PM
(Questo messaggio è stato modificato l'ultima volta il: 11-03-2018, 01:10 PM da Bonnox.)
questa lezione è vicinissima al completamento, direi anche la prossima volta.
quando tutte saranno finite le riunirò in un documento unico.
LEZIONE 1
I MATTONCINI DELLA ROM:
IL LINGUAGGIO BINARIO
Purtroppo, come ho già detto, questo corso deve coprire grandi quantità di informazioni. Prima di cominciare, dovrete quindi conoscere il significato di alcuni termini e concetti (ovviamente se li conoscete già potete saltare). Una volta chiedevo come prerequisito la conoscenza di una cosa chiamata "sistemi di numerazione", ma a scanso di equivoci, e per completezza, riporto comunque le nozioni basilari, alla "quick and dirty". Infatti, come tutte le cose che traggono origine dalla matematica, il discorso è molto complesso, ma io vi dirò solo quello che vi serve sapere.
Per la vostra gioia dunque partiamo con un po' di matematica.
Noi umani solitamente contiamo usando le mani, perciò arriviamo fino a 10. Stiamo dunque inconsapevolmente utilizzando la base decimale della notazione posizionale. Che significa? Semplicemente ogni posizione nel numero ha un significato diverso, ovvero, per esempio, tra 1, 10 e 100 c'è una bella differenza! Questa differenza è precisamente un'esponenziale di 10, ovvero, per ogni posizione che aggiungo, il numero aumenta di 10 volte. Inoltre, i numeri si possono esprimere, in forma completa, come somma dei contributi delle singole posizioni:
ad esempio il numero 619 si può vedere come 6*10^2 + 1*10^1 + 9*10^0.
Mentre invece gli antichi romani dovevano fare 500+100+10+10-1, dato che poverini avevano la notazione additiva.
Esistono poi, oltre alle notazioni, le basi. Tralasciando le complicazioni matematiche, a voi serve sapere che una base è il valore del peso di ciascuna cifra. Quando scriviamo numeri "normali" è 10. In informatica si usano molto anche il 2 e il 16. Il sistema che usa base 2 si chiama binario, mentre quello con la base 16 si chiama esadecimale. Come funzionano? Funzionano come il nostro, con l'unica differenza nel numero delle cifre. Noi contiamo da 0 fino a 9, e poi azzeriamo quella posizione per mettere un 1 a quella successiva. Lo stesso con il binario e l'esadecimale, ricordandoci però che le cifre sono rispettivamente {0, 1} e {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F}.
In generale, Per convertire da qualsiasi basa alla decimale si fa come il mio precedente esempio con 619, cambiando ovviamente il fattore moltiplicativo. Come esempio userò il famoso numero 80C, convertendolo da esadecimale a decimale:
8*16^2
+
0*16^1
+
12*10^0 (C vale 12)
= 2060.
Invece per convertire da decimale ad un altra base Dovete ripetere i passaggi:
- dividete il numero da convertire per la base (esempio 16)
- segnatevi il resto della divisione
- ora il numero da dividere diventa la parte intera della divisione precedente.
- e smettete quando arrivate per la prima volta ad avere resto 1 (altrimenti andate avanti all'infinito).
- per formare il numero mettete in sequenza i resti a partire dall'ultimo
http://pokehack.altervista.org/attachmen...mbnail=278
l'esempio mostra la conversione di 23 in base 2, ovvero 10111.
Una nota: precisate sempre in che sistema state scrivendo quando si parla di numeri in questa aula, altrimenti ci potrebbero essere disastrose incomprensioni!
è universale mettere un prefisso "0x" ai numeri esadecimali, poi ci sono comunque degli standard... Ecco quelli che io sicuramente "capisco" ("OCT"si riferisce alla base ottale, dove le cifre vanno da 0 a 7):
- PREFISSE:
- SUFFISSE:
- HEX:
- DEC:
- d
- # (dipende dalla piattaforma usata, in quanto va in conflitto con un altro, io di solito lo uso per numeri a tre cifre)
- BIN:
Per finire con i prerequisiti, diamo alcune semplici definizioni:
- Bit
Elemento che ha origini agli albori dell'informatica. E' un elemento che può assumere 2 stati diversi. Solitamente sono acceso e spento, nati dai valori della tensione in un circuito nei primi calcolatori elettronici, ma il significato non cambia a seconda della tecnologia utilizzata (magnetica, ottica, quantistica). Bit è la contrazione dell'inglese "BInary digiT", che significa "cifra binaria". Si rappresenta con le 2 cifre del sistema binario (0 e 1). È l'unità fisica minima nell'informatica.
- Byte:
È l'unità logica fondamentale (logica>fisica), composta da un gruppo di 8 bit su un qualunque supporto di memorizzazione (CD, chiavetta, radio...) Se facciamo la combinazione di tutti i suoi termini, vediamo che può assumere 2^8 = 256 stati diversi. Nel nostro sistema decimale per elencarli si parte da 0 e si arriva a 255. In binario si parte da 00000000b e si arriva a 11111111b. In esadecimale, la base che useremo più spesso, quei valori si scrivono 0x0 e 0xFF. Potreste anche verificarlo voi stessi con le formuline di prima.
Perchè un byte si rappresenta in esadecimale? perchè è il modo più veloce, in quanto ha solo 2 cifre, e ciascuna rappresenta separatamente i primi o gli ultimi 4 degli 8 bit, cosa che non avviene in base 10. Se non ci credete, fate delle prove.
- Offset:
letteralmente "scostamento" in inglese, indica lo spostamento di un preciso byte relativamente a un'origine. Noi fortunatamente consideriamo sempre tale origine come il primo byte della ROM, dunque indirizzo 0 (ricordo che in informatica, e a volte in matematica, si inizia sempre a contare da 0), il che semplifica i conti; ma non è raro il caso di dover iniziare a contare a partire da un altro valore: ad esempio per hacking di altre console, principalmente nintendo e vecchie (il caso più vicino a noi è il GB) si divide la ROM in varie parti di uguale grandezza, e ognuna determina una diversa origine del valore dell'offset.
- Puntatore:
generalmente in informatica è un valore che indica, da cui l'usanza di dire "punta", un'area della memoria della macchina. Generalmente nei computer indica la RAM, ovvero la memoria temporanea che contiene i dati in attesa di essere elaborati; Mentre noi avremo quasi sempre a che fare con puntatori alla ROM, che è la memoria di sola lettura in cui risiede il gioco.
Come avrete capito in questa prima parte lavoreremo sui byte; nonostante ahimè sia un lavoro noioso secondo me è più facile da comprendere rispetto agli ultimi argomenti, più difficili ma divertenti, una volta compresi.
Ogni file sul nostro computer è composto da una serie più o meno lunga di bytes. Come avrete avuto modo di notare usando il PC durante il vostro hacking, la rom occupa esattamente 16 MB, il che è veramente poco al giorno d'oggi, ma dobbiamo considerare che risale al 2002 e per giunta è per una piattaforma mobile.
All'interno di ogni programma informatico (tra cui il gioco) ci sono, stipati insieme, due elementi: Istruzioni e Dati. La loro presenza dovrebbe far funzionare correttamente il tutto. Le istruzioni sono ciò che vedremo con l'Assembly, ovvero il "codice" che il GameBoy esegue una volta caricato il gioco, come ad esempio "fai questo suono", "memorizza tale valore", “visualizza l’immagine”, "muovi la pokeball", eccetera. I dati invece sono informazioni conservate nella ROM con un preciso formato, ma da soli non basterebbero a dar vita al gioco, nonostante siano proprio loro a caratterizzarlo come tale. Ad esempio, pokemon rosso fuoco e smeraldo condividono la maggior parte delle istruzioni, ma i dati sono completamente diversi. Servono tutti e due, ma se uno ha solo i dati non fa nulla, mentre se ha solo le istruzioni può avere qualcosa da mostrare con il minimo sforzo aggiuntivo - vedasi pokemon essentials, un progetto RPG con tutte le istruzioni di un gioco pokemon e 4 mappe in croce. Le prime versioni avevano pochissimi dati, però funzionava. Ad esempio sono dati le musiche, le mappe, i pokemon degli allenatori, i testi dei messaggi…
Tutto ciò che non rappresenta il comportamento del sistema è un dato. Coincidenza, quasi tutto quello che viene modificato dai programmi di hacking è un dato. Advance map modifica i dati. Ricordatevelo.
In questa sezione imparariamo a farlo anche senza programmi, non perchè io sia cattivo o cosa, ma in alcune occasioni può tornare utile. Comunque tranquilli, una volta imparato non dovreste averne quasi più bisogno, ma sempre meglio sapere come fare.
E' altresì importante chiarire il fatto che di per sè non esisterebbe la distinzione tra istruzioni e dati. Infatti, sia le istruzioni che i dati sono rappresentati sotto forma di bit e byte. Capiremo meglio il motivo quando faremo l'ASM, per ora prendetelo come un dogma di fede: i dati possono essere anche erroneamente interpretati come istruzioni, ma anche viceversa (vedasi i vari glitch di pokemon red). E se per noi è un fastidio in quanto tutto va male, per la macchina in realtà non cambia assolutamente nulla, semplicemente non gliene frega niente, è solo colpa nostra. Sta al creatore controllare che il suo gioco non si comporti in modo errato. Sul computer questo invece non succede quasi più da quando esistono sistemi operativi solidi, ma nel caso dovesse accadere probabilmente c'è un virus nel computer. Dal 3DS in avanti anche le console nintendo hanno un sistema operativo.
Bene, eccoci alla vera lezione. Mi scuso se sarà un po’ monotona, ma è importante. Come diceva un mio professore, “il brutto delle cose facili è che vanno sapute perfettamente”.
In questa lezione faremo una partenza soft con l'hex editor, giusto per prenderci la mano.
Aprite un hex editor. L'Hex editor è un software che ci permette di visionare e modificare i bytes di un file. Ecco come si presentano alcuni di essi una volta aperti (non spaventatevi, sono 3 programmi diversi, li ho affiancati per paragonarli):
http://pokehack.altervista.org/attachment.php?aid=297
Iniziamo caricando un nuovo file. Consiglio un file che non vi serve più (ad esempio potete creare un nuovo documento di testo da usare come cavia), dato che andremo a pasticciare e a rovinare
Normalmente troveremo tre colonne: la prima, piccola, indica l’offset in cui ci troviamo, quella centrale visualizza tutti i byte, e l’ultima colonna ci indica gentilmente la loro rappresentazione testuale, cosa di cui non potrebbe fregarci di meno, dato che per noi è inutile.
L’unico utilizzo che può avere per noi tale parte è per “rincuorarci”, ovvero trovare un piccolo conforto in caratteri familiari di fronte all'agonia della prima vista dei bytes. Ok, dovrò andare a fare il drammaturgo  Posizionate il cursore e clickate sulla colonna a destra, e iniziate a scrivere cose a caso sul file cavia. Notate che c’è una corrispondenza a sinistra con ciò che scrivete?
Ora vorrei che vi prendeste un attimo di tempo per fare una cosa. Iniziate a scrivete tutte le lettere dell'alfabeto, dalla a alla z, minuscole e maiuscole, e poi anche i numeri. Cosa notate? I byte a destra assumono precisi valori. Signori, questo è l’ASCII. Questo è uno standard americano di comunicazione nei primi computer. In pratica assegna ad ognuno dei valori ottenibili da 7 bit a un carattere o simbolo. La tabella attualmente diffusa è quella di MS-DOS, mentre tanto tempo fa c'erano discrepanze a seconda del sistema operativo.
Ora prendiamo confidenza con le funzionalità del'H.E.. Non so il percorso del mouse da seguire con il vostro, ma esiste una scorciatoia praticamente universale che tutti implementano: CTRL+F. Si aprirà una finestra chiamata ricerca. Qua ci mettete del testo che volete venga cercato all'interno di un file. Se state usando una rom di pokemon non avrete fortuna, perciò cambiate subito file. Potete ad esempio scegliere un documento di testo (txt, non word). Dopo aver avviato la ricerca il cursore si posizionerà sulla prima occorrenza del testo; per cercare ancora premete F3. Oppure create una lista di risultati, che è più comoda:
http://pokehack.altervista.org/attachment.php?aid=298
Ricordate che anche se in generale sono simili, ogni hex editor ha proprie funzioni aggiuntive che vale la pena provare e sfruttare
Ad esempio poco fa, con la lista dei risultati, avete visto in azione una delle caratteristiche che più mi piacciono di windhex. Peccato che lui sia un po’ scomodo da usare “quotidianamente”.
http://pokehack.altervista.org/attachment.php?aid=415
http://pokehack.altervista.org/attachment.php?aid=416
Ora vorrei concentrarmi su una cosa molto importante che tornerà sempre utile, ovvero la ricerca dei puntatori. Come accennato prima, sono dei valori che indicano una posizione all'interno della memoria del GBA, che vedremo in dettaglio in futuro. Ipoteticamente, ogni byte potrebbe avere il suo puntatore, basta costruirlo. Nella realtà però non è così perché si indica soltanto il primo byte di qualcosa, la cosiddetta "risorsa" del gioco, come un'immagine, un testo, ecc..., mentre quelli seguenti sono referenziati tramite un indice di scostamento rispetto al puntatore (l’origine di cui parlavo prima).
Considerate questo esempio:
“Quel fez sghembo copre davanti”
non preoccupatevi, è soltanto un pangramma. Volevo mettere quello degli ioni o quello della volpe, ma nell’aprire wikipedia ed aver visto una citazione al mio telefilm preferito… beh… <3 giustamente dovevo metterla, concedetemelo.
Analizziamo ora la frase:
[ Q ][ U ][ E ][ L ][ ][ F ][ E ][ Z ][ ][ S ][ G ][ H ][ E ][ M ][ B ][ O ][ ][ C ][ O ][ P ][ R ][ E ][ ][ D ][ A ][ V ][ A ][ N ][ T ][ I ]
Abbiamo un indice che identifica ogni lettera:
[00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29]
Se contate, le due righe hanno lo stesso numero di caratteri.
Se volessimo accedere ad una lettera, non dovremmo fare altro che sommare l’indice all’offset del primo carattere.
capiamo meglio con un’immagine:
http://pokehack.altervista.org/attachment.php?aid=300
In questo esempio possiamo vedere che l’offset del primo carattere è 9D3CE4h, e se voglio l’indice del carattere z devo sommare l’indice di z, ovvero 7.
Spero sia chiaro, altrimenti non fatevi scrupoli a chiedere.
Ora vediamo quali sono i passaggi per ottenere un puntatore. Per il momento ci saranno dei punti poco chiari, ma nelle prossime lezioni saranno rivelati.
Dato un offset lungo 3 byte, il suo puntatore è: - scrivere XX XX XX 08;
- invertire l’ordine dei 3 byte (quello in mezzo ovviamente resta in mezzo)
- sostituire i nuovi byte alle X, in ordine.
Ecco l’esempio per 9D3CE4: - scrivo XX XX XX 08;
- ribalto i bytes: E4, 3C, 9D.
- sostituisco: E43C9D08.
Questo è il puntatore come se fosse stato inserito nella ROM originale. Ora basta metterlo nel posto giusto e il gioco potrà usare il nuovo testo, e nessuno si accorgerà della modifica! Questo è ciò che fa, a volte sbagliando perchè è buggato come l'inferno, advance text.
Avete voglia di ricavare qualche puntatore, così giusto per esercizio? è proprio una sciocchezza, si fa in meno di 2 minuti, ma serve a molto.
Ricavate i puntatori dei seguenti offset:
Spero lo abbiate fatto, perché alla fine della lezione vi servirà.
Bene, eccoci finalmente alla vera pratica. Recatevi all’offset 3E6E50 di ruby. Come fare? Non so quale sia il vostro menu a tendina, ma sicuramente potete fare CTRL+G, tutti gli hex editor hanno questa scorciatoia.
Inserite l’offset come faccio io e dovreste avere il seguente risultato;
http://pokehack.altervista.org/attachment.php?aid=301
Questo è un dato binario. Significa che è un dato rappresentato nel suo tipo (formato) naturale. ne consegue che solo chi sa leggere quel tipo di dato potrà comprenderne il significato. Fate una prova: aprite un’immagine con il blocco note. Cosa esce? Caratteri incomprensibili, perché il blocco note non sa leggere le immagini, lui poverino cerca solo il suo formato di dati (il testo) nell'immagine. Se provate ad aprire file prodotti da un'altra applicazione con un programma totalmente diverso, sarete fermati da un errore di incompatibilità. I programmi si aspettano certe cose nel file che aprono, e se non le trovano prevengono potenziali (anzi, sicuri) catastrofici errori dicendo di non poter aprire il file.
Che poi VLC sia zelante e apre tutti i formati dell'universo in tha worldz forevah and evah mentre Windows media player invece è una checca schizzinoso sono dettagli… L'importante è che non cerchiate di fargli aprire un documento, ma un video! Dunque dicevo, ciò che troviamo sulla rom deve essere interpretato come il tipo di dati giusto per produrre un output coerente per l’utente. Altrimenti si verifica la stessa cosa di missingno: Secondo pokemon rosso laggiù ci doveva essere il verso di un pokemon, mentre invece c’erano altri dati… ecco da dove nasce l’inquietante verso di ♀ (“female”). Ed ecco perché sembra non finire mai: interpretando tali dati come suono, i byte che indicano la fine del suono non vengono raggiunti in tempi ragionevoli. A noi invece il massimo che possa capitare è vedere qualche carattere giapponese in un messaggio (mai capitato durante il corso di XSE?), perché magari sbagliamo a mettere l’offset, confondendolo con il puntatore o il testo; questo perché una ROM del GBA è dannatamente più stabile e comoda da modificare rispetto al GB.
Come modificare tali dati binari allora? Dobbiamo innanzitutto scoprire cosa rappresentano. Io lo so già perché riciclo gli esempi
Nota:
Non è questo il caso, ma se vi capitasse che i dati non siano word-aligned, ovvero allineati ogni 4 byte, ovvero ad un offet non terminante per 0,4,8,C (visto che belli i criteri di divisibilità in base 16??), è necessario copiare i byte in un nuovo file per poterli analizzare meglio.
Dovete, con il vostro hex editor di fiducia, selezionare il pezzo che vi interessa, copiarlo e incollarlo in un nuovo file. Il procedimento cambia da programma a programma, se non riuscite sono qui apposta.
Tuttavia anche se stavolta non serve è utile sapere come si fa, perciò ricordatevelo.
riprendendo il discorso, ecco cosa dovreste vedere nell'immagine, come i test che fa lo spicologo:
http://pokehack.altervista.org/attachment.php?aid=237
Sicuramente ve lo aspettavate, conoscendomi  chiedo nuovamente scusa a fiammy per aver dimenticato di colorare il suo posticino di meditazione quotidiana
Bene, ora che sappiamo cosa è analizziamo il formato: sembra che ogni valore del byte corrisponda a una città (A GINIUS!). è importante però notare una cosa: il valore 57h indica il vuoto. Anzi, empiricamente possiamo notare che qualunque valore al di sopra di 57h indica vuoto.
Il vostro compito è di modificare (tramite hex editor, ovviamente) la worldmap e farmi vedere il risultato.
Una volta gli alunni passati mi hanno posto due domande argute, vi lascio qualche riga vuota per farvi provare a formularle anche a voi.
-
-
-
-
-
La prima domanda era se è possibile mettere più di 56h città. La risposta, mio caro ragazzo, è che sì, è possibile, ma non con l'hex editor. Noi con l'hex editor abbiamo modificato i dati, ma le istruzioni impongono un numero massimo di città. Capite bene che la vera potenza sta nell'ASM, l'hex editor è solo il canale di sfogo di questa.
La seconda domanda è come io sia arrivato a trovare l'offset contenente la mappa. Ci sono due modi: il primo, da non fare, è aprire advance map, andare su editor mappa del mondo, vedere che ciascun quadratino corrisponde a una città e ha un numero, prendere una riga qualunque della mappa, e cercare nell'hex editor la sequenza di numeri ottenuta scorrendo il cursore. Il secondo modo invece, quello giusto, purtroppo mentre stavo scrivendo in realtà non posso dirvelo perchè mi sono accorto che prevede conoscenze di lezioni future. ricordatemi di dirlo nella prossima lezione verde.
#
Vi do un cosniglio: anche se la tentazione di non farlo è forte, conviene sempre spostare il vostro dato in un nuovo file. Infatti potete vedere subito se per sbaglio aggiungete dei byte. Controllate sempre di essere in modalità OVERWRITE! Inserendo bytes spostate altra roba che viene dopo, che dunque non è più al suo posto, e non verrà letta correttamente. Finchè si tratta di dati si può soprassedere (immagini, testi e suoni glitchati senza sapere da dove vengano), ma se sono istruzioni, la cosa si fa grave: non va mai bene, e alla peggio ci crasha la ROM...
Inoltre, fate spesso backup. vi torneranno MOLTO utili, soprattutto le prime volte che sperimentate qualcosa di nuovo, dato che sono più alte le probabilità che qualcosa vada storto.
Per compito i 4 angoli della tabella devono contenere una città a vostra scelta, in più invertite albanova e solarosa. Chi lavora su fire red può fare il compito su fire red, per questa volta. L’offset è 3F2500h. Anche lì, con l'hex editor invertite le prime 2 città.
Questo è un compito per farvi imparare a contare. Come?, direte. Si, perché avrete notato che i dati sono tutti immagazzinati in fila indiana, non ci sono righe o colonne. La presenza di righe e colonne è dedotta dal software, mediante un semplice procedimento:
- So le coordinate X e Y del dato della tabella che devo leggere.
- Moltiplico la Y per il numero di elementi di una riga
- Sommo X al precedente risultato
- Sommo l’offset del primo elemento della tabella al precedente risultato.
Come funzionano questi passaggi? Facciamo un esempio passo-passo.
Supponiamo di avere all’inizio di un file una talebba di 9 elementi, così:
A B C
D E F
G H I
Ma ovviamente nella memoria essa è contenuta in linea retta: [ [ ( A ), ( B ), ( C ) ], [ ( D ), ( E ), ( F ) ], [ ( G ), ( H ), ( I ) ] ] . Come facciamo ad accedere ad un elemento? Dobbiamo indicizzarla.
Mettiamo di voler accedere alla posizione centrale E, di indice 1,1 (si parte a contare da 0).
- Moltiplico y*la larghezza: 1*3=3
- Sommo la x: 3+1=4
- Sommo l’offset di inizio della tabella: 4+0=4
Dunque prendiamo il valore alla posizione 4. Contiamo insieme (scusate se vi sembro Dora l'esploratrice >.<  ):
0-A,
1-B,
2-C,
3-D,
4-E.
Tutto questo casino per cosa? Per sapere cosa state modificando. Se siete sulla ROM vi perderete in fretta, per cui bisogna sempre contare prima di scrivere qualcosa.
Ma tanto già so che voi avrete ridimensionato la finestra del programma per avere esattamente 28 colonne, vero? Sempre che il vostro hex editor permetta ciò. A questo punto il compito diventa una bazzecola.
Ora proviamo a fare una cosa più complicata. Vi giuro che è l’ultima per oggi.
Spostiamo la worldmap.
Cosa? Eh, dai, su, non ho mica detto di spostare una regione intera, è solo una cartina! Mica siamo dei titani, solo dei geografi!  ok pessima citazione della mitologia greca Ecco il procedimento passo per passo. Vorrei lo faceste per compito.
Per poter proseguire, dovete aver fatto il mini esercizio sui puntatori. Se proprio non riuscite chiedete.
Prendete l'offset della worldmap. Aprite la ROM con l'hex editor e cercate una stringa esadecimale. Scrivete il puntatore che avete ricavato prima (quello dell'esercizio è lo stesso di questo). Se tutto è corretto dovreste averlo trovato una sola volta. Se di più o avete usato rosso fuoco e allora non so, oppure c’è qualcosa di sbagliato, nel caso chiedete pure. Si trova a FB328h per ruby.
Sostituitelo. Con cosa? Ma con quello che volete voi. Ad esempio provate un offset a caso. Scrivete davvero 3 (TRE!) byte a caso, anche se vi sembra assurdo, è un procedimento istruttivo. Poi aprite la mappa città nel gioco e vedete che succede. Il gioco interpreta come mappa città dati che mappa città non sono. Complimenti, avete buggato la ROM! Tranquilli, è riparabilissimo, basta fare l'operazione inversa! Ora torniamo indietro. Mettete il puntatore di questo valore: 720000h. se la rom è vergine, dovrebbe esserci spazio laggiù. Ora, copiate la vostra wolrdmap in tale punto. Modificate valori della worldmap che vi ho chiesto. Se tutto va bene, cancellate quella originale, scrivendo 420d volte 00h o FFh. O qualsiasi cosa, ma questi due valori sono molto più "convenzionali".
Per concludere, vi lascio un piccolo esempio che riassume al meglio cosa significhi l'hex editing.
- Aprite advance map, una ROM qualsiasi e una mappa qualsiasi.
- prendete un tile qualsiasi e mettetelo nella prima casella della mappa, in alto a sinistra, e ricordatevene il numero, che compare nella barra di stato in basso.
- salvate
- aprite windhex, e usate la funzione compare files.
- mettete la rom che avete appena usato come cavia e una pulita.
- se fate compare, vi dirà 2 byte sono cambiati.
- andate a vedere tali byte, ad esempio io che ho usato albanova ho "2913B4" e noterete che i numeri che troverete lì coincidono, più o meno, con il vostro tile. Più o meno perchè innanzitutto sono "girati", e poi perchè il secondo non è identico, ma ha un 4 o un 3 aggiuntivi. Il 4 o il 3 io stesso non so cosa siano, suppongo sarà qualche ottimizzazione fatta da game freak. Il perchè è girato lo vedremo un'altra volta. Però sono loro. Per fare una prova, tornate in advance map, e selezionate la scheda "vista header", e premete CTRL+H, per aprire la vista "professionale". Se tutto è andato bene, dovreste vedere il vostro offset sotto il riquadro "dati mappa" e "offset mappa".
Cosa è successo?
Abbiamo visto cosa succede nella realtà quando usiamo un programma automagico. Ora io non voglio dirvi di buttare advance map e usare per sempre l'hex editor, ma farvi capire la mole di lavoro fanno questi programmi per voi. E pensate che se si aumentano le dimensioni il programma deve anche trovare dello spazio libero per inserire la nuova mappa più grande. Vi ho fatto fare questo perchè prima o poi si rivelerà necessario: ad esempio talvolta si "bruciano" le mappe, e con un po' di fortuna potete recuperarle. Ovviamente con ciò non dovrete scordare di fare i backup.
Inoltre è sempre importante almeno sapere nella teoria cosa fanno a basso livello i programmi di automazione che si usano, questo vale in ogni campo dell'informatica.
Se avete qualsiasi cosa da dire, non abbiate paura!
Bye!
- 171008: istituito changelog per questo testo. migliorata sezione matematica,
migliorie in generale, rimosse cose inopportune (esempio: emoticon wozzap),
correzioni (esempio .doc non è visionabile in modo intelligibile con hex editor). corretto il ( c ) (copyright) nella tabella aggiungendo spazi per armonizzare l'aspetto. rimosse soluzioni esercizio puntatori. rimosse alcune parentesi. aggiunto reminder backup
NOTA PER ME: METTERE SECONDO MODO MAPPA HOENN
mi raccomando come al solito leggete attentamente tutto e ponderate ogni frase, il programma è enorme e sono costretto a fare grandi tagli, ciò che esprimo in una frase in realtà potrebbe essere uno spunto d'approfondimento per intere pagine
.
LEZIONE 3.1
DA UN PROBLEMA ALLA SOLUZIONE:
INTRODUZIONE ALLA PROGRAMMAZIONE
Siccome questo è un argomento troppo importante per essere saltato, vi tocca. Senza di esso potreste avere varie difficoltà in seguito, perciò ho deciso di affrontarlo una volta per tutte. Inoltre è un requisito nel caso in cui voleste imparare un linguaggio di programmazione ad oggetti (come il Ruby, usato in rpg).
___
Ogni giorno ci troviamo a dover risolvere dei problemi. Ad esempio scegliere cosa fare da mangiare o montare un mobile sono alcuni dei problemi quotidiani. La maggior parte di essi sono risolti istintivamente da, nel senso che non ci riflettiamo più di tanto perché viene spontaneo. Mentre se il problema è più difficile (montare il mobile IKEA) dobbiamo seguire le istruzioni che ci vengono fornite. Anche i computer vengono utilizzati per risolvere problemi, infatti è il loro scopo principale (a parte giocare e visitare pokehack e i socialnetwork :p) Una volta erano prevalentemente di tipo matematico (i primi computer erano solo enormi calcolatori), mentre oggi si utilizzano per qualsiasi scopo: esempio previsioni del tempo, controllo di una centrale atomica, realizzazione di grafica. I computer però non ragionano da soli, serve qualcuno che li "istruisca" per fare tutte queste cose utili, ovvero il programmatore. Ebbene, c'è una similitudine tra il computer e noi che montiamo un mobile: seguiamo delle istruzioni scritte da altri. Questo insieme di istruzioni viene chiamato algoritmo. Si potrebbe scendere nei dettagli sulle proprietà degli algoritmi, ma sarebbe noioso per voi e per me che dovrei andare a riprendere gli appunti di tanti anni fa. Perciò per il momento ci concentriamo sul capire bene cosa fanno e come funzionano questi algoritmi. Ne incontriamo a bizzeffe ogni giorno, il mondo ne è pieno. Sostanzialmente, ad ogni problema risolvibile è possibile associare un algoritmo risolutivo. Un algoritmo è una sequenza di passi (istruzioni) da eseguire per risolvere un problema.
Ad esempio per preparare la pasta ci sono dei passi che il cuoco esegue: accendi il Gas, metti l'acqua, ecc. Per quanto possa sembrarci “naturale” o istintiva, in realtà una qualsiasi azione è il frutto di ben precise "istruzioni", eseguite in sequenza dal nostro cervello. Un altro esempio di algoritmo molto semplice lo avevamo visto le volte scorse, quando vi avevo detto come ricavare un puntatore o indicizzare una tabella.
La programmazione è l'"arte" di istruire i computer. per farlo serve elaborare un algoritmo che risolve il problema. in questo corso non risolveremo problemi di tipo strano, come la costruzione di un mobile o la preparazione di una pietanza; agli inizi saranno prevalentemente di tipo matematico per prendere confidenza con le strutture necessarie, e poi sposteremo il campo verso la piattaforma GBA e i pokimunz.
Un tipico problema che vi potrei dare di compito è determinare il massimo tra una serie di numeri.
Un esempio di problema che potreste ritrovarvi a risolvere durante l'hacking: eliminare un pokemon esausto dalla squadra per la modalità di difficoltà estrema.
Adesso compirò quella "brutta cosa" che è copiare wikipedia per informarvi sulle proprietà degli algoritmi, per aiutarvi a capire il tipo di procedimento necessario:
- I passi costituenti devono essere "elementari", ovvero non ulteriormente scomponibili (atomicità)
- I passi costituenti devono essere interpretabili in modo diretto e univoco dall'esecutore, sia esso umano o artificiale (non ambiguità)
- L'algoritmo deve essere composto da un numero finito di passi e richiedere una quantità finita di dati in ingresso (finitezza)
- L'esecuzione deve avere termine dopo un tempo finito (terminazione)
- L'esecuzione deve portare a un risultato univoco (effettività).
In generale non esiste una sola soluzione ad un dato problema; le soluzioni potrebbero essere numerose. La programmazione consiste proprio nel trovare la strada più efficiente che conduce alla soluzione del problema in oggetto. Ecco perchè programmatori diversi possono dare diverse soluzioni (magari corrispondenti a diverse visioni del problema), anche se entrambe corrette.
"Ho capito, ma come faccio a risolvere un problema?"
Bisogna precisare che non esiste una "ricetta" universalmente valida, ma ci sono dei paletti che definiscono in generale un percorso da seguire per semplificare l'approccio.
Per risolvere un problema innanzitutto bisogna "prenderlo" e analizzarlo. La prima cosa da fare è stabilire cosa richiede la soluzione (output) e cosa dobbiamo conoscere in principio per poter risolverlo (input). Prendo l'esempio del massimo tra dei numeri: cosa devo fornire al programma e cosa deve "buttar fuori"? Devo inserire alcuni numeri, e devo ricevere ancora un numero. Non è detto che si utilizzino sempre solo i numeri per operare, si può anche operare sul testo, sulle immagini, sui pokemon, ecc, così come il programma potrebbe dare quelle cose come soluzione.
Poi esistono due diversi approcci, entrambi validi, per analizzare il problema e iniziare a determinare una soluzione. Il secondo è sconsigliato ai Principianti.
Top-down e Bottom-up; Come suggerisce il nome, i due sono opposti.
Nel modello top-down si formula inizialmente una visione generale del sistema, ovvero se ne descrive la finalità principale senza scendere nel dettaglio delle sue parti. Ogni parte del sistema è successivamente rifinita aggiungendo maggiori dettagli della progettazione. Ogni nuova parte così ottenuta può quindi essere nuovamente rifinita, specificando ulteriori dettagli, finché la specifica completa è sufficientemente dettagliata da validare il modello. Il modello top-down è spesso progettato con l'ausilio di "scatole nere" che semplificano il riempimento ma non consentono di capirne il meccanismo elementare.
In contrasto con il modello top-down c'è la progettazione bottom-up, nella quale parti individuali del sistema sono specificate in dettaglio, e poi connesse tra loro in modo da formare componenti più grandi, a loro volta interconnesse fino a realizzare un sistema completo. Le strategie basate sul flusso informativo bottom-up sembrano potenzialmente necessarie e sufficienti, poiché basate sulla conoscenza di tutte le variabili in grado di condizionare gli elementi del sistema.
Ricapitolando le differenze ma senza scendere troppo nei dettagli tecnici, abbiamo che:
La programmazione top-down è uno stile di programmazione in cui la progettazione inizia specificando parti complesse e suddividendole successivamente in parti più piccole (“divide et impera”). Eventualmente, i componenti sono specificati quanto basta per la codifica ed il programma viene anche scritto.
Il bottom up prende corpo dal punto di partenza (bottom) ovvero dalla situazione iniziale; considera l'obiettivo finale, induce a costruire un percorso sequenziale organizzato in passaggi successivi in cui l'ancoraggio tra traguardi intermedi e obiettivo finale è generalmente ricercato in modo intuitivo (euristico).
Come compito potreste descrivermi nel linguaggio a voi più naturale (es: italiano scritto) la risoluzione di un paio di problemi. (non copiatevi)
nella lezione successiva vedremo di formalizzare le vostre soluzioni con opportuni metodi e iniziare la programmazione. Dopodichè vedremo l’ASM.
In passato c’è stata incomprensione su come eseguire questo compito. Ciò che dovete fare è raccontarmi, come se foste un libretto di istruziini per montare il mobil,. cosa fareste per risolvere il problema, il vostro approccio insomma.
Se conoscete già un linguaggio più formale usatelo pure.
ESEMPIO:
problema: dati 3 numeri, determinare il maggiore.
Soluzione:
- chiedo all'utente i valori dei 3 numeri, uno per volta
- li confronto due a due
- quello che "vince più volte" è sicuramente il maggiore.
COMPITO:
facile: Calcola l'area di un n-agono (figura geometrica regolare con n lati) (n a scelta dell'utente) (SUGGERIMENTO: vai a rivedere le formule)
facile/medio (ma dipende dal livello di formalismo del linguaggio usato): fornire i primi 40 multipli di 13 (SUGGERIMENTO: dovrete contare le volte...)
facile/medio: Dati due numeri effettuare il loro prodotto usando solo l’operazione somma
medio: Calcolare le soluzioni reali dell'equazione ax^2+bx+c=k (SUGGERIMENTO: torna comodo un linguaggio matematico)
ciao
-171020: Chiarite cose, reso meno pesante (parentesi), specialmente a inizio e fine
- 160613: liste, maiuscole, interpunzione, sistemazione alcune frasi sconnesse, sbianchettato una frasi
- prima: boh # quando metti le funzioni aggiungi questo
You can think of a procedure like a spy who leaves with a secret plan, acquires resources, performs the task, covers his or her tracks, and then returns to the point of origin with the desired result. Nothing else should be perturbed once the mission is complete. Moreover, a spy operates on only a “need to know” basis, so the spy can’t make assumptions about his employer
.
LEZIONE 4
ASM
#integrare con jpan
Eccoci alla parte che forse vi interessa maggiormente! Se avete capito bene l'ultima lezione non dovreste avere grossi problemi.
Spesso abbreviato in ASM, è quanto di più vicino al linguaggio macchina l'uomo possa comprendere senza diventare pazzo. Infatti il linguaggio macchina è fatto dai cosiddetti codici operativi, ovvero dei byte per noi apparentemente incomprensibili che vengono letti dal processore, ed ciascuno ha un preciso significato come istruzione. La sua particolarità rispetto agli altri linguaggi di programmazione è che c'è una corrispondenza 1:1 tra istruzioni scritte e istruzioni reali della macchina: significa che per ogni istruzione scritta/letta da noi esiste un singolo codice operativo. Per noi programmatori moderni questo è un grosso handicap, perchè complica molto il lavoro di programmazione, in quanto dobbiamo occuparci di tutti i piccoli dettagli di cui di solito il compilatore si occupa per noi. L'assembli infatti è stato inventato per risparmiare la fatica di programmare i primi calcolatori inserendo a mano nella loro memoria direttamente il codice macchina costituito da zeri e uni (potete vederli nei documenti linkati nella lezione 0).
L'assembly, come avrete intuito, è un linguaggio a basso livello, per cui non è dotato di tutti i meccanismi di sicurezza che di solito abbiamo con la programmazione. Siamo solo noi e l'hardware. In altre parole, siamo i padroni totali, ma dobbiamo anche prenderne le responsabilità (come dicevano in un film).
Prima di elencare i comandi però bisogna capire come funziona il processore.
Esso è responsabile dell'esecuzione fisica del gioco, svolge i calcoli necessari e controlla le periferiche (tutta roba trovabile su wikipedia).
La CPU è composta da varie parti; a grandi linee troviamo l'ALU, unità che esegue le operazioni via hardware (i circuiti elettronici elaborano i byte), la CU, unità di controllo, serve per coordinare il funzionamento di ALU e altre unità che non ho citato per semplificazione, e i BUS, ovvero collegamenti che trasferiscono i dati da una unità all'altra a seconda di cosa bisogna fare. Esiste poi un minuscolo settore di memoria che è sufficiente a contenere giusto i dati che servono per la corrente operazione. Tale spazio prende il nome di registri (da non confondere con i registri I/O tipici del GBA). I registri possono essere paragonati a delle variabili che si usano durante la programmazione, ovvero dei contenitori di informazioni, con l'unica differenza che qui sono in numero finito, mentre in un programma possiamo averne quante vogliamo. Pensate ad una tazza piena di riso: noi possiamo mettere dentro tutti i chicchi di riso che vogliamo, ovviamente finchè non tracima, oppure possiamo svuotarne il contenuto, o anche solo contare quanti chicchi contiene in un certo momento (perdonatemi il brutto esempio, copiato da qualcuno su internet). I registri del GBA sono lunghi 32 bit, ovvero possono contenere fino a FFFFFFFFh "chicchi di riso", da cui si suol dire che il GBA è una macchina a 32 bit (come i computer fino a qualche anno fa). Tramite le opportune istruzioni si riesce a convertire il numero contenuto nei registri in informazioni comprensibili al giocatore, quali mappe o pokemon.
Il processore funziona secondo uno schema fisso sempre uguale: - reperimento delle istruzioni(fetch): Durante questa fase il processore manda un comando alla RAM o alla ROM dicendo che vuole leggere un indirizzo. La memoria risponde
- decodifica delle istruzioni(decode): il processore riceve il risultato della memoria e lo traduce, ovvero l'unità di controllo decide cosa devono fare le altre unità a seconda di cosa signfica il codice operativo letto.
- esecuzione delle istruzioni(execute): i circuiti del processore, che sono stati impostati correttamente per il lavoro da svolgere nella precedente fase, eseguono l'istruzione.
Questo processo, ripetuto all'infinito fino allo spegnimento, si chiama pipeline. Il termine indica le condutture petrolifere, proprio perchè il processo è costante come il flusso di liquido. Infatti le fasi vengono tutte svolte contemporanamente, come in una catena di montaggio. Avete presente le fabbriche in cui ogni ad stadio si lavora il pezzo aggiungendo qualcosa? Il concetto è lo stesso. Ad ogni istante dunque, avremo un'istruzione che sta passando in ciascuno dei 3 stadi del processore. Questo è fatto per migliorare le prestazioni, in quanto consente di ridurre molto i tempi morti. E' come se in una fabbrica ci fosse un solo operaio che produce il prodotto costruendolo pezzo per pezzo. Con la pipeline invece ciascun operaio si occupa di una porzione limitata del prodotto e si azzerano i tempi morti. Una ulteriore tecnica, che non è presente nel GBA ma ve la dico perchè utile da sapere, è aumentare il numero di linee di montaggio, ovvero avere processori multicore.
Questa pipeline a 3 stadi è tra le più semplici, Giusto per curiosità, i processori desktop hanno pipeline con addirittura decine di passi! (il pentium 4 di intel addirittura una quarantina, perchè doveva essere il più veloce processore single core)
Prima di tuffarci a capofitto nelle istruzioni, bisogna spendere ancora qualche parola sullo specifico processore con cui lavoreremo: l'ARM7TDMI.
Il processore del GBA adotta l'architettura RISC, dunque è piuttosto semplice. RISC vuol dire Reduced Instruction Set Computer, ovvero elaboratore con insieme di istruzioni ridotto; modello che si contrappone ai CISC (Complex Instruction Set Computer), di uso tipico nei desktop. L'e due architetture sono opposte; la seconda presenta molte istruzioni elementari utilizzabili, mentre la prima, per ridurre la complessità in ambienti critici, come una console portatile, offre soltanto lo stretto indispensabile. Ma proprio questo gli conferisce consumi energetici ridotti (io a volte arrivavo a 10 ore col GBA!!! [emoji15]), tanto che è anche stato usato in diversi vecchi dispositivi come l'ipod touch 1G, ovviamente in versione più potente.
Architettura Semplice fino a un certo punto: ci sono comunque un sacco di aspetti da tenere conto, anche tralasciando la realizzazione fisica (per quello c'è il noiosissimo libro facoltativo linkato all'inizio, ne sconsiglio vivamente la lettura se non siete bravi in elettronica).
All'inizio avevo introdotto i registri, ora ve li spiego:
- R0-R12: registri general purpose, possono essere usati per contenere qualunque dato, sono le nostre variabili. Purtroppo, per un motivo che illustrerò dopo, possiamo usare solo quelli da 0 a 7.
- R13: Stack Pointer. usato per tenere traccia dell'ultima posizione dello stack. Lo stack è una "Pila" costruita nella RAM che contiene le variabili locali della funzione corrente. Ogni volta che entriamo in profondità chiamando una funzione, la pila cresce. Quando usciamo dalla funzione, la pila diminuisce
- R14: Link Register, contiene l'indirizzo di ritorno della funzione.
- R15: Program counter, indica la prossima istruzione da fetchare.
- CPSR: Current Program Status Register è il "nome proprio" che il produttore del processore del GBA ha dato al PSW, un registro interno che raccoglie informazioni critiche come lo stato dell'ultima operazione. A noi non interessa quasi per niente.
Alcune delle info seguenti le ho prese dai documenti linkati nella lezione 0.
L'ARM7TDMI ha due "modalità operative", ovvero può lavorare con due diversi set di istruzioni
- ARM, set di istruzioni a 32 bit
- Thumb, set di istruzioni a 16 bit
Il set thumb è un sotto-set dell'ARM, ogni sua istruzione ha una corrispondenza nel set esteso, che svolge lo stesso compito. La cosa forte è che entrambe le modalità condividono gli stessi registri, permettendo una forte collaborazione tra le due, consentendo di ottimizzare sia lo spazio occupato sia le prestazioni.
Infatti durante l'esecuzione, ogni istruzione a 16 bit viene "decompressa" nel suo equivalente a 32 bit, permettendo di sfruttare appieno le capacità della macchina.
Thumb ha tutti i vantaggi di un "cuore" a 32 bit:
- indirizzamento a 32 bit (significa che potrete trattare memoria fino a 4 GB, ma siccome come sapete il GBA si ferma a 0E-000000, avrete comunque tutto il range disponibile)
- registri a 32 bit
- operazioni a 32 bit
- trasferimento di memoria a 32 bit
il codice thumb occupa tipicamente il 65% del corrispettivo ARM, e fornisce il 160% delle prestazioni, se letto da una memoria a 16 bit. La ROM guarda caso ha un sistema di trasferimento a 16 bit, ecco spiegato il motivo per cui i giochi sono principalmente compilati in questa modalità. Usare istruzioni lunghe 32 bit non sarebbe convenuto i quanto avrebbe raddopiato il tempo necessario per trasferirle dalla ROM al processore. Tuttavia, se eseguito in uno spazio a 32 bit (ad esempio dalla RAM), la superiorità del codice thumb scema. Infatti sono fatte in ARM e residenti in RAM, che trasferisce 32 bit alla volta, le routine di gestione degli interrupt, un argomento che noi non vedremo perchè complesso e poco utile all'hacking di base. Se vi servirà, ora sapete che esiste.
Il core del processore usa il primo bit del program counter per determinare cosa mettere in un altro registro interno, che serve per stabilire il set di istruzioni da usare (ecco spiegato l'arcano mistero di mettere +1 nell'indirizzo del callasm, serve per dire di usare la modalità thumb  ).
Il processore supporta sia la modalità di storage dei dati big endian che little endian.
ma siccome devono complicarci le cose (-.-") il default è little endian, in quanto di più veloce processamento (ha a che fare con la realizazione fisica dei circuiti dediti ai calcoli).
Questi termini si riferiscono a come le informazioni vengono scritte nella memoria. Big endian memorizza le informazioni a partire dal MSB (most significant bit), mentre little endian dal LSB (least significant bit). Sicuramente wikipedia spiega meglio di me:
https://it.wikipedia.org/wiki/Ordine_dei_byte
e con questo abbiamo svelato un altro mistero, ovvero il perchè nei puntatori bisogna invertire i byte. Succede perchè dobbiamo tenere conto di tutti i dettagli della macchina.
Come accennato prima, Durante la modalità thumb, i registri alti (8-15) non sono immediatamente accessibili con le operazioni elementari. Se non possiamo farne a meno come deposito temporaneo di informazioni, possiamo usare alcune istruzioni per copiarvi il contenuto dei registri bassi (0-7), o anche copiare il loro contenuto nei registri bassi, ovvero nell'altro senso. Questo purtroppo si verifica per un limite di design: se abbiamo i codici operativi a 16 bit, bisogna cercare di fare economia sull'utilizzo degli stessi per indicare le funzioni, ed è stato deciso di utilizzare 3 bit per indicare i registri che devono essere usati nelle operazioni. In modalità ARM non esiste questo problema perchè in 32 bit ci sono abbastanza bit per indicare il numero di registro che vogliamo.
Dopo questa estenuante introduzione penso che possiamo vedere i veri comandi! ~
NOTA: non vi insegnerò la sintassi, a parte un caso che vedremo, perchè è noiosa e fine a se stessa, e potete trovarla comodamente nella documentazione. Reputo molto più istruttivo prima di tutto comprendere bene effettivamente cosa fanno i vari comandi.
Se non sapete cosa siano alcune cose, in fondo c'è uno spoiler salvagente con and, or, not, shift.
ISTRUZIONI ARITMETICHE- ADD/MUL/SUB
operazioni matematiche come somma, moltiplicazione, sottrazione.
di solito si scrive il comando seguito da 3 registri: registro destinazione del risultato, registro operando 1, registro operando 2. oppure si usa un immediato (un piccolo valore scritto direttamente nel codice operativo, senza dover sprecare un registro)
ISTRUZIONI LOGICHE- AND fa l'and bit a bit di due registri
- EOR fa l'Esclusive Or (XOR) dei bit di due registri
- LSL/LSR serve per shiftare i bytes a destra o a sinistra.
- NEG nega il contenuto di un registro, bit per bit, ma attenzione, se consideriamo il numero, otterremo "0-valore", dunque il risultato sarà avanti di 1 rispetto a quello che ci aspetteremmo!
- ORR fa l'or dei registri, bit a bit.
ISTRUZIONI PER IL CONTROLLO DEL FLUSSO- B/BL/BX servono per eseguire dei salti nel codice. I salti permettono di alterare il normale flusso di esecuzione del programma, ma per routine semplici non sono necessari. Di solito si usano quando si testa una condizione e si vuole un comportamento diverso a seconda dei casi, come il rombo nei diagrammi di flusso. Se avete capito bene i goto negli script, non avrete problemi. La differenza tra i tre è che B salta e basta, BL salta e copia il PC nel LR per un facile ritorno, BX salta e cambia modo operativo, a seconda dell'ultimo bit del valore.
E' possibile aggiungere delle condizioni all'istruzione B.-
B + qualcosa significa salta se:
- EQ equal
- NE not equal
- CS Carry Set
- CC Carry clear
- HS unsigned higer or same
- LO Unsigned Lower
- MI Minus/negative
- PL Plus/Positive or Zero
- VS Overflow
- VC No Overflow
- HI unsigned higher
- LS Unsigned Lower or Same
- GE Signed Greater Than or Equal
- LT Less than
- GT Signed Greater than
- LE Signed less than or equal
- GE Greater than or equal
sopra, carry vuol dire riporto.
overflow è la condizione in cui il risultato è più grande di quello rappresentabile. Avete mai scritto su una calcolatrice a singola linea tutti 9 e poi sommato 1? Ottenete un errore, lo stesso qui.
I salti condizionali sono molto usati con l'istruzione CMP.
le varianti condizionali del B si basano sul CPSR, perciò sono utili solamente se seguono un'istruzione CMP, che serve appunto a modificarlo. Potreste comunque usarle quando volete (come ogni istruzione del resto), ma non ha senso.
- CMP compare, paragona. può paragonare un registro ad un byte, o 2 registri tra loro e mette il risultato nel PSW (CPSR), subito dopo sarebbe utile eseguire un salto. altrimenti è un'operazione sprecata.
ISTRUZIONI PER OPERAZIONI SULLA MEMORIA
- LDR/LDRB/LDRH/MOV Serve per caricare un registro con dei dati. Esistono varie opzioni, come un valore immediato; un valore letto dall'indirizzamento indiretto; un valore ottenuto mediante operazioni, ecc. La differenza sostanziale tra i tre sta in cosa caricano: LDR carica 32 bit, LDRH 16 bit (H sta per Half) , LDRB 8 bit (B sta per Byte). MOV invece inizializza un registro con un byte presente nello stesso codice operativo. Se si caricano meno di 32 bit, i rimanenti saranno giustamente messi a 0.
- STR/STRB/STRH Questi invece fanno l'operazione inversa del LDR, ovvero "stoccano" (da store) il dato da qualche parte. Anche qui Vi sono molte opzioni, ma è meglio visionarle sulla guida, in quanto in questa sede appesantirebbe la lettura oltre il necessario. La differenza tra i 3 è nella dimensione del dato trattato, come con gli LDR.
- POP/PUSH servono all'inizio e alla fine della nostra funzione ASM (non in tutti i casi, solo nelle sotto-funzioni) per accatastare sullo stack i contenuti dei registri che ci serviranno per compiere le operazioni. E' buona cosa ricordarsi di andare a riprendere le informazioni e rimetterle alloro posto una volta terminata la routine.
E' importante ricordare che per iniziare una sotto-funzione si usa PUSH LR (più eventuali registri usati) e per terminarla si deve fare POP PC (più i registri usati). Questo perchè quando eseguiamo un salto BL, pensato per entrare in una sotto funzione, il Link Register assume il valore dell'offset dell'istruzione successiva a quella del salto. Una volta accantonato il LR e compiuta la routine, dobbiamo tornare indietro. Come? Facile. Poppando (ok, doppiosenso, scusate) il LR otteniamo il punto dove continua la funzione di livello superiore, ma per andarci dobbiamo metterlo nel Program Counter.
vi è andata bene che non vi do compiti, prossima volta esercizi, vediamo qualcosa in azione!
ciao! questo è una patch aggiornamento flash per spiegarvi alcune operazioni poco chiare prima.
LE ISTRUZIONI LOGICHE
Sono delle operazioni che si ritrovano anche nella logica, una branca della matematica. In questo caso le operazioni sono le stesse, ma si svolgeranno sui nostri registri.
innanzitutto chiariamo che se un'istruzione è "bit a bit" vuol dire che viene eseguita separatamente per ciascun bit del registro, a prescindere dunque dal suo valore ottenuto considerando i suoi 32 bit come un numero unico.
Queste sono le istruzioni che possiamo fare col GBA. le altre possono essere ricavate da queste, precisamente dalle prime 3.
AND
questa operazione restituisce il valore 1 solo se tutti gli ingressi sono a 1, 0 altrimenti. Il nome and (in inglese "e") deriva dal fatto appunto di pronunciare "se il primo ingresso vale 1 e il secondo ingresso vale 1...", in quanto il processore manipola al massimo due registri alla volta.
OR
questa operazione restituisce 1 se almeno un ingresso vale 1. se nessun ingresso vale 1, restituisce 0.
questa operazione è l'esatto contrario della and. or in inglese significa "o", dato che restituisce 1 se il primo ingresso o il secondo ingresso vale 1.
NOT
questa operazione restituisce il contrario dell'ingresso (da cui il nome che significa "negare"), ovvero restituisce 1 se l'ingresso vale 0 e viceversa
XOR
significa "exclusive or", ovvero or esclusivo. questa operazione restituisce 1 se solo un ingresso vale 1.
possiamo riassumere il tutto con un'immagine che si chiama "tabella di verità", in cui sulle colonne ci sono gli ingressi e l'uscita, e sulle righe i loro valori (lasciate pure stare quegli strani oggetti rotondi):
per vedere qualche esempio vi basta usare la calcolatrice sul computer e smanettare un po'
SHIFT: https://en.wikipedia.org/wiki/Bitwise_op...Bit_shifts
BREVE COMPITO:
fatemi (via MP) la tabella di verità delle operazioni NAND e NOR, sapendo che significano "not and" e "not or"
Bye
- 171022: introduzione chNGELOG, rimosse cose pesanti come sostituzione mnemonica, spostate parti per un ordine logico migliore, semplificata pipeline e sopra, rimossa ogni istruzione
è condizionale arm, rimosse alcune fonti di confusione come B ALways, BKPT che forse non va, cercare di spiegare lo step over degli IDE, semplificate alcune parentesi
NOTA PER ME STESSO: non copiare direttamente queste, prima sfoglia l'ultima lezione per vedere se ci sono parti da aggiungere. e guarda notepad
 Mi Piace Ricevuti:  |
|
Messaggi: 2,197
Discussioni: 103
Registrato: 06-07-2014
Reputazione:
16
23-11-2017, 09:27 PM
(Questo messaggio è stato modificato l'ultima volta il: 21-03-2018, 02:43 PM da Bonnox.)
scusa se questa lezione contiene pochi esempi, ma ho deciso di postarla perchè mi ero liberato da alcuni impegni, ma non ho comunque abbastanza tempo per includere nuovi esempi completamente corretti. se te ne serviranno altri chiedili pure, solo fai attenzione che non arriveranno immediatamente.
nota: ho spiegato lo swi senza averlo spiegato nella lez precedente, ecco qua un riassunto
è l'acronimo di SoftWare Interrupt e consiste nell'eseguire alcune funzioni che stanno nel Bios del GBA. il suo utilizzo è simile agli script, quando usiamo un comando che vuole un numero d'indice.
ESERCIZI 4
ASM BASE
in questa sede trasporremo in ASM gli algoritmi visti nelle precedenti lezioni, con lo scopo di abituarci alla sintassi ^^
ho preso alcuni degli esercizi visti nella lezione di programmazione, in modo da poter riflettere sulle differenze, più alcuni presi da internet sul C, o inventati da me ^^
innanzitutto se avete dei dubbi sulla sintassi consultate pure il PDF che vi ho fato scaricare all'inizio.
esso ha 3 aree: una zona in cui viene presentato il comando in modo molto sintetico, una che illustra la sintassi di ogni variante di ogni comando, e una che mostra come sono fisicamente realizzati gli opcodes. Ora vi esporrò brevemente i punti salienti della sintassi.
nota: le virgolette sono per delimitare la citazione. non fanno parte della sintassi.
- "[RX]" indica di indirizzare l'operazione all'offset di memoria contenuto nel registro.
dunque, l'istruzione
"LDR RX, [RY]"
caricherà in RX i 4 byte presenti all'indirizzo di memoria contenuto in RY.
Invece "[RX, RY]"
oppure
"[RX, #valore]"
significa indirizzare l'operazione all'indirizzo contenuto da RX + RY o RX + valore)
.
- le etichette servono per distinguere parti di programma, come le funzioni, e servono come destinazione dei salti. per dichiarare un'etichetta basta metterne il nome seguito da due punti, così:
"main:"
.
- quando iniziate una routine ricordatevi SEMPRE di allinearla. per farlo si usa:
".align X, 0xY"
questa è una direttiva al compilatore, ovvero delle istruzioni che noi gli diamo per informarlo di qualcosa prima di procedere a compilare. le direttive iniziano con il punto. in particolare align indica di allineare il compilato a partire da 2^X byte, riempiendo lo spazio intermedio con il byte Y. Di solito questo parametro si omette.
L'align è anche usato sui dati, in quanto se non fossero allineati (specialmente le strutture), sarebbe un casino assicurato nella gestione della memoria. Inoltre alcuni opcodes, se avete letto la documentazione, hanno un offset di reperimento delle informazioni che va a blocchi di 4 byte.
Dunque la pratica, abbastanza diffusa, di usare
"LDR RX, .pointer
[...]
.align 2
.pointer:
.word 0xqualcosa"
nasce dal fatto che l'istruzione LDR ha nei suoi campi (a livello fisico, potete vederlo nella thumbref) un valore che indica "quante word in là" andare a prendere il dato. (ricordando che una word è lunga 4 bytes, e 2^2 fa 4, si spiega il perchè si mette sempre align 2)
In realtà sarebbe meglio fare così:
"LDR RX, valore
[...]
.align 2
valore: .word 0xqualcosa".
Se proprio non voleste niente sotto, un'altra soluzione è
"LDR RX, =0xqualcosa"
in questo modo caricherete subito il valore.
Oppure potreste anche fare di meglio. quest'ultimo metodo è parecchio scomodo, in quanto incline agli errori e non centralizzato: se usate un valore molte volte e ad un tratto lo volete sostituire, dovrete cercarlo per tutto il sorgente. Leggendo la guida dell'assemblatoreho scoperto questa nuova direttiva chiamata "equ". Svolge un compito simile al #define del C, ovvero sostituisce tutte le occorrenze di un valore nel testo, gestendo automaticamente la questione degli allineamenti. In questo modo scriverete una sola volta il valore, ma potrete usarlo sempre, unendo così i vantaggi dei due precedenti metodi (centralizzazione del valore e praticità). ecco un esempio:
".equ alias, 0xqualcosa
LDR RX, =alias"
dove alias è una qualunque parola inventata da noi. la direttiva può essere inserita ovunque nel sorgente, perciò prestate attenzione, anche se vi potrebbe sembrare un vantaggio, in realtà contribuisce a rendere meno leggibile il codice. Sarà bene adottare un proprio stile, ovvero decidere se mettere tutte le dichiarazioni di costanti all'inizio o alla fine del file: personalmente ritengo che dichiarare una costante al momento dell'uso renda poco leggibile il codice.
Un'altra direttiva è .include, che unisce un file in quello corrente, a compile-time:
supponete di aver creato un file con delle funzioni che usate spesso. potrete "includere" il file nel vostro nuovo sorgente (di solito i file di sorgente assembly si chiamano *.ASM o *.S ) in modo da poterle usare senza doverle riscrivere. è una tecnica molto comoda, in quanto consente di risparmiare tempo. Il meccanismo è lo stesso dei blocchi più grossi nei diagrammi di flusso, che contengono un'insieme di operazioni già definite da trattarsi come una atomica. la sintassi è questa:
Citazione:.include "path"
dove path è il percorso al vostro file. le virgolette vanno messe.
.
- per inserire un immediato, si usa "#"
Un immediato è un valore da usare nell'operazione, inserito nell'istruzione stessa, al posto di usare un registro. in genere se avete valori, conosciuti prima dell'esecuzione, inferiori o uguali a 255 si possono tranquillamente mettere come immediati.
esempio:
"MOV R1, #0"
.
- potete inserire un commento con la chiocciola, e quel'intera riga, a partire dal carattere chiocciola, non verrà considerata durante la compilazione. esempio:
"LDR R0, 0x083E6E50 @carico l'offset"
Consiglio di inserire sempre qualche commento, anche se all'inizio possa sembrare inutile, perchè potrebbe capitarvi di non riuscire a capire il vostro stesso codice! Questo perchè è complicato, e se non lo guardate per un po' vi dimenticherete. Credeteci. Poi se lo dovrete far leggere ad altri è ancora più "moralmente obbligatorio": è un vero atto di cortesia, e se non lo fate rischierete il linciaggio!
ed ecco alcuni swi che potrebbero tornarvi utili (#se leggete "dsi" o "nds" per favore ignoratelo):
Codice: SWI 06h - Div
Signed Division, r0/r1.
r0 signed 32bit Number
r1 signed 32bit Denom
Return:
r0 Number DIV Denom ;signed
r1 Number MOD Denom ;signed
r3 ABS (Number DIV Denom) ;unsigned
For example, incoming -1234, 10 should return -123, -4, +123.
The function usually gets caught in an endless loop upon division by zero.
SWI 08h - Sqrt
Calculate square root.
r0 unsigned 32bit number
Return:
r0 unsigned 16bit number
The result is an integer value, so Sqrt(2) would return 1, to avoid this inaccuracy, shift left incoming number by 2*N as much as possible (the result is then shifted left by 1*N). Ie. Sqrt(2 shl 30) would return 1.41421 shl 15.
SWI 09h - ArcTan
Calculates the arc tangent.
r0 Tan, 16bit (1bit sign, 1bit integral part, 14bit decimal part)
Return:
r0 "-PI/2<THETA/<PI/2" in a range of C000h-4000h.
Note: there is a problem in accuracy with "THETA<-PI/4, PI/4<THETA".
LZ77UnCompReadNormalWrite8bit (Wram) - SWI 11h
LZ77UnCompReadNormalWrite16bit (Vram) - SWI 12h
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits. For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
CAUTION: Writing 16bit units to [dest-1] instead of 8bit units to [dest] means the reading from [dest-1] won't work, ie. the "Vram" function works only with disp=001h..FFFh, but not with disp=000h.
If the size of the compressed data is not a multiple of 4, please adjust it as much as possible by padding with 0. Align the source address to a 4-Byte boundary.
r0 Source address, pointing to data as such:
Data header (32bit)
Bit 0-3 Reserved
Bit 4-7 Compressed type (must be 1 for LZ77)
Bit 8-31 Size of decompressed data
Repeat below. Each Flag Byte followed by eight Blocks.
Flag data (8bit)
Bit 0-7 Type Flags for next 8 Blocks, MSB first
Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
Bit 0-7 One data byte to be copied to dest
Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
Bit 0-3 Disp MSBs
Bit 4-7 Number of bytes to copy (minus 3)
Bit 8-15 Disp LSBs
r1 Destination address
r2 Callback parameter ;\for NDS/DSi "ReadByCallback" variants only
r3 Callback structure ;/(see Callback notes below)
Return: No return value.
SWI 0Ch - CpuFastSet
Memory copy/fill in units of 32 bytes. Memcopy is implemented as repeated LDMIA/STMIA [Rb]!,r2-r9 instructions. Memfill as single LDR followed by repeated STMIA [Rb]!,r2-r9.
After processing all 32-byte-blocks, the NDS/DSi additonally processes the remaining words as 4-byte blocks. BUG: The NDS/DSi uses the fast 32-byte-block processing only for the first N bytes (not for the first N words), so only the first quarter of the memory block is FAST, the remaining three quarters are SLOWLY copied word-by-word.
The length is specifed as wordcount, ie. the number of bytes divided by 4.
On the GBA, the length should be a multiple of 8 words (32 bytes) (otherwise the GBA is forcefully rounding-up the length). On NDS/DSi, the length may be any number of words (4 bytes).
r0 Source address (must be aligned by 4)
r1 Destination address (must be aligned by 4)
r2 Length/Mode
Bit 0-20 Wordcount (GBA: rounded-up to multiple of 8 words)
Bit 24 Fixed Source Address (0=Copy, 1=Fill by WORD[r0])
Return: No return value, Data written to destination address.
SWI 0Bh - CpuSet
Memory copy/fill in units of 4 bytes or 2 bytes. Memcopy is implemented as repeated LDMIA/STMIA [Rb]!,r3 or LDRH/STRH r3,[r0,r5] instructions. Memfill as single LDMIA or LDRH followed by repeated STMIA [Rb]!,r3 or STRH r3,[r0,r5].
The length must be a multiple of 4 bytes (32bit mode) or 2 bytes (16bit mode). The (half)wordcount in r2 must be length/4 (32bit mode) or length/2 (16bit mode), ie. length in word/halfword units rather than byte units.
r0 Source address (must be aligned by 4 for 32bit, by 2 for 16bit)
r1 Destination address (must be aligned by 4 for 32bit, by 2 for 16bit)
r2 Length/Mode
Bit 0-20 Wordcount (for 32bit), or Halfwordcount (for 16bit)
Bit 24 Fixed Source Address (0=Copy, 1=Fill by {HALF}WORD[r0])
Bit 26 Datasize (0=16bit, 1=32bit)
Return: No return value, Data written to destination address.
Note: On GBA, NDS7 and DSi7, these two functions will silently reject to do anything if the source start or end addresses are reaching into the BIOS area. The NDS9 and DSi9 don't have such read-proctections.
SWI 05h - VBlankIntrWait ;DSi7/DSi9=bugged?
Continues to wait in Halt status until a new V-Blank interrupt occurs.
The function sets r0=1 and r1=1 (plus r2=0 on DSi7) and does then execute IntrWait (SWI 04h), see IntrWait for details.
No parameters, no return value.
noi (io) negli esercizi useremo l'indirizzo 02000000 come scambio di informazioni tra script e routine; potrete facilmente cambiarlo.
ESERCIZIO: dato un numero, stampa (o ritorna) il fattoriale
Codice: .THUMB
.ALIGN 2, 0x0
@; RO: OFFSET MEM
@; R1: VALORE
@; R2: DECREMENTO
PUSH {R0-R4,LR}
MOV R0, #1 @;INIZIALIZZO REGISTRO: 2000000
LSL R0, #0X19
LDRH R1, [R0] @; LEGGO VALORE INPUT
MOV R2, R1
fattoriale_ciclo_calcolo:
SUB R2, R2, #1 @; ALGORITMO ITERATIVO DEL FATTORIALE
MUL R1, R2
CMP R2, #1
BHI fattoriale_ciclo_calcolo
STR R1, [R0] @;FORNISCO IL RISULTATO
POP {R0-R4,PC}
tutto quello che abbiamo fatto è stato inizializzare i valori ed eseguire un semplice ciclo in cui moltiplichiamo il numero per sè stesso.
ESERCIZIO: dati n numeri, calcolare la media
avvertenza: ho usato il byte a 200000 per indicare il numero di elementi, che ho messo in un vettore (per complicare un pochino le cose, se no non c'è gusto XD - no scherzo in realtà perchè così avete già in mente come trattare gli altri problemi complicati sui vettori) che compare subito dopo.
ecco, ogni tanto provate a fare un riassunto del contenuto dei registri, come ho fato io due volte qua sotto (le righe lunghe), così da non confondervi!
(consiglio di usare programmers notepad o un altro editor di testo potenziato rispetto allo squallore di blocco note, per avere la sintassi colorata)
Codice: .thumb
.align 2, 0x0
.equ scambio, 0x2000000
push {r0-r4, lr}
@; r0: accesso vettore, r1: numero elementi r2: somma temporanea r3: elemento letto corrente r4: indice del vettore
inizializzazione:
mov r2, #0
mov r4, #0
ldr r1, =scambio
mov r0, r1 @; copio
ldrb r1, [r1] @; leggo il numero di elementi
add r0, r0, #1 @; mi posiziono sul vettore
ciclo:
ldrb r3, [r0, r4] @; accesso tramite indicizzazione
add r2, r2, r3
add r4, r4, #1
cmp r1, r4
bhi ciclo
@; r0: somma temporanea r1: numero elementi r2: / r3: / r4: memorizzazione
mov r4, r0 @; preparo la divisione
sub r4, r4, #1
mov r0, r2
mov r2, #0
mov r3, #0
swi 0x6
strb r3, [r4] @; comunicazione del risultato
fine:
pop {r0-r4, pc}
notate che per entrambi gli esempi ho scelto di memorizzare il risultato nella memoria RAM per semplicità. Se però le funzioni fossero state inserite in un contesto più ampio, sarebbe stato preferibile usare un valore di ritorno. come si fa? bisogna semplicemente non pushare un (o più) registro, che useremo per contenere il risultato. un esempio di questa tecnica è lo SWI, come abbiamo visto nella divisione, che ritorna qualcosa nei registri. ma noi come possiamo?
generalizzando,
Codice: PUSH {RY-RZ, LR}
@ fai qualcosa
MOV RX, XXX @ memorizza in qualche modo il risultato
POP {RY-RZ,PC}
con, generalmente, X < Y < Z (numeri sempre a vostra scelta, ma meglio se sensata)
in questo modo RX sarà in comune sia alla funzione corrente che a quella chiamante. poi quello che la chiamante farà non è affar della corrente.
nella seconda tipologia di esercizi userò il valore di ritorno, dunque attenti!
#sposare su programmazione
una funzione si dice ricorsiva se durante l'esecuzione chiama sè stessa o chiama una funzione che chiama sè stessa. equivalentemente, in matematica, una funzione è ricorsiva se è definita in termini di sè stessa.
è importante che esista una condizione di base che permette di non chiamare la funzione, altrimenti si genererebbe un ciclo infinito.
pensiamo al fattoriale di n, ovvero la produttoria di numeri che vanno da 1 a n.
è possibile usare l'algoritmo iterativo (anzi c'è un teorema che dice che qualunque problema è risolvibile tramite le strutture fonfamentali), oppure quello ricorsivo.
in questo caso, il fattoriale di n (scritto n!) possiamo vederlo come n*(n-1)!.
http://pokehack.altervista.org/attachment.php?aid=441
è proprio la condizione di base che ci permette di uscire dal calcolo.
Che succede se finite i registri come variabili?
abbiamo essenzialmente tre alternative: usare la memoria, lo stack o i registri alti.
per usare la memoria non ci vuole molto, basta scrivere sulla 02 qualche valore da andare a prendere dopo. ovviamente però non dovrete dimenticare dove avete messo i dati! per questo è meglio organizzare la cosa come un vettore di int (il tipo di grandezza massima) allineato, e il cui indirizzo è mantenuto in un rgistro. ora, con semplici immediati (ricordate equ), potrete accedere a qualsiasi cosa vogliate (dubito che abbiate più di 255 variabili), tramite l'indirizzamento scostato (quello con il [RX, #numero]).
la seconda alternativa invece è più integrata nel sistema, ma più delicata.
infatti potrete pushare (accatastare) sullo stack un qualsiasi valore, caricare il nuovo dato in un registro, fare l'operazione e poi poppare (togliere) il valore. RICORDATE CHE ALL'INIZIO E ALLA FINE DEL PROGRAMMA ASM LO STACK DEVE ESSERE NELLO STESSO STATO! ovvero, POPPATE SEMPRE CIO' CHE PUSHATE!
questo perchè altrimenti il programma esterno (la ROM) si ritroverà dati non coerenti e anrà in crash (nel migliore dei casi sarà tutto glitchato).
Poi voi in mezzo alla vostra pila personale potrete fare tutte le vostre porcherie (so che le farete, anche se dovrebbe essere vietato da un'autorità universale), come ad esempio prendere un valore dal mezzo (se lo fate con una pila di piatti vedete che vi succede... XD)... l'importante però è che alla fine della vostra funzione lo stack sia come l'avete trovato.
la terza soluzione, che è un po' scontata, prevede di utilizzare i registri da 8 a 12. il problema è che pochissimi opcodes li trattano, perciò sono scomodi. e comunque dovrete depositarne il contenuto con uno dei metodi di prima ^^".
ora c'è una nuova tipologia di esercizio: io vi darò una funzione, e dovrete rispondere cosa fanno. le prime sono di esempio.
1)
avete due files, quello del programma e quello di utility.
Codice: .thumb
.equ input, 0x2000000
.ascii "inizio programma" @; scrive sul file binario
.align 4, 0x0
PUSH {R0-R4, LR}
main:
LDR R2, =input
LDR R4, [R2]
MOV R0, R4
MOV R1, #4
BL utility_main
CMP R0, #0
BNE no
MOV R0, R4 @; riprendo il dato parcheggiato
MOV R1, #100
BL utility_main
CMP R0, #0
BNE si
MOV R0, R4
MOV R1, #25
LSL R1, #4
BL utility_main
CMP R0, #0
BNE no
si:
MOV R0, #1
LDR R2, =input
STRB R0, [R2]
b return
no:
MOV R0, #0
LDR R2, =input
STRB R0, [R2]
return:
POP {R0-R4, PC}
.include "lib/utility.s" @; entro in una cartella per prendere l'utility
@; l'ho messo in fondo perchè il compilatore non ha capacità di riconoscere il programma prinicipale, compila solo
@; nell'ordine in cui trova il codice, perciò così abbiamo subito il nostro programma all'inizio del file binario
@; (utile per fare eventualmente un callasm); mentre le librerie non ci interessano e rimarranno confinate in fondo.
Codice: .THUMB
.ALIGN 4, 0xFF
utility_main:
PUSH {R2-R6,LR}
MOV R2, #0
MOV R3, #0
MOV R5, R0
MOV R4, R1
SWI #0X6
CMP R1, R4
BHI utility_correggi
B utility_fine
utility_correggi:
NEG R1, R1
SUB R1, R1, #1
utility_fine:
MOV R0, R1
POP {R2-R6,PC}
innanzitutto scopriamo cosa fa l'utiliti. R0 e R1 sono parametri, in quanto usati senza essere pushati. notiamo inoltre che usa lo swi del div, dunque sarà qualcosa attinente alla divisione. noi sappiamo l'output del div, e vediamo che la routine è interessata al R1, ovvero il modulo. anzi, la funzione ritorna proprio quello in R0. ma cos'è quel pezzo prima della fine? se il modulo è maggiore del denominatore (#per una questione che mi son dimenticato di spiegare, si chiama "complemento a due", se volete cercarla su internet o se no mandatemi un messaggio), significa che il numero è necessariamente negativo, dunque lo nega e sottrae 1, ovvero ottiene lo stesso numero positivo.
dunque la routine restituisce il valore assoluto del modulo tra R0 e R1.
cosa fa il file principale?
-controlla se un numero è divisibile per 4
--se non è divisibile restituisce 0
--altrimenti
---controlla se è divisibile per 100
----se no, restituisce 1
----altrimenti
-----controlla se è divisibile per 400 (25*2^4)
-----restituisce la stessa verità del'ultimo controllo.
questo è palesemente l'algoritmo di controllo della bisestilità di un anno.
la comunicazione con l'esterno avviene tramite RAM e non tramite ritorno perchè è stata pensata per essere usata in uno script.
consiglio: usate le librerie, aiuteranno a scrivere molto meno!
in particolare, come esercizio, potreste fare dei "wrapper" per le funzioni swi, come la precedente, dato che fanno spesso e volentieri macello con i registri, e potreste trovarvi in difficoltà. dunque con una routine come questa annullerete l'effetto caos e anzi ritornerete in modo elegante ciò che vi serve.
compito
vi consiglio di trovare prima una soluzione con gli schemi a blocchi. e dato che non sono necessarie molte variabili, vi consiglio anzi di tradurre 1:1 le singole strutture in blocchi di codice assemly (ad esempio tutte le sequenze in una sequenza asm), e poi di etichettarli. così potrete facilmente creare il controllo del flusso di esecuzione.
- verificare se un vettore è ordinato
- verificare se un vettore contiene elementi tutti uguali
- bonus: compattare un vettore (eliminare i valori duplicati e quelli pari a 0)
consigli:
- inutile dire che i cicli saranno d'importanza fondamentale.
- non avete limitazioni oltre alle richieste. (a buon intenditor... vabbè ve la spiego: non vi ho detto di che tipo è il vettore, dunque sceglietene uno comodo... vabbè ve lo dico ancora: di sicuro non sarà il tipo booleano o short, ma un tipo che sfrutta appieno la tecnologia del processore...)
- per l'ultimo, prima create una funzione per individuare gli zeri e scorrere a "sinistra" (nella memoria) tutte le celle successive. poi create una funzione che itera su tutto l'array in cerca di valori duplicati, che verranno "marcati" con degli 0. poi fate ripassare la funzione di eliminazione degli zeri.
è vero, questo algoritmo non è il massimo dell'efficienza (anzi è il male in persona), ma sicuramente è molto intuitivo, dunque di facile realizzazione.
è possibile utilizzare sia l'algoritmo iterativo che ricorsivo, dunque buona fortuna! ^^
cosa fanno queste routine?
1)
Codice: .thumb
.align 2, 0xFF
.equ input, 0x2000000
main:
Push {r0-r4, lr}
ldr r1, =input
ldr r0, [r1]
bl func
str r0, [r1]
pop {r0-r4, pc}
func:
push {r1-r4, lr}
cmp r0, #1
beq return
cmp r0, #0
beq return
mov r1, r0
sub r0, #1
bl func
mul r0, r1
return:
pop {r1-r4, pc}
anche per stavolta mandatemi i compiti via MP, più avanti studierò un sistema per evitare che gli "esterni" "riciclino" i vostri compiti (perchè do per scontato che non vi copiate tra voi  ).
crediti: gbatek, tonc
changelog e #todo
- todo: leggere insieme la thumbref, intersezione di 2 vettori (in c), calcolatrice, palindromo
- 171122: citazione sintassi, intro, rimossa critica a direttive come word, tolte parentesi, rimosse distrazioni come pascal vettore
- una volta sola prima, per data approx. andare a prendere msg mega huge guida
LEZIONE 1.2
IMPARIAMO A SCRIVERE?!
Se ricordate, l'altra volta ho detto che per visualizzare i caratteri sono utilizzati gli standard di comunicazione, in cui ad ogni byte corrisponde un carattere ben preciso.
Ovviamente in GF hanno avuto la brillante idea (si fa per dire... Anche se probabilmente l'hanno fatto per rendere più difficili le operazioni dei cheater) di alterare l'ordine naturale delle cose sostituendo tutti i caratteri con dei nuovi. Il funzionamento è il medesimo, ma i giochi adottano un set di caratteri diverso, come si suol dire. Questi possono essere trovati sull'enciclopedia ( http://bulbapedia.bulbagarden.net/wiki/C...ration_III) dove sono descritti in maniera molto dettagliata. Noterete che ci sono alcuni valori strani: sono le sequenze di escape, ovvero i caratteri di controllo. Questi sono speciali caratteri, presenti in ogni sistema operativo, che hanno particolari compiti. Il programma che si occupa della scrittura del testo riconosce il carattere speciale e si comporta di conseguenza. Al link menzionato prima ogni singolo byte è ampiamente documentato. Ovviamente, come al solito in questo corso, non è necessario impararli a memoria tutti, ma basta "saperli leggere" per poterli consultare in caso di bisogno.
Ma a cosa servono praticamente? Ad esempio con essi potete, negli script, cambiare colore, oppure fare una pausa, o usare il grassetto. Sono tecniche molto utili per la regia 
Anche nel computer normale ci sono le sequenze di escape: l'accapo è un esempio.
Tutte le volte che usate una sequenza mnemonica in xse, come ad esempio "LASTRESULT" o "RS_cyan" (non son sicuro che la seconda sia corretta così com'è, mi riferisco al colore del testo) lui sostituisce nella ROM una particolare sequenza di caratteri al posto della parola chiave. Nel nostro caso al posto del colore metterà il byte che indica il cambio di colore, e poi il byte del colore. E se volete inserire in XSE altre sequenze di escape? C'è il comando "\h", ma Comunque dovete inserire un "\h" per ogni singolo byte che compone la nostra sequenza di controllo. Noioso, vero? Ecco perchè a volte preferisco usare l'hex editor. Ovviamente non dovrete usarlo sempre, anzi, riconosco che usare XSE è più comodo, ma sapere come fare è sempre meglio; forse vi capiterà anche qualche caso in cui vi servirà.
Per svolgere correttamente questa attività dovrete avere una tabella dei caratteri, che essenzialmente è un file che dice all'hex editor quali sono le corrispondenze tra i caratteri "normali" (ASCII) e "quelli pokemon" . Io vi passo quella che si trova insieme a thingy 32, un hex editor sviluppato principalmente per le traduzioni, e quella incompleta che ho fatto io per XVI32 in un momento di noia.
http://pokehack.altervista.org/attachment.php?aid=279
http://pokehack.altervista.org/attachment.php?aid=280
Per caricarli ho dovuto spacciarli per file di testo, voi rinominate l'estensione in "TBL" (tabla) e "XCT" (xvi character table).
Come si usano? Ogni programma ha i suoi problemi, dunque bisognerà stare attenti. Comincio col dire che il tanto amato HxD neanche ha questa possibilità, oppure non l'ho vista. Rimangono windhex e thingy che si comportano in modo piuttosto simile, mentre xvi, come vedrete tra poco, fa una "cassanata".
Dunque è giunto il momento di aprire rom e tabella. Solitamente i comandi stanno nel menu file. Windhex legge la tabella di thingy. Una volta completato dovreste vedere che i caratteri a destra sono cambiati. Il programma sta sostituendo i byte della ROM con i caratteri indicati da noi. Ora, finalmente, potete provare a sbizzarrirvi con la ricerca di testo, in quanto ci sono un mucchio di parole di senso compiuto! E se provate a scrivere con le normali lettere della tastiera, queste vengono automaticamente tradotte nel formato corretto, mentre a noi appariranno come lettere normali!
http://pokehack.altervista.org/attachment.php?aid=308
Bisogna ricordare, però, che il programma è stupido, e non sa quali byte sono effettivamente testo e quali no, perciò li sostituisce tutti. Per superare questo inconveniente basta cambiare la tabella in uso, ritornando ad ASCII, o quello che è in uso dal vostro programma. Di solito tale comando sta o in file o in modifica. In windhex è File>Swap table file.
Ora arriviamo al problema XVI: purtroppo non riesce ad astrarre i caratteri, perciò la soluzione che adotta è sostituirli fisicamente nella vista di sinistra! [emoji33] Se salvate vi ritroverete una ROM sicuramente corrotta! NON SALVATE LA ROM DOPO AVER APPLICATO LA SOSTITUZIONE CON XVI! L'unico modo è avere una ROM "cavia" (una delle tante ahah) che userete per vedere come saranno i caratteri tradotti, che riporterete nella ROM originale. Già, è più comodo usare windhex per questo compito, anche se non ha grandi funzioni di hex editor.
Ora impareremo a cambiare il testo direttamente con l'hex editor. Come funziona questo metodo? Se sapete trovare e modificare i puntatori lo applicate alla svelta. - Individuate il testo da modificare con la ricerca di stringa, di testo stavolta
- Ricavatene il puntatore
- Cercate il puntatore dall'inizio della ROM. Meglio se pochi (1) risultati, perchè significa che la risorsa è usata una sola volta. Nel caso del testo degli eventi dovrebbe essere così, a meno che non stiate modificando del testo "di sistema", usato più volte. Segnate l'offset.
- Andate in spazio libero, createne il puntatore, e scrivete! Bisogna però stare attenti alla larghezza, in quanto finora tutti gli hex editor che conosco adottano larghezza fissa delle colonne. In Certi casi torna utile, ma non in questo. Indicativamente, in minuscolo potete scrivere 30 lettere.
- Andate al primo offset segnato. Contiene il puntatore al vostro testo. Dovrete sostituirlo con il puntatore al nuovo testo.
Se conoscete un hex editor migliore di quelli elencati in questo corso (windhex, XVI, HxD, bless) per favore segnalatelo.
Come potete notare non ci siamo spostati neanche per un attimo dal programma corrente, quindi, se il testo è favorevole da scrivere, questo consente di risparmiare un po' di tempo rispetto ad altri metodi.
Come vedremo nelle ultime lezioni, disporre dei testi di una ROM è essenziale per iniziare piuttosto agevolmente alcune particolari ricerche di ASM.
Come compito modificate un testo come volete, Tanto poi fatto uno fatti tutti.
Lo so che stavolta era breve, ma d'altronde siamo in regime di festività : p
auguri (emoticon dell'albero di natale)
BONUS:
L'altra volta vi ho lasciato sulle spine, io stesso odio quando i professori poco professionali fanno questo, ma almeno mi faccio perdonare perchè rimedio subito! (una volta una mia prof ha anticipato una cosa un mese prima... -.-")
L'argomento era la ricerca della mappa. Ora che sapete tutto sugli hex editor, potete caricare la tabella di caratteri di rubino e procedere alla ricerca. Cercate un nome di città in maiuscolo. Troverete, dopo qualche F3, intorno a 0x3E6FF0, una bella tabella con tutti i nomi delle città. Ora per fare le cose veramente per bene, per scoprire l'indirizzo della mappa bisognerebbe armarsi di disassemblatore e VBA SDL-H, ma comunque non è troppo fantasioso supporre che, dato che ci sono tutti i posti elencati in un qualche ordine, questi corrispondano agli indici di una tabella. Quindi uno sprovvisto di conoscenze ASM avrebbe potuto provare a cercare quei numerini corrispondenti ai luoghi che si vedono su Advance map, ma stavolta dedotti dalla tabella delle città.
Ovviamente non possiamo andare avanti così per sempre, con solo l'hex editor non si va molto lontano. Per questo in futuro vedremo anche l'ASM. ci saranno circa 4 lezioni per così dire introduttive e altrettante più addentrate nel cuore dell'azione.
- prima: boh
- 180102: migliorato rs cyan, migliorato rinomina table, rimossa battuta, maiuscole, typo, rimosse parentesi, aggiunto bonus ricerca mappa
.
LEZIONE 2
UNA LENTE D'INGRANDIMENTO SUL GBA
I moderni calcolatori sono costruiti secondo l'architettura di Von Neumann, scartando quella di Turing che ha grande rilevanza teorica, ma con i moderni dispositivi è inefficiente e poco gestibile.
Spiegando brevemente, Questo significa che Il cuore del dispositivo è la memoria centrale (nome rigoroso per RAM, ovvero la memoria temporanea in cui stanno i dati che devono essere elaborati). Tutte le componenti del dispositivo comunicano con la memoria centrale e con il processore.
Anche il GBA funziona secondo questo schema. Apriamo il VBA normale e andiamo nel menu a tendona "tools" e apriamo tutto da "io viewer" a "tile viewer". Che accidenti è tutta 'sta roba? Sono le varie parti del GBA, servono per "dissezionare" il gioco e ricavarne il funzionamento. Ora possiamo chiuderle tutte tranne una, il memory viewer. Essenzialmente tutte quelle finestre possono essere ricondotte al memory viewer, in quanto il contenuto di ciascuna è solo una forma comprensibile di ciò che sta nella memoria. Con il memory viewer avete accesso a tutte le macro aree della memoria del GBA, spiegate tra poco.
Come vedrete, ci sono dei buchi negli indirizzi di memoria. Questo non significa che la memoria del GBA abbia davvero dei buchi fisici (è piena di tarli? ovviamente no) oppure sia davvero grande come i numeri che vedrete, che sono centinaia di MB! Semplicemente lei fisicamente sarà come sarà, è compito di chi studia elettronica vederlo, ma viene "mappata" logicamente secondo gli indirizzi che vedremo, decisi dal costruttore. Questo procedimento è un'astrazione dall'ambiente fisico, e ci permette di manipolare indipendentemente qualsiasi settore. Questo significa che i circuiti del GBA mappano certi indirizzi con certi dispositivi di memoria, ignorando altri indirizzi. In questo modo è possibile semplificare i numeri stessi degli indirizzi, come vedrete dopo.
Tutto ciò trova un'applicazione pratica: il WBTO.
Questo comando degli script permette di scrivere un byte in una locazione di memoria a nostra scelta.
La sintassi è
Codice: writebytetooffset 0xXX 0xYYYYYYYY
dove XX è il nostro byte, e YYYYYYYY è l'indirizzo di memoria del GBA a cui vuoi scriverlo.
Non si può veramente "insegnare il WBTO", a parte perchè l'ho appena fatto nel periodo precedente (si, la frase precedente in grassetto è "insegnare il WBTO"), ma soprattutto perchè questo comando presuppone che ci sia uno studio dietro la sua applicazione, in modo da ottenere l'effetto ricercato. Ok, posso dirvi cosa dovrete scrivere nella memoria per ottenere qualcosa, ma allora l'insegnamento si riduce a una semplice elencazione di valori, cosa che potete trovare benissimo per il WEB (e quelli di forumcommunity ne sanno qualcosa, vero?). Qui vi spiego COME funzionano gli offset di memoria, in modo che possiate sviluppare il vostro atteggiamento critico verso la realtà (mi sembra filosofia  ) che vi porterà a fare le vostre nuove scoperte. Se poi unite questo al potente strumento che è la documentazione degli offset scoperti allora sarete un'arma dal grande potenziale.
SPIEGAZIONE SU COME FUNZIONA LA MEMORIA
#Todo prendi da tonc
in questa sezione spiegherò brevemente lo scopo di ciascuna delle memorie del GBA.
I numeri a 2 cifre riportati di seguito sono da mettere davanti all'offset, che in totale dovrà avere 8 cifre (32 bit). - 08 : La nostra ROM. Il GBA legge da questa memoria il gioco. E' una delle più lente della lista. Ed ecco spiegato il motivo del mettere lo 08 al puntatore. Ogni puntatore visto fino ad ora si riferiva alla ROM, perciò si metteva per forza il byte 08. Ora nella guida su come costruire un puntatore, sostituite il passo "metto 08 al puntatore" con "metto il numero della memoria che voglio usare".
Notate che ROM significa Read Only Memory, memoria di sola lettura, dunque evitate fin da subito di provare a farci un WBTO, perchè non funzionerebbe e vi disperereste inutilmente 
- 09 : Uno spazio addizionale per la nostra ROM. Per accedere alla ROM estesa, che va dai 16 MB ai 32 (il massimo) si usa questo prefisso. l'offset che il GBA vuole è quello che sarebbe aprendo la ROM con l'hex editor con l'origine relativa in 01000000, come se fosse una sorta di bank 2. Siamo fortunati, il primo game boy aveva un bank ogni 64 KB! Quello che avevamo detto la scorsa volta sugli scostamenti torna molto utile. In pratica serve solo a chi ha tantissimi dati e ha finito lo spazio delle ROM originali.
Esempio:
Con XSE ho espanso la ROM a 32 MB perchè ho inserito un sacco di canzoni e non ci stava tutto in 16. Voglio accedere a 0x1500000. Che offset servirà? 0x9500000. Basta sommare.
- 07 : è una memoria piccolissima che contiene le informazioni sugli oggetti. un oggetto può essere qualunque cosa della grafica, da un people a un mugshot, a un elemento dell'interfaccia utente. Essenzialmente sono comunque degli sprite. Trovate alcune informazioni nelle varie guide del forum.
- 00 : BIOS di sistema. è una cosa che tutti i computer hanno, e contiene "l'essenza della vita", ovvero, più praticamente, tutto ciò che serve a far funzionare il computer a livello basilare (del tipo accendersi, rispondere agli stimoli, ecc). Non a caso l'acronimo sta per Basic Input/Output System. La scritta "game boy advance" quando si accende è opera sua. Noi potremo trarre vantaggio dal BIOS con l'ASM, in quanto potremo usare alcune funzioni non proprio elementari contenute in esso: ad esempio la decompressione dei dati, oppure funzioni matematiche trigonometriche, che si vedono al triennio delle superiori. Già, non sembrano molto essenziali per far funzionare una macchina, ma probabilmente sono state inserite perchè di frequente uso nei giochi. Infatti, dato che risiedono in questa memoria, sono molto più veloci rispetto a quanto potremmo fare noi "artigianalmente".
- 0E : SRAM, ovvero il salvataggio. La memoria più lenta.
- 02 : WRAM, La memoria temporanea che hanno tutti i computer. Qua abbiamo la bellezza di 256 KB di RAM. E' una memoria veloce, sicuramente più della ROM, ma sta a metà classifica.
- 03 : Con questo codice ci si riferisce all'IRAM, ovvero una memoria interna (come suggerisce l'iniziale) al processore. E' la più veloce di tutte, ma è grande solo 32 KB. Meglio non utilizzarla per i nostri scopi, in quanto è già utilizzata da alcune cose critiche necessarie al funzionamento corretto del sistema, e pasticciandoci rischieremmo solo di fare dei casini e crashare il gioco.
- 05 : Contiene le palette da utilizzare. contiene 16 palette per un totale di 256 colori. Agli atti pratici on è modificabile, perchè in pokemon viene costantemente aggiornata prendendo i dati dall'indirizzo 0202EEC8 (ROM AXVE, per altre ROM sicuramente c'è scritto su pokecommunity), che i programmatori del gioco hanno deciso di usare come deposito temporaneo (buffer).
- 04 : Questa locazione si chiama registri di Input/Output. è un minuscolo settore in cui ci stanno i valori interni del GBA per utilizzare le periferiche, come il suono, la porta dati, o il display stesso.
- 06 : VRAM. Questa è la memoria Video da 96 KB. Il suo contenuto è grezzo, per visionarla in forma comprensibile si usano il tile viewer e il map viewer. Le map essenialmente sono ciò che forma l'immagine da visualizzare: Sono dei riferimenti ai tiles. Ci possono essere fino a 4 strati, chiamati BG, probabilmente per background. In pokemon il BG0 è utilizzato principalmente per l'interfaccia. Gli altri variano a seconda del contesto, ma durante l'overworld sono usati tutti e 3 per le varie altezze dei blocchi. Ad esempio il tetto delle case è nel BG1. Ci sarà una lezione approfondita su questo.
Ricordate comunque che per ogni esigenza di consultazione tecnica esistono i siti internet, che non dovete leggere subito, ma comprenderete man mano con l'avanzare delle lezioni:
http://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm
http://problemkaputt.de/gbatek.htm
Il secondo è prevalentemente una referenza: se uno non si ricorda a memoria una cosa va e la trova, il primo invece spiega un po' di più.
Ora che sapete un po' meglio come funziona la mappatura della memoria, vi mancano gli offset. In questo forum io mi sto battendo per avere una raccolta ordinata di tutti gli offset, ma l'idea sembra non riscuotere successo. Comunque se volete alcuni sono qui
http://pokehack.altervista.org/showthread.php?tid=1754
http://pokehack.altervista.org/showthread.php?tid=2012
poi boh...
Altrimenti potete sempre bazzicare in altri fori e gozzovigliare un po' (e magari venire a riportarmi cosa scoprite). Io di sicuro prima o poi farò passare tutte le discussioni della macroarea apprendimento e ne coglierò ogni offset. Noiosissimo, lo so.
se volete, potete usare i 2 link sopra per giocherellare con i registri.
Ecco ora qualche esempio di WBTO: - difficoltà facile:
hmm, non mi garba molto il colore dell'erba del percorso 101. Aspetta che chiamo il giardiniere...
Codice: #org @start
writebytetooffset 0x19 0x0202ef22
writebytetooffset 0x29 0x0202ef23
end
et voilà, ora è diventata di un bel rosso sangue! (DICHIARAZIONE DI NON RESPONSABILITA': non voglio promuovere la violenza, ciò che faccio io è solo a scopo didattico)
Spiegazione: sostituisco il quattordicesimo colore della terza palette. Come ho ricavato i valori: sapendo l'indirizzo di base delle palette e che ciascun colore occupa due bytes, con un rapido e semplice calcolo scopro quale offset corrisponde al colore che voglio modificare. Per sapere quale colore sia quello dell'erba apro i viewer del VBA e smanetto un po' a caso. Oppure posso aprire un programma di grafica del GBA e cercare i tileset, dumparli, e vedere con un programma serio (NO paint) a quale colore corrisponde l'erba.
- difficoltà media:
Sono riuscito ad implementare una feature che per l'utente non ha rilevanza, ma può tornare utile a noi sviluppattori. Si tratta di dirottare i dati delle tabelle nella RAM. Come mai fare una cosa che a orecchio sembra complicata? Perchè può capitare di "finire lo spazio", ovvero arrivare a 255 elementi di una tabella indicizzata con un byte e dunque non poterne più inserire nessun'altro, a meno di avventurarsi nell'asm per cambiare il modo con cui vengono trovati gli elementi. Ma basta con le chiacchiere e passiamo ai fatti: Sono riuscito a dirottare in RAM i multichoice; Ovviamente è possibile farlo con tutto, ma mi piaceva farlo con questi dati.
Essenzialmente il comando multichoice degli script è stato tremendamente sprecato (come molti altri), con solo un'ottantina di valori, ma per cose inutili, prevalentemente per la gestione della reception.
Pensavo che sarebbe stato bello poter vere infiniti set di valori per abbellire la storia. Fortunatamente è stato facile dedurre la struttura dei dati senza dover guardare le istruzioni relative al multichoice: è soltanto un insieme di puntatori ai testi. Cambiando quei puntatori (che risiedono nella ROM) e facendoli puntare alla RAM, possiamo cambiare i testi ogni volta che vogliamo. Tutte queste cose sono possibili perchè il GBA non ha un sistema operativo. (più o meno... è un discorso complicato)
Come ben sapete i multichoice su rubino sono circa 80, ma possono essere al massimo 255, perchè in XSE viene detto chiaramente che l'ID occupa un byte. E se li finiamo? Semplicemente diciamo al GBA di andare a trovare i testi in RAM, così se ne possono mettere quanti si vuole! Dovrete sacrificarne alcuni, ma ne avrete infiniti! Quanti? dipende da voi, da quello che pensate sia il massimo numero di scelte tra tutti i multichoice del vostro gioco. Significa rinunciare a uno slot dei 255 per avere infiniti multichoice da una scelta, uno dei 255 per avere infiniti multichoice da due scelte, uno per tre scelte, e così via, fino al numero che volete. Il massimo numero di scelte che si può fare senza far crashare il gioco è 9. Quindi gli li ultimi 9 multichoice si riferiranno agli ultimi 9 puntatori dei boxset (per approfondimenti vi rimando al topic ufficiale del multichoice, ci dev'essere pure una mia guida), i quali punteranno alla RAM. Per poter utilizzare la tecnica negli script occorrerà fare un WBTO nell'area designata, con i caratteri che abbiamo visto la volta scorsa per comporre il testo, e successivamente chiamare il multichoice.
Esempio di script con cui scrivo del testo sulla RAM da usare come fonte per i multichoice infiniti:
Codice: #org @start
writebytetooffset 0xBB 0x2000000
writebytetooffset 0xFF 0x2000001
writebytetooffset 0xBC 0x2000002
writebytetooffset 0xBD 0x2000003
writebytetooffset 0xFF 0x2000004
writebytetooffset 0xBE 0x2000005
writebytetooffset 0xBF 0x2000006
writebytetooffset 0xFF 0x2000007
msgbox @string1 MSG_FACE //"PROF. BIRCH spends days in his LAB..."
multichoice 0x0 0x0 0x0 0x0
ho dovuto metere un testo se no non rimaneva fermo il riquadro. Bah, dettagli per scripter.
Per poter utilizzare lo script è necessario fare la modifica alla propria ROM come spiegato nel topic http://pokehack.altervista.org/showthread.php?tid=2795
L'effetto è
http://pokehack.altervista.org/attachment.php?aid=309, non contate il fatto che nell'immagine ci sono solo 2 testi invece di 3 come nello script, erano due prove diverse. Il concetto che rimane è il poter cambiare i dati del gioco durante la sua esecuzione, dati che per il gioco non significano niente, ma per l'utente sì. Questo trucchetto sarebbe quasi un virus, sui computer. Ma noi siamo i padroni dell'universo dell'hardware e facciamo tutto.
Spiegazione: A parte la modifica al multichoice che non è mostrata, ho semplicemente scritto del testo nella RAM, che viene letto correttamente dal programma multichoice.
compiti? Boh, non saprei, ci possono essere mille utilizzi differenti, a seconda della situazione! noi in un contesto come questo non abbiamo nemmeno delle occasioni, degli stimoli ad usarlo, in quanto operiamo (si presume) su ROM pulite, perciò non abbiamo le necessità che scaturiscono da un progetto reale. inoltre qua siamo liberi di fare ciò che ci sentiamo, senza vincoli (non come in altre lezioni). Dunque, per non saper né leggere né scrivere, provate a fare qualcosa con il WBTO, quello che vi sentite, e spiegatemi come l'avete trovato, e cosa fa.
In seconda battuta spiegatemi cosa significa questo:
Codice: writebytetooffset 0xAE 0x3004360
Consigli: per fare il primo, pensate al vostro obiettivo, poi scovatene l'offset. come funziona l'obiettivo? Se voglio ottenere questo, cosa devo mettere?
Per fare il secondo compito cercate l'offset indicato dal comando, e andate a vedere in quale memoria (e in quale settore in alcuni casi) risiede. pensate a cosa fa tale locazione e come si comporta con il nuovo byte. Se non riuscite a capire cosa sia, riconsiderate tutto quanto visto finora 
Ah, facciamo che se volete cambiare le palette lo fate per un'altra ROM? Sennò sapete già l'offsset. Tanto è facile, basta cercare i colori che il VBA vi dice. Per fare ciò basta fare il dump della memoria dal memory viewer e aprendolo con l'hex editor cercare i colori del palette viewer, scritti tutti attaccati, stando attenti a invertire i due byte.
Se avete dubbi come sempre non esitatee achiedere, ciao
-180319
abbellita leggermente impaginazione
tolte parentesi, migliorata sintassi frasi
tolte frasi poco consone ("manfrina poetica")
tentativo fallito di fare una battuta "potente strumento = il vostro cervello"
typo
migliorate spiegazioni memorie, compiti, esempi
aggiunte info chieste in precedente aula
-170111
piccoli cambiamenti alle frasi per spiegare meglio, rimozione link google a von newmann e altri contenuti poco contribuenti
liste invece di -
rimosso spiegazione semidettagliata sulle tilemap, e collegamento a little endian #reinserire
rimosso link doppio a cowbyte e "freakin'" inteso come parolaccia
aggiunto disclaimer a erba rosso sangue
soppressa alternativa, sostituita da piccola domanda. parte rimossa: "2) mi spiegate il funzionamento di uno dei "codici da inserire nelle ak rum" (sarebbero i WBTO) che trovate su forumcommunity internet."
corretto la descrizione della memoria 09
-Prima: ?
 Mi Piace Ricevuti:  |
|
|