Bomb Jack GX

Ich habe das EXAKT zur selben Zeit veröffentlicht, als CPCWiki offline ging, sodass ich nie dazu kam, über die technischen Details zu sprechen. Der Code nutzt jede Menge exaktes Timing, weshalb ich – mal wieder unbeabsichtigt – einen Test für Emulatoren geschaffen habe, wie ich feststellen musste, als Leute Videos davon posteten, wie es falsch aussieht…

Ich habe die „Extra Sugar“-Modi entfernt, weil all diese Highscore-Tabellen und Erfolge für ein diskettenbasiertes System ausgelegt waren, das deinen Fortschritt speichert. Also dachte ich mir, ich richte es so ein, dass es sich wie das Arcade-Spiel spielt und nutze einfach eine einzige Score-Tabelle, um es für ein Modul einfach zu halten.

Kurz bevor das Spiel fertig war, erhielt das PicoGX dann die Funktion, auf die SD-Karte zu schreiben und davon zu lesen. Ich habe das Speichern der Highscores also in letzter Minute hinzugefügt. Ich glaube, es wäre das erste Spiel gewesen, das dieses Feature nutzt, wenn mir die Bloodwych-Mod nicht zuvorgekommen wäre. Ich könnte also vielleicht darüber nachdenken, die „Extra Sugar“-Inhalte wieder einzubauen. Allerdings müsste ich dann all die neuen Hintergründe, die ich für „Extra Sugar“ gemacht habe und die nur in 4 Farben existieren, neu zeichnen. Und um ehrlich zu sein: Verglichen mit „Extra Sugar“ haben gar nicht so viele Leute Bomb Jack GX heruntergeladen, was durchaus interessant ist.

Die Memory Map ist komplett anders und eine Menge Code musste angepasst werden, um selbstmodifizierende Elemente zu entfernen, damit er vom ROM laufen kann. Der Bildschirm muss dank Hardware-Sprites nicht mehr doppelt gepuffert werden und der Großteil des Codes läuft direkt vom ROM – 64 KB RAM sind also mehr als genug. Und das ROM ist nur 128 KB groß, also auch hier: reichlich Platz.

Die Hintergrundbilder sind diesmal offensichtlich im Mode 0 und nutzen tatsächlich mehr Farben als die Arcade-Version, weil ich überall Dithering eingesetzt habe, wo es ging, damit sie im Mode 0 nicht ganz so klotzig aussehen. Sie wurden alle von Hand nachbearbeitet. Zudem nutzen sie, wo möglich, Farb-Splits, um mehr als 16 Farben zu erzielen. Oder 12 Farben, da die Plattformen immer schon 4 belegen.

Das Interrupt-System ist viel komplizierter als bei „Extra Sugar“, aber die Spielstruktur war dank des PRI viel einfacher zu schreiben – was vielleicht das am meisten unterschätzte Feature des GX ist. Sämtlicher timing-kritischer Code wurde in die Interrupt-Kette verlegt, was alles so viel einfacher und sauberer gemacht hat.

Der Sprite-Code wurde komplett überarbeitet, um Hardware-Sprites zu nutzen. Das Spiel benötigt maximal 12 Sprites für Spielobjekte (1 Spieler + 9 Gegner + P-Ball + B-Münze). Ich hatte Bedenken, wie viel Zeit es kosten würde, den ASIC zu aktualisieren, um sie zu animieren, da der Sprite-Speicher nicht indiziert ist (was extrem nervig ist). Um sie schneller zu machen, bestehen die Sprite-Daten komplett aus kompilierten Sprites und werden, wo möglich, als Delta gespeichert – das heißt, nur die Pixel, die sich vom vorherigen Sprite unterscheiden, werden geändert. Die Gegner-Animationen funktionieren alle so und sie wechseln sich beim Aktualisieren ab, immer 4 auf einmal. Dadurch geht das Aktualisieren der Sprites tatsächlich ziemlich schnell, meist noch bevor der sichtbare Frame gezeichnet wird. Und da die Spiellogik ohnehin schon schnell war, läuft das Spiel problemlos mit 50 Hz.

Mehr Zeit ging für das Sprite-Multiplexing drauf, was ebenfalls über den Interrupt geregelt wurde. Nach den Spielobjekten hatte ich noch 4 Sprites übrig und wollte sie per Multiplexing in 24 Bomben verwandeln. Das ist ein Kinderspiel, wenn sie vertikal untereinanderstehen, aber das Problem ist, dass bis zu 7 Bomben auf einer Linie liegen können. Wann immer es also mehr als 4 sind, wendet das Spiel ein kniffliges horizontales Multiplexing an, bei dem die Sprites in jeder Zeile hin und her verschoben werden, sodass sie doppelt erscheinen. Das erfordert präzises Timing und ist eine Schwachstelle bei Emulatoren.

Anzeige der Regenbogen-Leiste am oberen Bildschirmrand besteht ebenfalls aus zwei der Bomben-Sprites. Diese werden in der Zeit zwischen dem Ende der oberen Anzeige und dem Beginn des Spielfelds schnell wieder in Bomben umgezeichnet. Das Spiel hat also oft mehr als 30 Sprites gleichzeitig auf dem Bildschirm und kann mehr als 16 Sprites auf einer Zeile darstellen. Auf einem Master System oder NES geht das nicht.

Die Extra-Leben am unteren Bildschirmrand sind keine Sprites, sondern werden wie bei „Extra Sugar“ über Farb-Splits gelöst.

