Kannst du mal zeigen in den Anfängen wie der Char wandert?
Code für bitweises Verschieben von Character a -> b optimieren
-
aitsch -
30. Oktober 2019 um 11:14 -
Erledigt
Es gibt 35 Antworten in diesem Thema, welches 13.205 mal aufgerufen wurde. Der letzte Beitrag (
-
-
So, ich konnte mich am WE endlich wieder mit dem Programm auseinandersetzen.
Dabei habe ich mich hauptsächlich an den Vorschlägen von Acorn und JeeK gehalten.
Da die Zeichen im Speicher hintereinander liegen, kann man hoch/runter auch mit Selfmod-Code kürzen.
Deine Variante ist eigentlich mein Favorit, weil sie schön klar und übersichtlich ist.
Da ich die Adressen (CHAR_AB, CHAR_CD,...) nicht als Konstanten definiert habe sondern vorher ermitteln und setzen muss fallen die Vorteile leider wieder unter den Tisch.
Ich brauche so über 20 Bytes mehr als zuvor.
Alles anzeigenHat noch jemand eine gute Idee für hoch/runter ?????
( JeeK : Deinen Vorschlag muss ich am WE noch etwas genauer studieren)
Der selbstmodifizierende Code ist eigentlich auch nicht wirklich meines. Ich hab's versucht in Anlehnung an die Rechts/Links-Bewegung.
Ich selbst würde es eher so machen. Für die Bewegung rauf runter sind die beiden Zeichen übereinander angeordnet, oder?
D.h. du hast die eine Schleife über 7 Schritte gemacht, die in beiden Zeichen gleichzeitig nach oben (bzw. unten) kopiert.
Nur das eine Byte das von einem Block in den nächsten wandert muss gesondert behandelt werden. Ganz unten (oben) kommt eine 0 rein.
(das erklärt auch meine Frage zuvor)
Das PHA/PLA braucht man dann nur, um eben den "Übertrag" von einem Block zum nächsten zu machen.
Der Ansatz ist der, dass man nicht mit 2 ZP-Pointer, sondern mit 4 arbeitet, wobei 2 schon entsprechend versetzt sind.
Da muss man dann nicht mehr mit den Indizes herum tun.
Code
Alles anzeigen.shift_char2tmp lda #$18 ; High Byte für die Adressen sta zp+1 sta zp2+1 sta zp3+1 sta zp4+1 ldy character_no lda lowbyte_tmp,y sta zp2 ; LowByte für das Ziel sta zp4 ; LowByte für Ziel um 1 versetzt inc zp4 ; zp4 = zp2+1 bne .no_overflow_zp4 inc zp4+1 .no_overflow_zp4 lda lowbyte_char,y sta zp ; LowByte für die Ausgangsposition sta zp3 ; LowByte für Ausgangspos. um 1 versetzt inc zp3 ; zp3 = zp+1 bne .no_overflow_zp3 inc zp3+1 .no_overflow_zp3 ldy #7 lda DIR ; Bewegungsrichtung laden ... .scroll_d dey ; 6 - y ist eingangs immer auf 7 lda (zp3),y pha ; unterste Zeile kommt in den nächsten Block .loop_down lda (zp),y ; von Zeile 6 im Ausgangschar. sta (zp3),y ; auf Zeile 7 kopieren lda (zp2),y ; von Zeile 6 im Zielchar. sta (zp4),y ; auf Zeile 7 kopieren dey bpl .loop_down iny ; 0 tya sta (zp),y ; Zeile 0 pla ; gerettetes Byte aus Ausgangsblock wandert sta (zp2),ySchaut auch eleganter aus, ist fast so schnell wie der selbstmodifizierende Code, wobei beim letzteren mehr Initialisierungsarbeit nötig ist (das Patchen an 7 Stellen, wenn man von meinem Vorschlag ausgeht).
Ich habe Deinen Code nicht abgetippt, mich aber mich an Deiner Idee orientiert.
-------------------------------------------------------------------------------------------------------------------------
Hier ist das bisherige Ergebnis:
Code
Alles anzeigenshift_char2tmp lda ACTION bne .shift_char2tmp rts ; ---------- Alle Adressen mit Werten vorbelegen ---------- .shift_char2tmp ldy #$18 ; High Byte für die Adressen sty adr_rl_1+2 sty adr_rl_2+2 dey sty adr_dwn_1+2 sty adr_dwn_2+2 ldy character_no iny lda lowbyte_char,y sta adr_rl_2+1 dey lda lowbyte_char,y ; LowByte für die Ausgangsposition sta adr_rl_1+1 sta adr_up_1+1 sta adr_up_2+1 sbc #$f0 sta adr_dwn_1+1 sta adr_dwn_2+1 lda DIR ; Bewegungsrichtung laden ; -------- runter -------- .player_dir_down cmp #UNTEN bne .player_dir_up lda #$00 ldx #$f0 .scroll_d adr_dwn_1 ldy $1fff,x adr_dwn_2 sta $1fff,x tya inx bmi .scroll_d jmp .end ; -------- hoch -------- FUNKTIONIERT nicht !!!! .player_dir_up cmp #OBEN bne .player_dir_r_l lda #$00 ldx #$0F .scroll_u adr_up_1 ldy $18ff,x adr_up_2 sta $18ff,x tya dex bpl .scroll_u jmp .end .player_dir_r_l ; -------- rechts oder links -------- ; OP Codes für rechts: lsr $5e; ror $7e ; OP Codes für links: asl $1e; rol $3e ldx #$5e ; OP Code für rechts (lsr) ldy #$7e ; OP Code für rechts (ror) cmp #RECHTS beq .start_shift ldx #$1e ; OP Code für links (asl) ldy #$3e ; OP Code für links (rol) .start_shift stx adr_rl_1 sty adr_rl_2 ldx #7 ldy #7 lda DIR ; shifte bytes (rechts/links) .scroll_r_l adr_rl_1 lsr $1fff,x adr_rl_2 ror $1fff,x dex bpl .scroll_r_l .end rts- Das erste Drittel kümmert sich nur darum die Adressen für die adr_*-Speicherstellen zu ermitteln und zu setzen.
Dabei wird so viel Platz verbraucht, dass sich die ganze Vorteile im weiteren Verlauf nicht mehr rechnen.
- Dann kommt die UP/DOWN-Bewegung nach Acorns Vorschlag. Die DOWN-Routine läuft sehr gut. Die UP-Routine funktioniert bei mir nicht.
Wahrscheinlich fehlt mir die nötige Erfahrung um genau sagen zu können warum nicht.
- Die Rechts/Links-Bewegung hatte ich ja schon präsentiert. Die habe ich nach dem Vorschlag von Neptun umgesetzt.
Sie läuft super und bleibt auch so.
Es läuft also im Ergebnis auf einen Mix aus meiner ersten Version für UP/DOWN und dem selbst-modifizierenden Code für R/L hinaus.
Ich baue noch den Hinweis von Jeek mit ein (Tausch des Zwischenspeichers von PHA/PLA innerhalb der Schleife auf das X-Register) um ein paar Zyklen einzusparen.
Wenn das Fertig ist kopieren ich das hier nochmal rein.
VG
aitsch
-
Also in Zeile 20 das SBC, sollte man da nicht sicherheitshalber ein SEC setzen. Mich wunderts, dass DOWN zuverlässig funktioniert ... Gegebenenfalls muss auch das High-Byte berücksicht werden, wenn es zum Unterlauf bei der Subtraktion kommt, was ja wahrscheinlich ist, weil das Low-Byte ja eher kleiner $F0 sein wird. Wenn aber in diesem Fall DOWN funktioniert (mit einem falschen High-Byte?), dann wird aber UP falsch sein, weil dort das (eigentlich) richtige High-Byte dann als falsch gelten könnte ...
- Dann kommt die UP/DOWN-Bewegung nach Acorns Vorschlag. Die DOWN-Routine läuft sehr gut. Die UP-Routine funktioniert bei mir nicht.
Wahrscheinlich fehlt mir die nötige Erfahrung um genau sagen zu können warum nicht.
Wie zeigt sich das? Warum nicht im VICE testen, Breakpoint auf die Routine setzen und Schritt für Schritt durchgehen ...
-
Also rechts und links ist kein Problem in ASM.
Gruss
-
Jawohl, dass durften wir bereits einige Posts früher feststellen.
-
Mit einer kleinen Änderung an COPY_DOWN, kann man das kopieren in einer Unterroutine ausführen. Übrigens ein JMP .END kostet 3 Byte.
Code
Alles anzeigen; LDA #$00 ; Vor der Richtungsabfrage setzen ; TAX LAX #$00 ; Spart ein Byte LDY DIR ... ... COPY_DOWN JSR COPY INX CPX #$10 BNE COPY_DOWN RTS ; -------------------------------------------------------------------------------- UP LDX #$0F COPY_UP JSR COPY DEX BNE COPY_UP ; -------------------------------------------------------------------------------- COPY LDY CHAR_AB,X STA CHAR_AB,X TYA RTS -
Das eintragen der Adressen kostet jetzt zwar weniger, aber mit der Indirekten spart man doch mehr ein.
Code
Alles anzeigenLDA #<CHAR STA $FB LDA #>CHAR STA $FC ; -------------------------------------------------------------------------------- LDA #$00 TAY COPY_DOWN PHA LAX ($FB),Y PLA STA ($FB),Y TXA INY CPY #$10 BNE COPY_DOWN RTS ; -------------------------------------------------------------------------------- LDA #$00 LDY #$0F COPY_UP PHA LAX ($FB),Y PLA STA ($FB),Y TXA DEY BPL COPY_UP RTS -
Ich hab nicht alles gelesen vielleicht verstehe ich das Thema deswegen nicht wirklich (vielleicht auch Thema verfehlt oder das war schon hier so vorgekommen), aber:
Übrigens der Kram ist beliebig optimierbar.. Vor allem das Entrollen der Schleifen bring Performance wenn Speicher nicht so wichtig ist.. Ich würde das wahrscheinlich nie als Schleife schreiben..
Have Fun!
( Hoffe das hilft vielleicht eventuell weiter!
)Code
Alles anzeigenHier mal die nicht entrollten Versionen: down: .again lda char+1,x sta char+0,x inx cpx #end-1 bne .again Das kann man nochmehr optimieren wenn man mit negativem x anfängt, das spart das cpx die Schreibweise mit ZP,y wäre wohl dashier down: .again iny lda ($fb),y dey sta ($fb),y iny cpy #end-1 bne .again oder: down: .again lda ($fb),y sta ($fd),y iny cpy #end-1 bne .again für up sieht das so aus up: .again lda char+0,x sta char+1,x dex bpl .again oder: up: .again lda ($fb),y iny sta ($fb),y dey dey bpl .again oder up: .again lda ($fb),y sta ($fd),y dey bpl .again -
Achso, wenn man mit negativem x oder y anfaengt hat man wohl sehr oft noch den 1 Cycle Pageswitch Penalty dabei, kann sein, dass das nicht wirklich was bringt..

-
Ich hab nicht alles gelesen vielleicht verstehe ich das Thema deswegen nicht wirklich (vielleicht auch Thema verfehlt oder das war schon hier so vorgekommen), aber:
Übrigens der Kram ist beliebig optimierbar.. Vor allem das Entrollen der Schleifen bring Performance wenn Speicher nicht so wichtig ist.. Ich würde das wahrscheinlich nie als Schleife schreiben..
Have Fun!Danke für die Anregung.
Speicher ist extrem wichtig.
Das Spiel soll nach aktueller Planung 10 verschiedene Maps und zum Schluss noch einen Bosskampf beinhalten.
Ich versuche alles auf einem unexpandierten VC-20 - also auf nur 3,5 kByte - unterzubringen.
Es zählt also jeden Byte.
Das ist die Challenge (oder auch nur der wahnwitzige Traum eines alternden Nerds)
-
Wenn es nur auf 3,5kByte läuft , fehlen die schönen vielen eigenen erstellten Char um den ganzen Screen schön optisch zu gestallten..
Bei 3,5kByte musst du dann die unansehnlichen Char nehmen.
Bei mir läuft es Teilweise schon mit dem Turbo Rascal ab 8kByte um den Screen schön aussehen zu lassen.
Jetzt brauche ich nur noch die Abfragen zu machen zur Senkrechten, das andere funktioniert schon.
In Turbo Rascal kann man noch schönen feinen eigenen ASM-Code reinbringen.
Ich habe den Char-Sprite auch mal in ASM angefangen , wurde aber nach und nach unübersichtlich für mich.
Ich habe so viele abfragen gehabt , die auch nötig waren.
Gruss
-
Mein Ziel ist es auf jeden Fall mein Projekt in Assembler umzusetzen. Es ist der Spaß an der Sache.
Eine andere Programmiersprache kommt für mich nicht in Frage.
Bevor ich auf eine Speichererweitung für den VIC wechseln würde, würde ich eher das ganze Projekt auf dem C64 realisieren.
Und ja, es werden "häßliche", einfarbige Charaktäre werden. Das war damals halt so und ich will auch keinen Preis damit gewinnen.
VG
-
Zitat
Bevor ich auf eine Speichererweitung für den VIC wechseln würde, würde ich eher das ganze Projekt auf dem C64 realisieren.
Na, so schnell gibst du den VIC20 auf , nur um nicht 3kB einzubauen.
Ich dachte er war dein Freund um ihn total kennnenzulernen, also ist er ein kurzzeitiger Durchläufer.
Dann bist du ja kein VIC20 fan .
Gruss
-
Zitat
Ich suche schon länger, nach einer brauchbaren Lösung für Softwaresprites auf dem VC-20.
Gib in Google "VIC20 oder VC20" ein , dann erscheinen einige schöne Spritevorschläge im ASM-Code für den VIC.
Sind leicht lesbar und man kann sie verstehen. Es sind kleinere und Größere ASM-Programme.
Die sind so gut geschrieben das man hier nicht Fragen braucht, sondern damit lernen kann.
Gruss
-
Ich sehe keinen Grund Bitte melde dich an, um diesen Link zu sehen. ständig vorzuhalten, was er denn zu machen hat. Ich glaube, er fühlt sich ganz wohl, wie er die Sache angeht und man muss ihn da wohl auch nicht überzeugen das oder dies zu machen. Wirklich "Lernen" tut man nur, wenn die Idee selbst entwickelt, verbessert und von Grund auf selbst macht. Und wenn man bei einem Detail stecken bleibt, hier einfach im Forum fragt. Danach dann mit anderen Lösungen zu vergleichen, schadet natürlich nicht und sich daran zu verbessern. Aber von Haus aus sich Sachen aus dem Internet zu kopieren und daraus "lernen" zu wollen, reicht m.E. nicht, um sich wirklich gute Fähigkeiten anzueignen.
Das wäre in etwas so, wenn ich ein guter Buchautor werden will und mir aus dem Internet die tollsten Werke der Weltliteratur herunterlade und "anschaue" bzw. lerne ... davon ist noch niemand ein auch nur halbwegs passabler Buchautor geworden.

-
So wie er schreibt , kennt er das Verhalten zum Proggen nicht so gut im VIC20 mit den Char , deren Adressen zum verschieben der Char usw. Er geht vom Verhalten aus nach dem Motto , es ist ähnlich wie beim C64 , nur mit 3,5kByte, dem ist aber nicht so.
Gruss
-