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

letzter Beitrag von oobdoo am

OT: Neue C64 ASM/Basic Compo : Dreh' das Sprite [Alternative Systeme]

  • Und hier noch ein Beispiel auf die Schnelle in Loco Basic.


    20x20 Pixel Fantasie Bitmap gedreht.


    Die Verzerrung kommt durch mode 2 wo ja auch das 8x8 Zeichen Raster hochkant aussieht obwohl es quadratisch ist.


    Das Gute an Basic ist, dass ich mich hier wirklich nicht um den Hardware Aufbau des Screen RAM scheren muss.


    Es ist sozusagen das gedrehte Mühle Spiel von dem ich gesprochen habe.

  • so oobdoo nu hast du die ersten 8x8bit richtig gedreht. nun nimmst du dieses und aenderst 1.das offset der zu drehenden bytes. 2. die zielbits.


    ich verstehe ehrlich gesagt nicht wo das problem liegt der Z80 bringt alles mit was der 6502/10 auch mitbringt. rol ror is das
    stichwort und natuerlich das carry flag. der Z80 hatt sogar noch mehr bitshifting/rolling optionen soweit ich das von hier
    http://jgmalcolm.com/z80/advanced/shif.htm aus beobachten kann.


    wenn das dann laeuft kann man sich gedanken um andrer loesungen machen.


    also oobdoo jetzt bitte ma butter bei die fische ;D


    hier mal mein versuch einer 1:1 uebersetzt von 6502/10 asm zu Z80 asm, ungetestet da ich kein Z80 fachmann bin.
    dabei geh ich davon aus das der spicher bei C genullt ist


    sicher das funkt nur in den ersten 256 bytes aber das schema sollte ungefaehr klar sein(hoffe ich).

  • Da ich glaube, dass die CPC Lösung mit der C64 Compo eigentlich zu wenig zu tun hat, auch vom Konzept her, finde ich kann ich die CPC Lösung hier auch vor Compo-Ende posten, und zwar als dsk Datei, die man selber laden muss und den Inhalt selber listen. Das ist denke ich genug "Kopierschutz" und der Inhalt hat wie gesagt mit der C64 Compo zu wenig zu tun als dass man Rückschlüsse ziehen könnte wie man am C64 ein Sprite gemäß Compo Regeln dreht.


    Gestartet wird mit run"dreh


    Menupunkt 1 zeigt die "toten" 48 Byte-Blöcke im Screen RAM, die immer direkt hinter dem letzen Byte des sichtbaren Bildschirmbereichs beginnen und sich alle 2000 Bytes wiederholen.


    Menupunkt 2 füllt den Bildschirm byteweise mit $ff. Immer ein weiteres Byte pro Tastendruck. Man erkennt gut das zeilenweise füllen mit "Zeilensprung". Immer wenn man unten angekommen ist, bemerkt man, dass das Füllen 48 Drücke lang nicht weitergeht, weil man wieder einen "toten Bereich" erwischt hat.


    Menupunkt 3 zeigt das Setzen einzelner Bits von links nach rechts mit jedem Tastendruck. Hier verhält sich der CPC in Mode 2 (HighRes) ähnlich wie ein C64 Sprite.


    Menupunkt 4 gibt das Dreh-Experiment in Post 42 wieder. Es wird dabei zuerst ein Data-Bereich ausgelesen und geplottet. Der Data-Bereich enthält die zu setzende Farbe, das Plotten selbst passiert per doppelter For-Next-Schleife. Dann wird mit Restore der Data-Bereich zurückgesetzt und der Data-Bereich erneut in ein Array eingelesen. Während des Einlesens wird bereits gedreht, so dass die Farbdaten am Ende "gedreht" im Array stehen. Das Array wird dann im Grunde genauso geplottet wie davor die Datas. Das "Drehen" erfolgt nach dem Prinzip "gedrehtes Mühlespiel" oder auch "um 90 Grad gedrehtes Opatkono-Spielfeld". Haubitze dreht um 180 Grad, das ist der einzige Unterschied. Hier braucht man kein AND,OR oder ROL. Es ist nur Umplatzieren von Steinen.


    In Assembler sieht das Ganze beim CPC völlig anders aus und da bin ich auch völlig überfragt. Nur muss man da eben die Hardware etwas stärker im Blick haben als in Basic, was ja bei oobdoo der Fall zu sein scheint. Vielleicht kann man am Ende mit MJs Hilfe eine ASM-Lösung hier posten. Ich selber bin da noch zu unerfahren, was die Hardware und den Z80 angeht.

  • Da ist es besser auf ne weitere Lösung von M.J. zu warten. Der schüttelt Z80 Code mal eben so aus dem Ärmel.

    Seit wann das denn?? Davon weiß ich ja gar nichts... 8|
    Okay, ich hab Dir mal eine Versuchslösung zugeschickt. Verglichen mit dem 6502 (also mit Header und Ladeadresse) käme sie auf 53 Bytes. Das hat folgende Gründe:
    1.) Ich bin kein Z80-Experte.
    2.) Die Zeiger müssen komplett initialisiert werden.
    3.) Es gibt kein vorhergehendes Löschen der Register in der Form A=X=Y=0.
    4.) Sprünge bezogen auf das Vorzeichen sind 1 Byte länger als beim 6502.
    5.) Man kann mangels Register-indizierter Adressierung nicht so gut mit dem Index tricksen.

  • Gestartet wird mit run"dreh

    Das schaue ich mir erst an wenn die Compo vorbei ist.


    Ich selber bin da noch zu unerfahren, was die Hardware und den Z80 angeht.

    Nö, das sehe ich anders. Du hast doch schon mehrfach bewiesen das Du den Aufbau vom Bildschirmspeicher verstanden hast.


    Seit wann das denn?? Davon weiß ich ja gar nichts... 8| Okay, ich hab Dir mal eine Versuchslösung zugeschickt. Verglichen mit dem 6502 (also mit Header und Ladeadresse) käme sie auf 53 Bytes. Das hat folgende Gründe:
    1.) Ich bin kein Z80-Experte.

    :blah!


    Natürlich bist Du Experte. Und sag nicht das wäre anders. Das hast Du schon mehrfach hier im Forum bewiesen. ;)


    Wie schon in der Mail geschrieben, werde ich da erst reinschauen, wenn die Compo zuende ist. Noch ist mein kleiner Ehrgeiz nicht ganz verschwunden.
    Zumindest alleine hinbekommen wollte ich das schon, ohne auf die Größe zu achten.

  • Hab mich über die 6809-Version her gemacht. Hab mich an meiner Version und an jener von Gewinner Acorn orientiert und versucht das mit all der "dirtyness" hinzubekommen. Ich hab eine 6809-Simulationsumgebung mit der ich auch für einen Dragon 32 programmiere.
    Ich hab's aber bislang nur im Simulator probiert bzw. laufen lassen. Das PRG-File das der Assembler generiert ist eingebettet in einer Simulator-Umgebung, die dem PRG vermittelt, es würde in einer BASIC-Umgebung aufgerufen werden, mit den gewissen Randbedingungen, wie sie in der Compo ausgenutzt wurde, so eine Mischung zwischen Dragon 32 ColorBASIC-Umgebung und einem fiktiven C64 (der mit einer 6809-CPU laufen würde).


    sprite-drehen.lst.txt (hier sieht man den erzeugten Code und die Label-Werte (PRGSIZE!)


    sprite-drehen.asm


    Ergebnis: Das PRG hätte 48 Bytes (PRGSIZE $30), das sind als 5 Bytes mehr als die Gewinner-Lösung Acorns. Genauso die 3 BASIC-Ende-Bytes eingespart und von gewissen Voraussetzungen der Umgebung in der Zero-Page bzw. Direct-Page (wie es beim 6809 heißt) ausgegangen.


    Trotz gewisser Verwandschaft der 68xx-Linie zum 6502, schafft es auch ein 6809 mit dem komfortableren Befehlsatz nicht, für eine solche Aufgabe ganz so platzsparend zu sein. Oder gerade deswegen eigentlich nicht. :rolleyes: Eine Aufgabe, wo die Werte sich im Bereich <256 Bytes bewegen, da ist der 6502 kaum zu schlagen. Die Aufgabenstellung hat zudem den 6502 so begünstigt, dass man viele Flag-Zustände so nebenbei ausnützen kann.
    Anders beim 6809: Der plagt sich mit seinen 16-Bit-Index-Registern, die man auch mal laden muss, die Adressierungsarten sind mannigfaltig, aber nicht gerade so praktisch bzw. verbrauchen durch zusätzlich Postbytes im Opcode zusätzlich Platz. Schon alleine das CLC oder SEC ist je ein 2-Byte Opcode! Und bei Vergleichen und Substraktion ist die Carry-Bedeutung umgedreht, wodurch sich weniger Nebenwirkungen ausnutzen lassen. Damit gehen etliche Bytes an den 6502 verloren. Ein paar Goodies, wie Autoinkrement oder Subtraktion ohne Carry, Register auf 0 setzen und mehr Registerauswahl können nur den Schaden verkleinern, aber nicht wettmachen.
    Ich bin mit dem 6809 nicht so aufgewachsen, wie mit dem 6502, aber es ist denkbar, dass es noch etwas zum herausholen gibt. Aber die Nähe zur 6502-Lösung lassen für mich vermuten, dass da nicht mehr viel Spielraum ist. :D


    Eine 65816-Version hab ich mir noch nicht eingehend überlegt, aber da kann man m.M.n. nicht mehr viel gewinnen, wenn überhaupt. Die breiteren Register, zusätzliche Bit-Befehle und Adressierungsarten bringen hier überhaupt nichts. Ob STZ noch was bringt? Vielleicht noch eher der doppelte Akku (z.B. tauschen mit XBA) ...


    Hat jemand jetzt eine Z80-Variante?

  • Die 32-Bytes ohne Basiczeile sind schon eine Hausnummer.
    Da der 68K für jeden Befehl 16-Bit benötigt, glaube ich nicht das man damit den 65xx schlagen kann.


    Bin gespannt ob M.J. auf dem Z80 eine kürzere Routine schreiben kann (hat), vor allem da er fast die gleiche Routine mit der selben länge auf dem 65xx geschrieben hat.


  • Bin gespannt ob M.J. auf dem Z80 eine kürzere Routine schreiben kann (hat), vor allem da er fast die gleiche Routine mit der selben länge auf dem 65xx geschrieben hat.

    Ich weiß es. :saint:

  • Das PRG hätte 48 Byte

    Wow! Ihr seid alle wahnsinnig! :D

    M.J. hat eine, die soll er aber selber veröffentlichen.

    Hättest Du ruhig machen können. Hat kein Copyright. ^^

    Bin gespannt ob M.J. auf dem Z80 eine kürzere Routine schreiben kann

    Nee, M. J. ist kein Z80-Experte. ^^ Der nachfolgende Code entspricht noch ungefähr einer alten Lösung. Nachteilig war, daß die Initialisierung hinzugenommen werden mußte.

    Ein weiterer Nachteil des Z80 ist, daß ein Sprungbefehl, der auf das Vorzeichen testet, 3 Bytes braucht. Die kurzen Sprungbefehle gibt es nur für C, Z und als unbedingter Sprung. Da ich dies nur recht schnell konvertiert habe, gehe ich davon aus, daß da noch was rauszuholen ist. So habe ich z. B. noch nicht durchgespielt, wie es wäre, wenn man wie beim 6502 den Akkumulator gleichzeitig als Datenpuffer und (unter Einbeziehung des Carry) als Bitzähler verwendet.

    Da der 68K für jeden Befehl 16-Bit benötigt, glaube ich nicht das man damit den 65xx schlagen kann.

    Hmm... Interessanter Gedanke. Sollte man mal ausprobieren. Die Sprungbefehle wären ja gleich lang. Auch bei dem Dekrementieren könnte man ein Byte sparen (SUBQ #3, Ax), was man woanders verwenden könnte/müßte. Auch das Laden des Quellbytes dürfte kurz werden (MOVE.B (Ax)+, Dx). Problematisch bei alldem ist jedoch, daß Operationen auf ein Adreßregister keine Auswirkung haben auf CCR, um z. B. gleichzeitig das Vorzeichen des Lowbytes der Adresse zu testen. Daher würde man hier eher auf einen zusätzlichen Zähler ausweichen: SUBQ #1, Dx : BPL weiter : MOVEQ #0.
    Alles in allem könnte es vielleicht gar nicht so viel länger werden, mit Ausnahme der Initialiserung.


    P.S.: Ich sehe gerade, daß es wohl möglich wäre, im Z80-Code noch ein Byte zu sparen:

    Code
    1. bit 7, l ; Ist das Lowbyte der Adresse jetzt $80 ==> kein Sprung
    2. jr Z, ?0

    Man sieht, wenn man sich nicht mehr sklavisch am 6502-Code orientiert, sondern mehr auf den Z80 einläßt, kann man noch besseren Code schreiben. ^^

  • Red nich.

    Übertreib nich. :schande: Am obigen Beispiel kann man ja schon ablesen, wie ich mich selber korrigieren mußte. ^^

    vor allem da er fast die gleiche Routine mit der selben länge auf dem 65xx geschrieben hat.

    Das fand ich bei der letzten Compo besonders faszinierend: daß zwei Leute tatsächlich die gleiche Lösung hatten. Ich weiß ja nicht, wie das bei Dir war, ob Du sofort beim ersten Mal direkt auf die Lösung gekommen bist, aber ich habe dafür mehrere Schritte gebraucht. Und auch jeden dieser Schritte konnte ich in vergleichbaren Lösungsansätzen der anderen Beiträge wiedererkennen. So war auch der Algorithmus von thrust2600 mit dabei, aber anders als ihm war es mir nicht gelungen, diesen weiter zu optimieren. Nur deswegen hatte ich dann nach weiteren Möglichkeiten gesucht. Das wirft natürlich die Frage auf, ob es vielleicht auch möglich wäre, mit genetischer/evolutionärer Programmierung und viel Rechenpower die Aufgabe zu lösen. ^^

  • Also bei dem Thema kann ich mitreden

    Super Lösung. Hier haben wir mal einen echten Experten. Dies ist wieder ein Beispiel, wie 6502-Denken eine gute Lösung für den Z80 blockiert. Der 6502 kennt ja nur den RTS-Befehl, was zu Folge hat, daß man als 6502-Programmierer nur selten überhaupt auf die Idee kommt, die anderen RET-Befehle einzusetzen.
    Frage: Findest Du vielleicht noch andere Stellen, die man optimieren könnte?

  • oobdoo: Ich guck mir das Ganze normalerweise lieber aus sicherer Entfernung an :D
    Konnt nur grad nicht widerstehen, obwohl M.J. ja erwähnte, das er die Routine nicht weiter optimiert hat.


    M.J.: Ich schau bei Gelegenheit noch mal nach. Bin jetzt aber auch kein Z80-Guru (und eine Vollniete wat 6502 angeht).