ASM - Tutorial (German/Deutsch) by Darius
First...
I'm still writing English for those who come in here and can't understand a word. This is a german Tutorial. I have nothing to say now.
So, jetzt beginnen wir... ich hab 3 Jahre in Deutschland gelebt und habe somit ein paar Skills in Deutsch. Obwohl ich (viel) länger in Spanien gelebt habe kann ich besser Deutsch (ich weiß auch nicht warum). Aber egal... jetzt was zum Aufbau. Ich werde in diesem Tutorial erklären, wie ihr einfache Blöcke, nette Generatoren und vielleicht auch den ein oder anderen Sprite programmiert. Ich werde vielleicht so pro Tag ein Kapitel hinzufügen und ggf. (<- Krass, ich kenn 'ne Abkürzung) andere verbessern.
Bis jetzt solltet ihr wissen, wie:
Wenn ihr das alles könnt, könnt ihr euch ein paar Sachen zulegen:
Gut, beginnen wir dann mit dem Kapitel 0.
Wahrschenlich bist du schon vertraut mit dem Dezimalsystem:
Jetzt kommt was neues: Das Hexadezimale Zahlensystem!
Da zählst du so:
Also, das funktioniert (schriftlich erklärt) so: Zuerst kommen die 10 arabischen Zahlen 0-9, danach folgen die ersten 6 Buchstaben des euch sicherlich bekanntem Alphabets, nämlich A-F. Wenn ihr euch jetzt nochmal die Zahlenreihe oben anschaut, sollte es *bing* machen. Wenn nicht, dann hilft vielleicht mal eine Tabelle:
Jetzt (denke ich) ist das jedem klar geworden. Wenn nicht, schreibt mir eine PM!
Jetzt zum binären Zahlensystem. Grundlegend erzähle ich euch was zu dieser Zählweise: Dieses Zahlensystem besteht nur aus Nullen und Einen, genauso wie der Computersyntax. Es gibt nur zwei Möglichkeiten: Entweder die Eins steht (set) oder nicht bzw. Null (clear). Eine solche 0 oder 1 ist ein Bit. Acht Bits ergeben einen Byte.
00000001= 1 Byte (8 Bit)
0001 = 4 Bit
Rein dezimal gesehen sind diese Zahlen gleichwertig. (00000001 binär ist 1 dezimal, 0001 binär ist 1 dezimal). Warum also sollte man das Längere schreiben? Nun, nehmen wir mal an, jeder "Schalter" (ein Bit funktioniert wie ein Schalter beim Licht, 0 ist aus und 1 ist an) steht für eine Funktion, das erste Bit für ..., das Zweite für..., und so weiter. Diesen ganzen Textblock hätte ich euch ersparen können, denn: In SMW nutzen wir es einfach immer als Byte, z.B. beim Property Byte (das kommt viel später). Zählen in diesem System muss man nicht können, da ich Binär praktisch umsonst gelernt habe, da ich niemals bei irgendeinem ASM Zeugs zählen musste in binär. Gut, das wär dann rein theorethisch abgeschlossen. Aber wie gesagt auch nur rein theorethisch. Ihr habt das noch nie ausprobiert. Und da man nicht dadurch lernt, ein Tutorial zu lesen, sondern dadurch es auszuprobieren, schreibt doch mal bitte diese Dezimal-Zahlen in hex um.
a) 1, 6, 9;
b) 10, 14, 16;
c) 112, 113, 115;
d) 245, 254, 255;
Umso weiter ihr gekommen seid, desto besser. Aber normalerweise solltet ihr das mit dem Rechner umrechnen.
Unser wichtigstes Dokument: Die RAM Map! Klickt einfach rechts in der Navigation von SMWC Ganz unten auf "RAM Map". Dort seht ihr dann sowas hier:
Jetzt seht ihr Eine Tabelle mit etlichen 100 Zeilen und 4 Spalten. Die Spalten werde ich zunächst einmal erklären:
Noch was zu Scratch RAM von WhiteYoshiEgg:
So, jetzt solltet ihr auch das mit der RAM Map gecheckt haben. Wenn nicht, Fragen posten oder per PM an mich schicken. Die ROM Map wird eigentlich erst interessant, wenn ihr Patche programmieren wollt, und da das (wahrscheinlich) nicht in diesem Tutorial erklärt wird, werde ich euch nicht zusätzlich mit irgendwas unnötigem belasten. Funktioniert aber bis auf eine Spalte genau gleich (self-explianining... mir fällt das deutsche Wort gerade nicht ein). Ihr könnt das mit der RAM Map übrigens auch üben. Drückt einfach in eurem Browser STRG + F, dann tippt ihr ein Suchwort ein und erhaltet nach ein paar Klicks auf [->] eure RAM Addresse (hoffentlich). Zum Üben: Sucht folgende RAM Adressen:
a) Mario's Power-Up Status
b) P-Switch Timer
c) Münzen-Zähler
d) X-Speed eines Sprites
Wenn ihr bis c) erfolgreich ward, könnt ihr zufrieden sein. d) ist nur später ziemlich wichtig. Ich hab die Addresse schon so oft benutzt, dass ich die auswendig kann =D.
Wie angekündigt geht's hiermit weiter. Es gibt also verschiedene Arten von RAM Addressen. Kurz, Mittel, Lang (nicht falsch verstehen!). Wir bleiben bei meiner Beispieladresse von oben; $7E:0019. Zuerst einmal: Wenn wir Addressen benutzen, lassen wir den Doppelpunkt (":") IMMER weg. Es geht gar nicht anders, man muss den Doppelpunkt weglassen, ansonsten meldet xkas einen Fehler. Was ist xkas? Es ist ein Assembler, ein Tool, mit dem man ASM Codes in eine ROM einfügen kann. Es gibt schon ein paar davon, aber die am meist genutzten sind xkas und TRASM. Ich bevorzuge xkas, da TRASM mehr Bugs hat als xkas.
Als nächstes können wir noch zwei Sachen weglassen: das 7E und das 00. Warum? Immer, wenn ihr eine Addresse verwendet, ist standardgemäß die Addresse $7E00__ ausgewählt. Unsere Adresse wird also zu $19. Der Prozess läuft in dieser Reihenfolge ab: Ihr fangt vorne an und arbeitet euch nach hinten:
$7E0019 ;<- Das 7E ist standardgemäß ausgewählt und kann deshalb gelöscht werden.
$0019 ;<- Das 00 ist standardgemäß ausgewählt und kann deshalb gelöscht werden.
$19 ;<- Geschrumpft bis zum geht-nicht-mehr
So vermeidet ihr, $7F0019 in $7F19 zu schreiben (00 wurde gelöscht), denn das $7F19 wäre die Addresse $7E:7F19. Den Doppelpunkt schreibe ich und SMWC nur hin zur Verdeutlichung.
Die SMW Rom besteht aus 3 Teilen. Den ersten Teil kennt ihr ja schon: RAM. RAM Adressen befinden sich in der SMW Rom von $7E0000 bis $7F0000. Also besteht die RAM aus 2 Bänken, nämlich $7E und $7F. Die ersten zwei Zahlen stehen für die Bänke. Die ROM Map ist (viel) größer, und ist somit auch die größte Region der SMW Rom. Und dann gibt es noch die Hardware Register. Was aber enthalten nun diese 3 Teile?
Gut, wir werden bei Blöcken mit der RAM sehr stark arbeiten. Manche von euch werden wahrscheinlich schonmal ihre Rom mit einem Hex-Editor geöffnet haben, da habt ihr dann die RAM, ROM und die Hardware Register gesehen, aber nichts von alledem verstehen. Aber es gibt ja ASM, wo wir alles mit drei-stelligen Befehlen programmieren können.
In diesem Kapitel werdet ihr die ersten drei ASM Befehle erlernen. Diese wären Laden und Speichern. Warum drei? Für Speichern gibt es zwei. Die Befehle heißen LDA (Load Data from Accumulator) und STA (Save Data to Accumulator). Es wird so funktionieren: Mit LDA laden wir einen Wert, z.B. 01. Und mit STA speichern wir den Wert zu einer Addresse, zum Beipiel $19. Wenn wir das schreiben würden, sähe das so aus:
Das ist einfach oder? Wer das Prinzip nicht kapiert, hier mal ein Beispiel: Mit LDA legst du eine CD in den CD-Player und mit STA spielst du sie ab. Dem Code fehlt aber nochwas: Nämlich das Ende. Dazu einfach RTL oder RTS nach hinten schreiben.Ich bevorzuge es, RTL zu benutzen. RTL wird bei Blöcken für BTSD benuztzt, RTS hingegen bei Sprites oder Blocks für BlockTool. Also würde der Code so aussehen:
Ebenfalls ziemlich simpel. Jetzt wollen wir noch Kommentare hinter die Zeile schreiben, um den Code so zu dokumentieren und dass man auch danach noch weiß, wann was und was passiert. Das tun wir, indem wir ein Semicolon (heißt das so?) zwischen den Code und den Kommentar schreiben:
Wenn ihr den Code in eine Zeile schreiben wollt, könnt ihr nicht einfach alle Befehle hintereinander schreiben. Dazu muss ein Doppelpunkt zwischen die einzelnen Befehle:
Aber dann könnt ihr nicht mehr jede Aktion kommentieren und es wird schnell unübersichtlich, deshalb lasst das lieber! So, jetzt noch ein bischen was zu dem was wir da laden (Addressen haben wir ja schon genüg drüber geredet oder?). Wir laden eine Zahl, vor der ein # (sharp) steht. Das # kennzeichnet, dass da ein Wert geladen wird. Und wir können verschiedene Arten von Werten laden:
Ihr seht, wir haben in unserem Beispiel einen dezimalen Wert geladen. Wenn wir zwischen das # und den Wert noch ein $ quetschen, laden wir einen hexadezimalen Wert. Und wenn da ein % rein quetschen, laden wir einen binären Wert (1 Byte).
Wie ich oben noch gesagt habe, kommt ein zweites Speichern dazu. Der Befehl heißt STZ. Was der macht? Er speichert IMMER den Wert #00 zu einer Addresse.
Ich denke das muss ich nicht weiter erklären. Ihr habt die ersten 5 ASM Befehle gelernt. LDA, STA, STZ, RTL und RTS. Die Aufgaben dazu kommen am Ende des ersten Kapitels, wenn ihr euren ersten Block programmieren könnt.
Jetzt kommt endlich ASMPad ins Spiel! Öffnet es. Ihr solltet sowas sehen:

