Seite 1 von 2

Mein Textbox-Programm

Verfasst: 13. August 2012, 17:37
von lytron
Horrido,

ich habe in den vergangenen Monaten ein kleines Programm für den SNES geschrieben und möchte das jetzt hier zum Gucken, Verbessern und Verwenden(?) anbieten. Es ist mein zweites SNES-Programm (das erste beschränkte sich auf das Füllen eines BGs mit Tiles; es war wirklich das erste), und an vielen Stellen zusammengesetzt aus Tutorials, maßgeblich aus welchen von bazz, die ich auf wiki.superfamicom.org gefunden habe.

Inhalt und Funktionen des Programms
- Man kann die Textbox an einer beliebigen Stelle erscheinen lassen (#$FA80 = unten, #$F800 = oben, #F940 = Mitte; was anderes würde ein sehr gurkiges Ergebnis zu Tage fördern)
- Man kann Animationen starten, wie sich die Textbox öffnet und schließt
- Man kann Text in die Textbox schreiben und zwischen zwei Textfarben wechseln
- Man kann einen Zeilenumbruch einfügen
- Man kann die Textbox leeren
- Man kann auf einen Button-Druck warten (A)
- Man kann den Text schneller laufen lassen (B)
- Mittels des Konami-Codes ändert Mario seine Laufrichtung
Das Programm ist so ausgelegt, dass die Sprites sich unabhängig von der Textbox bewegen können, da es in keinem Spiel gut kommt, wenn jegliches Geschehen freezt, nur weil eine Textbox geöffnet ist. Dazu habe ich diese ultra-intelligente Spritebewegung implementiert (die Spritegrafik selbst habe ich aus bazz' Sprite-Tutorial übernimmen, AFAIK ist das aus einem Excite-Bike-Klon für das SatellaView(!?)), die sogar die meiste Zeit mit derselben Geschwindigkeit laufen sollte; wenn es nicht so ist und jemand diesbezüglich Verbesserungsvorschläge hat, wäre ich sehr dankbar dafür.
Das Programm ist auf Englisch (zumindest weitesgehend) kommentiert; ich denke, das ist essentiell, wenn man will, das andere den eigenen Code benutzen. :wink: Ich wollte auch gern versuchen, es so Newbie-freundlich wie möglich zu gestalten, dementsprechend mögen viele Erklärungen überflüssig sein für jemand, der sich mit SNES Programmierung schon mehr als einen Monat befasst hat. Viel hilft viel, im Zweifelsfall besteht immer die Möglichkeit zu überlesen. :wink:

To Do
- Fertig kommentieren
- Ich habe beim "Case Handling" eine Übergangslösung eingebaut, für die ich mir eine "JMP Map" bauen wollte. Die JMP Map sollte dann in etwa so aussehen, dass ich nach dem Label am Beginn selbiger eine Liste von JMP-Befehlen habe, und dann, wenn einer dieser Spezialfälle eintritt, er automatisch auf den passenden JMP-Befehl springt (soll heißen: Bei Spezialfall #2 gehe zu: (Adresse von JMP Map)+4 Byte, bei Spezialfall #3 gehe zu: (Adresse von JMP Map)+6 Byte usw. Habe ich bisher nicht eingebaut, weil die Menge der Sonderfälle noch überschaubar ist. Ein Vorgehen nach dem Muster "Ist es das? Nein. Ist es das? Nein. Ist es das?" lässt den 5A22 da noch nicht in die Knie gehen, und außerdeeem... hieße das bei meinen momentanen Kenntnissen mehrere Stunden Trial and Error für nix. :D
- Ich wollte noch einbauen, dass ich für eine beliebige, vorher festgesetzte Zeichenkette ("Schwert", "Holerö!", "ist zu viel!" o. ä.) nur ein einziges Zeichen in die Textdatei setzen muss. AFAIK wurde selbiges ja in vielen Spielen so programmiert, um Speicherplatz zu sparen. Hatte bisher nur keine Lust dazu (viel Aufwand, wenig Nutzen...?).
- "CloseTextBox" ist de facto nur eine Umkehr von "OpenTextBox" und wurde von mir am Sonntagabend hingekleckert; ich wollt' fertig werden. :wink: Dementsprechend habe ich eine absolut ungalante Lösung für ein ausstehendes Problem genommen: Bei OpenTextBox zählt man den Arbeitsschritt-Counter von #$00 bis #$0A, und bei #$0A ist die Box komplett fertig. Zum Schließen zählt man von #$0A bis #$FF, was mal sowas von unstylish ist, dass... äh...
- In "OpenTextBox" und "CloseTextBox" habe ich jeweils ein Knäuel aus JMP, JML, BNE, BEQ etc., um einige Long-Jumps bzw. Long-Branches (you know what I mean(?)) hinzubekommen, was damals eine Notlösung war, um zu erreichen, was ich wollte. Verbesserungsvorschläge? (Suchbegriff in den Dateien: "Avoid")

Gliederung des Programms / How To
Im Programm die Subroutinen "SubOpenTextBox", "SubCloseTextBox" und "SubTextBox" sind in eigene .inc-Dateien selbigen Namens ausgelagert; die Subroutinen erledigen, wie ihre Namen es erahnen lassen, das Öffnen und Schließen der Textbox, sowie die Verarbeitung der Textdaten (aus einer Binärdatei, in diesem Fall "text.inc"). In der Datei "mainprgm.inc" ist das Hauptprogramm ab dem Zeitpunkt enthalten, ab dem alle Register vorbereitet und alle Daten an die richtige Stelle geladen sind; es beginnt mit dem Befehl, dass Mario sich bewegt, dann dem Befehl, dass sich die Box öffnet etc.
Der Setupteil befindet sich in "textbox.asm", genauso wie die Makros, die die Subroutinen aufrufen und/oder die Variablen für die Subroutinen vorbereiten, und die Nonsense-Funktionen. Nonsense-Funktionen sind: DrawLandscape und DoSomethingWithSprites. Dienen dem Zweck, eine halbwegs spielähnliche Umgebung für mein Programm zu schaffen, mit einem Hintergrund, über (und nicht unter!) dem die Textbox sich öffnen soll, mit Sprites, die sich während der Textbox noch bewegen können sollen (siehe oben), tralala.

Schreiben:
In der Binärdatei stehen:
0C 20 für A
0E 20 für B
10 20 für C
[etc.]
3E 20 für Z
40 20 für Ä
42 20 für Ö
44 20 für Ü
46 20 für ?
48 20 für !
4A 20 für ,
4C 20 für -
4E 20 für ein Leerzeichen.

Sonderfunktionen:
00 C0 für eine neue Zeile
01 C0 für das Leeren der Textbox
02 C0 für das Warten auf Buttondruck
FF C0 für das Beenden der SubTextBox-Subroutine
0C 24 steht für ein A in blauer Schriftfarbe (und logischerweise lassen sich alle anderen Buchstaben und Zeichen so einfärben, wenn man die nachstehende 20 durch eine 24 ersetzt).

Diese "Codes" für die Buchstaben werden eins zu eins in die Tilemap geschrieben, wobei die vorne stehenden zwei Byte die Tile-Nummer angeben, die hintenstehenden die den Priority-Bit setzen (die 2 bei der 20/24 - die Textbox ist auf BG3) und die Nummer der Palette (0 = Palette 0, 4 = Palette 1, siehe zweite graue Box des Unterthemas "Tile Maps & Character Maps" auf dieser Seite).


Restekiste
- Geschrieben und getestet mit WordPad, irgendson Hexeditor (ich glaube HxD), WLA DX, BSNES (aus Kompatibilitätsgründen), ZSNES (aus Geschwindigkeitsgründen) und Super Everdrive/SNES (aus Motivationsgründen)
- Ich habe es geschafft, einen Bug zu produzieren, bei dem das Programm in BSNES und auf dem SNES lief, aber ZSNES zum Abstürzen brachte: Ich habe zweimal etwas vom Stack gepullt, obwohl ich insgesamt nur einmal was draufgeschmissen habe. Sollte ich mir merken, wenn ich irgendwann mal ein SNES-Spiel fertig habe, ist das wohl ein halbwegs funktionierender Kopierschutz. :D :wink:
- Die "OpenTextBox"-Funktion habe ich zuerst komplett ohne Loops gebaut, und erst danach zusammengestaucht. Das hat wahnsinnig viel Zeit gekostet! War aber sicherlich doch die beste Möglichkeit, ansonsten säße ich jetzt vielleicht immer noch am Bugfixen der Funktion. :wink:
- Wenn man vergisst, $4200 auf #$80 zu setzen, bewegen sich die Grafiken in ZSNES schon, in BSNES/auf dem SNES nicht.
- Wenn ich einen 16bit-Akkumulator habe und sage "STZ BytegrosseVariable.b", schreibt er #$0000 und nicht, wie gewünscht, #$00. Quintessenz von einer halben Woche auf Fehlersuche. ~_~



So. Ich bin durch. Ich denke, ich habe einiges wichtiges vergessen zu schreiben... aber ich denke, dieser Post ist schon lang genug. :wink:

Re: Mein Textbox-Programm

Verfasst: 13. August 2012, 19:22
von d4s
Finde ich gut, viel Erfolg weiterhin!
- Ich habe beim "Case Handling" eine Übergangslösung eingebaut, für die ich mir eine "JMP Map" bauen wollte. Die JMP Map sollte dann in etwa so aussehen, dass ich nach dem Label am Beginn selbiger eine Liste von JMP-Befehlen habe, und dann, wenn einer dieser Spezialfälle eintritt, er automatisch auf den passenden JMP-Befehl springt (soll heißen: Bei Spezialfall #2 gehe zu: (Adresse von JMP Map)+4 Byte, bei Spezialfall #3 gehe zu: (Adresse von JMP Map)+6 Byte usw. Habe ich bisher nicht eingebaut, weil die Menge der Sonderfälle noch überschaubar ist. Ein Vorgehen nach dem Muster "Ist es das? Nein. Ist es das? Nein. Ist es das?"
Aus dem Gedaechtnis, kompiliert vielleicht nicht, aber die Funktionsweise wird vielleicht klar:

Code: Alles auswählen


/**
* @return c<bool> set if char contained special command
*/
char.command.check:
php
rep #$31
lda char.current
and.w #$ff
cmp.w #(char.command.lut.end - char.command.lut.start) /2
bcs +
 asl a
 tax
 jsr (char.command.lut.start,x)
 plp
 sec
 rts

+
plp
clc
rts

char.command.irgendwas:
 rts

char.command.blah:
 rts

char.command.argh:
 rts


char.command.lut.start:
 .dw char.command.irgendwas
 .dw char.command.blah
 .dw char.command.argh
char.command.lut.end:


Re: Mein Textbox-Programm

Verfasst: 13. August 2012, 20:11
von lytron
d4s hat geschrieben:Finde ich gut, viel Erfolg weiterhin!
Woohoo! It's him! It's him! :D

Dankeschön. Danke auch für deinen Support per Mail. Ohne dich müsste ich immer noch die Textdaten in derselben Bank wie den Rest des Programms speichern. :)

d4s hat geschrieben: Aus dem Gedaechtnis, kompiliert vielleicht nicht, aber die Funktionsweise wird vielleicht klar:
versteckter Inhalt:

Code: Alles auswählen

/**
* @return c<bool> set if char contained special command
*/
char.command.check:
php
rep #$31
lda char.current
and.w #$ff
cmp.w #(char.command.lut.end - char.command.lut.start) /2
bcs +
 asl a
 tax
 jsr (char.command.lut.start,x)
 plp
 sec
 rts

+
plp
clc
rts

char.command.irgendwas:
 rts

char.command.blah:
 rts

char.command.argh:
 rts


char.command.lut.start:
 .dw char.command.irgendwas
 .dw char.command.blah
 .dw char.command.argh
char.command.lut.end:
Vielen Dank für den Code. Ich versuche mal mein Verständnis wiederzugeben, du kannst dann einfach dazwischen hauen, wenn ich was missinterpretiere, und ansonsten einfach "japp" sagen, wenn ich alles verstanden habe. :wink:

Du lädst das aktuelle Buchstaben-Word, nimmst dir nur den unteren(?) Byte, und schaust, ob der eine "niedrige" Zahl hat.
Da mein Buchstaben-Trara erst ab 0C beginnt, habe ich 00 bis 0B die Möglichkeit, die Sonderfunktionen hineinzuschmieren, das sind, öh, elf Plätze.
Du definierst zwei Labels für die, ich nenne sie mal wieder so, Jump-Map: Eine für den Anfang und eine fürs Ende. In der Zeile "cmp.w #(char.command.lut.end - char.command.lut.start) /2" subtrahierst du die Endadresse von der Anfangsadresse, das Ergebnis müsste 6 sein, da du zwischen Ende und Anfang 3x2 Bytes definierst. Du teilst 6 durch 2 und erhälst 3, %0011. Du vergleichst das mit dem Buchstaben-Byte. Wenn dabei der Carryflag gesetzt wird, ist der Wert im Akkumulator genauso groß oder größer als der Vergleichswert (gemäß dem Handbuch, Seite 347); es handelt sich um einen Buchstaben, also überspringt das Programm den Special-Case-Handling-Teil und geht zu +.

Wenn es ein Special-Case ist, verdoppelst du den Wert (ASL A), schiebst das Ergebnis von A nach X (TAX) und lässt ihn dann die Adresse aufrufen, die er bei Listenbeginn + X findet, was wiederum der Name der Subroutine ist, die er aufrufen soll.

*puh* Fremder Leute ASM-Code zu verstehen ist manchmal echt böse tricky. :wink:

Vielen lieben Dank!

Nur aus Interesse gefragt: Du schreibst "REP #$31" statt, wie ich es getan hätte, "REP #$30". Ist es Absicht, dass du die Carry-Flag gleich mitclearst?

Re: Mein Textbox-Programm

Verfasst: 14. August 2012, 21:34
von Ramsis
Textboxen sind was Feines. :D Supertolle Sache, lytron! :applaus: Werd' ich demnächst bestimmt mal ausprobieren. Weiter so, und vor allem viel Spaß dabei! :-)

Re: Mein Textbox-Programm

Verfasst: 18. August 2012, 09:21
von lytron
Textbox - Version 2.rar
(29.92 KiB) 247-mal heruntergeladen
Ramsis hat geschrieben:Textboxen sind was Feines. :D Supertolle Sache, lytron! :applaus: Werd' ich demnächst bestimmt mal ausprobieren. Weiter so, und vor allem viel Spaß dabei! :-)
Danke danke danke. :D

Kleines Update: Ich habe eine zweite Version fertig. Ich habe eine neue Textdatei hinzugefügt, deshalb erscheint jetzt ein anderer Text in der Textbox (endlich in englisch). Ansonsten habe ich die Kommentare fertig. Das hat mich vier bis sechs Stunden gekostet, aber ich denke, jetzt müsste es in jedem Fall für jeden Newbie verständlich sein. :wink:
(Bei den nächsten "Bausteinen" werde ich definitiv nicht so viel kommentieren. Das macht mich wahnsinnig. :wink: )

Ich will versuchen, noch dieses Wochenende so viele Punkte von der To-Do-Liste wie möglich zu erledigen, um dann eine dritte Version hier hochzuladen und dann (*endlich*) zu neuen Ufern aufzubrechen (Sprites einfügen und steuerbar machen, yay!).

Wenn wer von euch Zeit hat und über den Code drübergucken kann, bin ich für jeden Tipp und Kniff dankbar. :)

Ansonsten... ich habe mal ein Video aufgenommen, dass das Programm zeigt, dann brauch man sich den Kram nicht runterladen, wenn man nur sehen will, wies aussieht.



Tüdelü.

Re: Mein Textbox-Programm

Verfasst: 18. August 2012, 10:31
von ChronoMoogle
Super Sache! Weiter so mit deiner "Engine" :)

Re: Mein Textbox-Programm

Verfasst: 19. August 2012, 20:43
von lytron
ChronoMoogle hat geschrieben:Super Sache! Weiter so mit deiner "Engine" :)
Danke auch dir für deine Ermunterung... wobei ich bei dir nicht weiß, inwieweit das uneigennützig ist. Ich denke, dir ist schon klar, was für ein Genre man im Auge hat, wenn man seine Engine mit Textboxen beginnt... hehe... :wink:

Anyhow, Ladies...
Es ist Sonntag, es ist abend, ich habe den ganzen Tag nur am PC gesessen und bin gerade ein wenig sentimental, nicht nur aufgrund der bald beginnenden neuen Arbeitswoche, die stressig und widerlich warm wird...
Also, zur neuen Fassung meines Textbox-Tralala eine Zusammenfassung des Tages.

Faktisch habe ich den ganzen Tag mit diesem Dingens verbracht, auch weil der Tag sich nicht anderweitig nutzen ließ. Dafür bin ich jetzt fast mit dem Ding fertig.

Und dieses "fast" frustriert mich ein wenig.

Heute morgen habe ich den oben erwähnten "FF-Case" erledigt. Da ich nämlich bereits gestern beim Kommentieren gemerkt habe, dass Step 01 und Step 00 dasselbe machen, habe ich das, was Step FF ausgeführt hat, einfach in Step 00 verschoben und gut ist.

- Ich weiß, dass sich keiner meinen Source Code anguckt, um tatsächlich zu verstehen, wovon ich rede. ASM-Code ist keine Bettlektüre und nichts für ne Raucherpause, darum bin ich darüber nicht pikiert. Ich schreibe das hier nur, um es irgendwo mal losgeworden zu sein. :wink: -

Danach habe ich diese "Jump Maps" implementiert. Drei Stück. Nicht nur im zentralen SubTextBox, sondern auch beim Öffnen und Schließen. Ein herzliches Dankeschön an dieser Stelle an d4s, noch einmal.

