Erstellen von 1k Intro Chaos für ZX-Spectrum


Ursprünglich hatte ich nicht vor, eine Demo bei Chaos Constrictions 2018 zu machen , aber 2-3 Wochen vor cc wurde mir klar, dass man nicht mit leeren Händen zu einer Demo-Party gehen konnte, und ich beschloss, eine kurze Demo für 386 / EGA / DOS zu schreiben.

Nachdem ich in Turbo-C unter DOS meine lib AnotherGraphicsLibrary kompiliert hatte , die ideal in die Beat-Plan-Struktur des EGA- Modus passte, war ich von den Bremsen, insbesondere den EGA- Bremsen, enttäuscht. Die Demo in der Form, in der ich ihn für diesen sehr begrenzten Zeitraum sehen möchte, war unmöglich zu machen.

Ich konnte jedoch nicht aufgeben und nichts tun. Und dann fiel mir ein, dass ich schon lange an den ZX-Spectrum- Demowettbewerben teilnehmen wollte. Und da ich im letzten Jahr zwei 48k Reals bekommen habe, könnte es mir Spaß machen, eine Demo zu erstellen. Übrigens - für mich ist das Wichtigste beim Schreiben einer Demo das Testen im realen Leben. Emulgatoren machen dem Prozess keine solche Freude. Es ist wirklich ein wunderbares Gefühl, wenn Sie nach der nächsten Änderung des Codes die Demo in real hochladen und sehen, wie die reale Hardware die Bytes mischt Speicherzeichnungseffekt.

Da ich nur 48k Real habe, habe ich beschlossen, eine Demo für 48k zu machen. Und aufgrund der begrenzten Zeit und des Fehlens jeglicher Entwicklungen fiel die Wahl auf die Erstellung eines 1k-Intro (Demo von nur 1 Kilobyte oder 1024 Bytes).

Das letzte Mal habe ich den z80 asm in EmuZWin gestoßen - einem großartigen Emulator mit integriertem Assembler. Leider funktioniert EmuZWin nicht unter Windows XP oder ist fehlerhaft.
Nachdem ich verschiedene Optionen geprüft hatte, stoppte ich bei einer Reihe von Unreal + sjAsm + Notepad ++ - Programmen, die meiner Meinung nach viel einfacher als EmuZWin sind, aber im Gegensatz dazu lebendig sind.

Während ich dieses Intro schrieb, führte ich direkt in der Quelle ein Entwicklungsprotokoll durch, auf dessen Grundlage der folgende Text geschrieben wurde:

Hallo Welt!

Was soll ich zuerst schreiben, wenn ich fast keine Erfahrung mit dem z80 asm habe ? Richtig, die Ausgabe eines 5x5-Sprites ist für einen der Effekte bekannt oder 40x40 Pixel (ironischerweise wurde dieser unvollendete Teil in Zukunft aus dem Intro geworfen, um in 1k zu passen).

Erstaunlicherweise war es ziemlich einfach, dies mit dem vorgenerierten Zeilenadressenetikett mit Down HL von Grund auf neu zu tun.

Oh, Indexregister, wie bequem sie sind, aber langsamer sind, verbrauchen buchstäblich Balken. Ich musste ihren Gebrauch aus einer Reihe von Orten werfen.

Noch hier bin ich ganz am Anfang auf unglaubliche sjAsm- Pannen gestoßen , oder besser gesagt auf die neueste Version. Der Disrealismus in Unreal zeigte eine absolut verrückte Folge von Befehlen. Ich habe die vorletzte Version heruntergeladen - es war schon irgendwie möglich damit zu leben.



Es ist klar, dass Sie nicht genügend zuvor gezeichnete Sprites in 1k einfügen können. Deshalb habe ich beschlossen, sie dynamisch zu generieren. Und sowieso nicht, sondern mit Polygonen zeichnen.