Wie ihr in dem Bild sehen könnt, ist ein Button oben in der Leiste blau markiert: Der graue Zement-Block-Button. Wenn ihr Maus 3 Sekunden auf dem Button verweilen lasst, sagt euch der Hover-Effekt "New Block" (Neuer Block). Jetzt erscheint dieser Code:
Was bedeutet db $42? Das ist (sagen wir mal) eine Intro für BTSD, zum Erkennen (in etwa). Löscht das nicht! Was bedeutet dieses ganze MarioBlabla? Das ist das, wo Mario sich am Block aufhalten muss, um ihn zu aktievieren. Dieses Tutorial ist natürlich deutsch, deshalb braucht ihr keine English-Kenntnisse. Deshalb müsst ihr nicht wissen, was "below", "corner" und so was heißt. Guckt nur auf diese Grafik:

Wie man jetzt aber damit umgeht, wisst ihr nicht. Also, oben stehen alle Optionen in einer Reihe:
Von diesem JMP lasst ihr am besten gar nicht erst groß beeindrucken, dass ist ein Jumping-Command (Befehl zum Springen). Das kommt aber etwas später. In unserem Beispiel soll Mario eine Feuerblume bekommen, wenn er sich auf den Block draufstellt. Also: MarioAbove. Unser Code ist eigentlich jetzt total einfach:
So, das war dann der erste Block! Jetzt können wir noch ein bisschen rumspielen: Wir erstellen jetzt noch einen Block, der, wenn Mario ihn mit der Feuerblume abschießt, Mario klein macht. Da können wir dann auch das neu erlernte STZ ausprobieren:
Die ganze Spielerei könnt ihr euch mal auf YouTube angucken: Video.
Wie ihr vielleicht im Video gesehen habt, springt MArio einfach nur auf den Block drauf und -schwupp- man merkt es gar nicht, hat er auf einmal eine Feuerblume. Bemerkbar könnte man das durch einen Soundeffekt machen. Und wie wir einen Soundeffekt unterlegen, zeig ich euch in diesem Abschnitt! es funktioniert eigentlich genauso wie das normale Prinzip, ihr ladet einen Wert der für einen Effekt staht und speichert den auf die Soundeffektaddresse. Warum mache ich also solche Abschnitte? Nun, es gibt spezielle Addressen, die möchte ich euch halt ans Herzen legen, da ihr sie sehr oft später brauchen werdet.
So, alles was ihr braucht ist eine Datei, die bei ASM-Pad beigelegt ist, und zwar findet ihr die im 'data'-Ordner, sie heißt sound.txt. Ihr seht eine gigantische Liste, und nicht nur eine: Alle RAM Addressen $1DF9 - $1DFC sind belegt von Musikzeug. Ich geb euch mal kurz eine Übersicht der Jeweiligen Addresse:
$1DF9: Sound Effekte, großer Teil.
$1DFA: Sound/Neben Effekte
$1DFB: Custom Music
$1DFC: (Fast) Alle Soundeffekte
Als Beispiel wollen wir jetzt einen Sound abspielen. Das machen wir ganz einfach und wie gewohnt per LDA und STA.
Gut... hierzu sollte es eigentlich keine Fragen geben, falls doch, bitte posten!
Eigentlich wollte ich das hier erst später schreiben, doch ich habe mich dazu jetzt entschlossen! In der Überschrift steht etwas von Basis Codes. Selbsterklärend, das sind kleine ASM-Bausteine, die ihr verwenden könnt. Die sind sehr nützlich fürASM Einsteiger. Um aber Ordnung zu behalten, bringe ich euch mal das Springen zu Subroutines bei. Jumping to a subroutine im Englischen. Schaut euch das Jumping an. Daraus leiten wir jetzt den ASM Befehl ab: JMP, wie ihr es von den Mario Labels kennt, ist auch ein solcher Jumping Befehl. Wir benutzen aber das nicht, sondern JSR (BlockTool) oder JSL (BTSD). Das funktioniert so:
Hier sind übrigens die Basis Codes: Link
Ihr habt oben sicherlich schon diesen Befehl JMP wahrgenommen. Das ist ein sogenannter Jumping-Befehl. Er springt zu einer Routine. Und dabei gibt es verschiedene Jumping-Befehle:
Außerdem sind die beiden Befehle JSR und JMP nicht kompatibel mit langen Adressen ($xx:xxxx geht nicht!), JSL und JML hingegen nicht.
Vielleicht fragt ihr euch außerdem, was JML und JMP bringt. Die beiden ignorieren ja alles, was hinter dem Code kommt:
Aber natürlich wird der Code in der angesprungenen Routine beachtet. Wenn die Routine jetzt zu Ende wäre, würde der Code unterhalb von JML weiterlaufen - aber bei JML und JMP nicht! Eigentlich kann man sich das sparen...
Jetzt machen wir mal einen sinnvollen Code:
Ihr solltet euren Routinen einen sinnvollen Namen geben, denn wenn ihr später eure Sachen vielleicht noch mal technisch "überholen" wollt, wisst ihr dann gleich, was was macht. Wenn ihr es Ich_mag_Kekse_sehr_gerne_wer_denn_nicht_auch nennt, habt ihr Platz verschwendet und wisst später wahrscheinlich nur noch, dass ihr Kekse mögt! Also nennt es zum Beispiel Gib_Mario_Feuerblume.
....
MOOP! Bis hierhin erstmal. Weiter geht's dann heute Abend oder morgen!
Darius
First...
I'm still writing English for those who come in here and can't understand a word. This is a german Tutorial. I have nothing to say now.
So, jetzt beginnen wir... ich hab 3 Jahre in Deutschland gelebt und habe somit ein paar Skills in Deutsch. Obwohl ich (viel) länger in Spanien gelebt habe kann ich besser Deutsch (ich weiß auch nicht warum). Aber egal... jetzt was zum Aufbau. Ich werde in diesem Tutorial erklären, wie ihr einfache Blöcke, nette Generatoren und vielleicht auch den ein oder anderen Sprite programmiert. Ich werde vielleicht so pro Tag ein Kapitel hinzufügen und ggf. (<- Krass, ich kenn 'ne Abkürzung) andere verbessern.
Bis jetzt solltet ihr wissen, wie:
- ...man (Romi's) Sprite Tool benutzt
- ...man BTSD (Block Tool Super Deluxe) benutzt
- ...man Lunar Magic benutzt!
Wenn ihr das alles könnt, könnt ihr euch ein paar Sachen zulegen:
- Einen Texteditor oder Iceguy's ASM Pad
- RAM Map (Wenn du nicht immer Verbindung zum Internet hast)
- ROM Map (Wenn du nicht immer Verbindung zum Internet hast)
Gut, beginnen wir dann mit dem Kapitel 0.
Kapitel 0: Grundlegendes Zeug
0.1: Dezimal, Hexadezimal und Binär
Wahrschenlich bist du schon vertraut mit dem Dezimalsystem:
Code
0,1,2,3,4,5,6,7,8,9,10,11,12,13,...99,100,101,102,...100000, 100001,...
Jetzt kommt was neues: Das Hexadezimale Zahlensystem!
Da zählst du so:
Code
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15,16,...99,9A,9B,9C,9D,9E,9F,A0,A1,...FE,FF,100
Also, das funktioniert (schriftlich erklärt) so: Zuerst kommen die 10 arabischen Zahlen 0-9, danach folgen die ersten 6 Buchstaben des euch sicherlich bekanntem Alphabets, nämlich A-F. Wenn ihr euch jetzt nochmal die Zahlenreihe oben anschaut, sollte es *bing* machen. Wenn nicht, dann hilft vielleicht mal eine Tabelle:
Hex | Dez |
0 | 0 |
1 | 1 |
... | ... |
9 | 9 |
A | 10 |
B | 11 |
C | 12 |
D | 13 |
E | 14 |
F | 15 |
10 | 16 |
Jetzt (denke ich) ist das jedem klar geworden. Wenn nicht, schreibt mir eine PM!
Jetzt zum binären Zahlensystem. Grundlegend erzähle ich euch was zu dieser Zählweise: Dieses Zahlensystem besteht nur aus Nullen und Einen, genauso wie der Computersyntax. Es gibt nur zwei Möglichkeiten: Entweder die Eins steht (set) oder nicht bzw. Null (clear). Eine solche 0 oder 1 ist ein Bit. Acht Bits ergeben einen Byte.
00000001= 1 Byte (8 Bit)
0001 = 4 Bit
Rein dezimal gesehen sind diese Zahlen gleichwertig. (00000001 binär ist 1 dezimal, 0001 binär ist 1 dezimal). Warum also sollte man das Längere schreiben? Nun, nehmen wir mal an, jeder "Schalter" (ein Bit funktioniert wie ein Schalter beim Licht, 0 ist aus und 1 ist an) steht für eine Funktion, das erste Bit für ..., das Zweite für..., und so weiter. Diesen ganzen Textblock hätte ich euch ersparen können, denn: In SMW nutzen wir es einfach immer als Byte, z.B. beim Property Byte (das kommt viel später). Zählen in diesem System muss man nicht können, da ich Binär praktisch umsonst gelernt habe, da ich niemals bei irgendeinem ASM Zeugs zählen musste in binär. Gut, das wär dann rein theorethisch abgeschlossen. Aber wie gesagt auch nur rein theorethisch. Ihr habt das noch nie ausprobiert. Und da man nicht dadurch lernt, ein Tutorial zu lesen, sondern dadurch es auszuprobieren, schreibt doch mal bitte diese Dezimal-Zahlen in hex um.
a) 1, 6, 9;
b) 10, 14, 16;
c) 112, 113, 115;
d) 245, 254, 255;
Umso weiter ihr gekommen seid, desto besser. Aber normalerweise solltet ihr das mit dem Rechner umrechnen.
0.2: Die RAM Map Benutzen
Unser wichtigstes Dokument: Die RAM Map! Klickt einfach rechts in der Navigation von SMWC Ganz unten auf "RAM Map". Dort seht ihr dann sowas hier:
Originally posted by "RAM Map"