Nächster Punkt, nächstes Dankeschön an d4s:
Danke, dass du BCS bzw. BCC in mein ASM-Vokabular gebracht hast. Dadurch konnte ich das Programm noch weiter verschlanken bzw. gegen falsche Bedienung schützen:
Beim Öffnen und Schließen muss die Subroutine mit einem bestimmten Wert in einer bestimmten Variable aufgerufen werden, um den erwünschten "Animationsschritt" anzeigen zu lassen. Das ist das, was ich weiter oben mit Case bzw. Step gemeint habe. Mittels neu erworbener Kenntnis um die BCS/BCC-Befehle war es ein leichtes, den GAU auszuschließen, der auf dem Bildschirm passieren mag, wenn meine Subroutine einen Animationsschritt darzustellen versucht, für den es nicht ausgelegt war. Namentlich gibt es elf Animationsschritte, $00 bis $0A. Ich habe die Subroutinen OpenTextBox und CloseTextBox beide mal von ~#$F0 bis ~#$1A durchlaufen lassen, und keine Falschdarstellungen, und das schlichtweg dank "cmp #$0b / bcc value_okay/ rts / value_okay:"). Das ist effektives Coding. :wink:

Danach war ich maßgeblich in Korrespondenz mit meinem Bruder, während ich mich mit den Halloweenspecials des Happy Videogame Nerd die verlängerte Siesta-Time verschönerte. Zur Info: Während ich mich dazu entschlossen habe, nach meinem Abi in einem Städtchen im niedersächsischen Flachland eine Berufsausbildung in einem Betrieb zu absolvieren, der exakt auf der anderen Seite desselben Städtchens im niedersächsischen Flachland angesiedelt ist, hat mein Bruder ein Studium in Richtung Informatik absolviert, hat ein paar mehr Ecken von Deutschland gesehen als ich. Was ich damit sagen will: Er ist im Gegensatz zu mir wirklich profiliert im Programmieren.
Deshalb bat ich ihn, mir ein Programm in Qt zu schreiben, dass mir das verkackte Puzzlen im Hexeditor erspart, um neue Textdateien für die Textboxen zu erstellen. Das Programm war nach einigem Hin und Her dann auch fertig geworden. Ich habe es mal gezippt und mitangehängt, es ist die transscriptor.rar. Wenn wer den Sourcecode will, muss er nur bescheid sagen.

Zur Bedienung:
target.txt öffnen, Text eingeben, dann das Programm starten. Ist ein Kommandozeilen-Programm, also in den meisten Fällen müsste sich eine Eingabeaufforderung öffnen und sofort schließen, ehe man was lesen kann. Dann steht in output.txt eine ekelig lange Hex-Zahlenkette, die man kopiert und mittels Hexeditor in text.inc in meiner textbox.rar einfügt. Bei HxD, dem Hexeditor, den ich benutze, klappt das mit Copy & Paste. Dann die ganze Soße mit WLA DX neu kompilieren und fertig ist die Laube.

Zur Bedienung / 2:
In target.txt schreibt man den Text in Großbuchstaben. Leerzeichen ersetzt man durch Unterstriche. Sonderbefehle führt man folgendermaßen mit kleinen Buchstaben aus:
l = new line
c = clear screen
b = button
s = signal
x = exit program