Daher war das zweite Verfahren, das ich geschrieben habe, das Verfahren zum Zeichnen eines Dreiecks. Zum größten Teil war es eine Portierung ihres eigenen Codes, der in C geschrieben wurde . Mit dem einzigen globalen Unterschied zur C- Version werden die Polygon-Scanlinien zuerst generiert und erst dann auf diesen Scanlinien gezeichnet.

Nach Hochsprachen macht es Ihnen Spaß, jr aka goto :

.sort_me_please: ld de,(tr_x2) ld bc,(tr_x0) ld a,d cp b jr nc,.skip1 ld (tr_x2),bc ld (tr_x0),de .skip1: ld de,(tr_x1) ld bc,(tr_x0) ld a,d cp b jr nc,.skip2 ld (tr_x0),de ld (tr_x1),bc jr .sort_me_please .skip2: ld de,(tr_x2) ld bc,(tr_x1) ld a,d cp b jr nc,.skip3 ld (tr_x2),bc ld (tr_x1),de jr .sort_me_please .skip3: 

Ich war ein wenig schockiert über die Tatsache, dass es sich zu einem angemessenen Zeitpunkt herausstellte, ein funktionierendes draw_triangle auf z80 asm zu schreiben, das ein Polygon Pixel für Pixel und ohne Löcher beim Verbinden von Polygonen zeichnet.


Hallo Dreiecke!

Partikel



Aufgrund des Vorhandenseins eines Bildschirmlinien-Etikettengenerators habe ich mit diesem Etikett eine ziemlich gekrümmte und langsame Punktausgabeprozedur geschrieben. Die Prozedur hat zwei Eintrittspunkte - nur die Umkehrung des Pixels und die Umkehrung des Pixels, indem es mit INK + BRIGHT + und der in einem der Register angegebenen Farbe gefüllt wird .

Als ich einen Effekt mit Partikeln erzeugte, stellte ich fest, dass das Beispiel mit den Strukturen aus den Beispielen im Wiki sjAsm einfach nicht funktioniert. Beim Googeln wurde ein Thema von der Website zx-pk.ru angesprochen , auf der dieses Problem beschrieben wird, und es gibt keine Lösung - ha, gut - eine weitere Panne.

Ich beschloss, alles klar zu machen - die Koordinaten unabhängig vom Rendern durch Unterbrechung zu aktualisieren. Ja ... plus Bytes zum Generieren einer Interrupt-Tabelle.

Zu diesem Zeitpunkt gab es nur wenige Partikel, und sie passen kaum in den Rahmen - dies ist übrigens die Langsamkeit meines Verfahrens zur Ausgabe des% -Punkts.)) Die Verwendung einer gemeinsamen Tabelle mit Sprites ließ mich jedoch nicht herauswerfen und fertig machen, weil Dies sparte viel Platz, da nur ein Tabellengenerator benötigt wurde. Und meine Liebe zu Fahrrädern auch :)

Zu wenige Partikel ... haben ihre Anzahl erhöht, aber jetzt wurde das Rendering auf zwei Frames gemästet.


Testen auf Peters WS64 , den ich auf dem letzten cc bekommen und diesen Winter repariert habe :)

Übrigens haben sich die Punkte bereits zu diesem Zeitpunkt in fette horizontale Punkte 2: 1 verwandelt, wie beim Commodore 64 . Dies geschah aufgrund der anfänglich geringen Anzahl von Partikeln und meiner Unzufriedenheit mit der Tatsache, dass sie im realen Leben ziemlich unsichtbar waren. Das Problem wurde durch Ersetzen der Platte behoben

 db 128,64,32,16,8,4,2,1; 

auf

 db 192,192,96,24,12,6,3,3; 

Dies verschlechterte die Genauigkeit der Positionierung und machte den Flug ein wenig ruckartig, erhöhte aber die Sicht. Hier spielte es auch in die Hand, dass die Partikel von oben nach unten fielen - ihre Sicht war vertikal verschmiert.

Teilchen fallen übrigens jeweils mit ihrer eigenen zufälligen Geschwindigkeit, und zwei Bytes werden zum Speichern von Y- Koordinaten verwendet.

