MegaFamilyBros

Hier könnt ihr Euch mit Gleichgesinnten austauschen bei der Entwicklung eines neuen Spiels oder eines neuen Stücks Hardware... oder einfach nur über Coding und Spieleentwicklung allgemein plaudern.

Moderatoren: ikari_01, d4s

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

MegaFamilyBros

Beitrag von lytron » 18. August 2012, 20:21

Holerö,

ich schätze, ihr kennt alle diese letztjährige, französische Homebrew-Demo?



Dummerweise scheint es die Seite, auf der es die SMC und die "Technical Reference" gab, nicht mehr zu geben, oder sie ist temporär down. Error 500 sagt, laut Wikipedia, nicht unbedingt viel aus.

Ich weiß, dass ich davon noch irgendwas auf meinem Laptop habe, den ich nicht mehr allzu oft anschmeiße - aber ich weiß nicht, ob es die "vollständigen Unterlagen" sind, die der Programmierer dort angeboten hat. Hat wer von euch eventuell die Dateien? Sind die eventuell in einer dunklen Ecke auf eurer Cloud? Könnt ihr mir die zur Verfügung stellen? Wäre äußerst nett von euch. :)
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
ChronoMoogle
snesfreaks.com-Team
snesfreaks.com-Team
Beiträge: 9895
Registriert: 26. Februar 2007, 14:56
+Positive Tradingpoints+: 98 von 98
Wohnort: Nippon
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von ChronoMoogle » 19. August 2012, 02:02

Soweit ich weiss hat der Svambo die aktuellste Version. Er laedt sie bestimmt gerne hoch.
Bild
| Mein YT Channel | Mein Twitter | Ich suche | Ich verkaufe | Foren SuFu |
...weil Terranigma einfach das Größte ist!

Benutzeravatar
Svambo
Hardcore SNES-Freak
Hardcore SNES-Freak
Beiträge: 571
Registriert: 14. September 2009, 19:09
+Positive Tradingpoints+: 13 von 13

Re: MegaFamilyBros

Beitrag von Svambo » 19. August 2012, 07:17

Jepp, hab das Teil hier. Was sucht ihr, Rom oder Sourcecode? Das Ganze ist übrigens noch ziemlich buggy auf echter Hardware ...

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 19. August 2012, 07:30

Svambo hat geschrieben:Jepp, hab das Teil hier. Was sucht ihr, Rom oder Sourcecode? Das Ganze ist übrigens noch ziemlich buggy auf echter Hardware ...
Am besten beides!
Ich erinner mich auch, dass ich es für "mäßig spielbar" gehalten habe... und, dass der Spielfiguren-Sprite zur Hälfte am oberen Bildschirmrand wieder herausgekommen ist, wenn man in ein Bottomless Pit gesprungen ist.

Immerhin kann das Ding zu Studienzwecken dienen. :wink:
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 21. August 2012, 19:06

lytron hat geschrieben:Immerhin kann das Ding zu Studienzwecken dienen. :wink:
Danke an Svambo für die Dateien.

Ich weiß nicht, inwieweit sich jemand schon mal mit dem Sourcecode auseinandergesetzt hat, und ich habe beileibe no reason for bitchin' around...

ABER:
- Der Kerl wechselt zwischen Groß- und Kleinschreibung
- Rückt munter zwischen einem und fünfzehn Leerzeichen seine Befehle ein
- Kommentiert einigen Kram munter aus und lässt ihn in seinem Sourcecode vergammeln
- Kopiert locker-flockig sich seinen Code zusammen, ändert dabei verschiedene Werte, lässt aber alte Kommentare am Rande stehen, sodass man als Außenstehender vollends verwirrt wird, weil der Befehl augenscheinlich das eine tut, aber als Kommentar etwas vollkommen anderes oder zumindest komplett Zusammenhangsloses steht
- Der Typ schreibt sich Makros für Einzeilenbefehle wie "mach den Akkumulator 16 bit groß", nur damit er dann dennoch statt dem Makro den normalen REP-#$30-Befehl nutzt.
- In der Zipfile liegen zwei ASM-Dateien mit exakt 0kb Größe. Angelegt, nicht mehr benötigt, Code rauskopiert und woanders eingefügt, Datei liegengelassen.
- Viele Dinge kann ich nicht unbedingt logisch nachvollziehen. Z. B. hat er eine Variable in Wordsize (16bit), macht zuerst "STZ Variable+1" (leert die Hälfte dieser 16 bit), um im nächsten Schritt einen 16-bit-Wert in die Variable zu schreiben. Genie oder Wahnsinn? Ich meine es ernst, ich verstehe nicht unbedingt, weshalb er das tut, und da frage ich mich: Ist es wirklich so komplett sinnlos, wie es mir vorkommt, oder steckt da ein ungeheurer Masterplan hinter, den ich nur zu tumb bin zu erfassen?
- Da er des öfteren aber an vielen Punkten mehrfach dasselbe macht, weil er scheinbar viel mit Copy & Paste arbeitet, tendiere ich dazu, zu glauben, dass da nicht viel Masterplan drin steckt. Eher ein "Hey, es läuft, so what?". Als Beispiel: Wo der Bauplan für die einzelnen "Kachel-Lagen" liegt, kann man dem SNES sagen. Englisch: Man kann festlegen, wo die Tilemaps für die einzelnen BGs sind. Soweit okay. Die Snes_Init setzt das immer auf $0000. Die Snes_Init ist eine Datei, die von einem wahnsinnig schlauen Hund mal geschrieben wurde, und seither von Leuten wie mir immer blind eins zu eins in ihre SNES-Programm-Ordner reinkopiert werden. Jedenfalls, die vielen Nullen in $0000 zeigen schon an, damit ist gemeint: Im Grafikspeicher liegen diese Daten ganz vorne. Jedenfalls, kurz bevor das "Team Neo"-Logo bei MegaFamilyBros erscheint, sagt das Programm dem SNES nochmal: Die Tilemap findest du bei $0000. Und da die Datei mit dem Programmcode für den Titlescreen eine Kopie der Datei mit dem Programmcode für das Teamlogo ist, wird es dort ein drittes Mal gesagt, ohne dass dort jemals was zwischendrin geändert worden wäre, ohne dass auf Seiten des SNES daran je einen Zweifel gegeben hätte...

... Hands Down: Der Typ hat definitiv mehr erreicht als ich, und ich persönlich will in keinster Weise schlecht machen, was er geschafft hat. Dennoch ist der Quellcode dadurch nicht unbedingt einsteigerfreundlich.
Ob man das Programm ganz einfach ent-buggen könnte, will ich nicht behaupten. Aber ich behaupte, dass man es sehr leicht verschlanken und übersichtlicher machen kann.

Edit: Außerdem verwirrt es mich ziemlich, dass er grundsätzlich zwischen binärem, dezimalem(!) und hexadezimalem Zahlenformat hin- und herspringt, das dezimale Format benutzt, wo das hexadezimale schlichtweg übersichtlicher wäre (er schreibt "#512" statt "#$200", und "#32768" statt "#$8000"...? o_O).
Habe ich erwähnt, dass ich stark davon ausgehe, dass er einiges an Tippfehlern drin hat (Definition 7stelliger Bytewerte etc.)
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 26. August 2012, 16:19

Zwei Sachen:

1) Ist das nur bei mir so, dass das Spiel bei der dritten Spielfigur grundsätzlich langsamer läuft?
2) Läuft das Spiel nur auf meinem Everdrive nicht? Im BSNES klappt es allerdings. Wäre cool, wenn das (beides) wer von euch mal prüfen könnte. Vielleicht ein SD2SNES-Test wäre auch noch interessant. Aber, in jedem Fall, wäre es wohl für byuu von Interesse, wenn das Ding wirklich auf tatsächlicher Hardware nicht läuft, aber in seinem Emulator...

Wie gesagt, wäre cool, wenn wer von euch das testen könnte. :)
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
ChronoMoogle
snesfreaks.com-Team
snesfreaks.com-Team
Beiträge: 9895
Registriert: 26. Februar 2007, 14:56
+Positive Tradingpoints+: 98 von 98
Wohnort: Nippon
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von ChronoMoogle » 2. September 2012, 16:03

Ich habe das Game vor etwa einen Jahr beim Svambo auf seinen Everdrive gespielt, lief auf echter Hardware.
Bild
| Mein YT Channel | Mein Twitter | Ich suche | Ich verkaufe | Foren SuFu |
...weil Terranigma einfach das Größte ist!

Benutzeravatar
Svambo
Hardcore SNES-Freak
Hardcore SNES-Freak
Beiträge: 571
Registriert: 14. September 2009, 19:09
+Positive Tradingpoints+: 13 von 13

Re: MegaFamilyBros