Komme ich zum vorletzten Punkt, dem letzten neuen Feature dieser Version: Dem Signal.
Die einzige Möglichkeit, die meine TextboxSubroutine(n) haben, mit der Außenwelt zu kommunizieren, ist die Variable, in der eigentlich der Timerwert drin steckt, der immer wieder auf 6 gesetzt und bis null runtergezählt wird, um Zeit zwischen zwei Buchstaben verstreichen zu lassen. Wird das Ding auf #$FF gesetzt, ist das das Zeichen, den Loop im Hauptprogramm zu verlassen. Ihr seht das, wenn Mario aufhört sich zu bewegen. Dann ist der allerletzte Infinity-Loop erreicht, der wirkliche Point-of-No-Return (or escape).
In the same vein habe ich mal eine Signalfunktion gesetzt. Die lautet schlichtweg: Setze den Timer auf #$AA und beende diese Subroutine. Wenn die Subroutine das nächste Mal gestartet wird, ist der allererste Arbeitsschritt: Ist der Timer auf #$AA gesetzt? Wenn ja, setz ihn auf null. Allerdings kann jede andere Subroutine in der Zwischenzeit auf dieses Signal reagieren.
In meiner Beispieldatei ist es die Subroutine "DoSomethingWithSprites" (zu finden in textbox.asm), die sowieso nur Alibi ist und sich maßgeblich damit beschäftigt, Motorbike-Mario über den Screen zu schieben. In diesem Beispiel macht Mario dann auf einmal einen riesigen Sprung über die Hälfte des Bildschirms (das ist kein Bug).

Wozu das Ganze? Ganz einfach: In einem fertigen Spiel könnte man dann damit in der Textdaten-Datei einfach nur den Zeitpunkt festsetzen, wann ein Signal kommen soll, dass andere, bedeutungsschwangere Animationen auslöst. Z. B., wenn die Tante im Wasserpalast am Labern ist, dass die Koboldin die Angriffsmagien bekommt, und wir währenddessen sehen, wie besagtes Etwas sich rückwärts bewegt und die Beschwörungsanimation ablaufen lässt. Außerdem ist dabei wohl chic, dass der Text, theoretisch dabei weiterlaufen kann... wenn man will.

Letzter Punkt:
Wieder einmal gibt es wieder einen Punkt, den ich noch zusätzlich einbauen möchte. Eine Whole-in-One-Funktion, die alles, was zur Zeit in mainprgm.inc an Loops und Vorbereitungsschritten für selbige ist, in sich vereint, dass ich nur sagen muss: "Mach Textbox. Nimm den Text da und mach sie dorthin." Und der Rest läuft.

Im Kopf habe ich schon beisammen, wie das gehen kann. Aber jetzt habe ich auch keinen Bock mehr dazu, es ist vergleichsweise spät, dafür, dass ich morgen sündhaft früh rausmuss...