Sprites

Ich warf das unvollendete Teil des Sprite-Teils weg und stellte fest, dass ich nicht in 1k damit passen konnte.

Außerdem gab es bereits Platzmangel, so dass ich mich an Introspeks wunderbaren Artikel über Packer erinnerte. Ich entschied mich für zx7 als Packer, der etwa 110 Bytes sparte. Übrigens, vielleicht kennt jemand einen besser geeigneten Packer für ein 1k-Intro?

Chaoskonstruktionen



Da ich bereits ein Verfahren zum Ausgeben eines Polygons hatte, schien es mir eine coole Idee zu sein, das CC- Logo in Polygone aufzuteilen und diese einzeln anzuzeigen.

Ich habe einen Testcode geschrieben, der mehrere Polygone anzeigt - alles hat wie beabsichtigt funktioniert - in Ordnung.

Um zu überprüfen, ob meine Idee in 1k passt oder nicht, wurde nach Schätzungen eine bestimmte Anzahl zufälliger Polygone generiert, eine ausreichende Anzahl für das Logo, und zur Quelle gefahren. Kompiliert und sichergestellt, dass - ausgezeichnet - Intro in dieser Form in die Grenze von 1024 Bytes passt.


Lebensfoto, erkennen Sie das Gerät auf dem Tisch? :)))

Ich beschloss, das halbfertige Intro noch einmal zu testen, bereits mit Polygonen und einem Packer, der auf real hochgeladen wurde und ... zurückgesetzt wurde. Zuerst begann ich zu sündigen, dass ich vergessen hatte, den Speicher irgendwo zu initialisieren, von wo aus, wo auf dem 0x00- Emulator alles gut funktioniert, im wirklichen Leben Müll einen Reset verursacht.

Nichts ist besser, um einen Problemort zu finden, als die Halbteilungsmethode und der Halt, den ich mir nicht einfallen lassen konnte.

Bei einem zweistündigen Reset auf Real gab es keine Möglichkeit, den Fehler zu lokalisieren ...
Wie sich herausstellte, war es nicht in meinem Code enthalten, sondern in dem mitgelieferten Sound Enhancer auf dem Telefon, von dem ich WAVs geladen habe. Ein Verbesserer aus einem Bitstrom in einer WAV- Datei erzeugte einen Deliriumstrom.

Sobald ich es ausschaltete, funktionierte alles magisch.

Er skizzierte das Logo im fehlerhaften Greenpixel- Grafikeditor, zerlegte es in eine Reihe von Dreiecken und fuhr die Koordinaten manuell zur Quelle. Nachdem ich das Chaos Constructions- Logo vollständig ausgefüllt und im wirklichen Leben ausgeführt hatte - ich war froh -, sah es ziemlich gut aus.


Das erste Logo wird auf echt angezeigt

Allerdings habe ich zufällige Polygone zu wenig gestopft, und auf dem echten Logo gab es ein Limit von 1 KB pro 150 Byte. Und dies trotz der Tatsache, dass der Partikeleffekt immer noch nicht abgeschlossen war und der Übergang zwischen den Teilen scharf war.

An diesem Tag ins Bett zu gehen, stellte sich wegen der Aufregung mit Pannen bereits um 8 Uhr morgens heraus. 8)

Und ja, ich habe versucht, die Größe zu optimieren, indem ich die Koordinaten und Scheitelpunktindizes getrennt gespeichert habe, aber der Packer mochte es nicht sehr, was die Größe nur vergrößerte.

Finale



Ich habe mir überlegt, wie man die Ausgabe des Logos diversifizieren kann. Dafür waren fast zwei weitere Pixel-Labels erforderlich:

 fake_points1: db 1,2,4,8,16,32,64,128; 1 ch fake_points2: db 32,8,128,2,16,1,64,4; 2 ch normal_points: db 128,64,32,16,8,4,2,1; 3 ch 

