Fast sicher, daß man es nicht mehr vereinfachen kann im Anhang hier eine Routine aus meiner Engine.
Mich würde wundern, wenn man die noch erheblich vereinfachen kann.
Wer überrascht mich?
Es gibt 45 Antworten in diesem Thema, welches 6.720 mal aufgerufen wurde. Der letzte Beitrag (
Fast sicher, daß man es nicht mehr vereinfachen kann im Anhang hier eine Routine aus meiner Engine.
Mich würde wundern, wenn man die noch erheblich vereinfachen kann.
Wer überrascht mich?
hast dus auch ungepacked..
#pragma codeseg (push, "OVL1CODE");
char byte_messer_ausrichtung_aendern (char feld_x, char feld_y, char ausrichtung,
char bool_uhrzeigersinn)
{
char byte_zwischenausrichtung=0;
//0 entspricht unentschieden.
char byte_kleinster_abstand=100;
//100 entspricht hier maximalmöglichem Abstand.
//Drumherum auf Bomben testen
char bool_oben_stein;
char bool_unten_stein;
char bool_rechts_stein;
char bool_links_stein;
char bool_ecke_stein;
//1. Beschleunigungsvariablen
char* hilfszeiger=&zustand[feld_x][feld_y];
char byte_insg;
//Zunächst werden Stein-Ja-Nein-Testungen für die vier Richtungen
bool_oben_stein =((feld_y==0) || ( *(hilfszeiger-1)>0 ));
bool_unten_stein =((feld_y==24)|| ( *(hilfszeiger+1)>0 ));
bool_rechts_stein=((feld_x==39)|| ( *(hilfszeiger+25)>0 ));
bool_links_stein =((feld_x==0) || ( *(hilfszeiger-25)>0 ));
//Stehenbleiben
byte_insg=bool_oben_stein+bool_unten_stein
+bool_rechts_stein+bool_links_stein;
if (byte_insg==4) return 0;
//In eine Richtung gezwungen.
if (byte_insg==3)
{
if (!bool_oben_stein) return 3;
if (!bool_unten_stein) return 1;
if (!bool_links_stein) return 2;
return 4;
};
//In beiden Fällen kann jetzt ein stehendes Messer ausbrechen:
if (ausrichtung==0)
{
if (!bool_oben_stein) return 3;
if (!bool_unten_stein) return 1;
if (!bool_links_stein) return 2;
if (!bool_rechts_stein) return 4;
}
//Jetzt wird aufgeteilt:
if (!bool_uhrzeigersinn)
{ //Linksdreher
//Für die weiteren Möglichkeiten wird in Einfahrtsrichtung eingeteilt
switch (ausrichtung)
{
//Kommt von links
case 4:
//Die nötige Ecke berechnen.
bool_ecke_stein = (feld_x==0)||(feld_y==0)||
*(hilfszeiger-1-25)>0;
// Linksabbiegen (nur dann wenn Ecke vorhanden und Richtung frei)
if ((bool_oben_stein==0)&&(bool_ecke_stein==1))
return 3; //hoch
// Rechtsabbiegen (läuft gegen Wand und rechts frei, nachdem nicht links.)
if ((bool_rechts_stein==1)&&(bool_unten_stein==0))
return 1; //runter
// Zurückgezwungen (falls Wand, aber Rechtsabbiegen nicht möglich.)
if (bool_rechts_stein+bool_unten_stein==2)
return 2; //links
break;
//Kommt von oben
case 1:
//Ecke berechnen.
bool_ecke_stein = (feld_x==39)||(feld_y==0)||
*(hilfszeiger-1+25)>0;
// Linksabbiegen (nur dann wenn Ecke vorhanden und Richtung frei)
if ((bool_rechts_stein==0)&&(bool_ecke_stein==1))
return 4; //rechts
// Rechtsabbiegen (läuft gegen Wand und rechts frei, nachdem nicht links.)
if ((bool_unten_stein==1)&&(bool_links_stein==0))
return 2; //links
// Zurückgezwungen (falls Wand, aber Rechtsabbiegen nicht möglich.)
if (bool_rechts_stein+bool_unten_stein==2)
return 3; //hoch
break;
//Kommt von unten
case 3:
//Ecke berechnen.
bool_ecke_stein = (feld_x==0)||(feld_y==24)||
*(hilfszeiger+1-25)>0;
// Linksabbiegen (nur dann wenn Ecke vorhanden und Richtung frei)
if ((bool_links_stein==0)&&(bool_ecke_stein==1))
return 2; //links
// Rechtsabbiegen (läuft gegen Wand und rechts frei, nachdem nicht links.)
if ((bool_oben_stein==1)&&(bool_rechts_stein==0))
return 4; //rechts
// Zurückgezwungen (falls Wand, aber Rechtsabbiegen nicht möglich.)
if (bool_rechts_stein+bool_oben_stein==2)
return 3; //hoch
break;
//Kommt von rechts
case 2:
//Ecke berechnen.
bool_ecke_stein = (feld_x==39)||(feld_y==24)||
*(hilfszeiger+1+25)>0;
// Linksabbiegen (nur dann wenn Ecke vorhanden und Richtung frei)
if ((bool_unten_stein==0)&&(bool_ecke_stein==1))
return 1; //runter
// Rechtsabbiegen (läuft gegen Wand und rechts frei, nachdem nicht links.)
if ((bool_links_stein==1)&&(bool_oben_stein==0))
return 3; //hoch
// Zurückgezwungen (falls Wand, aber Rechtsabbiegen nicht möglich.)
if (bool_links_stein+bool_oben_stein==2)
return 4; //rechts
break;
};
}
else //Rechtsdreher hier
{
switch (ausrichtung)
{
//Kommt von rechts
case 2:
//Ecke berechnen.
bool_ecke_stein = (feld_x==39)||(feld_y==00)||
*(hilfszeiger-1+25)>0;
// Rechtsabbiegen (nur wenn Ecke vorhanden und Richtung frei)
if ((bool_oben_stein==0)&&(bool_ecke_stein==1))
return 3; //hoch
// Linksabbiegen (läuft gegen Wand,links frei,nicht rechts)
if ((bool_links_stein==1)&&(bool_unten_stein==0))
return 1; //hoch
// Zurückgezwungen (Wand, aber Linksabbiegen nicht möglich.)
if (bool_links_stein+bool_unten_stein==2)
return 4; //rechts
break;
//Kommt von links
case 4:
//Ecke berechnen.
bool_ecke_stein = (feld_x==00)||(feld_y==24)||
*(hilfszeiger+1-25)>0;
// Rechtsabbiegen (nur wenn Ecke vorhanden und Richtung frei)
if ((bool_unten_stein==0)&&(bool_ecke_stein==1))
return 1; //runter
// Linksabbiegen (läuft gegen Wand,links frei,nicht schon r)
if ((bool_rechts_stein==1)&&(bool_oben_stein==0))
return 3; //hoch
// Zurückgezwungen (Wand, aber Linksabbiegen nicht möglich.)
if (bool_rechts_stein+bool_oben_stein==2)
return 2; //links
break;
//Kommt von unten
case 3:
//Ecke berechnen.
bool_ecke_stein = (feld_x==39)||(feld_y==24)||
*(hilfszeiger+1+25)>0;
// Rechtsabbiegen (nur wenn Ecke vorhanden und Richtung frei)
if ((bool_rechts_stein==0)&&(bool_ecke_stein==1))
return 4; //rechts
// Linksabbiegen (läuft gegen Wand,links frei,nicht schon r)
if ((bool_oben_stein==1)&&(bool_links_stein==0))
return 2; //links
// Zurückgezwungen (Wand, aber Linksabbiegen nicht möglich.)
if (bool_oben_stein+bool_links_stein==2)
return 1; //runter
break;
//Kommt von oben
case 1:
//Ecke berechnen.
bool_ecke_stein = (feld_x==00)||(feld_y==00)||
*(hilfszeiger-1-25)>0;
// Rechtsabbiegen (nur wenn Ecke vorhanden und Richtung frei)
if ((bool_links_stein==0)&&(bool_ecke_stein==1))
return 2; //links
// Linksabbiegen (läuft gegen Wand,links frei,nicht schon r)
if ((bool_unten_stein==1)&&(bool_rechts_stein==0))
return 4; //rechts
// Zurückgezwungen (Wand, aber Linksabbiegen nicht möglich.)
if (bool_unten_stein+bool_rechts_stein==2)
return 2; //oben
break;
};
};
//Sonst keine Ablenkung.
return ausrichtung;
}
#pragma codeseg (pop);
Alles anzeigen
Würde es dadurch, das alles ins ASM zu übertragen, automatisch schneller?
Würde es dadurch, das alles ins ASM zu übertragen, automatisch schneller?
Das ist jetzt nicht wirklich eine Frage, oder?
ZitatDas ist jetzt nicht wirklich eine Frage, oder?
C ist schon sher maschinensprachenah. Ich gucke mir gleich ´mal die *.s-Datei an, ob ich das mit eigenem ASM übertreffen kann.
Was habt ihr so für Erfahrungen?
Was habt ihr so für Erfahrungen?
Übersetzter Code ist (mit an Wahrscheinlichkeit grenzender Sicherheit) immer langsamer als nativer Code.
Vorausgesetzt. man weiss, was man tut.
;
; *(hilfszeiger-1-25)>0;
;
.dbg line, "./selbst/Messer.h", 63
lda L06E0
ldx L06E0+1
sec
sbc #$01
bcs L2611
dex
sec
L2611: sbc #$19
bcs L0731
dex
L0731: sta ptr1
stx ptr1+1
ldy #$00
lda (ptr1),y
beq L0732
L072C: lda #$01
L0732: sta L06DF
Alles anzeigen
Da fällt man doch vom Glauben ab!
cc65 rechnet erst -1 und dann nochmal -25, statt einmal -26?
Da fällt man doch vom Glauben ab!
cc65 rechnet erst -1 und dann nochmal -25, statt einmal -26?
Hast du doch im Code auch so geschrieben.
Ich gucke noch nach, aber wenn der bei festen Multiplikationen in etwa beispielsweise 5*40+3 daraus eine Multiplikation macht?
Ich gucke noch nach, aber wenn der bei festen Multiplikationen in etwa beispielsweise 5*40+3 daraus eine Multiplikation macht?
Da der cc65 anscheinend keine Operationen mit Konstanten wegoptimiert, wird wohl auch die Multiplikation erhalten bleiben.
Nochwas herausgefunden:
bool_a&&bool_b ist weniger aufwendig als bool_a+bool_b==2;
Wirklich gut optimierende Compiler zu machen, ist eine Wissenschaft für sich, und eine Lebensaufgabe.
Das dies bei einem nicht kommerziellen Projekt normalerweise ein Manko ist, sollte jedem klar sein. Es gibt nur wenige non Profit Compiler, die wirklich sehr gut optimieren: GCC (Gnu), LCC (Uni Projekt)
Viele freie Compiler basieren auf den oben genannten oder auf aufgelassene kommerzielle Compiler.
Zumindest für 680x0 produziert der GCC nicht gerade besonders tollen Code.
Jeder Compiler hat seine Stärken und Schwächen. Deshalb kann man auch die Leistungstests sehr leicht manipulieren, mit speziell getunten Beispielcode.
Aber im Großen und Ganzen schneidet der GCC immer sehr gut ab, bei objektiv geführten Tests, und kann sich leicht gegen kommerzielle Produkte behaupten. Es steckt ja auch eine ziemlich beeindruckende Manpower drin in dem Produkt. Zudem gibt es wohl kaum einen Compiler, der Code für so viele verschiednen Zielplattformen ausgeben kann.
Und der GCC leistet schon Erstaunliches, wenn man sich den entstandenen Code genauer ansieht. Es muss einer schon sehr gute Assemblerkenntnisse haben, und darüber hinaus die CPU internas sehr gut kennen, dass er besseren Code schreibt wie der GCC.
Das gilt insbesondere für komplexere CPU's. Wenn eine CPU so einfach ist wie ein 6502, dann ist es für einen Menschen leichter gegen einen Compiler zu gewinnen. Bei komplexeren Prozessoren kann man die Vielzahl an speziellen Eigenschaften nicht mehr so gut erfassen.
Im Übrigen ist eine CPU wie die 6502 nicht gerade für C predistiniert. Insofern sollte man da bei Assembler bleiben, wenn etwas zeitkritisch ist. Aber trotzdem ist der CC65 schon ein geniales Stück Software!!
Fast sicher, daß man es nicht mehr vereinfachen kann im Anhang hier eine Routine aus meiner Engine.
Evtl. habe ich was nicht verstanden, aber man könnte doch z.B.
if (byte_insg==3 || ausrichtung==0)
{
if (!bool_oben_stein) return 3;
if (!bool_unten_stein) return 1;
if (!bool_links_stein) return 2;
return 4;
};
}
schreiben. Die zweite if Abfrage danach fällt dann weg, ist ja doppelt.
Die zweite if Abfrage danach fällt dann weg, ist ja doppelt.
Nicht ganz:
Bei dieser Änderung würde der gesamte Rest der Funktion nach der if-Abfrage nie ausgeführt, falls byte_insg==3 oder ausrichtung==0. Dies ist im ursprünglichen Beispiel nicht der Fall, da u.U. alle bool-Werte true sein könnten.
Gruß Dirk
Es gibt nur wenige non Profit Compiler, die wirklich sehr gut optimieren: GCC (Gnu), LCC (Uni Projekt)
LLVM/clang ist dir nicht gut genug? ![]()
ZitatZumindest für 680x0 produziert der GCC nicht gerade besonders tollen Code.
Der Status vom GCC auf 680x0 ist ja auch mehr oder weniger "abgekündigt" ...
Da sind viele aktuelle Entwicklungen, die auf moderneren Prozesssoren eingeflossen sind, warrscheinlich nicht drin.
Nicht ganz:
Bei dieser Änderung würde der gesamte Rest der Funktion nach der if-Abfrage nie ausgeführt, falls byte_insg==3 oder ausrichtung==0. Dies ist im ursprünglichen Beispiel nicht der Fall, da u.U. alle bool-Werte true sein könnten.Gruß Dirk
versteh ich nicht. Die if Abfrage wird jetzt auch nie ausgeführt falls einer der beiden Fälle auftritt. Man müßte nur "if (!bool_rechts_stein) return 4;" noch berücksichtigen.