...bleibt es halt liegen bis nächstes Wochenende... :(

PS: Rede ich zu viel? :D Manchmal glaube ich, im nächsten Leben werde ich cardassianischer Schneider... :wink:

Re: Mein Textbox-Programm

Verfasst: 19. August 2012, 23:02
von onkel istvan
PS: Rede ich zu viel? :D Manchmal glaube ich, im nächsten Leben werde ich cardassianischer Schneider... :wink:
Ich verstehe zwar nichts von den ganzen Details, Garak... äh Lytron, aber das macht es nicht weniger interessant. Das Video sieht schon mal sehr vielversprechend aus!

Re: Mein Textbox-Programm

Verfasst: 25. August 2012, 18:34
von d4s
lytron hat geschrieben: Vielen Dank für den Code. Ich versuche mal mein Verständnis wiederzugeben, du kannst dann einfach dazwischen hauen, wenn ich was missinterpretiere, und ansonsten einfach "japp" sagen, wenn ich alles verstanden habe. :wink:

Nur aus Interesse gefragt: Du schreibst "REP #$31" statt, wie ich es getan hätte, "REP #$30". Ist es Absicht, dass du die Carry-Flag gleich mitclearst?
Ich glaube, du hast ganz gut verstanden, was der Code macht.
Fremden Code zu lesen ist schwer, aber mit Übung wird es einfacher.

rep #$31 ist nur so ne Angewohnheit. Es stimmt, ob das Flag clear ist oder nicht, ist für das folgende Programm egal.

Ein Tipp noch:
Weniger Magic Numbers und mehr sprechende Variablennamen beim Programmieren verwenden.
In dem Moment, in dem du

Code: Alles auswählen

lda #$19.b
sta $2105
schreibst, mag der Zweck dessen zwar sonnenklar sein, wenn du aber nach nem halben Jahr noch mal versuchst, das nachzuvollziehen oder gar zu ändern, vergeudet man damit mehr Zeit als nötig, ausserdem ist es fehleranfällig.

Im Vergleich dazu liest sich das Folgende deutlicher und man läuft auch nicht Gefahr, versehentlich das falsche Bit zu setzen oder Sourcecode und Kommentare auseinanderdriften zu lassen.

Code: Alles auswählen

lda #BGMODE_MODE_1 | BGMODE_PRIORITY_LAYER_3 | BGMODE_CHARSIZE_LAYER_1
sta BGMODE
Dazu muss man sich dann natürlich mal die Mühe machen, alle Register und ihre Konfigurationswerte zu definieren, ich hab das so gemacht:

Code: Alles auswählen

;SNES register definitions

;PPU regs
.define INIDSP $2100					;Screen Display
	.define INIDSP_FORCE_BLANK			1 << 7
	.define INIDSP_BRIGHTNESS			$f << 0

.define OBJSEL $2101					;Object Size and Chr Address
	.define OBJSEL_SPRITES_8X8_16X16	0 << 5
	.define OBJSEL_SPRITES_8X8_32X32	1 << 5
	.define OBJSEL_SPRITES_8X8_64X64	2 << 5
	.define OBJSEL_SPRITES_16X16_32X32	3 << 5
	.define OBJSEL_SPRITES_16X16_64X64	4 << 5
	.define OBJSEL_SPRITES_32X32_64X64	5 << 5
	.define OBJSEL_SPRITES_16X32_32X64	6 << 5
	.define OBJSEL_SPRITES_16X32_32X32	7 << 5
	.define OBJSEL_BASE_0000			0
	.define OBJSEL_BASE_4000			1
	.define OBJSEL_BASE_8000			2
	.define OBJSEL_BASE_C000			3
	.define OBJSEL_NAME_1				0 << 3
	.define OBJSEL_NAME_2				1 << 3
	.define OBJSEL_NAME_3				2 << 3
	.define OBJSEL_NAME_4				3 << 3

.define OAMADDL $2102					;OAM Address
.define OAMADDH $2103
	.define OAMADDH_PRIORITY_ACTIVATE	1 << 7

.define OAMDATA $2104					;Data for OAM write

.define BGMODE $2105					;BG Mode and Character Size
	.define BGMODE_CHARSIZE_LAYER_4		1 << 7
	.define BGMODE_CHARSIZE_LAYER_3		1 << 6
	.define BGMODE_CHARSIZE_LAYER_2		1 << 5
	.define BGMODE_CHARSIZE_LAYER_1		1 << 4
	.define BGMODE_PRIORITY_LAYER_3		1 << 3
	.define BGMODE_MODE_7				7
	.define BGMODE_MODE_6				6
	.define BGMODE_MODE_5				5
	.define BGMODE_MODE_4				4
	.define BGMODE_MODE_3				3
	.define BGMODE_MODE_2				2
	.define BGMODE_MODE_1				1
	.define BGMODE_MODE_0				0

.define MOSAIC $2106					;Screen Pixelation
	.define MOSAIC_LAYER_4				1 << 3
	.define MOSAIC_LAYER_3				1 << 2
	.define MOSAIC_LAYER_2				1 << 1
	.define MOSAIC_LAYER_1				1 << 0

.define BG1SC $2107						;BG Tilemap Address and Size
.define BG2SC $2108
.define BG3SC $2109
.define BG4SC $210a
 	.define BGSC_Y_MIRROR				1 << 1
	.define BGSC_X_MIRROR				1 << 0

.define BG12NBA $210b					;BG Chr(Tiles) Address
	.define BG1NBA_0000					0 << 0
	.define BG1NBA_2000					1 << 0
	.define BG1NBA_4000					2 << 0
	.define BG1NBA_6000					3 << 0
	.define BG1NBA_8000					4 << 0
	.define BG1NBA_A000					5 << 0
	.define BG1NBA_C000					6 << 0
	.define BG1NBA_E000					7 << 0

	.define BG2NBA_0000					0 << 4
	.define BG2NBA_2000					1 << 4
	.define BG2NBA_4000					2 << 4
	.define BG2NBA_6000					3 << 4
	.define BG2NBA_8000					4 << 4
	.define BG2NBA_A000					5 << 4
	.define BG2NBA_C000					6 << 4
	.define BG2NBA_E000					7 << 4

.define BG34NBA $210c
	.define BG3NBA_0000					0 << 0
	.define BG3NBA_2000					1 << 0
	.define BG3NBA_4000					2 << 0
	.define BG3NBA_6000					3 << 0
	.define BG3NBA_8000					4 << 0
	.define BG3NBA_A000					5 << 0
	.define BG3NBA_C000					6 << 0
	.define BG3NBA_E000					7 << 0

	.define BG4NBA_0000					0 << 4
	.define BG4NBA_2000					1 << 4
	.define BG4NBA_4000					2 << 4
	.define BG4NBA_6000					3 << 4
	.define BG4NBA_8000					4 << 4
	.define BG4NBA_A000					5 << 4
	.define BG4NBA_C000					6 << 4
	.define BG4NBA_E000					7 << 4

.define BG1HOFS $210d					;BG x-Scroll
.define M7HOFS $210d
.define BG1VOFS $210e					;BG y-Scroll
.define M7VOFS $210e

.define BG2HOFS $210f
.define BG2VOFS $2110

.define BG3HOFS $2111
.define BG3VOFS $2112

.define BG4HOFS $2113
.define BG4VOFS $2114

.define VMAIN $2115						;Video Port Control
	.define VMAIN_INCREMENT_MODE		1 << 7
	.define VMAIN_INCREMENT_1			0 << 0
	.define VMAIN_INCREMENT_32			1 << 0
	.define VMAIN_INCREMENT_128			2 << 0

.define VMADDL $2116					;VRAM Address
.define VMADDH $2117

.define VMDATAL $2118					;VRAM Data
.define VMDATAH $2119

.define M7SEL $211a						;Mode 7 Settings
	.define M7SEL_PLAYFIELD_SIZE		1 << 7
	.define M7SEL_EMPTY_FILL			1 << 6
	.define M7SEL_Y_MIRROR				1 << 1
	.define M7SEL_X_MIRROR				1 << 0

.define M7A $211b						;Mode 7 Matrix
.define M7B $211c
.define M7C $211d
.define M7D $211e
.define M7X $211f						;Mode 7 Center
.define M7Y $2120

.define CGADD $2121						;CGRAM Address
.define CGDATA $2122					;CGRAM Data

.define W12SEL $2123					;Window Mask Settings
	.define W12SEL_BG2_W2_ENABLE		1 << 7
	.define W12SEL_BG2_W2_INVERT		1 << 6
	.define W12SEL_BG2_W1_ENABLE		1 << 5
	.define W12SEL_BG2_W1_INVERT		1 << 4
	.define W12SEL_BG1_W2_ENABLE		1 << 3
	.define W12SEL_BG1_W2_INVERT		1 << 2
	.define W12SEL_BG1_W1_ENABLE		1 << 1
	.define W12SEL_BG1_W1_INVERT		1 << 0

.define W34SEL $2124
	.define W34SEL_BG4_W2_ENABLE		1 << 7
	.define W34SEL_BG4_W2_INVERT		1 << 6
	.define W34SEL_BG4_W1_ENABLE		1 << 5
	.define W34SEL_BG4_W1_INVERT		1 << 4
	.define W34SEL_BG3_W2_ENABLE		1 << 3
	.define W34SEL_BG3_W2_INVERT		1 << 2
	.define W34SEL_BG3_W1_ENABLE		1 << 1
	.define W34SEL_BG3_W1_INVERT		1 << 0

.define WOBJSEL $2125
	.define WOBJSEL_COL_W2_ENABLE		1 << 7
	.define WOBJSEL_COL_W2_INVERT		1 << 6
	.define WOBJSEL_COL_W1_ENABLE		1 << 5
	.define WOBJSEL_COL_W1_INVERT		1 << 4
	.define WOBJSEL_OBJ_W2_ENABLE		1 << 3
	.define WOBJSEL_OBJ_W2_INVERT		1 << 2
	.define WOBJSEL_OBJ_W1_ENABLE		1 << 1
	.define WOBJSEL_OBJ_W1_INVERT		1 << 0

.define W1L $2126	;WH0				;Window Position
.define W1R $2127	;WH1
.define W2L $2128	;WH2
.define W2R $2129	;WH3

.define WBGLOG $212a					;Window mask logic
	.define WBGLOG_BG4_OR				0 << 6
	.define WBGLOG_BG4_AND				1 << 6
	.define WBGLOG_BG4_XOR				2 << 6
	.define WBGLOG_BG4_XNOR				3 << 6

	.define WBGLOG_BG3_OR				0 << 4
	.define WBGLOG_BG3_AND				1 << 4
	.define WBGLOG_BG3_XOR				2 << 4
	.define WBGLOG_BG3_XNOR				3 << 4

	.define WBGLOG_BG2_OR				0 << 2
	.define WBGLOG_BG2_AND				1 << 2
	.define WBGLOG_BG2_XOR				2 << 2
	.define WBGLOG_BG2_XNOR				3 << 2

	.define WBGLOG_BG1_OR				0 << 0
	.define WBGLOG_BG1_AND				1 << 0
	.define WBGLOG_BG1_XOR				2 << 0
	.define WBGLOG_BG1_XNOR				3 << 0

.define WOBJLOG $212b
	.define WOBJLOG_COL_OR				0 << 2
	.define WOBJLOG_COL_AND				1 << 2
	.define WOBJLOG_COL_XOR				2 << 2
	.define WOBJLOG_COL_XNOR			3 << 2

	.define WOBJLOG_OBJ_OR				0 << 0
	.define WOBJLOG_OBJ_AND				1 << 0
	.define WOBJLOG_OBJ_XOR				2 << 0
	.define WOBJLOG_OBJ_XNOR			3 << 0

.define TMAIN $212c						;Mainscreen Designation
.define TSUB $212d						;Subscreen Designation
.define TMW $212e						;Mainscreen Window Mask Designation
.define TSW $212f						;Subscreen Mask Designation
 	.define T_OBJ_ENABLE				1 << 4
 	.define T_BG4_ENABLE				1 << 3
 	.define T_BG3_ENABLE				1 << 2
 	.define T_BG2_ENABLE				1 << 1
 	.define T_BG1_ENABLE				1 << 0

.define CGWSEL $2130					;Color Addition Select
 	.define CGWSEL_CLIP_COL_NEVER		0 << 6
 	.define CGWSEL_CLIP_COL_OUTSIDE		1 << 6
 	.define CGWSEL_CLIP_COL_INSIDE		2 << 6
 	.define CGWSEL_CLIP_COL_ALWAYS		3 << 6

 	.define CGWSEL_NO_COL_MATH_NEVER	0 << 4
 	.define CGWSEL_NO_COL_MATH_OUTSIDE	1 << 4
 	.define CGWSEL_NO_COL_MATH_INSIDE	2 << 4
 	.define CGWSEL_NO_COL_MATH_ALWAYS	3 << 4

	.define CGWSEL_ADD_SUBSCREEN		1 << 1
	.define CGWSEL_DIRECT_COLOR_MODE	1 << 0

.define CGADSUB $2131					;Color math designation
 	.define CGADSUB_ADDSUB_COL			1 << 7
 	.define CGADSUB_HALF_COL			1 << 6
	.define CGADSUB_BAC_ENABLE			1 << 5
	.define CGADSUB_OBJ_ENABLE			1 << 4
	.define CGADSUB_BG4_ENABLE			1 << 3
	.define CGADSUB_BG3_ENABLE			1 << 2
	.define CGADSUB_BG2_ENABLE			1 << 1
	.define CGADSUB_BG1_ENABLE			1 << 0

.define COLDATA $2132					;Fixed Color Data
 	.define COLDATA_BLUE				1 << 7
 	.define COLDATA_GREEN				1 << 6
 	.define COLDATA_RED					1 << 5
	.define COLDATA_INTENSITY			$1f << 0

.define SETINI $2133					;Screen Mode/Video Select
 	.define SETINI_EXT_SYNC				1 << 7
 	.define SETINI_MODE7_EXTBG			1 << 6
 	.define SETINI_PSEUDO_HIRES			1 << 3
 	.define SETINI_OVERSCAN				1 << 2
 	.define SETINI_OBJ_INTERLACE		1 << 1
 	.define SETINI_SCREEN_INTERLACE		1 << 0

.define MPYL $2134						;Multiplication Result
.define MPYM $2135
.define MPYH $2136

.define SLHV $2137						;Software Latch for H/V Counter

.define OAMDATAREAD $2138				;Data for OAM read

.define VMDATALREAD $2139				;VRAM Data Read
.define VMDATAHREAD $213a

.define CGDATAREAD $213b				;CGRAM Data read

.define OPHCT $213c						;Scanline Location
.define OPVCT $213d

.define STAT77 $213e					;5C77 PPU-1 Status Flag and Version
 	.define STAT77_TIME_OVER			1 << 7
 	.define STAT77_RANGE_OVER			1 << 6
 	.define STAT77_PPU_SLAVE_MASTER		1 << 5

.define STAT78 $213f					;5C78 PPU-2 Status Flag and Version
 	.define STAT78_INTERLACE_FIELD		1 << 7
 	.define STAT78_EXT_LATCH			1 << 6
 	.define STAT78_NTSC_PAL				1 << 4

.define APUIO0 $2140					;APU I/O Ports
.define APUIO1 $2141
.define APUIO2 $2142
.define APUIO3 $2143

.define WMDATA $2180					;WRAM Data Port
.define WMADDL $2181					;WRAM Address
.define WMADDM $2182
.define WMADDH $2183


;cpu regs:
.define JOYSER0 $4016					;Joypad Port 1
  .define JOYSER0_DATA2					1 << 1
  .define JOYSER0_DATA1					1 << 0
  .define JOYSER0_LATCH					1 << 0

.define JOYSER1 $4017					;Joypad Port 2
  .define JOYSER1_DATA2					1 << 1
  .define JOYSER1_DATA1					1 << 0

.define NMITIMEN $4200					;Interrupt Enable Flags
  .define NMITIMEN_NMI_ENABLE			1 << 7
  .define NMITIMEN_Y_IRQ_ENABLE			1 << 5
  .define NMITIMEN_X_IRQ_ENABLE			1 << 4
  .define NMITIMEN_AUTO_JOY_READ		1 << 0

.define WRIO $4201						;I/O port output/write
  .define WRIO_JOY2_IOBIT_LATCH			1 << 7
  .define WRIO_JOY1_IOBIT				1 << 6

.define WRMPYA $4202					;Multiplicand
.define WRMPYB $4203
.define WRDIVL $4204					;Dividend
.define WRDIVH $4205
.define WRDIVB $4206					;Divisor

.define HTIMEL $4207					;H/X Timer
.define HTIMEH $4208
.define VTIMEL $4209					;V/Y Timer
.define VTIMEH $420a
  .define TIMER_RANGE					$1f

.define MDMAEN $420b					;DMA Enable
.define HDMAEN $420c					;HDMA Enable
  .define DMA_CHANNEL7_ENABLE			1 << 7
  .define DMA_CHANNEL6_ENABLE			1 << 6
  .define DMA_CHANNEL5_ENABLE			1 << 5
  .define DMA_CHANNEL4_ENABLE			1 << 4
  .define DMA_CHANNEL3_ENABLE			1 << 3
  .define DMA_CHANNEL2_ENABLE			1 << 2
  .define DMA_CHANNEL1_ENABLE			1 << 1
  .define DMA_CHANNEL0_ENABLE			1 << 0

.define MEMSEL $420d					;ROM Access Speed
  .define MEMSEL_FASTROM_ENABLE			1 << 0

.define RDNMI $4210						;NMI Flag and 5A22 Version
  .define RDNMI_NMI_FLAG				1 << 7

.define TIMEUP $4211					;IRQ Flag
  .define TIMEUP_IRQ_FLAG				1 << 7

.define HVBJOY $4212					;PPU Status
  .define HVBJOY_VBLANK_FLAG			1 << 7
  .define HVBJOY_HBLANK_FLAG			1 << 6
  .define HVBJOY_AUTO_JOY_STATUS		1 << 0

.define RDIO $4213						;I/O port input/read
  .define RDIO_JOY2_IOBIT_LATCH			1 << 7
  .define RDIO_JOY1_IOBIT				1 << 6

.define RDDIVL $4214					;Quotient of Divide Result
.define RDDIVH $4215
.define RDMPYL $4216					;Multiplication Product or Divide Remainder
.define RDMPYH $4217

.define JOY1L $4218						;Joyport1 Data1
.define JOY1H $4219
.define JOY2L $421a						;Joyport2 Data1
.define JOY2H $421b
.define JOY3L $421c						;Joyport1 Data2
.define JOY3H $421d
.define JOY4L $421e						;Joyport2 Data2
.define JOY4H $421f
  .define JOY_BUTTON_B					1 << 15
  .define JOY_BUTTON_Y					1 << 14
  .define JOY_BUTTON_SELECT				1 << 13
  .define JOY_BUTTON_START				1 << 12
  .define JOY_DIR_UP					1 << 11
  .define JOY_DIR_DOWN					1 << 10
  .define JOY_DIR_LEFT					1 << 9
  .define JOY_DIR_RIGHT					1 << 8
  .define JOY_BUTTON_A					1 << 7
  .define JOY_BUTTON_X					1 << 6
  .define JOY_BUTTON_L					1 << 5
  .define JOY_BUTTON_R					1 << 4

.define DMAP0 $4300						;DMA Control
  .define DMAP_TRANSFER_DIRECTION		1 << 7
  .define DMAP_HDMA_INDIRECT_MODE		1 << 6
  .define DMAP_ADRESS_INCREMENT			1 << 4
  .define DMAP_FIXED_TRANSFER			1 << 3
  .define DMAP_1_REG_WRITE_ONCE			0 << 0
  .define DMAP_2_REG_WRITE_ONCE			1 << 0
  .define DMAP_1_REG_WRITE_TWICE		2 << 0
  .define DMAP_2_REG_WRITE_TWICE_EACH	3 << 0
  .define DMAP_4_REG_WRITE_ONCE			4 << 0
  .define DMAP_2_REG_WRITE_TWICE_ALT	5 << 0

.define DMADEST0 $4301					;DMA Destination Register

.define DMASRC0L $4302					;DMA Source Adress
.define DMASRC0H $4303
.define DMASRC0B $4304

.define DMALEN0L $4305					;DMA Size/HDMA Indirect Adress
.define DMALEN0H $4306
.define DMALEN0B $4307

.define HDMATBL0L $4308					;HDMA Table Address
.define HDMATBL0H $4309

.define HDMACNT0 $430a					;HDMA Line Counter
  .define HDMACNT_REPEAT				1 << 7
  .define HDMACNT_RANGE					$7f

.define DMAP1		$4310
.define DMADEST1	$4311
.define DMASRC1L	$4312
.define DMASRC1H	$4313
.define DMASRC1B	$4314
.define DMALEN1L	$4315
.define DMALEN1H	$4316
.define DMALEN1B	$4317
.define HDMATBL1L	$4318
.define HDMATBL1H	$4319
.define HDMACNT1	$431a

.define DMAP2		$4320
.define DMADEST2	$4321
.define DMASRC2L	$4322
.define DMASRC2H	$4323
.define DMASRC2B	$4324
.define DMALEN2L	$4325
.define DMALEN2H	$4326
.define DMALEN2B	$4327
.define HDMATBL2L	$4328
.define HDMATBL2H	$4329
.define HDMACNT2	$432a

.define DMAP3		$4330
.define DMADEST3	$4331
.define DMASRC3L	$4332
.define DMASRC3H	$4333
.define DMASRC3B	$4334
.define DMALEN3L	$4335
.define DMALEN3H	$4336
.define DMALEN3B	$4337
.define HDMATBL3L	$4338
.define HDMATBL3H	$4339
.define HDMACNT3	$433a

.define DMAP4		$4340
.define DMADEST4	$4341
.define DMASRC4L	$4342
.define DMASRC4H	$4343
.define DMASRC4B	$4344
.define DMALEN4L	$4345
.define DMALEN4H	$4346
.define DMALEN4B	$4347
.define HDMATBL4L	$4348
.define HDMATBL4H	$4349
.define HDMACNT4	$434a

.define DMAP5		$4350
.define DMADEST5	$4351
.define DMASRC5L	$4352
.define DMASRC5H	$4353
.define DMASRC5B	$4354
.define DMALEN5L	$4355
.define DMALEN5H	$4356
.define DMALEN5B	$4357
.define HDMATBL5L	$4358
.define HDMATBL5H	$4359
.define HDMACNT5	$435a

.define DMAP6		$4360
.define DMADEST6	$4361
.define DMASRC6L	$4362
.define DMASRC6H	$4363
.define DMASRC6B	$4364
.define DMALEN6L	$4365
.define DMALEN6H	$4366
.define DMALEN6B	$4367
.define HDMATBL6L	$4368
.define HDMATBL6H	$4369
.define HDMACNT6	$436a

.define DMAP7		$4370
.define DMADEST7	$4371
.define DMASRC7L	$4372
.define DMASRC7H	$4373
.define DMASRC7B	$4374
.define DMALEN7L	$4375
.define DMALEN7H	$4376
.define DMALEN7B	$4377
.define HDMATBL7L	$4378
.define HDMATBL7H	$4379
.define HDMACNT7	$437a
Ausserdem macht es auch extrem viel Sinn, die enum/ramsection/struct-Features von wla dx zu nutzen.
Ich habe gesehen, dass du teilweise VRAM-Adressen und anderes hardgecodet hast, z.B. so:

Code: Alles auswählen

ldy #$F000.w
sty $2116
Lass doch stattdessen den Compiler diese Arbeit machen, dann musst du nicht nur weniger anpassen, wenn sich die Adressen mal ändern, es ist auch deutlich weniger fehleranfällig, simples Beispiel:

Code: Alles auswählen


.def TILEMAPSIZE $800
.enum 0
 VRAM.WHATEVER ds $4000
 VRAM.TILEMAP.BG ds TILEMAPSIZE
 VRAM.TILEMAP.TEXTLAYER ds TILEMAPSIZE1
.ende
usw.

Re: Mein Textbox-Programm

Verfasst: 25. August 2012, 20:14
von lytron
:shock:

Okay, damit habe ich nicht gerechnet. :wink:

Danke dir, wieder einmal!
Danke für die komplette Definitionsfile, ich glaube, das Ding wird mir viele Stunden Arbeit ersparen. Dazu nur zwei Verständnisfragen:

1) Was bedeutet die Pipe bei "lda #BGMODE_MODE_1 | BGMODE_PRIORITY_LAYER_3 | BGMODE_CHARSIZE_LAYER_1"? Setzt er dann die korrespondierenden Werte der drei Variablen zu einem Byte zusammen? In der WLA-DX-Readme wird die Pipe als "OR" definiert...
2) Funktioniert das aus Frage 1 nur wegen dem "3 << 2", also dem "schreib ne drei als Binärzahl und schieb das dann zwei Stellen nach links", oder klappt es auch, wenn ich %00001100 schreibe? (bzw.: Hast du da Erfahrungen?)
3) Die dritte der zwei Verständnisfragen (o_O):
Bei deinem letzten Code-Beispiel (als es um Definition einer Tilemap ging) bedeutet da das "ds" "definiere 256 Byte", oder lese ich da die WLA DX-Readme falsch? (So viele neue Befehle, waaa... :wink: )

