Ich werde mal so grundsätzlich wie möglich antworten.
Eine fundamentale Sache, die so selten explizit erwähnt wird, ich aber für essentiell halte, insbesondere, wenn man von höheren Sprachen kommt:
Es gibt kaum eine Art, unsicherer als in Assembler auf einem System wie dem SNES zu programmieren.
In Assembler zu programmieren bedeutet, untyped und unchecked zu programmieren.
Im Fall des SNES kommt noch hinzu, dass die CPU-Architektur nicht mal Memory Protection bietet.
Das bedeutet, dass es absolut kein Abfangen und keine Behandlung von irgendeiner Art von Programmierfehlern gibt.
Ein Resultat ist, dass viele Fehler unentdeckt bleiben und das Debuggen der gefundenen Fehler ungleich schwieriger ist als in anderen Sprachen.
Ein anderes Resultat ist, dass es mit steigender Programmkomplexität ungewöhnlich schnell sehr einfach wird, sich "in eine Ecke" zu programmieren:
Monolithische Programmblöcke, die schwer zu warten, erweitern und auf andere Projekte zu portieren sind und lauter versteckte Nebenwirkungen haben, sind eher die Regel als die Ausnahme, wenn man nicht von Anfang an mit Bedacht vorgeht.
Dieser Gefahr sind sich die meisten Anfänger nicht bewusst und das ist auch mit ein Grund dafür, warum es im Homebrew-Bereich zwar einige 1-Level Demos oder Spiele auf niedrigem NES-Niveau gibt, aber wenig, was an Komplexität darüber hinausgeht.
Dort liegt ungefähr die Grenze, zu der man mit mehr oder wenigem planlosem Hacken ohne größere Probleme hinkommt.
Viele (ich selbst anfangs eingeschlossen) überschätzen sich nach ersten Erfolgen, bauen eine kleine Demo zusammen, und wenn es dann daran geht, die Teile zu einem größeren Ganzen zusammenzubauen oder weitere Features hinzuzufügen, folgt Hack auf Hack.
Danach Hacks, um um die bestehenden Hacks herumzuarbeiten.
Irgendwann macht sich dann Ernüchterung breit.
Theoretisch kann man weitermachen (bei vielen veröffentlichten, offiziellen Spielen scheint das der Fall gewesen zu sein), aber man kämpft mehr und mehr gegen den bestehenden eigenen Programmcode, als mit ihm zu arbeiten.
An dieser Stelle hören die meisten auf.
Was mir sehr geholfen hat, war ein geplantes und strukturiertes Grundgerüst:
-Runtime-Fehlerbehandlung für alle Probleme, die ich erkennen (oder vermuten) kann (Stack under/overflow, memory corruption, unerwartete Interrupts, Gültigkeitsbereiche von Funktionsparametern, dynamische Sprungziele etc.).
-kleines Objektsystem, das die Gruppierung von Funktionen und Daten in logische, abgetrennte Blöcke ermöglicht, mir die Erzeugung und Verwaltung von Objekten während der Laufzeit abnimmt und standardisierte Aufrufregeln hat.
-dynamische Verwaltung von Ressourcen (DMA-Kanäle, Video-RAM, Farbpaletten etc.).
-Unit-Tests (auch, wenn dort oft die Faulheit siegt und ich lange nicht so viele schreibe, wie ich sollte)
Auf dieser Basis fällt es mir verhältnismässig leicht, flexibel und modular meine Codebasis zu vergrößern und Projekte zu skalieren, ohne dass sie unübersichtlich/unwartbar werden.
Nachteilig ist der zusätzliche Overhead des dynamischen Runtime-Krams, die Vorteile machen das für mich aber deutlich wieder wett, und ganz am Ende eines Projektes kann man immer noch mit statischen Hacks die Performance optimieren, andersrum geht das dagegen nur sehr schlecht.
Verglichen mit modernen High Level Frameworks ist meine Codebasis natürlich immer noch Low-Level-Gehacke, durch das wahrscheinlich kaum jemand ausser mir durchsteigt, aber es ist ein Schritt in die richtige Richtung.
snoer hat geschrieben:leider fehlt mir, trotz grundlegender Kenntnisse, Programmiererfahrung auch in den höheren Sprachen, aber die kriegen es ja auch hin sich libs zu schreiben.
Neben dem bereits genannten Problem des Fehlens jeglicher grundsätzlichen Struktur, Calling Conventions, Memory Management, standardisierter Typen etc. ist ein großes Problem, dass die SNES CPU relativ langsam ist.
Jedes Stück Flexiblität und Modularität geht i.d.R. auch mit Performance-Verlust einher.
Klar kann man ein generelles Framework zum Managen von animierten Sprites, Kollisionsabfrage usw. schreiben.
Spätestens wenn man aber ein Shmup schreibt und mehr als 3 Schüsse gleichzeitig auf dem Bildschirm haben will, wird man aber z.B. kaum um einen extrem spezialisierten und auf das jeweilige Spiel zugeschnittenen Bullet-Manager herumkommen.
Die bestehenden Libraries beschränken sich daher eher auf allgemeine Systemfunktionalität.
Als Beispiel kann man
pvsneslib nennen, ein bisschen mehr Kram gibts
hier.
snoer hat geschrieben:
Ich frage mich nur ob es am Ende performant ist in eine ASM Sprache solche Funtkionalität zu implementieren, oder ob es das Programm unnötig aufbläst. Wobei ich denke, dass die Größe des Programms heutzutage eh keine große Rolle mehr spielt, oder lieg ich da falsch?
Genauso träume ich ja von sowas wie einem ascii interpreter, damit das mit dem ganzen Text nicht so dermaßen umständlich ist.. (wobei man da eventuell sinnvoller einen parser in python oderso schreibt)
Ich denke, ROM-Größe ist heute praktisch irrelevant.
Textparser, wie auch sonstige Conversion Tools für Grafiken, Sound, Level etc. sind natürlich ausgesprochen sinnvoll, oft unumgänglich.
Ich persönlich hacke mir meine sämtlichen Hilfsprogramme für solche Zwecke, die entweder direkt Binärdaten, oder inkludierbare Asm-Sourcefiles ausspucken (je nach Einsatzbereich) auch alle in python zusammen und bin damit bisher sehr gut gefahren.
In meinem letzten veröffentlichen Projekt (Super Road Blaster) sind die Textstrings aufgrund der geringen Menge noch händisch geschriebene asm-includes, in meiner aktuellen Codebasis hab ich aber bereits einen Textparser mit multi-language-support und so.
snoer hat geschrieben:
Am ende frage ich mich grad.. hmm ..wenn dieses ganze processing vom SNES überommen werden muss, dann entstehen wahrscheinlich sowas wie Ladezeiten..
Grundsätzlich muss man natürlich sagen: Berechne so viel du kannst vor und include es statisch, anstatt es vom SNES zur Laufzeit berechnen zu lassen.
Ladezeiten haben lustigerweise viele SNES-Spiele, sie dauern aber selten länger als ein oder zwei Sekunden und lassen sich deswegen noch ganz gut kaschieren, sodass die meisten Leute sie nicht mal bemerken.
Klassisches Beispiel: Der schwarze "Mario start!"-Bildschirm vor jedem Level in Super Mario World.

Ich persönlich verzichte immer auf Kompression, wenn es nicht unbedingt notwendig ist, weil ROM-Größe heutzutage wie gesagt praktisch irrelevant ist.