Dies führte zu einem coolen Effekt der Vergrößerung der Details beim Rendern des Logos oder dem anfänglichen Mangel an Details und einer allmählichen Erhöhung der Schärfe.

Und schließlich habe ich die endgültige Version mit allen Übergängen erstellt und eine Menge von allem weggeworfen. Dabei habe ich einen Fehler in der Prozedur zum Zeichnen eines Dreiecks gefunden. Wenn die beiden Scheitelpunkte die gleichen Y- Koordinaten haben, wird das Dreieck schief gezeichnet (es sieht so aus, als würde man bei der Berechnung von dx durch 0 dividieren) und mit einem temporären Hack umgangen.


Testen der endgültigen Version auf Leningrad 48

Größenoptimierung


Zweistellige Zahlen sind „zusätzliche Bytes“.

94 zusätzliche Bytes ...

Es ist an der Zeit, die „kulturelle“ Bewahrung / Wiederherstellung von Registern von Eingabe- / Ausgabeverfahren zu unterbinden, weit entfernt von allem, was notwendig ist, aber die Erinnerung frisst.

86 Bytes ...

Im wirklichen Leben getestet - es funktioniert! Er hat etwas mehr Speicherplatz verloren und gleichzeitig einen Fehler behoben, der durch 0 - 63 Bytes geteilt wird!

57 Bytes ...

Looping hinzugefügt.

 random_store: start: 

Das Schleifen erfolgt übrigens auf der Auspackebene, wie Als Entropiequelle für das RNG wurden mehrere Bytes aus dem Initialisierungscode verwendet (um Platz zu sparen), die das RNG im ersten Teil verdarb. Daher gibt es zum Schleifen nach dem Ende des Intro ret , na ja , und dann noch ein Entpacken und Übergang zum entpackten Code ...

Es war nicht möglich, die letzten 48 Bytes loszuwerden, ich musste den Interrupt-Handler ausschalten, aber Hurra! Gefüllt! Es blieb sogar 1 zusätzliches Byte übrig.

Und da es keine Unterbrechungen gibt, kann es für Frames bewertet werden, und es ist schwierig, den Strahlquerschnitt im ersten Effekt bei einem Pixel zu sehen. Daher habe ich die Anzahl der Partikel pro Auge erhöht, wobei ein Kompromiss zwischen Geschwindigkeit und Unterhaltung besteht.

Noch härter gestochen, dumm Code und Daten von einem Ort zum anderen verschoben, um dem Packer zu helfen. Was einige Zeit gedauert hat :)

Dies gab ungefähr 10 Bytes frei, in die ich eine Parodie des Klangs steckte. Khk, khe, Ton - dies ist an einigen Stellen durch Ohr eingeführt:

  ifdef UseSound ld a,d and #10 out (#FE),a endif 

Ich habe den Sound nicht "genagelt", sondern eine Definition vorgenommen und so zwei Versionen des Intro mit und ohne Sound erhalten. In dem ohne Ton, in "zusätzlichen" Bytes vollgestopft

 db 'e','r','r','o','r' 

Ich habe trd und tap gesammelt und alles auf die cc- Website hochgeladen.

Hurra - ich nehme an Demopati teil!

Nachwort

Es stellte sich als lustig mit dem Geräusch heraus, jemand auf dem Patlace sagte "klares Geräusch", jemand sah mich seltsam an und auf Pouet fand ich Folgendes:



Und das:



Im Allgemeinen habe ich nicht verstanden, ob jemand den 10-Byte-Sound mochte oder nicht :)

Und das letzte - es ist eine Schande, dass der 1- km- Wettbewerb dieses Jahr nicht stattgefunden hat. Die Arbeit erwies sich meiner Meinung nach als anständig, aber es ist schwierig, mit 640 km zu konkurrieren, aber ich wollte unbedingt antreten.

Schreibe Demos, schreibe 1k!

Und hier ist, was endete (ps, pass auf deine Ohren auf):



Stille Version:

Source: https://habr.com/ru/post/de421837/


All Articles