d4s hat geschrieben:Fremden Code zu lesen ist schwer, aber mit Übung wird es einfacher.
Das macht Hoffnung! :wink:
Dank Svambos Mithilfe kann ich mich gerade am Code von MegaFamilyBros probieren; es ist schwierig, aber ich denke doch, dass es sich allmählich beschleunigt, wenn auch im Schneckentempo. :wink:
d4s hat geschrieben:rep #$31 ist nur so ne Angewohnheit. Es stimmt, ob das Flag clear ist oder nicht, ist für das folgende Programm egal.
Ah, cool. Ich möchte mal behaupten, der Carry-Flag ist sowieso sehr "sprunghaft", soll heißen: Oft genug beachtet man nicht, was er denn gerade so macht, wenn man nicht gerade die von mir frisch erlernte CMP/BCC bzw. CMP/BCS-Kombo macht. :D

... für Nichtwisser: Das ist das sogenannte "Assembler-Hadouken"... :crazy: :wink:

Re: Mein Textbox-Programm

Verfasst: 26. August 2012, 10:55
von Ramsis
lytron hat geschrieben:
d4s hat geschrieben:Fremden Code zu lesen ist schwer, aber mit Übung wird es einfacher.
Das macht Hoffnung! :wink:
Und ein kerniges Tracelog mal so zwischendurch härtet zusätzlich ab! :D