Beitrag von Svambo » 2. September 2012, 18:10

Also laufen tut es auf echter Hardware, ist aber extrem buggy. Sprite, die nicht zu sehen sind, Farben, die falsch initialisiert sind usw...
(Getestet haben wir das damals auf einem Powerpak, kanns gern die Tage nochmal auf SD2SNES versuchen)

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 2. September 2012, 19:21

Danke euch beiden für die Info. Wäre sehr freundlich, wenn du das checken könntest, aber mach, wie es passt.

Wie es auch schon an mir (weiter oben) herausgebrochen ist, habe ich gesehen, dass der Sourcecode nicht unbedingt übersichtlich geschrieben ist. Ich wollte da mal ein bisschen das sichten, aber die Zeit, die Zeit... :-/
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
KirbyKopf
Hardcore SNES-Freak
Hardcore SNES-Freak
Beiträge: 777
Registriert: 15. Oktober 2012, 19:59
+Positive Tradingpoints+: 2 von 2

Re: MegaFamilyBros

Beitrag von KirbyKopf » 27. Oktober 2012, 19:09

:D das spiel ist ja mal extem lustig!
Bild
Sag nichts sonst sauge ich dich ein!

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 11. Februar 2013, 21:07

Also. Ich will mal einige Daten loswerden, die bei mir auf der Festplatte sonst vergammeln. Das hier ist mein Projekt "Längster Foren-Post wo gibt". Mithilfe dieses Projekts bin ich wirklich schonmal an die sechzigtausend-Zeichen-Grenze für Posts gestoßen.

Das war eine Untersuchung und Dokumentation über MegaFamilyBros. Nach eineinhalb Monaten (20.08. - 06.10.2012) habe ich das Projekt aufgegeben, einmal, weil es *zu ausführlich* bzgl. der Subroutinen war, und ansonsten kamen wieder viele andere Dinge dazwischen, die spannender waren. :D

Anyways, viel Spaß. Und, falls jemand noch einmal wie ich den Einstieg ins Programmieren mithilfe dieser Opensource-Homebrew-Demo sucht, kann er meinen Kram vielleicht nutzen, erweitern, fertigstellen, korrigieren. Falls irgendjemand das für sinnvoll hält. Viel Spaß.



~~~



Inhaltsverzeichnis:
- Inhalt der Zipfile: Alle Dateien mit Ein-Satz-Erklärung. Zum Überblick.
- Inhalt der relevanten Dateien: Zur Übersicht, welche Subroutinen (SR) und Makros in den Dateien enthalten sind. Das ist eher ein Nachschlagewerk, wo man welche SR findet, und was sie genau macht. Nicht zwangsläufig aufschlussreich, wenn man sie von oben bis unten liest.
- Ablauf des Programms: Nennt die Reihenfolge und die Verschachtelung der relevanten Makros und Subroutinen. Dieser Teil ist das, was man in seiner Reihenfolge lesen sollte (und dann die Einzelfunktionen genauer untersuchen solle)
- Nutzung der Variablen: Stichwortverzeichnis, Teil 2



Inhalt der Zipfile
bg1.asm
boss1.asm
bossStep.asm
colision.asm
compilation.bat --- Batchdatei, die beim Kompilieren das Tippen in der Kommandozeile abnimmt.
deadlevel.asm
foe.Asm
gestion.asm
graphics.asm --- Leere Datei.
header.inc --- Kopfdaten. Standarddatei.
init.asm --- Weist verschiedenen Grafik-Koordinaten-Variablen Werte zu.
intro.asm --- Der Bildschirm mit dem Team-Neo-Logo.
joypad.Asm
level.asm
mainSprite.asm --- Leere Datei.
megafamilybros.asm
megafamilybros.link --- Datei relevant zur Kompilierung mit WLA DX
megafamilybros.obj --- Eine Art Zwischenergebnis-Datei von WLA DX
megafamilybros.smc --- ...
menu.asm
menuselection.asm --- Enthält die Subroutinen für die beiden Menüs (Level-/Charakterwahl).
rominfo.txt --- Sieht wie ein Dump von ZSNES oder einem anderen Emulator aus.
Snes_Init.asm --- Leert die Register für einen sauberen Start. Standarddatei.
sprite.asm
stock.asm
textdrawing.asm
ToolBox.asm --- Allerlei Macros. Für DMA, Bildschirmfunktionen, Dingelchen.
variable.asm --- Variablendefinition, SR zur Leerung/Reset der Variablen
vblank.asm --- VBlank Handling Subroutine. Ruft Subroutine "UpdateSprite" auf.
/build/wla-65816.exe --- Compiler, Teil eins
/build/wlalink.exe --- Compiler, Teil zwei
/image/ --- 45 .pic- & .clr-Dateien, also Bitplanes und Paletten
/image/etoile.pic --- Die Bilddaten der Münzen
/image/hitby.pic --- Die "Rückstoß bei Treffer"-Grafik des Körpers der Spielerfiguren im Spiel
/image/tete.pic --- Die Bilddaten der drei großen Köpfe der Spielfiguren (siehe Fußnote 1)
/image/workingtitouRun10.pic --- Die Laufanimation des Körpers der Spielerfiguren im Menü
/image/workingtitouRun10W.pic --- Die Laufanimation des Körpers der Spielerfiguren im Spiel
/image/workingtitouStand10.pic --- Die Standgrafik des Körpers der Spielerfiguren im Menü
/image/workingtitouStand10W.pic --- Die Stand- und Sprunggrafiken des Körpers der Spielerfiguren im Spiel
/image/lastText.pic.old --- eine Sicherheitskopie?
/image/master.pal --- Keine Ahnung. Letzte Änderung: 30.12.2010, im Vergleich zu allen anderen Dateien, die im März oder Mai 2011 erstellt, recht alt. Vielleicht eine Datenleiche.
/map/bg2map0.asm --- Tilemap, ASM-Datei (.DW $2000, $2000... etc. pp.)
/map/bg2map1.asm --- Tilemap, ASM-Datei
/map/map0.Asm --- Tilemap, ASM-Datei
/map/map1.asm --- Tilemap, ASM-Datei
/map/map2.asm --- Tilemap, ASM-Datei
/map/menuselection.asm --- Tilemap, ASM-Datei
/map/neo.map --- Tilemap, Binärdatei
/map/title.map --- Tilemap, Binärdatei
/spc/ --- 3 SPC-Musikdateien aus DKC, SD2 und, öh, TDSP?
/spc/loadspc.asm --- Joe Lees SPC-Player. Alles, was die Musik in MegaFamilyBros bringt

Fußnote 1: tete.pic ist #$800 Byte groß. Der Kopf der ersten Spielfigur, Hugo/Mega Krito, liegt bei #$600. Die anderen beiden Köpfe sind ab #$200. Das heißt, der Platz zwischen #$000 und #$1FF und #$400 bis #$5FF wird nicht genutzt.

~~~

