Hallo Besucher, der Thread wurde 5,9k mal aufgerufen und enthält 33 Antworten

letzter Beitrag von StingRay am

Programmieren auf dem Amiga - Speicherthematik [OT aus A500 und 2Mbyte Chip Ram]

  • Ich hätte sicher weniger dieser Probleme wenn ich Adressen "hart" ansprechen täte. Habe aber trotzdem oft bei einem und dem selben Code (nix "malloc()", hier geht's um asm) mehr oder weniger Probleme bei verschiedenen Configs wie der Speicher angesprochen wird. Äußert sich in kaputten Grafiken, die bei zb weniger Speicher noch sauber ausgeschaut haben.


    Wie sieht denn das Speicher- und Ressourcenmanagement bei dir konkret aus?


    Auf jeden solltest du dir auch mal den Public Domain Sourcecode von Frank Willes "Solid Gold" ansehen. Der macht das Ganze auch sehr maschinennah und trotzdem systemkonform.

  • steril: das Youtube-Video Preview sieht doch echt cool aus :)


    So mal ein paar Fragen:


    Könnte es sein das man dort ein paar Fehler schon sieht? So ein paar Refresh-Fehler z.B. bei 1:19 Laufzeit in dem Video? Die Fehler sehen ziemlich sporadisch aus, wenn das so ist würde ich mal testweise die Adressen prüfen, die du dem Blitter gibst. Sonst sehen ein paar Grafikfehler so aus, als ob dein Programm (vom Prozessor) wild in den Screen schreibt (z.B. falsch berechnete Adressen in den Adressregistern). Das ich lange nichts mehr am Amiga programmiert habe, würde ich mir irgendwelche Debugging Tools nehmen ... vielleicht gibt es sogar in den Emulatoren irgendwelche Hilfen um solche Zugriffe zu identifizieren. IIRC habe ich früher am Amiga, z.B. Enforcer (benötigt MMU) genutzt um solche Speicherfehler aus meinen Programmen raus zu bekommen.


    Sonst zu der Speicher/Systemproblematik, wie macht dein Programm das denn konkret? Nutzt du forbid() und permit()? Was machst du mit den Sytem Interrupts und deinen eigenen Interrupts? Nutzt du feste Adressen oder holst du dir das per AllocMem()? Oder hast du ein BSS Segment in deinem Executable? Holst du dir einen großen Block oder viele kleine Blöcke?


    Und sonst ... warum viele Spiele mit Fast-Ram nicht laufen ... Die Programme wurden einfach nicht sauber programmiert und die Fehler sind bei nur Chip-Ram nicht aufgefallen. Aber da gibt es unendlich Möglichkeiten warum das ein oder andere
    Programm nicht läuft. Manche dumme Programme sind sogar fest davon ausgegangen das System-Strukturen an der selber Adresse stehen ... ich hab das zwar früher immer für ein Gerücht gehalten, aber dann habe ich eine Crack von Archon gesehen, der genau das macht! Außerdem gibt es ja auch bei höheren Prozessoren häufig das Problem, dass dort auch das Timining nicht beachtet wird. Zum Beispiel dumme Warteschleifen oder selbstmodifizierende Programme, die das Cache nicht beachten ... da gibt es, wie gesagt, unzählige Möglichkeiten.

  • Auf jeden solltest du dir auch mal den Public Domain Sourcecode von Frank Willes "Solid Gold" ansehen.

    ja, den Solid Gold-Source kenn ich gut. Generell würde ich ohne dem Frank seine Tools kein Land sehen bei der Sache.



    Könnte es sein das man dort ein paar Fehler schon sieht?

    Ja, auf jeden Fall. Aber ich glaube die Sachen die man in dem Video sieht habe ich mittlerweile behoben. War zum Teil ganz verschiedenes Zeugs was die einzelnen Glitches verursacht hat.


    Generell hab ich halt alles an Labels stehen.
    Mit BSS Segmenten habe ich schlechte Erfahrungen gemacht.
    Denke das hat die meisten Probleme verursacht, die ich mir nicht erklären konnte.


    Zb hatte ich obwohl ich mir die Daten bei einem Label reinlade zum blitten da andere Sachen stehen bei verschiedenen Speicher Configs.


    Seitdem ich wieder alles stur als Chip deklariere scheint sich das gegessen zu haben.


    Ich benutze brav Forbid und schalte die system interrupts ab. Seit neuestem benutze ich auch noch so nen relativ umfangreichen Startup code aus einem Demo dass mir der bubob aus dem A1K zugesteckt hat.

  • anscheinend gibts leider nur "Ich und meine Art das anzugehen bin besser als du weil ich so toll systemkonform bin"-Gerede

    Ich sehe da zwei Möglichkeiten: Entweder Du wühlst Dich durch die offizielle System-Doku (inklusive Amiga-OS/DOS) und spielst nach dessen Regeln, wie man bestimmte Speicherarten belegt und nutzt. Oder Du gehst 100% 'bare metal', klemmst das Amiga-DOS komplett ab und findest selbst raus, wo welcher Speicher frei ist. Was aber ganz sicher nihct geht: Ein Programm schreiben und vom Amiga-DOS laden lassen, udn erwarten daß man _irgend_eine standardisierte Speicherbelegung vorfindet. Denn das tut Amiga DOS eben genau nicht. Da ist nur Adresse 4 fix, alles andere ist komplett dynamisch.


    (und Deien Art ist ganz offensichtlich nicht besser, denn Dein Code fliegt Dir ja andauernd um die Ohren...)

  • Und dann liest hier man noch den typischen extremst unhilfreichen "warum machst eigentlich nicht alles systemkonform?"-Post , und dann kocht einem die Galle schon mal über...

    Sorry, das wollte ich ganz sicher nicht auslösen. Mir war, als würdest Du Probleme beschreiben, die rein mit der Speicherconfig zu tun haben, denn Du hast beschrieben, dass Grafiken "kaputt" wären, wenn eine bestimmte Config vorliegt. Ich habe daraus geschlossen, dass Du Speicher wie Chipram benutzt, der gar nicht durch die DMA-Kanäle des Agnus zugänglich ist.


    Dem ist offenbar nicht so. Das konnte ich aber anhand Deiner Worte nicht wissen, schließlich hast Du die Art der Fehler nicht beschrieben, keinen Code mitgeteilt und nicht einmal die Config genannt, mit der es Schwierigkeiten gibt.


    Ich kann Dir versichern, dass ich das Amiga-Chipset sehr gut kenne. Und auch M68k CPUs sind mir nicht fremd. Von der bloßen Tatsache, dass ich noch nie ein Demo veröffentlicht habe, kannst Du jedoch nicht schließen, dass ich "keinen blassen Schimmer" habe. Ich kenne das Amiga-Chipset von der Hardware-Seite, denn wir haben es im FPGA implementiert. Und M68k CPUs programmieren kann ich ebenfalls. Was ich nicht kann ist OS-Programmierung. Da hört es nach ein paar exec-Aufrufen schon auf, und ich muss entweder in einer Labersprache weiter machen (z.B. Pascal), oder den Job abgeben.


    Ich werde also ganz sicher nicht (wie Thor das gern macht) den "mach' doch alles systemkonform"-Verfechter abgeben, denn das kann ich selbst nicht. Ich weiß auch sehr genau, dass Demos und Spiele dadurch nur leiden würden. Dennoch würde ich Startup-Code, der eine Speicherliste generiert, nah am System machen, denn das weiß eigentlich recht gut, welcher Speicher wo liegt. Der Aufwand ist einfach geringer als wenn man das selbst in die Hand nehmen wollte.


    Was ich aber sehr gut kann, ist das Übertragen des Hardware-Wissens auf Assemblerprogrammierung. Wir sind also gar nicht so weit voneinander entfernt, wie Du glauben magst.


    Ohne weitere Informationen von Dir können wir aber nur im Dunkeln stochern. Es gibt Methoden, ein wenig mehr Blitterleistung heraus zu kitzeln, indem Du schon den nächsten Satz Parameter schreibst, bevor der aktuell laufende Blit zuende ist (also das busy-flag nicht abwarten). Das geht so lange gut, wie die CPU *genau* die Anzahl Zyklen für die Ausführung braucht, die beim Debuggen des Codes auch gebraucht wurde. Wenn der Code aber dann in schnellerem Speicher liegt, läuft der Blitter auf einer anderen Config Amok. Wie gesagt - das ist nur eine Vermutung, sollte Dir aber zeigen dass ich a) gewillt bin zu helfen und b) nicht ganz ahnunglos bin.


    Jens

  • Ich sehe da zwei Möglichkeiten: Entweder Du wühlst Dich durch die offizielle System-Doku (inklusive Amiga-OS/DOS) und spielst nach dessen Regeln, wie man bestimmte Speicherarten belegt und nutzt. Oder Du gehst 100% 'bare metal', klemmst das Amiga-DOS komplett ab und findest selbst raus, wo welcher Speicher frei ist. Was aber ganz sicher nihct geht: Ein Programm schreiben und vom Amiga-DOS laden lassen, udn erwarten daß man _irgend_eine standardisierte Speicherbelegung vorfindet. Denn das tut Amiga DOS eben genau nicht. Da ist nur Adresse 4 fix, alles andere ist komplett dynamisch.
    (und Deien Art ist ganz offensichtlich nicht besser, denn Dein Code fliegt Dir ja andauernd um die Ohren...)

    Ja, ich denke da hast du gar nicht so unrecht.
    Mir "fliegt zwar mein Code nicht dauernd um die Ohren", und eine standardisierte memory map nehme ich ja auch nicht an, sondern arbeite brav mit Labels statt Festadressen.


    Aber es passieren manchmal Sachen, die mich ziemlich wundern. Dadurch dass ich nun alles im Chip Ram laufen lasse treten genau diese Probleme aber grad auch nicht mehr auf.
    Wäre da allerdings gern ein bisschen flexibler.


    Mich würde aber eben mal eine Erklärung interessieren, warum sowas passieren kann, dass ich meine Adresspointer die auf Labels gehen sich bei der einen Config die richtigen Daten fürs blitten holen, aber bei einer anderen dann woanders..


    Da kratzt man sich schon mal am Kopf.

  • Dann gehe ich davon aus, dass alles in einem Segment steht? Also praktisch als ein großes Code Segment und dass alles in einem zusammenhängenden Block drin steht?
    Vielleicht würde ich das in mehrere Segment aufteilen ... wenigstens zwei, ein Code Segment im Public Ram und ein Data-Segment im Chip Ram.


    Und warum sowas vor kommt, ist immer eine gute Frage, evtl. würde ich bedingte Breakpoints einsetzen wenn du die Möglichkeit dafür hast. Vielleicht ein falscher Wert, der in einem Adressregister steht ... ich hatte mal einen sehr merkwürdigen Fehler, da habe ich aus Versehen in die Exec-Base Struktur geschrieben und mein Programm ist ausgestiegen so bald ich eine Diskette ins Diskettenlaufwerk geschoben habe :D Ich hab aus Versehen irgendwelche trackdisk.device Strukturen überschrieben ...

  • ich hatte mal einen sehr merkwürdigen Fehler, da habe ich aus Versehen in die Exec-Base Struktur geschrieben und mein Programm ist ausgestiegen so bald ich eine Diskette ins Diskettenlaufwerk geschoben habe Ich hab aus Versehen irgendwelche trackdisk.device Strukturen überschrieben ...

    Haha, das klingt schräg. Glaub da würde ich mir schon sehr am Kopf kratzen. :D

  • Dann müssen wir offenbar ein paar Begriffe klären: Du schreibst, dass Du programierst. Gleichzeitig hast Du aber Probleme mit verschiedenen Speicherkonstellationen. Das ist ein Widerspruch in sich.
    Wenn Du programmierst, dann machst Du für Speicheranforderung einen sauberen Malloc() und forderst damit die richtige Art Speicher an (Chip- oder Fastmem). Du bekommst eine Adresse oder einen Fehler zurück. Das funktioniert schon problemlos seit Kickstart 1.2.


    Wenn Du aber Adressen "hart" ansprichst, dann programmierst Du nicht. Das kannst Du vielleicht Coden nennen, so Mancher würde vielleicht "Hacken" sagen, aber Programmieren ist anders. Der Amiga hat ein OS. Bitte benutze es wenigstens für diese simplen Dinge, auch wenn die nächste Amtshandlung danach ein forbid() ist. Selbst in der Demoszene ist es seit Jahren Standard, dass man ohne Ressourcenschwund wieder zur Kommandozeile zurück kommt und den Rechner ohne Reset normal weiter benutzen kann.


    Jens


    Montag früh mal in der Amigaecke im Forum64 gestöbert und bin platt, was einige selbsternannte Experten so ablassen... Zum Ersten: Absolute Adressen kann man sehr wohl benutzen, wenn man weiss, was man tut! Unzählige Spielecoder haben das aus den verschiedensten Gründen getan! Ein ganz simpler Grund wäre z.B. aligned Memory, damit man gewisse Effekte deutlich zeitsparender hinkriegt, da man nur die Low Words der Bitplane-Pointer setzen muss. Oder, weil man einfach extrem auf die Größe vom Code achten muss (Bootblockintros etc.) und daher jegliches "Extragedöns" unterlässt. Es gibt für alles ein Für und Wider, einfach alles, was man selbst nicht nachvollziehen bzw. verstehen kann, zu verteufeln und als "Müll" zu bezeichnen, ist weder zielführend noch angebracht!



    Das ist speziell beim Amiga eine streitbare Aussage. Speicher hart anzusprechen ist in einem 32-Bitter mit 2G nutzbarem Adressraum eigentlich ein no-go. Ja, wenn man die Chipregister selbst befingert, bekommt man viel hübschere Dinge hin als mit dem OS. Aber nichts weiß besser über die Speicherconfig bescheid als das OS. Und es hätte niemandem weh getan, wenn man sich einfach nach dem Start ein paar dicke Speicherblöcke holt, und die dann selbst verwaltet.
    WHDload zeigt's: Auch die alten Dinger müssen nur minimal gepatcht werden, damit sie z.B. ohne Speicher bei $00c0.0000 (trapdoor) funktionieren. Und wenn Dein Flight simulator nur ohne Speichererweiterung funktioniert, hat der Malloc()-Aufruf nur den falschen Parameter gesetzt, vermutlich "any RAM" anstelle von "chip ram".


    Jens


    So so, die "alten Dinger müssen also nur minimal gepatcht werden", verstehe. Wieviele WHDLoad Patches hast Du noch gleich gecoded? Ich kann auf diese Frage mit "über 900" antworten und unterstelle Dir, dass Du absolut nicht weisst, wieviel Aufwand es sein kann, ein OCS Spiel so zu patchen, dass es auf allen Konfigurationen läuft!



    Lass' uns mal konstruktiv weiter machen - Du hast Code, der nicht mit allen Speicherconfigs funktioniert, und hast um Hilfe gebeten. Wenn Du einen direkten Hinweis auf Literatur, sowie zwei Library-Funktionen ausreichend findest, mich persönlich unsympatisch zu finden, ist das Deine Entscheidung. Außenstehende denken sich sicher ihren Teil.
    Wenn Du möchtest, bin ich diesbezüglich ab sofort still und überlasse Anderen das Debuggen Deines Codes. Hinweise stehen jetzt ausreichend zur Verfügung. Wir brauchen nur noch Deinen Code und ne Angabe, mit welchem Assembler Du arbeitest.


    Ach ja, und vielleicht sollte ein Mod mal einen neuen Thread abspalten, hat ja nichts mehr mit dem Ursprungsposting zu tun.


    Jens


    Ich als Außenstehender denke mir tatsächlich meinen Teil. Und zwar über Deine (Jens) Kommentare hier in diesem Thread...


    ?(

    stimmt... :winke:
    PS: ich habe auch keine Ahnung vom Programmieren..


    aber ich kann verstehen, wenn Jens "es nicht verstehen" kann, wenn jemand programmiert und dann keinen Überblick :search: über Speicheraufteilung hat..


    Nun ja, es gibt beim Amiga so einige Stolperstellen, was Speicher angeht und alles kann und muss auch niemand wissen. Ausser Jens natürlich, er scheint ja der absolute Experte in Sachen Amigacoding zu sein...



    Um jetzt mal aufs eigentliche Thema zu kommen, wenn Code mit verschiedenen Speicherkonfigurationen nicht richtig läuft, kann das sehr viele Ursachen haben. Typische Knackpunkte sind hier z.B. inkorrektes Prüfen auf erweiterten Speicher (dieses Problem haben extrem viele alte Spiele), fehlerhaftes Handling von Speicherallokationen, die fehlschlagen, Bugs in der Speicherallokation (zu wenig Speicher allokiert), die nur unter bestimmten Konstellationen sichtbar werden (dieses Problem haben auch etliche alte Spiele) oder eben auch die bereits erwähnten absoluten Adressen, die durchaus unangenehme Folgen haben können. Und dann kann es auch ganz einfach noch daran liegen, an welcher Adresse der allokierte Speicher liegt, ist das z.B. an einer Position, die auf 64k ausgerichtet ist, kann Code wunderbar funktionieren, der davon ausgeht, dass das eben immer der Fall ist. Anderes Beispiel sind Zugriffe auf Speicher per Indexregister (z.B. move.w (a0,d1.l),d1), wenn der obere Teil von d1 gelöscht ist, funktioniert das wunderbar, ist er das aber nicht, gibt's die herrlichsten Bugs (die teilweise extrem schwer zu finden sein können), dieses Problem haben auch etliche alte Spiele und Demos.


    Ursachen gibt es mehr als genug, diese zu finden ist nicht immer einfach. Hilfreich kann es sein, eine Art Boundary Check einzubauen, solange man noch am Coden ist (in der fertigen Version sollte sowas entfernt werden), d.h. am Anfang und Ende eines jeden Speicherereichs/BSS Buffers eine ID (dc.l "STRT"/dc.l "END!") einzufügen, so dass man immer prüfen kann, ob Speicher überschrieben wurde. Gibt natürlich genügend andere Möglichkeiten, aber da hat eh' jeder Coder seine eigenen Vorlieben.

  • Ich weiß zwar nicht... warum ich "zitiert" wurde ??! (ich sehe da nur mein Avatar,.. aber KEIN Text von mir..)


    nur soviel...


    Jens hat sich anscheinend etwas aus dem F64 raus gezogen... => eine Antwort (wenn du darauf hoffst) könnte etwas dauern...


    mfG.

  • Zitat von ogd

    Was waren die häufigsten Programmiersünden, denen du dabei begegnet bist?


    Oha, da könnte ich Bücher drüber schreiben... Von den ganzen "normalen" Sachen mal abgesehen (fehlende Blitterwaits, Sprünge ins Kickstart ROM, um Interrupts zu beenden, komplett unbrauchbare Prüfungen auf erweiterten Speicher, Code, der nur im Fake Fast läuft, selbstmodifizierender Code etc. pp.) gab es da auch noch etliche andere "feine" Sachen. Schwer im Gedächtnis geblieben ist mir z.B. der Code von The Ultimate Pinball Quest, der nur deshalb funktionierte, weil der Coder Glück hatte, dass sein komplett sinnfreier und falscher Code trotzdem mehr oder weniger korrekt ausgeführt wurde, ich habe mich dazu auch im ReadMe vom WHDLoad Patch ausgelassen: http://www.whdload.de/games/TheUltimatePinballQuest.html


    Ansonsten würden viele Spiele problemlos auf höheren CPUs als dem 68000 laufen, wenn der Kopierschutz nicht wäre, habe aktuell gerade den Patch von Alien Breed neu gemacht und das war auch so ein Fall. Der eigentliche Gamecode ist sehr sauber, der Protection-Code nutzt Selbstmodifikation, so dass es auf 68010+ dann gewaltig kracht.