Re: Mein Textbox-Programm

Verfasst: 28. August 2012, 00:45
von bazz
I like your text box opening animation, as well as the cute "A"-Button Animation ;)

Re: Mein Textbox-Programm

Verfasst: 30. August 2012, 23:04
von d4s
lytron hat geschrieben: 1) Was bedeutet die Pipe bei "lda #BGMODE_MODE_1 | BGMODE_PRIORITY_LAYER_3 | BGMODE_CHARSIZE_LAYER_1"? Setzt er dann die korrespondierenden Werte der drei Variablen zu einem Byte zusammen? In der WLA-DX-Readme wird die Pipe als "OR" definiert...
Korrekt.
Falls du noch nicht firm im Umrechnen zwischen Hexadezimal-, Dezimal- und Binärsystem bist, hilft mit Sicherheit der Calculator deines Betriebsystems (unter Windows glaube ich calc.exe).
Zum besseren Verständnis kannst du das hier lesen:http://en.wikipedia.org/wiki/Bitwise_operation
lytron hat geschrieben: 2) Funktioniert das aus Frage 1 nur wegen dem "3 << 2", also dem "schreib ne drei als Binärzahl und schieb das dann zwei Stellen nach links", oder klappt es auch, wenn ich %00001100 schreibe? (bzw.: Hast du da Erfahrungen?)
Ja, das ist nur eine andere Repräsentation der gleichen Information.
Kannst du prinzipiell schreiben, wie du möchtest.
lytron hat geschrieben: 3) Die dritte der zwei Verständnisfragen (o_O):
Bei deinem letzten Code-Beispiel (als es um Definition einer Tilemap ging) bedeutet da das "ds" "definiere 256 Byte", oder lese ich da die WLA DX-Readme falsch? (So viele neue Befehle, waaa... :wink: )
Ja, ".def Blubb ds 256" bezeichnet, dass Blubb 256 Bytes groß ist.

