Da im Ergebnis die Assembler-Sources nicht mit dabei waren, hiermit nachgereicht. Ich würde alles Sources gerne gesammelt haben. Auch wenn's recht mühsam ist, das jetzt allle ihren Sourcecode einzeln hier posten müssen und man das so einsammeln muss ...
Bei der Vielzahl der 4x-Lösungen hat meine 50er-Lösung zwar nur Rang 8 erreicht. Hier der Vollständigkeit halber auch der Sourcecode:
- ; ### BASIC-Intro
- *= $0801
- start = entry
- basic_start
- ; ZN SYSnnnn
- !by <EOP,>EOP,<(src),>(src),$9E
- ; Zeilennummer entspricht Wert von scr
- !by '0' + start % 10000 DIV 1000
- !by '0' + start % 1000 DIV 100
- !by '0' + start % 100 DIV 10
- !by '0' + start % 10
- !by 0 ; End of Line
- EOP !by 0, 0 ; Basic-Programmende
- ; ### HAUPTPROGRAMM
- ; Quell-Sprite-Index Y startet bei 0
- newbytecolumn
- inc columnstart ; Low-Byte in "ror dst,x"!
- ; C=1 implizit, als Markierung in "Zähler" v:
- ; Byte im Ziel-Sprite 8 mal rotieren, v ist Zähler,
- ; Inhalt aber egal, Start-Bit ist gesetztes Bit 7,
- ; das nach 8 mal.
- pixelcolumn
- ; C=0 implizit
- ror v ; Höchstwertiges Bit muss 8 mal geschoben werden.
- ; -> C=1, das Markierungs-Bit.
- beq newbytecolumn ; Nach 8 mal ist es leer, d.h. Byte-Spalte ist fertig.
- entry
- ldx #60+3 ; Vertikale Startposition im Ziel-Sprite,
- ; +3 damit auf 0 endend.
- byte
- iny ; Quell-Sprite-Index: horizontal zum nächsten Byte.
- ; Spalte 22-24 des Ziel-Sprites wird abgeleitet
- ; aus Zeilenposition des Quell-Sprites (Zeile 22-24).
- cpy #sprlen+1 ; 1 - 63 tatsächliche Quell-Sprite-Daten
- ; < sprlen+1 ?
- bcs + ; Nein: A immer 0, als Quelle für Pseudozeilen 22-24.
- lda (zs),y ; Ja: Tatsächliches Byte aus Quell-Sprite (Zeile 1-21).
- sec ; Höchstwertiges Bit zuerst, Bit-Zähler (8x).
- + !by $24 ; Folgendes CLC ignorieren (BIT zp).
- getpixel
- clc ; 0-Bit nachschieben bis das Byte 0 ist.
- rol ; Quell-Sprite-Byte (horizontal) nächstes Bit.
- beq byte ; Alle 8 Bits durch?
- setpixel
- ; Position für Code-Modifikation,
- ; Low-Byte von dst wird inkrementiert.
- dst_1 rol dst,x ; Pixel aus Carry vertikal, erst nach 8 Durchläufen an
- ; richtiger Position.
- dex ; Ziel-Sprite vertikal eine Zeile nach oben bis Spaltenende.
- dex
- dex
- bne getpixel ; Spaltenende (ganz oben) erreicht?
- ; X endet immer auf 0, brauchen wir noch für A, da
- ; bei A Bit 7-6 unbestimmt, Bit 5 (Markierung)gesetzt ist,
- txa ; also damit sicherstellen, dass A wirklich immer 0 ist.
- nextpixelcolumn
- cpy #sprlen+9 ; Zeiger auf Quelle-Sprite<Ende eines fiktiven 24x24-Sprites
- bcc pixelcolumn ; wenn kleiner, dann gilt C=0, A=0.
- exit
- rts
Neben der obligatorischen $39-Einsparung, ist der Spaltenzähler wie bei anderen auch als 8-Shift-Zähler ausgebildet. Dieser bekommt seine Grundinitialisierung von Exponent der letzten Floatingpoint-Zahl (Auswertung des Sys-Ausdrucks), welcher als positiver Wert immer >= $80 ist. Das gesetzte Bit 7 brauche ich als initialen Zustand (Rest egal).
Für den Optimierungschritt in Zeile 38. bis 41. war der Wald vor lauter Bäumen nicht mehr zu sehen.
Also statt
sec
!by $24
loop
clc
rol ...
beq byte
dann
sec
loop
rol ...
clc
beq byte
scheint jetzt so offensichtlich.
Acorns tolle Lösung schaut für mich jetzt so klar aus, als hätte nie eine andere geben können.
Wie dort noch $B2 für X zu nehmen und Y in Ruhe zu lassen, damit damit A löschen kann (ich hab da X verwendet und damit die X-Ansätze von Acorn verbaut), ist das, was ja bereits im Thread erwähnt wurde: Wenn man stecken bleibt, noch mal von Null weg das Programm neu schreiben, statt das bestehende versuchen zu optimieren.
Also wirklich tollle Erkenntnisse, die die Compo hier geliefert hat. Danke an peiselulli als Ausrichter und an alle, die hier mitgemacht haben!