Hallo Besucher, der Thread wurde 1,6k mal aufgerufen und enthält 13 Antworten

letzter Beitrag von Mac Bacon am

Adresse übergeben & Selfmod Code

  • Ich stehe mal wieder auf dem Schlauch.


    Ich will eine Routine schreiben, die mir Text an einer definierten Stelle ausgibt.
    Dazu will ich die Position auf dem Screen und den Text übergeben.


    Code
    1. txt_002
    2. !word 2 + 4 * 40 + SCRRAM ; x, y
    3. !scr "the second sentence.#"




    Die Routine will ich möglichst modular halten und nur sowas aufrufen wie


    Code
    1. lda #<txt_002
    2. sta txt_store
    3. lda #>txt_002
    4. sta txt_store + 1
    5. jsr display_text

    Die eigentliche Routine sieht dann etwa so aus (gekürzt)


    Ich scheitere daran, die hinterlegte Screenposition auszulesen und Zeile 18 über selfmod zu schreiben.
    Vermutlich denke ich wieder zu kompliziert?



    Der gewünschte Zustand sollte sein, dass ich eine "Textdatei" habe, in der jeglicher Text sowie Konfiguration (Position, Farbe, Anzeigedauer etc.) stehen:



    Und ich diese einfach an meinen Text Display Code übergebe.



    Bin für jeden Tipp dankbar.

  • Ich seh' hier nicht wo Du den Operanden SCRRAM (bei setposition+1,+2) modifizierst. Außerdem solltest Du auch noch an das Farb-RAM denken.


    Wenn Du vier Adressen in der Zeropage frei hast (und das Farb-RAM erstmal egal ist), geht das ohne Selbstmodifikation ganz easy mit einer modifizierten Kopierschleife:

    ... und Aufruf wie von dir gewünscht mit:

    Code
    1. LDA #<txt_002
    2. STA src
    3. LDA #>txt_002
    4. STA src + 1
    5. JSR display
  • Danke Mike für Deine Rückmeldung.
    Ja, in dem Beispiel habe ich SCRRAM nicht modifiziert, das war der Teil, an dem ich mir die Zähne mit meiner Methode ausgebissen hatte.


    Dein Ansatz mit der Zeropage ist gut nachvollziehbar. Ich würde es gerne ohne Zeropage schaffen, auch, damit ich aus dem Problem was lerne. Und ja, das Farbram soll später auch noch berücksichtigt werden.

  • Das sieht eigentlich soweit alles richtig aus. Wobei man statt in die Variablen txt_store ja eigentlich gleich nach setcontent+1 und setcontent+2 schreiben könnte. Der Fehler muss also wohl in dem Teil liegen, den Du nicht gepostet hast :)


    EDIT: je nach verwendetem Assembler könnte es sein, dass Dein lda $0000,x automatisch zu einem lda $00,x konvertiert wird. Nimm mal lieber lda $ffff,x, um sicherzustellen, dass eine 16-Bit-Adressierung genommen wird.

  • Im Code fehlt ja gerade die Übergabe der absoluten Screen-Adresse..? ?(


    Aufrufen würde ich übrigens so:
    lda #<txt_002
    ldy #>txt_002
    jsr Display_Text


    Und in der Display_Text Routine dann sofort
    sta setcontent+1
    sty setcontent+2



    Dann sparst du dir fast die Hälfte deines zweiten Quellcodes :)


    Edit: Oh, wieder zu langsam beim Posten gewesen...

  • Stimmt, damit könnte ich es noch weiter kürzen, gute Idee. Muss ich aber noch schauen wie ich das mit der Idee, den Stack da vorher zu retten, sauber hinbekomme.


    Hier nochmal alles zusammenhängend (sind effektiv aber mehrere Files):



    Was nach wie vor fehlt und mein eigentliches Problem ist: wie bekomme ich die Werte aus den Zeilen 52 und 57 ausgelesen und überschreibe die SCRRAM Adresse in Zeile 34?

  • Aha, Du willst also hintereinander immer erst die Zieladresse und dann den Text speichern. Das ginge dann so:


    EDIT: verkackt ^^ . Das wird mit selbstmodifizierendem Code sehr hässlich, dafür wären Zeropage-Pointer wirklich wesentlich einfacher...


    EDIT2: Grund ist, dass Du ja mehrmals auf den Bereich auf den txt_store zeigt zugreifen musst. Zweimal für den Pointer auf die Screenposition (low und high byte) und dann noch auf den Text. Dadurch müsstest Du die entsprechenden Adressen an drei Stellen selbstmodifizierenderweise hinschreiben (also 6 Bytes kopieren). In der Zeropage müsstest Du sie nur einmal setzen und kannst dann per Y-Register auf die drei verschiedenen Offsets zugreifen.

  • EDIT: verkackt . Das wird mit selbstmodifizierendem Code sehr hässlich, dafür wären Zeropage-Pointer wirklich wesentlich einfacher...

    Haha, ja, es scheint so. Nunja, zumindest beruhigt mich, dass ich keine völlig triviale Lösung übersehen habe.
    Ich komme also um eine Zeropage Verwendung nicht herum wie es scheint...

  • Die ZP Methode + ein wenig Selfmod ist wirklich einfacher. Vergiss nur nicht, dass dein y schon bei #2 ist, wenn der erste Buchstabe kommt. Daher muss deine Text-Ziel-Adresse im Idealfall schon -2 sein. Oder du korrigierst den ZP Vector danach "zwei weiter"...


    Fall deine Text-Positionen nie mehr als 256 Zeichen auseinanderliegen (z.B. nur im oberen Viertel des Screens), dann kannst du auch statt zwei Bytes für die Adresse nur ein Byte für die Anzahl der Zeichen nach rechts nutzen. Dann wäre ein Aufruf wie dieser möglich:


    lda #80 ;Zwei Zeilen unter der Standardposition für Text
    ldy #<Text
    ldx #>Text
    jsr Display_Routine

  • Da man die selbstmodifzierte Adresse für mehrere Zwecke braucht (Adresse in den ersten 2 Bytes) und dann den String, bietet sich an, das Byte-holen in eine Routine auszulagern. Sonst müsste man an mehreren Stellen die Adresse im Code ändern (getbyte).
    Dann kann man bequem die Daten der Reihe nach lesen und auch setposition entsprechend setzen.


    Wie schon zuvor in einem anderen Posting angemerkt, kann man eigentlich txt_store = setcontent+1 setzen und erspart
    sich das Umkopieren in Zeile 7-10. Dann modifiziert der Aufrufer schon den Code. ;)
    Elegant ist freilich auch der andere Vorschlag, das in X und Y zu übergeben (sofern man die Register in diesem Aufrufkontext dafür beschmutzen möchte/kann).

  • Da man die selbstmodifzierte Adresse für mehrere Zwecke braucht (Adresse in den ersten 2 Bytes) und dann den String, bietet sich an, das Byte-holen in eine Routine auszulagern. Sonst müsste man an mehreren Stellen die Adresse im Code ändern (getbyte).


    Das ist auch smart, gute Idee.


    Ich habe noch eine andere Variante ausprobiert, die nicht mit Labels als Sprungadressen, sondern relativ arbeitet, das würde den Code noch etwas modularer halten, grob und unfertig angedacht wäre das so



    Aufruf aus dem main code wäre dann einfach


    Code
    1. jsr txt_001


    Aber ich weiß nicht, wie ich z.B. in Zeile 28 und 29 ähnlich verfahren kann wie in den Zeilen 35 und 36.


    Ich werde aber alle Tipps nochmal zusammensammeln und testen.

  • Wieso willst du Label einsparen? Die kosten doch nix :)


    Ps: Du beendest deinen Text immer mit #, kannst das Zeichen also nie als Text benutzen. Wenn du statt # zum Beispiel $ff abfragst stehen dir alle Schriftzeichen zur Verfügung. Einfach nach jedem Text ein
    !byte $ff
    schreiben.

  • Wieso willst du Label einsparen? Die kosten doch nix

    Das stimmt, aber wenn ich die Label spare kann ich den Teil eventuell wieder modular machen und auslagern. Sonst hätte ich immer die Nummerierung des Textes im Label als Zuordnung.



    Wenn du statt # zum Beispiel $ff abfragst stehen dir alle Schriftzeichen zur Verfügung. Einfach nach jedem Text ein
    !byte $ff

    Das stimmt auch, obwohl $ff ja auch ein Schriftzeichen wäre. Ich wollte es erstmal so bequem halten, wenn ich das # wirklich noch brauchen sollte, ändere ich es. Danke aber für den Hinweis.

  • Wenn maximal 256 verschiedene Strings im Programm verwaltet werden, kann die Auswahl auch durch ein einzelnes Register erfolgen, das macht die Aufrufe deutlich(!) kürzer.
    Nachteile:
    - Man braucht eine zusätzliche Tabelle mit den eigentlichen Zeigern (nein, das frisst die obige Ersparnis nicht auf)
    - Man hat globale Tabellen, kann die Strings also nicht schön modular im Source verteilen (mit fieser Macro-Magic kann man das abmildern, aber das ist ein Thema für einen Extra-Thread)


    Diese Technik kann man natürlich auch für beliebige andere Datenstrukturen anwenden. Für Spielerdaten bei Mehrspieler-Spielen macht das vermutlich jeder automatisch so, bei anderen Daten (wie z.B. Fenster- oder Menüdefinitionen) muss man erst einmal grundlegend umdenken - von anderen Sprachen ist man ja Objekt-Orientierung gewohnt, und da der 6502 keine Zeigerregister kennt, muss man diese entweder nachbilden (wie bisher im Thread) oder man verzichtet absichtlich darauf (wie bei dieser Tabellentechnik).