Jetzt seht ihr Eine Tabelle mit etlichen 100 Zeilen und 4 Spalten. Die Spalten werde ich zunächst einmal erklären:
Address: | Die jeweilge RAM Adresse. Format ist $XX:YYZZ, Beispiel: $7E:0019. Es gibt verschiedene Addressenarten, aber das erkläre ich im nächsten Kapitel. |
Length: | Die Größe der Adresse. Die Meisten befinden sich in der Größe 1 Byte, aber es geht noch (viel) höher. |
Type: | Der Typ der RAM Addresse. Kann sein: Misc, Subroutine, Player, Yoshi, Graphics, Counter, I/O (Input - Output), Hardware Mirror, Camera, Pointer, Timer und noch ein paar weitere. Diese Information soll euch dabei helfen, eure Addresse schneller zu finden. Wenn ihr jetzt zum Beispiel den P-Switch Timer haben wollt, sucht ihr bei Timer. |
Description | Zeigt euch eine (englische) Beschreibung von der Addresse, mögliche Werte, die man für diese Addresse speichern kann (verstehrt ihr erst später) und eventuelle Glitches/Bugs. |
Noch was zu Scratch RAM von WhiteYoshiEgg:
Originally posted by "WhiteYoshiEgg"
Scratch RAM hat nichts mit der Größe zu tun, sondern heißt nur, dass diese Adressen (in SMW $00-$0F) verschiedene Verwendungszwecke haben. Darin werden an vielen verschieden Stellen im Spiel vorübergehend Werte gespeichert, die kurz danach gebraucht werden.
So, jetzt solltet ihr auch das mit der RAM Map gecheckt haben. Wenn nicht, Fragen posten oder per PM an mich schicken. Die ROM Map wird eigentlich erst interessant, wenn ihr Patche programmieren wollt, und da das (wahrscheinlich) nicht in diesem Tutorial erklärt wird, werde ich euch nicht zusätzlich mit irgendwas unnötigem belasten. Funktioniert aber bis auf eine Spalte genau gleich (self-explianining... mir fällt das deutsche Wort gerade nicht ein). Ihr könnt das mit der RAM Map übrigens auch üben. Drückt einfach in eurem Browser STRG + F, dann tippt ihr ein Suchwort ein und erhaltet nach ein paar Klicks auf [->] eure RAM Addresse (hoffentlich). Zum Üben: Sucht folgende RAM Adressen:
a) Mario's Power-Up Status
b) P-Switch Timer
c) Münzen-Zähler
d) X-Speed eines Sprites
Wenn ihr bis c) erfolgreich ward, könnt ihr zufrieden sein. d) ist nur später ziemlich wichtig. Ich hab die Addresse schon so oft benutzt, dass ich die auswendig kann =D.
0.3: Addressen-Arten
Wie angekündigt geht's hiermit weiter. Es gibt also verschiedene Arten von RAM Addressen. Kurz, Mittel, Lang (nicht falsch verstehen!). Wir bleiben bei meiner Beispieladresse von oben; $7E:0019. Zuerst einmal: Wenn wir Addressen benutzen, lassen wir den Doppelpunkt (":") IMMER weg. Es geht gar nicht anders, man muss den Doppelpunkt weglassen, ansonsten meldet xkas einen Fehler. Was ist xkas? Es ist ein Assembler, ein Tool, mit dem man ASM Codes in eine ROM einfügen kann. Es gibt schon ein paar davon, aber die am meist genutzten sind xkas und TRASM. Ich bevorzuge xkas, da TRASM mehr Bugs hat als xkas.
Als nächstes können wir noch zwei Sachen weglassen: das 7E und das 00. Warum? Immer, wenn ihr eine Addresse verwendet, ist standardgemäß die Addresse $7E00__ ausgewählt. Unsere Adresse wird also zu $19. Der Prozess läuft in dieser Reihenfolge ab: Ihr fangt vorne an und arbeitet euch nach hinten:
$7E0019 ;<- Das 7E ist standardgemäß ausgewählt und kann deshalb gelöscht werden.
$0019 ;<- Das 00 ist standardgemäß ausgewählt und kann deshalb gelöscht werden.
$19 ;<- Geschrumpft bis zum geht-nicht-mehr
So vermeidet ihr, $7F0019 in $7F19 zu schreiben (00 wurde gelöscht), denn das $7F19 wäre die Addresse $7E:7F19. Den Doppelpunkt schreibe ich und SMWC nur hin zur Verdeutlichung.
0.4: Der Aufbau der SMW-Rom
Die SMW Rom besteht aus 3 Teilen. Den ersten Teil kennt ihr ja schon: RAM. RAM Adressen befinden sich in der SMW Rom von $7E0000 bis $7F0000. Also besteht die RAM aus 2 Bänken, nämlich $7E und $7F. Die ersten zwei Zahlen stehen für die Bänke. Die ROM Map ist (viel) größer, und ist somit auch die größte Region der SMW Rom. Und dann gibt es noch die Hardware Register. Was aber enthalten nun diese 3 Teile?
RAM | ROM | Hardware Registers |
|
|
|
Gut, wir werden bei Blöcken mit der RAM sehr stark arbeiten. Manche von euch werden wahrscheinlich schonmal ihre Rom mit einem Hex-Editor geöffnet haben, da habt ihr dann die RAM, ROM und die Hardware Register gesehen, aber nichts von alledem verstehen. Aber es gibt ja ASM, wo wir alles mit drei-stelligen Befehlen programmieren können.
Kapitel 1: Der erste Block
1.0: Laden und Speichern
In diesem Kapitel werdet ihr die ersten drei ASM Befehle erlernen. Diese wären Laden und Speichern. Warum drei? Für Speichern gibt es zwei. Die Befehle heißen LDA (Load Data from Accumulator) und STA (Save Data to Accumulator). Es wird so funktionieren: Mit LDA laden wir einen Wert, z.B. 01. Und mit STA speichern wir den Wert zu einer Addresse, zum Beipiel $19. Wenn wir das schreiben würden, sähe das so aus:
Code
LDA #01 STA $19
Das ist einfach oder? Wer das Prinzip nicht kapiert, hier mal ein Beispiel: Mit LDA legst du eine CD in den CD-Player und mit STA spielst du sie ab. Dem Code fehlt aber nochwas: Nämlich das Ende. Dazu einfach RTL oder RTS nach hinten schreiben.
Code
LDA #01 STA $19 RTL
Ebenfalls ziemlich simpel. Jetzt wollen wir noch Kommentare hinter die Zeile schreiben, um den Code so zu dokumentieren und dass man auch danach noch weiß, wann was und was passiert. Das tun wir, indem wir ein Semicolon (heißt das so?) zwischen den Code und den Kommentar schreiben:
Code
LDA #01 ;Lade den Wert #01 STA $19 ;Speicher das zu Mario's PowerUps RTL ;Beende den Code
Wenn ihr den Code in eine Zeile schreiben wollt, könnt ihr nicht einfach alle Befehle hintereinander schreiben. Dazu muss ein Doppelpunkt zwischen die einzelnen Befehle:
Code
LDA #01 : STA $19 : RTL
Aber dann könnt ihr nicht mehr jede Aktion kommentieren und es wird schnell unübersichtlich, deshalb lasst das lieber! So, jetzt noch ein bischen was zu dem was wir da laden (Addressen haben wir ja schon genüg drüber geredet oder?). Wir laden eine Zahl, vor der ein # (sharp) steht. Das # kennzeichnet, dass da ein Wert geladen wird. Und wir können verschiedene Arten von Werten laden:
Code
LDA #02 ;Dezimaler Wert (#) LDA #$02 ;Hexadezimaler Wert (#$) LDA #%00000010 ;Binärer Wert (#%)
Ihr seht, wir haben in unserem Beispiel einen dezimalen Wert geladen. Wenn wir zwischen das # und den Wert noch ein $ quetschen, laden wir einen hexadezimalen Wert. Und wenn da ein % rein quetschen, laden wir einen binären Wert (1 Byte).
Wie ich oben noch gesagt habe, kommt ein zweites Speichern dazu. Der Befehl heißt STZ. Was der macht? Er speichert IMMER den Wert #00 zu einer Addresse.
Code
LDA #00 STA $19 ;Ist dasselbe wie... STZ $19
Ich denke das muss ich nicht weiter erklären. Ihr habt die ersten 5 ASM Befehle gelernt. LDA, STA, STZ, RTL und RTS. Die Aufgaben dazu kommen am Ende des ersten Kapitels, wenn ihr euren ersten Block programmieren könnt.
1.1: Aufbau eines Blocks
Jetzt kommt endlich ASMPad ins Spiel! Öffnet es. Ihr solltet sowas sehen:

Wie ihr in dem Bild sehen könnt, ist ein Button oben in der Leiste blau markiert: Der graue Zement-Block-Button. Wenn ihr Maus 3 Sekunden auf dem Button verweilen lasst, sagt euch der Hover-Effekt "New Block" (Neuer Block). Jetzt erscheint dieser Code:
Code
db $42 JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteH : JMP SpriteV : JMP Fireball : JMP Cape : JMP MarioCorner : JMP MarioHead : JMP MarioBody MarioBelow: MarioAbove: MarioSide: RTL SpriteH: SpriteV: Fireball: Cape: MarioCorner: MarioHead: MarioBody: RTL
Was bedeutet db $42? Das ist (sagen wir mal) eine Intro für BTSD, zum Erkennen (in etwa). Löscht das nicht! Was bedeutet dieses ganze MarioBlabla? Das ist das, wo Mario sich am Block aufhalten muss, um ihn zu aktievieren. Dieses Tutorial ist natürlich deutsch, deshalb braucht ihr keine English-Kenntnisse. Deshalb müsst ihr nicht wissen, was "below", "corner" und so was heißt. Guckt nur auf diese Grafik:

Wie man jetzt aber damit umgeht, wisst ihr nicht. Also, oben stehen alle Optionen in einer Reihe:
Code
JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteH : JMP SpriteV : JMP Fireball : JMP Cape : JMP MarioCorner : JMP MarioHead : JMP MarioBody
Von diesem JMP lasst ihr am besten gar nicht erst groß beeindrucken, dass ist ein Jumping-Command (Befehl zum Springen). Das kommt aber etwas später. In unserem Beispiel soll Mario eine Feuerblume bekommen, wenn er sich auf den Block draufstellt. Also: MarioAbove. Unser Code ist eigentlich jetzt total einfach:
Code
db $42 JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteH : JMP SpriteV : JMP Fireball : JMP Cape : JMP MarioCorner : JMP MarioHead : JMP MarioBody MarioAbove: ;Wenn Mario auf dem Block ist... LDA #$03 STA $19 RTL MarioSide: MarioBelow: SpriteH: SpriteV: Fireball: Cape: MarioCorner: MarioHead: MarioBody: RTL
So, das war dann der erste Block! Jetzt können wir noch ein bisschen rumspielen: Wir erstellen jetzt noch einen Block, der, wenn Mario ihn mit der Feuerblume abschießt, Mario klein macht. Da können wir dann auch das neu erlernte STZ ausprobieren:
Code
db $42 JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteH : JMP SpriteV : JMP Fireball : JMP Cape : JMP MarioCorner : JMP MarioHead : JMP MarioBody Fireball: STZ $19 RTL MarioAbove: MarioSide: MarioBelow: SpriteH: SpriteV: Cape: MarioCorner: MarioHead: MarioBody: RTL
Die ganze Spielerei könnt ihr euch mal auf YouTube angucken: Video.
1.2: Soundeffekte benutzen
Wie ihr vielleicht im Video gesehen habt, springt MArio einfach nur auf den Block drauf und -schwupp- man merkt es gar nicht, hat er auf einmal eine Feuerblume. Bemerkbar könnte man das durch einen Soundeffekt machen. Und wie wir einen Soundeffekt unterlegen, zeig ich euch in diesem Abschnitt! es funktioniert eigentlich genauso wie das normale Prinzip, ihr ladet einen Wert der für einen Effekt staht und speichert den auf die Soundeffektaddresse. Warum mache ich also solche Abschnitte? Nun, es gibt spezielle Addressen, die möchte ich euch halt ans Herzen legen, da ihr sie sehr oft später brauchen werdet.
So, alles was ihr braucht ist eine Datei, die bei ASM-Pad beigelegt ist, und zwar findet ihr die im 'data'-Ordner, sie heißt sound.txt. Ihr seht eine gigantische Liste, und nicht nur eine: Alle RAM Addressen $1DF9 - $1DFC sind belegt von Musikzeug. Ich geb euch mal kurz eine Übersicht der Jeweiligen Addresse:
$1DF9: Sound Effekte, großer Teil.
$1DFA: Sound/Neben Effekte
$1DFB: Custom Music
$1DFC: (Fast) Alle Soundeffekte
Als Beispiel wollen wir jetzt einen Sound abspielen. Das machen wir ganz einfach und wie gewohnt per LDA und STA.
Code
LDA #$09 ;Irgend ein Soundeffekt STA $1DFC
Gut... hierzu sollte es eigentlich keine Fragen geben, falls doch, bitte posten!
1.3: Basis Codes einfügen
Eigentlich wollte ich das hier erst später schreiben, doch ich habe mich dazu jetzt entschlossen! In der Überschrift steht etwas von Basis Codes. Selbsterklärend, das sind kleine ASM-Bausteine, die ihr verwenden könnt. Die sind sehr nützlich fürASM Einsteiger. Um aber Ordnung zu behalten, bringe ich euch mal das Springen zu Subroutines bei. Jumping to a subroutine im Englischen. Schaut euch das Jumping an. Daraus leiten wir jetzt den ASM Befehl ab: JMP, wie ihr es von den Mario Labels kennt, ist auch ein solcher Jumping Befehl. Wir benutzen aber das nicht, sondern JSR (BlockTool) oder JSL (BTSD). Das funktioniert so:
Code
JSL Unterroutine ... anderer Code... Unterroutine: ... der Code der Unterroutine...
Hier sind übrigens die Basis Codes: Link
2.: Wenn das so ist, geh dahin! - Branching Befehle
2.0: Kleiner Zusatz - Subroutines erstellen und verwenden
Ihr habt oben sicherlich schon diesen Befehl JMP wahrgenommen. Das ist ein sogenannter Jumping-Befehl. Er springt zu einer Routine. Und dabei gibt es verschiedene Jumping-Befehle:
- JSL -> Springt zu einer Subroutine, die mit RTL geschlossen werden muss
- JSR -> Springt zu einer Subroutine, die mit RTS geschlossen werden muss
- JMP -> Springt zu einer Subroutine und der Restcode wird ignoriert, die angesprungene Routine muss zudem mit RTS geschlossen werden.
- JML -> Springt zu einer Subroutine und der Restcode wird ignoriert, die angesprungene Routine muss zudem mit RTL geschlossen werden.
Außerdem sind die beiden Befehle JSR und JMP nicht kompatibel mit langen Adressen ($xx:xxxx geht nicht!), JSL und JML hingegen nicht.
Vielleicht fragt ihr euch außerdem, was JML und JMP bringt. Die beiden ignorieren ja alles, was hinter dem Code kommt:
Code
JML $000990 LDA #40 ; Ignoriert. STA $55 ; Ignoriert.
Aber natürlich wird der Code in der angesprungenen Routine beachtet. Wenn die Routine jetzt zu Ende wäre, würde der Code unterhalb von JML weiterlaufen - aber bei JML und JMP nicht! Eigentlich kann man sich das sparen...
Jetzt machen wir mal einen sinnvollen Code:
Code
JSL Block_Main_Code ; Routine-Namen dürfen keine Leerzeichen enthalten! RTL Block_Main_Code: STZ $19 RTL ; Wir verwenden RTL, weil die Routine mit JSL angesprungen wurde!
Ihr solltet euren Routinen einen sinnvollen Namen geben, denn wenn ihr später eure Sachen vielleicht noch mal technisch "überholen" wollt, wisst ihr dann gleich, was was macht. Wenn ihr es Ich_mag_Kekse_sehr_gerne_wer_denn_nicht_auch nennt, habt ihr Platz verschwendet und wisst später wahrscheinlich nur noch, dass ihr Kekse mögt! Also nennt es zum Beispiel Gib_Mario_Feuerblume.
....
MOOP! Bis hierhin erstmal. Weiter geht's dann heute Abend oder morgen!
Darius