Inhalt der relevanten Dateien
bg1.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
boss1.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
bossStep.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
colision.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
deadlevel.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
foe.Asm
.......... Ich bin hier noch nicht fertig gewesen!!!
gestion.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
init.asm
..... SR InitBG1
.......... Setzt die Variablen XPos, XPos2, YPos und YPos2 auf #$00.
.......... Setzt die Variable SPR1XPos auf #112 (= #$70, einen 32 Pixel breiten Sprite
.......... setzt das direkt in die horizontale Bildschirmmitte).
.......... Setzt die Variable SPRYPos auf #68 (= #$44, irgendwo im oberen Drittel des
.......... Bildschirms).
.......... Setzt die Variablen BG1XOFFSET und BG2XOFFSET auf die Werte #$7414 und #$7814.
intro.asm
..... SR Intro
.......... Am besten die Kommentare in dieser Datei nicht beachten
.......... Leert VRAM und Palette (ClearVRAM, ClearPalette)
.......... Setzt den Grafikmodus auf Mode 3 (vergesst den "Mode 1"-Kommentar.
.......... Copy & Paste-Artefakt)
.......... Setzt den Versatz (Offset) für die Tiles für BG1/BG2 ($2105) auf #$0000
.......... (unnötig, erledigt die Snes_Init.asm schon und der Wert wird dazwischen
.......... nicht geändert).
.......... Der Anfang der Tilemap wird bei $C000 gesucht (durch das #$C0 --> $2107)
.......... Mittels CopyVRAM verschiebt er erst die Tilemap und dann die zugehörigen
.......... Tiles in den VRAM. Als nächstes werden die 256 Farben der Palette per
.......... introPalSelection-Loop übertragen.
.......... Als nächstes leert er einige Register für das BG-Scrolling ($210E - $2110),
.......... die aber dank Snes-Init.asm schon leer sein müssten.
.......... Er leert die Variable XPos (for whatever reason), aktiviert BG1 (der Kommentar
.......... sagt BG1 & 2; was allerdings nicht stimmt. Übrigens ist in der Zeile darüber ein
.......... Tippfehler im lda-Befehl. Er gibt nur eine 7stellige Zahl an. Nett, dass der SNES
.......... bzw. WLA scheinbar doch versteht, was er meint).
.......... Danach erlaubt er NMIs und Joypad-Interaktion, wobei ich nicht direkt weiß,
.......... weshalb es notwendig ist, das erst zu machen, wenn man einen kompletten
.......... Screen aufgebaut hat(!?)
.......... Danach lässt er die Bildschirmhelligkeit ganz dunkel auf ganz hell hochlaufen,
.......... indem er loopToLight hochlaufen lässt. relevant ist: loopToLight ist so programmiert,
.......... dass der Status der vollständigen Helligkeit niemals erreicht wird. Und, statt dass
.......... er seine Subroutine umschreibt, schiebt er das dann lieber per Hand nach (durch
.......... die Zeilen "lda #%00001111" und "sta $2100".
.......... Als nächstes folgt der "loopIntro":
.......... "WAI" heißt: Warte auf die nächste vertikale Austastlücke. Ich bin mir nicht sicher,
.......... ob das benötigt ist, dass das SNES ein "Zeitfenster" bekommt, die Buttonsignale
.......... auszulesen.
.......... Das nächste ist der "HandleJoyIntro"-Loop, in dem solange gewartet wird, bis der
.......... Controller bereit ist, dass man seine Signale auslesen kann. Ich bin mir auch hier
.......... nicht sicher, aber ich kann mir nicht vorstellen, dass das bei jedem Auslesen nötig
.......... ist, sondern nur einmal am Anfang des Programms. Könnte man mal testen, ob es auch
.......... ohne ginge.
.......... Als nächstes wird das Register ausgelesen, in das hineingeschrieben wird, wenn u. a.
.......... Startbutton gedrückt wird ($4219), es wird der eine Bit für den Start-Button
.......... freigestellt (and #JoyStart), und anschließend geprüft, ob er gesetzt ist. Andernfalls
.......... gehts wieder an den Anfang des loopIntro.
.......... Wenn gedrückt wurde, gehts zu FinIntro (so viel französisch kann man ja. ;D), wo
.......... "loopToDark" aktiviert wird, anschließend wird diese Subroutine beendet.
joypad.Asm
..... MACRO handleInput
.......... Ich bin hier noch nicht fertig gewesen!!!
level.asm
..... SR levelmatch
.......... Entsprechend dem Inhalt von Variable level, die in LoopMenuLevel gesetzt wird, werden hier
.......... die Leveldaten geladen.
..........
.......... Es wird zu Beginn wird die Variable level in den Akkumulator geladen und nach den drei Fällen
.......... #$00, #$01 und #$02 entschieden, ob Level 0, 1 oder 2 geladen werden muss.
.......... Der folgende Ablauf ist prinzipiell ähnlich, unterscheidet sich nur durch die jeweiligen
.......... Daten, die verarbeitet werden.
.......... ClearVRAM und ClearPalette werden aufgerufen.
.......... Es werden Adresse der Tilemaps für BG1 und BG2 sowie deren Bank in die Variablen map0, map0Bank,
.......... map1 und map1Bank geladen.
.......... Im folgenden wird in die Variable blockLimit ein Wert (Level 2: #$48, sonst: #$A0).
.......... Der Bildschirm wird komplett abgeschaltet (die letzte Stufe, die bei loopToDark grund-
.......... sätzlich fehlt), ab diesem Punkt werden einige SR aufgerufen, die sich bei den Levels
.......... unterscheiden:
..........
..........
..........
..........
.......... Ich bin hier noch nicht fertig gewesen!!!
megafamilybros.asm
.......... Ich bin hier noch nicht fertig gewesen!!!
menu.asm
..... SR title
.......... Ist de facto dasselbe wie die SR intro, siehe deren Erklärung.
.......... Unterschied ist, dass logischerweise einige Labels anders heißen (weil sie sonst
.......... doppelt definiert wären, WLA so nicht arbeiten kann und dann erstmal Brotzeit macht)
.......... und dass am Anfang der Bildschirm ausgemacht wird (Force Blank, "lda #%10000000" und
.......... "sta $2100"). Logischerweise kann einiges hier auch wegfallen, weil bereits in der
.......... Intro-SR viele Dinge doppelt sind.
..... MACRO LoopMenu
.......... Ich bin hier noch nicht fertig gewesen!!!
..... MACRO SetMode1ForMenu
.......... Allerlei Videoeinstellungen, nichts weltbewegendes ($2105, $210b, $2107, $2108):
.......... Die BG-Einstellung auf Mode 1, setzt die Adressen der Tilemaps für BG1 und BG2 fest.
.......... Mehr nicht.
menuselection.asm
..... MACRO changeColor (b, b, b)
.......... (A muss 8 Bit groß sein, SEP #$20)
.......... Das erste Argument enthält die Nummer der Farbe in der Palette, die geändert werden
.......... soll, das zweite Argument ist der Low Byte, das dritte Argument der High Byte des
.......... Farbwerts.
..... MACRO updateSprXY (b, b)
.......... A wird auf 8 Bit gesetzt (SEP #$20)
.......... Das erste Argument wird in SPR1XPos gespeichert, das zweite in SPR1YPos.
..... SR LoopMenuSelection
.......... Dasselbe wie LoopMenuLevel, mit einigen Abweichungen. Führe hier nur die Abweichungen auf.
..........
.......... BG1 und BG2 werden ohne horizontal flip und vertical flip initiiert (Register $2107 und $2108).
.......... Ich denke, dass hat keinen Effekt auf das Endergebnis.
.......... Logischerweise wird für BG1 eine andere Datei geladen (das ist die "Schicht", in der der
.......... Menütext erscheint, wo logischerweise jetzt die Namen der Figuren erscheinen sollen).
.......... Ein Teil zur Übertragung einer Sprite-Palette, der in LoopMenuLevel auskommentiert war,
.......... ist hier aktiv - und überschreibt Werte, die in InitSpriteAndPalette geschrieben und nicht
.......... genutzt wurden.
.......... Der Vollständigkeit halber sei erwähnt, dass ein Teil, der sich mit dem Laden einer Musikdatei
.......... beschäftigt, in "LoopMenuLevel" auskommentiert ist, und hier komplett fehlt.
.......... Es werden einige Variablen mit Werten gefüttert, die die Sprites betreffen, zusätzlich Spielwerte
.......... (Geld, Lebensenergie des Spielers).
.......... Die "tempB"-Variable wird geleert. (Wird hier die Nummer des ausgewählten Elements enthalten)
..........
.......... (loopSelection)
.......... Im Loop werden nach dem Ablauf des Timers (alle 6 Durchläufe) folgende Subroutinen aufgerufen:
.......... mainSpriteAnimation, updateSpriteAnimation und updateSpriteHead:
............. Durch den Wert von #$00, der zuvor in "SPR1ACTION" gespeichert wurde, und dem Wert #$01 in "SPR1STATUS"
............. wird mittels mainSpriteAnimation erwirkt, dass in "spr1Adress" die Adresse der ersten Grafik für die
............. Laufanimation steckt, sodass diese Grafik dann mit updateSpriteAnimation in den VRAM übertragen wird.
............. Der "richtige" Kopf wurde mit der Eingabe von "1536" (= #$600) in headoffset festgesetzt, wobei diese
............. Bilddaten dann mit updateSpriteHead übertragen werden. In der Grafikdatei für die Köpfe, tete.pic, liegt
............. der Kopf für die erste Figur bei $600.
.......... Anschließend wird, unabhängig vom Timer, bei jedem Durchlauf dieser SR die SR MajSprite aufgerufen.
..........
.......... (Ab hier (d. h. Label followStepMenü) erfolgt, sicherheitshalber, wieder eine Zeile-für-Zeile-Betrachtung.
..........
.......... Im nächsten Schritt (ab Label HandleJoy) wird geprüft, ob der Controller bereit ist; ist dies der Fall, werden
.......... die Daten ausgelesen und geprüft, ob der Rechts-Button gedrückt wird. Wenn, dann wird geprüft, ob tempB = 2 ist.
.......... tempB enthält den Wert des aktuell ausgewählten Spielers (null bis zwei). Ist tempB = 2, wird dasselbe gemacht,
.......... wie wenn Rechts nicht gedrückt wird (ab Label noRight).
.......... (ab Label updateTempB) Wenn rechts gedrückt wird und tempB < 2 ist, wird tempB um eins erhöht und die SR
.......... changeMapSelection aufgerufen, um das Fenster für die nächste Spielfigur darstellen zu lassen.
.......... (ab Label noRight) Wenn rechts nicht gedrückt wird, wird im selben Verfahren wie oben geprüft, ob der Links-
.......... Knopf gedrückt wurde. Wenn nicht, geht es weiter bei noLeft. Ansonsten wird tempB um eins verringert, wenn es
.......... nicht sowieso schon null ist, und changeMapSelection aufgerufen, um ein anderes Fenster auf den Bildschirm zu
.......... bringen.
.......... (ab Label noLeft) Nun wird geprüft, ob Start gedrückt wird. Wenn ja, geht es weiter bei FinSelection. Ansonsten
.......... wird mittels Variables XPos der karierte Background gescrollt und am Ende der loopSelection von vorne begonnen.
.......... (ab Label FinSelection) Der Bildschirm wird abgedunkelt und die Subroutine verlassen.
..... SR initplayervalue
.......... (Mega Krito ingame; Hugo in den Kommentaren)
.......... Wenn "player" den Wert "0" besitzt, wird "argent" (Geld) auf 0 und "playerlife" auf 2 gesetzt.
.......... Nächster Sprungpunkt: initplayer2
.......... (Mega Kikoo ingame; Tristan in den Kommentaren)
.......... Wenn "player" den Wert "1" besitzt, wird "argent" (Geld) auf 10 und "playerlife" auf 3 gesetzt.
.......... Nächster Sprungpunkt: initplayer3
.......... (Mega Mame in Game; Mae in den Kommentaren)
.......... Wenn "player" den Wert "1" besitzt, wird "argent" (Geld) auf 10 und "playerlife" auf 5 gesetzt.
..... SR changeMapSelection
.......... SR, die den Bildwechsel zwischen den Bildschirmen der unterschiedlichen Spielfiguren herbeiführt
..........
.......... Der Bildschirm wird langsam abgedunkelt (via loopToDark).
.......... Es wird geprüft, ob tempB = 0 ist, wenn nicht, wird zu Label test2 (für den zweiten Test) gesprungen.
.......... Bei test2 wird geprüft, ob tempB = 1 ist, wenn nicht, ist es logischerweise 2, in diesem Falle geht es bei
.......... Label test3 weiter.
.......... Das Handling dieser drei Fälle ist im Prinzip dasselbe, nur die Werte unterscheiden sich. Es wird zunächst
.......... die Tilemap per CopyVRAM-Makro in den VRAM kopiert. Als nächstes werden die Sprite-Koordinaten mit
.......... updateSprXY neu gesetzt. Mittels changeColor werden zwei Farben geändert (die für die Rüstungsteile z. B.
.......... an den Knien und Unterarmen). HeadOffset wird geändert, dass beim nächsten "updateSpriteHead" andere
.......... Grafikdaten für den Protagonisten-Kopf in die dafür vorgesehene VRAM-Adresse geladen werden.
.......... Es wird der SPR1XSpeed auf #02 gesetzt und eine Nummer in "player" gespeichert, die der jeweiligen
.......... Spielerfigur entspricht (01 bis 03).
.......... Danach wird zum Abschluss (ab Label endSelection) MajSprite aufgerufen und mit updateSpriteHead
.......... noch die richtige Grafik in den VRAM geladen, danach mit loopToLight der Bildschirm wieder an
.......... gemacht und die SR beendet.
..... SR LoopMenuLevel
.......... (Hat große Ähnlichkeit mit der SR intro)
.......... Stellt den Level-Wahl-Bildschirm da. BG2 enthält ein Kachelmuster, das sich kontinuierlich
.......... bewegt; BG1 enthält Schrift ("Level 0"), wobei man mit der Hoch- und Runter-Taste zwischen
.......... Level 0, 1 und 2 wählen kann.
.......... LoopMenuLevel ist in vielen Punkten Identisch mit LoopMenuSelection am Anfang der menuselection.asm.
.......... Der größte Unterschied ist, dass sich in LoopMenuLevel viele Einstellungen, die mit Sprites zu tun
.......... haben, auskommentiert sind. LoopMenuLevel wurde auf der Grundlage von LoopMenuSelection geschrieben
.......... und alles, was daraus nicht benötigt wurde, wie z. B. die Sprites, wurde so einfach deaktiviert.
..........
.......... Bildschirm aus (Force VBlank)
.......... Leert den VRAM.
.......... Bildschirmeinstellungen (mit einigen unnötigen Einstellungen)
.......... Per CopyVRAM-SR werden die Tilemaps für die beiden BGs an die entsprechenden
.......... Positionen im VRAM übertragen.
.......... Alles zwischen dem ";Load Palette" und "bne LoadPalLevel" dient dem
.......... Übertragen der Palette in den CGRAM.
.......... Alles danach bis zum "bne LoadPalSelectionSprite" dient dem Leeren des Sprite-
.......... speichers (OAM) und dem Befüllen mit einer Palette - alles auskommentiert, da
.......... beim Level-Wahl-Bildschirm keine Sprites verwandt werden.
.......... Danach werden die Tiles für BG1 und BG2 per CopyVRAM-Makro übertragen. Beide
.......... BGs benutzen dasselbe Tileset, was auch Sinn macht, da beide nicht viele Tiles
.......... enthalten.
.......... Bildschrim wird weiterhin eingestellt (Sprites, BG2 und BG1 werden dargestellt: $212C)
.......... Es werden *wieder einmal* VBlank und JoyPad aktiviert (EnableVBlankWithJoypad).
.......... Die Register $210D bis $2110 werden auf null gesetzt - diese Register sind für die Verschiebung
.......... von BG1 und BG2 zuständig.
.......... Die Variable XPos wird geleert, genauso wie "tempB", die laut Kommentar als Container für
.......... das gewählte Element (Level) fungiert (was nicht stimmt; es wird hier "level" genutzt; "tembB"
.......... wird in LoopMenuSelection genutzt).
.......... (Auskommentiert sind einige Einstellungen der Sprite-Einstellungen)
.......... Es wird der Bildschirm von komplett dunkel auf komplett hell hochgedreht (von "jsr
.......... loopToLight" bis "sta $2100")
.......... "cli" ermöglicht Interrupts. Ich halte es hier für unnötig, lasse mich aber gern eines
.......... Besseren belehren.
.......... Es wird noch eine Grafikeinstellung vorgenommen, die was mit dem Aufbau von Tilemaps zu
.......... tun hat (#$00 --> $2115), danach geht es in einen etwas komplizierten Loop.
.......... loopLevel:
.......... Springt zur SR showLevel (steht ganz am Ende der Datei)
.......... Erhöht den Inhalt von "Timer", "Timer" läuft konstant von #00 bis #05 (bei #06 wird Timer
.......... auf #00 resettet).
.......... Das Register mit den Controller-Daten wird ausgelesen ($4219) und geprüft, ob "Hoch" gedrückt wurde.
.......... Wenn, dann wird geprüft, ob keyflag = 0 ist (= ob gerade "Hoch" gedrückt wurde, oder ob es
.......... gehalten wird, das wäre dann keyflag = 1). Wenn nicht, dann wird nichts am Level geändert
.......... (das bedeutet die Jump-Mark "NothingLevel").
.......... Nun wird die Variable level geladen und geprüft. Wenn sie "2" ist, kann sie nicht weiter
.......... erhöht werden ("beq NothingLevel"), ansonsten wird die level um eins erhöht und der
.......... keyflag auf 1 gesetzt. Danach wird die Prüfung, ob "runter" gedrückt wurde übersprungen
.......... und direkt dasselbe gemacht, als wenn das Level nicht geändert wird (--> NothingLevel).
.......... Die "Runter"-Prüfung funktioniert genauso wie der Teil vor: Verringere level, wenn level
.......... nicht 0 ist, und wenn der keyflag nicht 1 ist. Ansonsten gehe direkt zu "NothingLevel",
.......... andernfalls anschließend.
.......... Bei "NoDown:" wird geprüft, ob Start gedrückt wird. Wenn ja, wird zu FinLevel gesprungen,
.......... der Bildschirm mit LoopToDark gemacht und diese Subroutine beendet.
.......... Sind die Button-Prüfungen (Hoch, Runter, Start) erfolglos geblieben, wird jetzt mit
.......... "stz keyflag" der keyflag auf null gesetzt. Danach laufen alle Fäden wieder zusammen, die
.......... bei der Button-Prüfung auseinanderliefen. Das NothingLevel-Label wird gesetzt.
.......... Danach wird mittels der Variable XPos der Kachelhintergrund eins weitergeschoben und
.......... wieder zum Anfang von loopLevel gesprungen.
..... SR showLevel
.......... "showLevel" prüft den Inhalt der Variable "level" und verändert die den entsprechenden
.......... Tile, sodass auf dem Bildschirm "Level 0", "Level 1" oder "Level 2" steht.
sprite.asm
..... SR mainSpriteAnimation
.......... Eine Subroutine, die in Abhängigkeit vom Inhalt der Variablen SPR1ACTION und SPR1STATUS
.......... entscheidet, welche Grafikdaten in den VRAM geschoben werden müssen. Das heißt, in dieser
.......... Subroutine werden diese beiden Status-Variablen in die entsprechenden Grafiken umgesetzt.
.......... Es sei darauf hingewiesen, dass Dieudunet nicht alle kompletten Animationsschritte seiner
.......... Figuren in den VRAM lädt und dann dem jeweiligen Sprite im OAM eine neue Grafik zuweißt,
.......... sondern dem Sprite eine "feste Adresse für seine Grafik" im OAM zugewiesen hat.
.......... Pro: Er spart Platz im VRAM, weil er nicht jeden der Animationsschritte dort "vorrätig" hat.
.......... Contra: Er muss jedes Mal #$200 Byte Grafikdaten updaten, statt #$4 Byte im OAM. Größere
.......... CPU-Belastung.
..........
.......... SPR1ACTION = %1xxxxxxx
............. Es wird die Adresse von spr1StandW in spr1StandAdress gespeichert.
............. Es wird die Adresse von spr1RunW in spr1RunAdress gespeichert.
.......... SPR1ACTION = %0xxxxxxx (ab Label "NoSpecialAction")
............. Es wird die Adresse von spr1Stand in spr1StandAdress gespeichert.
............. Es wird die Adresse von spr1Run in spr1RunAdress gespeichert.
............... Als Hinweis: Die beiden Dateien mit dem W am Ende werden im Spiel selbst für die Stand- bzw.
............... Laufanimation genutzt, die beiden Dateien ohne W nur im Menü.
.......... SPR1ACTION <> %x00xxxxx (ab Label "specialOK")
............. Es wird die Adresse der "hitby"-Grafik in "spr1Adress" gespeichert (und dann beim nächsten
............. Aufruf von "updateSpriteAnimation" hochgeladen).
............. Als nächstes wird der Inhalt von "sprite1Offset" von #0 auf #512 (#$200) gewechselt (oder andersrum)
............. Dieser neu berechnete Wert wird in "sprite1Offset" abgespeichert.
............. Anschließend wird dieser Wert mit "spr1Adress" addiert und in "spr1Adress" gespeichert.
............. Das bedeutet, dass jeweilswechselnd die Adresse des ersten und zweiten Sprites in der Variable steht.
.......... SPR1ACTION = %x00xxx00 (ab Label "continueUpdate")
............. Es wird geprüft, ob "SPR1STATUS" auf null steht (das "AND #$FF" kann man sich doch sparen, oder?)
............. Das bedeutet, wenn in dieser Variable ein anderer Wert als null ist, läuft noch eine andere
............. Animation.
.............
............. SPR1STATUS = %00000000
............... Wenn "SPR1STATUS" auf null steht, wird der Inhalt von "spr1StandAdress" in "spr1Adress"
............... gespeichert (also wird mit dem nächsten "updateSpriteAnimation" eine Grafik aus der jeweiligen
............... Datei in den Speicher geschoben, die zu Beginn dieser Subroutine in "spr1StandAdress" gespeichert
............... wurde).
............... Es wird #0512 (#$200) in spr1Offset gespeichert, was anscheinend der Standardwert ist.
............... Anschließend wird dieser Wert auf den Adresswert in "spr1Adress" gerechnet und dort wieder
............... abgespeichert (scheinbar soll der erste Sprite der Datei [die ich mal auf #$200 Byte Größe
............... schätze] grundsätzlich übersprungen werden, vermutlich weil das leer ist?).
............... Danach springt er zum Ende der SR (Label "spritemainend", direkt vorm "RTS").
............. SPR1STATUS = %xxx0xxxx (ab Label "MoveSpriteMain")
............... Es wird die Adresse der Grafikdaten für die Laufanimation in "spr1RunAdress" in "spr1Adress"
............... gespeichert. Der Wert in "spr1Offset" wird um #0512 ($200) erhöht. Ist der Wert in "spr1Offset"
............... #5120 (#$1400), wird er wieder auf 0 gesetzt.
............... Es wird jetzt der Offset auf den Wert in "spr1Adress" draufaddiert und das wieder in "spr1Adress"
............... gespeichert. Danach wird die SR beendet (Jump to Label "spritemainend").
............. SPR1STATUS = %xxx1xxxx (ab Label "MoveSpriteJumpUpMain") und
............. SPR1ACTION = %xxxxxx01 (ab Label "MoveSpriteJumpUpMain")
............... Wie in der Verfahrensweise, die schon mehrfach in dieser SR angewandt wird, wird die
............... Adresse des dritten Sprites in der Grafikdatei mit den Stand- und Sprungsprites (#1024 = $#0400)
............... in "spr1Adress" gespeichert und der "spr1Offset"-Wert auf erwähnte #1024 gesetzt.
............... Der dritte Sprite ist offensichtlich der Sprite für den Aufwärtssprung.
............. SPR1STATUS = %xxx1xxxx (ab Label "MoveSpriteJumpDownMain") und
............. SPR1ACTION <> %xxxxxx01 (ab Label "MoveSpriteJumpDownMain")
............... Wie in der Verfahrensweise, die schon mehrfach in dieser SR angewandt wird, wird die
............... Adresse des vierten Sprites in der Grafikdatei mit den Stand- und Sprungsprites (#1536 = $#0600)
............... in "spr1Adress" gespeichert und der "spr1Offset"-Wert auf erwähnte #1536 gesetzt.
............... Der vierte Sprite ist offensichtlich der Sprite für den Fall/"Abwärtssprung".
..... SR updateSpriteHead
.......... Addiert die Variable headOffset mit der Adresse der Grafikdaten tete (die Daten für die
.......... übergroßen Köpfe) und speichert Sie in Temp.
.......... Danach werden vier Mal 128 Byte in den VRAM übertragen, begonnen werden mit den Daten,
.......... deren Adresse in "Temp" steht. Übertragen werden in die Positionen $6040, $6140, $6240 und
.......... $6340. Wichtig: Das war gerade auch ein Verständnisfehler von mir, darum weise ich darauf hin:
.......... 128 Byte sind $80 Byte. Es werden aber NICHT folglich z. B. die Positionen $6040 bis $60A0 beschrieben,
.......... sondern nur $6040 bis $604F, denn jedes Register ($6040, $6041...) kann jeweils 8 Byte aufnehmen, also
.......... braucht man für 128 Byte (128 = $80 ... $80 : $8 = $10 ... $10 = 16) nur 16 Register mit je einem Byte
.......... Speicherplatz, um diese Daten abzuspeichern.
..... SR updateSpriteAnimation
.......... Schiebt vier Mal 128 Byte in den VRAM, gemäß dem Startwert, der in der Variable "spr1Adress"
.......... steht. Der Wert in "spr1Adress" ist nach Aufruf dieser SR um $240 höher als vorher.
..... SR updateWeapon
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR updateWeaponAnimation
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR InitSpriteAndPalette
.......... Die Größe der Sprites und deren Ablageposition ab $C000 eingestellt.
.......... Letzteres interpretiere ich so. Das muss geprüft werden, ob das stimmt.
.......... Es werden die Adressregister für CGRAM und OAM auf die Anfangspositionen für Spritedaten
.......... gesetzt (was beim CGRAM #128 und beim OAM #00 ist).
.......... Danach werden per Schleife Daten übertragen:
............. "palette" (in der Schleife "palette2")
............. "foe1Pal" (in der Schleife "pal")
............. "Tir1Pal" (in der Schleife "paltir")
............. "ghostpal" (in der Schleife "ghosttir")
............. "boss1Pal" (in der Schleife "bosspal")
............. "biosparkpal" (in der Schleife "biosparkPal")
.......... Augenscheinlich werden hier keine Spritedaten übertragen.
.......... Anschließend wird die Variable "priority" auf #$20 gesetzt und die SR beendet.
..... SR updateSXSprite
.......... Ich bin hier noch nicht fertig gewesen!!!
..... MACRO pushSXfromX (b)
.......... Ich bin hier noch nicht fertig gewesen!!!
..... MACRO pushXfromX (b)
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR forSXinitXY
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR getSXinitXY
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR initPaletteFoe
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR MajSprite
.......... Updated die Einträge der ersten beiden Sprites im OAM - Sprite 0 ist der Kopf, Sprite 1
.......... ist der Körper -, wenn sich die Positionen oder die horizontale Spiegelung (links/rechts)
.......... ändern müssen.
..........
.......... Mit dem "#%00001010" in dem OAMTemp+512 schreibt er in die "High Table" des OAM für die ersten
.......... beiden Sprites, dass diese "groß" sind, in diesem Fall 32x32 Pixel statt normal 16x16 Pixel.
.......... Als nächstes werden die Daten des Kopfes geupdated:
.......... Die X-Position wird SPR1XPos entnommen und in den ersten Byte der "Low Table" gespeichert.
.......... Die Y-Position wird mit 4 addiert und dann in den zweiten Byte der "Low Table" gespeichert;
.......... die +4 sind augenscheinlich der Versatz, mit dem der Kopf-Sprite über den Rumpf-Sprite überlappt,
.......... damit es so aussieht, dass der Kopf auf Hals und Schultern sitzt, und nicht unverbunden darüber
.......... schwebt.
.......... Im dritten Byte der "Low Table" wird #%00000100 geschrieben, das heißt, Grafik Nummer 4 soll
.......... für den Sprite genutzt werden, was nicht verwundert, da in updateSpriteHead an diesen Platz die
.......... Kopf-Grafikdaten gespeichert werden (was die vier in der Adresse $6040 und folgende bedeutet).
.......... Der Wert für den vierten und letzten Byte wird der Variable priority entnommen.
..........
.......... Anschließend wird in priority geprüft, ob Bit 6 gesetzt ist. Wenn priority in den vierten Byte
.......... eines OAM-Datensatzes eingesetzt wird, entscheidet dies über eine horizontale
.......... Spiegelung, also bedeutet diese Prüfung hier, ob so gesagt werden soll, dass die
.......... Spielfigur nach links guckt.
..........
.......... Abhängig von der Blickrichtung wird auf SPR1XPos 3 addiert (rechts) oder subtrahiert (links).
.......... Dies erfolgt, um den Körper richtig "unter den Kopf" zu positionieren. Danach wird SPR1XPos
.......... im OAMTemp gespeichert.
.......... Für den zweiten Byte des Körper-Sprite-Datensatzes zu SPR1YPos 24 hinzuaddiert. Da hier wiederum
.......... nicht 32, sondern 24 addiert wird, bedeutet das, dass der Körpersprite noch einmal 8 Pixel "nach
.......... oben" geschoben wird, um direkt unter/am dem Kopfsprite zu sein.
.......... Der dritte Byte wird der Variable sprite entnommen, der vierte wieder priority, und damit endet
.......... die Subroutine.
..... MACRO initbonus
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR realY
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR checkIfMinus
.......... Funktion ohne Wert. Die Indexregister werden auf den Stack verschoben und wieder
.......... heruntergezogen. Vermutlich war mal früher dazwischen etwas passiert.
..... SR destroyBonusAndUpdateMoney
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR destroySprMethod
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR bonusSpriteAnimation
.......... Ich bin hier noch nicht fertig gewesen!!!
..... MACRO UpdateSprite
.......... Ich bin hier noch nicht fertig gewesen!!!
..... MACRO ClearOAM
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR updateSpriteTir1
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR CopyTir1
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR tir1AnimBeginLeftMove
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR updateAnimationTir1
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR checkIfFallAndDied
.......... Ich bin hier noch nicht fertig gewesen!!!
stock.asm
..... SR controlUpdateFoe
.......... Ich bin hier noch nicht fertig gewesen!!!
textdrawing.asm
..... MACRO writeValue
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR rwvalue
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR resfreshLife
.......... Ich bin hier noch nicht fertig gewesen!!!
..... valueReference1To10
.......... Direkte Word-Definition: Eine Zahlenfolge von #$2008 bis $202A, immer in Zweierschritten erhöht.
.......... Ich bin hier noch nicht fertig gewesen!!!
..... zerovalue
.......... Direkte Word-Definition: #$2008
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR resfreshLife
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR push2119followingBG
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR incTimeandWrite
.......... Ich bin hier noch nicht fertig gewesen!!!
..... SR writeText
.......... Ich bin hier noch nicht fertig gewesen!!!
ToolBox.asm
..... Kommentar Aufbau des Statusregisters (Flags)
..... MACRO registerATo16bit
.......... Enthält nur ein einziges "REP #$30". ô_o
.......... Beim zweiten Gucken ist das aber doch interessant. "REP #$30" setzt nämlich
.......... gleichzeitig auch X und Y auf 16 bit zurück. Lässt mich vermuten: Der Programmierer
.......... kam wohl niemals in die Verlegenheit, X und Y auf 8 bit setzen zu müssen.
..... MACRO pushToColor (b, b)
.......... SEP #$20 (8 bit Akkumulator)
.......... Nimm den ersten bytegroßen Wert, der dir übergeben wurde, speicher ihn in "darkValue".
.......... Nimm den zweiten bytegroßen Wert, der dir übergeben wurde, speicher ihn in "tempB".
.......... Rücke vor bis auf SR pushToColor.
..... SR pushToColor
.......... Verringert die Bildschirmhelligkeit von "darkvalue" auf "tempB":
.......... "darkValue" wird genommen und per Schleife so oft in $2100 gespeichert (Register
.......... für Bildschirmhelligkeit) und um eins verringert, bis der Wert "tempB" entspricht.
..... SR pushToDark
.......... Verringert die Bildschirmhelligkeit von 100% auf 0%:
.......... "darkValue" wird auf #$0F setzt (Achtung! Er schreibt hier in Dezimal-, nicht in
.......... Hexadezimalzahlen, also: #15). In einer Schleife wird der Wert um eins verringert
.......... und wieder in $2100 (Register für Bildschirmhelligkeit) gespeichert, bis
.......... "darkValue" = 0 ist.
..... SR pushToLight
.......... Verringert die Bildschirmhelligkeit von 0% auf 100%:
.......... Wie pushToDark, nur umgedreht.
..... MACRO registerATo8Bit
.......... "sep #20"
..... MACRO clearWord (w)
.......... Löscht den Byte, dessen Adresse man übergibt, und den daneben.
..... MACRO CopyVRAM (w, label, w)
.......... Checker-Erklärung: VRAM-DMA, über Channel 0 (Ziel: $2118/9)
.......... Non-Checker-Erklärung: Makro, dass schnell große Mengen an Daten an den VRAM (Grafikspeicher)
.......... überträgt. Dieses Makro dient zum Übertragen von Tilemaps, Paletten oder Grafiken (für
.......... Tiles oder Sprites).
.......... Argumente:
............. (1) Ziel im VRAM ($2116)
............. (2) Adresse der zu übertragenen Daten
............. (3) Anzahl der Bytes, die zu übertragen sind
..... MACRO CopySprVRAM (w, w-variable, label(?), w)
.......... Wie CopyVRAM, aber andere Argumente
.......... Argumente:
............. (1) Ziel im VRAM ($2116)
............. (2) Adresse der zu übertragenen Daten (Offset/ "Versatz" wird übernommen)
............. (3) Adresse der zu übertragenden Daten (Bank wird übernommen)
............. (4) Anzahl der Bytes, die zu übertragen sind
.......... Hinweis: Dieses Makro unterscheidet sich in einem Punkt von CopyVRAM, dass
.......... der Versatz (engl. Offset) und die Bankadresse von zwei unterschiedlichen
.......... Argumenten übernommen werden.
.......... Dabei ist zu beachten: CopyVRAM nimmt bei der Offset-Adresse ein Label (#\2), CopySprVRAM
.......... nimmt den Inhalt einer ihm übergebenen Variable (\2).
.......... Ein Checker möge bitte prüfen, ob ich das hier falsch herum verstanden habe
..... MACRO addToPtrDirect (w, w)
.......... Nimm die Adresse von Argument zwei, addiere die Adresse von Argument eins, und speicher
.......... das Ergebnis in Argument eins. Logischerweise müssen Argument eins eine Variable/
.......... Speicheradresse sein.
..... MACRO addToPtr (w, w)
.......... Nimm die Adresse von Argument eins, addiere den Wert von Argument zwei, und speicher das
.......... Ergebnis in Argument eins. Hier muss nur Argument eins eine Variable/Speicheradresse
.......... sein.
..... MACRO CopyMapVRAM (w, w-variable, b-variable, w)
.......... Wie zuvor, jedoch sind sowohl Bank als auch Offset in einer Variable gespeichert.
..... SR(?) ClearVRAM
.......... Würde mich wundern, wenn das funktioniert, weil nach ClearVRAM ein Semikolon steht.
.......... Gehört dort nicht ein Doppelpunkt hin?
.......... ClearVRAM überschreibt in einer Schleife den gesamten Inhalt im VRAM mit #$0000
..... MACRO EnableVBlankWithJoypad
.......... Checker-Erklärung: $4200 = #$81. Mehr nicht.
.......... Non-Checker-Erklärung: Schreibt in das Interrupt-Enable-Register ($4200), dass es
.......... Interrupts (Unterbrechungen) durch die vertikale Austastlücke (VBlank / NMI)
.......... und durch das Drücken von Buttons auf Controllern zulassen soll.
.......... Ersteres schafft die Möglichkeit, Animationen ablaufen zu lassen, zweiteres
.......... ermöglicht dem Programm, auf Befehle vom Controller zu reagieren.
.......... Das ist für Spiele so essenziell, wie es sich anhört.
..... SR clearPalette
.......... (Schon wieder dieses Gegurke mit dem Semikolon, wo ich einen Doppelpunkt erwartet
.......... hätte... was soll das!?)
.......... Soll die Palette leeren. Verstehe ich aber nicht wirklich.
.......... 1) Wenn ich LDA.l 0, x mache, wobei X gleichzeitig als Counter genutzt wird,
.......... lädt er nach meinem Verständnis auf der aktuellen Bank aus den Registern $0000, $0001 etc.
.......... die Werte und packt sie in den CGRAM als Farben... das wiederum trifft nicht das, was ich
.......... unter "clearPalette" verstehen würde. Der nächste Punkt: Warum läuft der Counter bis
.......... #$64 (= hundert)? Benutzt er maximal 100 Farben? Oder ist es schlichtweg gurkig
.......... programmiert (wovon ich nicht ausgehe)?
variable.asm
..... Variablendefinition
.......... Alle Spielwerte werden ab $C8(00) definiert.
.......... Anschließend werden die Adressen für den temporären Speicherplatz für die Spritedaten
.......... definiert, auf Bank $7E (das ist IIRC der RAM), bei $1600 und bei $1801 (und damit müsste
.......... $1800 doch eigentlich leer sein und bleiben, oder?).
.......... Als drittes werden die Namen für die Controllertasten definiert.
.......... Danach kommt eine Definition der Register der Register zur Kommunikation mit dem SPC700.
.......... Als letztes werdeen "XY_8BIT" und "A_8BIT" definiert, ganz offensichtlich sind die
.......... angedacht, das wechseln zwischen 8bit- und 16bit-Registern zu vereinfachen (SEP/REP).
..... SR emptyVariable:
.......... Entsprechend dem Namen werden viele der Spielwert-Variablen geleert.
.......... Ausnahmen:
.......... SPR1ACTION --- wird gesetzt auf #$02: "; Falling"
.......... SPR1YSpeed --- wird gesetzt auf #$01
.......... headOffset --- wird gesetzt auf #512 (#$200)
.......... jumpCount --- wird gesetzt auf #19 (#$13): "; falling index"
.......... bossLife --- wird gesetzt auf #$03
vblank.asm
..... SR VBlank
.......... Die Subroutine, die abläuft, wenn das eine Bildschirmbild fertig dargestellt wurde
.......... und das nächste Bildschirmbild noch nicht begonnen wurde, dargestellt zu werden.
.......... Maßgeblich werden die Registerinhalte auf den Stack geschoben, die Subroutine "UpdateSprite"
.......... aufgerufen und anschließend die Register wieder vom Stack gezogen.
/spc/loadspc.asm
.......... Als allgemeiner Kommentar:
.......... Ich werde diese Datei nicht kommentieren, weil das für mich zu Hardcore ist. Tatsächlich ist
.......... der Inhalt dieser Datei, wie der Kommentar auch anzeigt, de facto der SPC Player von Joey Lee,
.......... den er unter Public Domain gestellt hat und der u. a. auch hier erklärt wird.
.......... Glaube ich.
.......... Gelesen habe ich es bisher noch nicht.
.......... Dieses Programm ist BTW auch mit Sicherheit der Grund, weshalb das Spiel nur Musik und keine
.......... Soundeffekte hat. (Bei dem Kram, der jetzt kommt, bin ich mir ziemlich sicher. Wenn jemand es
.......... besser weiß, mag er das bitte korrigieren).
.......... Schon mal aufgefallen, dass SPC-Dateien mit Vorliebe 64kb groß sind? SPC-Dateien sind nämlich
.......... "Gipsabdrücke" des RAM vom SPC700. Das heißt: Es wurde geguckt, was im Arbeitsspeicher des
.......... Soundchips liegt, wenn ein Lied abgespielt wird, und dann *alles* rüberkopiert. Selbiges
.......... Verfahren rückwärts ermöglicht z. B. auch den SPC-Player (auf vergleichsweise einfache Art und
.......... Weise). Aber eben auch nicht mehr.
.......... Die SPC-Dateien werden komplett von Anfang bis Ende in den RAM geschmissen und selbigem wird
.......... gesagt: "Mach mal", und er spielt ab. Das ist jetzt stark vereinfacht - wenn es wirklich so
.......... einfach wäre, wäre die loadspc.asm wesentlich kleiner.
.......... In jedem Fall kann man, wenn man eine der SPC-Dateien mit einem Hexeditor öffnet, dort gegen
.......... Ende weite Teile sehen, die nur mit $00 oder $FF gefüllt sind. Und man muss kein Programmierer
.......... sein, um zu wissen, dass das wohl kaum Musikdaten sind. Vielmehr sind es leere Stellen, wo man
.......... theoretisch andere Daten einfügen könnte. Aber dazu müsste man einen genaueren Überblick haben,
.......... wo diese freien Stellen sind, und wo bereits Musikdaten liegen. Und dazu braucht man ein
.......... wesentlich größeres Verständnis vom SPC700 und dem Umgang damit, als ich habe.
.......... Ich wiederhole mich: Ich will dieses Ding nicht schlecht machen, es ist besser als alles, was ich
.......... bisher zustande gebracht habe. Allerdings ist der Code, mit dem die Musik eingefügt wurde, eine
.......... Sackgasse, und darauf möchte ich hinweisen. Ich denke nicht, dass man "mal eben" es noch einfügen
.......... könnte, dass nebenbei Soundeffekte abgespielt werden. Ich schätze eher, dass man am effektivsten
.......... dahin kommt, wenn man die Fütterung des SPC700 komplett neu schriebe. Joe Lees SPC-Player
.......... umzuschreiben würde vermutlich mindestens genauso viel Aufwand bedeuten. *Newbie-Einschätzung*
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Benutzeravatar
lytron
Code Bro
Code Bro
Beiträge: 2664
Registriert: 12. August 2012, 20:18
+Positive Tradingpoints+: 12 von 12
Wohnort: ハノーファー区
Kontaktdaten:

Re: MegaFamilyBros

Beitrag von lytron » 11. Februar 2013, 21:07

~~~

Ablauf des Programms
SNES_Init (natürlich zuerst)
SR intro --- Der "Team Neo"-Screen
SR title --- Das schwarz-weiße Titelbild
SR LoopMenuLevel --- Der Level-Wahl-Bildschirm. BG1 enthält den Schriftzug "Level 0"/"1"/"2", BG2 ist ein Kachelhintergrund, der sich konstant bewegt, keine sichtbaren Sprites, Wahl des Levels mit Hoch- und Runter-Taste
SR InitSpriteAndPalette --- Zwei, drei Einstellungen und einige Paletten, die übertragen werden.
SR LoopMenuSelection --- Das Menü für die Charakterauswahl.
..... SR mainSpriteAnimation --- Weist an, welche Grafik für den Körper-Sprite genutzt werden muss,
..... je nachdem, was in zwei bestimmten Variablen gespeichert steht. Wird innerhalb von LoopMenu-
..... Selection aufgerufen.
..... updateSpriteHead --- Wird innerhalb von LoopMenuSelection aufgerufen. Ändert die Grafik des
..... Kopf-Sprites abhänigig vom Wert in headOffset.
..... updateSpriteAnimation --- Wird innerhalb von LoopMenuSelection aufgerufen. Ändert die Grafik
..... des Körpers entsprechend dem Inhalt der Variable Spr1Adress. Diese wird in mainSpriteAnimation
..... angepasst.
..... MajSprite --- Wird innerhalb von LoopMenuSelection aufgerufen. Update der Daten im OAMTemp;
..... mit MajSprite werden auch die X- und Y-Positionen der beiden Spielfiguren-Sprites (Kopf und
..... Körper) geupdatet.

~~~

Nutzung der Variablen
argent (b)
..... frz. für "Geld".
..... Wird gesetzt in "LoopMenuSelection". #$00
BG1XOFFSET (w)
..... ?
..... Wird gesetzt in "InitBG1". #$7414
BG2XOFFSET (w)
..... ?
..... Wird gesetzt in "InitBG1". #$7814
bossLife (b)
..... Die Lebensenergie des Bosses(?)
..... Wird gesetzt in "emptyVariable". #$03
darkValue (b)
..... Variable für allerlei Makros und Subroutinen, die mit der Bildschirmhelligkeit
..... zu tun haben (siehe Datei ToolBox.asm):
..... pushToColor, pushToDark, pushToLight
headOffset (w)
..... Die drei großen Köpfe der unterschiedlichen Spielfiguren sind in einer einzigen Datei
..... hintereinander gespeichert (tete.pic). Demnach wird in headOffset, je nach der Wahl der
..... Spielfigur, der Versatzwert für tete.pic gespeichert, ab wo in tete.pic die Daten für den Kopf
..... der ausgewählten Spielfigur befinden. Jeder Kopf ist $200 Byte groß, und die Köpfe der spielbaren
..... Figuren befinden sich in den letzten drei Viertel der Datei; ich habe ein bisschen herumgespielt,
..... um rauszukriegen, was in den ersten $200 Byte liegt; habe es nicht wirklich herausgekriegt, aber
..... habe nicht wirklich viel Aufwand darauf betrieben.
..... Wird gesetzt in "LoopMenuSelection". #$0600 (#1536)
..... Wird gesetzt in "emptyVariable". #$0200 (#512)
jumpCount (b)
..... ?
..... Wird gesetzt in "emptyVariable". #$19 (#$13)
keyflag (b)
..... Wird genutzt, um zu speichern, ob ein Button gerade gedrückt wird, oder ob er gehalten wird.
..... Wird genutzt in "LoopMenuSelection" für die Level-Auswahl (Hoch/Runter).
level (b)
..... Das gewählte Level. Liegt zwischen #00 und #02.
..... Wird gesetzt in "LoopMenuLevel" im "loopLevel".
map0 (w)
..... Container der Adresse des Tilesets des Levels für BG1.
..... Wird gesetzt in "levelMatch".
map0Bank (b)
..... Container der Bank des Tilesets des Levels für BG1.
..... Wird gesetzt in "levelMatch".
map1 (w)
..... Container der Adresse des Tilesets des Levels für BG2.
..... Wird gesetzt in "levelMatch".
map1Bank (b)
..... Container der Bank des Tilesets des Levels für BG2.
..... Wird gesetzt in "levelMatch".
player (b)
..... ?
..... Wird gesetzt in "LoopMenuSelection". #$01
playerlife (b)
..... Anzahl Leben.
..... Wird gesetzt in "LoopMenuSelection". #$02
priority (b)
..... Wird in der SR MajSprite genutzt, um den vierten Byte der Protagonisten-Sprites zu setzen.
..... Da priority in InitSpriteAndPalette mit #$20 belegt wird, heißt das, die Sprites liegen
..... automatisch auf der zweithöchsten Priorität.
..... priority wird auch genutzt, um zu sichern, in welche Richtung die Spielfigur schaut (Bit 6).
..... priority wird als vierter Byte eines OAM-Low-Table-Datensatzes genutzt, und das bedeutet,
..... Bit 6 entscheidet über die horizontale Spiegelung.
.....
..... Wird gesetzt in "InitSpriteAndPalette". #$20
SPR1ACTION (b)
..... Offizielle Erklärung:
....... xxxxxxba : b: falling , a: jumping , 000000000 = waiting
....... ba:11 : on top of the air
..... Wird gesetzt in "LoopMenuSelection". #$00
..... Wird gesetzt in "emptyVariable". #$02 ("Falling")
spr1Adress (w)
..... Dient in "updateSpriteAnimation" als Wert-Träger, wo der Beginn der zu übertragenden Sprite-
..... Daten ist.
..... Wird verändert in "updateSpriteAnimation" um #$240
..... Wird verändert in "mainSpriteAnimation": Wenn SPR1ACTION <> #%x00xxxxx ist, dann wird spr1Adress
..... auf den Anfang der Adresse der Grafik "hitby" gesetzt.
spr1Offset (w)
.....
SPR1STATUS (b)
..... Eine Art Flagregister für den Status der Spielfigur.
..... Byte 4 wird gesetzt beim Springen.
..... Wird gesetzt in "LoopMenuSelection". #$02
SPR1XPos (w)
..... Die x-Position der Spielfigur. Es handelt sich um den linken oberen Punkt der Spielfigur.
..... Verändert werden x- und y-Position (in SPR1XPos und SPR1YPos) mit dem Macro updateSprXY.
..... In der Subroutine MajSprite werden diese dann weiterverarbeitet und in den OAMTemp gespeichert.
..... Wird gesetzt in "InitBG1". #$0070 (#112)
SPR1YPos (w)
..... Die y-Position der Spielfigur. Es handelt sich um den linken oberen Punkt der Spielfigur.
..... Verändert werden x- und y-Position (in SPR1XPos und SPR1YPos) mit dem Macro updateSprXY.
..... In der Subroutine MajSprite werden diese dann weiterverarbeitet und in den OAMTemp gespeichert.
..... Wird gesetzt in "InitBG1". #$0044 (#68)
SPR1YSpeed (w)
..... ?
..... Wird gesetzt in "emptyVariable". #$01
sprite (b)
..... Wird genutzt in SR MajSprite, um den dritten Byte (Sprite-Tile-Nummer) des OAM-Datensatzes
..... des Körpers der Spielerfigur zu setzen.
..... Ich weiß nicht, wo diese Variable auf einen Wert gesetzt wird. Vielleicht wird sie es nicht
..... und dadurch entstehen auf richtiger Hardware Fehler...?
tempB (b)
..... Temp-Byte, wird an verschiedenen Stellen genutzt.
..... In "LoopMenuSelection" dient er (anscheinend) als Speicher für das gewählte Level.
..... In "pushToColor" dient er als Speicher für das gewählte Level.
Timer (b)
..... Zeit-Zähler-Variable.
..... Wird in "LoopMenuSelection" für das BG-Scrollen genutzt.
XPos (b)
..... Bitte beachten! Im Gegensatz zu XPos2, YPos und YPos2 ist XPos Bytegroß!
..... Wird in "LoopMenuSelection" für das BG-Scrollen genutzt; enthält den X-Wert des gescrollten
..... Kachelhintergrunds.
..... Wird gesetzt in "InitBG1". #$00
XPos2 (w)
..... ?
..... Wird gesetzt in "InitBG1". #$0000
YPos (w)
..... ?
..... Wird gesetzt in "InitBG1". #$0000
YPos2 (w)
..... ?
..... Wird gesetzt in "InitBG1". #$0000


bonusOffset dw
spr1Offset dw
spr1RunAdress dw
spr1StandAdress dw
TempTile dw
TempX dw
TempY dw

; BG1 Variable definition for move
BG1XOFFSET dw
BG2XOFFSET dw

; bg1Width dw
RedrawTile dw
RedrawTile2 dw
; Temporary storage for calculation
Temp dw
; Timer for Sprite & Bg
Compteur db
; Compteur argent

;ennemie
foe1Offset dw

;Tir
tir1Offset dw
tir1Status db

;colison variable
sourceSprX db
sourceSprY db
decalX dw
decalY dw
dstBoundX db
dstBoundY db
dstBoundOam db
MaxSprObj dw

; Joypad handle event
Joy1 dw
Joy2 dw

; Variable
dirTrajX db
indexTrajY db
; Sprite variable
SPR1XSpeed dw
status db
timerOnAir db
; Sprite Foe variable
bonus1SprX dw
bonus1SprY dw
bonus1SprStatus db
; Bonus Variable 16x16
BG1XOFFSETL dw
BG2XOFFSETL dw
RedrawTileL dw
RedrawTile2L dw
; Global Byte Temp Storage
tempW dw

;ennemie
foe2Offset dw
foe3Offset dw
isMoveBG dw

;life
playerTimer db
sourceSprXW dw
sourceSprYW dw
dstBoundXW dw
dstBoundYW dw

;boss
boss1Action db
bossOffset dw
bossOeilOffset dw
bossBouleOffset dw
bossSprX db
bossSprY db
boss1Step db
bossLifeOld db
boss1Scheduler db
bouleStep db

;to be supressed
tempStorage db

; Time
TimeElasped db
SyncCounter db
map0Reference dw

; LEvel
blockLimit dw
OAMSpecialCharacter1 dw
OAMSpecialCharacter2 dw
OAMSpecialCharacter3 dw
OAMSpecialCharacter4 dw
OAMSpecialCharacter5 dw
OAMSpecialCharacter6 dw
foe4Offset dw
player db
scorevalue db
spcSongNr db
oldlevel db
pantalytron: ルトロンはくそのディスアセンブラだよ!
Perikles hat geschrieben:Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.

Antworten