Re: Mein Textbox-Programm

Verfasst: 1. September 2012, 07:36
von lytron
Ramsis hat geschrieben:Und ein kerniges Tracelog mal so zwischendurch härtet zusätzlich ab! :D
Ourgh... ¬_¬' :D
bazz hat geschrieben:I like your text box opening animation, as well as the cute "A"-Button Animation ;)
Thanks alot (and welcome on board! :applaus: ), I intended to make this thing as "complete" as possible, rather doing one thing detailed and multifunctioned than just-let-it-do-what-you-want. So, if anyone will ever use this thing, he doesn't have to bother making these animations. :)
d4s hat geschrieben: Korrekt.
Falls du noch nicht firm im Umrechnen zwischen Hexadezimal-, Dezimal- und Binärsystem bist, hilft mit Sicherheit der Calculator deines Betriebsystems (unter Windows glaube ich calc.exe).
Zum besseren Verständnis kannst du das hier lesen:http://en.wikipedia.org/wiki/Bitwise_operation
Danke für den Link, den werde ich für demnächst als Schmierzettel benutzen. Auch nochmal danke für die restlichen Infos. :)
Langsam wirds. :)

~~~

Ich werde mein Textbox-Programm entweder an diesem oder am nächsten Wochenende überarbeiten, damit es eine neue Version gibt. Es lag jetzt wegen der drei großen Zeitkiller im Leben auf Eis (Arbeit, Familie, Earthbound).

Ein To-Do für mich für die nächste Fassung ist:
- Die Whole-in-One-Funktion
- delay-Funktion
- null-Funktion
- d4s' def-file einbauen

Die delay-Funktion soll den Timer-Counter wieder auf 3 hochsetzen und den Textdaten-Counter erhöhen. Das bedeutet, der Text läuft langsamer. Wie wir alle das gerade bei Illusion of Gaia geliebt haben! ;)
Die null-Funktion soll *nur* den Timer immer wieder auf 3 hochsetzen. Das bedeutet faktisch, dass das Programm sich an der Stelle "aufhängt", weil es niemals den Befehl bekommt, den nächsten Doppelbyte aus der Textdatei zu laden.
Damit ist die null-Funktion das perfekte Pendant zur Signal-Funktion. Mit der Signal-Funktion kann die SubTextBox einer anderen Subroutine ein Zeichen geben, mit der null-Funktion kann ich darauf warten, bis eine andere Subroutine ein Zeichen gibt.
Die andere Subroutine wird manuell den Textdaten-Counter erhöhen, das wird dann das "Zeichen" sein, dass die Textbox weitermachen soll.

Beispiel:
Text in einer Textbox erscheint.
während die Ansicht (die "Kamera") nach oben scrollt (SIGNAL), erscheint kein neuer Text (NULL).
Oben angekommen läuft der Text dann weiter (MANUELLE COUNTER-ERHÖHUNG).

Das bietet auch den Vorteil, dass man damit andere Subroutinen starten kann, deren Dauer variieren kann. Ein Beispiel: In einem Action-RPG betreten die Helden den Raum; es war von der Bewegung des Spielers abhängig, wie die hinterherlaufenden Figuren stehen. Nach einigem Text will man, dass eine der Mitstreiter-Figuren an einen ganz bestimmten Punkt auf der Map geht. Da man nicht exakt weiß, wo die Figur stehen wird, weiß man auch nicht, wie lang es exakt dauern wird.

Woll?

Re: Mein Textbox-Programm

Verfasst: 31. Januar 2013, 00:25
von snoer
Ich wollt nur mal eben anmerken, dass mich das lesen deiner Beiträge ziemlich motiviert mich selbst mit dem ganzen spaß auseinanderzusetzen!
Mach bloß weiter! :)

Ich würde zwar sagen, dass ich gefühlte 120 Übungsstunden hinter dir bin, was meinen Verständnislevel angeht, aber es ist, auch wenn dir das nur bedingt hilft, ein gutes Gefühl, dass ich mich auf einem Pfad bewege der in letzter Zeit schon von jemand anderem begegangen wurde :)