Der Titelbildschirm ist eine völlig andere Lösung für dasselbe Problem: Ich möchte, dass das Logo hochauflösend ist, aber man braucht mindestens 7 Farben, um es zu zeichnen, und die lassen sich nicht so einfach splitten. Diesmal hatte ich Hardware-Sprites auf meiner Seite, aber der Schriftzug ist zu groß, um ihn komplett mit Hardware-Sprites abzudecken. Am Ende habe ich das Logo in Mode 1 mit zwei Blautönen, Schwarz und Orange gezeichnet. Der Schriftzug wird durch eine strategische Anordnung von Hardware-Sprites in Kombination mit Farb-Splits auf dem Orange-Kanal abgedeckt. Dabei werden zwei der Hardware-Sprites neu geschrieben, sodass insgesamt 18 Sprites verwendet werden. Auch das erfordert wieder exaktes Timing – und ist somit wieder etwas, das nicht in allen Emulatoren zu 100 % korrekt aussieht.

Abgesehen davon ging alles ziemlich schnell zusammen. Das GX macht Spaß und hat immer noch eine Menge ungenutztes Potenzial.

23 „Gefällt mir“

Vielen Dank für diese wertvollen Informationen zu den technischen Lösungen.
Schande über mein Haupt, ich habe dein Spiel noch gar nicht gestartet… Ich schraube und programmiere einfach lieber auf alter Hardware, als darauf zu spielen. Aber deine Arbeit ist wirklich fantastisch, nochmals vielen Dank dafür!

Wahnsinn, das sieht so dermaßen fantastisch nach Arcade aus, ich bin selbst nach all der Zeit immer noch hin und weg…

Danke für den ausführlichen Bericht :slight_smile:

Richtig cool! Schade, dass es nie das gleiche Qualitätslevel erreichen konnte wie „Spiele, die in den letzten Monaten mithilfe von KI entwickelt wurden“, aber hey, trotzdem ein netter Versuch!

..und ich glaube, wir haben unser neues Meme gefunden :stuck_out_tongue:

7 „Gefällt mir“

Kannst du es bitte einfach auf sich beruhen lassen? Warum machst du eigentlich so ein Theater darum?

Gibt es Pläne, auch der GX-Version noch etwas zusätzliches Zuckerl zu verpassen?

PS: Manchmal lese ich lieber etwas über ein Spiel, als es tatsächlich zu spielen. In diesem Fall hat mir beides Spaß gemacht.

Vielen Dank für den wirklich interessanten Bericht und dafür, dass du diese zwei fantastischen Umsetzungen von Bomb Jack gemacht hast – besonders die GX-Version.

Ich liebe es, dass die Highscores gespeichert werden. Es macht richtig Spür, auf Punktejagd zu gehen :slight_smile:

Ich bin so neidisch, dass du das Sprite-Multiplexing auf dem Plus zum Laufen gebracht hast! Ich habe das nie ohne scheußliche Grafikfehler und seltsame Ruckler hinbekommen. Mein Königreich für eine ASIC-Sprite-Pointer-Tabelle!

Wie gesagt, es ist möglich, also vielleicht eines Tages. Das größte Hindernis ist, dass ich all die zusätzlichen Hintergründe neu zeichnen müsste. Und die GX-Version wurde im Vergleich zur CPC-Version viel seltener heruntergeladen.

Der Konvertierungsprozess hat allerdings Spaß gemacht, da riesige Abschnitte des Spiels auf einen Schlag zusammengefügt werden konnten.

2 „Gefällt mir“

Ich würde mich riesig freuen, wenn du ein weiteres Amstrad-Spiel aktualisierst, das dich interessiert! Oder vielleicht ein Arcade-Spiel, das du liebst und das nie für den CPC erschienen ist…

Oder Platypus CPC+!

1 „Gefällt mir“

Ich habe es in die Interrupt-Kette eingebaut, sodass ich mir, sobald es funktionierte, nicht mehr allzu viele Gedanken darüber machen musste. Ich habe eine Menge Code in den Interrupt gepackt. Schade, dass der reguläre CPC keine PRI hat. Es ist so ein einfaches Feature, das aber timing-kritischen Kram so viel einfacher macht.

Es hilft auch, dass sich die Bomben nicht umherbewegen. Vertikales Multiplexing ist einfach, aber das horizontale erforderte Timing auf die NOP genau und funktioniert gerade so eben. Es frisst für diese Zeilen zwar die gesamte CPU-Leistung, aber ich hatte jede Menge freie CPU-Zeit.

Da Interrupts beim Timing ein paar NOPs Unsicherheit aufweisen – je nachdem, was man gerade unterbricht –, habe ich präzise Interrupts genau dann bekommen, wenn ich sie brauchte, indem ich sie eine Zeile zu früh aufgerufen und dann die PRI so eingestellt habe, dass sie auf der nächsten Rasterzeile erneut unterbricht. Die Interrupt-Funktion wartet (WAIT) dann innerhalb des Interrupts darauf, dass der Interrupt auslöst. Das verschwendet zwar eine Rasterzeile an CPU-Zeit, liefert aber einen Interrupt mit exaktem Timing.

2 „Gefällt mir“

Wenn man das schlau anstellt, kann man einen Teil dieser Zeit für Vorbereitungsarbeiten nutzen. Die möglichen Interrupt-Zeiten variieren nur geringfügig. Wenn man also den frühen Interrupt nutzt, kann man Arbeit im Wert von gut 50 NOPs vorbereiten, bevor ein HALT in die nächste Scanline führt. Das ist besonders praktisch, wenn man DMA für das Timing von Scanline-Interrupts nutzt (statt mehrerer PRIs), weil man dann nicht einmal Zeit damit verschwendet, das PRI erneut zu setzen.

1 „Gefällt mir“

Man muss allerdings zugeben, dass Rodriks Modul erst seit Kurzem erhältlich ist.

Denn ehrlich gesagt gibt es hier definitiv die Möglichkeit, der – obwohl exzellenten – MSX2-Version eine gehörige Tracht Prügel zu verpassen.