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

  • Okay, Korrektur der Korrektur. Meine letzte Überlegung war Grütze, aber die Korrektur von utz war goldrichtig. Hier eine überarbeitete Version ohne Basic-Header aber mit Initialisierung (35 Bytes):

    Quellcode

    1. drehen:
    2. ld de, $340 ; Zeiger auf Originaldaten
    3. ld hl, $380 + 60 ; Zeiger auf die unterste Zeile und Spalte links
    4. ?0: ld b, 8 ; Zähler für die 8 Bits pro Spaltenbyte
    5. ?1: push hl ; Zeiger auf unterste Zeile (+ Spalte!) sichern
    6. ?2: ld a, (de) ; Original Spritewert holen
    7. inc e ; Erhöhe Zeiger auf Originaldaten
    8. jp P, ?3 ; Liegt der Zeiger bereits über $380 ==> nur noch 0 als Wert laden
    9. xor a ; Akku löschen für E >= $80 (Negativ!)
    10. ?3: scf ; setze Carry
    11. ?4: adc a ; Shifte Bit nach links ins Carry (Achtung: Nur ADC testet auf 0, nicht RLA!)
    12. jr Z, ?2 ; Bei 0 neues Byte holen
    13. rl (hl) ; übernehme Bit in die Zieldaten
    14. and a ; lösche Carry
    15. dec l ; Dekrementiere den Zeiger auf die Zieldaten um 3
    16. dec l ; Zeiger := Zeiger - 3
    17. dec l ; Dies setzt den Zeiger auf die nächst höhere Zeile
    18. jp M, ?4 ; Ist der Zeiger über $380 ==> weitermachen, ansonsten Ende der Schleife
    19. ld a, l ; sichere den aktuellen Stand des Zeigers
    20. pop hl ; Zeiger wiederherstellen
    21. djnz ?1 ; Alle 8 Bit der Zieldaten pro Spalte übernommen?
    22. inc l ; Erhöhe den Zeiger der Zieldaten auf die nächste Spalte
    23. inc a ; letzte Spalte überschritten?
    24. ret M ; utz Optimierung
    25. jr ?0
    Alles anzeigen
    Wichtig hierbei ist, daß man nicht den Befehl "RLA" verwendet, sondern stattdessen "ADC a", da RLA das Z-Flag nicht setzt.
  • M.J.: Ich hab grad keine Zeit, mich da reinzuvertiefen, aber ein paar Ideen hätt ich:
    1) Wie wärs denn, wenn man die Originaldaten bei $3c0 und die Zieldaten bei $400 ablegt? Dann würden sich die Sign-Checks ja erledigen und man könnte einfach auf Z testen.
    2) Da muß es doch irgendwo eine Möglichkeit geben, den allseits beliebten "sbc a,a\ and irgendwas"-Trick einzubauen?

    daybyter: Ja, länger dank FP-Zahlen. Dem Spectrum kann man dann wenigstens die FP-Zahlen abgewöhnen mit RANDOMIZE USR "adresse".
  • 1.) Leider kann man die Adressen nicht ändern, da sie als Bedingung für die Compo so festgelegt worden sind.
    2.) Den Trick kannte ich noch gar nicht. Naja, bin halt kein Experte. Ich nehme an, damit sollen in Abhängigkeit vom Carry beliebige Bits in A gesetzt werden. Hab mal drüber nachgedacht, wie man sowas verwenden könnte, aber keine Möglichkeit gefunden. :( Wenn ich das richtig sehe, ließe sich die Methode nur anwenden zum Setzen der Bits im Ziel. Dies geschieht jedoch bereits durch den ROL-Befehl, und kürzer als der dürfte es nicht gehen. Den Trick werde ich mir aber auf jeden Fall merken. Wer weiß, wozu ich den noch gebrauchen kann. Hab Dank dafür! :thumbsup:
  • M. J. schrieb:

    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.
    BTW, das sind in etwa auch die Punkte die den 6809 treffen.
    Naja, in der Größenordnung, wo der Netto-Code nur noch um die 32 Byte ausmacht, da macht es schon einen Unterschied, ob man im Schnitt dann ca. 16 oder 24 Befehle für die Aufgabe zur Verfügung hat. Also so optimistisch wäre ich beim 68k nicht, dass man da wirklich nahe hinkommt ... ;)
  • utz schrieb:

    daybyter: Ja, länger dank FP-Zahlen. Dem Spectrum kann man dann wenigstens die FP-Zahlen abgewöhnen mit RANDOMIZE USR "adresse".
    Äh, das muß natürlich RANDOMIZE USR VAL "<adresse>" heißen.

    M.J., ok, das mit den vorgegebenen Adressen hatte ich übersehen. Schade eigentlich :o Ich denk, bei dem Code geht definitiv noch was. Da müßte man vermutlich aber ein paar ausführlichere Umbauarbeiten vornehmen. Ich hab wie gesagt gerade nicht genug Zeit, aber ich schau mir das die Tage sicher noch mal an. Könnt mir auch vorstellen, daß man zb mit ex de,hl zwischen Quelle und Ziel umschaltet und somit den Zwischenschritt über den Accu umgeht.

    JeeK: Wenn Du Spaß haben willst, kannstes ja mal aufm Fairchild F8 versuchen :D
  • daybyter schrieb:

    Habt ihr euch mal die z80 Illegals angeguckt, ob da noch was hilfreiches bei ist?
    Hatte daran gedacht, aber nur kurz, da ich davon ausgegangen bin, daß die illegalen Befehle zu lang sind. In der Regel setzen sie ein Zusatzbefehlsbyte voraus ($dd, $ed, $fd, $cb) und sind damit 1 oder in Kombination 2 Bytes länger als ein regulärer Z80-Befehl. Was die zusätzlichen Register XL oder YH anbelangt, so lohnen sich diese gar nicht erst, solange die normalen Register noch nicht voll ausgelastet sind. (Das Register C ist immer noch frei.)
  • An die (IX + d)-Befehle hatte ich in anderem Zusammenhang auch schon gedacht, nämlich um die Basisadresse dadurch so zu verschieben, daß sie in einen Bereich kommt, wo man sie leichter testen kann. Das Problem bei (IX + d) ist aber, daß jeder Zugriff darauf gleich 3 Bytes verschluckt: 1.) $dd/$fd, 2.) Offset, 3.) eigentlicher Befehl. Außerdem braucht ein "INC XL" 1 Byte mehr als ein "INC E". Das ergäbe bei der Quelle keinen verwertbaren Vorteil. Beim Ziel hingegen bleibt ein "ROL (HL)" mit nur einem Byte wahrscheinlich unschlagbar. Für eine Selbstmodifikation müßte man ein Register (z. B. HL) zu Beginn mit der Adresse des zu verändernden Codes laden, da der Z80 nicht direkt auf den Speicher zugreifen kann, was 3 zusätzliche Bytes frißt. :/ Wie schon beim 6502 hat man beim Z80 zunächst das Problem, die Schleifen möglichst kurz zu halten. Dabei hilft einem der Befehl DJNZ ganz gut mit nur 4 Bytes für Initialisierung, Dekrementieren und Sprung. Auch die Bitschleife über die Quelle läuft jetzt ähnlich wie beim 6502 (insgesamt 4 Bytes ohne ADC a). Störend beim Z80 sind dann aber noch die PUSH und POP-Befehle für die Zieladresse, die ich eingebaut habe, da der Z80 keine Indexregister hat und daher die Basisadresse verändert, die deswegen anschließend auch wiederhergestellt werden muß. In der letzten Version könnte man wohl PUSH und POP ersetzen durch ein LD C, L bzw. LD L, C zum Retten und Wiederherstellen von L, doch bringt dies bis auf die Geschwindigkeit keinen Vorteil.